google-workspace-unlimited
🚀 GoogleUnlimited Google Workspace 플랫폼
GoogleUnlimited는 고급 미들웨어 아키텍처를 통해 Google Workspace와의 원활한 통합을 제공하는 포괄적인 MCP 프레임워크입니다. AI 어시스턴트와 MCP 클라이언트가 Gmail, Google Drive, Sheets, Docs, Slides, Calendar, Forms, Chat, Photos, Contacts(People API) 서비스를 통합된 보안 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는 Model Context Protocol(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 클라이언트에 적합합니다. 코드 모드가 기본적으로 활성화되어 있어, 클라이언트는 90개 이상의 스키마 대신 7개의 간결한 메타 도구를 확인할 수 있습니다.
방법 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.jsonOAuth 자격 증명 생성 및 API 활성화 방법은 Google Cloud Console 설정 단계를 참조하세요.
📚 구성 리소스:
🔧 전체 구성 가이드 — 포괄적인 환경 변수 및 설정 참조
🤖 Claude.ai 통합 가이드 — Claude.ai 원격 MCP 서버 사용 설정
🔒 HTTPS 설정 가이드 — 보안 연결을 위한 SSL 인증서 구성
⚙️ MCP JSON 구성 가이드 — 호환 가능한 모든 클라이언트를 위한 표준 MCP 구성
📋 환경 변수 참조
모든 환경 변수는 선택 사항입니다 — 서버는 합리적인 기본값으로 시작하며 .env 파일이 필요 없습니다. OAuth 자격 증명은 start_google_auth를 통한 최초 인증 흐름에서만 필요합니다.
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 카드 도구용 기본 웹훅 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
Cloudflare Tunnel을 사용한 Claude.ai
그 외...
🔗 전체 클라이언트 연결 가이드 - 지원되는 모든 AI 클라이언트 및 개발 환경에 대한 종합적인 설정 지침, 문제 해결 및 고급 구성
⚡ 코드 모드 (기본값)
코드 모드는 GoogleUnlimited의 대표 기능이며 기본적으로 활성화되어 있습니다. 90개 이상의 도구 스키마를 미리 로드하는 대신(토큰 비용이 높음), MCP 클라이언트는 7개의 메타 도구만 볼 수 있습니다. AI는 필요에 따라 도구를 발견한 다음, 샌드박스 처리된 단일 Python execute 블록 내에서 여러 실제 API 호출을 연결합니다.
메타 도구 | 용도 |
| 서비스 카테고리별 도구 탐색 (Gmail, Drive, Calendar 등) |
| 도구 이름과 설명에 대한 BM25 기반 키워드 검색 |
| 선택한 도구의 전체 매개변수 스키마 가져오기 |
| 이전에 저장된 도구 응답에 대한 자연어 검색 (Qdrant 기반) |
| 검색 결과의 포인트 ID로 저장된 전체 응답 검색 |
| 최근 도구 사용 패턴 및 활동 요약 |
|
|
중요한 이유:
💰 대규모 토큰 절약 — 90개 이상 대신 7개 스키마, 실제 사용된 도구에 대해서만 전체 스키마 가져오기
🔗 여러 왕복 대신 단일 왕복 — 검색 → 필터 → 실행이 클라이언트 왕복 체인이 아닌 단일
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 | 메시징, 카드, 공간, 웹훅, 통합 카드 | |
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 소비를 위한 일관되고 아름다운 출력 서식
💰 토큰 효율성: 템플릿 매크로가 구조화된 데이터 렌더링을 통해 토큰 사용량을 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 등)별로 도구를 개수와 함께 구성
세션 상태 가시성 — 활성화, 비활성화 또는 세션 비활성화된 도구를 한눈에 확인
필터 칩 — 서비스별로 빠르게 필터링하여 관련 도구에 집중
실시간 데이터 — 인스턴트
ui://data-dashboard리소스 액세스를 위해 list-tool 결과를 캐시하는DashboardCacheMiddleware기반
대시보드는 wire_dashboard_to_list_tools()를 통해 모든 목록 도구에 자동으로 연결됩니다 — 도구별 구성이 필요 없습니다.
🔗 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 위젯이 있는 섹션, 4개 항목이 있는 그리드, 2개의 DecoratedText 위젯과 3개의 버튼이 있는 ButtonList가 있는 중첩 섹션입니다. Jinja2 템플릿이 콘텐츠를 동적으로 채웁니다 — 그리고 templates/dynamic/에 저장되므로 send_dynamic_card 및 기타 도구에서 즉시 사용할 수 있습니다.
주요 기능:
⚡ 즉시 사용 가능: 생성 후 매크로를 즉시 사용할 수 있습니다
🎯 리소스 통합:
template://macros/macro_name을 통해 자동으로 사용 가능💾 선택적 저장: 매크로를 디스크에 저장하여 영구적으로 사용 가능
🔄 템플릿 처리: 전체 Jinja2 구문 검증 및 오류 처리
💬 DSL 통합: 매크로는 풍부한 Google Chat 카드를 위한 카드 DSL 표기법을 출력할 수 있습니다
🚀 실제 사용 사례
템플릿은 아름답고 구조화된 출력을 위해 도구 호출에서 직접 사용할 수 있습니다:
# 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는 지능적인 URI 패턴을 통해 API 호출 없이 초고속 데이터 액세스를 가능하게 하는 강력한 MCP 리소스 시스템을 제공합니다.

