@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,410 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/agent-install/install
|
|
3
|
+
* Plans and applies registration of a stdio MCP server into external coding
|
|
4
|
+
* agents' own configs (`<cli> mcp install <agent>`): the agent-slug registry,
|
|
5
|
+
* the CLI/JSON/manual install-plan shapes, and the JSON apply/remove primitives.
|
|
6
|
+
* Pure planning logic; imports no sibling MCP subdirectory.
|
|
7
|
+
*/
|
|
8
|
+
// Per-agent MCP registration planner.
|
|
9
|
+
//
|
|
10
|
+
// `<cli> mcp install <agent>` (and any hosted bootstrap that calls it) wires
|
|
11
|
+
// a stdio MCP server into a coding agent's own configuration. Each agent
|
|
12
|
+
// stores MCP servers differently, so this module maps a single resolved
|
|
13
|
+
// launch spec (command/args/env — the same shape buildMcpInstallPayload
|
|
14
|
+
// produces and the settings UI pastes) onto one of three registration
|
|
15
|
+
// strategies:
|
|
16
|
+
//
|
|
17
|
+
// - 'cli' : the agent ships its own `<bin> mcp add/remove/get`. We
|
|
18
|
+
// shell out to it so we inherit the agent's merge/validation
|
|
19
|
+
// rules instead of editing its config by hand. Used for
|
|
20
|
+
// claude / codex / kimi.
|
|
21
|
+
// - 'json' : the agent reads a JSON config file with a known schema.
|
|
22
|
+
// We deep-merge one server entry, never clobbering the
|
|
23
|
+
// rest of the file. Used for cursor / copilot / cline /
|
|
24
|
+
// opencode / openclaw / antigravity / trae.
|
|
25
|
+
// - 'manual' : we could not verify the agent's config path/format
|
|
26
|
+
// authoritatively (pi / hermes / vibe). We refuse to write
|
|
27
|
+
// a guessed path and instead print a ready-to-paste
|
|
28
|
+
// snippet plus the best-known location. Writing a wrong
|
|
29
|
+
// path risks corrupting a user-owned config, so this stays
|
|
30
|
+
// a print-only path until the format is confirmed.
|
|
31
|
+
//
|
|
32
|
+
// The planning functions are pure (no fs / spawn) so they unit-test
|
|
33
|
+
// against fixed launch specs + a fake home dir; the executor performs the IO.
|
|
34
|
+
import path from 'node:path';
|
|
35
|
+
/**
|
|
36
|
+
* Exhaustive tuple of all agent slugs recognized by `mcp install`.
|
|
37
|
+
* Used as the source of truth for the `AgentSlug` union type and the `isAgentSlug` guard.
|
|
38
|
+
*/
|
|
39
|
+
export const AGENT_SLUGS = [
|
|
40
|
+
'claude',
|
|
41
|
+
'codex',
|
|
42
|
+
'cursor',
|
|
43
|
+
'copilot',
|
|
44
|
+
'openclaw',
|
|
45
|
+
'antigravity',
|
|
46
|
+
'pi',
|
|
47
|
+
'vibe',
|
|
48
|
+
'hermes',
|
|
49
|
+
'cline',
|
|
50
|
+
'kimi',
|
|
51
|
+
'trae',
|
|
52
|
+
'opencode',
|
|
53
|
+
];
|
|
54
|
+
/**
|
|
55
|
+
* Type guard: returns `true` when `value` is a recognized `AgentSlug`.
|
|
56
|
+
* Used by the CLI argument parser to surface a clear error for unknown slugs.
|
|
57
|
+
* @param value The string to test.
|
|
58
|
+
* @returns `true` if `value` is a valid `AgentSlug`, `false` otherwise.
|
|
59
|
+
*/
|
|
60
|
+
export function isAgentSlug(value) {
|
|
61
|
+
return AGENT_SLUGS.includes(value);
|
|
62
|
+
}
|
|
63
|
+
// RESIDUAL RISK (CR-006 / SEC-RB-002): `-e`/`--env KEY=VALUE` is claude's,
|
|
64
|
+
// codex's, and kimi's own documented `mcp add` CLI contract for passing
|
|
65
|
+
// server env vars — a fixed, external interface this package does not
|
|
66
|
+
// control and cannot change unilaterally. Because these values land in
|
|
67
|
+
// `addArgv` (argv), they are visible to any other local process that can
|
|
68
|
+
// list this process's command line (e.g. `ps -ww`) for the — typically very
|
|
69
|
+
// brief — window while the daemon's executor shells out to `claude`/`codex`/
|
|
70
|
+
// `kimi mcp add`. This package only builds the plan (`planAgentInstall`
|
|
71
|
+
// itself performs no fs/spawn, per this file's header comment); there is no
|
|
72
|
+
// executor here yet to redact `addArgv` before logging it, so there is
|
|
73
|
+
// nothing left in this package's own code to redact. Whichever executor
|
|
74
|
+
// eventually drives these plans MUST NOT log/echo `addArgv` verbatim
|
|
75
|
+
// (redact anything that looks like an env value from `-e`/`--env` pairs
|
|
76
|
+
// before writing it to any log/error surface), and should prefer a
|
|
77
|
+
// less-exposed handoff (e.g. piping `env` via stdin, or setting it directly
|
|
78
|
+
// in the spawned child's environment) for any future agent whose CLI
|
|
79
|
+
// supports that instead of argv-only `KEY=VALUE`.
|
|
80
|
+
function envFlags(env, flag) {
|
|
81
|
+
const out = [];
|
|
82
|
+
for (const [k, v] of Object.entries(env)) {
|
|
83
|
+
out.push(flag, `${k}=${v}`);
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
/** JSON server entry shared by the `env`-style agents (cursor / copilot /
|
|
88
|
+
* cline / openclaw / antigravity / trae). `extra` carries per-agent
|
|
89
|
+
* fields; env is only attached when non-empty so configs stay clean. */
|
|
90
|
+
function jsonEntry(spec, extra = {}, envKey = 'env') {
|
|
91
|
+
const entry = {
|
|
92
|
+
command: spec.command,
|
|
93
|
+
args: spec.args,
|
|
94
|
+
...extra,
|
|
95
|
+
};
|
|
96
|
+
if (Object.keys(spec.env).length > 0) {
|
|
97
|
+
entry[envKey] = spec.env;
|
|
98
|
+
}
|
|
99
|
+
return entry;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Build the registration plan for one agent. Pure — all IO happens in the
|
|
103
|
+
* executor. Throws on an unknown slug so callers surface a clear error.
|
|
104
|
+
*/
|
|
105
|
+
export function planAgentInstall(slug, spec, ctx) {
|
|
106
|
+
const { home, platform, serverName } = ctx;
|
|
107
|
+
switch (slug) {
|
|
108
|
+
// ----- CLI-driven agents (idempotent via the agent's own tool) -----
|
|
109
|
+
case 'claude':
|
|
110
|
+
return {
|
|
111
|
+
kind: 'cli',
|
|
112
|
+
slug,
|
|
113
|
+
bin: 'claude',
|
|
114
|
+
addArgv: [
|
|
115
|
+
'mcp', 'add', '--scope', 'user',
|
|
116
|
+
serverName,
|
|
117
|
+
...envFlags(spec.env, '-e'),
|
|
118
|
+
'--', spec.command, ...spec.args,
|
|
119
|
+
],
|
|
120
|
+
removeArgv: ['mcp', 'remove', '--scope', 'user', serverName],
|
|
121
|
+
getArgv: ['mcp', 'get', serverName],
|
|
122
|
+
};
|
|
123
|
+
case 'codex':
|
|
124
|
+
return {
|
|
125
|
+
kind: 'cli',
|
|
126
|
+
slug,
|
|
127
|
+
bin: 'codex',
|
|
128
|
+
addArgv: [
|
|
129
|
+
'mcp', 'add', serverName,
|
|
130
|
+
...envFlags(spec.env, '--env'),
|
|
131
|
+
'--', spec.command, ...spec.args,
|
|
132
|
+
],
|
|
133
|
+
removeArgv: ['mcp', 'remove', serverName],
|
|
134
|
+
getArgv: ['mcp', 'get', serverName],
|
|
135
|
+
};
|
|
136
|
+
case 'kimi':
|
|
137
|
+
return {
|
|
138
|
+
kind: 'cli',
|
|
139
|
+
slug,
|
|
140
|
+
bin: 'kimi',
|
|
141
|
+
addArgv: [
|
|
142
|
+
'mcp', 'add', '--transport', 'stdio',
|
|
143
|
+
...envFlags(spec.env, '--env'),
|
|
144
|
+
serverName, '--', spec.command, ...spec.args,
|
|
145
|
+
],
|
|
146
|
+
removeArgv: ['mcp', 'remove', serverName],
|
|
147
|
+
getArgv: ['mcp', 'get', serverName],
|
|
148
|
+
};
|
|
149
|
+
// ----- JSON config-file agents (safe deep-merge) -----
|
|
150
|
+
case 'cursor':
|
|
151
|
+
return {
|
|
152
|
+
kind: 'json',
|
|
153
|
+
slug,
|
|
154
|
+
configPath: path.join(home, '.cursor', 'mcp.json'),
|
|
155
|
+
keyPath: ['mcpServers'],
|
|
156
|
+
serverKey: serverName,
|
|
157
|
+
entry: jsonEntry(spec, { type: 'stdio' }),
|
|
158
|
+
};
|
|
159
|
+
case 'copilot':
|
|
160
|
+
// GitHub Copilot CLI: ~/.copilot/mcp-config.json, type "local".
|
|
161
|
+
// (VS Code Copilot uses a different `servers` key in
|
|
162
|
+
// .vscode/mcp.json; the terminal installer targets the CLI.)
|
|
163
|
+
return {
|
|
164
|
+
kind: 'json',
|
|
165
|
+
slug,
|
|
166
|
+
configPath: path.join(home, '.copilot', 'mcp-config.json'),
|
|
167
|
+
keyPath: ['mcpServers'],
|
|
168
|
+
serverKey: serverName,
|
|
169
|
+
entry: jsonEntry(spec, { type: 'local', tools: ['*'] }),
|
|
170
|
+
};
|
|
171
|
+
case 'cline':
|
|
172
|
+
return {
|
|
173
|
+
kind: 'json',
|
|
174
|
+
slug,
|
|
175
|
+
configPath: clineConfigPath(home, platform),
|
|
176
|
+
keyPath: ['mcpServers'],
|
|
177
|
+
serverKey: serverName,
|
|
178
|
+
entry: jsonEntry(spec, { disabled: false, autoApprove: [] }),
|
|
179
|
+
};
|
|
180
|
+
case 'opencode':
|
|
181
|
+
// OpenCode nests under `mcp`, folds command+args into one array,
|
|
182
|
+
// and gates the server with `enabled`.
|
|
183
|
+
return {
|
|
184
|
+
kind: 'json',
|
|
185
|
+
slug,
|
|
186
|
+
configPath: path.join(home, '.config', 'opencode', 'opencode.json'),
|
|
187
|
+
keyPath: ['mcp'],
|
|
188
|
+
serverKey: serverName,
|
|
189
|
+
entry: (() => {
|
|
190
|
+
const e = {
|
|
191
|
+
type: 'local',
|
|
192
|
+
command: [spec.command, ...spec.args],
|
|
193
|
+
enabled: true,
|
|
194
|
+
};
|
|
195
|
+
if (Object.keys(spec.env).length > 0)
|
|
196
|
+
e.environment = spec.env;
|
|
197
|
+
return e;
|
|
198
|
+
})(),
|
|
199
|
+
};
|
|
200
|
+
case 'openclaw':
|
|
201
|
+
return {
|
|
202
|
+
kind: 'json',
|
|
203
|
+
slug,
|
|
204
|
+
configPath: path.join(home, '.openclaw', 'openclaw.json'),
|
|
205
|
+
keyPath: ['mcp', 'servers'],
|
|
206
|
+
serverKey: serverName,
|
|
207
|
+
entry: jsonEntry(spec),
|
|
208
|
+
};
|
|
209
|
+
case 'antigravity':
|
|
210
|
+
return {
|
|
211
|
+
kind: 'json',
|
|
212
|
+
slug,
|
|
213
|
+
configPath: path.join(home, '.gemini', 'antigravity', 'mcp_config.json'),
|
|
214
|
+
keyPath: ['mcpServers'],
|
|
215
|
+
serverKey: serverName,
|
|
216
|
+
entry: jsonEntry(spec),
|
|
217
|
+
};
|
|
218
|
+
case 'trae':
|
|
219
|
+
return {
|
|
220
|
+
kind: 'json',
|
|
221
|
+
slug,
|
|
222
|
+
configPath: traeConfigPath(home, platform),
|
|
223
|
+
keyPath: ['mcpServers'],
|
|
224
|
+
serverKey: serverName,
|
|
225
|
+
entry: jsonEntry(spec),
|
|
226
|
+
};
|
|
227
|
+
// ----- Unverified formats: print-only, never write -----
|
|
228
|
+
case 'vibe':
|
|
229
|
+
return {
|
|
230
|
+
kind: 'manual',
|
|
231
|
+
slug,
|
|
232
|
+
format: 'toml',
|
|
233
|
+
configPath: path.join(home, '.vibe', 'config.toml'),
|
|
234
|
+
snippet: vibeTomlSnippet(spec, serverName),
|
|
235
|
+
reason: 'Vibe uses a TOML array-of-tables ([[mcp_servers]]); ' +
|
|
236
|
+
'its exact schema is unverified, so append this block by hand ' +
|
|
237
|
+
'to avoid corrupting an existing config.',
|
|
238
|
+
};
|
|
239
|
+
case 'pi':
|
|
240
|
+
return {
|
|
241
|
+
kind: 'manual',
|
|
242
|
+
slug,
|
|
243
|
+
format: 'json',
|
|
244
|
+
configPath: path.join(home, '.pi', 'agent', 'mcp.json'),
|
|
245
|
+
snippet: genericMcpServersSnippet(spec, serverName),
|
|
246
|
+
reason: 'The pi coding agent exposes MCP, but its config path/schema is ' +
|
|
247
|
+
'not authoritatively documented. Paste this into pi’s MCP ' +
|
|
248
|
+
'config (check `pi --help` for the exact location).',
|
|
249
|
+
};
|
|
250
|
+
case 'hermes':
|
|
251
|
+
return {
|
|
252
|
+
kind: 'manual',
|
|
253
|
+
slug,
|
|
254
|
+
format: 'yaml',
|
|
255
|
+
configPath: path.join(home, '.hermes', 'config.yaml'),
|
|
256
|
+
snippet: hermesYamlSnippet(spec, serverName),
|
|
257
|
+
reason: 'Hermes config format is unverified. Add this under your Hermes ' +
|
|
258
|
+
'MCP server configuration by hand.',
|
|
259
|
+
};
|
|
260
|
+
default: {
|
|
261
|
+
const exhaustive = slug;
|
|
262
|
+
throw new Error(`unknown agent slug: ${String(exhaustive)}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
function clineConfigPath(home, platform) {
|
|
267
|
+
const rel = path.join('globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json');
|
|
268
|
+
if (platform === 'darwin') {
|
|
269
|
+
return path.join(home, 'Library', 'Application Support', 'Code', 'User', rel);
|
|
270
|
+
}
|
|
271
|
+
if (platform === 'win32') {
|
|
272
|
+
const appData = process.env.APPDATA ?? path.join(home, 'AppData', 'Roaming');
|
|
273
|
+
return path.join(appData, 'Code', 'User', rel);
|
|
274
|
+
}
|
|
275
|
+
return path.join(home, '.config', 'Code', 'User', rel);
|
|
276
|
+
}
|
|
277
|
+
function traeConfigPath(home, platform) {
|
|
278
|
+
if (platform === 'darwin') {
|
|
279
|
+
return path.join(home, 'Library', 'Application Support', 'Trae', 'User', 'mcp.json');
|
|
280
|
+
}
|
|
281
|
+
if (platform === 'win32') {
|
|
282
|
+
const appData = process.env.APPDATA ?? path.join(home, 'AppData', 'Roaming');
|
|
283
|
+
return path.join(appData, 'Trae', 'User', 'mcp.json');
|
|
284
|
+
}
|
|
285
|
+
return path.join(home, '.config', 'Trae', 'User', 'mcp.json');
|
|
286
|
+
}
|
|
287
|
+
// --- Pure JSON merge / removal (the heart of the 'json' strategy) -------
|
|
288
|
+
// CR-007: `JsonInstallPlan` is a public shape and `applyJsonInstall` /
|
|
289
|
+
// `removeJsonInstall` are public functions — a caller-supplied `keyPath`/
|
|
290
|
+
// `serverKey` containing `__proto__`, `prototype`, or `constructor` would
|
|
291
|
+
// otherwise let bracket-notation traversal (`cursor[key]`) walk onto (and
|
|
292
|
+
// then assign directly onto) `Object.prototype` or a constructor function,
|
|
293
|
+
// polluting every plain object in the process rather than merely the target
|
|
294
|
+
// config file. Every segment is validated before any traversal/assignment
|
|
295
|
+
// happens, so a dangerous plan is rejected outright instead of partially
|
|
296
|
+
// applied.
|
|
297
|
+
const DANGEROUS_OBJECT_PATH_SEGMENTS = new Set([
|
|
298
|
+
'__proto__',
|
|
299
|
+
'prototype',
|
|
300
|
+
'constructor',
|
|
301
|
+
]);
|
|
302
|
+
function assertSafeObjectPathSegment(segment, context) {
|
|
303
|
+
if (DANGEROUS_OBJECT_PATH_SEGMENTS.has(segment)) {
|
|
304
|
+
throw new Error(`refusing to apply MCP install plan: "${segment}" is not a safe ${context} segment (prototype-pollution guard)`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function assertSafeJsonInstallPlan(plan) {
|
|
308
|
+
for (const key of plan.keyPath) {
|
|
309
|
+
assertSafeObjectPathSegment(key, 'keyPath');
|
|
310
|
+
}
|
|
311
|
+
assertSafeObjectPathSegment(plan.serverKey, 'serverKey');
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Merge one server entry into existing config text without disturbing the
|
|
315
|
+
* rest. Missing intermediate objects are created. Returns pretty JSON with
|
|
316
|
+
* a trailing newline. Throws if existing text is non-empty but unparseable
|
|
317
|
+
* (caller decides whether to bail or back up), or if `plan.keyPath` /
|
|
318
|
+
* `plan.serverKey` contains a dangerous object-path segment (CR-007).
|
|
319
|
+
*/
|
|
320
|
+
export function applyJsonInstall(existingText, plan) {
|
|
321
|
+
assertSafeJsonInstallPlan(plan);
|
|
322
|
+
const root = parseJsonObject(existingText, plan.configPath);
|
|
323
|
+
let cursor = root;
|
|
324
|
+
for (const key of plan.keyPath) {
|
|
325
|
+
const next = cursor[key];
|
|
326
|
+
if (next == null || typeof next !== 'object' || Array.isArray(next)) {
|
|
327
|
+
cursor[key] = {};
|
|
328
|
+
}
|
|
329
|
+
cursor = cursor[key];
|
|
330
|
+
}
|
|
331
|
+
cursor[plan.serverKey] = plan.entry;
|
|
332
|
+
return `${JSON.stringify(root, null, 2)}\n`;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Remove the server entry. Returns the new text, or null when the file did
|
|
336
|
+
* not exist / had nothing to remove (caller treats null as a no-op). Throws
|
|
337
|
+
* if `plan.keyPath` / `plan.serverKey` contains a dangerous object-path
|
|
338
|
+
* segment (CR-007).
|
|
339
|
+
*/
|
|
340
|
+
export function removeJsonInstall(existingText, plan) {
|
|
341
|
+
assertSafeJsonInstallPlan(plan);
|
|
342
|
+
if (existingText == null || existingText.trim() === '')
|
|
343
|
+
return null;
|
|
344
|
+
const root = parseJsonObject(existingText, plan.configPath);
|
|
345
|
+
let cursor = root;
|
|
346
|
+
for (const key of plan.keyPath) {
|
|
347
|
+
const next = cursor[key];
|
|
348
|
+
if (next == null || typeof next !== 'object' || Array.isArray(next)) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
cursor = next;
|
|
352
|
+
}
|
|
353
|
+
if (!(plan.serverKey in cursor))
|
|
354
|
+
return null;
|
|
355
|
+
delete cursor[plan.serverKey];
|
|
356
|
+
return `${JSON.stringify(root, null, 2)}\n`;
|
|
357
|
+
}
|
|
358
|
+
function parseJsonObject(text, where) {
|
|
359
|
+
if (text == null || text.trim() === '')
|
|
360
|
+
return {};
|
|
361
|
+
let parsed;
|
|
362
|
+
try {
|
|
363
|
+
parsed = JSON.parse(text);
|
|
364
|
+
}
|
|
365
|
+
catch (err) {
|
|
366
|
+
// JSON.parse only ever throws a SyntaxError, so `err` is always an Error.
|
|
367
|
+
throw new Error(`existing config at ${where} is not valid JSON: ${err.message}`);
|
|
368
|
+
}
|
|
369
|
+
if (parsed == null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
370
|
+
throw new Error(`existing config at ${where} is not a JSON object`);
|
|
371
|
+
}
|
|
372
|
+
return parsed;
|
|
373
|
+
}
|
|
374
|
+
// --- Snippets for the manual (print-only) strategy ----------------------
|
|
375
|
+
function genericMcpServersSnippet(spec, name) {
|
|
376
|
+
const server = {
|
|
377
|
+
command: spec.command,
|
|
378
|
+
args: spec.args,
|
|
379
|
+
};
|
|
380
|
+
if (Object.keys(spec.env).length > 0)
|
|
381
|
+
server.env = spec.env;
|
|
382
|
+
return JSON.stringify({ mcpServers: { [name]: server } }, null, 2);
|
|
383
|
+
}
|
|
384
|
+
function hermesYamlSnippet(spec, name) {
|
|
385
|
+
const lines = [
|
|
386
|
+
'mcp_servers:',
|
|
387
|
+
` ${name}:`,
|
|
388
|
+
` command: ${JSON.stringify(spec.command)}`,
|
|
389
|
+
` args: ${JSON.stringify(spec.args)}`,
|
|
390
|
+
];
|
|
391
|
+
if (Object.keys(spec.env).length > 0) {
|
|
392
|
+
lines.push(' env:');
|
|
393
|
+
for (const [k, v] of Object.entries(spec.env)) {
|
|
394
|
+
lines.push(` ${k}: ${JSON.stringify(v)}`);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return lines.join('\n');
|
|
398
|
+
}
|
|
399
|
+
function vibeTomlSnippet(spec, name) {
|
|
400
|
+
const argsToml = `[${spec.args.map((a) => JSON.stringify(a)).join(', ')}]`;
|
|
401
|
+
const lines = [
|
|
402
|
+
'[[mcp_servers]]',
|
|
403
|
+
`name = ${JSON.stringify(name)}`,
|
|
404
|
+
'transport = "stdio"',
|
|
405
|
+
`command = ${JSON.stringify(spec.command)}`,
|
|
406
|
+
`args = ${argsToml}`,
|
|
407
|
+
];
|
|
408
|
+
return lines.join('\n');
|
|
409
|
+
}
|
|
410
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/agent-install/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @module @jini-ai/mcp/bin/serve
|
|
4
|
+
*
|
|
5
|
+
* The bootable `jini-mcp` binary (`package.json`'s `"bin": { "jini-mcp": "./dist/bin/serve.js" }`)
|
|
6
|
+
* — the real executable entry point gap 3's MCP-callback continuation-transport spike needed and
|
|
7
|
+
* did not have (see `packages/daemon/source-map.md`'s "run/chat orchestration gap 3, part 1"
|
|
8
|
+
* addition, and this package's own dated section in `source-map.md`). `../server/tool-server.js`'s
|
|
9
|
+
* `createMcpToolServer` was always designed to run as *this process's own* stdio — meant to be a
|
|
10
|
+
* script a client (Claude Code) spawns as its own child subprocess and talks to over that child's
|
|
11
|
+
* stdin/stdout — but until this file, nothing in this package actually was that script.
|
|
12
|
+
*
|
|
13
|
+
* Follows `@jini-ai/cli/main.ts`'s established shape for a bootable, side-effect-guarded, `#!/usr/bin/env
|
|
14
|
+
* node` entry point: a named, fully-dependency-injected `serve()` export (importable for tests, or
|
|
15
|
+
* for a consumer building its own bin wrapper around it) plus a bottom-of-file guard that only
|
|
16
|
+
* calls it for real when this module is the actual process entrypoint — mirrors that file's own
|
|
17
|
+
* `isMainModule` check (Node's ESM equivalent of the CommonJS `require.main === module` idiom).
|
|
18
|
+
* Deliberately **not** re-exported from `../index.ts`: that barrel is a plain library dependency, and
|
|
19
|
+
* this file's whole purpose is a `process.env`-reading, stdio-serving, potentially `process.exit`-
|
|
20
|
+
* calling side effect — bundling it into the library barrel would mean `import '@jini-ai/mcp'` could
|
|
21
|
+
* start behaving like a spawned MCP server.
|
|
22
|
+
*
|
|
23
|
+
* **Scope: what this process is spawned to do.** One `jini-mcp` process serves exactly one run for
|
|
24
|
+
* its entire lifetime — the spawning daemon injects {@link RUN_ID_ENV_VAR} into the child's own
|
|
25
|
+
* environment before Claude Code (which in turn spawns *this* as its own MCP server child, per its
|
|
26
|
+
* `.mcp.json`) ever starts talking to it. That is what lets `execute_delegated_tool`
|
|
27
|
+
* (`../server/tools/delegated-tool.js`) close over a fixed `runId` at construction time instead of
|
|
28
|
+
* trusting a model-supplied one — see that module's own doc for why that boundary matters. Every
|
|
29
|
+
* other tool this server hosts (`RUN_TOOLS`, `../server/tools/run-tools.js`) is run-agnostic and
|
|
30
|
+
* needed no such scoping.
|
|
31
|
+
*
|
|
32
|
+
* **Daemon-URL resolution** mirrors `@jini-ai/cli/main.ts`'s own posture: no baked-in default, just
|
|
33
|
+
* `resolveDaemonUrl` (`@jini-ai/cli`) wired to a `--daemon-url`-shaped precedence chain — except this
|
|
34
|
+
* process has no argv to parse (an MCP client launches it with a fixed `command`/`args`/`env`, not
|
|
35
|
+
* interactive flags), so only the env-var step applies: {@link DAEMON_URL_ENV_VAR}. When unset,
|
|
36
|
+
* `resolveDaemonUrl` throws, and this file's own top-level error boundary turns that into a clean
|
|
37
|
+
* stderr message + non-zero exit rather than an unhandled rejection.
|
|
38
|
+
*/
|
|
39
|
+
import type { Readable, Writable } from 'node:stream';
|
|
40
|
+
import { resolveDaemonUrl as resolveDaemonUrlDefault } from '@jini-ai/cli';
|
|
41
|
+
import { createMcpToolServer as createMcpToolServerDefault } from '../server/tool-server.js';
|
|
42
|
+
/** The one run this process is scoped to for its entire lifetime. Set by the spawning daemon, never by the MCP client. */
|
|
43
|
+
export declare const RUN_ID_ENV_VAR = "JINI_RUN_ID";
|
|
44
|
+
/** Checked (only) when resolving the daemon HTTP base URL — see `resolveDaemonUrl`'s own docs; matches `@jini-ai/cli/main.ts`'s identically-named constant. */
|
|
45
|
+
export declare const DAEMON_URL_ENV_VAR = "JINI_DAEMON_URL";
|
|
46
|
+
export interface ServeDeps {
|
|
47
|
+
/** @default process.env */
|
|
48
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
49
|
+
/** @default process.stderr.write */
|
|
50
|
+
readonly writeErr?: (text: string) => void;
|
|
51
|
+
/** @default process.exit; inject for tests (must not return) */
|
|
52
|
+
readonly exit?: (code: number) => never;
|
|
53
|
+
/** @default the real @jini-ai/cli resolveDaemonUrl */
|
|
54
|
+
readonly resolveDaemonUrl?: typeof resolveDaemonUrlDefault;
|
|
55
|
+
/** @default the real createMcpToolServer */
|
|
56
|
+
readonly createMcpToolServer?: typeof createMcpToolServerDefault;
|
|
57
|
+
/** Threaded into `execute_delegated_tool`'s per-call correlation id. @default node:crypto randomUUID */
|
|
58
|
+
readonly generateToolUseId?: () => string;
|
|
59
|
+
/** Threaded into every tool's daemon call. @default the global fetch */
|
|
60
|
+
readonly fetchImpl?: typeof fetch;
|
|
61
|
+
/** @default process.stdin */
|
|
62
|
+
readonly stdin?: Readable;
|
|
63
|
+
/** @default process.stdout */
|
|
64
|
+
readonly stdout?: Writable;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Assembles and runs the `jini-mcp` stdio MCP server: `RUN_ID_ENV_VAR` (required — this process
|
|
68
|
+
* has no meaningful default run to serve) plus `DAEMON_URL_ENV_VAR` resolution, then hosts
|
|
69
|
+
* `RUN_TOOLS` (run-agnostic) alongside a fresh `execute_delegated_tool` def scoped to the resolved
|
|
70
|
+
* `runId`, and `KERNEL_RESOURCES`. Resolves once the client disconnects (stdin EOF) or the
|
|
71
|
+
* idle-exit window elapses (`createMcpToolServer`'s own default) — never bare-throws: every error
|
|
72
|
+
* path below writes a message to `writeErr` and calls `exit(1)` instead.
|
|
73
|
+
*/
|
|
74
|
+
export declare function serve(deps?: ServeDeps): Promise<void>;
|
|
75
|
+
//# sourceMappingURL=serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/bin/serve.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,gBAAgB,IAAI,uBAAuB,EAAgC,MAAM,cAAc,CAAC;AACzG,OAAO,EAAE,mBAAmB,IAAI,0BAA0B,EAA6B,MAAM,0BAA0B,CAAC;AAOxH,0HAA0H;AAC1H,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAC5C,+JAA+J;AAC/J,eAAO,MAAM,kBAAkB,oBAAoB,CAAC;AASpD,MAAM,WAAW,SAAS;IACxB,2BAA2B;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,gEAAgE;IAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;IACxC,sDAAsD;IACtD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,uBAAuB,CAAC;IAC3D,4CAA4C;IAC5C,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,0BAA0B,CAAC;IACjE,wGAAwG;IACxG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,MAAM,CAAC;IAC1C,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,6BAA6B;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;IAC1B,8BAA8B;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;CAC5B;AAMD;;;;;;;GAOG;AACH,wBAAsB,KAAK,CAAC,IAAI,GAAE,SAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA8C/D"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { resolveDaemonUrl as resolveDaemonUrlDefault } from '@jini-ai/cli';
|
|
4
|
+
import { createMcpToolServer as createMcpToolServerDefault } from '../server/tool-server.js';
|
|
5
|
+
import { RUN_TOOLS } from '../server/tools/run-tools.js';
|
|
6
|
+
import { TOOL_CATALOG_TOOLS } from '../server/tools/tool-catalog-tools.js';
|
|
7
|
+
import { createExecuteDelegatedToolTool } from '../server/tools/delegated-tool.js';
|
|
8
|
+
import { KERNEL_RESOURCES } from '../server/resources/active-resource.js';
|
|
9
|
+
/** The one run this process is scoped to for its entire lifetime. Set by the spawning daemon, never by the MCP client. */
|
|
10
|
+
export const RUN_ID_ENV_VAR = 'JINI_RUN_ID';
|
|
11
|
+
/** Checked (only) when resolving the daemon HTTP base URL — see `resolveDaemonUrl`'s own docs; matches `@jini-ai/cli/main.ts`'s identically-named constant. */
|
|
12
|
+
export const DAEMON_URL_ENV_VAR = 'JINI_DAEMON_URL';
|
|
13
|
+
const SERVER_NAME = 'jini-mcp';
|
|
14
|
+
const SERVER_VERSION = '0.0.0';
|
|
15
|
+
const INSTRUCTIONS = 'Tools proxying this host\'s Jini daemon over loopback HTTP, scoped to the run that spawned this MCP server process. ' +
|
|
16
|
+
'Use execute_delegated_tool to invoke a Jini-registered tool (never an agent-vendor-specific tool name) against that run — ' +
|
|
17
|
+
'every call is routed through the daemon\'s deny-by-default ToolExecutor gate.';
|
|
18
|
+
function defaultWriteErr(text) {
|
|
19
|
+
process.stderr.write(text);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Assembles and runs the `jini-mcp` stdio MCP server: `RUN_ID_ENV_VAR` (required — this process
|
|
23
|
+
* has no meaningful default run to serve) plus `DAEMON_URL_ENV_VAR` resolution, then hosts
|
|
24
|
+
* `RUN_TOOLS` (run-agnostic) alongside a fresh `execute_delegated_tool` def scoped to the resolved
|
|
25
|
+
* `runId`, and `KERNEL_RESOURCES`. Resolves once the client disconnects (stdin EOF) or the
|
|
26
|
+
* idle-exit window elapses (`createMcpToolServer`'s own default) — never bare-throws: every error
|
|
27
|
+
* path below writes a message to `writeErr` and calls `exit(1)` instead.
|
|
28
|
+
*/
|
|
29
|
+
export async function serve(deps = {}) {
|
|
30
|
+
const env = deps.env ?? process.env;
|
|
31
|
+
const writeErr = deps.writeErr ?? defaultWriteErr;
|
|
32
|
+
const exit = deps.exit ?? ((code) => process.exit(code));
|
|
33
|
+
const resolveDaemonUrlFn = deps.resolveDaemonUrl ?? resolveDaemonUrlDefault;
|
|
34
|
+
const createMcpToolServerFn = deps.createMcpToolServer ?? createMcpToolServerDefault;
|
|
35
|
+
const runId = env[RUN_ID_ENV_VAR];
|
|
36
|
+
if (typeof runId !== 'string' || runId.length === 0) {
|
|
37
|
+
writeErr(`${SERVER_NAME}: missing required ${RUN_ID_ENV_VAR} environment variable (this process must be spawned by a Jini daemon, which sets it)\n`);
|
|
38
|
+
return exit(1);
|
|
39
|
+
}
|
|
40
|
+
const resolveBaseUrl = () => {
|
|
41
|
+
const options = { flagUrl: null, env, envVarName: DAEMON_URL_ENV_VAR, warn: writeErr };
|
|
42
|
+
return resolveDaemonUrlFn(options);
|
|
43
|
+
};
|
|
44
|
+
const tools = [
|
|
45
|
+
...RUN_TOOLS,
|
|
46
|
+
...TOOL_CATALOG_TOOLS,
|
|
47
|
+
createExecuteDelegatedToolTool({
|
|
48
|
+
runId,
|
|
49
|
+
...(deps.generateToolUseId !== undefined ? { generateToolUseId: deps.generateToolUseId } : {}),
|
|
50
|
+
}),
|
|
51
|
+
];
|
|
52
|
+
const serverOptions = {
|
|
53
|
+
name: SERVER_NAME,
|
|
54
|
+
version: SERVER_VERSION,
|
|
55
|
+
tools,
|
|
56
|
+
resources: KERNEL_RESOURCES,
|
|
57
|
+
resolveBaseUrl,
|
|
58
|
+
instructions: INSTRUCTIONS,
|
|
59
|
+
...(deps.fetchImpl !== undefined ? { fetchImpl: deps.fetchImpl } : {}),
|
|
60
|
+
...(deps.stdin !== undefined ? { stdin: deps.stdin } : {}),
|
|
61
|
+
...(deps.stdout !== undefined ? { stdout: deps.stdout } : {}),
|
|
62
|
+
};
|
|
63
|
+
try {
|
|
64
|
+
await createMcpToolServerFn(serverOptions).run();
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
68
|
+
writeErr(`${SERVER_NAME}: ${message}\n`);
|
|
69
|
+
return exit(1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Only run for real when this module is the actual process entrypoint (`node dist/bin/serve.js`,
|
|
73
|
+
// or the `jini-mcp` bin shim pnpm/npm links to it) — not merely imported, e.g. by this file's own
|
|
74
|
+
// tests importing the named `serve` export above. Mirrors `@jini-ai/cli/main.ts`'s identical guard.
|
|
75
|
+
const isMainModule = process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1];
|
|
76
|
+
if (isMainModule) {
|
|
77
|
+
await serve();
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/bin/serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
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
|
+
interface McpIdleExitControllerOptions {
|
|
10
|
+
idleMs: number;
|
|
11
|
+
onIdle: () => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create an idle-exit controller that calls `onIdle` after `idleMs` of
|
|
15
|
+
* inactivity. Activity is tracked via `noteActivity()` and `trackRequest()`;
|
|
16
|
+
* in-flight requests defer the idle timer. Used to auto-close a long-running
|
|
17
|
+
* stdio MCP server process after a period of no tool calls.
|
|
18
|
+
* @param options Idle duration in ms (finite positive integer, clamped to a
|
|
19
|
+
* 24h ceiling — throws `RangeError` otherwise) and the callback to invoke on idle.
|
|
20
|
+
* @returns An object with `noteActivity`, `trackRequest`, and `dispose` methods.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createMcpIdleExitController({ idleMs, onIdle, }: McpIdleExitControllerOptions): {
|
|
23
|
+
noteActivity(): void;
|
|
24
|
+
trackRequest<T>(fn: () => T | Promise<T>): Promise<T>;
|
|
25
|
+
dispose(): void;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* True when `mime` names a textual content type whose body can be surfaced
|
|
29
|
+
* as MCP `text` content (text/*, JSON, JS/TS, XML, YAML/TOML/PHP/sh, `+json`
|
|
30
|
+
* / `+xml` suffixes, and SVG). Returns false for an absent/unknown mime.
|
|
31
|
+
* @param mime The MIME type string to classify (undefined counts as non-textual).
|
|
32
|
+
* @returns Whether the content should be treated as text.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isTextualMime(mime: string | undefined): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Extract all relative (non-absolute, non-CDN, non-data-URI) file references from
|
|
37
|
+
* the text content of a file, normalized to root-relative paths.
|
|
38
|
+
* Runs HTML, CSS, and/or JS pattern sets based on the file's MIME type and extension.
|
|
39
|
+
* Skips `https?:`, `//`, `data:`, `mailto:`, `tel:`, and `#` prefixes; drops any
|
|
40
|
+
* reference that would escape the root via `..` traversal.
|
|
41
|
+
* @param text The textual content of the file.
|
|
42
|
+
* @param fromPath The root-relative path of the file (used for relative-path resolution).
|
|
43
|
+
* @param fromMime The MIME type of the file (used to select reference-extraction patterns).
|
|
44
|
+
* @returns Deduplicated root-relative paths of all referenced files found.
|
|
45
|
+
*/
|
|
46
|
+
export declare function extractRelativeRefs(text: string, fromPath: string, fromMime: string): string[];
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,UAAU,4BAA4B;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,EAC1C,MAAM,EACN,MAAM,GACP,EAAE,4BAA4B;;iBAmCR,CAAC,MAAM,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;;EA0B9D;AAeD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAG/D;AA6CD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA8D9F"}
|