{"version":3,"sources":["../src/index.ts","../src/McpServerAuth.ts","../src/constants.ts","../src/types.ts","../src/client/providers/persistence/InMemoryTokenPersistence.ts","../src/client/providers/CivicAuthProvider.ts","../src/client/providers/CLIAuthProvider.ts","../src/client/providers/TokenAuthProvider.ts","../src/client/transport/RestartableStreamableHTTPClientTransport.ts","../src/client/CLIClient.ts"],"sourcesContent":["import { Router } from \"express\";\nimport type { Request, RequestHandler } from \"express\";\nimport { McpServerAuth } from \"./McpServerAuth.js\";\nimport { DEFAULT_MCP_ROUTE } from \"./constants\";\nimport { AuthenticationError } from \"./types.js\";\nimport type { CivicAuthOptions, ExtendedAuthInfo } from \"./types.js\";\n\nexport * from \"./types.js\";\nexport * from \"./constants.js\";\nexport * from \"./client/index.js\";\nexport { McpServerAuth } from \"./McpServerAuth.js\";\n\n/**\n * Express middleware that configures an MCP server to use Civic Auth\n * as its authorization server.\n *\n * This middleware:\n * 1. Exposes /.well-known/oauth-protected-resource metadata\n * 2. Validates bearer tokens using Civic's JWKS\n * 3. Attaches user info to the request\n *\n * @param options Configuration options\n * @returns Express middleware\n */\nexport async function auth<TAuthInfo extends ExtendedAuthInfo>(\n  options: CivicAuthOptions<TAuthInfo, Request> = {}\n): Promise<RequestHandler> {\n  console.log(`Civic Auth MCP middleware initialized with options: ${JSON.stringify(options)}`);\n\n  // Initialize the core auth functionality\n  const mcpServerAuth = await McpServerAuth.init<TAuthInfo, Request>(options);\n\n  const mcpRoute = options.mcpRoute ?? DEFAULT_MCP_ROUTE;\n\n  // Create router\n  const router = Router();\n\n  // Expose OAuth Protected Resource Metadata\n  // This tells MCP clients where to authenticate\n  router.get(\"/.well-known/oauth-protected-resource\", (req, res) => {\n    const issuerUrl = options.issuerUrl || `${req.protocol}://${req.get(\"host\")}`;\n    const issuerUrlString = typeof issuerUrl === \"string\" ? issuerUrl : issuerUrl.toString();\n    const metadata = mcpServerAuth.getProtectedResourceMetadata(issuerUrlString);\n    res.json(metadata);\n  });\n\n  // Token validation middleware - only apply to mcpRoute\n  router.use(async (req, res, next) => {\n    // Skip auth for metadata endpoints\n    if (req.path === \"/.well-known/oauth-protected-resource\") {\n      return next();\n    }\n\n    // Only protect routes that start with mcpRoute\n    if (!req.path.startsWith(mcpRoute)) {\n      return next();\n    }\n\n    // Handle request authentication\n    try {\n      const authInfo = await mcpServerAuth.handleRequest(req);\n\n      // Attach to request for downstream use\n      // Express allows extending the Request interface through declaration merging\n      // @ts-expect-error - Adding auth property to request\n      req.auth = authInfo;\n\n      next();\n    } catch (error) {\n      if (error instanceof AuthenticationError) {\n        // authentication errors e.g. jwt verification errors (expired, invalid signature, etc.) should return 401\n        return res.status(401).json({\n          error: \"authentication_error\",\n          error_description: error.message,\n        });\n      }\n\n      // Unknown error\n      return res.status(500).json({\n        error: \"internal_error\",\n        error_description: \"An unexpected error occurred\",\n      });\n    }\n  });\n\n  return router;\n}\n","import type { IncomingMessage } from \"node:http\";\nimport { type JWTPayload, createRemoteJWKSet, jwtVerify } from \"jose\";\nimport { DEFAULT_SCOPES, DEFAULT_WELLKNOWN_URL, PUBLIC_CIVIC_CLIENT_ID } from \"./constants.js\";\nimport {\n  type AccessTokenPayload,\n  AuthenticationError,\n  type CivicAuthOptions,\n  type ExtendedAuthInfo,\n  JWTVerificationError,\n  type OIDCWellKnownConfiguration,\n} from \"./types.js\";\n\n/**\n * Return the client ID that must be in the jwt (in either the tid or client_id field).\n * If a client id is explicitly specified by the config then use that.\n * If the auth server is civic, then we allow the public client id if none is specified.\n * Otherwise, return undefined, which means the jwt will accept any access token from the specified issuer\n * @param options\n */\nconst getExpectedClientId = <TAuthInfo extends ExtendedAuthInfo, TRequest extends IncomingMessage = IncomingMessage>(\n  options: CivicAuthOptions<TAuthInfo, TRequest>\n): string | undefined => {\n  if (options.clientId) {\n    return options.clientId;\n  }\n\n  // If wellKnownUrl is not provided (undefined) or is the default, we're using Civic\n  if (!options.wellKnownUrl || options.wellKnownUrl === DEFAULT_WELLKNOWN_URL) {\n    return PUBLIC_CIVIC_CLIENT_ID;\n  }\n\n  return undefined;\n};\n\n/**\n * Get the auth server URL based on the options provided.\n * This adds tenant-specific information via the subdomain if using Civic Auth and dynamic client registration is enabled.\n */\nconst getAuthServer = <TAuthInfo extends ExtendedAuthInfo, TRequest extends IncomingMessage = IncomingMessage>(\n  options: CivicAuthOptions<TAuthInfo, TRequest>\n): string => {\n  // if the wellknown url is explicitly set to something other than Civic, just use that\n  if (options.wellKnownUrl && options.wellKnownUrl !== DEFAULT_WELLKNOWN_URL) return options.wellKnownUrl;\n\n  // If dynamic client registration is enabled, adapt the URL with subdomain\n  if (options.allowDynamicClientRegistration) {\n    const clientId = getExpectedClientId(options) ?? PUBLIC_CIVIC_CLIENT_ID;\n    return DEFAULT_WELLKNOWN_URL.replace(\"https://\", `https://${clientId}.`);\n  }\n\n  // Default behavior: use the URL as-is without subdomain\n  return DEFAULT_WELLKNOWN_URL;\n};\n\n/**\n * Verify that the client_id or tid in the token matches the expected client ID.\n * Throws an error if it does not match.\n *\n * In a DCR environment we would expect the actual client id to be the dynamically created one,\n * but in that case the \"tid\" should refer to the tenant ID, which is the same as the \"base\"\n * client ID passed in the options.\n *\n * @param payload The JWT payload containing client_id or tid\n * @param expectedClientId The expected client ID to match against\n */\nconst verifyClientId = (payload: AccessTokenPayload, expectedClientId: string | undefined) => {\n  if (!expectedClientId) return;\n\n  // Check if either the client_id or tid matches the expected client ID\n  // At least one of them must match\n  const clientIdMatches = payload.client_id === expectedClientId;\n  const tidMatches = payload.tid === expectedClientId;\n\n  if (!clientIdMatches && !tidMatches) {\n    throw new AuthenticationError(`Invalid client_id or tid in token. Expected: ${expectedClientId}`);\n  }\n};\n\n/**\n * Core authentication functionality that can be used with any framework\n */\nexport class McpServerAuth<TAuthInfo extends ExtendedAuthInfo, TRequest extends IncomingMessage = IncomingMessage> {\n  private oidcConfig: OIDCWellKnownConfiguration;\n  private jwks: ReturnType<typeof createRemoteJWKSet>;\n  private options: CivicAuthOptions<TAuthInfo, TRequest>;\n\n  private constructor(oidcConfig: OIDCWellKnownConfiguration, options: CivicAuthOptions<TAuthInfo, TRequest>) {\n    this.oidcConfig = oidcConfig;\n    this.options = options;\n    this.jwks = createRemoteJWKSet(new URL(oidcConfig.jwks_uri));\n  }\n\n  /**\n   * Initialize the auth core by fetching OIDC configuration\n   */\n  static async init<TAuthInfo extends ExtendedAuthInfo, TRequest extends IncomingMessage = IncomingMessage>(\n    options: CivicAuthOptions<TAuthInfo, TRequest> = {}\n  ): Promise<McpServerAuth<TAuthInfo, TRequest>> {\n    const wellKnownUrl = getAuthServer(options);\n    console.log(`Fetching Civic Auth OIDC configuration from ${wellKnownUrl}`);\n\n    const response = await fetch(wellKnownUrl);\n    if (!response.ok) {\n      throw new Error(`Failed to fetch Civic Auth configuration: ${response.statusText}`);\n    }\n\n    const oidcConfig = (await response.json()) as OIDCWellKnownConfiguration;\n    return new McpServerAuth(oidcConfig, options);\n  }\n\n  /**\n   * Get the OAuth Protected Resource metadata\n   * @param issuerUrl The issuer URL of the resource server (e.g., https://my-server.com)\n   */\n  getProtectedResourceMetadata(issuerUrl: string) {\n    return {\n      resource: issuerUrl,\n      authorization_servers: [this.oidcConfig.issuer],\n      scopes_supported: this.options.scopesSupported || DEFAULT_SCOPES,\n      bearer_methods_supported: [\"header\"],\n    };\n  }\n\n  /**\n   * Create auth info from a token (or null) and request\n   * @param token The JWT token (can be null)\n   * @param payload The JWT payload if token was already verified\n   * @param request Optional request object to pass to onLogin callback\n   * @returns ExtendedAuthInfo if successful, null otherwise\n   */\n  private async createAuthInfo(\n    token: string | null,\n    payload: JWTPayload | null,\n    request?: TRequest\n  ): Promise<TAuthInfo | null> {\n    const inputAuthInfo: ExtendedAuthInfo | null =\n      token && payload\n        ? {\n            token,\n            clientId: (payload.client_id as string) || (payload.aud as string),\n            scopes: payload.scope ? (payload.scope as string).split(\" \") : [],\n            expiresAt: payload.exp,\n            extra: {\n              sub: payload.sub as string,\n            },\n          }\n        : null;\n\n    if (!this.options.onLogin) return inputAuthInfo as TAuthInfo;\n\n    // Call onLogin if provided - it can create or enrich auth info\n    // If authInfo is null, onLogin might create it from request headers\n    return this.options.onLogin(inputAuthInfo, request);\n  }\n\n  /**\n   * Extract and verify bearer token from authorization header\n   * @param authHeader The Authorization header value\n   * @returns Object with token and payload if valid, throws if invalid token, returns null values if no token\n   */\n  private async extractBearerToken(authHeader: string | undefined): Promise<{\n    token: string | null;\n    payload: AccessTokenPayload | null;\n  }> {\n    if (!authHeader?.startsWith(\"Bearer \")) {\n      return { token: null, payload: null };\n    }\n\n    const token = authHeader.substring(7);\n\n    try {\n      // Verify the token - this will throw if invalid\n      const { payload } = await jwtVerify<AccessTokenPayload>(token, this.jwks, {\n        issuer: this.oidcConfig.issuer,\n      });\n\n      verifyClientId(payload, getExpectedClientId(this.options));\n\n      return { token, payload };\n    } catch (error) {\n      // Wrap jose errors in our custom error class, so that we can catch them and return 401\n      throw new JWTVerificationError(\n        error instanceof Error ? error.message : \"JWT verification failed\",\n        error instanceof Error ? error : undefined\n      );\n    }\n  }\n\n  /**\n   * Handle a request by extracting and verifying the bearer token\n   * @param request The request object\n   * @returns ExtendedAuthInfo if valid\n   * @throws Error if authentication fails\n   */\n  async handleRequest(request: TRequest): Promise<TAuthInfo> {\n    const { token, payload } = await this.extractBearerToken(request.headers.authorization);\n\n    // Try to create auth info (even with null token/payload, onLogin might handle it)\n    const authInfo = await this.createAuthInfo(token, payload, request);\n\n    if (!authInfo) throw new AuthenticationError(\"Authentication failed\");\n\n    return authInfo;\n  }\n}\n","export const DEFAULT_WELLKNOWN_URL = \"https://auth.civic.com/oauth/.well-known/openid-configuration\";\n\n/**\n * Default scope for OAuth authentication\n */\nexport const DEFAULT_SCOPES = [\"openid\", \"profile\", \"email\", \"offline_access\"];\n\n/**\n * Default callback port for CLI authentication flow\n */\nexport const DEFAULT_CALLBACK_PORT = 8080;\n\n// Default mcpRoute to '/mcp' if not specified\nexport const DEFAULT_MCP_ROUTE = \"/mcp\";\n\n// This client ID is used when a client is not provided.\n// It is registered on Civic Auth as a rate-limited public \"sandbox\" account.\n// Note, this option is used only if the auth server is Civic\nexport const PUBLIC_CIVIC_CLIENT_ID = \"12220cf4-1a9a-4964-8eb7-7c6d7d049f34\";\n","import type { IncomingMessage } from \"node:http\";\nimport type { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport type { JWTPayload } from \"jose\";\n\nexport interface CivicAuthOptions<\n  TAuthInfo extends ExtendedAuthInfo,\n  TRequest extends IncomingMessage = IncomingMessage,\n> {\n  /**\n   * The URL to the auth server's well-known OIDC configuration\n   * Defaults to https://auth.civic.com/oauth/.well-known/openid-configuration\n   */\n  wellKnownUrl?: string;\n\n  /**\n   * OAuth scopes to support\n   * Defaults to ['openid', 'profile', 'email']\n   */\n  scopesSupported?: string[];\n\n  /**\n   * The issuer URL for the resource server\n   * Defaults to the server's base URL\n   */\n  issuerUrl?: string | URL;\n\n  /**\n   * Base path for auth endpoints\n   * Defaults to '/'\n   */\n  basePath?: string;\n\n  /**\n   * The MCP route to protect with authentication\n   * Defaults to '/mcp'\n   */\n  mcpRoute?: string;\n\n  /**\n   * Optional callback to enrich the auth info with custom data\n   * Called after successful token verification\n   * @param authInfo The verified auth info from the token. Null if no token was provided.\n   * @param request Optional request object that may contain headers or other data\n   * @returns Enriched auth info with custom data\n   */\n  onLogin?: (authInfo: ExtendedAuthInfo | null, request?: TRequest) => Promise<TAuthInfo | null>;\n\n  /**\n   * Optional OAuth client ID / Tenant ID.\n   * When set, the access token must include *either* a \"client_id\" field or \"tid\" field that matches it.\n   */\n  clientId?: string;\n\n  /**\n   * Whether to allow dynamic client registration by adding client ID as subdomain.\n   * When true, the client ID will be added as a subdomain to the auth server URL.\n   * When false (default), the auth server URL will be used as-is without subdomain prefixing.\n   * Defaults to false.\n   */\n  allowDynamicClientRegistration?: boolean;\n}\n\nexport interface OIDCWellKnownConfiguration {\n  issuer: string;\n  authorization_endpoint: string;\n  token_endpoint: string;\n  jwks_uri: string;\n  scopes_supported?: string[];\n  response_types_supported?: string[];\n  grant_types_supported?: string[];\n  token_endpoint_auth_methods_supported?: string[];\n  introspection_endpoint?: string;\n  revocation_endpoint?: string;\n  registration_endpoint?: string;\n}\n\nexport interface ExtendedAuthInfo extends AuthInfo {\n  extra?: {\n    sub?: string;\n    email?: string;\n    name?: string;\n    picture?: string;\n  };\n}\n\n/**\n * Custom error class for all authentication errors\n */\nexport class AuthenticationError extends Error {}\n\n/**\n * Custom error class for JWT verification failures\n */\nexport class JWTVerificationError extends AuthenticationError {\n  constructor(\n    message: string,\n    public originalError?: Error\n  ) {\n    super(message);\n    this.name = \"JWTVerificationError\";\n  }\n}\n\nexport type AccessTokenPayload = JWTPayload & {\n  client_id: string | undefined;\n  tid: string | undefined;\n};\n","import type { OAuthTokens } from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport type { TokenPersistence } from \"./TokenPersistence.js\";\n\n/**\n * In-memory token persistence strategy\n * Tokens are stored in memory and lost when the process exits\n */\nexport class InMemoryTokenPersistence implements TokenPersistence {\n  private tokens: OAuthTokens | undefined;\n\n  saveTokens(tokens: OAuthTokens): void {\n    this.tokens = tokens;\n  }\n\n  loadTokens(): OAuthTokens | undefined {\n    return this.tokens;\n  }\n\n  clearTokens(): void {\n    this.tokens = undefined;\n  }\n}\n","import type { OAuthClientProvider } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type {\n  OAuthClientInformation,\n  OAuthClientMetadata,\n  OAuthTokens,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport { InMemoryTokenPersistence, type TokenPersistence } from \"./persistence/index.js\";\n\nexport interface CivicAuthProviderOptions {\n  /**\n   * Client secret for OAuth flows that don't support PKCE.\n   * Optional - only needed for auth servers that require client authentication.\n   */\n  clientSecret?: string;\n\n  /**\n   * Token persistence strategy to use for storing/retrieving tokens.\n   * Defaults to in-memory persistence if not provided.\n   */\n  tokenPersistence?: TokenPersistence;\n}\n\n/**\n * Abstract base class for Civic auth providers\n */\nexport abstract class CivicAuthProvider implements OAuthClientProvider {\n  protected clientSecret?: string;\n  protected tokenPersistence: TokenPersistence;\n\n  constructor(options: CivicAuthProviderOptions) {\n    this.clientSecret = options.clientSecret;\n    this.tokenPersistence = options.tokenPersistence ?? new InMemoryTokenPersistence();\n  }\n\n  abstract clientInformation(): OAuthClientInformation | Promise<OAuthClientInformation | undefined> | undefined;\n\n  abstract get clientMetadata(): OAuthClientMetadata;\n\n  abstract codeVerifier(): string | Promise<string>;\n\n  abstract get redirectUrl(): string | URL;\n\n  abstract saveCodeVerifier(codeVerifier: string): void;\n\n  saveTokens(tokens: OAuthTokens): void | Promise<void> {\n    return this.tokenPersistence.saveTokens(tokens);\n  }\n\n  /**\n   * Returns the stored tokens\n   */\n  tokens(): OAuthTokens | undefined | Promise<OAuthTokens | undefined> {\n    return this.tokenPersistence.loadTokens();\n  }\n\n  /**\n   * Clears the stored tokens\n   */\n  clearTokens(): void | Promise<void> {\n    return this.tokenPersistence.clearTokens();\n  }\n\n  abstract redirectToAuthorization(authorizationUrl: URL): void | Promise<void>;\n}\n","import { execFile } from \"node:child_process\";\nimport crypto from \"node:crypto\";\nimport http from \"node:http\";\nimport type { AddressInfo } from \"node:net\";\nimport url from \"node:url\";\nimport { promisify } from \"node:util\";\nimport type { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { OAuthClientInformation, OAuthClientMetadata } from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport escapeHtml from \"escape-html\";\nimport { DEFAULT_CALLBACK_PORT, DEFAULT_SCOPES } from \"../../constants.js\";\nimport { CivicAuthProvider, type CivicAuthProviderOptions } from \"./CivicAuthProvider.js\";\n\nexport interface CLIAuthProviderOptions extends CivicAuthProviderOptions {\n  clientId: string;\n  scope?: string;\n  callbackPort?: number;\n  enablePortFallback?: boolean;\n  successHtml?: string;\n  errorHtml?: string;\n  authTimeoutMs?: number;\n}\n\n/**\n * CLI Auth Provider for MCP\n * Opens authorization URL in default browser and stores tokens in memory\n */\nexport class CLIAuthProvider extends CivicAuthProvider {\n  private storedCodeVerifier: string | undefined;\n  private clientId: string;\n  private scope: string;\n  private callbackPort: number;\n  private enablePortFallback: boolean;\n  private authTimeoutMs: number;\n  private successHtml: string;\n  private errorHtml: string;\n  private callbackServer: http.Server | undefined;\n  private authorizationCodePromise: Promise<string> | undefined;\n  private authorizationCodeResolve: ((code: string) => void) | undefined;\n  private authorizationCodeReject: ((error: Error) => void) | undefined;\n  private transport: SSEClientTransport | StreamableHTTPClientTransport | undefined;\n  private serverTimeout: NodeJS.Timeout | undefined;\n\n  constructor(options: CLIAuthProviderOptions) {\n    super(options);\n    this.clientId = options.clientId;\n    this.scope = options.scope ?? DEFAULT_SCOPES.join(\" \");\n    this.callbackPort = options.callbackPort ?? DEFAULT_CALLBACK_PORT;\n    this.enablePortFallback = options.enablePortFallback ?? true;\n    this.authTimeoutMs = options.authTimeoutMs ?? 5 * 60 * 1000; // 5 minutes default\n    this.successHtml =\n      options.successHtml ??\n      '<html lang=\"en\"><body><h1>Authorization Successful</h1><p>You can now close this window.</p></body></html>';\n    this.errorHtml =\n      options.errorHtml ?? '<html lang=\"en\"><body><h1>Authorization Failed</h1><p>{{error}}</p></body></html>';\n  }\n\n  clientInformation(): OAuthClientInformation | Promise<OAuthClientInformation | undefined> | undefined {\n    const info: OAuthClientInformation = {\n      client_id: this.clientId,\n    };\n\n    // Include client_secret if provided (for non-PKCE auth servers)\n    if (this.clientSecret) {\n      info.client_secret = this.clientSecret;\n    }\n\n    return info;\n  }\n\n  get clientMetadata(): OAuthClientMetadata {\n    return {\n      redirect_uris: [this.getCallbackUrl(this.callbackPort)],\n      client_name: this.clientId,\n      scope: this.scope,\n    };\n  }\n\n  codeVerifier(): string | Promise<string> {\n    // Generate and return the stored code verifier\n    if (!this.storedCodeVerifier) {\n      this.storedCodeVerifier = crypto.randomBytes(32).toString(\"base64url\");\n    }\n    return this.storedCodeVerifier;\n  }\n\n  async redirectToAuthorization(authorizationUrl: URL): Promise<void> {\n    // Check if authorization flow is already in progress\n    if (this.callbackServer) {\n      throw new Error(\"Authorization flow already in progress. Please wait for it to complete.\");\n    }\n\n    console.log(`Opening authorization URL in browser: ${authorizationUrl.href}`);\n\n    // Start the callback server before opening the browser\n    const actualPort = await this.startCallbackServer();\n\n    // Modify the auth URL to use updated redirect URI if port changed\n    let urlToOpen = authorizationUrl.href;\n    if (actualPort) {\n      // update the callback URL\n      this.callbackPort = actualPort;\n      const authUrlObj = new URL(authorizationUrl);\n      authUrlObj.searchParams.set(\"redirect_uri\", this.getCallbackUrl(actualPort));\n      urlToOpen = authUrlObj.href;\n    }\n\n    // Open URL in default browser\n    await this.openInBrowser(urlToOpen);\n\n    console.log(\"Please complete the authorization in your browser.\");\n  }\n\n  /**\n   * Registers the transport with the auth provider so that we can call finishAuth when the code is received.\n   * @param transport\n   */\n  registerTransport(transport: SSEClientTransport | StreamableHTTPClientTransport): void {\n    this.transport = transport;\n  }\n\n  get redirectUrl(): string | URL {\n    // Return the redirect URL for the OAuth flow\n    return new URL(this.getCallbackUrl(this.callbackPort));\n  }\n\n  saveCodeVerifier(codeVerifier: string): void {\n    this.storedCodeVerifier = codeVerifier;\n  }\n\n  private getCallbackUrl(port: number): string {\n    return `http://localhost:${port}/callback`;\n  }\n\n  /**\n   * Listen on Port Promise\n   * @param server\n   * @param port\n   * @private port that is being listened on.\n   */\n  private listenOnPort(server: http.Server, port: number): Promise<number> {\n    return new Promise((resolve, reject) => {\n      const onError = (err: NodeJS.ErrnoException) => {\n        server.off(\"listening\", onListening);\n        reject(err);\n      };\n\n      const onListening = () => {\n        server.off(\"error\", onError);\n        const address = server.address() as AddressInfo;\n        resolve(address.port);\n      };\n\n      server.once(\"error\", onError);\n      server.once(\"listening\", onListening);\n      server.listen(port, \"localhost\");\n    });\n  }\n\n  /**\n   * Starts a local HTTP server to handle the OAuth callback with port fallback support\n   * @returns The actual port number if different from the configured port, undefined otherwise\n   */\n  private async startCallbackServer(): Promise<number | undefined> {\n    // Create a promise for the authorization code\n    this.authorizationCodePromise = new Promise((resolveCode, rejectCode) => {\n      this.authorizationCodeResolve = resolveCode;\n      this.authorizationCodeReject = rejectCode;\n    });\n\n    // Create the callback server\n    this.callbackServer = http.createServer((req, res) => {\n      try {\n        if (!req.url) {\n          res.writeHead(400);\n          res.end(\"Bad Request\");\n          return;\n        }\n\n        const parsedUrl = url.parse(req.url, true);\n\n        if (parsedUrl.pathname === \"/callback\") {\n          const code = parsedUrl.query.code as string;\n          const error = parsedUrl.query.error as string;\n\n          if (error) {\n            res.writeHead(200, { \"Content-Type\": \"text/html\" });\n            res.end(this.errorHtml.replace(\"{{error}}\", escapeHtml(error)));\n            this.authorizationCodeReject?.(new Error(`OAuth error: ${error}`));\n          } else if (code) {\n            res.writeHead(200, { \"Content-Type\": \"text/html\" });\n            res.end(this.successHtml);\n\n            // Call finishAuth on the transport if set. This triggers the token exchange\n            if (this.transport) {\n              this.transport\n                .finishAuth(code)\n                .then(() => this.authorizationCodeResolve?.(code))\n                .catch((error) => {\n                  console.error(\"Error in finishAuth:\", error);\n                  this.authorizationCodeReject?.(error);\n                });\n            } else {\n              this.authorizationCodeReject?.(new Error(\"No transport registered\"));\n            }\n          } else {\n            res.writeHead(400);\n            res.end(\"Missing authorization code\");\n          }\n        } else {\n          res.writeHead(404);\n          res.end(\"Not Found\");\n        }\n      } finally {\n        // Always stop the server after ANY request\n        this.cleanup();\n      }\n    });\n\n    let actualPort: number;\n    try {\n      actualPort = await this.listenOnPort(this.callbackServer, this.callbackPort);\n    } catch (err: unknown) {\n      if ((err as NodeJS.ErrnoException).code === \"EADDRINUSE\" && this.enablePortFallback) {\n        console.warn(`Port ${this.callbackPort} in use. Trying a random port...`);\n        actualPort = await this.listenOnPort(this.callbackServer, 0); // 0 = random available port\n      } else {\n        throw err;\n      }\n    }\n\n    // Set up timeout to automatically close server\n    this.serverTimeout = setTimeout(() => {\n      console.warn(`OAuth callback server timeout reached after ${this.authTimeoutMs / 1000}s. Closing server.`);\n      this.cleanup();\n    }, this.authTimeoutMs);\n\n    return actualPort !== this.callbackPort ? actualPort : undefined;\n  }\n\n  /**\n   * Resets the instance to its post-initialization state\n   * Stops any active server, clears timeouts\n   */\n  private cleanup(): void {\n    // Close the callback server\n    if (this.callbackServer) {\n      this.callbackServer.close();\n      this.callbackServer = undefined;\n    }\n\n    // Clear the timeout\n    if (this.serverTimeout) {\n      clearTimeout(this.serverTimeout);\n      this.serverTimeout = undefined;\n    }\n  }\n\n  /**\n   * Waits for the authorization code from the callback\n   */\n  async waitForAuthorizationCode(): Promise<string> {\n    if (!this.authorizationCodePromise) {\n      throw new Error(\"Authorization flow not started\");\n    }\n    return this.authorizationCodePromise;\n  }\n\n  private async openInBrowser(url: string): Promise<void> {\n    const execFileAsync = promisify(execFile);\n\n    try {\n      switch (process.platform) {\n        case \"darwin\":\n          await execFileAsync(\"open\", [url]);\n          break;\n        case \"win32\":\n          await execFileAsync(\"cmd\", [\"/c\", \"start\", url]);\n          break;\n        default:\n          // Linux/Unix\n          await execFileAsync(\"xdg-open\", [url]);\n      }\n    } catch (error) {\n      console.error(\"Failed to open browser:\", error);\n      console.log(\"Please open this URL manually:\", url);\n    }\n  }\n}\n","import type {\n  OAuthClientInformation,\n  OAuthClientMetadata,\n  OAuthTokens,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport { CivicAuthProvider, type CivicAuthProviderOptions } from \"./CivicAuthProvider.js\";\n\n/**\n * Configuration options for TokenAuthProvider\n */\nexport interface TokenAuthProviderOptions extends CivicAuthProviderOptions {\n  /**\n   * OAuth tokens to use for authentication\n   */\n  tokens: OAuthTokens;\n}\n\n/**\n * Authentication provider for pre-obtained tokens.\n * Use this when you already have access tokens from an external OAuth flow\n * and want to use them directly with the MCP client.\n */\nexport class TokenAuthProvider extends CivicAuthProvider {\n  /**\n   * Create a new TokenAuthProvider\n   * @param tokenOrOptions - Either a token string or full options object\n   */\n  constructor(tokenOrOptions: string | TokenAuthProviderOptions) {\n    // Handle simple string constructor for convenience\n    const options: TokenAuthProviderOptions =\n      typeof tokenOrOptions === \"string\"\n        ? { tokens: { access_token: tokenOrOptions, token_type: \"Bearer\" } }\n        : tokenOrOptions;\n\n    super(options);\n    // Save the initial tokens using the persistence strategy\n    this.tokenPersistence.saveTokens(options.tokens);\n  }\n\n  get redirectUrl(): string | URL {\n    // No redirect URL needed for token-based auth\n    return \"\";\n  }\n\n  get clientMetadata(): OAuthClientMetadata {\n    return {\n      redirect_uris: [],\n    };\n  }\n\n  clientInformation(): OAuthClientInformation | undefined {\n    return {\n      client_id: \"token-client\",\n    };\n  }\n\n  redirectToAuthorization(_authorizationUrl: URL): void {\n    // No-op - tokens are already available\n  }\n\n  saveCodeVerifier(_codeVerifier: string): void {\n    // No-op for token-based auth\n  }\n\n  codeVerifier(): string {\n    // Return empty string as no code verifier is needed for token-based auth\n    return \"\";\n  }\n}\n","import {\n  StreamableHTTPClientTransport,\n  type StreamableHTTPClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { CLIAuthProvider } from \"../providers/index.js\";\n\ntype RestartableStreamableHTTPClientTransportOpts = StreamableHTTPClientTransportOptions & {\n  authProvider: CLIAuthProvider;\n};\n\n/**\n * A transport that extends StreamableHTTPClientTransport to support restarting\n * the connection after authentication. This is particularly useful when\n * implementing authentication flows that require redirection and reconnection.\n */\nexport class RestartableStreamableHTTPClientTransport extends StreamableHTTPClientTransport {\n  private _cliAuthProvider: CLIAuthProvider;\n\n  constructor(url: URL, opts: RestartableStreamableHTTPClientTransportOpts) {\n    super(url, opts);\n    this._cliAuthProvider = opts.authProvider; // Assign the authProvider from options so that we have access\n\n    // Register this transport with the auth provider\n    this._cliAuthProvider.registerTransport(this);\n  }\n\n  get authProvider(): CLIAuthProvider {\n    return this._cliAuthProvider;\n  }\n\n  /**\n   * Extends the start method to properly handle reconnection.\n   * If the transport has already been started, it will disconnect first,\n   * then start again to establish a fresh connection.\n   */\n  override async start() {\n    try {\n      await super.start();\n    } catch (_error) {\n      // ignore restart errors here\n    }\n  }\n\n  override async close() {\n    // do nothing for now\n  }\n}\n","import { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { RestartableStreamableHTTPClientTransport } from \"./transport/index.js\";\n\n/**\n * MCP Client with built-in CLI authentication support\n * Handles the OAuth flow automatically and retries connection after auth\n */\nexport class CLIClient extends Client {\n  /**\n   * Connect to MCP server with automatic authentication handling\n   * If the first connection fails due to auth, it will wait for the OAuth flow\n   * to complete and then retry the connection\n   */\n  async connect(transport: RestartableStreamableHTTPClientTransport): Promise<void> {\n    try {\n      await super.connect(transport);\n    } catch (error: unknown) {\n      // Check if this is an authorization error\n      if (error instanceof Error) {\n        // This error.message is ONLY returned if auth() in @modelcontextprotocol/sdk/client/auth.js\n        // returns \"REDIRECT\", therefore we waitForAuthorizationCode() and connect again.\n        if (error.message === \"Unauthorized\") {\n          console.log(\"Authorization required, waiting for user to complete OAuth flow...\");\n          const authProvider = transport.authProvider;\n\n          // Wait for the OAuth flow to complete\n          await authProvider.waitForAuthorizationCode();\n          console.log(\"Authorization completed.\");\n\n          // Retry the connection - the auth provider now has tokens\n          return await super.connect(transport);\n        }\n      }\n\n      // Re-throw any other errors\n      throw error;\n    }\n  }\n}\n"],"mappings":"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","names":["crypto","http","url","escapeHtml","error","url"]}