Prism
Stateless MCP gateway. Sits between an AI client and an MCP server, relays
JSON-RPC verbatim, and turns every call into an OpenTelemetry span — shipped
over OTLP to any endpoint you choose. No database, no accounts, no
provisioning. See docs/PRISM.md for the full spec.
Fastest path to a live dashboard: get a free key at
telinea.terradev.cloud, set one destination,
and every span appears in Telinea within seconds.
Run
Where spans go
One pipeline, one egress primitive: PrismSpan → Serializer → Dispatcher.
Prism knows four destination schemes and nothing about backends:
https:// / http:// — POST serialized spans to any OTLP endpoint.
Grafana, Honeycomb, a collector, Telinea — read the backend's own docs for
its endpoint and auth header, fill in two fields, done.
file:// — append JSONL to a local path. No account, no network.
stdout:// — human-readable lines for development.
multi://a,b — fan-out to named destinations; failures are isolated.
Configure in ~/.prism/config.toml (or ./prism.toml, or PRISM_CONFIG):
Formats: otlp_json (default — the industry wire standard), otlp_proto
(needs pip install opentelemetry-proto), jsonl, telinea (native
envelope for Telinea ingest).
Every field has an env override — secrets never need to touch disk:
Hosted mode: "Authorization" = "Bearer {token}" resolves {token} to the
caller's bearer per span — each user's spans land in their own account.
Delivery: buffered, flushed every 5 s or 512 spans; Retry-After honored on
429 for every backend; failed batches go to a dead-letter ring buffer
(10k spans) retried on backoff; on shutdown, in-flight spans drain and the
dead-letter buffer is written to ~/.prism/deadletter.jsonl and replayed on
next start. Fire-and-forget — Prism never blocks a chat session on a flush.
Client config
The entire integration is a URL swap plus headers:
X-Prism-Upstream — the real MCP server. Must match PRISM_UPSTREAM_ALLOW.
X-Prism-Upstream-Authorization — forwarded upstream as Authorization.
X-Prism-Capture — none (default) | args | args,results. Redacted.
X-Prism-Sample — 0.0–1.0, sampled once per session.
Header-less clients can encode the upstream in the path:
POST /mcp/u/{base64url(upstream)}.
Registries (Smithery et al.)
Registry installs can't set custom headers — config arrives as query params.
Every X-Prism-* option has a query-param twin:
upstream → X-Prism-Upstream (or set PRISM_DEFAULT_UPSTREAM for
single-upstream deployments)
api_key / token → Authorization / X-Api-Key
upstream_authorization → X-Prism-Upstream-Authorization
project, env, role, capture, sample → their X-Prism-* twins
smithery.yaml in this directory is the registry manifest for the
self-hosted container path; the hosted listing just points at
https://prism-mcp.terradev.cloud/mcp.
What you get
One MCP session = one trace. One JSON-RPC request = one span. Tool failures
surface correctly (result.isError → ERROR, not a green 200). With a Telinea
destination, every Prism-fronted server also appears on the Telinea Gateway
board via the endpoint attribute — p50/p95/p99, req/min, sparkline — with
no backend changes.
Not built (by design)
- No backend-specific serialization. If a backend needs a proprietary format,
run an OpenTelemetry Collector and point Prism at it — that's what the
Collector is for.
- No query layer, storage, or UI. Prism emits; Telinea stores and visualizes.
- Legacy HTTP+SSE transport (
/sse + /messages, 2024-11-05 spec).
- DNS-rebinding-safe IP pinning at the transport layer (see
guard.py).