@kb-labs/mcp-app 2.96.0 → 2.100.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/dist/bin.cjs +6774 -12187
- package/dist/bin.cjs.map +1 -1
- package/dist/index.js +94 -21
- package/dist/index.js.map +1 -1
- package/package.json +17 -17
package/dist/index.js
CHANGED
|
@@ -146,6 +146,24 @@ function toCommandManifest(decl, entry) {
|
|
|
146
146
|
pkgRoot: entry.pluginRoot
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
|
+
function buildTool(entry, decl) {
|
|
150
|
+
if (typeof decl.path !== "string" || decl.path.trim().length === 0) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`command "${decl.id ?? "(unknown)"}" in plugin "${entry.pluginId}" has no "path" field \u2014 skipping`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
name: toolName(entry.pluginId, decl.path),
|
|
157
|
+
description: decl.describe,
|
|
158
|
+
inputSchema: generateCommandSchema(toCommandManifest(decl, entry)),
|
|
159
|
+
pluginId: entry.pluginId,
|
|
160
|
+
pluginRoot: entry.pluginRoot,
|
|
161
|
+
handlerPath: decl.handler,
|
|
162
|
+
version: entry.manifest.version ?? "0.0.0",
|
|
163
|
+
operationType: decl.operationType,
|
|
164
|
+
permissions: getHandlerPermissions(entry.manifest, "cli", decl.path)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
149
167
|
function filterTools(snapshot, permits) {
|
|
150
168
|
const tools = [];
|
|
151
169
|
for (const entry of snapshot.manifests) {
|
|
@@ -153,21 +171,31 @@ function filterTools(snapshot, permits) {
|
|
|
153
171
|
if (!permits(decl.operationType, entry.pluginId)) {
|
|
154
172
|
continue;
|
|
155
173
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
pluginId: entry.pluginId,
|
|
161
|
-
pluginRoot: entry.pluginRoot,
|
|
162
|
-
handlerPath: decl.handler,
|
|
163
|
-
version: entry.manifest.version ?? "0.0.0",
|
|
164
|
-
operationType: decl.operationType,
|
|
165
|
-
permissions: getHandlerPermissions(entry.manifest, "cli", decl.path)
|
|
166
|
-
});
|
|
174
|
+
try {
|
|
175
|
+
tools.push(buildTool(entry, decl));
|
|
176
|
+
} catch {
|
|
177
|
+
}
|
|
167
178
|
}
|
|
168
179
|
}
|
|
169
180
|
return tools;
|
|
170
181
|
}
|
|
182
|
+
function validateManifests(snapshot) {
|
|
183
|
+
const diagnostics = [];
|
|
184
|
+
for (const entry of snapshot.manifests) {
|
|
185
|
+
for (const decl of entry.manifest.cli?.commands ?? []) {
|
|
186
|
+
try {
|
|
187
|
+
buildTool(entry, decl);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
diagnostics.push({
|
|
190
|
+
pluginId: entry.pluginId,
|
|
191
|
+
commandId: decl.id ?? decl.path ?? "(unknown)",
|
|
192
|
+
error: error instanceof Error ? error.message : String(error)
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return diagnostics;
|
|
198
|
+
}
|
|
171
199
|
function resolveHandlerPath(pluginRoot, handler) {
|
|
172
200
|
const relative = handler.split("#")[0] ?? handler;
|
|
173
201
|
return relative.startsWith("dist/") ? path.resolve(pluginRoot, relative) : path.resolve(pluginRoot, "dist", relative);
|
|
@@ -295,6 +323,14 @@ var McpObservabilityCollector = class {
|
|
|
295
323
|
requestsTotal = 0;
|
|
296
324
|
errorsTotal = 0;
|
|
297
325
|
ops = new OperationMetricsTracker();
|
|
326
|
+
manifestDiagnostics = [];
|
|
327
|
+
/** Record the manifest diagnostics found by validateManifests() at startup. */
|
|
328
|
+
setManifestDiagnostics(diagnostics) {
|
|
329
|
+
this.manifestDiagnostics = diagnostics;
|
|
330
|
+
}
|
|
331
|
+
getManifestDiagnostics() {
|
|
332
|
+
return this.manifestDiagnostics;
|
|
333
|
+
}
|
|
298
334
|
/**
|
|
299
335
|
* Register Fastify hooks that track HTTP-level request counts and duration.
|
|
300
336
|
* Must be called before routes are registered so the hooks apply to all routes.
|
|
@@ -385,6 +421,11 @@ var McpObservabilityCollector = class {
|
|
|
385
421
|
id: "execution",
|
|
386
422
|
status: "ok",
|
|
387
423
|
message: `mode=${executionMode}`
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
id: "manifests",
|
|
427
|
+
status: this.manifestDiagnostics.length === 0 ? "ok" : "warn",
|
|
428
|
+
message: this.manifestDiagnostics.length === 0 ? "all commands loaded cleanly" : `${this.manifestDiagnostics.length} command(s) skipped \u2014 see /observability/diagnostics`
|
|
388
429
|
}
|
|
389
430
|
],
|
|
390
431
|
topOperations: this.ops.getTopOperations(5)
|
|
@@ -414,6 +455,17 @@ var McpObservabilityCollector = class {
|
|
|
414
455
|
};
|
|
415
456
|
|
|
416
457
|
// src/server.ts
|
|
458
|
+
var DIAGNOSTICS_TOOL = {
|
|
459
|
+
name: "kb-labs__mcp_diagnostics",
|
|
460
|
+
description: "List plugin commands that failed to load as MCP tools (malformed manifests), with the reason for each.",
|
|
461
|
+
inputSchema: { type: "object", properties: {} }
|
|
462
|
+
};
|
|
463
|
+
function renderManifestDiagnostics(diagnostics) {
|
|
464
|
+
if (diagnostics.length === 0) {
|
|
465
|
+
return "All plugin commands loaded cleanly \u2014 no manifest issues.";
|
|
466
|
+
}
|
|
467
|
+
return diagnostics.map((d) => `[${d.pluginId}] ${d.commandId}: ${d.error}`).join("\n");
|
|
468
|
+
}
|
|
417
469
|
var McpDaemonServer = class {
|
|
418
470
|
opts;
|
|
419
471
|
resolvePlatform;
|
|
@@ -438,6 +490,15 @@ var McpDaemonServer = class {
|
|
|
438
490
|
platformRoot: this.opts.platformRoot,
|
|
439
491
|
cache: this.opts.cache
|
|
440
492
|
});
|
|
493
|
+
const manifestDiagnostics = validateManifests(this.registry.snapshot());
|
|
494
|
+
this.collector.setManifestDiagnostics(manifestDiagnostics);
|
|
495
|
+
for (const diag of manifestDiagnostics) {
|
|
496
|
+
this.opts.logger.warn("MCP tool skipped \u2014 invalid manifest command", {
|
|
497
|
+
pluginId: diag.pluginId,
|
|
498
|
+
commandId: diag.commandId,
|
|
499
|
+
error: diag.error
|
|
500
|
+
});
|
|
501
|
+
}
|
|
441
502
|
const execMode = process.env.KB_MCP_EXECUTION_MODE ?? "subprocess";
|
|
442
503
|
const observabilityAdapter = {
|
|
443
504
|
register: (server) => this.collector.register(server),
|
|
@@ -462,6 +523,9 @@ var McpDaemonServer = class {
|
|
|
462
523
|
}
|
|
463
524
|
async registerMcpRoutes(server) {
|
|
464
525
|
const { cache, logger, jwtConfig } = this.opts;
|
|
526
|
+
server.get("/observability/diagnostics", async () => ({
|
|
527
|
+
diagnostics: this.collector.getManifestDiagnostics()
|
|
528
|
+
}));
|
|
465
529
|
server.all("/api/v1/mcp", async (request, reply) => {
|
|
466
530
|
reply.header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "GET, POST, OPTIONS").header("Access-Control-Allow-Headers", "Authorization, Content-Type, Mcp-Session-Id");
|
|
467
531
|
if (request.method === "OPTIONS") {
|
|
@@ -488,15 +552,24 @@ var McpDaemonServer = class {
|
|
|
488
552
|
{ capabilities: { tools: {} } }
|
|
489
553
|
);
|
|
490
554
|
mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
491
|
-
tools:
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
555
|
+
tools: [
|
|
556
|
+
...visibleTools.map((t) => ({
|
|
557
|
+
name: t.name,
|
|
558
|
+
description: t.description,
|
|
559
|
+
inputSchema: t.inputSchema
|
|
560
|
+
})),
|
|
561
|
+
// Authenticated callers only — mirrors the visibility gate above.
|
|
562
|
+
...permits ? [DIAGNOSTICS_TOOL] : []
|
|
563
|
+
]
|
|
496
564
|
}));
|
|
497
|
-
mcp.setRequestHandler(
|
|
498
|
-
|
|
499
|
-
|
|
565
|
+
mcp.setRequestHandler(CallToolRequestSchema, async ({ params }) => {
|
|
566
|
+
if (params.name === DIAGNOSTICS_TOOL.name) {
|
|
567
|
+
if (!permits) {
|
|
568
|
+
return { content: [{ type: "text", text: `Not authorized: ${params.name}` }], isError: true };
|
|
569
|
+
}
|
|
570
|
+
return { content: [{ type: "text", text: renderManifestDiagnostics(this.collector.getManifestDiagnostics()) }], isError: false };
|
|
571
|
+
}
|
|
572
|
+
return executeToolCall({
|
|
500
573
|
name: params.name,
|
|
501
574
|
args: params.arguments ?? {},
|
|
502
575
|
visibleTools,
|
|
@@ -505,8 +578,8 @@ var McpDaemonServer = class {
|
|
|
505
578
|
resolvePlatform: this.resolvePlatform,
|
|
506
579
|
analytics: this.opts.platform.analytics,
|
|
507
580
|
collector: this.collector
|
|
508
|
-
})
|
|
509
|
-
);
|
|
581
|
+
});
|
|
582
|
+
});
|
|
510
583
|
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
|
|
511
584
|
try {
|
|
512
585
|
await mcp.connect(transport);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/auth.ts","../src/mcp/output-capture.ts","../src/mcp/ui.ts","../src/mcp/authz.ts","../src/mcp/tool-builder.ts","../src/mcp/tool-router.ts","../src/mcp/request-handler.ts","../src/observability/collector.ts","../src/server.ts","../src/bootstrap.ts","../src/index.ts"],"names":["noopUI","durationMs","can","McpServer","resolveObservabilityInstanceId"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * MCP authentication — Bearer token verification against the shared gateway\n * JWT secret. Authorization (which tools an identity may use) lives in authz.ts,\n * routed through the platform PDP.\n */\n\nimport { AuthService, type JwtConfig } from '@kb-labs/gateway-auth';\nimport type { ICache } from '@kb-labs/core-platform';\nimport type { AuthContext } from '@kb-labs/gateway-contracts';\n\n/**\n * Insecure development fallback. Must never be used in production — loadJwtConfig\n * throws when NODE_ENV=production and no real secret is configured.\n */\nconst DEV_JWT_SECRET = 'dev-insecure-secret-change-me';\n\n/**\n * Load the JWT config from the environment. Uses the same GATEWAY_JWT_SECRET as\n * the gateway so tokens issued by the gateway are accepted by the MCP daemon.\n */\nexport function loadJwtConfig(): JwtConfig {\n const secret = process.env.GATEWAY_JWT_SECRET;\n if (!secret && process.env.NODE_ENV === 'production') {\n throw new Error(\n 'GATEWAY_JWT_SECRET must be set in production. ' +\n 'Generate one with: node -e \"console.log(require(\\'crypto\\').randomBytes(64).toString(\\'hex\\'))\"',\n );\n }\n return { secret: secret ?? DEV_JWT_SECRET };\n}\n\n/**\n * Extract a Bearer token from an Authorization header, or null.\n *\n * Parsing avoids overlapping quantifiers (e.g. `\\s+(.+)`) on the\n * attacker-controlled header: an anchored single-`\\s` scheme check is linear,\n * then the remainder is sliced and trimmed. This sidesteps the polynomial\n * ReDoS that `/^Bearer\\s+(.+)$/` exhibits on `\"Bearer\" + \" \".repeat(n)`.\n */\nexport function extractBearer(header: string | undefined): string | null {\n if (header === undefined || !/^bearer\\s/i.test(header)) {\n return null;\n }\n const token = header.slice('bearer'.length).trim();\n return token.length > 0 ? token : null;\n}\n\n/**\n * Resolve a verified AuthContext from an Authorization header.\n * Returns null for anonymous (no/invalid token) — the caller treats this as\n * \"no tools, no execution\".\n */\nexport async function resolveAuthContext(\n header: string | undefined,\n cache: ICache,\n jwtConfig: JwtConfig,\n): Promise<AuthContext | null> {\n const token = extractBearer(header);\n if (!token) {\n return null;\n }\n return new AuthService(cache, jwtConfig).verify(token);\n}\n","/**\n * AsyncLocalStorage singleton for per-call plugin output capture.\n *\n * bootstrap.ts wires a uiProvider that reads from this store so each\n * callTool() invocation captures plugin UI output into its own isolated\n * buffer — concurrent calls never mix their output.\n *\n * Usage:\n * // producer (callTool):\n * const lines: string[] = [];\n * await callOutput.run(lines, () => executeCommandV3(...));\n * return lines.join('\\n');\n *\n * // consumer (uiProvider in bootstrap):\n * uiProvider: () => {\n * const lines = callOutput.getStore();\n * return lines ? createBufferedUI((s) => lines.push(s)).ui : noopUI;\n * }\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nexport const callOutput = new AsyncLocalStorage<string[]>();\n","/**\n * BufferedUI — a UIFacade implementation that captures all output into a string\n * buffer instead of writing to a TTY. Used to run plugin commands headlessly and\n * return their textual output as an MCP tool result.\n *\n * Output methods append to the buffer. Interactive methods return safe,\n * non-blocking defaults (mirroring the canonical noopUI) because an MCP tool call\n * is non-interactive — there is no human to answer a prompt.\n */\n\nimport { noopUI } from '@kb-labs/plugin-contracts';\nimport type { UIFacade } from '@kb-labs/plugin-contracts';\n\nexport interface BufferedUI {\n ui: UIFacade;\n getOutput: () => string;\n}\n\nfunction stringifyError(error: Error | string): string {\n return typeof error === 'string' ? error : error.message;\n}\n\n/**\n * Create a buffered UI facade.\n *\n * @param pushFn - Optional external push function. When provided (e.g. from the\n * AsyncLocalStorage-backed uiProvider in bootstrap), output is appended there\n * and `getOutput()` returns an empty string. When omitted, output is stored in\n * an internal array and available via `getOutput()`.\n */\nexport function createBufferedUI(pushFn?: (text: string) => void): BufferedUI {\n const lines: string[] = [];\n const push = (text: string): void => {\n if (pushFn) {\n pushFn(text);\n } else {\n lines.push(text);\n }\n };\n\n const ui: UIFacade = {\n colors: noopUI.colors,\n symbols: noopUI.symbols,\n write: (text) => push(text),\n info: (message) => push(`[info] ${message}`),\n success: (message) => push(`[ok] ${message}`),\n warn: (message) => push(`[warn] ${message}`),\n error: (error) => push(`[error] ${stringifyError(error)}`),\n debug: (message) => push(`[debug] ${message}`),\n spinner: (message) => {\n push(`[spinner] ${message}`);\n return {\n update: (m) => push(`[spinner] ${m}`),\n succeed: (m) => push(`[ok] ${m ?? ''}`.trimEnd()),\n fail: (m) => push(`[fail] ${m ?? ''}`.trimEnd()),\n stop: () => {},\n };\n },\n table: (data) => push(JSON.stringify(data)),\n json: (data) => push(JSON.stringify(data)),\n newline: () => push(''),\n divider: () => push('---'),\n box: (content, title) => push(title ? `[${title}]\\n${content}` : content),\n sideBox: (options) => {\n push(`[${options.title}]`);\n if (options.summary) {\n push(JSON.stringify(options.summary));\n }\n },\n chain: (items) => items.forEach((item) => push(`• ${item.title}`)),\n log: (entry) => push(`[${entry.level}] ${entry.message}`),\n // Non-interactive defaults — same semantics as noopUI.\n confirm: async (message, options) => {\n push(`[confirm] ${message}`);\n return options?.defaultValue ?? true;\n },\n prompt: async (message, options) => {\n push(`[prompt] ${message}`);\n return options?.default ?? '';\n },\n select: async (message, choices) => {\n push(`[select] ${message}`);\n return choices[0]?.value as never;\n },\n multiSelect: async (message, choices) => {\n push(`[multiSelect] ${message}`);\n return choices.filter((c) => c.checked).map((c) => c.value) as never;\n },\n };\n\n return { ui, getOutput: () => lines.join('\\n') };\n}\n","/**\n * MCP authorization — decides which tools an authenticated identity may see and\n * call. Routed through the platform Policy Decision Point (@kb-labs/core-policy).\n *\n * The platform does not yet issue granular per-tool scopes in JWTs, and the PDP\n * is a permit-all stub by default. This module is the single seam where that\n * changes: when the platform resolves a real policy and/or richer identities,\n * only the policy passed to createPermits and the identity mapping here need to\n * evolve — the tool-builder and server code stay unchanged.\n */\n\nimport { can, type Policy, type Identity } from '@kb-labs/core-policy';\nimport type { AuthContext } from '@kb-labs/gateway-contracts';\n\n/**\n * Map a verified AuthContext to a policy Identity. Roles are derived from the\n * token's type and tier — the only identity signals the platform issues today.\n */\nexport function toIdentity(auth: AuthContext): Identity {\n return { user: auth.userId, roles: [auth.type, auth.tier] };\n}\n\n/**\n * Map a command's operationType to a PDP action verb. Read commands require the\n * read action; everything that can mutate or execute requires the write action.\n * Unknown/undefined operation types fail safe to write (the stronger gate).\n */\nexport function actionForOperation(operationType: string | undefined): string {\n return operationType === 'read' ? 'mcp.read' : 'mcp.write';\n}\n\n/** Predicate: may this identity use a command of the given operationType on the given plugin? */\nexport type Permits = (operationType: string | undefined, resource: string) => boolean;\n\n/**\n * Build a permits predicate bound to a resolved policy and identity. This is the\n * authorization seam — the policy is supplied by the daemon (permit-all stub\n * today, platform-resolved later).\n */\nexport function createPermits(policy: Policy, auth: AuthContext): Permits {\n const identity = toIdentity(auth);\n return (operationType, resource) =>\n can(policy, identity, actionForOperation(operationType), resource);\n}\n","/**\n * Tool builder — turns plugin manifests into MCP tool descriptors with ZERO\n * hardcoding. Every CLI command declared in a plugin manifest becomes a callable\n * MCP tool, gated by the authorization predicate (Permits) routed through the PDP.\n *\n * Two responsibilities, two functions:\n * - createToolRegistry(): called ONCE at daemon startup; builds the entity\n * registry whose snapshot is the source of available commands.\n * - filterTools(): pure, cheap, per-request; projects a snapshot down to the\n * tools the calling identity is permitted to use.\n */\n\nimport { createRegistry } from '@kb-labs/core-registry';\nimport { generateCommandSchema } from '@kb-labs/cli-commands';\nimport { getHandlerPermissions } from '@kb-labs/plugin-contracts';\nimport type { ICache } from '@kb-labs/core-platform';\nimport type {\n IEntityRegistry,\n RegistrySnapshot,\n RegistrySnapshotManifestEntry,\n} from '@kb-labs/core-registry';\nimport type { CliCommandDecl, PermissionSpec } from '@kb-labs/plugin-contracts';\nimport type { CommandManifest } from '@kb-labs/cli-commands';\nimport type { Permits } from './authz.js';\n\n/** A single plugin command exposed as an MCP tool, with everything needed to execute it. */\nexport interface McpTool {\n /** Namespaced, MCP-safe name: `${pluginId}__${command_path_with_underscores}`. */\n name: string;\n description: string;\n inputSchema: object;\n pluginId: string;\n pluginRoot: string;\n handlerPath: string;\n version: string;\n operationType: string | undefined;\n /** Handler permissions, propagated to executeCommandV3 for governance. */\n permissions: PermissionSpec;\n}\n\n/**\n * Build and initialize the entity registry. Called ONCE at daemon startup; the\n * returned registry's snapshot() feeds filterTools() on every request.\n */\nexport async function createToolRegistry(opts: {\n root: string;\n platformRoot?: string;\n cache: ICache;\n}): Promise<IEntityRegistry> {\n return createRegistry({\n root: opts.root,\n platformRoot: opts.platformRoot,\n cache: { ttlMs: 60_000, adapter: opts.cache },\n });\n}\n\n/**\n * Make a plugin ID safe for use in MCP tool names.\n * Strips the leading `@` from scoped npm packages and replaces `/` with `-`.\n * Example: \"@kb-labs/policy\" → \"kb-labs-policy\", \"my-plugin\" → \"my-plugin\".\n * Case is preserved because plugin IDs like \"pluginA\" are valid non-scoped names.\n */\nfunction sanitizePluginId(pluginId: string): string {\n return pluginId\n .replace(/^@/, '') // strip leading @\n .replace(/\\//g, '-') // replace / with -\n .replace(/[^a-zA-Z0-9-]/g, '-'); // replace any other unsafe chars\n}\n\n/**\n * Build a collision-safe MCP tool name: `{pluginId}__{command_path}`.\n * The plugin segment is sanitized so npm scope chars (@, /) are removed.\n */\nfunction toolName(pluginId: string, commandPath: string): string {\n return `${sanitizePluginId(pluginId)}__${commandPath.trim().replace(/\\s+/g, '_')}`;\n}\n\n/**\n * Adapt a manifest CLI command declaration into the CommandManifest shape that\n * generateCommandSchema consumes. Only the fields the schema generator reads are\n * meaningful here; loader is intentionally absent (schema generation never runs it).\n */\nfunction toCommandManifest(\n decl: CliCommandDecl,\n entry: RegistrySnapshotManifestEntry,\n): CommandManifest {\n const segments = decl.path.trim().split(/\\s+/).filter(Boolean);\n return {\n manifestVersion: '1.0',\n segments,\n id: segments[segments.length - 1] ?? '',\n group: segments[0] ?? '',\n subgroup: segments.length >= 3 ? segments[1] : undefined,\n describe: decl.describe ?? '',\n longDescription: decl.longDescription,\n aliases: decl.aliases,\n category: decl.category,\n flags: decl.flags,\n examples: decl.examples,\n operationType: decl.operationType,\n package: entry.pluginId,\n manifestV2: entry.manifest,\n pkgRoot: entry.pluginRoot,\n };\n}\n\n/**\n * Project a registry snapshot down to the MCP tools the identity may use.\n * Pure and cheap — safe to call per request. Authorization is delegated entirely\n * to the supplied Permits predicate (PDP seam).\n */\nexport function filterTools(\n snapshot: Pick<RegistrySnapshot, 'manifests'>,\n permits: Permits,\n): McpTool[] {\n const tools: McpTool[] = [];\n for (const entry of snapshot.manifests) {\n for (const decl of entry.manifest.cli?.commands ?? []) {\n if (!permits(decl.operationType, entry.pluginId)) {\n continue;\n }\n tools.push({\n name: toolName(entry.pluginId, decl.path),\n description: decl.describe,\n inputSchema: generateCommandSchema(toCommandManifest(decl, entry)),\n pluginId: entry.pluginId,\n pluginRoot: entry.pluginRoot,\n handlerPath: decl.handler,\n version: entry.manifest.version ?? '0.0.0',\n operationType: decl.operationType,\n permissions: getHandlerPermissions(entry.manifest, 'cli', decl.path),\n });\n }\n }\n return tools;\n}\n","/**\n * Tool router — executes a resolved McpTool by routing through the same V3\n * command pipeline the CLI uses (executeCommandV3). Plugin output is captured\n * via the platform's uiProvider mechanism:\n *\n * bootstrap.ts wires an AsyncLocalStorage-backed uiProvider to the execution\n * backend. callTool() activates the per-call context via callOutput.run();\n * the backend calls uiProvider() → createBufferedUI(push) where push appends\n * to the call-local buffer. Concurrent calls are fully isolated.\n *\n * Multi-tenancy seam: callTool never touches a global platform directly. It\n * resolves the PlatformContainer through `resolvePlatform(tenantId)`. Today that\n * returns the single global container; when the platform gains per-tenant\n * isolation, only the resolver changes — this module stays untouched.\n */\n\nimport path from 'node:path';\nimport { executeCommandV3 } from '@kb-labs/cli-runtime';\nimport { noopUI } from '@kb-labs/plugin-contracts';\nimport type { PlatformContainer } from '@kb-labs/core-runtime';\nimport type { PlatformServices } from '@kb-labs/plugin-contracts';\nimport { callOutput } from './output-capture.js';\nimport type { McpTool } from './tool-builder.js';\n\nexport interface ToolCallResult {\n success: boolean;\n output: string;\n exitCode: number;\n}\n\n/** Tenant → platform container. Default returns the global container; platform overrides for isolation. */\nexport type PlatformResolver = (tenantId: string) => PlatformContainer;\n\n/**\n * Resolve a manifest handler reference (e.g. \"dist/commands/x.js\" or\n * \"commands/x.js#handler\") to an absolute path under the plugin's dist/.\n * Mirrors the CLI plugin-executor so MCP and CLI execution stay identical.\n */\nfunction resolveHandlerPath(pluginRoot: string, handler: string): string {\n const relative = handler.split('#')[0] ?? handler;\n return relative.startsWith('dist/')\n ? path.resolve(pluginRoot, relative)\n : path.resolve(pluginRoot, 'dist', relative);\n}\n\n/** Project a PlatformContainer onto the PlatformServices surface executeCommandV3 consumes. */\nfunction createPlatformServices(container: PlatformContainer): PlatformServices {\n return {\n logger: container.logger,\n llm: container.llm,\n embeddings: container.embeddings,\n vectorStore: container.vectorStore,\n cache: container.cache,\n config: container.config,\n storage: container.storage,\n analytics: container.analytics,\n eventBus: container.eventBus,\n invoke: container.invoke,\n documentDatabase: container.documentDatabase,\n kvStore: container.kvStore,\n logs: container.logs,\n };\n}\n\n/**\n * Execute an MCP tool. tenantId is propagated end-to-end (no loss); the platform\n * container is resolved through the seam so isolation is the platform's concern.\n *\n * Output capture: activates the AsyncLocalStorage context so the execution\n * backend's uiProvider can write into the call-local `lines` buffer. The `ui`\n * param passed to executeCommandV3 is unused by V3 (the backend uses uiProvider),\n * but noopUI is passed explicitly to make the intent clear.\n */\nexport async function callTool(\n tool: McpTool,\n args: Record<string, unknown>,\n tenantId: string,\n resolvePlatform: PlatformResolver,\n): Promise<ToolCallResult> {\n const lines: string[] = [];\n const container = resolvePlatform(tenantId);\n\n const exitCode = await callOutput.run(lines, () =>\n executeCommandV3({\n pluginId: tool.pluginId,\n pluginVersion: tool.version,\n pluginRoot: tool.pluginRoot,\n handlerPath: resolveHandlerPath(tool.pluginRoot, tool.handlerPath),\n argv: [],\n flags: args,\n tenantId,\n // ui is ignored by executeCommandV3 V3 (backend uses uiProvider).\n // noopUI is passed explicitly to document this intent.\n ui: noopUI,\n platform: createPlatformServices(container),\n platformContainer: container,\n socketPath: container.getSocketPath(),\n permissions: tool.permissions,\n quotas: tool.permissions?.quotas,\n }),\n );\n\n return { success: exitCode === 0, output: lines.join('\\n'), exitCode };\n}\n","/**\n * Request handler logic for the MCP endpoint, extracted from the Fastify/MCP-SDK\n * shell so every authorization and caching branch is unit-testable without\n * spinning up an HTTP server or a transport.\n *\n * server.ts wires these pure(ish) functions to the MCP SDK request handlers;\n * the SDK/transport plumbing itself is exercised by the e2e suite.\n */\n\nimport { createHash } from 'node:crypto';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ICache, IAnalytics } from '@kb-labs/core-platform';\nimport type { IEntityRegistry } from '@kb-labs/core-registry';\nimport { filterTools, type McpTool } from './tool-builder.js';\nimport { callTool, type PlatformResolver } from './tool-router.js';\nimport type { Permits } from './authz.js';\nimport type { McpObservabilityCollector } from '../observability/collector.js';\n\n/** How long a per-identity tool listing stays cached. */\nexport const TOOLS_CACHE_TTL_MS = 60_000;\n\n/** Build a text-only MCP tool result (the only content shape this daemon emits). */\nfunction textResult(text: string, isError: boolean): CallToolResult {\n return { content: [{ type: 'text', text }], isError };\n}\n\n/**\n * Cache key for an identity's visible tool list. Authenticated identities are\n * keyed by a hash of their Authorization header (per-token, per-tenant\n * isolation); everything else shares the single anonymous bucket.\n */\nexport function toolsCacheKey(authHeader: string | null | undefined): string {\n if (!authHeader) {\n return 'mcp:tools:anonymous';\n }\n return `mcp:tools:${createHash('sha256').update(authHeader).digest('hex').slice(0, 16)}`;\n}\n\nexport interface ResolveVisibleToolsArgs {\n /** Identity-bound authorization predicate, or null for anonymous callers. */\n permits: Permits | null;\n /** Raw Authorization header — only used to derive the per-token cache key. */\n authHeader: string | null | undefined;\n registry: IEntityRegistry;\n cache: ICache;\n /** Platform analytics — emits mcp.tools.list event. Optional for tests. */\n analytics?: IAnalytics | null;\n /** Observability collector — records mcp.tools.list operation. Optional for tests. */\n collector?: McpObservabilityCollector;\n /** Tenant ID for analytics context. */\n tenantId?: string;\n}\n\n/**\n * Resolve the tools an identity may see. Cached per identity for 60s; the cache\n * is a LISTING optimization only — it is never the authority for execution\n * (executeToolCall re-checks the live policy). Anonymous callers (permits=null)\n * always get an empty list and never touch the registry.\n */\nexport async function resolveVisibleTools(args: ResolveVisibleToolsArgs): Promise<McpTool[]> {\n const { permits, authHeader, registry, cache, analytics, collector, tenantId = 'anonymous' } =\n args;\n const t0 = Date.now();\n\n // Anonymous identities share one bucket regardless of any (invalid) header.\n const cacheKey = toolsCacheKey(permits ? authHeader : null);\n\n const cached = await cache.get<McpTool[]>(cacheKey).catch(() => null);\n if (cached) {\n const durationMs = Date.now() - t0;\n collector?.recordOp('mcp.tools.list', durationMs, true);\n analytics?.track('mcp.tools.list', {\n tenantId,\n toolCount: cached.length,\n cached: true,\n durationMs,\n }).catch(() => {});\n return cached;\n }\n\n const tools = permits ? filterTools(registry.snapshot(), permits) : [];\n await cache.set(cacheKey, tools, TOOLS_CACHE_TTL_MS).catch(() => {});\n\n const durationMs = Date.now() - t0;\n collector?.recordOp('mcp.tools.list', durationMs, true);\n analytics?.track('mcp.tools.list', {\n tenantId,\n toolCount: tools.length,\n cached: false,\n durationMs,\n }).catch(() => {});\n\n return tools;\n}\n\nexport interface ExecuteToolCallArgs {\n name: string;\n args: Record<string, unknown>;\n visibleTools: McpTool[];\n /** Identity-bound predicate, or null for anonymous. */\n permits: Permits | null;\n tenantId: string;\n resolvePlatform: PlatformResolver;\n /** Platform analytics — emits mcp.tool.call events. Optional for tests. */\n analytics?: IAnalytics | null;\n /** Observability collector — records mcp.tool.call operation. Optional for tests. */\n collector?: McpObservabilityCollector;\n}\n\n/**\n * Execute a tool call. Two independent gates protect execution:\n * 1. the tool must be in the caller's visible set, and\n * 2. the LIVE policy must still permit it (re-checked here, not trusted from\n * the possibly-stale cached listing).\n * Only then is the command run via executeCommandV3.\n */\nexport async function executeToolCall(args: ExecuteToolCallArgs): Promise<CallToolResult> {\n const { name, visibleTools, permits, tenantId, resolvePlatform, analytics, collector } = args;\n const t0 = Date.now();\n\n const tool = visibleTools.find((t) => t.name === name);\n if (!tool) {\n return textResult(`Unknown tool: ${name}`, true);\n }\n\n // Authoritative gate — independent of the cached visibility list. When the\n // platform supplies a real policy, a tool that became forbidden after it was\n // cached is rejected here with no server code change.\n if (!permits || !permits(tool.operationType, tool.pluginId)) {\n return textResult(`Not authorized: ${name}`, true);\n }\n\n analytics?.track('mcp.tool.call.started', {\n toolName: name,\n tenantId,\n pluginId: tool.pluginId,\n }).catch(() => {});\n\n const result = await callTool(tool, args.args, tenantId, resolvePlatform);\n\n const durationMs = Date.now() - t0;\n collector?.recordOp('mcp.tool.call', durationMs, result.success);\n analytics?.track('mcp.tool.call.completed', {\n toolName: name,\n tenantId,\n pluginId: tool.pluginId,\n success: result.success,\n exitCode: result.exitCode,\n outputLength: result.output.length,\n durationMs,\n }).catch(() => {});\n\n return textResult(result.output, !result.success);\n}\n","/**\n * MCP Daemon observability collector.\n *\n * Mirrors the GatewayObservabilityCollector pattern: registers Fastify\n * onRequest/onResponse hooks for HTTP-level metrics, tracks domain operations\n * (mcp.tools.list, mcp.tool.call) via OperationMetricsTracker, and builds\n * the three standard observability payloads:\n *\n * /health → buildHealth() (also used for /observability/health)\n * /observability/describe → buildDescribe()\n * /metrics → renderPrometheusMetrics()\n *\n * All payloads are validated against the platform observability contract via\n * createServiceObservabilityDescribe / createServiceObservabilityHealth.\n */\n\nimport { performance } from 'node:perf_hooks';\nimport type { FastifyInstance } from 'fastify';\nimport {\n OperationMetricsTracker,\n createServiceObservabilityDescribe,\n createServiceObservabilityHealth,\n resolveObservabilityInstanceId,\n} from '@kb-labs/shared-http';\nimport type { ObservabilityCapability, CanonicalObservabilityMetric } from '@kb-labs/core-contracts';\n\n/** Domain operations tracked at the MCP level. */\nexport type McpOperation = 'mcp.tools.list' | 'mcp.tool.call';\n\nexport class McpObservabilityCollector {\n private readonly instanceId = resolveObservabilityInstanceId();\n private readonly startedAt = new Date().toISOString();\n private activeRequests = 0;\n private requestsTotal = 0;\n private errorsTotal = 0;\n private readonly ops = new OperationMetricsTracker();\n\n /**\n * Register Fastify hooks that track HTTP-level request counts and duration.\n * Must be called before routes are registered so the hooks apply to all routes.\n */\n register(server: FastifyInstance): void {\n server.addHook('onRequest', (req, _reply, done) => {\n req.kbMetricsStart = performance.now();\n this.activeRequests++;\n done();\n });\n\n server.addHook('onResponse', (req, reply, done) => {\n const start = req.kbMetricsStart;\n const durationMs = start != null ? performance.now() - start : 0;\n this.activeRequests = Math.max(0, this.activeRequests - 1);\n this.requestsTotal++;\n if (reply.statusCode >= 400) { this.errorsTotal++; }\n // Track HTTP ops in operation tracker for /metrics output.\n const route = (req.routeOptions?.url ?? req.url).replace(/[?#].*$/, '');\n this.ops.recordOperation(`http.${req.method} ${route}`, durationMs,\n reply.statusCode >= 400 ? 'error' : 'ok');\n done();\n });\n }\n\n /**\n * Record a completed domain operation. Called from request-handler after\n * each tools/list and tools/call cycle.\n */\n recordOp(name: McpOperation, durationMs: number, ok: boolean): void {\n this.ops.recordOperation(name, durationMs, ok ? 'ok' : 'error');\n }\n\n // ── Observability payload builders ──────────────────────────────────────\n\n buildDescribe(registryReady: boolean, toolCount: number) {\n return createServiceObservabilityDescribe({\n schema: 'kb.observability/1' as const,\n contractVersion: '1.0' as const,\n serviceId: 'mcp-daemon',\n instanceId: this.instanceId,\n serviceType: 'mcp-server',\n version: process.env.npm_package_version ?? '0.0.0',\n environment: process.env.NODE_ENV ?? 'development',\n startedAt: this.startedAt,\n logsSource: 'mcp-daemon',\n dependencies: [],\n metricsEndpoint: '/metrics',\n healthEndpoint: '/observability/health',\n capabilities: ['httpMetrics', 'operationMetrics', 'logCorrelation'] as ObservabilityCapability[],\n metricFamilies: [\n 'process_rss_bytes',\n 'process_heap_used_bytes',\n 'service_active_operations',\n 'http_requests_total',\n 'http_errors_total',\n 'service_operation_total',\n 'service_operation_duration_ms',\n ] as CanonicalObservabilityMetric[],\n meta: { toolCount, registryReady },\n });\n }\n\n buildHealth(registryReady: boolean, toolCount: number, executionMode: string) {\n const mem = process.memoryUsage();\n return createServiceObservabilityHealth({\n schema: 'kb.observability/1' as const,\n contractVersion: '1.0' as const,\n serviceId: 'mcp-daemon',\n instanceId: this.instanceId,\n observedAt: new Date().toISOString(),\n status: registryReady ? ('healthy' as const) : ('degraded' as const),\n uptimeSec: Math.floor(process.uptime()),\n logsSource: 'mcp-daemon',\n metricsEndpoint: '/metrics',\n capabilities: ['httpMetrics', 'operationMetrics', 'logCorrelation'] as ObservabilityCapability[],\n snapshot: {\n rssBytes: mem.rss,\n heapUsedBytes: mem.heapUsed,\n activeOperations: this.activeRequests,\n },\n checks: [\n {\n id: 'registry',\n status: (registryReady ? 'ok' : 'warn') as 'ok' | 'warn' | 'error',\n message: registryReady ? `${toolCount} tools loaded` : 'Registry not yet ready',\n },\n {\n id: 'execution',\n status: 'ok' as const,\n message: `mode=${executionMode}`,\n },\n ],\n topOperations: this.ops.getTopOperations(5),\n });\n }\n\n renderPrometheusMetrics(toolCount: number): string {\n const mem = process.memoryUsage();\n const lines: string[] = [\n '# HELP process_rss_bytes RSS memory in bytes',\n `process_rss_bytes ${mem.rss}`,\n '# HELP process_heap_used_bytes Heap used in bytes',\n `process_heap_used_bytes ${mem.heapUsed}`,\n '# HELP process_uptime_seconds Process uptime in seconds',\n `process_uptime_seconds ${Math.floor(process.uptime())}`,\n '# HELP mcp_tools_total Number of tools registered in the current snapshot',\n `mcp_tools_total ${toolCount}`,\n '# HELP http_requests_total Total MCP HTTP requests received',\n `http_requests_total ${this.requestsTotal}`,\n '# HELP http_errors_total Total MCP HTTP 4xx/5xx responses',\n `http_errors_total ${this.errorsTotal}`,\n '# HELP service_active_operations Currently active MCP requests',\n `service_active_operations ${this.activeRequests}`,\n ...this.ops.getMetricLines(),\n ];\n return lines.join('\\n');\n }\n}\n","/**\n * MCP Daemon HTTP server.\n *\n * Exposes a single JSON-RPC endpoint (`/api/v1/mcp`) speaking the Model Context\n * Protocol over Streamable HTTP, plus the standard platform observability endpoints:\n *\n * GET /health → McpObservabilityCollector.buildHealth()\n * GET /ready → 200/503 based on registry readiness\n * GET /metrics → Prometheus text format\n * GET /observability/describe → service identity + capabilities\n * GET /observability/health → full snapshot with checks and top operations\n *\n * Design notes:\n * - The entity registry is initialized ONCE at start() and reused for every\n * request; only the cheap, pure filterTools() runs per request.\n * - This endpoint sits in front of the gateway's auth scope (the gateway proxies\n * it as a dumb upstream), so the daemon validates the Bearer token itself via\n * the shared GATEWAY_JWT_SECRET — exactly mirroring the gateway's AuthService.\n * - Anonymous callers (no/invalid token) get an empty tool list and can never\n * reach callTool/executeCommandV3.\n * - tenantId flows end-to-end from AuthContext.namespaceId into executeCommandV3\n * via the resolvePlatform seam — ready for per-tenant isolation without code\n * changes here.\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport { Server as McpServer } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { can, type Policy, type Identity } from '@kb-labs/core-policy';\nimport type { ICache, ILogger } from '@kb-labs/core-platform';\nimport type { JwtConfig } from '@kb-labs/gateway-auth';\nimport type { PlatformContainer } from '@kb-labs/core-runtime';\nimport type { IEntityRegistry } from '@kb-labs/core-registry';\nimport { createDaemonServer, getListenOptions, type ObservabilityCollectorLike } from '@kb-labs/shared-http';\nimport { resolveAuthContext } from './mcp/auth.js';\nimport { toIdentity, actionForOperation, type Permits } from './mcp/authz.js';\nimport { createToolRegistry } from './mcp/tool-builder.js';\nimport { type PlatformResolver } from './mcp/tool-router.js';\nimport { resolveVisibleTools, executeToolCall } from './mcp/request-handler.js';\nimport { McpObservabilityCollector } from './observability/collector.js';\n\nexport interface McpDaemonServerOptions {\n port: number;\n host: string;\n logger: ILogger;\n cache: ICache;\n /** Default global platform container — used as the resolvePlatform fallback. */\n platform: PlatformContainer;\n /** Tenant → platform container seam. Defaults to always returning `platform`. */\n resolvePlatform?: PlatformResolver;\n /** Workspace root used to initialize the entity registry. */\n projectRoot: string;\n /** Platform installation root (installed mode); merges platform-level plugins. */\n platformRoot?: string;\n jwtConfig: JwtConfig;\n /** Authorization policy. Permit-all default until the platform supplies a real one. */\n policy: Policy;\n}\n\nexport class McpDaemonServer {\n private readonly opts: McpDaemonServerOptions;\n private readonly resolvePlatform: PlatformResolver;\n private readonly collector: McpObservabilityCollector;\n private app: FastifyInstance | undefined;\n private registry: IEntityRegistry | undefined;\n\n constructor(opts: McpDaemonServerOptions) {\n this.opts = opts;\n this.resolvePlatform = opts.resolvePlatform ?? (() => opts.platform);\n this.collector = new McpObservabilityCollector();\n }\n\n /** Build a per-request permits predicate bound to the identity (PDP seam). */\n private permitsFor(identity: Identity): Permits {\n return (operationType, resource) =>\n can(this.opts.policy, identity, actionForOperation(operationType), resource);\n }\n\n private get toolCount(): number {\n return (\n this.registry\n ?.snapshot()\n .manifests.flatMap((m) => m.manifest.cli?.commands ?? []).length ?? 0\n );\n }\n\n async start(): Promise<string> {\n // Initialize the registry ONCE; snapshot() is reused per request.\n this.registry = await createToolRegistry({\n root: this.opts.projectRoot,\n platformRoot: this.opts.platformRoot,\n cache: this.opts.cache,\n });\n\n const execMode = process.env.KB_MCP_EXECUTION_MODE ?? 'subprocess';\n\n // Adapter: wraps McpObservabilityCollector to match ObservabilityCollectorLike.\n // Arrow functions capture `this` so the live registry/toolCount state is always current.\n const observabilityAdapter: ObservabilityCollectorLike = {\n register: (server: FastifyInstance) => this.collector.register(server),\n buildDescribe: () => this.collector.buildDescribe(!!this.registry, this.toolCount),\n buildHealth: () => this.collector.buildHealth(!!this.registry, this.toolCount, execMode),\n renderPrometheusMetrics: (_status: string) => this.collector.renderPrometheusMetrics(this.toolCount),\n };\n\n this.app = await createDaemonServer({\n serviceId: 'mcp-daemon',\n logger: this.opts.logger,\n observability: observabilityAdapter,\n readyCheck: () => ({ ready: !!this.registry, service: 'mcp-daemon' }),\n registerRoutes: async (server) => this.registerMcpRoutes(server),\n });\n\n const listenOptions = getListenOptions(this.opts.port, this.opts.host);\n const address = await this.app.listen(listenOptions);\n\n this.opts.logger.info('MCP daemon listening', { address });\n return address;\n }\n\n async stop(): Promise<void> {\n await this.app?.close();\n }\n\n private async registerMcpRoutes(server: FastifyInstance): Promise<void> {\n const { cache, logger, jwtConfig } = this.opts;\n\n // ── MCP JSON-RPC endpoint ──────────────────────────────────────────────\n\n // CORS headers for all MCP responses (including preflight OPTIONS).\n // fastify.all() covers every method including OPTIONS, so no separate\n // fastify.options() is needed — that would cause a duplicate-route error.\n server.all('/api/v1/mcp', async (request, reply) => {\n reply\n .header('Access-Control-Allow-Origin', '*')\n .header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')\n .header('Access-Control-Allow-Headers', 'Authorization, Content-Type, Mcp-Session-Id');\n\n // Short-circuit preflight immediately — no auth or MCP processing needed.\n if (request.method === 'OPTIONS') {\n return reply.code(204).send();\n }\n\n const reqLogger = request.kbLogger ?? logger;\n\n // 1. Authenticate. Invalid/absent token → anonymous (no throw, no 401).\n const authHeader = request.headers.authorization;\n const authCtx = await resolveAuthContext(authHeader, cache, jwtConfig).catch(\n () => null,\n );\n const tenantId = authCtx?.namespaceId ?? 'anonymous';\n\n // Bind the authorization predicate to the identity once per request.\n // Anonymous callers get no predicate → they can neither list nor call tools.\n const permits = authCtx ? this.permitsFor(toIdentity(authCtx)) : null;\n\n // 2. Resolve the visible tool list (cached per identity). The cache is a\n // listing optimization ONLY — executeToolCall re-checks the live policy.\n const visibleTools = await resolveVisibleTools({\n permits,\n authHeader,\n registry: this.registry!,\n cache,\n analytics: this.opts.platform.analytics,\n collector: this.collector,\n tenantId,\n });\n\n // 3. Build a stateless per-request MCP server.\n const mcp = new McpServer(\n { name: 'kb-labs', version: '1.0.0' },\n { capabilities: { tools: {} } },\n );\n\n mcp.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: visibleTools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema as { type: 'object' },\n })),\n }));\n\n mcp.setRequestHandler(CallToolRequestSchema, async ({ params }) =>\n executeToolCall({\n name: params.name,\n args: (params.arguments ?? {}) as Record<string, unknown>,\n visibleTools,\n permits,\n tenantId,\n resolvePlatform: this.resolvePlatform,\n analytics: this.opts.platform.analytics,\n collector: this.collector,\n }),\n );\n\n // 4. Streamable HTTP transport (stateless). Pass Fastify's parsed body —\n // the raw stream is already consumed, so the SDK must not re-read it.\n const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });\n try {\n await mcp.connect(transport);\n await transport.handleRequest(request.raw, reply.raw, request.body);\n } catch (error) {\n reqLogger.error('MCP request handling failed', error as Error);\n if (!reply.raw.headersSent) {\n reply.code(500).send({ error: 'internal_error' });\n }\n } finally {\n // Closing may reject if the transport is already torn down — swallow it\n // so it can never surface as an unhandled rejection after the response.\n await mcp.close().catch(() => {});\n }\n });\n }\n}\n","import { platform, createServiceBootstrap, getPlatformRoot, getProjectRoot } from '@kb-labs/core-runtime';\nimport { makeAssemblyHook } from '@kb-labs/plugin-runtime';\nimport { resolvePolicy } from '@kb-labs/core-policy';\nimport { createCorrelatedLogger, resolveObservabilityInstanceId } from '@kb-labs/shared-http';\nimport { noopUI } from '@kb-labs/plugin-contracts';\nimport { runDaemon } from '@kb-labs/shared-daemon';\nimport { loadJwtConfig } from './mcp/auth.js';\nimport { callOutput } from './mcp/output-capture.js';\nimport { createBufferedUI } from './mcp/ui.js';\nimport { McpDaemonServer } from './server.js';\n\nexport async function bootstrap(): Promise<void> {\n await runDaemon(\n {\n appId: 'mcp-daemon',\n defaultPort: 7779,\n portEnvVar: 'KB_MCP_DAEMON_PORT',\n defaultHost: 'localhost',\n hostEnvVar: 'KB_MCP_DAEMON_HOST',\n async setup({ port, host }) {\n const logger = createCorrelatedLogger(platform.logger, {\n serviceId: 'mcp-daemon',\n instanceId: resolveObservabilityInstanceId(),\n logsSource: 'mcp-daemon',\n layer: 'mcp',\n service: 'bootstrap',\n operation: 'mcp-daemon.bootstrap',\n });\n\n logger.info('MCP daemon platform initialised');\n\n const projectRoot = getProjectRoot() ?? process.cwd();\n const platformRoot = getPlatformRoot();\n\n const { policy } = await resolvePolicy({});\n\n const server = new McpDaemonServer({\n port,\n host,\n logger,\n cache: platform.cache,\n platform,\n resolvePlatform: () => platform,\n projectRoot,\n platformRoot,\n jwtConfig: loadJwtConfig(),\n policy,\n });\n\n await server.start();\n\n return async () => {\n await server.stop();\n };\n },\n },\n // platformBootstrap: full init with uiProvider for callOutput ALS wiring.\n // uiProvider flows into initPlatform → createExecutionBackend so the backend\n // captures plugin output from the very start. Concurrent tool calls are\n // fully isolated — each gets its own AsyncLocalStorage slot.\n async (appId, repoRoot) => {\n await createServiceBootstrap({\n appId,\n repoRoot,\n uiProvider: (_hostType: string) => {\n const lines = callOutput.getStore();\n return lines ? createBufferedUI((s) => lines.push(s)).ui : noopUI;\n },\n assemblyHook: makeAssemblyHook(),\n });\n return platform;\n },\n );\n}\n","import { bootstrap } from './bootstrap.js';\n\n// runDaemon() (called inside bootstrap) resolves repo root via findRepoRoot().\nbootstrap().catch((error) => {\n console.error('Failed to start MCP daemon:', error);\n process.exit(1);\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/mcp/auth.ts","../src/mcp/output-capture.ts","../src/mcp/ui.ts","../src/mcp/authz.ts","../src/mcp/tool-builder.ts","../src/mcp/tool-router.ts","../src/mcp/request-handler.ts","../src/observability/collector.ts","../src/server.ts","../src/bootstrap.ts","../src/index.ts"],"names":["noopUI","durationMs","can","McpServer","resolveObservabilityInstanceId"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * MCP authentication — Bearer token verification against the shared gateway\n * JWT secret. Authorization (which tools an identity may use) lives in authz.ts,\n * routed through the platform PDP.\n */\n\nimport { AuthService, type JwtConfig } from '@kb-labs/gateway-auth';\nimport type { ICache } from '@kb-labs/core-platform';\nimport type { AuthContext } from '@kb-labs/gateway-contracts';\n\n/**\n * Insecure development fallback. Must never be used in production — loadJwtConfig\n * throws when NODE_ENV=production and no real secret is configured.\n */\nconst DEV_JWT_SECRET = 'dev-insecure-secret-change-me';\n\n/**\n * Load the JWT config from the environment. Uses the same GATEWAY_JWT_SECRET as\n * the gateway so tokens issued by the gateway are accepted by the MCP daemon.\n */\nexport function loadJwtConfig(): JwtConfig {\n const secret = process.env.GATEWAY_JWT_SECRET;\n if (!secret && process.env.NODE_ENV === 'production') {\n throw new Error(\n 'GATEWAY_JWT_SECRET must be set in production. ' +\n 'Generate one with: node -e \"console.log(require(\\'crypto\\').randomBytes(64).toString(\\'hex\\'))\"',\n );\n }\n return { secret: secret ?? DEV_JWT_SECRET };\n}\n\n/**\n * Extract a Bearer token from an Authorization header, or null.\n *\n * Parsing avoids overlapping quantifiers (e.g. `\\s+(.+)`) on the\n * attacker-controlled header: an anchored single-`\\s` scheme check is linear,\n * then the remainder is sliced and trimmed. This sidesteps the polynomial\n * ReDoS that `/^Bearer\\s+(.+)$/` exhibits on `\"Bearer\" + \" \".repeat(n)`.\n */\nexport function extractBearer(header: string | undefined): string | null {\n if (header === undefined || !/^bearer\\s/i.test(header)) {\n return null;\n }\n const token = header.slice('bearer'.length).trim();\n return token.length > 0 ? token : null;\n}\n\n/**\n * Resolve a verified AuthContext from an Authorization header.\n * Returns null for anonymous (no/invalid token) — the caller treats this as\n * \"no tools, no execution\".\n */\nexport async function resolveAuthContext(\n header: string | undefined,\n cache: ICache,\n jwtConfig: JwtConfig,\n): Promise<AuthContext | null> {\n const token = extractBearer(header);\n if (!token) {\n return null;\n }\n return new AuthService(cache, jwtConfig).verify(token);\n}\n","/**\n * AsyncLocalStorage singleton for per-call plugin output capture.\n *\n * bootstrap.ts wires a uiProvider that reads from this store so each\n * callTool() invocation captures plugin UI output into its own isolated\n * buffer — concurrent calls never mix their output.\n *\n * Usage:\n * // producer (callTool):\n * const lines: string[] = [];\n * await callOutput.run(lines, () => executeCommandV3(...));\n * return lines.join('\\n');\n *\n * // consumer (uiProvider in bootstrap):\n * uiProvider: () => {\n * const lines = callOutput.getStore();\n * return lines ? createBufferedUI((s) => lines.push(s)).ui : noopUI;\n * }\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nexport const callOutput = new AsyncLocalStorage<string[]>();\n","/**\n * BufferedUI — a UIFacade implementation that captures all output into a string\n * buffer instead of writing to a TTY. Used to run plugin commands headlessly and\n * return their textual output as an MCP tool result.\n *\n * Output methods append to the buffer. Interactive methods return safe,\n * non-blocking defaults (mirroring the canonical noopUI) because an MCP tool call\n * is non-interactive — there is no human to answer a prompt.\n */\n\nimport { noopUI } from '@kb-labs/plugin-contracts';\nimport type { UIFacade } from '@kb-labs/plugin-contracts';\n\nexport interface BufferedUI {\n ui: UIFacade;\n getOutput: () => string;\n}\n\nfunction stringifyError(error: Error | string): string {\n return typeof error === 'string' ? error : error.message;\n}\n\n/**\n * Create a buffered UI facade.\n *\n * @param pushFn - Optional external push function. When provided (e.g. from the\n * AsyncLocalStorage-backed uiProvider in bootstrap), output is appended there\n * and `getOutput()` returns an empty string. When omitted, output is stored in\n * an internal array and available via `getOutput()`.\n */\nexport function createBufferedUI(pushFn?: (text: string) => void): BufferedUI {\n const lines: string[] = [];\n const push = (text: string): void => {\n if (pushFn) {\n pushFn(text);\n } else {\n lines.push(text);\n }\n };\n\n const ui: UIFacade = {\n colors: noopUI.colors,\n symbols: noopUI.symbols,\n write: (text) => push(text),\n info: (message) => push(`[info] ${message}`),\n success: (message) => push(`[ok] ${message}`),\n warn: (message) => push(`[warn] ${message}`),\n error: (error) => push(`[error] ${stringifyError(error)}`),\n debug: (message) => push(`[debug] ${message}`),\n spinner: (message) => {\n push(`[spinner] ${message}`);\n return {\n update: (m) => push(`[spinner] ${m}`),\n succeed: (m) => push(`[ok] ${m ?? ''}`.trimEnd()),\n fail: (m) => push(`[fail] ${m ?? ''}`.trimEnd()),\n stop: () => {},\n };\n },\n table: (data) => push(JSON.stringify(data)),\n json: (data) => push(JSON.stringify(data)),\n newline: () => push(''),\n divider: () => push('---'),\n box: (content, title) => push(title ? `[${title}]\\n${content}` : content),\n sideBox: (options) => {\n push(`[${options.title}]`);\n if (options.summary) {\n push(JSON.stringify(options.summary));\n }\n },\n chain: (items) => items.forEach((item) => push(`• ${item.title}`)),\n log: (entry) => push(`[${entry.level}] ${entry.message}`),\n // Non-interactive defaults — same semantics as noopUI.\n confirm: async (message, options) => {\n push(`[confirm] ${message}`);\n return options?.defaultValue ?? true;\n },\n prompt: async (message, options) => {\n push(`[prompt] ${message}`);\n return options?.default ?? '';\n },\n select: async (message, choices) => {\n push(`[select] ${message}`);\n return choices[0]?.value as never;\n },\n multiSelect: async (message, choices) => {\n push(`[multiSelect] ${message}`);\n return choices.filter((c) => c.checked).map((c) => c.value) as never;\n },\n };\n\n return { ui, getOutput: () => lines.join('\\n') };\n}\n","/**\n * MCP authorization — decides which tools an authenticated identity may see and\n * call. Routed through the platform Policy Decision Point (@kb-labs/core-policy).\n *\n * The platform does not yet issue granular per-tool scopes in JWTs, and the PDP\n * is a permit-all stub by default. This module is the single seam where that\n * changes: when the platform resolves a real policy and/or richer identities,\n * only the policy passed to createPermits and the identity mapping here need to\n * evolve — the tool-builder and server code stay unchanged.\n */\n\nimport { can, type Policy, type Identity } from '@kb-labs/core-policy';\nimport type { AuthContext } from '@kb-labs/gateway-contracts';\n\n/**\n * Map a verified AuthContext to a policy Identity. Roles are derived from the\n * token's type and tier — the only identity signals the platform issues today.\n */\nexport function toIdentity(auth: AuthContext): Identity {\n return { user: auth.userId, roles: [auth.type, auth.tier] };\n}\n\n/**\n * Map a command's operationType to a PDP action verb. Read commands require the\n * read action; everything that can mutate or execute requires the write action.\n * Unknown/undefined operation types fail safe to write (the stronger gate).\n */\nexport function actionForOperation(operationType: string | undefined): string {\n return operationType === 'read' ? 'mcp.read' : 'mcp.write';\n}\n\n/** Predicate: may this identity use a command of the given operationType on the given plugin? */\nexport type Permits = (operationType: string | undefined, resource: string) => boolean;\n\n/**\n * Build a permits predicate bound to a resolved policy and identity. This is the\n * authorization seam — the policy is supplied by the daemon (permit-all stub\n * today, platform-resolved later).\n */\nexport function createPermits(policy: Policy, auth: AuthContext): Permits {\n const identity = toIdentity(auth);\n return (operationType, resource) =>\n can(policy, identity, actionForOperation(operationType), resource);\n}\n","/**\n * Tool builder — turns plugin manifests into MCP tool descriptors with ZERO\n * hardcoding. Every CLI command declared in a plugin manifest becomes a callable\n * MCP tool, gated by the authorization predicate (Permits) routed through the PDP.\n *\n * Two responsibilities, two functions:\n * - createToolRegistry(): called ONCE at daemon startup; builds the entity\n * registry whose snapshot is the source of available commands.\n * - filterTools(): pure, cheap, per-request; projects a snapshot down to the\n * tools the calling identity is permitted to use.\n */\n\nimport { createRegistry } from '@kb-labs/core-registry';\nimport { generateCommandSchema } from '@kb-labs/cli-commands';\nimport { getHandlerPermissions } from '@kb-labs/plugin-contracts';\nimport type { ICache } from '@kb-labs/core-platform';\nimport type {\n IEntityRegistry,\n RegistrySnapshot,\n RegistrySnapshotManifestEntry,\n} from '@kb-labs/core-registry';\nimport type { CliCommandDecl, PermissionSpec } from '@kb-labs/plugin-contracts';\nimport type { CommandManifest } from '@kb-labs/cli-commands';\nimport type { Permits } from './authz.js';\n\n/** A single plugin command exposed as an MCP tool, with everything needed to execute it. */\nexport interface McpTool {\n /** Namespaced, MCP-safe name: `${pluginId}__${command_path_with_underscores}`. */\n name: string;\n description: string;\n inputSchema: object;\n pluginId: string;\n pluginRoot: string;\n handlerPath: string;\n version: string;\n operationType: string | undefined;\n /** Handler permissions, propagated to executeCommandV3 for governance. */\n permissions: PermissionSpec;\n}\n\n/** A command that failed to become an MCP tool — malformed manifest, never a fatal error. */\nexport interface ToolBuildDiagnostic {\n pluginId: string;\n /** decl.id when present, else the raw (possibly missing) path — whatever identifies the command in the manifest. */\n commandId: string;\n error: string;\n}\n\n/**\n * Build and initialize the entity registry. Called ONCE at daemon startup; the\n * returned registry's snapshot() feeds filterTools() on every request.\n */\nexport async function createToolRegistry(opts: {\n root: string;\n platformRoot?: string;\n cache: ICache;\n}): Promise<IEntityRegistry> {\n return createRegistry({\n root: opts.root,\n platformRoot: opts.platformRoot,\n cache: { ttlMs: 60_000, adapter: opts.cache },\n });\n}\n\n/**\n * Make a plugin ID safe for use in MCP tool names.\n * Strips the leading `@` from scoped npm packages and replaces `/` with `-`.\n * Example: \"@kb-labs/policy\" → \"kb-labs-policy\", \"my-plugin\" → \"my-plugin\".\n * Case is preserved because plugin IDs like \"pluginA\" are valid non-scoped names.\n */\nfunction sanitizePluginId(pluginId: string): string {\n return pluginId\n .replace(/^@/, '') // strip leading @\n .replace(/\\//g, '-') // replace / with -\n .replace(/[^a-zA-Z0-9-]/g, '-'); // replace any other unsafe chars\n}\n\n/**\n * Build a collision-safe MCP tool name: `{pluginId}__{command_path}`.\n * The plugin segment is sanitized so npm scope chars (@, /) are removed.\n */\nfunction toolName(pluginId: string, commandPath: string): string {\n return `${sanitizePluginId(pluginId)}__${commandPath.trim().replace(/\\s+/g, '_')}`;\n}\n\n/**\n * Adapt a manifest CLI command declaration into the CommandManifest shape that\n * generateCommandSchema consumes. Only the fields the schema generator reads are\n * meaningful here; loader is intentionally absent (schema generation never runs it).\n */\nfunction toCommandManifest(\n decl: CliCommandDecl,\n entry: RegistrySnapshotManifestEntry,\n): CommandManifest {\n const segments = decl.path.trim().split(/\\s+/).filter(Boolean);\n return {\n manifestVersion: '1.0',\n segments,\n id: segments[segments.length - 1] ?? '',\n group: segments[0] ?? '',\n subgroup: segments.length >= 3 ? segments[1] : undefined,\n describe: decl.describe ?? '',\n longDescription: decl.longDescription,\n aliases: decl.aliases,\n category: decl.category,\n flags: decl.flags,\n examples: decl.examples,\n operationType: decl.operationType,\n package: entry.pluginId,\n manifestV2: entry.manifest,\n pkgRoot: entry.pluginRoot,\n };\n}\n\n/**\n * Build one MCP tool from a command declaration. Throws if the declaration\n * doesn't conform to CliCommandDecl (e.g. missing `path` — seen from manifests\n * scaffolded against an older/wrong shape). Callers decide what to do with a\n * throw; this function never partially mutates shared state.\n */\nfunction buildTool(entry: RegistrySnapshotManifestEntry, decl: CliCommandDecl): McpTool {\n if (typeof decl.path !== 'string' || decl.path.trim().length === 0) {\n throw new Error(\n `command \"${(decl as { id?: string }).id ?? '(unknown)'}\" in plugin \"${entry.pluginId}\" has no \"path\" field — skipping`,\n );\n }\n return {\n name: toolName(entry.pluginId, decl.path),\n description: decl.describe,\n inputSchema: generateCommandSchema(toCommandManifest(decl, entry)),\n pluginId: entry.pluginId,\n pluginRoot: entry.pluginRoot,\n handlerPath: decl.handler,\n version: entry.manifest.version ?? '0.0.0',\n operationType: decl.operationType,\n permissions: getHandlerPermissions(entry.manifest, 'cli', decl.path),\n };\n}\n\n/**\n * Project a registry snapshot down to the MCP tools the identity may use.\n * Pure and cheap — safe to call per request. Authorization is delegated entirely\n * to the supplied Permits predicate (PDP seam).\n *\n * A malformed command declaration must never fail the whole tools/list call —\n * it's skipped here. validateManifests() is the place that surfaces it as a\n * diagnostic (logged + queryable), so this stays silent on purpose.\n */\nexport function filterTools(\n snapshot: Pick<RegistrySnapshot, 'manifests'>,\n permits: Permits,\n): McpTool[] {\n const tools: McpTool[] = [];\n for (const entry of snapshot.manifests) {\n for (const decl of entry.manifest.cli?.commands ?? []) {\n if (!permits(decl.operationType, entry.pluginId)) {\n continue;\n }\n try {\n tools.push(buildTool(entry, decl));\n } catch {\n // Recorded by validateManifests() at startup — skip silently here.\n }\n }\n }\n return tools;\n}\n\n/**\n * Structural validation of every declared command in the snapshot, independent\n * of any identity's permissions. Run ONCE at startup so broken manifests show\n * up in logs and via /observability/diagnostics before any caller ever hits\n * them — permit-gated filterTools() would otherwise hide them until someone\n * with access to that plugin makes a request.\n */\nexport function validateManifests(\n snapshot: Pick<RegistrySnapshot, 'manifests'>,\n): ToolBuildDiagnostic[] {\n const diagnostics: ToolBuildDiagnostic[] = [];\n for (const entry of snapshot.manifests) {\n for (const decl of entry.manifest.cli?.commands ?? []) {\n try {\n buildTool(entry, decl);\n } catch (error) {\n diagnostics.push({\n pluginId: entry.pluginId,\n commandId: (decl as { id?: string }).id ?? decl.path ?? '(unknown)',\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n return diagnostics;\n}\n","/**\n * Tool router — executes a resolved McpTool by routing through the same V3\n * command pipeline the CLI uses (executeCommandV3). Plugin output is captured\n * via the platform's uiProvider mechanism:\n *\n * bootstrap.ts wires an AsyncLocalStorage-backed uiProvider to the execution\n * backend. callTool() activates the per-call context via callOutput.run();\n * the backend calls uiProvider() → createBufferedUI(push) where push appends\n * to the call-local buffer. Concurrent calls are fully isolated.\n *\n * Multi-tenancy seam: callTool never touches a global platform directly. It\n * resolves the PlatformContainer through `resolvePlatform(tenantId)`. Today that\n * returns the single global container; when the platform gains per-tenant\n * isolation, only the resolver changes — this module stays untouched.\n */\n\nimport path from 'node:path';\nimport { executeCommandV3 } from '@kb-labs/cli-runtime';\nimport { noopUI } from '@kb-labs/plugin-contracts';\nimport type { PlatformContainer } from '@kb-labs/core-runtime';\nimport type { PlatformServices } from '@kb-labs/plugin-contracts';\nimport { callOutput } from './output-capture.js';\nimport type { McpTool } from './tool-builder.js';\n\nexport interface ToolCallResult {\n success: boolean;\n output: string;\n exitCode: number;\n}\n\n/** Tenant → platform container. Default returns the global container; platform overrides for isolation. */\nexport type PlatformResolver = (tenantId: string) => PlatformContainer;\n\n/**\n * Resolve a manifest handler reference (e.g. \"dist/commands/x.js\" or\n * \"commands/x.js#handler\") to an absolute path under the plugin's dist/.\n * Mirrors the CLI plugin-executor so MCP and CLI execution stay identical.\n */\nfunction resolveHandlerPath(pluginRoot: string, handler: string): string {\n const relative = handler.split('#')[0] ?? handler;\n return relative.startsWith('dist/')\n ? path.resolve(pluginRoot, relative)\n : path.resolve(pluginRoot, 'dist', relative);\n}\n\n/** Project a PlatformContainer onto the PlatformServices surface executeCommandV3 consumes. */\nfunction createPlatformServices(container: PlatformContainer): PlatformServices {\n return {\n logger: container.logger,\n llm: container.llm,\n embeddings: container.embeddings,\n vectorStore: container.vectorStore,\n cache: container.cache,\n config: container.config,\n storage: container.storage,\n analytics: container.analytics,\n eventBus: container.eventBus,\n invoke: container.invoke,\n documentDatabase: container.documentDatabase,\n kvStore: container.kvStore,\n logs: container.logs,\n };\n}\n\n/**\n * Execute an MCP tool. tenantId is propagated end-to-end (no loss); the platform\n * container is resolved through the seam so isolation is the platform's concern.\n *\n * Output capture: activates the AsyncLocalStorage context so the execution\n * backend's uiProvider can write into the call-local `lines` buffer. The `ui`\n * param passed to executeCommandV3 is unused by V3 (the backend uses uiProvider),\n * but noopUI is passed explicitly to make the intent clear.\n */\nexport async function callTool(\n tool: McpTool,\n args: Record<string, unknown>,\n tenantId: string,\n resolvePlatform: PlatformResolver,\n): Promise<ToolCallResult> {\n const lines: string[] = [];\n const container = resolvePlatform(tenantId);\n\n const exitCode = await callOutput.run(lines, () =>\n executeCommandV3({\n pluginId: tool.pluginId,\n pluginVersion: tool.version,\n pluginRoot: tool.pluginRoot,\n handlerPath: resolveHandlerPath(tool.pluginRoot, tool.handlerPath),\n argv: [],\n flags: args,\n tenantId,\n // ui is ignored by executeCommandV3 V3 (backend uses uiProvider).\n // noopUI is passed explicitly to document this intent.\n ui: noopUI,\n platform: createPlatformServices(container),\n platformContainer: container,\n socketPath: container.getSocketPath(),\n permissions: tool.permissions,\n quotas: tool.permissions?.quotas,\n }),\n );\n\n return { success: exitCode === 0, output: lines.join('\\n'), exitCode };\n}\n","/**\n * Request handler logic for the MCP endpoint, extracted from the Fastify/MCP-SDK\n * shell so every authorization and caching branch is unit-testable without\n * spinning up an HTTP server or a transport.\n *\n * server.ts wires these pure(ish) functions to the MCP SDK request handlers;\n * the SDK/transport plumbing itself is exercised by the e2e suite.\n */\n\nimport { createHash } from 'node:crypto';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ICache, IAnalytics } from '@kb-labs/core-platform';\nimport type { IEntityRegistry } from '@kb-labs/core-registry';\nimport { filterTools, type McpTool } from './tool-builder.js';\nimport { callTool, type PlatformResolver } from './tool-router.js';\nimport type { Permits } from './authz.js';\nimport type { McpObservabilityCollector } from '../observability/collector.js';\n\n/** How long a per-identity tool listing stays cached. */\nexport const TOOLS_CACHE_TTL_MS = 60_000;\n\n/** Build a text-only MCP tool result (the only content shape this daemon emits). */\nfunction textResult(text: string, isError: boolean): CallToolResult {\n return { content: [{ type: 'text', text }], isError };\n}\n\n/**\n * Cache key for an identity's visible tool list. Authenticated identities are\n * keyed by a hash of their Authorization header (per-token, per-tenant\n * isolation); everything else shares the single anonymous bucket.\n */\nexport function toolsCacheKey(authHeader: string | null | undefined): string {\n if (!authHeader) {\n return 'mcp:tools:anonymous';\n }\n return `mcp:tools:${createHash('sha256').update(authHeader).digest('hex').slice(0, 16)}`;\n}\n\nexport interface ResolveVisibleToolsArgs {\n /** Identity-bound authorization predicate, or null for anonymous callers. */\n permits: Permits | null;\n /** Raw Authorization header — only used to derive the per-token cache key. */\n authHeader: string | null | undefined;\n registry: IEntityRegistry;\n cache: ICache;\n /** Platform analytics — emits mcp.tools.list event. Optional for tests. */\n analytics?: IAnalytics | null;\n /** Observability collector — records mcp.tools.list operation. Optional for tests. */\n collector?: McpObservabilityCollector;\n /** Tenant ID for analytics context. */\n tenantId?: string;\n}\n\n/**\n * Resolve the tools an identity may see. Cached per identity for 60s; the cache\n * is a LISTING optimization only — it is never the authority for execution\n * (executeToolCall re-checks the live policy). Anonymous callers (permits=null)\n * always get an empty list and never touch the registry.\n */\nexport async function resolveVisibleTools(args: ResolveVisibleToolsArgs): Promise<McpTool[]> {\n const { permits, authHeader, registry, cache, analytics, collector, tenantId = 'anonymous' } =\n args;\n const t0 = Date.now();\n\n // Anonymous identities share one bucket regardless of any (invalid) header.\n const cacheKey = toolsCacheKey(permits ? authHeader : null);\n\n const cached = await cache.get<McpTool[]>(cacheKey).catch(() => null);\n if (cached) {\n const durationMs = Date.now() - t0;\n collector?.recordOp('mcp.tools.list', durationMs, true);\n analytics?.track('mcp.tools.list', {\n tenantId,\n toolCount: cached.length,\n cached: true,\n durationMs,\n }).catch(() => {});\n return cached;\n }\n\n const tools = permits ? filterTools(registry.snapshot(), permits) : [];\n await cache.set(cacheKey, tools, TOOLS_CACHE_TTL_MS).catch(() => {});\n\n const durationMs = Date.now() - t0;\n collector?.recordOp('mcp.tools.list', durationMs, true);\n analytics?.track('mcp.tools.list', {\n tenantId,\n toolCount: tools.length,\n cached: false,\n durationMs,\n }).catch(() => {});\n\n return tools;\n}\n\nexport interface ExecuteToolCallArgs {\n name: string;\n args: Record<string, unknown>;\n visibleTools: McpTool[];\n /** Identity-bound predicate, or null for anonymous. */\n permits: Permits | null;\n tenantId: string;\n resolvePlatform: PlatformResolver;\n /** Platform analytics — emits mcp.tool.call events. Optional for tests. */\n analytics?: IAnalytics | null;\n /** Observability collector — records mcp.tool.call operation. Optional for tests. */\n collector?: McpObservabilityCollector;\n}\n\n/**\n * Execute a tool call. Two independent gates protect execution:\n * 1. the tool must be in the caller's visible set, and\n * 2. the LIVE policy must still permit it (re-checked here, not trusted from\n * the possibly-stale cached listing).\n * Only then is the command run via executeCommandV3.\n */\nexport async function executeToolCall(args: ExecuteToolCallArgs): Promise<CallToolResult> {\n const { name, visibleTools, permits, tenantId, resolvePlatform, analytics, collector } = args;\n const t0 = Date.now();\n\n const tool = visibleTools.find((t) => t.name === name);\n if (!tool) {\n return textResult(`Unknown tool: ${name}`, true);\n }\n\n // Authoritative gate — independent of the cached visibility list. When the\n // platform supplies a real policy, a tool that became forbidden after it was\n // cached is rejected here with no server code change.\n if (!permits || !permits(tool.operationType, tool.pluginId)) {\n return textResult(`Not authorized: ${name}`, true);\n }\n\n analytics?.track('mcp.tool.call.started', {\n toolName: name,\n tenantId,\n pluginId: tool.pluginId,\n }).catch(() => {});\n\n const result = await callTool(tool, args.args, tenantId, resolvePlatform);\n\n const durationMs = Date.now() - t0;\n collector?.recordOp('mcp.tool.call', durationMs, result.success);\n analytics?.track('mcp.tool.call.completed', {\n toolName: name,\n tenantId,\n pluginId: tool.pluginId,\n success: result.success,\n exitCode: result.exitCode,\n outputLength: result.output.length,\n durationMs,\n }).catch(() => {});\n\n return textResult(result.output, !result.success);\n}\n","/**\n * MCP Daemon observability collector.\n *\n * Mirrors the GatewayObservabilityCollector pattern: registers Fastify\n * onRequest/onResponse hooks for HTTP-level metrics, tracks domain operations\n * (mcp.tools.list, mcp.tool.call) via OperationMetricsTracker, and builds\n * the three standard observability payloads:\n *\n * /health → buildHealth() (also used for /observability/health)\n * /observability/describe → buildDescribe()\n * /metrics → renderPrometheusMetrics()\n *\n * All payloads are validated against the platform observability contract via\n * createServiceObservabilityDescribe / createServiceObservabilityHealth.\n */\n\nimport { performance } from 'node:perf_hooks';\nimport type { FastifyInstance } from 'fastify';\nimport {\n OperationMetricsTracker,\n createServiceObservabilityDescribe,\n createServiceObservabilityHealth,\n resolveObservabilityInstanceId,\n} from '@kb-labs/shared-http';\nimport type { ObservabilityCapability, CanonicalObservabilityMetric } from '@kb-labs/core-contracts';\nimport type { ToolBuildDiagnostic } from '../mcp/tool-builder.js';\n\n/** Domain operations tracked at the MCP level. */\nexport type McpOperation = 'mcp.tools.list' | 'mcp.tool.call';\n\nexport class McpObservabilityCollector {\n private readonly instanceId = resolveObservabilityInstanceId();\n private readonly startedAt = new Date().toISOString();\n private activeRequests = 0;\n private requestsTotal = 0;\n private errorsTotal = 0;\n private readonly ops = new OperationMetricsTracker();\n private manifestDiagnostics: ToolBuildDiagnostic[] = [];\n\n /** Record the manifest diagnostics found by validateManifests() at startup. */\n setManifestDiagnostics(diagnostics: ToolBuildDiagnostic[]): void {\n this.manifestDiagnostics = diagnostics;\n }\n\n getManifestDiagnostics(): ToolBuildDiagnostic[] {\n return this.manifestDiagnostics;\n }\n\n /**\n * Register Fastify hooks that track HTTP-level request counts and duration.\n * Must be called before routes are registered so the hooks apply to all routes.\n */\n register(server: FastifyInstance): void {\n server.addHook('onRequest', (req, _reply, done) => {\n req.kbMetricsStart = performance.now();\n this.activeRequests++;\n done();\n });\n\n server.addHook('onResponse', (req, reply, done) => {\n const start = req.kbMetricsStart;\n const durationMs = start != null ? performance.now() - start : 0;\n this.activeRequests = Math.max(0, this.activeRequests - 1);\n this.requestsTotal++;\n if (reply.statusCode >= 400) { this.errorsTotal++; }\n // Track HTTP ops in operation tracker for /metrics output.\n const route = (req.routeOptions?.url ?? req.url).replace(/[?#].*$/, '');\n this.ops.recordOperation(`http.${req.method} ${route}`, durationMs,\n reply.statusCode >= 400 ? 'error' : 'ok');\n done();\n });\n }\n\n /**\n * Record a completed domain operation. Called from request-handler after\n * each tools/list and tools/call cycle.\n */\n recordOp(name: McpOperation, durationMs: number, ok: boolean): void {\n this.ops.recordOperation(name, durationMs, ok ? 'ok' : 'error');\n }\n\n // ── Observability payload builders ──────────────────────────────────────\n\n buildDescribe(registryReady: boolean, toolCount: number) {\n return createServiceObservabilityDescribe({\n schema: 'kb.observability/1' as const,\n contractVersion: '1.0' as const,\n serviceId: 'mcp-daemon',\n instanceId: this.instanceId,\n serviceType: 'mcp-server',\n version: process.env.npm_package_version ?? '0.0.0',\n environment: process.env.NODE_ENV ?? 'development',\n startedAt: this.startedAt,\n logsSource: 'mcp-daemon',\n dependencies: [],\n metricsEndpoint: '/metrics',\n healthEndpoint: '/observability/health',\n capabilities: ['httpMetrics', 'operationMetrics', 'logCorrelation'] as ObservabilityCapability[],\n metricFamilies: [\n 'process_rss_bytes',\n 'process_heap_used_bytes',\n 'service_active_operations',\n 'http_requests_total',\n 'http_errors_total',\n 'service_operation_total',\n 'service_operation_duration_ms',\n ] as CanonicalObservabilityMetric[],\n meta: { toolCount, registryReady },\n });\n }\n\n buildHealth(registryReady: boolean, toolCount: number, executionMode: string) {\n const mem = process.memoryUsage();\n return createServiceObservabilityHealth({\n schema: 'kb.observability/1' as const,\n contractVersion: '1.0' as const,\n serviceId: 'mcp-daemon',\n instanceId: this.instanceId,\n observedAt: new Date().toISOString(),\n status: registryReady ? ('healthy' as const) : ('degraded' as const),\n uptimeSec: Math.floor(process.uptime()),\n logsSource: 'mcp-daemon',\n metricsEndpoint: '/metrics',\n capabilities: ['httpMetrics', 'operationMetrics', 'logCorrelation'] as ObservabilityCapability[],\n snapshot: {\n rssBytes: mem.rss,\n heapUsedBytes: mem.heapUsed,\n activeOperations: this.activeRequests,\n },\n checks: [\n {\n id: 'registry',\n status: (registryReady ? 'ok' : 'warn') as 'ok' | 'warn' | 'error',\n message: registryReady ? `${toolCount} tools loaded` : 'Registry not yet ready',\n },\n {\n id: 'execution',\n status: 'ok' as const,\n message: `mode=${executionMode}`,\n },\n {\n id: 'manifests',\n status: (this.manifestDiagnostics.length === 0 ? 'ok' : 'warn') as 'ok' | 'warn' | 'error',\n message:\n this.manifestDiagnostics.length === 0\n ? 'all commands loaded cleanly'\n : `${this.manifestDiagnostics.length} command(s) skipped — see /observability/diagnostics`,\n },\n ],\n topOperations: this.ops.getTopOperations(5),\n });\n }\n\n renderPrometheusMetrics(toolCount: number): string {\n const mem = process.memoryUsage();\n const lines: string[] = [\n '# HELP process_rss_bytes RSS memory in bytes',\n `process_rss_bytes ${mem.rss}`,\n '# HELP process_heap_used_bytes Heap used in bytes',\n `process_heap_used_bytes ${mem.heapUsed}`,\n '# HELP process_uptime_seconds Process uptime in seconds',\n `process_uptime_seconds ${Math.floor(process.uptime())}`,\n '# HELP mcp_tools_total Number of tools registered in the current snapshot',\n `mcp_tools_total ${toolCount}`,\n '# HELP http_requests_total Total MCP HTTP requests received',\n `http_requests_total ${this.requestsTotal}`,\n '# HELP http_errors_total Total MCP HTTP 4xx/5xx responses',\n `http_errors_total ${this.errorsTotal}`,\n '# HELP service_active_operations Currently active MCP requests',\n `service_active_operations ${this.activeRequests}`,\n ...this.ops.getMetricLines(),\n ];\n return lines.join('\\n');\n }\n}\n","/**\n * MCP Daemon HTTP server.\n *\n * Exposes a single JSON-RPC endpoint (`/api/v1/mcp`) speaking the Model Context\n * Protocol over Streamable HTTP, plus the standard platform observability endpoints:\n *\n * GET /health → McpObservabilityCollector.buildHealth()\n * GET /ready → 200/503 based on registry readiness\n * GET /metrics → Prometheus text format\n * GET /observability/describe → service identity + capabilities\n * GET /observability/health → full snapshot with checks and top operations\n *\n * Design notes:\n * - The entity registry is initialized ONCE at start() and reused for every\n * request; only the cheap, pure filterTools() runs per request.\n * - This endpoint sits in front of the gateway's auth scope (the gateway proxies\n * it as a dumb upstream), so the daemon validates the Bearer token itself via\n * the shared GATEWAY_JWT_SECRET — exactly mirroring the gateway's AuthService.\n * - Anonymous callers (no/invalid token) get an empty tool list and can never\n * reach callTool/executeCommandV3.\n * - tenantId flows end-to-end from AuthContext.namespaceId into executeCommandV3\n * via the resolvePlatform seam — ready for per-tenant isolation without code\n * changes here.\n */\n\nimport type { FastifyInstance } from 'fastify';\nimport { Server as McpServer } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { can, type Policy, type Identity } from '@kb-labs/core-policy';\nimport type { ICache, ILogger } from '@kb-labs/core-platform';\nimport type { JwtConfig } from '@kb-labs/gateway-auth';\nimport type { PlatformContainer } from '@kb-labs/core-runtime';\nimport type { IEntityRegistry } from '@kb-labs/core-registry';\nimport { createDaemonServer, getListenOptions, type ObservabilityCollectorLike } from '@kb-labs/shared-http';\nimport { resolveAuthContext } from './mcp/auth.js';\nimport { toIdentity, actionForOperation, type Permits } from './mcp/authz.js';\nimport { createToolRegistry, validateManifests } from './mcp/tool-builder.js';\nimport { type PlatformResolver } from './mcp/tool-router.js';\nimport { resolveVisibleTools, executeToolCall } from './mcp/request-handler.js';\nimport { McpObservabilityCollector } from './observability/collector.js';\nimport type { ToolBuildDiagnostic } from './mcp/tool-builder.js';\n\n/** Built-in diagnostic tool: always visible to authenticated callers, never\n * derived from a plugin manifest — reports which plugin commands failed to\n * load as MCP tools so a caller can self-diagnose without SSHing into the box. */\nconst DIAGNOSTICS_TOOL = {\n name: 'kb-labs__mcp_diagnostics',\n description:\n 'List plugin commands that failed to load as MCP tools (malformed manifests), with the reason for each.',\n inputSchema: { type: 'object' as const, properties: {} },\n};\n\nfunction renderManifestDiagnostics(diagnostics: ToolBuildDiagnostic[]): string {\n if (diagnostics.length === 0) {\n return 'All plugin commands loaded cleanly — no manifest issues.';\n }\n return diagnostics.map((d) => `[${d.pluginId}] ${d.commandId}: ${d.error}`).join('\\n');\n}\n\nexport interface McpDaemonServerOptions {\n port: number;\n host: string;\n logger: ILogger;\n cache: ICache;\n /** Default global platform container — used as the resolvePlatform fallback. */\n platform: PlatformContainer;\n /** Tenant → platform container seam. Defaults to always returning `platform`. */\n resolvePlatform?: PlatformResolver;\n /** Workspace root used to initialize the entity registry. */\n projectRoot: string;\n /** Platform installation root (installed mode); merges platform-level plugins. */\n platformRoot?: string;\n jwtConfig: JwtConfig;\n /** Authorization policy. Permit-all default until the platform supplies a real one. */\n policy: Policy;\n}\n\nexport class McpDaemonServer {\n private readonly opts: McpDaemonServerOptions;\n private readonly resolvePlatform: PlatformResolver;\n private readonly collector: McpObservabilityCollector;\n private app: FastifyInstance | undefined;\n private registry: IEntityRegistry | undefined;\n\n constructor(opts: McpDaemonServerOptions) {\n this.opts = opts;\n this.resolvePlatform = opts.resolvePlatform ?? (() => opts.platform);\n this.collector = new McpObservabilityCollector();\n }\n\n /** Build a per-request permits predicate bound to the identity (PDP seam). */\n private permitsFor(identity: Identity): Permits {\n return (operationType, resource) =>\n can(this.opts.policy, identity, actionForOperation(operationType), resource);\n }\n\n private get toolCount(): number {\n return (\n this.registry\n ?.snapshot()\n .manifests.flatMap((m) => m.manifest.cli?.commands ?? []).length ?? 0\n );\n }\n\n async start(): Promise<string> {\n // Initialize the registry ONCE; snapshot() is reused per request.\n this.registry = await createToolRegistry({\n root: this.opts.projectRoot,\n platformRoot: this.opts.platformRoot,\n cache: this.opts.cache,\n });\n\n // Structural manifest validation runs ONCE here, independent of any\n // identity's permissions — so broken manifests are visible in logs and\n // via /observability/diagnostics from boot, not only once someone with\n // access to the offending plugin happens to call tools/list.\n const manifestDiagnostics = validateManifests(this.registry.snapshot());\n this.collector.setManifestDiagnostics(manifestDiagnostics);\n for (const diag of manifestDiagnostics) {\n this.opts.logger.warn('MCP tool skipped — invalid manifest command', {\n pluginId: diag.pluginId,\n commandId: diag.commandId,\n error: diag.error,\n });\n }\n\n const execMode = process.env.KB_MCP_EXECUTION_MODE ?? 'subprocess';\n\n // Adapter: wraps McpObservabilityCollector to match ObservabilityCollectorLike.\n // Arrow functions capture `this` so the live registry/toolCount state is always current.\n const observabilityAdapter: ObservabilityCollectorLike = {\n register: (server: FastifyInstance) => this.collector.register(server),\n buildDescribe: () => this.collector.buildDescribe(!!this.registry, this.toolCount),\n buildHealth: () => this.collector.buildHealth(!!this.registry, this.toolCount, execMode),\n renderPrometheusMetrics: (_status: string) => this.collector.renderPrometheusMetrics(this.toolCount),\n };\n\n this.app = await createDaemonServer({\n serviceId: 'mcp-daemon',\n logger: this.opts.logger,\n observability: observabilityAdapter,\n readyCheck: () => ({ ready: !!this.registry, service: 'mcp-daemon' }),\n registerRoutes: async (server) => this.registerMcpRoutes(server),\n });\n\n const listenOptions = getListenOptions(this.opts.port, this.opts.host);\n const address = await this.app.listen(listenOptions);\n\n this.opts.logger.info('MCP daemon listening', { address });\n return address;\n }\n\n async stop(): Promise<void> {\n await this.app?.close();\n }\n\n private async registerMcpRoutes(server: FastifyInstance): Promise<void> {\n const { cache, logger, jwtConfig } = this.opts;\n\n // ── Diagnostics ──────────────────────────────────────────────────────\n // Same visibility as /health — no per-tenant data, just which manifest\n // commands failed to load. Mirrors the kb-labs__mcp_diagnostics MCP tool.\n server.get('/observability/diagnostics', async () => ({\n diagnostics: this.collector.getManifestDiagnostics(),\n }));\n\n // ── MCP JSON-RPC endpoint ──────────────────────────────────────────────\n\n // CORS headers for all MCP responses (including preflight OPTIONS).\n // fastify.all() covers every method including OPTIONS, so no separate\n // fastify.options() is needed — that would cause a duplicate-route error.\n server.all('/api/v1/mcp', async (request, reply) => {\n reply\n .header('Access-Control-Allow-Origin', '*')\n .header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')\n .header('Access-Control-Allow-Headers', 'Authorization, Content-Type, Mcp-Session-Id');\n\n // Short-circuit preflight immediately — no auth or MCP processing needed.\n if (request.method === 'OPTIONS') {\n return reply.code(204).send();\n }\n\n const reqLogger = request.kbLogger ?? logger;\n\n // 1. Authenticate. Invalid/absent token → anonymous (no throw, no 401).\n const authHeader = request.headers.authorization;\n const authCtx = await resolveAuthContext(authHeader, cache, jwtConfig).catch(\n () => null,\n );\n const tenantId = authCtx?.namespaceId ?? 'anonymous';\n\n // Bind the authorization predicate to the identity once per request.\n // Anonymous callers get no predicate → they can neither list nor call tools.\n const permits = authCtx ? this.permitsFor(toIdentity(authCtx)) : null;\n\n // 2. Resolve the visible tool list (cached per identity). The cache is a\n // listing optimization ONLY — executeToolCall re-checks the live policy.\n const visibleTools = await resolveVisibleTools({\n permits,\n authHeader,\n registry: this.registry!,\n cache,\n analytics: this.opts.platform.analytics,\n collector: this.collector,\n tenantId,\n });\n\n // 3. Build a stateless per-request MCP server.\n const mcp = new McpServer(\n { name: 'kb-labs', version: '1.0.0' },\n { capabilities: { tools: {} } },\n );\n\n mcp.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n ...visibleTools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema as { type: 'object' },\n })),\n // Authenticated callers only — mirrors the visibility gate above.\n ...(permits ? [DIAGNOSTICS_TOOL] : []),\n ],\n }));\n\n mcp.setRequestHandler(CallToolRequestSchema, async ({ params }) => {\n if (params.name === DIAGNOSTICS_TOOL.name) {\n if (!permits) {\n return { content: [{ type: 'text' as const, text: `Not authorized: ${params.name}` }], isError: true };\n }\n return { content: [{ type: 'text' as const, text: renderManifestDiagnostics(this.collector.getManifestDiagnostics()) }], isError: false };\n }\n return executeToolCall({\n name: params.name,\n args: (params.arguments ?? {}) as Record<string, unknown>,\n visibleTools,\n permits,\n tenantId,\n resolvePlatform: this.resolvePlatform,\n analytics: this.opts.platform.analytics,\n collector: this.collector,\n });\n });\n\n // 4. Streamable HTTP transport (stateless). Pass Fastify's parsed body —\n // the raw stream is already consumed, so the SDK must not re-read it.\n const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });\n try {\n await mcp.connect(transport);\n await transport.handleRequest(request.raw, reply.raw, request.body);\n } catch (error) {\n reqLogger.error('MCP request handling failed', error as Error);\n if (!reply.raw.headersSent) {\n reply.code(500).send({ error: 'internal_error' });\n }\n } finally {\n // Closing may reject if the transport is already torn down — swallow it\n // so it can never surface as an unhandled rejection after the response.\n await mcp.close().catch(() => {});\n }\n });\n }\n}\n","import { platform, createServiceBootstrap, getPlatformRoot, getProjectRoot } from '@kb-labs/core-runtime';\nimport { makeAssemblyHook } from '@kb-labs/plugin-runtime';\nimport { resolvePolicy } from '@kb-labs/core-policy';\nimport { createCorrelatedLogger, resolveObservabilityInstanceId } from '@kb-labs/shared-http';\nimport { noopUI } from '@kb-labs/plugin-contracts';\nimport { runDaemon } from '@kb-labs/shared-daemon';\nimport { loadJwtConfig } from './mcp/auth.js';\nimport { callOutput } from './mcp/output-capture.js';\nimport { createBufferedUI } from './mcp/ui.js';\nimport { McpDaemonServer } from './server.js';\n\nexport async function bootstrap(): Promise<void> {\n await runDaemon(\n {\n appId: 'mcp-daemon',\n defaultPort: 7779,\n portEnvVar: 'KB_MCP_DAEMON_PORT',\n defaultHost: 'localhost',\n hostEnvVar: 'KB_MCP_DAEMON_HOST',\n async setup({ port, host }) {\n const logger = createCorrelatedLogger(platform.logger, {\n serviceId: 'mcp-daemon',\n instanceId: resolveObservabilityInstanceId(),\n logsSource: 'mcp-daemon',\n layer: 'mcp',\n service: 'bootstrap',\n operation: 'mcp-daemon.bootstrap',\n });\n\n logger.info('MCP daemon platform initialised');\n\n const projectRoot = getProjectRoot() ?? process.cwd();\n const platformRoot = getPlatformRoot();\n\n const { policy } = await resolvePolicy({});\n\n const server = new McpDaemonServer({\n port,\n host,\n logger,\n cache: platform.cache,\n platform,\n resolvePlatform: () => platform,\n projectRoot,\n platformRoot,\n jwtConfig: loadJwtConfig(),\n policy,\n });\n\n await server.start();\n\n return async () => {\n await server.stop();\n };\n },\n },\n // platformBootstrap: full init with uiProvider for callOutput ALS wiring.\n // uiProvider flows into initPlatform → createExecutionBackend so the backend\n // captures plugin output from the very start. Concurrent tool calls are\n // fully isolated — each gets its own AsyncLocalStorage slot.\n async (appId, repoRoot) => {\n await createServiceBootstrap({\n appId,\n repoRoot,\n uiProvider: (_hostType: string) => {\n const lines = callOutput.getStore();\n return lines ? createBufferedUI((s) => lines.push(s)).ui : noopUI;\n },\n assemblyHook: makeAssemblyHook(),\n });\n return platform;\n },\n );\n}\n","import { bootstrap } from './bootstrap.js';\n\n// runDaemon() (called inside bootstrap) resolves repo root via findRepoRoot().\nbootstrap().catch((error) => {\n console.error('Failed to start MCP daemon:', error);\n process.exit(1);\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kb-labs/mcp-app",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.100.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -9,20 +9,20 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
11
11
|
"fastify": "^5.8.5",
|
|
12
|
-
"@kb-labs/core-contracts": "2.
|
|
13
|
-
"@kb-labs/cli-commands": "2.
|
|
14
|
-
"@kb-labs/
|
|
15
|
-
"@kb-labs/core-platform": "2.
|
|
16
|
-
"@kb-labs/core-
|
|
17
|
-
"@kb-labs/
|
|
18
|
-
"@kb-labs/plugin-
|
|
19
|
-
"@kb-labs/
|
|
20
|
-
"@kb-labs/gateway-
|
|
21
|
-
"@kb-labs/
|
|
22
|
-
"@kb-labs/
|
|
23
|
-
"@kb-labs/
|
|
24
|
-
"@kb-labs/
|
|
25
|
-
"@kb-labs/core-policy": "2.
|
|
12
|
+
"@kb-labs/core-contracts": "2.100.0",
|
|
13
|
+
"@kb-labs/cli-commands": "2.100.0",
|
|
14
|
+
"@kb-labs/cli-runtime": "2.100.0",
|
|
15
|
+
"@kb-labs/core-platform": "2.100.0",
|
|
16
|
+
"@kb-labs/core-registry": "2.100.0",
|
|
17
|
+
"@kb-labs/core-runtime": "2.100.0",
|
|
18
|
+
"@kb-labs/plugin-runtime": "2.100.0",
|
|
19
|
+
"@kb-labs/plugin-contracts": "2.100.0",
|
|
20
|
+
"@kb-labs/gateway-contracts": "2.100.0",
|
|
21
|
+
"@kb-labs/gateway-auth": "2.100.0",
|
|
22
|
+
"@kb-labs/shared-daemon": "2.100.0",
|
|
23
|
+
"@kb-labs/core-sys": "2.100.0",
|
|
24
|
+
"@kb-labs/shared-http": "2.100.0",
|
|
25
|
+
"@kb-labs/core-policy": "2.100.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"eslint": "^9",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"tsx": "^4.20.5",
|
|
32
32
|
"typescript": "^5.6.3",
|
|
33
33
|
"vitest": "^3.2.6",
|
|
34
|
-
"@kb-labs/
|
|
35
|
-
"@kb-labs/
|
|
34
|
+
"@kb-labs/devkit": "2.100.0",
|
|
35
|
+
"@kb-labs/shared-testing-e2e": "2.100.0"
|
|
36
36
|
},
|
|
37
37
|
"kb": {
|
|
38
38
|
"manifest": "./dist/manifest.js"
|