| |
| """Gmail MCP HTTP bridge — exposes Google's Gmail MCP as a local HTTP API. |
| |
| Use this when your AI tools don't support MCP stdio but can POST JSON. |
| |
| Usage: |
| python mcp/gmail_http_bridge.py --port 8766 |
| |
| Then curl it: |
| curl http://127.0.0.1:8766/mcp \ |
| -H 'content-type: application/json' \ |
| -d '{"method":"tools/list","jsonrpc":"2.0","id":1}' |
| """ |
|
|
| import argparse |
| import json |
| from pathlib import Path |
|
|
| import httpx |
| import uvicorn |
| from fastapi import FastAPI, Request |
| from google.auth.transport.requests import Request as GoogleRequest |
| from google.oauth2.credentials import Credentials |
|
|
| CREDS_PATH = Path.home() / ".config" / "infj_bot" / "gmail_credentials.json" |
| GMAIL_MCP_URL = "https://gmailmcp.googleapis.com/mcp/v1" |
| SCOPES = [ |
| "https://www.googleapis.com/auth/gmail.modify", |
| "https://www.googleapis.com/auth/gmail.readonly", |
| ] |
|
|
| app = FastAPI(title="Gmail MCP Bridge") |
|
|
|
|
| def _get_access_token() -> str: |
| if not CREDS_PATH.exists(): |
| raise RuntimeError("Run scripts/gmail_mcp_auth.py first") |
| creds = Credentials.from_authorized_user_file(str(CREDS_PATH), SCOPES) |
| if creds.expired and creds.refresh_token: |
| creds.refresh(GoogleRequest()) |
| data = json.loads(CREDS_PATH.read_text()) |
| data["token"] = creds.token |
| CREDS_PATH.write_text(json.dumps(data, indent=2)) |
| return creds.token |
|
|
|
|
| @app.post("/mcp") |
| async def mcp_endpoint(req: Request): |
| body = await req.json() |
| headers = { |
| "content-type": "application/json", |
| "accept": "application/json, text/event-stream", |
| } |
| if body.get("method") != "tools/list": |
| headers["Authorization"] = f"Bearer {_get_access_token()}" |
|
|
| r = httpx.post(GMAIL_MCP_URL, headers=headers, json=body, timeout=30) |
| r.raise_for_status() |
| return r.json() |
|
|
|
|
| def main() -> int: |
| p = argparse.ArgumentParser() |
| p.add_argument("--host", default="127.0.0.1") |
| p.add_argument("--port", type=int, default=8766) |
| args = p.parse_args() |
| print(f"🚀 Gmail MCP bridge running at http://{args.host}:{args.port}/mcp") |
| uvicorn.run(app, host=args.host, port=args.port) |
| return 0 |
|
|
|
|
| if __name__ == "__main__": |
| raise SystemExit(main()) |
|
|