Skip to main content
Relay

Find the latency in your AI agent, before your users do.

Relay is an open-source MCP server + CLI that audits AI agent and voice-agent codebases for latency bottlenecks. It reads your real source with an AST engine, ranks issues by impact, runs a verification pass to drop false positives, and can apply fixes directly from Claude Code.

No account. No API key. No backend. It runs entirely on your machine.

CI Python License: MIT

Quickstart · MCP tools · CLI · What it detects · Contributing


relay scan and relay verify running against five voice-agent frameworks

Why Relay

Agent latency is rarely one slow model call. It is a streaming response that was never streamed, three awaits that should have been one asyncio.gather, an HTTP client rebuilt on every request, a requests.post sitting inside an async def. These are structural, they are invisible in a profiler flame graph averaged over a request, and they are obvious in the AST.

Relay finds them, then argues with itself about each one so you don't get a wall of false positives.


Quickstart

In Claude Code (MCP)

claude mcp add relay -- uvx relay-mcp

Or add it to your MCP config (~/.claude/claude_code_config.json) by hand:

{
  "mcpServers": {
    "relay": {
      "command": "uvx",
      "args": ["relay-mcp"]
    }
  }
}

Then, in Claude Code, just say:

Audit this codebase for latency issues

That's it - there is no key to configure.

As a CLI

pip install relay-mcp     # or: uv tool install relay-mcp

relay scan   .            # structural pass - candidate latency patterns
relay verify .            # semantic pass  - only the confirmed gaps
relay report .            # write relay-report.json

Requires Python 3.11+.


Features

  • AST-based detection. Parses Python with the real grammar, not regexes, so it understands async/await, call targets, keyword arguments, and **kwargs forwarding.
  • Six latency detectors. Streaming gaps, sequential tool calls, cache misses, blocking I/O in async code, per-request client construction, and prefetch opportunities - see What it detects.
  • Verification pass. Every candidate is re-read in context and either confirmed as a real gap or dismissed as a false positive, each with a one-line reason.
  • Impact ranking. Findings are scored and sorted so the highest-impact fixes surface first.
  • Apply fixes from Claude Code. apply_fix rewrites the flagged site (dry-run by default) so you review before anything is written.
  • MCP and CLI share one engine. Agent output and terminal output never diverge.
  • CI gate. relay verify --fail-on high exits non-zero when a confirmed high-impact gap remains, so it can fail a pipeline.
  • Dashboard reports. Each audit writes a relay-report.json you can drop into the Relay dashboard for a visual view.
  • Essentially no dependencies. Just the mcp package - no network calls, no telemetry, nothing leaves your machine.
  • Persistent state. The last audit is cached at ~/.relay/last-audit.json, so get_findings, verify_audit, and apply_fix keep working across MCP restarts.

MCP tools

Tool Description
audit_codebase(directory, write_report=true) Reads Python files in a directory, returns ranked findings (each with a verification verdict) and writes relay-report.json.
get_findings(severity?, finding_type?, status?) Filters findings from the last audit.
verify_audit() Shows which findings the semantic pass confirmed vs dismissed, with reasons.
apply_fix(finding_rank, file_path?, dry_run=true) Applies a fix. Dry run by default; file path defaults to the finding's file.

The last audit is cached at ~/.relay/last-audit.json, so the read-only tools keep working after an MCP server restart.


CLI

relay scan   <dir>          # structural pass - flag candidate latency patterns
relay verify <dir>          # semantic pass  - keep only confirmed gaps
relay report <dir> [-o f]   # write relay-report.json for the dashboard
relay mcp                   # run the MCP server (same as relay-mcp)
Flag Applies to Meaning
--json scan, verify Print the full report as JSON (for CI, jq).
--fail-on {none,high,any} verify Exit non-zero when confirmed gaps remain. Default none.
-o, --output report Output path. Default <dir>/relay-report.json.

Use in CI

- run: pip install relay-mcp
- run: relay verify . --fail-on high

--fail-on high fails the job only when a confirmed high-impact gap remains, so a noisy structural match will not break your build.


What it detects

Detector What it flags
SyncOutput LLM calls missing streaming (stream=True), including calls that forward **kwargs.
SequentialTools Consecutive data-independent awaits that should run under asyncio.gather().
CacheMiss The same fully-static LLM call repeated at multiple call sites with no caching.
BlockingIO Sync requests / DB calls, plus time.sleep and blocking subprocess calls inside async functions.
ColdStart API clients (OpenAI, httpx.Client, aiohttp.ClientSession, …) built per request instead of at startup.
Prefetch Predictable tool-call pairs that could be started speculatively.

The verification pass

Every finding is re-read in context and either confirmed as a real latency gap or dismissed as a false positive, with a one-line reason either way - for example "one branch (lookup) is in-memory - nothing to parallelize" or "structured/JSON output - not streamable". The summary counts (flagged, confirmed, dismissed, confirmed_high_impact) drive both the CLI output and the --fail-on CI gate.

This is the difference between a linter you mute after a week and one you keep in CI.


The dashboard

Relay itself is fully local. If you want a visual view of a report, the Relay dashboard lets you drag in any relay-report.json and browse findings, severity breakdown, and time-lost aggregates. The report never leaves your browser - it is parsed client-side.


Configuration

None. Relay needs no environment variables, no config file, and no API key. It reads your source, writes a report, and does nothing else.


Repository structure

relay-mcp/
├── mcp_server/          # MCP server + CLI (ships as relay-mcp on PyPI)
│   ├── server.py        # entry point, exposes the MCP tools
│   ├── cli.py           # `relay` command (scan / verify / report / mcp)
│   └── engine/          # audit engine (detectors, scorer, verify, code_parser)
├── tests/               # end-to-end engine tests
├── assets/              # logo and screenshots
├── run.sh / run.ps1     # dev runners (install / register / test / serve)
└── pyproject.toml       # package config for uvx / pip install

Development

pip install -e ".[dev]"   # install relay + relay-mcp in editable mode
pytest                    # run the test suite
ruff check .              # lint
relay scan .              # dogfood the engine on itself

See RUNNING.md for the full dev workflow and CONTRIBUTING.md for how to add a detector or open a PR.


Project

Relay is a product of the Arclat studio. Learn more at relay.arclat.com.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

relay_arclat-0.3.0.tar.gz (28.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

relay_arclat-0.3.0-py3-none-any.whl (31.7 kB view details)

Uploaded Python 3

File details

Details for the file relay_arclat-0.3.0.tar.gz.

File metadata

  • Download URL: relay_arclat-0.3.0.tar.gz
  • Upload date:
  • Size: 28.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for relay_arclat-0.3.0.tar.gz
Algorithm Hash digest
SHA256 d12641a8c16148869942666384d248593a7cdb4e5abb53715c7d9dfc738e5fe0
MD5 580b669b29b12e1d34d8a97162060190
BLAKE2b-256 52043354a205be331be547988a8289309ac5c215d0b5c87666efac6fbd4f1144

See more details on using hashes here.

Provenance

The following attestation bundles were made for relay_arclat-0.3.0.tar.gz:

Publisher: release.yml on arclat-ai/relay-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file relay_arclat-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: relay_arclat-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 31.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for relay_arclat-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6e711b59744b227f60f309d509756431473b83270470944d411121b317b9bbad
MD5 f13b1388b3049120c4c0c54be188de0f
BLAKE2b-256 aa0b872682fb7b66425b0cf1ffc39dac79f33d749cc454d9c205e0713e9356a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for relay_arclat-0.3.0-py3-none-any.whl:

Publisher: release.yml on arclat-ai/relay-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page