@mcp-z/client 1.0.7 → 1.0.8

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.
Files changed (88) hide show
  1. package/dist/cjs/auth/capability-discovery.js +2 -5
  2. package/dist/cjs/auth/capability-discovery.js.map +1 -1
  3. package/dist/cjs/auth/index.js.map +1 -1
  4. package/dist/cjs/auth/interactive-oauth-flow.js +13 -30
  5. package/dist/cjs/auth/interactive-oauth-flow.js.map +1 -1
  6. package/dist/cjs/auth/oauth-callback-listener.js +3 -8
  7. package/dist/cjs/auth/oauth-callback-listener.js.map +1 -1
  8. package/dist/cjs/auth/pkce.js +2 -5
  9. package/dist/cjs/auth/pkce.js.map +1 -1
  10. package/dist/cjs/auth/rfc9728-discovery.js +2 -5
  11. package/dist/cjs/auth/rfc9728-discovery.js.map +1 -1
  12. package/dist/cjs/auth/types.js.map +1 -1
  13. package/dist/cjs/client-helpers.js +4 -6
  14. package/dist/cjs/client-helpers.js.map +1 -1
  15. package/dist/cjs/config/server-loader.js +8 -19
  16. package/dist/cjs/config/server-loader.js.map +1 -1
  17. package/dist/cjs/config/validate-config.js +8 -19
  18. package/dist/cjs/config/validate-config.js.map +1 -1
  19. package/dist/cjs/connection/connect-client.js +5 -11
  20. package/dist/cjs/connection/connect-client.js.map +1 -1
  21. package/dist/cjs/connection/existing-process-transport.js +3 -8
  22. package/dist/cjs/connection/existing-process-transport.js.map +1 -1
  23. package/dist/cjs/connection/types.d.cts +1 -1
  24. package/dist/cjs/connection/types.d.ts +1 -1
  25. package/dist/cjs/connection/types.js.map +1 -1
  26. package/dist/cjs/connection/wait-for-http-ready.js +2 -5
  27. package/dist/cjs/connection/wait-for-http-ready.js.map +1 -1
  28. package/dist/cjs/constants.js.map +1 -1
  29. package/dist/cjs/dcr/dcr-authenticator.js +13 -30
  30. package/dist/cjs/dcr/dcr-authenticator.js.map +1 -1
  31. package/dist/cjs/dcr/dynamic-client-registrar.js +3 -8
  32. package/dist/cjs/dcr/dynamic-client-registrar.js.map +1 -1
  33. package/dist/cjs/dcr/index.js.map +1 -1
  34. package/dist/cjs/index.js.map +1 -1
  35. package/dist/cjs/lib/url-utils.js.map +1 -1
  36. package/dist/cjs/monkey-patches.js +11 -14
  37. package/dist/cjs/monkey-patches.js.map +1 -1
  38. package/dist/cjs/response-wrappers.js +24 -31
  39. package/dist/cjs/response-wrappers.js.map +1 -1
  40. package/dist/cjs/search/index.js.map +1 -1
  41. package/dist/cjs/search/search.js +15 -18
  42. package/dist/cjs/search/search.js.map +1 -1
  43. package/dist/cjs/search/types.js.map +1 -1
  44. package/dist/cjs/spawn/spawn-server.js +22 -38
  45. package/dist/cjs/spawn/spawn-server.js.map +1 -1
  46. package/dist/cjs/spawn/spawn-servers.js +29 -47
  47. package/dist/cjs/spawn/spawn-servers.js.map +1 -1
  48. package/dist/cjs/types.js.map +1 -1
  49. package/dist/cjs/utils/logger.js +1 -1
  50. package/dist/cjs/utils/logger.js.map +1 -1
  51. package/dist/cjs/utils/path-utils.js +9 -20
  52. package/dist/cjs/utils/path-utils.js.map +1 -1
  53. package/dist/cjs/utils/sanitizer.js +4 -7
  54. package/dist/cjs/utils/sanitizer.js.map +1 -1
  55. package/dist/esm/auth/capability-discovery.js.map +1 -1
  56. package/dist/esm/auth/index.js.map +1 -1
  57. package/dist/esm/auth/interactive-oauth-flow.js.map +1 -1
  58. package/dist/esm/auth/oauth-callback-listener.js.map +1 -1
  59. package/dist/esm/auth/pkce.js.map +1 -1
  60. package/dist/esm/auth/rfc9728-discovery.js.map +1 -1
  61. package/dist/esm/auth/types.js.map +1 -1
  62. package/dist/esm/client-helpers.js.map +1 -1
  63. package/dist/esm/config/server-loader.js.map +1 -1
  64. package/dist/esm/config/validate-config.js.map +1 -1
  65. package/dist/esm/connection/connect-client.js.map +1 -1
  66. package/dist/esm/connection/existing-process-transport.js.map +1 -1
  67. package/dist/esm/connection/types.d.ts +1 -1
  68. package/dist/esm/connection/types.js.map +1 -1
  69. package/dist/esm/connection/wait-for-http-ready.js.map +1 -1
  70. package/dist/esm/constants.js.map +1 -1
  71. package/dist/esm/dcr/dcr-authenticator.js.map +1 -1
  72. package/dist/esm/dcr/dynamic-client-registrar.js.map +1 -1
  73. package/dist/esm/dcr/index.js.map +1 -1
  74. package/dist/esm/index.js.map +1 -1
  75. package/dist/esm/lib/url-utils.js.map +1 -1
  76. package/dist/esm/monkey-patches.js.map +1 -1
  77. package/dist/esm/response-wrappers.js +6 -3
  78. package/dist/esm/response-wrappers.js.map +1 -1
  79. package/dist/esm/search/index.js.map +1 -1
  80. package/dist/esm/search/search.js.map +1 -1
  81. package/dist/esm/search/types.js.map +1 -1
  82. package/dist/esm/spawn/spawn-server.js.map +1 -1
  83. package/dist/esm/spawn/spawn-servers.js.map +1 -1
  84. package/dist/esm/types.js.map +1 -1
  85. package/dist/esm/utils/logger.js.map +1 -1
  86. package/dist/esm/utils/path-utils.js.map +1 -1
  87. package/dist/esm/utils/sanitizer.js.map +1 -1
  88. package/package.json +9 -3
@@ -21,11 +21,8 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
21
21
  reject(error);
22
22
  return;
23
23
  }
24
- if (info.done) {
25
- resolve(value);
26
- } else {
27
- Promise.resolve(value).then(_next, _throw);
28
- }
24
+ if (info.done) resolve(value);
25
+ else Promise.resolve(value).then(_next, _throw);
29
26
  }
30
27
  function _async_to_generator(fn) {
31
28
  return function() {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/client/src/auth/capability-discovery.ts"],"sourcesContent":["/**\n * OAuth Server Capability Discovery\n * Probes RFC 9728 (Protected Resource) and RFC 8414 (Authorization Server) metadata\n */\n\nimport { normalizeUrl } from '../lib/url-utils.ts';\nimport { discoverAuthorizationServerIssuer, discoverAuthorizationServerMetadata, discoverProtectedResourceMetadata } from './rfc9728-discovery.ts';\nimport type { AuthCapabilities, AuthorizationServerMetadata } from './types.ts';\n\n/**\n * Extract origin (protocol + host) from a URL\n * @param url - Full URL that may include a path\n * @returns Origin (e.g., \"https://example.com\") or original string if invalid URL\n *\n * @example\n * getOrigin('https://example.com/mcp') // → 'https://example.com'\n * getOrigin('http://localhost:9999/api/v1/mcp') // → 'http://localhost:9999'\n */\nfunction getOrigin(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n // Invalid URL - return as-is for graceful degradation\n return url;\n }\n}\n\n/**\n * Probe OAuth server capabilities using RFC 9728 → RFC 8414 discovery chain\n * Returns capabilities including DCR support detection\n *\n * Discovery Strategy:\n * 1. Try RFC 9728 Protected Resource Metadata (supports cross-domain OAuth)\n * 2. If found, use first authorization_server to discover RFC 8414 Authorization Server Metadata\n * 3. Fall back to direct RFC 8414 discovery at resource origin\n *\n * @param baseUrl - Base URL of the protected resource (e.g., https://ai.todoist.net/mcp)\n * @returns AuthCapabilities object with discovered endpoints and features\n *\n * @example\n * // Todoist case: MCP at ai.todoist.net/mcp, OAuth at todoist.com\n * const caps = await probeAuthCapabilities('https://ai.todoist.net/mcp');\n * if (caps.supportsDcr) {\n * console.log('Registration endpoint:', caps.registrationEndpoint);\n * }\n */\nfunction buildCapabilities(metadata: AuthorizationServerMetadata, scopes?: string[]): AuthCapabilities {\n const supportsDcr = !!metadata.registration_endpoint;\n const capabilities: AuthCapabilities = { supportsDcr };\n\n if (metadata.registration_endpoint) {\n capabilities.registrationEndpoint = metadata.registration_endpoint;\n }\n if (metadata.authorization_endpoint) {\n capabilities.authorizationEndpoint = metadata.authorization_endpoint;\n }\n if (metadata.token_endpoint) capabilities.tokenEndpoint = metadata.token_endpoint;\n if (metadata.introspection_endpoint) {\n capabilities.introspectionEndpoint = metadata.introspection_endpoint;\n }\n\n if (scopes && scopes.length > 0) {\n capabilities.scopes = scopes;\n } else if (metadata.scopes_supported) {\n capabilities.scopes = metadata.scopes_supported;\n }\n\n return capabilities;\n}\n\nasync function resolveCapabilitiesFromAuthorizationServer(authServerUrl: string, scopes?: string[]): Promise<AuthCapabilities | null> {\n const metadata = await discoverAuthorizationServerMetadata(authServerUrl);\n if (!metadata) return null;\n return buildCapabilities(metadata, scopes);\n}\n\nexport async function probeAuthCapabilities(baseUrl: string): Promise<AuthCapabilities> {\n try {\n const normalizedBaseUrl = normalizeUrl(baseUrl);\n // Strategy 1: Try RFC 9728 Protected Resource Metadata discovery\n // This handles cross-domain OAuth (e.g., Todoist: ai.todoist.net/mcp → todoist.com)\n const resourceMetadata = await discoverProtectedResourceMetadata(normalizedBaseUrl);\n\n if (resourceMetadata && resourceMetadata.authorization_servers.length > 0) {\n // Found protected resource metadata with authorization servers\n // Discover the authorization server's metadata (RFC 8414)\n const authServerUrl = resourceMetadata.authorization_servers[0];\n if (!authServerUrl) {\n // Array has length > 0 but first element is undefined/null - skip this path\n return { supportsDcr: false };\n }\n const capabilities = await resolveCapabilitiesFromAuthorizationServer(authServerUrl, resourceMetadata.scopes_supported);\n if (capabilities) {\n return capabilities;\n }\n\n const issuer = await discoverAuthorizationServerIssuer(baseUrl);\n if (issuer) {\n const issuerCapabilities = await resolveCapabilitiesFromAuthorizationServer(issuer, resourceMetadata.scopes_supported);\n if (issuerCapabilities) return issuerCapabilities;\n }\n }\n\n const issuer = await discoverAuthorizationServerIssuer(normalizedBaseUrl);\n if (issuer) {\n const issuerCapabilities = await resolveCapabilitiesFromAuthorizationServer(issuer);\n if (issuerCapabilities) return issuerCapabilities;\n }\n\n // Strategy 2: Fall back to direct RFC 8414 discovery at resource origin\n // This handles same-domain OAuth (traditional setup)\n const origin = getOrigin(normalizedBaseUrl);\n const originCapabilities = await resolveCapabilitiesFromAuthorizationServer(origin);\n if (originCapabilities) return originCapabilities;\n\n // No OAuth metadata found\n return { supportsDcr: false };\n } catch (_error) {\n // Network error, invalid JSON, or other fetch failure\n // Gracefully degrade - assume no DCR support\n return { supportsDcr: false };\n }\n}\n"],"names":["probeAuthCapabilities","getOrigin","url","URL","origin","buildCapabilities","metadata","scopes","supportsDcr","registration_endpoint","capabilities","registrationEndpoint","authorization_endpoint","authorizationEndpoint","token_endpoint","tokenEndpoint","introspection_endpoint","introspectionEndpoint","length","scopes_supported","resolveCapabilitiesFromAuthorizationServer","authServerUrl","discoverAuthorizationServerMetadata","baseUrl","normalizedBaseUrl","resourceMetadata","issuer","issuerCapabilities","originCapabilities","_error","normalizeUrl","discoverProtectedResourceMetadata","authorization_servers","discoverAuthorizationServerIssuer"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/auth/capability-discovery.ts"],"sourcesContent":["/**\n * OAuth Server Capability Discovery\n * Probes RFC 9728 (Protected Resource) and RFC 8414 (Authorization Server) metadata\n */\n\nimport { normalizeUrl } from '../lib/url-utils.ts';\nimport { discoverAuthorizationServerIssuer, discoverAuthorizationServerMetadata, discoverProtectedResourceMetadata } from './rfc9728-discovery.ts';\nimport type { AuthCapabilities, AuthorizationServerMetadata } from './types.ts';\n\n/**\n * Extract origin (protocol + host) from a URL\n * @param url - Full URL that may include a path\n * @returns Origin (e.g., \"https://example.com\") or original string if invalid URL\n *\n * @example\n * getOrigin('https://example.com/mcp') // → 'https://example.com'\n * getOrigin('http://localhost:9999/api/v1/mcp') // → 'http://localhost:9999'\n */\nfunction getOrigin(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n // Invalid URL - return as-is for graceful degradation\n return url;\n }\n}\n\n/**\n * Probe OAuth server capabilities using RFC 9728 → RFC 8414 discovery chain\n * Returns capabilities including DCR support detection\n *\n * Discovery Strategy:\n * 1. Try RFC 9728 Protected Resource Metadata (supports cross-domain OAuth)\n * 2. If found, use first authorization_server to discover RFC 8414 Authorization Server Metadata\n * 3. Fall back to direct RFC 8414 discovery at resource origin\n *\n * @param baseUrl - Base URL of the protected resource (e.g., https://ai.todoist.net/mcp)\n * @returns AuthCapabilities object with discovered endpoints and features\n *\n * @example\n * // Todoist case: MCP at ai.todoist.net/mcp, OAuth at todoist.com\n * const caps = await probeAuthCapabilities('https://ai.todoist.net/mcp');\n * if (caps.supportsDcr) {\n * console.log('Registration endpoint:', caps.registrationEndpoint);\n * }\n */\nfunction buildCapabilities(metadata: AuthorizationServerMetadata, scopes?: string[]): AuthCapabilities {\n const supportsDcr = !!metadata.registration_endpoint;\n const capabilities: AuthCapabilities = { supportsDcr };\n\n if (metadata.registration_endpoint) {\n capabilities.registrationEndpoint = metadata.registration_endpoint;\n }\n if (metadata.authorization_endpoint) {\n capabilities.authorizationEndpoint = metadata.authorization_endpoint;\n }\n if (metadata.token_endpoint) capabilities.tokenEndpoint = metadata.token_endpoint;\n if (metadata.introspection_endpoint) {\n capabilities.introspectionEndpoint = metadata.introspection_endpoint;\n }\n\n if (scopes && scopes.length > 0) {\n capabilities.scopes = scopes;\n } else if (metadata.scopes_supported) {\n capabilities.scopes = metadata.scopes_supported;\n }\n\n return capabilities;\n}\n\nasync function resolveCapabilitiesFromAuthorizationServer(authServerUrl: string, scopes?: string[]): Promise<AuthCapabilities | null> {\n const metadata = await discoverAuthorizationServerMetadata(authServerUrl);\n if (!metadata) return null;\n return buildCapabilities(metadata, scopes);\n}\n\nexport async function probeAuthCapabilities(baseUrl: string): Promise<AuthCapabilities> {\n try {\n const normalizedBaseUrl = normalizeUrl(baseUrl);\n // Strategy 1: Try RFC 9728 Protected Resource Metadata discovery\n // This handles cross-domain OAuth (e.g., Todoist: ai.todoist.net/mcp → todoist.com)\n const resourceMetadata = await discoverProtectedResourceMetadata(normalizedBaseUrl);\n\n if (resourceMetadata && resourceMetadata.authorization_servers.length > 0) {\n // Found protected resource metadata with authorization servers\n // Discover the authorization server's metadata (RFC 8414)\n const authServerUrl = resourceMetadata.authorization_servers[0];\n if (!authServerUrl) {\n // Array has length > 0 but first element is undefined/null - skip this path\n return { supportsDcr: false };\n }\n const capabilities = await resolveCapabilitiesFromAuthorizationServer(authServerUrl, resourceMetadata.scopes_supported);\n if (capabilities) {\n return capabilities;\n }\n\n const issuer = await discoverAuthorizationServerIssuer(baseUrl);\n if (issuer) {\n const issuerCapabilities = await resolveCapabilitiesFromAuthorizationServer(issuer, resourceMetadata.scopes_supported);\n if (issuerCapabilities) return issuerCapabilities;\n }\n }\n\n const issuer = await discoverAuthorizationServerIssuer(normalizedBaseUrl);\n if (issuer) {\n const issuerCapabilities = await resolveCapabilitiesFromAuthorizationServer(issuer);\n if (issuerCapabilities) return issuerCapabilities;\n }\n\n // Strategy 2: Fall back to direct RFC 8414 discovery at resource origin\n // This handles same-domain OAuth (traditional setup)\n const origin = getOrigin(normalizedBaseUrl);\n const originCapabilities = await resolveCapabilitiesFromAuthorizationServer(origin);\n if (originCapabilities) return originCapabilities;\n\n // No OAuth metadata found\n return { supportsDcr: false };\n } catch (_error) {\n // Network error, invalid JSON, or other fetch failure\n // Gracefully degrade - assume no DCR support\n return { supportsDcr: false };\n }\n}\n"],"names":["probeAuthCapabilities","getOrigin","url","URL","origin","buildCapabilities","metadata","scopes","supportsDcr","registration_endpoint","capabilities","registrationEndpoint","authorization_endpoint","authorizationEndpoint","token_endpoint","tokenEndpoint","introspection_endpoint","introspectionEndpoint","length","scopes_supported","resolveCapabilitiesFromAuthorizationServer","authServerUrl","discoverAuthorizationServerMetadata","baseUrl","normalizedBaseUrl","resourceMetadata","issuer","issuerCapabilities","originCapabilities","_error","normalizeUrl","discoverProtectedResourceMetadata","authorization_servers","discoverAuthorizationServerIssuer"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/client/src/auth/index.ts"],"sourcesContent":["/**\n * Authentication Module\n * Exports public API for OAuth authentication only (DCR moved to ../dcr/)\n */\n\nexport { probeAuthCapabilities } from './capability-discovery.ts';\nexport { InteractiveOAuthFlow } from './interactive-oauth-flow.ts';\nexport type { OAuthCallbackListenerOptions } from './oauth-callback-listener.ts';\nexport { OAuthCallbackListener } from './oauth-callback-listener.ts';\nexport type { AuthCapabilities, CallbackResult, OAuthFlowOptions, TokenSet } from './types.ts';\n"],"names":["InteractiveOAuthFlow","OAuthCallbackListener","probeAuthCapabilities"],"mappings":"AAAA;;;CAGC;;;;;;;;;;;QAGQA;eAAAA,4CAAoB;;QAEpBC;eAAAA,8CAAqB;;QAHrBC;eAAAA,4CAAqB;;;qCAAQ;sCACD;uCAEC"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/auth/index.ts"],"sourcesContent":["/**\n * Authentication Module\n * Exports public API for OAuth authentication only (DCR moved to ../dcr/)\n */\n\nexport { probeAuthCapabilities } from './capability-discovery.ts';\nexport { InteractiveOAuthFlow } from './interactive-oauth-flow.ts';\nexport type { OAuthCallbackListenerOptions } from './oauth-callback-listener.ts';\nexport { OAuthCallbackListener } from './oauth-callback-listener.ts';\nexport type { AuthCapabilities, CallbackResult, OAuthFlowOptions, TokenSet } from './types.ts';\n"],"names":["InteractiveOAuthFlow","OAuthCallbackListener","probeAuthCapabilities"],"mappings":"AAAA;;;CAGC;;;;;;;;;;;QAGQA;eAAAA,4CAAoB;;QAEpBC;eAAAA,8CAAqB;;QAHrBC;eAAAA,4CAAqB;;;qCAAQ;sCACD;uCAEC"}
@@ -23,11 +23,8 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
23
23
  reject(error);
24
24
  return;
25
25
  }
26
- if (info.done) {
27
- resolve(value);
28
- } else {
29
- Promise.resolve(value).then(_next, _throw);
30
- }
26
+ if (info.done) resolve(value);
27
+ else Promise.resolve(value).then(_next, _throw);
31
28
  }
32
29
  function _async_to_generator(fn) {
33
30
  return function() {
@@ -45,16 +42,13 @@ function _async_to_generator(fn) {
45
42
  };
46
43
  }
47
44
  function _class_call_check(instance, Constructor) {
48
- if (!(instance instanceof Constructor)) {
49
- throw new TypeError("Cannot call a class as a function");
50
- }
45
+ if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
51
46
  }
52
47
  function _instanceof(left, right) {
48
+ "@swc/helpers - instanceof";
53
49
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
54
50
  return !!right[Symbol.hasInstance](left);
55
- } else {
56
- return left instanceof right;
57
- }
51
+ } else return left instanceof right;
58
52
  }
