feat(mcp): filter SafeOutputs tools based on front matter config#156
feat(mcp): filter SafeOutputs tools based on front matter config#156jamesadevine wants to merge 4 commits intomainfrom
Conversation
Only expose safe output tools that are configured in the front matter's safe-outputs section. This reduces agent confusion by hiding tools that aren't configured for the current pipeline. Implementation: - Add --enabled-tools repeatable CLI arg to mcp and mcp-http commands - SafeOutputs::new() accepts optional enabled tools list and uses ToolRouter::remove_route() to remove unconfigured tools at startup - Compiler derives tool list from safe-outputs keys and emits --enabled-tools args in the pipeline template - Always-on diagnostic tools (noop, missing-data, missing-tool, report-incomplete) are never filtered out Backward compatible: if --enabled-tools is not passed (empty safe-outputs or omitted), all tools remain available. Note: MCPG has a tools field in its config schema but does not enforce it at runtime. This change filters at the SafeOutputs server level instead, making it self-contained. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🔍 Rust PR ReviewSummary: Good approach overall — the design is clean and the test coverage is solid. One genuine security concern to address, plus two minor notes. Findings🔒 Security Concerns
|
- Validate tool names against safe regex (ASCII alphanumeric + hyphens) to prevent shell injection from malicious YAML keys - Fix dangling backslash in base.yml when enabled_tools_args is empty - Replace fragile exact-count assertion in test_tool_filtering_multiple_tools with explicit presence/absence checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🔍 Rust PR ReviewSummary: Needs a fix — the template has a shell-breaking separator bug that will cause the Findings🐛 Bugs / Logic Issues
|
- Add trailing space to generate_enabled_tools_args output when non-empty, preventing the last --enabled-tools value from concatenating with the next positional argument in the shell command - Move ALWAYS_ON_TOOLS constant from mcp.rs to tools/mod.rs to avoid compile→mcp coupling (common.rs now imports from tools directly) - Reduce list_all() calls in tool filtering to a single collect pass Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🔍 Rust PR ReviewSummary: Mostly solid — the core design, security model, and backward compatibility are all well-handled. One correctness concern worth addressing before merge. Findings🐛 Bugs / Logic Issues
|
- Add ALL_KNOWN_SAFE_OUTPUTS constant in tools/mod.rs enumerating every
valid safe-output key (MCP tools + always-on diagnostics + memory)
- Emit compile-time warning when a safe-outputs key doesn't match any
known tool, catching typos like 'crate-pull-request' early
- Use HashSet for O(1) deduplication when merging always-on tools
- Rename misleading test to test_generate_enabled_tools_args_warns_on_unknown_tool
and exercise the typo path (crate-pull-request)
- Document {{ enabled_tools_args }} template marker in AGENTS.md
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🔍 Rust PR ReviewSummary: Approach is solid and the implementation is clean — one correctness bug with misleading behaviour, a maintenance concern, and a missing integration test. Findings🐛 Bugs / Logic Issues
|
Summary
Only expose safe output tools that are configured in the front matter's
safe-outputs:section. This reduces agent confusion by hiding tools that aren't configured for the current pipeline.Problem
All 17+ safe output tools are always exposed to the agent via MCPG, regardless of what's configured in
safe-outputs:front matter. MCPG has atoolsfield in its config schema but does not enforce it at runtime. This means agents see tools they aren't configured to use, wasting context window and potentially causing confusion.Approach
Filter at the SafeOutputs server level using
ToolRouter::remove_route()— self-contained, no MCPG changes needed.Changes
src/main.rs— Add--enabled-toolsrepeatable CLI arg tomcpandmcp-httpcommandssrc/mcp.rs—SafeOutputs::new()accepts optional enabled tools list; removes unconfigured tools from the router at startupsrc/compile/common.rs—generate_enabled_tools_args()derives tool list fromsafe-outputs:keys + always-on diagnosticssrc/compile/standalone.rs— Wires the generated args into the pipeline templatetemplates/base.yml—{{ enabled_tools_args }}placeholder inmcp-httpinvocationAlways-on tools (never filtered)
noop,missing-data,missing-tool,report-incompleteBackward compatibility
If
--enabled-toolsis not passed (empty/omittedsafe-outputs:), all tools remain available.Testing