Skip to main content

Runtimes — reference

In v1.0 the spec repository normatively fixes three runtime adapters. Every binding must implement all three.

Property table

Propertyin_processmcp_stdiomcp_http
Where the plugin runsIn the same process as the hostIn a separate subprocess, communicating via stdin/stdoutIn a separate host, communicating via HTTP
Cross-languageHost language onlyAny language (via the MCP protocol)Any language
SerialisationNot required (native objects)JSON (line-delimited)JSON (HTTP body)
Call latencyNanoseconds / microsecondsTens of microsecondsMilliseconds (network)
Isolation from the host processNoneYes (separate process)Yes (separate host)
Transient errorsImpossibleImpossiblePossible (network, timeout)
Deploy independent of the hostNoYes (subprocess with its own version)Yes
Streaming supportYes (native iterator)Limited (line-delimited)Limited (SSE / WebSocket)
Requires MCP handshakeNoYesYes
Retry on call failureApplication's responsibilityCore may retry with backoffCore may retry with backoff
Suitable for hot paths with strict latency requirementsYesNo (serialise + IPC)No (serialise + network)

in_process

Runtime-specific manifest fields

FieldTypeRequiredDescription
entry_pointstringYes"module:ClassName". The module is loaded via importlib.util.spec_from_file_location (for Python) or its equivalent.

Example

[plugin]
runtime = "in_process"
entry_point = "plugin:OpenAIPlugin"

Plugin code contract

  • The plugin is a class implementing the protocol of its kind (derived from the hookspec).
  • setup(ctx) and teardown() are ordinary class methods.
  • Runtime invariants 1–8 must hold (see Runtime invariants).
  • Runtime invariant 2 (serialisability) is recommended, not required (the plugin may pass native objects within the host).

mcp_stdio

MCP = Model Context Protocol. JSON-RPC 2.0 over line-delimited JSON on the subprocess's stdin/stdout.

Runtime-specific manifest fields

FieldTypeRequiredDefaultDescription
commandstring[]YesLaunch command. The first element is the executable; the rest are arguments.
working_dirstringNohost cwdSubprocess working directory.
envobjectNo{}Environment variables. The host adds these on top of its own.
startup_timeout_secintNo30Initial MCP handshake timeout.

Example

[plugin]
runtime = "mcp_stdio"

[plugin.mcp_stdio]
command = ["python", "-m", "my_plugin.server"]
startup_timeout_sec = 45
env = { PYTHONUNBUFFERED = "1" }

Plugin code contract

  • The plugin is any executable that implements the MCP protocol: it reads requests from stdin and writes responses to stdout.
  • Tooling: mcp-sdk for Python / TypeScript / Go.
  • Every hook input and output must be JSON-serialisable.
  • The plugin may crash without affecting the host process; the host restarts the subprocess as needed.

mcp_http

JSON-RPC 2.0 over HTTP (POST with a JSON body).

Runtime-specific manifest fields

FieldTypeRequiredDefaultDescription
urlstringYesBase URL of the MCP service (no trailing slash).
auth_headerstringNoHTTP header name for the bearer token.
auth_secret_envstringNoName of the env variable from which the host reads the secret value.
timeout_secintNo60Per-request HTTP timeout.
tls_ca_bundlestringNosystem CAPath to a CA bundle (for corporate self-signed certificates).
tls_verifyboolNotrueWhether to verify the server certificate. false is permitted only in dev — forbidden in production.

Example

[plugin]
runtime = "mcp_http"

[plugin.mcp_http]
url = "https://plugins.example.com/tool/v1"
auth_header = "X-API-Token"
auth_secret_env = "EXAMPLE_API_TOKEN"
timeout_sec = 120
tls_ca_bundle = "/etc/ssl/certs/corp-ca.pem"

Plugin code contract

  • The plugin is an HTTP service available at the given URL and implementing MCP.
  • All mcp_stdio requirements apply, plus its own: certificate validation, network-error handling, server-side rate limiting.
  • The host retries transient errors (5xx, connection reset) with exponential backoff.

Multiple runtimes in a single plugin

A plugin may declare several runtime adapters:

runtime = ["in_process", "mcp_stdio"]

[plugin.mcp_stdio]
command = ["python", "-m", "my_plugin.server"]

The host picks a runtime at load time. Typical scenarios:

  • Python host, Python pluginin_process is chosen for performance.
  • TypeScript host, Python pluginmcp_stdio is chosen (TypeScript cannot import Python modules).
  • Heterogeneous deploymcp_http is chosen if the plugin is already deployed as a SaaS.

If the host supports none of the listed runtime adapters, the plugin is marked RuntimeNotSupported.

Choosing a runtime adapter — flowchart

Plugin in the same language as the host?
├── Yes:
│ ├── Need isolation? ─── No, performance matters ────── in_process
│ └─────────────────── Yes, untrusted code ──────────── mcp_stdio
└── No:
├── Plugin is an external service (SaaS, microservice) ── mcp_http
└── Local plugin in another language ──────────────────── mcp_stdio

See also