59
53
  function _getRequireWildcardCache(nodeInterop) {
60
54
  if (typeof WeakMap !== "function") return null;
@@ -65,18 +59,12 @@ function _getRequireWildcardCache(nodeInterop) {
65
59
  })(nodeInterop);
66
60
  }
67
61
  function _interop_require_wildcard(obj, nodeInterop) {
68
- if (!nodeInterop && obj && obj.__esModule) {
69
- return obj;
70
- }
71
- if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
72
- return {
73
- default: obj
74
- };
75
- }
62
+ if (!nodeInterop && obj && obj.__esModule) return obj;
63
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") return {
64
+ default: obj
65
+ };
76
66
  var cache = _getRequireWildcardCache(nodeInterop);
77
- if (cache && cache.has(obj)) {
78
- return cache.get(obj);
79
- }
67
+ if (cache && cache.has(obj)) return cache.get(obj);
80
68
  var newObj = {
81
69
  __proto__: null
82
70
  };
@@ -84,17 +72,12 @@ function _interop_require_wildcard(obj, nodeInterop) {
84
72
  for(var key in obj){
85
73
  if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
86
74
  var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
87
- if (desc && (desc.get || desc.set)) {
88
- Object.defineProperty(newObj, key, desc);
89
- } else {
90
- newObj[key] = obj[key];
91
- }
75
+ if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc);
76
+ else newObj[key] = obj[key];
92
77
  }
93
78
  }
94
79
  newObj.default = obj;
95
- if (cache) {
96
- cache.set(obj, newObj);
97
- }
80
+ if (cache) cache.set(obj, newObj);
98
81
  return newObj;
99
82
  }
100
83
  function _ts_generator(thisArg, body) {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/client/src/auth/interactive-oauth-flow.ts"],"sourcesContent":["/**\n * OAuth Authorization Flow Handler\n * Manages browser-based OAuth flows and token exchange with PKCE support\n */\n\nimport * as child_process from 'node:child_process';\nimport { logger as defaultLogger } from '../utils/logger.ts';\nimport { OAuthCallbackListener } from './oauth-callback-listener.ts';\nimport { generatePkce } from './pkce.ts';\nimport type { OAuthFlowOptions, PkceParams, TokenSet } from './types.ts';\n\n/**\n * OAuth token response from token endpoint\n */\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n scope?: string;\n token_type?: string;\n}\n\n/**\n * InteractiveOAuthFlow manages the complete OAuth authorization code flow\n */\nexport class InteractiveOAuthFlow {\n /**\n * Perform OAuth authorization code flow\n *\n * @param authorizationEndpoint - OAuth authorization endpoint URL\n * @param tokenEndpoint - OAuth token endpoint URL\n * @param clientId - OAuth client ID\n * @param clientSecret - OAuth client secret\n * @param options - Flow options (port is required - use get-port to find available port)\n * @returns Token set with access and refresh tokens\n *\n * @throws Error if flow fails or times out\n *\n * @example\n * import getPort from 'get-port';\n *\n * const flow = new InteractiveOAuthFlow();\n * const port = await getPort();\n * const tokens = await flow.performAuthFlow(\n * 'https://example.com/oauth/authorize',\n * 'https://example.com/oauth/token',\n * 'client-id',\n * 'client-secret',\n * { port, scopes: ['read', 'write'] }\n * );\n */\n async performAuthFlow(authorizationEndpoint: string, tokenEndpoint: string, clientId: string, clientSecret: string, options: OAuthFlowOptions): Promise<TokenSet> {\n const logger = options.logger ?? defaultLogger;\n const callbackListener = new OAuthCallbackListener({ port: options.port, logger });\n\n // Generate PKCE parameters if requested (RFC 7636)\n let pkce: PkceParams | undefined;\n if (options.pkce) {\n logger.debug('🔐 Generating PKCE parameters...');\n pkce = await generatePkce();\n }\n\n try {\n // Start callback server\n await callbackListener.start();\n\n // Build redirect URI\n const redirectUri = options.redirectUri || `http://localhost:${options.port}/callback`;\n\n // Build authorization URL\n const authUrl = new URL(authorizationEndpoint);\n authUrl.searchParams.set('client_id', clientId);\n authUrl.searchParams.set('redirect_uri', redirectUri);\n authUrl.searchParams.set('response_type', 'code');\n\n if (options.scopes && options.scopes.length > 0) {\n authUrl.searchParams.set('scope', options.scopes.join(' '));\n }\n\n // Add resource parameter if specified (RFC 8707)\n if (options.resource) {\n authUrl.searchParams.set('resource', options.resource);\n }\n\n // Add PKCE parameters if generated (RFC 7636)\n if (pkce) {\n authUrl.searchParams.set('code_challenge', pkce.codeChallenge);\n authUrl.searchParams.set('code_challenge_method', pkce.codeChallengeMethod);\n }\n\n // Open browser or print URL for headless mode\n if (options.headless) {\n logger.info('🔗 Please visit this URL to authorize:');\n logger.info(authUrl.toString());\n logger.info('Waiting for callback...');\n } else {\n logger.debug('🌐 Opening browser for OAuth authorization...');\n // Try to open browser (requires 'open' package or native command)\n await this.openBrowser(authUrl.toString());\n }\n\n // Wait for callback with timeout\n const timeout = options.timeout || (options.headless ? 60000 : 300000);\n const result = await callbackListener.waitForCallback(timeout);\n\n // Exchange authorization code for tokens (with PKCE verifier if used)\n const tokens = await this.exchangeCodeForTokens(tokenEndpoint, result.code, clientId, clientSecret, redirectUri, pkce?.codeVerifier);\n\n return tokens;\n } catch (error) {\n logger.error('❌ OAuth flow failed:', error instanceof Error ? error.message : String(error));\n throw error;\n } finally {\n // Always close callback server\n await callbackListener.stop();\n }\n }\n\n /**\n * Exchange authorization code for access and refresh tokens\n * @param codeVerifier - Optional PKCE code verifier (RFC 7636)\n */\n private async exchangeCodeForTokens(tokenEndpoint: string, code: string, clientId: string, clientSecret: string, redirectUri: string, codeVerifier?: string): Promise<TokenSet> {\n const params = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: redirectUri,\n client_id: clientId,\n client_secret: clientSecret,\n });\n\n // Add PKCE code verifier if provided (RFC 7636)\n if (codeVerifier) {\n params.set('code_verifier', codeVerifier);\n }\n\n const response = await fetch(tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n Connection: 'close',\n },\n body: params,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed (${response.status}): ${errorText}`);\n }\n\n const data = (await response.json()) as TokenResponse;\n\n if (!data.access_token) {\n throw new Error('Token response missing access_token');\n }\n\n const tokenSet: TokenSet = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token || '',\n expiresAt: Date.now() + data.expires_in * 1000,\n clientId,\n clientSecret,\n };\n\n if (data.scope) {\n tokenSet.scopes = data.scope.split(' ');\n }\n\n return tokenSet;\n }\n\n /**\n * Refresh access token using refresh token\n *\n * @param tokenEndpoint - OAuth token endpoint URL\n * @param refreshToken - Refresh token from previous token set\n * @param clientId - OAuth client ID\n * @param clientSecret - OAuth client secret\n * @returns New token set with refreshed access token\n *\n * @throws Error if refresh fails\n */\n async refreshTokens(tokenEndpoint: string, refreshToken: string, clientId: string, clientSecret: string): Promise<TokenSet> {\n const response = await fetch(tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n Connection: 'close',\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: clientId,\n client_secret: clientSecret,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed (${response.status}): ${errorText}`);\n }\n\n const data = (await response.json()) as TokenResponse;\n\n if (!data.access_token) {\n throw new Error('Token refresh response missing access_token');\n }\n\n const tokenSet: TokenSet = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token || refreshToken, // Reuse old refresh token if not provided\n expiresAt: Date.now() + data.expires_in * 1000,\n clientId,\n clientSecret,\n };\n\n if (data.scope) {\n tokenSet.scopes = data.scope.split(' ');\n }\n\n return tokenSet;\n }\n\n /**\n * Open browser to authorization URL\n * Uses platform-specific command to open default browser\n */\n private async openBrowser(url: string): Promise<void> {\n // Determine platform-specific command\n const platform = process.platform;\n let command: string;\n let args: string[];\n\n if (platform === 'darwin') {\n command = 'open';\n args = [url];\n } else if (platform === 'win32') {\n command = 'cmd';\n args = ['/c', 'start', url];\n } else {\n // Linux and others\n command = 'xdg-open';\n args = [url];\n }\n\n // Spawn browser process\n const child = child_process.spawn(command, args, {\n detached: true,\n stdio: 'ignore',\n });\n\n child.unref();\n }\n}\n"],"names":["InteractiveOAuthFlow","performAuthFlow","authorizationEndpoint","tokenEndpoint","clientId","clientSecret","options","logger","callbackListener","pkce","redirectUri","authUrl","timeout","result","tokens","error","defaultLogger","OAuthCallbackListener","port","debug","generatePkce","start","URL","searchParams","set","scopes","length","join","resource","codeChallenge","codeChallengeMethod","headless","info","toString","openBrowser","waitForCallback","exchangeCodeForTokens","code","codeVerifier","Error","message","String","stop","params","response","errorText","data","tokenSet","URLSearchParams","grant_type","redirect_uri","client_id","client_secret","fetch","method","headers","Accept","Connection","body","ok","text","status","json","access_token","accessToken","refreshToken","refresh_token","expiresAt","Date","now","expires_in","scope","split","refreshTokens","url","platform","command","args","child","process","child_process","spawn","detached","stdio","unref"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/auth/interactive-oauth-flow.ts"],"sourcesContent":["/**\n * OAuth Authorization Flow Handler\n * Manages browser-based OAuth flows and token exchange with PKCE support\n */\n\nimport * as child_process from 'node:child_process';\nimport { logger as defaultLogger } from '../utils/logger.ts';\nimport { OAuthCallbackListener } from './oauth-callback-listener.ts';\nimport { generatePkce } from './pkce.ts';\nimport type { OAuthFlowOptions, PkceParams, TokenSet } from './types.ts';\n\n/**\n * OAuth token response from token endpoint\n */\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n scope?: string;\n token_type?: string;\n}\n\n/**\n * InteractiveOAuthFlow manages the complete OAuth authorization code flow\n */\nexport class InteractiveOAuthFlow {\n /**\n * Perform OAuth authorization code flow\n *\n * @param authorizationEndpoint - OAuth authorization endpoint URL\n * @param tokenEndpoint - OAuth token endpoint URL\n * @param clientId - OAuth client ID\n * @param clientSecret - OAuth client secret\n * @param options - Flow options (port is required - use get-port to find available port)\n * @returns Token set with access and refresh tokens\n *\n * @throws Error if flow fails or times out\n *\n * @example\n * import getPort from 'get-port';\n *\n * const flow = new InteractiveOAuthFlow();\n * const port = await getPort();\n * const tokens = await flow.performAuthFlow(\n * 'https://example.com/oauth/authorize',\n * 'https://example.com/oauth/token',\n * 'client-id',\n * 'client-secret',\n * { port, scopes: ['read', 'write'] }\n * );\n */\n async performAuthFlow(authorizationEndpoint: string, tokenEndpoint: string, clientId: string, clientSecret: string, options: OAuthFlowOptions): Promise<TokenSet> {\n const logger = options.logger ?? defaultLogger;\n const callbackListener = new OAuthCallbackListener({ port: options.port, logger });\n\n // Generate PKCE parameters if requested (RFC 7636)\n let pkce: PkceParams | undefined;\n if (options.pkce) {\n logger.debug('🔐 Generating PKCE parameters...');\n pkce = await generatePkce();\n }\n\n try {\n // Start callback server\n await callbackListener.start();\n\n // Build redirect URI\n const redirectUri = options.redirectUri || `http://localhost:${options.port}/callback`;\n\n // Build authorization URL\n const authUrl = new URL(authorizationEndpoint);\n authUrl.searchParams.set('client_id', clientId);\n authUrl.searchParams.set('redirect_uri', redirectUri);\n authUrl.searchParams.set('response_type', 'code');\n\n if (options.scopes && options.scopes.length > 0) {\n authUrl.searchParams.set('scope', options.scopes.join(' '));\n }\n\n // Add resource parameter if specified (RFC 8707)\n if (options.resource) {\n authUrl.searchParams.set('resource', options.resource);\n }\n\n // Add PKCE parameters if generated (RFC 7636)\n if (pkce) {\n authUrl.searchParams.set('code_challenge', pkce.codeChallenge);\n authUrl.searchParams.set('code_challenge_method', pkce.codeChallengeMethod);\n }\n\n // Open browser or print URL for headless mode\n if (options.headless) {\n logger.info('🔗 Please visit this URL to authorize:');\n logger.info(authUrl.toString());\n logger.info('Waiting for callback...');\n } else {\n logger.debug('🌐 Opening browser for OAuth authorization...');\n // Try to open browser (requires 'open' package or native command)\n await this.openBrowser(authUrl.toString());\n }\n\n // Wait for callback with timeout\n const timeout = options.timeout || (options.headless ? 60000 : 300000);\n const result = await callbackListener.waitForCallback(timeout);\n\n // Exchange authorization code for tokens (with PKCE verifier if used)\n const tokens = await this.exchangeCodeForTokens(tokenEndpoint, result.code, clientId, clientSecret, redirectUri, pkce?.codeVerifier);\n\n return tokens;\n } catch (error) {\n logger.error('❌ OAuth flow failed:', error instanceof Error ? error.message : String(error));\n throw error;\n } finally {\n // Always close callback server\n await callbackListener.stop();\n }\n }\n\n /**\n * Exchange authorization code for access and refresh tokens\n * @param codeVerifier - Optional PKCE code verifier (RFC 7636)\n */\n private async exchangeCodeForTokens(tokenEndpoint: string, code: string, clientId: string, clientSecret: string, redirectUri: string, codeVerifier?: string): Promise<TokenSet> {\n const params = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: redirectUri,\n client_id: clientId,\n client_secret: clientSecret,\n });\n\n // Add PKCE code verifier if provided (RFC 7636)\n if (codeVerifier) {\n params.set('code_verifier', codeVerifier);\n }\n\n const response = await fetch(tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n Connection: 'close',\n },\n body: params,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token exchange failed (${response.status}): ${errorText}`);\n }\n\n const data = (await response.json()) as TokenResponse;\n\n if (!data.access_token) {\n throw new Error('Token response missing access_token');\n }\n\n const tokenSet: TokenSet = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token || '',\n expiresAt: Date.now() + data.expires_in * 1000,\n clientId,\n clientSecret,\n };\n\n if (data.scope) {\n tokenSet.scopes = data.scope.split(' ');\n }\n\n return tokenSet;\n }\n\n /**\n * Refresh access token using refresh token\n *\n * @param tokenEndpoint - OAuth token endpoint URL\n * @param refreshToken - Refresh token from previous token set\n * @param clientId - OAuth client ID\n * @param clientSecret - OAuth client secret\n * @returns New token set with refreshed access token\n *\n * @throws Error if refresh fails\n */\n async refreshTokens(tokenEndpoint: string, refreshToken: string, clientId: string, clientSecret: string): Promise<TokenSet> {\n const response = await fetch(tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Accept: 'application/json',\n Connection: 'close',\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: clientId,\n client_secret: clientSecret,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Token refresh failed (${response.status}): ${errorText}`);\n }\n\n const data = (await response.json()) as TokenResponse;\n\n if (!data.access_token) {\n throw new Error('Token refresh response missing access_token');\n }\n\n const tokenSet: TokenSet = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token || refreshToken, // Reuse old refresh token if not provided\n expiresAt: Date.now() + data.expires_in * 1000,\n clientId,\n clientSecret,\n };\n\n if (data.scope) {\n tokenSet.scopes = data.scope.split(' ');\n }\n\n return tokenSet;\n }\n\n /**\n * Open browser to authorization URL\n * Uses platform-specific command to open default browser\n */\n private async openBrowser(url: string): Promise<void> {\n // Determine platform-specific command\n const platform = process.platform;\n let command: string;\n let args: string[];\n\n if (platform === 'darwin') {\n command = 'open';\n args = [url];\n } else if (platform === 'win32') {\n command = 'cmd';\n args = ['/c', 'start', url];\n } else {\n // Linux and others\n command = 'xdg-open';\n args = [url];\n }\n\n // Spawn browser process\n const child = child_process.spawn(command, args, {\n detached: true,\n stdio: 'ignore',\n });\n\n child.unref();\n }\n}\n"],"names":["InteractiveOAuthFlow","performAuthFlow","authorizationEndpoint","tokenEndpoint","clientId","clientSecret","options","logger","callbackListener","pkce","redirectUri","authUrl","timeout","result","tokens","error","defaultLogger","OAuthCallbackListener","port","debug","generatePkce","start","URL","searchParams","set","scopes","length","join","resource","codeChallenge","codeChallengeMethod","headless","info","toString","openBrowser","waitForCallback","exchangeCodeForTokens","code","codeVerifier","Error","message","String","stop","params","response","errorText","data","tokenSet","URLSearchParams","grant_type","redirect_uri","client_id","client_secret","fetch","method","headers","Accept","Connection","body","ok","text","status","json","access_token","accessToken","refreshToken","refresh_token","expiresAt","Date","now","expires_in","scope","split","refreshTokens","url","platform","command","args","child","process","child_process","spawn","detached","stdio","unref"],"mappings":"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"}
@@ -21,11 +21,8 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
21
21
  reject(error);
22
22
  return;
23
23
  }
24
- if (info.done) {
25
- resolve(value);
26
- } else {
27
- Promise.resolve(value).then(_next, _throw);
28
- }
24
+ if (info.done) resolve(value);
25
+ else Promise.resolve(value).then(_next, _throw);
29
26
  }
