Skip to content

feat: offer the V compiler to agents as an MCP server - #558

Open
metif12 wants to merge 2 commits into
vlang:masterfrom
metif12:feat/v-compiler-mcp-server
Open

metif12 wants to merge 2 commits into
vlang:masterfrom
metif12:feat/v-compiler-mcp-server

Conversation

@metif12

@metif12 metif12 commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

What this adds

The V compiler already speaks MCP. v mcp serve calls the parser, checker and
formatter in process, so its answers hold for code that does not compile yet
— which a language server working from a failed parse cannot manage. It also
carries the standard library documentation, so an agent can look a signature up
instead of guessing one.

Until now the only way to reach any of that was to hand-edit .mcp.json. This
registers the server through vscode.lm.registerMcpServerDefinitionProvider, so
VS Code discovers it on its own. One server per workspace folder, because the
tools answer about one project. VS Code starts a server only when an agent
actually calls one of its tools, so an unused workspace costs nothing.

The three writing tools are guarded by design, which is worth having in an
editor where an agent may act on your files unattended:

  • v_rename_symbol defaults to a dry run listing every file and position
  • v_format reports its diff before writing
  • v_edit_replace has no preview at all — it writes as soon as the range
    matches the text the agent passed back, so passing that text is the approval

Read-only by default

v.mcp.readOnly defaults to true, which passes --read-only. That is not a
hint, it is the server registering no writing tool at all. The other fifteen
carry a readOnlyHint annotation from the compiler (tools.v:100,120), so an
editor approves them without prompting, and only a write — if you opt in —
reaches a confirmation dialog.

The label reports the mode from the flag rather than from the tool catalog,
because the catalog lists all eighteen tools either way. A read-only server whose
label said "3 tools can write" would be the kind of small lie this PR is about.

Compilers without v mcp

v mcp landed recently, so plenty of users will be on a compiler that has never
heard of it. The extension runs v mcp tools once per compiler path, caches the
answer, and treats anything that is not a tool list as "no server". I checked the
real failure modes rather than assuming:

$ v mcp bogus            -> "unknown subcommand `bogus`", exit 1
$ v nosuchcommand       -> "unknown command `nosuchcommand`", exit 1

So the probe rejects an old compiler by output shape, not just exit code. Changing
v.executablePath discards the cached answer.

--root is always passed

v mcp serve defaults its root to the working directory. For an MCP server that
is wherever the client launched it, so relying on the default would put the
server's idea of the project outside the folder you have open. v.mcp.root
overrides it for the case where the V project root is not the folder you opened.

Verification

Detection, the command line and the label live in src/mcpProbe.ts, a pure
module, so they are tested without a compiler or an editor. Four tests cover
parsing the catalog, separating the writers, rejecting output that is not a tool
list (empty, usage text, unknown command, a line with no description column,
and CRLF), the --root/--read-only combinations, and per-folder labels.

I also ran the real compiler through the real parser rather than trusting the
fixture alone:

parsed a catalog: true
tool count: 18
writers: v_edit_replace, v_rename_symbol, v_format
checked 11 tools, mismatches: 0
rejects old compiler output: true
rejects usage text: true

npm test (27 tests, 24 pass), npm run lint, npm run lint:md,
npm run test:grammar and npm run package pass.

test:logic now names its test files explicitly rather than using --outfile,
so a second test file can be added without a glob that would not expand in an npm
script on Windows.

Known limitations

  • Not exercised in a real VS Code window. The extension-host suite needs a VLS
    binary, and the MCP definition provider is not covered by it. The pure logic
    is tested; the wiring is not.
  • The label carries the tool count, not the compiler version. Reporting a
    version would mean a second probe per compiler, which seemed a poor trade for
    a label. v mcp tools does not report one.
  • Three folders or more means three servers, each with its own tool list in the
    agent's context. That is inherent to one-project-per-server, but it is a reason
    to keep v.mcp.enable available to turn it off.

Relation to #554

