Developer docs: all pages

Developers · MCP server

Protocol

Transport, the MCP revisions PorchQ speaks, the headers and fields each needs, and how results are shaped.

Transport

PorchQ serves MCP over Streamable HTTP at https://porchq.com/mcp.

  • Send every request as POST with a JSON-RPC 2.0 body and Content-Type: application/json. PorchQ answers with a single JSON response, never a stream.
  • GET and DELETE answer 405 Method Not Allowed with Allow: POST. PorchQ opens no server-sent event stream and keeps no sessions, so there is no Mcp-Session-Id.
  • A notification (no id) is accepted with 202 Accepted and no body.
  • Batches (a JSON array) are refused with -32600.
  • Every request needs an access token; see Sign-in and tokens.

Revisions

Revision How a client talks to the server
2026-07-28 Stateless: each request carries its version and client capabilities in params._meta; no initialize.
2025-11-25 Opens with initialize, then notifications/initialized.
2025-06-18 Opens with initialize, then notifications/initialized.
2025-03-26 Opens with initialize, then notifications/initialized.

A request that carries io.modelcontextprotocol/protocolVersion in params._meta is served as 2026-07-28. Anything else is served as one of the earlier revisions.

Revision 2026-07-28

Each request stands alone: there is no initialize. It names its protocol version and declares the client’s capabilities in params._meta, and three HTTP headers repeat what the body says.

POST /mcp
Authorization: Bearer kV3n…
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: community_overview

{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "community_overview",
    "arguments": { "property_id": "prop_web4k2m9q7x1v8c3n5b6z0a2s4d" },
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}
  • MCP-Protocol-Version and Mcp-Method are required on every request, Mcp-Name on tools/call. Each must equal the body’s value, or PorchQ answers 400 with -32020. A header may be sent as =?base64?…?= when the value isn’t plain ASCII.
  • io.modelcontextprotocol/clientCapabilities is required (an empty object is fine), or PorchQ answers 400 with -32602.
  • An unsupported version is answered 400 with -32022 and the supported versions in error.data.supported.
  • initialize and ping don’t exist in this revision and answer 404 with -32601.

server/discover

server/discover tells a client what PorchQ supports before it does anything else:

{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "supportedVersions": ["2026-07-28", "2025-11-25", "2025-06-18", "2025-03-26"],
    "capabilities": { "tools": {} },
    "ttlMs": 3600000,
    "cacheScope": "public",
    "resultType": "complete",
    "_meta": { "io.modelcontextprotocol/serverInfo": { "name": "PorchQ MCP Server", "version": "1.5.0" } }
  }
}

Every result says "resultType": "complete" and, in this revision, carries the server’s name and version in _meta.

Revisions 2025-03-26 to 2025-11-25

Open with initialize, then send notifications/initialized:

{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": { "name": "ExampleClient", "version": "1.0.0" } } }

PorchQ answers with your protocolVersion if it supports it, otherwise with 2025-11-25, and with capabilities: { "tools": {} } and its serverInfo. From 2025-06-18 on, send the negotiated version in the MCP-Protocol-Version header on later requests. An unsupported value there is answered 400 with -32022.

ping answers an empty result. server/discover works in these revisions too.

Tools

PorchQ offers tools only: no resources, prompts or sampling yet. tools/list returns all 14 with their input and output schemas, annotations and securitySchemes, and may be cached for 60 minutes (ttlMs, cacheScope: "public"): the list is the same for everyone, and each call is checked on its own.

tools/call answers with:

  • content: a short sentence for the person;
  • structuredContent: the data, described on each tool’s page;
  • isError: true when the tool couldn’t do what was asked, with the reason in content.

An unknown tool name is a protocol error, -32602.

Errors

Code HTTP When
-32700 200 The body isn’t valid JSON.
-32600 200 Not a JSON-RPC 2.0 request, or a batch.
-32601 404 (2026-07-28), 200 (earlier) Unknown method.
-32602 400 or 200 Missing _meta fields, or an unknown tool.
-32020 400 A header doesn’t match the body.
-32022 400 Unsupported protocol version.
-32000 401 No token, or a token that isn’t valid.

Sign-in and permission answers (401, 403) carry a WWW-Authenticate header; see Sign-in and tokens. Rate limits answer 429; see Errors and limits.

Browser origins

A request from a web page (one with an Origin header) is accepted only from PorchQ, https://chatgpt.com, https://claude.ai or a loopback address; anything else gets 403. This protects people against DNS-rebinding attacks. Requests from servers carry no Origin and are unaffected.

This page as Markdown: /developers/mcp/protocol.md

Loading PorchQ…