@civic/auth-mcp
Version:
Civic Auth integration for MCP servers
212 lines (202 loc) • 7.88 kB
text/typescript
import { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';
import { OAuthTokens, OAuthClientInformation, OAuthClientMetadata } from '@modelcontextprotocol/sdk/shared/auth.js';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
import { StreamableHTTPClientTransport, StreamableHTTPClientTransportOptions } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
declare const DEFAULT_WELLKNOWN_URL = "https://auth.civic.com/oauth/.well-known/openid-configuration";
/**
* Default scope for OAuth authentication
*/
declare const DEFAULT_SCOPES: string[];
/**
* Default callback port for CLI authentication flow
*/
declare const DEFAULT_CALLBACK_PORT = 8080;
declare const DEFAULT_MCP_ROUTE = "/mcp";
declare const PUBLIC_CIVIC_CLIENT_ID = "12220cf4-1a9a-4964-8eb7-7c6d7d049f34";
/**
* Interface for token persistence strategies
*/
interface TokenPersistence {
/**
* Save tokens to persistence storage
*/
saveTokens(tokens: OAuthTokens): Promise<void> | void;
/**
* Load tokens from persistence storage
*/
loadTokens(): Promise<OAuthTokens | undefined> | OAuthTokens | undefined;
/**
* Clear stored tokens
*/
clearTokens(): Promise<void> | void;
}
/**
* In-memory token persistence strategy
* Tokens are stored in memory and lost when the process exits
*/
declare class InMemoryTokenPersistence implements TokenPersistence {
private tokens;
saveTokens(tokens: OAuthTokens): void;
loadTokens(): OAuthTokens | undefined;
clearTokens(): void;
}
interface CivicAuthProviderOptions {
/**
* Client secret for OAuth flows that don't support PKCE.
* Optional - only needed for auth servers that require client authentication.
*/
clientSecret?: string;
/**
* Token persistence strategy to use for storing/retrieving tokens.
* Defaults to in-memory persistence if not provided.
*/
tokenPersistence?: TokenPersistence;
}
/**
* Abstract base class for Civic auth providers
*/
declare abstract class CivicAuthProvider implements OAuthClientProvider {
protected clientSecret?: string;
protected tokenPersistence: TokenPersistence;
constructor(options: CivicAuthProviderOptions);
abstract clientInformation(): OAuthClientInformation | Promise<OAuthClientInformation | undefined> | undefined;
abstract get clientMetadata(): OAuthClientMetadata;
abstract codeVerifier(): string | Promise<string>;
abstract get redirectUrl(): string | URL;
abstract saveCodeVerifier(codeVerifier: string): void;
saveTokens(tokens: OAuthTokens): void | Promise<void>;
/**
* Returns the stored tokens
*/
tokens(): OAuthTokens | undefined | Promise<OAuthTokens | undefined>;
/**
* Clears the stored tokens
*/
clearTokens(): void | Promise<void>;
abstract redirectToAuthorization(authorizationUrl: URL): void | Promise<void>;
}
interface CLIAuthProviderOptions extends CivicAuthProviderOptions {
clientId: string;
scope?: string;
callbackPort?: number;
enablePortFallback?: boolean;
successHtml?: string;
errorHtml?: string;
authTimeoutMs?: number;
}
/**
* CLI Auth Provider for MCP
* Opens authorization URL in default browser and stores tokens in memory
*/
declare class CLIAuthProvider extends CivicAuthProvider {
private storedCodeVerifier;
private clientId;
private scope;
private callbackPort;
private enablePortFallback;
private authTimeoutMs;
private successHtml;
private errorHtml;
private callbackServer;
private authorizationCodePromise;
private authorizationCodeResolve;
private authorizationCodeReject;
private transport;
private serverTimeout;
constructor(options: CLIAuthProviderOptions);
clientInformation(): OAuthClientInformation | Promise<OAuthClientInformation | undefined> | undefined;
get clientMetadata(): OAuthClientMetadata;
codeVerifier(): string | Promise<string>;
redirectToAuthorization(authorizationUrl: URL): Promise<void>;
/**
* Registers the transport with the auth provider so that we can call finishAuth when the code is received.
* @param transport
*/
registerTransport(transport: SSEClientTransport | StreamableHTTPClientTransport): void;
get redirectUrl(): string | URL;
saveCodeVerifier(codeVerifier: string): void;
private getCallbackUrl;
/**
* Listen on Port Promise
* @param server
* @param port
* @private port that is being listened on.
*/
private listenOnPort;
/**
* Starts a local HTTP server to handle the OAuth callback with port fallback support
* @returns The actual port number if different from the configured port, undefined otherwise
*/
private startCallbackServer;
/**
* Resets the instance to its post-initialization state
* Stops any active server, clears timeouts
*/
private cleanup;
/**
* Waits for the authorization code from the callback
*/
waitForAuthorizationCode(): Promise<string>;
private openInBrowser;
}
/**
* Configuration options for TokenAuthProvider
*/
interface TokenAuthProviderOptions extends CivicAuthProviderOptions {
/**
* OAuth tokens to use for authentication
*/
tokens: OAuthTokens;
}
/**
* Authentication provider for pre-obtained tokens.
* Use this when you already have access tokens from an external OAuth flow
* and want to use them directly with the MCP client.
*/
declare class TokenAuthProvider extends CivicAuthProvider {
/**
* Create a new TokenAuthProvider
* @param tokenOrOptions - Either a token string or full options object
*/
constructor(tokenOrOptions: string | TokenAuthProviderOptions);
get redirectUrl(): string | URL;
get clientMetadata(): OAuthClientMetadata;
clientInformation(): OAuthClientInformation | undefined;
redirectToAuthorization(_authorizationUrl: URL): void;
saveCodeVerifier(_codeVerifier: string): void;
codeVerifier(): string;
}
type RestartableStreamableHTTPClientTransportOpts = StreamableHTTPClientTransportOptions & {
authProvider: CLIAuthProvider;
};
/**
* A transport that extends StreamableHTTPClientTransport to support restarting
* the connection after authentication. This is particularly useful when
* implementing authentication flows that require redirection and reconnection.
*/
declare class RestartableStreamableHTTPClientTransport extends StreamableHTTPClientTransport {
private _cliAuthProvider;
constructor(url: URL, opts: RestartableStreamableHTTPClientTransportOpts);
get authProvider(): CLIAuthProvider;
/**
* Extends the start method to properly handle reconnection.
* If the transport has already been started, it will disconnect first,
* then start again to establish a fresh connection.
*/
start(): Promise<void>;
close(): Promise<void>;
}
/**
* MCP Client with built-in CLI authentication support
* Handles the OAuth flow automatically and retries connection after auth
*/
declare class CLIClient extends Client {
/**
* Connect to MCP server with automatic authentication handling
* If the first connection fails due to auth, it will wait for the OAuth flow
* to complete and then retry the connection
*/
connect(transport: RestartableStreamableHTTPClientTransport): Promise<void>;
}
export { CLIAuthProvider, type CLIAuthProviderOptions, CLIClient, CivicAuthProvider, type CivicAuthProviderOptions, DEFAULT_CALLBACK_PORT, DEFAULT_MCP_ROUTE, DEFAULT_SCOPES, DEFAULT_WELLKNOWN_URL, InMemoryTokenPersistence, PUBLIC_CIVIC_CLIENT_ID, RestartableStreamableHTTPClientTransport, TokenAuthProvider, type TokenAuthProviderOptions, type TokenPersistence };