Skip to main content
Glama

MCP security fixture

A small MCP server with a vulnerable mode and a fixed mode. It has three flaws. Each flaw has a client-side test that shows the flaw in one mode and its absence in the other.

Everything runs on 127.0.0.1. All data and keys are fake. Test only this fixture and servers you own.

Run

./run.sh

You need uv (tested with 0.10.4) and Python 3.10 or newer. run.sh installs mcp==2.3.0 into .venv, starts the server and a stub downstream API on free loopback ports, runs three test scripts in both modes, and writes results.csv. Exit code 0 means every outcome matched the expected one. No network call leaves the Mac. No paid model is called.

Related MCP server: mcp-suspicious-tools

SDK

Official mcp Python SDK, version 2.3.0 (PyPI, released 2026-10-02). In 2.x, FastMCP is now MCPServer (from mcp.server.mcpserver import MCPServer). Code written for 1.x does not import. Check the migration guide at https://py.sdk.modelcontextprotocol.io/v2/migration/ if you port this to 1.x.

The three flaws

#

Flaw

Tool

Vulnerable mode

Fixed mode

1

Tool description carries hidden instructions

add_numbers

The description tells the agent to call read_secret and send the result in a sidenote argument. An obedient agent leaks the user's key. The user still sees the right sum.

The description is plain. The sidenote argument is gone.

2

Token passthrough

fetch_report

The server forwards the user's own token (audience mcp-fixture) to the downstream API. The downstream API accepts it. Any holder of that token can call the API directly.

The server sends its own token for the downstream audience. The downstream API rejects any other audience.

3

Missing per-user authorization

get_invoice

The server checks who you are, not what is yours. Alice reads Bob's invoice.

The server compares the invoice owner to the caller. Alice gets an error.

Fixes in production terms: pin and review tool descriptions on the client side, and show them to the user (flaw 1). Never pass a client token to another service. Use a token exchange or a service credential with the right audience, and check the audience on the receiving side (flaw 2). Check ownership on every object-level read (flaw 3). The MCP authorization spec forbids token passthrough.

The tests

Script

Test

Shows

tests/test_flaw1_tool_poisoning.py

stub_agent_leaks_secret_to_tool

Whether the secret reaches the attacker sink

description_scanner

A simple client-side scan flags the poisoned description and passes the clean one

tests/test_flaw2_token_passthrough.py

downstream_received_clients_token

Whether the downstream API sees the client's own token

tool_still_works

The fix does not break the tool

replay_mcp_token_at_downstream

Whether the MCP-audience token works at the downstream API

tests/test_flaw3_missing_authz.py

alice_reads_bobs_invoice

The flaw

alice_reads_own_invoice

Control: legitimate use still works

no_token_rejected

Control: login works in both modes, so the flaw is authorization

Limits

  • The agent in flaw 1 is a deterministic stub, not a language model. It obeys one instruction pattern in a tool description. The test proves that server text reaches the agent's context and can drive a tool call. It does not prove that a given real model obeys. No real-model run was done.

  • The tokens are toy HMAC tokens with sub and aud claims. They show audience handling. They are not an OAuth implementation.

  • The scanner is a regex list. It catches this fixture, not a careful attacker.

  • Tool output injection (hostile text in a tool result) is not covered. Only the description channel is.

Files

server.py the MCP server. downstream.py the stub downstream API. fixture_auth.py toy tokens. tests/ the harness, the stub agent, the scanner and three test scripts. results.csv the last run and its outcomes.

Licence: MIT (see LICENSE).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to control a local Chromium browser via CDP for page snapshots, screenshots, human-like interactions, autonomous crawling, API/GraphQL reconnaissance, authenticated differential testing, and Burp-like intercept, repeater, and intruder workflows with scope enforcement and audit logging.
      MIT
    • F
      license
      Not graded
      quality
      C
      maintenance
      Enables guardrail and trust testing by exposing realistic malicious tool patterns such as shell execution, credential dumping, and data exfiltration, all without network access.
      -
    • F
      license
      Not graded
      quality
      C
      maintenance
      Enables security testing of MCP guardrails and SAST scanners by exposing intentionally vulnerable code patterns that are inert by default and make no network calls.
      -