@spences10/pi-mcp 0.0.1

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Scott Spence
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # @spences10/pi-mcp
2
+
3
+ [![built with vite+](https://img.shields.io/badge/built%20with-Vite+-646CFF?logo=vite&logoColor=white)](https://viteplus.dev)
4
+ [![tested with vitest](https://img.shields.io/badge/tested%20with-Vitest-6E9F18?logo=vitest&logoColor=white)](https://vitest.dev)
5
+
6
+ Pi extension for connecting MCP servers and exposing their tools
7
+ inside Pi.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pi install npm:@spences10/pi-mcp
13
+ ```
14
+
15
+ Local development from this monorepo:
16
+
17
+ ```bash
18
+ pnpm --filter @spences10/pi-mcp run build
19
+ pi install ./packages/pi-mcp
20
+ # or for one run only
21
+ pi -e ./packages/pi-mcp
22
+ ```
23
+
24
+ ## Configuration
25
+
26
+ The extension loads MCP server definitions from `mcp.json` files in
27
+ global and project locations.
28
+
29
+ A typical project `mcp.json` looks like:
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "sqlite": {
35
+ "command": "npx",
36
+ "args": ["-y", "mcp-sqlite-tools", "./data.db"]
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ Server tools are registered as Pi tools using this naming format:
43
+
44
+ ```text
45
+ mcp__<server>__<tool>
46
+ ```
47
+
48
+ For example, a `sqlite` server tool named `execute_read_query`
49
+ becomes:
50
+
51
+ ```text
52
+ mcp__sqlite__execute_read_query
53
+ ```
54
+
55
+ ## Commands
56
+
57
+ ```text
58
+ /mcp list
59
+ /mcp enable <server>
60
+ /mcp disable <server>
61
+ ```
62
+
63
+ Use `/mcp list` to inspect connection state and `/mcp enable` or
64
+ `/mcp disable` to toggle a server's registered tools during a session.
65
+
66
+ ## What it does
67
+
68
+ - reads MCP server config
69
+ - connects to stdio or HTTP MCP servers
70
+ - performs the MCP `initialize` handshake
71
+ - discovers tools via `tools/list`
72
+ - registers each discovered MCP tool with Pi
73
+ - forwards model tool calls to the MCP server
74
+ - cleans up server processes on session shutdown
75
+
76
+ ## Using from a custom harness
77
+
78
+ ```ts
79
+ import mcp from '@spences10/pi-mcp';
80
+
81
+ // pass `mcp` as an ExtensionFactory to your Pi runtime
82
+ ```
83
+
84
+ `my-pi` imports this package directly and enables it as the built-in
85
+ MCP extension.
86
+
87
+ ## Development
88
+
89
+ ```bash
90
+ pnpm --filter @spences10/pi-mcp run check
91
+ pnpm --filter @spences10/pi-mcp run test
92
+ pnpm --filter @spences10/pi-mcp run build
93
+ ```
94
+
95
+ ## License
96
+
97
+ MIT
@@ -0,0 +1,27 @@
1
+ export interface McpStdioServerConfig {
2
+ name: string;
3
+ transport: 'stdio';
4
+ command: string;
5
+ args?: string[];
6
+ env?: Record<string, string>;
7
+ }
8
+ export interface McpHttpServerConfig {
9
+ name: string;
10
+ transport: 'http';
11
+ url: string;
12
+ headers?: Record<string, string>;
13
+ }
14
+ export type McpServerConfig = McpStdioServerConfig | McpHttpServerConfig;
15
+ export interface McpToolInfo {
16
+ name: string;
17
+ description?: string;
18
+ inputSchema?: Record<string, unknown>;
19
+ }
20
+ export declare class McpClient {
21
+ #private;
22
+ constructor(config: McpServerConfig);
23
+ connect(): Promise<void>;
24
+ listTools(): Promise<McpToolInfo[]>;
25
+ callTool(name: string, args: Record<string, unknown>): Promise<unknown>;
26
+ disconnect(): Promise<void>;
27
+ }
package/dist/client.js ADDED
@@ -0,0 +1,227 @@
1
+ import { spawn } from 'node:child_process';
2
+ export class McpClient {
3
+ #proc = null;
4
+ #config;
5
+ #nextId = 1;
6
+ #pending = new Map();
7
+ #buffer = '';
8
+ #sessionId;
9
+ constructor(config) {
10
+ this.#config = config;
11
+ }
12
+ async connect() {
13
+ if (this.#config.transport === 'stdio') {
14
+ await this.#connect_stdio();
15
+ }
16
+ await this.#request('initialize', {
17
+ protocolVersion: '2024-11-05',
18
+ capabilities: {},
19
+ clientInfo: { name: 'my-pi', version: '0.0.1' },
20
+ });
21
+ await this.#send({
22
+ jsonrpc: '2.0',
23
+ method: 'notifications/initialized',
24
+ });
25
+ }
26
+ async listTools() {
27
+ const result = (await this.#request('tools/list', {}));
28
+ return result.tools;
29
+ }
30
+ async callTool(name, args) {
31
+ return this.#request('tools/call', {
32
+ name,
33
+ arguments: args,
34
+ });
35
+ }
36
+ async disconnect() {
37
+ if (this.#config.transport === 'http') {
38
+ await this.#disconnect_http();
39
+ }
40
+ if (this.#proc) {
41
+ this.#proc.kill();
42
+ this.#proc = null;
43
+ }
44
+ this.#pending.clear();
45
+ }
46
+ async #connect_stdio() {
47
+ const { command, args = [], env, } = this.#config;
48
+ this.#proc = spawn(command, args, {
49
+ stdio: ['pipe', 'pipe', 'pipe'],
50
+ env: { ...process.env, ...env },
51
+ });
52
+ this.#proc.stdout.setEncoding('utf8');
53
+ this.#proc.stdout.on('data', (chunk) => {
54
+ this.#buffer += chunk;
55
+ const lines = this.#buffer.split('\n');
56
+ this.#buffer = lines.pop() || '';
57
+ for (const line of lines) {
58
+ if (!line.trim())
59
+ continue;
60
+ try {
61
+ this.#handle_message(JSON.parse(line));
62
+ }
63
+ catch {
64
+ // ignore non-JSON lines
65
+ }
66
+ }
67
+ });
68
+ }
69
+ #request(method, params) {
70
+ return new Promise((resolve, reject) => {
71
+ const id = this.#nextId++;
72
+ this.#pending.set(id, { resolve, reject });
73
+ this.#send({ jsonrpc: '2.0', id, method, params }).catch((error) => {
74
+ if (this.#pending.has(id)) {
75
+ this.#pending.delete(id);
76
+ reject(error);
77
+ }
78
+ });
79
+ setTimeout(() => {
80
+ if (this.#pending.has(id)) {
81
+ this.#pending.delete(id);
82
+ reject(new Error(`MCP request ${method} timed out`));
83
+ }
84
+ }, 30_000);
85
+ });
86
+ }
87
+ async #send(msg) {
88
+ if (this.#config.transport === 'http') {
89
+ await this.#send_http(msg);
90
+ return;
91
+ }
92
+ if (!this.#proc?.stdin?.writable) {
93
+ throw new Error('MCP server not connected');
94
+ }
95
+ this.#proc.stdin.write(JSON.stringify(msg) + '\n');
96
+ }
97
+ async #send_http(msg) {
98
+ const config = this.#config;
99
+ const headers = new Headers(config.headers ?? {});
100
+ headers.set('content-type', 'application/json');
101
+ headers.set('accept', 'application/json, text/event-stream');
102
+ if (this.#sessionId) {
103
+ headers.set('mcp-session-id', this.#sessionId);
104
+ }
105
+ const response = await fetch(config.url, {
106
+ method: 'POST',
107
+ headers,
108
+ body: JSON.stringify(msg),
109
+ });
110
+ const sessionId = response.headers.get('mcp-session-id');
111
+ if (sessionId) {
112
+ this.#sessionId = sessionId;
113
+ }
114
+ if (!response.ok) {
115
+ const body = await response.text().catch(() => '');
116
+ throw new Error(`MCP HTTP ${response.status}${body ? `: ${body}` : ''}`);
117
+ }
118
+ if (response.status === 204)
119
+ return;
120
+ const contentType = response.headers.get('content-type') ?? '';
121
+ if (contentType.includes('text/event-stream')) {
122
+ await this.#consume_sse_response(response, config.name);
123
+ return;
124
+ }
125
+ const body = await response.text();
126
+ if (!body.trim())
127
+ return;
128
+ let parsed;
129
+ try {
130
+ parsed = JSON.parse(body);
131
+ }
132
+ catch {
133
+ throw new Error(`Invalid MCP HTTP response from ${config.name}: ${body.slice(0, 200)}`);
134
+ }
135
+ this.#dispatch_message(parsed);
136
+ }
137
+ async #disconnect_http() {
138
+ const config = this.#config;
139
+ if (!this.#sessionId)
140
+ return;
141
+ const headers = new Headers(config.headers ?? {});
142
+ headers.set('mcp-session-id', this.#sessionId);
143
+ const response = await fetch(config.url, {
144
+ method: 'DELETE',
145
+ headers,
146
+ });
147
+ if (response.status !== 405 && !response.ok) {
148
+ const body = await response.text().catch(() => '');
149
+ throw new Error(`MCP HTTP disconnect ${response.status}${body ? `: ${body}` : ''}`);
150
+ }
151
+ this.#sessionId = undefined;
152
+ }
153
+ async #consume_sse_response(response, server_name) {
154
+ if (!response.body)
155
+ return;
156
+ const reader = response.body.getReader();
157
+ const decoder = new TextDecoder();
158
+ let buffer = '';
159
+ let event_lines = [];
160
+ const flush_event = () => {
161
+ if (event_lines.length === 0)
162
+ return;
163
+ const data_lines = event_lines
164
+ .filter((line) => line.startsWith('data:'))
165
+ .map((line) => line.slice(5).trimStart());
166
+ event_lines = [];
167
+ if (data_lines.length === 0)
168
+ return;
169
+ const payload = data_lines.join('\n').trim();
170
+ if (!payload)
171
+ return;
172
+ try {
173
+ this.#dispatch_message(JSON.parse(payload));
174
+ }
175
+ catch {
176
+ throw new Error(`Invalid MCP SSE payload from ${server_name}: ${payload.slice(0, 200)}`);
177
+ }
178
+ };
179
+ while (true) {
180
+ const { done, value } = await reader.read();
181
+ buffer += decoder.decode(value ?? new Uint8Array(), {
182
+ stream: !done,
183
+ });
184
+ const normalized = buffer.replace(/\r\n/g, '\n');
185
+ const lines = normalized.split('\n');
186
+ buffer = lines.pop() ?? '';
187
+ for (const line of lines) {
188
+ if (line === '') {
189
+ flush_event();
190
+ continue;
191
+ }
192
+ if (line.startsWith(':'))
193
+ continue;
194
+ event_lines.push(line);
195
+ }
196
+ if (done)
197
+ break;
198
+ }
199
+ if (buffer.trim()) {
200
+ event_lines.push(buffer.trim());
201
+ }
202
+ flush_event();
203
+ }
204
+ #dispatch_message(message) {
205
+ if (Array.isArray(message)) {
206
+ for (const item of message) {
207
+ this.#dispatch_message(item);
208
+ }
209
+ return;
210
+ }
211
+ if (!message || typeof message !== 'object')
212
+ return;
213
+ this.#handle_message(message);
214
+ }
215
+ #handle_message(msg) {
216
+ if (msg.id == null || !this.#pending.has(msg.id))
217
+ return;
218
+ const pending = this.#pending.get(msg.id);
219
+ this.#pending.delete(msg.id);
220
+ if (msg.error) {
221
+ pending.reject(new Error(`MCP error ${msg.error.code}: ${msg.error.message}`));
222
+ return;
223
+ }
224
+ pending.resolve(msg.result);
225
+ }
226
+ }
227
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServerConfig } from './client.js';
2
+ export declare function load_mcp_config(cwd: string): McpServerConfig[];
package/dist/config.js ADDED
@@ -0,0 +1,73 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ function is_string_record(value, label, name) {
5
+ if (value === undefined)
6
+ return true;
7
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
8
+ throw new Error(`Invalid MCP server "${name}": ${label} must be an object of string values`);
9
+ }
10
+ for (const [key, entry] of Object.entries(value)) {
11
+ if (typeof entry !== 'string') {
12
+ throw new Error(`Invalid MCP server "${name}": ${label}.${key} must be a string`);
13
+ }
14
+ }
15
+ return true;
16
+ }
17
+ function parse_server(name, entry) {
18
+ const type = typeof entry.type === 'string'
19
+ ? entry.type.trim().toLowerCase()
20
+ : '';
21
+ if (type && !['stdio', 'http', 'streamable-http'].includes(type)) {
22
+ throw new Error(`Invalid MCP server "${name}": unsupported transport type "${type}"`);
23
+ }
24
+ if (type === 'http' ||
25
+ type === 'streamable-http' ||
26
+ entry.url !== undefined) {
27
+ if (typeof entry.url !== 'string' || !entry.url.trim()) {
28
+ throw new Error(`Invalid MCP server "${name}": http transport requires a url`);
29
+ }
30
+ is_string_record(entry.headers, 'headers', name);
31
+ const headers = entry.headers;
32
+ const config = {
33
+ name,
34
+ transport: 'http',
35
+ url: entry.url.trim(),
36
+ ...(headers ? { headers } : {}),
37
+ };
38
+ return config;
39
+ }
40
+ if (typeof entry.command !== 'string' || !entry.command.trim()) {
41
+ throw new Error(`Invalid MCP server "${name}": stdio transport requires a command`);
42
+ }
43
+ if (entry.args !== undefined &&
44
+ (!Array.isArray(entry.args) ||
45
+ entry.args.some((value) => typeof value !== 'string'))) {
46
+ throw new Error(`Invalid MCP server "${name}": args must be an array of strings`);
47
+ }
48
+ is_string_record(entry.env, 'env', name);
49
+ const args = entry.args;
50
+ const env = entry.env;
51
+ const config = {
52
+ name,
53
+ transport: 'stdio',
54
+ command: entry.command.trim(),
55
+ ...(args ? { args } : {}),
56
+ ...(env ? { env } : {}),
57
+ };
58
+ return config;
59
+ }
60
+ function read_config(path) {
61
+ if (!existsSync(path))
62
+ return {};
63
+ const raw = readFileSync(path, 'utf-8');
64
+ const config = JSON.parse(raw);
65
+ return config.mcpServers || {};
66
+ }
67
+ export function load_mcp_config(cwd) {
68
+ const global_servers = read_config(join(homedir(), '.pi', 'agent', 'mcp.json'));
69
+ const project_servers = read_config(join(cwd, 'mcp.json'));
70
+ const merged = { ...global_servers, ...project_servers };
71
+ return Object.entries(merged).map(([name, server]) => parse_server(name, server));
72
+ }
73
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type BeforeAgentStartEvent, type ExtensionAPI } from '@mariozechner/pi-coding-agent';
2
+ export declare function should_wait_for_mcp_connections(event: Pick<BeforeAgentStartEvent, 'systemPromptOptions'>): boolean;
3
+ export default function mcp(pi: ExtensionAPI): Promise<void>;
package/dist/index.js ADDED
@@ -0,0 +1,301 @@
1
+ import { defineTool, } from '@mariozechner/pi-coding-agent';
2
+ import { McpClient } from './client.js';
3
+ import { load_mcp_config } from './config.js';
4
+ function create_server_states(configs) {
5
+ return new Map(configs.map((config) => [
6
+ config.name,
7
+ {
8
+ config,
9
+ tool_names: [],
10
+ enabled: true,
11
+ status: 'disconnected',
12
+ },
13
+ ]));
14
+ }
15
+ function remove_server_tools_from_active(pi, tool_names) {
16
+ const tool_set = new Set(tool_names);
17
+ pi.setActiveTools(pi.getActiveTools().filter((tool) => !tool_set.has(tool)));
18
+ }
19
+ function format_server_status(state) {
20
+ switch (state.status) {
21
+ case 'connected':
22
+ return state.enabled ? 'enabled' : 'disabled';
23
+ case 'connecting':
24
+ return state.enabled ? 'connecting' : 'connecting, disabled';
25
+ case 'failed':
26
+ return state.enabled ? 'failed' : 'failed, disabled';
27
+ default:
28
+ return state.enabled ? 'not connected yet' : 'disabled';
29
+ }
30
+ }
31
+ function count_pending_enabled_servers(servers) {
32
+ return Array.from(servers.values()).filter((state) => state.enabled && state.status !== 'connected').length;
33
+ }
34
+ function report_mcp_failure(state, ctx) {
35
+ const message = `MCP server failed (${state.config.name}): ${state.error}`;
36
+ if (ctx?.hasUI) {
37
+ ctx.ui.notify(message, 'warning');
38
+ return;
39
+ }
40
+ console.error(message);
41
+ }
42
+ function update_mcp_status(ctx, servers) {
43
+ if (!ctx.hasUI)
44
+ return;
45
+ if (servers.size === 0) {
46
+ ctx.ui.setStatus('mcp', undefined);
47
+ return;
48
+ }
49
+ const states = Array.from(servers.values());
50
+ const enabled = states.filter((state) => state.enabled).length;
51
+ const connected = states.filter((state) => state.enabled && state.status === 'connected').length;
52
+ const connecting = states.filter((state) => state.enabled && state.status === 'connecting').length;
53
+ const failed = states.filter((state) => state.enabled && state.status === 'failed').length;
54
+ const fragments = [`MCP ${connected}/${enabled} connected`];
55
+ if (connecting > 0)
56
+ fragments.push(`${connecting} connecting`);
57
+ if (failed > 0)
58
+ fragments.push(`${failed} failed`);
59
+ ctx.ui.setStatus('mcp', ctx.ui.theme.fg('dim', fragments.join(' · ')));
60
+ }
61
+ function set_connect_feedback(ctx, pending_server_count) {
62
+ if (!ctx.hasUI) {
63
+ return () => { };
64
+ }
65
+ const label = pending_server_count === 1
66
+ ? 'Connecting 1 MCP server...'
67
+ : `Connecting ${pending_server_count} MCP servers...`;
68
+ ctx.ui.setWorkingMessage(label);
69
+ ctx.ui.setWorkingIndicator({
70
+ frames: [
71
+ ctx.ui.theme.fg('dim', '·'),
72
+ ctx.ui.theme.fg('muted', '•'),
73
+ ctx.ui.theme.fg('accent', '●'),
74
+ ctx.ui.theme.fg('muted', '•'),
75
+ ],
76
+ intervalMs: 120,
77
+ });
78
+ ctx.ui.setStatus('mcp', ctx.ui.theme.fg('dim', label));
79
+ return () => {
80
+ ctx.ui.setWorkingMessage();
81
+ ctx.ui.setWorkingIndicator();
82
+ };
83
+ }
84
+ export function should_wait_for_mcp_connections(event) {
85
+ const selected_tools = event.systemPromptOptions?.selectedTools;
86
+ return (!selected_tools ||
87
+ selected_tools.some((tool) => tool.startsWith('mcp__')));
88
+ }
89
+ // Default export for Pi Package / additionalExtensionPaths loading
90
+ export default async function mcp(pi) {
91
+ let initialized_cwd = null;
92
+ let servers = new Map();
93
+ const registered_tool_names = new Set();
94
+ const ensure_servers = (cwd) => {
95
+ if (initialized_cwd !== null)
96
+ return;
97
+ servers = create_server_states(load_mcp_config(cwd));
98
+ initialized_cwd = cwd;
99
+ };
100
+ const connect_server = async (state, ctx) => {
101
+ if (state.status === 'connected')
102
+ return;
103
+ if (state.connect_promise) {
104
+ await state.connect_promise;
105
+ return;
106
+ }
107
+ state.connect_promise = (async () => {
108
+ state.status = 'connecting';
109
+ state.error = undefined;
110
+ if (ctx)
111
+ update_mcp_status(ctx, servers);
112
+ const client = new McpClient(state.config);
113
+ try {
114
+ await client.connect();
115
+ state.client = client;
116
+ const mcp_tools = await client.listTools();
117
+ const tool_names = [];
118
+ for (const mcp_tool of mcp_tools) {
119
+ const tool_name = `mcp__${state.config.name}__${mcp_tool.name}`;
120
+ tool_names.push(tool_name);
121
+ if (registered_tool_names.has(tool_name))
122
+ continue;
123
+ registered_tool_names.add(tool_name);
124
+ pi.registerTool(defineTool({
125
+ name: tool_name,
126
+ label: `${state.config.name}: ${mcp_tool.name}`,
127
+ description: mcp_tool.description || mcp_tool.name,
128
+ parameters: (mcp_tool.inputSchema || {
129
+ type: 'object',
130
+ properties: {},
131
+ }),
132
+ execute: async (_id, params) => {
133
+ const result = (await state.client.callTool(mcp_tool.name, params));
134
+ const text = result?.content
135
+ ?.map((c) => c.text || '')
136
+ .join('\n') || JSON.stringify(result);
137
+ return {
138
+ content: [{ type: 'text', text }],
139
+ details: {},
140
+ };
141
+ },
142
+ }));
143
+ }
144
+ state.tool_names = tool_names;
145
+ state.status = 'connected';
146
+ if (!state.enabled) {
147
+ remove_server_tools_from_active(pi, state.tool_names);
148
+ }
149
+ }
150
+ catch (error) {
151
+ state.status = 'failed';
152
+ state.error =
153
+ error instanceof Error ? error.message : String(error);
154
+ state.client = undefined;
155
+ await client.disconnect().catch(() => { });
156
+ report_mcp_failure(state, ctx);
157
+ throw error;
158
+ }
159
+ finally {
160
+ state.connect_promise = undefined;
161
+ if (ctx)
162
+ update_mcp_status(ctx, servers);
163
+ }
164
+ })();
165
+ await state.connect_promise;
166
+ };
167
+ const connect_all_servers = async (options = {}) => {
168
+ await Promise.allSettled(Array.from(servers.values())
169
+ .filter((state) => state.enabled)
170
+ .filter((state) => options.include_failed || state.status !== 'failed')
171
+ .map((state) => connect_server(state, options.ctx)));
172
+ if (options.ctx)
173
+ update_mcp_status(options.ctx, servers);
174
+ };
175
+ pi.on('session_start', async (_event, ctx) => {
176
+ ensure_servers(ctx.cwd);
177
+ update_mcp_status(ctx, servers);
178
+ void connect_all_servers({ ctx });
179
+ });
180
+ pi.on('before_agent_start', async (event, ctx) => {
181
+ ensure_servers(ctx.cwd);
182
+ if (!should_wait_for_mcp_connections(event)) {
183
+ void connect_all_servers({ ctx });
184
+ return event;
185
+ }
186
+ const pending_server_count = count_pending_enabled_servers(servers);
187
+ if (pending_server_count === 0) {
188
+ update_mcp_status(ctx, servers);
189
+ return event;
190
+ }
191
+ const restore_feedback = set_connect_feedback(ctx, pending_server_count);
192
+ try {
193
+ await connect_all_servers({ ctx });
194
+ return event;
195
+ }
196
+ finally {
197
+ restore_feedback();
198
+ update_mcp_status(ctx, servers);
199
+ }
200
+ });
201
+ pi.registerCommand('mcp', {
202
+ description: 'Manage MCP servers (list, enable, disable)',
203
+ getArgumentCompletions: (prefix) => {
204
+ const parts = prefix.split(' ');
205
+ if (parts.length <= 1) {
206
+ return ['list', 'enable', 'disable']
207
+ .filter((s) => s.startsWith(prefix))
208
+ .map((s) => ({ value: s, label: s }));
209
+ }
210
+ if (parts[0] === 'enable' || parts[0] === 'disable') {
211
+ const name_prefix = parts[1] || '';
212
+ return Array.from(servers.keys())
213
+ .filter((n) => n.startsWith(name_prefix))
214
+ .map((n) => ({
215
+ value: `${parts[0]} ${n}`,
216
+ label: n,
217
+ }));
218
+ }
219
+ return null;
220
+ },
221
+ handler: async (args, ctx) => {
222
+ ensure_servers(ctx.cwd);
223
+ const [sub, ...rest] = args.trim().split(/\s+/);
224
+ const name = rest.join(' ');
225
+ switch (sub || 'list') {
226
+ case 'list': {
227
+ if (servers.size === 0) {
228
+ ctx.ui.notify('No MCP servers configured');
229
+ return;
230
+ }
231
+ const lines = [];
232
+ for (const [sname, state] of servers.entries()) {
233
+ lines.push(`${sname} (${format_server_status(state)}) — ${state.tool_names.length} tools${state.error ? ` — ${state.error}` : ''}`);
234
+ }
235
+ update_mcp_status(ctx, servers);
236
+ ctx.ui.notify(lines.join('\n'));
237
+ break;
238
+ }
239
+ case 'enable': {
240
+ const server = servers.get(name);
241
+ if (!server) {
242
+ ctx.ui.notify(`Unknown server: ${name}`, 'warning');
243
+ return;
244
+ }
245
+ if (server.enabled && server.status !== 'failed') {
246
+ ctx.ui.notify(`${name} already enabled`);
247
+ return;
248
+ }
249
+ server.enabled = true;
250
+ if (server.status === 'connected') {
251
+ const active = pi.getActiveTools();
252
+ pi.setActiveTools([
253
+ ...new Set([...active, ...server.tool_names]),
254
+ ]);
255
+ update_mcp_status(ctx, servers);
256
+ ctx.ui.notify(`Enabled ${name}`);
257
+ return;
258
+ }
259
+ if (server.status === 'failed') {
260
+ server.status = 'disconnected';
261
+ server.error = undefined;
262
+ }
263
+ update_mcp_status(ctx, servers);
264
+ void connect_server(server, ctx);
265
+ ctx.ui.notify(`Enabling ${name} and connecting in background`);
266
+ break;
267
+ }
268
+ case 'disable': {
269
+ const server = servers.get(name);
270
+ if (!server) {
271
+ ctx.ui.notify(`Unknown server: ${name}`, 'warning');
272
+ return;
273
+ }
274
+ if (!server.enabled) {
275
+ ctx.ui.notify(`${name} already disabled`);
276
+ return;
277
+ }
278
+ server.enabled = false;
279
+ remove_server_tools_from_active(pi, server.tool_names);
280
+ update_mcp_status(ctx, servers);
281
+ ctx.ui.notify(`Disabled ${name}`);
282
+ break;
283
+ }
284
+ default:
285
+ ctx.ui.notify(`Unknown subcommand: ${sub}. Use list, enable, or disable.`, 'warning');
286
+ }
287
+ },
288
+ });
289
+ pi.on('session_shutdown', async (_event, ctx) => {
290
+ await Promise.allSettled(Array.from(servers.values()).map(async (server) => {
291
+ await server.connect_promise?.catch(() => { });
292
+ await server.client?.disconnect();
293
+ server.client = undefined;
294
+ if (server.status !== 'failed') {
295
+ server.status = 'disconnected';
296
+ }
297
+ }));
298
+ ctx.ui.setStatus('mcp', undefined);
299
+ });
300
+ }
301
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,UAAU,GACV,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,SAAS,EAAwB,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAY9C,SAAS,oBAAoB,CAC5B,OAA0B;IAE1B,OAAO,IAAI,GAAG,CACb,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI;QACX;YACC,MAAM;YACN,UAAU,EAAE,EAAE;YACd,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,cAAuB;SAC/B;KACD,CAAC,CACF,CAAC;AACH,CAAC;AAED,SAAS,+BAA+B,CACvC,EAAgB,EAChB,UAAoB;IAEpB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IACrC,EAAE,CAAC,cAAc,CAChB,EAAE,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CACzD,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAkB;IAC/C,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,WAAW;YACf,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC;QAC/C,KAAK,YAAY;YAChB,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,sBAAsB,CAAC;QAC9D,KAAK,QAAQ;YACZ,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC;QACtD;YACC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,UAAU,CAAC;IAC1D,CAAC;AACF,CAAC;AAED,SAAS,6BAA6B,CACrC,OAAyC;IAEzC,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CACzC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,CACxD,CAAC,MAAM,CAAC;AACV,CAAC;AAED,SAAS,kBAAkB,CAC1B,KAAkB,EAClB,GAAsB;IAEtB,MAAM,OAAO,GAAG,sBAAsB,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;IAC3E,IAAI,GAAG,EAAE,KAAK,EAAE,CAAC;QAChB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAClC,OAAO;IACR,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,iBAAiB,CACzB,GAAqB,EACrB,OAAyC;IAEzC,IAAI,CAAC,GAAG,CAAC,KAAK;QAAE,OAAO;IACvB,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACxB,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACnC,OAAO;IACR,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAC9B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,CACxD,CAAC,MAAM,CAAC;IACT,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAC/B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,YAAY,CACzD,CAAC,MAAM,CAAC;IACT,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAC3B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,CACrD,CAAC,MAAM,CAAC;IAET,MAAM,SAAS,GAAG,CAAC,OAAO,SAAS,IAAI,OAAO,YAAY,CAAC,CAAC;IAC5D,IAAI,UAAU,GAAG,CAAC;QAAE,SAAS,CAAC,IAAI,CAAC,GAAG,UAAU,aAAa,CAAC,CAAC;IAC/D,IAAI,MAAM,GAAG,CAAC;QAAE,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC;IAEnD,GAAG,CAAC,EAAE,CAAC,SAAS,CACf,KAAK,EACL,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAC7C,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAC5B,GAAqB,EACrB,oBAA4B;IAE5B,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,KAAK,GACV,oBAAoB,KAAK,CAAC;QACzB,CAAC,CAAC,4BAA4B;QAC9B,CAAC,CAAC,cAAc,oBAAoB,iBAAiB,CAAC;IAExD,GAAG,CAAC,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAChC,GAAG,CAAC,EAAE,CAAC,mBAAmB,CAAC;QAC1B,MAAM,EAAE;YACP,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC;YAC3B,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC;YAC7B,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC;YAC9B,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC;SAC7B;QACD,UAAU,EAAE,GAAG;KACf,CAAC,CAAC;IACH,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAEvD,OAAO,GAAG,EAAE;QACX,GAAG,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAC3B,GAAG,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC;IAC9B,CAAC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC9C,KAAyD;IAEzD,MAAM,cAAc,GAAG,KAAK,CAAC,mBAAmB,EAAE,aAAa,CAAC;IAChE,OAAO,CACN,CAAC,cAAc;QACf,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CACvD,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,GAAG,CAAC,EAAgB;IACjD,IAAI,eAAe,GAAkB,IAAI,CAAC;IAC1C,IAAI,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC7C,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAC;IAEhD,MAAM,cAAc,GAAG,CAAC,GAAW,EAAQ,EAAE;QAC5C,IAAI,eAAe,KAAK,IAAI;YAAE,OAAO;QACrC,OAAO,GAAG,oBAAoB,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;QACrD,eAAe,GAAG,GAAG,CAAC;IACvB,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,KAAK,EAC3B,KAAkB,EAClB,GAAsB,EACN,EAAE;QAClB,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW;YAAE,OAAO;QACzC,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;YAC3B,MAAM,KAAK,CAAC,eAAe,CAAC;YAC5B,OAAO;QACR,CAAC;QAED,KAAK,CAAC,eAAe,GAAG,CAAC,KAAK,IAAI,EAAE;YACnC,KAAK,CAAC,MAAM,GAAG,YAAY,CAAC;YAC5B,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;YACxB,IAAI,GAAG;gBAAE,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAEzC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,CAAC;gBACJ,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;gBACvB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;gBAEtB,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;gBAC3C,MAAM,UAAU,GAAa,EAAE,CAAC;gBAEhC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;oBAClC,MAAM,SAAS,GAAG,QAAQ,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;oBAChE,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBAE3B,IAAI,qBAAqB,CAAC,GAAG,CAAC,SAAS,CAAC;wBAAE,SAAS;oBACnD,qBAAqB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;oBAErC,EAAE,CAAC,YAAY,CACd,UAAU,CAAC;wBACV,IAAI,EAAE,SAAS;wBACf,KAAK,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,EAAE;wBAC/C,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,IAAI;wBAClD,UAAU,EAAE,CAAC,QAAQ,CAAC,WAAW,IAAI;4BACpC,IAAI,EAAE,QAAQ;4BACd,UAAU,EAAE,EAAE;yBACd,CAAmD;wBACpD,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE;4BAC9B,MAAM,MAAM,GAAG,CAAC,MAAM,KAAK,CAAC,MAAO,CAAC,QAAQ,CAC3C,QAAQ,CAAC,IAAI,EACb,MAAiC,CACjC,CAKA,CAAC;4BAEF,MAAM,IAAI,GACT,MAAM,EAAE,OAAO;gCACd,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;iCACzB,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;4BAExC,OAAO;gCACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;gCAC1C,OAAO,EAAE,EAAE;6BACX,CAAC;wBACH,CAAC;qBACD,CAAC,CACF,CAAC;gBACH,CAAC;gBAED,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC;gBAC9B,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;oBACpB,+BAA+B,CAAC,EAAE,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;gBACvD,CAAC;YACF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC;gBACxB,KAAK,CAAC,KAAK;oBACV,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACxD,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;gBACzB,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBAC1C,kBAAkB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC/B,MAAM,KAAK,CAAC;YACb,CAAC;oBAAS,CAAC;gBACV,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC;gBAClC,IAAI,GAAG;oBAAE,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAC1C,CAAC;QACF,CAAC,CAAC,EAAE,CAAC;QAEL,MAAM,KAAK,CAAC,eAAe,CAAC;IAC7B,CAAC,CAAC;IAEF,MAAM,mBAAmB,GAAG,KAAK,EAChC,UAGI,EAAE,EACU,EAAE;QAClB,MAAM,OAAO,CAAC,UAAU,CACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;aAC1B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;aAChC,MAAM,CACN,CAAC,KAAK,EAAE,EAAE,CACT,OAAO,CAAC,cAAc,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,CACpD;aACA,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CACpD,CAAC;QACF,IAAI,OAAO,CAAC,GAAG;YAAE,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC1D,CAAC,CAAC;IAEF,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QAC5C,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxB,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,KAAK,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,oBAAoB,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAChD,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,+BAA+B,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7C,KAAK,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;YAClC,OAAO,KAAK,CAAC;QACd,CAAC;QAED,MAAM,oBAAoB,GACzB,6BAA6B,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,oBAAoB,KAAK,CAAC,EAAE,CAAC;YAChC,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAChC,OAAO,KAAK,CAAC;QACd,CAAC;QAED,MAAM,gBAAgB,GAAG,oBAAoB,CAC5C,GAAG,EACH,oBAAoB,CACpB,CAAC;QACF,IAAI,CAAC;YACJ,MAAM,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;YACnC,OAAO,KAAK,CAAC;QACd,CAAC;gBAAS,CAAC;YACV,gBAAgB,EAAE,CAAC;YACnB,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE;QACzB,WAAW,EAAE,4CAA4C;QACzD,sBAAsB,EAAE,CAAC,MAAM,EAAE,EAAE;YAClC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC;qBAClC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;qBACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACxC,CAAC;YACD,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;gBACrD,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACnC,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;qBAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;qBACxC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACZ,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;oBACzB,KAAK,EAAE,CAAC;iBACR,CAAC,CAAC,CAAC;YACN,CAAC;YACD,OAAO,IAAI,CAAC;QACb,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;YAC5B,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACxB,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAE5B,QAAQ,GAAG,IAAI,MAAM,EAAE,CAAC;gBACvB,KAAK,MAAM,CAAC,CAAC,CAAC;oBACb,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;wBACxB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC;wBAC3C,OAAO;oBACR,CAAC;oBACD,MAAM,KAAK,GAAa,EAAE,CAAC;oBAC3B,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;wBAChD,KAAK,CAAC,IAAI,CACT,GAAG,KAAK,KAAK,oBAAoB,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,UAAU,CAAC,MAAM,SAAS,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACvH,CAAC;oBACH,CAAC;oBACD,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;oBAChC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;oBAChC,MAAM;gBACP,CAAC;gBACD,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACf,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBACjC,IAAI,CAAC,MAAM,EAAE,CAAC;wBACb,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,mBAAmB,IAAI,EAAE,EAAE,SAAS,CAAC,CAAC;wBACpD,OAAO;oBACR,CAAC;oBACD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;wBAClD,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,IAAI,kBAAkB,CAAC,CAAC;wBACzC,OAAO;oBACR,CAAC;oBACD,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;oBACtB,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;wBACnC,MAAM,MAAM,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC;wBACnC,EAAE,CAAC,cAAc,CAAC;4BACjB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;yBAC7C,CAAC,CAAC;wBACH,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;wBAChC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;wBACjC,OAAO;oBACR,CAAC;oBACD,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;wBAChC,MAAM,CAAC,MAAM,GAAG,cAAc,CAAC;wBAC/B,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC;oBAC1B,CAAC;oBACD,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;oBAChC,KAAK,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;oBACjC,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,YAAY,IAAI,+BAA+B,CAC/C,CAAC;oBACF,MAAM;gBACP,CAAC;gBACD,KAAK,SAAS,CAAC,CAAC,CAAC;oBAChB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBACjC,IAAI,CAAC,MAAM,EAAE,CAAC;wBACb,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,mBAAmB,IAAI,EAAE,EAAE,SAAS,CAAC,CAAC;wBACpD,OAAO;oBACR,CAAC;oBACD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;wBACrB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,IAAI,mBAAmB,CAAC,CAAC;wBAC1C,OAAO;oBACR,CAAC;oBACD,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;oBACvB,+BAA+B,CAAC,EAAE,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;oBACvD,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;oBAChC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;oBAClC,MAAM;gBACP,CAAC;gBACD;oBACC,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,uBAAuB,GAAG,iCAAiC,EAC3D,SAAS,CACT,CAAC;YACJ,CAAC;QACF,CAAC;KACD,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QAC/C,MAAM,OAAO,CAAC,UAAU,CACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACjD,MAAM,MAAM,CAAC,eAAe,EAAE,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC9C,MAAM,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;YAClC,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC;YAC1B,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAChC,MAAM,CAAC,MAAM,GAAG,cAAc,CAAC;YAChC,CAAC;QACF,CAAC,CAAC,CACF,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@spences10/pi-mcp",
3
+ "version": "0.0.1",
4
+ "description": "Pi extension for connecting MCP servers and exposing their tools",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "pi",
9
+ "pi-package"
10
+ ],
11
+ "license": "MIT",
12
+ "author": "Scott Spence <me@scottspence.com>",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/spences10/my-pi.git",
16
+ "directory": "packages/pi-mcp"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "type": "module",
23
+ "main": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "default": "./dist/index.js"
29
+ }
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "dependencies": {
35
+ "@mariozechner/pi-coding-agent": "^0.70.2"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^25.6.0",
39
+ "typescript": "^5.9.3",
40
+ "vitest": "^4.1.5"
41
+ },
42
+ "engines": {
43
+ "node": ">=22.0.0"
44
+ },
45
+ "pi": {
46
+ "extensions": [
47
+ "./dist/index.js"
48
+ ]
49
+ },
50
+ "scripts": {
51
+ "build": "tsc -p tsconfig.build.json",
52
+ "check": "tsc --noEmit -p tsconfig.json",
53
+ "test": "vitest run"
54
+ }
55
+ }