30
27
  function _async_to_generator(fn) {
31
28
  return function() {
@@ -43,9 +40,7 @@ function _async_to_generator(fn) {
43
40
  };
44
41
  }
45
42
  function _class_call_check(instance, Constructor) {
46
- if (!(instance instanceof Constructor)) {
47
- throw new TypeError("Cannot call a class as a function");
48
- }
43
+ if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
49
44
  }
50
45
  function _interop_require_default(obj) {
51
46
  return obj && obj.__esModule ? obj : {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/client/src/auth/oauth-callback-listener.ts"],"sourcesContent":["/**\n * OAuth Callback Server for CLI Authentication\n * Listens for OAuth authorization callbacks and captures authorization code\n */\n\nimport http from 'node:http';\nimport { logger as defaultLogger, type Logger } from '../utils/logger.ts';\nimport type { CallbackResult } from './types.ts';\n\nexport interface OAuthCallbackListenerOptions {\n /** Port to listen on (required - use get-port package to find available port) */\n port: number;\n /** Optional logger for debug output (defaults to singleton logger) */\n logger?: Logger;\n}\n\n/**\n * OAuthCallbackListener handles OAuth redirect callbacks\n * Starts a temporary HTTP server to receive authorization code\n *\n * Note: Caller is responsible for finding an available port using get-port package\n */\nexport class OAuthCallbackListener {\n private server: http.Server | undefined;\n private resolveCallback?: (result: CallbackResult) => void;\n private rejectCallback?: (error: Error) => void;\n private timeout: NodeJS.Timeout | undefined;\n private port: number;\n private logger: Logger;\n\n constructor(options: OAuthCallbackListenerOptions) {\n this.port = options.port;\n this.logger = options.logger ?? defaultLogger;\n }\n\n /**\n * Start the callback server\n * Fails fast if port is already in use - caller should use get-port to find available port\n */\n async start(): Promise<void> {\n await this.listen(this.port);\n this.logger.debug(`✅ Callback server listening on http://localhost:${this.port}/callback`);\n }\n\n /**\n * Listen on a specific port\n */\n private listen(port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n this.server = http.createServer((req, res) => {\n this.handleRequest(req, res);\n });\n\n this.server.on('error', (error) => {\n reject(error);\n });\n\n this.server.listen(port, () => {\n resolve();\n });\n });\n }\n\n /**\n * Handle incoming HTTP requests\n */\n private handleRequest(req: http.IncomingMessage, res: http.ServerResponse): void {\n const url = new URL(req.url || '', `http://localhost:${this.port}`);\n\n if (url.pathname === '/callback') {\n this.handleCallback(url, res);\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not Found');\n }\n }\n\n /**\n * Handle OAuth callback\n */\n private handleCallback(url: URL, res: http.ServerResponse): void {\n const code = url.searchParams.get('code');\n const state = url.searchParams.get('state');\n const error = url.searchParams.get('error');\n const errorDescription = url.searchParams.get('error_description');\n\n // Handle OAuth errors\n if (error) {\n const errorMessage = errorDescription ? `${error}: ${errorDescription}` : error;\n\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(`\n <html>\n <body>\n <h1>Authorization Failed</h1>\n <p>${errorMessage}</p>\n <script>setTimeout(() => window.close(), 3000);</script>\n </body>\n </html>\n `);\n\n if (this.rejectCallback) {\n this.rejectCallback(new Error(errorMessage));\n }\n return;\n }\n\n // Validate code parameter\n if (!code) {\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(`\n <html>\n <body>\n <h1>Invalid Callback</h1>\n <p>Missing authorization code</p>\n <script>setTimeout(() => window.close(), 3000);</script>\n </body>\n </html>\n `);\n\n if (this.rejectCallback) {\n this.rejectCallback(new Error('Missing authorization code'));\n }\n return;\n }\n\n // Success - send confirmation page\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n </head>\n <body>\n <h1>Authorization Successful</h1>\n <p>You can close this window and return to the terminal.</p>\n <script>setTimeout(() => window.close(), 2000);</script>\n </body>\n </html>\n `);\n\n // Resolve the promise with authorization code\n if (this.resolveCallback) {\n const result: CallbackResult = { code };\n if (state) {\n result.state = state;\n }\n this.resolveCallback(result);\n }\n }\n\n /**\n * Wait for OAuth callback with timeout\n */\n async waitForCallback(timeoutMs = 300000): Promise<CallbackResult> {\n return new Promise((resolve, reject) => {\n this.resolveCallback = resolve;\n this.rejectCallback = reject;\n\n // Set timeout to prevent hanging forever\n this.timeout = setTimeout(() => {\n reject(new Error(`Authorization timeout - no callback received within ${timeoutMs / 1000} seconds`));\n this.stop();\n }, timeoutMs);\n });\n }\n\n /**\n * Stop the callback server and close\n */\n async stop(): Promise<void> {\n // Clear the timeout\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n }\n\n // Close the server\n if (this.server) {\n await new Promise<void>((resolve) => {\n this.server?.close(() => {\n this.logger.debug('🔒 Callback server closed');\n resolve();\n });\n });\n this.server = undefined;\n }\n }\n\n /**\n * Get the callback URL for this server\n */\n getCallbackUrl(): string {\n if (!this.port) {\n throw new Error('Server not started - call start() first');\n }\n return `http://localhost:${this.port}/callback`;\n }\n}\n"],"names":["OAuthCallbackListener","options","port","logger","defaultLogger","start","listen","debug","Promise","resolve","reject","server","http","createServer","req","res","handleRequest","on","error","url","URL","pathname","handleCallback","writeHead","end","code","searchParams","get","state","errorDescription","errorMessage","rejectCallback","Error","resolveCallback","result","waitForCallback","timeoutMs","timeout","setTimeout","stop","clearTimeout","undefined","close","getCallbackUrl"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/auth/oauth-callback-listener.ts"],"sourcesContent":["/**\n * OAuth Callback Server for CLI Authentication\n * Listens for OAuth authorization callbacks and captures authorization code\n */\n\nimport http from 'node:http';\nimport { logger as defaultLogger, type Logger } from '../utils/logger.ts';\nimport type { CallbackResult } from './types.ts';\n\nexport interface OAuthCallbackListenerOptions {\n /** Port to listen on (required - use get-port package to find available port) */\n port: number;\n /** Optional logger for debug output (defaults to singleton logger) */\n logger?: Logger;\n}\n\n/**\n * OAuthCallbackListener handles OAuth redirect callbacks\n * Starts a temporary HTTP server to receive authorization code\n *\n * Note: Caller is responsible for finding an available port using get-port package\n */\nexport class OAuthCallbackListener {\n private server: http.Server | undefined;\n private resolveCallback?: (result: CallbackResult) => void;\n private rejectCallback?: (error: Error) => void;\n private timeout: NodeJS.Timeout | undefined;\n private port: number;\n private logger: Logger;\n\n constructor(options: OAuthCallbackListenerOptions) {\n this.port = options.port;\n this.logger = options.logger ?? defaultLogger;\n }\n\n /**\n * Start the callback server\n * Fails fast if port is already in use - caller should use get-port to find available port\n */\n async start(): Promise<void> {\n await this.listen(this.port);\n this.logger.debug(`✅ Callback server listening on http://localhost:${this.port}/callback`);\n }\n\n /**\n * Listen on a specific port\n */\n private listen(port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n this.server = http.createServer((req, res) => {\n this.handleRequest(req, res);\n });\n\n this.server.on('error', (error) => {\n reject(error);\n });\n\n this.server.listen(port, () => {\n resolve();\n });\n });\n }\n\n /**\n * Handle incoming HTTP requests\n */\n private handleRequest(req: http.IncomingMessage, res: http.ServerResponse): void {\n const url = new URL(req.url || '', `http://localhost:${this.port}`);\n\n if (url.pathname === '/callback') {\n this.handleCallback(url, res);\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not Found');\n }\n }\n\n /**\n * Handle OAuth callback\n */\n private handleCallback(url: URL, res: http.ServerResponse): void {\n const code = url.searchParams.get('code');\n const state = url.searchParams.get('state');\n const error = url.searchParams.get('error');\n const errorDescription = url.searchParams.get('error_description');\n\n // Handle OAuth errors\n if (error) {\n const errorMessage = errorDescription ? `${error}: ${errorDescription}` : error;\n\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(`\n <html>\n <body>\n <h1>Authorization Failed</h1>\n <p>${errorMessage}</p>\n <script>setTimeout(() => window.close(), 3000);</script>\n </body>\n </html>\n `);\n\n if (this.rejectCallback) {\n this.rejectCallback(new Error(errorMessage));\n }\n return;\n }\n\n // Validate code parameter\n if (!code) {\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(`\n <html>\n <body>\n <h1>Invalid Callback</h1>\n <p>Missing authorization code</p>\n <script>setTimeout(() => window.close(), 3000);</script>\n </body>\n </html>\n `);\n\n if (this.rejectCallback) {\n this.rejectCallback(new Error('Missing authorization code'));\n }\n return;\n }\n\n // Success - send confirmation page\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(`\n <html>\n <head>\n <meta charset=\"UTF-8\">\n </head>\n <body>\n <h1>Authorization Successful</h1>\n <p>You can close this window and return to the terminal.</p>\n <script>setTimeout(() => window.close(), 2000);</script>\n </body>\n </html>\n `);\n\n // Resolve the promise with authorization code\n if (this.resolveCallback) {\n const result: CallbackResult = { code };\n if (state) {\n result.state = state;\n }\n this.resolveCallback(result);\n }\n }\n\n /**\n * Wait for OAuth callback with timeout\n */\n async waitForCallback(timeoutMs = 300000): Promise<CallbackResult> {\n return new Promise((resolve, reject) => {\n this.resolveCallback = resolve;\n this.rejectCallback = reject;\n\n // Set timeout to prevent hanging forever\n this.timeout = setTimeout(() => {\n reject(new Error(`Authorization timeout - no callback received within ${timeoutMs / 1000} seconds`));\n this.stop();\n }, timeoutMs);\n });\n }\n\n /**\n * Stop the callback server and close\n */\n async stop(): Promise<void> {\n // Clear the timeout\n if (this.timeout) {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n }\n\n // Close the server\n if (this.server) {\n await new Promise<void>((resolve) => {\n this.server?.close(() => {\n this.logger.debug('🔒 Callback server closed');\n resolve();\n });\n });\n this.server = undefined;\n }\n }\n\n /**\n * Get the callback URL for this server\n */\n getCallbackUrl(): string {\n if (!this.port) {\n throw new Error('Server not started - call start() first');\n }\n return `http://localhost:${this.port}/callback`;\n }\n}\n"],"names":["OAuthCallbackListener","options","port","logger","defaultLogger","start","listen","debug","Promise","resolve","reject","server","http","createServer","req","res","handleRequest","on","error","url","URL","pathname","handleCallback","writeHead","end","code","searchParams","get","state","errorDescription","errorMessage","rejectCallback","Error","resolveCallback","result","waitForCallback","timeoutMs","timeout","setTimeout","stop","clearTimeout","undefined","close","getCallbackUrl"],"mappings":"AAAA;;;CAGC;;;;+BAmBYA;;;eAAAA;;;+DAjBI;wBACoC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgB9C,IAAA,AAAMA,sCAAN;;aAAMA,sBAQCC,OAAqC;gCARtCD;YAUKC;QADd,IAAI,CAACC,IAAI,GAAGD,QAAQC,IAAI;QACxB,IAAI,CAACC,MAAM,IAAGF,kBAAAA,QAAQE,MAAM,cAAdF,6BAAAA,kBAAkBG,gBAAa;;iBAVpCJ;IAaX;;;GAGC,GACD,OAAMK,KAGL,GAHD,SAAMA;;;;;wBACJ;;4BAAM,IAAI,CAACC,MAAM,CAAC,IAAI,CAACJ,IAAI;;;wBAA3B;wBACA,IAAI,CAACC,MAAM,CAACI,KAAK,CAAC,AAAC,mDAA4D,OAAV,IAAI,CAACL,IAAI,EAAC;;;;;;QACjF;;IAEA;;GAEC,GACD,OAAQI,MAcP,GAdD,SAAQA,OAAOJ,IAAY;;QACzB,OAAO,IAAIM,QAAQ,SAACC,SAASC;YAC3B,MAAKC,MAAM,GAAGC,iBAAI,CAACC,YAAY,CAAC,SAACC,KAAKC;gBACpC,MAAKC,aAAa,CAACF,KAAKC;YAC1B;YAEA,MAAKJ,MAAM,CAACM,EAAE,CAAC,SAAS,SAACC;gBACvBR,OAAOQ;YACT;YAEA,MAAKP,MAAM,CAACL,MAAM,CAACJ,MAAM;gBACvBO;YACF;QACF;IACF;IAEA;;GAEC,GACD,OAAQO,aASP,GATD,SAAQA,cAAcF,GAAyB,EAAEC,GAAwB;QACvE,IAAMI,MAAM,IAAIC,IAAIN,IAAIK,GAAG,IAAI,IAAI,AAAC,oBAA6B,OAAV,IAAI,CAACjB,IAAI;QAEhE,IAAIiB,IAAIE,QAAQ,KAAK,aAAa;YAChC,IAAI,CAACC,cAAc,CAACH,KAAKJ;QAC3B,OAAO;YACLA,IAAIQ,SAAS,CAAC,KAAK;gBAAE,gBAAgB;YAAa;YAClDR,IAAIS,GAAG,CAAC;QACV;IACF;IAEA;;GAEC,GACD,OAAQF,cAqEP,GArED,SAAQA,eAAeH,GAAQ,EAAEJ,GAAwB;QACvD,IAAMU,OAAON,IAAIO,YAAY,CAACC,GAAG,CAAC;QAClC,IAAMC,QAAQT,IAAIO,YAAY,CAACC,GAAG,CAAC;QACnC,IAAMT,QAAQC,IAAIO,YAAY,CAACC,GAAG,CAAC;QACnC,IAAME,mBAAmBV,IAAIO,YAAY,CAACC,GAAG,CAAC;QAE9C,sBAAsB;QACtB,IAAIT,OAAO;YACT,IAAMY,eAAeD,mBAAmB,AAAC,GAAYA,OAAVX,OAAM,MAAqB,OAAjBW,oBAAqBX;YAE1EH,IAAIQ,SAAS,CAAC,KAAK;gBAAE,gBAAgB;YAAY;YACjDR,IAAIS,GAAG,CAAC,AAAC,iGAIe,OAAbM,cAAa;YAMxB,IAAI,IAAI,CAACC,cAAc,EAAE;gBACvB,IAAI,CAACA,cAAc,CAAC,IAAIC,MAAMF;YAChC;YACA;QACF;QAEA,0BAA0B;QAC1B,IAAI,CAACL,MAAM;YACTV,IAAIQ,SAAS,CAAC,KAAK;gBAAE,gBAAgB;YAAY;YACjDR,IAAIS,GAAG,CAAC;YAUR,IAAI,IAAI,CAACO,cAAc,EAAE;gBACvB,IAAI,CAACA,cAAc,CAAC,IAAIC,MAAM;YAChC;YACA;QACF;QAEA,mCAAmC;QACnCjB,IAAIQ,SAAS,CAAC,KAAK;YAAE,gBAAgB;QAA2B;QAChER,IAAIS,GAAG,CAAC;QAaR,8CAA8C;QAC9C,IAAI,IAAI,CAACS,eAAe,EAAE;YACxB,IAAMC,SAAyB;gBAAET,MAAAA;YAAK;YACtC,IAAIG,OAAO;gBACTM,OAAON,KAAK,GAAGA;YACjB;YACA,IAAI,CAACK,eAAe,CAACC;QACvB;IACF;IAEA;;GAEC,GACD,OAAMC,eAWL,GAXD,SAAMA;YAAgBC,YAAAA,iEAAY;;;;;gBAChC;;oBAAO,IAAI5B,QAAQ,SAACC,SAASC;wBAC3B,MAAKuB,eAAe,GAAGxB;wBACvB,MAAKsB,cAAc,GAAGrB;wBAEtB,yCAAyC;wBACzC,MAAK2B,OAAO,GAAGC,WAAW;4BACxB5B,OAAO,IAAIsB,MAAM,AAAC,uDAAuE,OAAjBI,YAAY,MAAK;4BACzF,MAAKG,IAAI;wBACX,GAAGH;oBACL;;;QACF;;IAEA;;GAEC,GACD,OAAMG,IAiBL,GAjBD,SAAMA;;;;;;;wBACJ,oBAAoB;wBACpB,IAAI,IAAI,CAACF,OAAO,EAAE;4BAChBG,aAAa,IAAI,CAACH,OAAO;4BACzB,IAAI,CAACA,OAAO,GAAGI;wBACjB;6BAGI,IAAI,CAAC9B,MAAM,EAAX;;;;wBACF;;4BAAM,IAAIH,QAAc,SAACC;oCACvB;iCAAA,eAAA,MAAKE,MAAM,cAAX,mCAAA,aAAa+B,KAAK,CAAC;oCACjB,MAAKvC,MAAM,CAACI,KAAK,CAAC;oCAClBE;gCACF;4BACF;;;wBALA;wBAMA,IAAI,CAACE,MAAM,GAAG8B;;;;;;;;QAElB;;IAEA;;GAEC,GACDE,OAAAA,cAKC,GALDA,SAAAA;QACE,IAAI,CAAC,IAAI,CAACzC,IAAI,EAAE;YACd,MAAM,IAAI8B,MAAM;QAClB;QACA,OAAO,AAAC,oBAA6B,OAAV,IAAI,CAAC9B,IAAI,EAAC;IACvC;WA/KWF"}
@@ -20,11 +20,8 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
20
20
  reject(error);
21
21
  return;
22
22
  }
23
- if (info.done) {
24
- resolve(value);
25
- } else {
26
- Promise.resolve(value).then(_next, _throw);
27
- }
23
+ if (info.done) resolve(value);
24
+ else Promise.resolve(value).then(_next, _throw);
28
25
  }
