@sammorrowdrums/mcpi-ext 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/.dockerignore +6 -0
  2. package/.github/dependabot.yml +25 -0
  3. package/.github/workflows/ci.yml +50 -0
  4. package/.hadolint.yaml +6 -0
  5. package/.prettierignore +4 -0
  6. package/.prettierrc +7 -0
  7. package/AGENTS.md +118 -0
  8. package/DECISIONS.md +99 -0
  9. package/Dockerfile +39 -0
  10. package/README.md +278 -0
  11. package/aube-lock.yaml +4146 -0
  12. package/dist/code-mode/code-mode-integration.test.d.ts +2 -0
  13. package/dist/code-mode/code-mode-integration.test.d.ts.map +1 -0
  14. package/dist/code-mode/code-mode-integration.test.js +116 -0
  15. package/dist/code-mode/code-mode-integration.test.js.map +1 -0
  16. package/dist/code-mode/eligibility.d.ts +10 -0
  17. package/dist/code-mode/eligibility.d.ts.map +1 -0
  18. package/dist/code-mode/eligibility.js +14 -0
  19. package/dist/code-mode/eligibility.js.map +1 -0
  20. package/dist/code-mode/eligibility.test.d.ts +2 -0
  21. package/dist/code-mode/eligibility.test.d.ts.map +1 -0
  22. package/dist/code-mode/eligibility.test.js +53 -0
  23. package/dist/code-mode/eligibility.test.js.map +1 -0
  24. package/dist/code-mode/executor.d.ts +35 -0
  25. package/dist/code-mode/executor.d.ts.map +1 -0
  26. package/dist/code-mode/executor.js +120 -0
  27. package/dist/code-mode/executor.js.map +1 -0
  28. package/dist/code-mode/executor.test.d.ts +2 -0
  29. package/dist/code-mode/executor.test.d.ts.map +1 -0
  30. package/dist/code-mode/executor.test.js +130 -0
  31. package/dist/code-mode/executor.test.js.map +1 -0
  32. package/dist/code-mode/index.d.ts +65 -0
  33. package/dist/code-mode/index.d.ts.map +1 -0
  34. package/dist/code-mode/index.js +175 -0
  35. package/dist/code-mode/index.js.map +1 -0
  36. package/dist/code-mode/tools.d.ts +45 -0
  37. package/dist/code-mode/tools.d.ts.map +1 -0
  38. package/dist/code-mode/tools.js +70 -0
  39. package/dist/code-mode/tools.js.map +1 -0
  40. package/dist/code-mode/type-hints.d.ts +20 -0
  41. package/dist/code-mode/type-hints.d.ts.map +1 -0
  42. package/dist/code-mode/type-hints.js +189 -0
  43. package/dist/code-mode/type-hints.js.map +1 -0
  44. package/dist/code-mode/type-hints.test.d.ts +2 -0
  45. package/dist/code-mode/type-hints.test.d.ts.map +1 -0
  46. package/dist/code-mode/type-hints.test.js +157 -0
  47. package/dist/code-mode/type-hints.test.js.map +1 -0
  48. package/dist/docker-e2e.d.ts +55 -0
  49. package/dist/docker-e2e.d.ts.map +1 -0
  50. package/dist/docker-e2e.js +235 -0
  51. package/dist/docker-e2e.js.map +1 -0
  52. package/dist/docker-e2e.test.d.ts +2 -0
  53. package/dist/docker-e2e.test.d.ts.map +1 -0
  54. package/dist/docker-e2e.test.js +176 -0
  55. package/dist/docker-e2e.test.js.map +1 -0
  56. package/dist/index.d.ts +3 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +128 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/index.test.d.ts +2 -0
  61. package/dist/index.test.d.ts.map +1 -0
  62. package/dist/index.test.js +8 -0
  63. package/dist/index.test.js.map +1 -0
  64. package/dist/mcp/client-manager.d.ts +46 -0
  65. package/dist/mcp/client-manager.d.ts.map +1 -0
  66. package/dist/mcp/client-manager.js +148 -0
  67. package/dist/mcp/client-manager.js.map +1 -0
  68. package/dist/mcp/client-manager.test.d.ts +2 -0
  69. package/dist/mcp/client-manager.test.d.ts.map +1 -0
  70. package/dist/mcp/client-manager.test.js +204 -0
  71. package/dist/mcp/client-manager.test.js.map +1 -0
  72. package/dist/mcp/config-loader.d.ts +8 -0
  73. package/dist/mcp/config-loader.d.ts.map +1 -0
  74. package/dist/mcp/config-loader.js +43 -0
  75. package/dist/mcp/config-loader.js.map +1 -0
  76. package/dist/mcp/config-loader.test.d.ts +2 -0
  77. package/dist/mcp/config-loader.test.d.ts.map +1 -0
  78. package/dist/mcp/config-loader.test.js +93 -0
  79. package/dist/mcp/config-loader.test.js.map +1 -0
  80. package/dist/mcp/config.d.ts +46 -0
  81. package/dist/mcp/config.d.ts.map +1 -0
  82. package/dist/mcp/config.js +28 -0
  83. package/dist/mcp/config.js.map +1 -0
  84. package/dist/mcp/index.d.ts +5 -0
  85. package/dist/mcp/index.d.ts.map +1 -0
  86. package/dist/mcp/index.js +4 -0
  87. package/dist/mcp/index.js.map +1 -0
  88. package/dist/skills/discover.d.ts +10 -0
  89. package/dist/skills/discover.d.ts.map +1 -0
  90. package/dist/skills/discover.js +60 -0
  91. package/dist/skills/discover.js.map +1 -0
  92. package/dist/skills/format.d.ts +10 -0
  93. package/dist/skills/format.d.ts.map +1 -0
  94. package/dist/skills/format.js +38 -0
  95. package/dist/skills/format.js.map +1 -0
  96. package/dist/skills/format.test.d.ts +2 -0
  97. package/dist/skills/format.test.d.ts.map +1 -0
  98. package/dist/skills/format.test.js +63 -0
  99. package/dist/skills/format.test.js.map +1 -0
  100. package/dist/skills/index.d.ts +6 -0
  101. package/dist/skills/index.d.ts.map +1 -0
  102. package/dist/skills/index.js +6 -0
  103. package/dist/skills/index.js.map +1 -0
  104. package/dist/skills/load-skill-tool.d.ts +40 -0
  105. package/dist/skills/load-skill-tool.d.ts.map +1 -0
  106. package/dist/skills/load-skill-tool.js +104 -0
  107. package/dist/skills/load-skill-tool.js.map +1 -0
  108. package/dist/skills/mcp-tool-proxy.d.ts +11 -0
  109. package/dist/skills/mcp-tool-proxy.d.ts.map +1 -0
  110. package/dist/skills/mcp-tool-proxy.js +116 -0
  111. package/dist/skills/mcp-tool-proxy.js.map +1 -0
  112. package/dist/skills/skill-integration.test.d.ts +2 -0
  113. package/dist/skills/skill-integration.test.d.ts.map +1 -0
  114. package/dist/skills/skill-integration.test.js +119 -0
  115. package/dist/skills/skill-integration.test.js.map +1 -0
  116. package/dist/skills/skill-registry.d.ts +39 -0
  117. package/dist/skills/skill-registry.d.ts.map +1 -0
  118. package/dist/skills/skill-registry.js +48 -0
  119. package/dist/skills/skill-registry.js.map +1 -0
  120. package/dist/skills/skill-registry.test.d.ts +2 -0
  121. package/dist/skills/skill-registry.test.d.ts.map +1 -0
  122. package/dist/skills/skill-registry.test.js +67 -0
  123. package/dist/skills/skill-registry.test.js.map +1 -0
  124. package/dist/test-servers/weather-server.d.ts +12 -0
  125. package/dist/test-servers/weather-server.d.ts.map +1 -0
  126. package/dist/test-servers/weather-server.js +139 -0
  127. package/dist/test-servers/weather-server.js.map +1 -0
  128. package/dist/test-servers/weather-stdio.d.ts +2 -0
  129. package/dist/test-servers/weather-stdio.d.ts.map +1 -0
  130. package/dist/test-servers/weather-stdio.js +11 -0
  131. package/dist/test-servers/weather-stdio.js.map +1 -0
  132. package/dist/tool-cli/cli.d.ts +3 -0
  133. package/dist/tool-cli/cli.d.ts.map +1 -0
  134. package/dist/tool-cli/cli.js +179 -0
  135. package/dist/tool-cli/cli.js.map +1 -0
  136. package/dist/tool-cli/constants.d.ts +7 -0
  137. package/dist/tool-cli/constants.d.ts.map +1 -0
  138. package/dist/tool-cli/constants.js +15 -0
  139. package/dist/tool-cli/constants.js.map +1 -0
  140. package/dist/tool-cli/format.d.ts +8 -0
  141. package/dist/tool-cli/format.d.ts.map +1 -0
  142. package/dist/tool-cli/format.js +57 -0
  143. package/dist/tool-cli/format.js.map +1 -0
  144. package/dist/tool-cli/format.test.d.ts +2 -0
  145. package/dist/tool-cli/format.test.d.ts.map +1 -0
  146. package/dist/tool-cli/format.test.js +30 -0
  147. package/dist/tool-cli/format.test.js.map +1 -0
  148. package/dist/tool-cli/index.d.ts +4 -0
  149. package/dist/tool-cli/index.d.ts.map +1 -0
  150. package/dist/tool-cli/index.js +4 -0
  151. package/dist/tool-cli/index.js.map +1 -0
  152. package/dist/tool-cli/rpc-client.d.ts +6 -0
  153. package/dist/tool-cli/rpc-client.d.ts.map +1 -0
  154. package/dist/tool-cli/rpc-client.js +25 -0
  155. package/dist/tool-cli/rpc-client.js.map +1 -0
  156. package/dist/tool-cli/rpc-server.d.ts +48 -0
  157. package/dist/tool-cli/rpc-server.d.ts.map +1 -0
  158. package/dist/tool-cli/rpc-server.js +220 -0
  159. package/dist/tool-cli/rpc-server.js.map +1 -0
  160. package/dist/tool-cli/rpc-server.test.d.ts +2 -0
  161. package/dist/tool-cli/rpc-server.test.d.ts.map +1 -0
  162. package/dist/tool-cli/rpc-server.test.js +154 -0
  163. package/dist/tool-cli/rpc-server.test.js.map +1 -0
  164. package/eslint.config.js +27 -0
  165. package/images/banner.webp +0 -0
  166. package/images/code-c-maude.webp +0 -0
  167. package/images/nuclear-mcp-football.webp +0 -0
  168. package/images/the-skill-dealer.webp +0 -0
  169. package/mise.toml +65 -0
  170. package/package.json +46 -0
  171. package/scripts/docker-entrypoint.sh +29 -0
  172. package/scripts/test-echo-server.mjs +28 -0
  173. package/scripts/test-mcp-integration.mjs +59 -0
  174. package/scripts/test-tool-cli-smoke.mjs +62 -0
  175. package/src/code-mode/code-mode-integration.test.ts +135 -0
  176. package/src/code-mode/eligibility.test.ts +60 -0
  177. package/src/code-mode/eligibility.ts +16 -0
  178. package/src/code-mode/executor.test.ts +168 -0
  179. package/src/code-mode/executor.ts +163 -0
  180. package/src/code-mode/index.ts +208 -0
  181. package/src/code-mode/tools.ts +110 -0
  182. package/src/code-mode/type-hints.test.ts +187 -0
  183. package/src/code-mode/type-hints.ts +249 -0
  184. package/src/docker-e2e.test.ts +195 -0
  185. package/src/docker-e2e.ts +277 -0
  186. package/src/index.test.ts +8 -0
  187. package/src/index.ts +158 -0
  188. package/src/mcp/client-manager.test.ts +250 -0
  189. package/src/mcp/client-manager.ts +199 -0
  190. package/src/mcp/config-loader.test.ts +115 -0
  191. package/src/mcp/config-loader.ts +46 -0
  192. package/src/mcp/config.ts +40 -0
  193. package/src/mcp/index.ts +4 -0
  194. package/src/skills/discover.ts +81 -0
  195. package/src/skills/format.test.ts +70 -0
  196. package/src/skills/format.ts +42 -0
  197. package/src/skills/index.ts +9 -0
  198. package/src/skills/load-skill-tool.ts +136 -0
  199. package/src/skills/mcp-tool-proxy.ts +143 -0
  200. package/src/skills/skill-integration.test.ts +139 -0
  201. package/src/skills/skill-registry.test.ts +83 -0
  202. package/src/skills/skill-registry.ts +69 -0
  203. package/src/test-servers/weather-server.ts +171 -0
  204. package/src/test-servers/weather-stdio.ts +11 -0
  205. package/src/tool-cli/cli.ts +232 -0
  206. package/src/tool-cli/constants.ts +15 -0
  207. package/src/tool-cli/format.test.ts +33 -0
  208. package/src/tool-cli/format.ts +56 -0
  209. package/src/tool-cli/index.ts +3 -0
  210. package/src/tool-cli/rpc-client.ts +39 -0
  211. package/src/tool-cli/rpc-server.test.ts +193 -0
  212. package/src/tool-cli/rpc-server.ts +287 -0
  213. package/tsconfig.json +21 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-e2e.test.js","sourceRoot":"","sources":["../src/docker-e2e.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ExtensionAPI } from "@sammorrowdrums/mcpi";