This is orthogonal to #554, which is about V/VLS tool management and says nothing
about v mcp. I kept the footprint small for that reason: src/extension.ts
grows by five lines, the rest of the change is three new files and additive blocks
in package.json, so a rebase onto that branch should be mechanical.

Three tests fail on Windows both before and after this change (they assert POSIX
path separators, and CI runs on ubuntu-latest):

  • parses and merges covered and uncovered LCOV lines
  • uses the nearest V project root for standalone saves and coverage
  • scopes and preserves the configured server compiler

metif12 pushed a commit to metif12/vscode-vlang that referenced this pull request Oct 6, 2026
There was no onboarding. Tasks, CodeLens, coverage and the agent commands were
only discoverable from the README, so a user who did not read it had no way to
learn that `V: Check` or the coverage status item existed.

The walkthrough has three steps, each completing when the command it describes has
been run:

1. install V
2. build, run and test
3. check, vet and format

That means the walkthrough walks a new user through the extension's own commands
rather than asking them to read documentation first, and it is also the natural
home for the agent features when those land.

The agents step is deliberately absent. It would describe `v mcp` and `v
skills`, which are not on this branch, and a walkthrough step for a command that
does not exist is worse than no step. It can be added when vlang#558 and vlang#559 merge.

A test checks the walkthrough rather than trusting it: every step must have a
title, a description and a media file that exists in the repository, and every
completion event must name a declared command. I confirmed it catches something by
pointing a step at a missing file and watching it fail, then reverting.
@metif12
metif12 force-pushed the feat/v-compiler-mcp-server branch from aa1f77c to d1efaa3 Compare October 7, 2026 06:07
metif12 pushed a commit to metif12/vscode-vlang that referenced this pull request Oct 7, 2026
There was no onboarding. Tasks, CodeLens, coverage and the agent commands were
only discoverable from the README, so a user who did not read it had no way to
learn that `V: Check` or the coverage status item existed.

The walkthrough has three steps, each completing when the command it describes has
been run:

1. install V
2. build, run and test
3. check, vet and format

That means the walkthrough walks a new user through the extension's own commands
rather than asking them to read documentation first, and it is also the natural
home for the agent features when those land.

The agents step is deliberately absent. It would describe `v mcp` and `v
skills`, which are not on this branch, and a walkthrough step for a command that
does not exist is worse than no step. It can be added when vlang#558 and vlang#559 merge.

A test checks the walkthrough rather than trusting it: every step must have a
title, a description and a media file that exists in the repository, and every
completion event must name a declared command. I confirmed it catches something by
pointing a step at a missing file and watching it fail, then reverting.
office added 2 commits October 7, 2026 21:30
The compiler already speaks MCP: `v mcp serve` calls the parser, checker and
formatter in process, so it answers correctly about code that does not compile
yet. An LSP working from a failed parse cannot. It also carries the standard
library documentation, so an agent can look a signature up rather than guess one,
and its three editing tools are guarded: a rename defaults to a dry run listing
every position it would change, and a replacement has to match text the agent
read back first.

Until now the only way to reach any of that was to hand-edit `.mcp.json`. The
extension registers the server instead, one per workspace folder, so VS Code
finds it on its own and starts it only when an agent calls a tool.

`v mcp` is recent, so a compiler may not have it. The extension probes
`v mcp tools` once per compiler path, caches the answer, and offers nothing when
the output is not a tool list, which is how an older compiler is recognised.
Changing `v.executablePath` discards the cached answer.

The server starts read-only by default. That registers no tool that writes a
file at all, and the remaining fifteen carry `readOnlyHint`, so an editor
approves them without asking. `v.mcp.readOnly` is what the label reports rather
than the catalog, because the catalog lists every tool the compiler has either
way.

`--root` is always passed. The server defaults it to its working directory,
which for an MCP server is wherever the client launched it, so relying on the
default would put the project's root outside the folder the user opened.

