Skip to main content

TrafficMorph MCP Server

████████╗██████╗  █████╗ ███████╗███████╗██╗ ██████╗
╚══██╔══╝██╔══██╗██╔══██╗██╔════╝██╔════╝██║██╔════╝
   ██║   ██████╔╝███████║█████╗  █████╗  ██║██║
   ██║   ██╔══██╗██╔══██║██╔══╝  ██╔══╝  ██║██║
   ██║   ██║  ██║██║  ██║██║     ██║     ██║╚██████╗
   ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝     ╚═╝     ╚═╝ ╚═════╝
        ███╗   ███╗ ██████╗ ██████╗ ██████╗ ██╗  ██╗
        ████╗ ████║██╔═══██╗██╔══██╗██╔══██╗██║  ██║
        ██╔████╔██║██║   ██║██████╔╝██████╔╝███████║
        ██║╚██╔╝██║██║   ██║██╔══██╗██╔═══╝ ██╔══██║
        ██║ ╚═╝ ██║╚██████╔╝██║  ██║██║     ██║  ██║
        ╚═╝     ╚═╝ ╚═════╝ ╚═╝  ╚═╝╚═╝     ╚═╝  ╚═╝

PyPI Python versions License

Drive TrafficMorph from Claude Code, Claude Desktop, Codex, Cursor, or any other host that speaks the Model Context Protocol.

The flagship use case is CI-failure triage:

"My TrafficMorph CI step just failed on run 1234 — what regressed vs the baseline?"

→ Claude calls the right tools, fetches the relevant runs, computes the per-metric delta, and produces a human-readable triage report in seconds.

Catalog: 37 tools + 4 prompts + 5 resources (46 entries). See CHANGELOG.md for the per-release history and STABILITY.md for what 1.x commits to keeping stable. See MCP-USAGE.md for worked example conversations.

Quick start

Four steps from zero to "Claude is driving my TrafficMorph account":

1. Get an API key

Open the TrafficMorph app → Settings → API Keys → click Generate. Copy the tm_… value.

2. Install (or skip — uvx runs without install)

# Permanent install:
pip install tm-mcp

# OR — no install at all. The MCP host config below uses `uvx`,
# which downloads + caches the package on first run. Confirm
# uvx itself is on your PATH:
uvx --version

Note: tm-mcp is a long-running MCP server, not a CLI with a --help flag. Invoking it directly without env vars exits 2 with a configuration error. The host (Claude Code / Desktop) subprocesses it and pipes JSON-RPC over stdio — you don't run it yourself unless you're debugging.

3. Register with your MCP host

Every supported host uses the same env-var protocol: TM_API_KEY for the API key, TM_BASE_URL for the base URL. The server reads both at startup and fails fast with a clean "couldn't start" message if either is missing — your host's log shows that instead of opaque "tool call failed" errors later.

In all snippets below, replace two placeholders with your own values:

  • TM_API_KEY=tm_xxxxxxxxxxxxxxxx → the API key from Step 1.
  • TM_BASE_URL=https://YOUR-TRAFFICMORPH-HOST → the URL of your TrafficMorph server. Common values:
    • Local dev: http://localhost:8092
    • Self-hosted prod: https://trafficmorph.your-company.com (or whatever URL your install lives at)
    • Cloud SaaS: the URL shown in your TrafficMorph app's browser address bar
    • Do not copy the literal YOUR-TRAFFICMORPH-HOST placeholder — it won't resolve and every tool call will fail.

Claude Code — one command:

claude mcp add trafficmorph \
  -e TM_API_KEY=tm_xxxxxxxxxxxxxxxx \
  -e TM_BASE_URL=https://YOUR-TRAFFICMORPH-HOST \
  -- uvx tm-mcp

Project-scope alternative — drop this at the repo root:

