@openeryc/pi-coding-agent 0.75.25 → 0.75.26

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 (34) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/core/agent-session.d.ts +3 -0
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +28 -0
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/mcp/client.d.ts +19 -0
  7. package/dist/core/mcp/client.d.ts.map +1 -0
  8. package/dist/core/mcp/client.js +143 -0
  9. package/dist/core/mcp/client.js.map +1 -0
  10. package/dist/core/mcp/index.d.ts +5 -0
  11. package/dist/core/mcp/index.d.ts.map +1 -0
  12. package/dist/core/mcp/index.js +3 -0
  13. package/dist/core/mcp/index.js.map +1 -0
  14. package/dist/core/mcp/manager.d.ts +17 -0
  15. package/dist/core/mcp/manager.d.ts.map +1 -0
  16. package/dist/core/mcp/manager.js +133 -0
  17. package/dist/core/mcp/manager.js.map +1 -0
  18. package/dist/core/mcp/types.d.ts +86 -0
  19. package/dist/core/mcp/types.d.ts.map +1 -0
  20. package/dist/core/mcp/types.js +8 -0
  21. package/dist/core/mcp/types.js.map +1 -0
  22. package/dist/core/settings-manager.d.ts +10 -0
  23. package/dist/core/settings-manager.d.ts.map +1 -1
  24. package/dist/core/settings-manager.js +3 -0
  25. package/dist/core/settings-manager.js.map +1 -1
  26. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  27. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  28. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  29. package/examples/extensions/sandbox/package-lock.json +2 -2
  30. package/examples/extensions/sandbox/package.json +1 -1
  31. package/examples/extensions/with-deps/package-lock.json +2 -2
  32. package/examples/extensions/with-deps/package.json +1 -1
  33. package/npm-shrinkwrap.json +12 -12
  34. package/package.json +4 -4
