@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,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/client/client
|
|
3
|
+
* Product-neutral runtime primitives for a stdio MCP server: an idle-exit
|
|
4
|
+
* controller that auto-closes an idle server process, a relative-reference
|
|
5
|
+
* extractor that walks HTML/CSS/JS text to find sibling files to bundle, and a
|
|
6
|
+
* textual-MIME classifier. Dependency-free (node stdlib only); imports no
|
|
7
|
+
* sibling MCP subdirectory.
|
|
8
|
+
*/
|
|
9
|
+
// These are the generic, product-agnostic building blocks that back a stdio
|
|
10
|
+
// MCP server's lifecycle and its "pull an entry file plus everything it
|
|
11
|
+
// references" bundling. They hold no state beyond the idle controller's own
|
|
12
|
+
// timer and never touch the network or filesystem, so they unit-test against
|
|
13
|
+
// plain values.
|
|
14
|
+
// SEC-RB-011: an unvalidated `idleMs` (negative, `NaN`, `Infinity`, or a
|
|
15
|
+
// non-integer) would either schedule an immediately/never-firing timer or
|
|
16
|
+
// hand `setTimeout` a value it silently coerces in surprising ways. Bound it
|
|
17
|
+
// to a sane, documented range instead: reject anything that isn't a finite
|
|
18
|
+
// positive integer (a caller bug, not something to silently paper over), and
|
|
19
|
+
// clamp anything absurdly large down to a one-day ceiling rather than
|
|
20
|
+
// scheduling an effectively-infinite timer.
|
|
21
|
+
const MIN_IDLE_MS = 1;
|
|
22
|
+
const MAX_IDLE_MS = 24 * 60 * 60 * 1000; // 24h
|
|
23
|
+
function normalizeIdleMs(idleMs) {
|
|
24
|
+
if (typeof idleMs !== 'number' || !Number.isFinite(idleMs) || !Number.isInteger(idleMs) || idleMs < MIN_IDLE_MS) {
|
|
25
|
+
throw new RangeError(`createMcpIdleExitController: idleMs must be a finite positive integer (>= ${MIN_IDLE_MS}ms), got ${String(idleMs)}`);
|
|
26
|
+
}
|
|
27
|
+
return Math.min(idleMs, MAX_IDLE_MS);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create an idle-exit controller that calls `onIdle` after `idleMs` of
|
|
31
|
+
* inactivity. Activity is tracked via `noteActivity()` and `trackRequest()`;
|
|
32
|
+
* in-flight requests defer the idle timer. Used to auto-close a long-running
|
|
33
|
+
* stdio MCP server process after a period of no tool calls.
|
|
34
|
+
* @param options Idle duration in ms (finite positive integer, clamped to a
|
|
35
|
+
* 24h ceiling — throws `RangeError` otherwise) and the callback to invoke on idle.
|
|
36
|
+
* @returns An object with `noteActivity`, `trackRequest`, and `dispose` methods.
|
|
37
|
+
*/
|
|
38
|
+
export function createMcpIdleExitController({ idleMs, onIdle, }) {
|
|
39
|
+
const effectiveIdleMs = normalizeIdleMs(idleMs);
|
|
40
|
+
let timer = null;
|
|
41
|
+
let inFlight = 0;
|
|
42
|
+
let disposed = false;
|
|
43
|
+
const clear = () => {
|
|
44
|
+
if (timer) {
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
timer = null;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const schedule = () => {
|
|
50
|
+
if (disposed)
|
|
51
|
+
return;
|
|
52
|
+
clear();
|
|
53
|
+
timer = setTimeout(() => {
|
|
54
|
+
// `dispose()` always clears the pending timer and `schedule()` bails when
|
|
55
|
+
// already disposed, so this callback can only fire while live.
|
|
56
|
+
timer = null;
|
|
57
|
+
if (inFlight > 0) {
|
|
58
|
+
schedule();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
disposed = true;
|
|
62
|
+
onIdle();
|
|
63
|
+
}, effectiveIdleMs);
|
|
64
|
+
};
|
|
65
|
+
schedule();
|
|
66
|
+
return {
|
|
67
|
+
noteActivity() {
|
|
68
|
+
schedule();
|
|
69
|
+
},
|
|
70
|
+
async trackRequest(fn) {
|
|
71
|
+
if (disposed) {
|
|
72
|
+
return fn();
|
|
73
|
+
}
|
|
74
|
+
inFlight += 1;
|
|
75
|
+
// Deliberately does NOT call `schedule()` here (SEC-RB-011): a request
|
|
76
|
+
// starting while the timer is already running doesn't need to reset
|
|
77
|
+
// the deadline — the timer, if it fires mid-flight, already re-checks
|
|
78
|
+
// `inFlight` and reschedules itself (above), and completion below
|
|
79
|
+
// reschedules once the last in-flight request finishes. Rescheduling
|
|
80
|
+
// on every concurrent request start instead caused needless
|
|
81
|
+
// clearTimeout/setTimeout churn under load with no behavioral benefit.
|
|
82
|
+
try {
|
|
83
|
+
return await fn();
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
inFlight -= 1;
|
|
87
|
+
if (inFlight === 0) {
|
|
88
|
+
schedule();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
dispose() {
|
|
93
|
+
disposed = true;
|
|
94
|
+
clear();
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Mimes whose body a stdio MCP server can surface as `text` content.
|
|
99
|
+
const TEXTUAL_MIME_PATTERNS = [
|
|
100
|
+
/^text\//i,
|
|
101
|
+
/^application\/json\b/i,
|
|
102
|
+
/^application\/javascript\b/i,
|
|
103
|
+
/^application\/typescript\b/i,
|
|
104
|
+
/^application\/xml\b/i,
|
|
105
|
+
/^application\/x-(yaml|toml|httpd-php|sh)\b/i,
|
|
106
|
+
/\+json\b/i,
|
|
107
|
+
/\+xml\b/i,
|
|
108
|
+
/^image\/svg\+xml\b/i,
|
|
109
|
+
];
|
|
110
|
+
/**
|
|
111
|
+
* True when `mime` names a textual content type whose body can be surfaced
|
|
112
|
+
* as MCP `text` content (text/*, JSON, JS/TS, XML, YAML/TOML/PHP/sh, `+json`
|
|
113
|
+
* / `+xml` suffixes, and SVG). Returns false for an absent/unknown mime.
|
|
114
|
+
* @param mime The MIME type string to classify (undefined counts as non-textual).
|
|
115
|
+
* @returns Whether the content should be treated as text.
|
|
116
|
+
*/
|
|
117
|
+
export function isTextualMime(mime) {
|
|
118
|
+
if (!mime)
|
|
119
|
+
return false;
|
|
120
|
+
return TEXTUAL_MIME_PATTERNS.some((re) => re.test(mime));
|
|
121
|
+
}
|
|
122
|
+
// Patterns common to HTML and CSS (also fine to run on plain markdown).
|
|
123
|
+
const HTML_REF_PATTERNS = [
|
|
124
|
+
/<script\b[^>]*\bsrc=["']([^"']+)["']/gi,
|
|
125
|
+
/<link\b[^>]*\bhref=["']([^"']+)["']/gi,
|
|
126
|
+
/<img\b[^>]*\bsrc=["']([^"']+)["']/gi,
|
|
127
|
+
/<source\b[^>]*\bsrc=["']([^"']+)["']/gi,
|
|
128
|
+
/<video\b[^>]*\bsrc=["']([^"']+)["']/gi,
|
|
129
|
+
/<audio\b[^>]*\bsrc=["']([^"']+)["']/gi,
|
|
130
|
+
/<iframe\b[^>]*\bsrc=["']([^"']+)["']/gi,
|
|
131
|
+
];
|
|
132
|
+
const CSS_REF_PATTERNS = [
|
|
133
|
+
/\burl\(\s*["']?([^"')]+)["']?\s*\)/gi,
|
|
134
|
+
/@import\s+(?:url\()?\s*["']([^"')]+)["']/gi,
|
|
135
|
+
];
|
|
136
|
+
// JS/TS only - running these on prose creates false positives on words
|
|
137
|
+
// like "imported from 'X'".
|
|
138
|
+
const JS_REF_PATTERNS = [
|
|
139
|
+
/\bimport\s+[^'"]*?['"]([^'"]+)['"]/g,
|
|
140
|
+
/\bfrom\s+['"]([^'"]+)['"]/g,
|
|
141
|
+
/\bimport\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
142
|
+
/\brequire\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
143
|
+
];
|
|
144
|
+
// `srcset` can list multiple comma-separated candidates.
|
|
145
|
+
const SRCSET_PATTERN = /\bsrcset=["']([^"']+)["']/gi;
|
|
146
|
+
function isJsLike(mime, fromPath) {
|
|
147
|
+
if (mime && /javascript|typescript/i.test(mime))
|
|
148
|
+
return true;
|
|
149
|
+
return /\.(?:m?jsx?|tsx?|cjs)$/i.test(fromPath);
|
|
150
|
+
}
|
|
151
|
+
function isCssLike(mime, fromPath) {
|
|
152
|
+
if (mime && /^text\/css\b/i.test(mime))
|
|
153
|
+
return true;
|
|
154
|
+
return /\.css$/i.test(fromPath);
|
|
155
|
+
}
|
|
156
|
+
function isHtmlLike(mime, fromPath) {
|
|
157
|
+
if (mime && /^text\/html\b/i.test(mime))
|
|
158
|
+
return true;
|
|
159
|
+
return /\.html?$/i.test(fromPath);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Extract all relative (non-absolute, non-CDN, non-data-URI) file references from
|
|
163
|
+
* the text content of a file, normalized to root-relative paths.
|
|
164
|
+
* Runs HTML, CSS, and/or JS pattern sets based on the file's MIME type and extension.
|
|
165
|
+
* Skips `https?:`, `//`, `data:`, `mailto:`, `tel:`, and `#` prefixes; drops any
|
|
166
|
+
* reference that would escape the root via `..` traversal.
|
|
167
|
+
* @param text The textual content of the file.
|
|
168
|
+
* @param fromPath The root-relative path of the file (used for relative-path resolution).
|
|
169
|
+
* @param fromMime The MIME type of the file (used to select reference-extraction patterns).
|
|
170
|
+
* @returns Deduplicated root-relative paths of all referenced files found.
|
|
171
|
+
*/
|
|
172
|
+
export function extractRelativeRefs(text, fromPath, fromMime) {
|
|
173
|
+
if (!text)
|
|
174
|
+
return [];
|
|
175
|
+
const refs = new Set();
|
|
176
|
+
const runPatterns = [];
|
|
177
|
+
if (isHtmlLike(fromMime, fromPath)) {
|
|
178
|
+
runPatterns.push(...HTML_REF_PATTERNS, ...CSS_REF_PATTERNS);
|
|
179
|
+
}
|
|
180
|
+
if (isCssLike(fromMime, fromPath)) {
|
|
181
|
+
runPatterns.push(...CSS_REF_PATTERNS);
|
|
182
|
+
}
|
|
183
|
+
if (isJsLike(fromMime, fromPath)) {
|
|
184
|
+
runPatterns.push(...JS_REF_PATTERNS);
|
|
185
|
+
}
|
|
186
|
+
// Fallback for unknown textual files: only the safest pattern,
|
|
187
|
+
// url() in case it's a CSS-in-something we don't recognize.
|
|
188
|
+
if (runPatterns.length === 0) {
|
|
189
|
+
runPatterns.push(...CSS_REF_PATTERNS);
|
|
190
|
+
}
|
|
191
|
+
const candidates = [];
|
|
192
|
+
for (const re of runPatterns) {
|
|
193
|
+
for (const m of text.matchAll(re)) {
|
|
194
|
+
// The capture group is required in every pattern, so `m[1]` is always a
|
|
195
|
+
// matched string here (the `!` only satisfies noUncheckedIndexedAccess).
|
|
196
|
+
const ref = m[1].trim();
|
|
197
|
+
if (ref)
|
|
198
|
+
candidates.push(ref);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Pull every candidate URL out of any srcset attributes in HTML.
|
|
202
|
+
if (isHtmlLike(fromMime, fromPath)) {
|
|
203
|
+
for (const m of text.matchAll(SRCSET_PATTERN)) {
|
|
204
|
+
const list = m[1];
|
|
205
|
+
for (const part of list.split(',')) {
|
|
206
|
+
const url = part.trim().split(/\s+/)[0];
|
|
207
|
+
if (url)
|
|
208
|
+
candidates.push(url);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
for (const raw of candidates) {
|
|
213
|
+
if (/^(?:https?:|\/\/|data:|mailto:|tel:|#)/i.test(raw))
|
|
214
|
+
continue;
|
|
215
|
+
const dir = fromPath.includes('/')
|
|
216
|
+
? fromPath.slice(0, fromPath.lastIndexOf('/') + 1)
|
|
217
|
+
: '';
|
|
218
|
+
const resolved = raw.startsWith('/') ? raw.slice(1) : dir + raw;
|
|
219
|
+
const stripped = resolved.replace(/[?#].*$/, '');
|
|
220
|
+
const segs = stripped.split('/').filter(Boolean);
|
|
221
|
+
const out = [];
|
|
222
|
+
let escaped = false;
|
|
223
|
+
for (const s of segs) {
|
|
224
|
+
if (s === '.')
|
|
225
|
+
continue;
|
|
226
|
+
if (s === '..') {
|
|
227
|
+
if (out.length === 0) {
|
|
228
|
+
escaped = true;
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
out.pop();
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
out.push(s);
|
|
235
|
+
}
|
|
236
|
+
if (escaped || out.length === 0)
|
|
237
|
+
continue;
|
|
238
|
+
refs.add(out.join('/'));
|
|
239
|
+
}
|
|
240
|
+
return [...refs];
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/client
|
|
3
|
+
* Product-neutral runtime primitives for a stdio MCP server: the idle-exit
|
|
4
|
+
* controller, the relative-reference extractor, and the textual-MIME
|
|
5
|
+
* classifier. Depends on node stdlib only; imports no sibling MCP subdirectory.
|
|
6
|
+
*/
|
|
7
|
+
export * from './client.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/client
|
|
3
|
+
* Product-neutral runtime primitives for a stdio MCP server: the idle-exit
|
|
4
|
+
* controller, the relative-reference extractor, and the textual-MIME
|
|
5
|
+
* classifier. Depends on node stdlib only; imports no sibling MCP subdirectory.
|
|
6
|
+
*/
|
|
7
|
+
export * from './client.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,157 @@
|
|
|
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
|
+
/** Wire-level transport discriminator for how the daemon connects to an external MCP server. */
|
|
9
|
+
export type McpTransport = 'stdio' | 'sse' | 'http';
|
|
10
|
+
/** Authentication mode for remote MCP servers: `'none'` for local/loopback targets, `'oauth'` for remote ones. */
|
|
11
|
+
export type McpAuthMode = 'none' | 'oauth';
|
|
12
|
+
/**
|
|
13
|
+
* Persisted configuration for a single external MCP server the user has added.
|
|
14
|
+
* Stored as an element of `McpConfig.servers` in `<dataDir>/mcp-config.json`.
|
|
15
|
+
*/
|
|
16
|
+
export interface McpServerConfig {
|
|
17
|
+
id: string;
|
|
18
|
+
label?: string;
|
|
19
|
+
transport: McpTransport;
|
|
20
|
+
enabled: boolean;
|
|
21
|
+
authMode?: McpAuthMode;
|
|
22
|
+
command?: string;
|
|
23
|
+
args?: string[];
|
|
24
|
+
env?: Record<string, string>;
|
|
25
|
+
url?: string;
|
|
26
|
+
headers?: Record<string, string>;
|
|
27
|
+
}
|
|
28
|
+
/** Top-level on-disk shape of `<dataDir>/mcp-config.json`. */
|
|
29
|
+
export interface McpConfig {
|
|
30
|
+
servers: McpServerConfig[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Infer the appropriate `McpAuthMode` for a given server URL.
|
|
34
|
+
* Returns `'none'` for loopback targets (localhost, 127.x.x.x, ::1)
|
|
35
|
+
* and `'oauth'` for everything else, including when `rawUrl` is absent or unparseable.
|
|
36
|
+
* @param rawUrl The server URL string to inspect, if any.
|
|
37
|
+
* @returns The inferred `McpAuthMode`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function inferMcpAuthModeForUrl(rawUrl: string | undefined): McpAuthMode;
|
|
40
|
+
/**
|
|
41
|
+
* Validate a single user-supplied entry. Drops invalid fields so a typo in
|
|
42
|
+
* one server doesn't tank the whole config. Returns null when the entry is
|
|
43
|
+
* unsalvageable (no id, or no transport-required fields).
|
|
44
|
+
*/
|
|
45
|
+
export declare function sanitizeMcpServer(raw: unknown): McpServerConfig | null;
|
|
46
|
+
/**
|
|
47
|
+
* Coerce and de-duplicate a freeform JSON blob into a valid `McpConfig`.
|
|
48
|
+
* Entries that fail `sanitizeMcpServer` are silently dropped; duplicate ids
|
|
49
|
+
* are kept first-wins. Returns `{ servers: [] }` for any non-object input.
|
|
50
|
+
* @param raw The raw parsed JSON to sanitize.
|
|
51
|
+
* @returns A clean `McpConfig` guaranteed to have only valid, unique server entries.
|
|
52
|
+
*/
|
|
53
|
+
export declare function sanitizeMcpConfig(raw: unknown): McpConfig;
|
|
54
|
+
/**
|
|
55
|
+
* Read and sanitize the MCP config from `<dataDir>/mcp-config.json`.
|
|
56
|
+
* Returns `{ servers: [] }` when the file does not exist or contains invalid JSON.
|
|
57
|
+
* @param dataDir The resolved runtime data directory.
|
|
58
|
+
* @returns The sanitized `McpConfig`, never rejects on missing-file or corrupt-JSON.
|
|
59
|
+
*/
|
|
60
|
+
export declare function readMcpConfig(dataDir: string): Promise<McpConfig>;
|
|
61
|
+
/**
|
|
62
|
+
* Sanitize and atomically write the MCP config to `<dataDir>/mcp-config.json`.
|
|
63
|
+
* Uses a per-`dataDir` promise-chain mutex so concurrent writes serialize
|
|
64
|
+
* instead of racing. The body is sanitized through `sanitizeMcpConfig` before
|
|
65
|
+
* being written. This file may carry environment variables and
|
|
66
|
+
* `Authorization` header values (API keys, bearer tokens — see
|
|
67
|
+
* `McpServerConfig.env`/`.headers`), so it is written with owner-only
|
|
68
|
+
* (0600) permissions from the very first byte via `writeSecretFileAtomic`
|
|
69
|
+
* rather than a post-rename chmod (CR-006 / SEC-RB-002).
|
|
70
|
+
* @param dataDir The resolved runtime data directory.
|
|
71
|
+
* @param body The raw config body to sanitize and persist.
|
|
72
|
+
* @returns The sanitized `McpConfig` that was written to disk.
|
|
73
|
+
*/
|
|
74
|
+
export declare function writeMcpConfig(dataDir: string, body: unknown): Promise<McpConfig>;
|
|
75
|
+
/**
|
|
76
|
+
* True when `cwd` is a daemon-managed project directory under `projectsDir`
|
|
77
|
+
* (= safe to write `.mcp.json` into without risk of clobbering a user-owned
|
|
78
|
+
* file). Git-linked projects whose cwd points at the user's own repo, and
|
|
79
|
+
* the no-project fallback that resolves to the project root, both return false
|
|
80
|
+
* — the daemon must NOT write external-MCP config into either of those.
|
|
81
|
+
*
|
|
82
|
+
* Both `cwd` and `projectsDir` are realpath-resolved before the containment
|
|
83
|
+
* check (falling back to lexical `path.resolve` normalization for a path
|
|
84
|
+
* that doesn't exist on disk yet), and containment is decided with
|
|
85
|
+
* `@jini-ai/platform`'s separator-aware `pathContains` rather than a raw
|
|
86
|
+
* string-prefix check — a `..`-containing path or a symlinked descendant
|
|
87
|
+
* can defeat a plain `startsWith` (CR-006 / SEC-RB-011).
|
|
88
|
+
*/
|
|
89
|
+
export declare function isManagedProjectCwd(cwd: string | null | undefined, projectsDir: string): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Project-cwd `.mcp.json` shape that Claude Code auto-loads on spawn (the
|
|
92
|
+
* same format Claude Desktop and Cursor use). Returns null when the user
|
|
93
|
+
* has no enabled servers — in that case the caller should NOT write the
|
|
94
|
+
* file (and should clean up any stale one).
|
|
95
|
+
*
|
|
96
|
+
* `tokens` is an optional map of `serverId -> bearer access token`, used
|
|
97
|
+
* for HTTP/SSE servers that completed the daemon's web OAuth flow. When a
|
|
98
|
+
* token is present we inject `Authorization: Bearer <token>` into the
|
|
99
|
+
* server's headers — this is what bypasses the per-spawn `mcp-remote`
|
|
100
|
+
* dance and lets Claude Code talk directly to the upstream MCP using
|
|
101
|
+
* pre-authenticated credentials. User-supplied headers always win on
|
|
102
|
+
* conflict so they can pin a specific token if they really want to.
|
|
103
|
+
*/
|
|
104
|
+
export declare function buildClaudeMcpJson(servers: McpServerConfig[], tokens?: Record<string, string>): unknown | null;
|
|
105
|
+
/**
|
|
106
|
+
* Convert user-configured external MCP servers into the ACP `mcpServers`
|
|
107
|
+
* shape that stdio-capable ACP agents accept.
|
|
108
|
+
* SSE/HTTP servers are dropped — ACP currently models stdio only.
|
|
109
|
+
*/
|
|
110
|
+
export interface AcpMcpServer {
|
|
111
|
+
type: 'stdio';
|
|
112
|
+
name: string;
|
|
113
|
+
command: string;
|
|
114
|
+
args: string[];
|
|
115
|
+
env: Array<{
|
|
116
|
+
name: string;
|
|
117
|
+
value: string;
|
|
118
|
+
}>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Convert user-configured external MCP servers into the ACP `mcpServers` array.
|
|
122
|
+
* Only stdio servers are included — SSE/HTTP are dropped because ACP currently
|
|
123
|
+
* models stdio only. Returns an empty array when no enabled stdio servers exist.
|
|
124
|
+
* @param servers The full server list from `McpConfig`.
|
|
125
|
+
* @returns ACP-shaped server entries for all enabled stdio servers.
|
|
126
|
+
*/
|
|
127
|
+
export declare function buildAcpMcpServers(servers: McpServerConfig[]): AcpMcpServer[];
|
|
128
|
+
/**
|
|
129
|
+
* OpenCode merges its config from multiple sources at boot — global
|
|
130
|
+
* `~/.config/opencode/opencode.json`, the `OPENCODE_CONFIG` file path, the
|
|
131
|
+
* project `opencode.json`, and the `OPENCODE_CONFIG_CONTENT` env var (an
|
|
132
|
+
* inline JSON string). The env-var path is what lets a launcher hand servers
|
|
133
|
+
* to a single `opencode run` invocation without writing into the user's
|
|
134
|
+
* global config or leaving a temp file around on crash. We also use the same
|
|
135
|
+
* payload to grant `external_directory` access to launcher-selected absolute
|
|
136
|
+
* paths (project cwd, staged skill dirs, etc.) so headless OpenCode runs do
|
|
137
|
+
* not auto-reject them.
|
|
138
|
+
*
|
|
139
|
+
* Returns `null` when nothing would be emitted — the caller must NOT set
|
|
140
|
+
* `OPENCODE_CONFIG_CONTENT` to `null`/empty in that case, because doing so
|
|
141
|
+
* would override the user's saved global config with an empty object. A
|
|
142
|
+
* null return means "leave the env untouched and let OpenCode read the
|
|
143
|
+
* user's home-dir config as-is."
|
|
144
|
+
*
|
|
145
|
+
* The OAuth Bearer merge mirrors `buildClaudeMcpJson` so a remote MCP
|
|
146
|
+
* server the daemon already authenticated against works the same way for
|
|
147
|
+
* OpenCode users without forcing them to re-authenticate inside OpenCode.
|
|
148
|
+
*/
|
|
149
|
+
/** Options for `buildOpenCodeMcpConfigContent`. */
|
|
150
|
+
export interface OpenCodeConfigBuildOptions {
|
|
151
|
+
/** Absolute filesystem paths OpenCode's `external_directory` permission should allow. */
|
|
152
|
+
allowedDirectories?: string[];
|
|
153
|
+
/** Additional top-level keys merged into the emitted config object (e.g. `provider`). */
|
|
154
|
+
extraConfig?: Record<string, unknown>;
|
|
155
|
+
}
|
|
156
|
+
export declare function buildOpenCodeMcpConfigContent(servers: McpServerConfig[], tokens?: Record<string, string>, options?: OpenCodeConfigBuildOptions): string | null;
|
|
157
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAsBH,gGAAgG;AAChG,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AACpD,kHAAkH;AAClH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3C;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,YAAY,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,8DAA8D;AAC9D,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AA+DD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAO9E;AAeD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAwCtE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,CAazD;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAcvE;AAID;;;;;;;;;;;;GAYG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,OAAO,GACZ,OAAO,CAAC,SAAS,CAAC,CASpB;AAyBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC9B,WAAW,EAAE,MAAM,GAClB,OAAO,CAOT;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,eAAe,EAAE,EAC1B,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAClC,OAAO,GAAG,IAAI,CAwBhB;AAiCD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7C;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,YAAY,EAAE,CAoB7E;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,mDAAmD;AACnD,MAAM,WAAW,0BAA0B;IACzC,yFAAyF;IACzF,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,yFAAyF;IACzF,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,eAAe,EAAE,EAC1B,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EACnC,OAAO,GAAE,0BAA+B,GACvC,MAAM,GAAG,IAAI,CAuDf"}
|