// .mcp.json
{
  "mcpServers": {
    "trafficmorph": {
      "command": "uvx",
      "args": ["tm-mcp"],
      "env": {
        "TM_API_KEY": "tm_xxxxxxxxxxxxxxxx",
        "TM_BASE_URL": "https://YOUR-TRAFFICMORPH-HOST"
      }
    }
  }
}

Claude Desktop — add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent on your OS, then restart Claude Desktop:

{
  "mcpServers": {
    "trafficmorph": {
      "command": "uvx",
      "args": ["tm-mcp"],
      "env": {
        "TM_API_KEY": "tm_xxxxxxxxxxxxxxxx",
        "TM_BASE_URL": "https://YOUR-TRAFFICMORPH-HOST"
      }
    }
  }
}

Codex — add to ~/.codex/config.toml (the Codex CLI reads MCP servers from this file at startup), then restart Codex. Note the TOML shape: a [mcp_servers.<name>] table with command / args and an inline env table.

[mcp_servers.trafficmorph]
command = "uvx"
args = ["tm-mcp"]
env = { TM_API_KEY = "tm_xxxxxxxxxxxxxxxx", TM_BASE_URL = "https://YOUR-TRAFFICMORPH-HOST" }

4. Verify

In Claude Code:

> /mcp

You should see trafficmorph listed with 37 tools, 4 prompts, and 5 resources. If you see red / error, check:

claude mcp list                # is `trafficmorph` registered?
claude mcp get trafficmorph    # what env vars + command?

The most common gotcha: forgetting TM_BASE_URL. The server refuses to start without it and surfaces a clear "$TM_BASE_URL is not set" error in your MCP host's log. Set it in the host config (see step 3).

Security

You've just put a long-lived API key — full access to your TrafficMorph account — into a config file on disk. A few real gotchas worth knowing about:

Don't commit / share / paste the host config file

The token sits in plaintext in your MCP host's config:

  • Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) / %AppData%\Claude\claude_desktop_config.json (Windows)
  • Claude Code — managed via claude mcp add, stored in ~/.claude/
  • Codex — ~/.codex/config.toml
  • Cursor — ~/.cursor/mcp.json

If you sync dotfiles to a public repo, paste your config into a support ticket, or DM it to a colleague to help them set up tm-mcp, you've leaked the token. Treat the file like an SSH private key. If it does leak, rotate immediately in the TrafficMorph app (Settings → API Keys → Regenerate) — the old key is revoked the moment the new one is generated.

Use env vars in the host config, never CLI args

tm-mcp hard-rejects any command-line argument other than --help / -h. This is deliberate — credentials passed via argv would show up in ps -ef, system audit logs, crash dumps, and any monitoring agent that records process command lines.

Right (what the Quick start above shows):

"trafficmorph": {
  "command": "uvx",
  "args": ["tm-mcp"],
  "env": {
    "TM_API_KEY": "tm_xxxxxxxxxxxxxxxx",
    "TM_BASE_URL": "https://YOUR-TRAFFICMORPH-HOST"
  }
}

Wrong (will refuse to start with command-line arguments are not supported):

"trafficmorph": {
  "command": "uvx",
  "args": ["tm-mcp", "--api-key=tm_xxxxxxxxxxxxxxxx"]
}

Verbose MCP-host logging can capture credentials

Most MCP hosts have a debug / verbose mode that logs every subprocess startup including its env block. If you enable that to troubleshoot something else, your TM_API_KEY will appear in the host's log file. Disable verbose logging once you're done debugging, and consider rotating the key if the log file ever left your machine.

Trust boundary is the MCP host itself