29
26
  function _async_to_generator(fn) {
30
27
  return function() {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/client/src/auth/pkce.ts"],"sourcesContent":["/**\n * PKCE (Proof Key for Code Exchange) utilities\n * Implements RFC 7636 for OAuth 2.0 public client security\n */\n\nimport { createHash, randomBytes } from 'node:crypto';\nimport type { PkceParams } from './types.ts';\n\n/**\n * Generate random code verifier for PKCE (RFC 7636 Section 4.1)\n * Returns cryptographically random string of 43-128 characters using base64url encoding\n */\nfunction generateRandomCodeVerifier(): string {\n // RFC 7636 recommends 43-128 characters\n // Using 32 random bytes -> 43 base64url characters\n return randomBytes(32).toString('base64url');\n}\n\n/**\n * Calculate PKCE code challenge from code verifier (RFC 7636 Section 4.2)\n * Uses S256 method: BASE64URL(SHA256(ASCII(code_verifier)))\n */\nasync function calculatePKCECodeChallenge(codeVerifier: string): Promise<string> {\n const hash = createHash('sha256').update(codeVerifier, 'ascii').digest();\n return Buffer.from(hash).toString('base64url');\n}\n\n/**\n * Generate PKCE parameters for OAuth 2.0 authorization code flow\n * Uses S256 method (SHA-256 hash) as recommended by RFC 7636\n *\n * @returns PkceParams with code verifier, challenge, and method\n *\n * @example\n * const pkce = await generatePkce();\n * // Use pkce.codeChallenge and pkce.codeChallengeMethod in authorization URL\n * // Store pkce.codeVerifier for token exchange\n */\nexport async function generatePkce(): Promise<PkceParams> {\n // Generate cryptographically random code verifier (RFC 7636 § 4.1)\n const codeVerifier = generateRandomCodeVerifier();\n\n // Generate code challenge using S256 method (RFC 7636 § 4.2)\n // S256: BASE64URL(SHA256(ASCII(code_verifier)))\n const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);\n\n return {\n codeVerifier,\n codeChallenge,\n codeChallengeMethod: 'S256',\n };\n}\n"],"names":["generatePkce","generateRandomCodeVerifier","randomBytes","toString","calculatePKCECodeChallenge","codeVerifier","hash","createHash","update","digest","Buffer","from","codeChallenge","codeChallengeMethod"],"mappings":"AAAA;;;CAGC;;;;+BAmCqBA;;;eAAAA;;;0BAjCkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGxC;;;CAGC,GACD,SAASC;IACP,wCAAwC;IACxC,mDAAmD;IACnD,OAAOC,IAAAA,uBAAW,EAAC,IAAIC,QAAQ,CAAC;AAClC;AAEA;;;CAGC,GACD,SAAeC,2BAA2BC,YAAoB;;YACtDC;;YAAAA,OAAOC,IAAAA,sBAAU,EAAC,UAAUC,MAAM,CAACH,cAAc,SAASI,MAAM;YACtE;;gBAAOC,OAAOC,IAAI,CAACL,MAAMH,QAAQ,CAAC;;;IACpC;;AAaO,SAAeH;;YAEdK,cAIAO;;;;oBALN,mEAAmE;oBAC7DP,eAAeJ;oBAIC;;wBAAMG,2BAA2BC;;;oBAAjDO,gBAAgB;oBAEtB;;wBAAO;4BACLP,cAAAA;4BACAO,eAAAA;4BACAC,qBAAqB;wBACvB;;;;IACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/auth/pkce.ts"],"sourcesContent":["/**\n * PKCE (Proof Key for Code Exchange) utilities\n * Implements RFC 7636 for OAuth 2.0 public client security\n */\n\nimport { createHash, randomBytes } from 'node:crypto';\nimport type { PkceParams } from './types.ts';\n\n/**\n * Generate random code verifier for PKCE (RFC 7636 Section 4.1)\n * Returns cryptographically random string of 43-128 characters using base64url encoding\n */\nfunction generateRandomCodeVerifier(): string {\n // RFC 7636 recommends 43-128 characters\n // Using 32 random bytes -> 43 base64url characters\n return randomBytes(32).toString('base64url');\n}\n\n/**\n * Calculate PKCE code challenge from code verifier (RFC 7636 Section 4.2)\n * Uses S256 method: BASE64URL(SHA256(ASCII(code_verifier)))\n */\nasync function calculatePKCECodeChallenge(codeVerifier: string): Promise<string> {\n const hash = createHash('sha256').update(codeVerifier, 'ascii').digest();\n return Buffer.from(hash).toString('base64url');\n}\n\n/**\n * Generate PKCE parameters for OAuth 2.0 authorization code flow\n * Uses S256 method (SHA-256 hash) as recommended by RFC 7636\n *\n * @returns PkceParams with code verifier, challenge, and method\n *\n * @example\n * const pkce = await generatePkce();\n * // Use pkce.codeChallenge and pkce.codeChallengeMethod in authorization URL\n * // Store pkce.codeVerifier for token exchange\n */\nexport async function generatePkce(): Promise<PkceParams> {\n // Generate cryptographically random code verifier (RFC 7636 § 4.1)\n const codeVerifier = generateRandomCodeVerifier();\n\n // Generate code challenge using S256 method (RFC 7636 § 4.2)\n // S256: BASE64URL(SHA256(ASCII(code_verifier)))\n const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);\n\n return {\n codeVerifier,\n codeChallenge,\n codeChallengeMethod: 'S256',\n };\n}\n"],"names":["generatePkce","generateRandomCodeVerifier","randomBytes","toString","calculatePKCECodeChallenge","codeVerifier","hash","createHash","update","digest","Buffer","from","codeChallenge","codeChallengeMethod"],"mappings":"AAAA;;;CAGC;;;;+BAmCqBA;;;eAAAA;;;0BAjCkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGxC;;;CAGC,GACD,SAASC;IACP,wCAAwC;IACxC,mDAAmD;IACnD,OAAOC,IAAAA,uBAAW,EAAC,IAAIC,QAAQ,CAAC;AAClC;AAEA;;;CAGC,GACD,SAAeC,2BAA2BC,YAAoB;;YACtDC;;YAAAA,OAAOC,IAAAA,sBAAU,EAAC,UAAUC,MAAM,CAACH,cAAc,SAASI,MAAM;YACtE;;gBAAOC,OAAOC,IAAI,CAACL,MAAMH,QAAQ,CAAC;;;IACpC;;AAaO,SAAeH;;YAEdK,cAIAO;;;;oBALN,mEAAmE;oBAC7DP,eAAeJ;oBAIC;;wBAAMG,2BAA2BC;;;oBAAjDO,gBAAgB;oBAEtB;;wBAAO;4BACLP,cAAAA;4BACAO,eAAAA;4BACAC,qBAAqB;wBACvB;;;;IACF"}
@@ -31,11 +31,8 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
31
31
  reject(error);
32
32
  return;
33
33
  }
34
- if (info.done) {
35
- resolve(value);
36
- } else {
37
- Promise.resolve(value).then(_next, _throw);
38
- }
34
+ if (info.done) resolve(value);
35
+ else Promise.resolve(value).then(_next, _throw);
39
36
  }
40
37
  function _async_to_generator(fn) {
41
38
  return function() {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/client/src/auth/rfc9728-discovery.ts"],"sourcesContent":["/**\n * RFC 9728 Protected Resource Metadata Discovery\n * Probes .well-known/oauth-protected-resource endpoint\n */\n\nimport { joinWellKnown, normalizeUrl } from '../lib/url-utils.ts';\nimport type { AuthorizationServerMetadata, ProtectedResourceMetadata } from './types.ts';\n\n/**\n * Extract origin (protocol + host) from a URL\n * @param url - Full URL that may include a path\n * @returns Origin (e.g., \"https://example.com\") or original string if invalid URL\n *\n * @example\n * getOrigin('https://example.com/mcp') // → 'https://example.com'\n * getOrigin('http://localhost:9999/api/v1/mcp') // → 'http://localhost:9999'\n */\nfunction getOrigin(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n // Invalid URL - return as-is for graceful degradation\n return url;\n }\n}\n\n/**\n * Extract path from a URL (without origin)\n * @param url - Full URL\n * @returns Path component (e.g., \"/mcp\", \"/api/v1/mcp\") or empty string if no path\n */\nfunction getPath(url: string): string {\n try {\n const parsed = new URL(url);\n // pathname includes leading slash, e.g., \"/mcp\"\n return parsed.pathname === '/' ? '' : parsed.pathname;\n } catch {\n return '';\n }\n}\n\n/**\n * Normalize a resource URL by stripping query/hash and trailing slashes.\n */\n/**\n * Discover OAuth 2.0 Protected Resource Metadata (RFC 9728)\n * Probes .well-known/oauth-protected-resource endpoint\n *\n * Discovery Strategy:\n * 1. Try origin root: {origin}/.well-known/oauth-protected-resource\n * 2. If 404, try sub-path: {origin}/.well-known/oauth-protected-resource{path}\n *\n * @param resourceUrl - URL of the protected resource (e.g., https://ai.todoist.net/mcp)\n * @returns ProtectedResourceMetadata if discovered, null otherwise\n *\n * @example\n * // Todoist case: MCP at ai.todoist.net/mcp, OAuth at todoist.com\n * const metadata = await discoverProtectedResourceMetadata('https://ai.todoist.net/mcp');\n * // Returns: { resource: \"https://ai.todoist.net/mcp\", authorization_servers: [\"https://todoist.com\"] }\n */\nexport async function discoverProtectedResourceMetadata(resourceUrl: string): Promise<ProtectedResourceMetadata | null> {\n try {\n const normalizedResourceUrl = normalizeUrl(resourceUrl);\n const headerMetadata = await discoverProtectedResourceMetadataFromHeader(normalizedResourceUrl);\n if (headerMetadata) return headerMetadata;\n\n // Strategy 0: Try path-local well-known (supports path-prefixed deployments like /outlook)\n const localWellKnownUrl = joinWellKnown(normalizedResourceUrl, '/.well-known/oauth-protected-resource');\n try {\n const response = await fetch(localWellKnownUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n if (response.ok) {\n return (await response.json()) as ProtectedResourceMetadata;\n }\n } catch {\n // Continue to origin-based discovery\n }\n\n const origin = getOrigin(normalizedResourceUrl);\n const path = getPath(normalizedResourceUrl);\n\n // Strategy 1: Try root location (REQUIRED by RFC 9728)\n const rootUrl = `${origin}/.well-known/oauth-protected-resource`;\n\n try {\n const response = await fetch(rootUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (response.ok) {\n const metadata = (await response.json()) as ProtectedResourceMetadata;\n // Check if the discovered resource matches what we're looking for\n if (metadata.resource === normalizedResourceUrl) {\n return metadata;\n }\n // If there's no path component, return root metadata\n // (e.g., looking for http://example.com and found it)\n if (!path) {\n return metadata;\n }\n // If requested URL starts with metadata.resource, the root metadata applies to sub-paths\n // (e.g., looking for http://example.com/api/v1/mcp, found http://example.com)\n if (normalizedResourceUrl.startsWith(metadata.resource)) {\n // Still try sub-path location to see if there's more specific metadata\n // But save root metadata as fallback\n const rootMetadata = metadata;\n\n // Try sub-path location for more specific metadata\n const subPathUrl = `${origin}/.well-known/oauth-protected-resource${path}`;\n try {\n const subPathResponse = await fetch(subPathUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n if (subPathResponse.ok) {\n return (await subPathResponse.json()) as ProtectedResourceMetadata;\n }\n } catch {\n // Sub-path failed, use root metadata\n }\n\n // Return root metadata as it applies to this resource\n return rootMetadata;\n }\n // Otherwise, try sub-path location before giving up\n }\n } catch {\n // Continue to sub-path location\n }\n\n // Strategy 2: Try sub-path location (MCP spec extension)\n // Only try if there's a path component\n if (path) {\n const subPathUrl = `${origin}/.well-known/oauth-protected-resource${path}`;\n\n try {\n const response = await fetch(subPathUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (response.ok) {\n return (await response.json()) as ProtectedResourceMetadata;\n }\n } catch {\n // Fall through to return null\n }\n }\n\n // Neither location found or resource didn't match\n return null;\n } catch (_error) {\n // Network error, invalid URL, or other failure\n return null;\n }\n}\n\nasync function discoverProtectedResourceMetadataFromHeader(resourceUrl: string): Promise<ProtectedResourceMetadata | null> {\n try {\n const response = await fetch(resourceUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n let header = response.headers.get('www-authenticate');\n if (!header) {\n const postResponse = await fetch(resourceUrl, {\n method: 'POST',\n headers: { Accept: 'application/json', Connection: 'close', 'Content-Type': 'application/json' },\n body: '{}',\n });\n header = postResponse.headers.get('www-authenticate');\n }\n\n if (!header) return null;\n\n const match = header.match(/resource_metadata=\"([^\"]+)\"/i);\n if (!match || !match[1]) return null;\n\n const metadataUrl = match[1];\n const metadataResponse = await fetch(metadataUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (!metadataResponse.ok) {\n return null;\n }\n\n return (await metadataResponse.json()) as ProtectedResourceMetadata;\n } catch (_error) {\n return null;\n }\n}\n\n/**\n * Discover OAuth 2.0 Authorization Server Metadata (RFC 8414)\n * Probes .well-known/oauth-authorization-server endpoint\n *\n * @param authServerUrl - URL of the authorization server (typically from RFC 9728 discovery)\n * @returns AuthorizationServerMetadata if discovered, null otherwise\n *\n * @example\n * const metadata = await discoverAuthorizationServerMetadata('https://todoist.com');\n * // Returns: { issuer: \"https://todoist.com\", authorization_endpoint: \"...\", ... }\n */\nexport async function discoverAuthorizationServerMetadata(authServerUrl: string): Promise<AuthorizationServerMetadata | null> {\n try {\n const normalizedAuthServerUrl = normalizeUrl(authServerUrl);\n const localWellKnownUrl = joinWellKnown(normalizedAuthServerUrl, '/.well-known/oauth-authorization-server');\n const localResponse = await fetch(localWellKnownUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (localResponse.ok) {\n return (await localResponse.json()) as AuthorizationServerMetadata;\n }\n\n const origin = getOrigin(normalizedAuthServerUrl);\n const wellKnownUrl = `${origin}/.well-known/oauth-authorization-server`;\n\n const response = await fetch(wellKnownUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (!response.ok) {\n return null;\n }\n\n return (await response.json()) as AuthorizationServerMetadata;\n } catch (_error) {\n return null;\n }\n}\n\n/**\n * Discover OAuth Authorization Server Issuer from resource response (RFC 9207)\n *\n * @param resourceUrl - URL of the protected resource\n * @returns Issuer URL if present in WWW-Authenticate header, null otherwise\n */\nexport async function discoverAuthorizationServerIssuer(resourceUrl: string): Promise<string | null> {\n try {\n const response = await fetch(resourceUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n const header = response.headers.get('www-authenticate');\n if (!header) return null;\n\n const match = header.match(/(?:authorization_server|issuer)=\"([^\"]+)\"/i);\n if (!match) return null;\n\n return match[1] ?? null;\n } catch (_error) {\n return null;\n }\n}\n"],"names":["discoverAuthorizationServerIssuer","discoverAuthorizationServerMetadata","discoverProtectedResourceMetadata","getOrigin","url","URL","origin","getPath","parsed","pathname","resourceUrl","normalizedResourceUrl","headerMetadata","localWellKnownUrl","response","path","rootUrl","metadata","rootMetadata","subPathUrl","subPathResponse","_error","normalizeUrl","discoverProtectedResourceMetadataFromHeader","joinWellKnown","fetch","method","headers","Accept","Connection","ok","json","resource","startsWith","header","postResponse","match","metadataUrl","metadataResponse","get","body","authServerUrl","normalizedAuthServerUrl","localResponse","wellKnownUrl"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/auth/rfc9728-discovery.ts"],"sourcesContent":["/**\n * RFC 9728 Protected Resource Metadata Discovery\n * Probes .well-known/oauth-protected-resource endpoint\n */\n\nimport { joinWellKnown, normalizeUrl } from '../lib/url-utils.ts';\nimport type { AuthorizationServerMetadata, ProtectedResourceMetadata } from './types.ts';\n\n/**\n * Extract origin (protocol + host) from a URL\n * @param url - Full URL that may include a path\n * @returns Origin (e.g., \"https://example.com\") or original string if invalid URL\n *\n * @example\n * getOrigin('https://example.com/mcp') // → 'https://example.com'\n * getOrigin('http://localhost:9999/api/v1/mcp') // → 'http://localhost:9999'\n */\nfunction getOrigin(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n // Invalid URL - return as-is for graceful degradation\n return url;\n }\n}\n\n/**\n * Extract path from a URL (without origin)\n * @param url - Full URL\n * @returns Path component (e.g., \"/mcp\", \"/api/v1/mcp\") or empty string if no path\n */\nfunction getPath(url: string): string {\n try {\n const parsed = new URL(url);\n // pathname includes leading slash, e.g., \"/mcp\"\n return parsed.pathname === '/' ? '' : parsed.pathname;\n } catch {\n return '';\n }\n}\n\n/**\n * Normalize a resource URL by stripping query/hash and trailing slashes.\n */\n/**\n * Discover OAuth 2.0 Protected Resource Metadata (RFC 9728)\n * Probes .well-known/oauth-protected-resource endpoint\n *\n * Discovery Strategy:\n * 1. Try origin root: {origin}/.well-known/oauth-protected-resource\n * 2. If 404, try sub-path: {origin}/.well-known/oauth-protected-resource{path}\n *\n * @param resourceUrl - URL of the protected resource (e.g., https://ai.todoist.net/mcp)\n * @returns ProtectedResourceMetadata if discovered, null otherwise\n *\n * @example\n * // Todoist case: MCP at ai.todoist.net/mcp, OAuth at todoist.com\n * const metadata = await discoverProtectedResourceMetadata('https://ai.todoist.net/mcp');\n * // Returns: { resource: \"https://ai.todoist.net/mcp\", authorization_servers: [\"https://todoist.com\"] }\n */\nexport async function discoverProtectedResourceMetadata(resourceUrl: string): Promise<ProtectedResourceMetadata | null> {\n try {\n const normalizedResourceUrl = normalizeUrl(resourceUrl);\n const headerMetadata = await discoverProtectedResourceMetadataFromHeader(normalizedResourceUrl);\n if (headerMetadata) return headerMetadata;\n\n // Strategy 0: Try path-local well-known (supports path-prefixed deployments like /outlook)\n const localWellKnownUrl = joinWellKnown(normalizedResourceUrl, '/.well-known/oauth-protected-resource');\n try {\n const response = await fetch(localWellKnownUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n if (response.ok) {\n return (await response.json()) as ProtectedResourceMetadata;\n }\n } catch {\n // Continue to origin-based discovery\n }\n\n const origin = getOrigin(normalizedResourceUrl);\n const path = getPath(normalizedResourceUrl);\n\n // Strategy 1: Try root location (REQUIRED by RFC 9728)\n const rootUrl = `${origin}/.well-known/oauth-protected-resource`;\n\n try {\n const response = await fetch(rootUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (response.ok) {\n const metadata = (await response.json()) as ProtectedResourceMetadata;\n // Check if the discovered resource matches what we're looking for\n if (metadata.resource === normalizedResourceUrl) {\n return metadata;\n }\n // If there's no path component, return root metadata\n // (e.g., looking for http://example.com and found it)\n if (!path) {\n return metadata;\n }\n // If requested URL starts with metadata.resource, the root metadata applies to sub-paths\n // (e.g., looking for http://example.com/api/v1/mcp, found http://example.com)\n if (normalizedResourceUrl.startsWith(metadata.resource)) {\n // Still try sub-path location to see if there's more specific metadata\n // But save root metadata as fallback\n const rootMetadata = metadata;\n\n // Try sub-path location for more specific metadata\n const subPathUrl = `${origin}/.well-known/oauth-protected-resource${path}`;\n try {\n const subPathResponse = await fetch(subPathUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n if (subPathResponse.ok) {\n return (await subPathResponse.json()) as ProtectedResourceMetadata;\n }\n } catch {\n // Sub-path failed, use root metadata\n }\n\n // Return root metadata as it applies to this resource\n return rootMetadata;\n }\n // Otherwise, try sub-path location before giving up\n }\n } catch {\n // Continue to sub-path location\n }\n\n // Strategy 2: Try sub-path location (MCP spec extension)\n // Only try if there's a path component\n if (path) {\n const subPathUrl = `${origin}/.well-known/oauth-protected-resource${path}`;\n\n try {\n const response = await fetch(subPathUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (response.ok) {\n return (await response.json()) as ProtectedResourceMetadata;\n }\n } catch {\n // Fall through to return null\n }\n }\n\n // Neither location found or resource didn't match\n return null;\n } catch (_error) {\n // Network error, invalid URL, or other failure\n return null;\n }\n}\n\nasync function discoverProtectedResourceMetadataFromHeader(resourceUrl: string): Promise<ProtectedResourceMetadata | null> {\n try {\n const response = await fetch(resourceUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n let header = response.headers.get('www-authenticate');\n if (!header) {\n const postResponse = await fetch(resourceUrl, {\n method: 'POST',\n headers: { Accept: 'application/json', Connection: 'close', 'Content-Type': 'application/json' },\n body: '{}',\n });\n header = postResponse.headers.get('www-authenticate');\n }\n\n if (!header) return null;\n\n const match = header.match(/resource_metadata=\"([^\"]+)\"/i);\n if (!match || !match[1]) return null;\n\n const metadataUrl = match[1];\n const metadataResponse = await fetch(metadataUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (!metadataResponse.ok) {\n return null;\n }\n\n return (await metadataResponse.json()) as ProtectedResourceMetadata;\n } catch (_error) {\n return null;\n }\n}\n\n/**\n * Discover OAuth 2.0 Authorization Server Metadata (RFC 8414)\n * Probes .well-known/oauth-authorization-server endpoint\n *\n * @param authServerUrl - URL of the authorization server (typically from RFC 9728 discovery)\n * @returns AuthorizationServerMetadata if discovered, null otherwise\n *\n * @example\n * const metadata = await discoverAuthorizationServerMetadata('https://todoist.com');\n * // Returns: { issuer: \"https://todoist.com\", authorization_endpoint: \"...\", ... }\n */\nexport async function discoverAuthorizationServerMetadata(authServerUrl: string): Promise<AuthorizationServerMetadata | null> {\n try {\n const normalizedAuthServerUrl = normalizeUrl(authServerUrl);\n const localWellKnownUrl = joinWellKnown(normalizedAuthServerUrl, '/.well-known/oauth-authorization-server');\n const localResponse = await fetch(localWellKnownUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (localResponse.ok) {\n return (await localResponse.json()) as AuthorizationServerMetadata;\n }\n\n const origin = getOrigin(normalizedAuthServerUrl);\n const wellKnownUrl = `${origin}/.well-known/oauth-authorization-server`;\n\n const response = await fetch(wellKnownUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n if (!response.ok) {\n return null;\n }\n\n return (await response.json()) as AuthorizationServerMetadata;\n } catch (_error) {\n return null;\n }\n}\n\n/**\n * Discover OAuth Authorization Server Issuer from resource response (RFC 9207)\n *\n * @param resourceUrl - URL of the protected resource\n * @returns Issuer URL if present in WWW-Authenticate header, null otherwise\n */\nexport async function discoverAuthorizationServerIssuer(resourceUrl: string): Promise<string | null> {\n try {\n const response = await fetch(resourceUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n const header = response.headers.get('www-authenticate');\n if (!header) return null;\n\n const match = header.match(/(?:authorization_server|issuer)=\"([^\"]+)\"/i);\n if (!match) return null;\n\n return match[1] ?? null;\n } catch (_error) {\n return null;\n }\n}\n"],"names":["discoverAuthorizationServerIssuer","discoverAuthorizationServerMetadata","discoverProtectedResourceMetadata","getOrigin","url","URL","origin","getPath","parsed","pathname","resourceUrl","normalizedResourceUrl","headerMetadata","localWellKnownUrl","response","path","rootUrl","metadata","rootMetadata","subPathUrl","subPathResponse","_error","normalizeUrl","discoverProtectedResourceMetadataFromHeader","joinWellKnown","fetch","method","headers","Accept","Connection","ok","json","resource","startsWith","header","postResponse","match","metadataUrl","metadataResponse","get","body","authServerUrl","normalizedAuthServerUrl","localResponse","wellKnownUrl"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/client/src/auth/types.ts"],"sourcesContent":["/**\n * Shared types for OAuth and DCR authentication\n */\n\n/**\n * OAuth callback result from authorization server\n */\nexport interface CallbackResult {\n /** Authorization code from OAuth server */\n code: string;\n /** State parameter for CSRF protection */\n state?: string;\n}\n\n/**\n * PKCE (Proof Key for Code Exchange) parameters (RFC 7636)\n * Used to secure OAuth 2.0 authorization code flow for public clients\n */\nexport interface PkceParams {\n /** Code verifier - cryptographically random string (43-128 characters) */\n codeVerifier: string;\n /** Code challenge - derived from code verifier using challenge method */\n codeChallenge: string;\n /** Code challenge method - S256 (SHA-256) or plain */\n codeChallengeMethod: 'S256' | 'plain';\n}\n\n/**\n * OAuth token set with access and refresh tokens\n */\nexport interface TokenSet {\n /** Access token for API requests */\n accessToken: string;\n /** Refresh token for obtaining new access tokens */\n refreshToken: string;\n /** Timestamp when access token expires (milliseconds since epoch) */\n expiresAt: number;\n /** Scopes granted for this token set */\n scopes?: string[];\n /** Client ID used for DCR registration (stored for future use) */\n clientId?: string;\n /** Client secret used for DCR registration (stored for future use) */\n clientSecret?: string;\n}\n\n/**\n * OAuth 2.0 Protected Resource Metadata (RFC 9728)\n * Response from .well-known/oauth-protected-resource endpoint\n */\nexport interface ProtectedResourceMetadata {\n /** The protected resource identifier */\n resource: string;\n /** List of authorization server URLs that can issue tokens for this resource */\n authorization_servers: string[];\n /** Optional list of scopes supported by this resource */\n scopes_supported?: string[];\n /** Optional list of bearer token methods supported (header, query, body) */\n bearer_methods_supported?: string[];\n}\n\n/**\n * OAuth 2.0 Authorization Server Metadata (RFC 8414)\n * Response from .well-known/oauth-authorization-server endpoint\n */\nexport interface AuthorizationServerMetadata {\n /** The authorization server's issuer identifier */\n issuer?: string;\n /** URL of the authorization endpoint */\n authorization_endpoint?: string;\n /** URL of the token endpoint */\n token_endpoint?: string;\n /** URL of the client registration endpoint (DCR - RFC 7591) */\n registration_endpoint?: string;\n /** URL of the token introspection endpoint */\n introspection_endpoint?: string;\n /** List of OAuth scopes supported by the authorization server */\n scopes_supported?: string[];\n /** Response types supported (code, token, etc.) */\n response_types_supported?: string[];\n /** Grant types supported (authorization_code, refresh_token, etc.) */\n grant_types_supported?: string[];\n /** Token endpoint authentication methods supported */\n token_endpoint_auth_methods_supported?: string[];\n}\n\n/**\n * OAuth server capabilities discovered from .well-known endpoint\n */\nexport interface AuthCapabilities {\n /** Whether the server supports Dynamic Client Registration (RFC 7591) */\n supportsDcr: boolean;\n /** DCR client registration endpoint */\n registrationEndpoint?: string;\n /** OAuth authorization endpoint */\n authorizationEndpoint?: string;\n /** OAuth token endpoint */\n tokenEndpoint?: string;\n /** Token introspection endpoint */\n introspectionEndpoint?: string;\n /** Supported OAuth scopes */\n scopes?: string[];\n}\n\n/**\n * Client credentials from DCR registration\n */\nexport interface ClientCredentials {\n /** OAuth client ID */\n clientId: string;\n /** OAuth client secret */\n clientSecret: string;\n /** Timestamp when client was registered */\n issuedAt?: number;\n}\n\n/**\n * Options for DCR client registration\n */\nexport interface DcrRegistrationOptions {\n /** Client name to register */\n clientName?: string;\n /** Redirect URI for OAuth callback */\n redirectUri?: string;\n}\n\n/**\n * Options for OAuth authorization flow\n */\nexport interface OAuthFlowOptions {\n /** Port for OAuth callback listener (required - use get-port to find available port) */\n port: number;\n /** Redirect URI for OAuth callback (optional - will be built from port if not provided) */\n redirectUri?: string;\n /** OAuth scopes to request */\n scopes?: string[];\n /** Resource parameter (RFC 8707) - target resource server identifier */\n resource?: string;\n /** Enable PKCE (RFC 7636) - recommended for all clients, required for public clients */\n pkce?: boolean;\n /** Headless mode (don't open browser) */\n headless?: boolean;\n /** Timeout for callback (milliseconds) */\n timeout?: number;\n /** Optional logger for debug output (defaults to singleton logger) */\n logger?: import('../utils/logger.ts').Logger;\n}\n"],"names":[],"mappings":"AAAA;;CAEC,GAED;;CAEC"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/auth/types.ts"],"sourcesContent":["/**\n * Shared types for OAuth and DCR authentication\n */\n\n/**\n * OAuth callback result from authorization server\n */\nexport interface CallbackResult {\n /** Authorization code from OAuth server */\n code: string;\n /** State parameter for CSRF protection */\n state?: string;\n}\n\n/**\n * PKCE (Proof Key for Code Exchange) parameters (RFC 7636)\n * Used to secure OAuth 2.0 authorization code flow for public clients\n */\nexport interface PkceParams {\n /** Code verifier - cryptographically random string (43-128 characters) */\n codeVerifier: string;\n /** Code challenge - derived from code verifier using challenge method */\n codeChallenge: string;\n /** Code challenge method - S256 (SHA-256) or plain */\n codeChallengeMethod: 'S256' | 'plain';\n}\n\n/**\n * OAuth token set with access and refresh tokens\n */\nexport interface TokenSet {\n /** Access token for API requests */\n accessToken: string;\n /** Refresh token for obtaining new access tokens */\n refreshToken: string;\n /** Timestamp when access token expires (milliseconds since epoch) */\n expiresAt: number;\n /** Scopes granted for this token set */\n scopes?: string[];\n /** Client ID used for DCR registration (stored for future use) */\n clientId?: string;\n /** Client secret used for DCR registration (stored for future use) */\n clientSecret?: string;\n}\n\n/**\n * OAuth 2.0 Protected Resource Metadata (RFC 9728)\n * Response from .well-known/oauth-protected-resource endpoint\n */\nexport interface ProtectedResourceMetadata {\n /** The protected resource identifier */\n resource: string;\n /** List of authorization server URLs that can issue tokens for this resource */\n authorization_servers: string[];\n /** Optional list of scopes supported by this resource */\n scopes_supported?: string[];\n /** Optional list of bearer token methods supported (header, query, body) */\n bearer_methods_supported?: string[];\n}\n\n/**\n * OAuth 2.0 Authorization Server Metadata (RFC 8414)\n * Response from .well-known/oauth-authorization-server endpoint\n */\nexport interface AuthorizationServerMetadata {\n /** The authorization server's issuer identifier */\n issuer?: string;\n /** URL of the authorization endpoint */\n authorization_endpoint?: string;\n /** URL of the token endpoint */\n token_endpoint?: string;\n /** URL of the client registration endpoint (DCR - RFC 7591) */\n registration_endpoint?: string;\n /** URL of the token introspection endpoint */\n introspection_endpoint?: string;\n /** List of OAuth scopes supported by the authorization server */\n scopes_supported?: string[];\n /** Response types supported (code, token, etc.) */\n response_types_supported?: string[];\n /** Grant types supported (authorization_code, refresh_token, etc.) */\n grant_types_supported?: string[];\n /** Token endpoint authentication methods supported */\n token_endpoint_auth_methods_supported?: string[];\n}\n\n/**\n * OAuth server capabilities discovered from .well-known endpoint\n */\nexport interface AuthCapabilities {\n /** Whether the server supports Dynamic Client Registration (RFC 7591) */\n supportsDcr: boolean;\n /** DCR client registration endpoint */\n registrationEndpoint?: string;\n /** OAuth authorization endpoint */\n authorizationEndpoint?: string;\n /** OAuth token endpoint */\n tokenEndpoint?: string;\n /** Token introspection endpoint */\n introspectionEndpoint?: string;\n /** Supported OAuth scopes */\n scopes?: string[];\n}\n\n/**\n * Client credentials from DCR registration\n */\nexport interface ClientCredentials {\n /** OAuth client ID */\n clientId: string;\n /** OAuth client secret */\n clientSecret: string;\n /** Timestamp when client was registered */\n issuedAt?: number;\n}\n\n/**\n * Options for DCR client registration\n */\nexport interface DcrRegistrationOptions {\n /** Client name to register */\n clientName?: string;\n /** Redirect URI for OAuth callback */\n redirectUri?: string;\n}\n\n/**\n * Options for OAuth authorization flow\n */\nexport interface OAuthFlowOptions {\n /** Port for OAuth callback listener (required - use get-port to find available port) */\n port: number;\n /** Redirect URI for OAuth callback (optional - will be built from port if not provided) */\n redirectUri?: string;\n /** OAuth scopes to request */\n scopes?: string[];\n /** Resource parameter (RFC 8707) - target resource server identifier */\n resource?: string;\n /** Enable PKCE (RFC 7636) - recommended for all clients, required for public clients */\n pkce?: boolean;\n /** Headless mode (don't open browser) */\n headless?: boolean;\n /** Timeout for callback (milliseconds) */\n timeout?: number;\n /** Optional logger for debug output (defaults to singleton logger) */\n logger?: import('../utils/logger.ts').Logger;\n}\n"],"names":[],"mappings":"AAAA;;CAEC,GAED;;CAEC"}
@@ -17,9 +17,7 @@ function _define_property(obj, key, value) {
17
17
  configurable: true,
18
18
  writable: true
19
19
  });
20
- } else {
21
- obj[key] = value;
22
- }
20
+ } else obj[key] = value;
23
21
  return obj;
24
22
  }