Detection, the command line and the label live in a pure module so they can be
tested without a compiler or an editor.
Resolving � for a workspace folder is not specific to MCP, and having two
implementations would let them drift apart when the resolution changes. It
now lives in src/vExecutable.ts.
@metif12
metif12 force-pushed the feat/v-compiler-mcp-server branch from d1efaa3 to db47626 Compare October 7, 2026 18:02
metif12 pushed a commit to metif12/vscode-vlang that referenced this pull request Oct 7, 2026
There was no onboarding. Tasks, CodeLens, coverage and the agent commands were
only discoverable from the README, so a user who did not read it had no way to
learn that `V: Check` or the coverage status item existed.

The walkthrough has three steps, each completing when the command it describes has
been run:

1. install V
2. build, run and test
3. check, vet and format

That means the walkthrough walks a new user through the extension's own commands
rather than asking them to read documentation first, and it is also the natural
home for the agent features when those land.

The agents step is deliberately absent. It would describe `v mcp` and `v
skills`, which are not on this branch, and a walkthrough step for a command that
does not exist is worse than no step. It can be added when vlang#558 and vlang#559 merge.

A test checks the walkthrough rather than trusting it: every step must have a
title, a description and a media file that exists in the repository, and every
completion event must name a declared command. I confirmed it catches something by
pointing a step at a missing file and watching it fail, then reverting.
metif12 pushed a commit to metif12/vscode-vlang that referenced this pull request Oct 9, 2026
There was no onboarding. Tasks, CodeLens, coverage and the agent commands were
only discoverable from the README, so a user who did not read it had no way to
learn that `V: Check` or the coverage status item existed.

The walkthrough has three steps, each completing when the command it describes has
been run:

1. install V
2. build, run and test
3. check, vet and format

That means the walkthrough walks a new user through the extension's own commands
rather than asking them to read documentation first, and it is also the natural
home for the agent features when those land.

The agents step is deliberately absent. It would describe `v mcp` and `v
skills`, which are not on this branch, and a walkthrough step for a command that
does not exist is worse than no step. It can be added when vlang#558 and vlang#559 merge.

A test checks the walkthrough rather than trusting it: every step must have a
title, a description and a media file that exists in the repository, and every
completion event must name a declared command. I confirmed it catches something by
pointing a step at a missing file and watching it fail, then reverting.
metif12 pushed a commit to metif12/vscode-vlang that referenced this pull request Oct 9, 2026
There was no onboarding. Tasks, CodeLens, coverage and the agent commands were
only discoverable from the README, so a user who did not read it had no way to
learn that `V: Check` or the coverage status item existed.

The walkthrough has three steps, each completing when the command it describes has
been run:

1. install V
2. build, run and test
3. check, vet and format

That means the walkthrough walks a new user through the extension's own commands
rather than asking them to read documentation first, and it is also the natural
home for the agent features when those land.

The agents step is deliberately absent. It would describe `v mcp` and `v
skills`, which are not on this branch, and a walkthrough step for a command that
does not exist is worse than no step. It can be added when vlang#558 and vlang#559 merge.

A test checks the walkthrough rather than trusting it: every step must have a
title, a description and a media file that exists in the repository, and every
completion event must name a declared command. I confirmed it catches something by
pointing a step at a missing file and watching it fail, then reverting.
metif12 pushed a commit to metif12/vscode-vlang that referenced this pull request Oct 10, 2026
There was no onboarding. Tasks, CodeLens, coverage and the agent commands were
only discoverable from the README, so a user who did not read it had no way to
learn that `V: Check` or the coverage status item existed.

The walkthrough has three steps, each completing when the command it describes has
been run:

1. install V
2. build, run and test
3. check, vet and format

That means the walkthrough walks a new user through the extension's own commands
rather than asking them to read documentation first, and it is also the natural
home for the agent features when those land.

The agents step is deliberately absent. It would describe `v mcp` and `v
skills`, which are not on this branch, and a walkthrough step for a command that
does not exist is worse than no step. It can be added when vlang#558 and vlang#559 merge.

A test checks the walkthrough rather than trusting it: every step must have a
title, a description and a media file that exists in the repository, and every
completion event must name a declared command. I confirmed it catches something by
pointing a step at a missing file and watching it fail, then reverting.
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.

1 participant