Integration guides

Custom HTTP client

Drive the HTTP + SSE transport directly from curl or any custom client.

Last updated

Custom HTTP client

This guide drives the MCP server's HTTP transport with raw curl. Use it as a reference when building a bespoke client in any language — the wire format is JSON-RPC 2.0 over HTTP + Server-Sent Events.

Start the server

Per Installation → Self-hosted HTTP:

PLAINWORK_API_KEY=pw_agent_… \
MCP_TRANSPORT=http \
  node apps/mcp/dist/index.js

Default port 9090. All traffic hits /mcp; any other path returns 404.

1. Initialize

curl -i -X POST http://localhost:9090/mcp \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2024-11-05",
      "capabilities": {},
      "clientInfo": { "name": "curl-demo", "version": "0.1" }
    }
  }'

The response headers include mcp-session-id: <uuid>. Capture it; every later request must send it back as a header.

HTTP/1.1 200 OK
mcp-session-id: 6f1e8c3a-…
Content-Type: application/json

2. List tools

SESSION=6f1e8c3a-…

curl -s -X POST http://localhost:9090/mcp \
  -H 'Content-Type: application/json' \
  -H "mcp-session-id: $SESSION" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | jq

The response lists all nine tools with their JSON schemas — the same schemas documented on this site's Tools pages.

3. Call a tool

curl -s -X POST http://localhost:9090/mcp \
  -H 'Content-Type: application/json' \
  -H "mcp-session-id: $SESSION" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "list_collections",
      "arguments": {}
    }
  }' | jq

The JSON-RPC envelope wraps a result.content array; the first element is a { "type": "text", "text": "<serialized JSON>" } block.

4. Stream server messages (SSE)

curl -N -H "mcp-session-id: $SESSION" \
  http://localhost:9090/mcp

The response stays open and streams text/event-stream frames. Most consumers don't need this; tools respond directly to the matching POST.

5. Terminate the session

curl -s -X DELETE http://localhost:9090/mcp \
  -H "mcp-session-id: $SESSION"

Omitting the DELETE is fine — sessions die when the transport closes or the process exits — but explicit cleanup is nicer in a script.

Building a real client

  • Use a JSON-RPC 2.0 library if your language has one; the envelope is boring but unforgiving about id / jsonrpc / method / params.
  • Keep the session ID in a single place in your client; losing it forces a re-initialize and the next call starts with no prior tool capability info.
  • Treat tool responses as opaque text blocks — even numeric or boolean returns come through as stringified JSON inside content[0].text.
  • Errors surface as either HTTP errors (4xx/5xx from the transport layer) or JSON-RPC error objects (from the tool layer). Handle both.

See also