Skip to content

feat(mcp): chat-side tool routing GUI (wave 2) — closes v0.5 tool routing#63

Merged
magicnight merged 1 commit into
mainfrom
feat/mcp-tool-routing-gui
Jul 8, 2026
Merged

feat(mcp): chat-side tool routing GUI (wave 2) — closes v0.5 tool routing#63
magicnight merged 1 commit into
mainfrom
feat/mcp-tool-routing-gui

Conversation

@magicnight

Copy link
Copy Markdown
Owner

Wave 2 of MCP chat-side tool routing: makes tool calling work end-to-end in the app. Wave 1 (#61) shipped the MacMLXCore core; this wires it into the GUI, closing the v0.5 roadmap's "chat-side MCP tool routing" item.

What lands

  • AppState owns MCPClientPool + MCPClientConfigStore: bootstrapMCP() connects configured ~/.mac-mlx/mcp.json servers on launch (backgrounded — a slow server can't delay startup), builds the tool index/specs; teardown() best-effort disconnects on app exit (new AppDelegate.onWillTerminate hook, so npx/uvx subprocesses don't outlive the app). Zero servers configured = complete no-op; chat is byte-for-byte unchanged.
  • ToolValueBridge.toolIndexAndSpecs (pure, unit-tested): maps tool→server (first-wins by sorted server name) + one OpenAI spec per tool.
  • makeToolCallingSession() injects coordinator.generate into a ToolCallingSession — MacMLXCore stays app-import-free (closure boundary, like loadHook).
  • ChatViewModel.runToolLoop drives the session: streams assistant deltas into a UUID-tracked bubble, renders tool-call + tool-result activity rows, auto-runs sequentially. Stop cancels cleanly through all four onTermination hops.
  • ToolActivityView: compact monospaced card, collapsible, error tint. Tool activity is UI-ephemeral (not persisted).

Review + verification

Adversarially reviewed APPROVE — the zero-behavior-change invariant (no mcp.json → identical chat), the @MainActor+actor+@Sendable concurrency isolation, and the cancellation wiring all adjudicated sound; the MEDIUM (Stop rendering a spurious CancellationError) + a LOW (stale-id reset) are fixed. No force-unwrap/try!/as!. Independently verified: app ** BUILD SUCCEEDED **, MacMLXCore ** TEST SUCCEEDED ** (239 swift-testing + 80 XCTest, incl. the new toolIndexAndSpecs test + 11 DeepSeek parity), bare swift test green. GUI wiring is build+review-covered (app target has no test target — stated honestly).

Follow-ups tracked (not blocking): cross-turn tool context is UI-ephemeral (a later turn can't reference a prior tool result); in-flight pool.callTool isn't abandoned promptly on Stop (Core callTool cancellation-awareness); Integrations screen + server tools pass-through are separate waves.

… chat)

Makes MCP tool calling work end-to-end in the app (wave 1 shipped the
MacMLXCore core; this wires it into AppState + ChatViewModel).

- AppState owns MCPClientPool + MCPClientConfigStore: bootstrapMCP()
  connects configured ~/.mac-mlx/mcp.json servers on launch (backgrounded
  so a slow server can't delay startup), builds the tool index/specs,
  and teardown() best-effort disconnects on app exit (AppDelegate
  onWillTerminate hook). Zero servers = no-op; the feature stays inactive.
- ToolValueBridge.toolIndexAndSpecs: pure, tested — maps tools to servers
  (first-wins by sorted server name) + builds one OpenAI spec per tool.
- makeToolCallingSession() injects coordinator.generate into a
  ToolCallingSession; MacMLXCore stays app-import-free (closure boundary).
- ChatViewModel.runToolLoop drives the session: streams assistant deltas
  into a UUID-tracked bubble, renders tool-call + tool-result activity
  rows, auto-runs sequentially. When no tools are active the plain path
  is byte-for-byte unchanged (zero-behavior-change invariant, reviewed).
- ToolActivityView: compact monospaced card, collapsible, error tint.
- Stop cancels cleanly through all hops (no spurious error line); tool
  activity is UI-ephemeral (not persisted).

Reviewed APPROVE (zero-change invariant + concurrency + cancellation
sound); the two review fixes (Stop-as-clean-stop, stale-id reset) are
included. Verified: app BUILD SUCCEEDED, MacMLXCore 239+80 tests green,
bare swift test green. toolIndexAndSpecs is unit-tested; GUI wiring is
build+review-covered (app target has no test target).
@cursor

cursor Bot commented Jul 8, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@magicnight magicnight merged commit 28de092 into main Jul 8, 2026
3 checks passed
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