Skip to content

Comments

feat(mcp): add run_task tool for executing mise tasks#8179

Merged
jdx merged 10 commits intojdx:mainfrom
joaommartins:feature(mcp)/add-run-task-tool
Feb 17, 2026
Merged

feat(mcp): add run_task tool for executing mise tasks#8179
jdx merged 10 commits intojdx:mainfrom
joaommartins:feature(mcp)/add-run-task-tool

Conversation

@joaommartins
Copy link
Contributor

Summary

  • Add working run_task MCP tool that executes mise tasks via subprocess with full stdout/stderr capture
  • Integrate rmcp's #[tool_router] macro system with schemars-derived JSON schemas for self-describing tools
  • Add install_tool stub with proper schema (returns not-yet-implemented error)
  • Harden subprocess execution: kill_on_drop(true), stdin(null), -- arg separator, timeout support via task_timeout_duration()
  • Update documentation with tool parameters, examples, and integration guide
  • Rewrite e2e tests with full MCP protocol coverage (initialize, tools/list, run_task success/args/unknown, install_tool stub)

Test plan

  • mise run test:e2e test_mcp_protocol passes — tests initialize handshake, tool listing with schema validation, task execution (success, with args, unknown task error), and install_tool stub
  • Manual testing with Claude Desktop or other MCP client

Implements the run_task MCP tool that allows AI assistants to execute
mise tasks with optional arguments, returning stdout/stderr and exit status.
…t handling

Replace spawn_blocking with tokio::process::Command for direct async
execution. Simplify output formatting using match expressions and use
ErrorData types. Update docs to reflect implemented run_task tool.
- Use spawn() with kill_on_drop(true) to prevent orphaned processes on timeout
- Set stdin to Stdio::null() to isolate child from MCP JSON-RPC transport
- Add -- separator before task args to prevent flag confusion with mise run
- Add install_tool stub with proper schema via ToolRouter
- Rewrite e2e tests with full protocol coverage: initialize handshake,
  tools/list schema validation, run_task success/args/unknown, install_tool stub
- Remove hardcoded developer path and unnecessary chmod from test
Copilot AI review requested due to automatic review settings February 16, 2026 12:21
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @joaommartins, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the Model Context Protocol (MCP) integration within mise by introducing a new run_task tool. This allows AI assistants to directly execute mise tasks, expanding the interactive capabilities and enabling more dynamic and automated development workflows. The changes also improve the robustness of tool execution and provide better self-description for MCP clients through schema generation.

Highlights

  • New run_task MCP Tool: Implemented a fully functional run_task Model Context Protocol (MCP) tool, allowing AI assistants to execute mise tasks via subprocesses with comprehensive stdout/stderr capture.
  • Dynamic Tool Schema Generation: Integrated rmcp's #[tool_router] macro system with schemars to automatically generate JSON schemas for self-describing tools, enhancing discoverability and validation for MCP clients.
  • Robust Subprocess Execution: Hardened subprocess execution for run_task by adding kill_on_drop(true), stdin(null), a -- argument separator, and support for configurable task timeouts.
  • Updated Documentation and E2E Tests: Revised the MCP documentation to include details on run_task parameters, examples, and AI assistant integration, and rewrote end-to-end tests for full MCP protocol coverage, including tool listing, schema validation, and task execution scenarios.
  • Improved Error Handling: Refactored error codes in the MiseServer implementation to use specific ErrorCode enums (e.g., INVALID_REQUEST, INTERNAL_ERROR, RESOURCE_NOT_FOUND) instead of magic numbers.
