@akon-labs/nexus-cli 0.1.9 → 0.1.11-rc.2
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/CHANGELOG.md +21 -0
- package/LICENSE +1 -0
- package/README.md +3 -2
- package/dist/app-bridge.bundle.js +67 -0
- package/dist/cli/require-login.d.ts.map +1 -1
- package/dist/cli/require-login.js +2 -2
- package/dist/cli/require-login.js.map +1 -1
- package/dist/cli.js +20866 -1882
- package/dist/core/agent-session.d.ts +3 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +5 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auto-model.d.ts +1 -1
- package/dist/core/auto-model.d.ts.map +1 -1
- package/dist/core/auto-model.js +1 -1
- package/dist/core/auto-model.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +6 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +7 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +14 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +18 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-resolver.d.ts +2 -2
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +3 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +15 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +50 -0
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +3 -3
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +5 -5
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/websearch.d.ts.map +1 -1
- package/dist/core/tools/websearch.js +3 -3
- package/dist/core/tools/websearch.js.map +1 -1
- package/dist/extensions/gitnexus/config.d.ts +15 -1
- package/dist/extensions/gitnexus/config.d.ts.map +1 -1
- package/dist/extensions/gitnexus/config.js +86 -2
- package/dist/extensions/gitnexus/config.js.map +1 -1
- package/dist/extensions/gitnexus/gateway.d.ts +6 -6
- package/dist/extensions/gitnexus/gateway.d.ts.map +1 -1
- package/dist/extensions/gitnexus/gateway.js +4 -4
- package/dist/extensions/gitnexus/gateway.js.map +1 -1
- package/dist/extensions/gitnexus/index.d.ts.map +1 -1
- package/dist/extensions/gitnexus/index.js +6 -4
- package/dist/extensions/gitnexus/index.js.map +1 -1
- package/dist/extensions/gitnexus/observatory.d.ts.map +1 -1
- package/dist/extensions/gitnexus/observatory.js +2 -2
- package/dist/extensions/gitnexus/observatory.js.map +1 -1
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +3 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/mcp/abort.d.ts +3 -0
- package/dist/extensions/mcp/abort.d.ts.map +1 -0
- package/dist/extensions/mcp/abort.js +41 -0
- package/dist/extensions/mcp/abort.js.map +1 -0
- package/dist/extensions/mcp/agent-dir.d.ts +6 -0
- package/dist/extensions/mcp/agent-dir.d.ts.map +1 -0
- package/dist/extensions/mcp/agent-dir.js +18 -0
- package/dist/extensions/mcp/agent-dir.js.map +1 -0
- package/dist/extensions/mcp/agent-plugin-loader.d.ts +9 -0
- package/dist/extensions/mcp/agent-plugin-loader.d.ts.map +1 -0
- package/dist/extensions/mcp/agent-plugin-loader.js +384 -0
- package/dist/extensions/mcp/agent-plugin-loader.js.map +1 -0
- package/dist/extensions/mcp/app-bridge.bundle.js +67 -0
- package/dist/extensions/mcp/commands.d.ts +47 -0
- package/dist/extensions/mcp/commands.d.ts.map +1 -0
- package/dist/extensions/mcp/commands.js +821 -0
- package/dist/extensions/mcp/commands.js.map +1 -0
- package/dist/extensions/mcp/config.d.ts +123 -38
- package/dist/extensions/mcp/config.d.ts.map +1 -1
- package/dist/extensions/mcp/config.js +1035 -70
- package/dist/extensions/mcp/config.js.map +1 -1
- package/dist/extensions/mcp/consent-manager.d.ts +14 -0
- package/dist/extensions/mcp/consent-manager.d.ts.map +1 -0
- package/dist/extensions/mcp/consent-manager.js +60 -0
- package/dist/extensions/mcp/consent-manager.js.map +1 -0
- package/dist/extensions/mcp/direct-tools.d.ts +11 -0
- package/dist/extensions/mcp/direct-tools.d.ts.map +1 -0
- package/dist/extensions/mcp/direct-tools.js +562 -0
- package/dist/extensions/mcp/direct-tools.js.map +1 -0
- package/dist/extensions/mcp/elicitation-handler.d.ts +18 -0
- package/dist/extensions/mcp/elicitation-handler.d.ts.map +1 -0
- package/dist/extensions/mcp/elicitation-handler.js +320 -0
- package/dist/extensions/mcp/elicitation-handler.js.map +1 -0
- package/dist/extensions/mcp/error-signal.d.ts +16 -0
- package/dist/extensions/mcp/error-signal.d.ts.map +1 -0
- package/dist/extensions/mcp/error-signal.js +22 -0
- package/dist/extensions/mcp/error-signal.js.map +1 -0
- package/dist/extensions/mcp/errors.d.ts +104 -0
- package/dist/extensions/mcp/errors.d.ts.map +1 -0
- package/dist/extensions/mcp/errors.js +171 -0
- package/dist/extensions/mcp/errors.js.map +1 -0
- package/dist/extensions/mcp/glimpse-ui.d.ts +10 -0
- package/dist/extensions/mcp/glimpse-ui.d.ts.map +1 -0
- package/dist/extensions/mcp/glimpse-ui.js +67 -0
- package/dist/extensions/mcp/glimpse-ui.js.map +1 -0
- package/dist/extensions/mcp/host-html-template.d.ts +17 -0
- package/dist/extensions/mcp/host-html-template.d.ts.map +1 -0
- package/dist/extensions/mcp/host-html-template.js +442 -0
- package/dist/extensions/mcp/host-html-template.js.map +1 -0
- package/dist/extensions/mcp/index.d.ts +20 -15
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +1113 -82
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/init.d.ts +28 -0
- package/dist/extensions/mcp/init.d.ts.map +1 -0
- package/dist/extensions/mcp/init.js +631 -0
- package/dist/extensions/mcp/init.js.map +1 -0
- package/dist/extensions/mcp/json-schema-validator.d.ts +3 -0
- package/dist/extensions/mcp/json-schema-validator.d.ts.map +1 -0
- package/dist/extensions/mcp/json-schema-validator.js +53 -0
- package/dist/extensions/mcp/json-schema-validator.js.map +1 -0
- package/dist/extensions/mcp/lifecycle.d.ts +56 -0
- package/dist/extensions/mcp/lifecycle.d.ts.map +1 -0
- package/dist/extensions/mcp/lifecycle.js +395 -0
- package/dist/extensions/mcp/lifecycle.js.map +1 -0
- package/dist/extensions/mcp/logger.d.ts +52 -0
- package/dist/extensions/mcp/logger.d.ts.map +1 -0
- package/dist/extensions/mcp/logger.js +134 -0
- package/dist/extensions/mcp/logger.js.map +1 -0
- package/dist/extensions/mcp/mcp-auth-flow.d.ts +117 -0
- package/dist/extensions/mcp/mcp-auth-flow.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-auth-flow.js +869 -0
- package/dist/extensions/mcp/mcp-auth-flow.js.map +1 -0
- package/dist/extensions/mcp/mcp-auth.d.ts +162 -0
- package/dist/extensions/mcp/mcp-auth.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-auth.js +897 -0
- package/dist/extensions/mcp/mcp-auth.js.map +1 -0
- package/dist/extensions/mcp/mcp-bearer-store.d.ts +25 -0
- package/dist/extensions/mcp/mcp-bearer-store.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-bearer-store.js +350 -0
- package/dist/extensions/mcp/mcp-bearer-store.js.map +1 -0
- package/dist/extensions/mcp/mcp-callback-server.d.ts +54 -0
- package/dist/extensions/mcp/mcp-callback-server.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-callback-server.js +454 -0
- package/dist/extensions/mcp/mcp-callback-server.js.map +1 -0
- package/dist/extensions/mcp/mcp-code.d.ts +48 -0
- package/dist/extensions/mcp/mcp-code.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-code.js +358 -0
- package/dist/extensions/mcp/mcp-code.js.map +1 -0
- package/dist/extensions/mcp/mcp-keyring-helper.cjs +89 -0
- package/dist/extensions/mcp/mcp-oauth-provider.d.ts +135 -0
- package/dist/extensions/mcp/mcp-oauth-provider.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-oauth-provider.js +491 -0
- package/dist/extensions/mcp/mcp-oauth-provider.js.map +1 -0
- package/dist/extensions/mcp/mcp-output-guard.d.ts +59 -0
- package/dist/extensions/mcp/mcp-output-guard.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-output-guard.js +343 -0
- package/dist/extensions/mcp/mcp-output-guard.js.map +1 -0
- package/dist/extensions/mcp/mcp-panel.d.ts +71 -0
- package/dist/extensions/mcp/mcp-panel.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-panel.js +973 -0
- package/dist/extensions/mcp/mcp-panel.js.map +1 -0
- package/dist/extensions/mcp/mcp-probe.d.ts +7 -0
- package/dist/extensions/mcp/mcp-probe.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-probe.js +155 -0
- package/dist/extensions/mcp/mcp-probe.js.map +1 -0
- package/dist/extensions/mcp/mcp-script-worker.mjs +130 -0
- package/dist/extensions/mcp/mcp-setup-panel.d.ts +146 -0
- package/dist/extensions/mcp/mcp-setup-panel.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-setup-panel.js +1104 -0
- package/dist/extensions/mcp/mcp-setup-panel.js.map +1 -0
- package/dist/extensions/mcp/mcp-status.d.ts +12 -0
- package/dist/extensions/mcp/mcp-status.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-status.js +98 -0
- package/dist/extensions/mcp/mcp-status.js.map +1 -0
- package/dist/extensions/mcp/mcp-trace.d.ts +95 -0
- package/dist/extensions/mcp/mcp-trace.d.ts.map +1 -0
- package/dist/extensions/mcp/mcp-trace.js +252 -0
- package/dist/extensions/mcp/mcp-trace.js.map +1 -0
- package/dist/extensions/mcp/metadata-cache.d.ts +20 -0
- package/dist/extensions/mcp/metadata-cache.d.ts.map +1 -0
- package/dist/extensions/mcp/metadata-cache.js +318 -0
- package/dist/extensions/mcp/metadata-cache.js.map +1 -0
- package/dist/extensions/mcp/npx-resolver.d.ts +7 -0
- package/dist/extensions/mcp/npx-resolver.d.ts.map +1 -0
- package/dist/extensions/mcp/npx-resolver.js +505 -0
- package/dist/extensions/mcp/npx-resolver.js.map +1 -0
- package/dist/extensions/mcp/oauth.d.ts +21 -0
- package/dist/extensions/mcp/oauth.d.ts.map +1 -0
- package/dist/extensions/mcp/oauth.js +15 -0
- package/dist/extensions/mcp/oauth.js.map +1 -0
- package/dist/extensions/mcp/onboarding-state.d.ts +13 -0
- package/dist/extensions/mcp/onboarding-state.d.ts.map +1 -0
- package/dist/extensions/mcp/onboarding-state.js +65 -0
- package/dist/extensions/mcp/onboarding-state.js.map +1 -0
- package/dist/extensions/mcp/package-mcp-loader.d.ts +3 -0
- package/dist/extensions/mcp/package-mcp-loader.d.ts.map +1 -0
- package/dist/extensions/mcp/package-mcp-loader.js +170 -0
- package/dist/extensions/mcp/package-mcp-loader.js.map +1 -0
- package/dist/extensions/mcp/panel-keys.d.ts +21 -0
- package/dist/extensions/mcp/panel-keys.d.ts.map +1 -0
- package/dist/extensions/mcp/panel-keys.js +29 -0
- package/dist/extensions/mcp/panel-keys.js.map +1 -0
- package/dist/extensions/mcp/prompts.d.ts +63 -0
- package/dist/extensions/mcp/prompts.d.ts.map +1 -0
- package/dist/extensions/mcp/prompts.js +297 -0
- package/dist/extensions/mcp/prompts.js.map +1 -0
- package/dist/extensions/mcp/proxy-modes.d.ts +15 -0
- package/dist/extensions/mcp/proxy-modes.d.ts.map +1 -0
- package/dist/extensions/mcp/proxy-modes.js +1421 -0
- package/dist/extensions/mcp/proxy-modes.js.map +1 -0
- package/dist/extensions/mcp/request-headers-command.d.ts +11 -0
- package/dist/extensions/mcp/request-headers-command.d.ts.map +1 -0
- package/dist/extensions/mcp/request-headers-command.js +334 -0
- package/dist/extensions/mcp/request-headers-command.js.map +1 -0
- package/dist/extensions/mcp/resource-tools.d.ts +2 -0
- package/dist/extensions/mcp/resource-tools.d.ts.map +1 -0
- package/dist/extensions/mcp/resource-tools.js +15 -0
- package/dist/extensions/mcp/resource-tools.js.map +1 -0
- package/dist/extensions/mcp/runtime-owner.d.ts +14 -0
- package/dist/extensions/mcp/runtime-owner.d.ts.map +1 -0
- package/dist/extensions/mcp/runtime-owner.js +84 -0
- package/dist/extensions/mcp/runtime-owner.js.map +1 -0
- package/dist/extensions/mcp/sampling-handler.d.ts +18 -0
- package/dist/extensions/mcp/sampling-handler.d.ts.map +1 -0
- package/dist/extensions/mcp/sampling-handler.js +229 -0
- package/dist/extensions/mcp/sampling-handler.js.map +1 -0
- package/dist/extensions/mcp/search-ranking.d.ts +25 -0
- package/dist/extensions/mcp/search-ranking.d.ts.map +1 -0
- package/dist/extensions/mcp/search-ranking.js +234 -0
- package/dist/extensions/mcp/search-ranking.js.map +1 -0
- package/dist/extensions/mcp/server-manager.d.ts +116 -0
- package/dist/extensions/mcp/server-manager.d.ts.map +1 -0
- package/dist/extensions/mcp/server-manager.js +1052 -0
- package/dist/extensions/mcp/server-manager.js.map +1 -0
- package/dist/extensions/mcp/session-recovery.d.ts +27 -0
- package/dist/extensions/mcp/session-recovery.d.ts.map +1 -0
- package/dist/extensions/mcp/session-recovery.js +140 -0
- package/dist/extensions/mcp/session-recovery.js.map +1 -0
- package/dist/extensions/mcp/skills/mcp-scripting/SKILL.md +38 -0
- package/dist/extensions/mcp/state.d.ts +62 -0
- package/dist/extensions/mcp/state.d.ts.map +1 -0
- package/dist/extensions/mcp/state.js +2 -0
- package/dist/extensions/mcp/state.js.map +1 -0
- package/dist/extensions/mcp/tool-approval.d.ts +11 -0
- package/dist/extensions/mcp/tool-approval.d.ts.map +1 -0
- package/dist/extensions/mcp/tool-approval.js +156 -0
- package/dist/extensions/mcp/tool-approval.js.map +1 -0
- package/dist/extensions/mcp/tool-metadata.d.ts +11 -0
- package/dist/extensions/mcp/tool-metadata.d.ts.map +1 -0
- package/dist/extensions/mcp/tool-metadata.js +264 -0
- package/dist/extensions/mcp/tool-metadata.js.map +1 -0
- package/dist/extensions/mcp/tool-registrar.d.ts +21 -0
- package/dist/extensions/mcp/tool-registrar.d.ts.map +1 -0
- package/dist/extensions/mcp/tool-registrar.js +229 -0
- package/dist/extensions/mcp/tool-registrar.js.map +1 -0
- package/dist/extensions/mcp/tool-result-renderer.d.ts +83 -0
- package/dist/extensions/mcp/tool-result-renderer.d.ts.map +1 -0
- package/dist/extensions/mcp/tool-result-renderer.js +345 -0
- package/dist/extensions/mcp/tool-result-renderer.js.map +1 -0
- package/dist/extensions/mcp/ts-shape.d.ts +3 -0
- package/dist/extensions/mcp/ts-shape.d.ts.map +1 -0
- package/dist/extensions/mcp/ts-shape.js +160 -0
- package/dist/extensions/mcp/ts-shape.js.map +1 -0
- package/dist/extensions/mcp/types.d.ts +521 -0
- package/dist/extensions/mcp/types.d.ts.map +1 -0
- package/dist/extensions/mcp/types.js +294 -0
- package/dist/extensions/mcp/types.js.map +1 -0
- package/dist/extensions/mcp/ui-app-bridge-helpers.d.ts +7 -0
- package/dist/extensions/mcp/ui-app-bridge-helpers.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-app-bridge-helpers.js +37 -0
- package/dist/extensions/mcp/ui-app-bridge-helpers.js.map +1 -0
- package/dist/extensions/mcp/ui-resource-handler.d.ts +18 -0
- package/dist/extensions/mcp/ui-resource-handler.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-resource-handler.js +210 -0
- package/dist/extensions/mcp/ui-resource-handler.js.map +1 -0
- package/dist/extensions/mcp/ui-server.d.ts +52 -0
- package/dist/extensions/mcp/ui-server.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-server.js +740 -0
- package/dist/extensions/mcp/ui-server.js.map +1 -0
- package/dist/extensions/mcp/ui-session.d.ts +40 -0
- package/dist/extensions/mcp/ui-session.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-session.js +477 -0
- package/dist/extensions/mcp/ui-session.js.map +1 -0
- package/dist/extensions/mcp/ui-stream-types.d.ts +105 -0
- package/dist/extensions/mcp/ui-stream-types.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-stream-types.js +61 -0
- package/dist/extensions/mcp/ui-stream-types.js.map +1 -0
- package/dist/extensions/mcp/ui-tool-visibility.d.ts +5 -0
- package/dist/extensions/mcp/ui-tool-visibility.d.ts.map +1 -0
- package/dist/extensions/mcp/ui-tool-visibility.js +27 -0
- package/dist/extensions/mcp/ui-tool-visibility.js.map +1 -0
- package/dist/extensions/mcp/unix-socket-transport.d.ts +15 -0
- package/dist/extensions/mcp/unix-socket-transport.d.ts.map +1 -0
- package/dist/extensions/mcp/unix-socket-transport.js +85 -0
- package/dist/extensions/mcp/unix-socket-transport.js.map +1 -0
- package/dist/extensions/mcp/utils.d.ts +32 -0
- package/dist/extensions/mcp/utils.d.ts.map +1 -0
- package/dist/extensions/mcp/utils.js +336 -0
- package/dist/extensions/mcp/utils.js.map +1 -0
- package/dist/extensions/subagent/index.d.ts +62 -1
- package/dist/extensions/subagent/index.d.ts.map +1 -1
- package/dist/extensions/subagent/index.js +195 -9
- package/dist/extensions/subagent/index.js.map +1 -1
- package/dist/extensions/subagent-render.d.ts +3 -0
- package/dist/extensions/subagent-render.d.ts.map +1 -0
- package/dist/extensions/subagent-render.js +39 -0
- package/dist/extensions/subagent-render.js.map +1 -0
- package/dist/extensions/web-access.d.ts.map +1 -1
- package/dist/extensions/web-access.js +1 -1
- package/dist/extensions/web-access.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20992 -2003
- package/dist/index.js.map +1 -1
- package/dist/mcp-keyring-helper.cjs +89 -0
- package/dist/mcp-script-worker.mjs +130 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +1 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/response-separator.d.ts +1 -1
- package/dist/modes/interactive/components/response-separator.d.ts.map +1 -1
- package/dist/modes/interactive/components/response-separator.js +1 -1
- package/dist/modes/interactive/components/response-separator.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +3 -2
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +12 -2
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +14 -8
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/rpc-entry.js +20866 -1882
- package/dist/skills/mcp-scripting/SKILL.md +38 -0
- package/dist/utils/hidden-spawn.d.ts +29 -0
- package/dist/utils/hidden-spawn.d.ts.map +1 -0
- package/dist/utils/hidden-spawn.js +101 -0
- package/dist/utils/hidden-spawn.js.map +1 -0
- package/dist/vendor/ai.js +110 -35
- package/docs/mcp.md +178 -0
- package/docs/pi-subagents.md +75 -0
- package/docs/quickstart.md +1 -1
- package/docs/usage.md +2 -1
- package/examples/extensions/pi-subagents-worker-policy.ts +86 -0
- package/native/win32/build.mjs +95 -0
- package/native/win32/prebuilds/win32-x64/hidden-spawn.exe +0 -0
- package/native/win32/src/hidden-spawn.c +157 -0
- package/npm-shrinkwrap.json +728 -6
- package/package.json +21 -6
- package/dist/extensions/mcp/client.d.ts +0 -86
- package/dist/extensions/mcp/client.d.ts.map +0 -1
- package/dist/extensions/mcp/client.js +0 -275
- package/dist/extensions/mcp/client.js.map +0 -1
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP OAuth Provider
|
|
3
|
+
*
|
|
4
|
+
* Implementation of the MCP SDK's OAuthClientProvider interface.
|
|
5
|
+
* Handles OAuth client registration, token storage, and authorization redirection.
|
|
6
|
+
*/
|
|
7
|
+
import { UnauthorizedError, } from "@modelcontextprotocol/client";
|
|
8
|
+
import { getAppClientUri, getAppName } from "./agent-dir.js";
|
|
9
|
+
import { clearAllCredentials, clearClientInfo, clearCodeVerifier, clearTokens, getAuthForUrl, updateClientInfo, updateTokens, } from "./mcp-auth.js";
|
|
10
|
+
import { resolveCommandSecret } from "./utils.js";
|
|
11
|
+
/**
|
|
12
|
+
* Client name advertised during Dynamic Client Registration.
|
|
13
|
+
*
|
|
14
|
+
* OAuth consent screens must identify the application users are running.
|
|
15
|
+
*/
|
|
16
|
+
function defaultClientName() {
|
|
17
|
+
return getAppName();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Client homepage advertised during Dynamic Client Registration.
|
|
21
|
+
*
|
|
22
|
+
* RFC 7591 defines client_uri as the home page of the client.
|
|
23
|
+
*/
|
|
24
|
+
function defaultClientUri() {
|
|
25
|
+
const declared = getAppClientUri();
|
|
26
|
+
if (declared)
|
|
27
|
+
return declared;
|
|
28
|
+
return getAppName() === "Nexus" ? "https://github.com/Akon-Labs/nexus-cli" : undefined;
|
|
29
|
+
}
|
|
30
|
+
function issuersMatch(first, second) {
|
|
31
|
+
return (first === second ||
|
|
32
|
+
(first.endsWith("/") && first.slice(0, -1) === second) ||
|
|
33
|
+
(second.endsWith("/") && second.slice(0, -1) === first));
|
|
34
|
+
}
|
|
35
|
+
// Callback server configuration
|
|
36
|
+
const DEFAULT_OAUTH_CALLBACK_PORT = 19876;
|
|
37
|
+
const DEFAULT_OAUTH_CALLBACK_PATH = "/callback";
|
|
38
|
+
let configuredOAuthCallbackPort = DEFAULT_OAUTH_CALLBACK_PORT;
|
|
39
|
+
if (process.env.MCP_OAUTH_CALLBACK_PORT) {
|
|
40
|
+
const parsedPort = Number.parseInt(process.env.MCP_OAUTH_CALLBACK_PORT, 10);
|
|
41
|
+
if (Number.isInteger(parsedPort) && parsedPort > 0 && parsedPort <= 65535) {
|
|
42
|
+
configuredOAuthCallbackPort = parsedPort;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
let oauthCallbackPort = configuredOAuthCallbackPort;
|
|
46
|
+
let oauthCallbackPath = DEFAULT_OAUTH_CALLBACK_PATH;
|
|
47
|
+
export function getConfiguredOAuthCallbackPort() {
|
|
48
|
+
return configuredOAuthCallbackPort;
|
|
49
|
+
}
|
|
50
|
+
export function getOAuthCallbackPort() {
|
|
51
|
+
return oauthCallbackPort;
|
|
52
|
+
}
|
|
53
|
+
export function setOAuthCallbackPort(port) {
|
|
54
|
+
oauthCallbackPort = port;
|
|
55
|
+
}
|
|
56
|
+
export function getOAuthCallbackPath() {
|
|
57
|
+
return oauthCallbackPath;
|
|
58
|
+
}
|
|
59
|
+
export function setOAuthCallbackPath(path) {
|
|
60
|
+
oauthCallbackPath = path.startsWith("/") ? path : `/${path}`;
|
|
61
|
+
}
|
|
62
|
+
const reservedAuthorizationParams = new Set([
|
|
63
|
+
"client_id",
|
|
64
|
+
"code_challenge",
|
|
65
|
+
"code_challenge_method",
|
|
66
|
+
"redirect_uri",
|
|
67
|
+
"resource",
|
|
68
|
+
"response_type",
|
|
69
|
+
"scope",
|
|
70
|
+
"state",
|
|
71
|
+
]);
|
|
72
|
+
function addAuthorizationParams(authorizationUrl, params) {
|
|
73
|
+
if (!params)
|
|
74
|
+
return authorizationUrl;
|
|
75
|
+
const nextUrl = new URL(authorizationUrl.toString());
|
|
76
|
+
for (const [key, value] of Object.entries(params)) {
|
|
77
|
+
if (reservedAuthorizationParams.has(key) || nextUrl.searchParams.has(key)) {
|
|
78
|
+
throw new Error(`OAuth authorizationParams.${key} cannot override an authorization flow parameter`);
|
|
79
|
+
}
|
|
80
|
+
nextUrl.searchParams.set(key, value);
|
|
81
|
+
}
|
|
82
|
+
return nextUrl;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* OAuth provider implementation for MCP servers.
|
|
86
|
+
* Implements the OAuthClientProvider interface from the MCP SDK.
|
|
87
|
+
*/
|
|
88
|
+
export class McpOAuthProvider {
|
|
89
|
+
redirectUrlSnapshot;
|
|
90
|
+
active = true;
|
|
91
|
+
flowClientInfo;
|
|
92
|
+
flowCodeVerifier;
|
|
93
|
+
flowDiscoveryState;
|
|
94
|
+
flowIssuerMismatch = false;
|
|
95
|
+
flowState;
|
|
96
|
+
serverName;
|
|
97
|
+
serverUrl;
|
|
98
|
+
config;
|
|
99
|
+
callbacks;
|
|
100
|
+
storageOptions;
|
|
101
|
+
runtimeSignal;
|
|
102
|
+
constructor(serverName, serverUrl, config, callbacks, storageOptions = {}, runtimeSignal, initialState) {
|
|
103
|
+
this.serverName = serverName;
|
|
104
|
+
this.serverUrl = serverUrl;
|
|
105
|
+
this.config = config;
|
|
106
|
+
this.callbacks = callbacks;
|
|
107
|
+
this.storageOptions = storageOptions;
|
|
108
|
+
this.runtimeSignal = runtimeSignal;
|
|
109
|
+
this.flowState = initialState;
|
|
110
|
+
this.redirectUrlSnapshot =
|
|
111
|
+
config.grantType === "client_credentials"
|
|
112
|
+
? undefined
|
|
113
|
+
: (config.redirectUri ?? `http://localhost:${getOAuthCallbackPort()}${getOAuthCallbackPath()}`);
|
|
114
|
+
}
|
|
115
|
+
get usesClientCredentials() {
|
|
116
|
+
return this.config.grantType === "client_credentials";
|
|
117
|
+
}
|
|
118
|
+
get discoveredIssuer() {
|
|
119
|
+
return (this.flowDiscoveryState?.authorizationServerMetadata?.issuer ?? this.flowDiscoveryState?.authorizationServerUrl);
|
|
120
|
+
}
|
|
121
|
+
deactivate() {
|
|
122
|
+
this.active = false;
|
|
123
|
+
}
|
|
124
|
+
assertStoredIssuerBindings(entry, issuer) {
|
|
125
|
+
if (this.flowIssuerMismatch) {
|
|
126
|
+
throw new Error(`OAuth authorization server issuer changed for ${this.serverName}; clear credentials before authenticating again`);
|
|
127
|
+
}
|
|
128
|
+
if (!entry || !issuer)
|
|
129
|
+
return;
|
|
130
|
+
const storedIssuers = [entry.clientInfo?.issuer, entry.tokens?.issuer].filter((storedIssuer) => storedIssuer !== undefined);
|
|
131
|
+
if (storedIssuers.some((storedIssuer) => !issuersMatch(storedIssuer, issuer))) {
|
|
132
|
+
this.flowIssuerMismatch = true;
|
|
133
|
+
throw new Error(`OAuth authorization server issuer changed for ${this.serverName}; clear credentials before authenticating again`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
throwIfInactive() {
|
|
137
|
+
if (!this.active)
|
|
138
|
+
throw new Error("OAuth flow is no longer active");
|
|
139
|
+
this.runtimeSignal?.throwIfAborted();
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The redirect URL for OAuth callbacks.
|
|
143
|
+
* This must match the redirect_uri in client metadata.
|
|
144
|
+
*/
|
|
145
|
+
get redirectUrl() {
|
|
146
|
+
return this.redirectUrlSnapshot;
|
|
147
|
+
}
|
|
148
|
+
/** Configured homepage, otherwise the Nexus repository. */
|
|
149
|
+
get clientUri() {
|
|
150
|
+
return this.config.clientUri ?? defaultClientUri();
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Client metadata for dynamic registration.
|
|
154
|
+
* Describes this client to the OAuth authorization server.
|
|
155
|
+
*/
|
|
156
|
+
get clientMetadata() {
|
|
157
|
+
if (this.usesClientCredentials) {
|
|
158
|
+
return {
|
|
159
|
+
client_name: this.config.clientName ?? defaultClientName(),
|
|
160
|
+
...(this.clientUri !== undefined ? { client_uri: this.clientUri } : {}),
|
|
161
|
+
...(this.config.logoUri !== undefined ? { logo_uri: this.config.logoUri } : {}),
|
|
162
|
+
redirect_uris: [],
|
|
163
|
+
grant_types: ["client_credentials"],
|
|
164
|
+
token_endpoint_auth_method: this.config.clientSecret ? "client_secret_post" : "none",
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
const redirectUrl = this.redirectUrl;
|
|
168
|
+
if (!redirectUrl) {
|
|
169
|
+
throw new Error("redirectUrl is required for authorization_code flow");
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
redirect_uris: [redirectUrl],
|
|
173
|
+
client_name: this.config.clientName ?? defaultClientName(),
|
|
174
|
+
...(this.clientUri !== undefined ? { client_uri: this.clientUri } : {}),
|
|
175
|
+
...(this.config.logoUri !== undefined ? { logo_uri: this.config.logoUri } : {}),
|
|
176
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
177
|
+
response_types: ["code"],
|
|
178
|
+
token_endpoint_auth_method: this.config.clientSecret ? "client_secret_post" : "none",
|
|
179
|
+
...(this.config.scope !== undefined ? { scope: this.config.scope } : {}),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get client information (for pre-registered or dynamically registered clients).
|
|
184
|
+
* Returns undefined if no client info exists or if the server URL has changed.
|
|
185
|
+
*/
|
|
186
|
+
async clientInformation() {
|
|
187
|
+
const issuer = this.discoveredIssuer;
|
|
188
|
+
const stored = await getAuthForUrl(this.serverName, this.serverUrl, this.storageOptions);
|
|
189
|
+
this.assertStoredIssuerBindings(stored, issuer);
|
|
190
|
+
// Check config first (pre-registered client). Store only its issuer binding.
|
|
191
|
+
// The configured secret stays in config and never enters the credential store.
|
|
192
|
+
if (this.config.clientId) {
|
|
193
|
+
const storedClient = stored?.clientInfo?.clientId === this.config.clientId ? stored.clientInfo : undefined;
|
|
194
|
+
if (issuer && (storedClient?.issuer !== issuer || storedClient.configPreRegistered !== true)) {
|
|
195
|
+
updateClientInfo(this.serverName, { clientId: this.config.clientId, issuer, configPreRegistered: true }, this.serverUrl, this.storageOptions);
|
|
196
|
+
}
|
|
197
|
+
const clientSecret = this.config.clientSecret?.startsWith("!")
|
|
198
|
+
? resolveCommandSecret(this.config.clientSecret, `MCP server "${this.serverName}" OAuth clientSecret`)
|
|
199
|
+
: this.config.clientSecret;
|
|
200
|
+
return {
|
|
201
|
+
client_id: this.config.clientId,
|
|
202
|
+
client_secret: clientSecret,
|
|
203
|
+
...(issuer !== undefined ? { issuer } : {}),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
// Keep client registration associated with this in-flight flow even if
|
|
207
|
+
// another runtime writes the shared persistent entry for the same name.
|
|
208
|
+
const clientInfo = this.flowClientInfo ?? stored?.clientInfo;
|
|
209
|
+
if (clientInfo) {
|
|
210
|
+
// A stored SEP-2352 issuer stub for a config-pre-registered client
|
|
211
|
+
// (identified by its explicit marker) is only meaningful
|
|
212
|
+
// when the config supplies the matching client secret. Since we reach
|
|
213
|
+
// this branch only when config.clientId is absent, serving the stub
|
|
214
|
+
// would let a token refresh go out with a client_id but no secret,
|
|
215
|
+
// causing invalid_client and credential invalidation. Return undefined
|
|
216
|
+
// so callers treat this as "no client info".
|
|
217
|
+
const isConfigStub = clientInfo.configPreRegistered === true;
|
|
218
|
+
if (isConfigStub) {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
// Check if client secret has expired
|
|
222
|
+
if (clientInfo.clientSecretExpiresAt && clientInfo.clientSecretExpiresAt < Date.now() / 1000) {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
if (issuer && clientInfo.issuer && !issuersMatch(clientInfo.issuer, issuer)) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
if (issuer && clientInfo.issuer === undefined) {
|
|
229
|
+
clientInfo.issuer = issuer;
|
|
230
|
+
this.flowClientInfo = clientInfo;
|
|
231
|
+
updateClientInfo(this.serverName, clientInfo, this.serverUrl, this.storageOptions);
|
|
232
|
+
}
|
|
233
|
+
// Return all registration metadata and the local issuer extension.
|
|
234
|
+
// This keeps the SDK OAuth view and the stored issuer binding consistent.
|
|
235
|
+
return {
|
|
236
|
+
client_id: clientInfo.clientId,
|
|
237
|
+
client_secret: clientInfo.clientSecret,
|
|
238
|
+
...(clientInfo.clientIdIssuedAt !== undefined ? { client_id_issued_at: clientInfo.clientIdIssuedAt } : {}),
|
|
239
|
+
...(clientInfo.clientSecretExpiresAt !== undefined
|
|
240
|
+
? { client_secret_expires_at: clientInfo.clientSecretExpiresAt }
|
|
241
|
+
: {}),
|
|
242
|
+
...(clientInfo.redirectUris !== undefined ? { redirect_uris: clientInfo.redirectUris } : {}),
|
|
243
|
+
...(clientInfo.issuer !== undefined ? { issuer: clientInfo.issuer } : {}),
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
// No client info or URL changed - will trigger dynamic registration
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Save client information from dynamic registration.
|
|
251
|
+
*/
|
|
252
|
+
async saveClientInformation(info) {
|
|
253
|
+
this.throwIfInactive();
|
|
254
|
+
const issuer = this.discoveredIssuer ?? info.issuer;
|
|
255
|
+
if (this.config.clientId && info.client_id === this.config.clientId) {
|
|
256
|
+
updateClientInfo(this.serverName, {
|
|
257
|
+
clientId: info.client_id,
|
|
258
|
+
...(issuer !== undefined ? { issuer } : {}),
|
|
259
|
+
configPreRegistered: true,
|
|
260
|
+
}, this.serverUrl, this.storageOptions);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const redirectUris = ("redirect_uris" in info ? info.redirect_uris : undefined) ??
|
|
264
|
+
(this.redirectUrl ? [this.redirectUrl] : undefined);
|
|
265
|
+
const clientInfo = {
|
|
266
|
+
clientId: info.client_id,
|
|
267
|
+
...(info.client_secret !== undefined ? { clientSecret: info.client_secret } : {}),
|
|
268
|
+
...(info.client_id_issued_at !== undefined ? { clientIdIssuedAt: info.client_id_issued_at } : {}),
|
|
269
|
+
...(info.client_secret_expires_at !== undefined
|
|
270
|
+
? { clientSecretExpiresAt: info.client_secret_expires_at }
|
|
271
|
+
: {}),
|
|
272
|
+
...(redirectUris !== undefined ? { redirectUris } : {}),
|
|
273
|
+
...(issuer !== undefined ? { issuer } : {}),
|
|
274
|
+
};
|
|
275
|
+
this.flowClientInfo = clientInfo;
|
|
276
|
+
updateClientInfo(this.serverName, clientInfo, this.serverUrl, this.storageOptions);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Get stored OAuth tokens.
|
|
280
|
+
* Returns undefined if no tokens exist or if the server URL has changed.
|
|
281
|
+
*/
|
|
282
|
+
async tokens() {
|
|
283
|
+
// Use getAuthForUrl to validate tokens are for the current server URL.
|
|
284
|
+
const entry = await getAuthForUrl(this.serverName, this.serverUrl, this.storageOptions);
|
|
285
|
+
if (!entry?.tokens)
|
|
286
|
+
return undefined;
|
|
287
|
+
const issuer = this.discoveredIssuer;
|
|
288
|
+
this.assertStoredIssuerBindings(entry, issuer);
|
|
289
|
+
if (issuer && entry.tokens.issuer === undefined) {
|
|
290
|
+
entry.tokens.issuer = issuer;
|
|
291
|
+
updateTokens(this.serverName, entry.tokens, this.serverUrl, this.storageOptions);
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
access_token: entry.tokens.accessToken,
|
|
295
|
+
token_type: "Bearer",
|
|
296
|
+
refresh_token: entry.tokens.refreshToken,
|
|
297
|
+
expires_in: entry.tokens.expiresAt !== undefined
|
|
298
|
+
? Math.max(0, Math.floor(entry.tokens.expiresAt - Date.now() / 1000))
|
|
299
|
+
: undefined,
|
|
300
|
+
scope: entry.tokens.scope,
|
|
301
|
+
...(entry.tokens.issuer !== undefined ? { issuer: entry.tokens.issuer } : {}),
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Save OAuth tokens.
|
|
306
|
+
*/
|
|
307
|
+
async saveTokens(tokens) {
|
|
308
|
+
const issuer = this.discoveredIssuer ?? tokens.issuer;
|
|
309
|
+
const storedTokens = {
|
|
310
|
+
accessToken: tokens.access_token,
|
|
311
|
+
...(tokens.refresh_token !== undefined ? { refreshToken: tokens.refresh_token } : {}),
|
|
312
|
+
// Preserve expiry even when expires_in is 0 (e.g. the SDK re-saving an
|
|
313
|
+
// already-expired token) so expired tokens stay expired instead of
|
|
314
|
+
// being persisted as never-expiring.
|
|
315
|
+
...(tokens.expires_in !== undefined ? { expiresAt: Date.now() / 1000 + tokens.expires_in } : {}),
|
|
316
|
+
...(tokens.scope !== undefined ? { scope: tokens.scope } : {}),
|
|
317
|
+
...(issuer !== undefined ? { issuer } : {}),
|
|
318
|
+
};
|
|
319
|
+
this.throwIfInactive();
|
|
320
|
+
updateTokens(this.serverName, storedTokens, this.serverUrl, this.storageOptions);
|
|
321
|
+
// Discovery must survive the browser redirect so the callback can verify
|
|
322
|
+
// the authorization server that minted the code. Once token issuance
|
|
323
|
+
// succeeds, clear it so a later 401 re-reads PRM and can observe an
|
|
324
|
+
// authorization-server migration.
|
|
325
|
+
this.flowDiscoveryState = undefined;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Redirect the user to the authorization URL.
|
|
329
|
+
* This opens the browser for the user to authenticate.
|
|
330
|
+
*
|
|
331
|
+
* Throws UnauthorizedError when called outside of a user-initiated flow
|
|
332
|
+
* (no oauthState saved by startAuth). That path is reached when the SDK
|
|
333
|
+
* falls through from a failed refresh into a fresh authorization_code
|
|
334
|
+
* flow, which library hosts cannot complete in-process.
|
|
335
|
+
*/
|
|
336
|
+
async redirectToAuthorization(authorizationUrl) {
|
|
337
|
+
if (this.usesClientCredentials) {
|
|
338
|
+
throw new Error("redirectToAuthorization is not used for client_credentials flow");
|
|
339
|
+
}
|
|
340
|
+
// No flow-local state means we're on the post-refresh authorize fallback.
|
|
341
|
+
this.throwIfInactive();
|
|
342
|
+
if (!this.flowState) {
|
|
343
|
+
throw new UnauthorizedError(`Re-authentication required for MCP server: ${this.serverName}`);
|
|
344
|
+
}
|
|
345
|
+
// URL is passed to callback, not logged (may contain sensitive params)
|
|
346
|
+
await this.callbacks.onRedirect(addAuthorizationParams(authorizationUrl, this.config.authorizationParams));
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Save the PKCE code verifier.
|
|
350
|
+
*/
|
|
351
|
+
async saveCodeVerifier(codeVerifier) {
|
|
352
|
+
this.throwIfInactive();
|
|
353
|
+
this.flowCodeVerifier = codeVerifier;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Get the stored PKCE code verifier.
|
|
357
|
+
* @throws Error if no code verifier is stored
|
|
358
|
+
*/
|
|
359
|
+
async codeVerifier() {
|
|
360
|
+
if (this.usesClientCredentials) {
|
|
361
|
+
throw new Error("codeVerifier is not used for client_credentials flow");
|
|
362
|
+
}
|
|
363
|
+
this.throwIfInactive();
|
|
364
|
+
if (!this.flowCodeVerifier) {
|
|
365
|
+
throw new Error(`No code verifier saved for MCP server: ${this.serverName}`);
|
|
366
|
+
}
|
|
367
|
+
return this.flowCodeVerifier;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Keep discovery with the in-flight PKCE verifier. The callback leg uses it
|
|
371
|
+
* to validate the authorization response issuer before token exchange.
|
|
372
|
+
*/
|
|
373
|
+
async saveDiscoveryState(state) {
|
|
374
|
+
this.throwIfInactive();
|
|
375
|
+
this.flowDiscoveryState = structuredClone(state);
|
|
376
|
+
}
|
|
377
|
+
async discoveryState() {
|
|
378
|
+
this.throwIfInactive();
|
|
379
|
+
return this.flowDiscoveryState ? structuredClone(this.flowDiscoveryState) : undefined;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Save the OAuth state parameter for CSRF protection.
|
|
383
|
+
*/
|
|
384
|
+
async saveState(state) {
|
|
385
|
+
this.throwIfInactive();
|
|
386
|
+
this.flowState = state;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get the stored OAuth state parameter.
|
|
390
|
+
* @throws UnauthorizedError if no flow is in progress (see redirectToAuthorization)
|
|
391
|
+
*/
|
|
392
|
+
async state() {
|
|
393
|
+
if (this.usesClientCredentials) {
|
|
394
|
+
throw new Error("state is not used for client_credentials flow");
|
|
395
|
+
}
|
|
396
|
+
this.throwIfInactive();
|
|
397
|
+
if (!this.flowState) {
|
|
398
|
+
throw new UnauthorizedError(`Re-authentication required for MCP server: ${this.serverName}`);
|
|
399
|
+
}
|
|
400
|
+
return this.flowState;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Invalidate credentials when authentication fails.
|
|
404
|
+
* Clears tokens, client info, or all credentials based on the type.
|
|
405
|
+
*/
|
|
406
|
+
async invalidateCredentials(type) {
|
|
407
|
+
this.throwIfInactive();
|
|
408
|
+
switch (type) {
|
|
409
|
+
case "all":
|
|
410
|
+
this.flowClientInfo = undefined;
|
|
411
|
+
this.flowCodeVerifier = undefined;
|
|
412
|
+
this.flowDiscoveryState = undefined;
|
|
413
|
+
this.flowIssuerMismatch = false;
|
|
414
|
+
this.flowState = undefined;
|
|
415
|
+
clearAllCredentials(this.serverName, this.storageOptions);
|
|
416
|
+
break;
|
|
417
|
+
case "client":
|
|
418
|
+
this.flowClientInfo = undefined;
|
|
419
|
+
clearClientInfo(this.serverName, this.storageOptions);
|
|
420
|
+
break;
|
|
421
|
+
case "tokens":
|
|
422
|
+
clearTokens(this.serverName, this.storageOptions);
|
|
423
|
+
break;
|
|
424
|
+
case "verifier":
|
|
425
|
+
clearCodeVerifier(this.serverName, this.storageOptions);
|
|
426
|
+
break;
|
|
427
|
+
case "discovery":
|
|
428
|
+
this.flowDiscoveryState = undefined;
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Adds configured authorization-code scope without replacing the SDK's
|
|
434
|
+
* default token endpoint authentication behavior.
|
|
435
|
+
*/
|
|
436
|
+
addClientAuthentication = async (headers, params, _url, metadata) => {
|
|
437
|
+
this.throwIfInactive();
|
|
438
|
+
if (params.get("grant_type") === "authorization_code" && !params.has("scope") && this.config.scope) {
|
|
439
|
+
params.set("scope", this.config.scope);
|
|
440
|
+
}
|
|
441
|
+
const clientInfo = await this.clientInformation();
|
|
442
|
+
this.throwIfInactive();
|
|
443
|
+
if (!clientInfo) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const supportedMethods = metadata?.token_endpoint_auth_methods_supported ?? [];
|
|
447
|
+
const hasClientSecret = clientInfo.client_secret !== undefined;
|
|
448
|
+
let authMethod;
|
|
449
|
+
if (supportedMethods.length === 0) {
|
|
450
|
+
authMethod = hasClientSecret ? "client_secret_post" : "none";
|
|
451
|
+
}
|
|
452
|
+
else if (hasClientSecret && supportedMethods.includes("client_secret_basic")) {
|
|
453
|
+
authMethod = "client_secret_basic";
|
|
454
|
+
}
|
|
455
|
+
else if (hasClientSecret && supportedMethods.includes("client_secret_post")) {
|
|
456
|
+
authMethod = "client_secret_post";
|
|
457
|
+
}
|
|
458
|
+
else if (supportedMethods.includes("none")) {
|
|
459
|
+
authMethod = "none";
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
authMethod = hasClientSecret ? "client_secret_post" : "none";
|
|
463
|
+
}
|
|
464
|
+
if (authMethod === "client_secret_basic") {
|
|
465
|
+
if (!clientInfo.client_secret) {
|
|
466
|
+
throw new Error("client_secret_basic authentication requires a client_secret");
|
|
467
|
+
}
|
|
468
|
+
headers.set("Authorization", `Basic ${Buffer.from(`${clientInfo.client_id}:${clientInfo.client_secret}`).toString("base64")}`);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (!params.has("client_id")) {
|
|
472
|
+
params.set("client_id", clientInfo.client_id);
|
|
473
|
+
}
|
|
474
|
+
if (authMethod === "client_secret_post" && clientInfo.client_secret && !params.has("client_secret")) {
|
|
475
|
+
params.set("client_secret", clientInfo.client_secret);
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
prepareTokenRequest(scope) {
|
|
479
|
+
if (!this.usesClientCredentials) {
|
|
480
|
+
return undefined;
|
|
481
|
+
}
|
|
482
|
+
const params = new URLSearchParams({ grant_type: "client_credentials" });
|
|
483
|
+
const requestedScope = scope ?? this.config.scope;
|
|
484
|
+
if (requestedScope) {
|
|
485
|
+
params.set("scope", requestedScope);
|
|
486
|
+
}
|
|
487
|
+
return params;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
export { DEFAULT_OAUTH_CALLBACK_PORT, DEFAULT_OAUTH_CALLBACK_PATH };
|
|
491
|
+
//# sourceMappingURL=mcp-oauth-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-oauth-provider.js","sourceRoot":"","sources":["../../../src/extensions/mcp/mcp-oauth-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP OAuth Provider\n *\n * Implementation of the MCP SDK's OAuthClientProvider interface.\n * Handles OAuth client registration, token storage, and authorization redirection.\n */\n\nimport type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthTokens } from \"@modelcontextprotocol/client\";\nimport {\n\ttype AddClientAuthentication,\n\ttype OAuthClientProvider,\n\ttype OAuthDiscoveryState,\n\tUnauthorizedError,\n} from \"@modelcontextprotocol/client\";\nimport { getAppClientUri, getAppName } from \"./agent-dir.ts\";\nimport {\n\ttype AuthEntry,\n\ttype AuthStorageOptions,\n\tclearAllCredentials,\n\tclearClientInfo,\n\tclearCodeVerifier,\n\tclearTokens,\n\tgetAuthForUrl,\n\ttype StoredClientInfo,\n\ttype StoredTokens,\n\tupdateClientInfo,\n\tupdateTokens,\n} from \"./mcp-auth.ts\";\nimport { resolveCommandSecret } from \"./utils.ts\";\n\n/**\n * Client name advertised during Dynamic Client Registration.\n *\n * OAuth consent screens must identify the application users are running.\n */\nfunction defaultClientName(): string {\n\treturn getAppName();\n}\n\n/**\n * Client homepage advertised during Dynamic Client Registration.\n *\n * RFC 7591 defines client_uri as the home page of the client.\n */\nfunction defaultClientUri(): string | undefined {\n\tconst declared = getAppClientUri();\n\tif (declared) return declared;\n\treturn getAppName() === \"Nexus\" ? \"https://github.com/Akon-Labs/nexus-cli\" : undefined;\n}\n\ntype IssuerBoundClientInformation = OAuthClientInformationMixed & { issuer?: string };\ntype IssuerBoundTokens = OAuthTokens & { issuer?: string };\n\nfunction issuersMatch(first: string, second: string): boolean {\n\treturn (\n\t\tfirst === second ||\n\t\t(first.endsWith(\"/\") && first.slice(0, -1) === second) ||\n\t\t(second.endsWith(\"/\") && second.slice(0, -1) === first)\n\t);\n}\n\n// Callback server configuration\nconst DEFAULT_OAUTH_CALLBACK_PORT = 19876;\nconst DEFAULT_OAUTH_CALLBACK_PATH = \"/callback\";\n\nlet configuredOAuthCallbackPort = DEFAULT_OAUTH_CALLBACK_PORT;\n\nif (process.env.MCP_OAUTH_CALLBACK_PORT) {\n\tconst parsedPort = Number.parseInt(process.env.MCP_OAUTH_CALLBACK_PORT, 10);\n\tif (Number.isInteger(parsedPort) && parsedPort > 0 && parsedPort <= 65535) {\n\t\tconfiguredOAuthCallbackPort = parsedPort;\n\t}\n}\n\nlet oauthCallbackPort = configuredOAuthCallbackPort;\nlet oauthCallbackPath = DEFAULT_OAUTH_CALLBACK_PATH;\n\nexport function getConfiguredOAuthCallbackPort(): number {\n\treturn configuredOAuthCallbackPort;\n}\n\nexport function getOAuthCallbackPort(): number {\n\treturn oauthCallbackPort;\n}\n\nexport function setOAuthCallbackPort(port: number): void {\n\toauthCallbackPort = port;\n}\n\nexport function getOAuthCallbackPath(): string {\n\treturn oauthCallbackPath;\n}\n\nexport function setOAuthCallbackPath(path: string): void {\n\toauthCallbackPath = path.startsWith(\"/\") ? path : `/${path}`;\n}\n\n/** Configuration options for OAuth */\nexport interface McpOAuthConfig {\n\tgrantType?: \"authorization_code\" | \"client_credentials\";\n\tclientId?: string;\n\tclientSecret?: string;\n\tscope?: string;\n\tauthorizationParams?: Record<string, string>;\n\tredirectUri?: string;\n\tclientName?: string;\n\tclientUri?: string;\n\tlogoUri?: string;\n\tskipIssuerMetadataValidation?: boolean;\n}\n\nconst reservedAuthorizationParams = new Set([\n\t\"client_id\",\n\t\"code_challenge\",\n\t\"code_challenge_method\",\n\t\"redirect_uri\",\n\t\"resource\",\n\t\"response_type\",\n\t\"scope\",\n\t\"state\",\n]);\n\nfunction addAuthorizationParams(authorizationUrl: URL, params: Record<string, string> | undefined): URL {\n\tif (!params) return authorizationUrl;\n\tconst nextUrl = new URL(authorizationUrl.toString());\n\tfor (const [key, value] of Object.entries(params)) {\n\t\tif (reservedAuthorizationParams.has(key) || nextUrl.searchParams.has(key)) {\n\t\t\tthrow new Error(`OAuth authorizationParams.${key} cannot override an authorization flow parameter`);\n\t\t}\n\t\tnextUrl.searchParams.set(key, value);\n\t}\n\treturn nextUrl;\n}\n\n/** Callbacks for OAuth flow interactions */\nexport interface McpOAuthCallbacks {\n\tonRedirect: (url: URL) => void | Promise<void>;\n}\n\n/**\n * OAuth provider implementation for MCP servers.\n * Implements the OAuthClientProvider interface from the MCP SDK.\n */\nexport class McpOAuthProvider implements OAuthClientProvider {\n\tprivate readonly redirectUrlSnapshot: string | undefined;\n\tprivate active = true;\n\tprivate flowClientInfo: StoredClientInfo | undefined;\n\tprivate flowCodeVerifier: string | undefined;\n\tprivate flowDiscoveryState: OAuthDiscoveryState | undefined;\n\tprivate flowIssuerMismatch = false;\n\tprivate flowState: string | undefined;\n\tprivate serverName: string;\n\tprivate serverUrl: string;\n\tprivate config: McpOAuthConfig;\n\tprivate callbacks: McpOAuthCallbacks;\n\tprivate storageOptions: AuthStorageOptions;\n\tprivate runtimeSignal: AbortSignal | undefined;\n\n\tconstructor(\n\t\tserverName: string,\n\t\tserverUrl: string,\n\t\tconfig: McpOAuthConfig,\n\t\tcallbacks: McpOAuthCallbacks,\n\t\tstorageOptions: AuthStorageOptions = {},\n\t\truntimeSignal?: AbortSignal,\n\t\tinitialState?: string,\n\t) {\n\t\tthis.serverName = serverName;\n\t\tthis.serverUrl = serverUrl;\n\t\tthis.config = config;\n\t\tthis.callbacks = callbacks;\n\t\tthis.storageOptions = storageOptions;\n\t\tthis.runtimeSignal = runtimeSignal;\n\t\tthis.flowState = initialState;\n\t\tthis.redirectUrlSnapshot =\n\t\t\tconfig.grantType === \"client_credentials\"\n\t\t\t\t? undefined\n\t\t\t\t: (config.redirectUri ?? `http://localhost:${getOAuthCallbackPort()}${getOAuthCallbackPath()}`);\n\t}\n\n\tprivate get usesClientCredentials(): boolean {\n\t\treturn this.config.grantType === \"client_credentials\";\n\t}\n\n\tprivate get discoveredIssuer(): string | undefined {\n\t\treturn (\n\t\t\tthis.flowDiscoveryState?.authorizationServerMetadata?.issuer ?? this.flowDiscoveryState?.authorizationServerUrl\n\t\t);\n\t}\n\n\tdeactivate(): void {\n\t\tthis.active = false;\n\t}\n\n\tprivate assertStoredIssuerBindings(entry: AuthEntry | undefined, issuer: string | undefined): void {\n\t\tif (this.flowIssuerMismatch) {\n\t\t\tthrow new Error(\n\t\t\t\t`OAuth authorization server issuer changed for ${this.serverName}; clear credentials before authenticating again`,\n\t\t\t);\n\t\t}\n\t\tif (!entry || !issuer) return;\n\n\t\tconst storedIssuers = [entry.clientInfo?.issuer, entry.tokens?.issuer].filter(\n\t\t\t(storedIssuer): storedIssuer is string => storedIssuer !== undefined,\n\t\t);\n\t\tif (storedIssuers.some((storedIssuer) => !issuersMatch(storedIssuer, issuer))) {\n\t\t\tthis.flowIssuerMismatch = true;\n\t\t\tthrow new Error(\n\t\t\t\t`OAuth authorization server issuer changed for ${this.serverName}; clear credentials before authenticating again`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate throwIfInactive(): void {\n\t\tif (!this.active) throw new Error(\"OAuth flow is no longer active\");\n\t\tthis.runtimeSignal?.throwIfAborted();\n\t}\n\n\t/**\n\t * The redirect URL for OAuth callbacks.\n\t * This must match the redirect_uri in client metadata.\n\t */\n\tget redirectUrl(): string | undefined {\n\t\treturn this.redirectUrlSnapshot;\n\t}\n\n\t/** Configured homepage, otherwise the Nexus repository. */\n\tprivate get clientUri(): string | undefined {\n\t\treturn this.config.clientUri ?? defaultClientUri();\n\t}\n\n\t/**\n\t * Client metadata for dynamic registration.\n\t * Describes this client to the OAuth authorization server.\n\t */\n\tget clientMetadata(): OAuthClientMetadata {\n\t\tif (this.usesClientCredentials) {\n\t\t\treturn {\n\t\t\t\tclient_name: this.config.clientName ?? defaultClientName(),\n\t\t\t\t...(this.clientUri !== undefined ? { client_uri: this.clientUri } : {}),\n\t\t\t\t...(this.config.logoUri !== undefined ? { logo_uri: this.config.logoUri } : {}),\n\t\t\t\tredirect_uris: [],\n\t\t\t\tgrant_types: [\"client_credentials\"],\n\t\t\t\ttoken_endpoint_auth_method: this.config.clientSecret ? \"client_secret_post\" : \"none\",\n\t\t\t};\n\t\t}\n\n\t\tconst redirectUrl = this.redirectUrl;\n\t\tif (!redirectUrl) {\n\t\t\tthrow new Error(\"redirectUrl is required for authorization_code flow\");\n\t\t}\n\n\t\treturn {\n\t\t\tredirect_uris: [redirectUrl],\n\t\t\tclient_name: this.config.clientName ?? defaultClientName(),\n\t\t\t...(this.clientUri !== undefined ? { client_uri: this.clientUri } : {}),\n\t\t\t...(this.config.logoUri !== undefined ? { logo_uri: this.config.logoUri } : {}),\n\t\t\tgrant_types: [\"authorization_code\", \"refresh_token\"],\n\t\t\tresponse_types: [\"code\"],\n\t\t\ttoken_endpoint_auth_method: this.config.clientSecret ? \"client_secret_post\" : \"none\",\n\t\t\t...(this.config.scope !== undefined ? { scope: this.config.scope } : {}),\n\t\t};\n\t}\n\n\t/**\n\t * Get client information (for pre-registered or dynamically registered clients).\n\t * Returns undefined if no client info exists or if the server URL has changed.\n\t */\n\tasync clientInformation(): Promise<OAuthClientInformationMixed | undefined> {\n\t\tconst issuer = this.discoveredIssuer;\n\t\tconst stored = await getAuthForUrl(this.serverName, this.serverUrl, this.storageOptions);\n\t\tthis.assertStoredIssuerBindings(stored, issuer);\n\n\t\t// Check config first (pre-registered client). Store only its issuer binding.\n\t\t// The configured secret stays in config and never enters the credential store.\n\t\tif (this.config.clientId) {\n\t\t\tconst storedClient = stored?.clientInfo?.clientId === this.config.clientId ? stored.clientInfo : undefined;\n\t\t\tif (issuer && (storedClient?.issuer !== issuer || storedClient.configPreRegistered !== true)) {\n\t\t\t\tupdateClientInfo(\n\t\t\t\t\tthis.serverName,\n\t\t\t\t\t{ clientId: this.config.clientId, issuer, configPreRegistered: true },\n\t\t\t\t\tthis.serverUrl,\n\t\t\t\t\tthis.storageOptions,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst clientSecret = this.config.clientSecret?.startsWith(\"!\")\n\t\t\t\t? resolveCommandSecret(this.config.clientSecret, `MCP server \"${this.serverName}\" OAuth clientSecret`)\n\t\t\t\t: this.config.clientSecret;\n\t\t\treturn {\n\t\t\t\tclient_id: this.config.clientId,\n\t\t\t\tclient_secret: clientSecret,\n\t\t\t\t...(issuer !== undefined ? { issuer } : {}),\n\t\t\t} as IssuerBoundClientInformation;\n\t\t}\n\n\t\t// Keep client registration associated with this in-flight flow even if\n\t\t// another runtime writes the shared persistent entry for the same name.\n\t\tconst clientInfo = this.flowClientInfo ?? stored?.clientInfo;\n\t\tif (clientInfo) {\n\t\t\t// A stored SEP-2352 issuer stub for a config-pre-registered client\n\t\t\t// (identified by its explicit marker) is only meaningful\n\t\t\t// when the config supplies the matching client secret. Since we reach\n\t\t\t// this branch only when config.clientId is absent, serving the stub\n\t\t\t// would let a token refresh go out with a client_id but no secret,\n\t\t\t// causing invalid_client and credential invalidation. Return undefined\n\t\t\t// so callers treat this as \"no client info\".\n\t\t\tconst isConfigStub = clientInfo.configPreRegistered === true;\n\t\t\tif (isConfigStub) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\t// Check if client secret has expired\n\t\t\tif (clientInfo.clientSecretExpiresAt && clientInfo.clientSecretExpiresAt < Date.now() / 1000) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (issuer && clientInfo.issuer && !issuersMatch(clientInfo.issuer, issuer)) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tif (issuer && clientInfo.issuer === undefined) {\n\t\t\t\tclientInfo.issuer = issuer;\n\t\t\t\tthis.flowClientInfo = clientInfo;\n\t\t\t\tupdateClientInfo(this.serverName, clientInfo, this.serverUrl, this.storageOptions);\n\t\t\t}\n\t\t\t// Return all registration metadata and the local issuer extension.\n\t\t\t// This keeps the SDK OAuth view and the stored issuer binding consistent.\n\t\t\treturn {\n\t\t\t\tclient_id: clientInfo.clientId,\n\t\t\t\tclient_secret: clientInfo.clientSecret,\n\t\t\t\t...(clientInfo.clientIdIssuedAt !== undefined ? { client_id_issued_at: clientInfo.clientIdIssuedAt } : {}),\n\t\t\t\t...(clientInfo.clientSecretExpiresAt !== undefined\n\t\t\t\t\t? { client_secret_expires_at: clientInfo.clientSecretExpiresAt }\n\t\t\t\t\t: {}),\n\t\t\t\t...(clientInfo.redirectUris !== undefined ? { redirect_uris: clientInfo.redirectUris } : {}),\n\t\t\t\t...(clientInfo.issuer !== undefined ? { issuer: clientInfo.issuer } : {}),\n\t\t\t} as IssuerBoundClientInformation;\n\t\t}\n\n\t\t// No client info or URL changed - will trigger dynamic registration\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Save client information from dynamic registration.\n\t */\n\tasync saveClientInformation(info: OAuthClientInformationMixed): Promise<void> {\n\t\tthis.throwIfInactive();\n\t\tconst issuer = this.discoveredIssuer ?? (info as IssuerBoundClientInformation).issuer;\n\t\tif (this.config.clientId && info.client_id === this.config.clientId) {\n\t\t\tupdateClientInfo(\n\t\t\t\tthis.serverName,\n\t\t\t\t{\n\t\t\t\t\tclientId: info.client_id,\n\t\t\t\t\t...(issuer !== undefined ? { issuer } : {}),\n\t\t\t\t\tconfigPreRegistered: true,\n\t\t\t\t},\n\t\t\t\tthis.serverUrl,\n\t\t\t\tthis.storageOptions,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst redirectUris =\n\t\t\t(\"redirect_uris\" in info ? info.redirect_uris : undefined) ??\n\t\t\t(this.redirectUrl ? [this.redirectUrl] : undefined);\n\t\tconst clientInfo: StoredClientInfo = {\n\t\t\tclientId: info.client_id,\n\t\t\t...(info.client_secret !== undefined ? { clientSecret: info.client_secret } : {}),\n\t\t\t...(info.client_id_issued_at !== undefined ? { clientIdIssuedAt: info.client_id_issued_at } : {}),\n\t\t\t...(info.client_secret_expires_at !== undefined\n\t\t\t\t? { clientSecretExpiresAt: info.client_secret_expires_at }\n\t\t\t\t: {}),\n\t\t\t...(redirectUris !== undefined ? { redirectUris } : {}),\n\t\t\t...(issuer !== undefined ? { issuer } : {}),\n\t\t};\n\t\tthis.flowClientInfo = clientInfo;\n\t\tupdateClientInfo(this.serverName, clientInfo, this.serverUrl, this.storageOptions);\n\t}\n\n\t/**\n\t * Get stored OAuth tokens.\n\t * Returns undefined if no tokens exist or if the server URL has changed.\n\t */\n\tasync tokens(): Promise<OAuthTokens | undefined> {\n\t\t// Use getAuthForUrl to validate tokens are for the current server URL.\n\t\tconst entry = await getAuthForUrl(this.serverName, this.serverUrl, this.storageOptions);\n\t\tif (!entry?.tokens) return undefined;\n\t\tconst issuer = this.discoveredIssuer;\n\t\tthis.assertStoredIssuerBindings(entry, issuer);\n\t\tif (issuer && entry.tokens.issuer === undefined) {\n\t\t\tentry.tokens.issuer = issuer;\n\t\t\tupdateTokens(this.serverName, entry.tokens, this.serverUrl, this.storageOptions);\n\t\t}\n\n\t\treturn {\n\t\t\taccess_token: entry.tokens.accessToken,\n\t\t\ttoken_type: \"Bearer\",\n\t\t\trefresh_token: entry.tokens.refreshToken,\n\t\t\texpires_in:\n\t\t\t\tentry.tokens.expiresAt !== undefined\n\t\t\t\t\t? Math.max(0, Math.floor(entry.tokens.expiresAt - Date.now() / 1000))\n\t\t\t\t\t: undefined,\n\t\t\tscope: entry.tokens.scope,\n\t\t\t...(entry.tokens.issuer !== undefined ? { issuer: entry.tokens.issuer } : {}),\n\t\t} as IssuerBoundTokens;\n\t}\n\n\t/**\n\t * Save OAuth tokens.\n\t */\n\tasync saveTokens(tokens: OAuthTokens): Promise<void> {\n\t\tconst issuer = this.discoveredIssuer ?? (tokens as IssuerBoundTokens).issuer;\n\t\tconst storedTokens: StoredTokens = {\n\t\t\taccessToken: tokens.access_token,\n\t\t\t...(tokens.refresh_token !== undefined ? { refreshToken: tokens.refresh_token } : {}),\n\t\t\t// Preserve expiry even when expires_in is 0 (e.g. the SDK re-saving an\n\t\t\t// already-expired token) so expired tokens stay expired instead of\n\t\t\t// being persisted as never-expiring.\n\t\t\t...(tokens.expires_in !== undefined ? { expiresAt: Date.now() / 1000 + tokens.expires_in } : {}),\n\t\t\t...(tokens.scope !== undefined ? { scope: tokens.scope } : {}),\n\t\t\t...(issuer !== undefined ? { issuer } : {}),\n\t\t};\n\t\tthis.throwIfInactive();\n\t\tupdateTokens(this.serverName, storedTokens, this.serverUrl, this.storageOptions);\n\t\t// Discovery must survive the browser redirect so the callback can verify\n\t\t// the authorization server that minted the code. Once token issuance\n\t\t// succeeds, clear it so a later 401 re-reads PRM and can observe an\n\t\t// authorization-server migration.\n\t\tthis.flowDiscoveryState = undefined;\n\t}\n\n\t/**\n\t * Redirect the user to the authorization URL.\n\t * This opens the browser for the user to authenticate.\n\t *\n\t * Throws UnauthorizedError when called outside of a user-initiated flow\n\t * (no oauthState saved by startAuth). That path is reached when the SDK\n\t * falls through from a failed refresh into a fresh authorization_code\n\t * flow, which library hosts cannot complete in-process.\n\t */\n\tasync redirectToAuthorization(authorizationUrl: URL): Promise<void> {\n\t\tif (this.usesClientCredentials) {\n\t\t\tthrow new Error(\"redirectToAuthorization is not used for client_credentials flow\");\n\t\t}\n\t\t// No flow-local state means we're on the post-refresh authorize fallback.\n\t\tthis.throwIfInactive();\n\t\tif (!this.flowState) {\n\t\t\tthrow new UnauthorizedError(`Re-authentication required for MCP server: ${this.serverName}`);\n\t\t}\n\t\t// URL is passed to callback, not logged (may contain sensitive params)\n\t\tawait this.callbacks.onRedirect(addAuthorizationParams(authorizationUrl, this.config.authorizationParams));\n\t}\n\n\t/**\n\t * Save the PKCE code verifier.\n\t */\n\tasync saveCodeVerifier(codeVerifier: string): Promise<void> {\n\t\tthis.throwIfInactive();\n\t\tthis.flowCodeVerifier = codeVerifier;\n\t}\n\n\t/**\n\t * Get the stored PKCE code verifier.\n\t * @throws Error if no code verifier is stored\n\t */\n\tasync codeVerifier(): Promise<string> {\n\t\tif (this.usesClientCredentials) {\n\t\t\tthrow new Error(\"codeVerifier is not used for client_credentials flow\");\n\t\t}\n\t\tthis.throwIfInactive();\n\t\tif (!this.flowCodeVerifier) {\n\t\t\tthrow new Error(`No code verifier saved for MCP server: ${this.serverName}`);\n\t\t}\n\t\treturn this.flowCodeVerifier;\n\t}\n\n\t/**\n\t * Keep discovery with the in-flight PKCE verifier. The callback leg uses it\n\t * to validate the authorization response issuer before token exchange.\n\t */\n\tasync saveDiscoveryState(state: OAuthDiscoveryState): Promise<void> {\n\t\tthis.throwIfInactive();\n\t\tthis.flowDiscoveryState = structuredClone(state);\n\t}\n\n\tasync discoveryState(): Promise<OAuthDiscoveryState | undefined> {\n\t\tthis.throwIfInactive();\n\t\treturn this.flowDiscoveryState ? structuredClone(this.flowDiscoveryState) : undefined;\n\t}\n\n\t/**\n\t * Save the OAuth state parameter for CSRF protection.\n\t */\n\tasync saveState(state: string): Promise<void> {\n\t\tthis.throwIfInactive();\n\t\tthis.flowState = state;\n\t}\n\n\t/**\n\t * Get the stored OAuth state parameter.\n\t * @throws UnauthorizedError if no flow is in progress (see redirectToAuthorization)\n\t */\n\tasync state(): Promise<string> {\n\t\tif (this.usesClientCredentials) {\n\t\t\tthrow new Error(\"state is not used for client_credentials flow\");\n\t\t}\n\t\tthis.throwIfInactive();\n\t\tif (!this.flowState) {\n\t\t\tthrow new UnauthorizedError(`Re-authentication required for MCP server: ${this.serverName}`);\n\t\t}\n\t\treturn this.flowState;\n\t}\n\n\t/**\n\t * Invalidate credentials when authentication fails.\n\t * Clears tokens, client info, or all credentials based on the type.\n\t */\n\tasync invalidateCredentials(type: \"all\" | \"client\" | \"tokens\" | \"verifier\" | \"discovery\"): Promise<void> {\n\t\tthis.throwIfInactive();\n\t\tswitch (type) {\n\t\t\tcase \"all\":\n\t\t\t\tthis.flowClientInfo = undefined;\n\t\t\t\tthis.flowCodeVerifier = undefined;\n\t\t\t\tthis.flowDiscoveryState = undefined;\n\t\t\t\tthis.flowIssuerMismatch = false;\n\t\t\t\tthis.flowState = undefined;\n\t\t\t\tclearAllCredentials(this.serverName, this.storageOptions);\n\t\t\t\tbreak;\n\t\t\tcase \"client\":\n\t\t\t\tthis.flowClientInfo = undefined;\n\t\t\t\tclearClientInfo(this.serverName, this.storageOptions);\n\t\t\t\tbreak;\n\t\t\tcase \"tokens\":\n\t\t\t\tclearTokens(this.serverName, this.storageOptions);\n\t\t\t\tbreak;\n\t\t\tcase \"verifier\":\n\t\t\t\tclearCodeVerifier(this.serverName, this.storageOptions);\n\t\t\t\tbreak;\n\t\t\tcase \"discovery\":\n\t\t\t\tthis.flowDiscoveryState = undefined;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/**\n\t * Adds configured authorization-code scope without replacing the SDK's\n\t * default token endpoint authentication behavior.\n\t */\n\taddClientAuthentication: AddClientAuthentication = async (headers, params, _url, metadata) => {\n\t\tthis.throwIfInactive();\n\t\tif (params.get(\"grant_type\") === \"authorization_code\" && !params.has(\"scope\") && this.config.scope) {\n\t\t\tparams.set(\"scope\", this.config.scope);\n\t\t}\n\n\t\tconst clientInfo = await this.clientInformation();\n\t\tthis.throwIfInactive();\n\t\tif (!clientInfo) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst supportedMethods = metadata?.token_endpoint_auth_methods_supported ?? [];\n\t\tconst hasClientSecret = clientInfo.client_secret !== undefined;\n\t\tlet authMethod: \"client_secret_basic\" | \"client_secret_post\" | \"none\";\n\n\t\tif (supportedMethods.length === 0) {\n\t\t\tauthMethod = hasClientSecret ? \"client_secret_post\" : \"none\";\n\t\t} else if (hasClientSecret && supportedMethods.includes(\"client_secret_basic\")) {\n\t\t\tauthMethod = \"client_secret_basic\";\n\t\t} else if (hasClientSecret && supportedMethods.includes(\"client_secret_post\")) {\n\t\t\tauthMethod = \"client_secret_post\";\n\t\t} else if (supportedMethods.includes(\"none\")) {\n\t\t\tauthMethod = \"none\";\n\t\t} else {\n\t\t\tauthMethod = hasClientSecret ? \"client_secret_post\" : \"none\";\n\t\t}\n\n\t\tif (authMethod === \"client_secret_basic\") {\n\t\t\tif (!clientInfo.client_secret) {\n\t\t\t\tthrow new Error(\"client_secret_basic authentication requires a client_secret\");\n\t\t\t}\n\t\t\theaders.set(\n\t\t\t\t\"Authorization\",\n\t\t\t\t`Basic ${Buffer.from(`${clientInfo.client_id}:${clientInfo.client_secret}`).toString(\"base64\")}`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!params.has(\"client_id\")) {\n\t\t\tparams.set(\"client_id\", clientInfo.client_id);\n\t\t}\n\t\tif (authMethod === \"client_secret_post\" && clientInfo.client_secret && !params.has(\"client_secret\")) {\n\t\t\tparams.set(\"client_secret\", clientInfo.client_secret);\n\t\t}\n\t};\n\n\tprepareTokenRequest(scope?: string): URLSearchParams | undefined {\n\t\tif (!this.usesClientCredentials) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst params = new URLSearchParams({ grant_type: \"client_credentials\" });\n\t\tconst requestedScope = scope ?? this.config.scope;\n\t\tif (requestedScope) {\n\t\t\tparams.set(\"scope\", requestedScope);\n\t\t}\n\t\treturn params;\n\t}\n}\n\nexport { DEFAULT_OAUTH_CALLBACK_PORT, DEFAULT_OAUTH_CALLBACK_PATH };\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ContentBlock, McpSettings } from "./types.ts";
|
|
2
|
+
export declare const DEFAULT_MCP_OUTPUT_MAX_BYTES: number;
|
|
3
|
+
export declare const DEFAULT_MCP_OUTPUT_MAX_LINES = 2000;
|
|
4
|
+
export declare const DEFAULT_MCP_DETAILS_MAX_BYTES: number;
|
|
5
|
+
export interface McpOutputGuardDetails {
|
|
6
|
+
truncated: true;
|
|
7
|
+
originalBytes: number;
|
|
8
|
+
returnedBytes: number;
|
|
9
|
+
originalLines: number;
|
|
10
|
+
returnedLines: number;
|
|
11
|
+
/** Number of image content blocks returned untouched alongside the truncated text. */
|
|
12
|
+
imageBlocksPassedThrough?: number;
|
|
13
|
+
fullOutputPath?: string;
|
|
14
|
+
writeError?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface McpResultSummary {
|
|
17
|
+
omitted: true;
|
|
18
|
+
reason: string;
|
|
19
|
+
isError: boolean;
|
|
20
|
+
contentBlocks: number;
|
|
21
|
+
contentSummary: Array<Record<string, unknown>>;
|
|
22
|
+
structuredContent?: Record<string, unknown>;
|
|
23
|
+
meta?: Record<string, unknown>;
|
|
24
|
+
extraFields?: Array<Record<string, unknown>>;
|
|
25
|
+
rawResultBytes: number;
|
|
26
|
+
fullResultPath?: string;
|
|
27
|
+
resultWriteError?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface McpOutputGuardOptions {
|
|
30
|
+
enabled?: boolean;
|
|
31
|
+
prefix?: string;
|
|
32
|
+
suffix?: string;
|
|
33
|
+
emptyTextFallback?: string;
|
|
34
|
+
maxBytes?: number;
|
|
35
|
+
maxLines?: number;
|
|
36
|
+
detailsMaxBytes?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Raw MCP result to expose as details.mcpResult. Kept raw when its JSON
|
|
39
|
+
* fits detailsMaxBytes (or when the guard is disabled); otherwise replaced
|
|
40
|
+
* with a compact summary and spilled to a temp file. Omit for call sites
|
|
41
|
+
* whose details never carried the raw result (e.g. direct tools).
|
|
42
|
+
*/
|
|
43
|
+
rawMcpResult?: unknown;
|
|
44
|
+
}
|
|
45
|
+
export interface GuardedMcpOutput {
|
|
46
|
+
content: ContentBlock[];
|
|
47
|
+
outputGuard?: McpOutputGuardDetails;
|
|
48
|
+
mcpResult?: unknown;
|
|
49
|
+
}
|
|
50
|
+
export declare function resolveMcpOutputGuardOptions(settings?: McpSettings): Pick<McpOutputGuardOptions, "enabled" | "maxBytes" | "maxLines" | "detailsMaxBytes">;
|
|
51
|
+
/** Spread helper for tool-result details: includes mcpResult/outputGuard only when present. */
|
|
52
|
+
export declare function guardedMcpDetails(guarded: GuardedMcpOutput): Record<string, unknown>;
|
|
53
|
+
/**
|
|
54
|
+
* Bound model-facing MCP output. Text output is capped at maxBytes/maxLines and
|
|
55
|
+
* spilled to a temp file when oversized. Image blocks pass through untouched —
|
|
56
|
+
* they are delivered to the provider as native image content, not text context.
|
|
57
|
+
*/
|
|
58
|
+
export declare function guardMcpOutput(content: ContentBlock[], options?: McpOutputGuardOptions): Promise<GuardedMcpOutput>;
|
|
59
|
+
//# sourceMappingURL=mcp-output-guard.d.ts.map
|