Any MCP host you configure tm-mcp into has full read access to the env vars you pass it (that's what makes it work). Only configure tm-mcp in hosts you trust — same posture as installing any local CLI tool or IDE extension.

Server-side defences (already in place)

  • Network leg uses HTTPS to your TrafficMorph deployment (the underlying trafficmorph SDK validates the base URL on startup and refuses non-http/https schemes).
  • Tokens are hashed at rest server-side, never stored in plaintext in the database.
  • Every tm_… token is revocable independently — rotating one key doesn't affect the rest of your account.

What you can do

Conversational examples — try any of these once the server is wired up:

  • "List my TrafficMorph profiles."
  • "Show me the last 5 runs for profile 42."
  • "Start a run on profile 42 and wait for the verdict."
  • "Create a profile 'smoke-test' hitting https://api.example.com/health at 50 RPS for 60s."
  • "What domains am I cleared to load-test against?"
  • "Add api.example.com as a new domain and walk me through verification."
  • "Compare run 1234 against run 1198."

Or invoke a slash-command prompt for a guided workflow:

  • /tm_triage 42 — find the most recent failed run for profile 42, diff against the latest PASS baseline, narrate the regression.
  • /tm_setup_loadtest https://api.example.com 100 60 — handle domain verification + profile creation + optional immediate run.
  • /tm_compare_baseline 42 — quick regression check vs the last green.
  • /tm_import_capture_guided ~/.trafficmorph/captures/my.jsonl — analyse → preview → import workflow.

Or @-mention a resource to pull pre-baked context into the chat:

  • @tm://profiles — your full profile list as session-start context.
  • @tm://history/recent — the last 20 runs across all profiles.
  • @tm://domains — verified domain list.
  • @tm://profiles/42 or @tm://history/1234 — one specific entity by id.

See MCP-USAGE.md for end-to-end worked conversations including failure triage, new-test setup, and capture-driven profile import.

Full catalog

Tools (37) — AI-invoked actions

Tool Action
Read
tm_list_profiles List all profiles owned by the authenticated user
tm_get_profile Full config + run status for one profile
tm_list_history Paginated past runs with filters (auto_verdict=FAIL is the CI-triage filter)
tm_get_run Full metric set + verdict for one run (include_series=False drops the per-bucket series)
tm_list_domains All registered domains + verification status
tm_compare_runs Metric-by-metric diff of two runs plus the server's significance tests
tm_get_run_status Live progress of a profile's current run (RPS, response codes, last minute of latency)
tm_list_regions Dispatch regions available to the account
tm_get_account Plan, limits (RPS, concurrent runs, profiles, quotas) and this month's usage
tm_list_history_filters Profiles, regions, tags and verdicts the history filters accept
tm_export_profile Portable trafficmorph-profile-v1 document (same as the web UI's Export)
tm_analyse_capture Per-endpoint analysis of a JSONL capture file
tm_list_capture_sources Remote capture sources (SFTP / S3) configured in the web UI; no credentials
tm_list_capture_source_files Capture files in one remote source, newest first
tm_analyse_remote_capture Per-endpoint analysis of a capture file in a remote source
Run control
tm_start_run Start a run, optionally in a given region and with history tags; with wait=True + fail_on_verdict=["FAIL","WARN"] mirrors tm runs start --wait in the CLI
tm_stop_run Stop the in-flight run for a profile (idempotent)
tm_pause_run Pause without losing position (idempotent)
tm_resume_run Resume a paused run from where it left off
Profile lifecycle + capture import
tm_create_profile Create a new profile, optionally with scripts, callback URL, alert policy, weekly schedule, variables sets, default region, readiness URL and interpolation mode (fails fast on name collision to prevent silent upsert wipe)
tm_update_profile Partial update by id (read-modify-write internally — only pass the fields you want to change)
tm_delete_profile Remove a profile
tm_import_capture Persist analysed-capture groups as profiles
tm_import_remote_capture Same, for a capture file in a remote source
tm_import_profile Create a profile from a portable document; refuses to overwrite unless overwrite=True
tm_delete_schedule Remove a profile's schedule (idempotent)
tm_delete_run Delete one run from history
Domain management
tm_add_domain Register a domain for verification (idempotent)
tm_verify_domain_dns Check the TXT challenge record
tm_verify_domain_http Check the /.well-known/trafficmorph-verify.txt file
tm_delete_domain Remove a domain
Variables-set lifecycle
tm_list_variables_sets List all variables sets owned by the user
tm_get_variables_set Single set's metadata (id, name, mode, columns, row count)
tm_create_variables_set Upload a CSV-style set (inline csv_content string, mode is one of "ROW" / "COLUMN" / "SEQUENTIAL")
tm_rename_variables_set Rename without touching content (idempotent)
tm_change_variables_set_mode Switch between ROW / COLUMN / SEQUENTIAL without re-uploading
tm_delete_variables_set Remove a set; 400s if still attached to any profile (detach via tm_update_profile(variables_set_ids=...) first)

Read tools carry readOnlyHint=true, so hosts can run them without a confirmation prompt. Run-history payloads come back with their metric maps (latencyQuantiles, responseCodes, series, verdict reasons) decoded into JSON objects.

Server compatibility. tm_get_run_status, tm_list_regions, tm_start_run(region=/tags=), the significance part of tm_compare_runs, the variables-set / region / readiness / interpolation profile fields, and the account, history-filter, schedule-delete, run-delete, export / import and remote-capture tools need a TrafficMorph server that has them in /api/v1. Against an older server those calls fail (compare falls back to its client-side diff), and tm_update_profile still resets those four profile settings.

Known limitations:

  • tm_start_run(wait=True) no longer blocks other calls and sends progress notifications, but the MCP host's own tool-call timeout still applies; for runs longer than that, use wait=False and poll tm_get_run_status.

Prompts (4) — user-invoked slash commands

Slash command Workflow
/tm_triage <profile_id> Find the most recent FAIL → diff vs latest PASS → narrate the regression
/tm_setup_loadtest <url> <rps> <duration_seconds> Domain verification (if needed) + profile creation + optional run
/tm_compare_baseline <profile_id> Quick regression check: latest run vs latest PASS
/tm_import_capture_guided <path> Analyse → present groups → user picks → import

Prompts return a templated user message that steers the AI through a specific tool sequence. They're how you kick off a known workflow without typing the full natural-language description every time.

Resources (5) — @-mention URIs

URI What it returns
tm://profiles All your profiles, JSON
tm://profiles/{id} One profile's full config
tm://history/recent Last 20 runs across all profiles
tm://history/{run_id} One run's full metrics
tm://domains All registered domains + verification status

Resources are read-only data the host pulls into context — usually at session start via @-mention. They wrap the corresponding read tools 1:1; the difference is who decides when to read (AI for tools, host for resources).

Configuration

Env var Required Notes
TM_API_KEY yes Full tm_… value provisioned from in-app Settings → API keys
TM_BASE_URL yes URL of your TrafficMorph install (http://localhost:8092 for local dev, your hosted URL otherwise). No built-in default — the server refuses to start without it
TM_MCP_CAPTURE_ROOT no Defaults to ~/.trafficmorph/captures/. Allow-listed root for tm_analyse_capture + tm_import_capture file paths

Capture-file path validation

tm_analyse_capture and tm_import_capture accept a server-side file path. The MCP server validates each path before passing it through:

Rule Why
Must resolve inside $TM_MCP_CAPTURE_ROOT (default ~/.trafficmorph/captures/) Prevents AI invocation from probing ~/.ssh/, ~/.aws/, ~/Documents/…
Symlinks resolving outside the root are rejected Classic symlink-escape defense
.. segments rejected at parse time Path-traversal defense
Only .jsonl extension The capture parser reads plain JSONL (no gzip wrapping)

Override the root via TM_MCP_CAPTURE_ROOT in your MCP host's server config:

"env": {
  "TM_API_KEY": "...",
  "TM_BASE_URL": "...",
  "TM_MCP_CAPTURE_ROOT": "/path/to/your/captures"
}

Troubleshooting

Server fails to start with $TM_API_KEY is not set or $TM_BASE_URL is not set. One of the required env vars wasn't delivered to the subprocess by your MCP host. The error names the missing variable; add it to the env block in your host config (see Step 3).

Server starts, but every tool call hits a network / DNS error. TM_BASE_URL is set to something that doesn't resolve — typically a placeholder like https://YOUR-TRAFFICMORPH-HOST that wasn't edited, a typo in the hostname, or an internal URL not reachable from where the MCP host runs. Read the URL back from claude mcp get trafficmorph and confirm it resolves with curl -I "$TM_BASE_URL/api/v1/profiles".

Tools work, but specific ones return 404. Your TrafficMorph server is running an older build that doesn't expose those endpoints yet. Upgrade the server.

PLAN_UPGRADE_REQUIRED on every call. Your TrafficMorph account doesn't have API access enabled. Check your account settings, or point the MCP server at a deployment where your account has API access.

tm_create_profile refuses with "A profile named X already exists". The server's POST endpoint is upsert-by-name and would silently replace every field of the existing profile, including settings you didn't pass. Use tm_update_profile(profile_id=<id from error>) instead, or pick a unique name.

tm_update_profile refuses to rename. A rename would collide with another profile under your account. The error names both ids; either pick a unique new name OR call tm_update_profile against the OTHER profile if you actually meant to edit that one.

"Could not reach the TrafficMorph server at …". No HTTP response came back: the server isn't running, or TM_BASE_URL in the MCP host config points at the wrong place. The error names the URL it tried.

Domain verify returns 400 immediately. That's the fail-fast contract — verification is NOT polling-style. The 400 message includes the expected TXT record / URL + token; read it back to the user, wait for them to install the record / file, then retry.

Versioning

Source Notes
MCP server release tm-mcp on PyPI Pin via pip install 'tm-mcp==X.Y.Z'. See CHANGELOG.md.
API version tm_mcp.__version__ matches the PyPI version Use to identify what's installed in support tickets

The MCP server is a thin layer over the trafficmorph Python SDK. The dependency pin in pyproject.toml constrains the SDK range this release is tested against; updating the SDK ships as a new tm-mcp release.

See also

  • MCP-USAGE.md — comprehensive user guide with worked example conversations
  • CHANGELOG.md — per-release history
  • STABILITY.md — v1.0 stability promise (what tools / prompts / resources stay stable across 1.x)
  • examples/ — full conversation transcripts (triage, setup, capture import)
  • TrafficMorph Python SDK — the HTTP layer this MCP server uses

Metadata

Release files for tm-mcp 1.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 tm-mcp 1.4.0
File Size Uploaded
tm_mcp-1.4.0.tar.gz 89.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tm-mcp 1.4.0
File Interpreter ABI Platform
tm_mcp-1.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 162.2 kB

Release files / tm_mcp-1.4.0.tar.gz

Download URL tm_mcp-1.4.0.tar.gz
Size 89.4 kB
Tags Source
SHA-256 checksum
How to use checksums
25ce4bdb3ba3ffe11c0b579e9f48c85145a03a91fb25b19b3c7251d1541e1515
BLAKE2b-256 checksum
How to use checksums
036be843f130cf4b4165320a0ff860627d4f04f36197527bb091063906f5fa2e
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 29, 2026.

Transparency log

Release files / tm_mcp-1.4.0-py3-none-any.whl

Download URL tm_mcp-1.4.0-py3-none-any.whl
Size 72.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
82a987f262dec41c4991d730d41206d5a3e5e19a45a82a6671187d22db78a393
BLAKE2b-256 checksum
How to use checksums
34215b0471d8688394f9bb48cada529ee90265b116a64f5874b2f4ea227c4b35
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 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.4.0 This release

2 release files

1.3.0

2 release files

1.2.1

2 release files

1.2.0

2 release files

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