Changelog
  • Cargo.lock
    • Added schemars 1.2.1 dependency.
  • Cargo.toml
    • Added schemars = "1" dependency.
  • docs/mcp.md
    • Updated the 'Available Tools' section to reflect the implementation of run_task and the stub for install_tool.
    • Added detailed parameters and an example for the run_task tool.
    • Updated the 'Integration with AI Assistants' section to include task execution capabilities.
    • Revised the 'Technical Details' section to mention tool invocation (task execution).
  • e2e/cli/test_mcp_protocol
    • Removed deprecated helper functions for sending MCP requests and extracting results.
    • Rewrote the Python e2e test script to include comprehensive tests for MCP initialization, tool listing with schema validation, and various run_task scenarios (success, with arguments, unknown task, and install_tool stub).
  • src/cli/mcp.rs
    • Imported necessary rmcp modules for JsonSchema, tool, and tool_router, along with serde traits.
    • Introduced tool_router field to MiseServer and implemented #[tool_router] macro.
    • Defined InstallToolParams and RunTaskParams structs with JsonSchema for tool parameter serialization and schema generation.
    • Implemented the install_tool method as a stub, returning a 'not yet implemented' error.
    • Implemented the run_task method to execute mise tasks via subprocess, capturing stdout/stderr, handling exit codes, and supporting timeouts.
    • Updated ServerHandler implementation to use self.tool_router.list_all() for list_tools and self.tool_router.call() for call_tool.
    • Replaced magic number error codes with specific ErrorCode enums (e.g., ErrorCode::INVALID_REQUEST, ErrorCode::INTERNAL_ERROR, ErrorCode::RESOURCE_NOT_FOUND).
    • Updated the AFTER_LONG_HELP constant to include descriptions for the new install_tool and run_task tools.
Activity
  • joaommartins implemented the run_task MCP tool, enabling AI assistants to execute mise tasks.
  • joaommartins integrated rmcp's #[tool_router] macro system with schemars for dynamic tool schema generation.
  • joaommartins added a stub for the install_tool MCP tool with a defined schema.
  • joaommartins enhanced the robustness of subprocess execution for run_task by adding kill_on_drop, stdin(null), and timeout support.
  • joaommartins updated the docs/mcp.md file to reflect the new tool and its usage.
  • joaommartins rewrote the e2e/cli/test_mcp_protocol script to provide comprehensive testing for the new MCP features.
  • joaommartins verified that mise run test:e2e test_mcp_protocol passes.
  • joaommartins performed manual testing with Claude Desktop or other MCP clients.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a run_task tool for the MCP server, allowing AI assistants to execute mise tasks. The implementation is robust, including features like subprocess hardening, timeout support, and integration with schemars for self-describing tools. The e2e tests have been significantly improved to provide comprehensive coverage of the MCP protocol, and the documentation is updated accordingly.

My review focuses on improving code readability in the new run_task implementation. I've suggested refactoring a couple of match statements to use if/else chains, which I believe makes the logic for handling stdout and stderr more explicit and easier to follow.

Overall, this is a solid feature addition that enhances mise's capabilities for AI integration.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds MCP (Model Context Protocol) tool support to mise, enabling AI assistants to execute mise tasks programmatically. The implementation integrates rmcp's #[tool_router] macro system with schemars-derived JSON schemas for self-describing tools, providing a working run_task tool and a stub install_tool tool.

Changes:

  • Implemented run_task MCP tool with subprocess execution, timeout handling, and comprehensive error reporting
  • Added install_tool stub that returns a not-yet-implemented error
  • Integrated rmcp's tool router system with proper JSON schema generation using schemars
  • Rewrote e2e tests with full MCP protocol coverage including initialize, tools/list, and tool execution scenarios
  • Updated documentation with detailed parameter descriptions and usage examples

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/cli/mcp.rs Added tool router integration, implemented run_task with hardened subprocess execution, added install_tool stub, migrated ErrorCode usage to named constants
e2e/cli/test_mcp_protocol Completely rewrote tests with Python script providing comprehensive MCP protocol testing including handshake, tool listing with schema validation, and tool execution scenarios
docs/mcp.md Updated documentation to reflect working run_task tool with parameters, examples, and integration guide; removed stub language
Cargo.toml Added schemars dependency for JSON schema generation
Cargo.lock Updated lockfile with schemars dependency

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

Copy link
Owner

@jdx jdx left a comment

Choose a reason for hiding this comment

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

This review was AI-generated.

Overall the implementation is solid — good subprocess hardening (kill_on_drop, stdin(null), NO_COLOR, -- separator) and the #[tool_router] macro integration is clean. A few notes:

test_run_task_with_args doesn't actually test args — it passes "args": [] (empty array) and doesn't verify arguments are forwarded to the task. It would be more useful to pass real args and verify the task receives them.

