@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.
Files changed (86) hide show
  1. package/LICENSE +201 -0
  2. package/dist/agent-install/index.d.ts +9 -0
  3. package/dist/agent-install/index.d.ts.map +1 -0
  4. package/dist/agent-install/index.js +9 -0
  5. package/dist/agent-install/index.js.map +1 -0
  6. package/dist/agent-install/install.d.ts +97 -0
  7. package/dist/agent-install/install.d.ts.map +1 -0
  8. package/dist/agent-install/install.js +410 -0
  9. package/dist/agent-install/install.js.map +1 -0
  10. package/dist/bin/serve.d.ts +75 -0
  11. package/dist/bin/serve.d.ts.map +1 -0
  12. package/dist/bin/serve.js +79 -0
  13. package/dist/bin/serve.js.map +1 -0
  14. package/dist/client/client.d.ts +48 -0
  15. package/dist/client/client.d.ts.map +1 -0
  16. package/dist/client/client.js +242 -0
  17. package/dist/client/client.js.map +1 -0
  18. package/dist/client/index.d.ts +8 -0
  19. package/dist/client/index.d.ts.map +1 -0
  20. package/dist/client/index.js +8 -0
  21. package/dist/client/index.js.map +1 -0
  22. package/dist/core/config.d.ts +157 -0
  23. package/dist/core/config.d.ts.map +1 -0
  24. package/dist/core/config.js +475 -0
  25. package/dist/core/config.js.map +1 -0
  26. package/dist/core/index.d.ts +14 -0
  27. package/dist/core/index.d.ts.map +1 -0
  28. package/dist/core/index.js +14 -0
  29. package/dist/core/index.js.map +1 -0
  30. package/dist/core/install-info.d.ts +69 -0
  31. package/dist/core/install-info.d.ts.map +1 -0
  32. package/dist/core/install-info.js +79 -0
  33. package/dist/core/install-info.js.map +1 -0
  34. package/dist/core/oauth.d.ts +274 -0
  35. package/dist/core/oauth.d.ts.map +1 -0
  36. package/dist/core/oauth.js +667 -0
  37. package/dist/core/oauth.js.map +1 -0
  38. package/dist/core/secure-write.d.ts +17 -0
  39. package/dist/core/secure-write.d.ts.map +1 -0
  40. package/dist/core/secure-write.js +72 -0
  41. package/dist/core/secure-write.js.map +1 -0
  42. package/dist/core/tokens.d.ts +72 -0
  43. package/dist/core/tokens.d.ts.map +1 -0
  44. package/dist/core/tokens.js +197 -0
  45. package/dist/core/tokens.js.map +1 -0
  46. package/dist/index.d.ts +28 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +29 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/server/daemon-client.d.ts +21 -0
  51. package/dist/server/daemon-client.d.ts.map +1 -0
  52. package/dist/server/daemon-client.js +176 -0
  53. package/dist/server/daemon-client.js.map +1 -0
  54. package/dist/server/index.d.ts +18 -0
  55. package/dist/server/index.d.ts.map +1 -0
  56. package/dist/server/index.js +18 -0
  57. package/dist/server/index.js.map +1 -0
  58. package/dist/server/resource-protocol.d.ts +38 -0
  59. package/dist/server/resource-protocol.d.ts.map +1 -0
  60. package/dist/server/resource-protocol.js +68 -0
  61. package/dist/server/resource-protocol.js.map +1 -0
  62. package/dist/server/resources/active-resource.d.ts +12 -0
  63. package/dist/server/resources/active-resource.d.ts.map +1 -0
  64. package/dist/server/resources/active-resource.js +46 -0
  65. package/dist/server/resources/active-resource.js.map +1 -0
  66. package/dist/server/tool-protocol.d.ts +45 -0
  67. package/dist/server/tool-protocol.d.ts.map +1 -0
  68. package/dist/server/tool-protocol.js +74 -0
  69. package/dist/server/tool-protocol.js.map +1 -0
  70. package/dist/server/tool-server.d.ts +105 -0
  71. package/dist/server/tool-server.d.ts.map +1 -0
  72. package/dist/server/tool-server.js +96 -0
  73. package/dist/server/tool-server.js.map +1 -0
  74. package/dist/server/tools/delegated-tool.d.ts +15 -0
  75. package/dist/server/tools/delegated-tool.d.ts.map +1 -0
  76. package/dist/server/tools/delegated-tool.js +90 -0
  77. package/dist/server/tools/delegated-tool.js.map +1 -0
  78. package/dist/server/tools/run-tools.d.ts +14 -0
  79. package/dist/server/tools/run-tools.d.ts.map +1 -0
  80. package/dist/server/tools/run-tools.js +142 -0
  81. package/dist/server/tools/run-tools.js.map +1 -0
  82. package/dist/server/tools/tool-catalog-tools.d.ts +8 -0
  83. package/dist/server/tools/tool-catalog-tools.d.ts.map +1 -0
  84. package/dist/server/tools/tool-catalog-tools.js +66 -0
  85. package/dist/server/tools/tool-catalog-tools.js.map +1 -0
  86. 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"}