Files
Matt Godbolt 312846230a Add built-in MCP endpoint for LLM tool integration (#8644)
Expose Compiler Explorer's compile, list, shortlink and asm-docs APIs
via a Model Context Protocol (MCP) endpoint mounted at `/mcp`. This lets
MCP-aware clients (Claude, etc.) drive CE directly as a tool.

## Tools exposed at `/mcp`

- **`compile`** — compile source and return assembly / stdout / stderr,
with optional execution.
- `compiler` is **optional**; falls back to the language's
`defaultCompiler` from `list_languages` ("compile this hello world in
C++" is one call).
- `libraries[].version` accepts **either** the version id (`"188"`) or
the human form (`"1.88.0"`) — both work.
- When `execute: true` and the build fails,
`buildResult.stdout`/`stderr` carry the real compiler diagnostics with
**ANSI codes stripped** so an LLM caller sees clean text.
- Caps: `maxAsmLines` / `maxStdoutLines` / `maxStderrLines` with
truncation flags + total counts.
- **`list_compilers`** — with `language`, `instructionSet` (closed enum
from `InstructionSetsList`), `match` (case-insensitive AND-of-tokens;
numeric/dotted-version tokens treated as version-prefix), `lean: true`,
`maxResults`, `latestPerMajor: true`, and `includeExperimental: true`.
- Hard cap of 200 entries on lean responses with a refinement hint —
prevents the unfiltered call from overflowing.
- Each entry exposes `releaseTrack` (`stable | nightly | prerelease |
experimental`) and `supportsExecute` / `supportsBinary`.
- **`list_libraries`** — with `match`, `lean`, `maxResults` (same
lean-cap behaviour).
- **`list_languages`** — minimal listing including `defaultCompiler` and
`compilerCount` per language.
- **`generate_short_url`** — returns `{url}`. Library versions are
normalised before saving.
- **`get_shortlink_info`** — returns saved sessions in the **same shape
`compile` accepts** (`{compiler, options, libraries:[{id, version}]}`)
for direct round-tripping. Multi-pane shortlinks (executors,
conformance, CMake trees) are flattened to the basic compile inputs.
- **`lookup_asm_instruction`** — `instruction_set` is a closed enum
derived from the registered providers (no hand-listed enum values; one
source of truth in `lib/asm-docs/`).

## Implementation

- New `lib/mcp/` module wiring `@modelcontextprotocol/sdk` into the
existing Express router via `StreamableHTTPServerTransport` (stateless
mode — one server per request).
- `lib/mcp/utils.ts`: tokenised `match` with version-prefix matching for
numeric/dotted-version tokens (so `"gcc 14.1"` matches `"gcc 14.1"` and
`"gcc 14.1.0"` but NOT `"gcc 14.10"` or `"gcc 14.0.1"`); `applyCap` with
both per-call lean degradation and an absolute hard cap; `truncateLines`
strips ANSI escapes via the existing `filterEscapeSequences` helper from
`lib/utils.ts`.
- `lib/mcp/library-utils.ts`: `normaliseLibraryVersion` and
`normaliseRequestLibraries` — single source of truth for "accept id or
human version" semantics, used by both `compile` and
`generate_short_url`.
- Schema descriptions are tight (LLM context cost matters) and derive
closed-set enums programmatically from `InstructionSetsList`,
`RELEASE_TRACKS`, and a new `availableAsmDocsKeys` export — no
hand-listed values that can rot.
- Refactor `StorageBase` static helpers (`encodeBuffer`, `isCleanText`,
`getSafeHash`) to module-level functions with type-checked input so MCP
tools can build shortlink hashes without instantiating a storage
backend.
- Expose `ApiHandler.compileHandler` and split out
`getAvailableLanguages()` so MCP can reuse the same code paths the REST
API uses; new `ApiHandler.getDefaultCompilerFor()` for the
compile-default-compiler resolution.
- Browser-friendly CORS on `/mcp`: OPTIONS preflight advertises
`Access-Control-Allow-Methods: POST, OPTIONS` (the shared `cors`
middleware doesn't set Methods); 405 responses on other verbs use the
same Allow header.
- `docs/API.md`: clarify that `/api/shortener` requires a JSON object
body (the prior docs implied but didn't state it).

## Tester feedback addressed

A Claude tester drove the staging deployment through several rounds;
full thread in PR comments. Round-by-round refinements:

- Compile diagnostics surfaced on execute-mode build failures (the
original "silent `Build failed` with empty stderr" bug).
- `execute: true` schema description rewritten to reflect the actual
behaviour.
- Library `version` accepts both forms; clean errors when neither
matches with a sample of available versions.
- `latestPerMajor` rebuilt on top of the `releaseTrack` field added in
#8685, with `includeExperimental` opt-in for c++ proposal forks.
- Lean mode (`lean: true`) for catalog browsing, plus a hard 200-item
cap so even unfiltered calls don't overflow the host.
- Tokenised `match` with version-prefix semantics for
numeric/dotted-version tokens. **Behaviour change** vs the old
`/api/compilers?fields=...` text matching: bare numeric tokens are now
treated as version segments — `"2024"` no longer substring-matches
inside `"v2024beta"`, and `"14.1"` no longer wrongly matches `"14.0.1"`.
Strict improvements but worth a release-note line for callers depending
on the prior loose behaviour.
- ANSI escape code stripping from compile output.
- `instructionSet` as a structured filter (instead of relying on `match`
strings).
- `supportsExecute` / `supportsBinary` on `list_compilers` so an agent
knows whether `execute: true` will work without trying.
- `compilerCount` per language so an agent can tell well-stocked vs
niche languages at a glance.
- Compiler-not-found / library-not-found errors point at the right
`list_*` tool.

## Depends on

#8685 (releaseTrack metadata on `CompilerInfo`) — merged.

## Test plan

- [x] `npm run test -- --run mcp release-track` — all pass (78 + 22)
- [x] `npm run test-min` — full minus expensive, all green
- [x] `make pre-commit` — exits 0
- [x] Multi-round driving on staging via the live MCP endpoint,
including: default-compiler hello-world (no compiler arg), human-form
library version (`"1.88.0"`), broken-compile-with-execute (verifies
buildResult), compile+run with stdin, compile+library Boost 1.90,
parallel `-O0` vs `-O3` diff, `list_compilers latestPerMajor` for
c++/rust/go/csharp, `list_libraries match boost/fmt/json`,
`lookup_asm_instruction MOV amd64`, full `generate_short_url` →
`get_shortlink_info` → re-`compile` round-trip with library
normalisation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Matt Godbolt <mattgodbolt@hudson-trading.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: mattgodbolt-molty <mattgodbolt-molty@users.noreply.github.com>
2026-05-08 10:50:09 -04:00
..
2023-07-30 18:06:09 -05:00
2026-05-06 10:38:05 -04:00
2020-05-20 12:55:12 +02:00
2026-03-21 21:21:40 +01:00
2018-02-23 09:19:04 -06:00
2026-02-20 12:54:12 +01:00
2025-08-02 16:20:20 -05:00
2022-05-09 23:13:50 -05:00
2022-12-27 18:46:15 -06:00
2022-05-09 23:13:50 -05:00
2023-02-02 20:44:45 +01:00
2024-03-08 22:25:09 -06:00
2025-10-04 16:37:04 +02:00
2020-10-01 23:40:14 +02:00

How do I ?

This is a how-to guide for the user-interface presented by Compiler Explorer. This doesn't cover the details of how to set up or modify Compiler Explorer for your own needs. For that, please check the documents which already cover topics like:

Fast links:

Change the assembly syntax from Intel

Output, intel and at&t

The option to switch assembly from Intel to AT&T syntax is present in the Output option of each compiler. If enough space is not present, the option also presents itself as the gear symbol (⚙)

Compare the time taken by compilation and networking

Brief overview of UI

This is the symbol that looks like a bar graph (📊). If your compilations are taking long, you can use this to check the time taken by:

  • Networking, JavaScript, waiting for events, etc.
  • Checking the cache and retrieving from it on a cache-hit
  • Compilation (on force compilation or cache-miss)
  • Parsing the generated assembly before presenting it

View intermediate information provided by the compilers

Options for GCC Options for Clang

Though both GCC and Clang create supplementary outputs along with assembly (shown by default), and an executable (created if an executor has been added), the exact nature of the outputs and their formats differ between the compilers.

GCC allows the Tree, IPA, RTL and graph outputs, while Clang allows optimization, AST, IR and graph outputs. Some outputs (e.g. RTL or graph) also have a rich set of options in the UI to enable focussing on a particular function or compiler stage.