25
23
  function _object_spread(target) {
@@ -52,7 +50,7 @@ function decorateClient(client, metadata) {
52
50
  writable: false
53
51
  });
54
52
  var nativeCallTool = client.callTool.bind(client);
55
- var wrapCallTool = function(promise) {
53
+ var wrapCallTool = function wrapCallTool(promise) {
56
54
  return promise.then(function(payload) {
57
55
  return new _responsewrappersts.ToolResponseWrapper(payload);
58
56
  });
@@ -76,7 +74,7 @@ function decorateClient(client, metadata) {
76
74
  return nativeCallTool(nameOrInvocation, argsOrSession, requestOptions);
77
75
  };
78
76
  var nativeGetPrompt = client.getPrompt.bind(client);
79
- var wrapPrompt = function(promise) {
77
+ var wrapPrompt = function wrapPrompt(promise) {
80
78
  return promise.then(function(payload) {
81
79
  return new _responsewrappersts.PromptResponseWrapper(payload);
82
80
  });
@@ -102,7 +100,7 @@ function decorateClient(client, metadata) {
102
100
  return nativeGetPrompt(nameOrParams, argsOrOptions);
103
101
  };
104
102
  var nativeReadResource = client.readResource.bind(client);
105
- var wrapResource = function(promise) {
103
+ var wrapResource = function wrapResource(promise) {
106
104
  return promise.then(function(payload) {
107
105
  return new _responsewrappersts.ResourceResponseWrapper(payload);
108
106
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/client/src/client-helpers.ts"],"sourcesContent":["import type { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport type { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport type { ToolArguments } from './connection/types.ts';\nimport { type NativeCallToolResponse, type NativeGetPromptResponse, type NativeReadResourceResponse, PromptResponseWrapper, ResourceResponseWrapper, ToolResponseWrapper } from './response-wrappers.ts';\n\nexport type PromptArguments = Record<string, string>;\n\ntype NativeCallToolParams = Parameters<Client['callTool']>;\ntype NativeCallToolReturn = ReturnType<Client['callTool']>;\n/**\n * Fetch-style wrapper returned by `ManagedClient.callTool()`.\n * @public\n */\nexport type WrappedCallToolReturn = Promise<ToolResponseWrapper>;\n\ntype NativeGetPromptParams = Parameters<Client['getPrompt']>;\ntype NativeGetPromptReturn = ReturnType<Client['getPrompt']>;\n/**\n * Fetch-style wrapper returned by `ManagedClient.getPrompt()`.\n * @public\n */\nexport type WrappedGetPromptReturn = Promise<PromptResponseWrapper>;\n\ntype NativeReadResourceParams = Parameters<Client['readResource']>;\ntype NativeReadResourceReturn = ReturnType<Client['readResource']>;\n/**\n * Fetch-style wrapper returned by `ManagedClient.readResource()`.\n * @public\n */\nexport type WrappedReadResourceReturn = Promise<ResourceResponseWrapper>;\n\n/**\n * Client returned by registry.connect() with convenience overloads for\n * calling tools, reading resources, and getting prompts using simple arguments.\n */\nexport type ManagedClient = Omit<Client, 'callTool' | 'getPrompt' | 'readResource'> & {\n /** Name of the server this client is connected to. */\n readonly serverName: string;\n /** Underlying MCP SDK client for advanced scenarios. */\n readonly nativeClient: Client;\n\n callTool(toolName: string, args?: ToolArguments, requestOptions?: RequestOptions): WrappedCallToolReturn;\n callTool(invocation: NativeCallToolParams[0], sessionId?: NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]): WrappedCallToolReturn;\n callToolRaw(toolName: string, args?: ToolArguments, requestOptions?: RequestOptions): NativeCallToolReturn;\n callToolRaw(invocation: NativeCallToolParams[0], sessionId?: NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]): NativeCallToolReturn;\n\n getPrompt(name: string, args?: PromptArguments, requestOptions?: NativeGetPromptParams[1]): WrappedGetPromptReturn;\n getPrompt(invocation: NativeGetPromptParams[0], requestOptions?: NativeGetPromptParams[1]): WrappedGetPromptReturn;\n getPromptRaw(name: string, args?: PromptArguments, requestOptions?: NativeGetPromptParams[1]): NativeGetPromptReturn;\n getPromptRaw(invocation: NativeGetPromptParams[0], requestOptions?: NativeGetPromptParams[1]): NativeGetPromptReturn;\n\n readResource(uri: string, requestOptions?: NativeReadResourceParams[1]): WrappedReadResourceReturn;\n readResource(request: NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]): WrappedReadResourceReturn;\n readResourceRaw(uri: string, requestOptions?: NativeReadResourceParams[1]): NativeReadResourceReturn;\n readResourceRaw(request: NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]): NativeReadResourceReturn;\n};\n\n/**\n * Enhance an MCP SDK client with convenience overloads.\n */\nexport function decorateClient(client: Client, metadata: { serverName: string }): ManagedClient {\n const enhanced = client as unknown as ManagedClient;\n\n Object.defineProperty(enhanced, 'serverName', {\n value: metadata.serverName,\n enumerable: true,\n configurable: false,\n writable: false,\n });\n Object.defineProperty(enhanced, 'nativeClient', {\n value: client,\n enumerable: false,\n configurable: false,\n writable: false,\n });\n\n const nativeCallTool = client.callTool.bind(client);\n const wrapCallTool = (promise: NativeCallToolReturn): WrappedCallToolReturn => promise.then((payload) => new ToolResponseWrapper(payload as NativeCallToolResponse));\n\n enhanced.callTool = ((nameOrInvocation: string | NativeCallToolParams[0], argsOrSession?: ToolArguments | NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]) => {\n if (typeof nameOrInvocation === 'string') {\n return wrapCallTool(nativeCallTool({ name: nameOrInvocation, arguments: (argsOrSession as ToolArguments) ?? {} }, undefined, requestOptions));\n }\n return wrapCallTool(nativeCallTool(nameOrInvocation, argsOrSession as NativeCallToolParams[1], requestOptions));\n }) as ManagedClient['callTool'];\n\n enhanced.callToolRaw = ((nameOrInvocation: string | NativeCallToolParams[0], argsOrSession?: ToolArguments | NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]) => {\n if (typeof nameOrInvocation === 'string') {\n return nativeCallTool({ name: nameOrInvocation, arguments: (argsOrSession as ToolArguments) ?? {} }, undefined, requestOptions);\n }\n return nativeCallTool(nameOrInvocation, argsOrSession as NativeCallToolParams[1], requestOptions);\n }) as ManagedClient['callToolRaw'];\n\n const nativeGetPrompt = client.getPrompt.bind(client);\n const wrapPrompt = (promise: NativeGetPromptReturn): WrappedGetPromptReturn => promise.then((payload) => new PromptResponseWrapper(payload as NativeGetPromptResponse));\n\n enhanced.getPrompt = ((nameOrParams: string | NativeGetPromptParams[0], argsOrOptions?: PromptArguments | NativeGetPromptParams[1], requestOptions?: NativeGetPromptParams[1]) => {\n if (typeof nameOrParams === 'string') {\n return wrapPrompt(nativeGetPrompt({ name: nameOrParams, ...(argsOrOptions ? { arguments: argsOrOptions as PromptArguments } : {}) }, requestOptions));\n }\n return wrapPrompt(nativeGetPrompt(nameOrParams, argsOrOptions as NativeGetPromptParams[1]));\n }) as ManagedClient['getPrompt'];\n\n enhanced.getPromptRaw = ((nameOrParams: string | NativeGetPromptParams[0], argsOrOptions?: PromptArguments | NativeGetPromptParams[1], requestOptions?: NativeGetPromptParams[1]) => {\n if (typeof nameOrParams === 'string') {\n return nativeGetPrompt({ name: nameOrParams, ...(argsOrOptions ? { arguments: argsOrOptions as PromptArguments } : {}) }, requestOptions);\n }\n return nativeGetPrompt(nameOrParams, argsOrOptions as NativeGetPromptParams[1]);\n }) as ManagedClient['getPromptRaw'];\n\n const nativeReadResource = client.readResource.bind(client);\n const wrapResource = (promise: NativeReadResourceReturn): WrappedReadResourceReturn => promise.then((payload) => new ResourceResponseWrapper(payload as NativeReadResourceResponse));\n\n enhanced.readResource = ((uriOrRequest: string | NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]) => {\n if (typeof uriOrRequest === 'string') {\n return wrapResource(nativeReadResource({ uri: uriOrRequest }, requestOptions));\n }\n return wrapResource(nativeReadResource(uriOrRequest, requestOptions));\n }) as ManagedClient['readResource'];\n\n enhanced.readResourceRaw = ((uriOrRequest: string | NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]) => {\n if (typeof uriOrRequest === 'string') {\n return nativeReadResource({ uri: uriOrRequest }, requestOptions);\n }\n return nativeReadResource(uriOrRequest, requestOptions);\n }) as ManagedClient['readResourceRaw'];\n\n return enhanced;\n}\n"],"names":["decorateClient","client","metadata","enhanced","Object","defineProperty","value","serverName","enumerable","configurable","writable","nativeCallTool","callTool","bind","wrapCallTool","promise","then","payload","ToolResponseWrapper","nameOrInvocation","argsOrSession","requestOptions","name","arguments","undefined","callToolRaw","nativeGetPrompt","getPrompt","wrapPrompt","PromptResponseWrapper","nameOrParams","argsOrOptions","getPromptRaw","nativeReadResource","readResource","wrapResource","ResourceResponseWrapper","uriOrRequest","uri","readResourceRaw"],"mappings":";;;;+BA4DgBA;;;eAAAA;;;kCAzDgK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDzK,SAASA,eAAeC,MAAc,EAAEC,QAAgC;IAC7E,IAAMC,WAAWF;IAEjBG,OAAOC,cAAc,CAACF,UAAU,cAAc;QAC5CG,OAAOJ,SAASK,UAAU;QAC1BC,YAAY;QACZC,cAAc;QACdC,UAAU;IACZ;IACAN,OAAOC,cAAc,CAACF,UAAU,gBAAgB;QAC9CG,OAAOL;QACPO,YAAY;QACZC,cAAc;QACdC,UAAU;IACZ;IAEA,IAAMC,iBAAiBV,OAAOW,QAAQ,CAACC,IAAI,CAACZ;IAC5C,IAAMa,eAAe,SAACC;eAAyDA,QAAQC,IAAI,CAAC,SAACC;mBAAY,IAAIC,uCAAmB,CAACD;;;IAEjId,SAASS,QAAQ,GAAI,SAACO,kBAAoDC,eAAyDC;QACjI,IAAI,OAAOF,qBAAqB,UAAU;YACxC,OAAOL,aAAaH,eAAe;gBAAEW,MAAMH;gBAAkBI,SAAS,EAAGH,0BAAAA,2BAAAA,gBAAmC,CAAC;YAAE,GAAGI,WAAWH;QAC/H;QACA,OAAOP,aAAaH,eAAeQ,kBAAkBC,eAA0CC;IACjG;IAEAlB,SAASsB,WAAW,GAAI,SAACN,kBAAoDC,eAAyDC;QACpI,IAAI,OAAOF,qBAAqB,UAAU;YACxC,OAAOR,eAAe;gBAAEW,MAAMH;gBAAkBI,SAAS,EAAGH,0BAAAA,2BAAAA,gBAAmC,CAAC;YAAE,GAAGI,WAAWH;QAClH;QACA,OAAOV,eAAeQ,kBAAkBC,eAA0CC;IACpF;IAEA,IAAMK,kBAAkBzB,OAAO0B,SAAS,CAACd,IAAI,CAACZ;IAC9C,IAAM2B,aAAa,SAACb;eAA2DA,QAAQC,IAAI,CAAC,SAACC;mBAAY,IAAIY,yCAAqB,CAACZ;;;IAEnId,SAASwB,SAAS,GAAI,SAACG,cAAiDC,eAA4DV;QAClI,IAAI,OAAOS,iBAAiB,UAAU;YACpC,OAAOF,WAAWF,gBAAgB;gBAAEJ,MAAMQ;eAAkBC,gBAAgB;gBAAER,WAAWQ;YAAiC,IAAI,CAAC,IAAMV;QACvI;QACA,OAAOO,WAAWF,gBAAgBI,cAAcC;IAClD;IAEA5B,SAAS6B,YAAY,GAAI,SAACF,cAAiDC,eAA4DV;QACrI,IAAI,OAAOS,iBAAiB,UAAU;YACpC,OAAOJ,gBAAgB;gBAAEJ,MAAMQ;eAAkBC,gBAAgB;gBAAER,WAAWQ;YAAiC,IAAI,CAAC,IAAMV;QAC5H;QACA,OAAOK,gBAAgBI,cAAcC;IACvC;IAEA,IAAME,qBAAqBhC,OAAOiC,YAAY,CAACrB,IAAI,CAACZ;IACpD,IAAMkC,eAAe,SAACpB;eAAiEA,QAAQC,IAAI,CAAC,SAACC;mBAAY,IAAImB,2CAAuB,CAACnB;;;IAE7Id,SAAS+B,YAAY,GAAI,SAACG,cAAoDhB;QAC5E,IAAI,OAAOgB,iBAAiB,UAAU;YACpC,OAAOF,aAAaF,mBAAmB;gBAAEK,KAAKD;YAAa,GAAGhB;QAChE;QACA,OAAOc,aAAaF,mBAAmBI,cAAchB;IACvD;IAEAlB,SAASoC,eAAe,GAAI,SAACF,cAAoDhB;QAC/E,IAAI,OAAOgB,iBAAiB,UAAU;YACpC,OAAOJ,mBAAmB;gBAAEK,KAAKD;YAAa,GAAGhB;QACnD;QACA,OAAOY,mBAAmBI,cAAchB;IAC1C;IAEA,OAAOlB;AACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/client-helpers.ts"],"sourcesContent":["import type { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport type { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport type { ToolArguments } from './connection/types.ts';\nimport { type NativeCallToolResponse, type NativeGetPromptResponse, type NativeReadResourceResponse, PromptResponseWrapper, ResourceResponseWrapper, ToolResponseWrapper } from './response-wrappers.ts';\n\nexport type PromptArguments = Record<string, string>;\n\ntype NativeCallToolParams = Parameters<Client['callTool']>;\ntype NativeCallToolReturn = ReturnType<Client['callTool']>;\n/**\n * Fetch-style wrapper returned by `ManagedClient.callTool()`.\n * @public\n */\nexport type WrappedCallToolReturn = Promise<ToolResponseWrapper>;\n\ntype NativeGetPromptParams = Parameters<Client['getPrompt']>;\ntype NativeGetPromptReturn = ReturnType<Client['getPrompt']>;\n/**\n * Fetch-style wrapper returned by `ManagedClient.getPrompt()`.\n * @public\n */\nexport type WrappedGetPromptReturn = Promise<PromptResponseWrapper>;\n\ntype NativeReadResourceParams = Parameters<Client['readResource']>;\ntype NativeReadResourceReturn = ReturnType<Client['readResource']>;\n/**\n * Fetch-style wrapper returned by `ManagedClient.readResource()`.\n * @public\n */\nexport type WrappedReadResourceReturn = Promise<ResourceResponseWrapper>;\n\n/**\n * Client returned by registry.connect() with convenience overloads for\n * calling tools, reading resources, and getting prompts using simple arguments.\n */\nexport type ManagedClient = Omit<Client, 'callTool' | 'getPrompt' | 'readResource'> & {\n /** Name of the server this client is connected to. */\n readonly serverName: string;\n /** Underlying MCP SDK client for advanced scenarios. */\n readonly nativeClient: Client;\n\n callTool(toolName: string, args?: ToolArguments, requestOptions?: RequestOptions): WrappedCallToolReturn;\n callTool(invocation: NativeCallToolParams[0], sessionId?: NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]): WrappedCallToolReturn;\n callToolRaw(toolName: string, args?: ToolArguments, requestOptions?: RequestOptions): NativeCallToolReturn;\n callToolRaw(invocation: NativeCallToolParams[0], sessionId?: NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]): NativeCallToolReturn;\n\n getPrompt(name: string, args?: PromptArguments, requestOptions?: NativeGetPromptParams[1]): WrappedGetPromptReturn;\n getPrompt(invocation: NativeGetPromptParams[0], requestOptions?: NativeGetPromptParams[1]): WrappedGetPromptReturn;\n getPromptRaw(name: string, args?: PromptArguments, requestOptions?: NativeGetPromptParams[1]): NativeGetPromptReturn;\n getPromptRaw(invocation: NativeGetPromptParams[0], requestOptions?: NativeGetPromptParams[1]): NativeGetPromptReturn;\n\n readResource(uri: string, requestOptions?: NativeReadResourceParams[1]): WrappedReadResourceReturn;\n readResource(request: NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]): WrappedReadResourceReturn;\n readResourceRaw(uri: string, requestOptions?: NativeReadResourceParams[1]): NativeReadResourceReturn;\n readResourceRaw(request: NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]): NativeReadResourceReturn;\n};\n\n/**\n * Enhance an MCP SDK client with convenience overloads.\n */\nexport function decorateClient(client: Client, metadata: { serverName: string }): ManagedClient {\n const enhanced = client as unknown as ManagedClient;\n\n Object.defineProperty(enhanced, 'serverName', {\n value: metadata.serverName,\n enumerable: true,\n configurable: false,\n writable: false,\n });\n Object.defineProperty(enhanced, 'nativeClient', {\n value: client,\n enumerable: false,\n configurable: false,\n writable: false,\n });\n\n const nativeCallTool = client.callTool.bind(client);\n const wrapCallTool = (promise: NativeCallToolReturn): WrappedCallToolReturn => promise.then((payload) => new ToolResponseWrapper(payload as NativeCallToolResponse));\n\n enhanced.callTool = ((nameOrInvocation: string | NativeCallToolParams[0], argsOrSession?: ToolArguments | NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]) => {\n if (typeof nameOrInvocation === 'string') {\n return wrapCallTool(nativeCallTool({ name: nameOrInvocation, arguments: (argsOrSession as ToolArguments) ?? {} }, undefined, requestOptions));\n }\n return wrapCallTool(nativeCallTool(nameOrInvocation, argsOrSession as NativeCallToolParams[1], requestOptions));\n }) as ManagedClient['callTool'];\n\n enhanced.callToolRaw = ((nameOrInvocation: string | NativeCallToolParams[0], argsOrSession?: ToolArguments | NativeCallToolParams[1], requestOptions?: NativeCallToolParams[2]) => {\n if (typeof nameOrInvocation === 'string') {\n return nativeCallTool({ name: nameOrInvocation, arguments: (argsOrSession as ToolArguments) ?? {} }, undefined, requestOptions);\n }\n return nativeCallTool(nameOrInvocation, argsOrSession as NativeCallToolParams[1], requestOptions);\n }) as ManagedClient['callToolRaw'];\n\n const nativeGetPrompt = client.getPrompt.bind(client);\n const wrapPrompt = (promise: NativeGetPromptReturn): WrappedGetPromptReturn => promise.then((payload) => new PromptResponseWrapper(payload as NativeGetPromptResponse));\n\n enhanced.getPrompt = ((nameOrParams: string | NativeGetPromptParams[0], argsOrOptions?: PromptArguments | NativeGetPromptParams[1], requestOptions?: NativeGetPromptParams[1]) => {\n if (typeof nameOrParams === 'string') {\n return wrapPrompt(nativeGetPrompt({ name: nameOrParams, ...(argsOrOptions ? { arguments: argsOrOptions as PromptArguments } : {}) }, requestOptions));\n }\n return wrapPrompt(nativeGetPrompt(nameOrParams, argsOrOptions as NativeGetPromptParams[1]));\n }) as ManagedClient['getPrompt'];\n\n enhanced.getPromptRaw = ((nameOrParams: string | NativeGetPromptParams[0], argsOrOptions?: PromptArguments | NativeGetPromptParams[1], requestOptions?: NativeGetPromptParams[1]) => {\n if (typeof nameOrParams === 'string') {\n return nativeGetPrompt({ name: nameOrParams, ...(argsOrOptions ? { arguments: argsOrOptions as PromptArguments } : {}) }, requestOptions);\n }\n return nativeGetPrompt(nameOrParams, argsOrOptions as NativeGetPromptParams[1]);\n }) as ManagedClient['getPromptRaw'];\n\n const nativeReadResource = client.readResource.bind(client);\n const wrapResource = (promise: NativeReadResourceReturn): WrappedReadResourceReturn => promise.then((payload) => new ResourceResponseWrapper(payload as NativeReadResourceResponse));\n\n enhanced.readResource = ((uriOrRequest: string | NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]) => {\n if (typeof uriOrRequest === 'string') {\n return wrapResource(nativeReadResource({ uri: uriOrRequest }, requestOptions));\n }\n return wrapResource(nativeReadResource(uriOrRequest, requestOptions));\n }) as ManagedClient['readResource'];\n\n enhanced.readResourceRaw = ((uriOrRequest: string | NativeReadResourceParams[0], requestOptions?: NativeReadResourceParams[1]) => {\n if (typeof uriOrRequest === 'string') {\n return nativeReadResource({ uri: uriOrRequest }, requestOptions);\n }\n return nativeReadResource(uriOrRequest, requestOptions);\n }) as ManagedClient['readResourceRaw'];\n\n return enhanced;\n}\n"],"names":["decorateClient","client","metadata","enhanced","Object","defineProperty","value","serverName","enumerable","configurable","writable","nativeCallTool","callTool","bind","wrapCallTool","promise","then","payload","ToolResponseWrapper","nameOrInvocation","argsOrSession","requestOptions","name","arguments","undefined","callToolRaw","nativeGetPrompt","getPrompt","wrapPrompt","PromptResponseWrapper","nameOrParams","argsOrOptions","getPromptRaw","nativeReadResource","readResource","wrapResource","ResourceResponseWrapper","uriOrRequest","uri","readResourceRaw"],"mappings":";;;;+BA4DgBA;;;eAAAA;;;kCAzDgK;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDzK,SAASA,eAAeC,MAAc,EAAEC,QAAgC;IAC7E,IAAMC,WAAWF;IAEjBG,OAAOC,cAAc,CAACF,UAAU,cAAc;QAC5CG,OAAOJ,SAASK,UAAU;QAC1BC,YAAY;QACZC,cAAc;QACdC,UAAU;IACZ;IACAN,OAAOC,cAAc,CAACF,UAAU,gBAAgB;QAC9CG,OAAOL;QACPO,YAAY;QACZC,cAAc;QACdC,UAAU;IACZ;IAEA,IAAMC,iBAAiBV,OAAOW,QAAQ,CAACC,IAAI,CAACZ;IAC5C,IAAMa,eAAe,sBAACC;eAAyDA,QAAQC,IAAI,CAAC,SAACC;mBAAY,IAAIC,uCAAmB,CAACD;;;IAEjId,SAASS,QAAQ,GAAI,SAACO,kBAAoDC,eAAyDC;QACjI,IAAI,OAAOF,qBAAqB,UAAU;YACxC,OAAOL,aAAaH,eAAe;gBAAEW,MAAMH;gBAAkBI,SAAS,EAAGH,0BAAAA,2BAAAA,gBAAmC,CAAC;YAAE,GAAGI,WAAWH;QAC/H;QACA,OAAOP,aAAaH,eAAeQ,kBAAkBC,eAA0CC;IACjG;IAEAlB,SAASsB,WAAW,GAAI,SAACN,kBAAoDC,eAAyDC;QACpI,IAAI,OAAOF,qBAAqB,UAAU;YACxC,OAAOR,eAAe;gBAAEW,MAAMH;gBAAkBI,SAAS,EAAGH,0BAAAA,2BAAAA,gBAAmC,CAAC;YAAE,GAAGI,WAAWH;QAClH;QACA,OAAOV,eAAeQ,kBAAkBC,eAA0CC;IACpF;IAEA,IAAMK,kBAAkBzB,OAAO0B,SAAS,CAACd,IAAI,CAACZ;IAC9C,IAAM2B,aAAa,oBAACb;eAA2DA,QAAQC,IAAI,CAAC,SAACC;mBAAY,IAAIY,yCAAqB,CAACZ;;;IAEnId,SAASwB,SAAS,GAAI,SAACG,cAAiDC,eAA4DV;QAClI,IAAI,OAAOS,iBAAiB,UAAU;YACpC,OAAOF,WAAWF,gBAAgB;gBAAEJ,MAAMQ;eAAkBC,gBAAgB;gBAAER,WAAWQ;YAAiC,IAAI,CAAC,IAAMV;QACvI;QACA,OAAOO,WAAWF,gBAAgBI,cAAcC;IAClD;IAEA5B,SAAS6B,YAAY,GAAI,SAACF,cAAiDC,eAA4DV;QACrI,IAAI,OAAOS,iBAAiB,UAAU;YACpC,OAAOJ,gBAAgB;gBAAEJ,MAAMQ;eAAkBC,gBAAgB;gBAAER,WAAWQ;YAAiC,IAAI,CAAC,IAAMV;QAC5H;QACA,OAAOK,gBAAgBI,cAAcC;IACvC;IAEA,IAAME,qBAAqBhC,OAAOiC,YAAY,CAACrB,IAAI,CAACZ;IACpD,IAAMkC,eAAe,sBAACpB;eAAiEA,QAAQC,IAAI,CAAC,SAACC;mBAAY,IAAImB,2CAAuB,CAACnB;;;IAE7Id,SAAS+B,YAAY,GAAI,SAACG,cAAoDhB;QAC5E,IAAI,OAAOgB,iBAAiB,UAAU;YACpC,OAAOF,aAAaF,mBAAmB;gBAAEK,KAAKD;YAAa,GAAGhB;QAChE;QACA,OAAOc,aAAaF,mBAAmBI,cAAchB;IACvD;IAEAlB,SAASoC,eAAe,GAAI,SAACF,cAAoDhB;QAC/E,IAAI,OAAOgB,iBAAiB,UAAU;YACpC,OAAOJ,mBAAmB;gBAAEK,KAAKD;YAAa,GAAGhB;QACnD;QACA,OAAOY,mBAAmBI,cAAchB;IAC1C;IAEA,OAAOlB;AACT"}
@@ -36,18 +36,12 @@ function _getRequireWildcardCache(nodeInterop) {
36
36
  })(nodeInterop);
