Skip to content

docs(levelcode): an MCP section — the protocol, and servers worth connecting - #95

Merged
ndemianc merged 2 commits into
developfrom
docs/mcp
Jul 29, 2026
Merged

docs(levelcode): an MCP section — the protocol, and servers worth connecting#95
ndemianc merged 2 commits into
developfrom
docs/mcp

Conversation

@ndemianc

Copy link
Copy Markdown
Member

MCP shipped across slices S1–S6a (#41, #55, #56, #57, #58) and has no user-facing documentation. The only mention is a fifteen-line aside on the Agent page.

Adds an MCP group between AI and The editor.

MCP servers — /docs/mcp

What the protocol is, exactly what LevelCode implements and what it doesn't, the three ways to add a server, and the approval model in full — which tier a server came from, the launch gate for repo-defined ones, the allow-list, and why Autopilot doesn't relax any of it.

Plus the two things that surprise people, both of which are architectural rather than incidental:

  • Every tool schema rides every turn. A sixty-tool server spends context on every message whether you use it or not. The page points at the context popover's MCP segment.
  • A result reaches the agent as text. A server returning an inline image block produces [image image/png omitted] and nothing else.

Server recipes — /docs/mcp-recipes

Configurations that work: GitHub (with a wrapper that keeps the token in the keychain rather than settings.json), filesystem, image generation, and hosted servers through a stdio bridge.

The traps documented here are the ones that cost real time:

Trap Why it bites
"command": "env FOO=1 npx" Every other client's README shows this. We spawn with no shell, so it's one filename → ENOENT
models.searchreplicate__models_search Dots are illegal in tool names, so an allow-list key using the raw name silently never matches
Works from a terminal, not from the Dock macOS GUI apps don't inherit your shell environment, so an exported key isn't there
"*": "allow" on GitHub No GitHub tool sets destructiveHint, so that grants merge_pull_request too

Ten troubleshooting entries, each tied to a message the product actually prints.

Sourcing

Every setting, limit and behaviour was read out of the shipped extension, not recalled. The caps table comes from mcpConfig.js / mcpClient.js / mcpProtocol.js; the image-result table was measured against flattenContent rather than inferred from the protocol spec.

One stale claim fixed

The Agent page said "opening an untrusted repo can never make LevelCode spawn a process". That's been inaccurate since S4b — a repo can define servers in .levelcode/mcp.json. They just can't start without you approving the exact command line, which is a more interesting guarantee and now has a page to explain it. The aside is replaced by a pointer.

Verified, not assumed

Checked in the browser against the running app:

  • both pages render; every component mounts (Steps, 10 Accordions, callouts, 9 tables, 15 code blocks)
  • deep links scroll to the right heading — /docs/mcp#trust-and-approval lands 23px from the top
  • zero broken in-page anchors (asserted across every href^="#" on both pages)
  • llms.txt regenerates to 6 groups / 15 pages with both entries
  • npm run build and npm run lint clean, 0 errors
  • docs stay in their own lazy chunk — entry bundle unchanged at 130 kB, prose in bundle-*.js

…necting

MCP shipped across slices S1–S6a (levelcodeai/levelcode#41, #55, #56, #57, #58)
and had no user-facing documentation. The only mention was a fifteen-line aside
in the Agent page.

Adds a two-page **MCP** group between AI and The editor:

**MCP servers** (/docs/mcp) — what the protocol is, exactly what LevelCode
implements and what it does not, the three ways to add a server, and the
approval model in full: which tier a server came from, the launch gate for
repo-defined ones, the allow-list, and why Autopilot does not relax any of it.
Also the two things that surprise people — every tool schema rides every turn,
and a result reaches the agent as text, so inline images are dropped.

**Server recipes** (/docs/mcp-recipes) — configurations that work: GitHub with a
wrapper that keeps the token in the keychain instead of settings.json,
filesystem, image generation, and hosted servers through a stdio bridge. Plus
the traps that cost real time: the `env FOO=1 npx` command form every other
client's README shows, which fails here because we spawn with no shell; dotted
tool names arriving rewritten, so an allow-list key silently never matches; and
a GUI launch not inheriting the shell environment. Ten troubleshooting entries.

Every setting, limit and behaviour was read out of the shipped extension rather
than recalled — the caps table is mcpConfig.js/mcpClient.js/mcpProtocol.js, and
the image-result table was measured against flattenContent.

The Agent page's MCP aside is replaced by a pointer. Its claim that "opening an
untrusted repo can never make LevelCode spawn a process" had gone stale: a repo
CAN define servers in .levelcode/mcp.json since S4b — they just cannot start
without approval, which is a more interesting guarantee and now has a page to
explain it.

Verified in the browser, not assumed: both pages render, every component mounts
(Steps, Accordions, callouts, tables), deep links scroll to the right heading,
and zero in-page anchors are broken. llms.txt regenerates to 15 pages. Build and
lint clean; the docs stay in their own lazy chunk, so the entry bundle is
unchanged at 130 kB.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class user-facing documentation for Model Context Protocol (MCP) support in LevelCode, including a new docs nav group and two new pages covering the protocol/approval model plus practical server configuration recipes. Updates the Agent page to point readers to the new MCP docs and refreshes the generated llms.txt index accordingly.

Changes:

  • Add new docs pages: /docs/mcp (protocol + trust/approval model) and /docs/mcp-recipes (working configurations + troubleshooting).
  • Wire the new pages into the docs navigation and docs bundle routing.
  • Update existing docs index surfaces (Agent page MCP section + public/llms.txt).

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/levelcode/docs/nav.ts Adds an MCP docs group and links to the two new pages.
src/levelcode/docs/mcp.mdx New MCP overview page documenting capabilities, trust/approval, limits, and caveats.
src/levelcode/docs/mcp-recipes.mdx New recipes page with practical server configs (GitHub/filesystem/image/hosted bridge) + troubleshooting.
src/levelcode/docs/bundle.tsx Registers the two new docs pages in the lazy-loaded docs bundle.
src/levelcode/docs/agent.mdx Replaces the older aside with a succinct pointer to the new MCP docs.
public/llms.txt Adds an MCP section and links for the new pages.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/levelcode/docs/mcp.mdx Outdated
Comment thread src/levelcode/docs/mcp-recipes.mdx Outdated
Comment on lines +50 to +52
GH=${GH_BIN:-/opt/homebrew/bin/gh}
DOCKER=${DOCKER_BIN:-/usr/local/bin/docker}

**The GitHub wrapper hard-coded Homebrew and Docker paths.** `/opt/homebrew/bin/gh`
is the Apple Silicon prefix; on an Intel Mac gh lives in /usr/local/bin, so a
copy-pasted script failed outright on hardware LevelCode supports.

Fixed, but not with `command -v` alone as suggested — that would have broken the
one case the wrapper exists for. A GUI-launched macOS app inherits a minimal PATH
(/usr/bin:/bin:/usr/sbin:/sbin) containing neither Homebrew prefix, and "works
from a terminal, not from the Dock" is a documented entry on this very page. PATH
lookup on its own reintroduces it.

So: explicit override, then PATH, then the known install locations — both Homebrew
prefixes, /usr/bin, and Docker Desktop's bundled bin — and a message naming the
missing binary rather than an opaque ENOENT.

Extracted the script from the rendered page and ran it, so what ships is what was
tested:

  1. Apple Silicon, full PATH        -> /opt/homebrew/bin/gh, /usr/local/bin/docker
  2. minimal PATH (Dock launch)      -> both still resolve
  3. Intel (no /opt/homebrew)        -> resolves from /usr/local/bin
  4. binary absent                   -> "gh not found", exit 78
  5. GH_BIN / DOCKER_BIN set         -> override wins

Also: `sanitises` -> `sanitizes` and `catalogue` -> `catalog`. The repo is
American English (behavior, customize, license, color; no British spellings), so
these were the only two. Swept both new pages for the rest of the -ise/-our set —
clean.

Build and lint green.
@ndemianc

Copy link
Copy Markdown
Member Author

Both addressed in f926002.

Hard-coded binary paths — correct and worse than it looked: /opt/homebrew/bin is the Apple Silicon prefix, so the copy-pasted script failed outright on Intel Macs, which LevelCode supports.

I didn't take command -v on its own, though. That would have broken the one case the wrapper exists for: a GUI-launched macOS app inherits a minimal PATH (/usr/bin:/bin:/usr/sbin:/sbin) with neither Homebrew prefix on it — and "works from a terminal, not from the Dock" is a documented troubleshooting entry on this same page. PATH lookup alone reintroduces exactly that bug.

The resolution order is now explicit override → PATH → known install locations (both Homebrew prefixes, /usr/bin, and Docker Desktop's bundled bin), with an error naming the missing binary instead of an opaque ENOENT.

Extracted the script from the rendered page and ran it, so what ships is what was tested:

Case Result
Apple Silicon, full PATH /opt/homebrew/bin/gh, /usr/local/bin/docker
Minimal PATH (Dock launch) both still resolve
Intel — no /opt/homebrew resolves from /usr/local/bin
Binary absent gh not found, exit 78
GH_BIN / DOCKER_BIN set override wins

Spelling — also correct. sanitisessanitizes, plus cataloguecatalog on the other page. The repo is American English (behavior, customize, license, color; no British spellings anywhere), so I swept both new pages for the rest of the -ise/-our set — those two were the only hits.

@ndemianc
ndemianc merged commit 2eb96cb into develop Jul 29, 2026
@ndemianc
ndemianc deleted the docs/mcp branch July 29, 2026 01:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants