@stigmer/runner 3.12.3 → 3.12.5
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/.build-fingerprint +1 -1
- package/dist/activities/call-http.js +12 -0
- package/dist/activities/call-http.js.map +1 -1
- package/dist/activities/call-llm.d.ts +18 -0
- package/dist/activities/call-llm.js +56 -2
- package/dist/activities/call-llm.js.map +1 -1
- package/dist/activities/execute-cursor/agent-session-cache.d.ts +72 -0
- package/dist/activities/execute-cursor/agent-session-cache.js +186 -0
- package/dist/activities/execute-cursor/agent-session-cache.js.map +1 -0
- package/dist/activities/execute-cursor/cursor-mcp-config.d.ts +45 -0
- package/dist/activities/execute-cursor/cursor-mcp-config.js +76 -0
- package/dist/activities/execute-cursor/cursor-mcp-config.js.map +1 -0
- package/dist/activities/execute-cursor/index.d.ts +10 -1
- package/dist/activities/execute-cursor/index.js +108 -57
- package/dist/activities/execute-cursor/index.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +13 -2
- package/dist/activities/execute-cursor/prompt-builder.js +11 -0
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/service-tier.d.ts +5 -15
- package/dist/activities/execute-cursor/service-tier.js +5 -21
- package/dist/activities/execute-cursor/service-tier.js.map +1 -1
- package/dist/activities/execute-cursor/session-lifecycle.d.ts +1 -1
- package/dist/activities/execute-cursor/skill-resolver.d.ts +2 -21
- package/dist/activities/execute-cursor/skill-resolver.js +5 -108
- package/dist/activities/execute-cursor/skill-resolver.js.map +1 -1
- package/dist/activities/execute-deep-agent/approval-file-change.d.ts +9 -0
- package/dist/activities/execute-deep-agent/approval-file-change.js +2 -1
- package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -1
- package/dist/activities/execute-deep-agent/cas-capture-backend.d.ts +18 -1
- package/dist/activities/execute-deep-agent/cas-capture-backend.js +20 -3
- package/dist/activities/execute-deep-agent/cas-capture-backend.js.map +1 -1
- package/dist/activities/execute-deep-agent/index.js +57 -5
- package/dist/activities/execute-deep-agent/index.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +9 -0
- package/dist/activities/execute-deep-agent/prompt-builder.js +10 -0
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/setup.js +31 -16
- package/dist/activities/execute-deep-agent/setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/shell-env.d.ts +8 -5
- package/dist/activities/execute-deep-agent/shell-env.js +10 -7
- package/dist/activities/execute-deep-agent/shell-env.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.js +17 -11
- package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +3 -3
- package/dist/config.js +10 -5
- package/dist/config.js.map +1 -1
- package/dist/encryption/config.js +7 -2
- package/dist/encryption/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/main.js +12 -6
- package/dist/main.js.map +1 -1
- package/dist/middleware/path-normalization.d.ts +49 -49
- package/dist/middleware/path-normalization.js +73 -84
- package/dist/middleware/path-normalization.js.map +1 -1
- package/dist/middleware/types.d.ts +3 -3
- package/dist/payload-codecs.js +2 -1
- package/dist/payload-codecs.js.map +1 -1
- package/dist/runner-manager.d.ts +1 -1
- package/dist/runner-manager.js +42 -22
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.js +30 -6
- package/dist/runner.js.map +1 -1
- package/dist/shared/args-preview.d.ts +8 -0
- package/dist/shared/args-preview.js +14 -3
- package/dist/shared/args-preview.js.map +1 -1
- package/dist/shared/artifact-storage.d.ts +11 -1
- package/dist/shared/artifact-storage.js +10 -1
- package/dist/shared/artifact-storage.js.map +1 -1
- package/dist/shared/declared-preferences.d.ts +47 -0
- package/dist/shared/declared-preferences.js +64 -0
- package/dist/shared/declared-preferences.js.map +1 -0
- package/dist/shared/fingerprint-secret.d.ts +3 -2
- package/dist/shared/fingerprint-secret.js +5 -3
- package/dist/shared/fingerprint-secret.js.map +1 -1
- package/dist/shared/llm-backend.js +8 -1
- package/dist/shared/llm-backend.js.map +1 -1
- package/dist/shared/mcp-enabled-tools.d.ts +2 -3
- package/dist/shared/mcp-enabled-tools.js +2 -3
- package/dist/shared/mcp-enabled-tools.js.map +1 -1
- package/dist/shared/mcp-resolver.d.ts +20 -15
- package/dist/shared/mcp-resolver.js +11 -12
- package/dist/shared/mcp-resolver.js.map +1 -1
- package/dist/shared/model-client.d.ts +15 -0
- package/dist/shared/model-client.js +57 -13
- package/dist/shared/model-client.js.map +1 -1
- package/dist/shared/placeholder-resolver.d.ts +9 -2
- package/dist/shared/placeholder-resolver.js +9 -2
- package/dist/shared/placeholder-resolver.js.map +1 -1
- package/dist/shared/plan-mode-permissions.d.ts +26 -46
- package/dist/shared/plan-mode-permissions.js +27 -55
- package/dist/shared/plan-mode-permissions.js.map +1 -1
- package/dist/shared/registry-endpoint.d.ts +5 -0
- package/dist/shared/registry-endpoint.js +7 -1
- package/dist/shared/registry-endpoint.js.map +1 -1
- package/dist/shared/runner-credential-keys.d.ts +26 -1
- package/dist/shared/runner-credential-keys.js +34 -1
- package/dist/shared/runner-credential-keys.js.map +1 -1
- package/dist/shared/runner-credential-store.d.ts +77 -0
- package/dist/shared/runner-credential-store.js +111 -0
- package/dist/shared/runner-credential-store.js.map +1 -0
- package/dist/shared/service-tier.d.ts +55 -0
- package/dist/shared/service-tier.js +67 -0
- package/dist/shared/service-tier.js.map +1 -0
- package/dist/shared/skill-mount.d.ts +89 -0
- package/dist/shared/skill-mount.js +142 -0
- package/dist/shared/skill-mount.js.map +1 -0
- package/dist/shared/skill-writer.d.ts +28 -26
- package/dist/shared/skill-writer.js +79 -102
- package/dist/shared/skill-writer.js.map +1 -1
- package/dist/shared/worker-shutdown.d.ts +67 -0
- package/dist/shared/worker-shutdown.js +79 -0
- package/dist/shared/worker-shutdown.js.map +1 -0
- package/dist/shared/workspace/types.d.ts +3 -2
- package/dist/shared/zip-extract.d.ts +10 -3
- package/dist/shared/zip-extract.js +10 -3
- package/dist/shared/zip-extract.js.map +1 -1
- package/dist/workflow-engine/loader.js +38 -1
- package/dist/workflow-engine/loader.js.map +1 -1
- package/dist/workflow-engine/tasks/call-function.d.ts +14 -0
- package/dist/workflow-engine/tasks/call-function.js +49 -5
- package/dist/workflow-engine/tasks/call-function.js.map +1 -1
- package/dist/workflow-engine/tasks/human-input.js +23 -2
- package/dist/workflow-engine/tasks/human-input.js.map +1 -1
- package/dist/workflow-engine/types.d.ts +6 -0
- package/dist/workflow-engine/types.js.map +1 -1
- package/dist/workflows/engine-core.js +36 -8
- package/dist/workflows/engine-core.js.map +1 -1
- package/package.json +15 -11
- package/src/activities/__tests__/call-http.test.ts +36 -0
- package/src/activities/__tests__/call-llm.test.ts +77 -0
- package/src/activities/call-http.ts +17 -0
- package/src/activities/call-llm.ts +78 -2
- package/src/activities/execute-cursor/__tests__/agent-session-cache.test.ts +220 -0
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +50 -0
- package/src/activities/execute-cursor/__tests__/cursor-mcp-config.test.ts +111 -0
- package/src/activities/execute-cursor/__tests__/service-tier.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/skill-resolver.test.ts +3 -94
- package/src/activities/execute-cursor/agent-session-cache.ts +229 -0
- package/src/activities/execute-cursor/cursor-mcp-config.ts +107 -0
- package/src/activities/execute-cursor/index.ts +129 -55
- package/src/activities/execute-cursor/prompt-builder.ts +29 -2
- package/src/activities/execute-cursor/service-tier.ts +5 -29
- package/src/activities/execute-cursor/session-lifecycle.ts +1 -1
- package/src/activities/execute-cursor/skill-resolver.ts +10 -137
- package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +15 -0
- package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +75 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/index.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +42 -29
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +52 -0
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +11 -8
- package/src/activities/execute-deep-agent/approval-file-change.ts +11 -1
- package/src/activities/execute-deep-agent/cas-capture-backend.ts +20 -3
- package/src/activities/execute-deep-agent/index.ts +57 -5
- package/src/activities/execute-deep-agent/prompt-builder.ts +22 -0
- package/src/activities/execute-deep-agent/setup.ts +36 -19
- package/src/activities/execute-deep-agent/shell-env.ts +10 -7
- package/src/activities/execute-deep-agent/subagent-transformer.ts +19 -12
- package/src/activities/execute-deep-agent/subagent-wiring.ts +3 -3
- package/src/config.ts +10 -5
- package/src/encryption/config.ts +8 -2
- package/src/index.ts +1 -1
- package/src/main.ts +16 -6
- package/src/middleware/__tests__/path-normalization.test.ts +32 -32
- package/src/middleware/path-normalization.ts +78 -90
- package/src/middleware/types.ts +3 -3
- package/src/payload-codecs.ts +2 -1
- package/src/runner-manager.ts +55 -22
- package/src/runner.ts +39 -6
- package/src/shared/__tests__/artifact-storage.test.ts +28 -0
- package/src/shared/__tests__/bedrock-seam.test.ts +5 -5
- package/src/shared/__tests__/declared-preferences.test.ts +109 -0
- package/src/shared/__tests__/foundry-seam.test.ts +5 -5
- package/src/shared/__tests__/model-client.test.ts +99 -0
- package/src/shared/__tests__/plan-mode-permissions.test.ts +15 -44
- package/src/shared/__tests__/runner-credential-store.test.ts +155 -0
- package/src/shared/__tests__/skill-mount.test.ts +238 -0
- package/src/shared/__tests__/skill-writer.test.ts +151 -128
- package/src/shared/__tests__/vertex-adapter.test.ts +30 -3
- package/src/shared/__tests__/vertex-seam.test.ts +5 -5
- package/src/shared/__tests__/worker-shutdown.test.ts +101 -0
- package/src/shared/__tests__/zip-extract.test.ts +46 -11
- package/src/shared/args-preview.ts +17 -3
- package/src/shared/artifact-storage.ts +20 -1
- package/src/shared/declared-preferences.ts +84 -0
- package/src/shared/fingerprint-secret.ts +5 -3
- package/src/shared/llm-backend.ts +7 -1
- package/src/shared/mcp-enabled-tools.ts +2 -3
- package/src/shared/mcp-resolver.ts +20 -20
- package/src/shared/model-client.ts +76 -13
- package/src/shared/placeholder-resolver.ts +9 -2
- package/src/shared/plan-mode-permissions.ts +27 -58
- package/src/shared/registry-endpoint.ts +9 -1
- package/src/shared/runner-credential-keys.ts +36 -1
- package/src/shared/runner-credential-store.ts +115 -0
- package/src/shared/service-tier.ts +78 -0
- package/src/shared/skill-mount.ts +179 -0
- package/src/shared/skill-writer.ts +96 -130
- package/src/shared/worker-shutdown.ts +99 -0
- package/src/shared/workspace/types.ts +3 -2
- package/src/shared/zip-extract.ts +14 -7
- package/src/workflow-engine/__tests__/golden-execution.test.ts +20 -1
- package/src/workflow-engine/__tests__/loader.test.ts +51 -0
- package/src/workflow-engine/__tests__/tasks/call-function.test.ts +105 -0
- package/src/workflow-engine/__tests__/tasks/human-input.test.ts +117 -0
- package/src/workflow-engine/loader.ts +46 -1
- package/src/workflow-engine/tasks/call-function.ts +74 -13
- package/src/workflow-engine/tasks/human-input.ts +33 -5
- package/src/workflow-engine/types.ts +6 -0
- package/src/workflows/engine-core.ts +39 -8
- package/dist/activities/execute-cursor/connect-backfill.d.ts +0 -19
- package/dist/activities/execute-cursor/connect-backfill.js +0 -27
- package/dist/activities/execute-cursor/connect-backfill.js.map +0 -1
- package/dist/activities/execute-cursor/mcp-resolver.d.ts +0 -120
- package/dist/activities/execute-cursor/mcp-resolver.js +0 -194
- package/dist/activities/execute-cursor/mcp-resolver.js.map +0 -1
- package/dist/activities/execute-cursor/placeholder-resolver.d.ts +0 -34
- package/dist/activities/execute-cursor/placeholder-resolver.js +0 -82
- package/dist/activities/execute-cursor/placeholder-resolver.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/mcp-resolver.test.ts +0 -125
- package/src/activities/execute-cursor/connect-backfill.ts +0 -52
- package/src/activities/execute-cursor/mcp-resolver.ts +0 -324
- package/src/activities/execute-cursor/placeholder-resolver.ts +0 -109
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolves Stigmer McpServerUsage references into Cursor SDK McpServerConfig
|
|
3
|
-
* and loads tool approval policies from each MCP server resource.
|
|
4
|
-
*
|
|
5
|
-
* Stigmer sessions reference MCP servers by slug via McpServerUsage. Each
|
|
6
|
-
* usage points to an McpServer resource that has connection config (stdio
|
|
7
|
-
* or HTTP) and tool approval policies (system-generated + manual overrides).
|
|
8
|
-
*
|
|
9
|
-
* This module fetches those resources and produces:
|
|
10
|
-
* 1. Cursor SDK McpServerConfig for Agent.create()
|
|
11
|
-
* 2. Tool approval policies for the HITL hook script
|
|
12
|
-
*
|
|
13
|
-
* Secrets (env vars, headers) come from the merged execution context,
|
|
14
|
-
* same pipeline as the Python agent-runner's config_transformer.py.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import type { McpServerUsage, ToolApprovalOverride } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
18
|
-
import type { McpServer } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
|
|
19
|
-
import type { ToolApprovalPolicy } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/spec_pb";
|
|
20
|
-
import type { StigmerClient } from "../../client/stigmer-client.js";
|
|
21
|
-
import {
|
|
22
|
-
assertTransportAllowed,
|
|
23
|
-
McpTransportError,
|
|
24
|
-
type McpTransportPosture,
|
|
25
|
-
} from "../../shared/mcp-transport-guard.js";
|
|
26
|
-
import {
|
|
27
|
-
resolveHeaders,
|
|
28
|
-
resolvePlaceholders,
|
|
29
|
-
filterEnvToDeclaredKeys,
|
|
30
|
-
PlaceholderResolutionError,
|
|
31
|
-
} from "./placeholder-resolver.js";
|
|
32
|
-
import { effectiveEnabledTools } from "../../shared/mcp-enabled-tools.js";
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Cursor SDK MCP server config shape (matches @cursor/sdk McpServerConfig).
|
|
36
|
-
* Defined here to avoid tight coupling to the SDK's internal types.
|
|
37
|
-
*/
|
|
38
|
-
export type CursorMcpServerConfig =
|
|
39
|
-
| {
|
|
40
|
-
type?: "stdio";
|
|
41
|
-
command: string;
|
|
42
|
-
args?: string[];
|
|
43
|
-
env?: Record<string, string>;
|
|
44
|
-
cwd?: string;
|
|
45
|
-
}
|
|
46
|
-
| {
|
|
47
|
-
type?: "http" | "sse";
|
|
48
|
-
url: string;
|
|
49
|
-
headers?: Record<string, string>;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Resolved MCP server with connection config and approval policies.
|
|
54
|
-
*
|
|
55
|
-
* Extends the basic connection info with the full policy data needed
|
|
56
|
-
* for HITL enforcement. Loaded in a single fetch per server to avoid
|
|
57
|
-
* extra round-trips.
|
|
58
|
-
*/
|
|
59
|
-
export interface ResolvedMcpServer {
|
|
60
|
-
slug: string;
|
|
61
|
-
connectionType: "stdio" | "http" | "sse";
|
|
62
|
-
command?: string;
|
|
63
|
-
args?: string[];
|
|
64
|
-
env?: Record<string, string>;
|
|
65
|
-
cwd?: string;
|
|
66
|
-
url?: string;
|
|
67
|
-
headers?: Record<string, string>;
|
|
68
|
-
/** System-generated approval policies from the connect flow's LLM classifier. */
|
|
69
|
-
toolApprovals: ToolApprovalPolicy[];
|
|
70
|
-
/** Manual overrides set by the MCP server owner. */
|
|
71
|
-
pinnedToolApprovals: ToolApprovalPolicy[];
|
|
72
|
-
/** True when the server has never been connected (no tool discovery yet). */
|
|
73
|
-
discoveredCapabilitiesEmpty: boolean;
|
|
74
|
-
/**
|
|
75
|
-
* The EFFECTIVE tool allow-list for this server (issue #350): the usage's
|
|
76
|
-
* enabled_tools, falling back to the server's default_enabled_tools when
|
|
77
|
-
* the usage's list is empty (see shared/mcp-enabled-tools.ts). Absent when
|
|
78
|
-
* unrestricted. The Cursor SDK config cannot hide tools, so this harness
|
|
79
|
-
* enforces it in the HITL hook: the restricted map is written into the
|
|
80
|
-
* approval state (mcpServerEnabledTools) and non-enabled calls are denied
|
|
81
|
-
* with the non-pausing "disabled" kind (see hook-script.ts).
|
|
82
|
-
*/
|
|
83
|
-
enabledTools?: string[];
|
|
84
|
-
/**
|
|
85
|
-
* Layer-3 per-agent approval overrides from the usage that resolved this
|
|
86
|
-
* server (issue #349): riding the resolved server is what SCOPES an
|
|
87
|
-
* override to its own server — a flat cross-server list is how an
|
|
88
|
-
* override once leaked onto (or silently un-gated) a same-named tool on
|
|
89
|
-
* another server. Deliberately REQUIRED, not optional: empty means "no
|
|
90
|
-
* overrides", and every construction site — including the shared
|
|
91
|
-
* resolver this one mirrors and the synthesized attachments, which have
|
|
92
|
-
* no usage and therefore no layer 3 — must say so explicitly, so a
|
|
93
|
-
* forgotten mirror cannot compile. Consumed by mergeApprovalPolicies
|
|
94
|
-
* (shared/approval-policy.ts).
|
|
95
|
-
*/
|
|
96
|
-
toolApprovalOverrides: ToolApprovalOverride[];
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Result of resolving MCP servers: Cursor SDK config for Agent.create()
|
|
101
|
-
* and the full resolved server list for policy evaluation.
|
|
102
|
-
*/
|
|
103
|
-
export interface McpResolutionResult {
|
|
104
|
-
cursorConfig: Record<string, CursorMcpServerConfig>;
|
|
105
|
-
resolvedServers: ResolvedMcpServer[];
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Fetch McpServer resources for each merged usage and resolve into
|
|
110
|
-
* Cursor SDK config format plus approval policies.
|
|
111
|
-
*
|
|
112
|
-
* Replicates the Python agent-runner's pattern:
|
|
113
|
-
* 1. For each McpServerUsage, use the ref to fetch the full McpServer resource
|
|
114
|
-
* 2. Extract connection config (stdio or http) from McpServerSpec
|
|
115
|
-
* 3. Extract approval policies from McpServerStatus + McpServerSpec
|
|
116
|
-
* 4. Transform into Cursor SDK's mcpServers config
|
|
117
|
-
*
|
|
118
|
-
* @param transportPosture Whether stdio servers may run here (derive via
|
|
119
|
-
* resolveMcpTransportPosture(config.mode)). A stdio server under a
|
|
120
|
-
* forbidding posture throws {@link McpTransportError} and fails the
|
|
121
|
-
* whole resolution — never degraded to a skipped server.
|
|
122
|
-
*/
|
|
123
|
-
export async function resolveMcpServers(
|
|
124
|
-
client: StigmerClient,
|
|
125
|
-
usages: McpServerUsage[],
|
|
126
|
-
envVars: Record<string, string>,
|
|
127
|
-
transportPosture: McpTransportPosture,
|
|
128
|
-
): Promise<McpResolutionResult> {
|
|
129
|
-
const resolved: ResolvedMcpServer[] = [];
|
|
130
|
-
|
|
131
|
-
for (const usage of usages) {
|
|
132
|
-
const ref = usage.mcpServerRef;
|
|
133
|
-
if (!ref?.slug) continue;
|
|
134
|
-
|
|
135
|
-
try {
|
|
136
|
-
const mcpServer = await client.getMcpServerByReference(ref);
|
|
137
|
-
const serverEnv = filterEnvToDeclaredKeys(
|
|
138
|
-
mcpServer.spec?.env,
|
|
139
|
-
envVars,
|
|
140
|
-
ref.slug,
|
|
141
|
-
);
|
|
142
|
-
const server = mcpServerToResolved(
|
|
143
|
-
mcpServer,
|
|
144
|
-
ref.slug,
|
|
145
|
-
serverEnv,
|
|
146
|
-
usage.enabledTools,
|
|
147
|
-
usage.toolApprovalOverrides ?? [],
|
|
148
|
-
);
|
|
149
|
-
if (server) {
|
|
150
|
-
assertTransportAllowed(server.slug, server.connectionType, transportPosture);
|
|
151
|
-
resolved.push(server);
|
|
152
|
-
}
|
|
153
|
-
} catch (err) {
|
|
154
|
-
if (err instanceof McpTransportError) {
|
|
155
|
-
// Policy rejection, not a resolution hiccup: swallowing it here
|
|
156
|
-
// would mean the agent silently loses tools. Fail the execution.
|
|
157
|
-
throw err;
|
|
158
|
-
}
|
|
159
|
-
if (err instanceof PlaceholderResolutionError) {
|
|
160
|
-
console.error(
|
|
161
|
-
`MCP server ${ref.org}/${ref.slug}: ${err.message}`,
|
|
162
|
-
);
|
|
163
|
-
} else {
|
|
164
|
-
console.warn(
|
|
165
|
-
`Failed to resolve MCP server ${ref.org}/${ref.slug}: ${err instanceof Error ? err.message : err}`,
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return {
|
|
172
|
-
cursorConfig: toCursorMcpConfig(resolved),
|
|
173
|
-
resolvedServers: resolved,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Convert a fetched McpServer resource into our intermediate format,
|
|
179
|
-
* including approval policies and discovery state.
|
|
180
|
-
*/
|
|
181
|
-
function mcpServerToResolved(
|
|
182
|
-
server: McpServer,
|
|
183
|
-
slug: string,
|
|
184
|
-
envVars: Record<string, string>,
|
|
185
|
-
usageEnabledTools?: readonly string[],
|
|
186
|
-
usageToolApprovalOverrides: ToolApprovalOverride[] = [],
|
|
187
|
-
): ResolvedMcpServer | null {
|
|
188
|
-
const spec = server.spec;
|
|
189
|
-
if (!spec) return null;
|
|
190
|
-
|
|
191
|
-
const status = server.status;
|
|
192
|
-
const toolApprovals = status?.toolApprovals ?? [];
|
|
193
|
-
const pinnedToolApprovals = spec.pinnedToolApprovals ?? [];
|
|
194
|
-
const discoveredCapabilitiesEmpty = !status?.discoveredCapabilities
|
|
195
|
-
|| (status.discoveredCapabilities.tools.length === 0
|
|
196
|
-
&& status.discoveredCapabilities.resourceTemplates.length === 0);
|
|
197
|
-
|
|
198
|
-
const base = {
|
|
199
|
-
toolApprovals,
|
|
200
|
-
pinnedToolApprovals,
|
|
201
|
-
discoveredCapabilitiesEmpty,
|
|
202
|
-
enabledTools: effectiveEnabledTools(usageEnabledTools, spec.defaultEnabledTools),
|
|
203
|
-
toolApprovalOverrides: usageToolApprovalOverrides,
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
switch (spec.serverType.case) {
|
|
207
|
-
case "stdio": {
|
|
208
|
-
const stdio = spec.serverType.value;
|
|
209
|
-
if (!stdio.command) return null;
|
|
210
|
-
const resolvedArgs = stdio.args.length > 0
|
|
211
|
-
? stdio.args.map((arg, i) =>
|
|
212
|
-
resolvePlaceholders(arg, envVars, `stdio arg[${i}]`),
|
|
213
|
-
)
|
|
214
|
-
: undefined;
|
|
215
|
-
return {
|
|
216
|
-
slug,
|
|
217
|
-
connectionType: "stdio",
|
|
218
|
-
command: stdio.command,
|
|
219
|
-
args: resolvedArgs,
|
|
220
|
-
env: Object.keys(envVars).length > 0 ? { ...envVars } : undefined,
|
|
221
|
-
cwd: stdio.workingDir || undefined,
|
|
222
|
-
...base,
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
case "http": {
|
|
226
|
-
const http = spec.serverType.value;
|
|
227
|
-
if (!http.url) return null;
|
|
228
|
-
const rawHeaders = Object.keys(http.headers).length > 0 ? http.headers : undefined;
|
|
229
|
-
const resolved = rawHeaders
|
|
230
|
-
? resolveHeaders(Object.fromEntries(Object.entries(rawHeaders)), envVars)
|
|
231
|
-
: undefined;
|
|
232
|
-
return {
|
|
233
|
-
slug,
|
|
234
|
-
connectionType: "http",
|
|
235
|
-
url: http.url,
|
|
236
|
-
headers: resolved,
|
|
237
|
-
...base,
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
default:
|
|
241
|
-
return null;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Transform resolved MCP servers into the Cursor SDK's mcpServers config
|
|
247
|
-
* for Agent.create().
|
|
248
|
-
*/
|
|
249
|
-
export function toCursorMcpConfig(
|
|
250
|
-
servers: ResolvedMcpServer[],
|
|
251
|
-
): Record<string, CursorMcpServerConfig> {
|
|
252
|
-
const result: Record<string, CursorMcpServerConfig> = {};
|
|
253
|
-
|
|
254
|
-
for (const server of servers) {
|
|
255
|
-
if (server.connectionType === "stdio") {
|
|
256
|
-
if (!server.command) continue;
|
|
257
|
-
result[server.slug] = {
|
|
258
|
-
type: "stdio",
|
|
259
|
-
command: server.command,
|
|
260
|
-
args: server.args,
|
|
261
|
-
env: server.env,
|
|
262
|
-
cwd: server.cwd,
|
|
263
|
-
};
|
|
264
|
-
} else {
|
|
265
|
-
if (!server.url) continue;
|
|
266
|
-
result[server.slug] = {
|
|
267
|
-
type: server.connectionType,
|
|
268
|
-
url: server.url,
|
|
269
|
-
headers: server.headers,
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
return result;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Extract MCP server slugs from session-level McpServerUsage references.
|
|
279
|
-
*/
|
|
280
|
-
export function extractMcpServerSlugs(usages: McpServerUsage[]): string[] {
|
|
281
|
-
return usages
|
|
282
|
-
.map((u) => u.mcpServerRef?.slug)
|
|
283
|
-
.filter((s): s is string => !!s);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Validate that resolved MCP servers have their required env vars populated.
|
|
288
|
-
* Returns a list of warnings for servers with empty/missing env.
|
|
289
|
-
* Used as a pre-flight check before agent.send() to surface config issues early.
|
|
290
|
-
*/
|
|
291
|
-
export function validateMcpServerEnv(
|
|
292
|
-
servers: ResolvedMcpServer[],
|
|
293
|
-
usages: McpServerUsage[],
|
|
294
|
-
envVars: Record<string, string>,
|
|
295
|
-
): string[] {
|
|
296
|
-
const warnings: string[] = [];
|
|
297
|
-
|
|
298
|
-
for (const usage of usages) {
|
|
299
|
-
const slug = usage.mcpServerRef?.slug;
|
|
300
|
-
if (!slug) continue;
|
|
301
|
-
|
|
302
|
-
const resolved = servers.find((s) => s.slug === slug);
|
|
303
|
-
if (!resolved) {
|
|
304
|
-
warnings.push(`MCP server '${slug}': failed to resolve (server may not exist or is inaccessible)`);
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (resolved.connectionType === "stdio" && resolved.env) {
|
|
309
|
-
const emptyKeys = Object.entries(resolved.env)
|
|
310
|
-
.filter(([, v]) => !v)
|
|
311
|
-
.map(([k]) => k);
|
|
312
|
-
if (emptyKeys.length > 0) {
|
|
313
|
-
warnings.push(
|
|
314
|
-
`MCP server '${slug}': env vars [${emptyKeys.join(", ")}] are empty — ` +
|
|
315
|
-
`server subprocess will likely fail to connect`,
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return warnings;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
export { PlaceholderResolutionError } from "./placeholder-resolver.js";
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Strict placeholder resolver for ${VAR_NAME} syntax in MCP server configs.
|
|
3
|
-
*
|
|
4
|
-
* Port of the Python agent-runner's PlaceholderResolver (strict mode only).
|
|
5
|
-
* Always raises on unresolved placeholders — sending literal ${VAR} as an
|
|
6
|
-
* HTTP header value (e.g. Authorization: Bearer ${API_KEY}) produces
|
|
7
|
-
* cryptic auth failures from the remote server.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const PLACEHOLDER_RE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
11
|
-
|
|
12
|
-
export class PlaceholderResolutionError extends Error {
|
|
13
|
-
constructor(
|
|
14
|
-
public readonly variableName: string,
|
|
15
|
-
public readonly context?: string,
|
|
16
|
-
) {
|
|
17
|
-
const where = context ? ` in ${context}` : "";
|
|
18
|
-
super(
|
|
19
|
-
`Unresolved placeholder \${${variableName}}${where}: ` +
|
|
20
|
-
`variable is not present in the execution environment`,
|
|
21
|
-
);
|
|
22
|
-
this.name = "PlaceholderResolutionError";
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Resolve all ${VAR_NAME} placeholders in a template string.
|
|
28
|
-
*
|
|
29
|
-
* @throws PlaceholderResolutionError if any placeholder cannot be resolved.
|
|
30
|
-
*/
|
|
31
|
-
export function resolvePlaceholders(
|
|
32
|
-
template: string,
|
|
33
|
-
envVars: Record<string, string>,
|
|
34
|
-
context?: string,
|
|
35
|
-
): string {
|
|
36
|
-
return template.replace(PLACEHOLDER_RE, (match, varName: string) => {
|
|
37
|
-
if (varName in envVars) {
|
|
38
|
-
return envVars[varName];
|
|
39
|
-
}
|
|
40
|
-
throw new PlaceholderResolutionError(varName, context);
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Resolve placeholders in all values of a headers map.
|
|
46
|
-
*
|
|
47
|
-
* @throws PlaceholderResolutionError if any header value contains an
|
|
48
|
-
* unresolvable placeholder.
|
|
49
|
-
*/
|
|
50
|
-
export function resolveHeaders(
|
|
51
|
-
headers: Record<string, string>,
|
|
52
|
-
envVars: Record<string, string>,
|
|
53
|
-
): Record<string, string> {
|
|
54
|
-
const resolved: Record<string, string> = {};
|
|
55
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
56
|
-
resolved[key] = resolvePlaceholders(value, envVars, `header "${key}"`);
|
|
57
|
-
}
|
|
58
|
-
return resolved;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Filter env vars to only keys declared in the MCP server's spec.env.
|
|
63
|
-
*
|
|
64
|
-
* Mirrors the agent-runner's _filter_env_to_declared_keys: prevents
|
|
65
|
-
* secret over-sharing by restricting the subprocess/HTTP environment to
|
|
66
|
-
* explicitly declared variables.
|
|
67
|
-
*/
|
|
68
|
-
export function filterEnvToDeclaredKeys(
|
|
69
|
-
declaredEnv: Record<string, unknown> | undefined,
|
|
70
|
-
envVars: Record<string, string>,
|
|
71
|
-
serverSlug: string,
|
|
72
|
-
): Record<string, string> {
|
|
73
|
-
if (!declaredEnv || Object.keys(declaredEnv).length === 0) {
|
|
74
|
-
if (Object.keys(envVars).length > 0) {
|
|
75
|
-
console.log(
|
|
76
|
-
`MCP server '${serverSlug}' has no env declarations — ` +
|
|
77
|
-
`dropping ${Object.keys(envVars).length} env var(s)`,
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
return {};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const declaredKeys = new Set(Object.keys(declaredEnv));
|
|
84
|
-
const filtered: Record<string, string> = {};
|
|
85
|
-
|
|
86
|
-
for (const [key, value] of Object.entries(envVars)) {
|
|
87
|
-
if (declaredKeys.has(key)) {
|
|
88
|
-
filtered[key] = value;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const dropped = Object.keys(envVars).length - Object.keys(filtered).length;
|
|
93
|
-
if (dropped > 0) {
|
|
94
|
-
console.log(
|
|
95
|
-
`MCP server '${serverSlug}': passing ${Object.keys(filtered).length} ` +
|
|
96
|
-
`declared env var(s), filtered out ${dropped} undeclared key(s)`,
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const missing = [...declaredKeys].filter((k) => !(k in filtered));
|
|
101
|
-
if (missing.length > 0) {
|
|
102
|
-
console.warn(
|
|
103
|
-
`MCP server '${serverSlug}': env declares [${missing.sort().join(", ")}] ` +
|
|
104
|
-
`but they are not present in the resolved environment`,
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return filtered;
|
|
109
|
-
}
|