37
37
  }
38
38
  function _interop_require_wildcard(obj, nodeInterop) {
39
- if (!nodeInterop && obj && obj.__esModule) {
40
- return obj;
41
- }
42
- if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
43
- return {
44
- default: obj
45
- };
46
- }
39
+ if (!nodeInterop && obj && obj.__esModule) return obj;
40
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") return {
41
+ default: obj
42
+ };
47
43
  var cache = _getRequireWildcardCache(nodeInterop);
48
- if (cache && cache.has(obj)) {
49
- return cache.get(obj);
50
- }
44
+ if (cache && cache.has(obj)) return cache.get(obj);
51
45
  var newObj = {
52
46
  __proto__: null
53
47
  };
@@ -55,17 +49,12 @@ function _interop_require_wildcard(obj, nodeInterop) {
55
49
  for(var key in obj){
56
50
  if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
57
51
  var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
58
- if (desc && (desc.get || desc.set)) {
59
- Object.defineProperty(newObj, key, desc);
60
- } else {
61
- newObj[key] = obj[key];
62
- }
52
+ if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc);
53
+ else newObj[key] = obj[key];
63
54
  }
64
55
  }
65
56
  newObj.default = obj;
66
- if (cache) {
67
- cache.set(obj, newObj);
68
- }
57
+ if (cache) cache.set(obj, newObj);
69
58
  return newObj;
