@machina.ai/cell-cli-core 1.20.2-rc1 → 1.22.5-rc1
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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/agents/delegate-to-agent-tool.d.ts +19 -0
- package/dist/src/agents/delegate-to-agent-tool.js +111 -0
- package/dist/src/agents/delegate-to-agent-tool.js.map +1 -0
- package/dist/src/agents/delegate-to-agent-tool.test.d.ts +6 -0
- package/dist/src/agents/delegate-to-agent-tool.test.js +133 -0
- package/dist/src/agents/delegate-to-agent-tool.test.js.map +1 -0
- package/dist/src/agents/executor.js +1 -1
- package/dist/src/agents/executor.js.map +1 -1
- package/dist/src/agents/executor.test.js.map +1 -1
- package/dist/src/agents/registry.d.ts +15 -0
- package/dist/src/agents/registry.js +58 -2
- package/dist/src/agents/registry.js.map +1 -1
- package/dist/src/agents/registry.test.js +61 -0
- package/dist/src/agents/registry.test.js.map +1 -1
- package/dist/src/availability/errorClassification.d.ts +7 -0
- package/dist/src/availability/errorClassification.js +20 -0
- package/dist/src/availability/errorClassification.js.map +1 -0
- package/dist/src/availability/modelAvailabilityService.d.ts +1 -0
- package/dist/src/availability/modelAvailabilityService.js +3 -0
- package/dist/src/availability/modelAvailabilityService.js.map +1 -1
- package/dist/src/availability/modelPolicy.d.ts +8 -1
- package/dist/src/availability/policyCatalog.d.ts +1 -0
- package/dist/src/availability/policyCatalog.js +6 -7
- package/dist/src/availability/policyCatalog.js.map +1 -1
- package/dist/src/availability/policyCatalog.test.js +2 -2
- package/dist/src/availability/policyCatalog.test.js.map +1 -1
- package/dist/src/availability/policyHelpers.d.ts +33 -3
- package/dist/src/availability/policyHelpers.js +113 -13
- package/dist/src/availability/policyHelpers.js.map +1 -1
- package/dist/src/availability/policyHelpers.test.js +133 -13
- package/dist/src/availability/policyHelpers.test.js.map +1 -1
- package/dist/src/availability/testUtils.d.ts +10 -0
- package/dist/src/availability/testUtils.js +22 -0
- package/dist/src/availability/testUtils.js.map +1 -0
- package/dist/src/code_assist/experiments/client_metadata.js +2 -1
- package/dist/src/code_assist/experiments/client_metadata.js.map +1 -1
- package/dist/src/code_assist/experiments/client_metadata.test.js +7 -10
- package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -1
- package/dist/src/code_assist/oauth2.d.ts +2 -0
- package/dist/src/code_assist/oauth2.js +38 -12
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +113 -6
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/commands/init.d.ts +7 -0
- package/dist/src/commands/init.js +53 -0
- package/dist/src/commands/init.js.map +1 -0
- package/dist/src/commands/init.test.d.ts +6 -0
- package/dist/src/commands/init.test.js +25 -0
- package/dist/src/commands/init.test.js.map +1 -0
- package/dist/src/commands/restore.d.ts +9 -0
- package/dist/src/commands/restore.js +46 -0
- package/dist/src/commands/restore.js.map +1 -0
- package/dist/src/commands/restore.test.d.ts +6 -0
- package/dist/src/commands/restore.test.js +137 -0
- package/dist/src/commands/restore.test.js.map +1 -0
- package/dist/src/commands/types.d.ts +41 -0
- package/dist/src/commands/types.js +7 -0
- package/dist/src/commands/types.js.map +1 -0
- package/dist/src/config/config.d.ts +29 -3
- package/dist/src/config/config.js +146 -29
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +203 -9
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/defaultModelConfigs.js +21 -0
- package/dist/src/config/defaultModelConfigs.js.map +1 -1
- package/dist/src/config/models.d.ts +33 -11
- package/dist/src/config/models.js +82 -24
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/models.test.js +70 -76
- package/dist/src/config/models.test.js.map +1 -1
- package/dist/src/confirmation-bus/message-bus.js +1 -0
- package/dist/src/confirmation-bus/message-bus.js.map +1 -1
- package/dist/src/confirmation-bus/types.d.ts +4 -0
- package/dist/src/core/baseLlmClient.d.ts +3 -1
- package/dist/src/core/baseLlmClient.js +40 -3
- package/dist/src/core/baseLlmClient.js.map +1 -1
- package/dist/src/core/baseLlmClient.test.js +184 -7
- package/dist/src/core/baseLlmClient.test.js.map +1 -1
- package/dist/src/core/client.js +47 -13
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +133 -6
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.js +5 -3
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +29 -22
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +1 -1
- package/dist/src/core/coreToolScheduler.js +76 -34
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +135 -37
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.js +60 -29
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +236 -188
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/geminiChat_network_retry.test.d.ts +6 -0
- package/dist/src/core/geminiChat_network_retry.test.js +198 -0
- package/dist/src/core/geminiChat_network_retry.test.js.map +1 -0
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +4 -5
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.js +13 -11
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +19 -8
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/sessionHookTriggers.d.ts +28 -0
- package/dist/src/core/sessionHookTriggers.js +68 -0
- package/dist/src/core/sessionHookTriggers.js.map +1 -0
- package/dist/src/core/turn.d.ts +1 -0
- package/dist/src/core/turn.js +1 -1
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/fallback/handler.js +56 -115
- package/dist/src/fallback/handler.js.map +1 -1
- package/dist/src/fallback/handler.test.js +124 -278
- package/dist/src/fallback/handler.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/hooks/hookEventHandler.js +59 -1
- package/dist/src/hooks/hookEventHandler.js.map +1 -1
- package/dist/src/hooks/hookEventHandler.test.js +8 -1
- package/dist/src/hooks/hookEventHandler.test.js.map +1 -1
- package/dist/src/hooks/hookRegistry.d.ts +0 -7
- package/dist/src/hooks/hookRegistry.js +8 -21
- package/dist/src/hooks/hookRegistry.js.map +1 -1
- package/dist/src/hooks/hookRegistry.test.js +2 -7
- package/dist/src/hooks/hookRegistry.test.js.map +1 -1
- package/dist/src/hooks/hookRunner.js +12 -2
- package/dist/src/hooks/hookRunner.js.map +1 -1
- package/dist/src/hooks/hookRunner.test.js +1 -1
- package/dist/src/hooks/hookRunner.test.js.map +1 -1
- package/dist/src/hooks/hookSystem.d.ts +0 -8
- package/dist/src/hooks/hookSystem.js +0 -18
- package/dist/src/hooks/hookSystem.js.map +1 -1
- package/dist/src/hooks/hookSystem.test.js +123 -18
- package/dist/src/hooks/hookSystem.test.js.map +1 -1
- package/dist/src/hooks/index.d.ts +3 -1
- package/dist/src/hooks/index.js +3 -0
- package/dist/src/hooks/index.js.map +1 -1
- package/dist/src/hooks/types.d.ts +1 -2
- package/dist/src/hooks/types.js +0 -1
- package/dist/src/hooks/types.js.map +1 -1
- package/dist/src/ide/detect-ide.test.js +32 -1
- package/dist/src/ide/detect-ide.test.js.map +1 -1
- package/dist/src/ide/ide-client.js +2 -0
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +1 -1
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +8 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/output/json-formatter.d.ts +2 -2
- package/dist/src/output/json-formatter.js +6 -3
- package/dist/src/output/json-formatter.js.map +1 -1
- package/dist/src/output/json-formatter.test.js +37 -9
- package/dist/src/output/json-formatter.test.js.map +1 -1
- package/dist/src/output/stream-json-formatter.js +6 -0
- package/dist/src/output/stream-json-formatter.js.map +1 -1
- package/dist/src/output/stream-json-formatter.test.js +98 -100
- package/dist/src/output/stream-json-formatter.test.js.map +1 -1
- package/dist/src/output/types.d.ts +3 -0
- package/dist/src/output/types.js.map +1 -1
- package/dist/src/policy/config.js +97 -11
- package/dist/src/policy/config.js.map +1 -1
- package/dist/src/policy/persistence.test.d.ts +6 -0
- package/dist/src/policy/persistence.test.js +154 -0
- package/dist/src/policy/persistence.test.js.map +1 -0
- package/dist/src/policy/policies/agent.toml +31 -0
- package/dist/src/policy/policy-engine.d.ts +10 -1
- package/dist/src/policy/policy-engine.js +79 -5
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/policy-engine.test.js +26 -2
- package/dist/src/policy/policy-engine.test.js.map +1 -1
- package/dist/src/policy/policy-updater.test.d.ts +6 -0
- package/dist/src/policy/policy-updater.test.js +116 -0
- package/dist/src/policy/policy-updater.test.js.map +1 -0
- package/dist/src/policy/shell-safety.test.d.ts +6 -0
- package/dist/src/policy/shell-safety.test.js +75 -0
- package/dist/src/policy/shell-safety.test.js.map +1 -0
- package/dist/src/policy/toml-loader.d.ts +11 -5
- package/dist/src/policy/toml-loader.js +38 -23
- package/dist/src/policy/toml-loader.js.map +1 -1
- package/dist/src/policy/toml-loader.test.js +28 -7
- package/dist/src/policy/toml-loader.test.js.map +1 -1
- package/dist/src/policy/types.d.ts +15 -0
- package/dist/src/resources/resource-registry.d.ts +30 -0
- package/dist/src/resources/resource-registry.js +57 -0
- package/dist/src/resources/resource-registry.js.map +1 -0
- package/dist/src/resources/resource-registry.test.d.ts +6 -0
- package/dist/src/resources/resource-registry.test.js +54 -0
- package/dist/src/resources/resource-registry.test.js.map +1 -0
- package/dist/src/routing/modelRouterService.js +0 -15
- package/dist/src/routing/modelRouterService.js.map +1 -1
- package/dist/src/routing/modelRouterService.test.js +0 -62
- package/dist/src/routing/modelRouterService.test.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.js +10 -21
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.test.js +2 -1
- package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.js +23 -12
- package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.test.js +69 -39
- package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -1
- package/dist/src/routing/strategies/overrideStrategy.js +4 -3
- package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
- package/dist/src/safety/checker-runner.js +17 -6
- package/dist/src/safety/checker-runner.js.map +1 -1
- package/dist/src/services/chatCompressionService.js +15 -1
- package/dist/src/services/chatCompressionService.js.map +1 -1
- package/dist/src/services/chatCompressionService.test.js +2 -0
- package/dist/src/services/chatCompressionService.test.js.map +1 -1
- package/dist/src/services/chatRecordingService.d.ts +14 -0
- package/dist/src/services/chatRecordingService.js +37 -0
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/fileSystemService.d.ts +0 -9
- package/dist/src/services/fileSystemService.js +0 -11
- package/dist/src/services/fileSystemService.js.map +1 -1
- package/dist/src/services/gitService.js +5 -0
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +28 -0
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.js +2 -2
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/modelConfig.golden.test.js +32 -0
- package/dist/src/services/modelConfig.golden.test.js.map +1 -1
- package/dist/src/services/modelConfigService.d.ts +3 -0
- package/dist/src/services/modelConfigService.js +3 -2
- package/dist/src/services/modelConfigService.js.map +1 -1
- package/dist/src/services/modelConfigService.test.js +110 -0
- package/dist/src/services/modelConfigService.test.js.map +1 -1
- package/dist/src/services/modelConfigServiceTestUtils.d.ts +10 -0
- package/dist/src/services/modelConfigServiceTestUtils.js +17 -0
- package/dist/src/services/modelConfigServiceTestUtils.js.map +1 -0
- package/dist/src/services/sessionSummaryService.d.ts +28 -0
- package/dist/src/services/sessionSummaryService.js +131 -0
- package/dist/src/services/sessionSummaryService.js.map +1 -0
- package/dist/src/services/sessionSummaryService.test.d.ts +6 -0
- package/dist/src/services/sessionSummaryService.test.js +785 -0
- package/dist/src/services/sessionSummaryService.test.js.map +1 -0
- package/dist/src/services/sessionSummaryUtils.d.ts +16 -0
- package/dist/src/services/sessionSummaryUtils.js +129 -0
- package/dist/src/services/sessionSummaryUtils.js.map +1 -0
- package/dist/src/services/sessionSummaryUtils.test.d.ts +6 -0
- package/dist/src/services/sessionSummaryUtils.test.js +137 -0
- package/dist/src/services/sessionSummaryUtils.test.js.map +1 -0
- package/dist/src/services/shellExecutionService.js +28 -22
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +46 -4
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/services/test-data/resolved-aliases-retry.golden.json +238 -0
- package/dist/src/services/test-data/resolved-aliases.golden.json +16 -0
- package/dist/src/telemetry/activity-detector.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +28 -5
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +67 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +1 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +3 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/config.js +2 -0
- package/dist/src/telemetry/config.js.map +1 -1
- package/dist/src/telemetry/config.test.js +25 -0
- package/dist/src/telemetry/config.test.js.map +1 -1
- package/dist/src/telemetry/gcp-exporters.d.ts +4 -3
- package/dist/src/telemetry/gcp-exporters.js +8 -4
- package/dist/src/telemetry/gcp-exporters.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +1 -1
- package/dist/src/telemetry/index.js +1 -1
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +2 -1
- package/dist/src/telemetry/loggers.js +345 -335
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +20 -5
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/sdk.d.ts +9 -2
- package/dist/src/telemetry/sdk.js +143 -17
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/sdk.test.js +130 -28
- package/dist/src/telemetry/sdk.test.js.map +1 -1
- package/dist/src/telemetry/startupProfiler.js +26 -3
- package/dist/src/telemetry/startupProfiler.js.map +1 -1
- package/dist/src/telemetry/startupProfiler.test.js +49 -7
- package/dist/src/telemetry/startupProfiler.test.js.map +1 -1
- package/dist/src/telemetry/telemetry.test.js +10 -3
- package/dist/src/telemetry/telemetry.test.js.map +1 -1
- package/dist/src/telemetry/trace.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +31 -6
- package/dist/src/telemetry/types.js +47 -8
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +1 -0
- package/dist/src/telemetry/uiTelemetry.js +2 -0
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +4 -0
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/test-utils/mock-message-bus.js.map +1 -1
- package/dist/src/tools/confirmation-policy.test.d.ts +6 -0
- package/dist/src/tools/confirmation-policy.test.js +152 -0
- package/dist/src/tools/confirmation-policy.test.js.map +1 -0
- package/dist/src/tools/edit.js +5 -0
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.d.ts +2 -1
- package/dist/src/tools/mcp-client-manager.js +20 -4
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +13 -10
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +39 -3
- package/dist/src/tools/mcp-client.js +433 -168
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +648 -28
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.js +13 -0
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +25 -0
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/memoryTool.js +1 -0
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +22 -13
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/read-file.js +1 -1
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.js +6 -4
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +1 -1
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +2 -1
- package/dist/src/tools/shell.js +15 -1
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +2 -1
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.js +5 -0
- package/dist/src/tools/smart-edit.js.map +1 -1
- package/dist/src/tools/smart-edit.test.js.map +1 -1
- package/dist/src/tools/tool-names.d.ts +2 -0
- package/dist/src/tools/tool-names.js +2 -0
- package/dist/src/tools/tool-names.js.map +1 -1
- package/dist/src/tools/tools.d.ts +19 -0
- package/dist/src/tools/tools.js +29 -8
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.js +17 -4
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +1 -0
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/write-file.js +5 -0
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.d.ts +8 -0
- package/dist/src/utils/bfsFileSearch.js +63 -23
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.test.js +65 -1
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
- package/dist/src/utils/checkpointUtils.d.ts +82 -0
- package/dist/src/utils/checkpointUtils.js +117 -0
- package/dist/src/utils/checkpointUtils.js.map +1 -0
- package/dist/src/utils/checkpointUtils.test.d.ts +6 -0
- package/dist/src/utils/checkpointUtils.test.js +229 -0
- package/dist/src/utils/checkpointUtils.test.js.map +1 -0
- package/dist/src/utils/debugLogger.d.ts +3 -0
- package/dist/src/utils/debugLogger.js +27 -0
- package/dist/src/utils/debugLogger.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +4 -0
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.d.ts +9 -1
- package/dist/src/utils/editor.js +23 -14
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/errors.d.ts +8 -0
- package/dist/src/utils/errors.js +39 -2
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/errors.test.d.ts +6 -0
- package/dist/src/utils/errors.test.js +155 -0
- package/dist/src/utils/errors.test.js.map +1 -0
- package/dist/src/utils/extensionLoader.d.ts +2 -2
- package/dist/src/utils/extensionLoader.js +5 -6
- package/dist/src/utils/extensionLoader.js.map +1 -1
- package/dist/src/utils/extensionLoader.test.js +11 -0
- package/dist/src/utils/extensionLoader.test.js.map +1 -1
- package/dist/src/utils/fetch.d.ts +1 -1
- package/dist/src/utils/fetch.js +3 -3
- package/dist/src/utils/fetch.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +15 -0
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/filesearch/crawlCache.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
- package/dist/src/utils/flashFallback.test.js +1 -1
- package/dist/src/utils/flashFallback.test.js.map +1 -1
- package/dist/src/utils/googleErrors.js +31 -18
- package/dist/src/utils/googleErrors.js.map +1 -1
- package/dist/src/utils/googleErrors.test.js +10 -2
- package/dist/src/utils/googleErrors.test.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.d.ts +3 -3
- package/dist/src/utils/googleQuotaErrors.js +32 -6
- package/dist/src/utils/googleQuotaErrors.js.map +1 -1
- package/dist/src/utils/googleQuotaErrors.test.js +94 -2
- package/dist/src/utils/googleQuotaErrors.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +4 -0
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/pathCorrector.js +12 -2
- package/dist/src/utils/pathCorrector.js.map +1 -1
- package/dist/src/utils/pathCorrector.test.js +6 -2
- package/dist/src/utils/pathCorrector.test.js.map +1 -1
- package/dist/src/utils/retry.d.ts +11 -0
- package/dist/src/utils/retry.js +54 -13
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js +170 -10
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/shell-permissions.d.ts +52 -0
- package/dist/src/utils/shell-permissions.js +188 -0
- package/dist/src/utils/shell-permissions.js.map +1 -0
- package/dist/src/utils/shell-permissions.test.d.ts +6 -0
- package/dist/src/utils/shell-permissions.test.js +347 -0
- package/dist/src/utils/shell-permissions.test.js.map +1 -0
- package/dist/src/utils/shell-utils.d.ts +10 -47
- package/dist/src/utils/shell-utils.js +1 -182
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +1 -288
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/terminalSerializer.test.js +17 -0
- package/dist/src/utils/terminalSerializer.test.js.map +1 -1
- package/dist/src/utils/tool-utils.js.map +1 -1
- package/dist/src/utils/version.d.ts +6 -0
- package/dist/src/utils/version.js +15 -0
- package/dist/src/utils/version.js.map +1 -0
- package/dist/src/utils/version.test.d.ts +6 -0
- package/dist/src/utils/version.test.js +39 -0
- package/dist/src/utils/version.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ import { AjvJsonSchemaValidator } from '@modelcontextprotocol/sdk/validation/ajv
|
|
|
8
8
|
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
9
9
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
10
10
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
11
|
-
import { ListRootsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
11
|
+
import { ListResourcesResultSchema, ListRootsRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, ToolListChangedNotificationSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
12
12
|
import { parse } from 'shell-quote';
|
|
13
13
|
import { AuthProviderType } from '../config/config.js';
|
|
14
14
|
import { GoogleCredentialProvider } from '../mcp/google-auth-provider.js';
|
|
@@ -19,7 +19,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
19
19
|
import { MCPOAuthProvider } from '../mcp/oauth-provider.js';
|
|
20
20
|
import { MCPOAuthTokenStorage } from '../mcp/oauth-token-storage.js';
|
|
21
21
|
import { OAuthUtils } from '../mcp/oauth-utils.js';
|
|
22
|
-
import { getErrorMessage } from '../utils/errors.js';
|
|
22
|
+
import { getErrorMessage, isAuthenticationError, UnauthorizedError, } from '../utils/errors.js';
|
|
23
23
|
import { debugLogger } from '../utils/debugLogger.js';
|
|
24
24
|
import { coreEvents } from '../utils/events.js';
|
|
25
25
|
import { loadYamlConfig } from '@machina.ai/config-yaml';
|
|
@@ -95,18 +95,28 @@ export class McpClient {
|
|
|
95
95
|
serverConfig;
|
|
96
96
|
toolRegistry;
|
|
97
97
|
promptRegistry;
|
|
98
|
+
resourceRegistry;
|
|
98
99
|
workspaceContext;
|
|
100
|
+
cliConfig;
|
|
99
101
|
debugMode;
|
|
102
|
+
onToolsUpdated;
|
|
100
103
|
client;
|
|
101
104
|
transport;
|
|
102
105
|
status = MCPServerStatus.DISCONNECTED;
|
|
103
|
-
|
|
106
|
+
isRefreshingTools = false;
|
|
107
|
+
pendingToolRefresh = false;
|
|
108
|
+
isRefreshingResources = false;
|
|
109
|
+
pendingResourceRefresh = false;
|
|
110
|
+
constructor(serverName, serverConfig, toolRegistry, promptRegistry, resourceRegistry, workspaceContext, cliConfig, debugMode, onToolsUpdated) {
|
|
104
111
|
this.serverName = serverName;
|
|
105
112
|
this.serverConfig = serverConfig;
|
|
106
113
|
this.toolRegistry = toolRegistry;
|
|
107
114
|
this.promptRegistry = promptRegistry;
|
|
115
|
+
this.resourceRegistry = resourceRegistry;
|
|
108
116
|
this.workspaceContext = workspaceContext;
|
|
117
|
+
this.cliConfig = cliConfig;
|
|
109
118
|
this.debugMode = debugMode;
|
|
119
|
+
this.onToolsUpdated = onToolsUpdated;
|
|
110
120
|
}
|
|
111
121
|
/**
|
|
112
122
|
* Connects to the MCP server.
|
|
@@ -118,6 +128,7 @@ export class McpClient {
|
|
|
118
128
|
this.updateStatus(MCPServerStatus.CONNECTING);
|
|
119
129
|
try {
|
|
120
130
|
this.client = await connectToMcpServer(this.serverName, this.serverConfig, this.debugMode, this.workspaceContext);
|
|
131
|
+
this.registerNotificationHandlers();
|
|
121
132
|
const originalOnError = this.client.onerror;
|
|
122
133
|
this.client.onerror = (error) => {
|
|
123
134
|
if (this.status !== MCPServerStatus.CONNECTED) {
|
|
@@ -142,8 +153,10 @@ export class McpClient {
|
|
|
142
153
|
this.assertConnected();
|
|
143
154
|
const prompts = await this.discoverPrompts();
|
|
144
155
|
const tools = await this.discoverTools(cliConfig);
|
|
145
|
-
|
|
146
|
-
|
|
156
|
+
const resources = await this.discoverResources();
|
|
157
|
+
this.updateResourceRegistry(resources);
|
|
158
|
+
if (prompts.length === 0 && tools.length === 0 && resources.length === 0) {
|
|
159
|
+
throw new Error('No prompts, tools, or resources found on the server.');
|
|
147
160
|
}
|
|
148
161
|
for (const tool of tools) {
|
|
149
162
|
this.toolRegistry.registerTool(tool);
|
|
@@ -159,6 +172,7 @@ export class McpClient {
|
|
|
159
172
|
}
|
|
160
173
|
this.toolRegistry.removeMcpToolsByServer(this.serverName);
|
|
161
174
|
this.promptRegistry.removePromptsByServer(this.serverName);
|
|
175
|
+
this.resourceRegistry.removeResourcesByServer(this.serverName);
|
|
162
176
|
this.updateStatus(MCPServerStatus.DISCONNECTING);
|
|
163
177
|
const client = this.client;
|
|
164
178
|
this.client = undefined;
|
|
@@ -185,20 +199,157 @@ export class McpClient {
|
|
|
185
199
|
throw new Error(`Client is not connected, must connect before interacting with the server. Current state is ${this.status}`);
|
|
186
200
|
}
|
|
187
201
|
}
|
|
188
|
-
async discoverTools(cliConfig) {
|
|
202
|
+
async discoverTools(cliConfig, options) {
|
|
189
203
|
this.assertConnected();
|
|
190
|
-
return discoverTools(this.serverName, this.serverConfig, this.client, cliConfig, this.toolRegistry.getMessageBus()
|
|
204
|
+
return discoverTools(this.serverName, this.serverConfig, this.client, cliConfig, this.toolRegistry.getMessageBus(), options ?? {
|
|
205
|
+
timeout: this.serverConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
|
|
206
|
+
});
|
|
191
207
|
}
|
|
192
208
|
async discoverPrompts() {
|
|
193
209
|
this.assertConnected();
|
|
194
210
|
return discoverPrompts(this.serverName, this.client, this.promptRegistry);
|
|
195
211
|
}
|
|
212
|
+
async discoverResources() {
|
|
213
|
+
this.assertConnected();
|
|
214
|
+
return discoverResources(this.serverName, this.client);
|
|
215
|
+
}
|
|
216
|
+
updateResourceRegistry(resources) {
|
|
217
|
+
this.resourceRegistry.setResourcesForServer(this.serverName, resources);
|
|
218
|
+
}
|
|
219
|
+
async readResource(uri) {
|
|
220
|
+
this.assertConnected();
|
|
221
|
+
return this.client.request({
|
|
222
|
+
method: 'resources/read',
|
|
223
|
+
params: { uri },
|
|
224
|
+
}, ReadResourceResultSchema);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Registers notification handlers for dynamic updates from the MCP server.
|
|
228
|
+
* This includes handlers for tool list changes and resource list changes.
|
|
229
|
+
*/
|
|
230
|
+
registerNotificationHandlers() {
|
|
231
|
+
if (!this.client) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const capabilities = this.client.getServerCapabilities();
|
|
235
|
+
if (capabilities?.tools?.listChanged) {
|
|
236
|
+
debugLogger.log(`Server '${this.serverName}' supports tool updates. Listening for changes...`);
|
|
237
|
+
this.client.setNotificationHandler(ToolListChangedNotificationSchema, async () => {
|
|
238
|
+
debugLogger.log(`🔔 Received tool update notification from '${this.serverName}'`);
|
|
239
|
+
await this.refreshTools();
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
if (capabilities?.resources?.listChanged) {
|
|
243
|
+
debugLogger.log(`Server '${this.serverName}' supports resource updates. Listening for changes...`);
|
|
244
|
+
this.client.setNotificationHandler(ResourceListChangedNotificationSchema, async () => {
|
|
245
|
+
debugLogger.log(`🔔 Received resource update notification from '${this.serverName}'`);
|
|
246
|
+
await this.refreshResources();
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Refreshes the resources for this server by re-querying the MCP `resources/list` endpoint.
|
|
252
|
+
*
|
|
253
|
+
* This method implements a **Coalescing Pattern** to handle rapid bursts of notifications
|
|
254
|
+
* (e.g., during server startup or bulk updates) without overwhelming the server or
|
|
255
|
+
* creating race conditions in the ResourceRegistry.
|
|
256
|
+
*/
|
|
257
|
+
async refreshResources() {
|
|
258
|
+
if (this.isRefreshingResources) {
|
|
259
|
+
debugLogger.log(`Resource refresh for '${this.serverName}' is already in progress. Pending update.`);
|
|
260
|
+
this.pendingResourceRefresh = true;
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
this.isRefreshingResources = true;
|
|
264
|
+
try {
|
|
265
|
+
do {
|
|
266
|
+
this.pendingResourceRefresh = false;
|
|
267
|
+
if (this.status !== MCPServerStatus.CONNECTED || !this.client)
|
|
268
|
+
break;
|
|
269
|
+
const timeoutMs = this.serverConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC;
|
|
270
|
+
const abortController = new AbortController();
|
|
271
|
+
const timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
|
|
272
|
+
let newResources;
|
|
273
|
+
try {
|
|
274
|
+
newResources = await this.discoverResources();
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
debugLogger.error(`Resource discovery failed during refresh: ${getErrorMessage(err)}`);
|
|
278
|
+
clearTimeout(timeoutId);
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
this.updateResourceRegistry(newResources);
|
|
282
|
+
clearTimeout(timeoutId);
|
|
283
|
+
coreEvents.emitFeedback('info', `Resources updated for server: ${this.serverName}`);
|
|
284
|
+
} while (this.pendingResourceRefresh);
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
debugLogger.error(`Critical error in resource refresh loop for ${this.serverName}: ${getErrorMessage(error)}`);
|
|
288
|
+
}
|
|
289
|
+
finally {
|
|
290
|
+
this.isRefreshingResources = false;
|
|
291
|
+
this.pendingResourceRefresh = false;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
196
294
|
getServerConfig() {
|
|
197
295
|
return this.serverConfig;
|
|
198
296
|
}
|
|
199
297
|
getInstructions() {
|
|
200
298
|
return this.client?.getInstructions();
|
|
201
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Refreshes the tools for this server by re-querying the MCP `tools/list` endpoint.
|
|
302
|
+
*
|
|
303
|
+
* This method implements a **Coalescing Pattern** to handle rapid bursts of notifications
|
|
304
|
+
* (e.g., during server startup or bulk updates) without overwhelming the server or
|
|
305
|
+
* creating race conditions in the global ToolRegistry.
|
|
306
|
+
*/
|
|
307
|
+
async refreshTools() {
|
|
308
|
+
if (this.isRefreshingTools) {
|
|
309
|
+
debugLogger.log(`Tool refresh for '${this.serverName}' is already in progress. Pending update.`);
|
|
310
|
+
this.pendingToolRefresh = true;
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
this.isRefreshingTools = true;
|
|
314
|
+
try {
|
|
315
|
+
do {
|
|
316
|
+
this.pendingToolRefresh = false;
|
|
317
|
+
if (this.status !== MCPServerStatus.CONNECTED || !this.client)
|
|
318
|
+
break;
|
|
319
|
+
const timeoutMs = this.serverConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC;
|
|
320
|
+
const abortController = new AbortController();
|
|
321
|
+
const timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
|
|
322
|
+
let newTools;
|
|
323
|
+
try {
|
|
324
|
+
newTools = await this.discoverTools(this.cliConfig, {
|
|
325
|
+
signal: abortController.signal,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
catch (err) {
|
|
329
|
+
debugLogger.error(`Discovery failed during refresh: ${getErrorMessage(err)}`);
|
|
330
|
+
clearTimeout(timeoutId);
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
this.toolRegistry.removeMcpToolsByServer(this.serverName);
|
|
334
|
+
for (const tool of newTools) {
|
|
335
|
+
this.toolRegistry.registerTool(tool);
|
|
336
|
+
}
|
|
337
|
+
this.toolRegistry.sortTools();
|
|
338
|
+
if (this.onToolsUpdated) {
|
|
339
|
+
await this.onToolsUpdated(abortController.signal);
|
|
340
|
+
}
|
|
341
|
+
clearTimeout(timeoutId);
|
|
342
|
+
coreEvents.emitFeedback('info', `Tools updated for server: ${this.serverName}`);
|
|
343
|
+
} while (this.pendingToolRefresh);
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
debugLogger.error(`Critical error in refresh loop for ${this.serverName}: ${getErrorMessage(error)}`);
|
|
347
|
+
}
|
|
348
|
+
finally {
|
|
349
|
+
this.isRefreshingTools = false;
|
|
350
|
+
this.pendingToolRefresh = false;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
202
353
|
}
|
|
203
354
|
/**
|
|
204
355
|
* Map to track the status of each MCP server within the core package
|
|
@@ -357,21 +508,6 @@ function createAuthProvider(mcpServerConfig) {
|
|
|
357
508
|
}
|
|
358
509
|
return undefined;
|
|
359
510
|
}
|
|
360
|
-
/**
|
|
361
|
-
* Create a transport for URL based servers (remote servers).
|
|
362
|
-
*
|
|
363
|
-
* @param mcpServerConfig The MCP server configuration
|
|
364
|
-
* @param transportOptions The transport options
|
|
365
|
-
*/
|
|
366
|
-
function createUrlTransport(mcpServerConfig, transportOptions) {
|
|
367
|
-
if (mcpServerConfig.httpUrl) {
|
|
368
|
-
return new StreamableHTTPClientTransport(new URL(mcpServerConfig.httpUrl), transportOptions);
|
|
369
|
-
}
|
|
370
|
-
if (mcpServerConfig.url) {
|
|
371
|
-
return new SSEClientTransport(new URL(mcpServerConfig.url), transportOptions);
|
|
372
|
-
}
|
|
373
|
-
throw new Error('No URL configured for MCP Server');
|
|
374
|
-
}
|
|
375
511
|
/**
|
|
376
512
|
* Create a transport with OAuth token for the given server configuration.
|
|
377
513
|
*
|
|
@@ -388,7 +524,7 @@ async function createTransportWithOAuth(mcpServerName, mcpServerConfig, accessTo
|
|
|
388
524
|
const transportOptions = {
|
|
389
525
|
requestInit: createTransportRequestInit(mcpServerConfig, headers),
|
|
390
526
|
};
|
|
391
|
-
return createUrlTransport(mcpServerConfig, transportOptions);
|
|
527
|
+
return createUrlTransport(mcpServerName, mcpServerConfig, transportOptions);
|
|
392
528
|
}
|
|
393
529
|
catch (error) {
|
|
394
530
|
coreEvents.emitFeedback('error', `Failed to create OAuth transport for server '${mcpServerName}': ${getErrorMessage(error)}`, error);
|
|
@@ -480,7 +616,7 @@ export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolReg
|
|
|
480
616
|
};
|
|
481
617
|
// Attempt to discover both prompts and tools
|
|
482
618
|
const prompts = await discoverPrompts(mcpServerName, mcpClient, promptRegistry);
|
|
483
|
-
const tools = await discoverTools(mcpServerName, mcpServerConfig, mcpClient, cliConfig, toolRegistry.getMessageBus());
|
|
619
|
+
const tools = await discoverTools(mcpServerName, mcpServerConfig, mcpClient, cliConfig, toolRegistry.getMessageBus(), { timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC });
|
|
484
620
|
// If we have neither prompts nor tools, it's a failed discovery
|
|
485
621
|
if (prompts.length === 0 && tools.length === 0) {
|
|
486
622
|
throw new Error('No prompts or tools found on the server.');
|
|
@@ -495,6 +631,7 @@ export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolReg
|
|
|
495
631
|
}
|
|
496
632
|
catch (error) {
|
|
497
633
|
if (mcpClient) {
|
|
634
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
498
635
|
mcpClient.close();
|
|
499
636
|
}
|
|
500
637
|
coreEvents.emitFeedback('error', `Error connecting to MCP server '${mcpServerName}': ${getErrorMessage(error)}`, error);
|
|
@@ -514,12 +651,12 @@ export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolReg
|
|
|
514
651
|
* @returns A promise that resolves to an array of discovered and enabled tools.
|
|
515
652
|
* @throws An error if no enabled tools are found or if the server provides invalid function declarations.
|
|
516
653
|
*/
|
|
517
|
-
export async function discoverTools(mcpServerName, mcpServerConfig, mcpClient, cliConfig, messageBus) {
|
|
654
|
+
export async function discoverTools(mcpServerName, mcpServerConfig, mcpClient, cliConfig, messageBus, options) {
|
|
518
655
|
try {
|
|
519
656
|
// Only request tools if the server supports them.
|
|
520
657
|
if (mcpClient.getServerCapabilities()?.tools == null)
|
|
521
658
|
return [];
|
|
522
|
-
const response = await mcpClient.listTools({});
|
|
659
|
+
const response = await mcpClient.listTools({}, options);
|
|
523
660
|
const discoveredTools = [];
|
|
524
661
|
for (const toolDef of response.tools) {
|
|
525
662
|
try {
|
|
@@ -634,6 +771,35 @@ export async function discoverPrompts(mcpServerName, mcpClient, promptRegistry)
|
|
|
634
771
|
return [];
|
|
635
772
|
}
|
|
636
773
|
}
|
|
774
|
+
export async function discoverResources(mcpServerName, mcpClient) {
|
|
775
|
+
if (mcpClient.getServerCapabilities()?.resources == null) {
|
|
776
|
+
return [];
|
|
777
|
+
}
|
|
778
|
+
const resources = await listResources(mcpServerName, mcpClient);
|
|
779
|
+
return resources;
|
|
780
|
+
}
|
|
781
|
+
async function listResources(mcpServerName, mcpClient) {
|
|
782
|
+
const resources = [];
|
|
783
|
+
let cursor;
|
|
784
|
+
try {
|
|
785
|
+
do {
|
|
786
|
+
const response = await mcpClient.request({
|
|
787
|
+
method: 'resources/list',
|
|
788
|
+
params: cursor ? { cursor } : {},
|
|
789
|
+
}, ListResourcesResultSchema);
|
|
790
|
+
resources.push(...(response.resources ?? []));
|
|
791
|
+
cursor = response.nextCursor ?? undefined;
|
|
792
|
+
} while (cursor);
|
|
793
|
+
}
|
|
794
|
+
catch (error) {
|
|
795
|
+
if (error instanceof Error && error.message?.includes('Method not found')) {
|
|
796
|
+
return [];
|
|
797
|
+
}
|
|
798
|
+
coreEvents.emitFeedback('error', `Error discovering resources from ${mcpServerName}: ${getErrorMessage(error)}`, error);
|
|
799
|
+
throw error;
|
|
800
|
+
}
|
|
801
|
+
return resources;
|
|
802
|
+
}
|
|
637
803
|
/**
|
|
638
804
|
* Invokes a prompt on a connected MCP client.
|
|
639
805
|
*
|
|
@@ -674,6 +840,116 @@ export async function invokeMcpPrompt(mcpServerName, mcpClient, promptName, prom
|
|
|
674
840
|
export function hasNetworkTransport(config) {
|
|
675
841
|
return !!(config.url || config.httpUrl);
|
|
676
842
|
}
|
|
843
|
+
/**
|
|
844
|
+
* Helper function to retrieve a stored OAuth token for an MCP server.
|
|
845
|
+
* Handles token validation and refresh automatically.
|
|
846
|
+
*
|
|
847
|
+
* @param serverName The name of the MCP server
|
|
848
|
+
* @returns The valid access token, or null if no token is stored
|
|
849
|
+
*/
|
|
850
|
+
async function getStoredOAuthToken(serverName) {
|
|
851
|
+
const tokenStorage = new MCPOAuthTokenStorage();
|
|
852
|
+
const credentials = await tokenStorage.getCredentials(serverName);
|
|
853
|
+
if (!credentials)
|
|
854
|
+
return null;
|
|
855
|
+
const authProvider = new MCPOAuthProvider(tokenStorage);
|
|
856
|
+
return authProvider.getValidToken(serverName, {
|
|
857
|
+
// Pass client ID if available
|
|
858
|
+
clientId: credentials.clientId,
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Helper function to create an SSE transport with optional OAuth authentication.
|
|
863
|
+
*
|
|
864
|
+
* @param config The MCP server configuration
|
|
865
|
+
* @param accessToken Optional OAuth access token for authentication
|
|
866
|
+
* @returns A configured SSE transport ready for connection
|
|
867
|
+
*/
|
|
868
|
+
function createSSETransportWithAuth(config, accessToken) {
|
|
869
|
+
const headers = {
|
|
870
|
+
...config.headers,
|
|
871
|
+
...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),
|
|
872
|
+
};
|
|
873
|
+
const options = {};
|
|
874
|
+
if (Object.keys(headers).length > 0) {
|
|
875
|
+
options.requestInit = { headers };
|
|
876
|
+
}
|
|
877
|
+
return new SSEClientTransport(new URL(config.url), options);
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Helper function to connect a client using SSE transport with optional OAuth.
|
|
881
|
+
*
|
|
882
|
+
* @param client The MCP client to connect
|
|
883
|
+
* @param config The MCP server configuration
|
|
884
|
+
* @param accessToken Optional OAuth access token for authentication
|
|
885
|
+
*/
|
|
886
|
+
async function connectWithSSETransport(client, config, accessToken) {
|
|
887
|
+
const transport = createSSETransportWithAuth(config, accessToken);
|
|
888
|
+
await client.connect(transport, {
|
|
889
|
+
timeout: config.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Helper function to show authentication required message and throw error.
|
|
894
|
+
* Checks if there's a stored token that was rejected (requires re-auth).
|
|
895
|
+
*
|
|
896
|
+
* @param serverName The name of the MCP server
|
|
897
|
+
* @throws Always throws an error with authentication instructions
|
|
898
|
+
*/
|
|
899
|
+
async function showAuthRequiredMessage(serverName) {
|
|
900
|
+
const hasRejectedToken = !!(await getStoredOAuthToken(serverName));
|
|
901
|
+
const message = hasRejectedToken
|
|
902
|
+
? `MCP server '${serverName}' rejected stored OAuth token. Please re-authenticate using: /mcp auth ${serverName}`
|
|
903
|
+
: `MCP server '${serverName}' requires authentication using: /mcp auth ${serverName}`;
|
|
904
|
+
coreEvents.emitFeedback('info', message);
|
|
905
|
+
throw new UnauthorizedError(message);
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Helper function to retry connection with OAuth token after authentication.
|
|
909
|
+
* Handles both HTTP and SSE transports based on what previously failed.
|
|
910
|
+
*
|
|
911
|
+
* @param client The MCP client to connect
|
|
912
|
+
* @param serverName The name of the MCP server
|
|
913
|
+
* @param config The MCP server configuration
|
|
914
|
+
* @param accessToken The OAuth access token to use
|
|
915
|
+
* @param httpReturned404 Whether the HTTP transport returned 404 (indicating SSE-only server)
|
|
916
|
+
*/
|
|
917
|
+
async function retryWithOAuth(client, serverName, config, accessToken, httpReturned404) {
|
|
918
|
+
if (httpReturned404) {
|
|
919
|
+
// HTTP returned 404, only try SSE
|
|
920
|
+
debugLogger.log(`Retrying SSE connection to '${serverName}' with OAuth token...`);
|
|
921
|
+
await connectWithSSETransport(client, config, accessToken);
|
|
922
|
+
debugLogger.log(`Successfully connected to '${serverName}' using SSE with OAuth.`);
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
// HTTP returned 401, try HTTP with OAuth first
|
|
926
|
+
debugLogger.log(`Retrying connection to '${serverName}' with OAuth token...`);
|
|
927
|
+
const httpTransport = await createTransportWithOAuth(serverName, config, accessToken);
|
|
928
|
+
if (!httpTransport) {
|
|
929
|
+
throw new Error(`Failed to create OAuth transport for server '${serverName}'`);
|
|
930
|
+
}
|
|
931
|
+
try {
|
|
932
|
+
await client.connect(httpTransport, {
|
|
933
|
+
timeout: config.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
|
|
934
|
+
});
|
|
935
|
+
debugLogger.log(`Successfully connected to '${serverName}' using HTTP with OAuth.`);
|
|
936
|
+
}
|
|
937
|
+
catch (httpError) {
|
|
938
|
+
await httpTransport.close();
|
|
939
|
+
// If HTTP+OAuth returns 404 and auto-detection enabled, try SSE+OAuth
|
|
940
|
+
if (String(httpError).includes('404') &&
|
|
941
|
+
config.url &&
|
|
942
|
+
!config.type &&
|
|
943
|
+
!config.httpUrl) {
|
|
944
|
+
debugLogger.log(`HTTP with OAuth returned 404, trying SSE with OAuth...`);
|
|
945
|
+
await connectWithSSETransport(client, config, accessToken);
|
|
946
|
+
debugLogger.log(`Successfully connected to '${serverName}' using SSE with OAuth.`);
|
|
947
|
+
}
|
|
948
|
+
else {
|
|
949
|
+
throw httpError;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
677
953
|
/**
|
|
678
954
|
* Creates and connects an MCP client to a server based on the provided configuration.
|
|
679
955
|
* It determines the appropriate transport (Stdio, SSE, or Streamable HTTP) and
|
|
@@ -733,6 +1009,9 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
733
1009
|
unlistenDirectories?.();
|
|
734
1010
|
unlistenDirectories = undefined;
|
|
735
1011
|
};
|
|
1012
|
+
let firstAttemptError = null;
|
|
1013
|
+
let httpReturned404 = false; // Track if HTTP returned 404 to skip it in OAuth retry
|
|
1014
|
+
let sseError = null; // Track SSE fallback error
|
|
736
1015
|
try {
|
|
737
1016
|
const transport = await createTransport(mcpServerName, mcpServerConfig, debugMode);
|
|
738
1017
|
try {
|
|
@@ -743,52 +1022,92 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
743
1022
|
}
|
|
744
1023
|
catch (error) {
|
|
745
1024
|
await transport.close();
|
|
1025
|
+
firstAttemptError = error;
|
|
746
1026
|
throw error;
|
|
747
1027
|
}
|
|
748
1028
|
}
|
|
749
|
-
catch (
|
|
1029
|
+
catch (initialError) {
|
|
1030
|
+
let error = initialError;
|
|
1031
|
+
// Check if this is a 401 error FIRST (before attempting SSE fallback)
|
|
1032
|
+
// This ensures OAuth flow happens before we try SSE
|
|
1033
|
+
if (isAuthenticationError(error) && hasNetworkTransport(mcpServerConfig)) {
|
|
1034
|
+
// Continue to OAuth handling below (after SSE fallback section)
|
|
1035
|
+
}
|
|
1036
|
+
else if (
|
|
1037
|
+
// If not 401, and HTTP failed with url without explicit type, try SSE fallback
|
|
1038
|
+
firstAttemptError &&
|
|
1039
|
+
mcpServerConfig.url &&
|
|
1040
|
+
!mcpServerConfig.type &&
|
|
1041
|
+
!mcpServerConfig.httpUrl) {
|
|
1042
|
+
// Check if HTTP returned 404 - if so, we know it's not an HTTP server
|
|
1043
|
+
httpReturned404 = String(firstAttemptError).includes('404');
|
|
1044
|
+
const logMessage = httpReturned404
|
|
1045
|
+
? `HTTP returned 404, trying SSE transport...`
|
|
1046
|
+
: `HTTP connection failed, attempting SSE fallback...`;
|
|
1047
|
+
debugLogger.log(`MCP server '${mcpServerName}': ${logMessage}`);
|
|
1048
|
+
try {
|
|
1049
|
+
// Try SSE with stored OAuth token if available
|
|
1050
|
+
// This ensures that SSE fallback works for authenticated servers
|
|
1051
|
+
await connectWithSSETransport(mcpClient, mcpServerConfig, await getStoredOAuthToken(mcpServerName));
|
|
1052
|
+
debugLogger.log(`MCP server '${mcpServerName}': Successfully connected using SSE transport.`);
|
|
1053
|
+
return mcpClient;
|
|
1054
|
+
}
|
|
1055
|
+
catch (sseFallbackError) {
|
|
1056
|
+
sseError = sseFallbackError;
|
|
1057
|
+
// If SSE also returned 401, handle OAuth below
|
|
1058
|
+
if (isAuthenticationError(sseError)) {
|
|
1059
|
+
debugLogger.log(`MCP server '${mcpServerName}': SSE returned 401, OAuth authentication required.`);
|
|
1060
|
+
// Update error to be the SSE error for OAuth handling
|
|
1061
|
+
error = sseError;
|
|
1062
|
+
// Continue to OAuth handling below
|
|
1063
|
+
}
|
|
1064
|
+
else {
|
|
1065
|
+
debugLogger.log(`MCP server '${mcpServerName}': SSE fallback also failed.`);
|
|
1066
|
+
// Both failed without 401, throw the original error
|
|
1067
|
+
throw firstAttemptError;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
750
1071
|
// Check if this is a 401 error that might indicate OAuth is required
|
|
751
|
-
|
|
752
|
-
if (errorString.includes('401') && hasNetworkTransport(mcpServerConfig)) {
|
|
1072
|
+
if (isAuthenticationError(error) && hasNetworkTransport(mcpServerConfig)) {
|
|
753
1073
|
mcpServerRequiresOAuth.set(mcpServerName, true);
|
|
754
|
-
// Only trigger automatic OAuth
|
|
755
|
-
//
|
|
756
|
-
const shouldTriggerOAuth = mcpServerConfig.
|
|
1074
|
+
// Only trigger automatic OAuth if explicitly enabled in config
|
|
1075
|
+
// Otherwise, show error and tell user to run /mcp auth command
|
|
1076
|
+
const shouldTriggerOAuth = mcpServerConfig.oauth?.enabled;
|
|
757
1077
|
if (!shouldTriggerOAuth) {
|
|
758
|
-
|
|
759
|
-
const tokenStorage = new MCPOAuthTokenStorage();
|
|
760
|
-
const credentials = await tokenStorage.getCredentials(mcpServerName);
|
|
761
|
-
if (credentials) {
|
|
762
|
-
const authProvider = new MCPOAuthProvider(tokenStorage);
|
|
763
|
-
const hasStoredTokens = await authProvider.getValidToken(mcpServerName, {
|
|
764
|
-
// Pass client ID if available
|
|
765
|
-
clientId: credentials.clientId,
|
|
766
|
-
});
|
|
767
|
-
if (hasStoredTokens) {
|
|
768
|
-
coreEvents.emitFeedback('error', `Stored OAuth token for SSE server '${mcpServerName}' was rejected. ` +
|
|
769
|
-
`Please re-authenticate using: /mcp auth ${mcpServerName}`);
|
|
770
|
-
}
|
|
771
|
-
else {
|
|
772
|
-
coreEvents.emitFeedback('error', `401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
|
|
773
|
-
`Please authenticate using: /mcp auth ${mcpServerName}`);
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
throw new Error(`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
|
|
777
|
-
`Please authenticate using: /mcp auth ${mcpServerName}`);
|
|
1078
|
+
await showAuthRequiredMessage(mcpServerName);
|
|
778
1079
|
}
|
|
779
1080
|
// Try to extract www-authenticate header from the error
|
|
1081
|
+
const errorString = String(error);
|
|
780
1082
|
let wwwAuthenticate = extractWWWAuthenticateHeader(errorString);
|
|
781
1083
|
// If we didn't get the header from the error string, try to get it from the server
|
|
782
1084
|
if (!wwwAuthenticate && hasNetworkTransport(mcpServerConfig)) {
|
|
783
1085
|
debugLogger.log(`No www-authenticate header in error, trying to fetch it from server...`);
|
|
784
1086
|
try {
|
|
785
1087
|
const urlToFetch = mcpServerConfig.httpUrl || mcpServerConfig.url;
|
|
1088
|
+
// Determine correct Accept header based on what transport failed
|
|
1089
|
+
let acceptHeader;
|
|
1090
|
+
if (mcpServerConfig.httpUrl) {
|
|
1091
|
+
acceptHeader = 'application/json';
|
|
1092
|
+
}
|
|
1093
|
+
else if (mcpServerConfig.type === 'http') {
|
|
1094
|
+
acceptHeader = 'application/json';
|
|
1095
|
+
}
|
|
1096
|
+
else if (mcpServerConfig.type === 'sse') {
|
|
1097
|
+
acceptHeader = 'text/event-stream';
|
|
1098
|
+
}
|
|
1099
|
+
else if (httpReturned404) {
|
|
1100
|
+
// HTTP failed with 404, SSE returned 401 - use SSE header
|
|
1101
|
+
acceptHeader = 'text/event-stream';
|
|
1102
|
+
}
|
|
1103
|
+
else {
|
|
1104
|
+
// HTTP returned 401 - use HTTP header
|
|
1105
|
+
acceptHeader = 'application/json';
|
|
1106
|
+
}
|
|
786
1107
|
const response = await fetch(urlToFetch, {
|
|
787
1108
|
method: 'HEAD',
|
|
788
1109
|
headers: {
|
|
789
|
-
Accept:
|
|
790
|
-
? 'application/json'
|
|
791
|
-
: 'text/event-stream',
|
|
1110
|
+
Accept: acceptHeader,
|
|
792
1111
|
},
|
|
793
1112
|
signal: AbortSignal.timeout(5000),
|
|
794
1113
|
});
|
|
@@ -809,38 +1128,12 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
809
1128
|
const oauthSuccess = await handleAutomaticOAuth(mcpServerName, mcpServerConfig, wwwAuthenticate);
|
|
810
1129
|
if (oauthSuccess) {
|
|
811
1130
|
// Retry connection with OAuth token
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
const tokenStorage = new MCPOAuthTokenStorage();
|
|
816
|
-
const credentials = await tokenStorage.getCredentials(mcpServerName);
|
|
817
|
-
if (credentials) {
|
|
818
|
-
const authProvider = new MCPOAuthProvider(tokenStorage);
|
|
819
|
-
const accessToken = await authProvider.getValidToken(mcpServerName, {
|
|
820
|
-
// Pass client ID if available
|
|
821
|
-
clientId: credentials.clientId,
|
|
822
|
-
});
|
|
823
|
-
if (accessToken) {
|
|
824
|
-
// Create transport with OAuth token
|
|
825
|
-
const oauthTransport = await createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken);
|
|
826
|
-
if (oauthTransport) {
|
|
827
|
-
await mcpClient.connect(oauthTransport, {
|
|
828
|
-
timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
|
|
829
|
-
});
|
|
830
|
-
// Connection successful with OAuth
|
|
831
|
-
return mcpClient;
|
|
832
|
-
}
|
|
833
|
-
else {
|
|
834
|
-
throw new Error(`Failed to create OAuth transport for server '${mcpServerName}'`);
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
else {
|
|
838
|
-
throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
else {
|
|
842
|
-
throw new Error(`Failed to get credentials for server '${mcpServerName}' after successful OAuth authentication`);
|
|
1131
|
+
const accessToken = await getStoredOAuthToken(mcpServerName);
|
|
1132
|
+
if (!accessToken) {
|
|
1133
|
+
throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
|
|
843
1134
|
}
|
|
1135
|
+
await retryWithOAuth(mcpClient, mcpServerName, mcpServerConfig, accessToken, httpReturned404);
|
|
1136
|
+
return mcpClient;
|
|
844
1137
|
}
|
|
845
1138
|
else {
|
|
846
1139
|
throw new Error(`Failed to handle automatic OAuth for server '${mcpServerName}'`);
|
|
@@ -848,29 +1141,10 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
848
1141
|
}
|
|
849
1142
|
else {
|
|
850
1143
|
// No www-authenticate header found, but we got a 401
|
|
851
|
-
// Only try OAuth discovery
|
|
852
|
-
|
|
853
|
-
const shouldTryDiscovery = mcpServerConfig.httpUrl || mcpServerConfig.oauth?.enabled;
|
|
1144
|
+
// Only try OAuth discovery when OAuth is explicitly enabled in config
|
|
1145
|
+
const shouldTryDiscovery = mcpServerConfig.oauth?.enabled;
|
|
854
1146
|
if (!shouldTryDiscovery) {
|
|
855
|
-
|
|
856
|
-
const credentials = await tokenStorage.getCredentials(mcpServerName);
|
|
857
|
-
if (credentials) {
|
|
858
|
-
const authProvider = new MCPOAuthProvider(tokenStorage);
|
|
859
|
-
const hasStoredTokens = await authProvider.getValidToken(mcpServerName, {
|
|
860
|
-
// Pass client ID if available
|
|
861
|
-
clientId: credentials.clientId,
|
|
862
|
-
});
|
|
863
|
-
if (hasStoredTokens) {
|
|
864
|
-
coreEvents.emitFeedback('error', `Stored OAuth token for SSE server '${mcpServerName}' was rejected. ` +
|
|
865
|
-
`Please re-authenticate using: /mcp auth ${mcpServerName}`);
|
|
866
|
-
}
|
|
867
|
-
else {
|
|
868
|
-
coreEvents.emitFeedback('error', `401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
|
|
869
|
-
`Please authenticate using: /mcp auth ${mcpServerName}`);
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
throw new Error(`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
|
|
873
|
-
`Please authenticate using: /mcp auth ${mcpServerName}`);
|
|
1147
|
+
await showAuthRequiredMessage(mcpServerName);
|
|
874
1148
|
}
|
|
875
1149
|
// For SSE/HTTP servers, try to discover OAuth configuration from the base URL
|
|
876
1150
|
debugLogger.log(`🔍 Attempting OAuth discovery for '${mcpServerName}'...`);
|
|
@@ -895,35 +1169,20 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
895
1169
|
const authProvider = new MCPOAuthProvider(new MCPOAuthTokenStorage());
|
|
896
1170
|
await authProvider.authenticate(mcpServerName, oauthAuthConfig, authServerUrl);
|
|
897
1171
|
// Retry connection with OAuth token
|
|
898
|
-
const
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
const authProvider = new MCPOAuthProvider(tokenStorage);
|
|
902
|
-
const accessToken = await authProvider.getValidToken(mcpServerName, {
|
|
903
|
-
// Pass client ID if available
|
|
904
|
-
clientId: credentials.clientId,
|
|
905
|
-
});
|
|
906
|
-
if (accessToken) {
|
|
907
|
-
// Create transport with OAuth token
|
|
908
|
-
const oauthTransport = await createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken);
|
|
909
|
-
if (oauthTransport) {
|
|
910
|
-
await mcpClient.connect(oauthTransport, {
|
|
911
|
-
timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
|
|
912
|
-
});
|
|
913
|
-
// Connection successful with OAuth
|
|
914
|
-
return mcpClient;
|
|
915
|
-
}
|
|
916
|
-
else {
|
|
917
|
-
throw new Error(`Failed to create OAuth transport for server '${mcpServerName}'`);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
else {
|
|
921
|
-
throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
|
|
922
|
-
}
|
|
1172
|
+
const accessToken = await getStoredOAuthToken(mcpServerName);
|
|
1173
|
+
if (!accessToken) {
|
|
1174
|
+
throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
|
|
923
1175
|
}
|
|
924
|
-
|
|
925
|
-
|
|
1176
|
+
// Create transport with OAuth token
|
|
1177
|
+
const oauthTransport = await createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken);
|
|
1178
|
+
if (!oauthTransport) {
|
|
1179
|
+
throw new Error(`Failed to create OAuth transport for server '${mcpServerName}'`);
|
|
926
1180
|
}
|
|
1181
|
+
await mcpClient.connect(oauthTransport, {
|
|
1182
|
+
timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
|
|
1183
|
+
});
|
|
1184
|
+
// Connection successful with OAuth
|
|
1185
|
+
return mcpClient;
|
|
927
1186
|
}
|
|
928
1187
|
else {
|
|
929
1188
|
throw new Error(`OAuth configuration failed for '${mcpServerName}'. Please authenticate manually with /mcp auth ${mcpServerName}`);
|
|
@@ -936,24 +1195,39 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
936
1195
|
}
|
|
937
1196
|
else {
|
|
938
1197
|
// Handle other connection errors
|
|
939
|
-
//
|
|
940
|
-
|
|
941
|
-
const isNetworkError = errorMessage.includes('ENOTFOUND') ||
|
|
942
|
-
errorMessage.includes('ECONNREFUSED');
|
|
943
|
-
let conciseError;
|
|
944
|
-
if (isNetworkError) {
|
|
945
|
-
conciseError = `Cannot connect to '${mcpServerName}' - server may be down or URL incorrect`;
|
|
946
|
-
}
|
|
947
|
-
else {
|
|
948
|
-
conciseError = `Connection failed for '${mcpServerName}': ${errorMessage}`;
|
|
949
|
-
}
|
|
950
|
-
if (process.env['SANDBOX']) {
|
|
951
|
-
conciseError += ` (check sandbox availability)`;
|
|
952
|
-
}
|
|
953
|
-
throw new Error(conciseError);
|
|
1198
|
+
// Re-throw the original error to preserve its structure
|
|
1199
|
+
throw error;
|
|
954
1200
|
}
|
|
955
1201
|
}
|
|
956
1202
|
}
|
|
1203
|
+
/**
|
|
1204
|
+
* Helper function to create the appropriate transport based on config
|
|
1205
|
+
* This handles the logic for httpUrl/url/type consistently
|
|
1206
|
+
*/
|
|
1207
|
+
function createUrlTransport(mcpServerName, mcpServerConfig, transportOptions) {
|
|
1208
|
+
// Priority 1: httpUrl (deprecated)
|
|
1209
|
+
if (mcpServerConfig.httpUrl) {
|
|
1210
|
+
if (mcpServerConfig.url) {
|
|
1211
|
+
debugLogger.warn(`MCP server '${mcpServerName}': Both 'httpUrl' and 'url' are configured. ` +
|
|
1212
|
+
`Using deprecated 'httpUrl'. Please migrate to 'url' with 'type: "http"'.`);
|
|
1213
|
+
}
|
|
1214
|
+
return new StreamableHTTPClientTransport(new URL(mcpServerConfig.httpUrl), transportOptions);
|
|
1215
|
+
}
|
|
1216
|
+
// Priority 2 & 3: url with explicit type
|
|
1217
|
+
if (mcpServerConfig.url && mcpServerConfig.type) {
|
|
1218
|
+
if (mcpServerConfig.type === 'http') {
|
|
1219
|
+
return new StreamableHTTPClientTransport(new URL(mcpServerConfig.url), transportOptions);
|
|
1220
|
+
}
|
|
1221
|
+
else if (mcpServerConfig.type === 'sse') {
|
|
1222
|
+
return new SSEClientTransport(new URL(mcpServerConfig.url), transportOptions);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
// Priority 4: url without type (default to HTTP)
|
|
1226
|
+
if (mcpServerConfig.url) {
|
|
1227
|
+
return new StreamableHTTPClientTransport(new URL(mcpServerConfig.url), transportOptions);
|
|
1228
|
+
}
|
|
1229
|
+
throw new Error(`No URL configured for MCP server '${mcpServerName}'`);
|
|
1230
|
+
}
|
|
957
1231
|
/** Visible for Testing */
|
|
958
1232
|
export async function createTransport(mcpServerName, mcpServerConfig, debugMode) {
|
|
959
1233
|
const noUrl = !mcpServerConfig.url && !mcpServerConfig.httpUrl;
|
|
@@ -970,35 +1244,26 @@ export async function createTransport(mcpServerName, mcpServerConfig, debugMode)
|
|
|
970
1244
|
const authProvider = createAuthProvider(mcpServerConfig);
|
|
971
1245
|
const headers = (await authProvider?.getRequestHeaders?.()) ?? {};
|
|
972
1246
|
let accessToken = null;
|
|
973
|
-
|
|
1247
|
+
const hasOAuthConfig = mcpServerConfig.oauth?.enabled;
|
|
974
1248
|
if (authProvider === undefined) {
|
|
975
1249
|
// Check if we have OAuth configuration or stored tokens
|
|
976
|
-
if (
|
|
1250
|
+
if (mcpServerConfig.oauth?.enabled && mcpServerConfig.oauth) {
|
|
977
1251
|
const tokenStorage = new MCPOAuthTokenStorage();
|
|
978
1252
|
const mcpAuthProvider = new MCPOAuthProvider(tokenStorage);
|
|
979
1253
|
accessToken = await mcpAuthProvider.getValidToken(mcpServerName, mcpServerConfig.oauth);
|
|
980
1254
|
if (!accessToken) {
|
|
981
|
-
|
|
982
|
-
|
|
1255
|
+
// Emit info message (not error) since this is expected behavior
|
|
1256
|
+
coreEvents.emitFeedback('info', `MCP server '${mcpServerName}' requires authentication using: /mcp auth ${mcpServerName}`);
|
|
983
1257
|
}
|
|
984
1258
|
}
|
|
985
1259
|
else {
|
|
986
1260
|
// Check if we have stored OAuth tokens for this server (from previous authentication)
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
const mcpAuthProvider = new MCPOAuthProvider(tokenStorage);
|
|
991
|
-
accessToken = await mcpAuthProvider.getValidToken(mcpServerName, {
|
|
992
|
-
// Pass client ID if available
|
|
993
|
-
clientId: credentials.clientId,
|
|
994
|
-
});
|
|
995
|
-
if (accessToken) {
|
|
996
|
-
hasOAuthConfig = true;
|
|
997
|
-
debugLogger.log(`Found stored OAuth token for server '${mcpServerName}'`);
|
|
998
|
-
}
|
|
1261
|
+
accessToken = await getStoredOAuthToken(mcpServerName);
|
|
1262
|
+
if (accessToken) {
|
|
1263
|
+
debugLogger.log(`Found stored OAuth token for server '${mcpServerName}'`);
|
|
999
1264
|
}
|
|
1000
1265
|
}
|
|
1001
|
-
if (
|
|
1266
|
+
if (accessToken) {
|
|
1002
1267
|
headers['Authorization'] = `Bearer ${accessToken}`;
|
|
1003
1268
|
}
|
|
1004
1269
|
}
|
|
@@ -1016,7 +1281,7 @@ export async function createTransport(mcpServerName, mcpServerConfig, debugMode)
|
|
|
1016
1281
|
};
|
|
1017
1282
|
}
|
|
1018
1283
|
await applyAgentAuthHeaderIfNeeded(mcpServerConfig, transportOptions);
|
|
1019
|
-
return createUrlTransport(mcpServerConfig, transportOptions);
|
|
1284
|
+
return createUrlTransport(mcpServerName, mcpServerConfig, transportOptions);
|
|
1020
1285
|
}
|
|
1021
1286
|
if (mcpServerConfig.command) {
|
|
1022
1287
|
const transport = new StdioClientTransport({
|