From 94363d4e5b4fe7f026e06b65fb847342224428d8 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Wed, 24 Jun 2026 18:50:24 +0900 Subject: feat(mcp): Model Context Protocol host extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New `mcp` standard extension (`packages/mcp/`) that makes Dispatch an MCP host: spawns configured MCP servers (stdio child processes), performs the MCP handshake (initialize → notifications/initialized), discovers tools via tools/list, and registers each as a first-class Dispatch ToolContract via host.defineTool. When the model calls an MCP tool, the extension proxies the call to tools/call on the MCP server and returns the flattened result. Architecture (sibling of `lsp` extension): - Config: .dispatch/mcp.json (servers key) → opencode.json mcp key fallback, resolved per-cwd (mirrors LSP config resolution) - Transport: StdioTransport (spawn child, Content-Length framing + JSON-RPC 2.0) - Client: initialize → tools/list → tools/call; handles list_changed notifications for dynamic tool updates - Registry: tool name namespacing (__), ToolContract adapter that proxies execute → callTool, content flattening (text/image/ resource → string) - Manager: one client per server, lazy-spawn, status(), shutdownAll() - Extension: manifest (dependsOn session-orchestrator, capabilities spawn), registers tools + a toolsFilter (drops disconnected server's tools), mcpServiceHandle, deactivate kills all child processes Phase 1 scope: stdio only, Tools only (no Resources/Prompts/HTTP/sampling). Hand-rolled JSON-RPC + framing (zero external deps, adapts LSP patterns). Wave 1 (agent): 12 source + 8 test files, 69 new tests. Wave 2 (orchestrator): root tsconfig ref, host-bin CORE_EXTENSIONS registration + package.json dep, bun install. Verified: tsc -b EXIT 0, biome clean, 1537 vitest pass (was 1468, +69). --- packages/host-bin/package.json | 1 + packages/host-bin/src/main.ts | 2 ++ 2 files changed, 3 insertions(+) (limited to 'packages/host-bin') diff --git a/packages/host-bin/package.json b/packages/host-bin/package.json index abc4a3e..568fd6c 100644 --- a/packages/host-bin/package.json +++ b/packages/host-bin/package.json @@ -13,6 +13,7 @@ "@dispatch/provider-openai-compat": "workspace:*", "@dispatch/provider-umans": "workspace:*", "@dispatch/message-queue": "workspace:*", + "@dispatch/mcp": "workspace:*", "@dispatch/session-orchestrator": "workspace:*", "@dispatch/skills": "workspace:*", "@dispatch/throughput-store": "workspace:*", diff --git a/packages/host-bin/src/main.ts b/packages/host-bin/src/main.ts index c045e6b..bd79497 100644 --- a/packages/host-bin/src/main.ts +++ b/packages/host-bin/src/main.ts @@ -20,6 +20,7 @@ import { type StorageNamespace, } from "@dispatch/kernel"; import { extension as lspExt } from "@dispatch/lsp"; +import { extension as mcpExt } from "@dispatch/mcp"; import { extension as messageQueueExt } from "@dispatch/message-queue"; import { extension as providerOpenaiCompatExt } from "@dispatch/provider-openai-compat"; import { extension as providerUmansExt } from "@dispatch/provider-umans"; @@ -84,6 +85,7 @@ const CORE_EXTENSIONS: readonly Extension[] = [ throughputStoreExt, todoExt, messageQueueExt, + mcpExt, sessionOrchestratorExt, skillsExt, systemPromptExt, -- cgit v1.2.3