## Summary
Anthropic's [connector review
criteria](https://claude.com/docs/connectors/building/review-criteria)
and [submission
requirements](https://claude.com/docs/connectors/building/submission)
call out two things our `/mcp` endpoint is missing today:
- every tool needs a `title` plus `readOnlyHint` / `destructiveHint`
annotation
- a public docs page covering setup and usage must exist by publish date
This PR adds both:
- **Tool annotations** on all 7 MCP tools (`compile`, `list_compilers`,
`list_languages`, `list_libraries`, `lookup_asm_instruction`,
`generate_short_url`, `get_shortlink_info`). All read-only tools get
`readOnlyHint: true`. `generate_short_url` is marked `readOnlyHint:
false` + `destructiveHint: false` + `idempotentHint: true` (it's
additive and the storage layer dedupes by config hash). Every tool gets
`openWorldHint: false` since none reach out to third-party services.
- **`docs/MCP.md`** describing the endpoint URL, transport, tool
catalogue, and a Claude Code setup line.
A judgement call worth flagging: `compile` is annotated `readOnlyHint:
true` even though `execute=true` runs user code. The CE service is
stateless from the connector's point of view and sandbox effects don't
escape the call, so the hint matches the spirit of the annotation, but
we may want to revisit if Anthropic pushes back during review.
Two known gaps not addressed here, that I'd like to discuss separately
before submission:
- **Origin-header validation** — required by the submission doc as
DNS-rebinding mitigation. The threat model mostly applies to
localhost-bound desktop servers; we're a public HTTPS service with no
auth, so the public REST API's `Allow-Origin: *` posture is consistent.
Suggest asking Anthropic to confirm exemption, or add an allowlist with
a missing-Origin pass-through (Claude Code currently sends none).
- **Submission form prep** — name/tagline/description/screenshots/logo,
and a pass through MCP Inspector. Operational, not code.
## Test plan
- [x] `npm run ts-check`
- [x] `npm run lint`
- [x] `npm run test -- --run mcp` (78 tests pass)
- [x] pre-commit hook runs clean
- [ ] manual smoke test from a fresh Claude Code MCP install (`claude
mcp add --transport http compiler-explorer https://godbolt.org/mcp` once
deployed)
- [ ] confirm tool annotations show up correctly in MCP Inspector
🤖 Generated with [Claude Code](https://claude.com/claude-code)
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>
## Summary
Adds a structured `releaseTrack: 'stable' | 'nightly' | 'prerelease' |
'experimental'` field on `CompilerInfo` so consumers can distinguish
release tracks that aren't currently separable from the existing
`isSemVer` / `isNightly` / `semver` fields.
Today every compiler with a non-numeric semver and `isNightly=true`
looks the same from the outside: Rust nightly, Rust beta, gcc snapshot,
and gcc's various experimental forks (`gcontracts-trunk`,
`gcc-modules-trunk`, `glambda-p2034-trunk`, ...) all share the same
shape. Anything that wants to ask "what's the canonical newest build of
language X" — a UI badge, the upcoming MCP `latestPerMajor` knob
(#8644), etc. — has no way to tell those apart.
## Implementation
- **Heuristic** in `lib/release-track.ts` driven by `asSafeVer` + the
existing `isSemVer`/`isNightly` flags. Real semvers with a prerelease
segment (e.g. micropython `1.28.0-preview`) are flagged `prerelease`;
semvers containing `trunk`/`main` and the literal `nightly` tag go to
`nightly`; bare `beta`/`alpha`/`rc` tags go to `prerelease`; `isNightly`
with anything else (the c++ experimental forks) goes to `experimental`;
everything else stays `stable`.
- **Override:** `compiler.releaseTrack=` / `group.releaseTrack=` in
`.properties` for cases the heuristic can't reach from structural
fields. Used here for `rustccggcc-master` / `mrustc-master`, where
"master" lives in the compiler id but not the semver field.
- **Backfill** in `loadPrediscovered()` so cached discovery JSON written
before this field existed doesn't break, and so a hand-edited invalid
value gets re-inferred rather than violating the type contract.
- **Tests:** 18 unit tests covering each rule + edge cases (whitespace,
mixed case, prerelease segments) and the `isReleaseTrack` type guard.
## API exposure
`releaseTrack` is on `CompilerInfo` so it appears via
`/api/compilers?fields=all`. It is **not** in the default field set, so
existing API responses are unchanged. UI consumers can opt in.
## Why this is a separate PR
This started as a piece of #8644 (MCP endpoint) — the MCP
`list_compilers` `latestPerMajor` knob needs this distinction to give
clean answers ("newest GCC" should not return a sea of experimental
forks). Rather than hack around the missing metadata in just the MCP
layer, the metadata belongs at the source where other features (UI
badging, etc.) can consume it. #8644 will rebase on top of this.
## Test plan
- [ ] `npm run test -- --run release-track` — 18/18 pass
- [ ] `npm run test:props` — 90/90 pass
- [ ] `make pre-commit` — exits 0 (pre-existing warnings only)
- [ ] Manual sanity check on staging:
`/api/compilers/c%2B%2B?fields=all` returns `releaseTrack` for each
compiler
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: mattgodbolt-molty <mattgodbolt-molty@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Some languages like Go update cross-architecture compiler IDs in-place
when new patch releases come out (e.g. `386_gl124` moves from 1.24.2 to
1.24.13). This documents it as an accepted exception to the general rule
that compiler IDs must not change meaning.
Discovered while reviewing #8462.
*(I'm Molty, an AI assistant acting on behalf of @mattgodbolt)*
🤖 Generated by LLM (Claude, via OpenClaw)
Co-authored-by: mattgodbolt-molty <mattgodbolt-molty@users.noreply.github.com>
Adds a section to `AddingACompiler.md` explaining that compiler IDs are
permanent and must not be removed or reassigned. This is a common
mistake in version-bump PRs where contributors replace existing entries
with newer patch releases instead of adding alongside them.
The new section covers:
- Why IDs must be stable (shortlinks, saved sessions, embeds)
- The correct approach when adding newer versions (add, don't replace)
- Using `alias` as a fallback when a compiler genuinely can't be kept
- The same rule applying to infra install targets
- The rare exception for lesser-used languages with involved maintainers
🤖 Generated by LLM (Claude, via OpenClaw)
Co-authored-by: mattgodbolt-molty <mattgodbolt-molty@users.noreply.github.com>
Add sections covering Ctrl+S file inclusion behaviour (including the
filename dialog), tab stacking in IDE mode, CMake language requirements
and CMakeLists.txt prerequisite, and a note about adding compilers from
the tree view.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce a += operator in property file parsing that appends values to
existing string properties. This allows splitting long property values
across multiple lines for improved readability.
Example:
group.compilers=comp1:comp2:comp3
group.compilers+=:comp4:comp5:comp6
Error handling:
- Logs error and skips if += is used on an undefined property
- Logs error and skips if += is used on a non-string property
Includes unit tests for the new functionality.
<!-- THIS COMMENT IS INVISIBLE IN THE FINAL PR, BUT FEEL FREE TO REMOVE
IT
Thanks for taking the time to improve CE. We really appreciate it.
Before opening the PR, please make sure that the tests & linter pass
their checks,
by running `make check`.
In the best case scenario, you are also adding tests to back up your
changes,
but don't sweat it if you don't. We can discuss them at a later date.
Feel free to append your name to the CONTRIBUTORS.md file
Thanks again, we really appreciate this!
-->
Add a note in AddingACompiler.md pointing to pseyfert's
[compilecommands_to_compilerexplorer](https://github.com/pseyfert/compilecommands_to_compilerexplorer)
tool, which generates `.local.properties` from `compile_commands.json`.
Closes#953🤖 Generated by LLM (Claude, via OpenClaw)
## Summary
Replaces the Python `propscheck.py` validation script with TypeScript
code that:
- Uses a testable validator module (`lib/properties-validator.ts`)
- Has comprehensive unit tests (71 tests in
`test/properties-validation-tests.ts`)
- Integrates with the existing property loading infrastructure
- Runs as part of the normal test suite
## Changes
- **New validator module** (`lib/properties-validator.ts`):
- Raw file validation: duplicate keys, empty list elements, typos,
suspicious paths
- Orphan detection: compilers, groups, formatters, tools, libraries
- Cross-file duplicate compiler ID detection
- Disabled allowlist support (`# Disabled: id1 id2`)
- Invalid property format detection (leverages `parseProperties()` with
new `collectErrors` option)
- Missing compilers list detection for language files
- **Property library enhancement** (`lib/properties.ts`):
- Added `collectErrors` option to `parseProperties()` for structured
error collection
- **New npm script**: `npm run test:props` for quick property validation
- Set `CHECK_LOCAL_PROPS=true` to include `.local.properties` files
- **Updated references**:
- CI workflow no longer calls propscheck.py
- Pre-commit hook uses `npm run test:props`
- CE Properties Wizard uses the new validation
- **Removed**: `etc/scripts/util/propscheck.py` and `propschecktest.py`
## Test plan
- [x] All 71 unit tests pass
- [x] Integration tests validate real config files
- [x] `npm run test:props` works standalone
- [x] CE Properties Wizard validation works
- [x] CI passes
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
The "Adding a new compiler to the live site" section was outdated,
referencing deprecated bash scripts in update_compilers/ directory.
Updated to reference the current YAML-based configuration system:
- References ce_install tool instead of old scripts
- Points to bin/yaml/*.yaml configuration files
- Links to infra repo documentation (ce_install_yaml.md,
installing_compilers.md)
- Provides concrete installation command examples
- Updates terminology (non-free instead of install_nonfree_compilers.sh)
Fixes#5937🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
- Add comprehensive test suite covering all Claude Explain functionality:
- Basic pane opening and consent flow
- no-ai directive detection
- API interactions and error handling
- Options/customization features
- Caching behavior and persistence
- Compilation state handling
- State persistence across page loads
- Fix caching bug in explain-view.ts:
- Cache was incorrectly implemented as instance variable, losing cached explanations when panes were closed/reopened
- Made cache static to persist across all pane instances (matches consent persistence pattern)
- Fixes failing "Caching and reload" Cypress test
- Aligns implementation with documented behavior: "shared across all explain views in the session"
- Add test utilities and helpers:
- Monaco editor content manipulation using clipboard events
- Claude Explain specific helpers moved to test file
- General utilities remain in utils.ts
- Performance optimizations:
- Clear Cypress intercepts in afterEach to prevent O(n²) degradation
- Use :visible selectors to avoid GoldenLayout template elements
- Proper mock setup timing to prevent race conditions
- Add comprehensive README with lessons learned and best practices
All tests use fake test data (test_first, focus_a, etc.) to clearly distinguish from production values and prevent accidental API calls.
Add Claude Explain feature for AI-powered code explanations
This PR introduces Claude Explain, a new feature that provides AI-powered explanations of compiler output directly within Compiler Explorer.
Key features:
Claude Explain functionality:
- New explain view pane
- Explains compiler output with full context of source code and compilation output
- Configurable audience level and explanation type
- Response caching to improve performance and reduce API calls
- Usage statistics display showing requests used and token counts
User experience:
- Consent flow on first use explaining data handling and privacy
- AI disclaimer banner warning about potential LLM inaccuracies
- Respects "no-ai" directive in source code for users who don't want AI processing
Privacy and security:
- Data sent to Anthropic's Claude API as documented in privacy policy
- No data used for model training
- Clear consent required before first use
- Support for opting out via "no-ai" directive
The feature is marked as beta and can be enabled via configuration.
Co-authored-by: Claude <noreply@anthropic.com>
A whole bunch of changes I've been meaning to make:
- Clarify things and put the TLDR at the top
- Remove my own darn address etc (after checking this is OK)
- Clarifying the goo.gl situation
- Paving the way for the explain feature
This adds some unit tests for the front end.
- configures "frontend tests" as a unit tests in `static/tests`,
removing the old cypress-requiring "unit" tests
- hack enough of a DOM to get things working
- port motd and id tests
- *adds* a golden layout checks (see #7807)
- Updates READMEs etc
---------
Co-authored-by: Claude <noreply@anthropic.com>
This PR includes various documentation improvements:
- Fix grammar in README.md introduction
- Update Node.js version references to consistently indicate 'Node.js 20
or higher'
- Enhance macOS installation and setup guide with detailed instructions
- Fix broken link in API.md
- Fix formatting inconsistencies in WhatIsCompilerExplorer.md
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
This PR adds a detailed Configuration.md document that comprehensively
explains the Compiler Explorer configuration system. It covers:
- Configuration file structure and hierarchical loading
- Property types and automatic conversions
- List separators and specialized formats
- Group inheritance and compiler configuration
- Variable substitution mechanisms
- Advanced features like remote compilers and property debugging
Additionally, it updates all related documentation to reference this
central document for configuration details, reducing duplication and
ensuring consistency.
This document will serve as the foundation for future configuration
system improvements by providing clear documentation of the current
implementation.
- Mark documentation update tasks as complete
- Add a comprehensive documentation section for custom component implementations
- Document key changes between Bootstrap 4 and 5 for each component type
- Add sections on event handling, CSS class changes, and special integration notes
- Track remaining tasks with GitHub issues (#7602, #7603, #7604)
- Update references from "beta site" to "live site"
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This PR completes the migration from Bootstrap 4 to Bootstrap 5.3.5
following the plan outlined in
[docs/Bootstrap5Migration.md](https://github.com/compiler-explorer/compiler-explorer/blob/mg/bootstrap5/docs/Bootstrap5Migration.md).
## Migration Process
We followed a phased approach as documented in the migration plan:
1. **Phase 1: Dependency Updates and Basic Setup**
- Updated Bootstrap from 4.6.2 to 5.3.5
- Added @popperjs/core dependency (replacing Popper.js)
- Updated Tom Select theme from bootstrap4 to bootstrap5
2. **Phase 2: Global CSS Class Migration**
- Updated directional utility classes (ml/mr → ms/me)
- Updated floating utility classes (float-left/right → float-start/end)
- Updated text alignment classes (text-left/right → text-start/end)
3. **Phase 3: HTML Attribute Updates**
- Updated data attributes to use Bootstrap 5 prefixes (data-bs-toggle,
data-bs-target, etc.)
- Fixed tab navigation issues
4. **Phase 4: JavaScript API Compatibility Layer**
- Created bootstrap-utils.ts compatibility layer
- Updated component initialization for modals, dropdowns, popovers, etc.
5. **Phase 5: Component Migration**
- Updated and tested specific components (modals, dropdowns, toasts,
etc.)
- Fixed styling issues in cards and button groups
6. **Phase 6: Form System Updates**
- Updated form control classes to Bootstrap 5 standards
- Updated checkbox/radio markup patterns
- Simplified input groups
7. **Phase 7: Navbar Structure Updates**
- Updated navbar structure with container-fluid
- Fixed responsive behavior
8. **Phase 8: SCSS Variables and Theming**
- Added custom CSS fixes for navbar alignment
- Verified theme compatibility
9. **Phase 9: Accessibility Improvements**
- Updated sr-only to visually-hidden
- Added proper ARIA attributes
- Enhanced screen reader support
## Key Changes
- No more jQuery dependency in Bootstrap 5
- New prefix for data attributes (data-bs-*)
- Improved accessibility with ARIA attributes
- Updated positioning classes (start/end instead of left/right)
- Simplified input group structure
## Test Plan
1. **Navigation Testing**
- Verify all dropdown menus open and close properly
- Test mobile menu responsiveness
- Check tab navigation in settings dialog
2. **Component Testing**
- Verify all modals open and close correctly (settings, share,
load/save)
- Test tooltips and popovers
- Check form controls in different dialogs
3. **Layout Testing**
- Test responsiveness on different screen sizes
- Verify proper alignment of elements
- Check dark mode compatibility
4. **Specific Features to Test**
- Compiler selection and options
- Share dialog functionality
- Settings dialog
- Tree view (IDE mode)
- Font selection dropdown
5. **Browser Testing**
- Test in Chrome, Firefox, Safari
- Test in mobile browsers
## Note on Further Improvements
After this migration is stable, we could consider Phase 12: removing
jQuery dependency entirely, as Bootstrap 5 no longer requires it. This
would be a separate effort.
---------
Co-authored-by: Claude <noreply@anthropic.com>