MCP Server

Manage a running Ingate gateway from any MCP-capable coding agent, with the same authorization checks as the REST API.

Ingate ships a Model Context Protocol (MCP) surface so any MCP-capable coding agent (Claude Code, Cursor, Windsurf, VS Code, Codex, or a custom client) can manage a running gateway directly: add providers, create keys, inspect logs and usage, run evals, publish skills, wire up exports, and more, all as tool calls instead of hand-rolled curl.

There are 63 tools, grouped in the catalog below, backed by the same REST API. Every tool call still goes through the gateway's normal RBAC and entitlement checks. MCP is a second transport onto the same authorization boundary, not a bypass of it.

Two ways to connect

1. Gateway /mcp endpoint (recommended)

POST
/mcp

Streamable-HTTP MCP transport served by the running gateway (GET is also supported).

The running gateway serves MCP directly at POST/GET {base_url}/mcp over the streamable-HTTP transport. One URL, no extra process to install or keep alive. Point any MCP-capable agent at it and authenticate per session with a header.

bash
https://gateway.example.com/mcp

Auth is per-request, not baked into a running process:

  • X-Ingate-Key: sk-ingate-..., an org-scoped API key, same as the REST API, or
  • Authorization: Bearer <session-token>, a session token from ingate_login/ingate_signup

Connecting with no credentials at all is allowed. That's the zero-credential onboarding path below. Every tool call still enforces the same authorization as its underlying REST endpoint, so an unauthenticated session can only reach ingate_setup (and anything else already public, like ingate_health); everything else is rejected.

2. Local stdio binary

ingate-mcp is a standalone binary that speaks MCP over stdio and proxies every tool call to a gateway over HTTP. Use this when your agent host only supports launching a local process rather than an HTTP MCP server.

bash
ingate-mcp --api-url http://localhost:7100 --api-key sk-ingate-...

Or via environment variables (the --api-url/--api-key flags win if both are set):

bash
export INGATE_URL=http://localhost:7100      # default if unset
export INGATE_API_KEY=sk-ingate-...
export INGATE_TOKEN=...                       # alternative to INGATE_API_KEY
ingate-mcp

INGATE_URL defaults to http://localhost:7100 when neither the flag nor the env var is set. ingate-mcp also supports --transport sse and --transport streamable-http for running it as its own local HTTP server instead of stdio, but stdio is the common case: most agent hosts spawn it as a child process per the config snippets below.

Connect your agent

Claude Code

bash
claude mcp add --transport http ingate https://gateway.example.com/mcp --header "X-Ingate-Key: sk-ingate-..."

Cursor

json.cursor/mcp.json
{
  "mcpServers": {
    "ingate": {
      "url": "https://gateway.example.com/mcp",
      "headers": {
        "X-Ingate-Key": "sk-ingate-..."
      }
    }
  }
}

Windsurf

json~/.codeium/windsurf/mcp_config.json
{
  "mcpServers": {
    "ingate": {
      "url": "https://gateway.example.com/mcp",
      "headers": {
        "X-Ingate-Key": "sk-ingate-..."
      }
    }
  }
}

VS Code

json.vscode/mcp.json
{
  "servers": {
    "ingate": {
      "type": "http",
      "url": "https://gateway.example.com/mcp",
      "headers": {
        "X-Ingate-Key": "sk-ingate-..."
      }
    }
  }
}

Codex

yaml~/.codex/config.toml
[mcp_servers.ingate]
url = "https://gateway.example.com/mcp"
http_headers = { "X-Ingate-Key" = "sk-ingate-..." }

stdio (any MCP client that spawns a local process)

json
{
  "mcpServers": {
    "ingate": {
      "command": "ingate-mcp",
      "env": {
        "INGATE_URL": "https://gateway.example.com",
        "INGATE_API_KEY": "sk-ingate-..."
      }
    }
  }
}

Zero-credential onboarding

