Skip to content

Execute host MCP tools in dashboard runs and evaluations - #421

Open
TonsOfFun wants to merge 2 commits into
mainfrom
codex/419-host-mcp-execution
Open

Execute host MCP tools in dashboard runs and evaluations#421
TonsOfFun wants to merge 2 commits into
mainfrom
codex/419-host-mcp-execution

Conversation

@TonsOfFun

Copy link
Copy Markdown
Contributor

Closes #419.

Dashboard runs previously dropped host MCP tools from the model’s tool roster, allowing a healthcheck prompt to succeed without touching the host. This change resolves every declared tool before generation, offers live schemas from enabled MCP servers, and dispatches calls through their MCP session. Unbound tools fail with an actionable error.

  • Extract a generic Streamable HTTP client, retaining Playwright compatibility; support HTTPS, JSON/SSE, paginated discovery, optional sessions, and tool-error reporting.
  • Reuse configured-server normalization, enforce the selected tool roster, and prefer enabled MCP bindings over built-ins. Keep arbitrary MCP names from overriding runtime agent methods.
  • Allow observed agents to run and evaluate under existing ownership, execution, and quota gates. Evaluation diagnosis uses the same resolved tool roster.

Validation: 318 engine and SolidAgent integration tests, 1,441 assertions, zero failures/errors/skips (Ruby 4.0.2, Rails 8.1.3.1). Includes native Anthropic tool-loop replay against simulated MCP HTTP responses. Repository-wide RuboCop: 516 files, no offenses. git diff --check passes.

Built on current main. #414 remains a compatible host-adapter path; #405 overlaps AgentExecutionService and will need to preserve MCP precedence and callback dispatch when rebased. Supports Streamable HTTP endpoints; does not launch stdio processes or implement OAuth/custom authentication headers.

Issue, branch, milestones, and PR review notes: docs-tracking/issues/419-host-mcp-execution/. Setup example: actionagent/README.md.

@TonsOfFun

Copy link
Copy Markdown
Contributor Author

Heads-up: #420 has merged (cd65327), which lands host MCP tool execution on main and closes #419.

That was driven by release timing rather than a judgement about this PR — a host app needed the execution path in a tagged gem to get off path: Gemfile pins, and #420 was rebased and green. This PR is the larger change of the two (+1680/-217 across 22 files against #420's +546/-185 across 14), and it covers ground #420 does not: paginated discovery, the tool-name/runtime-method collision guard, and quota gating on observed agents.

Worth rebasing onto the new main and keeping whatever it still adds, rather than closing it outright. main now has MCPClient (generic Streamable HTTP, optional sessions, stateless servers, TLS) and MCPToolDispatcher (per-agent server scoping, tool_definitions from a live tools/list, errors returned as scoreable results).

One known gap this PR may already handle better: #425MCPToolDispatcher#tool_definitions rescues a failed tools/list to [] with only a logger.warn, so an agent whose servers are unreachable runs tool-less and the model fabricates results instead of failing.

(Generated using Claude Code)

TonsOfFun added a commit that referenced this pull request Sep 11, 2026
A failed tools/list was rescued to [] and logged as a warning, so a server
that 401s and a server that legitimately serves no tools were
indistinguishable. The agent then ran tool-less, the model fabricated an
answer, and the run reported a plausible low score — #425 records that
costing hours to diagnose, because the report recommended prompt changes
for what was a transport failure.

Contributing nothing still keeps the run alive; that part was deliberate
and is unchanged. What was missing is the reason, so callers can tell the
two cases apart:

- discovery_errors returns why each declared server contributed no tools,
  naming the server, its url and the underlying error.
- all_servers_failed? reports the case where nothing could be discovered
  at all, which is when a tool-backed scenario cannot produce a meaningful
  score and a caller should fail loudly rather than grade an invented
  answer.

Errors reset per tool_definitions call, so a transient failure does not
leak into a later run.

This takes the approach from the unmerged #421 (MCPToolBinding's
@discovery_errors), narrowed to the dispatcher on current main rather than
rebasing that branch across 54 commits of divergence.

Surfacing these in the evaluation report is the follow-up, and is what
turns "improve the instructions" back into "sparkle-diagnostic returned
401". Filed as the scoring-side counterpart in #433.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01He34kWksjpqPPDpCCqJq2C
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.

Execute a host's MCP tools from the dashboard, so hosts do not need their own evaluation runner

1 participant