8000 feat(mcp): minimal sessions MCP by 0chroma · Pull Request #1778 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

feat(mcp): minimal sessions MCP - #1778

Closed
0chroma wants to merge 6 commits into
mainfrom
mcp-server
Closed

0chroma wants to merge 6 commits into
mainfrom
mcp-server

Conversation

@0chroma
@0chroma 0chroma commented Oct 1, 2026
Copy link
Copy Markdown
Contributor

min mcp serves the Model Context Protocol over stdio, exposing the session plane as a sandboxed shell-execution surface for an agent harness. Tools create isolated sandboxes (uploading a working directory), run commands, read and write files, and manage sessions.

Stacked on the activation extraction in the PR below.

Tools

  • list_loadouts, create_session, destroy_session, list_sessions
  • exec, with optional stdin and a timeout, returning stdout, stderr, and exit code
  • read_file and write_file over SFTP, resolving at the session home

The first exec or file call with no session_id lazily creates a default session from --workdir. The initialize instructions field states the contract. Each session has its own filesystem and processes. Creating one uploads a directory that becomes /workbench. Sessions persist until destroyed.

Approach

  • New shared-client helpers: Client::exec_collect drains an exec channel with an optional timeout, and Client::open_sftp opens the SFTP subsystem.
  • The loadout listing splits into loadout_listing, shared by min loadout list and the list_loadouts tool.
  • A headless activation reuses every client-side resolution step with a concrete Send gate, which the rmcp tool handlers require.

stdout is the JSON-RPC channel, so Command::Mcp routes tracing to stderr and the uploads draw no progress bars.

Risks

The server creates sandboxes and runs commands on the host daemon. Session creation uses the same gate as the CLI, so a composition needing interactive approval fails with the user_policy.toml hint. New dependency: rmcp, vetted by cargo-deny.

Testing

cargo test -p minimal --test mcp drives the compiled binary over stdio against a test daemon: initialize, tool listing, create, list, and destroy. exec and SFTP need a real package registry to spawn, so the integration test covers creation and management. Unit tests cover argv quoting, the instructions text, and parameter parsing.

@coderabbitai
coderabbitai Bot commented Oct 1, 2026 •
Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@0chroma
0chroma added this pull request to stack #1779 October 1, 2026 06:32
@0chroma 0chroma changed the title feat(mcp): serve MCP over minimal sessions feat(mcp): MCP for minimal sessions Oct 1, 2026
@0chroma 0chroma changed the title feat(mcp): MCP for minimal sessions feat(mcp): minimal sessions MCP Oct 1, 2026
@0chroma
0chroma force-pushed the mcp-server branch 2 times, most recently from 6166ed3 to 7f0b725 Compare October 9, 2026 00:49
@0chroma
0chroma removed this pull request from stack #1779 October 9, 2026 00:50
@0chroma
0chroma changed the base branch from refactor/activation-to-minimal-client to refactor/dash-share-cli-helpers October 9, 2026 00:50
@0chroma
0chroma added this pull request to stack #2115 October 9, 2026 00:50
@0chroma
0chroma force-pushed the mcp-server branch 5 times, most recently from f93f8ae to 6b11754 Compare October 10, 2026 05:30
@0chroma
0chroma force-pushed the mcp-server branch 3 times, most recently from 50c2b13 to e1d2d1b Compare October 14, 2026 17:54
@0chroma
0chroma force-pushed the mcp-server branch 2 times, most recently from d3117a1 to fcddf99 Compare October 15, 2026 15:11
@0chroma
0chroma force-pushed the mcp-server branch 3 times, most recently from 5b9293d to 89aa28e Compare October 20, 2026 18:12
Base automatically changed from refactor/dash-share-cli-helpers to main October 27, 2026 12:32
Add `min mcp`, a Model Context Protocol server on stdio that exposes the
session plane as a shell-execution surface for an agent harness. Tools
create isolated sandboxes (uploading a working directory), exec commands,
read and write files over SFTP, list and destroy sessions, and list
loadouts; the initialize instructions teach the isolation, upload,
/workbench layout, default-session, and lifetime contract.

Supporting client helpers: `Client::exec_collect` (drain an exec channel
into stdout/stderr/exit code with an optional timeout), `Client::open_sftp`,
and a structured loadout listing shared with `min loadout list`. The
activation core gains `activate_headless`, whose concrete gate keeps the
future `Send` for rmcp handlers; the CLI split exposes a headless create
that shares every client-side resolution step.

stdout is the JSON-RPC channel, so `Command::Mcp` joins the tracing
stdout-contract set and the uploads are quiet.
SftpSession::write opens with OpenFlags::WRITE alone, so write_file failed
with ENOENT on any file that did not already exist and never truncated an
existing one. Open with create (CREATE | TRUNCATE | WRITE), write, and close
the handle instead.

The SFTP server also resolves a bare relative path against the sandbox root,
not the session home as the tool descriptions claimed. Anchor relative paths
at /workbench, the uploaded tree and the exec working directory, and correct
the descriptions and the initialize instructions.

Extend the mcp integration test with a write/read round-trip so the regression
is covered.
… them all

The headless gate refused every Pending configure response, so min mcp could not
create a session the CLI creates without a prompt: the daemon routes project
config back for gating even when the user policy approves every item, and min
session activate --no-prompt resolves that with NoPromptHook and only aborts
when an item genuinely needs a prompt.

Give the server the same lane: compute the verdict under NoPromptHook and the
user policy, submit it when nothing is left unapproved, and refuse with the
user_policy.toml snippet only when something is. Drop the minimal-client
RefusePending gate; the MCP path supplies this concrete, Send gate instead.
create_session gains a `sync` argument: `tarball` force-uploads the
working directory, `none` starts the sandbox with an empty workspace, and
omitting it keeps the activation default, which uploads only a VCS root
or a directory carrying a minimal.toml. The result now reports `uploaded`
so the model knows whether /workbench is populated.

Thread the resolved upload decision through the shared activation core
(`PreparedActivation` and `ActivatedSession` gain `uploaded`), and update
the tool and section descriptions to state the upload rules.
`min mcp` only spoke stdio. Enable rmcp's streamable-HTTP server
transport and serve it under `/mcp` with axum, selected by a new
`--transport` flag; `--bind` (default 127.0.0.1:3000) chooses the
address.

Loopback is the default because the server runs unrestricted commands
in the sandboxes it creates. A non-loopback bind is an explicit
exposure: rmcp's Host-header allowlist is disabled for it and a stderr
warning says it carries no authentication.

The bound address goes to stderr (stdout stays empty in HTTP mode), so
a `--bind ...:0` caller can find the port. The integration test drives
initialize, notifications/initialized, and tools/list over HTTP.
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

0