2
+ export default function (pi: ExtensionAPI): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EAIb,MAAM,sBAAsB,CAAC;AAa9B,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,QA0IxC"}
package/dist/index.js ADDED
@@ -0,0 +1,128 @@
1
+ import { CodeModeManager } from "./code-mode/index.js";
2
+ import { dockerE2ETool } from "./docker-e2e.js";
3
+ import { McpClientManager, loadMcpConfig } from "./mcp/index.js";
4
+ import { SkillRegistry, createLoadSkillTool, discoverSkillsFromServer, formatMcpSkillsForPrompt, registerMcpToolProxies, } from "./skills/index.js";
5
+ import { ToolCliRpcServer, formatToolCliForPrompt } from "./tool-cli/index.js";
6
+ export default function (pi) {
7
+ pi.registerTool(dockerE2ETool);
8
+ pi.registerFlag("mcp-config", {
9
+ description: "Path to MCP server configuration JSON file",
10
+ type: "string",
11
+ });
12
+ const mcpManager = new McpClientManager();
13
+ const skillRegistry = new SkillRegistry();
14
+ const rpcServer = new ToolCliRpcServer(mcpManager);
15
+ const codeModeManager = new CodeModeManager();
16
+ const enabledTools = new Set();
17
+ const gatedToolNames = new Set();
18
+ // Register the load_skill tool so the model can activate MCP skills
19
+ pi.registerTool(createLoadSkillTool({ registry: skillRegistry, mcpManager, enabledTools }));
20
+ pi.on("session_start", async (_event, ctx) => {
21
+ if (ctx.hasUI) {
22
+ ctx.ui.notify("mcpi-ext loaded", "info");
23
+ }
24
+ const configPath = pi.getFlag("mcp-config");
25
+ const log = (msg) => {
26
+ if (ctx.hasUI) {
27
+ ctx.ui.notify(msg, "info");
28
+ }
29
+ else {
30
+ console.error(msg);
31
+ }
32
+ };
33
+ try {
34
+ const config = await loadMcpConfig(configPath);
35
+ const serverCount = Object.keys(config.mcpServers).length;
36
+ if (serverCount > 0) {
37
+ await mcpManager.connectAll(config, log);
38
+ const tools = mcpManager.getTools();
39
+ log(`MCP: ${mcpManager.getConnectedServers().length} server(s), ${tools.length} tool(s) discovered`);
40
+ // Pre-register all MCP tools as deferred Pi tool proxies
41
+ // (in tools array for dispatch but excluded from system prompt)
42
+ const allToolNames = tools.map((t) => t.name);
43
+ registerMcpToolProxies(allToolNames, mcpManager, pi);
44
+ // Discover skills from all connected servers
45
+ for (const serverName of mcpManager.getConnectedServers()) {
46
+ const client = mcpManager.getClient(serverName);
47
+ if (!client)
48
+ continue;
49
+ try {
50
+ const skills = await discoverSkillsFromServer(client, serverName, log);
51
+ skillRegistry.registerAll(skills);
52
+ }
53
+ catch (err) {
54
+ log(`[skills] Failed to discover skills from "${serverName}": ${err.message}`);
55
+ }
56
+ }
57
+ if (skillRegistry.size > 0) {
58
+ for (const skill of skillRegistry.getAll()) {
59
+ for (const t of skill.allowedTools) {
60
+ gatedToolNames.add(t);
61
+ }
62
+ }
63
+ log(`MCP: ${skillRegistry.size} skill(s) discovered, ${gatedToolNames.size} tool(s) deferred`);
64
+ }
65
+ // Start the tool-cli RPC server for progressive tool discovery
66
+ try {
67
+ await rpcServer.start(log);
68
+ }
69
+ catch (err) {
70
+ log(`[tool-cli] Failed to start RPC server: ${err.message}`);
71
+ }
72
+ // Initialize code mode (Tier 3) for read-only tools with structured output
73
+ codeModeManager.initialize(mcpManager);
74
+ if (codeModeManager.isActive) {
75
+ const { codeSearch, codeExecute } = codeModeManager.createTools();
76
+ pi.registerTool(codeSearch);
77
+ pi.registerTool(codeExecute);
78
+ log(`MCP: Code mode active (${codeModeManager.getEligibleTools().length} eligible tool(s))`);
79
+ }
80
+ }
81
+ }
82
+ catch (err) {
83
+ const msg = `MCP config error: ${err.message}`;
84
+ if (ctx.hasUI) {
85
+ ctx.ui.notify(msg, "warning");
86
+ }
87
+ else {
88
+ console.error(msg);
89
+ }
90
+ }
91
+ });
92
+ // Inject MCP skills, tool-cli advice, and code mode type hints into the system prompt
93
+ pi.on("before_agent_start", async (event) => {
94
+ let extra = "";
95
+ const skills = skillRegistry.getAll();
96
+ if (skills.length > 0) {
97
+ extra += formatMcpSkillsForPrompt(skills);
98
+ }
99
+ const serverCount = mcpManager.getConnectedServers().length;
100
+ extra += formatToolCliForPrompt(serverCount);
101
+ if (codeModeManager.isActive) {
102
+ extra += codeModeManager.formatSystemPromptSection();
103
+ }
104
+ if (extra.length === 0)
105
+ return;
106
+ return { systemPrompt: event.systemPrompt + extra };
107
+ });
108
+ // Block deferred MCP tools until their skill is loaded
109
+ pi.on("tool_call", async (event) => {
110
+ const name = "toolName" in event ? event.toolName : undefined;
111
+ if (!name || !gatedToolNames.has(name) || enabledTools.has(name))
112
+ return;
113
+ const relevantSkills = skillRegistry
114
+ .getAll()
115
+ .filter((s) => s.allowedTools.includes(name))
116
+ .map((s) => s.name);
117
+ return {
118
+ block: true,
119
+ reason: `Tool "${name}" requires loading a skill first. Call load_skill with one of: ${relevantSkills.join(", ")}`,
120
+ };
121
+ });
122
+ pi.on("session_shutdown", async () => {
123
+ await rpcServer.stop();
124
+ await mcpManager.disconnectAll();
125
+ skillRegistry.clear();
126
+ });
127
+ }
128
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import { describe, it, expect } from "vitest";
2
+ describe("mcpi-ext", () => {
3
+ it("exports a default function", async () => {
4
+ const mod = await import("./index.js");
5
+ expect(typeof mod.default).toBe("function");
6
+ });
7
+ });
8
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;IACxB,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import type { McpConfig, ServerConfig } from "./config.js";
3
+ /** An MCP tool as discovered from a server. */
4
+ export interface McpTool {
5
+ /** Tool name as reported by the server. */
6
+ name: string;
7
+ description?: string;
8
+ /** JSON Schema for the tool's parameters. */
9
+ inputSchema: Record<string, unknown>;
10
+ /** JSON Schema for structured output, if declared. */
11
+ outputSchema?: Record<string, unknown>;
12
+ /** Tool annotations (readOnlyHint, destructiveHint, etc.). */
13
+ annotations?: Record<string, unknown>;
14
+ /** Which configured server this tool came from. */
15
+ serverName: string;
16
+ }
17
+ /**
18
+ * Manages connections to multiple MCP servers and aggregates their tools.
19
+ *
20
+ * Tools are discovered and stored internally. They are NOT registered with pi
21
+ * automatically — that responsibility belongs to the access tiers (Skills,
22
+ * Football, Code Mode).
23
+ */
24
+ export declare class McpClientManager {
25
+ private connections;
26
+ /**
27
+ * Connect to all servers defined in the config.
28
+ * Connections that fail are logged and skipped — partial success is fine.
29
+ */
30
+ connectAll(config: McpConfig, log?: (msg: string) => void): Promise<void>;
31
+ /** Connect to a single server by name. */
32
+ connectOne(name: string, serverConfig: ServerConfig, log?: (msg: string) => void): Promise<void>;
33
+ /** Disconnect a single server. */
34
+ disconnectOne(name: string): Promise<void>;
35
+ /** Disconnect all servers. */
36
+ disconnectAll(): Promise<void>;
37
+ /** Get all discovered tools across all connected servers. */
38
+ getTools(): McpTool[];
39
+ /** Get tools from a specific server. */
40
+ getToolsForServer(name: string): McpTool[];
41
+ /** Get the MCP Client for a specific server (needed to call tools). */
42
+ getClient(name: string): Client | undefined;
43
+ /** List connected server names. */
44
+ getConnectedServers(): string[];
45
+ }
46
+ //# sourceMappingURL=client-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-manager.d.ts","sourceRoot":"","sources":["../../src/mcp/client-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3D,+CAA+C;AAC/C,MAAM,WAAW,OAAO;IACtB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;CACpB;AAQD;;;;;;GAMG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAAwC;IAE3D;;;OAGG;IACG,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9F,0CAA0C;IACpC,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,YAAY,EAC1B,GAAG,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAoB,GACzC,OAAO,CAAC,IAAI,CAAC;IAwDhB,kCAAkC;IAC5B,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWhD,8BAA8B;IACxB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAKpC,6DAA6D;IAC7D,QAAQ,IAAI,OAAO,EAAE;IAQrB,wCAAwC;IACxC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE;IAI1C,uEAAuE;IACvE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3C,mCAAmC;IACnC,mBAAmB,IAAI,MAAM,EAAE;CAGhC"}
@@ -0,0 +1,148 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
3
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4
+ /**
5
+ * Manages connections to multiple MCP servers and aggregates their tools.
6
+ *
7
+ * Tools are discovered and stored internally. They are NOT registered with pi
8
+ * automatically — that responsibility belongs to the access tiers (Skills,
9
+ * Football, Code Mode).
10
+ */
11
+ export class McpClientManager {
12
+ connections = new Map();
13
+ /**
14
+ * Connect to all servers defined in the config.
15
+ * Connections that fail are logged and skipped — partial success is fine.
16
+ */
17
+ async connectAll(config, log = console.error) {
18
+ const entries = Object.entries(config.mcpServers);
19
+ const results = await Promise.allSettled(entries.map(([name, serverConfig]) => this.connectOne(name, serverConfig, log)));
20
+ for (let i = 0; i < results.length; i++) {
21
+ const result = results[i];
22
+ if (result.status === "rejected") {
23
+ log(`[mcp] Failed to connect to "${entries[i][0]}": ${result.reason}`);
24
+ }
25
+ }
26
+ }
27
+ /** Connect to a single server by name. */
28
+ async connectOne(name, serverConfig, log = console.error) {
29
+ // Disconnect existing connection with this name if any
30
+ if (this.connections.has(name)) {
31
+ await this.disconnectOne(name);
32
+ }
33
+ const transport = createTransport(serverConfig);
34
+ const client = new Client({ name: "mcpi-ext", version: "0.1.0" }, {
35
+ capabilities: {},
36
+ listChanged: {
37
+ tools: {
38
+ onChanged: (_error, tools) => {
39
+ if (tools) {
40
+ const conn = this.connections.get(name);
41
+ if (conn && conn.client === client) {
42
+ conn.tools = toMcpTools(name, tools);
43
+ log(`[mcp] Tools updated for "${name}" (${conn.tools.length} tools)`);
44
+ }
45
+ }
46
+ },
47
+ },
48
+ },
49
+ });
50
+ // Insert placeholder so listChanged notifications during connect aren't dropped
51
+ this.connections.set(name, { client, transport, tools: [] });
52
+ try {
53
+ await client.connect(transport);
54
+ const toolsResult = await client.listTools();
55
+ const tools = toMcpTools(name, toolsResult.tools);
56
+ const conn = this.connections.get(name);
57
+ if (conn && conn.client === client) {
58
+ conn.tools = tools;
59
+ }
60
+ log(`[mcp] Connected to "${name}" (${tools.length} tools)`);
61
+ }
62
+ catch (error) {
63
+ // Clean up on failure so we don't leak a partially connected client
64
+ const conn = this.connections.get(name);
65
+ if (conn && conn.client === client) {
66
+ this.connections.delete(name);
67
+ }
68
+ try {
69
+ await client.close();
70
+ }
71
+ catch {
72
+ // best-effort cleanup
73
+ }
74
+ throw error;
75
+ }
76
+ }
77
+ /** Disconnect a single server. */
78
+ async disconnectOne(name) {
79
+ const conn = this.connections.get(name);
80
+ if (!conn)
81
+ return;
82
+ this.connections.delete(name);
83
+ try {
84
+ await conn.client.close();
85
+ }
86
+ catch {
87
+ // best-effort
88
+ }
89
+ }
90
+ /** Disconnect all servers. */
91
+ async disconnectAll() {
92
+ const names = [...this.connections.keys()];
93
+ await Promise.allSettled(names.map((n) => this.disconnectOne(n)));
94
+ }
95
+ /** Get all discovered tools across all connected servers. */
96
+ getTools() {
97
+ const tools = [];
98
+ for (const conn of this.connections.values()) {
99
+ tools.push(...conn.tools);
100
+ }
101
+ return tools;
102
+ }
103
+ /** Get tools from a specific server. */
104
+ getToolsForServer(name) {
105
+ return this.connections.get(name)?.tools ?? [];
106
+ }
107
+ /** Get the MCP Client for a specific server (needed to call tools). */
108
+ getClient(name) {
109
+ return this.connections.get(name)?.client;
110
+ }
111
+ /** List connected server names. */
112
+ getConnectedServers() {
113
+ return [...this.connections.keys()];
114
+ }
115
+ }
116
+ function createTransport(config) {
117
+ if (config.type === "stdio") {
118
+ const env = config.env
119
+ ? Object.fromEntries(Object.entries({ ...process.env, ...config.env }).filter((entry) => entry[1] !== undefined))
120
+ : undefined;
121
+ return new StdioClientTransport({
122
+ command: config.command,
123
+ args: config.args,
124
+ env,
125
+ cwd: config.cwd,
126
+ });
127
+ }
128
+ const headers = {
129
+ ...(config.headers ?? {}),
130
+ };
131
+ return new StreamableHTTPClientTransport(new URL(config.url), {
132
+ requestInit: {
133
+ headers,
134
+ },
135
+ });
136
+ }
137
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
138
+ function toMcpTools(serverName, tools) {
139
+ return tools.map((t) => ({
140
+ name: t.name,
141
+ description: t.description,
142
+ inputSchema: t.inputSchema,
143
+ outputSchema: t.outputSchema,
144
+ annotations: t.annotations,
145
+ serverName,
146
+ }));
147
+ }
148
+ //# sourceMappingURL=client-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-manager.js","sourceRoot":"","sources":["../../src/mcp/client-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=client-manager.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-manager.test.d.ts","sourceRoot":"","sources":["../../src/mcp/client-manager.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,204 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { McpClientManager } from "./client-manager.js";
3
+ // Mock the MCP SDK transports and client
4
+ vi.mock("@modelcontextprotocol/sdk/client/index.js", () => {
5
+ class MockClient {
6
+ _onToolsChanged;
7
+ constructor(_info, options) {
8
+ this._onToolsChanged = options?.listChanged?.tools?.onChanged;
9
+ }
10
+ async connect(_transport) {
11
+ // no-op for tests
12
+ }
13
+ async close() {
14
+ // no-op for tests
15
+ }
16
+ async listTools() {
17
+ return {
18
+ tools: [
19
+ {
20
+ name: "mock_tool",
21
+ description: "A mock tool for testing",
22
+ inputSchema: { type: "object", properties: { arg: { type: "string" } } },
23
+ annotations: { readOnlyHint: true },
24
+ },
25
+ {
26
+ name: "mock_tool_2",
27
+ description: "Another mock tool",
28
+ inputSchema: { type: "object", properties: {} },
29
+ },
30
+ ],
31
+ };
32
+ }
33
+ /** Test helper to simulate tools/list_changed notification. */
34
+ _simulateToolsChanged(tools) {
35
+ this._onToolsChanged?.(null, tools);
36
+ }
37
+ }
38
+ return { Client: MockClient };
39
+ });
40
+ vi.mock("@modelcontextprotocol/sdk/client/stdio.js", () => ({
41
+ // eslint-disable-next-line @typescript-eslint/no-extraneous-class
42
+ StdioClientTransport: class {
43
+ // eslint-disable-next-line @typescript-eslint/no-useless-constructor
44
+ constructor(_params) {
45
+ // no-op mock
46
+ }
47
+ },
48
+ }));
49
+ vi.mock("@modelcontextprotocol/sdk/client/streamableHttp.js", () => ({
50
+ // eslint-disable-next-line @typescript-eslint/no-extraneous-class
51
+ StreamableHTTPClientTransport: class {
52
+ // eslint-disable-next-line @typescript-eslint/no-useless-constructor
53
+ constructor(_url, _opts) {
54
+ // no-op mock
55
+ }
56
+ },
57
+ }));
58
+ describe("McpClientManager", () => {
59
+ let manager;
60
+ beforeEach(() => {
61
+ manager = new McpClientManager();
62
+ });
63
+ it("connects to a stdio server and discovers tools", async () => {
64
+ await manager.connectAll({
65
+ mcpServers: {
66
+ "test-stdio": {
67
+ type: "stdio",
68
+ command: "node",
69
+ args: ["test-server.js"],
70
+ },
71
+ },
72
+ });
73
+ expect(manager.getConnectedServers()).toEqual(["test-stdio"]);
74
+ const tools = manager.getTools();
75
+ expect(tools).toHaveLength(2);
76
+ expect(tools[0].name).toBe("mock_tool");
77
+ expect(tools[0].serverName).toBe("test-stdio");
78
+ expect(tools[0].description).toBe("A mock tool for testing");
79
+ expect(tools[0].annotations).toEqual({ readOnlyHint: true });
80
+ expect(tools[1].name).toBe("mock_tool_2");
81
+ });
82
+ it("connects to a remote server and discovers tools", async () => {
83
+ await manager.connectAll({
84
+ mcpServers: {
85
+ "test-remote": {
86
+ type: "remote",
87
+ url: "https://example.com/mcp",
88
+ headers: { Authorization: "Bearer test" },
89
+ },
90
+ },
91
+ });
92
+ expect(manager.getConnectedServers()).toEqual(["test-remote"]);
93
+ expect(manager.getTools()).toHaveLength(2);
94
+ });
95
+ it("connects to multiple servers and aggregates tools", async () => {
96
+ await manager.connectAll({
97
+ mcpServers: {
98
+ server1: { type: "stdio", command: "node", args: ["s1.js"] },
99
+ server2: { type: "remote", url: "https://example.com/mcp" },
100
+ },
101
+ });
102
+ expect(manager.getConnectedServers()).toHaveLength(2);
103
+ // 2 tools per server
104
+ expect(manager.getTools()).toHaveLength(4);
105
+ });
106
+ it("getToolsForServer returns tools for a specific server", async () => {
107
+ await manager.connectAll({
108
+ mcpServers: {
109
+ srv: { type: "stdio", command: "echo" },
110
+ },
111
+ });
112
+ expect(manager.getToolsForServer("srv")).toHaveLength(2);
113
+ expect(manager.getToolsForServer("nonexistent")).toEqual([]);
114
+ });
115
+ it("getClient returns the client for a connected server", async () => {
116
+ await manager.connectAll({
117
+ mcpServers: {
118
+ srv: { type: "stdio", command: "echo" },
119
+ },
120
+ });
121
+ expect(manager.getClient("srv")).toBeDefined();
122
+ expect(manager.getClient("nonexistent")).toBeUndefined();
123
+ });
124
+ it("disconnectOne removes a server", async () => {
125
+ await manager.connectAll({
126
+ mcpServers: {
127
+ srv: { type: "stdio", command: "echo" },
128
+ },
129
+ });
130
+ expect(manager.getConnectedServers()).toEqual(["srv"]);
131
+ await manager.disconnectOne("srv");
132
+ expect(manager.getConnectedServers()).toEqual([]);
133
+ expect(manager.getTools()).toEqual([]);
134
+ });
135
+ it("disconnectAll removes all servers", async () => {
136
+ await manager.connectAll({
137
+ mcpServers: {
138
+ s1: { type: "stdio", command: "echo" },
139
+ s2: { type: "remote", url: "https://example.com/mcp" },
140
+ },
141
+ });
142
+ expect(manager.getConnectedServers()).toHaveLength(2);
143
+ await manager.disconnectAll();
144
+ expect(manager.getConnectedServers()).toEqual([]);
145
+ });
146
+ it("handles empty config gracefully", async () => {
147
+ await manager.connectAll({ mcpServers: {} });
148
+ expect(manager.getConnectedServers()).toEqual([]);
149
+ expect(manager.getTools()).toEqual([]);
150
+ });
151
+ it("reconnects when connecting to an already-connected server name", async () => {
152
+ await manager.connectOne("srv", { type: "stdio", command: "node" });
153
+ expect(manager.getConnectedServers()).toEqual(["srv"]);
154
+ // Connect again with same name — should replace
155
+ await manager.connectOne("srv", { type: "remote", url: "https://example.com/mcp" });
156
+ expect(manager.getConnectedServers()).toEqual(["srv"]);
157
+ expect(manager.getTools()).toHaveLength(2);
158
+ });
159
+ it("logs failures but continues connecting other servers", async () => {
160
+ const logs = [];
161
+ // Patch Client.connect to fail for a specific transport
162
+ const { Client } = await import("@modelcontextprotocol/sdk/client/index.js");
163
+ const origConnect = Client.prototype.connect;
164
+ let callCount = 0;
165
+ Client.prototype.connect = async function (transport) {
166
+ callCount++;
167
+ if (callCount === 1)
168
+ throw new Error("Connection refused");
169
+ return origConnect.call(this, transport);
170
+ };
171
+ try {
172
+ await manager.connectAll({
173
+ mcpServers: {
174
+ failing: { type: "stdio", command: "bad-command" },
175
+ working: { type: "stdio", command: "good-command" },
176
+ },
177
+ }, (msg) => logs.push(msg));
178
+ // The working server should still be connected
179
+ expect(manager.getConnectedServers()).toContain("working");
180
+ expect(logs.some((l) => l.includes("Failed to connect") && l.includes("failing"))).toBe(true);
181
+ }
182
+ finally {
183
+ Client.prototype.connect = origConnect;
184
+ }
185
+ });
186
+ it("updates tools when list_changed notification fires", async () => {
187
+ const logs = [];
188
+ await manager.connectAll({ mcpServers: { srv: { type: "stdio", command: "echo" } } }, (msg) => logs.push(msg));
189
+ expect(manager.getToolsForServer("srv")).toHaveLength(2);
190
+ // Simulate a tools/list_changed notification via the mock
191
+ const client = manager.getClient("srv");
192
+ client._simulateToolsChanged([
193
+ {
194
+ name: "new_tool",
195
+ description: "A dynamically added tool",
196
+ inputSchema: { type: "object", properties: {} },
197
+ },
198
+ ]);
199
+ expect(manager.getToolsForServer("srv")).toHaveLength(1);
200
+ expect(manager.getToolsForServer("srv")[0].name).toBe("new_tool");
201
+ expect(logs.some((l) => l.includes("Tools updated"))).toBe(true);
202
+ });
203
+ });
204
+ //# sourceMappingURL=client-manager.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-manager.test.js","sourceRoot":"","sources":["../../src/mcp/client-manager.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { McpConfig } from "./config.js";
2
+ /**
3
+ * Load and validate an MCP config file.
4
+ * Returns an empty config if the file doesn't exist.
5
+ * Throws on invalid JSON or schema violations.
6
+ */
7
+ export declare function loadMcpConfig(configPath?: string): Promise<McpConfig>;
8
+ //# sourceMappingURL=config-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/mcp/config-loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAgC3E"}