-- is always inserted even with no argsmise run test-task -- is functionally harmless, but if !args.is_empty() { cmd.arg("--").args(&args) } would be slightly cleaner.

schemars direct dependency may be unnecessaryrmcp already has the schemars feature enabled, and the code imports rmcp::schemars::JsonSchema. Worth checking if the direct schemars = "1" in Cargo.toml can be dropped.

Consider setting MISE_YES=1 on the subprocess — if a task triggers interactive prompts, the subprocess would hang until timeout. stdin(null) helps but MISE_YES=1 would be more defensive.

Minor nits: stderr is placed before stdout in combined output ({stderr}\n{stdout}), which is unconventional but not wrong. The install_tool stub changing from success to error is semantically better.

The ErrorCode cleanup (ErrorCode(400)ErrorCode::INVALID_REQUEST, etc.) throughout is a nice incidental improvement.

Bump recv timeouts from 10s to 30s for task execution calls to reduce
flaky test failures in slower CI environments.
Add explicit match arm for when both stdout and stderr are empty on
task failure, returning a descriptive message instead of an empty string.
- Handle empty output on task failure with descriptive message
- Only insert `--` separator when args are non-empty
- Add MISE_YES=1 to subprocess env to prevent interactive hangs
- Drop direct schemars dependency using #[schemars(crate = "rmcp::schemars")]
- Fix test_run_task_with_args to pass real args and verify forwarding
@joaommartins
Copy link
Contributor Author

Thanks for the review! Addressed all feedback in 3f97d2b:

  • test_run_task_with_args doesn't actually test args — Added an echo-args task and now passes ["hello", "world"], verifying they appear in output.
  • -- always inserted even with no args — Now only inserted when !args.is_empty().
  • schemars direct dependency — Confirmed it's needed for the derive macro, but worked around it with #[schemars(crate = "rmcp::schemars")] so the direct dep is dropped.
  • MISE_YES=1 — Added to the subprocess env.

@joaommartins joaommartins requested a review from jdx February 17, 2026 00:09
@jdx jdx merged commit dacb2dd into jdx:main Feb 17, 2026
34 checks passed
@joaommartins joaommartins deleted the feature(mcp)/add-run-task-tool branch February 18, 2026 03:35
mise-en-dev added a commit that referenced this pull request Feb 18, 2026
### 🚀 Features

- **(mcp)** add run_task tool for executing mise tasks by @joaommartins
in [#8179](#8179)
- **(node)** suggest setting node.flavor if the flavor is not found in
mirror by @risu729 in [#8206](#8206)

### 🐛 Bug Fixes

- **(java)** sort order for shorthand versions by @roele in
[#8197](#8197)
- **(node)** migrate env vars to settings by @risu729 in
[#8200](#8200)
- **(registry)** apply overrides in shims by @risu729 in
[#8199](#8199)
- migrate MISE_CARGO_BINSTALL_ONLY to settings by @risu729 in
[#8202](#8202)

### 📚 Documentation

- **(doctor)** fix subcommand in an example by @risu729 in
[#8198](#8198)

### 📦 Registry

- add github backend for typst by @3w36zj6 in
[#8210](#8210)

### Chore

- **(test)** disable flaky Forgejo e2e test by @jdx in
[#8211](#8211)
lucasew pushed a commit to lucasew/CONTRIB-mise that referenced this pull request Feb 18, 2026
## Summary

- Add working `run_task` MCP tool that executes mise tasks via
subprocess with full stdout/stderr capture
- Integrate rmcp's `#[tool_router]` macro system with `schemars`-derived
JSON schemas for self-describing tools
- Add `install_tool` stub with proper schema (returns
not-yet-implemented error)
- Harden subprocess execution: `kill_on_drop(true)`, `stdin(null)`, `--`
arg separator, timeout support via `task_timeout_duration()`
- Update documentation with tool parameters, examples, and integration
guide
- Rewrite e2e tests with full MCP protocol coverage (initialize,
tools/list, run_task success/args/unknown, install_tool stub)

## Test plan

- [x] `mise run test:e2e test_mcp_protocol` passes — tests initialize
handshake, tool listing with schema validation, task execution (success,
with args, unknown task error), and install_tool stub
- [x] Manual testing with Claude Desktop or other MCP client

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
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