Skip to content

feat(mcp): serve mise's command effects to agents - #11389

Merged
jdx merged 1 commit into
mainfrom
claude/mise-mcp-commands
Jul 27, 2026
Merged

feat(mcp): serve mise's command effects to agents#11389
jdx merged 1 commit into
mainfrom
claude/mise-mcp-commands

Conversation

@jdx

@jdx jdx commented Jul 27, 2026

Copy link
Copy Markdown
Owner

mise classifies all 167 of its commands as read, write or destructive (#11306) — and nothing an agent talks to can see any of it. mise mcp exposes install_tool and run_task, neither of which says what a command does. An agent about to run mise prune has the answer sitting in the binary and no way to ask for it.

This adds list_commands, returning the command tree with each command's effect, help and hidden flag:

156 visible commands — 74 read, 65 write, 7 destructive, 10 deliberately unclassified
prune         → destructive
ls            → read
install       → write
settings set  → write
run           → (unclassified)

How

cli::usage::spec() is extracted out of Usage::run, so the spec mise usage prints and the one mise mcp serves are the same construction rather than two that drift. It's built once in MiseServer::new — deriving it walks the whole clap tree, which isn't work to repeat per request.

Hidden commands take their subtree with them. clap doesn't propagate hide, so bootstrap launchd is hidden while bootstrap launchd apply isn't; a flat filter on hide would surface the child along with the hidden path it sits under.

On unclassified commands

A missing effect means unknown, not safe, and the tool description says so explicitly. Ten commands are deliberately unset because they run code the user supplies — run, exec, watch, tool-stub, en, oci run — where any label would be a lie in one direction or the other, and read in particular would be dangerous.

The risk is a new command going unlabeled by accident and reading the same way. A test asserts every unclassified command in the served output has an entry in command_effects::UNCLASSIFIED, which is where the reason lives.

Not in this PR

describe_command — per-command flags and args with their own effects — needs usage::available_flags from jdx/usage#746 to resolve inherited globals correctly. mise's run re-declares root globals as non-global flags, which is precisely the case a hand-rolled ancestor walk gets wrong (it reports the local declaration's absent effect instead of the global's). It follows once that releases.

Verified

Against a real client handshake — initializenotifications/initializedtools/listtools/call — plus five unit tests covering the effects surviving into the output, nested paths, hidden-subtree pruning, and the unclassified guard.

This PR was generated by an AI coding assistant.


Note

Low Risk
Additive MCP surface and refactored spec construction; no changes to how mise commands execute on disk.

Overview
Exposes mise’s read / write / destructive command classifications to MCP clients via a new list_commands tool, so agents can see what a CLI subcommand does before invoking it.

list_commands walks the shared usage spec and returns JSON rows (command, help, effect, hidden). Optional include_hidden controls whether hidden commands appear; when hidden, entire subtrees are omitted (so children of a hidden parent do not leak). Server instructions now tell clients to call list_commands first and treat a missing effect as unknown, not safe.

cli::usage::spec() is extracted from mise usage and reused by MiseServer, with the spec cached in Arc at startup. Docs (docs/cli/mcp.md, usage KDL) list the new tool. Unit tests cover effects in output, nesting, hidden pruning, and a guard that only deliberately unclassified commands lack an effect.

Reviewed by Cursor Bugbot for commit 1dcf0fd. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Added the list_commands MCP tool and resource to enumerate available mise commands.
    • Results include command descriptions, declared effects, and hidden-command status.
    • Added an include_hidden option to include hidden commands when needed.
    • Nested command effects are now represented consistently.
  • Documentation

    • Updated MCP documentation and CLI help with the new tool, resource, and usage example.

mise classifies all 167 of its commands as `read`, `write` or
`destructive` (#11306), and nothing an agent talks to can see any of it.
`mise mcp` exposes two tools, `install_tool` and `run_task`, neither of
which says what a command does. So an agent about to run `mise prune`
has the answer sitting in the binary and no way to ask for it.

`list_commands` returns the command tree with each command's effect,
help and hidden flag. 156 visible commands: 74 read, 65 write, 7
destructive, 10 deliberately unclassified.

The spec is built once in `MiseServer::new` from `cli::usage::spec()`,
extracted from `Usage::run` so the spec `mise usage` prints and the one
`mise mcp` serves cannot drift. Deriving it walks the whole clap tree,
which is not work to repeat per request.

Hidden commands take their subtree with them, since clap does not
propagate `hide` and a visible child of a hidden parent is not a
documented path — `bootstrap launchd apply` would otherwise surface
along with the hidden path it sits under.

A missing effect means unknown, not safe, and the tool description says
so. Ten commands are deliberately unset because they run code the user
supplies — `run`, `exec`, `watch`, `tool-stub` — where any label would
be a lie in one direction or the other. A test asserts every unclassified
command has an entry in `command_effects::UNCLASSIFIED`, so a new command
cannot go unlabeled by accident.

`describe_command` (per-command flags and args, with their own effects)
needs `usage::available_flags` from jdx/usage#746 to resolve inherited
globals correctly — mise's `run` re-declares root globals as non-global
flags, which is exactly the case a hand-rolled walk gets wrong. It
follows once that releases.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d835348-6f05-4778-a490-fd62b8545bec

📥 Commits

Reviewing files that changed from the base of the PR and between b1018ab and 1dcf0fd.

📒 Files selected for processing (4)
  • docs/cli/mcp.md
  • mise.usage.kdl
  • src/cli/mcp.rs
  • src/cli/usage.rs

📝 Walkthrough

Walkthrough

Adds the MCP list_commands tool, backed by a reusable usage specification, to return command metadata including help, effects, and hidden status. It also adds filtering behavior, tests, expanded server instructions, and CLI/documentation examples.

Changes

MCP command discovery

Layer / File(s) Summary
Reusable usage specification
src/cli/usage.rs, src/cli/mcp.rs
Exports usage-spec construction and caches the specification in MiseServer; list_commands accepts an include_hidden option.
list_commands implementation
src/cli/mcp.rs
Traverses command metadata, filters hidden subtrees by default, and returns JSON records containing command, help, effect, and hidden fields.
Validation and documentation
src/cli/mcp.rs, docs/cli/mcp.md, mise.usage.kdl
Tests nested effects and hidden filtering, while help and documentation describe the tool and its example payload.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPClient
  participant MiseServer
  participant UsageSpec
  MCPClient->>MiseServer: list_commands(include_hidden)
  MiseServer->>UsageSpec: traverse command tree
  UsageSpec-->>MiseServer: command metadata
  MiseServer-->>MCPClient: JSON result
Loading

Possibly related PRs

  • jdx/mise#11306: Provides centralized command effect metadata consumed by this command listing.
  • jdx/mise#11361: Also modifies MCP server metadata in src/cli/mcp.rs.

Suggested reviewers: risu729, jambalaya56562

Poem

I’m a bunny with commands to share,
Effects and help now float through the air.
Hidden ones nap unless asked to arise,
JSON trails sparkle before curious eyes.
Hop through the spec—what a neat little leap! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: exposing mise command effects through MCP for agents.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@greptile-apps

greptile-apps Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds an MCP list_commands tool that exposes mise’s command tree, help text, visibility, and declared effects.

  • Extracts shared usage-spec construction for the CLI and MCP server.
  • Prunes hidden command subtrees unless explicitly requested.
  • Adds tests covering effects, nested commands, hidden commands, and deliberate unclassification.
  • Updates generated MCP usage documentation.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete correctness or security failures identified in the changed paths.

The MCP tool traverses the same usage command tree that receives effect annotations, hidden subtrees are pruned deliberately and tested, and the usage refactor preserves the previous output construction.

Important Files Changed

Filename Overview
src/cli/mcp.rs Adds the cached command specification, list_commands MCP tool, JSON response helper, client instructions, and focused tests without an identified actionable defect.
src/cli/usage.rs Extracts usage-spec construction into a shared pure function while preserving the existing mise usage output assembly.
mise.usage.kdl Updates the generated usage specification documentation to advertise the new MCP tool.
docs/cli/mcp.md Documents list_commands and its include_hidden argument consistently with the implementation.

Reviews (1): Last reviewed commit: "feat(mcp): serve mise's command effects ..." | Re-trigger Greptile

@github-actions

Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.7.14 x -- echo 19.2 ± 1.5 16.7 25.0 1.00
mise x -- echo 20.7 ± 1.7 17.2 27.5 1.08 ± 0.12

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.7.14 env 19.0 ± 1.5 16.1 27.9 1.00
mise env 20.5 ± 1.6 16.4 32.4 1.08 ± 0.12

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.7.14 hook-env 19.2 ± 1.2 16.6 23.6 1.00
mise hook-env 20.3 ± 1.5 17.5 24.8 1.06 ± 0.10

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.7.14 ls 16.5 ± 1.1 14.2 21.8 1.00
mise ls 18.9 ± 1.6 15.3 25.8 1.14 ± 0.12
⚠️ Inconclusive: ls measured 14% slower, but the relative uncertainty overlaps the 10% threshold.

xtasks/test/perf

Command mise-2026.7.14 mise Variance
install (cached) 163ms 179ms -8%
ls (cached) 64ms 68ms -5%
bin-paths (cached) 68ms 72ms -5%
task-ls (cached) 94ms 97ms -3%

@jdx
jdx merged commit dc0829e into main Jul 27, 2026
35 checks passed
@jdx
jdx deleted the claude/mise-mcp-commands branch July 27, 2026 17:56
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