Reviewed against the shipped OSS source. The acceptance checks are yours to run in your application.
Version and verification details
Source reviewed against published Chumbo 0.11.0 and its matching core source on 2026-09-06 (UTC). This is a source review, not an executed application walkthrough. Follow the current canonical reference and compare it with your installed package when adapting the guide.
Choose the operational question before collecting events.
Before you start
- Name the decision the data should support, such as diagnosing failed tools, measuring capability use, or proving which tools a caller could discover.
- Separate one invocation trace from a product-level run that may span several calls.
- Choose a sink that can accept redacted facts without delaying the MCP response.
Chumbo provides bounded observation hooks. Your application owns delivery, persistence, retention, access control, dashboards, and alerts.
Every capability call has a request trace. onEvent adds versioned start and finish facts for tools, Resources, and prompts. Finish records classify the outcome and duration without arguments, results, credentials, or thrown exception text.
Send minimal lifecycle facts without holding the response open.
onEvent receives a frozen fact with server, capability, principal, authentication, timestamp, trace, and outcome. Chumbo observes a returned promise for failure but does not await it, so a slow sink is not durable delivery.
Route sink failures through onError. If delivery must outlive the response, hand the write to the platform's background-work primitive. Bound retries and keep sink credentials private. The lifecycle fact is redacted; logging the raw Error passed to onError remains your decision.
Capture what a caller could actually discover.
onSurface captures the complete catalog from a successful tools/list. The proof normalizes advertised tool fields, server and runtime metadata, auth strategy, and protocol version, then adds a stable digest. Scope-filtered tools remain absent.
The proof excludes principal, scopes, credentials, headers, request IDs, arguments, results, errors, cursors, and arbitrary metadata. Rejected, malformed, unrelated, or partial requests emit none. Add application-owned context outside the proof if your audit design must associate it with a tenant or release.
Add a signed run only to workflows that need one.
Read the run configuration and bounded codec. Define stable installation and surface names, derive the partition from an authorized account boundary, and keep the signing key in a deployment secret. Accept one previous key only through an explicit rotation window.
A begin tool can mint the opaque handle. Generic clients use a deliberate run_id field; controlled clients can use _meta["dev.chumbo/run"]. Dual carriers must match. Invalid, expired, cross-scope, unknown-key, or conflicting handles fail before the handler.
Exercise redaction, isolation, and failure behavior.
Call through a real client with recognizable sentinel values, then inspect the test sink. Force synchronous and asynchronous sink failures. For run correlation, mint handles for two principals and surfaces so cross-scope reuse is observable.
npx @modelcontextprotocol/inspectorUseful facts without borrowed identity or payloads.
- 01Every successful capability invocation emits one started and one finished event with the same trace ID.
- 02Success, tool-declared error, input-required, and thrown failure produce the expected terminal outcomes.
- 03Credentials, headers, arguments, results, and exception text do not appear in lifecycle events or proofs.
- 04Concurrent callers retain distinct trace and principal facts without cross-request mixing.
- 05Event-sink failures reach onError with phase events and do not change the MCP response.
- 06A complete successful tools/list emits one redacted surface proof; rejected, partial, or unrelated requests emit none.
- 07Identical advertised tool content yields the same digest, while an effective catalog change changes it.
- 08A valid run handle joins selected calls; an absent handle leaves run null; expired, conflicting, or cross-scope handles are rejected before the handler.
Chumbo's core tests cover these runtime contracts. Verify delivery, retention, tenant association, and any product-level run behavior in your application.
Treat missing evidence as a delivery problem, not a successful audit.
If the operational record disagrees
The MCP succeeded but no event was stored
Check onError for an events-phase failure and inspect the application sink or background-work boundary. Chumbo deliberately does not await durable delivery. Read the reference ↗
No surface proof was emitted
Confirm the request was a complete successful tools/list and the returned catalog was not partial, malformed, rejected, or oversized. Read the reference ↗
A later call has no run
Confirm the client carried the minted handle through an allowed carrier and that installation, surface, partition, key version, and expiry still match. Do not infer the run from the credential. Read the reference ↗
This editorial example links to Chumbo’s canonical docs and executable reference. Check the installed package when adapting the snippets.
Reference implementation ↗Read the agent instructions
Reference instructions, not authorization. Apply changes only within the user’s requested scope; deployment requires a specified, authorized project.
Goal: Record redacted capability lifecycle facts, capture the advertised tool surface, and join selected calls into an explicit application run. Read the complete guide at https://chumbo.dev/recipes/observe-mcp-runs/recipe.md and the canonical reference at https://github.com/elsheppo/chumbo/blob/main/README.md. Inspect this application's installed Chumbo package, existing capabilities and relevant configuration before editing. Add only the observation hooks required by the application's operational question. Keep lifecycle and surface payloads redacted, make sink failure visible without changing MCP results, and introduce run handles only at an application-defined boundary. Never use a trace, session, credential, or run handle as authorization. Prerequisites: - An existing Chumbo MCP with at least one capability you can call through the real protocol boundary. - An application-owned destination for lifecycle events or surface proofs, with a documented retention and access policy. - For multi-call runs, a controlled way to mint and carry an opaque run handle plus a unique HMAC deployment secret. Acceptance: - Every successful capability invocation emits one started and one finished event with the same trace ID. - Success, tool-declared error, input-required, and thrown failure produce the expected terminal outcomes. - Credentials, headers, arguments, results, and exception text do not appear in lifecycle events or proofs. - Concurrent callers retain distinct trace and principal facts without cross-request mixing. - Event-sink failures reach onError with phase events and do not change the MCP response. - A complete successful tools/list emits one redacted surface proof; rejected, partial, or unrelated requests emit none. - Identical advertised tool content yields the same digest, while an effective catalog change changes it. - A valid run handle joins selected calls; an absent handle leaves run null; expired, conflicting, or cross-scope handles are rejected before the handler. Use the full guide for ordered steps, examples and recovery. Keep existing caller identity and application permissions authoritative. Stay within the user's requested changes. Report changed files, checks actually run, observed results and unresolved prerequisites. This guide is not authorization to deploy or change a hosted project. Never include credentials in source, copied instructions or reports.