Connect an agent over MCP
Fanout serves MCP at /mcp for external agents. Its tools
query telemetry and manage the authenticated user’s dashboards. The browser
client and built-in agent use the same typed query results.
Build and refine dashboards covers schema discovery, panel previews, targeted edits and saved-version restore through chat or MCP.
You need a running instance with an HTTPS address first: install Fanout, finish first boot, then serve it over TLS, directly or behind a proxy. That HTTPS origin is the URL your MCP client connects to.
Set the public URL first
Section titled “Set the public URL first”export FANOUT_PUBLIC_URL=https://fanout.example.comFanout derives the MCP resource URI from this canonical, externally reachable origin that clients are issued tokens against. It must be HTTPS, and it must stay stable across restarts: tokens carry the derived resource as their audience, so changing it invalidates every one already issued.
FANOUT_PUBLIC_URL is the only public-origin setting; see
server settings.
Set FANOUT_MCP_ENABLED=false to turn the endpoint off entirely; it defaults
to true.
What the client does
Section titled “What the client does”Fanout implements the standard remote-MCP OAuth flow, so a compliant client needs only the URL:
- Discovers the endpoints from
/.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-server. - Registers itself at
/oauth/registerthrough dynamic client registration, so nothing is pre-provisioned by hand. - Obtains a token from
/oauth/token, bound to the resource URI above.
You authorize it in the browser as yourself, which ties the agent to your account without delegating your first-party account role.
Claude Code
Section titled “Claude Code”Add Fanout as a remote MCP server:
claude mcp add --transport http fanout https://fanout.example.com/mcpUse your instance’s public URL, then authorize the connection in your browser.
Disconnect an agent
Section titled “Disconnect an agent”Open Settings → Connected agents, find the agent, and choose Disconnect. Confirm to revoke its access immediately. Your other agents and browser session stay connected. To reconnect, authorize that agent again in your browser.
Administrators can still revoke all of a user’s access, including browser sessions and OAuth tokens.
Protocol
Section titled “Protocol”Fanout serves modern and legacy MCP clients concurrently over Streamable HTTP
on /mcp. Modern 2026-07-28 requests carry per-request metadata and
MCP-Protocol-Version: 2026-07-28, with no session or initialize handshake.
Legacy clients use initialize to negotiate 2025-11-25 or 2025-06-18 and
receive an Mcp-Session-Id bound to the authenticated user. Legacy sessions
expire after 10 idle minutes, with at most eight live sessions per user/OAuth
client pair. An expired session or a server restart requires re-initialization.
Versions 2025-03-26 and 2024-11-05 are not served. The browser’s /api/mcp
route uses only the modern protocol.
On /mcp and /api/mcp, an Origin header must exactly match the RFC 6454
serialization of FANOUT_PUBLIC_URL. Malformed or untrusted origins receive
403 before authentication. Without a public URL, only same-authority loopback
origins are accepted. Requests without Origin pass this check.
tools/call requests are limited to 20 per second per user/OAuth client pair,
with a burst of 100. Excess calls receive 429 with Retry-After. The in-process
agent is exempt. Modern client disconnects cancel in-flight tool calls, including
DuckDB queries.
Scopes
Section titled “Scopes”| Scope | Grants |
|---|---|
telemetry:read | Required for every remote MCP request. |
dashboard:manage | list_dashboards, get_dashboard, create_dashboard, replace_dashboard, edit_dashboard, list_dashboard_versions, and restore_dashboard_version |
Dashboard tools additionally require dashboard:manage. An insufficient_scope
challenge lists every scope required by the request, including scopes already
granted.
Restore requires an explicit user request and appends the selected historical spec as a new saved version with a save receipt. Dashboard deletion uses the HTTP API; there is no MCP delete tool.
What the agent can and cannot do
Section titled “What the agent can and cannot do”It acts on your behalf, but its delegated authority comes from the scopes you approve rather than your account role. Fanout also checks that your current account capabilities still permit those scopes. Two consequences:
- Dashboard tools are owner-scoped. An agent can manage your dashboards and cannot touch anyone else’s.
agent:runis not involved here. That capability gates Fanout’s own built-in agent; an external MCP client is a separate path.
There is no tool that writes telemetry, edits configuration, manages users or changes alert rules.
Behind a proxy
Section titled “Behind a proxy”If TLS terminates at a reverse proxy, FANOUT_PUBLIC_URL must be the externally
visible HTTPS origin rather than the internal address Fanout is listening on. Terminate TLS covers the rest of that setup.
Checking it
Section titled “Checking it”/.well-known/oauth-protected-resource is unauthenticated, so a plain fetch
tells you whether discovery is answering and what resource it advertises:
curl -s https://fanout.example.com/.well-known/oauth-protected-resourceIf the resource in that document is not the URL your client is calling, fix
FANOUT_PUBLIC_URL before debugging anything else.