Files
compiler-explorer/lib/mcp
Patrick Quist 500c09675b MCP: proxy compiles for remotely-hosted compilers (#9016)
cc @mattgodbolt — this is in the MCP endpoint from #8644.

## The problem

`compile` in the MCP tool calls `baseCompiler.compile()` directly, so a
compiler served by a sub-server gets attempted on whichever node handled
the MCP request. There's no compiler binary there to launch, so every
remotely-hosted compiler fails through `/mcp`:

```
runChild():486 Launching child process failed
```

Reproducible on production right now — `vcpp_v19_51_VS18_6_x64` through
`compiler-explorer.com/mcp` fails, while the same id and options through
`/api/compiler/<id>/compile` works. It affects any remote, not just the
Windows ones.

`CompileHandler.handle` has the branch that makes this work for REST:

```ts
const remote = compiler.getRemote();
if (remote) {
    req.url = remote.path;
    this.proxy.web(req, res, {target: remote.target, changeOrigin: true}, ...);
    return;
}
```

There's no equivalent anywhere in `lib/mcp` — `git log -S"getRemote" --
lib/mcp` is empty, so this has been the case since the endpoint landed.

## The change

Check `getRemote()` and, when it's set, POST an equivalent request to
`remote.target + remote.path` rather than compiling locally. A tool call
has no `req`/`res` to hand to `http-proxy`, hence an outbound `fetch`
instead of the proxy. The sub-server returns the same JSON shape
`compile()` returns locally, so truncation, `buildResult` and
`execResult` handling below are untouched.

One wart: `result` is annotated `Awaited<ReturnType<typeof
baseCompiler.compile>>` rather than `CompilationResult`, because the
declared wire type has `asm?: string | ParsedAsmResultLine[]` and
`truncateLines` wants the array form — typing it as `CompilationResult`
doesn't compile. There's a cast on the remote branch with a comment
explaining why. Happy to do this differently if you'd rather.

## Testing

Unit tests: the existing fake compiler had no `getRemote`, so it's added
there; two new cases cover the remote path posting to the sub-server
(and never calling `compile()` locally) and a failing sub-server
response surfacing as a tool error.

Manually, against a local instance configured with the `gpu` and
`winprod` remotes:

| compiler | before | after |
| --- | --- | --- |
| `vcpp_v19_51_VS18_6_x64` `/O2` | `runChild():486` | `code 0`, `lea
eax, DWORD PTR [rcx+1]` |
| `vcpp_v19_51_VS18_6_x86` `/O2 /std:c++20` | — | `code 0`, `mov eax,
DWORD PTR _x$[esp-4]` |
| `clang-cl2216-v19_50_VS18_2` `/O2` | — | `code 0` |

Compile errors propagate too: a deliberate typo returns `code 2` with
`<source>(1): error C2065: 'nope': undeclared identifier`.

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

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 17:38:37 -05:00
..