Data Flow: notion-mcp-remote
Data Flow: notion-mcp-remote
Diagram
Components
| Component | Purpose | Notes |
|---|---|---|
| Dynamic Client Registration | claude.ai registers itself with no prior configuration | Standard MCP DCR; handled by mcp-remote-auth |
| Authorize/Callback | Three-legged OAuth proxy: claude.ai → notion-mcp-remote → Notion | notion-mcp-remote is both an OAuth server (to claude.ai) and an OAuth client (to Notion) |
| Token exchange | Converts Notion OAuth response into an MCP access token that wraps the notion_token | <code>upstream_token_key = "notion_token"</code> |
| ContextVar injection | Per-request NotionClient isolation | set via <code>client_patch.set_client_for_request</code> |
| Tool handlers | The 26 notion_mcp tools, imported unchanged | <code>apply_patch()</code> swaps their get_client before tools register |
Key Decisions
- OAuth proxy (not pass-through) — issue our own MCP tokens rather than handing the raw Notion token to claude.ai. Lets us rotate independently and audit per-client.
- ContextVar over global state — required because multiple concurrent requests may hit the same process with different user tokens (story: multi-workspace-safety).
- apply_patch before notion_mcp import — notion_mcp registers tools eagerly at import; the monkey-patch must land first or tool modules capture the unpatched get_client.
- stateless_http = False — claude.ai needs session affinity; fixed in PR #17/18.
Related
arch-domain-notion-mcp-remotearch-deployment-notion-mcp-remoteproject-notion-mcp-remote