Skip to content

Migrating from MCP-only to multi-transport

Move an integration from the Model Context Protocol (MCP) stdio transport to Representational State Transfer (REST) or gRPC. Engine behavior does not change. The catalog, risk model, and confirmation gate stay the same. Three things change: wire protocol, authentication, and concurrency model.

Terminal window
composer require nextpdf/server
./vendor/bin/rr get-binary

Early documentation for this package described one transport: MCP over stdio. The package now serves the same tool registry over three transports. To migrate, choose a networked transport, then map your MCP calls to it. You do not need to rewrite your document logic.

Choose the transport that fits your deployment:

  • Stay on MCP for a single local agent, the lowest latency (no network hop), or an MCP-native client, such as a local IDE assistant.
  • Move to REST for multi-client access with per-client API keys, container or Kubernetes deployment, per-client rate limiting, async jobs, or clients in any language.
  • Move to gRPC for typed contracts, server-streaming large PDFs, and mutual-TLS service-to-service deployments.
  • The tool registry and the runtime-dependent catalog (see /connect/tool-catalog/).
  • The four-level risk model and the confirmation gate (see /connect/hitl-risk-tiers/).
  • The document model and engine semantics.
AspectMCP (stdio)RESTgRPC
Wire formatJSON-RPC 2.0 over stdioJSON over HTTPProtobuf over gRPC
Authenticationnone (local subprocess)Authorization: Bearer API keybearer in call metadata
Concurrencyone process, one callRoadRunner worker poolRoadRunner gRPC pool
Asyncnot applicablejob endpointsjob RPCs
Streamingnot applicablesync bodyserver-streaming RPCs

A typical MCP sequence is create_pdf, then content tools, then output_pdf. In REST, this becomes one stateless POST /api/v1/render request with an ordered operations array. When you need step-by-step state, use the opt-in session endpoints instead. In gRPC, the equivalent is the Render RPC, or RenderStream for chunked delivery. For stateful builds, use the CreateSession, SessionOperation, and SessionRender RPCs.

MCP tool sequenceRESTgRPC
create_pdf + content tools + output_pdfPOST /api/v1/renderRender / RenderStream
Stateful build across callsPOST /api/v1/sessions (+ session ops)CreateSession (+ SessionOperation)
Long renderPOST /api/v1/jobs then poll resultSubmitJob then GetJobResult
Tier-gated operationPOST /api/v1/<operation>ExecuteCapability

The MCP call:

{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"add_text","arguments":{"text":"Hello"}}}

becomes the REST request:

Terminal window
curl -sS -X POST http://localhost:8080/api/v1/render \
-H "Authorization: Bearer $NEXTPDF_KEY" \
-H 'Content-Type: application/json' \
-d '{"operations":[{"type":"add_text","text":"Hello"}]}' \
--output hello.pdf

Run both transports during a phased migration. The combined RoadRunner profile serves REST and gRPC from one supervisor. The old MCP integration can keep running locally where it still fits:

Terminal window
export NEXTPDF_API_KEYS_FILE=/run/secrets/api-keys
./vendor/bin/rr serve -c .rr.full.yaml

There is no shared state to migrate. The transports are independent processes over the same engine. Move clients over incrementally.

  • Add authentication. The MCP transport had none because it was a local subprocess. The networked transports require a valid API key on every non-health request. Provision keys before cutover. See /connect/security-and-operations/.

  • The confirmation gate still fires. An approval_required tool challenges in REST and gRPC exactly as it did in MCP. Carry the confirmation flow into the new integration. Do not assume the gate is MCP-only. See /connect/hitl-risk-tiers/.

  • Tier gating is unchanged. A Pro or Enterprise operation needs nextpdf/premium installed and an entitled key on the new transport, just as the corresponding tool needed the package in MCP.

  • Idempotency is new and useful. REST adds an idempotency control that the stdio transport never had. Use it to make job submission safe to retry. See /connect/production-usage/.

MCP is single-process and has the lowest latency for one local agent. The networked transports add a worker pool and a network hop. In return, they scale to many concurrent clients. Move long renders to the async job path on the new transport so workers are not held.

Migrating off stdio adds network exposure. Terminate Transport Layer Security (TLS) in front of REST, use mutual TLS for gRPC on untrusted networks, scope keys per client, and keep enabled_tools minimal. The MCP transport’s no-credential model is safe only because it is a local subprocess. Do not recreate that exposure over a network. See /connect/security-and-operations/.

This page provides migration guidance. Protocol and authentication citations are pinned on /transports/mcp/, /transports/rest/, /transports/grpc/, and /connect/security-and-operations/.

Tier-gated operations require nextpdf/premium regardless of transport. Migrating does not change what is core versus Premium. It changes only how you reach the catalog.

  • /transports/mcp/ — the transport you migrate from
  • /transports/rest/ · /transports/grpc/ — the transports you migrate to
  • /connect/tool-catalog/ — the catalog, identical across transports
  • /connect/hitl-risk-tiers/ — the gate, identical across transports
  • /connect/security-and-operations/ — the authentication you must add