🎯 리소스 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 사용을 검증하는 클라이언트 테스트와 추가 테스트 스위트를 포함한 포괄적인 테스트를 제공합니다. 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를 통한 린팅 및ruff format을 통한 포맷팅전체 테스트 스위트 실행
TestPyPI 게시: 테스트를 위한 자동화된 패키지 게시
📚 테스트 리소스:
📋 클라이언트 테스트 프레임워크 가이드 - 전체 클라이언트 테스트 문서 및 패턴
🧪 클라이언트 테스트 디렉토리 - 결정론적 MCP 검증을 위한 실제 리소스 통합 테스트
🤖 MCP 클라이언트 통합 - MCP 클라이언트 패턴 및 사용법 자세히 알아보기
🔐 인증 패턴 - 이메일 vs 미들웨어 주입 검증 테스트
🔒 보안 및 인증
GoogleUnlimited는 OAuth 2.1 + PKCE, 고급 세션 관리, 포괄적인 감사 기능을 갖춘 엔터프라이즈급 보안을 구현합니다.

🛡️ 인증 흐름
🌐 MCP Inspector OAuth: 동적 클라이언트 등록을 지원하는 MCP Spec 준수
🖥️ 직접 서버 OAuth: 직접 액세스를 위한 웹 기반 인증
🔧 개발 JWT: 생성된 토큰을 사용한 테스트 모드
📁 향상된 파일 자격 증명: 암호화 옵션이 포함된 영구 저장
🔑 사용자 정의 OAuth 클라이언트: 자동 폴백과 함께 자체 OAuth 자격 증명 사용
🪪 사용자별 API 키: 자격 증명 격리와 함께 OAuth 완료 시 개별 키 생성
✨ 보안 기능
🔐 OAuth 2.1 + PKCE: 키 교환 증명을 통한 현대적인 인증(공개 클라이언트 지원)
🔑 사용자별 API 키: 사용자별 고유하고 취소 가능한 키, 해시 전용 저장 및 타이밍 안전 조회
🛡️ 자격 증명 격리: 인증 출처 기반 액세스 제어로 사용자 간 자격 증명 상속 방지
🔗 계정 연결: 사용자별 키에 대한 다중 계정 액세스를 위한 양방향 계정 연결
🔒 암호화 기반 암호화:
MCP_API_KEY에 바인딩된 HKDF-SHA256 파생 암호화 키🔒 세션 격리: 데이터 유출을 방지하는 멀티테넌트 지원
🏷️ 27개 이상의 API 범위: 모든 서비스에 걸친 세분화된 권한 관리
📊 감사 로깅: 인증 출처가 포함된 완전한 보안 이벤트 추적
🔐 AES-256 암호화: 레거시 키 마이그레이션을 지원하는 자격 증명 저장
🔄 3계층 폴백: 서버 재시작 시 견고한 자격 증명 유지(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.-