MCP server

Connecting

Endpoint, headers, wire format, and batch behavior for the DTPR MCP server.

Connecting

The DTPR MCP server implements a read-only subset of the Model Context Protocol over Streamable HTTP. There is no SSE channel and no server-initiated notifications.

Endpoint

POST https://api.dtpr.io/mcp
HeaderValueRequired
Content-Typeapplication/jsonyes
Acceptapplication/jsonrecommended
mcp-session-idAny opaque string chosen by the clientyes for render_datachainresources/read

GET /mcp returns 405 Method Not Allowed. Server-initiated streams are not supported.

Protocol version

The server advertises protocol version 2025-06-18 in the initialize response. The initialize handshake is optional — you can call tools/list or tools/call directly — but clients that implement it will receive the capability set.

Supported methods

MethodResponse shape
initialize{ protocolVersion, serverInfo, capabilities }
notifications/initializedno response (notification)
initializedno response (unprefixed alias)
tools/list{ tools: ToolDescriptor[] }
tools/call{ structuredContent, content, isError? }
resources/list{ resources: ResourceDescriptor[] }
resources/read{ contents: [{ uri, mimeType, text }] }
ping{}

Unknown methods return JSON-RPC error -32601 Method not found.

Sessions

mcp-session-id isolates cross-call state per session. Its only current use is the render_datachainresources/read ui://dtpr/datachain/view.html handshake: the HTML produced by a tool call lands in a per-session slot and is returned verbatim to the resources/read on the same session id.

Clients that omit the header share a single fallback slot (__dtpr_default_session__). Concurrent callers that both omit the header can read each other's last-rendered HTML — set mcp-session-id to a per-session value to avoid that.

Batch requests

A JSON array of JSON-RPC requests is processed sequentially; responses are returned in a matching array. Per JSON-RPC 2.0 §6, a batch containing only notifications produces no response body — the server returns HTTP 204 No Content instead of an empty array.

Wire format

POST /mcp HTTP/1.1
Host: api.dtpr.io
Content-Type: application/json
Accept: application/json
mcp-session-id: 01HR...

{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "serverInfo": { "name": "dtpr-api", "version": "0.1.0" },
    "capabilities": { "tools": {}, "resources": {} }
  }
}

Example: initialize + list tools

curl -s https://api.dtpr.io/mcp \
  -H 'content-type: application/json' \
  -H 'mcp-session-id: demo-session' \
  --data '[
    {"jsonrpc":"2.0","id":1,"method":"initialize"},
    {"jsonrpc":"2.0","id":2,"method":"tools/list"}
  ]'

Notes

  • No SSE. A single POST returns a single JSON response. If your MCP client insists on text/event-stream, use a Streamable-HTTP-aware transport that falls through to JSON.
  • JSON-RPC 2.0 strictness. jsonrpc must be exactly "2.0"; other values return -32600 Invalid Request.
  • Why hand-rolled. The @modelcontextprotocol/sdk server transport pulls CJS-only Ajv, which workerd's nodejs_compat cannot load. See api/docs/mcp-fallback.md for the full rationale.

See also

  • Envelopeok / err / _meta shape.
  • Resources — the ui://dtpr/datachain/view.html MCP App resource.
  • Tools — the 9 tools.
Copyright © 2026