Skip to main content

MCP Observatory

MCP Observatory now includes a two-phase execution pattern for high-risk MCP tool calls, with a generic proposer/verifier wrapper that can be reused by any tool:

  1. PROPOSE: plan/simulate, evaluate uncertainty/integrity, no side effects.
  2. COMMIT: execute side effects only when a signed commit token is valid.

Two-Phase Sequence (Text Diagram)

Client
  -> transfer_funds_propose(amount,to)
      -> scoring(output_instability, numeric_variance, prompt_drift)
      -> decision:
          - blocked: deterministic fallback (create_draft), no side effects
          - allowed: issue signed commit_token bound to tool args hash
  <- {proposal_id, commit_token?}

Client
  -> transfer_funds_commit(proposal_id, commit_token, amount, to)
      -> verify signature + expiry + proposal existence + args_hash binding + nonce replay
      -> if valid: perform side effect (funds transfer)
      -> else: block with explicit reason
  <- commit outcome

New Modules

  • mcp_observatory/proposal_commit/hashing.py
    • canonical JSON hashing for stable tool_args_hash
    • normalized prompt_hash
  • mcp_observatory/proposal_commit/scoring.py
    • output_instability = 1 - jaccard_similarity
    • numeric_variance from extracted numbers
    • prompt_drift from prompt hash vs baseline
    • weighted renormalized composite_score
    • demo model_generate(prompt, temperature) stub
  • mcp_observatory/proposal_commit/token.py
    • HMAC-SHA256 token issue/verify
    • payload fields: token_id, proposal_id, tool_name, tool_args_hash, issued_at, expires_at, nonce, composite_score
  • mcp_observatory/proposal_commit/proposer.py
    • generic ToolProposer.propose(...) for any tool name/args
    • deterministic blocked fallback
  • mcp_observatory/proposal_commit/verifier.py
    • commit verification and nonce replay protection
  • mcp_observatory/proposal_commit/storage.py
    • in-memory storage fallback
    • optional Postgres storage via asyncpg
  • mcp_observatory/core/wrapper_api.py
    • generic InvocationWrapperAPI for wrapping either agent or model invocations
    • captures input/output hashes, token/cost metrics, and emits allow/review/block decisions
  • mcp_observatory/instrument.py
    • adds instrument_wrapper_api(...) helper for fast wrapper setup
  • mcp_observatory/demo/server.py
    • MCP-like tools:
      • transfer_funds_propose
      • transfer_funds_commit
  • mcp_observatory/demo/run_demo.py
    • propose -> commit -> replay-attempt demo
  • sql/schema.sql
    • Postgres tables: proposals, commits, nonces, tool_prompt_baselines

Security / Verification Rules

Commit verifies all of the following:

  • token signature is valid (bad_signature on failure)
  • token not expired (expired)
  • proposal exists and was allowed (unknown_proposal)
  • commit args hash equals token payload args hash (args_hash_mismatch)
  • nonce has not already been used (nonce_replay)

Deterministic Fallback on Proposal Block

Blocked proposal response is deterministic and side-effect free:

{
  "status": "blocked",
  "action": "create_draft",
  "reason": "low_integrity",
  "draft": {"tool": "transfer_funds", "amount": 100, "to": "acct_123"}
}

Environment Variables

Variable Default Description
MCP_OBSERVATORY_TOKEN_SECRET (none — required) HMAC secret for TokenIssuer/TokenVerifier (the v2 control-plane execution token).
MCP_OBSERVATORY_COMMIT_SECRET (none — required) HMAC secret for CommitTokenManager (the propose/commit token).
MCP_OBSERVATORY_ALLOW_DEV_SECRET unset Set to 1 to allow the library's known development secrets when the two variables above are unset. Local development and tests only — the default secrets are public (they are in this repository's source) and a production deployment that relies on them is signing tokens with a key anyone can look up. The bundled demos (mcp_observatory.demo.server, mcp_observatory.demo.real_world_server) set this automatically, with a loud warning, so they keep running with no configuration.
MCP_OBSERVATORY_MAX_INPUT_BYTES 10240 Ceiling, in UTF-8 bytes, on the canonical JSON of tool_args and on any single text input (answer, retrieved context, tool result summary, prompt, candidate outputs) before it is scored. Scoring cost is linear in input size (docs/gate-properties.md P5), so the gate has no latency bound of its own without this. Over the limit, core/interceptor.py's v2 path routes to the fallback and proposal_commit/proposer.py returns a blocked response, both with reason input_too_large, instead of hashing or scoring the oversized input.
MCP_OBSERVATORY_PG_DSN (or DATABASE_URL) unset Postgres DSN for create_storage_from_env()/PostgresExporter. Falls back to in-memory storage when unset.

Neither secret variable has a default: constructing TokenIssuer, TokenVerifier, or CommitTokenManager without an explicit secret and without one of these set raises InsecureDefaultSecretError (mcp_observatory.utils.secrets) rather than silently signing with a hardcoded value.

Running the Demo

Without Postgres (default)

No env vars needed; in-memory store is used.

python -m mcp_observatory.demo.run_demo

With Postgres

  1. Set DSN:
export MCP_OBSERVATORY_PG_DSN='postgresql://user:pass@localhost:5432/postgres'
  1. Apply schema:
psql "$MCP_OBSERVATORY_PG_DSN" -f sql/schema.sql
  1. Run demo:
