google-workspace-unlimited
🚀 GoogleUnlimited Google Workspace 平台
GoogleUnlimited 是一个全面的 MCP 框架,通过先进的中介架构提供无缝的 Google Workspace 集成。它使 AI 助手和 MCP 客户端能够使用统一、安全的 API 与 Gmail、Google Drive、Docs、Sheets、Slides、Calendar、Forms、Chat、Photos 和 Contacts(People API)服务进行交互。
它的独特之处:
⚡ 默认启用代码模式(Code Mode) — 服务器不会用 90+ 个工具模式淹没你的客户端,而是暴露 7 个轻量级元工具;AI 按需发现工具,并在单个沙箱化的
execute块内链式调用真实 API🚀 零配置启动 — 服务器无需
.env文件即可立即运行;OAuth 在首次使用时惰性触发🔧 按会话控制工具 — 基于 URL 的服务过滤和会话范围的启用/禁用,使每个连接的客户端只看到它需要的工具
🎨 模板与卡片 DSL 系统 — Jinja2 宏和紧凑的卡片记法将原始 API 数据转化为丰富的电子邮件、仪表板和 Google Chat 卡片
🧠 语义记忆 — 每个工具响应都被嵌入到 Qdrant 中,之后可以用自然语言搜索
📋 目录
Related MCP server: mcp-google-workspace
⚡ 快速安装说明
什么是 GoogleUnlimited?
GoogleUnlimited 通过模型上下文协议(MCP)为 AI 助手提供 Google Workspace 服务的访问。它支持 9 个 Google 服务中的 92+ 个工具,以革命性的性能改进实现 AI 工作流与 Google Workspace 应用之间的无缝集成。
🛠️ 安装方法
方法 1:通过 uvx 快速安装(推荐)
最快的入门方式——直接从 PyPI 安装:
{
"mcpServers": {
"google-workspace-unlimited": {
"command": "uvx",
"args": ["google-workspace-unlimited"],
"disabled": false,
"timeout": 300
}
}
}⚡ 就是这样! 服务器默认以 stdio 模式运行,非常适合 Claude Desktop、Cursor、Roo 等 MCP 客户端。代码模式 开箱即用,因此你的客户端看到的是 7 个精简的元工具,而不是 90+ 个模式。
方法 1b:Claude Code 插件(服务器 + 技能)
Claude Code 用户可以通过两条命令安装服务器 以及 教 Claude 其卡片/电子邮件 DSL、代码模式和 Qdrant 搜索的技能:
/plugin marketplace add dipseth/google_workspace_fastmcp2
/plugin install google-workspace-unlimited@riversunlimited详见 plugins/google-workspace-unlimited。
方法 2:克隆与开发设置
用于开发或自定义:
克隆并设置:
git clone https://github.com/dipseth/google_workspace_fastmcp2.git cd google_workspace_fastmcp2 uv sync启动服务器:
uv run python server.py服务器 零配置 即可立即启动。启动时不需要 OAuth 凭据——认证在你首次与 Google 服务交互时惰性处理。
准备好时进行认证:
当你调用任何 Google Workspace 工具时,服务器会提示你通过
start_google_auth工具进行认证。这会打开基于浏览器的 OAuth 流程。完成后,凭据会存储在本地,并在后续会话中复用。要预先配置 OAuth 凭据(可选),请创建一个
.env文件:cp .env.example .env然后添加你的 Google Cloud Console 凭据:
# Option A: Client ID + Secret GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=your-client-secret # Option B: Downloaded JSON credentials file GOOGLE_CLIENT_SECRETS_FILE=credentials.json有关创建 OAuth 凭据和启用 API 的步骤,请参阅 Google Cloud Console 设置步骤。
📚 配置资源:
🔧 完整配置指南 — 全面的环境变量和设置参考
🤖 Claude.ai 集成指南 — 用于 Claude.ai 远程 MCP 服务器使用
🔒 HTTPS 设置指南 — 用于安全连接的 SSL 证书配置
⚙️ MCP JSON 配置指南 — 用于任何兼容客户端的标准 MCP 配置
📋 环境变量参考
所有环境变量都是 可选的 — 服务器以合理的默认值启动,无需 .env 文件。只有在通过 start_google_auth 发起新的认证流程时才需要 OAuth 凭据。
Google OAuth(首次认证时需要):
变量 | 默认值 | 描述 |
| (空) | 来自 Google Cloud Console 的 OAuth 2.0 客户端 ID |
| (空) | OAuth 2.0 客户端密钥 |
| (空) | 替代方案:下载的 OAuth JSON 文件路径 |
|
| 必须与 Google Console 重定向 URI 匹配 |
在首次 OAuth 流程之前,提供
GOOGLE_CLIENT_ID+GOOGLE_CLIENT_SECRET或GOOGLE_CLIENT_SECRETS_FILE。认证后,凭据会存储在本地,这些变量不再需要。
服务器:
变量 | 默认值 | 描述 |
|
| 服务器绑定地址 |
|
| 服务器端口 |
|
| 启用 HTTPS/SSL |
| - | SSL 证书路径(如果启用 HTTPS 则必需) |
| - | SSL 私钥路径(如果启用 HTTPS 则必需) |
|
|
|
安全与会话:
变量 | 默认值 | 描述 |
|
|
|
|
| 存储凭据的目录 |
| (空) | 服务器 API 密钥 — 也用于加密绑定的凭据加密(HKDF-SHA256)和每用户密钥生成 |
|
| 会话空闲超时 |
| (空) | 逗号分隔的可信电子邮件地址 |
工具管理:
变量 | 默认值 | 描述 |
|
| 仅启用 5 个受保护工具启动 |
| (空) | 启动时启用的逗号分隔服务(例如 |
|
| 代码模式(默认)— 用 7 个元工具 + 沙箱化 |
|
| 启用 FastMCP SkillsDirectoryProvider 以进行动态技能生成 |
|
| 生成的技能文档目录 |
|
| 最大工具响应大小(字节)(0 = 禁用) |
| (空) | 要限制的逗号分隔工具名称(空 = 全部) |
Qdrant 向量数据库:
变量 | 默认值 | 描述 |
|
| Qdrant 向量数据库 URL |
|
| Qdrant API 密钥(使用 |
|
| 如果无法访问,则通过 Docker 自动启动 Qdrant |
|
| 自动启动的 Docker 镜像 |
|
| 自动启动的 Qdrant 容器名称 |
其他:
变量 | 默认值 | 描述 |
| (空) | Google Chat 卡片工具的默认 webhook URL |
|
| 启用云部署模式(自动切换到 |
🔗 客户端连接
GoogleUnlimited 支持多种连接方法。以下是两种最流行的入门方式:
🎯 快速设置选项
选项 1:Cursor IDE(STDIO - 社区验证 ✅):
{
"mcpServers": {
"google-workspace": {
"command": "uv",
"args": [
"--directory", "/path/to/google_workspace_fastmcp2",
"run", "python", "server.py"
],
"env": {
"GOOGLE_CLIENT_SECRETS_FILE": "/path/to/client_secrets.json",
"MCP_TRANSPORT": "stdio"
}
}
}
}选项 2:HTTP Streamable(VS Code Roo、Claude Code、Claude Desktop 等):
# Start server in HTTP mode
uv run python server.py --transport http --port 8002基本单连接配置:
{
"google-workspace": {
"type": "streamable-http",
"url": "https://localhost:8002/mcp",
"disabled": false
}
}多连接设置 —— 使用 URL 查询参数将同一客户端(或多个客户端)连接到同一服务器,并使用不同的工具集:
{
"google-email": {
"type": "streamable-http",
"url": "https://localhost:8002/mcp?service=gmail"
},
"google-chat": {
"type": "streamable-http",
"url": "https://localhost:8002/mcp?service=chat"
},
"google-productivity": {
"type": "streamable-http",
"url": "https://localhost:8002/mcp?service=drive,docs,sheets,slides"
}
}每个连接都会获得自己的隔离会话,并且只启用请求的服务工具。你还可以使用 ?uuid= 固定会话 ID,以便在重新连接时恢复相同的会话状态:
{
"google-workspace": {
"type": "streamable-http",
"url": "https://localhost:8002/mcp?uuid=my-workspace&service=gmail,drive,calendar"
}
}查看 基于 URL 的服务过滤 以获取完整的查询参数列表。
🤖 Claude Code 与 Claude Desktop
Claude Code(CLI) —— 一条命令,使用已发布的 PyPI 包:
# Local stdio (recommended): uvx fetches and runs the server on demand
claude mcp add google-workspace -- uvx google-workspace-unlimited
# Or connect to an already-running HTTP server
claude mcp add --transport http google-workspace https://localhost:8002/mcpClaude Desktop(本地开发路径) —— 添加到 claude_desktop_config.json(设置 → 开发者 → 编辑配置):
{
"mcpServers": {
"google-workspace-unlimited": {
"command": "uvx",
"args": ["google-workspace-unlimited"]
}
}
}Claude.ai / Claude Desktop(托管连接器) —— 在公共 HTTPS 端点(例如 Cloudflare 或 ngrok 隧道)后面运行服务器,然后在 设置 → 连接器 → 添加自定义连接器 中添加你的 https://your-domain/mcp URL。服务器的 OAuth 2.1 + PKCE 流程负责处理身份验证,包括 https://claude.ai/api/mcp/auth_callback 重定向。完整的操作指南请参阅 Claude.ai 集成指南。
📚 完整连接指南
有关所有受支持客户端的详细设置说明、故障排除和配置,包括:
Claude Code CLI (HTTP & STDIO)
Claude Desktop
VS Code / Roo / GitHub Copilot
Claude.ai with Cloudflare Tunnel
以及更多……
🔗 完整客户端连接指南 —— 面向所有受支持的 AI 客户端和开发环境的全面设置说明、故障排除和高级配置
⚡ 代码模式(默认)
代码模式是 GoogleUnlimited 的旗舰功能——而且默认开启。MCP 客户端无需预先加载 90 多个工具架构(这会消耗大量 token),只需看到 7 个元工具。AI 按需发现工具,然后在单个沙箱化的 Python execute 块内链式调用任意数量的真实 API。
Meta-Tool | 用途 |
| 按服务类别浏览工具(Gmail、Drive、Calendar 等) |
| 基于 BM25 的关键词搜索,覆盖工具名称和描述 |
| 获取所选工具的完整参数架构 |
| 对先前存储的工具响应进行自然语言搜索(基于 Qdrant) |
| 通过搜索结果中的点 ID 检索完整的已存储响应 |
| 总结最近的工具使用模式和活动 |
| 运行一个沙箱化的 Python 块,通过 |
为什么重要:
💰 大幅节省 token —— 只需 7 个架构,而不是 90 多个;仅在实际使用的工具上获取完整架构
🔗 一次往返替代多次往返 —— 搜索 → 过滤 → 执行在单个
execute块内完成,而不是一连串客户端往返🧰 沙箱开箱即用 —— 40 多个内置辅助函数(
now()、days_ago()、to_json()、re_find()、gather_tools()等)无需任何导入即可处理日期、JSON、URL、正则表达式、数学和批量调用
# One execute block: find a Drive file, then email its link
files = await call_tool("search_drive_files", {"query": "Q4 report"})
link = files["files"][0]["webViewLink"]
result = await call_tool("send_gmail_message", {
"to": "manager@company.com",
"subject": "Q4 Report",
"body": "Here's the Q4 report: " + link,
})
return result更喜欢经典目录? 选择退出后,每个工具都会直接暴露给客户端:
ENABLE_CODE_MODE=false # expose the full 90+ tool catalog instead代码模式与经典目录是互斥的——当代码模式激活时,直接工具调用会被搜索 +
execute模式取代。无论会话级过滤如何,发现工具始终看到完整目录。
🎯 服务能力
GoogleUnlimited 支持 10 个 Google Workspace 服务,提供 90 多个专用工具:
服务 | 图标 | 工具数 | 关键特性 | 文档 |
Gmail | 📧 | 14 | 发送、回复、标签、过滤器、搜索、允许列表 | |
Drive | 📁 | 9 | 上传、下载、共享、Office 文档、文件管理 | |
Docs | 📄 | 4 | 创建、编辑、格式化、批量操作 | |
Sheets | 📊 | 7 | 读取、写入、公式、格式化 | |
Slides | 🎯 | 5 | 演示文稿、模板、导出 | |
Calendar | 📅 | 9 | 事件、日程安排、与会者、时区 | |
Forms | 📝 | 8 | 创建、响应、验证、发布 | |
Chat | 💬 | 24 | 消息、卡片、空间、Webhook、统一卡片 | |
Photos | 📷 | 12 | 相册、上传、搜索、元数据、智能搜索 | |
People | 👤 | 4 | 姓名→邮箱搜索(联系人 + 组织目录)、联系人标签 |
📚 API 文档资源:
🔗 完整 API 参考 —— 覆盖 10 个服务中全部 92+ 工具的全面文档
📧 Gmail API 指南 —— 电子邮件管理、标签、过滤器和搜索操作
📁 Drive API 指南 —— 文件操作、共享和 Office 文档处理
📊 Sheets API 指南 —— 电子表格数据操作与格式化
📅 Calendar API 指南 —— 事件日程安排和时区管理
🧠 中间件架构
GoogleUnlimited 采用中间件架构,可提供无缝的服务集成、智能资源管理和强大的模板功能。

🔧 核心中间件组件
🏷️ TagBasedResourceMiddleware:使用 URI 模式(
service://gmail/messages、user://current/email)进行智能资源发现🧠 QdrantUnifiedMiddleware:利用向量嵌入对所有工具响应进行 AI 驱动的语义搜索
🎨 TemplateMiddleware:高级 Jinja2 模板系统,用于美观、结构化的输出格式化
✨ 架构优势
🔄 统一资源访问:无需 API 调用,基于 URI 访问服务数据
🧠 语义智能:跨所有已存储响应进行自然语言搜索
🎨 视觉卓越:一致、美观的输出格式化,优化 AI 消费体验
💰 Token 效率:模板宏通过结构化数据渲染将 token 用量降低 60-80%
⚡ 性能:通过智能缓存,比传统方法快 30 倍
📚 中间件文档资源:
📖 中间件架构指南 —— 完整的中间件系统文档和实现细节
🏷️ TagBasedResourceMiddleware —— URI 模式资源发现与管理
🧠 QdrantUnifiedMiddleware —— AI 驱动的语义搜索和向量嵌入
🎨 TemplateMiddleware —— 用于输出格式化的高级 Jinja2 模板系统
🔧 SessionToolFilteringMiddleware —— 按会话启用/禁用工具的管理
🚀 极简工具启动
默认情况下,GoogleUnlimited 以仅启用 5 个受保护工具启动,以实现最佳性能和安全性。这样客户端只需启用自己需要的工具。
受保护工具(始终可用):
manage_tools—— 全局或按会话启用/禁用工具manage_tools_by_analytics—— 基于分析的工具管理health_check—— 服务器健康与配置状态start_google_auth—— 发起 OAuth 身份验证check_drive_auth—— 验证身份验证状态
配置:
# Default: Start with minimal tools (only 5 protected tools)
MINIMAL_TOOLS_STARTUP=true
# Optional: Pre-enable specific services at startup
MINIMAL_STARTUP_SERVICES=drive,gmail,calendar
# Disable minimal startup (enable all 92+ tools immediately)
MINIMAL_TOOLS_STARTUP=false在运行时启用工具:
# Enable all tools globally
manage_tools(action="enable_all")
# Enable specific tools
manage_tools(action="enable", tool_names=["search_drive_files", "list_gmail_labels"])
# List all registered tools (shows enabled/disabled status)
manage_tools(action="list")🔧 会话级工具管理
GoogleUnlimited 支持按会话启用/禁用工具的功能,允许不同的 MCP 客户端拥有不同的工具可用性,而不会影响其他连接的客户端。
主要特性:
会话隔离:为一个客户端会话禁用工具,而不影响其他会话
非侵入式:会话级操作永远不会修改全局工具注册表
受保护工具:核心管理工具(
manage_tools、health_check等)始终可用基于中间件:使用
SessionToolFilteringMiddleware进行协议级过滤
使用示例:
# Disable tools for this session only (other clients unaffected)
manage_tools(action="disable", tool_names=["send_gmail_message"], scope="session")
# Disable all except specific tools for this session
manage_tools(action="disable_all_except", tool_names=["search_drive_files", "list_events"], scope="session")
# Re-enable all tools for this session
manage_tools(action="enable_all", scope="session")
# Global operations (original behavior, affects all clients)
manage_tools(action="disable", tool_names=["send_gmail_message"], scope="global")响应结构:
{
"success": true,
"action": "disable_all_except",
"scope": "session",
"enabledCount": 94,
"disabledCount": 0,
"toolsAffected": ["tool1", "tool2", "..."],
"sessionState": {
"sessionId": "f725be09...",
"sessionAvailable": true,
"sessionDisabledTools": ["tool1", "tool2"],
"sessionDisabledCount": 89
},
"message": "Kept 5 tools, disabled 89 tools for this session"
}📚 技能提供器
当通过 ENABLE_SKILLS_PROVIDER=true 启用时,GoogleUnlimited 会从 ModuleWrapper 实例生成技能文档,并通过 FastMCP 的 SkillsDirectoryProvider 提供服务。技能提供结构化知识,LLM 可在复杂的多步骤任务中引用这些知识。
当前支持的模块:
card_framework→gchat-cards技能(Google Chat 卡片 DSL 参考、组件层次结构、示例)
配置:
ENABLE_SKILLS_PROVIDER=true # Enable skill generation
SKILLS_DIRECTORY=~/.claude/skills # Output directory (default)技能会在每次启动时自动重新生成,并可立即通过 FastMCP 技能系统使用。
🖥️ 工具管理仪表板
GoogleUnlimited 内置工具管理仪表板,通过 MCP Apps 的 ui:// 资源方案提供。这为跨会话监控和管理工具可用性提供了可视化界面。

特性:
按服务分组的工具视图 —— 工具按 Google 服务(Gmail、Drive、Sheets 等)分组并显示数量
会话状态可见性 —— 一目了然地查看哪些工具已启用、已禁用或已在会话中禁用
筛选标签 —— 按服务快速筛选,聚焦相关工具
实时数据 —— 由
DashboardCacheMiddleware提供支持,该中间件缓存 list-tool 结果,以便即时访问ui://data-dashboard资源
仪表板通过 wire_dashboard_to_list_tools() 自动连接到所有 list 工具——无需逐工具配置。
🔗 基于 URL 的服务过滤(HTTP 传输)
使用 HTTP/SSE 传输时,你可以直接通过 URL 查询参数按服务过滤工具——无需编写代码:
# Enable only Gmail tools
http://localhost:8002/mcp?service=gmail
# Enable Gmail + Drive + Calendar
http://localhost:8002/mcp?service=gmail,drive,calendar
# Resume a previous session
http://localhost:8002/mcp?uuid=your-session-id
# Resume session with specific services
http://localhost:8002/mcp?uuid=abc123&service=gmail,drive
# Disable minimal startup (enable all tools)
http://localhost:8002/mcp?minimal=false可用的 URL 参数:
参数 | 示例 | 描述 |
|
| 要启用的服务列表,以逗号分隔 |
|
| 按 ID 恢复之前的会话 |
|
| 覆盖最小启动模式 |
可用服务: gmail, drive, calendar, docs, sheets, slides, photos, chat, forms, people
📚 会话工具管理资源:
🔧 SessionToolFilteringMiddleware 指南 - 按会话进行工具管理的完整文档
🎨 模板系统
GoogleUnlimited 提供强大的 Jinja2 模板宏,可将原始 Google Workspace 数据转换为视觉惊艳、针对 AI 优化的格式。
🎯 可用模板宏
模板文件 | 宏 | 用途 | 主要特性 |
|
| Gmail 标签可视化 | 交互式标签块、未读计数、Gmail 直接链接 |
|
| 日历与事件仪表板 | 主日历/共享日历、即将发生的事件、深色主题 |
|
| 日历事件仪表板 | 事件卡片、时间/地点详情、可点击链接、深色主题 |
|
| 专业报告 | 指标、表格、图表、公司品牌标识 |
|
| 富 HTML 电子邮件 | 多种签名、渐变、响应式设计 |
💡 模板宏示例
Gmail 标签可视化 - 将标签列表转换为精美的交互式标签块:
{{ render_gmail_labels_chips( service://gmail/labels , 'Label summary for: ' + user://current/email ) }}日历仪表板 - 创建全面的日历概览:
{{ render_calendar_dashboard( service://calendar/calendars, service://calendar/events, 'My Calendar Overview' ) }}日历事件仪表板 - 将日历事件转换为精美、交互式的事件卡片:
{{ render_calendar_events_dashboard( service://calendar/events , 'Upcoming Events for: ' + user://current/email.email ) }}
此宏可创建令人惊艳的深色主题仪表板,具有以下特性:
📅 交互式事件卡片:每个事件都渲染为可点击的卡片,可在 Google 日历中打开
🕐 智能时间显示:自动格式化全天事件与定时事件,并支持时区
📍 位置集成:显示会议地点和虚拟会议链接
👥 与会者信息:显示与会者人数和参与者详情
✅ 状态指示器:彩色编码状态(已确认、待定、已取消),并带有视觉反馈
📱 响应式设计:针对移动端优化的布局,支持触控友好交互
🎨 深色主题样式:专业外观,带有渐变背景和悬停效果
专业文档 - 生成包含指标和图表的报告:
{{ generate_report_doc(
report_title='Q4 Performance Report',
metrics=[{'value': '$1.2M', 'label': 'Revenue', 'change': 15}],
company_name='Your Company'
) }}🔍 宏发现与动态创建
使用模板资源系统探索所有可用宏:
# Access the template://macros resource to discover all available macros
macros = await access_resource("template://macros")
# Returns comprehensive macro information with usage examples
# Access specific macro details
macro_details = await access_resource("template://macros/render_gmail_labels_chips")🎯 动态宏创建
使用 create_template_macro 工具在运行时创建自定义宏:
# Create a new macro dynamically
await create_template_macro(
macro_name="render_task_status_badge",
macro_content='''
{% macro render_task_status_badge(status, size='small') %}
{% if status == 'completed' %}
<span class="status-badge status-completed {{ size }}">✅ Complete</span>
{% elif status == 'in_progress' %}
<span class="status-badge status-in-progress {{ size }}">🔄 In Progress</span>
{% else %}
<span class="status-badge status-pending {{ size }}">⏳ {{ status|title }}</span>
{% endif %}
{% endmacro %}
''',
description="Renders visual status badges for task states with appropriate icons",
usage_example="{{ render_task_status_badge('completed', 'large') }}",
persist_to_file=True
)
# Immediately use the newly created macro
await send_gmail_message(
html_body="Task Status: {{ render_task_status_badge('completed', 'large') }}"
)DSL 驱动的宏 — 动态宏还可以嵌入 Google Chat 卡片 DSL 表示法 来生成丰富的结构化卡片。DSL 符号定义卡片布局,而 Jinja2 处理动态内容:
{# workspace_dashboard.j2 — a dynamic macro that outputs a Google Chat card #}
{% macro workspace_dashboard(user_email, stats=None, quick_actions=None) %}
{% set username = user_email.split('@')[0] if user_email else 'User' %}
{% set default_stats = stats or [
{'label': 'Emails', 'value': '12 unread'},
{'label': 'Calendar', 'value': '3 meetings today'},
{'label': 'Tasks', 'value': '5 pending'}
] %}
§[δ×3, ℊ[ǵ×4], §[δ×2, Ƀ[ᵬ×3]]]
Welcome back, {{ username | title }}!
Your Workspace Overview:
{% for stat in default_stats %}
- {{ stat.label }}: {{ stat.value }}
{% endfor %}
Actions:
- Button: Open Gmail → https://mail.google.com
- Button: Open Calendar → https://calendar.google.com
- Button: Open Drive → https://drive.google.com
{% endmacro %}DSL 行 §[δ×3, ℊ[ǵ×4], §[δ×2, Ƀ[ᵬ×3]]] 定义了卡片结构:一个包含 3 个 DecoratedText 小部件的 Section、一个包含 4 个项目的 Grid,以及一个嵌套的 Section,其中包含 2 个 DecoratedText 小部件和一个包含 3 个按钮的 ButtonList。Jinja2 模板动态填充内容——由于它持久化到 templates/dynamic/,因此可立即供 send_dynamic_card 和其他工具使用。
主要特性:
⚡ 即时可用:宏创建后立即可用
🎯 资源集成:可通过
template://macros/macro_name自动获取💾 可选持久化:将宏保存到磁盘以实现永久可用
🔄 模板处理:完整的 Jinja2 语法验证和错误处理
💬 DSL 集成:宏可以输出卡片 DSL 表示法,用于生成丰富的 Google Chat 卡片
🚀 实际应用
模板可直接在工具调用中使用,以生成美观、结构化的输出:
# Send a beautiful email with calendar dashboard
await send_gmail_message(
to="manager@company.com",
subject="Weekly Schedule Update",
html_body="{{ render_calendar_events_dashboard( service://calendar/events, 'My upcoming events') }}",
content_type="mixed"
)
# Generate and send a professional report
await create_doc(
title="Q4 Performance Report",
content="{{ generate_report_doc( report_title='Quarterly Results', company_name='GoogleUnlimited' ) }}"
)📚 模板系统资源:
🎨 模板目录 - Jinja2 模板和宏的完整集合
💌 精美电子邮件模板 - 富 HTML 电子邮件样式和主题
🏷️ Gmail 标签卡片 - 带标签块的交互式标签可视化
📅 日历仪表板 - 事件时间线和日程视图
📄 文档模板 - 结构化文档格式
🗂️ 资源发现
GoogleUnlimited 提供强大的 MCP 资源系统,通过智能 URI 模式实现无需 API 调用的闪电般快速数据访问。

🎯 资源 URI 模式
模式 | 用途 | 示例 | 返回内容 |
| 用户身份验证状态 |
| 个人资料 + 身份验证状态 |
| 可用的服务列表 |
| [过滤器、标签] |
| 列表中的所有项目 |
| 所有 Gmail 标签 |
| 特定项目详情 |
| INBOX 标签详情 |
| 最近项目 |
| 最近的 Drive 文件 |
| 语义搜索 |
| 相关响应 |
🏗️ 关键资源文件
resources/user_resources.py:身份验证、个人资料、会话管理(1,812 行)resources/service_list_resources.py:通过 TagBasedResourceMiddleware 进行服务发现(446 行)middleware/qdrant_core/resources.py:AI 驱动的搜索和分析(319 行)
⚡ 闪电般快速访问
# Instant Gmail labels (no API call needed)
labels = await access_resource("service://gmail/labels")
# Current user info from session
user = await access_resource("user://current/email")
# Semantic search across all tool responses
results = await access_resource("qdrant://search/gmail errors today")
# Recent calendar events
events = await access_resource("recent://calendar")📚 资源系统文档:
🗂️ 用户资源 - 身份验证、个人资料和会话管理(1,812 行)
🏷️ 服务列表资源 - 通过 TagBasedResourceMiddleware 进行服务发现(446 行)
🧠 Qdrant 核心资源 - AI 驱动的搜索和分析(319 行)
📋 资源模式指南 - 完整的 URI 模式参考和使用示例
🧪 测试框架
GoogleUnlimited 包含全面的测试,其中 客户端测试 以 LLM 体验 MCP 的完全相同方式验证 MCP 用法,此外还有额外的测试套件。559 个测试全部通过,通过率 100%。
🎯 客户端测试重点

客户端测试是最重要的组成部分——它们使用真实的资源集成和跨所有 92+ 个工具 和 9 项 Google 服务 的标准化模式,对 MCP 操作进行确定性测试。这些测试同时验证显式电子邮件身份验证和中间件注入模式。
🚀 快速测试命令
# 🧪 Run all client tests (primary test suite)
uv run pytest tests/client/ -v
# 📧 Test specific service
uv run pytest tests/client/ -k "gmail" -v
# 🔐 Authentication required tests
uv run pytest tests/client/ -m "auth_required" -v🔬 真实资源 ID 集成
测试框架从服务资源中获取 真实 ID 以进行真实测试:
# Available fixtures for real resource testing
real_gmail_message_id # From service://gmail/messages
real_drive_document_id # From service://drive/items
real_calendar_event_id # From service://calendar/events
real_photos_album_id # From service://photos/albums
real_forms_form_id # From service://forms/forms
real_chat_space_id # From service://chat/spaces🔄 CI/CD 流水线
通过 GitHub Actions 实现自动化测试和发布:
CI 工作流:在每次 PR 和推送到 main 分支时运行
Python 3.11 和 3.12 矩阵测试
使用
ruff check进行 lint 检查,使用ruff format进行格式化执行完整测试套件
TestPyPI 发布:自动化包发布以进行测试
📚 测试资源:
🔒 安全与身份验证
GoogleUnlimited 通过 OAuth 2.1 + PKCE、高级会话管理和全面的审计功能实现 企业级安全。

🛡️ 身份验证流程
🌐 MCP Inspector OAuth:符合 MCP 规范,支持动态客户端注册
🖥️ Direct Server OAuth:基于 Web 的身份验证,用于直接访问
🔧 Development JWT:测试模式,使用生成的令牌
📁 Enhanced File Credentials:持久化存储,支持加密选项
🔑 Custom OAuth Clients:自带 OAuth 凭据,支持自动回退
🪪 Per-User API Keys:OAuth 完成后生成独立密钥,实现凭据隔离
✨ 安全特性
🔐 OAuth 2.1 + PKCE:带密钥证明交换的现代身份验证(支持公共客户端)
🔑 每用户 API 密钥:每个用户拥有唯一、可撤销的密钥,仅存储哈希值并支持定时安全查找
🛡️ 凭据隔离:基于身份验证来源的访问控制,防止跨用户凭据继承
🔗 账户关联:双向账户关联,支持多账户每用户密钥访问
🔒 加密绑定加密:使用 HKDF-SHA256 派生的加密密钥,绑定到
MCP_API_KEY🔒 会话隔离:多租户支持,防止数据泄露
🏷️ 27+ 个 API 范围:跨所有服务的细粒度权限管理
📊 审计日志:完整的安全事件跟踪,带有身份验证来源
🔐 AES-256 加密:凭据存储,支持旧密钥迁移
🔄 三层回退:服务器重启后可靠的凭据持久化(State Map → UnifiedSession → Context Storage)
🧹 敏感数据剥离:存储前从 Qdrant 嵌入中移除身份验证元数据
⚙️ 安全配置
# 🔒 Security settings in .env
CREDENTIAL_STORAGE_MODE=FILE_ENCRYPTED
SESSION_SECRET_KEY=your-secret-key
SESSION_TIMEOUT_MINUTES=30
ENABLE_AUDIT_LOGGING=true
GMAIL_ALLOW_LIST=trusted@example.com📚 安全文档资源:
🛡️ 统一 OAuth 架构 - 完整的安全架构和身份验证设计
🔐 OAuth 2.1 + PKCE 实现 - 带密钥证明交换的现代身份验证
🏠 会话管理指南 - 多租户支持和会话隔离
🔒 加密与存储 - AES-256 凭据加密和机器特定密钥
📊 审计日志系统 - 完整的安全事件跟踪和监控
🚀 准备好彻底革新您的 Google Workspace 集成了吗?
Available Tools
7 toolsexecuteExecuteA
Run sandboxed Python that calls this server's Google Workspace tools via await call_tool(tool_name, params), chaining calls in one block.
Use when: you know which tools to call. To find tool names first use search or tags; for exact parameters use get_schema; to look up past results instead, use semantic_search.
Behavior: each call_tool runs the real tool immediately — sends, edits, and deletes take effect; there is no dry-run.
Use return to produce output; prefer returning the final answer from a single block.
Only call_tool(tool_name: str, params: dict) -> Any is available in scope. Unknown tool names raise NotFoundError; disallowed syntax raises SandboxError.
SANDBOX RESTRICTIONS — these produce SandboxError, avoid them:
sorted_(items, key=lambda x: x['k'])→ lambda args fail; use builtins likekey=lenor sort manuallyimportonly covers a small stdlib subset (e.g. json); no third-party modules — prefer the built-in helpers listed below
Built-in helpers (import is not available — use these instead):
now(tz_offset=0)→ current datetime string (UTC by default)today(tz_offset=0)→ current date 'YYYY-MM-DD' (UTC by default)days_ago(n, tz_offset=0)→ ISO datetime string N days agohours_ago(n, tz_offset=0)→ ISO datetime string N hours agoformat_date(iso_str, fmt='%Y-%m-%d %H:%M')→ formatted dateparse_date(iso_str)→ normalized ISO datetimetimestamp()→ current unix timestamp (int)to_json(obj, indent=None)→ JSON stringfrom_json(s)→ parsed objecturl_encode(s)→ URL-encoded stringurl_decode(s)→ URL-decoded stringurl_join(base, *parts)→ joined URL pathquery_string(params)→ URL query string from dictre_find(pattern, text)→ list of matchesre_match(pattern, text)→ boolre_sub(pattern, repl, text)→ substituted stringtruncate(text, n=80)→ truncated with '...'dedent(text)→ remove common leading whitespacewrap_text(text, width=72)→ word-wrap to widthpad_left(s, width, char=' ')→ right-justify / zero-padpad_right(s, width, char=' ')→ left-justifyjoin(items, sep=', ')→ joined stringhtml_escape(s)→ HTML-safe stringsqrt(n),ceil(n),floor(n)→ mathround_(n, digits=2),abs_(),min_(),max_(),sum_()→ mathsorted_(items, key=None, reverse=False)→ sorted listunique(items)→ deduplicated list (preserves order)flatten(lists)→ flat list from nested listscounter(items)→ dict of {item: count}chunk(items, size)→ list of chunkszip_(*iterables)→ zipped as list of listsdict_get(d, 'a.b.c', default=None)→ nested dict accessmd5(s),sha256(s)→ hash hex digestsgather_tools(calls)→ run multiple tool calls sequentially;callsis a list of[tool_name, params]pairs, returns list of results (assign to variable, then index:r = await gather_tools([...]); a, b = r[0], r[1])sleep(seconds)→ async sleep
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | Python async code to execute tool calls via call_tool(name, arguments) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the full burden, and it does so thoroughly. It discloses that each call_tool runs the real tool immediately with sends/edits/deletes taking effect and no dry-run, plus sandbox restrictions, error types, and disallowed syntax. This is substantial behavioral context beyond what the schema provides.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections: use-when, behavior, sandbox restrictions, and built-in helpers. Core usage and side effects are front-loaded, and every block provides actionable information rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that annotations and an output schema are absent, the description is remarkably complete. It covers selection criteria, invocation syntax, execution environment, side effects, error modes, restrictions, and helper APIs, so an agent can use this tool without needing additional documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes the single `code` parameter at 100% coverage, but the description adds far more semantic value: valid async syntax, `call_tool` signature, use of `return`, restrictions on `import`, sandbox errors, and a full list of available built-in helpers. This gives the agent everything needed to construct valid code.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a precise verb and resource: running sandboxed Python that calls this server's Google Workspace tools via `await call_tool(tool_name, params)` and chaining calls in one block. It also distinguishes itself clearly from discovery/search siblings by framing this as the execution step once tool names are known.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit 'Use when' condition: when you know which tools to call. It also names alternatives for other cases: `search` or `tags` for finding tool names, `get_schema` for exact parameters, and `semantic_search` for past results, providing clear routing to sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_documentFetch DocumentA
Preview one stored tool response by its Qdrant point ID.
Use when: inspecting a hit returned by semantic_search. To find
point IDs in the first place, use semantic_search; for the full
untruncated content, call the fetch tool inside an execute block.
Behavior: read-only. Returns: tool name, service, timestamp, user, argument count, and the first 500 characters of stored content. Errors: 'Document not found' for unknown or expired point IDs.
| Name | Required | Description | Default |
|---|---|---|---|
| point_id | Yes | Qdrant point ID (UUID) from a search result | |
| user_google_email | No | User's Google email (auto-injected by middleware) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the behavioral disclosure burden. It states 'Behavior: read-only', describes the exact return fields including the 500-character truncation, and documents the error condition 'Document not found' for unknown or expired IDs. This is unusually transparent for a tool description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, well-organized with labeled sections, and front-loads the core purpose. Every sentence adds useful content, and there is no redundant repetition of schema or annotation details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description enumerates the return fields and truncation behavior, making the tool's output predictable. It also covers errors, read-only behavior, and usage context, making the description complete for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters clearly. The description adds context around the point_id's role in previewing a stored response, but does not need to add more because the parameter semantics are fully captured in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Preview one stored tool response') and identifies the resource by 'Qdrant point ID', clearly distinguishing this from sibling search and execute tools. It also explicitly indicates what it is not for, such as full untruncated content, which further sharpens purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Use when' section directly instructs to use this tool when inspecting a hit from semantic_search, and explicitly points to alternatives for finding point IDs and retrieving full content. This is exemplary routing guidance that leaves no ambiguity about when to use this tool versus siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_schemaGet SchemaA
Get parameter schemas for named tools before calling them via execute. Use when: you already have tool names (from search or tags) and need exact parameters. Not for discovery — use search for that. Returns: per-tool parameter markdown ('detailed', default), names + descriptions ('brief'), or full JSON schemas ('full'); unknown names are reported under 'Tools not found'.
| Name | Required | Description | Default |
|---|---|---|---|
| tools | Yes | List of tool names to get schemas for | |
| detail | No | 'brief' for names and descriptions, 'detailed' for parameter schemas as markdown, 'full' for complete JSON schemas | detailed |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses the output formats for each detail mode and the unknown-name handling behavior ('reported under Tools not found'). It does not explicitly state side effects, but the read-only nature is strongly implied by the verb 'get' and the schema-fetching purpose.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core purpose, and uses clear logical sections ('Use when', 'Not for discovery', 'Returns'). Every sentence earns its place without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a tool with no output schema and no annotations. It covers the main purpose, usage conditions, output formats, defaults, and error handling for unknown tool names. No critical operational gap remains for an agent deciding how to call this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema coverage is 100%, so the baseline is 3. The description mostly restates what the schema already says about 'detail' and 'tools'; it adds minor value with 'per-tool parameter markdown' and unknown-name behavior, but does not substantially deepen parameter understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get parameter schemas for named tools before calling them via execute.' It clearly differentiates from the sibling search tool by framing this as a pre-execute lookup step, not a discovery mechanism.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool ('when you already have tool names... and need exact parameters'), when not to use it ('Not for discovery'), and names the alternative ('use search for that'). This gives an agent unambiguous routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchSearchA
Find this server's Google Workspace tools by keyword (BM25 over names, descriptions, and tags). Use when: you don't know the exact tool name yet. To browse by category use tags; once you have names, use get_schema for parameters, then execute to call them. To search past results rather than tools, use semantic_search. Returns: matching tools as names + descriptions ('brief', default), parameter markdown ('detailed'), or complete JSON definitions ('full'). An empty result means no keyword match — retry with different terms.
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Filter to tools with any of these tags before searching | |
| limit | No | Maximum number of results to return | |
| query | Yes | Search query to find available tools | |
| detail | No | 'brief' for names and descriptions, 'detailed' for parameter schemas as markdown, 'full' for complete JSON schemas | brief |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It does this well by revealing the BM25 ranking mechanism, the three return detail modes, the default 'brief' mode, and the meaning of an empty result ('no keyword match — retry with different terms'). This gives an agent a clear behavioral model beyond what the schema states.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured. The primary purpose is stated first, followed by explicit usage guidance, sibling routing, and return behavior. Every sentence earns its place; there is no filler or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with no annotations and no output schema, the description is thorough: it explains what is searched, when to use it, how to route to alternatives, what the return values look like in each detail mode, and how to interpret empty results. Nothing critical is missing for safe and correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all parameters clearly. The description adds a little context around the detail parameter's output modes, but most of what it says about parameters mirrors the schema. This meets the baseline but does not go substantially beyond it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: 'Find this server's Google Workspace tools by keyword,' and specifies the search mechanism (BM25 over names, descriptions, and tags). It also distinguishes the tool from siblings like tags and semantic_search, so an agent can immediately tell what this tool is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'Use when: you don't know the exact tool name yet.' It also names alternatives and the conditions for choosing them, such as using tags to browse by category, get_schema for parameters, execute to call, and semantic_search for past results. This is exemplary routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
semantic_searchSemantic SearchA
Search the Qdrant vector store of this server's past tool responses and card templates.
Use when: looking up previous results, usage history, or analytics ('service:gmail last week', 'tool:search recent', 'overview'). For discovering tools to call, use search; to preview one stored document, pass its point ID to fetch_document.
Modes: semantic text similarity; service/tool history queries; analytics ('overview', 'usage stats'); filter_dsl for structured filters; positive/negative point IDs for recommendation; query_dsl for fusion/discover/order-by; prefetch_dsl for multi-stage retrieval.
Behavior: read-only against the local Qdrant instance; no Google APIs are called. Returns: scored rows 'score service/tool timestamp id:'. Errors: 'Search failed' when Qdrant is unreachable; 'No results' when nothing clears score_threshold (default 0.3 — lower it to widen the net).
DSL filter symbols: D_5=DatetimeRange, ʄ=FieldCondition, ƒ=Filter, F_6=FilterSelector, ℏ=HasIdCondition, I_2=IsEmptyCondition, I_0=IsNullCondition, ɱ=MatchAny, ṁ=MatchText, M_0=MatchTextAny, ☆=MatchValue, ř=Range Query-DSL symbols: Å=AcornSearchParams, C_14=ContextExamplePair, ¢=ContextPair, C_0=ContextQuery, D_6=DiscoverInput, D_2=DiscoverQuery, D_4=DiscoverRequest, D_21=DiscoverRequestBatch, ℱ=Fusion, φ=FusionQuery, ø=OrderBy, ɵ=OrderByQuery, ¶=Prefetch, ʔ=QuantizationSearchParams, R_12=RecommendGroupsRequest, R_2=RecommendInput, R_4=RecommendQuery, R_5=RecommendRequest, R_18=RecommendRequestBatch, R_10=RecommendStrategy, ♦=SearchParams Example: ƒ{must=[ʄ{key="tool_name", match=☆{value="send_dynamic_card"}}]} MatchAny: ƒ{must=[ʄ{key="tool_name", match=ɱ{any=["tool_a", "tool_b"]}}]}
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results to return | |
| query | Yes | Search query — natural language, 'service:gmail recent', 'overview', 'id:<point_id>', or semantic text when filter_dsl is set | |
| dry_run | No | If true with filter_dsl, parse and validate DSL without executing the query | |
| query_dsl | No | Query DSL for recommend, discover, fusion, or order-by queries | |
| collection | No | Qdrant collection to search. Default: mcp_tool_responses | |
| filter_dsl | No | Qdrant DSL filter notation for precise filtering (see docstring for symbols) | |
| prefetch_dsl | No | Multi-stage prefetch DSL for hierarchical search strategies | |
| score_threshold | No | Minimum similarity score (0.0-1.0) | |
| user_google_email | No | User's Google email (auto-injected by middleware) | |
| negative_point_ids | No | Point IDs to use as negative examples for recommendation search | |
| positive_point_ids | No | Point IDs to use as positive examples for recommendation search |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It explicitly states the tool is read-only, that no Google APIs are called, the exact return row format, the two error messages ('Search failed', 'No results'), and the effect of score_threshold. This is far more transparent than typical tool descriptions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded: purpose, use-when, modes, behavior, returns, errors, then reference material. It is long, but the DSL symbol tables and examples earn their place because the schema refers to 'see docstring for symbols.' A minor redundancy between the 'Modes' section and the query parameter description prevents a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 11-parameter tool with no output schema and no annotations, this description is remarkably complete: it covers return shape, error behavior, default threshold semantics, DSL syntax, example queries, sibling routing, and parameter mode mappings. An agent has nearly everything needed to invoke it correctly and interpret the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, giving a baseline of 3, but the description adds substantial meaning beyond the schema: a DSL symbol legend, a worked filter_dsl example, a MatchAny example, mapping of query_dsl/filter_dsl/prefetch_dsl to modes, explanation of positive/negative point IDs, and guidance to lower score_threshold. This meaningfully helps an agent construct parameters correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with a specific verb and resource: 'Search the Qdrant vector store of this server's past tool responses and card templates.' It also names sibling tools and clarifies what they do instead, so an agent can distinguish semantic_search from search and fetch_document without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Use when' section explicitly lists trigger conditions: looking up previous results, usage history, or analytics, with concrete query examples. It also provides exclusion guidance: 'For discovering tools to call, use search; to preview one stored document, pass its point ID to fetch_document.' This is exactly the when/when-not context an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tagsTagsA
List this server's tool tags (service areas like gmail, drive, docs, photos) with tool counts. Use when: browsing what capability areas exist before a targeted lookup. For keyword lookup use search; for parameters of known tools use get_schema. Returns: '- tag (N tools)' lines at detail='brief' (default), or every tool listed under each tag at detail='full'.
| Name | Required | Description | Default |
|---|---|---|---|
| detail | No | Level of detail: 'brief' for tag names and counts, 'full' for tools listed under each tag | brief |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden, and it does well: it specifies the exact output shape at default detail ('- tag (N tools)' lines) and the change at detail='full'. It clearly frames the operation as a non-mutating listing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences front-load the core action and use case before return details. There is no filler or unnecessary repetition of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with one optional schema-defined parameter and no output schema, the description covers purpose, routing, default behavior, and return format. Nothing material needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully documents the single parameter with its enum, default, and per-value meaning, so the baseline is 3. The description adds the concrete output format for brief detail and confirms what full detail returns, which is a small but meaningful addition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise action ('List this server's tool tags...') with resource and scope, plus concrete examples of categories like gmail, drive, docs, and photos. The mention of tool counts and the overview nature distinguishes it from sibling tools such as search and get_schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the intended use case ('browsing what capability areas exist before a targeted lookup') and names alternatives for adjacent cases: 'For keyword lookup use search; for parameters of known tools use get_schema.' This gives an agent clear routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tool_activityTool ActivityA
Show usage analytics for this server's tools: call counts, error rates, last-used times.
Use when: answering 'what has been used or failing lately'. To read an individual response, pass a sample point ID to fetch_document; to discover tools to call, use search instead.
Behavior: read-only aggregation over the Qdrant response store. Returns: a text dashboard grouped by tool_name or user_email, with sample point IDs per group. Errors: 'Analytics failed' when the response store is unreachable.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum groups to show | |
| group_by | No | Group results by 'tool_name' or 'user_email' | tool_name |
| user_google_email | No | User's Google email (auto-injected by middleware) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses read-only behavior ('read-only aggregation over the Qdrant response store'), return format ('text dashboard... with sample point IDs per group'), and an error condition ('Analytics failed' when the response store is unreachable). It does not mention authentication or rate limits, but for this tool the provided behavioral details are substantive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well structured with labeled segments ('Use when', 'Behavior', 'Returns', 'Errors'), front-loads the core purpose, and every sentence adds distinct value. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema and no annotations, the description provides enough context for correct invocation: what it returns (text dashboard), how it groups, what error to expect, and when to use alternatives. All three optional parameters are already covered by the schema, so nothing needed for this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter is already documented in the schema. The description mentions grouping by tool_name or user_email, which mirrors the group_by schema description, but does not add new semantic detail beyond that. Baseline 3 is appropriate when the schema handles parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Show usage analytics for this server's tools: call counts, error rates, last-used times'), and later explicitly contrasts with fetch_document and search, distinguishing its purpose. An agent can immediately tell what this tool does and how it differs from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains explicit 'Use when' guidance ('answering what has been used or failing lately'), plus clear redirections: 'pass a sample point ID to fetch_document' and 'use search instead'. This leaves no ambiguity about when to select this tool over alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v3.0.0- Changed
fetch_document1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "type": "string" - } - }, - "required": [ - "result" - ], - "type": "object", - "x-fastmcp-wrap-result": true -}New value: +null
- Changed
get_schema1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "type": "string" - } - }, - "required": [ - "result" - ], - "type": "object", - "x-fastmcp-wrap-result": true -}New value: +null
- Changed
search1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "type": "string" - } - }, - "required": [ - "result" - ], - "type": "object", - "x-fastmcp-wrap-result": true -}New value: +null
- Changed
semantic_search1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "type": "string" - } - }, - "required": [ - "result" - ], - "type": "object", - "x-fastmcp-wrap-result": true -}New value: +null
- Changed
tags1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "type": "string" - } - }, - "required": [ - "result" - ], - "type": "object", - "x-fastmcp-wrap-result": true -}New value: +null
- Changed
tool_activity1 field changed- changed
Output schema / (root)Previous value: -{ - "properties": { - "result": { - "type": "string" - } - }, - "required": [ - "result" - ], - "type": "object", - "x-fastmcp-wrap-result": true -}New value: +null
103 tool updates
v2.3.2- Removed
add_questions_to_form - Removed
add_slide - Removed
bulk_calendar_operations - Removed
check_drive_auth - Removed
cleanup_qdrant_data - Removed
compose_dynamic_email - Removed
create_calendar - Removed
create_doc - Removed
create_drive_file - Removed
create_event - Removed
create_form - Removed
create_gmail_filter - Removed
create_photos_album - Removed
create_presentation - Removed
create_sheet - Removed
create_spreadsheet - Removed
create_template_macro - Removed
delete_event - Removed
delete_gmail_filter - Removed
download_gmail_attachment - Removed
draft_gmail_forward - Removed
draft_gmail_message - Removed
draft_gmail_reply - Added
execute - Removed
export_and_download_presentation - Removed
fetch - Added
fetch_document - Removed
format_sheet_range - Removed
forward_gmail_message - Removed
get_doc_content - Removed
get_drive_file_content - Removed
get_event - Removed
get_form - Removed
get_form_response - Removed
get_gmail_filter - Removed
get_gmail_message_content - Removed
get_gmail_messages_content_batch - Removed
get_gmail_thread_content - Removed
get_people_contact_group_members - Removed
get_photo_details - Removed
get_photos_library_info - Removed
get_presentation_info - Removed
get_response_details - Added
get_schema - Removed
get_spreadsheet_info - Removed
get_tool_analytics - Removed
health_check - Removed
list_album_photos - Removed
list_calendars - Removed
list_docs_in_folder - Removed
list_drive_items - Removed
list_events - Removed
list_form_responses - Removed
list_gmail_filters - Removed
list_gmail_labels - Removed
list_messages - Removed
list_people_contact_labels - Removed
list_photos_albums - Removed
list_spaces - Removed
list_spreadsheets - Removed
make_drive_files_public - Removed
manage_credentials - Removed
manage_drive_files - Removed
manage_gmail_allow_list - Removed
manage_gmail_label - Removed
manage_people_contact_labels - Removed
manage_space - Removed
manage_tools - Removed
modify_event - Removed
modify_gmail_message_labels - Removed
modify_sheet_values - Removed
move_events_between_calendars - Removed
photos_batch_details - Removed
photos_optimized_album_sync - Removed
photos_performance_stats - Removed
photos_smart_search - Removed
publish_form_publicly - Removed
qdrant_search - Removed
read_sheet_values - Removed
reply_to_gmail_message - Added
search - Removed
search_docs - Removed
search_drive_files - Removed
search_gmail_messages - Removed
search_messages - Removed
search_photos - Removed
search_tool_history - Added
semantic_search - Removed
send_dynamic_card - Removed
send_gmail_message - Removed
send_message - Removed
set_form_publish_state - Removed
set_privacy_mode - Removed
share_drive_files - Removed
start_google_auth - Added
tags - Added
tool_activity - Removed
update_form_questions - Removed
update_slide_content - Removed
upload_folder_photos - Removed
upload_photos - Removed
upload_to_drive - Removed
verify_payment
96 tool updates
v2.2.1- First observed
add_questions_to_form - First observed
add_slide - First observed
bulk_calendar_operations - First observed
check_drive_auth - First observed
cleanup_qdrant_data - First observed
compose_dynamic_email - First observed
create_calendar - First observed
create_doc - First observed
create_drive_file - First observed
create_event - First observed
create_form - First observed
create_gmail_filter - First observed
create_photos_album - First observed
create_presentation - First observed
create_sheet - First observed
create_spreadsheet - First observed
create_template_macro - First observed
delete_event - First observed
delete_gmail_filter - First observed
download_gmail_attachment - First observed
draft_gmail_forward - First observed
draft_gmail_message - First observed
draft_gmail_reply - First observed
export_and_download_presentation - First observed
fetch - First observed
format_sheet_range - First observed
forward_gmail_message - First observed
get_doc_content - First observed
get_drive_file_content - First observed
get_event - First observed
get_form - First observed
get_form_response - First observed
get_gmail_filter - First observed
get_gmail_message_content - First observed
get_gmail_messages_content_batch - First observed
get_gmail_thread_content - First observed
get_people_contact_group_members - First observed
get_photo_details - First observed
get_photos_library_info - First observed
get_presentation_info - First observed
get_response_details - First observed
get_spreadsheet_info - First observed
get_tool_analytics - First observed
health_check - First observed
list_album_photos - First observed
list_calendars - First observed
list_docs_in_folder - First observed
list_drive_items - First observed
list_events - First observed
list_form_responses - First observed
list_gmail_filters - First observed
list_gmail_labels - First observed
list_messages - First observed
list_people_contact_labels - First observed
list_photos_albums - First observed
list_spaces - First observed
list_spreadsheets - First observed
make_drive_files_public - First observed
manage_credentials - First observed
manage_drive_files - First observed
manage_gmail_allow_list - First observed
manage_gmail_label - First observed
manage_people_contact_labels - First observed
manage_space - First observed
manage_tools - First observed
modify_event - First observed
modify_gmail_message_labels - First observed
modify_sheet_values - First observed
move_events_between_calendars - First observed
photos_batch_details - First observed
photos_optimized_album_sync - First observed
photos_performance_stats - First observed
photos_smart_search - First observed
publish_form_publicly - First observed
qdrant_search - First observed
read_sheet_values - First observed
reply_to_gmail_message - First observed
search_docs - First observed
search_drive_files - First observed
search_gmail_messages - First observed
search_messages - First observed
search_photos - First observed
search_tool_history - First observed
send_dynamic_card - First observed
send_gmail_message - First observed
send_message - First observed
set_form_publish_state - First observed
set_privacy_mode - First observed
share_drive_files - First observed
start_google_auth - First observed
update_form_questions - First observed
update_slide_content - First observed
upload_folder_photos - First observed
upload_photos - First observed
upload_to_drive - First observed
verify_payment
TDQS
Scored across 7 tools
The tools are mostly separable: tags and search provide different discovery paths, and semantic_search is clearly scoped to past responses. The main ambiguity is that search, semantic_search, and tags all surface tool/response names in slightly different ways, though the descriptions mitigate this by stating when to use each.
All names use lowercase with underscores, but the structural conventions are mixed: standalone verbs (search, execute), nouns (tags, tool_activity), and verb_noun compounds (get_schema, fetch_document) coexist. This is readable, but there is no single consistent naming pattern across the tool set.
Seven tools is an appropriate, well-scoped count for a discovery, schema, execution, history, and analytics server. Each tool carries a distinct responsibility, with no obvious redundancy or bloat.
The tool surface covers the core lifecycle of discovering tools, fetching schemas, executing calls, and retrieving historical results/analytics. Minor gaps exist, such as no dedicated tool for deleting/cleaning stored history or batch management of point IDs, but these are workable around.
Maintenance
Related MCP Connectors
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Hosted MCP server with managed OAuth for 15+ toolkits: Google Workspace, Fitbit, Oura, Kalshi, etc.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2
Related MCP Servers
- Apache 2.0
- AlicenseBqualityAmaintenanceMCP server integrating multiple Google Workspace services including Gmail, Calendar, Drive, Sheets, Docs, Tasks, People, Forms, and Slides, enabling users to manage emails, events, files, documents, and more through natural language.15MIT
- AlicenseBqualityCmaintenanceComprehensive Google Workspace MCP server with Gmail, Drive, Calendar, and Contacts integration.2614 npmMIT
- FlicenseNot gradedqualityDmaintenanceAn MCP server that exposes 17 Google Workspace APIs (e.g., Gmail, Drive, Calendar) as auto-generated tools for AI assistants, enabling natural language control of Google services.-