Guides

The MCP Server

Gostly ships a Model Context Protocol server so an AI agent — Claude Desktop, Cursor, or any MCP client — can operate its own mock environment. The agent discovers your services, inspects coverage and the gaps in your mock library, switches proxy modes, and authors mocks, all over a single JSON-RPC endpoint. It is a Team-tier capability, part of the licensed self-hosted product.

What it is

The MCP server is a thin, tenant-scoped control surface served by the control-plane API on the same port as the rest of the REST API. It speaks the MCP 2024-11-05 protocol over a single JSON-RPC endpoint:

POST http://localhost:8000/mcp
X-API-Key: <your-api-key>
Content-Type: application/json

It implements the three JSON-RPC methods an MCP client expects — initialize, tools/list, and tools/call — and advertises a tools capability. There is no separate process and no separate port: every call is authenticated with the same X-API-Key header as the rest of the control plane and is scoped to the calling tenant.

Team tier

The /mcp endpoint is gated behind the mcp feature. Unlicensed or lower-tier deployments receive a license-shaped 403. The same gate guards the MCP Server page in the operator dashboard, which renders the connection details and a ready-to-paste client config.

Connecting a client

Generate an API key in the dashboard under Settings (the full key is shown only once, at generation time). Then point your MCP client at the server URL with that key in the X-API-Key header. For Claude Desktop, add the server to claude_desktop_config.json and restart:

{
  "mcpServers": {
    "gostly": {
      "url": "http://localhost:8000/mcp",
      "headers": {
        "X-API-Key": "<your-api-key-from-settings>"
      }
    }
  }
}

The dashboard's MCP Server page generates this block pre-filled with your server URL and a key prefix, with a one-click copy. Swap localhost:8000 for the host your control plane is reachable on if the agent runs elsewhere.

The tools

The server exposes sixtools. Four are read-only (discovery and inspection); two mutate state (switch mode, author a mock). Every tool is scoped to the calling tenant — an agent can only ever see and touch its own deployment's data.

list_services(no arguments)

Lists every configured proxy service (upstream target) for the current tenant. The agent's first call — it discovers what surfaces exist before deciding what to record or mock.

list_mocksmethod?, service_ids?, limit?

Lists recorded mock entries, newest first. Optionally filter by HTTP method and/or one or more service IDs (OR logic). Returns up to 200 by default, 1000 max, alongside the total count.

get_coverage(no arguments)

Returns total recordings, the count of unique endpoints, and a per-endpoint hit count keyed by method + URI. The agent uses this to reason about how complete the library is.

get_unmatched(no arguments)

Returns requests that arrived in MOCK mode but matched no recorded response. This is the gap list — the agent reads it to decide what to record next or what mock to author. Sourced live from the proxy; an unreachable proxy yields an empty list, not an error.

set_modemode (LEARN | MOCK | PASSTHROUGH)

Switches the proxy operating mode. LEARN records all traffic as mocks, MOCK serves recorded responses, PASSTHROUGH forwards upstream without recording. The change is forwarded to the agent and written to the tenant activity log.

create_mockrequest_method, request_uri, response_status (+ optional body/headers)

Authors a mock entry directly — method, URI, status code, and optional request body, response body, and response headers. The mock persists to the library and the proxy is signalled to reload, so it is served on the next matching request in MOCK mode.

Read four, write two

list_services, list_mocks, get_coverage, and get_unmatched only read. set_mode and create_mock are the only tools that change state — and both are recorded: a mode change writes a mode_changed entry to the tenant activity log, and an authored mock is persisted before the proxy reloads. There is no tool to delete data.

A typical agent loop

The tool roster is designed around one workflow: find the gaps, then close them. An agent asked to make a test suite pass against mocks will typically:

Discover

Call list_services to see what upstreams exist, then get_coverage to learn how complete each one's library already is.

Find gaps

Call get_unmatched to read the requests that hit MOCK mode with no recorded response. This is the concrete to-do list.

Record or author

Either set_mode(LEARN) to record real traffic for the missing endpoints, or create_mock to write a response directly when no upstream is reachable.

Serve

Call set_mode(MOCK). create_mock has already signalled the proxy to reload, so the new entries are matched on the next request.

Every tools/callruns the same control-plane logic the dashboard uses. The read tools query the tenant's Postgres-backed library directly; get_unmatched and set_mode forward to the proxy agent; create_mock writes the library entry and then signals the agent to reload. A raw tools/call looks like this:

curl -X POST http://localhost:8000/mcp \
  -H "X-API-Key: $GHOST_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "set_mode",
      "arguments": { "mode": "MOCK" }
    }
  }'

The agent never bypasses the deterministic match cascade. When it switches to MOCK mode, requests are still served exact-match first, then session-verbatim replay, statechart/resource transitions, and smart swap before any AI generation — and AI generation runs on a background worker, never in the request hot path. See How It Works for the full cascade.

Boundaries and safety

The MCP server inherits the product's structural guarantees — it is a control surface, not a back door:

  • Authenticated and tenant-scoped.Every call requires a valid API key and operates only on the calling tenant's data. Gostly is single-tenant per deployment, so in practice the agent sees exactly one environment — its own.
  • Bounded tool surface. The agent can list, inspect, record, switch mode, and author mocks. It cannot delete the library, export data, manage users, or touch billing — those surfaces are not exposed as tools.
  • Redaction still applies. Credential headers are stripped before anything is written to disk, and mocks the agent reads through list_mocks reflect the same scrub boundary as the rest of the library. The MCP server adds no new data path that escapes it.
  • Self-hosted. The server runs inside your own Docker stack. No request, mock body, or coverage report leaves the box because of MCP.

Licensed product vs. OSS proxy

The MCP server is part of the licensed self-hosted product (distributed as docker-compose + container images, no host CLI). The separate open-source proxy is a standalone product with its own command-line interface and does not ship this control-plane MCP surface.

Next steps