python -m mcp_observatory.demo.run_demo

Testing

PYTHONPATH=. pytest -q

The suite includes tests for token verification, hash stability, replay protection, and expired-token rejection.

Real-World MCP Scenario Demo (10 End-to-End Flows)

A realistic MCP server example is available at:

  • mcp_observatory/demo/real_world_server.py
  • executable shim: examples/real_world_mcp_server.py
  • executable client: examples/real_world_mcp_client.py
  • prompt-to-invocation MVP: examples/prompt_to_mcp_invocation_mvp.py
  • OpenAI GPT utility: examples/openai_prompt_to_mcp_invocation.py

It includes:

  • 10 distinct prompts mapped to 10 different MCP tool handlers
  • per-invocation annotations (e.g. destructiveHint, idempotentHint, openWorldHint)
  • proposal/commit execution for HIGH-risk tools (no secondary-response gating)
  • irreversible actions never pass a secondary LLM response
  • simulated LLM responses and grounding summaries for standard-risk tools
  • deterministic fallback routing for blocked/review-required scenarios
  • prompt-to-invocation MVP now extracts required tool parameters from user prompts before server invocation
  • openai-gpt utility for service selection + parameter extraction + MCP invocation

Run server demo:

python examples/real_world_mcp_server.py

Run client demo (client interacting with server):

python examples/real_world_mcp_client.py

Run prompt -> LLM planner -> server invocation MVP:

python examples/prompt_to_mcp_invocation_mvp.py

Run OpenAI GPT utility (manual, requires OPENAI_API_KEY):

python examples/openai_prompt_to_mcp_invocation.py

Optional (recommended): install OpenAI SDK for first-class client support (client auto-detects and uses SDK when available; otherwise it uses HTTPS fallback):

pip install -e .[openai]

Wrapper API (Agent or Model Invocation)

Use the wrapper to route either agent-side orchestration calls or direct model calls through a single observability envelope.

from mcp_observatory.instrument import instrument_wrapper_api

wrapper = instrument_wrapper_api("my-service")

result = await wrapper.invoke(
    source="agent",
    model="gpt-4o-mini",
    prompt="Generate deployment plan",
    input_payload={"request_id": "abc123", "task": "deployment_plan"},
    call=lambda: {"plan": "blue-green rollout"},
)

print(result.decision.action)  # allow/review/block
print(result.span.cost_usd)

Dual-run measurement is supported with dual_invoke=True and shadow parameters (shadow_source, shadow_model, shadow_agent_params, shadow_model_params, and shadow_call) to compare alternate execution paths and capture disagreement metrics.

The wrapper output (WrapperResult) includes:

  • output: raw callable output
  • span: captured telemetry metrics (tokens, cost, hashes, timing)
  • decision: policy decision suitable for downstream execution routing
  • shadow_output and shadow_span (when dual_invoke=True) with comparison metrics on primary span (shadow_disagreement_score, shadow_numeric_variance)

AWS Integration (mcp_observatory.aws)

Common wiring extracted from services that deploy this library on AWS Lambda. Install the extra to use it:

pip install mcp-observatory[aws]

Importing mcp_observatory.aws never requires boto3 — it is imported lazily on first use, so the rest of the library still imports fine without it.

from mcp_observatory.aws import DynamoDBSpanExporter, build_gate

# Writes every populated TraceContext field to a DynamoDB table (name from
# OBSERVATORY_METRICS_TABLE, or pass table_name=) with a TTL attribute.
exporter = DynamoDBSpanExporter(ttl_seconds=90 * 24 * 60 * 60)

# Wires an InMemoryStorage- (or Postgres-, when MCP_OBSERVATORY_PG_DSN is
# set) backed ToolProposer + CommitVerifier sharing one CommitTokenManager.
# secret_env/block_threshold_env let each service keep its own env var
# names; the secret still fails closed per the Environment Variables table
# above.
proposer, verifier, token_manager = build_gate(
    secret_env="OBSERVATORY_SECRET_KEY",
    block_threshold_env="OBSERVATORY_BLOCK_THRESHOLD",
)

There is no observe_model_request-style helper here: the services this was extracted from do not agree on its shape (see CHANGELOG.md 0.3.0), so none is provided.

Metadata

Release files for mcp-observatory 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-observatory 0.3.0
File Size Uploaded Provenance
mcp_observatory-0.3.0.tar.gz 74.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-observatory 0.3.0
File Interpreter ABI Platform
mcp_observatory-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 152.5 kB

Release files / mcp_observatory-0.3.0.tar.gz

Download URL mcp_observatory-0.3.0.tar.gz
Size 74.5 kB
Tags Source
SHA-256 checksum
How to use checksums
cbe9b5c77ab47e412eaa54ff14c8864ef4f883711703c0c7b7d470374bace6f6
BLAKE2b-256 checksum
How to use checksums
3837b5991782e9bf896620cd410a5ab1616165c1f8eb29005e1f9586547cdb23
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Release files / mcp_observatory-0.3.0-py3-none-any.whl

Download URL mcp_observatory-0.3.0-py3-none-any.whl
Size 78.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
89a5e762771d1230f7ecdd535444460a2fb9b58cacd87e8089cffdf134b26549
BLAKE2b-256 checksum
How to use checksums
0457ab35918c2a38541dcf6303adc0aa135386bb211bea90088539f80ef60d8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

Security for mcp-observatory 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for mcp_observatory-0.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page