Skip to content

feat: add ai mcp stdio MCP server - #110

Merged
ctate merged 16 commits into
mainfrom
feat/mcp-server
Oct 29, 2026
Merged

ctate merged 16 commits into
mainfrom
feat/mcp-server

Conversation

@lahfir

@lahfir lahfir commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor
  1. Agents could only use ai by shelling out and guessing flags, with no typed contract to discover.
  2. ai mcp adds a stdio MCP server whose tools are generated from the CLI's own command definitions, so every call runs the same ai binary and new flags show up automatically.
  3. No related issues or PRs.

Demo

opencode connected to ai mcp lists the tools and makes a typed decision with openai/gpt-6-luna-decisions.

demo.mp4

`ai mcp [--profile core|media|all]` serves newline-delimited JSON-RPC
(MCP 2025-11-25, tools only). Each tool call runs the same `ai` binary
with the typed arguments turned into argv, so the CLI stays the only
place that does the work.

Tool schemas come from the registered command tree through a new
read-only `Command.definition()` accessor. A small override table adds
what the parser cannot know: profile, forced --json, required output on
video start, hidden plumbing flags, and the typed ai_decide questions.

Child runs ignore stdin (except decide state), have no controlling TTY,
run with color off, and are killed as a process group on timeout,
stdout close, or SIGTERM/SIGINT/SIGHUP.
Unit tests for the argv translation, validation messages, and result
mapping, plus one end-to-end stdio session against the built binary
that compares ai_models with plain `ai models --json`.

A sync test walks the CLI command tree and fails when a command is
neither a tool nor explicitly excluded, or when a command option is
neither exposed nor hidden, so CLI changes cannot silently drift from
the MCP tools.
Add an MCP page to the website docs and nav, an MCP section to the
README, the command to the agent skill and footer, and an Unreleased
changelog entry. The release markers stay on 0.7.0.

AGENTS.md now says how to keep MCP in step with the CLI: map or exclude
new commands and hide flags agents should not see; the sync test
enforces it.
Drop the duplicated question schema, unreachable checks, and the second
input pass; move decide's replaced flags into its override; skip blank
stdin lines. Require text and audio on the speech tools, since MCP runs
have no stdin to fall back on.

Tests now cover only behavior that can break: argv encoding, input the
CLI would misread, result mapping, one stdio session against the built
binary, and the CLI sync check. The sync check walks every runnable
command (new `runnable` field on Command.definition()), so a command
with subcommands and its own action, like `video`, is not missed.
opencode prefixes tool ids with the server key, so a key of `ai` shows
tools as `ai_ai_text`. Found while dogfooding the server in opencode.
- Requests without `jsonrpc: "2.0"` or with a non string/number id now
  get -32600 instead of running.
- `decide --images` gets the `[]` default the other repeatable options
  have, so the generated ai_decide schema takes an array of images.
- An empty value for a required input, such as video start `output`,
  counts as missing, so no video is submitted without its operation file.
- A failed run with no output reports its exit code or signal.

Adds a stdio test that a hung child is killed at its timeout; it fails
if the process-group kill is removed.
@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
ai-cli Ready Ready Preview, v0 Oct 29, 2026 1:01pm UTC

@vercel-security-reviewer

Copy link
Copy Markdown

Security review details

Tools keep the binary-name prefix (ai_*) and the opencode examples use
the server key "ai", matching agent-browser's agent_browser_* tools
under the "agent-browser" key. Reverts the cli key change.
An agent could pass `--base-url` through extraArgs and point image,
video, or models at its own endpoint. The child inherits the server's
AI_GATEWAY_API_KEY, so the request carried the key as a bearer token.

Gateway connection flags (--base-url, --headers, --team-id-or-slug) are
now rejected in extraArgs in both the split and `=` forms, and were
already hidden from typed inputs. The blocked flags come from each
command's definition, so a new command with these options is covered.
Operators set AI_GATEWAY_BASE_URL and AI_GATEWAY_TEAM_ID_OR_SLUG in the
server environment instead. The models tool hint no longer suggests
--base-url.
Comment thread packages/ai-cli/src/commands/mcp.ts
Move setup to the top of the MCP page and README section. It says the
server reads AI_GATEWAY_API_KEY from its environment and gives a
copy-paste setup for Claude Code, Codex, opencode, and mcpServers
clients, plus a table of the variables the server reads.
The README MCP section repeated the website page. It now shows the
mcpServers config with the API key and links to the MCP docs for other
clients, profiles, and tools. The docs page leads with the mcpServers
config that most clients accept, then opencode, Claude Code, and Codex.
fx is the first setup example on the MCP page. Placeholders now read
your-vercel-ai-gateway-api-key, and the README links to the MCP page
for configuring any MCP client rather than naming a few.
An empty string skipped type checks for every input, so `extraArgs: ""`
reached the connection-flag check as a string and threw, taking the
whole server down. Only required inputs now treat "" as missing; other
inputs are type-checked as usual. An unexpected error inside a request
now returns a JSON-RPC -32603 error instead of exiting the server.
Many MCP clients pass only a few variables to the servers they start,
so exporting the key in the shell does not reach the server. The MCP
Inspector showed this: the key reached the server only through its
-e flag.
MCP clients already put the server name in front of each tool, so the
ai_ prefix showed up twice, as ai_ai_text in opencode. Tools are now
text, image, decide, models, video_start, video_status, audio_speak, and
audio_transcribe.
- Retain MCP tools and Gateway scope support.
- Keep Gateway connection settings in the server environment.
@ctate
ctate merged commit 3d5bad7 into main Oct 29, 2026
11 checks passed

This branch was successfully deployed

1 active deployment
Preview — 999c57a9 Deployed Oct 29, 2026 by vercel[bot]
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