使用说明
助理MCP
MCP(模型上下文协议)服务器模板,为代理客户端提供OAuth 2.0保护的工具。使用FastMCP构建,目前与Google API集成。
组件
| 组件 | 位置 | 目的 |
|---|---|---|
| FastMCP服务器 | src/main.py |
入口点、工具定义、OAuth路由 |
| OAuth门 | src/auth/oauth_gate.py |
令牌验证和OAuth流启动 |
| OAuthToolApp | src/mcp_tools/auth_tool_app.py |
OAuth保护工具的基类 |
| 谷歌提供商 | src/auth/providers/google_provider.py |
谷歌OAuth 2.0实现 |
| 日历工具 | src/mcp_tools/google/calendar.py |
Google日历API包装器 |
| 装饰师 | src/utils/decorators.py |
作用域、重试、OAuth错误处理 |
OAuth流程步骤
| 步骤 | 说明 |
|---|---|
| 1 | 客户端调用MCP工具(例如。, list_calendars) |
| 2 | @mcp_oauth_handler 装饰器包装工具功能 |
| 3 | OAuthToolApp.run_method 传递给 ensure_auth |
| 4 | ensure_auth 通过提供程序检查有效令牌 |
| 5 | 如果没有代币,则加薪 OAuthRequiredError 随着 elicitation_id |
| 6 | 装饰师转换为 UrlElicitationRequiredError 带有身份验证URL |
| 7 | 客户端将用户重定向到 /auth/connect/{elicitation_id} |
| 8 | 服务器重定向到Google OAuth同意屏幕 |
| 9 | 同意后,谷歌重定向到 /auth/callback/{elicitation_id} |
| 10 | 服务器将代码交换为令牌并存储 |
| 11 | 客户端使用有效令牌重试原始工具调用 |
项目结构
assistant-mcp/
├── .env # Environment configuration
├── .gitignore
├── .python-version # Python 3.13
├── pyproject.toml # Dependencies and metadata
├── uv.lock # Dependency lock file
├── CLAUDE.md # Project documentation
├── README.md
│
└── src/
├── main.py # FastMCP server entry point, tool definitions
│
├── auth/
│ ├── oauth_gate.py # OAuth flow management, token elicitation
│ ├── providers/
│ │ ├── provider.py # Abstract OAuthProvider interface
│ │ ├── google_provider.py # Google OAuth implementation
│ │ └── provider_registry.py # Provider lookup by name
│ └── tokens/
│ ├── auth_token.py # Abstract token interface
│ └── google_token.py # Google token implementation
│
├── mcp_tools/
│ ├── auth_tool_app.py # Base class for OAuth-protected tools
│ └── google/
│ └── calendar.py # Google Calendar tool implementations
│
├── utils/
│ ├── decorators.py # @tool_scope_factory, @tool_retry_factory, @mcp_oauth_handler
│ └── errors.py # Custom exceptions (OAuthRequiredError, etc.)
│
└── db/
└── db.py # Database utilities
安装
# Clone the repository
git clone <repo-url>
cd assistant-mcp
# Install dependencies with uv
uv sync
配置
创建一个 .env 文件包含:
GOOGLE_SECRETS_PATH=./secrets/client_secret.json
GOOGLE_LOCAL_TOKEN_PATH=./secrets/token.json
SERVER_HOST=127.0.0.1
SERVER_PORT=8000
| 变量 | 描述 |
|---|---|
GOOGLE_SECRETS_PATH |
Google OAuth客户端机密JSON文件的路径 |
GOOGLE_LOCAL_TOKEN_PATH |
OAuth令牌的存储路径 |
SERVER_HOST |
服务器主机地址(默认值:127.0.0.1) |
SERVER_PORT |
服务器端口号(默认值:8000) |
Google OAuth本地设置
对于本地设置,您需要创建一个Google Cloud项目并放置一个 secrets.json 文件
在该仓库的根目录下设置Google OAuth Provider。
跑步
uv run python src/main.py
服务器运行在 http://{SERVER_HOST}:{SERVER_PORT}/mcp 使用流式HTTP传输。
MCP工具
日历工具
| 工具 | 参数 | 输出 | 需要OAuth |
|---|---|---|---|
list_calendars |
(无) | calendar_id, name, description |
是的 |
list_events |
calendar_id, start_time, duration_days |
event_id, name, start, end |
是的 |
create_event |
calendar_id, start, name, duration_minutes, location, description |
event_id, event_details |
是的 |
update_event |
calendar_id, event_id, start, name, duration_minutes, location, description |
event_id, event_details |
是的 |
工具先决条件
| 工具 | 先决条件 |
|---|---|
list_calendars |
没有 |
list_events |
calendar_id 从 list_calendars |
create_event |
calendar_id 从 list_calendars |
update_event |
calendar_id 从 list_calendars, event_id 从 list_events |
默认值
calendar_id:'primary'(如果未指定,则使用主日历)duration_minutes:30(用于创建/更新)duration_days:7(针对list_events)
OAuth流
当工具需要身份验证且不存在有效令牌时:
1. Client calls tool (e.g., list_calendars)
↓
2. OAuthToolApp.run_method invokes ensure_auth
↓
3. ensure_auth checks provider for valid token
↓
4. No token found → OAuthRequiredError with elicitation_id
↓
5. @mcp_oauth_handler converts to UrlElicitationRequiredError
↓
6. MCP client receives auth URL, displays to user
↓
7. User visits /auth/connect/{elicitation_id}
↓
8. Server redirects to Google OAuth consent
↓
9. User authorizes, Google redirects to /auth/callback/{elicitation_id}
↓
10. Server exchanges code for token, stores in JSON file
↓
11. User sees "You may close this tab"
↓
12. Client retries tool call → succeeds with valid token
API路线
GET/auth/connect/{启发_id}
通过重定向到Google OAuth同意屏幕来启动OAuth流。
请求:
curl -L http://127.0.0.1:8000/auth/connect/{elicitation_id}
答复: 302重定向到Google OAuth同意URL
GET/auth/recall/{启发_id}
OAuth回调处理程序。接收授权码并交换令牌。
请求: (来自谷歌重定向)
http://127.0.0.1:8000/auth/callback/{elicitation_id}?code=...&state=...
答复:
You may close this tab.
关键设计模式
工厂图案(装饰)
装饰器为工具方法创建专门的行为:
@tool_scope_factory(scopes=["https://www.googleapis.com/auth/calendar"])
@tool_retry_factory(error_message="Google Calendar error", retry_on=(HttpError,))
def list_calendars(self, *, token: GoogleToken, ctx: Dict[str, Any]):
...
策略模式(OAuthProvider接口)
抽象提供者接口允许多种OAuth实现:
class OAuthProvider(ABC):
@abstractmethod
def get_access_token(self, principal_id: str, scopes: Sequence[str]) -> Optional[OAuthToken]:
...
@abstractmethod
def generate_auth_url(self, scopes: Sequence[str], elicitation_id: str, ...) -> dict:
...
装饰师组成
工具函数组成多个装饰器:
@mcp.tool()
@mcp_oauth_handler("Authorization is required to access your Google Calendar.")
def list_calendars(ctx: Context):
return calendar_tools.run_method('list_calendars', ctx=ctx)
@mcp.tool():寄存器用作MCP工具@mcp_oauth_handler:处理OAuth错误,转换为URL启发
关注点分离
- main.py:仅工具定义和MCP布线
- auth/:所有OAuth逻辑(提供者、令牌、流管理)
- mcp_tools/:具有业务逻辑的工具实现
- utils/:共享实用程序(装饰器、错误)
工具实施
要添加新的OAuth保护工具,请执行以下操作:
# In src/main.py
@mcp.tool()
@mcp_oauth_handler("Authorization message")
def my_tool(ctx: Context, param: str):
"""Docstring becomes tool description"""
return tool_app.run_method('method_name', ctx=ctx, param=param)
# In tool app class
@tool_scope_factory(scopes=[...])
@tool_retry_factory(error_message=..., retry_on=(...))
def method_name(self, *, token: GoogleToken, ctx: Dict, param: str):
# Implementation using token.present_creds()
...
相关
- msg代理:使用LangGraph使用这些工具的配套MCP客户端项目
- 测试客户端:提供了一个粗略的测试客户端来测试MCP服务器
