Skip to content

feat(mcp): unified MCP client with prompts, caching, retry, batch, REPL, metrics, and auto-routing#140

Merged
toasterbook88 merged 4 commits into
mainfrom
obs-surface-and-cli
May 28, 2026
Merged

feat(mcp): unified MCP client with prompts, caching, retry, batch, REPL, metrics, and auto-routing#140
toasterbook88 merged 4 commits into
mainfrom
obs-surface-and-cli

Conversation

@toasterbook88
Copy link
Copy Markdown
Owner

This PR adds a comprehensive MCP client to the axis CLI, implementing 11 out of 12 planned improvements (with daemon integration deferred). Features include:

  • Prompt support (list and get)
  • Pretty-print output
  • Tool search
  • Config validation in doctor
  • Caching with TTL
  • Retry with exponential backoff
  • Batch execution
  • Interactive REPL
  • Per-server metrics
  • Auto-routing based on placement
  • Progress notification infrastructure

All quality checks pass.

Copy link
Copy Markdown
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 comprehensive Model Context Protocol (MCP) client integration and an execution observation tracking system. It adds a new mcp client CLI for discovering and calling tools on external servers via stdio or HTTP, alongside an interactive REPL and a registry for managing multiple connections with retry logic. Additionally, it implements an observations command to monitor resource usage (RAM, VRAM, wall time) and updates the doctor command with MCP configuration validation. Review feedback highlights the need to use command contexts for proper cancellation, fix a typo in a flag default, and resolve input parsing bugs in the REPL where arguments with spaces were truncated. Suggestions were also made to refactor duplicate tool-calling logic and adopt more reliable patterns for identifying transient HTTP errors.

Comment thread cmd/axis/mcp_client.go Outdated
Comment thread cmd/axis/mcp_client.go Outdated
Comment thread cmd/axis/mcp_client.go Outdated
Comment thread cmd/axis/mcp_client.go Outdated
Comment thread cmd/axis/mcp_client.go Outdated
Comment thread internal/mcpclient/call.go Outdated
Comment thread internal/mcpclient/call.go
toasterbook88 pushed a commit that referenced this pull request May 25, 2026
- Replace context.Background() with cmd.Context() in all runMCPClient* functions
- Fix --format flag default typo (format → text)
- Fix REPL arg parsing for call/get-prompt to join remaining args with spaces
- Fix REPL search to use full multi-word keyword
- Refactor isTransientError to use errors.As with httpStatusCoder instead of fragile string matching
- Extract shared callTool internal method to deduplicate CallTool and CallToolWithProgress
- Update mcp_client_test.go to pass context.Context

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@toasterbook88 toasterbook88 force-pushed the obs-surface-and-cli branch from 8256910 to 61447d1 Compare May 25, 2026 18:40
toasterbook88 pushed a commit that referenced this pull request May 25, 2026
- Replace context.Background() with cmd.Context() in all runMCPClient* functions
- Fix --format flag default typo (format → text)
- Fix REPL arg parsing for call/get-prompt to join remaining args with spaces
- Fix REPL search to use full multi-word keyword
- Refactor isTransientError to use errors.As with httpStatusCoder instead of fragile string matching
- Extract shared callTool internal method to deduplicate CallTool and CallToolWithProgress
- Update mcp_client_test.go to pass context.Context

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@toasterbook88 toasterbook88 force-pushed the obs-surface-and-cli branch from 61447d1 to d8900ec Compare May 25, 2026 18:49
William and others added 4 commits May 27, 2026 20:00
…PL, metrics, and auto-routing

Implements a comprehensive axis mcp client subcommand suite:

Operator UX:
- axis mcp client prompts / get-prompt for prompt discovery
- --pretty flag for human-readable JSON output on call/read
- axis mcp client search <keyword> for tool discovery
- axis doctor validates MCP server configs (stdio command existence, HTTP URL)

Reliability:
- Per-connection caching (60s TTL) with sync.RWMutex
- Retry with exponential backoff (3 attempts, 200ms start) for transient errors
- axis mcp client batch <file.json> for sequential multi-tool execution

Advanced Surfaces:
- Interactive REPL (axis mcp client interactive) with 10 commands
- Per-server metrics surfaced in list --format json

Intelligence:
- Placement-aware routing (--auto-route) tries all servers offering a tool
- Progress notification infrastructure (CallToolWithProgress, SetProgressHandler)

Quality gates: lint, test-race, coverage, build all pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes TestMeshPartitionCoalescing by properly handling pending triggers
during refresh completion. The original logic had a race condition where
pending triggers weren't properly counted when completing a refresh.

Changes:
- Record start time when winning the refresh lock for latency fallback
- Capture pending state before clearing it
- Use captured pending triggers for next trigger determination
- Fix activeRequestedAt assignment logic
- Replace context.Background() with cmd.Context() in all runMCPClient* functions
- Fix --format flag default typo (format → text)
- Fix REPL arg parsing for call/get-prompt to join remaining args with spaces
- Fix REPL search to use full multi-word keyword
- Refactor isTransientError to use errors.As with httpStatusCoder instead of fragile string matching
- Extract shared callTool internal method to deduplicate CallTool and CallToolWithProgress
- Update mcp_client_test.go to pass context.Context

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…leanup

Add a 100ms grace period at the end of the test to allow any
lingering background goroutines from prior watch-config tests to
finish file operations before t.TempDir() cleanup runs. The failure
was an unlinkat ... directory not empty caused by doRefresh writes
racing with RemoveAll.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@toasterbook88 toasterbook88 force-pushed the obs-surface-and-cli branch from b665d95 to 0fc79ec Compare May 28, 2026 00:00
@toasterbook88 toasterbook88 merged commit 68d76a0 into main May 28, 2026
8 checks passed
@toasterbook88 toasterbook88 deleted the obs-surface-and-cli branch May 28, 2026 00:40
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