@@ -0,0 +1,19 @@
1
+ import type { MCPCallToolResult, MCPListToolsResult, MCPServerConfig } from "./types.ts";
2
+ export declare class MCPClient {
3
+ private process;
4
+ private requestId;
5
+ private pendingRequests;
6
+ private lineReader;
7
+ private config;
8
+ private errorLogs;
9
+ get errors(): readonly string[];
10
+ constructor(config: MCPServerConfig);
11
+ connect(): Promise<void>;
12
+ private sendRequest;
13
+ private handleLine;
14
+ private initialize;
15
+ listTools(): Promise<MCPListToolsResult>;
16
+ callTool(name: string, args: Record<string, unknown>): Promise<MCPCallToolResult>;
17
+ disconnect(): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,iBAAiB,EAIjB,kBAAkB,EAClB,eAAe,EACf,MAAM,YAAY,CAAC;AAMpB,qBAAa,SAAS;IACrB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,eAAe,CAA4F;IACnH,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,SAAS,CAAgB;IAEjC,IAAI,MAAM,IAAI,SAAS,MAAM,EAAE,CAE9B;IAED,YAAY,MAAM,EAAE,eAAe,EAElC;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAkD7B;YAEa,WAAW;IAoBzB,OAAO,CAAC,UAAU;YAmBJ,UAAU;IAQlB,SAAS,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAE7C;IAEK,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAKtF;IAEK,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CA2BhC;CACD","sourcesContent":["import { type ChildProcess, spawn } from \"child_process\";\nimport { createInterface, type Interface } from \"readline\";\nimport type {\n\tMCPCallToolResult,\n\tMCPInitializeResult,\n\tMCPJsonRpcRequest,\n\tMCPJsonRpcResponse,\n\tMCPListToolsResult,\n\tMCPServerConfig,\n} from \"./types.ts\";\n\nconst INITIALIZE_REQUEST = \"initialize\";\nconst TOOLS_LIST_REQUEST = \"tools/list\";\nconst TOOLS_CALL_REQUEST = \"tools/call\";\n\nexport class MCPClient {\n\tprivate process: ChildProcess | null = null;\n\tprivate requestId = 0;\n\tprivate pendingRequests = new Map<number, { resolve: (value: unknown) => void; reject: (error: Error) => void }>();\n\tprivate lineReader: Interface | null = null;\n\tprivate config: MCPServerConfig;\n\tprivate errorLogs: string[] = [];\n\n\tget errors(): readonly string[] {\n\t\treturn this.errorLogs;\n\t}\n\n\tconstructor(config: MCPServerConfig) {\n\t\tthis.config = config;\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tconst { command, args = [], env } = this.config;\n\t\tconst childEnv = env ? { ...process.env, ...env } : process.env;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.process = spawn(command, args, {\n\t\t\t\tenv: childEnv,\n\t\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t\t\tshell: false,\n\t\t\t});\n\n\t\t\tconst onError = (error: Error) => {\n\t\t\t\treject(new Error(`Failed to spawn MCP server \"${command}\": ${error.message}`));\n\t\t\t};\n\n\t\t\tthis.process.on(\"error\", onError);\n\t\t\tthis.process.once(\"spawn\", () => {\n\t\t\t\tthis.process!.removeListener(\"error\", onError);\n\t\t\t});\n\n\t\t\tif (!this.process.stdout) {\n\t\t\t\treject(new Error(`MCP server \"${command}\" has no stdout`));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.lineReader = createInterface({ input: this.process.stdout, crlfDelay: Infinity });\n\n\t\t\tthis.lineReader.on(\"line\", (line: string) => {\n\t\t\t\tthis.handleLine(line);\n\t\t\t});\n\n\t\t\tif (this.process.stderr) {\n\t\t\t\tthis.process.stderr.setEncoding(\"utf-8\");\n\t\t\t\tthis.process.stderr.on(\"data\", (data: string) => {\n\t\t\t\t\tthis.errorLogs.push(data);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.process.on(\"exit\", (code) => {\n\t\t\t\tconst pendingCopy = new Map(this.pendingRequests);\n\t\t\t\tthis.pendingRequests.clear();\n\t\t\t\tfor (const [, handler] of pendingCopy) {\n\t\t\t\t\thandler.reject(new Error(`MCP server \"${command}\" exited with code ${code}`));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.initialize()\n\t\t\t\t.then(() => resolve())\n\t\t\t\t.catch(reject);\n\t\t});\n\t}\n\n\tprivate async sendRequest(method: string, params?: Record<string, unknown>): Promise<unknown> {\n\t\tif (!this.process || !this.process.stdin) {\n\t\t\tthrow new Error(`MCP client not connected`);\n\t\t}\n\n\t\tconst id = ++this.requestId;\n\t\tconst request: MCPJsonRpcRequest = {\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tid,\n\t\t\tmethod,\n\t\t\tparams,\n\t\t};\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.pendingRequests.set(id, { resolve, reject });\n\t\t\tconst payload = JSON.stringify(request);\n\t\t\tthis.process!.stdin!.write(`${payload}\\n`);\n\t\t});\n\t}\n\n\tprivate handleLine(line: string): void {\n\t\ttry {\n\t\t\tconst response = JSON.parse(line) as MCPJsonRpcResponse;\n\t\t\tif (response.id !== undefined) {\n\t\t\t\tconst request = this.pendingRequests.get(response.id);\n\t\t\t\tif (request) {\n\t\t\t\t\tthis.pendingRequests.delete(response.id);\n\t\t\t\t\tif (response.error) {\n\t\t\t\t\t\trequest.reject(new Error(`MCP error: ${response.error.message} (code ${response.error.code})`));\n\t\t\t\t\t} else {\n\t\t\t\t\t\trequest.resolve(response.result);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore non-JSON lines (stderr or informational messages)\n\t\t}\n\t}\n\n\tprivate async initialize(): Promise<MCPInitializeResult> {\n\t\treturn (await this.sendRequest(INITIALIZE_REQUEST, {\n\t\t\tprotocolVersion: \"2024-11-05\",\n\t\t\tcapabilities: {},\n\t\t\tclientInfo: { name: \"pi\", version: \"1.0.0\" },\n\t\t})) as MCPInitializeResult;\n\t}\n\n\tasync listTools(): Promise<MCPListToolsResult> {\n\t\treturn (await this.sendRequest(TOOLS_LIST_REQUEST)) as MCPListToolsResult;\n\t}\n\n\tasync callTool(name: string, args: Record<string, unknown>): Promise<MCPCallToolResult> {\n\t\treturn (await this.sendRequest(TOOLS_CALL_REQUEST, {\n\t\t\tname,\n\t\t\targuments: args,\n\t\t} as unknown as Record<string, unknown>)) as MCPCallToolResult;\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tif (this.lineReader) {\n\t\t\tthis.lineReader.close();\n\t\t\tthis.lineReader = null;\n\t\t}\n\t\tif (this.process) {\n\t\t\tconst proc = this.process;\n\t\t\tthis.process = null;\n\t\t\tthis.pendingRequests.clear();\n\t\t\tif (!proc.killed) {\n\t\t\t\tproc.kill();\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\tconst onExit = () => {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t};\n\t\t\t\t\tproc.on(\"exit\", onExit);\n\t\t\t\t\tif (proc.exitCode !== null) {\n\t\t\t\t\t\tproc.removeListener(\"exit\", onExit);\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tproc.removeListener(\"exit\", onExit);\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t}, 3000);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,143 @@
1
+ import { spawn } from "child_process";
2
+ import { createInterface } from "readline";
3
+ const INITIALIZE_REQUEST = "initialize";
4
+ const TOOLS_LIST_REQUEST = "tools/list";
5
+ const TOOLS_CALL_REQUEST = "tools/call";
6
+ export class MCPClient {
7
+ process = null;
8
+ requestId = 0;
9
+ pendingRequests = new Map();
10
+ lineReader = null;
11
+ config;
12
+ errorLogs = [];
13
+ get errors() {
14
+ return this.errorLogs;
15
+ }
16
+ constructor(config) {
17
+ this.config = config;
18
+ }
19
+ async connect() {
20
+ const { command, args = [], env } = this.config;
21
+ const childEnv = env ? { ...process.env, ...env } : process.env;
22
+ return new Promise((resolve, reject) => {
23
+ this.process = spawn(command, args, {
24
+ env: childEnv,
25
+ stdio: ["pipe", "pipe", "pipe"],
26
+ shell: false,
27
+ });
28
+ const onError = (error) => {
29
+ reject(new Error(`Failed to spawn MCP server "${command}": ${error.message}`));
30
+ };
31
+ this.process.on("error", onError);
32
+ this.process.once("spawn", () => {
33
+ this.process.removeListener("error", onError);
34
+ });
35
+ if (!this.process.stdout) {
36
+ reject(new Error(`MCP server "${command}" has no stdout`));
37
+ return;
38
+ }
39
+ this.lineReader = createInterface({ input: this.process.stdout, crlfDelay: Infinity });
40
+ this.lineReader.on("line", (line) => {
41
+ this.handleLine(line);
42
+ });
43
+ if (this.process.stderr) {
44
+ this.process.stderr.setEncoding("utf-8");
45
+ this.process.stderr.on("data", (data) => {
46
+ this.errorLogs.push(data);
47
+ });
48
+ }
49
+ this.process.on("exit", (code) => {
50
+ const pendingCopy = new Map(this.pendingRequests);
51
+ this.pendingRequests.clear();
52
+ for (const [, handler] of pendingCopy) {
53
+ handler.reject(new Error(`MCP server "${command}" exited with code ${code}`));
54
+ }
55
+ });
56
+ this.initialize()
57
+ .then(() => resolve())
58
+ .catch(reject);
59
+ });
60
+ }
61
+ async sendRequest(method, params) {
62
+ if (!this.process || !this.process.stdin) {
63
+ throw new Error(`MCP client not connected`);
64
+ }
65
+ const id = ++this.requestId;
66
+ const request = {
67
+ jsonrpc: "2.0",
68
+ id,
69
+ method,
70
+ params,
71
+ };
72
+ return new Promise((resolve, reject) => {
73
+ this.pendingRequests.set(id, { resolve, reject });
74
+ const payload = JSON.stringify(request);
75
+ this.process.stdin.write(`${payload}\n`);
76
+ });
77
+ }
78
+ handleLine(line) {
79
+ try {
80
+ const response = JSON.parse(line);
81
+ if (response.id !== undefined) {
82
+ const request = this.pendingRequests.get(response.id);
83
+ if (request) {
84
+ this.pendingRequests.delete(response.id);
85
+ if (response.error) {
86
+ request.reject(new Error(`MCP error: ${response.error.message} (code ${response.error.code})`));
87
+ }
88
+ else {
89
+ request.resolve(response.result);
90
+ }
91
+ }
92
+ }
93
+ }
94
+ catch {
95
+ // Ignore non-JSON lines (stderr or informational messages)
96
+ }
97
+ }
98
+ async initialize() {
99
+ return (await this.sendRequest(INITIALIZE_REQUEST, {
100
+ protocolVersion: "2024-11-05",
101
+ capabilities: {},
102
+ clientInfo: { name: "pi", version: "1.0.0" },
103
+ }));
104
+ }
105
+ async listTools() {
106
+ return (await this.sendRequest(TOOLS_LIST_REQUEST));
107
+ }
108
+ async callTool(name, args) {
109
+ return (await this.sendRequest(TOOLS_CALL_REQUEST, {
110
+ name,
111
+ arguments: args,
112
+ }));
113
+ }
114
+ async disconnect() {
115
+ if (this.lineReader) {
116
+ this.lineReader.close();
117
+ this.lineReader = null;
118
+ }
119
+ if (this.process) {
120
+ const proc = this.process;
121
+ this.process = null;
122
+ this.pendingRequests.clear();
123
+ if (!proc.killed) {
124
+ proc.kill();
125
+ await new Promise((resolve) => {
126
+ const onExit = () => {
127
+ resolve();
128
+ };
129
+ proc.on("exit", onExit);
130
+ if (proc.exitCode !== null) {
131
+ proc.removeListener("exit", onExit);
132
+ resolve();
133
+ }
134
+ setTimeout(() => {
135
+ proc.removeListener("exit", onExit);
136
+ resolve();
137
+ }, 3000);
138
+ });
139
+ }
140
+ }
141
+ }
142
+ }
143
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/core/mcp/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcess, spawn } from \"child_process\";\nimport { createInterface, type Interface } from \"readline\";\nimport type {\n\tMCPCallToolResult,\n\tMCPInitializeResult,\n\tMCPJsonRpcRequest,\n\tMCPJsonRpcResponse,\n\tMCPListToolsResult,\n\tMCPServerConfig,\n} from \"./types.ts\";\n\nconst INITIALIZE_REQUEST = \"initialize\";\nconst TOOLS_LIST_REQUEST = \"tools/list\";\nconst TOOLS_CALL_REQUEST = \"tools/call\";\n\nexport class MCPClient {\n\tprivate process: ChildProcess | null = null;\n\tprivate requestId = 0;\n\tprivate pendingRequests = new Map<number, { resolve: (value: unknown) => void; reject: (error: Error) => void }>();\n\tprivate lineReader: Interface | null = null;\n\tprivate config: MCPServerConfig;\n\tprivate errorLogs: string[] = [];\n\n\tget errors(): readonly string[] {\n\t\treturn this.errorLogs;\n\t}\n\n\tconstructor(config: MCPServerConfig) {\n\t\tthis.config = config;\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tconst { command, args = [], env } = this.config;\n\t\tconst childEnv = env ? { ...process.env, ...env } : process.env;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.process = spawn(command, args, {\n\t\t\t\tenv: childEnv,\n\t\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t\t\tshell: false,\n\t\t\t});\n\n\t\t\tconst onError = (error: Error) => {\n\t\t\t\treject(new Error(`Failed to spawn MCP server \"${command}\": ${error.message}`));\n\t\t\t};\n\n\t\t\tthis.process.on(\"error\", onError);\n\t\t\tthis.process.once(\"spawn\", () => {\n\t\t\t\tthis.process!.removeListener(\"error\", onError);\n\t\t\t});\n\n\t\t\tif (!this.process.stdout) {\n\t\t\t\treject(new Error(`MCP server \"${command}\" has no stdout`));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.lineReader = createInterface({ input: this.process.stdout, crlfDelay: Infinity });\n\n\t\t\tthis.lineReader.on(\"line\", (line: string) => {\n\t\t\t\tthis.handleLine(line);\n\t\t\t});\n\n\t\t\tif (this.process.stderr) {\n\t\t\t\tthis.process.stderr.setEncoding(\"utf-8\");\n\t\t\t\tthis.process.stderr.on(\"data\", (data: string) => {\n\t\t\t\t\tthis.errorLogs.push(data);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthis.process.on(\"exit\", (code) => {\n\t\t\t\tconst pendingCopy = new Map(this.pendingRequests);\n\t\t\t\tthis.pendingRequests.clear();\n\t\t\t\tfor (const [, handler] of pendingCopy) {\n\t\t\t\t\thandler.reject(new Error(`MCP server \"${command}\" exited with code ${code}`));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.initialize()\n\t\t\t\t.then(() => resolve())\n\t\t\t\t.catch(reject);\n\t\t});\n\t}\n\n\tprivate async sendRequest(method: string, params?: Record<string, unknown>): Promise<unknown> {\n\t\tif (!this.process || !this.process.stdin) {\n\t\t\tthrow new Error(`MCP client not connected`);\n\t\t}\n\n\t\tconst id = ++this.requestId;\n\t\tconst request: MCPJsonRpcRequest = {\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tid,\n\t\t\tmethod,\n\t\t\tparams,\n\t\t};\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.pendingRequests.set(id, { resolve, reject });\n\t\t\tconst payload = JSON.stringify(request);\n\t\t\tthis.process!.stdin!.write(`${payload}\\n`);\n\t\t});\n\t}\n\n\tprivate handleLine(line: string): void {\n\t\ttry {\n\t\t\tconst response = JSON.parse(line) as MCPJsonRpcResponse;\n\t\t\tif (response.id !== undefined) {\n\t\t\t\tconst request = this.pendingRequests.get(response.id);\n\t\t\t\tif (request) {\n\t\t\t\t\tthis.pendingRequests.delete(response.id);\n\t\t\t\t\tif (response.error) {\n\t\t\t\t\t\trequest.reject(new Error(`MCP error: ${response.error.message} (code ${response.error.code})`));\n\t\t\t\t\t} else {\n\t\t\t\t\t\trequest.resolve(response.result);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore non-JSON lines (stderr or informational messages)\n\t\t}\n\t}\n\n\tprivate async initialize(): Promise<MCPInitializeResult> {\n\t\treturn (await this.sendRequest(INITIALIZE_REQUEST, {\n\t\t\tprotocolVersion: \"2024-11-05\",\n\t\t\tcapabilities: {},\n\t\t\tclientInfo: { name: \"pi\", version: \"1.0.0\" },\n\t\t})) as MCPInitializeResult;\n\t}\n\n\tasync listTools(): Promise<MCPListToolsResult> {\n\t\treturn (await this.sendRequest(TOOLS_LIST_REQUEST)) as MCPListToolsResult;\n\t}\n\n\tasync callTool(name: string, args: Record<string, unknown>): Promise<MCPCallToolResult> {\n\t\treturn (await this.sendRequest(TOOLS_CALL_REQUEST, {\n\t\t\tname,\n\t\t\targuments: args,\n\t\t} as unknown as Record<string, unknown>)) as MCPCallToolResult;\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tif (this.lineReader) {\n\t\t\tthis.lineReader.close();\n\t\t\tthis.lineReader = null;\n\t\t}\n\t\tif (this.process) {\n\t\t\tconst proc = this.process;\n\t\t\tthis.process = null;\n\t\t\tthis.pendingRequests.clear();\n\t\t\tif (!proc.killed) {\n\t\t\t\tproc.kill();\n\t\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t\tconst onExit = () => {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t};\n\t\t\t\t\tproc.on(\"exit\", onExit);\n\t\t\t\t\tif (proc.exitCode !== null) {\n\t\t\t\t\t\tproc.removeListener(\"exit\", onExit);\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\tproc.removeListener(\"exit\", onExit);\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t}, 3000);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export { MCPClient } from "./client.ts";
2
+ export type { McpServerTools } from "./manager.ts";
3
+ export { MCPManager } from "./manager.ts";
4
+ export type { MCPCallToolContent, MCPCallToolImageContent, MCPCallToolResult, MCPCallToolTextContent, MCPServerConfig, MCPToolDefinition, } from "./types.ts";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EACX,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,EACf,iBAAiB,GACjB,MAAM,YAAY,CAAC","sourcesContent":["export { MCPClient } from \"./client.ts\";\nexport type { McpServerTools } from \"./manager.ts\";\nexport { MCPManager } from \"./manager.ts\";\nexport type {\n\tMCPCallToolContent,\n\tMCPCallToolImageContent,\n\tMCPCallToolResult,\n\tMCPCallToolTextContent,\n\tMCPServerConfig,\n\tMCPToolDefinition,\n} from \"./types.ts\";\n"]}
@@ -0,0 +1,3 @@
1
+ export { MCPClient } from "./client.js";
2
+ export { MCPManager } from "./manager.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export { MCPClient } from \"./client.ts\";\nexport type { McpServerTools } from \"./manager.ts\";\nexport { MCPManager } from \"./manager.ts\";\nexport type {\n\tMCPCallToolContent,\n\tMCPCallToolImageContent,\n\tMCPCallToolResult,\n\tMCPCallToolTextContent,\n\tMCPServerConfig,\n\tMCPToolDefinition,\n} from \"./types.ts\";\n"]}
@@ -0,0 +1,17 @@
1
+ import type { ToolDefinition } from "../extensions/types.ts";
2
+ import type { MCPServerConfig } from "./types.ts";
3
+ export interface McpServerTools {
4
+ serverName: string;
5
+ tools: ToolDefinition[];
6
+ }
7
+ export declare class MCPManager {
8
+ private serverConfigs;
9
+ private clients;
10
+ private serverTools;
11
+ constructor(serverConfigs: Record<string, MCPServerConfig>);
12
+ start(): Promise<void>;
13
+ getToolDefinitions(): ToolDefinition[];
14
+ getServerNames(): string[];
15
+ stop(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAqB,MAAM,YAAY,CAAC;AAkErE,MAAM,WAAW,cAAc;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,cAAc,EAAE,CAAC;CACxB;AAED,qBAAa,UAAU;IACtB,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,OAAO,CAAgC;IAC/C,OAAO,CAAC,WAAW,CAAuC;IAE1D,YAAY,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,EAEzD;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAmD3B;IAED,kBAAkB,IAAI,cAAc,EAAE,CAMrC;IAED,cAAc,IAAI,MAAM,EAAE,CAEzB;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAc1B;CACD","sourcesContent":["import type { AgentToolResult } from \"@openeryc/pi-agent-core\";\nimport { Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { MCPClient } from \"./client.ts\";\nimport type { MCPServerConfig, MCPToolDefinition } from \"./types.ts\";\n\nfunction jsonSchemaToTypeBox(schema: MCPToolDefinition[\"inputSchema\"]): ReturnType<typeof Type.Object> {\n\tconst properties: Record<string, unknown> = {};\n\n\tif (schema.properties) {\n\t\tfor (const [key, prop] of Object.entries(schema.properties)) {\n\t\t\tconst type = prop.type || \"string\";\n\t\t\tlet field: unknown;\n\n\t\t\tswitch (type) {\n\t\t\t\tcase \"string\":\n\t\t\t\t\tfield = prop.enum ? Type.Unsafe<string>({ type: \"string\", enum: prop.enum as string[] }) : Type.String();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"number\":\n\t\t\t\tcase \"integer\":\n\t\t\t\t\tfield = Type.Number();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"boolean\":\n\t\t\t\t\tfield = Type.Boolean();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"array\":\n\t\t\t\t\tfield = Type.Array(Type.Any());\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"object\":\n\t\t\t\t\tfield = Type.Record(Type.String(), Type.Any());\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tfield = Type.Any();\n\t\t\t}\n\n\t\t\tif (prop.description) {\n\t\t\t\t(field as { description?: string }).description = prop.description;\n\t\t\t}\n\n\t\t\tproperties[key] = field;\n\t\t}\n\t}\n\n\tif (Object.keys(properties).length === 0) {\n\t\treturn Type.Object({});\n\t}\n\n\tconst required = new Set(schema.required ?? []);\n\tfor (const key of Object.keys(properties)) {\n\t\tif (!required.has(key)) {\n\t\t\tproperties[key] = Type.Optional(properties[key] as ReturnType<typeof Type.String>);\n\t\t}\n\t}\n\n\treturn Type.Object(properties as Record<string, ReturnType<typeof Type.String>>);\n}\n\nfunction formatToolResult(result: {\n\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n}): string {\n\treturn result.content\n\t\t.map((item) => {\n\t\t\tif (item.type === \"text\" && item.text !== undefined) {\n\t\t\t\treturn item.text;\n\t\t\t}\n\t\t\treturn `[Image: ${item.mimeType}]`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nexport interface McpServerTools {\n\tserverName: string;\n\ttools: ToolDefinition[];\n}\n\nexport class MCPManager {\n\tprivate serverConfigs: Record<string, MCPServerConfig>;\n\tprivate clients = new Map<string, MCPClient>();\n\tprivate serverTools = new Map<string, ToolDefinition[]>();\n\n\tconstructor(serverConfigs: Record<string, MCPServerConfig>) {\n\t\tthis.serverConfigs = { ...serverConfigs };\n\t}\n\n\tasync start(): Promise<void> {\n\t\tfor (const [serverName, config] of Object.entries(this.serverConfigs)) {\n\t\t\ttry {\n\t\t\t\tconst client = new MCPClient(config);\n\t\t\t\tawait client.connect();\n\n\t\t\t\tconst toolsResult = await client.listTools();\n\t\t\t\tthis.clients.set(serverName, client);\n\n\t\t\t\tconst tools: ToolDefinition[] = [];\n\t\t\t\tfor (const tool of toolsResult.tools) {\n\t\t\t\t\tconst namespacedName = `mcp.${serverName}.${tool.name}`;\n\t\t\t\t\tconst description = tool.description\n\t\t\t\t\t\t? `${tool.description} (from MCP server \"${serverName}\")`\n\t\t\t\t\t\t: `Tool from MCP server \"${serverName}\"`;\n\n\t\t\t\t\ttools.push({\n\t\t\t\t\t\tname: namespacedName,\n\t\t\t\t\t\tlabel: namespacedName,\n\t\t\t\t\t\tdescription,\n\t\t\t\t\t\tpromptSnippet: namespacedName,\n\t\t\t\t\t\tparameters: jsonSchemaToTypeBox(tool.inputSchema),\n\t\t\t\t\t\trenderShell: \"default\",\n\t\t\t\t\t\texecutionMode: \"sequential\",\n\t\t\t\t\t\texecute: async (_toolCallId, params, _signal) => {\n\t\t\t\t\t\t\tconst result: AgentToolResult<unknown> = {\n\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\t\t\t\t\t\tdetails: {},\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst mcpResult = await client.callTool(tool.name, params as Record<string, unknown>);\n\t\t\t\t\t\t\t\tresult.content = [{ type: \"text\", text: formatToolResult(mcpResult) }];\n\t\t\t\t\t\t\t\tresult.details = mcpResult;\n\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\tconst errMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\t\t\tresult.content = [{ type: \"text\", text: `MCP tool error: ${errMsg}` }];\n\t\t\t\t\t\t\t\tresult.details = { error: errMsg };\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tthis.serverTools.set(serverName, tools);\n\t\t\t} catch (error) {\n\t\t\t\tconst errMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\tconsole.warn(`Failed to connect to MCP server \"${serverName}\": ${errMsg}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tgetToolDefinitions(): ToolDefinition[] {\n\t\tconst allTools: ToolDefinition[] = [];\n\t\tfor (const tools of this.serverTools.values()) {\n\t\t\tallTools.push(...tools);\n\t\t}\n\t\treturn allTools;\n\t}\n\n\tgetServerNames(): string[] {\n\t\treturn [...this.clients.keys()];\n\t}\n\n\tasync stop(): Promise<void> {\n\t\tconst disconnectPromises: Promise<void>[] = [];\n\t\tfor (const [name, client] of this.clients) {\n\t\t\tdisconnectPromises.push(\n\t\t\t\tclient.disconnect().catch((err) => {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Error disconnecting from MCP server \"${name}\": ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tthis.clients.clear();\n\t\tthis.serverTools.clear();\n\t\tawait Promise.all(disconnectPromises);\n\t}\n}\n"]}
@@ -0,0 +1,133 @@
1
+ import { Type } from "typebox";
2
+ import { MCPClient } from "./client.js";
3
+ function jsonSchemaToTypeBox(schema) {
4
+ const properties = {};
5
+ if (schema.properties) {
6
+ for (const [key, prop] of Object.entries(schema.properties)) {
7
+ const type = prop.type || "string";
8
+ let field;
9
+ switch (type) {
10
+ case "string":
11
+ field = prop.enum ? Type.Unsafe({ type: "string", enum: prop.enum }) : Type.String();
12
+ break;
13
+ case "number":
14
+ case "integer":
15
+ field = Type.Number();
16
+ break;
17
+ case "boolean":
18
+ field = Type.Boolean();
19
+ break;
20
+ case "array":
21
+ field = Type.Array(Type.Any());
22
+ break;
23
+ case "object":
24
+ field = Type.Record(Type.String(), Type.Any());
25
+ break;
26
+ default:
27
+ field = Type.Any();
28
+ }
29
+ if (prop.description) {
30
+ field.description = prop.description;
31
+ }
32
+ properties[key] = field;
33
+ }
34
+ }
35
+ if (Object.keys(properties).length === 0) {
36
+ return Type.Object({});
37
+ }
38
+ const required = new Set(schema.required ?? []);
39
+ for (const key of Object.keys(properties)) {
40
+ if (!required.has(key)) {
41
+ properties[key] = Type.Optional(properties[key]);
42
+ }
43
+ }
44
+ return Type.Object(properties);
45
+ }
46
+ function formatToolResult(result) {
47
+ return result.content
48
+ .map((item) => {
49
+ if (item.type === "text" && item.text !== undefined) {
50
+ return item.text;
51
+ }
52
+ return `[Image: ${item.mimeType}]`;
53
+ })
54
+ .join("\n");
55
+ }
56
+ export class MCPManager {
57
+ serverConfigs;
58
+ clients = new Map();
59
+ serverTools = new Map();
60
+ constructor(serverConfigs) {
61
+ this.serverConfigs = { ...serverConfigs };
62
+ }
63
+ async start() {
64
+ for (const [serverName, config] of Object.entries(this.serverConfigs)) {
65
+ try {
66
+ const client = new MCPClient(config);
67
+ await client.connect();
68
+ const toolsResult = await client.listTools();
69
+ this.clients.set(serverName, client);
70
+ const tools = [];
71
+ for (const tool of toolsResult.tools) {
72
+ const namespacedName = `mcp.${serverName}.${tool.name}`;
73
+ const description = tool.description
74
+ ? `${tool.description} (from MCP server "${serverName}")`
75
+ : `Tool from MCP server "${serverName}"`;
76
+ tools.push({
77
+ name: namespacedName,
78
+ label: namespacedName,
79
+ description,
80
+ promptSnippet: namespacedName,
81
+ parameters: jsonSchemaToTypeBox(tool.inputSchema),
82
+ renderShell: "default",
83
+ executionMode: "sequential",
84
+ execute: async (_toolCallId, params, _signal) => {
85
+ const result = {
86
+ content: [{ type: "text", text: "" }],
87
+ details: {},
88
+ };
89
+ try {
90
+ const mcpResult = await client.callTool(tool.name, params);
91
+ result.content = [{ type: "text", text: formatToolResult(mcpResult) }];
92
+ result.details = mcpResult;
93
+ }
94
+ catch (error) {
95
+ const errMsg = error instanceof Error ? error.message : String(error);
96
+ result.content = [{ type: "text", text: `MCP tool error: ${errMsg}` }];
97
+ result.details = { error: errMsg };
98
+ }
99
+ return result;
100
+ },
101
+ });
102
+ }
103
+ this.serverTools.set(serverName, tools);
104
+ }
105
+ catch (error) {
106
+ const errMsg = error instanceof Error ? error.message : String(error);
107
+ console.warn(`Failed to connect to MCP server "${serverName}": ${errMsg}`);
108
+ }
109
+ }
110
+ }
111
+ getToolDefinitions() {
112
+ const allTools = [];
113
+ for (const tools of this.serverTools.values()) {
114
+ allTools.push(...tools);
115
+ }
116
+ return allTools;
117
+ }
118
+ getServerNames() {
119
+ return [...this.clients.keys()];
120
+ }
121
+ async stop() {
122
+ const disconnectPromises = [];
123
+ for (const [name, client] of this.clients) {
124
+ disconnectPromises.push(client.disconnect().catch((err) => {
125
+ console.warn(`Error disconnecting from MCP server "${name}": ${err instanceof Error ? err.message : String(err)}`);
126
+ }));
127
+ }
128
+ this.clients.clear();
129
+ this.serverTools.clear();
130
+ await Promise.all(disconnectPromises);
131
+ }
132
+ }
133
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../../src/core/mcp/manager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentToolResult } from \"@openeryc/pi-agent-core\";\nimport { Type } from \"typebox\";\nimport type { ToolDefinition } from \"../extensions/types.ts\";\nimport { MCPClient } from \"./client.ts\";\nimport type { MCPServerConfig, MCPToolDefinition } from \"./types.ts\";\n\nfunction jsonSchemaToTypeBox(schema: MCPToolDefinition[\"inputSchema\"]): ReturnType<typeof Type.Object> {\n\tconst properties: Record<string, unknown> = {};\n\n\tif (schema.properties) {\n\t\tfor (const [key, prop] of Object.entries(schema.properties)) {\n\t\t\tconst type = prop.type || \"string\";\n\t\t\tlet field: unknown;\n\n\t\t\tswitch (type) {\n\t\t\t\tcase \"string\":\n\t\t\t\t\tfield = prop.enum ? Type.Unsafe<string>({ type: \"string\", enum: prop.enum as string[] }) : Type.String();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"number\":\n\t\t\t\tcase \"integer\":\n\t\t\t\t\tfield = Type.Number();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"boolean\":\n\t\t\t\t\tfield = Type.Boolean();\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"array\":\n\t\t\t\t\tfield = Type.Array(Type.Any());\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"object\":\n\t\t\t\t\tfield = Type.Record(Type.String(), Type.Any());\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tfield = Type.Any();\n\t\t\t}\n\n\t\t\tif (prop.description) {\n\t\t\t\t(field as { description?: string }).description = prop.description;\n\t\t\t}\n\n\t\t\tproperties[key] = field;\n\t\t}\n\t}\n\n\tif (Object.keys(properties).length === 0) {\n\t\treturn Type.Object({});\n\t}\n\n\tconst required = new Set(schema.required ?? []);\n\tfor (const key of Object.keys(properties)) {\n\t\tif (!required.has(key)) {\n\t\t\tproperties[key] = Type.Optional(properties[key] as ReturnType<typeof Type.String>);\n\t\t}\n\t}\n\n\treturn Type.Object(properties as Record<string, ReturnType<typeof Type.String>>);\n}\n\nfunction formatToolResult(result: {\n\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n}): string {\n\treturn result.content\n\t\t.map((item) => {\n\t\t\tif (item.type === \"text\" && item.text !== undefined) {\n\t\t\t\treturn item.text;\n\t\t\t}\n\t\t\treturn `[Image: ${item.mimeType}]`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nexport interface McpServerTools {\n\tserverName: string;\n\ttools: ToolDefinition[];\n}\n\nexport class MCPManager {\n\tprivate serverConfigs: Record<string, MCPServerConfig>;\n\tprivate clients = new Map<string, MCPClient>();\n\tprivate serverTools = new Map<string, ToolDefinition[]>();\n\n\tconstructor(serverConfigs: Record<string, MCPServerConfig>) {\n\t\tthis.serverConfigs = { ...serverConfigs };\n\t}\n\n\tasync start(): Promise<void> {\n\t\tfor (const [serverName, config] of Object.entries(this.serverConfigs)) {\n\t\t\ttry {\n\t\t\t\tconst client = new MCPClient(config);\n\t\t\t\tawait client.connect();\n\n\t\t\t\tconst toolsResult = await client.listTools();\n\t\t\t\tthis.clients.set(serverName, client);\n\n\t\t\t\tconst tools: ToolDefinition[] = [];\n\t\t\t\tfor (const tool of toolsResult.tools) {\n\t\t\t\t\tconst namespacedName = `mcp.${serverName}.${tool.name}`;\n\t\t\t\t\tconst description = tool.description\n\t\t\t\t\t\t? `${tool.description} (from MCP server \"${serverName}\")`\n\t\t\t\t\t\t: `Tool from MCP server \"${serverName}\"`;\n\n\t\t\t\t\ttools.push({\n\t\t\t\t\t\tname: namespacedName,\n\t\t\t\t\t\tlabel: namespacedName,\n\t\t\t\t\t\tdescription,\n\t\t\t\t\t\tpromptSnippet: namespacedName,\n\t\t\t\t\t\tparameters: jsonSchemaToTypeBox(tool.inputSchema),\n\t\t\t\t\t\trenderShell: \"default\",\n\t\t\t\t\t\texecutionMode: \"sequential\",\n\t\t\t\t\t\texecute: async (_toolCallId, params, _signal) => {\n\t\t\t\t\t\t\tconst result: AgentToolResult<unknown> = {\n\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"\" }],\n\t\t\t\t\t\t\t\tdetails: {},\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst mcpResult = await client.callTool(tool.name, params as Record<string, unknown>);\n\t\t\t\t\t\t\t\tresult.content = [{ type: \"text\", text: formatToolResult(mcpResult) }];\n\t\t\t\t\t\t\t\tresult.details = mcpResult;\n\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\tconst errMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\t\t\tresult.content = [{ type: \"text\", text: `MCP tool error: ${errMsg}` }];\n\t\t\t\t\t\t\t\tresult.details = { error: errMsg };\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tthis.serverTools.set(serverName, tools);\n\t\t\t} catch (error) {\n\t\t\t\tconst errMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\tconsole.warn(`Failed to connect to MCP server \"${serverName}\": ${errMsg}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tgetToolDefinitions(): ToolDefinition[] {\n\t\tconst allTools: ToolDefinition[] = [];\n\t\tfor (const tools of this.serverTools.values()) {\n\t\t\tallTools.push(...tools);\n\t\t}\n\t\treturn allTools;\n\t}\n\n\tgetServerNames(): string[] {\n\t\treturn [...this.clients.keys()];\n\t}\n\n\tasync stop(): Promise<void> {\n\t\tconst disconnectPromises: Promise<void>[] = [];\n\t\tfor (const [name, client] of this.clients) {\n\t\t\tdisconnectPromises.push(\n\t\t\t\tclient.disconnect().catch((err) => {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Error disconnecting from MCP server \"${name}\": ${err instanceof Error ? err.message : String(err)}`,\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tthis.clients.clear();\n\t\tthis.serverTools.clear();\n\t\tawait Promise.all(disconnectPromises);\n\t}\n}\n"]}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * MCP (Model Context Protocol) client types.
3
+ *
4
+ * Implements a minimal MCP client supporting stdio transport
5
+ * and tool listing/calling (tools only, no resources/prompts).
6
+ */
7
+ export interface MCPServerConfig {
8
+ command: string;
9
+ args?: string[];
10
+ env?: Record<string, string>;
11
+ }
12
+ export interface MCPJsonRpcRequest {
13
+ jsonrpc: "2.0";
14
+ id: number;
15
+ method: string;
16
+ params?: Record<string, unknown>;
17
+ }
18
+ export interface MCPJsonRpcResponse {
19
+ jsonrpc: "2.0";
20
+ id: number;
21
+ result?: unknown;
22
+ error?: MCPJsonRpcError;
23
+ }
24
+ export interface MCPJsonRpcError {
25
+ code: number;
26
+ message: string;
27
+ data?: unknown;
28
+ }
29
+ export interface MCPInitializeResult {
30
+ protocolVersion: string;
31
+ capabilities: MCPCapabilities;
32
+ serverInfo?: MCPInfo;
33
+ }
34
+ export interface MCPCapabilities {
35
+ tools?: MCPToolsCapability;
36
+ }
37
+ export interface MCPToolsCapability {
38
+ listChanged?: boolean;
39
+ }
40
+ export interface MCPInfo {
41
+ name: string;
42
+ version: string;
43
+ }
44
+ export interface MCPToolDefinition {
45
+ name: string;
46
+ description?: string;
47
+ inputSchema: MCPJsonSchema;
48
+ }
49
+ export interface MCPJsonSchema {
50
+ type: string;
51
+ properties?: Record<string, MCPJsonSchemaProperty>;
52
+ required?: string[];
53
+ additionalProperties?: boolean;
54
+ items?: MCPJsonSchema;
55
+ description?: string;
56
+ enum?: string[];
57
+ }
58
+ export interface MCPJsonSchemaProperty {
59
+ type?: string;
60
+ description?: string;
61
+ enum?: string[];
62
+ items?: MCPJsonSchema;
63
+ default?: unknown;
64
+ }
65
+ export interface MCPListToolsResult {
66
+ tools: MCPToolDefinition[];
67
+ }
68
+ export interface MCPCallToolRequest {
69
+ name: string;
70
+ arguments: Record<string, unknown>;
71
+ }
72
+ export interface MCPCallToolResult {
73
+ content: MCPCallToolContent[];
74
+ isError?: boolean;
75
+ }
76
+ export interface MCPCallToolTextContent {
77
+ type: "text";
78
+ text: string;
79
+ }
80
+ export interface MCPCallToolImageContent {
81
+ type: "image";
82
+ data: string;
83
+ mimeType: string;
84
+ }
85
+ export type MCPCallToolContent = MCPCallToolTextContent | MCPCallToolImageContent;
86
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/mcp/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,eAAe,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,CAAC,EAAE,kBAAkB,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,aAAa,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IACnD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,uBAAuB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,GAAG,uBAAuB,CAAC","sourcesContent":["/**\n * MCP (Model Context Protocol) client types.\n *\n * Implements a minimal MCP client supporting stdio transport\n * and tool listing/calling (tools only, no resources/prompts).\n */\n\nexport interface MCPServerConfig {\n\tcommand: string;\n\targs?: string[];\n\tenv?: Record<string, string>;\n}\n\nexport interface MCPJsonRpcRequest {\n\tjsonrpc: \"2.0\";\n\tid: number;\n\tmethod: string;\n\tparams?: Record<string, unknown>;\n}\n\nexport interface MCPJsonRpcResponse {\n\tjsonrpc: \"2.0\";\n\tid: number;\n\tresult?: unknown;\n\terror?: MCPJsonRpcError;\n}\n\nexport interface MCPJsonRpcError {\n\tcode: number;\n\tmessage: string;\n\tdata?: unknown;\n}\n\nexport interface MCPInitializeResult {\n\tprotocolVersion: string;\n\tcapabilities: MCPCapabilities;\n\tserverInfo?: MCPInfo;\n}\n\nexport interface MCPCapabilities {\n\ttools?: MCPToolsCapability;\n}\n\nexport interface MCPToolsCapability {\n\tlistChanged?: boolean;\n}\n\nexport interface MCPInfo {\n\tname: string;\n\tversion: string;\n}\n\nexport interface MCPToolDefinition {\n\tname: string;\n\tdescription?: string;\n\tinputSchema: MCPJsonSchema;\n}\n\nexport interface MCPJsonSchema {\n\ttype: string;\n\tproperties?: Record<string, MCPJsonSchemaProperty>;\n\trequired?: string[];\n\tadditionalProperties?: boolean;\n\titems?: MCPJsonSchema;\n\tdescription?: string;\n\tenum?: string[];\n}\n\nexport interface MCPJsonSchemaProperty {\n\ttype?: string;\n\tdescription?: string;\n\tenum?: string[];\n\titems?: MCPJsonSchema;\n\tdefault?: unknown;\n}\n\nexport interface MCPListToolsResult {\n\ttools: MCPToolDefinition[];\n}\n\nexport interface MCPCallToolRequest {\n\tname: string;\n\targuments: Record<string, unknown>;\n}\n\nexport interface MCPCallToolResult {\n\tcontent: MCPCallToolContent[];\n\tisError?: boolean;\n}\n\nexport interface MCPCallToolTextContent {\n\ttype: \"text\";\n\ttext: string;\n}\n\nexport interface MCPCallToolImageContent {\n\ttype: \"image\";\n\tdata: string;\n\tmimeType: string;\n}\n\nexport type MCPCallToolContent = MCPCallToolTextContent | MCPCallToolImageContent;\n"]}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * MCP (Model Context Protocol) client types.
3
+ *
4
+ * Implements a minimal MCP client supporting stdio transport
5
+ * and tool listing/calling (tools only, no resources/prompts).
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/mcp/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG","sourcesContent":["/**\n * MCP (Model Context Protocol) client types.\n *\n * Implements a minimal MCP client supporting stdio transport\n * and tool listing/calling (tools only, no resources/prompts).\n */\n\nexport interface MCPServerConfig {\n\tcommand: string;\n\targs?: string[];\n\tenv?: Record<string, string>;\n}\n\nexport interface MCPJsonRpcRequest {\n\tjsonrpc: \"2.0\";\n\tid: number;\n\tmethod: string;\n\tparams?: Record<string, unknown>;\n}\n\nexport interface MCPJsonRpcResponse {\n\tjsonrpc: \"2.0\";\n\tid: number;\n\tresult?: unknown;\n\terror?: MCPJsonRpcError;\n}\n\nexport interface MCPJsonRpcError {\n\tcode: number;\n\tmessage: string;\n\tdata?: unknown;\n}\n\nexport interface MCPInitializeResult {\n\tprotocolVersion: string;\n\tcapabilities: MCPCapabilities;\n\tserverInfo?: MCPInfo;\n}\n\nexport interface MCPCapabilities {\n\ttools?: MCPToolsCapability;\n}\n\nexport interface MCPToolsCapability {\n\tlistChanged?: boolean;\n}\n\nexport interface MCPInfo {\n\tname: string;\n\tversion: string;\n}\n\nexport interface MCPToolDefinition {\n\tname: string;\n\tdescription?: string;\n\tinputSchema: MCPJsonSchema;\n}\n\nexport interface MCPJsonSchema {\n\ttype: string;\n\tproperties?: Record<string, MCPJsonSchemaProperty>;\n\trequired?: string[];\n\tadditionalProperties?: boolean;\n\titems?: MCPJsonSchema;\n\tdescription?: string;\n\tenum?: string[];\n}\n\nexport interface MCPJsonSchemaProperty {\n\ttype?: string;\n\tdescription?: string;\n\tenum?: string[];\n\titems?: MCPJsonSchema;\n\tdefault?: unknown;\n}\n\nexport interface MCPListToolsResult {\n\ttools: MCPToolDefinition[];\n}\n\nexport interface MCPCallToolRequest {\n\tname: string;\n\targuments: Record<string, unknown>;\n}\n\nexport interface MCPCallToolResult {\n\tcontent: MCPCallToolContent[];\n\tisError?: boolean;\n}\n\nexport interface MCPCallToolTextContent {\n\ttype: \"text\";\n\ttext: string;\n}\n\nexport interface MCPCallToolImageContent {\n\ttype: \"image\";\n\tdata: string;\n\tmimeType: string;\n}\n\nexport type MCPCallToolContent = MCPCallToolTextContent | MCPCallToolImageContent;\n"]}
@@ -93,6 +93,11 @@ export interface Settings {
93
93
  sessionDir?: string;
94
94
  sessionRetentionDays?: number;
95
95
  httpIdleTimeoutMs?: number;
96
+ mcpServers?: Record<string, {
97
+ command: string;
98
+ args?: string[];
99
+ env?: Record<string, string>;
100
+ }>;
96
101
  }
97
102
  export type SettingsScope = "global" | "project";
98
103
  export interface SettingsStorage {
@@ -261,5 +266,10 @@ export declare class SettingsManager {
261
266
  getCodeBlockIndent(): string;
262
267
  getWarnings(): WarningSettings;
263
268
  setWarnings(warnings: WarningSettings): void;
269
+ getMcpServers(): Record<string, {
270
+ command: string;
271
+ args?: string[];
272
+ env?: Record<string, string>;
273
+ }> | undefined;
264
274
  }
265
275
  //# sourceMappingURL=settings-manager.d.ts.map