@glows777/vela-mcp 0.0.0-stage → 0.5.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.
- package/CHANGELOG.md +263 -0
- package/LICENSE +21 -0
- package/README.md +4 -2
- package/dist/config.d.ts +79 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +226 -0
- package/dist/config.js.map +1 -0
- package/dist/connection.d.ts +61 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +248 -0
- package/dist/connection.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +200 -0
- package/dist/index.js.map +1 -0
- package/dist/tools.d.ts +40 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +167 -0
- package/dist/tools.js.map +1 -0
- package/package.json +38 -4
package/dist/config.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server configuration (like pi's `extensions/mcp/config.ts`): the `mcpServers` format of
|
|
3
|
+
* Claude Desktop / Claude Code, read from `~/.vela/mcp.json` and the trusted project's
|
|
4
|
+
* `.vela/mcp.json`. Invalid entries are reported and skipped; they don't stop other servers.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
const isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
9
|
+
const EXPOSURES = ['direct', 'deferred', 'hidden'];
|
|
10
|
+
/** Server names: letters, digits, `_` and `-` (like pi). */
|
|
11
|
+
const SERVER_NAME = /^[A-Za-z0-9_-]+$/;
|
|
12
|
+
const stringRecord = (value) => isPlainObject(value) &&
|
|
13
|
+
Object.values(value).every((item) => typeof item === 'string');
|
|
14
|
+
/** Validates one `mcpServers` entry; throws a message naming the problem. */
|
|
15
|
+
function parseServerConfig(name, raw) {
|
|
16
|
+
const fail = (message) => {
|
|
17
|
+
throw new Error(`MCP server "${name}": ${message}`);
|
|
18
|
+
};
|
|
19
|
+
if (!SERVER_NAME.test(name))
|
|
20
|
+
fail('names may contain only letters, digits, "_" and "-"');
|
|
21
|
+
if (!isPlainObject(raw))
|
|
22
|
+
return fail('must be an object');
|
|
23
|
+
const { type } = raw;
|
|
24
|
+
if (type === 'sse' || (type === undefined && raw.transport === 'sse'))
|
|
25
|
+
fail('the legacy SSE transport is not supported; use the streamable HTTP endpoint (often /mcp instead of /sse)');
|
|
26
|
+
if (type !== undefined &&
|
|
27
|
+
type !== 'stdio' &&
|
|
28
|
+
type !== 'http' &&
|
|
29
|
+
type !== 'streamable-http')
|
|
30
|
+
fail(`type must be "stdio", "http" or "streamable-http"`);
|
|
31
|
+
if (raw.timeout !== undefined) {
|
|
32
|
+
if (typeof raw.timeout !== 'number' || !(raw.timeout > 0))
|
|
33
|
+
fail('timeout must be a positive number of seconds');
|
|
34
|
+
}
|
|
35
|
+
if (raw.enabled !== undefined && typeof raw.enabled !== 'boolean')
|
|
36
|
+
fail('enabled must be true or false');
|
|
37
|
+
if (raw.description !== undefined && typeof raw.description !== 'string')
|
|
38
|
+
fail('description must be a string');
|
|
39
|
+
const exposure = (value, where) => {
|
|
40
|
+
if (value === 'codemode' || value === 'codemode-deferred')
|
|
41
|
+
fail(`${where} "${value}" is not available: Vela has no codemode yet. Use "deferred" (tool_search loads the tools) or "direct"`);
|
|
42
|
+
if (!EXPOSURES.includes(value))
|
|
43
|
+
fail(`${where} must be one of ${EXPOSURES.join(', ')}`);
|
|
44
|
+
};
|
|
45
|
+
if (raw.exposure !== undefined)
|
|
46
|
+
exposure(raw.exposure, 'exposure');
|
|
47
|
+
if (raw.toolExposure !== undefined) {
|
|
48
|
+
if (!isPlainObject(raw.toolExposure))
|
|
49
|
+
fail('toolExposure must be an object of tool name → exposure');
|
|
50
|
+
for (const [tool, value] of Object.entries(raw.toolExposure))
|
|
51
|
+
exposure(value, `toolExposure["${tool}"]`);
|
|
52
|
+
}
|
|
53
|
+
const isHttp = type === 'http' ||
|
|
54
|
+
type === 'streamable-http' ||
|
|
55
|
+
(type === undefined && raw.url !== undefined);
|
|
56
|
+
if (isHttp) {
|
|
57
|
+
if (typeof raw.url !== 'string' || !URL.canParse(raw.url))
|
|
58
|
+
fail('url must be a valid URL');
|
|
59
|
+
if (raw.headers !== undefined && !stringRecord(raw.headers))
|
|
60
|
+
fail('headers must be an object of strings');
|
|
61
|
+
if (raw.command !== undefined)
|
|
62
|
+
fail('set either command (stdio) or url (HTTP), not both');
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
if (typeof raw.command !== 'string' || raw.command.trim() === '')
|
|
66
|
+
fail('needs a command (stdio) or a url (HTTP)');
|
|
67
|
+
if (raw.args !== undefined &&
|
|
68
|
+
!(Array.isArray(raw.args) &&
|
|
69
|
+
raw.args.every((arg) => typeof arg === 'string')))
|
|
70
|
+
fail('args must be an array of strings');
|
|
71
|
+
if (raw.env !== undefined && !stringRecord(raw.env))
|
|
72
|
+
fail('env must be an object of strings');
|
|
73
|
+
if (raw.cwd !== undefined && typeof raw.cwd !== 'string')
|
|
74
|
+
fail('cwd must be a string');
|
|
75
|
+
}
|
|
76
|
+
return raw;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Validates `mcpServers`. Server names that differ only in `-` and `_` count as the same server
|
|
80
|
+
* (their tool names would be the same); the second one is an error.
|
|
81
|
+
*/
|
|
82
|
+
export function parseServers(servers, sources = {}) {
|
|
83
|
+
const entries = [];
|
|
84
|
+
const errors = [];
|
|
85
|
+
const keys = new Map();
|
|
86
|
+
for (const [name, raw] of Object.entries(servers)) {
|
|
87
|
+
try {
|
|
88
|
+
const config = parseServerConfig(name, raw);
|
|
89
|
+
const key = name.replaceAll('-', '_');
|
|
90
|
+
const clash = keys.get(key);
|
|
91
|
+
if (clash)
|
|
92
|
+
throw new Error(`MCP server "${name}": clashes with "${clash}" (names differing only in "-" and "_" are the same server)`);
|
|
93
|
+
keys.set(key, name);
|
|
94
|
+
entries.push({ name, config, source: sources[name] ?? 'options' });
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
errors.push(error instanceof Error ? error.message : String(error));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return { entries, errors };
|
|
101
|
+
}
|
|
102
|
+
/** The exposure of one of the server's tools: exact `toolExposure` names, then the first matching pattern, then the server's. */
|
|
103
|
+
export function toolExposureOf(config, tool) {
|
|
104
|
+
const overrides = config.toolExposure ?? {};
|
|
105
|
+
const exact = overrides[tool];
|
|
106
|
+
if (exact)
|
|
107
|
+
return exact;
|
|
108
|
+
for (const [pattern, exposure] of Object.entries(overrides)) {
|
|
109
|
+
if (!pattern.includes('*'))
|
|
110
|
+
continue;
|
|
111
|
+
const regex = new RegExp(`^${pattern
|
|
112
|
+
.split('*')
|
|
113
|
+
.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
114
|
+
.join('.*')}$`);
|
|
115
|
+
if (regex.test(tool))
|
|
116
|
+
return exposure;
|
|
117
|
+
}
|
|
118
|
+
return config.exposure ?? 'deferred';
|
|
119
|
+
}
|
|
120
|
+
/** Keys a project entry without `command`, `url` or `type` overrides on the user entry of the same name (like pi). */
|
|
121
|
+
const OVERRIDE_KEYS = ['enabled', 'exposure', 'toolExposure'];
|
|
122
|
+
/** `${NAME}` / `$NAME` in env and header values; unlike settings.json, an unset variable is an error (the server would fail anyway). */
|
|
123
|
+
function interpolateStrict(value, env, where) {
|
|
124
|
+
return value.replace(/\$\$|\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g, (match, braced, bare) => {
|
|
125
|
+
if (match === '$$')
|
|
126
|
+
return '$';
|
|
127
|
+
const name = (braced ?? bare);
|
|
128
|
+
const resolved = env[name];
|
|
129
|
+
if (resolved === undefined)
|
|
130
|
+
throw new Error(`${where} uses \${${name}}, which is not set`);
|
|
131
|
+
return resolved;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function interpolateServer(name, raw, env) {
|
|
135
|
+
if (!isPlainObject(raw))
|
|
136
|
+
return raw;
|
|
137
|
+
const result = { ...raw };
|
|
138
|
+
for (const key of ['env', 'headers']) {
|
|
139
|
+
const values = raw[key];
|
|
140
|
+
if (!stringRecord(values))
|
|
141
|
+
continue;
|
|
142
|
+
result[key] = Object.fromEntries(Object.entries(values).map(([k, v]) => [
|
|
143
|
+
k,
|
|
144
|
+
interpolateStrict(v, env, `MCP server "${name}" ${key} "${k}"`),
|
|
145
|
+
]));
|
|
146
|
+
}
|
|
147
|
+
for (const key of ['url', 'command', 'cwd'])
|
|
148
|
+
if (typeof raw[key] === 'string')
|
|
149
|
+
result[key] = interpolateStrict(raw[key], env, `MCP server "${name}" ${key}`);
|
|
150
|
+
if (Array.isArray(raw.args))
|
|
151
|
+
result.args = raw.args.map((arg) => typeof arg === 'string'
|
|
152
|
+
? interpolateStrict(arg, env, `MCP server "${name}" args`)
|
|
153
|
+
: arg);
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Reads `<agentDir>/mcp.json`, then `<cwd>/.vela/mcp.json` when the project is trusted (like pi). A
|
|
158
|
+
* project entry replaces the user entry of the same name; one without `command`, `url` or `type`
|
|
159
|
+
* only overrides its `enabled`, `exposure` and `toolExposure`. Variables are resolved from `env`.
|
|
160
|
+
*/
|
|
161
|
+
export function loadMcpServers(options) {
|
|
162
|
+
const result = { servers: {}, sources: {}, errors: [] };
|
|
163
|
+
const files = [join(options.agentDir, 'mcp.json')];
|
|
164
|
+
if (options.trusted)
|
|
165
|
+
files.push(join(options.projectDir, 'mcp.json'));
|
|
166
|
+
for (const file of files) {
|
|
167
|
+
if (!existsSync(file))
|
|
168
|
+
continue;
|
|
169
|
+
let servers;
|
|
170
|
+
try {
|
|
171
|
+
servers = JSON.parse(readFileSync(file, 'utf-8')).mcpServers;
|
|
172
|
+
if (servers === undefined)
|
|
173
|
+
continue;
|
|
174
|
+
if (!isPlainObject(servers))
|
|
175
|
+
throw new Error('mcpServers must be an object');
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
result.errors.push(`${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
for (const [name, raw] of Object.entries(servers)) {
|
|
182
|
+
const existing = result.servers[name];
|
|
183
|
+
let entry = raw;
|
|
184
|
+
if (isPlainObject(raw) &&
|
|
185
|
+
isPlainObject(existing) &&
|
|
186
|
+
raw.command === undefined &&
|
|
187
|
+
raw.url === undefined &&
|
|
188
|
+
raw.type === undefined) {
|
|
189
|
+
const extra = Object.keys(raw).filter((key) => !OVERRIDE_KEYS.includes(key));
|
|
190
|
+
if (extra.length > 0) {
|
|
191
|
+
result.errors.push(`${file}: MCP server "${name}": an override can only set ${OVERRIDE_KEYS.join(', ')} (found ${extra.join(', ')})`);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const overrides = Object.fromEntries(OVERRIDE_KEYS.filter((key) => key in raw).map((key) => [
|
|
195
|
+
key,
|
|
196
|
+
raw[key],
|
|
197
|
+
]));
|
|
198
|
+
entry = { ...existing, ...overrides };
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
result.servers[name] = interpolateServer(name, entry, options.env);
|
|
202
|
+
result.sources[name] = file;
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
delete result.servers[name];
|
|
206
|
+
result.errors.push(error instanceof Error ? error.message : String(error));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
export const mcpConfig = {
|
|
213
|
+
name: 'mcp',
|
|
214
|
+
projectResources: ['mcp.json'],
|
|
215
|
+
resolve(section, context) {
|
|
216
|
+
const files = loadMcpServers(context);
|
|
217
|
+
const settings = isPlainObject(section.mcpServers) ? section.mcpServers : {};
|
|
218
|
+
return {
|
|
219
|
+
...section,
|
|
220
|
+
mcpServers: { ...settings, ...files.servers },
|
|
221
|
+
sources: files.sources,
|
|
222
|
+
errors: files.errors,
|
|
223
|
+
};
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
//# 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,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One MCP server connection on the official MCP SDK (pi uses its own pi-mcp client; the behavior
|
|
3
|
+
* follows pi's `extensions/mcp/runtime.ts`). The SDK is imported only when a server connects, so
|
|
4
|
+
* Vela without MCP servers never loads it.
|
|
5
|
+
*/
|
|
6
|
+
import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
7
|
+
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
8
|
+
import type { CallToolResult, Tool as McpTool } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
+
import type { McpServerEntry } from './config.ts';
|
|
10
|
+
import type { McpToolCaller } from './tools.ts';
|
|
11
|
+
/**
|
|
12
|
+
* `disconnected`: the connection dropped (e.g. the stdio server exited); the next call reconnects.
|
|
13
|
+
* `failed`: the last connect failed; the next call tries again.
|
|
14
|
+
*/
|
|
15
|
+
export type McpServerState = 'idle' | 'connecting' | 'connected' | 'disconnected' | 'failed' | 'closed';
|
|
16
|
+
export interface McpConnectionOptions {
|
|
17
|
+
entry: McpServerEntry;
|
|
18
|
+
/** The Vela's cwd: stdio servers' relative `cwd` resolves against it */
|
|
19
|
+
cwd: string;
|
|
20
|
+
/** Called when the tool list or instructions change (after connect, or on `tools/list_changed`) */
|
|
21
|
+
onTools: (connection: McpConnection) => void;
|
|
22
|
+
/** Called when `state` or `error` change */
|
|
23
|
+
onChange?: (connection: McpConnection) => void;
|
|
24
|
+
/** Creates the transport; tests pass an in-memory one */
|
|
25
|
+
createTransport?: (entry: McpServerEntry, cwd: string) => Promise<Transport>;
|
|
26
|
+
}
|
|
27
|
+
/** One configured server, shared by all sessions of a Vela. Connects lazily and reconnects after a drop. */
|
|
28
|
+
export declare class McpConnection implements McpToolCaller {
|
|
29
|
+
private readonly options;
|
|
30
|
+
readonly entry: McpServerEntry;
|
|
31
|
+
state: McpServerState;
|
|
32
|
+
error: string | undefined;
|
|
33
|
+
tools: McpTool[];
|
|
34
|
+
/** Server instructions from `initialize`, describing its tools as a group */
|
|
35
|
+
instructions: string | undefined;
|
|
36
|
+
private client;
|
|
37
|
+
private opening;
|
|
38
|
+
/** The transport of a connect in progress, closed by close() so a starting server doesn't outlive the Vela */
|
|
39
|
+
private connecting;
|
|
40
|
+
/** Aborted by close(): cancels a connect in progress, including the wait between retries */
|
|
41
|
+
private readonly shutdown;
|
|
42
|
+
private stderrTail;
|
|
43
|
+
constructor(options: McpConnectionOptions);
|
|
44
|
+
get name(): string;
|
|
45
|
+
private get timeoutMs();
|
|
46
|
+
private setState;
|
|
47
|
+
/** Connects if not connected; concurrent callers share one attempt. */
|
|
48
|
+
connect(): Promise<Client>;
|
|
49
|
+
private open;
|
|
50
|
+
private describeConnectError;
|
|
51
|
+
private openOnce;
|
|
52
|
+
private createTransport;
|
|
53
|
+
private listTools;
|
|
54
|
+
private refreshTools;
|
|
55
|
+
callTool(name: string, args: Record<string, unknown>, options: Parameters<McpToolCaller['callTool']>[2]): Promise<CallToolResult>;
|
|
56
|
+
/** Closes the connection (stdio: close stdin, then SIGTERM, then SIGKILL, as the SDK does). */
|
|
57
|
+
close(): Promise<void>;
|
|
58
|
+
/** Drops the connection and connects again (`/mcp reconnect`). */
|
|
59
|
+
reconnect(): Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAC9E,OAAO,KAAK,EACV,cAAc,EACd,IAAI,IAAI,OAAO,EAChB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAO/C;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,YAAY,GACZ,WAAW,GACX,cAAc,GACd,QAAQ,GACR,QAAQ,CAAA;AA2CZ,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,cAAc,CAAA;IACrB,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAA;IACX,mGAAmG;IACnG,OAAO,EAAE,CAAC,UAAU,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,KAAK,IAAI,CAAA;IAC9C,yDAAyD;IACzD,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAA;CAC7E;AAED,4GAA4G;AAC5G,qBAAa,aAAc,YAAW,aAAa;IAerC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAdpC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAA;IAC9B,KAAK,EAAE,cAAc,CAAS;IAC9B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,KAAK,EAAE,OAAO,EAAE,CAAK;IACrB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,OAAO,CAA6B;IAC5C,8GAA8G;IAC9G,OAAO,CAAC,UAAU,CAAuB;IACzC,4FAA4F;IAC5F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,UAAU,CAAK;gBAEM,OAAO,EAAE,oBAAoB;IAI1D,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,KAAK,SAAS,GAEpB;IAED,OAAO,CAAC,QAAQ;IAMhB,uEAAuE;IACvE,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;YAYZ,IAAI;IAkClB,OAAO,CAAC,oBAAoB;YAYd,QAAQ;YA2DR,eAAe;YA2Bf,SAAS;YAaT,YAAY;IAOpB,QAAQ,CACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,UAAU,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,GAChD,OAAO,CAAC,cAAc,CAAC;IAW1B,+FAA+F;IACzF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,kEAAkE;IAC5D,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CAMjC"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One MCP server connection on the official MCP SDK (pi uses its own pi-mcp client; the behavior
|
|
3
|
+
* follows pi's `extensions/mcp/runtime.ts`). The SDK is imported only when a server connects, so
|
|
4
|
+
* Vela without MCP servers never loads it.
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync } from 'node:fs';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
import { join, resolve } from 'node:path';
|
|
9
|
+
import { setTimeout as sleep } from 'node:timers/promises';
|
|
10
|
+
const DEFAULT_TIMEOUT_SECONDS = 60;
|
|
11
|
+
const STDERR_TAIL_CHARS = 2_000;
|
|
12
|
+
/** Delays between attempts to connect to an HTTP server that failed with a transient error (like pi). */
|
|
13
|
+
const CONNECT_RETRY_DELAYS_MS = [250, 1_000];
|
|
14
|
+
function errorMessage(error) {
|
|
15
|
+
return error instanceof Error ? error.message : String(error);
|
|
16
|
+
}
|
|
17
|
+
/** HTTP status of an SDK transport error, when it has one. */
|
|
18
|
+
function httpStatus(error) {
|
|
19
|
+
const code = error?.code;
|
|
20
|
+
return typeof code === 'number' && code >= 100 && code < 600
|
|
21
|
+
? code
|
|
22
|
+
: undefined;
|
|
23
|
+
}
|
|
24
|
+
/** Network failures and overloaded or restarting servers, worth another attempt (like pi). */
|
|
25
|
+
function isTransient(error) {
|
|
26
|
+
const status = httpStatus(error);
|
|
27
|
+
if (status !== undefined)
|
|
28
|
+
return status === 408 || status === 429 || (status >= 500 && status !== 501);
|
|
29
|
+
return error instanceof TypeError;
|
|
30
|
+
}
|
|
31
|
+
/** `~` and `~/…` name the home directory, like in a shell. */
|
|
32
|
+
function expandHome(value) {
|
|
33
|
+
if (value === '~')
|
|
34
|
+
return homedir();
|
|
35
|
+
if (value.startsWith('~/') || value.startsWith('~\\'))
|
|
36
|
+
return join(homedir(), value.slice(2));
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
/** Vela's version for `initialize`, from package.json (three levels up from src/ and dist/). */
|
|
40
|
+
function velaVersion() {
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(readFileSync(new URL('../../../package.json', import.meta.url), 'utf8')).version;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return '0.0.0';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** One configured server, shared by all sessions of a Vela. Connects lazily and reconnects after a drop. */
|
|
49
|
+
export class McpConnection {
|
|
50
|
+
options;
|
|
51
|
+
entry;
|
|
52
|
+
state = 'idle';
|
|
53
|
+
error;
|
|
54
|
+
tools = [];
|
|
55
|
+
/** Server instructions from `initialize`, describing its tools as a group */
|
|
56
|
+
instructions;
|
|
57
|
+
client;
|
|
58
|
+
opening;
|
|
59
|
+
/** The transport of a connect in progress, closed by close() so a starting server doesn't outlive the Vela */
|
|
60
|
+
connecting;
|
|
61
|
+
/** Aborted by close(): cancels a connect in progress, including the wait between retries */
|
|
62
|
+
shutdown = new AbortController();
|
|
63
|
+
stderrTail = '';
|
|
64
|
+
constructor(options) {
|
|
65
|
+
this.options = options;
|
|
66
|
+
this.entry = options.entry;
|
|
67
|
+
}
|
|
68
|
+
get name() {
|
|
69
|
+
return this.entry.name;
|
|
70
|
+
}
|
|
71
|
+
get timeoutMs() {
|
|
72
|
+
return (this.entry.config.timeout ?? DEFAULT_TIMEOUT_SECONDS) * 1000;
|
|
73
|
+
}
|
|
74
|
+
setState(state, error) {
|
|
75
|
+
this.state = state;
|
|
76
|
+
this.error = error;
|
|
77
|
+
this.options.onChange?.(this);
|
|
78
|
+
}
|
|
79
|
+
/** Connects if not connected; concurrent callers share one attempt. */
|
|
80
|
+
connect() {
|
|
81
|
+
if (this.client)
|
|
82
|
+
return Promise.resolve(this.client);
|
|
83
|
+
if (this.state === 'closed')
|
|
84
|
+
return Promise.reject(new Error(`MCP server "${this.name}" has been shut down`));
|
|
85
|
+
this.opening ??= this.open().finally(() => {
|
|
86
|
+
this.opening = undefined;
|
|
87
|
+
});
|
|
88
|
+
return this.opening;
|
|
89
|
+
}
|
|
90
|
+
async open() {
|
|
91
|
+
this.setState('connecting');
|
|
92
|
+
const isHttp = 'url' in this.entry.config;
|
|
93
|
+
for (let attempt = 0;; attempt++) {
|
|
94
|
+
try {
|
|
95
|
+
const client = await this.openOnce();
|
|
96
|
+
if (this.shutdown.signal.aborted) {
|
|
97
|
+
await client.close().catch(() => { });
|
|
98
|
+
throw new Error('shut down');
|
|
99
|
+
}
|
|
100
|
+
this.client = client;
|
|
101
|
+
this.setState('connected');
|
|
102
|
+
this.options.onTools(this);
|
|
103
|
+
return client;
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
const delay = CONNECT_RETRY_DELAYS_MS[attempt];
|
|
107
|
+
if (isHttp &&
|
|
108
|
+
delay !== undefined &&
|
|
109
|
+
isTransient(error) &&
|
|
110
|
+
!this.shutdown.signal.aborted) {
|
|
111
|
+
await sleep(delay, undefined, { signal: this.shutdown.signal }).catch(() => { });
|
|
112
|
+
if (!this.shutdown.signal.aborted)
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const message = this.describeConnectError(error);
|
|
116
|
+
if (this.state !== 'closed')
|
|
117
|
+
this.setState('failed', message);
|
|
118
|
+
throw new Error(message);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
describeConnectError(error) {
|
|
123
|
+
if (this.shutdown.signal.aborted)
|
|
124
|
+
return `MCP server "${this.name}" has been shut down`;
|
|
125
|
+
const status = httpStatus(error);
|
|
126
|
+
let message = `MCP server "${this.name}" failed to connect: ${errorMessage(error)}`;
|
|
127
|
+
if (status === 401 || status === 403)
|
|
128
|
+
message += `. It requires sign-in, and Vela does not support MCP OAuth yet; set an Authorization header in its config instead`;
|
|
129
|
+
const tail = this.stderrTail.trim();
|
|
130
|
+
if (tail)
|
|
131
|
+
message += `\nServer stderr:\n${tail}`;
|
|
132
|
+
return message;
|
|
133
|
+
}
|
|
134
|
+
async openOnce() {
|
|
135
|
+
const [{ Client }, { ToolListChangedNotificationSchema }, { CfWorkerJsonSchemaValidator },] = await Promise.all([
|
|
136
|
+
import('@modelcontextprotocol/sdk/client/index.js'),
|
|
137
|
+
import('@modelcontextprotocol/sdk/types.js'),
|
|
138
|
+
import('@modelcontextprotocol/sdk/validation/cfworker'),
|
|
139
|
+
]);
|
|
140
|
+
this.stderrTail = '';
|
|
141
|
+
const transport = await (this.options.createTransport ?? this.createTransport)(this.entry, this.options.cwd);
|
|
142
|
+
if (this.shutdown.signal.aborted) {
|
|
143
|
+
await transport.close().catch(() => { });
|
|
144
|
+
throw new Error('shut down');
|
|
145
|
+
}
|
|
146
|
+
this.connecting = transport;
|
|
147
|
+
const stderr = transport
|
|
148
|
+
.stderr;
|
|
149
|
+
stderr?.on('data', (chunk) => {
|
|
150
|
+
this.stderrTail = (this.stderrTail + chunk.toString()).slice(-STDERR_TAIL_CHARS);
|
|
151
|
+
});
|
|
152
|
+
const client = new Client({ name: 'vela', version: velaVersion() }, {
|
|
153
|
+
capabilities: {},
|
|
154
|
+
// Vela already depends on @cfworker/json-schema; ajv would compile schemas with new Function
|
|
155
|
+
jsonSchemaValidator: new CfWorkerJsonSchemaValidator(),
|
|
156
|
+
});
|
|
157
|
+
client.onclose = () => {
|
|
158
|
+
if (this.client !== client)
|
|
159
|
+
return;
|
|
160
|
+
this.client = undefined;
|
|
161
|
+
if (this.state !== 'closed')
|
|
162
|
+
this.setState('disconnected', `MCP server "${this.name}" disconnected${this.stderrTail.trim() ? `\nServer stderr:\n${this.stderrTail.trim()}` : ''}`);
|
|
163
|
+
};
|
|
164
|
+
client.setNotificationHandler(ToolListChangedNotificationSchema, () => {
|
|
165
|
+
void this.refreshTools(client).catch(() => { });
|
|
166
|
+
});
|
|
167
|
+
try {
|
|
168
|
+
await client.connect(transport, { timeout: this.timeoutMs });
|
|
169
|
+
this.instructions = client.getInstructions()?.trim() || undefined;
|
|
170
|
+
this.tools = await this.listTools(client);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
await client.close().catch(() => { });
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
this.connecting = undefined;
|
|
178
|
+
}
|
|
179
|
+
return client;
|
|
180
|
+
}
|
|
181
|
+
async createTransport(entry, cwd) {
|
|
182
|
+
const { config } = entry;
|
|
183
|
+
if ('url' in config) {
|
|
184
|
+
const { StreamableHTTPClientTransport } = await import('@modelcontextprotocol/sdk/client/streamableHttp.js');
|
|
185
|
+
return new StreamableHTTPClientTransport(new URL(config.url), {
|
|
186
|
+
requestInit: { headers: config.headers ?? {} },
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const { StdioClientTransport } = await import('@modelcontextprotocol/sdk/client/stdio.js');
|
|
190
|
+
return new StdioClientTransport({
|
|
191
|
+
command: expandHome(config.command),
|
|
192
|
+
args: config.args?.map(expandHome),
|
|
193
|
+
// Like pi: the server inherits the environment, as bash does (the SDK's default passes only a few variables)
|
|
194
|
+
// vela-boundary: allow
|
|
195
|
+
env: { ...process.env, ...config.env },
|
|
196
|
+
cwd: resolve(cwd, expandHome(config.cwd ?? '.')),
|
|
197
|
+
stderr: 'pipe',
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
async listTools(client) {
|
|
201
|
+
const tools = [];
|
|
202
|
+
let cursor;
|
|
203
|
+
do {
|
|
204
|
+
const page = await client.listTools(cursor ? { cursor } : undefined, {
|
|
205
|
+
timeout: this.timeoutMs,
|
|
206
|
+
});
|
|
207
|
+
tools.push(...page.tools);
|
|
208
|
+
cursor = page.nextCursor;
|
|
209
|
+
} while (cursor);
|
|
210
|
+
return tools;
|
|
211
|
+
}
|
|
212
|
+
async refreshTools(client) {
|
|
213
|
+
const tools = await this.listTools(client);
|
|
214
|
+
if (this.client !== client)
|
|
215
|
+
return;
|
|
216
|
+
this.tools = tools;
|
|
217
|
+
this.options.onTools(this);
|
|
218
|
+
}
|
|
219
|
+
async callTool(name, args, options) {
|
|
220
|
+
const client = await this.connect();
|
|
221
|
+
// Tool calls are not retried: the server may already have performed them (like pi)
|
|
222
|
+
return (await client.callTool({ name, arguments: args }, undefined, {
|
|
223
|
+
signal: options.signal,
|
|
224
|
+
timeout: this.timeoutMs,
|
|
225
|
+
resetTimeoutOnProgress: true,
|
|
226
|
+
...(options.onProgress ? { onprogress: options.onProgress } : {}),
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
/** Closes the connection (stdio: close stdin, then SIGTERM, then SIGKILL, as the SDK does). */
|
|
230
|
+
async close() {
|
|
231
|
+
this.shutdown.abort();
|
|
232
|
+
this.setState('closed');
|
|
233
|
+
const client = this.client;
|
|
234
|
+
this.client = undefined;
|
|
235
|
+
await Promise.all([
|
|
236
|
+
client?.close().catch(() => { }),
|
|
237
|
+
this.connecting?.close().catch(() => { }),
|
|
238
|
+
]);
|
|
239
|
+
}
|
|
240
|
+
/** Drops the connection and connects again (`/mcp reconnect`). */
|
|
241
|
+
async reconnect() {
|
|
242
|
+
const client = this.client;
|
|
243
|
+
this.client = undefined;
|
|
244
|
+
await client?.close().catch(() => { });
|
|
245
|
+
await this.connect();
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The built-in MCP extension (like pi's `extensions/mcp`): connects to MCP servers over stdio or
|
|
3
|
+
* streamable HTTP and registers their tools as `mcp__<server>__<tool>`, deferred by default so
|
|
4
|
+
* tool_search loads them on demand.
|
|
5
|
+
*
|
|
6
|
+
* Unlike pi, one set of connections serves all sessions of a Vela (a Lark bot has many concurrent
|
|
7
|
+
* sessions); they start with the first session and close when the Vela is disposed.
|
|
8
|
+
*/
|
|
9
|
+
import type { VelaExtension } from '@glows777/vela-core/extension-api';
|
|
10
|
+
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
11
|
+
import { type McpServerConfig, type McpServerEntry } from './config.ts';
|
|
12
|
+
export type { McpExposure, McpHttpServerConfig, McpServerConfig, McpServersFile, McpStdioServerConfig, } from './config.ts';
|
|
13
|
+
export interface McpOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Servers in the `mcpServers` format of Claude Desktop / Claude Code (`{ name: { command, args } }`
|
|
16
|
+
* or `{ name: { url, headers } }`). Default: `mcpServers` in this extension's config, which the
|
|
17
|
+
* CLI fills from `~/.vela/mcp.json` and the trusted project's `.vela/mcp.json`.
|
|
18
|
+
*/
|
|
19
|
+
servers?: Record<string, McpServerConfig>;
|
|
20
|
+
/** @internal Creates transports (tests use in-memory servers) */
|
|
21
|
+
createTransport?: (entry: McpServerEntry, cwd: string) => Promise<Transport>;
|
|
22
|
+
}
|
|
23
|
+
/** The built-in MCP extension. Its tools are `mcp__<server>__<tool>`. */
|
|
24
|
+
export declare function mcp(options?: McpOptions): VelaExtension;
|
|
25
|
+
export { mcpConfig } from './config.ts';
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAEV,aAAa,EACd,MAAM,mCAAmC,CAAA;AAC1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAA;AAC9E,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EAGpB,MAAM,aAAa,CAAA;AAIpB,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,oBAAoB,GACrB,MAAM,aAAa,CAAA;AAKpB,MAAM,WAAW,UAAU;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACzC,iEAAiE;IACjE,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,CAAA;CAC7E;AAKD,yEAAyE;AACzE,wBAAgB,GAAG,CAAC,OAAO,GAAE,UAAe,GAAG,aAAa,CA2L3D;AA2CD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA"}
|