@machina.ai/cell-cli-core 1.19.4-rc3 → 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 +12 -17
- package/dist/src/agents/executor.js.map +1 -1
- package/dist/src/agents/executor.test.js +8 -9
- 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 +2 -1
- package/dist/src/availability/modelAvailabilityService.js +5 -2
- package/dist/src/availability/modelAvailabilityService.js.map +1 -1
- package/dist/src/availability/modelAvailabilityService.test.js +3 -3
- package/dist/src/availability/modelAvailabilityService.test.js.map +1 -1
- package/dist/src/availability/modelPolicy.d.ts +8 -1
- package/dist/src/availability/policyCatalog.d.ts +4 -1
- package/dist/src/availability/policyCatalog.js +8 -9
- 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 +51 -0
- package/dist/src/availability/policyHelpers.js +145 -0
- package/dist/src/availability/policyHelpers.js.map +1 -0
- package/dist/src/availability/policyHelpers.test.d.ts +6 -0
- package/dist/src/availability/policyHelpers.test.js +172 -0
- package/dist/src/availability/policyHelpers.test.js.map +1 -0
- 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 +3 -2
- 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/experiments/experiments.js +2 -2
- package/dist/src/code_assist/experiments/experiments.js.map +1 -1
- package/dist/src/code_assist/oauth2.d.ts +2 -0
- package/dist/src/code_assist/oauth2.js +41 -15
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +114 -7
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +2 -1
- package/dist/src/code_assist/server.js +7 -4
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +24 -0
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/types.d.ts +14 -0
- 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 +43 -3
- package/dist/src/config/config.js +182 -29
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +217 -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/AuthenticatedContentGenerator.js +4 -4
- package/dist/src/core/AuthenticatedContentGenerator.js.map +1 -1
- 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 +52 -51
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +178 -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/coreToolHookTriggers.d.ts +55 -0
- package/dist/src/core/coreToolHookTriggers.js +244 -0
- package/dist/src/core/coreToolHookTriggers.js.map +1 -0
- package/dist/src/core/coreToolScheduler.d.ts +1 -1
- package/dist/src/core/coreToolScheduler.js +87 -36
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +201 -38
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.js +144 -41
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +251 -192
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/geminiChatHookTriggers.d.ts +64 -0
- package/dist/src/core/geminiChatHookTriggers.js +136 -0
- package/dist/src/core/geminiChatHookTriggers.js.map +1 -0
- 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/loggingContentGenerator.js +9 -4
- package/dist/src/core/loggingContentGenerator.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 +50 -29
- 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 +82 -69
- package/dist/src/fallback/handler.js.map +1 -1
- package/dist/src/fallback/handler.test.js +186 -170
- package/dist/src/fallback/handler.test.js.map +1 -1
- package/dist/src/fallback/types.d.ts +8 -0
- 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 +70 -12
- 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 +19 -3
- package/dist/src/hooks/hookRunner.js.map +1 -1
- package/dist/src/hooks/hookRunner.test.js +2 -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 +124 -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 +5 -3
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-client.test.js +17 -0
- package/dist/src/ide/ide-client.test.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 +10 -0
- package/dist/src/index.js +10 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/auth-provider.d.ts +16 -0
- package/dist/src/mcp/auth-provider.js +7 -0
- package/dist/src/mcp/auth-provider.js.map +1 -0
- package/dist/src/mcp/google-auth-provider.d.ts +10 -2
- package/dist/src/mcp/google-auth-provider.js +28 -0
- package/dist/src/mcp/google-auth-provider.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.test.js +45 -0
- package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
- package/dist/src/mcp/mcpLauncher.js +6 -3
- package/dist/src/mcp/mcpLauncher.js.map +1 -1
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/sa-impersonation-provider.d.ts +2 -2
- package/dist/src/mcp/sa-impersonation-provider.js.map +1 -1
- package/dist/src/mcp/token-storage/hybrid-token-storage.js +1 -1
- package/dist/src/mcp/token-storage/hybrid-token-storage.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/policies/read-only.toml +5 -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 +17 -3
- package/dist/src/services/chatCompressionService.js.map +1 -1
- package/dist/src/services/chatCompressionService.test.js +9 -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/contextManager.d.ts +35 -0
- package/dist/src/services/contextManager.js +68 -0
- package/dist/src/services/contextManager.js.map +1 -0
- package/dist/src/services/contextManager.test.d.ts +6 -0
- package/dist/src/services/contextManager.test.js +105 -0
- package/dist/src/services/contextManager.test.js.map +1 -0
- 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 +3 -3
- 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 +56 -22
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +137 -5
- 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 +2 -1
- package/dist/src/telemetry/index.js +2 -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 -338
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +195 -18
- 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.d.ts +51 -0
- package/dist/src/telemetry/startupProfiler.js +170 -0
- package/dist/src/telemetry/startupProfiler.js.map +1 -0
- package/dist/src/telemetry/startupProfiler.test.d.ts +6 -0
- package/dist/src/telemetry/startupProfiler.test.js +289 -0
- package/dist/src/telemetry/startupProfiler.test.js.map +1 -0
- 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 +2 -2
- package/dist/src/telemetry/trace.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +37 -10
- package/dist/src/telemetry/types.js +82 -17
- 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 +3 -1
- package/dist/src/tools/mcp-client-manager.js +30 -4
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +38 -10
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +40 -3
- package/dist/src/tools/mcp-client.js +437 -174
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +695 -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 +58 -4
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +25 -5
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.js +6 -1
- 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 +18 -5
- 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/exitCodes.d.ts +12 -0
- package/dist/src/utils/exitCodes.js +13 -0
- package/dist/src/utils/exitCodes.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/memoryDiscovery.d.ts +5 -0
- package/dist/src/utils/memoryDiscovery.js +7 -3
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +28 -0
- package/dist/src/utils/memoryDiscovery.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/stdio.d.ts +2 -2
- package/dist/src/utils/stdio.js +2 -2
- package/dist/src/utils/stdio.js.map +1 -1
- package/dist/src/utils/stdio.test.js +5 -5
- package/dist/src/utils/stdio.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/tokenCalculation.d.ts +19 -0
- package/dist/src/utils/tokenCalculation.js +70 -0
- package/dist/src/utils/tokenCalculation.js.map +1 -0
- package/dist/src/utils/tokenCalculation.test.d.ts +6 -0
- package/dist/src/utils/tokenCalculation.test.js +78 -0
- package/dist/src/utils/tokenCalculation.test.js.map +1 -0
- 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,17 +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
|
}
|
|
297
|
+
getInstructions() {
|
|
298
|
+
return this.client?.getInstructions();
|
|
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
|
+
}
|
|
199
353
|
}
|
|
200
354
|
/**
|
|
201
355
|
* Map to track the status of each MCP server within the core package
|
|
@@ -354,21 +508,6 @@ function createAuthProvider(mcpServerConfig) {
|
|
|
354
508
|
}
|
|
355
509
|
return undefined;
|
|
356
510
|
}
|
|
357
|
-
/**
|
|
358
|
-
* Create a transport for URL based servers (remote servers).
|
|
359
|
-
*
|
|
360
|
-
* @param mcpServerConfig The MCP server configuration
|
|
361
|
-
* @param transportOptions The transport options
|
|
362
|
-
*/
|
|
363
|
-
function createUrlTransport(mcpServerConfig, transportOptions) {
|
|
364
|
-
if (mcpServerConfig.httpUrl) {
|
|
365
|
-
return new StreamableHTTPClientTransport(new URL(mcpServerConfig.httpUrl), transportOptions);
|
|
366
|
-
}
|
|
367
|
-
if (mcpServerConfig.url) {
|
|
368
|
-
return new SSEClientTransport(new URL(mcpServerConfig.url), transportOptions);
|
|
369
|
-
}
|
|
370
|
-
throw new Error('No URL configured for MCP Server');
|
|
371
|
-
}
|
|
372
511
|
/**
|
|
373
512
|
* Create a transport with OAuth token for the given server configuration.
|
|
374
513
|
*
|
|
@@ -385,7 +524,7 @@ async function createTransportWithOAuth(mcpServerName, mcpServerConfig, accessTo
|
|
|
385
524
|
const transportOptions = {
|
|
386
525
|
requestInit: createTransportRequestInit(mcpServerConfig, headers),
|
|
387
526
|
};
|
|
388
|
-
return createUrlTransport(mcpServerConfig, transportOptions);
|
|
527
|
+
return createUrlTransport(mcpServerName, mcpServerConfig, transportOptions);
|
|
389
528
|
}
|
|
390
529
|
catch (error) {
|
|
391
530
|
coreEvents.emitFeedback('error', `Failed to create OAuth transport for server '${mcpServerName}': ${getErrorMessage(error)}`, error);
|
|
@@ -477,7 +616,7 @@ export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolReg
|
|
|
477
616
|
};
|
|
478
617
|
// Attempt to discover both prompts and tools
|
|
479
618
|
const prompts = await discoverPrompts(mcpServerName, mcpClient, promptRegistry);
|
|
480
|
-
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 });
|
|
481
620
|
// If we have neither prompts nor tools, it's a failed discovery
|
|
482
621
|
if (prompts.length === 0 && tools.length === 0) {
|
|
483
622
|
throw new Error('No prompts or tools found on the server.');
|
|
@@ -492,6 +631,7 @@ export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolReg
|
|
|
492
631
|
}
|
|
493
632
|
catch (error) {
|
|
494
633
|
if (mcpClient) {
|
|
634
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
495
635
|
mcpClient.close();
|
|
496
636
|
}
|
|
497
637
|
coreEvents.emitFeedback('error', `Error connecting to MCP server '${mcpServerName}': ${getErrorMessage(error)}`, error);
|
|
@@ -511,12 +651,12 @@ export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolReg
|
|
|
511
651
|
* @returns A promise that resolves to an array of discovered and enabled tools.
|
|
512
652
|
* @throws An error if no enabled tools are found or if the server provides invalid function declarations.
|
|
513
653
|
*/
|
|
514
|
-
export async function discoverTools(mcpServerName, mcpServerConfig, mcpClient, cliConfig, messageBus) {
|
|
654
|
+
export async function discoverTools(mcpServerName, mcpServerConfig, mcpClient, cliConfig, messageBus, options) {
|
|
515
655
|
try {
|
|
516
656
|
// Only request tools if the server supports them.
|
|
517
657
|
if (mcpClient.getServerCapabilities()?.tools == null)
|
|
518
658
|
return [];
|
|
519
|
-
const response = await mcpClient.listTools({});
|
|
659
|
+
const response = await mcpClient.listTools({}, options);
|
|
520
660
|
const discoveredTools = [];
|
|
521
661
|
for (const toolDef of response.tools) {
|
|
522
662
|
try {
|
|
@@ -631,6 +771,35 @@ export async function discoverPrompts(mcpServerName, mcpClient, promptRegistry)
|
|
|
631
771
|
return [];
|
|
632
772
|
}
|
|
633
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
|
+
}
|
|
634
803
|
/**
|
|
635
804
|
* Invokes a prompt on a connected MCP client.
|
|
636
805
|
*
|
|
@@ -671,6 +840,116 @@ export async function invokeMcpPrompt(mcpServerName, mcpClient, promptName, prom
|
|
|
671
840
|
export function hasNetworkTransport(config) {
|
|
672
841
|
return !!(config.url || config.httpUrl);
|
|
673
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
|
+
}
|
|
674
953
|
/**
|
|
675
954
|
* Creates and connects an MCP client to a server based on the provided configuration.
|
|
676
955
|
* It determines the appropriate transport (Stdio, SSE, or Streamable HTTP) and
|
|
@@ -730,6 +1009,9 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
730
1009
|
unlistenDirectories?.();
|
|
731
1010
|
unlistenDirectories = undefined;
|
|
732
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
|
|
733
1015
|
try {
|
|
734
1016
|
const transport = await createTransport(mcpServerName, mcpServerConfig, debugMode);
|
|
735
1017
|
try {
|
|
@@ -740,52 +1022,92 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
740
1022
|
}
|
|
741
1023
|
catch (error) {
|
|
742
1024
|
await transport.close();
|
|
1025
|
+
firstAttemptError = error;
|
|
743
1026
|
throw error;
|
|
744
1027
|
}
|
|
745
1028
|
}
|
|
746
|
-
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
|
+
}
|
|
747
1071
|
// Check if this is a 401 error that might indicate OAuth is required
|
|
748
|
-
|
|
749
|
-
if (errorString.includes('401') && hasNetworkTransport(mcpServerConfig)) {
|
|
1072
|
+
if (isAuthenticationError(error) && hasNetworkTransport(mcpServerConfig)) {
|
|
750
1073
|
mcpServerRequiresOAuth.set(mcpServerName, true);
|
|
751
|
-
// Only trigger automatic OAuth
|
|
752
|
-
//
|
|
753
|
-
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;
|
|
754
1077
|
if (!shouldTriggerOAuth) {
|
|
755
|
-
|
|
756
|
-
const tokenStorage = new MCPOAuthTokenStorage();
|
|
757
|
-
const credentials = await tokenStorage.getCredentials(mcpServerName);
|
|
758
|
-
if (credentials) {
|
|
759
|
-
const authProvider = new MCPOAuthProvider(tokenStorage);
|
|
760
|
-
const hasStoredTokens = await authProvider.getValidToken(mcpServerName, {
|
|
761
|
-
// Pass client ID if available
|
|
762
|
-
clientId: credentials.clientId,
|
|
763
|
-
});
|
|
764
|
-
if (hasStoredTokens) {
|
|
765
|
-
coreEvents.emitFeedback('error', `Stored OAuth token for SSE server '${mcpServerName}' was rejected. ` +
|
|
766
|
-
`Please re-authenticate using: /mcp auth ${mcpServerName}`);
|
|
767
|
-
}
|
|
768
|
-
else {
|
|
769
|
-
coreEvents.emitFeedback('error', `401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
|
|
770
|
-
`Please authenticate using: /mcp auth ${mcpServerName}`);
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
throw new Error(`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
|
|
774
|
-
`Please authenticate using: /mcp auth ${mcpServerName}`);
|
|
1078
|
+
await showAuthRequiredMessage(mcpServerName);
|
|
775
1079
|
}
|
|
776
1080
|
// Try to extract www-authenticate header from the error
|
|
1081
|
+
const errorString = String(error);
|
|
777
1082
|
let wwwAuthenticate = extractWWWAuthenticateHeader(errorString);
|
|
778
1083
|
// If we didn't get the header from the error string, try to get it from the server
|
|
779
1084
|
if (!wwwAuthenticate && hasNetworkTransport(mcpServerConfig)) {
|
|
780
1085
|
debugLogger.log(`No www-authenticate header in error, trying to fetch it from server...`);
|
|
781
1086
|
try {
|
|
782
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
|
+
}
|
|
783
1107
|
const response = await fetch(urlToFetch, {
|
|
784
1108
|
method: 'HEAD',
|
|
785
1109
|
headers: {
|
|
786
|
-
Accept:
|
|
787
|
-
? 'application/json'
|
|
788
|
-
: 'text/event-stream',
|
|
1110
|
+
Accept: acceptHeader,
|
|
789
1111
|
},
|
|
790
1112
|
signal: AbortSignal.timeout(5000),
|
|
791
1113
|
});
|
|
@@ -806,38 +1128,12 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
806
1128
|
const oauthSuccess = await handleAutomaticOAuth(mcpServerName, mcpServerConfig, wwwAuthenticate);
|
|
807
1129
|
if (oauthSuccess) {
|
|
808
1130
|
// Retry connection with OAuth token
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
const tokenStorage = new MCPOAuthTokenStorage();
|
|
813
|
-
const credentials = await tokenStorage.getCredentials(mcpServerName);
|
|
814
|
-
if (credentials) {
|
|
815
|
-
const authProvider = new MCPOAuthProvider(tokenStorage);
|
|
816
|
-
const accessToken = await authProvider.getValidToken(mcpServerName, {
|
|
817
|
-
// Pass client ID if available
|
|
818
|
-
clientId: credentials.clientId,
|
|
819
|
-
});
|
|
820
|
-
if (accessToken) {
|
|
821
|
-
// Create transport with OAuth token
|
|
822
|
-
const oauthTransport = await createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken);
|
|
823
|
-
if (oauthTransport) {
|
|
824
|
-
await mcpClient.connect(oauthTransport, {
|
|
825
|
-
timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
|
|
826
|
-
});
|
|
827
|
-
// Connection successful with OAuth
|
|
828
|
-
return mcpClient;
|
|
829
|
-
}
|
|
830
|
-
else {
|
|
831
|
-
throw new Error(`Failed to create OAuth transport for server '${mcpServerName}'`);
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
else {
|
|
835
|
-
throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
else {
|
|
839
|
-
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}'`);
|
|
840
1134
|
}
|
|
1135
|
+
await retryWithOAuth(mcpClient, mcpServerName, mcpServerConfig, accessToken, httpReturned404);
|
|
1136
|
+
return mcpClient;
|
|
841
1137
|
}
|
|
842
1138
|
else {
|
|
843
1139
|
throw new Error(`Failed to handle automatic OAuth for server '${mcpServerName}'`);
|
|
@@ -845,29 +1141,10 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
845
1141
|
}
|
|
846
1142
|
else {
|
|
847
1143
|
// No www-authenticate header found, but we got a 401
|
|
848
|
-
// Only try OAuth discovery
|
|
849
|
-
|
|
850
|
-
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;
|
|
851
1146
|
if (!shouldTryDiscovery) {
|
|
852
|
-
|
|
853
|
-
const credentials = await tokenStorage.getCredentials(mcpServerName);
|
|
854
|
-
if (credentials) {
|
|
855
|
-
const authProvider = new MCPOAuthProvider(tokenStorage);
|
|
856
|
-
const hasStoredTokens = await authProvider.getValidToken(mcpServerName, {
|
|
857
|
-
// Pass client ID if available
|
|
858
|
-
clientId: credentials.clientId,
|
|
859
|
-
});
|
|
860
|
-
if (hasStoredTokens) {
|
|
861
|
-
coreEvents.emitFeedback('error', `Stored OAuth token for SSE server '${mcpServerName}' was rejected. ` +
|
|
862
|
-
`Please re-authenticate using: /mcp auth ${mcpServerName}`);
|
|
863
|
-
}
|
|
864
|
-
else {
|
|
865
|
-
coreEvents.emitFeedback('error', `401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
|
|
866
|
-
`Please authenticate using: /mcp auth ${mcpServerName}`);
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
throw new Error(`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
|
|
870
|
-
`Please authenticate using: /mcp auth ${mcpServerName}`);
|
|
1147
|
+
await showAuthRequiredMessage(mcpServerName);
|
|
871
1148
|
}
|
|
872
1149
|
// For SSE/HTTP servers, try to discover OAuth configuration from the base URL
|
|
873
1150
|
debugLogger.log(`🔍 Attempting OAuth discovery for '${mcpServerName}'...`);
|
|
@@ -892,35 +1169,20 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
892
1169
|
const authProvider = new MCPOAuthProvider(new MCPOAuthTokenStorage());
|
|
893
1170
|
await authProvider.authenticate(mcpServerName, oauthAuthConfig, authServerUrl);
|
|
894
1171
|
// Retry connection with OAuth token
|
|
895
|
-
const
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
const authProvider = new MCPOAuthProvider(tokenStorage);
|
|
899
|
-
const accessToken = await authProvider.getValidToken(mcpServerName, {
|
|
900
|
-
// Pass client ID if available
|
|
901
|
-
clientId: credentials.clientId,
|
|
902
|
-
});
|
|
903
|
-
if (accessToken) {
|
|
904
|
-
// Create transport with OAuth token
|
|
905
|
-
const oauthTransport = await createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken);
|
|
906
|
-
if (oauthTransport) {
|
|
907
|
-
await mcpClient.connect(oauthTransport, {
|
|
908
|
-
timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
|
|
909
|
-
});
|
|
910
|
-
// Connection successful with OAuth
|
|
911
|
-
return mcpClient;
|
|
912
|
-
}
|
|
913
|
-
else {
|
|
914
|
-
throw new Error(`Failed to create OAuth transport for server '${mcpServerName}'`);
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
else {
|
|
918
|
-
throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
|
|
919
|
-
}
|
|
1172
|
+
const accessToken = await getStoredOAuthToken(mcpServerName);
|
|
1173
|
+
if (!accessToken) {
|
|
1174
|
+
throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
|
|
920
1175
|
}
|
|
921
|
-
|
|
922
|
-
|
|
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}'`);
|
|
923
1180
|
}
|
|
1181
|
+
await mcpClient.connect(oauthTransport, {
|
|
1182
|
+
timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
|
|
1183
|
+
});
|
|
1184
|
+
// Connection successful with OAuth
|
|
1185
|
+
return mcpClient;
|
|
924
1186
|
}
|
|
925
1187
|
else {
|
|
926
1188
|
throw new Error(`OAuth configuration failed for '${mcpServerName}'. Please authenticate manually with /mcp auth ${mcpServerName}`);
|
|
@@ -933,24 +1195,39 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
|
|
|
933
1195
|
}
|
|
934
1196
|
else {
|
|
935
1197
|
// Handle other connection errors
|
|
936
|
-
//
|
|
937
|
-
|
|
938
|
-
const isNetworkError = errorMessage.includes('ENOTFOUND') ||
|
|
939
|
-
errorMessage.includes('ECONNREFUSED');
|
|
940
|
-
let conciseError;
|
|
941
|
-
if (isNetworkError) {
|
|
942
|
-
conciseError = `Cannot connect to '${mcpServerName}' - server may be down or URL incorrect`;
|
|
943
|
-
}
|
|
944
|
-
else {
|
|
945
|
-
conciseError = `Connection failed for '${mcpServerName}': ${errorMessage}`;
|
|
946
|
-
}
|
|
947
|
-
if (process.env['SANDBOX']) {
|
|
948
|
-
conciseError += ` (check sandbox availability)`;
|
|
949
|
-
}
|
|
950
|
-
throw new Error(conciseError);
|
|
1198
|
+
// Re-throw the original error to preserve its structure
|
|
1199
|
+
throw error;
|
|
951
1200
|
}
|
|
952
1201
|
}
|
|
953
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
|
+
}
|
|
954
1231
|
/** Visible for Testing */
|
|
955
1232
|
export async function createTransport(mcpServerName, mcpServerConfig, debugMode) {
|
|
956
1233
|
const noUrl = !mcpServerConfig.url && !mcpServerConfig.httpUrl;
|
|
@@ -965,37 +1242,28 @@ export async function createTransport(mcpServerName, mcpServerConfig, debugMode)
|
|
|
965
1242
|
}
|
|
966
1243
|
if (mcpServerConfig.httpUrl || mcpServerConfig.url) {
|
|
967
1244
|
const authProvider = createAuthProvider(mcpServerConfig);
|
|
968
|
-
const headers = {};
|
|
1245
|
+
const headers = (await authProvider?.getRequestHeaders?.()) ?? {};
|
|
969
1246
|
let accessToken = null;
|
|
970
|
-
|
|
1247
|
+
const hasOAuthConfig = mcpServerConfig.oauth?.enabled;
|
|
971
1248
|
if (authProvider === undefined) {
|
|
972
1249
|
// Check if we have OAuth configuration or stored tokens
|
|
973
|
-
if (
|
|
1250
|
+
if (mcpServerConfig.oauth?.enabled && mcpServerConfig.oauth) {
|
|
974
1251
|
const tokenStorage = new MCPOAuthTokenStorage();
|
|
975
1252
|
const mcpAuthProvider = new MCPOAuthProvider(tokenStorage);
|
|
976
1253
|
accessToken = await mcpAuthProvider.getValidToken(mcpServerName, mcpServerConfig.oauth);
|
|
977
1254
|
if (!accessToken) {
|
|
978
|
-
|
|
979
|
-
|
|
1255
|
+
// Emit info message (not error) since this is expected behavior
|
|
1256
|
+
coreEvents.emitFeedback('info', `MCP server '${mcpServerName}' requires authentication using: /mcp auth ${mcpServerName}`);
|
|
980
1257
|
}
|
|
981
1258
|
}
|
|
982
1259
|
else {
|
|
983
1260
|
// Check if we have stored OAuth tokens for this server (from previous authentication)
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
const mcpAuthProvider = new MCPOAuthProvider(tokenStorage);
|
|
988
|
-
accessToken = await mcpAuthProvider.getValidToken(mcpServerName, {
|
|
989
|
-
// Pass client ID if available
|
|
990
|
-
clientId: credentials.clientId,
|
|
991
|
-
});
|
|
992
|
-
if (accessToken) {
|
|
993
|
-
hasOAuthConfig = true;
|
|
994
|
-
debugLogger.log(`Found stored OAuth token for server '${mcpServerName}'`);
|
|
995
|
-
}
|
|
1261
|
+
accessToken = await getStoredOAuthToken(mcpServerName);
|
|
1262
|
+
if (accessToken) {
|
|
1263
|
+
debugLogger.log(`Found stored OAuth token for server '${mcpServerName}'`);
|
|
996
1264
|
}
|
|
997
1265
|
}
|
|
998
|
-
if (
|
|
1266
|
+
if (accessToken) {
|
|
999
1267
|
headers['Authorization'] = `Bearer ${accessToken}`;
|
|
1000
1268
|
}
|
|
1001
1269
|
}
|
|
@@ -1012,13 +1280,8 @@ export async function createTransport(mcpServerName, mcpServerConfig, debugMode)
|
|
|
1012
1280
|
},
|
|
1013
1281
|
};
|
|
1014
1282
|
}
|
|
1015
|
-
else if (mcpServerConfig.headers) {
|
|
1016
|
-
transportOptions.requestInit = {
|
|
1017
|
-
headers: mcpServerConfig.headers,
|
|
1018
|
-
};
|
|
1019
|
-
}
|
|
1020
1283
|
await applyAgentAuthHeaderIfNeeded(mcpServerConfig, transportOptions);
|
|
1021
|
-
return createUrlTransport(mcpServerConfig, transportOptions);
|
|
1284
|
+
return createUrlTransport(mcpServerName, mcpServerConfig, transportOptions);
|
|
1022
1285
|
}
|
|
1023
1286
|
if (mcpServerConfig.command) {
|
|
1024
1287
|
const transport = new StdioClientTransport({
|