@skastr0/prism-sdk 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +12 -0
- package/dist/compile-manifest.d.ts +293 -0
- package/dist/compile-manifest.js +232 -0
- package/dist/mcp/daemon-resolver.d.ts +100 -0
- package/dist/mcp/daemon-resolver.js +185 -0
- package/dist/mcp/shim.d.ts +155 -0
- package/dist/mcp/shim.js +434 -0
- package/dist/mcp/uds-path.d.ts +26 -0
- package/dist/mcp/uds-path.js +70 -0
- package/dist/mcp/uds-registry.d.ts +109 -0
- package/dist/mcp/uds-registry.js +270 -0
- package/dist/mcp/uds-singleton.d.ts +124 -0
- package/dist/mcp/uds-singleton.js +360 -0
- package/dist/refs.d.ts +15 -0
- package/dist/refs.js +26 -0
- package/dist/snapshot.d.ts +92 -0
- package/dist/snapshot.js +74 -0
- package/dist/stable-json.d.ts +8 -0
- package/dist/stable-json.js +27 -0
- package/package.json +73 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve-or-spawn: given a plugin name, produce a *live* daemon registry
|
|
3
|
+
* entry to connect to -- spawning a fresh daemon when the registry has no
|
|
4
|
+
* entry, the recorded entry is dead, or the recorded entry's bundle hash no
|
|
5
|
+
* longer matches the compiled bundle on disk (a `prism refresh` ran since
|
|
6
|
+
* that daemon started).
|
|
7
|
+
*
|
|
8
|
+
* Builds entirely on the wave-0 substrate rather than re-implementing any of
|
|
9
|
+
* it:
|
|
10
|
+
* - `getDaemon` / the per-plugin registry file (`uds-registry.ts`).
|
|
11
|
+
* - `udsPathFor`, the content-addressed socket path (`uds-path.ts`) --
|
|
12
|
+
* a different bundle hash always yields a different socket path, so a
|
|
13
|
+
* stale daemon (old hash) and a fresh one (new hash) never collide on the
|
|
14
|
+
* same file.
|
|
15
|
+
* - `probeSocketLiveness` (`uds-singleton.ts`).
|
|
16
|
+
*
|
|
17
|
+
* This module deliberately never binds a socket or acquires the bind lock
|
|
18
|
+
* itself. Every compiled bundle's own runtime already calls
|
|
19
|
+
* `bindUnixSocketSingleton` on startup (see `src/compile/mcp-bundle.ts`'s
|
|
20
|
+
* `MCP_SDK_HTTP_RUNTIME`), and *that* is what guarantees exactly one winner
|
|
21
|
+
* when N callers race to spawn the same plugin: this module just spawns
|
|
22
|
+
* (possibly redundantly) and waits for a live registry entry to show up.
|
|
23
|
+
* Losing spawns detect "already-served" inside their own bundle and
|
|
24
|
+
* `process.exit(0)` before ever registering.
|
|
25
|
+
*/
|
|
26
|
+
import { spawn } from "node:child_process";
|
|
27
|
+
import { createHash } from "node:crypto";
|
|
28
|
+
import { readFile } from "node:fs/promises";
|
|
29
|
+
import { dirname, join } from "node:path";
|
|
30
|
+
import { udsPathFor as udsPathForDefault } from "./uds-path.js";
|
|
31
|
+
import { getDaemon as getDaemonDefault } from "./uds-registry.js";
|
|
32
|
+
import { probeSocketLiveness as probeSocketLivenessDefault } from "./uds-singleton.js";
|
|
33
|
+
export class DaemonResolveError extends Error {
|
|
34
|
+
pluginName;
|
|
35
|
+
cause;
|
|
36
|
+
kind = "daemon-resolve-error";
|
|
37
|
+
constructor(pluginName, message, cause) {
|
|
38
|
+
super(`[${pluginName}] ${message}`);
|
|
39
|
+
this.pluginName = pluginName;
|
|
40
|
+
this.cause = cause;
|
|
41
|
+
this.name = "DaemonResolveError";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const errorMessage = (error) => (error instanceof Error ? error.message : String(error));
|
|
45
|
+
const delay = (ms) => new Promise((resolveDelay) => setTimeout(resolveDelay, ms));
|
|
46
|
+
export const DEFAULT_SPAWN_TIMEOUT_MS = 15_000;
|
|
47
|
+
const DEFAULT_POLL_INTERVAL_MS = 50;
|
|
48
|
+
/**
|
|
49
|
+
* `<prismHome>/runtime/mcp/<plugin>` -- the per-plugin runtime directory
|
|
50
|
+
* that owns this plugin's registry file, socket file(s), and compiled
|
|
51
|
+
* bundle. Derived from `udsPathFor` (any hash value yields the same parent
|
|
52
|
+
* directory) rather than re-deriving the layout independently.
|
|
53
|
+
*
|
|
54
|
+
* `prismHome` is threaded explicitly (never read from the environment
|
|
55
|
+
* here): the CLI edge resolves `PRISM_HOME` once via `resolvePrismHome()`
|
|
56
|
+
* and passes the result down. An omitted value falls back to the same
|
|
57
|
+
* `~/.prism` default `resolvePrismHome()` uses when unset -- `prism-sdk`
|
|
58
|
+
* cannot import that resolver itself (no dependency on the root `src/`
|
|
59
|
+
* tree).
|
|
60
|
+
*/
|
|
61
|
+
export const pluginRuntimeDir = (plugin, prismHome) => dirname(udsPathForDefault(plugin, "", prismHome));
|
|
62
|
+
/**
|
|
63
|
+
* `<prismHome>/runtime/mcp/<plugin>/server.mjs` -- the canonical compiled
|
|
64
|
+
* bundle a `prism refresh` run produces. This module only ever reads it; it
|
|
65
|
+
* never writes or rebuilds it.
|
|
66
|
+
*/
|
|
67
|
+
export const pluginBundlePath = (plugin, prismHome) => join(pluginRuntimeDir(plugin, prismHome), "server.mjs");
|
|
68
|
+
const sha256Hex = (content) => createHash("sha256").update(content).digest("hex");
|
|
69
|
+
const defaultHashBundle = async (bundlePath) => sha256Hex(await readFile(bundlePath));
|
|
70
|
+
/**
|
|
71
|
+
* Spawns `bun <bundle>` detached (so it outlives this process) with the UDS
|
|
72
|
+
* + registry identity env the bundle's own runtime reads at startup (see
|
|
73
|
+
* `PRISM_MCP_UDS_PATH` / `PRISM_MCP_REGISTRY_PLUGIN_NAME` /
|
|
74
|
+
* `PRISM_MCP_REGISTRY_BUNDLE_HASH` in `MCP_SDK_HTTP_RUNTIME`). Never waits
|
|
75
|
+
* on the child and never lets a spawn-level error (e.g. `bun` missing from
|
|
76
|
+
* PATH) throw unhandled -- resolution simply times out and reports a typed
|
|
77
|
+
* `DaemonResolveError` instead.
|
|
78
|
+
*/
|
|
79
|
+
const defaultSpawnDaemon = ({ plugin, bundlePath, udsPath, bundleHash }) => {
|
|
80
|
+
const child = spawn("bun", [bundlePath], {
|
|
81
|
+
cwd: dirname(bundlePath),
|
|
82
|
+
env: {
|
|
83
|
+
...process.env,
|
|
84
|
+
PRISM_MCP_UDS_PATH: udsPath,
|
|
85
|
+
PRISM_MCP_REGISTRY_PLUGIN_NAME: plugin,
|
|
86
|
+
PRISM_MCP_REGISTRY_BUNDLE_HASH: bundleHash,
|
|
87
|
+
},
|
|
88
|
+
detached: true,
|
|
89
|
+
stdio: "ignore",
|
|
90
|
+
});
|
|
91
|
+
child.on("error", () => undefined);
|
|
92
|
+
child.unref();
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Returns `true` when the bundle on disk no longer matches
|
|
96
|
+
* `registeredHash`. Locating the bundle (`bundlePathFor`, which by default
|
|
97
|
+
* derives from `udsPathFor` and so can throw `UDSPathLengthError` for a
|
|
98
|
+
* plugin/home combination that would not fit a UDS socket path either) or
|
|
99
|
+
* reading it (deleted, or -- in a hermetic test -- never written) are both
|
|
100
|
+
* treated as "unknown, not proven stale": a live daemon is strictly better
|
|
101
|
+
* than none, so failing to independently re-derive where a *hypothetical
|
|
102
|
+
* replacement* bundle would live never forces a respawn of an
|
|
103
|
+
* otherwise-healthy, already-reachable daemon.
|
|
104
|
+
*/
|
|
105
|
+
const isBundleStale = async (options) => {
|
|
106
|
+
try {
|
|
107
|
+
const bundlePath = options.bundlePathFor(options.plugin);
|
|
108
|
+
return (await options.hashBundle(bundlePath)) !== options.registeredHash;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const waitForLiveEntry = async (options) => {
|
|
115
|
+
const { plugin, udsPath, getDaemon, probeSocketLiveness, spawnTimeoutMs, pollIntervalMs } = options;
|
|
116
|
+
const deadline = Date.now() + spawnTimeoutMs;
|
|
117
|
+
while (true) {
|
|
118
|
+
const registered = await getDaemon(plugin);
|
|
119
|
+
if (registered.kind === "ok" && registered.value.sock === udsPath) {
|
|
120
|
+
const liveness = await probeSocketLiveness(registered.value.sock);
|
|
121
|
+
if (liveness === "live")
|
|
122
|
+
return registered.value;
|
|
123
|
+
}
|
|
124
|
+
if (Date.now() >= deadline) {
|
|
125
|
+
throw new DaemonResolveError(plugin, `spawned daemon did not become live at ${udsPath} within ${spawnTimeoutMs}ms`);
|
|
126
|
+
}
|
|
127
|
+
await delay(pollIntervalMs);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Resolves the live registry entry to connect to for `plugin`:
|
|
132
|
+
*
|
|
133
|
+
* registry entry present -> liveness probe
|
|
134
|
+
* live & bundle hash matches on-disk bundle -> use it
|
|
135
|
+
* dead, OR bundle hash stale -> spawn fresh
|
|
136
|
+
* registry entry absent -> spawn fresh
|
|
137
|
+
*
|
|
138
|
+
* "Spawn fresh" computes the bundle's current content hash, derives its
|
|
139
|
+
* content-addressed socket path via `udsPathFor`, launches the daemon, and
|
|
140
|
+
* polls the registry + a liveness probe until a live entry at that exact
|
|
141
|
+
* socket path appears or `spawnTimeoutMs` elapses.
|
|
142
|
+
*
|
|
143
|
+
* Throws `DaemonResolveError` when the bundle cannot be read (nothing to
|
|
144
|
+
* spawn) or the spawned daemon never becomes live in time.
|
|
145
|
+
*/
|
|
146
|
+
export const resolveOrSpawnDaemon = async (options) => {
|
|
147
|
+
const { plugin } = options;
|
|
148
|
+
const spawnTimeoutMs = options.spawnTimeoutMs ?? DEFAULT_SPAWN_TIMEOUT_MS;
|
|
149
|
+
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
150
|
+
const getDaemon = options.getDaemon ?? getDaemonDefault;
|
|
151
|
+
const probeSocketLiveness = options.probeSocketLiveness ?? probeSocketLivenessDefault;
|
|
152
|
+
const bundlePathFor = options.bundlePathFor ?? ((plugin) => pluginBundlePath(plugin, options.prismHome));
|
|
153
|
+
const buildUdsPath = options.udsPathFor ?? ((plugin, bundleHash) => udsPathForDefault(plugin, bundleHash, options.prismHome));
|
|
154
|
+
const hashBundle = options.hashBundle ?? defaultHashBundle;
|
|
155
|
+
const spawnDaemon = options.spawnDaemon ?? defaultSpawnDaemon;
|
|
156
|
+
const registered = await getDaemon(plugin);
|
|
157
|
+
if (registered.kind === "ok") {
|
|
158
|
+
const liveness = await probeSocketLiveness(registered.value.sock);
|
|
159
|
+
if (liveness === "live") {
|
|
160
|
+
const stale = await isBundleStale({
|
|
161
|
+
plugin,
|
|
162
|
+
registeredHash: registered.value.bundleHash,
|
|
163
|
+
bundlePathFor,
|
|
164
|
+
hashBundle,
|
|
165
|
+
});
|
|
166
|
+
if (!stale)
|
|
167
|
+
return registered.value;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Reaching here means we are actually about to spawn, so -- unlike the
|
|
171
|
+
// staleness check above -- locating and reading the bundle now has to
|
|
172
|
+
// succeed; there is nothing to fall back to.
|
|
173
|
+
let bundlePath;
|
|
174
|
+
let currentHash;
|
|
175
|
+
try {
|
|
176
|
+
bundlePath = bundlePathFor(plugin);
|
|
177
|
+
currentHash = await hashBundle(bundlePath);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
throw new DaemonResolveError(plugin, `cannot spawn: unable to locate/read compiled bundle: ${errorMessage(error)}`, error);
|
|
181
|
+
}
|
|
182
|
+
const udsPath = buildUdsPath(plugin, currentHash);
|
|
183
|
+
spawnDaemon({ plugin, bundlePath, udsPath, bundleHash: currentHash });
|
|
184
|
+
return waitForLiveEntry({ plugin, udsPath, getDaemon, probeSocketLiveness, spawnTimeoutMs, pollIntervalMs });
|
|
185
|
+
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aggregating MCP shim.
|
|
3
|
+
*
|
|
4
|
+
* A single stdio MCP server, spawned once by the harness, that fronts N
|
|
5
|
+
* Prism-generated plugin daemons over Unix domain sockets. It replaces the
|
|
6
|
+
* "one spawned process per plugin" shape with "one spawned process,
|
|
7
|
+
* multiplexed over UDS to N already-running daemons":
|
|
8
|
+
*
|
|
9
|
+
* harness <--stdio(JSON-RPC)--> shim <--HTTP-over-UDS--> daemon[plugin A]
|
|
10
|
+
* \-HTTP-over-UDS--> daemon[plugin B]
|
|
11
|
+
*
|
|
12
|
+
* Harness side (this module's `runShim`/`createShimServer`): a bare
|
|
13
|
+
* JSON-RPC MCP server over stdin/stdout using the SDK's low-level `Server`
|
|
14
|
+
* + `StdioServerTransport`. Stdio is a single duplex pipe with exactly one
|
|
15
|
+
* peer, so there is no SSE and no HTTP session concept to manage here —
|
|
16
|
+
* that machinery only exists on the daemon side.
|
|
17
|
+
*
|
|
18
|
+
* Daemon side (`DaemonConnection`): a minimal hand-rolled HTTP-over-UDS
|
|
19
|
+
* JSON-RPC client, deliberately not the SDK's `Client` +
|
|
20
|
+
* `StreamableHTTPClientTransport`. The SDK client runs every response
|
|
21
|
+
* through `safeParse(resultSchema, ...)`, which is a plain (non-passthrough)
|
|
22
|
+
* Zod object and silently drops any field the schema does not declare. This
|
|
23
|
+
* shim's job is to forward a daemon's tool-call result value-preserving —
|
|
24
|
+
* stripping no field (name mapping aside) — so the daemon's raw JSON-RPC
|
|
25
|
+
* `result`/`error` is read and handed back untouched instead of being
|
|
26
|
+
* round-tripped through schema validation on the way in.
|
|
27
|
+
*
|
|
28
|
+
* A plugin absent from the UDS registry, whose recorded daemon is dead, or
|
|
29
|
+
* whose recorded bundle hash no longer matches the compiled bundle on disk,
|
|
30
|
+
* is resolved via `daemon-resolver.ts`'s `resolveOrSpawnDaemon`: it spawns a
|
|
31
|
+
* fresh daemon and waits (bounded by a spawn timeout) for it to register
|
|
32
|
+
* and answer live. If that also fails, or a live daemon is unreachable
|
|
33
|
+
* within `daemonTimeoutMs`, the failure is never fatal to the shim: the
|
|
34
|
+
* plugin's tools are omitted from the merged `tools/list`, and a
|
|
35
|
+
* `tools/call` naming it returns a typed `McpError` (SDK
|
|
36
|
+
* `ErrorCode.ConnectionClosed`). Every other configured plugin keeps
|
|
37
|
+
* serving normally — each plugin's request runs against its own timeout and
|
|
38
|
+
* failure is caught per-plugin.
|
|
39
|
+
*/
|
|
40
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
41
|
+
import { type Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
42
|
+
import { type RegistryResult, type RegistryEntry } from "./uds-registry.js";
|
|
43
|
+
/** `p_<hash8>` — see `stableHash8` above for why this exact shape. */
|
|
44
|
+
export declare const pluginWireNamespace: (pluginName: string) => string;
|
|
45
|
+
/** Harness-visible tool name: `<pluginWireNamespace>__<originalToolName>`. */
|
|
46
|
+
export declare const namespacedToolName: (pluginName: string, toolName: string) => string;
|
|
47
|
+
/**
|
|
48
|
+
* Inverse of `namespacedToolName`. The namespace segment has a fixed
|
|
49
|
+
* width, so this splits on position rather than searching for the `__`
|
|
50
|
+
* separator — a tool name is free-form and may itself legally contain
|
|
51
|
+
* `__`, but the namespace segment never does.
|
|
52
|
+
*/
|
|
53
|
+
export declare const splitNamespacedToolName: (fqName: string) => {
|
|
54
|
+
readonly namespace: string;
|
|
55
|
+
readonly toolName: string;
|
|
56
|
+
} | undefined;
|
|
57
|
+
export declare class ShimDaemonError extends Error {
|
|
58
|
+
readonly pluginName: string;
|
|
59
|
+
readonly cause?: unknown | undefined;
|
|
60
|
+
readonly kind: "shim-daemon-error";
|
|
61
|
+
constructor(pluginName: string, message: string, cause?: unknown | undefined);
|
|
62
|
+
}
|
|
63
|
+
export type GetDaemonFn = (plugin: string) => Promise<RegistryResult<RegistryEntry>>;
|
|
64
|
+
export type ResolveOrSpawnFn = (plugin: string) => Promise<RegistryEntry>;
|
|
65
|
+
export interface ShimAggregatorOptions {
|
|
66
|
+
readonly plugins: ReadonlyArray<string>;
|
|
67
|
+
/**
|
|
68
|
+
* Prism home directory, threaded from the process entrypoint (see
|
|
69
|
+
* `src/mcp/shim-main.ts`, which resolves `PRISM_HOME` once via
|
|
70
|
+
* `resolvePrismHome()`). Forwarded to the default `resolveOrSpawn` so a
|
|
71
|
+
* `PRISM_HOME` override locates the same bundle/socket path `prism
|
|
72
|
+
* refresh` wrote, instead of always falling back to `~/.prism`. Ignored
|
|
73
|
+
* when `resolveOrSpawn` is supplied directly.
|
|
74
|
+
*/
|
|
75
|
+
readonly prismHome?: string;
|
|
76
|
+
readonly daemonTimeoutMs?: number;
|
|
77
|
+
readonly spawnTimeoutMs?: number;
|
|
78
|
+
readonly getDaemon?: GetDaemonFn;
|
|
79
|
+
/**
|
|
80
|
+
* Full override of daemon resolution, bypassing `getDaemon` entirely.
|
|
81
|
+
* Tests that only want to exercise merge/dispatch/isolation (not
|
|
82
|
+
* resolve-or-spawn itself) inject a stub here instead of standing up a
|
|
83
|
+
* real compiled bundle on disk.
|
|
84
|
+
*/
|
|
85
|
+
readonly resolveOrSpawn?: ResolveOrSpawnFn;
|
|
86
|
+
/** Optional set of tool names to enable; if present, only these tools are exposed. */
|
|
87
|
+
readonly enabledTools?: ReadonlySet<string>;
|
|
88
|
+
/** Optional exposure profile to pass to daemon as X-Prism-Mcp-Exposure header. */
|
|
89
|
+
readonly exposureProfile?: string;
|
|
90
|
+
}
|
|
91
|
+
export declare const DEFAULT_SHIM_DAEMON_TIMEOUT_MS = 30000;
|
|
92
|
+
export declare class ShimAggregator {
|
|
93
|
+
private readonly plugins;
|
|
94
|
+
private readonly daemonTimeoutMs;
|
|
95
|
+
private readonly getDaemon;
|
|
96
|
+
private readonly spawnTimeoutMs;
|
|
97
|
+
private readonly resolveOrSpawn;
|
|
98
|
+
private readonly enabledTools;
|
|
99
|
+
private readonly exposureProfile;
|
|
100
|
+
private readonly connections;
|
|
101
|
+
constructor(options: ShimAggregatorOptions);
|
|
102
|
+
/**
|
|
103
|
+
* Resolves (or reuses) the connection for `plugin`: registry record
|
|
104
|
+
* present and live and fresh -> reuse; absent, dead, or stale (bundle
|
|
105
|
+
* hash no longer matches the on-disk bundle) -> `resolveOrSpawn` spawns a
|
|
106
|
+
* fresh daemon and waits for it to come up (see `daemon-resolver.ts`).
|
|
107
|
+
*
|
|
108
|
+
* Returns `undefined` if resolution ultimately fails (no bundle to spawn,
|
|
109
|
+
* or the daemon never became live within the timeout) — that is
|
|
110
|
+
* "unavailable", not fatal: the caller omits its tools / reports a typed
|
|
111
|
+
* error, but the aggregator itself never throws for one bad plugin.
|
|
112
|
+
*/
|
|
113
|
+
private resolveConnection;
|
|
114
|
+
/**
|
|
115
|
+
* Merged, namespaced `tools/list` across every configured plugin.
|
|
116
|
+
* Per-plugin fetches run in parallel (one slow/dead plugin never blocks
|
|
117
|
+
* another), but results are reassembled in the fixed configured-plugin
|
|
118
|
+
* order afterward, so the merged list is deterministic regardless of
|
|
119
|
+
* which daemon happened to answer first.
|
|
120
|
+
*
|
|
121
|
+
* Tools are filtered by `enabledTools` if set: only tools in that set are
|
|
122
|
+
* returned. This is the shim-side filtering applied before any daemon
|
|
123
|
+
* response is merged.
|
|
124
|
+
*/
|
|
125
|
+
listTools(): Promise<ReadonlyArray<Tool>>;
|
|
126
|
+
/**
|
|
127
|
+
* Dispatches a namespaced tool name to its owning plugin's daemon and
|
|
128
|
+
* returns the daemon's raw `CallToolResult` untouched. Throws
|
|
129
|
+
* `ShimDaemonError` (typed) when the name cannot be resolved to a
|
|
130
|
+
* configured plugin, when that plugin's daemon is absent/unreachable
|
|
131
|
+
* within the timeout, or when the tool is not in the enabled set —
|
|
132
|
+
* either way, this never crashes the shim and never touches any other
|
|
133
|
+
* plugin's connection.
|
|
134
|
+
*/
|
|
135
|
+
callTool(fqName: string, args: Record<string, unknown>): Promise<unknown>;
|
|
136
|
+
}
|
|
137
|
+
export declare const createShimServer: (aggregator: ShimAggregator) => Server;
|
|
138
|
+
export interface RunShimOptions {
|
|
139
|
+
readonly plugins: ReadonlyArray<string>;
|
|
140
|
+
/** Prism home directory, threaded from the process entrypoint. See `ShimAggregatorOptions.prismHome`. */
|
|
141
|
+
readonly prismHome?: string;
|
|
142
|
+
readonly daemonTimeoutMs?: number;
|
|
143
|
+
readonly spawnTimeoutMs?: number;
|
|
144
|
+
readonly getDaemon?: GetDaemonFn;
|
|
145
|
+
/** Optional set of tool names to enable; if present, only these tools are exposed. */
|
|
146
|
+
readonly enabledTools?: ReadonlySet<string>;
|
|
147
|
+
/** Optional exposure profile to pass to daemon as X-Prism-Mcp-Exposure header. */
|
|
148
|
+
readonly exposureProfile?: string;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Wires the aggregator to a stdio transport and runs until stdin closes or
|
|
152
|
+
* the process receives SIGINT/SIGTERM. Never throws for daemon-level
|
|
153
|
+
* failures — those surface per-request as typed MCP errors instead.
|
|
154
|
+
*/
|
|
155
|
+
export declare const runShim: (options: RunShimOptions) => Promise<void>;
|