You don't need an Ingate account, org, or API key to start. Connect to /mcp with no X-Ingate-Key and no Authorization header at all, then:

  • Call ingate_setup with an email, password, an app_name, and the LLM providers you want configured (name, base_url, optional api_key per provider). Under the hood this is one call to the public POST /api/v1/setup endpoint: signup (falling back to login if the account already exists), provider configs, an app, and an API key, all in one round trip.
  • ingate_setup returns api_key (an org-scoped sk-ingate-... key), gateway_url, and a ready-to-run snippet (a curl command). Copy the key out of the tool result.
  • Reconnect (or reconfigure) your agent host with that key in the X-Ingate-Key header, per the per-agent snippets above. This turns your one-shot onboarding session into a persistent, authenticated config.
  • Optionally call ingate_get_connection_snippet with the key, a language (python, javascript, go, or curl), and a provider/model to get a ready-to-use code snippet for calling the gateway's proxy endpoint directly (separate from the MCP tools, this is for wiring an LLM SDK through Ingate).

Partial provider failures

Partial provider failures don't abort the rest of the setup flow. Check providers[].success in the result.

After reconnecting with the key, every other tool, ingate_list_providers, ingate_list_skills, ingate_create_export, and so on, is available subject to the role and entitlement each one requires.

Tool catalog

Min role is the minimum RBAC role the underlying REST route requires (viewer < member < admin); "public" means no authentication is required at all. Entitlement gate is the enterprise entitlement feature required, if any.

GroupToolsMin roleEntitlement gate
Setup & Auth6public–viewernone
Providers5viewer/adminnone
Apps & Keys3viewer/membernone
Observability3public–viewernone
Prompts4any authenticatednone
Evals4viewer/memberevals
Datasets5viewer/memberdatasets
Teams7viewer/adminnone
Agent monitoring6membernone
Skill marketplace13viewer/memberskill_marketplace
Exports5viewer/adminintegrations
Eval results2viewer/memberintegrations

Setup & Auth

ToolRead-onlyRoleDescription
ingate_setupnopublicOne-shot onboarding: signup/login + providers + app + key
ingate_signupnopublicCreate a new account and org
ingate_loginnopublicAuthenticate an existing account
ingate_whoamiyesviewerCurrent identity, org, and role
ingate_get_entitlementsyesviewerPlan and feature flags for the caller's org
ingate_get_connection_snippetyesnone (local)Generate a proxy-connection code snippet (python/js/go/curl)

The remaining groups follow the same shape: each tool maps onto a REST endpoint with a read-only flag, a minimum role, and an entitlement gate where one applies. For a machine-readable listing an agent can fetch directly, see {base_url}/llms.txt and {base_url}/openapi.yaml.

Security notes

Tokens in the transcript

ingate_signup and ingate_login return raw tokens into the conversation transcript, and anything an MCP tool returns can end up logged, cached, or replayed by the agent host. Prefer connecting with a pre-issued X-Ingate-Key header for any persistent, unattended, or checked-in config. Reserve ingate_signup/ingate_login/ingate_setup for interactive, one-time onboarding sessions, and treat their output (token, api_key) as a secret to move somewhere safer immediately.
  • Keys are org-scoped, not personal. An X-Ingate-Key (or session token) authorizes as the org it belongs to, with whatever role that key's identity carries. Rotate a key by creating a new one and deleting the old one rather than sharing a single key across unrelated tools.
  • Unauthenticated /mcp is onboarding-only. Connecting without credentials is allowed specifically so ingate_setup and ingate_health can bootstrap a brand-new install. Anonymous calls to any other tool are rejected: with server.admin_auth enabled the gateway returns a 401; with it disabled, the route's own RBAC check fails closed and returns a 403 (error_code: missing_auth_context). Either way, an anonymous session cannot reach org-scoped data.
  • The stdio binary holds its credential in the parent process's environment/argv, same as any other locally-launched MCP server: treat ingate-mcp's config file the same way you'd treat a .env with a real API key in it: not committed, not world-readable.