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.4.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.4.0
File Size Uploaded Provenance
mcp_observatory-0.4.0.tar.gz 82.0 kB With provenance Details

Built distribution (wheel)

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

Total release size: 164.2 kB

Release files / mcp_observatory-0.4.0.tar.gz

Download URL mcp_observatory-0.4.0.tar.gz
Size 82.0 kB
Tags Source
SHA-256 checksum
How to use checksums
78440d62b54bcd548e4f42e680520afffbd72cd94f8e4573fce8623e227fe033
BLAKE2b-256 checksum
How to use checksums
f6d8b7bb8d08d88a1bb82f5550255720f41889a3b68b9a4dea03dd794b492eb5
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 14, 2026.

Transparency log

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

Download URL mcp_observatory-0.4.0-py3-none-any.whl
Size 82.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
146050b7de924d92898ee4527290af522c9c1435be8716bc2a3b1915eb4fd885
BLAKE2b-256 checksum
How to use checksums
05335d27036613a3ff444aa607b9ab4c34f2734b5411aadb71805057b68893d3
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 14, 2026.

Transparency log

Security for mcp-observatory 0.4.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.4.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 14, 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