mcpcac 0.0.1

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.
@@ -0,0 +1,134 @@
1
+ import type { OAuthClientProvider } from "@modelcontextprotocol/sdk/client/auth.js";
2
+ import type {
3
+ OAuthClientInformation,
4
+ OAuthClientInformationFull,
5
+ OAuthClientMetadata,
6
+ OAuthTokens,
7
+ } from "@modelcontextprotocol/sdk/shared/auth.js";
8
+ import type { McpOAuthState } from "./types.js";
9
+
10
+ export interface FileOAuthProviderOptions {
11
+ serverUrl: string;
12
+ redirectUri: string;
13
+ clientName: string;
14
+ tokens?: OAuthTokens;
15
+ clientInformation?: OAuthClientInformation;
16
+ codeVerifier?: string;
17
+ /**
18
+ * Called when tokens are updated (initial save or refresh).
19
+ * Use this to persist the new state.
20
+ */
21
+ onStateUpdated?: (state: McpOAuthState) => void;
22
+ }
23
+
24
+ /**
25
+ * File-based OAuth provider implementation for CLI usage.
26
+ * Implements the OAuthClientProvider interface from MCP SDK.
27
+ *
28
+ * Unlike server-based implementations that use a database,
29
+ * this stores state in memory and calls onStateUpdated for persistence.
30
+ */
31
+ export class FileOAuthProvider implements OAuthClientProvider {
32
+ private _clientInformation: OAuthClientInformation | undefined;
33
+ private _codeVerifier: string | undefined;
34
+ private _tokens: OAuthTokens | undefined;
35
+ private _redirectStartAuthUrl: URL | undefined;
36
+
37
+ private readonly serverUrl: string;
38
+ private readonly redirectUri: string;
39
+ private readonly clientName: string;
40
+ private readonly onStateUpdated?: (state: McpOAuthState) => void;
41
+
42
+ constructor(options: FileOAuthProviderOptions) {
43
+ this.serverUrl = options.serverUrl;
44
+ this.redirectUri = options.redirectUri;
45
+ this.clientName = options.clientName;
46
+ this._tokens = options.tokens;
47
+ this._clientInformation = options.clientInformation;
48
+ this._codeVerifier = options.codeVerifier;
49
+ this.onStateUpdated = options.onStateUpdated;
50
+ }
51
+
52
+ get redirectUrl(): string {
53
+ return this.redirectUri;
54
+ }
55
+
56
+ /**
57
+ * The authorization URL to redirect the user to.
58
+ * Set by redirectToAuthorization().
59
+ */
60
+ get redirectStartAuthUrl(): URL | undefined {
61
+ return this._redirectStartAuthUrl;
62
+ }
63
+
64
+ async clientInformation(): Promise<OAuthClientInformation | undefined> {
65
+ return this._clientInformation;
66
+ }
67
+
68
+ async saveClientInformation(clientInformation: OAuthClientInformationFull): Promise<void> {
69
+ this._clientInformation = clientInformation;
70
+ this.notifyStateUpdated();
71
+ }
72
+
73
+ async codeVerifier(): Promise<string> {
74
+ if (!this._codeVerifier) {
75
+ throw new Error("Code verifier not set");
76
+ }
77
+ return this._codeVerifier;
78
+ }
79
+
80
+ async saveCodeVerifier(codeVerifier: string): Promise<void> {
81
+ this._codeVerifier = codeVerifier;
82
+ this.notifyStateUpdated();
83
+ }
84
+
85
+ get clientMetadata(): OAuthClientMetadata {
86
+ return {
87
+ redirect_uris: [this.redirectUri],
88
+ client_name: this.clientName,
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Called by the MCP SDK when the user needs to be redirected to authorize.
94
+ * We store the URL so the CLI can open it in the browser.
95
+ */
96
+ redirectToAuthorization(authorizationUrl: URL): void {
97
+ this._redirectStartAuthUrl = authorizationUrl;
98
+ }
99
+
100
+ async tokens(): Promise<OAuthTokens | undefined> {
101
+ return this._tokens;
102
+ }
103
+
104
+ async saveTokens(tokens: OAuthTokens): Promise<void> {
105
+ this._tokens = tokens;
106
+ this.notifyStateUpdated();
107
+ }
108
+
109
+ /**
110
+ * Get the current state for persistence
111
+ */
112
+ getState(): McpOAuthState {
113
+ return {
114
+ tokens: this._tokens,
115
+ clientInformation: this._clientInformation,
116
+ codeVerifier: this._codeVerifier,
117
+ serverUrl: this.serverUrl,
118
+ };
119
+ }
120
+
121
+ private notifyStateUpdated(): void {
122
+ if (this.onStateUpdated) {
123
+ this.onStateUpdated(this.getState());
124
+ }
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Create a FileOAuthProvider for use with MCP transports.
130
+ * This is the simpler factory function for common use cases.
131
+ */
132
+ export function createFileOAuthProvider(options: FileOAuthProviderOptions): FileOAuthProvider {
133
+ return new FileOAuthProvider(options);
134
+ }
package/src/types.ts ADDED
@@ -0,0 +1,87 @@
1
+ import type { OAuthTokens, OAuthClientInformation } from "@modelcontextprotocol/sdk/shared/auth.js";
2
+
3
+ /**
4
+ * Persisted OAuth state for file-based storage
5
+ */
6
+ export interface McpOAuthState {
7
+ tokens?: OAuthTokens;
8
+ clientInformation?: OAuthClientInformation;
9
+ codeVerifier?: string;
10
+ serverUrl?: string;
11
+ }
12
+
13
+ /**
14
+ * OAuth configuration for addMcpCommands
15
+ */
16
+ export interface McpOAuthConfig {
17
+ /** Client name shown during OAuth consent screen */
18
+ clientName: string;
19
+
20
+ /**
21
+ * Load persisted OAuth state from storage (e.g., config file)
22
+ */
23
+ load: () => McpOAuthState | undefined;
24
+
25
+ /**
26
+ * Save OAuth state to storage. Called after successful auth or token refresh.
27
+ * Pass undefined to clear the state (logout).
28
+ */
29
+ save: (state: McpOAuthState | undefined) => void;
30
+
31
+ /**
32
+ * Called with the authorization URL. Default behavior opens the browser.
33
+ * Override to customize (e.g., just print the URL).
34
+ */
35
+ onAuthUrl?: (url: string) => void;
36
+
37
+ /**
38
+ * Called on successful authentication
39
+ */
40
+ onAuthSuccess?: () => void;
41
+
42
+ /**
43
+ * Called on authentication error
44
+ */
45
+ onAuthError?: (error: string) => void;
46
+ }
47
+
48
+ /**
49
+ * Result of startOAuthFlow
50
+ */
51
+ export interface OAuthFlowResult {
52
+ success: boolean;
53
+ state?: McpOAuthState;
54
+ error?: string;
55
+ }
56
+
57
+ /**
58
+ * Options for starting OAuth flow
59
+ */
60
+ export interface StartOAuthFlowOptions {
61
+ serverUrl: string;
62
+ clientName: string;
63
+ /** Existing OAuth state (for re-auth scenarios) */
64
+ existingState?: McpOAuthState;
65
+ /** Called with auth URL, default opens browser */
66
+ onAuthUrl?: (url: string) => void;
67
+ /** Timeout in ms waiting for callback, default 5 minutes */
68
+ timeout?: number;
69
+ }
70
+
71
+ /**
72
+ * Options for the local callback server
73
+ */
74
+ export interface CallbackServerOptions {
75
+ /** Called when server starts with the redirect URI */
76
+ onReady?: (redirectUri: string) => void;
77
+ /** Timeout in ms, default 5 minutes */
78
+ timeout?: number;
79
+ }
80
+
81
+ /**
82
+ * Result from callback server
83
+ */
84
+ export interface CallbackResult {
85
+ code: string;
86
+ state: string;
87
+ }