Skip to main content

MCP Server Overview

The MCP server is mounted inside the Nest API as a normal module (src/mcp/). It exposes one endpoint and speaks the Model Context Protocol over streamable HTTP.

Endpoint

MethodPathBehaviour
POST/mcpJSON-RPC MCP requests (initialize, tools/list, tools/call).
GET/mcp405 — the endpoint is stateless, there is no SSE session.
DELETE/mcp405 — no sessions to tear down.

Default base URL in local dev: http://localhost:4000/mcp (the API listens on PORT, default 4000).

Authentication

The endpoint is protected by the same guard as the rest of the API (ApiKeyOrClerkGuard). It accepts either:

  • an Unkey API key (Authorization: Bearer vld_…) — the intended path for machine clients, or
  • a Clerk session JWT (dashboard users).

The workspace is derived from the credential — there is no :workspaceId in the path. An API key is bound to exactly one workspace, so every tool call it makes is automatically scoped to that workspace. This is what keeps tenants isolated even though all clients hit the same URL.

Create an API key from the dashboard (or the API-keys endpoints) before connecting; the plaintext key is shown only once.

Statelessness

Each request builds a fresh MCP server and a fresh transport (StreamableHTTPServerTransport with no session id), handles the request, and tears both down when the response closes. There are no long-lived sessions to store or expire, which keeps the endpoint horizontally scalable and simple to reason about.

How tools do their work

Tools don't reimplement anything — they delegate to the same services the REST API uses:

  • Lists — verify the target list belongs to the caller's workspace.
  • Columns — ensure/create the column that results are written into.
  • AI execution — run the AI-column pipeline over the list's records.

For research_company, that pipeline fans out one Hatchet ai-column-execution run per record, and each result is persisted into the record's fields under the column's key. Because execution is asynchronous, the Hatchet worker must be running (bun run worker:dev) for cells to fill in.

Prerequisites checklist

  • API running — bun run start:dev
  • Worker running — bun run worker:dev
  • API keys configured — UNKEY_ROOT_KEY and UNKEY_API_ID set
  • AI gateway enabled — AI_GATEWAY_ENABLED not set to false
  • A workspace API key created (vld_…)