# The ClosedMCP library What you use depends on where your MCP server runs. | Your MCP runs... | Use | |---|---| | On ClosedMCP (a [Serverless MCP](/docs/serverless)) | the **hosted contract** below: four headers in, two `_meta` keys out. Nothing to install. | | On your own servers | the **Log in with ClosedMCP SDK** (`@closedmcp/sdk` for TypeScript, `closedmcp` for Python, also Go and Rust). See [SDK reference](/docs/sdk). | Do not wrap a hosted app with the SDK's server wrapper (`serveWithClosedMcp` / `serve_with_closedmcp`). It expects a signed pass in `Authorization: Bearer`, and ClosedMCP removes that header before a call reaches a hosted app, so every call would be rejected. A small hosted helper module for the TypeScript and Python SDKs is coming. ## What is already installed Every hosted app and every `closedmcp_run` sandbox starts from the same base image: - Node 22 with `@modelcontextprotocol/sdk`, `fastmcp`, `@closedmcp/sdk`, `pg` and `postgres`, found through `NODE_PATH` (so load them with `require`). - Python 3.12 with `mcp`, `fastmcp` 2, `psycopg[binary]`, `SQLAlchemy`, `uvicorn` and `closedmcp`. - `psql`, `bash`, `git`, `curl` and `jq`. Your own `node_modules` or Python packages win over these. ## In: who is calling | Header | Meaning | |---|---| | `X-ClosedMCP-User` | the person's ID, stable | | `X-ClosedMCP-Email` | their email | | `X-ClosedMCP-Org` | their company's org ID, the slug (e.g. `dacme_io`) | | `X-ClosedMCP-Client` | the AI app they use; display only | ClosedMCP sets these on every call and removes copies sent by anyone else. - Python (FastMCP 2): `get_http_headers(include_all=True).get("x-closedmcp-email")`, with `from fastmcp.server.dependencies import get_http_headers`. - Node (official MCP SDK): `extra.requestInfo?.headers["x-closedmcp-email"]` in the tool handler. ## Out: event channels | `_meta` key in a tool result | Effect | |---|---| | `"closedmcp/channel": {name, topic, ttl}` | opens a channel the caller can wait on | | `"closedmcp/events": [{topic, data}, ...]` | delivers each `data` to every open channel of this app with that `topic` | - Python (FastMCP 2): return `ToolResult(content="...", meta={...})`, with `from fastmcp.tools.tool import ToolResult`. - Node (official MCP SDK): return `{ content: [...], _meta: {...} }`. Details and limits: [Event channels](/docs/event-channels).