@leanmcp/auth 0.4.2 → 0.4.4-alpha.6.6dae082
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -23
- package/dist/{auth0-UTD4QBG6.mjs → auth0-DWCHZ7IN.mjs} +1 -1
- package/dist/{chunk-RGCCBQWG.mjs → chunk-MXTUNMHA.mjs} +4 -4
- package/dist/{chunk-P4HFKA5R.mjs → chunk-ZJYMG6ZM.mjs} +4 -4
- package/dist/{clerk-3SDKGD6C.mjs → clerk-YVTZMRLF.mjs} +1 -1
- package/dist/client/index.d.mts +499 -0
- package/dist/client/index.d.ts +499 -0
- package/dist/client/index.js +56 -56
- package/dist/client/index.mjs +53 -53
- package/dist/{cognito-QQT7LK2Y.mjs → cognito-XKPEG6UH.mjs} +1 -1
- package/dist/index.d.mts +181 -0
- package/dist/index.d.ts +181 -0
- package/dist/index.js +8 -8
- package/dist/index.mjs +1 -1
- package/dist/{leanmcp-Y7TXNSTD.mjs → leanmcp-73RUGZ2B.mjs} +9 -9
- package/dist/proxy/index.d.mts +376 -0
- package/dist/proxy/index.d.ts +376 -0
- package/dist/proxy/index.js +36 -36
- package/dist/proxy/index.mjs +36 -36
- package/dist/server/index.d.mts +496 -0
- package/dist/server/index.d.ts +496 -0
- package/dist/server/index.js +69 -69
- package/dist/server/index.mjs +69 -69
- package/dist/storage/index.d.mts +181 -0
- package/dist/storage/index.d.ts +181 -0
- package/dist/storage/index.js +24 -24
- package/dist/storage/index.mjs +21 -21
- package/dist/types-DMpGN530.d.mts +122 -0
- package/dist/types-DMpGN530.d.ts +122 -0
- package/package.json +2 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { T as TokenStorage, O as OAuthTokens, C as ClientRegistration, S as StoredSession } from '../types-DMpGN530.mjs';
|
|
2
|
+
export { i as isTokenExpired, w as withExpiresAt } from '../types-DMpGN530.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* In-memory token storage
|
|
6
|
+
*
|
|
7
|
+
* Fast, simple storage for development and short-lived sessions.
|
|
8
|
+
* Tokens are lost when the process exits.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* In-memory token storage implementation
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const storage = new MemoryStorage();
|
|
17
|
+
* await storage.setTokens('https://mcp.example.com', tokens);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
declare class MemoryStorage implements TokenStorage {
|
|
21
|
+
private tokens;
|
|
22
|
+
private clients;
|
|
23
|
+
/**
|
|
24
|
+
* Normalize server URL for consistent key lookup
|
|
25
|
+
*/
|
|
26
|
+
private normalizeUrl;
|
|
27
|
+
/**
|
|
28
|
+
* Check if an entry is expired
|
|
29
|
+
*/
|
|
30
|
+
private isExpired;
|
|
31
|
+
getTokens(serverUrl: string): Promise<OAuthTokens | null>;
|
|
32
|
+
setTokens(serverUrl: string, tokens: OAuthTokens): Promise<void>;
|
|
33
|
+
clearTokens(serverUrl: string): Promise<void>;
|
|
34
|
+
getClientInfo(serverUrl: string): Promise<ClientRegistration | null>;
|
|
35
|
+
setClientInfo(serverUrl: string, info: ClientRegistration): Promise<void>;
|
|
36
|
+
clearClientInfo(serverUrl: string): Promise<void>;
|
|
37
|
+
clearAll(): Promise<void>;
|
|
38
|
+
getAllSessions(): Promise<StoredSession[]>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* File-based token storage
|
|
43
|
+
*
|
|
44
|
+
* Persists tokens to a JSON file for survival across restarts.
|
|
45
|
+
* Optionally encrypts tokens for security.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
interface FileStorageOptions {
|
|
49
|
+
/** Path to the storage file */
|
|
50
|
+
filePath: string;
|
|
51
|
+
/** Optional encryption key (if omitted, data stored in plaintext) */
|
|
52
|
+
encryptionKey?: string;
|
|
53
|
+
/** Whether to pretty-print JSON (default: false) */
|
|
54
|
+
prettyPrint?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* File-based token storage with optional encryption
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* // Plaintext storage
|
|
62
|
+
* const storage = new FileStorage({ filePath: '~/.leanmcp/tokens.json' });
|
|
63
|
+
*
|
|
64
|
+
* // Encrypted storage
|
|
65
|
+
* const storage = new FileStorage({
|
|
66
|
+
* filePath: '~/.leanmcp/tokens.enc',
|
|
67
|
+
* encryptionKey: process.env.TOKEN_ENCRYPTION_KEY
|
|
68
|
+
* });
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare class FileStorage implements TokenStorage {
|
|
72
|
+
private filePath;
|
|
73
|
+
private encryptionKey?;
|
|
74
|
+
private prettyPrint;
|
|
75
|
+
private cache;
|
|
76
|
+
private writePromise;
|
|
77
|
+
constructor(options: FileStorageOptions | string);
|
|
78
|
+
/**
|
|
79
|
+
* Expand ~ to home directory
|
|
80
|
+
*/
|
|
81
|
+
private expandPath;
|
|
82
|
+
/**
|
|
83
|
+
* Normalize server URL for consistent key lookup
|
|
84
|
+
*/
|
|
85
|
+
private normalizeUrl;
|
|
86
|
+
/**
|
|
87
|
+
* Encrypt data
|
|
88
|
+
*/
|
|
89
|
+
private encrypt;
|
|
90
|
+
/**
|
|
91
|
+
* Decrypt data
|
|
92
|
+
*/
|
|
93
|
+
private decrypt;
|
|
94
|
+
/**
|
|
95
|
+
* Read data from file
|
|
96
|
+
*/
|
|
97
|
+
private readFile;
|
|
98
|
+
/**
|
|
99
|
+
* Write data to file (coalesced to avoid race conditions)
|
|
100
|
+
*/
|
|
101
|
+
private writeFile;
|
|
102
|
+
getTokens(serverUrl: string): Promise<OAuthTokens | null>;
|
|
103
|
+
setTokens(serverUrl: string, tokens: OAuthTokens): Promise<void>;
|
|
104
|
+
clearTokens(serverUrl: string): Promise<void>;
|
|
105
|
+
getClientInfo(serverUrl: string): Promise<ClientRegistration | null>;
|
|
106
|
+
setClientInfo(serverUrl: string, info: ClientRegistration): Promise<void>;
|
|
107
|
+
clearClientInfo(serverUrl: string): Promise<void>;
|
|
108
|
+
clearAll(): Promise<void>;
|
|
109
|
+
getAllSessions(): Promise<StoredSession[]>;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* OS Keychain Token Storage
|
|
114
|
+
*
|
|
115
|
+
* Secure storage using the operating system's credential manager:
|
|
116
|
+
* - macOS: Keychain
|
|
117
|
+
* - Windows: Credential Vault
|
|
118
|
+
* - Linux: libsecret (GNOME Keyring, KWallet, etc.)
|
|
119
|
+
*
|
|
120
|
+
* Requires the optional 'keytar' peer dependency.
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Keychain storage options
|
|
125
|
+
*/
|
|
126
|
+
interface KeychainStorageOptions {
|
|
127
|
+
/** Custom service name (default: 'leanmcp-auth') */
|
|
128
|
+
serviceName?: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* OS Keychain-based token storage
|
|
132
|
+
*
|
|
133
|
+
* Uses the operating system's secure credential storage for maximum security.
|
|
134
|
+
* Tokens are encrypted at rest by the OS.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* import { KeychainStorage } from '@leanmcp/auth/storage';
|
|
139
|
+
*
|
|
140
|
+
* // Requires 'keytar' to be installed
|
|
141
|
+
* const storage = new KeychainStorage();
|
|
142
|
+
*
|
|
143
|
+
* await storage.setTokens('https://mcp.example.com', tokens);
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
declare class KeychainStorage implements TokenStorage {
|
|
147
|
+
private serviceName;
|
|
148
|
+
private keytar;
|
|
149
|
+
private initPromise;
|
|
150
|
+
constructor(options?: KeychainStorageOptions);
|
|
151
|
+
/**
|
|
152
|
+
* Initialize keytar (lazy load)
|
|
153
|
+
*/
|
|
154
|
+
private init;
|
|
155
|
+
/**
|
|
156
|
+
* Normalize server URL for consistent key lookup
|
|
157
|
+
*/
|
|
158
|
+
private normalizeUrl;
|
|
159
|
+
/**
|
|
160
|
+
* Get account key for tokens
|
|
161
|
+
*/
|
|
162
|
+
private getTokensAccount;
|
|
163
|
+
/**
|
|
164
|
+
* Get account key for client info
|
|
165
|
+
*/
|
|
166
|
+
private getClientAccount;
|
|
167
|
+
getTokens(serverUrl: string): Promise<OAuthTokens | null>;
|
|
168
|
+
setTokens(serverUrl: string, tokens: OAuthTokens): Promise<void>;
|
|
169
|
+
clearTokens(serverUrl: string): Promise<void>;
|
|
170
|
+
getClientInfo(serverUrl: string): Promise<ClientRegistration | null>;
|
|
171
|
+
setClientInfo(serverUrl: string, info: ClientRegistration): Promise<void>;
|
|
172
|
+
clearClientInfo(serverUrl: string): Promise<void>;
|
|
173
|
+
clearAll(): Promise<void>;
|
|
174
|
+
getAllSessions(): Promise<StoredSession[]>;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Check if keychain storage is available
|
|
178
|
+
*/
|
|
179
|
+
declare function isKeychainAvailable(): Promise<boolean>;
|
|
180
|
+
|
|
181
|
+
export { ClientRegistration, FileStorage, KeychainStorage, type KeychainStorageOptions, MemoryStorage, OAuthTokens, StoredSession, TokenStorage, isKeychainAvailable };
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { T as TokenStorage, O as OAuthTokens, C as ClientRegistration, S as StoredSession } from '../types-DMpGN530.js';
|
|
2
|
+
export { i as isTokenExpired, w as withExpiresAt } from '../types-DMpGN530.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* In-memory token storage
|
|
6
|
+
*
|
|
7
|
+
* Fast, simple storage for development and short-lived sessions.
|
|
8
|
+
* Tokens are lost when the process exits.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* In-memory token storage implementation
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const storage = new MemoryStorage();
|
|
17
|
+
* await storage.setTokens('https://mcp.example.com', tokens);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
declare class MemoryStorage implements TokenStorage {
|
|
21
|
+
private tokens;
|
|
22
|
+
private clients;
|
|
23
|
+
/**
|
|
24
|
+
* Normalize server URL for consistent key lookup
|
|
25
|
+
*/
|
|
26
|
+
private normalizeUrl;
|
|
27
|
+
/**
|
|
28
|
+
* Check if an entry is expired
|
|
29
|
+
*/
|
|
30
|
+
private isExpired;
|
|
31
|
+
getTokens(serverUrl: string): Promise<OAuthTokens | null>;
|
|
32
|
+
setTokens(serverUrl: string, tokens: OAuthTokens): Promise<void>;
|
|
33
|
+
clearTokens(serverUrl: string): Promise<void>;
|
|
34
|
+
getClientInfo(serverUrl: string): Promise<ClientRegistration | null>;
|
|
35
|
+
setClientInfo(serverUrl: string, info: ClientRegistration): Promise<void>;
|
|
36
|
+
clearClientInfo(serverUrl: string): Promise<void>;
|
|
37
|
+
clearAll(): Promise<void>;
|
|
38
|
+
getAllSessions(): Promise<StoredSession[]>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* File-based token storage
|
|
43
|
+
*
|
|
44
|
+
* Persists tokens to a JSON file for survival across restarts.
|
|
45
|
+
* Optionally encrypts tokens for security.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
interface FileStorageOptions {
|
|
49
|
+
/** Path to the storage file */
|
|
50
|
+
filePath: string;
|
|
51
|
+
/** Optional encryption key (if omitted, data stored in plaintext) */
|
|
52
|
+
encryptionKey?: string;
|
|
53
|
+
/** Whether to pretty-print JSON (default: false) */
|
|
54
|
+
prettyPrint?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* File-based token storage with optional encryption
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* // Plaintext storage
|
|
62
|
+
* const storage = new FileStorage({ filePath: '~/.leanmcp/tokens.json' });
|
|
63
|
+
*
|
|
64
|
+
* // Encrypted storage
|
|
65
|
+
* const storage = new FileStorage({
|
|
66
|
+
* filePath: '~/.leanmcp/tokens.enc',
|
|
67
|
+
* encryptionKey: process.env.TOKEN_ENCRYPTION_KEY
|
|
68
|
+
* });
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare class FileStorage implements TokenStorage {
|
|
72
|
+
private filePath;
|
|
73
|
+
private encryptionKey?;
|
|
74
|
+
private prettyPrint;
|
|
75
|
+
private cache;
|
|
76
|
+
private writePromise;
|
|
77
|
+
constructor(options: FileStorageOptions | string);
|
|
78
|
+
/**
|
|
79
|
+
* Expand ~ to home directory
|
|
80
|
+
*/
|
|
81
|
+
private expandPath;
|
|
82
|
+
/**
|
|
83
|
+
* Normalize server URL for consistent key lookup
|
|
84
|
+
*/
|
|
85
|
+
private normalizeUrl;
|
|
86
|
+
/**
|
|
87
|
+
* Encrypt data
|
|
88
|
+
*/
|
|
89
|
+
private encrypt;
|
|
90
|
+
/**
|
|
91
|
+
* Decrypt data
|
|
92
|
+
*/
|
|
93
|
+
private decrypt;
|
|
94
|
+
/**
|
|
95
|
+
* Read data from file
|
|
96
|
+
*/
|
|
97
|
+
private readFile;
|
|
98
|
+
/**
|
|
99
|
+
* Write data to file (coalesced to avoid race conditions)
|
|
100
|
+
*/
|
|
101
|
+
private writeFile;
|
|
102
|
+
getTokens(serverUrl: string): Promise<OAuthTokens | null>;
|
|
103
|
+
setTokens(serverUrl: string, tokens: OAuthTokens): Promise<void>;
|
|
104
|
+
clearTokens(serverUrl: string): Promise<void>;
|
|
105
|
+
getClientInfo(serverUrl: string): Promise<ClientRegistration | null>;
|
|
106
|
+
setClientInfo(serverUrl: string, info: ClientRegistration): Promise<void>;
|
|
107
|
+
clearClientInfo(serverUrl: string): Promise<void>;
|
|
108
|
+
clearAll(): Promise<void>;
|
|
109
|
+
getAllSessions(): Promise<StoredSession[]>;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* OS Keychain Token Storage
|
|
114
|
+
*
|
|
115
|
+
* Secure storage using the operating system's credential manager:
|
|
116
|
+
* - macOS: Keychain
|
|
117
|
+
* - Windows: Credential Vault
|
|
118
|
+
* - Linux: libsecret (GNOME Keyring, KWallet, etc.)
|
|
119
|
+
*
|
|
120
|
+
* Requires the optional 'keytar' peer dependency.
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Keychain storage options
|
|
125
|
+
*/
|
|
126
|
+
interface KeychainStorageOptions {
|
|
127
|
+
/** Custom service name (default: 'leanmcp-auth') */
|
|
128
|
+
serviceName?: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* OS Keychain-based token storage
|
|
132
|
+
*
|
|
133
|
+
* Uses the operating system's secure credential storage for maximum security.
|
|
134
|
+
* Tokens are encrypted at rest by the OS.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* import { KeychainStorage } from '@leanmcp/auth/storage';
|
|
139
|
+
*
|
|
140
|
+
* // Requires 'keytar' to be installed
|
|
141
|
+
* const storage = new KeychainStorage();
|
|
142
|
+
*
|
|
143
|
+
* await storage.setTokens('https://mcp.example.com', tokens);
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
declare class KeychainStorage implements TokenStorage {
|
|
147
|
+
private serviceName;
|
|
148
|
+
private keytar;
|
|
149
|
+
private initPromise;
|
|
150
|
+
constructor(options?: KeychainStorageOptions);
|
|
151
|
+
/**
|
|
152
|
+
* Initialize keytar (lazy load)
|
|
153
|
+
*/
|
|
154
|
+
private init;
|
|
155
|
+
/**
|
|
156
|
+
* Normalize server URL for consistent key lookup
|
|
157
|
+
*/
|
|
158
|
+
private normalizeUrl;
|
|
159
|
+
/**
|
|
160
|
+
* Get account key for tokens
|
|
161
|
+
*/
|
|
162
|
+
private getTokensAccount;
|
|
163
|
+
/**
|
|
164
|
+
* Get account key for client info
|
|
165
|
+
*/
|
|
166
|
+
private getClientAccount;
|
|
167
|
+
getTokens(serverUrl: string): Promise<OAuthTokens | null>;
|
|
168
|
+
setTokens(serverUrl: string, tokens: OAuthTokens): Promise<void>;
|
|
169
|
+
clearTokens(serverUrl: string): Promise<void>;
|
|
170
|
+
getClientInfo(serverUrl: string): Promise<ClientRegistration | null>;
|
|
171
|
+
setClientInfo(serverUrl: string, info: ClientRegistration): Promise<void>;
|
|
172
|
+
clearClientInfo(serverUrl: string): Promise<void>;
|
|
173
|
+
clearAll(): Promise<void>;
|
|
174
|
+
getAllSessions(): Promise<StoredSession[]>;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Check if keychain storage is available
|
|
178
|
+
*/
|
|
179
|
+
declare function isKeychainAvailable(): Promise<boolean>;
|
|
180
|
+
|
|
181
|
+
export { ClientRegistration, FileStorage, KeychainStorage, type KeychainStorageOptions, MemoryStorage, OAuthTokens, StoredSession, TokenStorage, isKeychainAvailable };
|
package/dist/storage/index.js
CHANGED
|
@@ -59,14 +59,14 @@ var MemoryStorage = class {
|
|
|
59
59
|
tokens = /* @__PURE__ */ new Map();
|
|
60
60
|
clients = /* @__PURE__ */ new Map();
|
|
61
61
|
/**
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
* Normalize server URL for consistent key lookup
|
|
63
|
+
*/
|
|
64
64
|
normalizeUrl(serverUrl) {
|
|
65
65
|
return serverUrl.replace(/\/+$/, "").toLowerCase();
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
* Check if an entry is expired
|
|
69
|
+
*/
|
|
70
70
|
isExpired(entry) {
|
|
71
71
|
if (!entry) return true;
|
|
72
72
|
if (!entry.expiresAt) return false;
|
|
@@ -162,8 +162,8 @@ var FileStorage = class {
|
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
/**
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
* Expand ~ to home directory
|
|
166
|
+
*/
|
|
167
167
|
expandPath(filePath) {
|
|
168
168
|
if (filePath.startsWith("~")) {
|
|
169
169
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
@@ -172,14 +172,14 @@ var FileStorage = class {
|
|
|
172
172
|
return filePath;
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
* Normalize server URL for consistent key lookup
|
|
176
|
+
*/
|
|
177
177
|
normalizeUrl(serverUrl) {
|
|
178
178
|
return serverUrl.replace(/\/+$/, "").toLowerCase();
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
* Encrypt data
|
|
182
|
+
*/
|
|
183
183
|
encrypt(data) {
|
|
184
184
|
if (!this.encryptionKey) return data;
|
|
185
185
|
const iv = (0, import_crypto.randomBytes)(16);
|
|
@@ -190,8 +190,8 @@ var FileStorage = class {
|
|
|
190
190
|
return `${iv.toString("hex")}:${authTag.toString("hex")}:${encrypted}`;
|
|
191
191
|
}
|
|
192
192
|
/**
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
* Decrypt data
|
|
194
|
+
*/
|
|
195
195
|
decrypt(data) {
|
|
196
196
|
if (!this.encryptionKey) return data;
|
|
197
197
|
const [ivHex, authTagHex, encrypted] = data.split(":");
|
|
@@ -204,8 +204,8 @@ var FileStorage = class {
|
|
|
204
204
|
return decrypted;
|
|
205
205
|
}
|
|
206
206
|
/**
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
* Read data from file
|
|
208
|
+
*/
|
|
209
209
|
async readFile() {
|
|
210
210
|
if (this.cache) return this.cache;
|
|
211
211
|
try {
|
|
@@ -225,8 +225,8 @@ var FileStorage = class {
|
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
/**
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
* Write data to file (coalesced to avoid race conditions)
|
|
229
|
+
*/
|
|
230
230
|
async writeFile(data) {
|
|
231
231
|
this.cache = data;
|
|
232
232
|
if (this.writePromise) {
|
|
@@ -361,8 +361,8 @@ var KeychainStorage = class {
|
|
|
361
361
|
this.serviceName = options.serviceName ?? SERVICE_NAME;
|
|
362
362
|
}
|
|
363
363
|
/**
|
|
364
|
-
|
|
365
|
-
|
|
364
|
+
* Initialize keytar (lazy load)
|
|
365
|
+
*/
|
|
366
366
|
async init() {
|
|
367
367
|
if (this.keytar) return;
|
|
368
368
|
if (this.initPromise) {
|
|
@@ -379,20 +379,20 @@ var KeychainStorage = class {
|
|
|
379
379
|
await this.initPromise;
|
|
380
380
|
}
|
|
381
381
|
/**
|
|
382
|
-
|
|
383
|
-
|
|
382
|
+
* Normalize server URL for consistent key lookup
|
|
383
|
+
*/
|
|
384
384
|
normalizeUrl(serverUrl) {
|
|
385
385
|
return serverUrl.replace(/\/+$/, "").toLowerCase();
|
|
386
386
|
}
|
|
387
387
|
/**
|
|
388
|
-
|
|
389
|
-
|
|
388
|
+
* Get account key for tokens
|
|
389
|
+
*/
|
|
390
390
|
getTokensAccount(serverUrl) {
|
|
391
391
|
return `tokens:${this.normalizeUrl(serverUrl)}`;
|
|
392
392
|
}
|
|
393
393
|
/**
|
|
394
|
-
|
|
395
|
-
|
|
394
|
+
* Get account key for client info
|
|
395
|
+
*/
|
|
396
396
|
getClientAccount(serverUrl) {
|
|
397
397
|
return `client:${this.normalizeUrl(serverUrl)}`;
|
|
398
398
|
}
|
package/dist/storage/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
MemoryStorage,
|
|
3
3
|
isTokenExpired,
|
|
4
4
|
withExpiresAt
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-MXTUNMHA.mjs";
|
|
6
6
|
import {
|
|
7
7
|
__name,
|
|
8
8
|
__require
|
|
@@ -36,8 +36,8 @@ var FileStorage = class {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
* Expand ~ to home directory
|
|
40
|
+
*/
|
|
41
41
|
expandPath(filePath) {
|
|
42
42
|
if (filePath.startsWith("~")) {
|
|
43
43
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
@@ -46,14 +46,14 @@ var FileStorage = class {
|
|
|
46
46
|
return filePath;
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
* Normalize server URL for consistent key lookup
|
|
50
|
+
*/
|
|
51
51
|
normalizeUrl(serverUrl) {
|
|
52
52
|
return serverUrl.replace(/\/+$/, "").toLowerCase();
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
* Encrypt data
|
|
56
|
+
*/
|
|
57
57
|
encrypt(data) {
|
|
58
58
|
if (!this.encryptionKey) return data;
|
|
59
59
|
const iv = randomBytes(16);
|
|
@@ -64,8 +64,8 @@ var FileStorage = class {
|
|
|
64
64
|
return `${iv.toString("hex")}:${authTag.toString("hex")}:${encrypted}`;
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
* Decrypt data
|
|
68
|
+
*/
|
|
69
69
|
decrypt(data) {
|
|
70
70
|
if (!this.encryptionKey) return data;
|
|
71
71
|
const [ivHex, authTagHex, encrypted] = data.split(":");
|
|
@@ -78,8 +78,8 @@ var FileStorage = class {
|
|
|
78
78
|
return decrypted;
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
* Read data from file
|
|
82
|
+
*/
|
|
83
83
|
async readFile() {
|
|
84
84
|
if (this.cache) return this.cache;
|
|
85
85
|
try {
|
|
@@ -99,8 +99,8 @@ var FileStorage = class {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
/**
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
* Write data to file (coalesced to avoid race conditions)
|
|
103
|
+
*/
|
|
104
104
|
async writeFile(data) {
|
|
105
105
|
this.cache = data;
|
|
106
106
|
if (this.writePromise) {
|
|
@@ -235,8 +235,8 @@ var KeychainStorage = class {
|
|
|
235
235
|
this.serviceName = options.serviceName ?? SERVICE_NAME;
|
|
236
236
|
}
|
|
237
237
|
/**
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
* Initialize keytar (lazy load)
|
|
239
|
+
*/
|
|
240
240
|
async init() {
|
|
241
241
|
if (this.keytar) return;
|
|
242
242
|
if (this.initPromise) {
|
|
@@ -253,20 +253,20 @@ var KeychainStorage = class {
|
|
|
253
253
|
await this.initPromise;
|
|
254
254
|
}
|
|
255
255
|
/**
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
* Normalize server URL for consistent key lookup
|
|
257
|
+
*/
|
|
258
258
|
normalizeUrl(serverUrl) {
|
|
259
259
|
return serverUrl.replace(/\/+$/, "").toLowerCase();
|
|
260
260
|
}
|
|
261
261
|
/**
|
|
262
|
-
|
|
263
|
-
|
|
262
|
+
* Get account key for tokens
|
|
263
|
+
*/
|
|
264
264
|
getTokensAccount(serverUrl) {
|
|
265
265
|
return `tokens:${this.normalizeUrl(serverUrl)}`;
|
|
266
266
|
}
|
|
267
267
|
/**
|
|
268
|
-
|
|
269
|
-
|
|
268
|
+
* Get account key for client info
|
|
269
|
+
*/
|
|
270
270
|
getClientAccount(serverUrl) {
|
|
271
271
|
return `client:${this.normalizeUrl(serverUrl)}`;
|
|
272
272
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Storage Types
|
|
3
|
+
*
|
|
4
|
+
* Defines interfaces for storing OAuth tokens across different backends
|
|
5
|
+
* (memory, file, keychain, browser localStorage, etc.)
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* OAuth 2.0/2.1 token response
|
|
9
|
+
*/
|
|
10
|
+
interface OAuthTokens {
|
|
11
|
+
/** The access token issued by the authorization server */
|
|
12
|
+
access_token: string;
|
|
13
|
+
/** Token type (usually "Bearer") */
|
|
14
|
+
token_type: string;
|
|
15
|
+
/** Lifetime in seconds of the access token */
|
|
16
|
+
expires_in?: number;
|
|
17
|
+
/** Refresh token for obtaining new access tokens */
|
|
18
|
+
refresh_token?: string;
|
|
19
|
+
/** ID token (OpenID Connect) */
|
|
20
|
+
id_token?: string;
|
|
21
|
+
/** Scope granted by the authorization server */
|
|
22
|
+
scope?: string;
|
|
23
|
+
/** Computed: Unix timestamp when token expires */
|
|
24
|
+
expires_at?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* OAuth client registration information
|
|
28
|
+
* Used for Dynamic Client Registration (RFC 7591)
|
|
29
|
+
*/
|
|
30
|
+
interface ClientRegistration {
|
|
31
|
+
/** OAuth client identifier */
|
|
32
|
+
client_id: string;
|
|
33
|
+
/** OAuth client secret (for confidential clients) */
|
|
34
|
+
client_secret?: string;
|
|
35
|
+
/** Unix timestamp when client secret expires */
|
|
36
|
+
client_secret_expires_at?: number;
|
|
37
|
+
/** Token for accessing registration endpoint */
|
|
38
|
+
registration_access_token?: string;
|
|
39
|
+
/** Client metadata from registration */
|
|
40
|
+
metadata?: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Stored session combining tokens and client info
|
|
44
|
+
*/
|
|
45
|
+
interface StoredSession {
|
|
46
|
+
/** Server URL this session is for */
|
|
47
|
+
serverUrl: string;
|
|
48
|
+
/** OAuth tokens */
|
|
49
|
+
tokens: OAuthTokens;
|
|
50
|
+
/** Client registration info (if dynamic registration used) */
|
|
51
|
+
clientInfo?: ClientRegistration;
|
|
52
|
+
/** Unix timestamp when session was created */
|
|
53
|
+
createdAt: number;
|
|
54
|
+
/** Unix timestamp when session was last updated */
|
|
55
|
+
updatedAt: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Token storage interface
|
|
59
|
+
*
|
|
60
|
+
* Implement this interface to create custom storage backends.
|
|
61
|
+
* All operations should be async to support various backends.
|
|
62
|
+
*/
|
|
63
|
+
interface TokenStorage {
|
|
64
|
+
/**
|
|
65
|
+
* Get stored tokens for a server
|
|
66
|
+
* @param serverUrl - The MCP server URL
|
|
67
|
+
* @returns Tokens if found, null otherwise
|
|
68
|
+
*/
|
|
69
|
+
getTokens(serverUrl: string): Promise<OAuthTokens | null>;
|
|
70
|
+
/**
|
|
71
|
+
* Store tokens for a server
|
|
72
|
+
* @param serverUrl - The MCP server URL
|
|
73
|
+
* @param tokens - OAuth tokens to store
|
|
74
|
+
*/
|
|
75
|
+
setTokens(serverUrl: string, tokens: OAuthTokens): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Clear tokens for a server
|
|
78
|
+
* @param serverUrl - The MCP server URL
|
|
79
|
+
*/
|
|
80
|
+
clearTokens(serverUrl: string): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Get stored client registration for a server
|
|
83
|
+
* @param serverUrl - The MCP server URL
|
|
84
|
+
* @returns Client info if found, null otherwise
|
|
85
|
+
*/
|
|
86
|
+
getClientInfo(serverUrl: string): Promise<ClientRegistration | null>;
|
|
87
|
+
/**
|
|
88
|
+
* Store client registration for a server
|
|
89
|
+
* @param serverUrl - The MCP server URL
|
|
90
|
+
* @param info - Client registration info
|
|
91
|
+
*/
|
|
92
|
+
setClientInfo(serverUrl: string, info: ClientRegistration): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Clear client registration for a server
|
|
95
|
+
* @param serverUrl - The MCP server URL
|
|
96
|
+
*/
|
|
97
|
+
clearClientInfo(serverUrl: string): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Clear all stored data
|
|
100
|
+
*/
|
|
101
|
+
clearAll(): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Get all stored sessions (optional)
|
|
104
|
+
* @returns Array of stored sessions
|
|
105
|
+
*/
|
|
106
|
+
getAllSessions?(): Promise<StoredSession[]>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if tokens are expired or about to expire
|
|
110
|
+
* @param tokens - OAuth tokens to check
|
|
111
|
+
* @param bufferSeconds - Seconds before expiry to consider expired (default: 60)
|
|
112
|
+
* @returns True if tokens are expired or will expire within buffer
|
|
113
|
+
*/
|
|
114
|
+
declare function isTokenExpired(tokens: OAuthTokens, bufferSeconds?: number): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Compute expires_at from expires_in if not present
|
|
117
|
+
* @param tokens - OAuth tokens to enhance
|
|
118
|
+
* @returns Tokens with expires_at computed
|
|
119
|
+
*/
|
|
120
|
+
declare function withExpiresAt(tokens: OAuthTokens): OAuthTokens;
|
|
121
|
+
|
|
122
|
+
export { type ClientRegistration as C, type OAuthTokens as O, type StoredSession as S, type TokenStorage as T, isTokenExpired as i, withExpiresAt as w };
|