This document is the authoritative reference for which transport modes OpenChrome supports, what stability guarantees apply to each, and how deprecations are announced and enforced.
OpenChrome exposes three transport modes. The package CLI uses stdio by default, enables HTTP with --http [port], and can select explicit modes with the OPENCHROME_TRANSPORT environment variable.
| Transport | Selector | Status | Since | Sunset | Recommended use case |
|---|---|---|---|---|---|
| stdio | default or OPENCHROME_TRANSPORT=stdio |
stable | v1.0.0 | — | Default. Single MCP client over stdin/stdout. Use for Claude Code, Codex CLI, Cursor, Windsurf, and any stdio-native MCP client. |
| Streamable HTTP daemon | --http [port] or OPENCHROME_TRANSPORT=http |
stable | v1.0.0 | — | Long-running daemon serving multiple MCP clients over Streamable HTTP. Binds a local port; auth via bearer token or per-tenant API key. |
| Dual (stdio + HTTP) | OPENCHROME_TRANSPORT=both |
stable | v1.0.0 | — | Run stdio and HTTP simultaneously. Intended for dashboard integrations that need both a direct MCP pipe and an HTTP fan-out endpoint. |
Note on SSE: The
/mcp/sseendpoint is the notification delivery channel inside the HTTP transport — it is not a separate transport mode. When a client connects viaGET /mcp/sse, it receives server-initiated notifications over a persistent SSE stream while issuing requests viaPOST /mcp. Operators should not conflate/mcp/ssewith a distinct transport; the lifecycle of that endpoint is tied to thehttptransport above.
Streamable HTTP:
--httpis OpenChrome's current Streamable HTTP transport surface. UsePOST /mcpfor JSON-RPC requests andGET /mcporGET /mcp/ssefor server-sent event streams.
A transport listed as stable carries the following guarantees across all patch and minor releases within the same major version:
-
Message-shape compatibility. The JSON-RPC 2.0 wire format, method names, and parameter shapes for all requests and responses remain unchanged. A client that works against v1.x.0 will continue to work against v1.x.y and v1.(x+1).0 without modification.
-
Guaranteed events. The following server-initiated notification types are guaranteed to remain available on all stable transports:
notifications/tools/list_changed— emitted when the tool list changes at runtime.- Lifecycle error notifications emitted via
console.errorto stderr (never to stdout, which carries MCP JSON-RPC).
-
Minor-version allowance. Within a major version, minor releases may:
- Add new optional fields to existing messages (additive change, backward-compatible).
- Add new notification types (clients that do not handle them ignore them per the MCP spec).
- Change default port bindings, keepalive intervals, or internal routing — provided the observable wire protocol is unchanged.
- Update authentication mechanisms in an additive way (new auth scheme available; existing scheme continues to work until a separate deprecation notice).
-
What is NOT guaranteed. Internal implementation details — HTTP handler internals, keepalive ping interval, rate-limiter queue depth, SSE connection book-keeping — are not part of the stability contract and may change in any release.
Minimum overlap window: 3 minor versions or 6 months, whichever is longer.
When a transport (or a specific transport feature) is deprecated:
- A GitHub issue is opened announcing the deprecation, the sunset version, and the recommended migration target.
- The transport row in the Supported transports table above is updated to
deprecated, and theSunsetcolumn is filled in. - Starting with the release that announces the deprecation, the server emits a boot-time deprecation warning on stderr whenever the deprecated transport is selected (see Boot-time deprecation warnings).
- The transport is removed no earlier than the later of:
- Three minor version increments after the deprecation announcement (e.g., deprecated in v1.11.0 → earliest removal is v1.14.0), or
- Six calendar months after the deprecation announcement date.
Suppose
httpwere deprecated in v1.11.0 on 2026-05-12.
- Earliest removal by minor-version rule: v1.14.0 (three increments: v1.11 → v1.12 → v1.13 → v1.14).
- Earliest removal by calendar rule: 2026-11-12 (six months later).
- Actual earliest removal: whichever date is later. If v1.14.0 ships on 2026-08-01 (before the 6-month mark), removal is deferred to a release on or after 2026-11-12. If v1.14.0 ships on 2026-12-01 (after the 6-month mark), removal may proceed in v1.14.0.
No transport is currently deprecated. This example is illustrative only.
When the server starts with a deprecated transport selected, it emits a single line to stderr:
[openchrome] DEPRECATION WARNING: transport "<name>" is deprecated as of v<announcement-version>. Sunset: v<sunset-version>. Migrate before that release. See: https://github.com/shaun0927/openchrome/blob/main/docs/transport-lifecycle.md
This line:
- Is emitted via
console.error()(stderr), neverconsole.log()(stdout). stdout carries MCP JSON-RPC and must not be polluted. - Contains the marker string
DEPRECATION WARNINGfor easygrepin CI log scanners. - Names the exact sunset version so operators have a concrete calendar target.
- Links to this document for migration instructions.
Implementation note: The warning emitter is not yet present in the codebase (as of v1.11.0). It will be added in a follow-up code PR when the first transport is actually deprecated. This section specifies the contract that implementation must satisfy.
Current state: No transport is deprecated in v1.11.0. Zero deprecation warnings are emitted at boot for any supported transport.
Switch from the default stdio mode to the Streamable HTTP daemon for multi-client or IDE use cases.
Before (stdio):
# Claude Code auto-configures stdio by default
openchrome serve --auto-launchAfter (Streamable HTTP daemon):
# Start the HTTP daemon on port 3100 (default) with bearer-token authentication
OPENCHROME_AUTH_TOKEN="$(openssl rand -hex 32)" openchrome serve --auto-launch --http
# Or specify a custom port and non-loopback bind address
OPENCHROME_AUTH_TOKEN="$(openssl rand -hex 32)" OPENCHROME_HTTP_HOST=0.0.0.0 openchrome serve --auto-launch --http 4000Configure your MCP client to connect over Streamable HTTP:
{
"mcpServers": {
"openchrome": {
"type": "http",
"url": "http://localhost:4000/mcp",
"headers": { "Authorization": "Bearer YOUR_TOKEN" }
}
}
}For unauthenticated loopback-only development, explicitly opt in and keep the bind address on loopback. Non-loopback HTTP binds require authentication.
OPENCHROME_ALLOW_UNAUTHENTICATED_HTTP=1 openchrome serve --auto-launch --http--http starts OpenChrome's current Streamable HTTP transport. Clients issue JSON-RPC requests with POST /mcp. Clients that need server-initiated notifications can open GET /mcp or GET /mcp/sse as an SSE stream. No additional migration flag is required; the http transport selector remains stable and has no sunset date.
- docs/auth.md — API key store, bearer tokens, OAuth
- docs/roadmap/portability-harness-contract.md — core/pilot tier split and portability principles
- Issue #839 — Streamable HTTP transport implementation history