@duckmind/dm-windows-x64 0.61.4 → 0.61.9
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/dm.exe +0 -0
- package/extensions/.dm-extensions.json +211 -67
- package/extensions/dm-subagents/agents/claude-code-writer.md +15 -0
- package/extensions/dm-subagents/agents/claude-code.md +15 -0
- package/extensions/dm-subagents/agents/codex-exec-writer.md +15 -0
- package/extensions/dm-subagents/agents/codex-exec.md +15 -0
- package/extensions/dm-subagents/agents/cursor-agent-writer.md +14 -0
- package/extensions/dm-subagents/agents/cursor-agent.md +14 -0
- package/extensions/dm-subagents/agents/delegate.md +3 -2
- package/extensions/dm-subagents/agents/oracle.md +10 -5
- package/extensions/dm-subagents/agents/researcher.md +2 -2
- package/extensions/dm-subagents/agents/reviewer.md +17 -7
- package/extensions/dm-subagents/agents/scout.md +5 -5
- package/extensions/dm-subagents/agents/worker.md +6 -2
- package/extensions/dm-subagents/async-retention-discovery-worker.mjs +167 -0
- package/extensions/dm-subagents/index.js +4 -0
- package/extensions/dm-subagents/inspector-runner.mjs +10 -0
- package/extensions/dm-subagents/install.mjs +3 -2
- package/extensions/dm-subagents/package.json +2 -2
- package/extensions/dm-subagents/prompts/council.md +60 -0
- package/extensions/dm-subagents/prompts/parallel-review.md +5 -1
- package/extensions/dm-subagents/prompts/review-loop.md +13 -7
- package/extensions/dm-subagents/skills/council-mode/SKILL.md +59 -0
- package/extensions/dm-subagents/skills/council-mode/references/pass-contracts.md +150 -0
- package/extensions/dm-subagents/skills/dm-subagents/SKILL.md +96 -911
- package/extensions/dm-subagents/skills/dm-subagents/references/constraints-and-recipes.md +70 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/execution-controls.md +539 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/management-authoring-rpc.md +161 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/multi-lane-orchestration.md +51 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/prompting-and-roles.md +295 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/review-and-validation.md +73 -0
- package/extensions/dm-subagents/src/agents/agent-management.js +716 -484
- package/extensions/dm-subagents/src/agents/agent-refinements.js +563 -0
- package/extensions/dm-subagents/src/agents/agent-serializer.js +70 -5
- package/extensions/dm-subagents/src/agents/agents.js +1447 -299
- package/extensions/dm-subagents/src/agents/builtin-names.js +15 -0
- package/extensions/dm-subagents/src/agents/chain-serializer.js +12 -7
- package/extensions/dm-subagents/src/agents/frontmatter.js +64 -14
- package/extensions/dm-subagents/src/agents/identity.js +1 -1
- package/extensions/dm-subagents/src/agents/proactive-skills.js +14 -11
- package/extensions/dm-subagents/src/agents/runtime-agent-events.js +49 -0
- package/extensions/dm-subagents/src/agents/runtime-agent-registry.js +412 -0
- package/extensions/dm-subagents/src/agents/skills.js +52 -35
- package/extensions/dm-subagents/src/api/agents.js +6 -0
- package/extensions/dm-subagents/src/api/background-work.js +151 -0
- package/extensions/dm-subagents/src/api/capability-ceiling.js +12 -0
- package/extensions/dm-subagents/src/api/control-channel.js +3 -0
- package/extensions/dm-subagents/src/api/delegation.js +5 -0
- package/extensions/dm-subagents/src/api/dm-args.js +3 -0
- package/extensions/dm-subagents/src/api/external-job-provider.js +137 -0
- package/extensions/dm-subagents/src/api/external-runs.js +233 -0
- package/extensions/dm-subagents/src/api/intercom-bridge.js +3 -0
- package/extensions/dm-subagents/src/api/preflight.js +322 -0
- package/extensions/dm-subagents/src/api/project-panes.js +11 -0
- package/extensions/dm-subagents/src/api/shared-types.js +4 -0
- package/extensions/dm-subagents/src/extension/config.js +175 -0
- package/extensions/dm-subagents/src/extension/control-notices.js +4 -43
- package/extensions/dm-subagents/src/extension/doctor.js +71 -17
- package/extensions/dm-subagents/src/extension/fanout-child.js +49 -32
- package/extensions/dm-subagents/src/extension/index.js +711 -265
- package/extensions/dm-subagents/src/extension/public-execution.js +114 -0
- package/extensions/dm-subagents/src/extension/rpc.js +427 -22
- package/extensions/dm-subagents/src/extension/schemas.js +158 -65
- package/extensions/dm-subagents/src/extension/steering-notices.js +23 -0
- package/extensions/dm-subagents/src/extension/subagent-guide.js +31 -0
- package/extensions/dm-subagents/src/extension/tool-description.js +92 -74
- package/extensions/dm-subagents/src/extension/tool-result.js +7 -0
- package/extensions/dm-subagents/src/inspectors/herdr/actions.js +218 -0
- package/extensions/dm-subagents/src/inspectors/herdr/client.js +123 -0
- package/extensions/dm-subagents/src/inspectors/herdr/focus.js +47 -0
- package/extensions/dm-subagents/src/inspectors/herdr/inspector-runner.js +160 -0
- package/extensions/dm-subagents/src/inspectors/herdr/project-panes.js +618 -0
- package/extensions/dm-subagents/src/inspectors/herdr/session-roots-codec.js +21 -0
- package/extensions/dm-subagents/src/inspectors/herdr/shell-command.js +15 -0
- package/extensions/dm-subagents/src/integrations/herdr-status.js +377 -0
- package/extensions/dm-subagents/src/intercom/intercom-bridge.js +17 -13
- package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +371 -79
- package/extensions/dm-subagents/src/intercom/result-intercom.js +47 -7
- package/extensions/dm-subagents/src/missions/actions.js +394 -0
- package/extensions/dm-subagents/src/missions/goal-driver.js +149 -0
- package/extensions/dm-subagents/src/missions/lifecycle.js +331 -0
- package/extensions/dm-subagents/src/missions/store.js +548 -0
- package/extensions/dm-subagents/src/missions/types.js +9 -0
- package/extensions/dm-subagents/src/missions/workflow-state.js +245 -0
- package/extensions/dm-subagents/src/policy/authority.js +37 -0
- package/extensions/dm-subagents/src/profiles/profiles.js +36 -18
- package/extensions/dm-subagents/src/runs/background/active-async-capacity.js +427 -0
- package/extensions/dm-subagents/src/runs/background/active-run-index.js +122 -0
- package/extensions/dm-subagents/src/runs/background/async-execution.js +925 -137
- package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +515 -148
- package/extensions/dm-subagents/src/runs/background/async-resume.js +378 -51
- package/extensions/dm-subagents/src/runs/background/async-retention.js +828 -0
- package/extensions/dm-subagents/src/runs/background/async-status-snapshot.js +31 -0
- package/extensions/dm-subagents/src/runs/background/async-status.js +259 -22
- package/extensions/dm-subagents/src/runs/background/auto-drain.js +46 -0
- package/extensions/dm-subagents/src/runs/background/chain-append.js +50 -15
- package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +67 -12
- package/extensions/dm-subagents/src/runs/background/completion-batcher.js +5 -1
- package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +3 -11
- package/extensions/dm-subagents/src/runs/background/completion-replay.js +245 -0
- package/extensions/dm-subagents/src/runs/background/control-channel.js +423 -36
- package/extensions/dm-subagents/src/runs/background/fleet-view.js +132 -59
- package/extensions/dm-subagents/src/runs/background/index-segment.js +38 -0
- package/extensions/dm-subagents/src/runs/background/inspect-rpc.js +373 -0
- package/extensions/dm-subagents/src/runs/background/notify.js +357 -57
- package/extensions/dm-subagents/src/runs/background/owned-process-tree.js +86 -0
- package/extensions/dm-subagents/src/runs/background/process-terminal.js +269 -0
- package/extensions/dm-subagents/src/runs/background/result-delivery-ownership.js +34 -0
- package/extensions/dm-subagents/src/runs/background/result-files.js +469 -0
- package/extensions/dm-subagents/src/runs/background/result-watcher.js +540 -75
- package/extensions/dm-subagents/src/runs/background/resume-guidance.js +44 -0
- package/extensions/dm-subagents/src/runs/background/retained-children.js +119 -0
- package/extensions/dm-subagents/src/runs/background/run-id-query.js +5 -0
- package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +93 -9
- package/extensions/dm-subagents/src/runs/background/run-status.js +303 -32
- package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +784 -376
- package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +75 -34
- package/extensions/dm-subagents/src/runs/background/steering.js +221 -0
- package/extensions/dm-subagents/src/runs/background/subagent-runner.js +3106 -844
- package/extensions/dm-subagents/src/runs/background/subagent-wait.js +529 -0
- package/extensions/dm-subagents/src/runs/background/terminal-run-index.js +106 -0
- package/extensions/dm-subagents/src/runs/background/top-level-async.js +1 -1
- package/extensions/dm-subagents/src/runs/background/wait-completions.js +155 -0
- package/extensions/dm-subagents/src/runs/background/wait-config.js +46 -0
- package/extensions/dm-subagents/src/runs/background/wait-subscriptions.js +278 -0
- package/extensions/dm-subagents/src/runs/background/wait-tool.js +47 -0
- package/extensions/dm-subagents/src/runs/foreground/async-dismiss-action.js +81 -0
- package/extensions/dm-subagents/src/runs/foreground/async-steering-action.js +245 -0
- package/extensions/dm-subagents/src/runs/foreground/async-stop-action.js +74 -0
- package/extensions/dm-subagents/src/runs/foreground/execution.js +1401 -342
- package/extensions/dm-subagents/src/runs/foreground/foreground-control.js +133 -0
- package/extensions/dm-subagents/src/runs/foreground/foreground-history.js +148 -0
- package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +139 -0
- package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +4278 -1441
- package/extensions/dm-subagents/src/runs/foreground/workflow-detach-reconcile.js +278 -0
- package/extensions/dm-subagents/src/runs/foreground/workflow-foreground-steering.js +155 -0
- package/extensions/dm-subagents/src/runs/shared/abort-recovery.js +97 -0
- package/extensions/dm-subagents/src/runs/shared/acceptance.js +597 -148
- package/extensions/dm-subagents/src/runs/shared/agent-contract.js +35 -0
- package/extensions/dm-subagents/src/runs/shared/async-status-projection.js +472 -0
- package/extensions/dm-subagents/src/runs/shared/background-process-options.js +6 -0
- package/extensions/dm-subagents/src/runs/shared/capability-ceiling.js +175 -0
- package/extensions/dm-subagents/src/runs/shared/child-identity.js +32 -0
- package/extensions/dm-subagents/src/runs/shared/child-launch-plan.js +65 -0
- package/extensions/dm-subagents/src/runs/shared/child-protocol.js +447 -0
- package/extensions/dm-subagents/src/runs/shared/claude-code-adapter.js +120 -0
- package/extensions/dm-subagents/src/runs/shared/codex-exec-adapter.js +129 -0
- package/extensions/dm-subagents/src/runs/shared/completion-evidence.js +40 -0
- package/extensions/dm-subagents/src/runs/shared/completion-guard.js +140 -83
- package/extensions/dm-subagents/src/runs/shared/context-mode.js +38 -0
- package/extensions/dm-subagents/src/runs/shared/cursor-agent-adapter.js +101 -0
- package/extensions/dm-subagents/src/runs/shared/dm-args.js +445 -72
- package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +27 -16
- package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +19 -6
- package/extensions/dm-subagents/src/runs/shared/extension-bindings.js +81 -0
- package/extensions/dm-subagents/src/runs/shared/external-cli-contract.js +134 -0
- package/extensions/dm-subagents/src/runs/shared/external-cli-preflight.js +98 -0
- package/extensions/dm-subagents/src/runs/shared/external-cli-runner.js +419 -0
- package/extensions/dm-subagents/src/runs/shared/external-job-bridge.js +404 -0
- package/extensions/dm-subagents/src/runs/shared/external-job-runner.js +334 -0
- package/extensions/dm-subagents/src/runs/shared/fast-mode-extension.js +8 -0
- package/extensions/dm-subagents/src/runs/shared/host-step-status.js +228 -0
- package/extensions/dm-subagents/src/runs/shared/lane-metadata.js +104 -0
- package/extensions/dm-subagents/src/runs/shared/launch-cwd.js +17 -0
- package/extensions/dm-subagents/src/runs/shared/llm-intent-arbiter.js +190 -0
- package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +48 -3
- package/extensions/dm-subagents/src/runs/shared/mcp-config-sources.js +387 -0
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +212 -137
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-grant.js +131 -0
- package/extensions/dm-subagents/src/runs/shared/model-exclusions.js +207 -0
- package/extensions/dm-subagents/src/runs/shared/model-fallback.js +225 -55
- package/extensions/dm-subagents/src/runs/shared/model-scope.js +85 -28
- package/extensions/dm-subagents/src/runs/shared/mutation-evidence.js +182 -0
- package/extensions/dm-subagents/src/runs/shared/nested-events.js +264 -102
- package/extensions/dm-subagents/src/runs/shared/nested-render.js +15 -5
- package/extensions/dm-subagents/src/runs/shared/orca-progress-tabs.js +505 -0
- package/extensions/dm-subagents/src/runs/shared/parallel-handoff.js +653 -0
- package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +29 -12
- package/extensions/dm-subagents/src/runs/shared/permissions.js +108 -0
- package/extensions/dm-subagents/src/runs/shared/process-signal.js +13 -0
- package/extensions/dm-subagents/src/runs/shared/run-fanout-budget.js +257 -0
- package/extensions/dm-subagents/src/runs/shared/run-history.js +133 -13
- package/extensions/dm-subagents/src/runs/shared/runtime-acknowledged-extensions.js +62 -0
- package/extensions/dm-subagents/src/runs/shared/session-lease.js +225 -0
- package/extensions/dm-subagents/src/runs/shared/single-output.js +129 -27
- package/extensions/dm-subagents/src/runs/shared/spawn-budget.js +95 -0
- package/extensions/dm-subagents/src/runs/shared/structured-output.js +129 -10
- package/extensions/dm-subagents/src/runs/shared/subagent-control.js +66 -11
- package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +548 -70
- package/extensions/dm-subagents/src/runs/shared/subagent-startup-retry.js +50 -0
- package/extensions/dm-subagents/src/runs/shared/task-intent.js +130 -0
- package/extensions/dm-subagents/src/runs/shared/tool-availability.js +59 -0
- package/extensions/dm-subagents/src/runs/shared/tool-budget.js +7 -5
- package/extensions/dm-subagents/src/runs/shared/tool-timeout.js +64 -0
- package/extensions/dm-subagents/src/runs/shared/usage-budget.js +74 -0
- package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +22 -0
- package/extensions/dm-subagents/src/runs/shared/worktree-cleanup-plan.js +721 -0
- package/extensions/dm-subagents/src/runs/shared/worktree.js +168 -19
- package/extensions/dm-subagents/src/shared/accessible-dir.js +35 -0
- package/extensions/dm-subagents/src/shared/agent-stream-options.js +3 -0
- package/extensions/dm-subagents/src/shared/artifacts.js +170 -11
- package/extensions/dm-subagents/src/shared/atomic-json.js +36 -38
- package/extensions/dm-subagents/src/shared/capacity-resilient-json.js +77 -0
- package/extensions/dm-subagents/src/shared/child-session-name.js +15 -0
- package/extensions/dm-subagents/src/shared/child-transcript.js +57 -2
- package/extensions/dm-subagents/src/shared/completion-owner.js +7 -0
- package/extensions/dm-subagents/src/shared/display-text.js +142 -0
- package/extensions/dm-subagents/src/shared/extension-context.js +17 -0
- package/extensions/dm-subagents/src/shared/file-coalescer.js +9 -0
- package/extensions/dm-subagents/src/shared/file-system-retry.js +56 -0
- package/extensions/dm-subagents/src/shared/fork-context.js +96 -33
- package/extensions/dm-subagents/src/shared/formatters.js +21 -7
- package/extensions/dm-subagents/src/shared/launch-contract.js +94 -0
- package/extensions/dm-subagents/src/shared/model-info.js +10 -5
- package/extensions/dm-subagents/src/shared/node-executable.js +19 -0
- package/extensions/dm-subagents/src/shared/prompt-resources.js +10 -0
- package/extensions/dm-subagents/src/shared/pruned-fork.js +427 -0
- package/extensions/dm-subagents/src/shared/session-file-trust.js +19 -0
- package/extensions/dm-subagents/src/shared/session-tokens.js +14 -3
- package/extensions/dm-subagents/src/shared/settings.js +39 -47
- package/extensions/dm-subagents/src/shared/shortcuts.js +16 -0
- package/extensions/dm-subagents/src/shared/status-format.js +9 -2
- package/extensions/dm-subagents/src/shared/thinking-ceiling.js +41 -0
- package/extensions/dm-subagents/src/shared/types.js +47 -7
- package/extensions/dm-subagents/src/shared/utf8.js +12 -0
- package/extensions/dm-subagents/src/shared/utils.js +151 -131
- package/extensions/dm-subagents/src/shared/watch-strategy.js +3 -0
- package/extensions/dm-subagents/src/shared/workflow-child-permit.js +84 -0
- package/extensions/dm-subagents/src/slash/delegation-adapters.js +274 -0
- package/extensions/dm-subagents/src/slash/delegation-json.js +113 -0
- package/extensions/dm-subagents/src/slash/delegation-request.js +152 -0
- package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +294 -243
- package/extensions/dm-subagents/src/slash/prompt-workflows.js +35 -73
- package/extensions/dm-subagents/src/slash/selector.js +101 -0
- package/extensions/dm-subagents/src/slash/slash-bridge.js +17 -1
- package/extensions/dm-subagents/src/slash/slash-commands.js +722 -732
- package/extensions/dm-subagents/src/slash/slash-live-state.js +37 -19
- package/extensions/dm-subagents/src/slash/subagents-admin.js +410 -0
- package/extensions/dm-subagents/src/tui/fleet-status.js +824 -0
- package/extensions/dm-subagents/src/tui/fleet-transcript.js +479 -0
- package/extensions/dm-subagents/src/tui/fleet.js +1326 -0
- package/extensions/dm-subagents/src/tui/render-helpers.js +22 -0
- package/extensions/dm-subagents/src/tui/render.js +1511 -261
- package/extensions/dm-subagents/src/watchdog/change-signature.js +220 -0
- package/extensions/dm-subagents/src/watchdog/child-status.js +151 -0
- package/extensions/dm-subagents/src/watchdog/emission-guard.js +90 -0
- package/extensions/dm-subagents/src/watchdog/lsp-diagnostics.js +484 -0
- package/extensions/dm-subagents/src/watchdog/model-selection.js +154 -0
- package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +138 -0
- package/extensions/dm-subagents/src/watchdog/register-child.js +112 -0
- package/extensions/dm-subagents/src/watchdog/register-main.js +419 -0
- package/extensions/dm-subagents/src/watchdog/render.js +54 -0
- package/extensions/dm-subagents/src/watchdog/review.js +251 -0
- package/extensions/dm-subagents/src/watchdog/runtime.js +803 -0
- package/extensions/dm-subagents/src/watchdog/scope.js +56 -0
- package/extensions/dm-subagents/src/watchdog/settings.js +515 -0
- package/extensions/dm-subagents/src/watchdog/tool-actions.js +151 -0
- package/extensions/dm-subagents/src/watchdog/turn-delta.js +169 -0
- package/extensions/dm-subagents/src/watchdog/types.js +29 -0
- package/extensions/dm-subagents/src/watchdog/warning-format.js +58 -0
- package/extensions/dm-subagents/src/workflows/chat-progress.js +116 -0
- package/extensions/dm-subagents/src/workflows/host-command.js +227 -0
- package/extensions/dm-subagents/src/workflows/scripted-workflow.js +2011 -0
- package/extensions/dm-subagents/src/workflows/workflow-child-summary.js +116 -0
- package/extensions/dm-subagents/src/workflows/workflow-preflight.js +243 -0
- package/extensions/dm-subagents/src/workflows/workflow-receipt.js +387 -0
- package/extensions/dm-subagents/src/workflows/workflow-settlement.js +189 -0
- package/package.json +4 -3
- package/extensions/dm-fff/package.json +0 -21
- package/extensions/dm-fff/src/index.js +0 -691
- package/extensions/dm-fff/src/query.js +0 -60
- package/extensions/dm-subagents/agents/context-builder.md +0 -46
- package/extensions/dm-subagents/agents/planner.md +0 -55
- package/extensions/dm-subagents/prompts/parallel-context-build.md +0 -55
- package/extensions/dm-subagents/prompts/parallel-handoff-plan.md +0 -61
- package/extensions/dm-subagents/src/runs/background/wait.js +0 -206
- package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +0 -1013
- package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +0 -981
- package/extensions/dm-subagents/src/runs/shared/turn-budget.js +0 -50
|
@@ -2,10 +2,17 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as os from "node:os";
|
|
4
4
|
import * as path from "node:path";
|
|
5
|
+
import { findConfiguredProjectRoot } from "../../agents/agents.js";
|
|
5
6
|
import { getAgentDir, getProjectConfigDir } from "../../shared/utils.js";
|
|
7
|
+
import { isMcpServerDefinition, loadAgentPluginMcpServers, loadPackageMcpServers } from "./mcp-config-sources.js";
|
|
8
|
+
import {
|
|
9
|
+
normalizeMcpDirectToolSelectors,
|
|
10
|
+
parseMcpDirectToolSelectors,
|
|
11
|
+
planMcpDirectToolGrant
|
|
12
|
+
} from "./mcp-direct-tool-grant.js";
|
|
13
|
+
export { formatUnresolvedMcpDirectToolSelectors } from "./mcp-direct-tool-grant.js";
|
|
6
14
|
const CACHE_VERSION = 1;
|
|
7
15
|
const CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
8
|
-
const BUILTIN_TOOL_NAMES = new Set(["read", "bash", "edit", "write", "grep", "find", "ls", "mcp"]);
|
|
9
16
|
const GENERIC_GLOBAL_CONFIG_PATH = path.join(os.homedir(), ".config", "mcp", "mcp.json");
|
|
10
17
|
const IMPORT_PATHS = {
|
|
11
18
|
cursor: [path.join(os.homedir(), ".cursor", "mcp.json")],
|
|
@@ -19,18 +26,41 @@ const IMPORT_PATHS = {
|
|
|
19
26
|
windsurf: [path.join(os.homedir(), ".windsurf", "mcp.json")],
|
|
20
27
|
vscode: [".vscode/mcp.json"]
|
|
21
28
|
};
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
export const MCP_RUNTIME_SNAPSHOT_EVENT = "dm-mcp-adapter:runtime-snapshot:v1";
|
|
30
|
+
export const MCP_RUNTIME_SNAPSHOT_VERSION = 1;
|
|
31
|
+
export function resolveMcpDirectToolResolution(mcpDirectTools, cwd = process.cwd(), runtimeSnapshotHost, configOverride) {
|
|
32
|
+
const selectors = normalizeMcpDirectToolSelectors(mcpDirectTools);
|
|
33
|
+
if (selectors.length === 0)
|
|
34
|
+
return { selections: [], unresolvedSelectors: [] };
|
|
35
|
+
const config = configOverride ?? loadMcpConfig(cwd);
|
|
36
|
+
const { servers: selectedServers, tools: selectedTools } = parseMcpDirectToolSelectors(selectors);
|
|
37
|
+
const runtimeSelectionServers = new Set([...selectedServers, ...selectedTools.keys()]);
|
|
38
|
+
const runtimeServers = resolveRuntimeMcpServers(config, runtimeSelectionServers, runtimeSnapshotHost);
|
|
39
|
+
const resolvedConfig = Object.keys(runtimeServers).length > 0 ? mergeConfigs(config, { mcpServers: runtimeServers }) : config;
|
|
40
|
+
validateSelectedServerDefinitions(resolvedConfig, selectors);
|
|
41
|
+
const cache = loadMetadataCache();
|
|
42
|
+
if (!cache)
|
|
43
|
+
return { selections: [], unresolvedSelectors: selectors };
|
|
44
|
+
const validMetadata = {};
|
|
45
|
+
for (const [serverName, definition] of Object.entries(resolvedConfig.mcpServers)) {
|
|
46
|
+
const serverCache = cache.servers[serverName];
|
|
47
|
+
if (isServerCacheValid(serverCache, definition))
|
|
48
|
+
validMetadata[serverName] = serverCache;
|
|
33
49
|
}
|
|
50
|
+
const grant = planMcpDirectToolGrant({
|
|
51
|
+
selectors,
|
|
52
|
+
servers: resolvedConfig.mcpServers,
|
|
53
|
+
metadata: validMetadata,
|
|
54
|
+
toolPrefix: resolvedConfig.settings?.toolPrefix
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
selections: grant.selections,
|
|
58
|
+
unresolvedSelectors: grant.unresolvedSelectors,
|
|
59
|
+
...Object.keys(runtimeServers).length > 0 ? { mcpConfig: resolvedConfig, runtimeServerNames: Object.keys(runtimeServers) } : {}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export function resolveMcpDirectToolSelections(mcpDirectTools, cwd = process.cwd(), runtimeSnapshotHost) {
|
|
63
|
+
return resolveMcpDirectToolResolution(mcpDirectTools, cwd, runtimeSnapshotHost).selections;
|
|
34
64
|
}
|
|
35
65
|
function loadMetadataCache() {
|
|
36
66
|
const cachePath = path.join(getAgentDir(), "mcp-cache.json");
|
|
@@ -40,28 +70,106 @@ function loadMetadataCache() {
|
|
|
40
70
|
} catch {
|
|
41
71
|
return null;
|
|
42
72
|
}
|
|
43
|
-
if (!parsed ||
|
|
44
|
-
return null;
|
|
45
|
-
const raw = parsed;
|
|
46
|
-
if (raw.version !== CACHE_VERSION || !raw.servers || typeof raw.servers !== "object" || Array.isArray(raw.servers)) {
|
|
73
|
+
if (!isRecord(parsed) || parsed.version !== CACHE_VERSION || !isRecord(parsed.servers))
|
|
47
74
|
return null;
|
|
75
|
+
const servers = {};
|
|
76
|
+
for (const [name, value] of Object.entries(parsed.servers)) {
|
|
77
|
+
const entry = parseServerCacheEntry(value);
|
|
78
|
+
if (entry)
|
|
79
|
+
servers[name] = entry;
|
|
80
|
+
}
|
|
81
|
+
return { version: CACHE_VERSION, servers };
|
|
82
|
+
}
|
|
83
|
+
function parseServerCacheEntry(value) {
|
|
84
|
+
if (!isRecord(value))
|
|
85
|
+
return;
|
|
86
|
+
if (value.configHash !== undefined && typeof value.configHash !== "string")
|
|
87
|
+
return;
|
|
88
|
+
if (value.cachedAt !== undefined && (typeof value.cachedAt !== "number" || !Number.isFinite(value.cachedAt)))
|
|
89
|
+
return;
|
|
90
|
+
if (value.tools !== undefined && !Array.isArray(value.tools))
|
|
91
|
+
return;
|
|
92
|
+
if (value.resources !== undefined && !Array.isArray(value.resources))
|
|
93
|
+
return;
|
|
94
|
+
const tools = value.tools?.map(parseCachedTool);
|
|
95
|
+
const resources = value.resources?.map(parseCachedResource);
|
|
96
|
+
if (tools && !tools.every((entry) => entry !== undefined))
|
|
97
|
+
return;
|
|
98
|
+
if (resources && !resources.every((entry) => entry !== undefined))
|
|
99
|
+
return;
|
|
100
|
+
return {
|
|
101
|
+
...value.configHash !== undefined ? { configHash: value.configHash } : {},
|
|
102
|
+
...value.cachedAt !== undefined ? { cachedAt: value.cachedAt } : {},
|
|
103
|
+
...tools ? { tools } : {},
|
|
104
|
+
...resources ? { resources } : {}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function parseCachedTool(value) {
|
|
108
|
+
if (!isRecord(value) || value.name !== undefined && typeof value.name !== "string")
|
|
109
|
+
return;
|
|
110
|
+
return value.name === undefined ? {} : { name: value.name };
|
|
111
|
+
}
|
|
112
|
+
function parseCachedResource(value) {
|
|
113
|
+
if (!isRecord(value))
|
|
114
|
+
return;
|
|
115
|
+
if (value.uri !== undefined && typeof value.uri !== "string")
|
|
116
|
+
return;
|
|
117
|
+
if (value.name !== undefined && typeof value.name !== "string")
|
|
118
|
+
return;
|
|
119
|
+
return {
|
|
120
|
+
...value.uri !== undefined ? { uri: value.uri } : {},
|
|
121
|
+
...value.name !== undefined ? { name: value.name } : {}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function resolveRuntimeMcpServers(config, selectedServers, runtimeSnapshotHost) {
|
|
125
|
+
if (!runtimeSnapshotHost)
|
|
126
|
+
return {};
|
|
127
|
+
const runtimeServers = {};
|
|
128
|
+
for (const serverName of selectedServers) {
|
|
129
|
+
if (Object.hasOwn(config.mcpServers, serverName))
|
|
130
|
+
continue;
|
|
131
|
+
try {
|
|
132
|
+
const snapshot = getRuntimeMcpServerSnapshot(runtimeSnapshotHost, serverName);
|
|
133
|
+
runtimeServers[serverName] = snapshot.definition;
|
|
134
|
+
} catch {}
|
|
48
135
|
}
|
|
49
|
-
return
|
|
136
|
+
return runtimeServers;
|
|
137
|
+
}
|
|
138
|
+
function getRuntimeMcpServerSnapshot(host, name) {
|
|
139
|
+
const request = {
|
|
140
|
+
version: MCP_RUNTIME_SNAPSHOT_VERSION,
|
|
141
|
+
name
|
|
142
|
+
};
|
|
143
|
+
host.events.emit(MCP_RUNTIME_SNAPSHOT_EVENT, request);
|
|
144
|
+
if (!request.result)
|
|
145
|
+
throw new Error("dm-mcp-adapter is not installed for this DM instance");
|
|
146
|
+
if (!request.result.ok)
|
|
147
|
+
throw request.result.error;
|
|
148
|
+
const snapshot = request.result.snapshot;
|
|
149
|
+
if (!snapshot || snapshot.name !== name || snapshot.runtime !== true || snapshot.persisted !== false || !isMcpServerDefinition(snapshot.definition)) {
|
|
150
|
+
throw new Error(`Invalid MCP runtime snapshot for server "${name}"`);
|
|
151
|
+
}
|
|
152
|
+
return snapshot;
|
|
50
153
|
}
|
|
51
154
|
function loadMcpConfig(cwd) {
|
|
155
|
+
const resolvedCwd = path.resolve(cwd);
|
|
156
|
+
const projectRoot = findConfiguredProjectRoot(resolvedCwd) ?? resolvedCwd;
|
|
52
157
|
let config = { mcpServers: {} };
|
|
53
|
-
for (const sourcePath of getConfigPaths(
|
|
158
|
+
for (const sourcePath of getConfigPaths(projectRoot)) {
|
|
54
159
|
const loaded = readConfig(sourcePath);
|
|
55
160
|
if (!loaded)
|
|
56
161
|
continue;
|
|
57
|
-
config = mergeConfigs(config, expandImports(loaded,
|
|
162
|
+
config = mergeConfigs(config, expandImports(loaded, projectRoot));
|
|
58
163
|
}
|
|
59
|
-
|
|
164
|
+
const packageServers = loadPackageMcpServers(projectRoot);
|
|
165
|
+
const pluginServers = loadAgentPluginMcpServers(config.settings?.agentPluginPaths, projectRoot);
|
|
166
|
+
const packageOnlyServers = Object.fromEntries(Object.entries(packageServers).filter(([name]) => !Object.hasOwn(pluginServers, name)));
|
|
167
|
+
return mergeConfigs({ mcpServers: packageOnlyServers }, mergeConfigs({ mcpServers: pluginServers }, config));
|
|
60
168
|
}
|
|
61
|
-
function getConfigPaths(
|
|
169
|
+
function getConfigPaths(projectRoot) {
|
|
62
170
|
const piGlobalPath = path.join(getAgentDir(), "mcp.json");
|
|
63
|
-
const projectPath = path.resolve(
|
|
64
|
-
const projectPiPath = path.resolve(getProjectConfigDir(
|
|
171
|
+
const projectPath = path.resolve(projectRoot, ".mcp.json");
|
|
172
|
+
const projectPiPath = path.resolve(getProjectConfigDir(projectRoot), "mcp.json");
|
|
65
173
|
const sources = [];
|
|
66
174
|
if (GENERIC_GLOBAL_CONFIG_PATH !== piGlobalPath)
|
|
67
175
|
sources.push(GENERIC_GLOBAL_CONFIG_PATH);
|
|
@@ -82,15 +190,32 @@ function readConfig(configPath) {
|
|
|
82
190
|
return validateConfig(parsed);
|
|
83
191
|
}
|
|
84
192
|
function validateConfig(raw) {
|
|
85
|
-
if (!
|
|
193
|
+
if (!isRecord(raw))
|
|
86
194
|
return { mcpServers: {} };
|
|
87
195
|
const obj = raw;
|
|
88
196
|
const servers = obj.mcpServers ?? obj["mcp-servers"] ?? {};
|
|
89
197
|
return {
|
|
90
|
-
mcpServers:
|
|
198
|
+
mcpServers: parseServerEntries(servers),
|
|
91
199
|
imports: Array.isArray(obj.imports) ? obj.imports.filter((value) => isImportKind(value)) : undefined,
|
|
92
|
-
settings:
|
|
200
|
+
settings: parseSettings(obj.settings)
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function parseServerEntries(value) {
|
|
204
|
+
if (!isRecord(value))
|
|
205
|
+
return {};
|
|
206
|
+
return Object.fromEntries(Object.entries(value).filter((entry) => isMcpServerDefinition(entry[1])));
|
|
207
|
+
}
|
|
208
|
+
function parseSettings(value) {
|
|
209
|
+
if (!isRecord(value))
|
|
210
|
+
return;
|
|
211
|
+
const toolPrefix = value.toolPrefix === "server" || value.toolPrefix === "short" || value.toolPrefix === "none" ? value.toolPrefix : undefined;
|
|
212
|
+
const directTools = typeof value.directTools === "boolean" ? value.directTools : undefined;
|
|
213
|
+
const settings = {
|
|
214
|
+
...toolPrefix ? { toolPrefix } : {},
|
|
215
|
+
...directTools !== undefined ? { directTools } : {},
|
|
216
|
+
...value.agentPluginPaths !== undefined ? { agentPluginPaths: value.agentPluginPaths } : {}
|
|
93
217
|
};
|
|
218
|
+
return Object.keys(settings).length ? settings : undefined;
|
|
94
219
|
}
|
|
95
220
|
function mergeConfigs(base, next) {
|
|
96
221
|
const imports = [...base.imports ?? [], ...next.imports ?? []];
|
|
@@ -134,74 +259,22 @@ function resolveImportPath(importKind, cwd) {
|
|
|
134
259
|
return null;
|
|
135
260
|
}
|
|
136
261
|
function extractServers(config, kind) {
|
|
137
|
-
if (!
|
|
262
|
+
if (!isRecord(config))
|
|
138
263
|
return {};
|
|
139
264
|
const obj = config;
|
|
140
265
|
const servers = kind === "cursor" || kind === "windsurf" || kind === "vscode" ? obj.mcpServers ?? obj["mcp-servers"] : obj.mcpServers;
|
|
141
|
-
return
|
|
266
|
+
return parseServerEntries(servers);
|
|
142
267
|
}
|
|
143
|
-
function
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (!toolFilter)
|
|
153
|
-
continue;
|
|
154
|
-
for (const tool of Array.isArray(serverCache.tools) ? serverCache.tools : []) {
|
|
155
|
-
if (typeof tool?.name !== "string" || !tool.name)
|
|
156
|
-
continue;
|
|
157
|
-
if (toolFilter !== true && !toolFilter.has(tool.name))
|
|
158
|
-
continue;
|
|
159
|
-
if (isToolExcluded(tool.name, serverName, prefix, definition.excludeTools))
|
|
160
|
-
continue;
|
|
161
|
-
const prefixedName = formatToolName(tool.name, serverName, prefix);
|
|
162
|
-
if (BUILTIN_TOOL_NAMES.has(prefixedName) || seenNames.has(prefixedName))
|
|
163
|
-
continue;
|
|
164
|
-
seenNames.add(prefixedName);
|
|
165
|
-
names.push(prefixedName);
|
|
166
|
-
}
|
|
167
|
-
if (definition.exposeResources === false)
|
|
168
|
-
continue;
|
|
169
|
-
for (const resource of Array.isArray(serverCache.resources) ? serverCache.resources : []) {
|
|
170
|
-
if (typeof resource?.name !== "string" || !resource.name || typeof resource.uri !== "string" || !resource.uri)
|
|
171
|
-
continue;
|
|
172
|
-
const baseName = `get_${resourceNameToToolName(resource.name)}`;
|
|
173
|
-
if (toolFilter !== true && !toolFilter.has(baseName))
|
|
174
|
-
continue;
|
|
175
|
-
if (isToolExcluded(baseName, serverName, prefix, definition.excludeTools))
|
|
176
|
-
continue;
|
|
177
|
-
const prefixedName = formatToolName(baseName, serverName, prefix);
|
|
178
|
-
if (BUILTIN_TOOL_NAMES.has(prefixedName) || seenNames.has(prefixedName))
|
|
179
|
-
continue;
|
|
180
|
-
seenNames.add(prefixedName);
|
|
181
|
-
names.push(prefixedName);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return names;
|
|
185
|
-
}
|
|
186
|
-
function parseSelections(selections) {
|
|
187
|
-
const servers = new Set;
|
|
188
|
-
const tools = new Map;
|
|
189
|
-
for (let item of selections) {
|
|
190
|
-
item = item.replace(/\/+$/, "");
|
|
191
|
-
if (item.includes("/")) {
|
|
192
|
-
const [server, tool] = item.split("/", 2);
|
|
193
|
-
if (server && tool) {
|
|
194
|
-
if (!tools.has(server))
|
|
195
|
-
tools.set(server, new Set);
|
|
196
|
-
tools.get(server).add(tool);
|
|
197
|
-
} else if (server) {
|
|
198
|
-
servers.add(server);
|
|
199
|
-
}
|
|
200
|
-
} else if (item) {
|
|
201
|
-
servers.add(item);
|
|
202
|
-
}
|
|
268
|
+
export function resolveMcpDirectToolNames(mcpDirectTools, cwd = process.cwd()) {
|
|
269
|
+
return resolveMcpDirectToolSelections(mcpDirectTools, cwd).map((selection) => selection.name);
|
|
270
|
+
}
|
|
271
|
+
function validateSelectedServerDefinitions(config, selectors) {
|
|
272
|
+
const { servers, tools } = parseMcpDirectToolSelectors(selectors);
|
|
273
|
+
for (const serverName of new Set([...servers, ...tools.keys()])) {
|
|
274
|
+
const definition = config.mcpServers[serverName];
|
|
275
|
+
if (definition)
|
|
276
|
+
computeMcpServerHash(definition);
|
|
203
277
|
}
|
|
204
|
-
return { servers, tools };
|
|
205
278
|
}
|
|
206
279
|
function isServerCacheValid(entry, definition) {
|
|
207
280
|
if (!entry || entry.configHash !== computeMcpServerHash(definition))
|
|
@@ -214,72 +287,74 @@ export function computeMcpServerHash(definition) {
|
|
|
214
287
|
const identity = {
|
|
215
288
|
command: definition.command,
|
|
216
289
|
args: definition.args,
|
|
290
|
+
socket: resolveConfigPath(definition.socket),
|
|
217
291
|
env: interpolateEnvRecord(definition.env),
|
|
218
292
|
cwd: resolveConfigPath(definition.cwd),
|
|
219
|
-
url: definition
|
|
293
|
+
url: resolveServerUrl(definition),
|
|
220
294
|
headers: interpolateEnvRecord(definition.headers),
|
|
295
|
+
requestHeadersCommand: definition.requestHeadersCommand ? {
|
|
296
|
+
command: interpolateEnvVars(definition.requestHeadersCommand.command),
|
|
297
|
+
args: definition.requestHeadersCommand.args?.map(interpolateEnvVars),
|
|
298
|
+
env: interpolateEnvRecord(definition.requestHeadersCommand.env),
|
|
299
|
+
timeoutMs: definition.requestHeadersCommand.timeoutMs
|
|
300
|
+
} : undefined,
|
|
221
301
|
auth: definition.auth,
|
|
222
302
|
bearerToken: resolveBearerToken(definition),
|
|
223
303
|
bearerTokenEnv: definition.bearerTokenEnv,
|
|
224
304
|
exposeResources: definition.exposeResources,
|
|
225
|
-
|
|
305
|
+
includeTools: definition.includeTools,
|
|
306
|
+
excludeTools: definition.excludeTools,
|
|
307
|
+
protocolVersion: definition.protocolVersion
|
|
226
308
|
};
|
|
227
309
|
return createHash("sha256").update(stableStringify(identity)).digest("hex");
|
|
228
310
|
}
|
|
229
|
-
function getToolPrefix(value) {
|
|
230
|
-
return value === "none" || value === "short" || value === "server" ? value : "server";
|
|
231
|
-
}
|
|
232
311
|
function isImportKind(value) {
|
|
233
312
|
return typeof value === "string" && Object.hasOwn(IMPORT_PATHS, value);
|
|
234
313
|
}
|
|
235
|
-
function
|
|
236
|
-
|
|
237
|
-
return "";
|
|
238
|
-
if (mode === "short") {
|
|
239
|
-
const short = serverName.replace(/-?mcp$/i, "").replace(/-/g, "_");
|
|
240
|
-
return short || "mcp";
|
|
241
|
-
}
|
|
242
|
-
return serverName.replace(/-/g, "_");
|
|
314
|
+
function isRecord(value) {
|
|
315
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
243
316
|
}
|
|
244
|
-
function
|
|
245
|
-
|
|
246
|
-
|
|
317
|
+
function interpolateEnvRecord(values) {
|
|
318
|
+
if (!values)
|
|
319
|
+
return;
|
|
320
|
+
return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, interpolateSecretExpression(value)]));
|
|
247
321
|
}
|
|
248
|
-
function
|
|
249
|
-
|
|
250
|
-
return false;
|
|
251
|
-
const candidates = new Set([
|
|
252
|
-
normalizeToolName(toolName),
|
|
253
|
-
normalizeToolName(formatToolName(toolName, serverName, prefix)),
|
|
254
|
-
normalizeToolName(formatToolName(toolName, serverName, "server")),
|
|
255
|
-
normalizeToolName(formatToolName(toolName, serverName, "short"))
|
|
256
|
-
]);
|
|
257
|
-
return excludeTools.some((excluded) => typeof excluded === "string" && candidates.has(normalizeToolName(excluded)));
|
|
258
|
-
}
|
|
259
|
-
function normalizeToolName(value) {
|
|
260
|
-
return value.replace(/-/g, "_");
|
|
261
|
-
}
|
|
262
|
-
function resourceNameToToolName(name) {
|
|
263
|
-
let result = name.replace(/[^a-zA-Z0-9]/g, "_").replace(/_+/g, "_").replace(/^_+/, "").replace(/_+$/, "").toLowerCase();
|
|
264
|
-
if (!result || /^\d/.test(result))
|
|
265
|
-
result = `resource${result ? `_${result}` : ""}`;
|
|
266
|
-
return result;
|
|
322
|
+
function interpolateEnvVars(value) {
|
|
323
|
+
return value.replace(/\$\{(\w+)\}/g, (_, name) => process.env[name] ?? "").replace(/\$env:(\w+)/g, (_, name) => process.env[name] ?? "").replace(/\{env:(\w+)\}/g, (_, name) => process.env[name] ?? "");
|
|
267
324
|
}
|
|
268
|
-
function
|
|
269
|
-
if (
|
|
325
|
+
function interpolateSecretExpression(value) {
|
|
326
|
+
if (value.startsWith("!!"))
|
|
327
|
+
return interpolateEnvVars(value.slice(1));
|
|
328
|
+
return value.startsWith("!") ? value : interpolateEnvVars(value);
|
|
329
|
+
}
|
|
330
|
+
function getMissingEnvVars(value) {
|
|
331
|
+
const missing = new Set;
|
|
332
|
+
for (const match of value.matchAll(/\$\{(\w+)\}|\$env:(\w+)|\{env:(\w+)\}/g)) {
|
|
333
|
+
const name = match[1] ?? match[2] ?? match[3];
|
|
334
|
+
if (name && process.env[name] === undefined)
|
|
335
|
+
missing.add(name);
|
|
336
|
+
}
|
|
337
|
+
return [...missing];
|
|
338
|
+
}
|
|
339
|
+
function resolveServerUrl(definition) {
|
|
340
|
+
if (definition.url == null)
|
|
270
341
|
return;
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
342
|
+
if (typeof definition.url !== "string")
|
|
343
|
+
throw new Error("MCP server URL must be a string");
|
|
344
|
+
const missing = getMissingEnvVars(definition.url);
|
|
345
|
+
if (missing.length > 0) {
|
|
346
|
+
throw new Error(`Missing environment variable${missing.length === 1 ? "" : "s"} in MCP server URL: ${missing.join(", ")}`);
|
|
347
|
+
}
|
|
348
|
+
const resolved = interpolateEnvVars(definition.url);
|
|
349
|
+
try {
|
|
350
|
+
new URL(resolved);
|
|
351
|
+
} catch (error) {
|
|
352
|
+
throw new Error(`Invalid MCP server URL after environment interpolation: ${resolved}`, { cause: error });
|
|
275
353
|
}
|
|
276
354
|
return resolved;
|
|
277
355
|
}
|
|
278
|
-
function interpolateEnvVars(value) {
|
|
279
|
-
return value.replace(/\$\{(\w+)\}/g, (_, name) => process.env[name] ?? "").replace(/\$env:(\w+)/g, (_, name) => process.env[name] ?? "");
|
|
280
|
-
}
|
|
281
356
|
function resolveConfigPath(value) {
|
|
282
|
-
if (
|
|
357
|
+
if (value === undefined)
|
|
283
358
|
return;
|
|
284
359
|
const resolved = interpolateEnvVars(value);
|
|
285
360
|
if (resolved === "~")
|
|
@@ -289,9 +364,9 @@ function resolveConfigPath(value) {
|
|
|
289
364
|
return resolved;
|
|
290
365
|
}
|
|
291
366
|
function resolveBearerToken(definition) {
|
|
292
|
-
if (
|
|
293
|
-
return
|
|
294
|
-
return
|
|
367
|
+
if (definition.bearerToken !== undefined)
|
|
368
|
+
return interpolateSecretExpression(definition.bearerToken);
|
|
369
|
+
return definition.bearerTokenEnv ? process.env[definition.bearerTokenEnv] : undefined;
|
|
295
370
|
}
|
|
296
371
|
function stableStringify(value) {
|
|
297
372
|
if (value === null || value === undefined || typeof value !== "object") {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const BUILTIN_TOOL_NAMES = new Set(["read", "bash", "edit", "write", "grep", "find", "ls", "mcp"]);
|
|
2
|
+
export function normalizeMcpDirectToolSelectors(selectors) {
|
|
3
|
+
return [...new Set((selectors ?? []).map((selector) => selector.replace(/\/+$/, "")).filter(Boolean))];
|
|
4
|
+
}
|
|
5
|
+
export function parseMcpDirectToolSelectors(selectors) {
|
|
6
|
+
const servers = new Set;
|
|
7
|
+
const tools = new Map;
|
|
8
|
+
for (const item of selectors) {
|
|
9
|
+
if (item.includes("/")) {
|
|
10
|
+
const [server, tool] = item.split("/", 2);
|
|
11
|
+
if (server && tool) {
|
|
12
|
+
if (!tools.has(server))
|
|
13
|
+
tools.set(server, new Set);
|
|
14
|
+
tools.get(server).add(tool);
|
|
15
|
+
} else if (server) {
|
|
16
|
+
servers.add(server);
|
|
17
|
+
}
|
|
18
|
+
} else if (item) {
|
|
19
|
+
servers.add(item);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return { servers, tools };
|
|
23
|
+
}
|
|
24
|
+
export function planMcpDirectToolGrant(input) {
|
|
25
|
+
const selectors = normalizeMcpDirectToolSelectors(input.selectors);
|
|
26
|
+
if (selectors.length === 0)
|
|
27
|
+
return { selections: [], unresolvedSelectors: [] };
|
|
28
|
+
const { servers: selectedServers, tools: selectedTools } = parseMcpDirectToolSelectors(selectors);
|
|
29
|
+
const selections = [];
|
|
30
|
+
const seenNames = new Set;
|
|
31
|
+
const prefix = normalizeMcpToolPrefix(input.toolPrefix);
|
|
32
|
+
for (const [serverName, server] of Object.entries(input.servers)) {
|
|
33
|
+
const metadata = input.metadata[serverName];
|
|
34
|
+
if (!metadata)
|
|
35
|
+
continue;
|
|
36
|
+
const toolFilter = selectedServers.has(serverName) ? true : selectedTools.get(serverName);
|
|
37
|
+
if (!toolFilter)
|
|
38
|
+
continue;
|
|
39
|
+
for (const tool of Array.isArray(metadata.tools) ? metadata.tools : []) {
|
|
40
|
+
if (typeof tool?.name !== "string" || !tool.name)
|
|
41
|
+
continue;
|
|
42
|
+
if (toolFilter !== true && !toolFilter.has(tool.name))
|
|
43
|
+
continue;
|
|
44
|
+
if (!isToolAllowed(tool.name, serverName, prefix, server.includeTools, server.excludeTools))
|
|
45
|
+
continue;
|
|
46
|
+
const name = formatToolName(tool.name, serverName, prefix);
|
|
47
|
+
if (BUILTIN_TOOL_NAMES.has(name) || seenNames.has(name))
|
|
48
|
+
continue;
|
|
49
|
+
seenNames.add(name);
|
|
50
|
+
selections.push({ name, selector: `${serverName}/${tool.name}` });
|
|
51
|
+
}
|
|
52
|
+
if (server.exposeResources === false)
|
|
53
|
+
continue;
|
|
54
|
+
for (const resource of Array.isArray(metadata.resources) ? metadata.resources : []) {
|
|
55
|
+
if (typeof resource?.name !== "string" || !resource.name || typeof resource.uri !== "string" || !resource.uri)
|
|
56
|
+
continue;
|
|
57
|
+
const baseName = `get_${resourceNameToToolName(resource.name)}`;
|
|
58
|
+
if (toolFilter !== true && !toolFilter.has(baseName))
|
|
59
|
+
continue;
|
|
60
|
+
if (!isToolAllowed(baseName, serverName, prefix, server.includeTools, server.excludeTools))
|
|
61
|
+
continue;
|
|
62
|
+
const name = formatToolName(baseName, serverName, prefix);
|
|
63
|
+
if (BUILTIN_TOOL_NAMES.has(name) || seenNames.has(name))
|
|
64
|
+
continue;
|
|
65
|
+
seenNames.add(name);
|
|
66
|
+
selections.push({ name, selector: `${serverName}/${baseName}` });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const unresolvedSelectors = selectors.filter((selector) => selector.includes("/") ? !selections.some((selection) => selection.selector === selector) : !selections.some((selection) => selection.selector.startsWith(`${selector}/`)));
|
|
70
|
+
return { selections, unresolvedSelectors };
|
|
71
|
+
}
|
|
72
|
+
export function normalizeMcpToolPrefix(value) {
|
|
73
|
+
return value === "none" || value === "short" || value === "server" ? value : "server";
|
|
74
|
+
}
|
|
75
|
+
export function formatUnresolvedMcpDirectToolSelectors(selectors) {
|
|
76
|
+
return `Unresolved MCP direct-tool selectors: ${selectors.join(", ")}. Direct MCP tools require a matching configured server and fresh metadata cache; runtime-registered servers require a host/dm-mcp-adapter handoff before child launch.`;
|
|
77
|
+
}
|
|
78
|
+
function getServerPrefix(serverName, mode) {
|
|
79
|
+
if (mode === "none")
|
|
80
|
+
return "";
|
|
81
|
+
if (mode === "short")
|
|
82
|
+
return serverName.replace(/-?mcp$/i, "") || "mcp";
|
|
83
|
+
return serverName;
|
|
84
|
+
}
|
|
85
|
+
function formatToolName(toolName, serverName, prefix) {
|
|
86
|
+
const serverPrefix = getServerPrefix(serverName, prefix);
|
|
87
|
+
return serverPrefix ? `${serverPrefix}_${toolName}` : toolName;
|
|
88
|
+
}
|
|
89
|
+
function isToolAllowed(toolName, serverName, prefix, includeTools, excludeTools) {
|
|
90
|
+
const candidates = toolNameCandidates(toolName, serverName, prefix);
|
|
91
|
+
return (!Array.isArray(includeTools) || includeTools.length === 0 || matchesToolPatterns(candidates, includeTools)) && !matchesToolPatterns(candidates, excludeTools);
|
|
92
|
+
}
|
|
93
|
+
function toolNameCandidates(toolName, serverName, prefix) {
|
|
94
|
+
return new Set([
|
|
95
|
+
toolName,
|
|
96
|
+
`mcp_${toolName}`,
|
|
97
|
+
formatToolName(toolName, serverName, prefix),
|
|
98
|
+
formatToolName(toolName, serverName, "server"),
|
|
99
|
+
formatToolName(toolName, serverName, "short"),
|
|
100
|
+
formatToolName(toolName, serverName, "none")
|
|
101
|
+
]);
|
|
102
|
+
}
|
|
103
|
+
function matchesToolPatterns(candidates, patterns) {
|
|
104
|
+
if (!Array.isArray(patterns) || patterns.length === 0)
|
|
105
|
+
return false;
|
|
106
|
+
for (const pattern of patterns) {
|
|
107
|
+
if (typeof pattern !== "string")
|
|
108
|
+
continue;
|
|
109
|
+
const normalizedPattern = normalizeToolName(pattern);
|
|
110
|
+
const matcher = normalizedPattern.includes("*") || normalizedPattern.includes("?") ? globToRegExp(normalizedPattern) : undefined;
|
|
111
|
+
for (const candidate of candidates) {
|
|
112
|
+
const normalizedCandidate = normalizeToolName(candidate);
|
|
113
|
+
if (matcher ? matcher.test(normalizedCandidate) : normalizedCandidate === normalizedPattern)
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
function globToRegExp(pattern) {
|
|
120
|
+
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
121
|
+
return new RegExp(`^${escaped}$`);
|
|
122
|
+
}
|
|
123
|
+
function normalizeToolName(value) {
|
|
124
|
+
return value.replace(/-/g, "_");
|
|
125
|
+
}
|
|
126
|
+
function resourceNameToToolName(name) {
|
|
127
|
+
let result = name.replace(/[^a-zA-Z0-9]/g, "_").replace(/_+/g, "_").replace(/^_+/, "").replace(/_+$/, "").toLowerCase();
|
|
128
|
+
if (!result || /^\d/.test(result))
|
|
129
|
+
result = `resource${result ? `_${result}` : ""}`;
|
|
130
|
+
return result;
|
|
131
|
+
}
|