70
59
  }
71
60
  // Get package root: dist/esm/lib -> ../../../ or dist/cjs/lib -> ../../../
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/Projects/mcp-z/client/src/config/server-loader.ts"],"sourcesContent":["/**\n * Load server definitions from .mcp.json (data-driven)\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\n\n// Get package root: dist/esm/lib -> ../../../ or dist/cjs/lib -> ../../../\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\nconst packageRoot = path.resolve(__dirname, '../../..');\n\nexport interface McpServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n}\n\nexport interface MCPConfiguration {\n mcpServers: Record<string, McpServerConfig>;\n}\n\n/**\n * Load available servers from resources/.mcp.json\n */\nexport function loadAvailableServers(): MCPConfiguration {\n const configPath = path.join(packageRoot, 'resources/.mcp.json');\n\n if (!fs.existsSync(configPath)) {\n throw new Error(`Server configuration not found: ${configPath}`);\n }\n\n const content = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(content) as MCPConfiguration;\n}\n\n/**\n * Get list of all available server names\n */\nexport function getAllServerNames(): string[] {\n const config = loadAvailableServers();\n return Object.keys(config.mcpServers);\n}\n\n/**\n * Parse comma-separated server list or \"all\"\n */\nexport function parseServerList(input: string): string[] {\n const allServers = getAllServerNames();\n\n if (input === 'all') {\n return allServers;\n }\n\n const requested = input.split(',').map((s) => s.trim());\n const invalid = requested.filter((s) => !allServers.includes(s));\n\n if (invalid.length > 0) {\n throw new Error(`Invalid server names: ${invalid.join(', ')}.\\nAvailable: ${allServers.join(', ')}`);\n }\n\n return requested;\n}\n\n/**\n * Get server configuration by name\n */\nexport function getServerConfig(serverName: string): McpServerConfig {\n const config = loadAvailableServers();\n const serverConfig = config.mcpServers[serverName];\n\n if (!serverConfig) {\n throw new Error(`Unknown server: ${serverName}.\\nAvailable: ${getAllServerNames().join(', ')}`);\n }\n\n return serverConfig;\n}\n"],"names":["getAllServerNames","getServerConfig","loadAvailableServers","parseServerList","__filename","fileURLToPath","__dirname","path","dirname","packageRoot","resolve","configPath","join","fs","existsSync","Error","content","readFileSync","JSON","parse","config","Object","keys","mcpServers","input","allServers","requested","split","map","s","trim","invalid","filter","includes","length","serverName","serverConfig"],"mappings":"AAAA;;CAEC;;;;;;;;;;;QAsCeA;eAAAA;;QA4BAC;eAAAA;;QA1CAC;eAAAA;;QAsBAC;eAAAA;;;0DA5CI;4DACE;mBACQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE9B,2EAA2E;AAC3E,IAAMC,cAAaC,IAAAA,kBAAa,EAAC;AACjC,IAAMC,YAAYC,MAAKC,OAAO,CAACJ;AAC/B,IAAMK,cAAcF,MAAKG,OAAO,CAACJ,WAAW;AAerC,SAASJ;IACd,IAAMS,aAAaJ,MAAKK,IAAI,CAACH,aAAa;IAE1C,IAAI,CAACI,IAAGC,UAAU,CAACH,aAAa;QAC9B,MAAM,IAAII,MAAM,AAAC,mCAA6C,OAAXJ;IACrD;IAEA,IAAMK,UAAUH,IAAGI,YAAY,CAACN,YAAY;IAC5C,OAAOO,KAAKC,KAAK,CAACH;AACpB;AAKO,SAAShB;IACd,IAAMoB,SAASlB;IACf,OAAOmB,OAAOC,IAAI,CAACF,OAAOG,UAAU;AACtC;AAKO,SAASpB,gBAAgBqB,KAAa;IAC3C,IAAMC,aAAazB;IAEnB,IAAIwB,UAAU,OAAO;QACnB,OAAOC;IACT;IAEA,IAAMC,YAAYF,MAAMG,KAAK,CAAC,KAAKC,GAAG,CAAC,SAACC;eAAMA,EAAEC,IAAI;;IACpD,IAAMC,UAAUL,UAAUM,MAAM,CAAC,SAACH;eAAM,CAACJ,WAAWQ,QAAQ,CAACJ;;IAE7D,IAAIE,QAAQG,MAAM,GAAG,GAAG;QACtB,MAAM,IAAInB,MAAM,AAAC,yBAA2DU,OAAnCM,QAAQnB,IAAI,CAAC,OAAM,kBAAsC,OAAtBa,WAAWb,IAAI,CAAC;IAC9F;IAEA,OAAOc;AACT;AAKO,SAASzB,gBAAgBkC,UAAkB;IAChD,IAAMf,SAASlB;IACf,IAAMkC,eAAehB,OAAOG,UAAU,CAACY,WAAW;IAElD,IAAI,CAACC,cAAc;QACjB,MAAM,IAAIrB,MAAM,AAAC,mBAA6Cf,OAA3BmC,YAAW,kBAA+C,OAA/BnC,oBAAoBY,IAAI,CAAC;IACzF;IAEA,OAAOwB;AACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/config/server-loader.ts"],"sourcesContent":["/**\n * Load server definitions from .mcp.json (data-driven)\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { fileURLToPath } from 'url';\n\n// Get package root: dist/esm/lib -> ../../../ or dist/cjs/lib -> ../../../\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\nconst packageRoot = path.resolve(__dirname, '../../..');\n\nexport interface McpServerConfig {\n command: string;\n args: string[];\n env?: Record<string, string>;\n}\n\nexport interface MCPConfiguration {\n mcpServers: Record<string, McpServerConfig>;\n}\n\n/**\n * Load available servers from resources/.mcp.json\n */\nexport function loadAvailableServers(): MCPConfiguration {\n const configPath = path.join(packageRoot, 'resources/.mcp.json');\n\n if (!fs.existsSync(configPath)) {\n throw new Error(`Server configuration not found: ${configPath}`);\n }\n\n const content = fs.readFileSync(configPath, 'utf-8');\n return JSON.parse(content) as MCPConfiguration;\n}\n\n/**\n * Get list of all available server names\n */\nexport function getAllServerNames(): string[] {\n const config = loadAvailableServers();\n return Object.keys(config.mcpServers);\n}\n\n/**\n * Parse comma-separated server list or \"all\"\n */\nexport function parseServerList(input: string): string[] {\n const allServers = getAllServerNames();\n\n if (input === 'all') {\n return allServers;\n }\n\n const requested = input.split(',').map((s) => s.trim());\n const invalid = requested.filter((s) => !allServers.includes(s));\n\n if (invalid.length > 0) {\n throw new Error(`Invalid server names: ${invalid.join(', ')}.\\nAvailable: ${allServers.join(', ')}`);\n }\n\n return requested;\n}\n\n/**\n * Get server configuration by name\n */\nexport function getServerConfig(serverName: string): McpServerConfig {\n const config = loadAvailableServers();\n const serverConfig = config.mcpServers[serverName];\n\n if (!serverConfig) {\n throw new Error(`Unknown server: ${serverName}.\\nAvailable: ${getAllServerNames().join(', ')}`);\n }\n\n return serverConfig;\n}\n"],"names":["getAllServerNames","getServerConfig","loadAvailableServers","parseServerList","__filename","fileURLToPath","__dirname","path","dirname","packageRoot","resolve","configPath","join","fs","existsSync","Error","content","readFileSync","JSON","parse","config","Object","keys","mcpServers","input","allServers","requested","split","map","s","trim","invalid","filter","includes","length","serverName","serverConfig"],"mappings":"AAAA;;CAEC;;;;;;;;;;;QAsCeA;eAAAA;;QA4BAC;eAAAA;;QA1CAC;eAAAA;;QAsBAC;eAAAA;;;0DA5CI;4DACE;mBACQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE9B,2EAA2E;AAC3E,IAAMC,cAAaC,IAAAA,kBAAa,EAAC;AACjC,IAAMC,YAAYC,MAAKC,OAAO,CAACJ;AAC/B,IAAMK,cAAcF,MAAKG,OAAO,CAACJ,WAAW;AAerC,SAASJ;IACd,IAAMS,aAAaJ,MAAKK,IAAI,CAACH,aAAa;IAE1C,IAAI,CAACI,IAAGC,UAAU,CAACH,aAAa;QAC9B,MAAM,IAAII,MAAM,AAAC,mCAA6C,OAAXJ;IACrD;IAEA,IAAMK,UAAUH,IAAGI,YAAY,CAACN,YAAY;IAC5C,OAAOO,KAAKC,KAAK,CAACH;AACpB;AAKO,SAAShB;IACd,IAAMoB,SAASlB;IACf,OAAOmB,OAAOC,IAAI,CAACF,OAAOG,UAAU;AACtC;AAKO,SAASpB,gBAAgBqB,KAAa;IAC3C,IAAMC,aAAazB;IAEnB,IAAIwB,UAAU,OAAO;QACnB,OAAOC;IACT;IAEA,IAAMC,YAAYF,MAAMG,KAAK,CAAC,KAAKC,GAAG,CAAC,SAACC;eAAMA,EAAEC,IAAI;;IACpD,IAAMC,UAAUL,UAAUM,MAAM,CAAC,SAACH;eAAM,CAACJ,WAAWQ,QAAQ,CAACJ;;IAE7D,IAAIE,QAAQG,MAAM,GAAG,GAAG;QACtB,MAAM,IAAInB,MAAM,AAAC,yBAA2DU,OAAnCM,QAAQnB,IAAI,CAAC,OAAM,kBAAsC,OAAtBa,WAAWb,IAAI,CAAC;IAC9F;IAEA,OAAOc;AACT;AAKO,SAASzB,gBAAgBkC,UAAkB;IAChD,IAAMf,SAASlB;IACf,IAAMkC,eAAehB,OAAOG,UAAU,CAACY,WAAW;IAElD,IAAI,CAACC,cAAc;QACjB,MAAM,IAAIrB,MAAM,AAAC,mBAA6Cf,OAA3BmC,YAAW,kBAA+C,OAA/BnC,oBAAoBY,IAAI,CAAC;IACzF;IAEA,OAAOwB;AACT"}