@jini-ai/mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/agent-install/index.d.ts +9 -0
- package/dist/agent-install/index.d.ts.map +1 -0
- package/dist/agent-install/index.js +9 -0
- package/dist/agent-install/index.js.map +1 -0
- package/dist/agent-install/install.d.ts +97 -0
- package/dist/agent-install/install.d.ts.map +1 -0
- package/dist/agent-install/install.js +410 -0
- package/dist/agent-install/install.js.map +1 -0
- package/dist/bin/serve.d.ts +75 -0
- package/dist/bin/serve.d.ts.map +1 -0
- package/dist/bin/serve.js +79 -0
- package/dist/bin/serve.js.map +1 -0
- package/dist/client/client.d.ts +48 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +242 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +8 -0
- package/dist/client/index.js.map +1 -0
- package/dist/core/config.d.ts +157 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +475 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/index.d.ts +14 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/install-info.d.ts +69 -0
- package/dist/core/install-info.d.ts.map +1 -0
- package/dist/core/install-info.js +79 -0
- package/dist/core/install-info.js.map +1 -0
- package/dist/core/oauth.d.ts +274 -0
- package/dist/core/oauth.d.ts.map +1 -0
- package/dist/core/oauth.js +667 -0
- package/dist/core/oauth.js.map +1 -0
- package/dist/core/secure-write.d.ts +17 -0
- package/dist/core/secure-write.d.ts.map +1 -0
- package/dist/core/secure-write.js +72 -0
- package/dist/core/secure-write.js.map +1 -0
- package/dist/core/tokens.d.ts +72 -0
- package/dist/core/tokens.d.ts.map +1 -0
- package/dist/core/tokens.js +197 -0
- package/dist/core/tokens.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/server/daemon-client.d.ts +21 -0
- package/dist/server/daemon-client.d.ts.map +1 -0
- package/dist/server/daemon-client.js +176 -0
- package/dist/server/daemon-client.js.map +1 -0
- package/dist/server/index.d.ts +18 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +18 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/resource-protocol.d.ts +38 -0
- package/dist/server/resource-protocol.d.ts.map +1 -0
- package/dist/server/resource-protocol.js +68 -0
- package/dist/server/resource-protocol.js.map +1 -0
- package/dist/server/resources/active-resource.d.ts +12 -0
- package/dist/server/resources/active-resource.d.ts.map +1 -0
- package/dist/server/resources/active-resource.js +46 -0
- package/dist/server/resources/active-resource.js.map +1 -0
- package/dist/server/tool-protocol.d.ts +45 -0
- package/dist/server/tool-protocol.d.ts.map +1 -0
- package/dist/server/tool-protocol.js +74 -0
- package/dist/server/tool-protocol.js.map +1 -0
- package/dist/server/tool-server.d.ts +105 -0
- package/dist/server/tool-server.d.ts.map +1 -0
- package/dist/server/tool-server.js +96 -0
- package/dist/server/tool-server.js.map +1 -0
- package/dist/server/tools/delegated-tool.d.ts +15 -0
- package/dist/server/tools/delegated-tool.d.ts.map +1 -0
- package/dist/server/tools/delegated-tool.js +90 -0
- package/dist/server/tools/delegated-tool.js.map +1 -0
- package/dist/server/tools/run-tools.d.ts +14 -0
- package/dist/server/tools/run-tools.d.ts.map +1 -0
- package/dist/server/tools/run-tools.js +142 -0
- package/dist/server/tools/run-tools.js.map +1 -0
- package/dist/server/tools/tool-catalog-tools.d.ts +8 -0
- package/dist/server/tools/tool-catalog-tools.d.ts.map +1 -0
- package/dist/server/tools/tool-catalog-tools.js +66 -0
- package/dist/server/tools/tool-catalog-tools.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/core/config
|
|
3
|
+
* Config schema + on-disk store for the external MCP servers the daemon connects
|
|
4
|
+
* to as a client, plus the per-agent config builders (Claude `.mcp.json`, ACP
|
|
5
|
+
* `mcpServers`, OpenCode) that hand those servers to a launching agent. Part of
|
|
6
|
+
* the MCP `core` kernel; depends on no sibling subdirectory.
|
|
7
|
+
*/
|
|
8
|
+
// External MCP server configuration storage + spawn-time wiring.
|
|
9
|
+
//
|
|
10
|
+
// The daemon acts as an MCP CLIENT to one or more external MCP servers
|
|
11
|
+
// (image/video generation, GitHub, filesystem, anything the user
|
|
12
|
+
// configures). At spawn time we hand those servers to whichever agent is
|
|
13
|
+
// being launched (Claude Code via a project-cwd `.mcp.json`, ACP agents via
|
|
14
|
+
// the existing `mcpServers` parameter) so the agent surfaces their tools to
|
|
15
|
+
// the model.
|
|
16
|
+
//
|
|
17
|
+
// Storage: <dataDir>/mcp-config.json with shape `{ servers: [...] }`.
|
|
18
|
+
//
|
|
19
|
+
// We deliberately keep the schema close to Claude Code's `.mcp.json` and
|
|
20
|
+
// Cursor's MCP config — those are the de-facto interchange formats — so
|
|
21
|
+
// users can copy-paste between tools without translation.
|
|
22
|
+
import { readFile } from 'node:fs/promises';
|
|
23
|
+
import { realpathSync } from 'node:fs';
|
|
24
|
+
import path from 'node:path';
|
|
25
|
+
import { pathContains } from '@jini-ai/platform';
|
|
26
|
+
import { writeSecretFileAtomic } from './secure-write.js';
|
|
27
|
+
const VALID_TRANSPORTS = new Set([
|
|
28
|
+
'stdio',
|
|
29
|
+
'sse',
|
|
30
|
+
'http',
|
|
31
|
+
]);
|
|
32
|
+
const VALID_AUTH_MODES = new Set(['none', 'oauth']);
|
|
33
|
+
// Slug rule for server ids. The id flows into agent-facing config files
|
|
34
|
+
// (Claude Code's `mcpServers` map keys, ACP `name`) and in some cases into
|
|
35
|
+
// argv / env, so we keep it strictly alphanumeric + `-` / `_`.
|
|
36
|
+
const SERVER_ID_PATTERN = /^[a-z0-9][a-z0-9_-]{0,63}$/i;
|
|
37
|
+
function configFile(dataDir) {
|
|
38
|
+
return path.join(dataDir, 'mcp-config.json');
|
|
39
|
+
}
|
|
40
|
+
function isPlainObject(v) {
|
|
41
|
+
return Boolean(v) && typeof v === 'object' && !Array.isArray(v);
|
|
42
|
+
}
|
|
43
|
+
function sanitizeStringMap(raw) {
|
|
44
|
+
if (!isPlainObject(raw))
|
|
45
|
+
return undefined;
|
|
46
|
+
const out = {};
|
|
47
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
48
|
+
if (k === '__proto__' || k === 'constructor')
|
|
49
|
+
continue;
|
|
50
|
+
if (!k.trim())
|
|
51
|
+
continue;
|
|
52
|
+
if (typeof v !== 'string')
|
|
53
|
+
continue;
|
|
54
|
+
// Drop empty / whitespace-only values. Persisting them is worse than
|
|
55
|
+
// omitting them: the spawn-time merge treats a present header as
|
|
56
|
+
// "user pinned this", which would block our daemon-issued OAuth
|
|
57
|
+
// Bearer from being injected. The UI also has placeholder fields
|
|
58
|
+
// (e.g. an "Authorization=" template row) the user can leave blank
|
|
59
|
+
// — those should never make it into the saved config.
|
|
60
|
+
if (v.trim() === '')
|
|
61
|
+
continue;
|
|
62
|
+
out[k] = v;
|
|
63
|
+
}
|
|
64
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
65
|
+
}
|
|
66
|
+
function sanitizeStringArray(raw) {
|
|
67
|
+
if (!Array.isArray(raw))
|
|
68
|
+
return undefined;
|
|
69
|
+
const out = raw.filter((v) => typeof v === 'string');
|
|
70
|
+
return out.length > 0 ? out : undefined;
|
|
71
|
+
}
|
|
72
|
+
function normalizeHost(hostname) {
|
|
73
|
+
return hostname
|
|
74
|
+
.replace(/^\[|\]$/g, '')
|
|
75
|
+
.toLowerCase()
|
|
76
|
+
.replace(/\.+$/g, '');
|
|
77
|
+
}
|
|
78
|
+
function isLoopbackHost(hostname) {
|
|
79
|
+
const host = normalizeHost(hostname);
|
|
80
|
+
if (host === 'localhost' || host === '::1')
|
|
81
|
+
return true;
|
|
82
|
+
// Note: IPv4-mapped IPv6 loopback (`::ffff:127.0.0.1`) is not special-cased —
|
|
83
|
+
// the WHATWG URL parser compresses it to `::ffff:7f00:1` before it reaches
|
|
84
|
+
// here, so a dotted-quad match is unreachable through `inferMcpAuthModeForUrl`.
|
|
85
|
+
return /^127(?:\.\d{1,3}){3}$/.test(host);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Infer the appropriate `McpAuthMode` for a given server URL.
|
|
89
|
+
* Returns `'none'` for loopback targets (localhost, 127.x.x.x, ::1)
|
|
90
|
+
* and `'oauth'` for everything else, including when `rawUrl` is absent or unparseable.
|
|
91
|
+
* @param rawUrl The server URL string to inspect, if any.
|
|
92
|
+
* @returns The inferred `McpAuthMode`.
|
|
93
|
+
*/
|
|
94
|
+
export function inferMcpAuthModeForUrl(rawUrl) {
|
|
95
|
+
if (!rawUrl)
|
|
96
|
+
return 'oauth';
|
|
97
|
+
try {
|
|
98
|
+
return isLoopbackHost(new URL(rawUrl).hostname) ? 'none' : 'oauth';
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return 'oauth';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function sanitizeMcpAuthMode(raw) {
|
|
105
|
+
return typeof raw === 'string' && VALID_AUTH_MODES.has(raw)
|
|
106
|
+
? raw
|
|
107
|
+
: undefined;
|
|
108
|
+
}
|
|
109
|
+
// Only ever invoked for http/sse servers (the callers gate on transport), so
|
|
110
|
+
// there is no stdio short-circuit here — the token merge just needs the
|
|
111
|
+
// effective auth mode for a remote server.
|
|
112
|
+
function effectiveMcpAuthMode(server) {
|
|
113
|
+
return server.authMode ?? inferMcpAuthModeForUrl(server.url);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Validate a single user-supplied entry. Drops invalid fields so a typo in
|
|
117
|
+
* one server doesn't tank the whole config. Returns null when the entry is
|
|
118
|
+
* unsalvageable (no id, or no transport-required fields).
|
|
119
|
+
*/
|
|
120
|
+
export function sanitizeMcpServer(raw) {
|
|
121
|
+
if (!isPlainObject(raw))
|
|
122
|
+
return null;
|
|
123
|
+
const id = typeof raw.id === 'string' ? raw.id.trim() : '';
|
|
124
|
+
if (!SERVER_ID_PATTERN.test(id))
|
|
125
|
+
return null;
|
|
126
|
+
const transport = typeof raw.transport === 'string' ? raw.transport : 'stdio';
|
|
127
|
+
if (!VALID_TRANSPORTS.has(transport))
|
|
128
|
+
return null;
|
|
129
|
+
const next = {
|
|
130
|
+
id,
|
|
131
|
+
transport,
|
|
132
|
+
enabled: raw.enabled !== false,
|
|
133
|
+
};
|
|
134
|
+
if (typeof raw.label === 'string' && raw.label.trim()) {
|
|
135
|
+
next.label = raw.label.trim();
|
|
136
|
+
}
|
|
137
|
+
if (transport === 'stdio') {
|
|
138
|
+
if (typeof raw.command !== 'string' || !raw.command.trim())
|
|
139
|
+
return null;
|
|
140
|
+
next.command = raw.command.trim();
|
|
141
|
+
const args = sanitizeStringArray(raw.args);
|
|
142
|
+
if (args)
|
|
143
|
+
next.args = args;
|
|
144
|
+
const env = sanitizeStringMap(raw.env);
|
|
145
|
+
if (env)
|
|
146
|
+
next.env = env;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
if (typeof raw.url !== 'string' || !raw.url.trim())
|
|
150
|
+
return null;
|
|
151
|
+
// Reject anything that isn't an http(s) URL — protects against accidental
|
|
152
|
+
// `file://` / `javascript:` slipping into a config file.
|
|
153
|
+
let parsed;
|
|
154
|
+
try {
|
|
155
|
+
parsed = new URL(raw.url.trim());
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:')
|
|
161
|
+
return null;
|
|
162
|
+
next.url = parsed.toString();
|
|
163
|
+
next.authMode = sanitizeMcpAuthMode(raw.authMode) ?? inferMcpAuthModeForUrl(next.url);
|
|
164
|
+
const headers = sanitizeStringMap(raw.headers);
|
|
165
|
+
if (headers)
|
|
166
|
+
next.headers = headers;
|
|
167
|
+
}
|
|
168
|
+
return next;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Coerce and de-duplicate a freeform JSON blob into a valid `McpConfig`.
|
|
172
|
+
* Entries that fail `sanitizeMcpServer` are silently dropped; duplicate ids
|
|
173
|
+
* are kept first-wins. Returns `{ servers: [] }` for any non-object input.
|
|
174
|
+
* @param raw The raw parsed JSON to sanitize.
|
|
175
|
+
* @returns A clean `McpConfig` guaranteed to have only valid, unique server entries.
|
|
176
|
+
*/
|
|
177
|
+
export function sanitizeMcpConfig(raw) {
|
|
178
|
+
if (!isPlainObject(raw))
|
|
179
|
+
return { servers: [] };
|
|
180
|
+
const list = Array.isArray(raw.servers) ? raw.servers : [];
|
|
181
|
+
const seen = new Set();
|
|
182
|
+
const out = [];
|
|
183
|
+
for (const entry of list) {
|
|
184
|
+
const ok = sanitizeMcpServer(entry);
|
|
185
|
+
if (!ok)
|
|
186
|
+
continue;
|
|
187
|
+
if (seen.has(ok.id))
|
|
188
|
+
continue; // de-dupe by id
|
|
189
|
+
seen.add(ok.id);
|
|
190
|
+
out.push(ok);
|
|
191
|
+
}
|
|
192
|
+
return { servers: out };
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Read and sanitize the MCP config from `<dataDir>/mcp-config.json`.
|
|
196
|
+
* Returns `{ servers: [] }` when the file does not exist or contains invalid JSON.
|
|
197
|
+
* @param dataDir The resolved runtime data directory.
|
|
198
|
+
* @returns The sanitized `McpConfig`, never rejects on missing-file or corrupt-JSON.
|
|
199
|
+
*/
|
|
200
|
+
export async function readMcpConfig(dataDir) {
|
|
201
|
+
try {
|
|
202
|
+
const raw = await readFile(configFile(dataDir), 'utf8');
|
|
203
|
+
const parsed = JSON.parse(raw);
|
|
204
|
+
return sanitizeMcpConfig(parsed);
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
const e = err;
|
|
208
|
+
if (e.code === 'ENOENT')
|
|
209
|
+
return { servers: [] };
|
|
210
|
+
if (e.name === 'SyntaxError') {
|
|
211
|
+
console.error('[mcp-config] Corrupted JSON, returning empty:', e.message);
|
|
212
|
+
return { servers: [] };
|
|
213
|
+
}
|
|
214
|
+
throw err;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const writeLocks = new Map();
|
|
218
|
+
/**
|
|
219
|
+
* Sanitize and atomically write the MCP config to `<dataDir>/mcp-config.json`.
|
|
220
|
+
* Uses a per-`dataDir` promise-chain mutex so concurrent writes serialize
|
|
221
|
+
* instead of racing. The body is sanitized through `sanitizeMcpConfig` before
|
|
222
|
+
* being written. This file may carry environment variables and
|
|
223
|
+
* `Authorization` header values (API keys, bearer tokens — see
|
|
224
|
+
* `McpServerConfig.env`/`.headers`), so it is written with owner-only
|
|
225
|
+
* (0600) permissions from the very first byte via `writeSecretFileAtomic`
|
|
226
|
+
* rather than a post-rename chmod (CR-006 / SEC-RB-002).
|
|
227
|
+
* @param dataDir The resolved runtime data directory.
|
|
228
|
+
* @param body The raw config body to sanitize and persist.
|
|
229
|
+
* @returns The sanitized `McpConfig` that was written to disk.
|
|
230
|
+
*/
|
|
231
|
+
export async function writeMcpConfig(dataDir, body) {
|
|
232
|
+
const prev = writeLocks.get(dataDir) ?? Promise.resolve();
|
|
233
|
+
const task = prev.catch(() => { }).then(() => doWrite(dataDir, body));
|
|
234
|
+
writeLocks.set(dataDir, task);
|
|
235
|
+
try {
|
|
236
|
+
return await task;
|
|
237
|
+
}
|
|
238
|
+
finally {
|
|
239
|
+
if (writeLocks.get(dataDir) === task)
|
|
240
|
+
writeLocks.delete(dataDir);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
async function doWrite(dataDir, body) {
|
|
244
|
+
const next = sanitizeMcpConfig(body);
|
|
245
|
+
await writeSecretFileAtomic(configFile(dataDir), JSON.stringify(next, null, 2));
|
|
246
|
+
return next;
|
|
247
|
+
}
|
|
248
|
+
// ───────────────────────────────────────────────────────────────────────
|
|
249
|
+
// Spawn-time wiring helpers.
|
|
250
|
+
// ───────────────────────────────────────────────────────────────────────
|
|
251
|
+
/**
|
|
252
|
+
* Resolve `p` to its real (symlink-free) path when it exists on disk;
|
|
253
|
+
* falls back to lexical `path.resolve` (still normalizing `..`/`.`
|
|
254
|
+
* segments) when it does not exist yet, or the platform can't resolve it.
|
|
255
|
+
*/
|
|
256
|
+
function resolveRealOrLexical(p) {
|
|
257
|
+
try {
|
|
258
|
+
return realpathSync.native(p);
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
return path.resolve(p);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* True when `cwd` is a daemon-managed project directory under `projectsDir`
|
|
266
|
+
* (= safe to write `.mcp.json` into without risk of clobbering a user-owned
|
|
267
|
+
* file). Git-linked projects whose cwd points at the user's own repo, and
|
|
268
|
+
* the no-project fallback that resolves to the project root, both return false
|
|
269
|
+
* — the daemon must NOT write external-MCP config into either of those.
|
|
270
|
+
*
|
|
271
|
+
* Both `cwd` and `projectsDir` are realpath-resolved before the containment
|
|
272
|
+
* check (falling back to lexical `path.resolve` normalization for a path
|
|
273
|
+
* that doesn't exist on disk yet), and containment is decided with
|
|
274
|
+
* `@jini-ai/platform`'s separator-aware `pathContains` rather than a raw
|
|
275
|
+
* string-prefix check — a `..`-containing path or a symlinked descendant
|
|
276
|
+
* can defeat a plain `startsWith` (CR-006 / SEC-RB-011).
|
|
277
|
+
*/
|
|
278
|
+
export function isManagedProjectCwd(cwd, projectsDir) {
|
|
279
|
+
if (!cwd || typeof cwd !== 'string')
|
|
280
|
+
return false;
|
|
281
|
+
if (typeof projectsDir !== 'string' || projectsDir.length === 0)
|
|
282
|
+
return false;
|
|
283
|
+
const resolvedProjectsDir = resolveRealOrLexical(projectsDir);
|
|
284
|
+
const resolvedCwd = resolveRealOrLexical(cwd);
|
|
285
|
+
if (resolvedCwd === resolvedProjectsDir)
|
|
286
|
+
return false; // projects root, not a project
|
|
287
|
+
return pathContains(resolvedProjectsDir, resolvedCwd);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Project-cwd `.mcp.json` shape that Claude Code auto-loads on spawn (the
|
|
291
|
+
* same format Claude Desktop and Cursor use). Returns null when the user
|
|
292
|
+
* has no enabled servers — in that case the caller should NOT write the
|
|
293
|
+
* file (and should clean up any stale one).
|
|
294
|
+
*
|
|
295
|
+
* `tokens` is an optional map of `serverId -> bearer access token`, used
|
|
296
|
+
* for HTTP/SSE servers that completed the daemon's web OAuth flow. When a
|
|
297
|
+
* token is present we inject `Authorization: Bearer <token>` into the
|
|
298
|
+
* server's headers — this is what bypasses the per-spawn `mcp-remote`
|
|
299
|
+
* dance and lets Claude Code talk directly to the upstream MCP using
|
|
300
|
+
* pre-authenticated credentials. User-supplied headers always win on
|
|
301
|
+
* conflict so they can pin a specific token if they really want to.
|
|
302
|
+
*/
|
|
303
|
+
export function buildClaudeMcpJson(servers, tokens = {}) {
|
|
304
|
+
const enabled = servers.filter((s) => s.enabled);
|
|
305
|
+
if (enabled.length === 0)
|
|
306
|
+
return null;
|
|
307
|
+
const out = {};
|
|
308
|
+
for (const s of enabled) {
|
|
309
|
+
if (s.transport === 'stdio') {
|
|
310
|
+
const entry = { command: s.command };
|
|
311
|
+
if (s.args && s.args.length > 0)
|
|
312
|
+
entry.args = s.args;
|
|
313
|
+
if (s.env && Object.keys(s.env).length > 0)
|
|
314
|
+
entry.env = s.env;
|
|
315
|
+
out[s.id] = entry;
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
const entry = {
|
|
319
|
+
type: s.transport, // 'sse' | 'http'
|
|
320
|
+
url: s.url,
|
|
321
|
+
};
|
|
322
|
+
const headers = mergeAuthHeader(s.headers, effectiveMcpAuthMode(s) === 'oauth' ? tokens[s.id] : undefined);
|
|
323
|
+
if (headers && Object.keys(headers).length > 0)
|
|
324
|
+
entry.headers = headers;
|
|
325
|
+
out[s.id] = entry;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return { mcpServers: out };
|
|
329
|
+
}
|
|
330
|
+
/** Build a headers object that includes the daemon-issued bearer token when
|
|
331
|
+
* the user hasn't already supplied a NON-EMPTY Authorization header. A
|
|
332
|
+
* blank Authorization (empty string / whitespace only) is treated as
|
|
333
|
+
* "not pinned" — historically the template UI persisted empty values from
|
|
334
|
+
* unfilled fields, and we never want a blank Authorization to suppress a
|
|
335
|
+
* valid OAuth Bearer (the upstream MCP would refuse the connection and
|
|
336
|
+
* fall back to its in-tool re-auth dance). Real user-pinned values still
|
|
337
|
+
* win so manually-set PATs aren't silently overwritten. */
|
|
338
|
+
function mergeAuthHeader(existing, bearer) {
|
|
339
|
+
const merged = {};
|
|
340
|
+
let userAuth = null;
|
|
341
|
+
for (const [k, v] of Object.entries(existing ?? {})) {
|
|
342
|
+
if (k.toLowerCase() === 'authorization') {
|
|
343
|
+
if (typeof v === 'string' && v.trim() !== '') {
|
|
344
|
+
userAuth = v;
|
|
345
|
+
merged[k] = v;
|
|
346
|
+
}
|
|
347
|
+
// empty / whitespace authorization is ignored, NOT carried through
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
merged[k] = v;
|
|
351
|
+
}
|
|
352
|
+
if (bearer && !userAuth) {
|
|
353
|
+
merged['Authorization'] = `Bearer ${bearer}`;
|
|
354
|
+
}
|
|
355
|
+
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Convert user-configured external MCP servers into the ACP `mcpServers` array.
|
|
359
|
+
* Only stdio servers are included — SSE/HTTP are dropped because ACP currently
|
|
360
|
+
* models stdio only. Returns an empty array when no enabled stdio servers exist.
|
|
361
|
+
* @param servers The full server list from `McpConfig`.
|
|
362
|
+
* @returns ACP-shaped server entries for all enabled stdio servers.
|
|
363
|
+
*/
|
|
364
|
+
export function buildAcpMcpServers(servers) {
|
|
365
|
+
const enabled = servers.filter((s) => s.enabled && s.transport === 'stdio');
|
|
366
|
+
const out = [];
|
|
367
|
+
for (const s of enabled) {
|
|
368
|
+
const envEntries = [];
|
|
369
|
+
if (s.env) {
|
|
370
|
+
for (const [name, value] of Object.entries(s.env)) {
|
|
371
|
+
if (typeof value !== 'string')
|
|
372
|
+
continue;
|
|
373
|
+
envEntries.push({ name, value });
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
out.push({
|
|
377
|
+
type: 'stdio',
|
|
378
|
+
name: s.id,
|
|
379
|
+
command: s.command ?? '',
|
|
380
|
+
args: Array.isArray(s.args) ? [...s.args] : [],
|
|
381
|
+
env: envEntries,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
return out;
|
|
385
|
+
}
|
|
386
|
+
export function buildOpenCodeMcpConfigContent(servers, tokens = {}, options = {}) {
|
|
387
|
+
const enabled = servers.filter((s) => s.enabled);
|
|
388
|
+
const mcp = {};
|
|
389
|
+
for (const s of enabled) {
|
|
390
|
+
if (s.transport === 'stdio') {
|
|
391
|
+
const cmd = typeof s.command === 'string' ? s.command.trim() : '';
|
|
392
|
+
if (!cmd)
|
|
393
|
+
continue;
|
|
394
|
+
const entry = {
|
|
395
|
+
type: 'local',
|
|
396
|
+
command: [cmd, ...(Array.isArray(s.args) ? s.args : [])],
|
|
397
|
+
};
|
|
398
|
+
if (s.env && Object.keys(s.env).length > 0) {
|
|
399
|
+
entry.environment = { ...s.env };
|
|
400
|
+
}
|
|
401
|
+
entry.enabled = true;
|
|
402
|
+
mcp[s.id] = entry;
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
const url = typeof s.url === 'string' ? s.url.trim() : '';
|
|
406
|
+
if (!url)
|
|
407
|
+
continue;
|
|
408
|
+
const entry = {
|
|
409
|
+
type: 'remote',
|
|
410
|
+
url: s.url,
|
|
411
|
+
};
|
|
412
|
+
const headers = mergeAuthHeader(s.headers, effectiveMcpAuthMode(s) === 'oauth' ? tokens[s.id] : undefined);
|
|
413
|
+
if (headers && Object.keys(headers).length > 0)
|
|
414
|
+
entry.headers = headers;
|
|
415
|
+
entry.enabled = true;
|
|
416
|
+
mcp[s.id] = entry;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const externalDirectory = buildOpenCodeExternalDirectoryAllowlist(options.allowedDirectories);
|
|
420
|
+
const extraConfig = options.extraConfig ?? {};
|
|
421
|
+
if (Object.keys(mcp).length === 0 &&
|
|
422
|
+
!externalDirectory &&
|
|
423
|
+
Object.keys(extraConfig).length === 0)
|
|
424
|
+
return null;
|
|
425
|
+
const config = { ...extraConfig };
|
|
426
|
+
if (Object.keys(mcp).length > 0)
|
|
427
|
+
config.mcp = mcp;
|
|
428
|
+
if (externalDirectory) {
|
|
429
|
+
const priorPermission = config.permission && typeof config.permission === 'object' && !Array.isArray(config.permission)
|
|
430
|
+
? config.permission
|
|
431
|
+
: {};
|
|
432
|
+
config.permission = {
|
|
433
|
+
...priorPermission,
|
|
434
|
+
external_directory: externalDirectory,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
return JSON.stringify(config);
|
|
438
|
+
}
|
|
439
|
+
function buildOpenCodeExternalDirectoryAllowlist(directories) {
|
|
440
|
+
const normalized = Array.from(new Set((directories ?? [])
|
|
441
|
+
.filter((dir) => typeof dir === 'string' && dir.trim().length > 0)
|
|
442
|
+
.filter((dir) => path.isAbsolute(dir))
|
|
443
|
+
.flatMap((dir) => normalizeAllowedDirectoryVariants(dir))));
|
|
444
|
+
if (normalized.length === 0)
|
|
445
|
+
return null;
|
|
446
|
+
const allowlist = {};
|
|
447
|
+
for (const dir of normalized) {
|
|
448
|
+
allowlist[dir] = 'allow';
|
|
449
|
+
allowlist[joinPermissionGlob(dir, '*')] = 'allow';
|
|
450
|
+
allowlist[joinPermissionGlob(dir, '**')] = 'allow';
|
|
451
|
+
}
|
|
452
|
+
return allowlist;
|
|
453
|
+
}
|
|
454
|
+
function normalizeAllowedDirectory(dir) {
|
|
455
|
+
const resolved = path.resolve(dir);
|
|
456
|
+
const root = path.parse(resolved).root;
|
|
457
|
+
if (resolved === root)
|
|
458
|
+
return root;
|
|
459
|
+
return resolved.replace(/[\\/]+$/, '');
|
|
460
|
+
}
|
|
461
|
+
function normalizeAllowedDirectoryVariants(dir) {
|
|
462
|
+
const normalized = normalizeAllowedDirectory(dir);
|
|
463
|
+
let real = null;
|
|
464
|
+
try {
|
|
465
|
+
real = normalizeAllowedDirectory(realpathSync.native(dir));
|
|
466
|
+
}
|
|
467
|
+
catch {
|
|
468
|
+
real = null;
|
|
469
|
+
}
|
|
470
|
+
return real && real !== normalized ? [normalized, real] : [normalized];
|
|
471
|
+
}
|
|
472
|
+
function joinPermissionGlob(dir, suffix) {
|
|
473
|
+
return dir.endsWith(path.sep) ? `${dir}${suffix}` : `${dir}${path.sep}${suffix}`;
|
|
474
|
+
}
|
|
475
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/core
|
|
3
|
+
* Foundation kernel for the MCP domain: the shared config schema and IO
|
|
4
|
+
* (`config`), the OAuth 2.1 / PKCE client-credential flow (`oauth`), the
|
|
5
|
+
* per-server token store (`tokens`), and the install-payload builder
|
|
6
|
+
* (`install-info`). These are the pure, dependency-light primitives every other
|
|
7
|
+
* MCP concern (client, agent-install) and the daemon's routes and runtime build
|
|
8
|
+
* on. `core` imports no sibling subdirectory.
|
|
9
|
+
*/
|
|
10
|
+
export * from './config.js';
|
|
11
|
+
export * from './oauth.js';
|
|
12
|
+
export * from './tokens.js';
|
|
13
|
+
export * from './install-info.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/core
|
|
3
|
+
* Foundation kernel for the MCP domain: the shared config schema and IO
|
|
4
|
+
* (`config`), the OAuth 2.1 / PKCE client-credential flow (`oauth`), the
|
|
5
|
+
* per-server token store (`tokens`), and the install-payload builder
|
|
6
|
+
* (`install-info`). These are the pure, dependency-light primitives every other
|
|
7
|
+
* MCP concern (client, agent-install) and the daemon's routes and runtime build
|
|
8
|
+
* on. `core` imports no sibling subdirectory.
|
|
9
|
+
*/
|
|
10
|
+
export * from './config.js';
|
|
11
|
+
export * from './oauth.js';
|
|
12
|
+
export * from './tokens.js';
|
|
13
|
+
export * from './install-info.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/core/install-info
|
|
3
|
+
* Pure builder for the MCP install-info payload (command/args/env) shared by the
|
|
4
|
+
* daemon route, the settings UI, and its test fixture, so every install surface
|
|
5
|
+
* configures byte-identical bytes. Part of the MCP `core` kernel; intentionally
|
|
6
|
+
* side-effect-free and depends on no sibling subdirectory.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* All runtime facts the caller resolves before calling `buildMcpInstallPayload`.
|
|
10
|
+
* Kept as a plain-data interface so the builder stays side-effect-free and
|
|
11
|
+
* can be unit-tested with fake filesystem/env values.
|
|
12
|
+
*/
|
|
13
|
+
export interface BuildMcpInstallPayloadInputs {
|
|
14
|
+
cliPath: string;
|
|
15
|
+
cliExists: boolean;
|
|
16
|
+
execPath: string;
|
|
17
|
+
nodeExists: boolean;
|
|
18
|
+
port: number;
|
|
19
|
+
platform: NodeJS.Platform;
|
|
20
|
+
dataDir: string;
|
|
21
|
+
/** Env var name under which to pin the data directory so the spawned MCP
|
|
22
|
+
* process writes to the same directory the daemon uses even when the IDE
|
|
23
|
+
* that launched it does not inherit the packaged app's environment (e.g.
|
|
24
|
+
* `"JINI_DATA_DIR"`). */
|
|
25
|
+
dataDirEnvVar: string;
|
|
26
|
+
electronAsNode: boolean;
|
|
27
|
+
/** True when the daemon was bootstrapped as a sidecar and the spawned MCP
|
|
28
|
+
* process should discover the live URL via the IPC status socket instead
|
|
29
|
+
* of a baked `--daemon-url`. */
|
|
30
|
+
isSidecarMode: boolean;
|
|
31
|
+
/** Already-filtered sidecar transport env entries the caller wants
|
|
32
|
+
* propagated into the snippet. The caller decides what's worth
|
|
33
|
+
* propagating; this builder just merges. */
|
|
34
|
+
sidecarEnv: Record<string, string>;
|
|
35
|
+
/** Browser-facing base URL (e.g. `http://127.0.0.1:65321`). Used by MCP
|
|
36
|
+
* clients to build deep links so the outer agent can suggest a URL. Null
|
|
37
|
+
* when the daemon was launched without a known web port (headless). */
|
|
38
|
+
webBaseUrl?: string | null;
|
|
39
|
+
/** MCP subcommand the spawned CLI runs. Defaults to `"mcp"`. */
|
|
40
|
+
subcommand?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The install-info response shape: the command/args/env an MCP client must use
|
|
44
|
+
* to spawn the CLI's MCP subcommand, plus diagnostic flags and a human-readable
|
|
45
|
+
* `buildHint` describing any missing prerequisites.
|
|
46
|
+
*/
|
|
47
|
+
export interface McpInstallPayload {
|
|
48
|
+
command: string;
|
|
49
|
+
args: string[];
|
|
50
|
+
env: Record<string, string>;
|
|
51
|
+
daemonUrl: string;
|
|
52
|
+
/** Browser-facing base URL the daemon is paired with, when known. */
|
|
53
|
+
webBaseUrl: string | null;
|
|
54
|
+
platform: NodeJS.Platform;
|
|
55
|
+
cliExists: boolean;
|
|
56
|
+
nodeExists: boolean;
|
|
57
|
+
buildHint: string | null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build the `McpInstallPayload` from resolved runtime facts.
|
|
61
|
+
* Decides whether to bake `--daemon-url` into args (direct launch) or omit it
|
|
62
|
+
* (sidecar mode, where the spawned process discovers the URL via the IPC socket).
|
|
63
|
+
* Also pins the data-dir env var to prevent EPERM failures in packaged installs
|
|
64
|
+
* and injects `ELECTRON_RUN_AS_NODE=1` when running under Electron.
|
|
65
|
+
* @param inputs Runtime facts collected by the production route or test fixture.
|
|
66
|
+
* @returns The install payload; `buildHint` is non-null when prerequisites are missing.
|
|
67
|
+
*/
|
|
68
|
+
export declare function buildMcpInstallPayload(inputs: BuildMcpInstallPayloadInputs): McpInstallPayload;
|
|
69
|
+
//# sourceMappingURL=install-info.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-info.d.ts","sourceRoot":"","sources":["../../src/core/install-info.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB;;;8BAG0B;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB;;qCAEiC;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB;;iDAE6C;IAC7C,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;4EAEwE;IACxE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,4BAA4B,GACnC,iBAAiB,CAuDnB"}
|