Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Agent System Architecture β Complete Blueprint</title> | |
| <script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script> | |
| <style> | |
| * { margin: 0; padding: 0; box-sizing: border-box; } | |
| body { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| background: #0d1117; | |
| color: #e6edf3; | |
| padding: 40px 60px; | |
| line-height: 1.6; | |
| } | |
| h1 { | |
| font-size: 2.2rem; | |
| margin-bottom: 8px; | |
| background: linear-gradient(90deg, #58a6ff, #bc8cff); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| .subtitle { | |
| color: #8b949e; | |
| font-size: 1rem; | |
| margin-bottom: 40px; | |
| border-bottom: 1px solid #21262d; | |
| padding-bottom: 20px; | |
| } | |
| .diagram-section { | |
| background: #161b22; | |
| border: 1px solid #30363d; | |
| border-radius: 12px; | |
| padding: 32px; | |
| margin-bottom: 40px; | |
| page-break-inside: avoid; | |
| } | |
| .diagram-section h2 { | |
| font-size: 1.5rem; | |
| color: #58a6ff; | |
| margin-bottom: 8px; | |
| } | |
| .diagram-section p { | |
| color: #8b949e; | |
| margin-bottom: 20px; | |
| font-size: 0.95rem; | |
| } | |
| .mermaid { | |
| background: #0d1117; | |
| border-radius: 8px; | |
| padding: 20px; | |
| overflow-x: auto; | |
| } | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| margin: 16px 0; | |
| } | |
| th, td { | |
| padding: 10px 16px; | |
| text-align: left; | |
| border: 1px solid #30363d; | |
| } | |
| th { | |
| background: #21262d; | |
| color: #58a6ff; | |
| font-weight: 600; | |
| } | |
| td { color: #c9d1d9; } | |
| .file-ref { | |
| font-family: 'Cascadia Code', 'Fira Code', monospace; | |
| background: #21262d; | |
| padding: 2px 8px; | |
| border-radius: 4px; | |
| font-size: 0.85rem; | |
| color: #bc8cff; | |
| } | |
| .timing-table td:last-child { | |
| font-family: monospace; | |
| color: #7ee787; | |
| } | |
| .legend { | |
| display: flex; | |
| gap: 20px; | |
| flex-wrap: wrap; | |
| margin-top: 12px; | |
| } | |
| .legend-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 6px; | |
| font-size: 0.85rem; | |
| color: #8b949e; | |
| } | |
| .legend-dot { | |
| width: 12px; | |
| height: 12px; | |
| border-radius: 3px; | |
| } | |
| .print-btn { | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| background: #238636; | |
| color: white; | |
| border: none; | |
| padding: 10px 24px; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| font-size: 0.95rem; | |
| font-weight: 600; | |
| z-index: 100; | |
| transition: background 0.2s; | |
| } | |
| .print-btn:hover { background: #2ea043; } | |
| @media print { | |
| body { background: white; color: #1f2328; padding: 20px; } | |
| .diagram-section { border-color: #d1d9e0; background: #f6f8fa; } | |
| .mermaid { background: white; } | |
| h1 { background: none; -webkit-text-fill-color: #1f2328; } | |
| .diagram-section h2 { color: #0969da; } | |
| .subtitle { color: #656d76; border-color: #d1d9e0; } | |
| th { background: #f6f8fa; color: #0969da; } | |
| td { color: #1f2328; } | |
| .print-btn { display: none; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <button class="print-btn" onclick="window.print()">π Save as PDF</button> | |
| <h1>Agent System Architecture β Complete Blueprint</h1> | |
| <p class="subtitle"> | |
| Multi-Agent Google Workspace System | | |
| OpenAI Agent SDK + MCP Protocol + OpenRouter LLM | | |
| Generated February 2026 | |
| </p> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <!-- DIAGRAM 1: High-Level Overview --> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <div class="diagram-section"> | |
| <h2>1. High-Level Architecture Overview</h2> | |
| <p> | |
| The complete request flow from user to Google API and back. | |
| Two nested Agent loops β an <strong>Outer Orchestrator</strong> with 6 function_tools, | |
| and <strong>Inner Sub-Agents</strong> with MCP tools β both talk to the same LLM. | |
| </p> | |
| <pre class="mermaid"> | |
| flowchart TB | |
| subgraph USER["π€ User Layer"] | |
| UI["Browser / Chat UI"] | |
| API["FastAPI Backend\n/api/chat"] | |
| end | |
| subgraph ORCH["π§ ORCHESTRATOR AGENT β Outer Agent"] | |
| direction TB | |
| SVC["service(query)"] | |
| CACHE["LRU Cache\n100 entries Β· 5min TTL"] | |
| ENSURE["_ensure_connection()"] | |
| AGENT["Agent(\nname='Assistant'\nmodel=trinity-large-preview:free\ntools=6 function_tools\n)"] | |
| RUNNER["Runner.run(agent, query)\nβ sends to OpenRouter LLM"] | |
| end | |
| subgraph TOOLS["π§ 6 function_tool Wrappers β Registered on Outer Agent"] | |
| direction LR | |
| FT1["google_sheets_task()"] | |
| FT2["google_docs_task()"] | |
| FT3["google_drive_task()"] | |
| FT4["google_calendar_task()"] | |
| FT5["gmail_task()"] | |
| FT6["google_slides_task()"] | |
| end | |
| subgraph INNER["π¦ Inner Sub-Agent β e.g. GmailAgent"] | |
| direction TB | |
| INIT["GmailAgent.__init__()\nCreate AsyncOpenAI client"] | |
| MCPOBJ["create_google_mcp_server()\nβ MCPServerStdio object"] | |
| SUBPROCESS["async with mcp_server:\nβ Spawn MCP subprocess"] | |
| LISTTOOL["mcp_server.list_tools()\nβ 15 Gmail tools"] | |
| INNERAGENT["Agent(\nname='Gmail Agent'\nmcp_servers=[mcp_server]\nmodel=trinity-large-preview:free\n)"] | |
| INNERRUN["Runner.run(inner_agent, query)\nβ LLM calls MCP tools"] | |
| end | |
| subgraph MCP["βοΈ Google MCP Server β Subprocess via stdio"] | |
| direction TB | |
| MAIN["main.py --tools gmail --single-user"] | |
| OAUTH["OAuth Credential Store\n~/.google_workspace_mcp/credentials/"] | |
| GAPI["Google Gmail API\nvia googleapis"] | |
| end | |
| subgraph LLM["βοΈ OpenRouter LLM"] | |
| MODEL["arcee-ai/trinity-large-preview:free\nhttps://openrouter.ai/api/v1"] | |
| end | |
| UI -->|"HTTP POST /chat"| API | |
| API -->|"await service(query)"| SVC | |
| SVC --> CACHE | |
| CACHE -->|"miss"| ENSURE | |
| ENSURE --> AGENT | |
| AGENT --> RUNNER | |
| RUNNER <-->|"Turn 1: query + 6 tool defs"| MODEL | |
| MODEL -->|"function_call: gmail_task(query)"| FT5 | |
| FT5 --> INIT | |
| INIT --> MCPOBJ | |
| MCPOBJ --> SUBPROCESS | |
| SUBPROCESS --> LISTTOOL | |
| LISTTOOL --> INNERAGENT | |
| INNERAGENT --> INNERRUN | |
| INNERRUN <-->|"Turn 1: query + 15 MCP tool defs"| MODEL | |
| MODEL -->|"function_call: search_gmail_messages"| SUBPROCESS | |
| SUBPROCESS -->|"stdio JSON-RPC"| MAIN | |
| MAIN --> OAUTH | |
| OAUTH -->|"auto-refresh token"| GAPI | |
| GAPI -->|"Gmail results"| MAIN | |
| MAIN -->|"stdio response"| SUBPROCESS | |
| SUBPROCESS -->|"tool result β Turn 2"| MODEL | |
| MODEL -->|"final text answer"| INNERRUN | |
| INNERRUN -->|"result.final_output"| FT5 | |
| FT5 -->|"return string"| RUNNER | |
| RUNNER -->|"Turn 2 with tool result"| MODEL | |
| MODEL -->|"final formatted answer"| RUNNER | |
| RUNNER -->|"result.final_output"| SVC | |
| SVC -->|"cache + return"| API | |
| API -->|"JSON response"| UI | |
| </pre> | |
| </div> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <!-- DIAGRAM 2: Detailed Sequence --> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <div class="diagram-section"> | |
| <h2>2. Detailed Request Sequence β "Show my unread emails"</h2> | |
| <p> | |
| Step-by-step message flow with exact timing from real test runs (~20s total). | |
| </p> | |
| <table class="timing-table"> | |
| <tr><th>Phase</th><th>What Happens</th><th>Time</th></tr> | |
| <tr><td>Outer Turn 1</td><td>LLM receives query + 6 tool schemas β picks <code>gmail_task</code></td><td>~5s</td></tr> | |
| <tr><td>Inner Setup</td><td>GmailAgent spawns MCP subprocess, loads 15 tools</td><td>~2.5s</td></tr> | |
| <tr><td>Inner Turn 1</td><td>LLM receives query + 15 Gmail tool schemas β picks <code>search_gmail_messages</code></td><td>~4s</td></tr> | |
| <tr><td>MCP Execution</td><td>JSON-RPC over stdio β OAuth auto-refresh β Gmail API call</td><td>~1s</td></tr> | |
| <tr><td>Inner Turn 2</td><td>LLM formats raw Gmail results into readable text</td><td>~4s</td></tr> | |
| <tr><td>Outer Turn 2</td><td>LLM wraps sub-agent response for the user</td><td>~5s</td></tr> | |
| </table> | |
| <pre class="mermaid"> | |
| sequenceDiagram | |
| autonumber | |
| participant U as π€ User | |
| participant API as FastAPI | |
| participant SVC as service() | |
| participant Cache as LRU Cache | |
| participant OA as Outer Agent<br/>(Assistant) | |
| participant OR as OpenRouter LLM<br/>(trinity-large) | |
| participant FT as gmail_task()<br/>function_tool | |
| participant GA as GmailAgent | |
| participant MF as MCP Factory<br/>google_mcp_config | |
| participant MS as MCPServerStdio<br/>(subprocess) | |
| participant GS as google-mcp-server<br/>main.py | |
| participant OAuth as OAuth Store<br/>credentials/ | |
| participant Gmail as Google Gmail<br/>API | |
| U->>API: POST /api/chat {message: "show unread emails"} | |
| API->>SVC: await service(query) | |
| SVC->>Cache: _get_cached_response(query) | |
| Cache-->>SVC: None (cache miss) | |
| SVC->>OA: _ensure_connection() β Agent created once | |
| Note over OA: Agent with 6 function_tools:<br/>sheets, docs, drive,<br/>calendar, gmail, slides | |
| SVC->>OR: Runner.run(agent, query)<br/>Turn 1: query + 6 tool JSON schemas | |
| Note over OR: LLM analyzes query:<br/>"show unread emails"<br/>β matches gmail_task | |
| OR-->>SVC: ResponseFunctionToolCall<br/>{name: "gmail_task", args: {query: "..."}} | |
| Note over SVC: SDK auto-invokes<br/>the function_tool | |
| SVC->>FT: gmail_task(query="Search unread emails...") | |
| FT->>GA: GmailAgent() β __init__ | |
| GA->>GA: Create AsyncOpenAI client<br/>(OpenRouter endpoint) | |
| FT->>GA: await agent.run(query) | |
| GA->>MF: create_google_mcp_server("gmail", GMAIL_TOOLS) | |
| Note over MF: MCPServerStdio(<br/>command: python main.py<br/>args: --tools gmail --single-user<br/>cwd: google-mcp-server/<br/>tool_filter: 15 gmail tools<br/>) | |
| MF-->>GA: MCPServerStdio object (not started yet) | |
| GA->>MS: async with mcp_server: (START subprocess) | |
| MS->>GS: spawn: python main.py --tools gmail --single-user | |
| Note over GS: FastMCP server boots<br/>loads gmail tools only<br/>stdio transport ready<br/>(~2.5 seconds) | |
| GS-->>MS: subprocess ready (stdio pipe open) | |
| GA->>MS: await mcp_server.list_tools() | |
| MS->>GS: JSON-RPC: tools/list | |
| GS-->>MS: 15 tool definitions | |
| MS-->>GA: [search_gmail_messages, get_gmail_message_content, ...] | |
| Note over GA: create_static_tool_filter<br/>filters to exactly 15 allowed tools | |
| GA->>GA: Create inner Agent<br/>(name="Gmail Agent", mcp_servers=[ms]) | |
| GA->>OR: Runner.run(inner_agent, query)<br/>Turn 1: query + 15 MCP tool schemas | |
| Note over OR: LLM sees 15 Gmail tools<br/>picks: search_gmail_messages<br/>args: {query: "is:unread"} | |
| OR-->>GA: ResponseFunctionToolCall<br/>{name: "search_gmail_messages"} | |
| Note over GA: SDK auto-invokes<br/>MCP tool via call_tool() | |
| GA->>MS: call_tool("search_gmail_messages", {query: "is:unread"}) | |
| MS->>GS: JSON-RPC: tools/call {search_gmail_messages} | |
| GS->>OAuth: get_credential("aiwithjawadsaghir@gmail.com") | |
| OAuth-->>GS: credentials (auto-refresh if expired) | |
| GS->>Gmail: Gmail API: messages.list(q="is:unread") | |
| Gmail-->>GS: {messages: [{id, threadId}, ...]} | |
| GS-->>MS: JSON-RPC response: 10 unread messages | |
| MS-->>GA: tool result: "Found 10 messages..." | |
| GA->>OR: Turn 2: tool result + conversation history | |
| Note over OR: LLM formats the<br/>Gmail results into<br/>human-readable text | |
| OR-->>GA: "I found 10 unread emails..." | |
| GA-->>FT: return result.final_output | |
| MS->>MS: subprocess exits (async with ends) | |
| FT-->>SVC: "I found 10 unread emails..." | |
| SVC->>OR: Turn 2: function_tool result | |
| Note over OR: LLM wraps the sub-agent<br/>response for the user | |
| OR-->>SVC: Final formatted response | |
| SVC->>Cache: _set_cached_response(query, response) | |
| SVC-->>API: return response string | |
| API-->>U: JSON {response: "I found 10 unread emails..."} | |
| </pre> | |
| </div> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <!-- DIAGRAM 3: Component Relationships --> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <div class="diagram-section"> | |
| <h2>3. Component & Module Relationships</h2> | |
| <p> | |
| How the source files, classes, and external services connect. | |
| <span class="file-ref">google_mcp_config.py</span> is the shared config, | |
| <span class="file-ref">Gmail_Agent.py</span> (and 5 siblings) are inner agents, | |
| <span class="file-ref">Orchestrator_Agent.py</span> is the outer agent. | |
| </p> | |
| <pre class="mermaid"> | |
| flowchart TB | |
| subgraph CONFIG["google_mcp_config.py β Shared Config"] | |
| direction TB | |
| C1["MCP_SERVER_DIR = ../google-mcp-server/"] | |
| C2["MCP_PYTHON = .venv/Scripts/python.exe"] | |
| C3["OPENROUTER_API_KEY / BASE_URL"] | |
| C4["MODEL_NAME = arcee-ai/trinity-large-preview:free"] | |
| C5["GMAIL_TOOLS = 15 tool names"] | |
| C6["SHEETS_TOOLS = 14 tool names"] | |
| C7["DOCS_TOOLS = 19 tool names"] | |
| C8["DRIVE_TOOLS = 17 tool names"] | |
| C9["CALENDAR_TOOLS = 6 tool names"] | |
| C10["SLIDES_TOOLS = 9 tool names"] | |
| CF["create_google_mcp_server(service, tool_names)\nβ MCPServerStdio"] | |
| end | |
| subgraph AGENTS["6 Specialized Agent Classes"] | |
| direction TB | |
| A1["GoogleSheetsAgent β 14 tools via MCP"] | |
| A2["GoogleDocsAgent β 19 tools via MCP"] | |
| A3["GoogleDriveAgent β 17 tools via MCP"] | |
| A4["GoogleCalendarAgent β 6 tools via MCP"] | |
| A5["GmailAgent β 15 tools via MCP"] | |
| A6["GoogleSlidesAgent β 9 tools via MCP"] | |
| end | |
| subgraph ORCH_FILE["Orchestrator_Agent.py"] | |
| direction TB | |
| O1["@function_tool google_sheets_task"] | |
| O2["@function_tool google_docs_task"] | |
| O3["@function_tool google_drive_task"] | |
| O4["@function_tool google_calendar_task"] | |
| O5["@function_tool gmail_task"] | |
| O6["@function_tool google_slides_task"] | |
| OC["_create_agent() β Agent with 6 tools"] | |
| OS["service(query) β response string"] | |
| OSS["service_streaming(query) β async generator"] | |
| end | |
| subgraph SDK["OpenAI Agent SDK"] | |
| direction TB | |
| S1["Agent β wraps model + tools + instructions"] | |
| S2["Runner.run() β multi-turn loop"] | |
| S3["MCPServerStdio β subprocess manager"] | |
| S4["create_static_tool_filter β whitelist tools"] | |
| S5["function_tool β decorator for Python functions"] | |
| S6["OpenAIChatCompletionsModel β LLM adapter"] | |
| end | |
| subgraph EXTERNAL["External Services"] | |
| direction LR | |
| E1["OpenRouter API\n(LLM inference)"] | |
| E2["Google APIs\n(Gmail, Drive, Docs, etc.)"] | |
| E3["OAuth2 Credentials\n(local file store)"] | |
| end | |
| CF --> A1 & A2 & A3 & A4 & A5 & A6 | |
| O1 --> A1 | |
| O2 --> A2 | |
| O3 --> A3 | |
| O4 --> A4 | |
| O5 --> A5 | |
| O6 --> A6 | |
| OC --> O1 & O2 & O3 & O4 & O5 & O6 | |
| OS --> OC | |
| A5 --> S3 | |
| S3 --> S4 | |
| OC --> S1 | |
| OS --> S2 | |
| S2 --> S6 | |
| S6 --> E1 | |
| S3 --> E2 | |
| S3 --> E3 | |
| </pre> | |
| </div> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <!-- DIAGRAM 4: Runner.run() Turn Loop --> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <div class="diagram-section"> | |
| <h2>4. Runner.run() Turn Loop β How the Agent Loops Internally</h2> | |
| <p> | |
| <code>Runner.run()</code> is a <strong>multi-turn loop</strong>. It sends the query + tool schemas to the LLM, | |
| checks if the response is text or a tool call, executes tools, and loops back. This loop runs | |
| <strong>twice</strong> β once for the Outer Orchestrator (function_tools) and once inside the Inner Sub-Agent (MCP tools). | |
| </p> | |
| <pre class="mermaid"> | |
| flowchart TD | |
| START(["User query arrives"]) --> CHECK_CACHE{"Cache hit?"} | |
| CHECK_CACHE -->|Yes| RETURN_CACHED["Return cached response"] | |
| CHECK_CACHE -->|No| OUTER_T1 | |
| subgraph OUTER["OUTER AGENT LOOP β Orchestrator"] | |
| OUTER_T1["Turn 1 β LLM\nSend: query + 6 tool schemas"] | |
| OUTER_T1 --> OUTER_RESP1{"LLM response type?"} | |
| OUTER_RESP1 -->|"text message"| OUTER_DONE["Return text as final_output"] | |
| OUTER_RESP1 -->|"function_call"| OUTER_INVOKE["SDK invokes function_tool\ne.g. gmail_task(query)"] | |
| OUTER_INVOKE --> INNER_START | |
| subgraph INNER["INNER AGENT LOOP β e.g. GmailAgent"] | |
| INNER_START["1. create_google_mcp_server()"] | |
| INNER_START --> INNER_SPAWN["2. async with mcp_server:\n Spawn subprocess\n ~2.5s startup"] | |
| INNER_SPAWN --> INNER_LIST["3. list_tools()\n Get 15 Gmail tools"] | |
| INNER_LIST --> INNER_AGENT["4. Create inner Agent\n with mcp_servers=[server]"] | |
| INNER_AGENT --> INNER_T1["5. Runner.run(agent, query)\n Turn 1 β LLM\n Send: query + 15 MCP tool schemas"] | |
| INNER_T1 --> INNER_RESP{"LLM response?"} | |
| INNER_RESP -->|"text"| INNER_DONE["Return final_output"] | |
| INNER_RESP -->|"MCP tool call"| MCP_CALL | |
| subgraph MCP_EXEC["MCP Tool Execution"] | |
| MCP_CALL["SDK calls mcp_server.call_tool()\ne.g. search_gmail_messages"] | |
| MCP_CALL --> STDIO["JSON-RPC over stdio pipe\nβ google-mcp-server process"] | |
| STDIO --> CRED["Load OAuth credentials\nauto-refresh if expired"] | |
| CRED --> GAPI["Call Google API\ngmail.users.messages.list"] | |
| GAPI --> RESULT["Return API result\nmessage IDs, subjects, etc."] | |
| end | |
| RESULT --> INNER_T2["Turn 2 β LLM\nSend: tool result + history"] | |
| INNER_T2 --> INNER_RESP2{"LLM response?"} | |
| INNER_RESP2 -->|"more tool calls"| MCP_CALL | |
| INNER_RESP2 -->|"text"| INNER_DONE | |
| end | |
| INNER_DONE --> OUTER_T2["Turn 2 β LLM\nSend: function_tool result"] | |
| OUTER_T2 --> OUTER_RESP2{"LLM response?"} | |
| OUTER_RESP2 -->|"more function_calls"| OUTER_INVOKE | |
| OUTER_RESP2 -->|"text"| OUTER_DONE | |
| end | |
| OUTER_DONE --> CACHE_SET["Cache response\n5min TTL"] | |
| CACHE_SET --> RESPOND(["Return to user"]) | |
| RETURN_CACHED --> RESPOND | |
| </pre> | |
| </div> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <!-- LEGEND --> | |
| <!-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <div class="diagram-section"> | |
| <h2>Key Files</h2> | |
| <table> | |
| <tr><th>File</th><th>Role</th><th>Key Exports</th></tr> | |
| <tr> | |
| <td><span class="file-ref">Orchestrator_Agent.py</span></td> | |
| <td>Outer Agent β routes queries to specialist sub-agents</td> | |
| <td><code>service()</code>, <code>service_streaming()</code>, 6Γ <code>@function_tool</code></td> | |
| </tr> | |
| <tr> | |
| <td><span class="file-ref">Gmail_Agent.py</span></td> | |
| <td>Inner Agent β Gmail specialist with 15 MCP tools</td> | |
| <td><code>GmailAgent.run(query)</code></td> | |
| </tr> | |
| <tr> | |
| <td><span class="file-ref">google_mcp_config.py</span></td> | |
| <td>Shared config β MCP factory, tool lists, LLM settings</td> | |
| <td><code>create_google_mcp_server()</code>, tool name constants</td> | |
| </tr> | |
| <tr> | |
| <td><span class="file-ref">google-mcp-server/main.py</span></td> | |
| <td>MCP Server β runs as subprocess, provides Google API tools</td> | |
| <td>FastMCP <code>@server.tool()</code> functions (80 total across 6 services)</td> | |
| </tr> | |
| </table> | |
| <h2 style="margin-top: 24px;">Tool Counts Per Service</h2> | |
| <table> | |
| <tr><th>Service</th><th>Agent Class</th><th>Tools</th><th>Capabilities</th></tr> | |
| <tr><td>Gmail</td><td>GmailAgent</td><td>15</td><td>Search, read, send, draft, labels, filters, threads, attachments</td></tr> | |
| <tr><td>Docs</td><td>GoogleDocsAgent</td><td>19</td><td>Create, edit, find-replace, tables, images, PDF export, comments</td></tr> | |
| <tr><td>Drive</td><td>GoogleDriveAgent</td><td>17</td><td>Search, upload, share, permissions, copy, download, ownership</td></tr> | |
| <tr><td>Sheets</td><td>GoogleSheetsAgent</td><td>14</td><td>Read, write, format, conditional formatting, comments</td></tr> | |
| <tr><td>Slides</td><td>GoogleSlidesAgent</td><td>9</td><td>Create, update, thumbnails, comments</td></tr> | |
| <tr><td>Calendar</td><td>GoogleCalendarAgent</td><td>6</td><td>List calendars, CRUD events, free/busy</td></tr> | |
| <tr><th colspan="2">Total</th><th>80</th><th></th></tr> | |
| </table> | |
| </div> | |
| <script> | |
| mermaid.initialize({ | |
| startOnLoad: true, | |
| theme: 'dark', | |
| themeVariables: { | |
| primaryColor: '#238636', | |
| primaryTextColor: '#e6edf3', | |
| primaryBorderColor: '#30363d', | |
| lineColor: '#58a6ff', | |
| secondaryColor: '#161b22', | |
| tertiaryColor: '#21262d', | |
| fontFamily: 'Segoe UI, sans-serif', | |
| fontSize: '14px', | |
| }, | |
| flowchart: { curve: 'basis', padding: 20 }, | |
| sequence: { mirrorActors: false, messageMargin: 40 }, | |
| }); | |
| </script> | |
| </body> | |
| </html> | |