PPactDocs
MCP & AI agents

Raw HTTP API (curl)

Call Pact's MCP server with plain HTTP — the Streamable HTTP handshake, JSON-RPC framing, and copy-paste curl examples.

Pact's MCP server speaks Streamable HTTP — MCP's standard remote transport: JSON-RPC 2.0 messages POSTed to a single endpoint, with responses returned as JSON or as a short SSE stream. This page is for anyone building a custom client or debugging with curl. If you just want a working client, the TypeScript and Python SDKs handle everything below.

text
Endpoint   https://api.pact.place/mcp/        (keep the trailing slash)
Auth       Authorization: Bearer <pact_live_* key or OAuth access token>
Framing    JSON-RPC 2.0 over POST
Accept     application/json, text/event-stream   (both, on every request)
Session    mcp-session-id header, issued by initialize

Note

There is no WebSocket transport — Streamable HTTP is the remote transport MCP standardizes on. Clients that can only launch stdio servers can bridge with mcp-remote.

1. Initialize a session

The first request is initialize. The response carries the server's capabilities — and, in the mcp-session-id response header, your session id. Capture it:

bash
curl -isS https://api.pact.place/mcp/ \
  -H "Authorization: Bearer pact_live_xxx" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0", "id": 1, "method": "initialize",
    "params": {
      "protocolVersion": "2025-03-26",
      "capabilities": {},
      "clientInfo": { "name": "curl", "version": "0.0.0" }
    }
  }' | grep -i "^mcp-session-id"

2. Confirm initialization

Send the notifications/initialized notification (no id — it's a notification, and the server replies 202 Accepted with no body):

bash
SESSION="<value from step 1>"

curl -sS https://api.pact.place/mcp/ \
  -H "Authorization: Bearer pact_live_xxx" \
  -H "mcp-session-id: $SESSION" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc": "2.0", "method": "notifications/initialized"}'

3. List tools

bash
curl -sS https://api.pact.place/mcp/ \
  -H "Authorization: Bearer pact_live_xxx" \
  -H "mcp-session-id: $SESSION" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}'

Each tool comes back with its inputSchema, so you can build requests — or forms — mechanically. (That's exactly what the in-app tool sandbox does.)

4. Call a tool

bash
curl -sS https://api.pact.place/mcp/ \
  -H "Authorization: Bearer pact_live_xxx" \
  -H "mcp-session-id: $SESSION" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0", "id": 3, "method": "tools/call",
    "params": {
      "name": "query_accounts",
      "arguments": { "search": "Acme" }
    }
  }'

Responses may arrive as plain JSON or SSE-framed (event: message lines with data: payloads) — parse whichever Content-Type the response declares. Results report Pact's guarantees inline: consent_filtered (records hidden because the subject withdrew consent), cost_cents on AI-powered tools, and every call writes one tenant-scoped audit row.

Gotchas

  • Trailing slash. /mcp redirects to /mcp/, and most HTTP clients drop the Authorization header across the redirect — which surfaces as a 401.
  • Both Accept types. Omitting text/event-stream from Accept is a 406 Not Acceptable.
  • Session reuse. Reuse one mcp-session-id for a conversation; sessions are cheap but not free. A 404 on a previously-good session means it expired — initialize again.
  • Scopes. A key without a tool's scope gets a scope error, not an empty result. Scopes per tool are in the tool reference.