带有GitHub OAuth和位置管理功能的天气MCP服务器
这个项目展示了一个高级的模型上下文协议(MCP)服务器,它集成了GitHub OAuth认证、个性化位置管理,以及使用Open-Meteo的免费API进行天气数据检索的功能。
特点/特性
- 🔐 GitHub OAuth 2.0 认证使用GitHub Apps进行安全认证
- 📍 个人位置管理保存和管理自定义位置标签(例如,“家”,“办公室”)
- 🌤️ 智能天气查询使用保存的标签或直接输入地点名称来查询天气
- 💾 SQLite 数据库用户及其位置的持久化存储
- 免费天气API使用Open-Meteo API - 无需API密钥!
- 🔄 可流式传输的HTTP传输使用MCP SDK的现代HTTP传输
- 🛠️ 多种工具天气查询、位置管理(添加、列出、删除)、用户信息
- 👤 用户资料从GitHub个人资料数据中自动创建用户,并检索个人资料
先决条件
- Node.js(建议使用v18或更高版本)
- GitHub账号
- GitHub OAuth 应用(以下为说明)
- OpenAI API密钥(可选,用于客户端示例)
设置
1. 安装依赖项:
npm install2. 创建GitHub OAuth应用程序:
- 首选
- 点击 “新的OAuth应用”
- 填写申请详情:
- 应用程序名称天气MCP服务器(或您偏好的名称) - 主页网址: http://localhost:3000 - 授权回调URL: http://localhost:3000/oauth/callback
- 点击 “注册应用程序”
- 复制你的 客户端ID
- 点击 “生成一个新的客户端密钥” 并复制它
3. 配置环境变量:
cp .env.example .env编辑 .env 并添加您的GitHub OAuth凭据:
GITHUB_CLIENT_ID=your_github_client_id_here
GITHUB_CLIENT_SECRET=your_github_client_secret_here
GITHUB_REDIRECT_URI=http://localhost:3000/oauth/callback
PORT=30004. 启动MCP服务器:
node server.js服务器将在 http://127.0.0.1:3000
5. 使用GitHub进行身份验证:
- 打开您的浏览器并访问:
http://localhost:3000/oauth/login - 点击 “Authorize”翻译成中文是“授权” 连接到GitHub
- 复制 访问令牌 在成功页面上显示
- 在“Authorization”头中使用此令牌:
Bearer
6. 配置Claude桌面版
将配置添加到您的Claude Desktop配置文件中:
macOS(苹果电脑操作系统): ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
选项A:自动OAuth(推荐)
{
"mcpServers": {
"weather-server": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://127.0.0.1:3000/mcp"
]
}
}
}Claude Desktop 将自动发现 OAuth 端点并打开您的浏览器进行身份验证。只需在提示时授权 GitHub 即可!
选项B:手动令牌
{
"mcpServers": {
"weather-server": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://127.0.0.1:3000/mcp",
"--header",
"Authorization: Bearer YOUR_GITHUB_ACCESS_TOKEN",
"--no-auth"
]
}
}
}首先,通过访问(某个网站或服务)获取您的令牌 http://localhost:3000/oauth/login,然后替换 YOUR_GITHUB_ACCESS_TOKEN 使用您的令牌。
使用示例
一旦通过Claude Desktop连接,您可以:
基本天气查询
- “旧金山的天气怎么样?”
- “告诉我东京现在的天气”
- “巴黎的天气怎么样?”
保存个人位置
- “将我的家庭位置保存为纽约”
- 添加我的办公室位置为旧金山
- “将健身房位置保存为波士顿主街123号”
使用已保存标签进行查询
- “家里天气怎么样?”
- “办公室那边天气怎么样?”
- “查看健身房的天气情况”
管理位置
- “列出我保存的所有位置”
- “显示我的位置”
- “删除我的家庭位置”
用户配置文件
- “我是谁?”
- “显示我的个人资料”
- “我的GitHub用户名是什么?”
它是如何工作的
- OAuth 流程用户通过GitHub OAuth 2.0进行身份验证
- 代币交换服务器用授权码换取访问令牌
- 用户创建服务器根据GitHub数据创建或更新用户资料
- 认证客户端在Authorization头部发送Bearer令牌
- 令牌验证服务器使用SQLite数据库验证令牌
- 会话创建服务器与用户上下文建立认证会话
- 工具发现客户端从服务器发现可用的MCP工具
- 工具执行:
- 天气查询将位置标签解析为实际地址 - 位置管理将数据按用户存储在数据库中 - 所有操作均限制在已认证用户范围内
- 天气数据服务器从Open-Meteo API获取实时天气信息
- 回应结果返回给客户端,并附带用户特定的上下文信息
建筑学
User Browser
│
│ 1. Visit /oauth/login
▼
GitHub OAuth Server
│
│ 2. Authorization
▼
/oauth/callback
│
│ 3. Access Token
▼
┌─────────────────────────────────────────────┐
│ Claude Desktop / MCP Client │
│ (with Authorization: Bearer token) │
└─────────────────┬───────────────────────────┘
│ Streamable HTTP + Auth
▼
┌─────────────────────────────────────────────┐
│ server.js (MCP Server) │
│ ┌───────────────────────────────────────┐ │
│ │ OAuth Authentication (auth.js) │ │
│ │ ↓ │ │
│ │ Token Validation Middleware │ │
│ │ ↓ │ │
│ │ Session Management (per-user) │ │
│ │ ↓ │ │
│ │ MCP Tools: │ │
│ │ - get_current_weather │ │
│ │ - add_location │ │
│ │ - list_locations │ │
│ │ - delete_location │ │
│ └───────────────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────────────┐ │
│ │ SQLite Database (weather.db) │ │
│ │ - users (with GitHub data) │ │
│ │ - locations │ │
│ └───────────────────────────────────────┘ │
└─────────────────┬───────────────────────────┘
│
▼
Open-Meteo Weather APIMCP 工具
1. get_current_weather
获取任意地点或已保存标签的实时天气数据。
- 参数:
- location (字符串):位置名称或已保存的标签(例如,“纽约”,“家”) - unit (枚举): 温度单位 - “摄氏”或“华氏”(默认: 摄氏)
- 退货温度、状况、湿度、风速、气压、云量
- 特别自动将保存的位置标签解析为地址
2. add_location
为位置保存一个自定义标签以便快速访问。
- 参数:
- label (字符串):自定义标签(例如,“家庭”,“办公室”,“健身房”) - location (字符串):实际位置名称或地址
- 退货确认信息
- 注如果已存在标签,则替换现有标签
3. list_locations
显示已认证用户的所有已保存位置。
- 参数无
- 退货所有已保存位置及其标签的列表
4. delete_location
通过标签删除已保存的位置。
- 参数:
- label (字符串):要删除的位置的标签
- 退货确认信息或错误信息
5. get_user_info
获取当前登录用户的信息。
- 参数无
- 回报用户资料,包括GitHub用户名、姓名、电子邮件、头像URL和用户ID
项目结构
komunite-bootcamp-mcp/
├── server.js # MCP HTTP server with OAuth
├── database.js # SQLite database operations
├── auth.js # GitHub OAuth authentication
├── index.js # OpenAI function calling example (legacy)
├── .env.example # Environment variables template
├── .env # Your environment variables (create this)
├── package.json # Dependencies and scripts
├── weather.db # SQLite database (created on first run)
└── README.md # This file数据库模式
用户表
CREATE TABLE users (
id TEXT PRIMARY KEY,
github_id TEXT UNIQUE,
github_username TEXT,
github_email TEXT,
name TEXT,
avatar_url TEXT,
access_token TEXT,
refresh_token TEXT,
token_expires_at DATETIME,
auth_token TEXT UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)位置表
CREATE TABLE locations (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
label TEXT NOT NULL,
location_name TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
UNIQUE(user_id, label)
)安全特性
- GitHub OAuth 2.0行业标准的OAuth认证流程
- PKCE(RFC 7636)公共客户端使用S256进行代码交换的证明密钥
- 动态客户端注册(RFC 7591)自动客户端注册
- 状态参数带有状态验证的CSRF保护
- 不记名令牌认证所有MCP终端均需有效认证
- 令牌验证访问令牌已与数据库进行验证
- 用户隔离每个用户只能访问自己的位置信息
- 会话管理使用用户上下文进行安全的会话处理
- 数据库约束外键约束确保数据完整性
- 自动令牌过期令牌过期追踪以增强安全性
定制化
添加自定义MCP工具
- 开放
server.js - 在现有工具之后注册新工具:
sessionServer.tool(
'your_tool_name',
'Tool description',
{
param1: z.string().describe('Parameter description'),
},
async ({ param1 }) => {
const userId = sessionUsers[transport.sessionId]?.id;
// Your tool logic here
return {
content: [{ type: 'text', text: 'Result' }],
};
}
);- 客户端将自动发现该工具
API 端点
OAuth 发现端点(RFC 8414 和 RFC 9728)
- GET /.well-known/oauth-authorization-server 翻译为中文是:“获取 /.well-known/oauth-authorization-server 路径下的资源” - OAuth 2.0 授权服务器元数据
- 获取 /.well-known/oauth-protected-resource - OAuth 2.0 受保护资源元数据
OAuth 端点(符合标准)
- POST /oauth/register 翻译为中文是:“向 /oauth/register 发送 POST 请求” - 动态客户端注册(RFC 7591)
- GET /oauth/authorize 翻译为中文是:“获取/授权端点” - OAuth 2.0 授权端点
- POST /oauth/token(中文可译为:“发送到 /oauth/token 路径”) - OAuth 2.0 令牌端点
- POST /oauth/revoke 翻译为中文是:“发送到 /oauth/revoke” 或者更自然地表达为:“执行 OAuth 撤销操作(POST 请求)”。这里,“POST”是HTTP方法,用于向服务器提交数据;“/oauth/revoke”是API路径,用于指定执行撤销OAuth令牌的操作 - OAuth 2.0 令牌撤销(RFC 7009)
- GET /oauth/login 翻译为中文是:“获取/登录到OAuth(开放授权)接口”。不过,这里的“GET /oauth/login”更常被理解为是一个用于发起OAuth登录流程的请求,具体翻译时可能会根据上下文稍作调整,但核心意思是“发起OAuth登录请求” - 手动OAuth流程(基于浏览器)
- GET /oauth/callback 翻译为中文是:“获取(GET)/oauth/回调(callback)” - OAuth回调处理程序
- GET /oauth/me 翻译为中文是:“获取/授权/我” 或者更简洁地表达为:“获取用户授权信息”。不过,这里的“/oauth/me”在实际应用中通常指的是通过OAuth协议获取当前用户的相关信息,所以更具体的翻译可能是“获取当前用户通过OAuth授权的信息”。但根据简洁性原则,“获取/授权/我”也是可以接受的 - 返回当前用户信息(需要认证)
MCP端点
- POST /mcp 翻译成中文可以是:“发送到 /mcp(路径)”。不过,具体翻译可能需要根据上下文来确定“/mcp”所代表的具体含义,因为在这个上下文中,“/mcp”可能是一个特定的API路径、文件夹路径或某种系统指令,没有具体上下文,只能提供一个通用的翻译。如果“/mcp”有特定的含义,比如是某个软件或系统的特定功能,那么翻译时可能需要加入这个特定含义的解释 - 工具调用的主要MCP终端
- GET /mcp 翻译为中文是:“获取 /mcp(资源)”。不过,这里的“/mcp”可能是一个特定上下文中的路径或资源标识符,具体含义需要根据上下文来确定。在一般情况下,可以理解为“获取位于/mcp的资源或页面” - 用于通知的服务器发送事件(Server-Sent Events)
- 删除 /mcp - 会话终止
实用程序端点
- GET /health 翻译为中文是:“获取/健康(状态)” - 健康检查端点
备注
- 基于 模型上下文协议(MCP) 规格;说明书;规范
- 用途 @modelcontextprotocol/sdk(可翻译为)“@模型上下文协议/开发工具包”或根据具体语境简化为“模型上下文协议SDK”,但直接保留原样也是可接受的,因为SDK(Software Development Kit,软件开发工具包)在技术领域是一个通用术语,无需翻译 用于MCP服务器实现
- 可流式传输的HTTP传输带有会话管理的现代HTTP传输
- SQLite 数据库基于文件的轻量级数据库,使用better-sqlite3
- GitHub OAuth 2.0通过GitHub Apps实现安全认证
- 用途 Open-Meteo API(开放气象API) 免费且开源的天气API
- 无需API密钥即可获取天气数据!
- 基于用户的地理位置管理,实现数据库隔离
- 自动标签解析,便于天气查询
- 从GitHub数据自动创建的用户资料
登出 / 撤销访问权限
在使用 Claude Desktop 时登出 OAuth:
选项1:清除mcp-remote缓存
rm -rf ~/.cache/mcp-remote/auth/选项2:手动撤销令牌
curl -X POST http://localhost:3000/oauth/revoke \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=YOUR_ACCESS_TOKEN"然后清除缓存并重新启动Claude桌面应用。
故障排除
令牌已过期
如果你遇到身份验证错误,可能是你的GitHub令牌已过期:
- 访问
http://localhost:3000/oauth/login再次 - 获取新的访问令牌
- 使用新令牌更新您的Claude桌面配置
使用cURL进行测试
你可以直接使用cURL测试API:
# Check OAuth server metadata:
curl http://localhost:3000/.well-known/oauth-authorization-server
# Check protected resource metadata:
curl http://localhost:3000/.well-known/oauth-protected-resource
# Get your access token first by visiting:
open http://localhost:3000/oauth/login
# Then test the authenticated endpoint:
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
http://localhost:3000/oauth/me