@assistant-ui/react-mcp 0.1.16 → 0.1.18
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/dist/auth/createOAuthProvider.d.ts +13 -2
- package/dist/auth/createOAuthProvider.d.ts.map +1 -1
- package/dist/auth/createOAuthProvider.js +109 -31
- package/dist/auth/createOAuthProvider.js.map +1 -1
- package/dist/auth/types.d.ts +5 -1
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormAuthFields.js +71 -28
- package/dist/primitives/addForm/McpAddFormAuthFields.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormError.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormError.js +30 -10
- package/dist/primitives/addForm/McpAddFormError.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormNameField.js +31 -18
- package/dist/primitives/addForm/McpAddFormNameField.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormRoot.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormRoot.js +32 -11
- package/dist/primitives/addForm/McpAddFormRoot.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormUrlField.js +31 -18
- package/dist/primitives/addForm/McpAddFormUrlField.js.map +1 -1
- package/dist/primitives/addForm/context.d.ts +9 -1
- package/dist/primitives/addForm/context.d.ts.map +1 -1
- package/dist/primitives/addForm/context.js.map +1 -1
- package/dist/resources/McpManagerResource.d.ts.map +1 -1
- package/dist/resources/McpManagerResource.js +330 -247
- package/dist/resources/McpManagerResource.js.map +1 -1
- package/dist/resources/McpServerRemovalFence.d.ts +7 -0
- package/dist/resources/McpServerRemovalFence.d.ts.map +1 -0
- package/dist/resources/McpServerRemovalFence.js +11 -0
- package/dist/resources/McpServerRemovalFence.js.map +1 -0
- package/dist/resources/McpServerResource.d.ts.map +1 -1
- package/dist/resources/McpServerResource.js +41 -16
- package/dist/resources/McpServerResource.js.map +1 -1
- package/dist/resources/storage/McpLocalStorage.d.ts.map +1 -1
- package/dist/resources/storage/McpLocalStorage.js +16 -1
- package/dist/resources/storage/McpLocalStorage.js.map +1 -1
- package/dist/resources/storage/types.d.ts +10 -8
- package/dist/resources/storage/types.d.ts.map +1 -1
- package/dist/utils/serverUrl.d.ts +8 -0
- package/dist/utils/serverUrl.d.ts.map +1 -0
- package/dist/utils/serverUrl.js +15 -0
- package/dist/utils/serverUrl.js.map +1 -0
- package/package.json +7 -7
- package/src/auth/createOAuthProvider.test.ts +544 -35
- package/src/auth/createOAuthProvider.ts +201 -46
- package/src/auth/types.ts +5 -1
- package/src/primitives/addForm/McpAddFormAccessibility.test.tsx +261 -0
- package/src/primitives/addForm/McpAddFormAuthFields.tsx +33 -15
- package/src/primitives/addForm/McpAddFormError.tsx +17 -3
- package/src/primitives/addForm/McpAddFormNameField.tsx +13 -1
- package/src/primitives/addForm/McpAddFormRoot.tsx +51 -8
- package/src/primitives/addForm/McpAddFormUrlField.tsx +12 -1
- package/src/primitives/addForm/context.tsx +10 -0
- package/src/resources/McpManagerResource.test.ts +712 -9
- package/src/resources/McpManagerResource.ts +208 -56
- package/src/resources/McpServerRemovalFence.ts +21 -0
- package/src/resources/McpServerResource.test.ts +252 -17
- package/src/resources/McpServerResource.ts +40 -15
- package/src/resources/storage/McpLocalStorage.test.ts +28 -0
- package/src/resources/storage/McpLocalStorage.ts +23 -1
- package/src/resources/storage/types.ts +10 -8
- package/src/utils/serverUrl.test.ts +66 -0
- package/src/utils/serverUrl.ts +23 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { MCPAuthConfig } from "../mcp-scope.js";
|
|
2
2
|
import { MCPStorage } from "../resources/storage/types.js";
|
|
3
|
-
import { OAuthClientProvider } from "@modelcontextprotocol/client";
|
|
3
|
+
import { OAuthClientInformationFull, OAuthClientProvider, OAuthTokens } from "@modelcontextprotocol/client";
|
|
4
4
|
//#region src/auth/createOAuthProvider.d.ts
|
|
5
5
|
declare function decodeServerIdFromState(state: string): string | null;
|
|
6
6
|
type CreateOAuthProviderOptions = {
|
|
7
7
|
serverId: string;
|
|
8
|
+
serverUrl: string;
|
|
8
9
|
/** Must be `auth.type === "oauth"`. */
|
|
9
10
|
config: Extract<MCPAuthConfig, {
|
|
10
11
|
type: "oauth";
|
|
@@ -14,6 +15,16 @@ type CreateOAuthProviderOptions = {
|
|
|
14
15
|
/** Called by the SDK to start the authorization redirect. */
|
|
15
16
|
onAuthorizationUrl: (url: URL) => void;
|
|
16
17
|
};
|
|
18
|
+
type OAuthConfig = Extract<MCPAuthConfig, {
|
|
19
|
+
type: "oauth";
|
|
20
|
+
}>;
|
|
21
|
+
type OAuthCredentialState = {
|
|
22
|
+
tokens?: OAuthTokens | undefined;
|
|
23
|
+
tokensClientId?: string | undefined;
|
|
24
|
+
clientInformation?: OAuthClientInformationFull | undefined;
|
|
25
|
+
clientInformationSource?: "registered" | undefined;
|
|
26
|
+
};
|
|
27
|
+
declare const hasUsableOAuthTokens: (state: OAuthCredentialState | null | undefined, config: OAuthConfig) => boolean;
|
|
17
28
|
/**
|
|
18
29
|
* Clears persisted OAuth state after the in-flight load and every queued write
|
|
19
30
|
* for that server have settled, so a discarded provider cannot recreate the
|
|
@@ -27,5 +38,5 @@ declare const clearOAuthProviderAuthState: (storage: MCPStorage, serverId: strin
|
|
|
27
38
|
*/
|
|
28
39
|
declare function createOAuthProvider(opts: CreateOAuthProviderOptions): OAuthClientProvider;
|
|
29
40
|
//#endregion
|
|
30
|
-
export { CreateOAuthProviderOptions, clearOAuthProviderAuthState, createOAuthProvider, decodeServerIdFromState };
|
|
41
|
+
export { CreateOAuthProviderOptions, clearOAuthProviderAuthState, createOAuthProvider, decodeServerIdFromState, hasUsableOAuthTokens };
|
|
31
42
|
//# sourceMappingURL=createOAuthProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createOAuthProvider.d.ts","names":[],"sources":["../../src/auth/createOAuthProvider.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"createOAuthProvider.d.ts","names":[],"sources":["../../src/auth/createOAuthProvider.ts"],"mappings":";;;;iBAsCgB,wBAAwB;KAgB5B;EACV;EACA;;EAEA,QAAQ,QAAQ;IAAiB;;EACjC,SAAS;EACT;;EAEA,qBAAqB,KAAK;;KAcvB,cAAc,QAAQ;EAAiB;;KAEvC;EACH,SAAS;EACT;EACA,oBAAoB;EACpB;;cAUW,uBACX,OAAO,yCACP,QAAQ;;;;;;cAkHG,8BACX,SAAS,YACT,qBACC;;;;;;iBA2Ba,oBACd,MAAM,6BACL"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isAuthStateForServerUrl, normalizeMcpServerUrl } from "../utils/serverUrl.js";
|
|
1
2
|
//#region src/auth/createOAuthProvider.ts
|
|
2
3
|
const STATE_PREFIX = "aui-mcp:";
|
|
3
4
|
function bytesToBase64Url(bytes) {
|
|
@@ -26,6 +27,15 @@ function decodeServerIdFromState(state) {
|
|
|
26
27
|
return null;
|
|
27
28
|
}
|
|
28
29
|
}
|
|
30
|
+
const registeredClientId = (state) => state?.clientInformationSource === "registered" ? state.clientInformation?.client_id : void 0;
|
|
31
|
+
const hasUsableOAuthTokens = (state, config) => {
|
|
32
|
+
const clientId = config.clientId ?? registeredClientId(state);
|
|
33
|
+
return clientId !== void 0 && state?.tokens !== void 0 && state.tokensClientId === clientId;
|
|
34
|
+
};
|
|
35
|
+
const hasUsableRegisteredClientInformation = (state, config) => {
|
|
36
|
+
const clientId = registeredClientId(state);
|
|
37
|
+
return clientId !== void 0 && (config.clientId === void 0 || config.clientId === clientId);
|
|
38
|
+
};
|
|
29
39
|
const anchorByStorage = /* @__PURE__ */ new WeakMap();
|
|
30
40
|
const anchorByScope = /* @__PURE__ */ new Map();
|
|
31
41
|
const anchorRegistry = new FinalizationRegistry((scopeId) => {
|
|
@@ -46,7 +56,7 @@ const getStorageIdentity = (storage) => {
|
|
|
46
56
|
return anchor;
|
|
47
57
|
};
|
|
48
58
|
const persistenceByIdentity = /* @__PURE__ */ new WeakMap();
|
|
49
|
-
const getPersistence = (storage, serverId) => {
|
|
59
|
+
const getPersistence = (storage, serverId, serverUrl) => {
|
|
50
60
|
const identity = getStorageIdentity(storage);
|
|
51
61
|
let byServerId = persistenceByIdentity.get(identity);
|
|
52
62
|
if (!byServerId) {
|
|
@@ -56,14 +66,27 @@ const getPersistence = (storage, serverId) => {
|
|
|
56
66
|
let persistence = byServerId.get(serverId);
|
|
57
67
|
if (!persistence) {
|
|
58
68
|
persistence = {
|
|
59
|
-
|
|
60
|
-
cachePromise: null,
|
|
69
|
+
endpoint: null,
|
|
61
70
|
queue: Promise.resolve(),
|
|
62
71
|
invalidated: false
|
|
63
72
|
};
|
|
64
73
|
byServerId.set(serverId, persistence);
|
|
65
74
|
}
|
|
66
|
-
|
|
75
|
+
let endpoint = persistence.endpoint;
|
|
76
|
+
if (endpoint?.serverUrl !== serverUrl) {
|
|
77
|
+
if (endpoint) endpoint.invalidated = true;
|
|
78
|
+
endpoint = {
|
|
79
|
+
serverUrl,
|
|
80
|
+
cached: null,
|
|
81
|
+
cachePromise: null,
|
|
82
|
+
invalidated: false
|
|
83
|
+
};
|
|
84
|
+
persistence.endpoint = endpoint;
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
persistence,
|
|
88
|
+
endpoint
|
|
89
|
+
};
|
|
67
90
|
};
|
|
68
91
|
/**
|
|
69
92
|
* Clears persisted OAuth state after the in-flight load and every queued write
|
|
@@ -81,7 +104,10 @@ const clearOAuthProviderAuthState = async (storage, serverId) => {
|
|
|
81
104
|
persistence.invalidated = true;
|
|
82
105
|
byServerId.delete(serverId);
|
|
83
106
|
if (byServerId.size === 0) persistenceByIdentity.delete(identity);
|
|
84
|
-
|
|
107
|
+
if (persistence.endpoint) persistence.endpoint.invalidated = true;
|
|
108
|
+
const cachePromise = persistence.endpoint?.cachePromise;
|
|
109
|
+
if (cachePromise) await Promise.allSettled([cachePromise]);
|
|
110
|
+
await persistence.queue;
|
|
85
111
|
await storage.clearAuthState(serverId);
|
|
86
112
|
};
|
|
87
113
|
/**
|
|
@@ -90,10 +116,11 @@ const clearOAuthProviderAuthState = async (storage, serverId) => {
|
|
|
90
116
|
* load/save and the redirect step.
|
|
91
117
|
*/
|
|
92
118
|
function createOAuthProvider(opts) {
|
|
93
|
-
const { serverId, config, storage, redirectUri, onAuthorizationUrl } = opts;
|
|
94
|
-
const
|
|
119
|
+
const { serverId, serverUrl, config, storage, redirectUri, onAuthorizationUrl } = opts;
|
|
120
|
+
const normalizedServerUrl = normalizeMcpServerUrl(serverUrl);
|
|
121
|
+
const { persistence, endpoint } = getPersistence(storage, serverId, normalizedServerUrl);
|
|
95
122
|
let pendingState;
|
|
96
|
-
const
|
|
123
|
+
const configuredClientInformation = () => {
|
|
97
124
|
if (!config.clientId) return void 0;
|
|
98
125
|
const ci = {
|
|
99
126
|
client_id: config.clientId,
|
|
@@ -101,41 +128,64 @@ function createOAuthProvider(opts) {
|
|
|
101
128
|
};
|
|
102
129
|
if (config.clientSecret) ci.client_secret = config.clientSecret;
|
|
103
130
|
return ci;
|
|
104
|
-
}
|
|
131
|
+
};
|
|
132
|
+
let clientInformationOverlay = configuredClientInformation();
|
|
133
|
+
const activeClientId = (cache) => clientInformationOverlay?.client_id ?? registeredClientId(cache);
|
|
105
134
|
const loadCache = () => {
|
|
106
|
-
if (
|
|
107
|
-
if (
|
|
108
|
-
|
|
135
|
+
if (endpoint.invalidated) return Promise.resolve({});
|
|
136
|
+
if (endpoint.cached) return Promise.resolve(endpoint.cached);
|
|
137
|
+
if (endpoint.cachePromise) return endpoint.cachePromise;
|
|
138
|
+
endpoint.cachePromise = persistence.queue.then(() => storage.loadAuthState(serverId)).then(async (persisted) => {
|
|
109
139
|
const initial = {};
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
if (persisted
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
140
|
+
let needsMigration = false;
|
|
141
|
+
if (endpoint.invalidated) return initial;
|
|
142
|
+
if (persisted && isAuthStateForServerUrl(persisted, normalizedServerUrl)) {
|
|
143
|
+
if (hasUsableRegisteredClientInformation(persisted, config) && persisted.clientInformation) {
|
|
144
|
+
initial.clientInformation = persisted.clientInformation;
|
|
145
|
+
initial.clientInformationSource = "registered";
|
|
146
|
+
} else if (persisted?.clientInformation || persisted?.clientInformationSource !== void 0) needsMigration = true;
|
|
147
|
+
if (hasUsableOAuthTokens(persisted, config)) {
|
|
148
|
+
initial.tokens = persisted.tokens;
|
|
149
|
+
initial.tokensClientId = persisted.tokensClientId;
|
|
150
|
+
} else if (persisted?.tokens || persisted?.tokensClientId !== void 0) needsMigration = true;
|
|
151
|
+
if (persisted?.token) initial.token = persisted.token;
|
|
152
|
+
if (persisted?.codeVerifier) initial.codeVerifier = persisted.codeVerifier;
|
|
153
|
+
if (persisted?.state) initial.state = persisted.state;
|
|
154
|
+
if (persisted?.discoveryState) initial.discoveryState = persisted.discoveryState;
|
|
155
|
+
}
|
|
156
|
+
endpoint.cached = initial;
|
|
157
|
+
if (needsMigration) await persist().catch(() => {});
|
|
116
158
|
return initial;
|
|
117
159
|
}, (error) => {
|
|
118
|
-
|
|
160
|
+
endpoint.cachePromise = null;
|
|
119
161
|
throw error;
|
|
120
162
|
});
|
|
121
|
-
return
|
|
163
|
+
return endpoint.cachePromise;
|
|
122
164
|
};
|
|
123
|
-
|
|
165
|
+
function persist() {
|
|
124
166
|
const task = persistence.queue.then(async () => {
|
|
125
|
-
if (persistence.invalidated) return;
|
|
126
|
-
const c =
|
|
167
|
+
if (persistence.invalidated || endpoint.invalidated) return;
|
|
168
|
+
const c = endpoint.cached;
|
|
127
169
|
if (!c) return;
|
|
128
170
|
const next = {};
|
|
129
|
-
if (c
|
|
130
|
-
|
|
171
|
+
if (hasUsableOAuthTokens(c, config) && c.tokens && c.tokensClientId) {
|
|
172
|
+
next.tokens = c.tokens;
|
|
173
|
+
next.tokensClientId = c.tokensClientId;
|
|
174
|
+
}
|
|
175
|
+
if (c.clientInformation && c.clientInformationSource === "registered") {
|
|
176
|
+
next.clientInformation = c.clientInformation;
|
|
177
|
+
next.clientInformationSource = "registered";
|
|
178
|
+
}
|
|
179
|
+
if (c.token) next.token = c.token;
|
|
131
180
|
if (c.codeVerifier) next.codeVerifier = c.codeVerifier;
|
|
132
181
|
if (c.state) next.state = c.state;
|
|
133
182
|
if (c.discoveryState) next.discoveryState = c.discoveryState;
|
|
183
|
+
next.serverUrl = normalizedServerUrl;
|
|
134
184
|
await storage.saveAuthState(serverId, next);
|
|
135
185
|
});
|
|
136
186
|
persistence.queue = task.catch(() => {});
|
|
137
187
|
return task;
|
|
138
|
-
}
|
|
188
|
+
}
|
|
139
189
|
const clientMetadata = {
|
|
140
190
|
client_name: "assistant-ui",
|
|
141
191
|
redirect_uris: [redirectUri],
|
|
@@ -158,19 +208,36 @@ function createOAuthProvider(opts) {
|
|
|
158
208
|
},
|
|
159
209
|
async clientInformation() {
|
|
160
210
|
const c = await loadCache();
|
|
161
|
-
|
|
211
|
+
if (clientInformationOverlay) return clientInformationOverlay;
|
|
212
|
+
if (c.clientInformationSource !== "registered") return void 0;
|
|
213
|
+
return c.clientInformation;
|
|
162
214
|
},
|
|
163
215
|
async saveClientInformation(info) {
|
|
216
|
+
if (clientInformationOverlay) {
|
|
217
|
+
clientInformationOverlay = info;
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
164
220
|
const c = await loadCache();
|
|
165
221
|
c.clientInformation = info;
|
|
222
|
+
c.clientInformationSource = "registered";
|
|
223
|
+
if (c.tokensClientId !== c.clientInformation.client_id) {
|
|
224
|
+
delete c.tokens;
|
|
225
|
+
delete c.tokensClientId;
|
|
226
|
+
}
|
|
166
227
|
await persist();
|
|
167
228
|
},
|
|
168
229
|
async tokens() {
|
|
169
|
-
|
|
230
|
+
const c = await loadCache();
|
|
231
|
+
const clientId = activeClientId(c);
|
|
232
|
+
if (clientId === void 0 || c.tokensClientId !== clientId) return void 0;
|
|
233
|
+
return c.tokens;
|
|
170
234
|
},
|
|
171
235
|
async saveTokens(tokens) {
|
|
172
236
|
const c = await loadCache();
|
|
173
237
|
c.tokens = tokens;
|
|
238
|
+
const clientId = activeClientId(c);
|
|
239
|
+
if (clientId) c.tokensClientId = clientId;
|
|
240
|
+
else delete c.tokensClientId;
|
|
174
241
|
delete c.state;
|
|
175
242
|
await persist();
|
|
176
243
|
},
|
|
@@ -201,8 +268,19 @@ function createOAuthProvider(opts) {
|
|
|
201
268
|
},
|
|
202
269
|
async invalidateCredentials(scope) {
|
|
203
270
|
const c = await loadCache();
|
|
204
|
-
if (scope === "all" || scope === "tokens")
|
|
205
|
-
|
|
271
|
+
if (scope === "all" || scope === "tokens") {
|
|
272
|
+
delete c.tokens;
|
|
273
|
+
delete c.tokensClientId;
|
|
274
|
+
}
|
|
275
|
+
if (scope === "all" || scope === "client") {
|
|
276
|
+
delete c.clientInformation;
|
|
277
|
+
delete c.clientInformationSource;
|
|
278
|
+
if (!config.clientId) {
|
|
279
|
+
delete c.tokens;
|
|
280
|
+
delete c.tokensClientId;
|
|
281
|
+
}
|
|
282
|
+
clientInformationOverlay = configuredClientInformation();
|
|
283
|
+
}
|
|
206
284
|
if (scope === "all" || scope === "verifier") {
|
|
207
285
|
delete c.codeVerifier;
|
|
208
286
|
delete c.state;
|
|
@@ -213,6 +291,6 @@ function createOAuthProvider(opts) {
|
|
|
213
291
|
};
|
|
214
292
|
}
|
|
215
293
|
//#endregion
|
|
216
|
-
export { clearOAuthProviderAuthState, createOAuthProvider, decodeServerIdFromState };
|
|
294
|
+
export { clearOAuthProviderAuthState, createOAuthProvider, decodeServerIdFromState, hasUsableOAuthTokens };
|
|
217
295
|
|
|
218
296
|
//# sourceMappingURL=createOAuthProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createOAuthProvider.js","names":["OAuthClientProvider","OAuthClientInformationFull","OAuthClientMetadata","OAuthDiscoveryState","OAuthTokens","MCPStorage","MCPAuthConfig","STATE_PREFIX","bytesToBase64Url","bytes","Uint8Array","s","b","String","fromCharCode","btoa","replace","base64UrlToBytes","b64url","padded","repeat","length","bin","atob","out","i","charCodeAt","encodeServerIdInState","serverId","TextEncoder","encode","decodeServerIdFromState","state","startsWith","dot","indexOf","encoded","slice","TextDecoder","fatal","decode","CreateOAuthProviderOptions","config","Extract","type","storage","redirectUri","onAuthorizationUrl","url","URL","OAuthProviderCache","tokens","clientInformation","codeVerifier","discoveryState","OAuthProviderPersistence","cached","cachePromise","Promise","queue","invalidated","anchorByStorage","WeakMap","anchorByScope","Map","WeakRef","anchorRegistry","FinalizationRegistry","scopeId","get","deref","delete","getStorageIdentity","existing","undefined","anchor","set","register","persistenceByIdentity","getPersistence","identity","byServerId","persistence","resolve","clearOAuthProviderAuthState","clearAuthState","size","allSettled","createOAuthProvider","opts","pendingState","staticClientInformation","clientId","ci","client_id","redirect_uris","clientSecret","client_secret","loadCache","loadAuthState","then","persisted","initial","error","persist","task","c","next","Parameters","saveAuthState","catch","clientMetadata","client_name","grant_types","response_types","token_endpoint_auth_method","scope","scopes","join","redirectUrl","nonce","crypto","randomUUID","Date","now","Math","random","saveClientInformation","info","saveTokens","redirectToAuthorization","saveCodeVerifier","Error","saveDiscoveryState","invalidateCredentials"],"sources":["../../src/auth/createOAuthProvider.ts"],"sourcesContent":["import type {\n OAuthClientProvider,\n OAuthClientInformationFull,\n OAuthClientMetadata,\n OAuthDiscoveryState,\n OAuthTokens,\n} from \"@modelcontextprotocol/client\";\nimport type { MCPStorage } from \"../resources/storage/types\";\nimport type { MCPAuthConfig } from \"../mcp-scope\";\n\nconst STATE_PREFIX = \"aui-mcp:\";\n\nfunction bytesToBase64Url(bytes: Uint8Array): string {\n let s = \"\";\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction base64UrlToBytes(b64url: string): Uint8Array {\n const padded =\n b64url.replace(/-/g, \"+\").replace(/_/g, \"/\") +\n \"=\".repeat((4 - (b64url.length % 4)) % 4);\n const bin = atob(padded);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nfunction encodeServerIdInState(serverId: string): string {\n const bytes = new TextEncoder().encode(serverId);\n return `${STATE_PREFIX}${bytesToBase64Url(bytes)}`;\n}\n\nexport function decodeServerIdFromState(state: string): string | null {\n if (!state.startsWith(STATE_PREFIX)) return null;\n const dot = state.indexOf(\".\", STATE_PREFIX.length);\n const encoded =\n dot === -1\n ? state.slice(STATE_PREFIX.length)\n : state.slice(STATE_PREFIX.length, dot);\n try {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(\n base64UrlToBytes(encoded),\n );\n } catch {\n return null;\n }\n}\n\nexport type CreateOAuthProviderOptions = {\n serverId: string;\n /** Must be `auth.type === \"oauth\"`. */\n config: Extract<MCPAuthConfig, { type: \"oauth\" }>;\n storage: MCPStorage;\n redirectUri: string;\n /** Called by the SDK to start the authorization redirect. */\n onAuthorizationUrl: (url: URL) => void;\n};\n\ntype OAuthProviderCache = {\n tokens?: OAuthTokens | undefined;\n clientInformation?: OAuthClientInformationFull | undefined;\n codeVerifier?: string | undefined;\n state?: string | undefined;\n discoveryState?: OAuthDiscoveryState | undefined;\n};\n\ntype OAuthProviderPersistence = {\n cached: OAuthProviderCache | null;\n cachePromise: Promise<OAuthProviderCache> | null;\n queue: Promise<void>;\n invalidated: boolean;\n};\n\n// scopeId, not object identity, is what addresses the same persisted data, so\n// storages sharing one share an anchor and an unscoped storage is its own\n// identity. Every storage declaring a scope holds that scope's anchor, so the\n// coordination state below is collected once the last of them is gone.\nconst anchorByStorage = new WeakMap<MCPStorage, object>();\nconst anchorByScope = new Map<string, WeakRef<object>>();\nconst anchorRegistry = new FinalizationRegistry<string>((scopeId) => {\n if (!anchorByScope.get(scopeId)?.deref()) anchorByScope.delete(scopeId);\n});\n\nconst getStorageIdentity = (storage: MCPStorage): object => {\n const existing = anchorByStorage.get(storage);\n if (existing) return existing;\n\n const { scopeId } = storage;\n if (scopeId === undefined) return storage;\n\n let anchor = anchorByScope.get(scopeId)?.deref();\n if (!anchor) {\n anchor = {};\n anchorByScope.set(scopeId, new WeakRef(anchor));\n anchorRegistry.register(anchor, scopeId);\n }\n anchorByStorage.set(storage, anchor);\n return anchor;\n};\n\n// McpServerResource builds a fresh provider for every transport, so the cache,\n// the in-flight load, and the write queue have to outlive any one provider.\n// saveAuthState replaces the whole record, so two providers writing their own\n// snapshots concurrently would drop whichever field the loser had added.\nconst persistenceByIdentity = new WeakMap<\n object,\n Map<string, OAuthProviderPersistence>\n>();\n\nconst getPersistence = (\n storage: MCPStorage,\n serverId: string,\n): OAuthProviderPersistence => {\n const identity = getStorageIdentity(storage);\n let byServerId = persistenceByIdentity.get(identity);\n if (!byServerId) {\n byServerId = new Map();\n persistenceByIdentity.set(identity, byServerId);\n }\n\n let persistence = byServerId.get(serverId);\n if (!persistence) {\n persistence = {\n cached: null,\n cachePromise: null,\n queue: Promise.resolve(),\n invalidated: false,\n };\n byServerId.set(serverId, persistence);\n }\n return persistence;\n};\n\n/**\n * Clears persisted OAuth state after the in-flight load and every queued write\n * for that server have settled, so a discarded provider cannot recreate the\n * record it was mid-save on.\n */\nexport const clearOAuthProviderAuthState = async (\n storage: MCPStorage,\n serverId: string,\n): Promise<void> => {\n const identity = getStorageIdentity(storage);\n const byServerId = persistenceByIdentity.get(identity);\n const persistence = byServerId?.get(serverId);\n if (!byServerId || !persistence) {\n await storage.clearAuthState(serverId);\n return;\n }\n\n // Detaching the entry before awaiting keeps a provider built during the clear\n // on a fresh generation instead of inheriting the fenced one.\n persistence.invalidated = true;\n byServerId.delete(serverId);\n if (byServerId.size === 0) persistenceByIdentity.delete(identity);\n\n await Promise.allSettled([persistence.cachePromise, persistence.queue]);\n await storage.clearAuthState(serverId);\n};\n\n/**\n * Builds an OAuthClientProvider for the MCP SDK, backed by MCPStorage.\n * Token refresh and DCR are handled by the SDK; this provider only mediates\n * load/save and the redirect step.\n */\nexport function createOAuthProvider(\n opts: CreateOAuthProviderOptions,\n): OAuthClientProvider {\n const { serverId, config, storage, redirectUri, onAuthorizationUrl } = opts;\n const persistence = getPersistence(storage, serverId);\n let pendingState: string | undefined;\n\n // The cache is shared with every other provider for this (storage, serverId),\n // so a statically configured client stays a read-time overlay owned by this\n // provider. Writing it into the cache would leak this provider's registration\n // to a replacement built for a different, or absent, clientId.\n const staticClientInformation = (():\n | OAuthClientInformationFull\n | undefined => {\n if (!config.clientId) return undefined;\n const ci: OAuthClientInformationFull = {\n client_id: config.clientId,\n redirect_uris: [redirectUri],\n };\n if (config.clientSecret) ci.client_secret = config.clientSecret;\n return ci;\n })();\n\n const loadCache = (): Promise<OAuthProviderCache> => {\n if (persistence.cached) return Promise.resolve(persistence.cached);\n if (persistence.cachePromise) return persistence.cachePromise;\n\n persistence.cachePromise = storage.loadAuthState(serverId).then(\n (persisted) => {\n const initial: OAuthProviderCache = {};\n if (persisted?.tokens) initial.tokens = persisted.tokens;\n if (persisted?.clientInformation)\n initial.clientInformation = persisted.clientInformation;\n if (persisted?.codeVerifier)\n initial.codeVerifier = persisted.codeVerifier;\n if (persisted?.state) initial.state = persisted.state;\n if (persisted?.discoveryState)\n initial.discoveryState = persisted.discoveryState;\n persistence.cached = initial;\n return initial;\n },\n (error) => {\n persistence.cachePromise = null;\n throw error;\n },\n );\n return persistence.cachePromise;\n };\n\n const persist = () => {\n const task = persistence.queue.then(async () => {\n if (persistence.invalidated) return;\n const c = persistence.cached;\n if (!c) return;\n const next: Parameters<typeof storage.saveAuthState>[1] = {};\n if (c.tokens) next.tokens = c.tokens;\n if (c.clientInformation) next.clientInformation = c.clientInformation;\n if (c.codeVerifier) next.codeVerifier = c.codeVerifier;\n if (c.state) next.state = c.state;\n if (c.discoveryState) next.discoveryState = c.discoveryState;\n await storage.saveAuthState(serverId, next);\n });\n persistence.queue = task.catch(() => {});\n return task;\n };\n\n const clientMetadata: OAuthClientMetadata = {\n client_name: \"assistant-ui\",\n redirect_uris: [redirectUri],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n scope: config.scopes?.join(\" \"),\n };\n\n return {\n get redirectUrl() {\n return redirectUri;\n },\n get clientMetadata() {\n return clientMetadata;\n },\n state() {\n // Embed the server id so the callback handler can route it back to the\n // right MCPServerResource without app-level wiring.\n const nonce =\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}.${Math.random()}`;\n pendingState = `${encodeServerIdInState(serverId)}.${nonce}`;\n return pendingState;\n },\n async clientInformation() {\n const c = await loadCache();\n return staticClientInformation ?? c.clientInformation;\n },\n async saveClientInformation(info) {\n const c = await loadCache();\n c.clientInformation = info as OAuthClientInformationFull;\n await persist();\n },\n async tokens() {\n const c = await loadCache();\n return c.tokens;\n },\n async saveTokens(tokens) {\n const c = await loadCache();\n c.tokens = tokens;\n delete c.state;\n await persist();\n },\n async redirectToAuthorization(url) {\n onAuthorizationUrl(url);\n },\n async saveCodeVerifier(codeVerifier) {\n const c = await loadCache();\n c.codeVerifier = codeVerifier;\n if (pendingState) {\n c.state = pendingState;\n pendingState = undefined;\n }\n await persist();\n },\n async codeVerifier() {\n const c = await loadCache();\n if (!c.codeVerifier) {\n throw new Error(\"No code verifier saved for this OAuth flow\");\n }\n return c.codeVerifier;\n },\n async saveDiscoveryState(discoveryState) {\n const c = await loadCache();\n c.discoveryState = discoveryState;\n await persist();\n },\n async discoveryState() {\n const c = await loadCache();\n return c.discoveryState;\n },\n async invalidateCredentials(scope) {\n const c = await loadCache();\n if (scope === \"all\" || scope === \"tokens\") delete c.tokens;\n if (scope === \"all\" || scope === \"client\") delete c.clientInformation;\n if (scope === \"all\" || scope === \"verifier\") {\n delete c.codeVerifier;\n delete c.state;\n }\n if (scope === \"all\" || scope === \"discovery\") delete c.discoveryState;\n await persist();\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createOAuthProvider.js","names":["OAuthClientProvider","OAuthClientInformationFull","OAuthClientMetadata","OAuthDiscoveryState","OAuthTokens","MCPStorage","MCPAuthConfig","MCPPersistedAuthState","isAuthStateForServerUrl","normalizeMcpServerUrl","STATE_PREFIX","bytesToBase64Url","bytes","Uint8Array","s","b","String","fromCharCode","btoa","replace","base64UrlToBytes","b64url","padded","repeat","length","bin","atob","out","i","charCodeAt","encodeServerIdInState","serverId","TextEncoder","encode","decodeServerIdFromState","state","startsWith","dot","indexOf","encoded","slice","TextDecoder","fatal","decode","CreateOAuthProviderOptions","serverUrl","config","Extract","type","storage","redirectUri","onAuthorizationUrl","url","URL","OAuthProviderCache","token","tokens","tokensClientId","clientInformation","clientInformationSource","codeVerifier","discoveryState","OAuthConfig","OAuthCredentialState","registeredClientId","client_id","undefined","hasUsableOAuthTokens","clientId","hasUsableRegisteredClientInformation","OAuthProviderEndpointCache","cached","cachePromise","Promise","invalidated","OAuthProviderPersistence","endpoint","queue","anchorByStorage","WeakMap","anchorByScope","Map","WeakRef","anchorRegistry","FinalizationRegistry","scopeId","get","deref","delete","getStorageIdentity","existing","anchor","set","register","persistenceByIdentity","getPersistence","persistence","identity","byServerId","resolve","clearOAuthProviderAuthState","clearAuthState","size","allSettled","createOAuthProvider","opts","normalizedServerUrl","pendingState","configuredClientInformation","ci","redirect_uris","clientSecret","client_secret","clientInformationOverlay","activeClientId","cache","loadCache","then","loadAuthState","persisted","initial","needsMigration","persist","catch","error","task","c","next","Parameters","saveAuthState","clientMetadata","client_name","grant_types","response_types","token_endpoint_auth_method","scope","scopes","join","redirectUrl","nonce","crypto","randomUUID","Date","now","Math","random","saveClientInformation","info","saveTokens","redirectToAuthorization","saveCodeVerifier","Error","saveDiscoveryState","invalidateCredentials"],"sources":["../../src/auth/createOAuthProvider.ts"],"sourcesContent":["import type {\n OAuthClientProvider,\n OAuthClientInformationFull,\n OAuthClientMetadata,\n OAuthDiscoveryState,\n OAuthTokens,\n} from \"@modelcontextprotocol/client\";\nimport type { MCPStorage } from \"../resources/storage/types\";\nimport type { MCPAuthConfig } from \"../mcp-scope\";\nimport type { MCPPersistedAuthState } from \"./types\";\nimport {\n isAuthStateForServerUrl,\n normalizeMcpServerUrl,\n} from \"../utils/serverUrl\";\n\nconst STATE_PREFIX = \"aui-mcp:\";\n\nfunction bytesToBase64Url(bytes: Uint8Array): string {\n let s = \"\";\n for (const b of bytes) s += String.fromCharCode(b);\n return btoa(s).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\nfunction base64UrlToBytes(b64url: string): Uint8Array {\n const padded =\n b64url.replace(/-/g, \"+\").replace(/_/g, \"/\") +\n \"=\".repeat((4 - (b64url.length % 4)) % 4);\n const bin = atob(padded);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\nfunction encodeServerIdInState(serverId: string): string {\n const bytes = new TextEncoder().encode(serverId);\n return `${STATE_PREFIX}${bytesToBase64Url(bytes)}`;\n}\n\nexport function decodeServerIdFromState(state: string): string | null {\n if (!state.startsWith(STATE_PREFIX)) return null;\n const dot = state.indexOf(\".\", STATE_PREFIX.length);\n const encoded =\n dot === -1\n ? state.slice(STATE_PREFIX.length)\n : state.slice(STATE_PREFIX.length, dot);\n try {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(\n base64UrlToBytes(encoded),\n );\n } catch {\n return null;\n }\n}\n\nexport type CreateOAuthProviderOptions = {\n serverId: string;\n serverUrl: string;\n /** Must be `auth.type === \"oauth\"`. */\n config: Extract<MCPAuthConfig, { type: \"oauth\" }>;\n storage: MCPStorage;\n redirectUri: string;\n /** Called by the SDK to start the authorization redirect. */\n onAuthorizationUrl: (url: URL) => void;\n};\n\ntype OAuthProviderCache = {\n token?: string | undefined;\n tokens?: OAuthTokens | undefined;\n tokensClientId?: string | undefined;\n clientInformation?: OAuthClientInformationFull | undefined;\n clientInformationSource?: MCPPersistedAuthState[\"clientInformationSource\"];\n codeVerifier?: string | undefined;\n state?: string | undefined;\n discoveryState?: OAuthDiscoveryState | undefined;\n};\n\ntype OAuthConfig = Extract<MCPAuthConfig, { type: \"oauth\" }>;\n\ntype OAuthCredentialState = {\n tokens?: OAuthTokens | undefined;\n tokensClientId?: string | undefined;\n clientInformation?: OAuthClientInformationFull | undefined;\n clientInformationSource?: \"registered\" | undefined;\n};\n\nconst registeredClientId = (\n state: OAuthCredentialState | null | undefined,\n): string | undefined =>\n state?.clientInformationSource === \"registered\"\n ? state.clientInformation?.client_id\n : undefined;\n\nexport const hasUsableOAuthTokens = (\n state: OAuthCredentialState | null | undefined,\n config: OAuthConfig,\n): boolean => {\n const clientId = config.clientId ?? registeredClientId(state);\n return (\n clientId !== undefined &&\n state?.tokens !== undefined &&\n state.tokensClientId === clientId\n );\n};\n\nconst hasUsableRegisteredClientInformation = (\n state: OAuthCredentialState | null | undefined,\n config: OAuthConfig,\n): boolean => {\n const clientId = registeredClientId(state);\n return (\n clientId !== undefined &&\n (config.clientId === undefined || config.clientId === clientId)\n );\n};\n\ntype OAuthProviderEndpointCache = {\n serverUrl: string;\n cached: OAuthProviderCache | null;\n cachePromise: Promise<OAuthProviderCache> | null;\n invalidated: boolean;\n};\n\ntype OAuthProviderPersistence = {\n endpoint: OAuthProviderEndpointCache | null;\n queue: Promise<void>;\n invalidated: boolean;\n};\n\n// scopeId, not object identity, is what addresses the same persisted data, so\n// storages sharing one share an anchor and an unscoped storage is its own\n// identity. Every storage declaring a scope holds that scope's anchor, so the\n// coordination state below is collected once the last of them is gone.\nconst anchorByStorage = new WeakMap<MCPStorage, object>();\nconst anchorByScope = new Map<string, WeakRef<object>>();\nconst anchorRegistry = new FinalizationRegistry<string>((scopeId) => {\n if (!anchorByScope.get(scopeId)?.deref()) anchorByScope.delete(scopeId);\n});\n\nconst getStorageIdentity = (storage: MCPStorage): object => {\n const existing = anchorByStorage.get(storage);\n if (existing) return existing;\n\n const { scopeId } = storage;\n if (scopeId === undefined) return storage;\n\n let anchor = anchorByScope.get(scopeId)?.deref();\n if (!anchor) {\n anchor = {};\n anchorByScope.set(scopeId, new WeakRef(anchor));\n anchorRegistry.register(anchor, scopeId);\n }\n anchorByStorage.set(storage, anchor);\n return anchor;\n};\n\n// McpServerResource builds a fresh provider for every transport, so the cache,\n// the in-flight load, and the write queue have to outlive any one provider.\n// saveAuthState replaces the whole record, so two providers writing their own\n// snapshots concurrently would drop whichever field the loser had added.\nconst persistenceByIdentity = new WeakMap<\n object,\n Map<string, OAuthProviderPersistence>\n>();\n\nconst getPersistence = (\n storage: MCPStorage,\n serverId: string,\n serverUrl: string,\n): {\n persistence: OAuthProviderPersistence;\n endpoint: OAuthProviderEndpointCache;\n} => {\n const identity = getStorageIdentity(storage);\n let byServerId = persistenceByIdentity.get(identity);\n if (!byServerId) {\n byServerId = new Map();\n persistenceByIdentity.set(identity, byServerId);\n }\n\n let persistence = byServerId.get(serverId);\n if (!persistence) {\n persistence = {\n endpoint: null,\n queue: Promise.resolve(),\n invalidated: false,\n };\n byServerId.set(serverId, persistence);\n }\n\n let endpoint = persistence.endpoint;\n if (endpoint?.serverUrl !== serverUrl) {\n if (endpoint) endpoint.invalidated = true;\n endpoint = {\n serverUrl,\n cached: null,\n cachePromise: null,\n invalidated: false,\n };\n persistence.endpoint = endpoint;\n }\n return { persistence, endpoint };\n};\n\n/**\n * Clears persisted OAuth state after the in-flight load and every queued write\n * for that server have settled, so a discarded provider cannot recreate the\n * record it was mid-save on.\n */\nexport const clearOAuthProviderAuthState = async (\n storage: MCPStorage,\n serverId: string,\n): Promise<void> => {\n const identity = getStorageIdentity(storage);\n const byServerId = persistenceByIdentity.get(identity);\n const persistence = byServerId?.get(serverId);\n if (!byServerId || !persistence) {\n await storage.clearAuthState(serverId);\n return;\n }\n\n // Detaching the entry before awaiting keeps a provider built during the clear\n // on a fresh generation instead of inheriting the fenced one.\n persistence.invalidated = true;\n byServerId.delete(serverId);\n if (byServerId.size === 0) persistenceByIdentity.delete(identity);\n\n if (persistence.endpoint) persistence.endpoint.invalidated = true;\n const cachePromise = persistence.endpoint?.cachePromise;\n if (cachePromise) await Promise.allSettled([cachePromise]);\n await persistence.queue;\n await storage.clearAuthState(serverId);\n};\n\n/**\n * Builds an OAuthClientProvider for the MCP SDK, backed by MCPStorage.\n * Token refresh and DCR are handled by the SDK; this provider only mediates\n * load/save and the redirect step.\n */\nexport function createOAuthProvider(\n opts: CreateOAuthProviderOptions,\n): OAuthClientProvider {\n const {\n serverId,\n serverUrl,\n config,\n storage,\n redirectUri,\n onAuthorizationUrl,\n } = opts;\n const normalizedServerUrl = normalizeMcpServerUrl(serverUrl);\n const { persistence, endpoint } = getPersistence(\n storage,\n serverId,\n normalizedServerUrl,\n );\n let pendingState: string | undefined;\n\n // The cache is shared with every other provider for this storage, server id,\n // and server URL, so a statically configured client stays a read-time overlay\n // owned by this provider. Writing it into the cache would leak this provider's\n // registration to a replacement built for a different, or absent, clientId.\n // The SDK's write-backs, its issuer stamp included, replace the overlay.\n const configuredClientInformation = ():\n | OAuthClientInformationFull\n | undefined => {\n if (!config.clientId) return undefined;\n const ci: OAuthClientInformationFull = {\n client_id: config.clientId,\n redirect_uris: [redirectUri],\n };\n if (config.clientSecret) ci.client_secret = config.clientSecret;\n return ci;\n };\n let clientInformationOverlay = configuredClientInformation();\n\n const activeClientId = (cache: OAuthProviderCache): string | undefined =>\n clientInformationOverlay?.client_id ?? registeredClientId(cache);\n\n const loadCache = (): Promise<OAuthProviderCache> => {\n if (endpoint.invalidated) return Promise.resolve({});\n if (endpoint.cached) return Promise.resolve(endpoint.cached);\n if (endpoint.cachePromise) return endpoint.cachePromise;\n\n endpoint.cachePromise = persistence.queue\n .then(() => storage.loadAuthState(serverId))\n .then(\n async (persisted) => {\n const initial: OAuthProviderCache = {};\n let needsMigration = false;\n if (endpoint.invalidated) return initial;\n if (\n persisted &&\n isAuthStateForServerUrl(persisted, normalizedServerUrl)\n ) {\n if (\n hasUsableRegisteredClientInformation(persisted, config) &&\n persisted.clientInformation\n ) {\n initial.clientInformation = persisted.clientInformation;\n initial.clientInformationSource = \"registered\";\n } else if (\n persisted?.clientInformation ||\n persisted?.clientInformationSource !== undefined\n ) {\n needsMigration = true;\n }\n if (hasUsableOAuthTokens(persisted, config)) {\n initial.tokens = persisted.tokens;\n initial.tokensClientId = persisted.tokensClientId;\n } else if (\n persisted?.tokens ||\n persisted?.tokensClientId !== undefined\n ) {\n needsMigration = true;\n }\n if (persisted?.token) initial.token = persisted.token;\n if (persisted?.codeVerifier)\n initial.codeVerifier = persisted.codeVerifier;\n if (persisted?.state) initial.state = persisted.state;\n if (persisted?.discoveryState)\n initial.discoveryState = persisted.discoveryState;\n }\n endpoint.cached = initial;\n if (needsMigration) await persist().catch(() => {});\n return initial;\n },\n (error) => {\n endpoint.cachePromise = null;\n throw error;\n },\n );\n return endpoint.cachePromise;\n };\n\n function persist() {\n const task = persistence.queue.then(async () => {\n if (persistence.invalidated || endpoint.invalidated) return;\n const c = endpoint.cached;\n if (!c) return;\n const next: Parameters<typeof storage.saveAuthState>[1] = {};\n if (hasUsableOAuthTokens(c, config) && c.tokens && c.tokensClientId) {\n next.tokens = c.tokens;\n next.tokensClientId = c.tokensClientId;\n }\n if (c.clientInformation && c.clientInformationSource === \"registered\") {\n next.clientInformation = c.clientInformation;\n next.clientInformationSource = \"registered\";\n }\n if (c.token) next.token = c.token;\n if (c.codeVerifier) next.codeVerifier = c.codeVerifier;\n if (c.state) next.state = c.state;\n if (c.discoveryState) next.discoveryState = c.discoveryState;\n next.serverUrl = normalizedServerUrl;\n await storage.saveAuthState(serverId, next);\n });\n persistence.queue = task.catch(() => {});\n return task;\n }\n\n const clientMetadata: OAuthClientMetadata = {\n client_name: \"assistant-ui\",\n redirect_uris: [redirectUri],\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\",\n scope: config.scopes?.join(\" \"),\n };\n\n return {\n get redirectUrl() {\n return redirectUri;\n },\n get clientMetadata() {\n return clientMetadata;\n },\n state() {\n // Embed the server id so the callback handler can route it back to the\n // right MCPServerResource without app-level wiring.\n const nonce =\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `${Date.now()}.${Math.random()}`;\n pendingState = `${encodeServerIdInState(serverId)}.${nonce}`;\n return pendingState;\n },\n async clientInformation() {\n const c = await loadCache();\n if (clientInformationOverlay) return clientInformationOverlay;\n if (c.clientInformationSource !== \"registered\") return undefined;\n return c.clientInformation;\n },\n async saveClientInformation(info) {\n if (clientInformationOverlay) {\n clientInformationOverlay = info as OAuthClientInformationFull;\n return;\n }\n const c = await loadCache();\n c.clientInformation = info as OAuthClientInformationFull;\n c.clientInformationSource = \"registered\";\n if (c.tokensClientId !== c.clientInformation.client_id) {\n delete c.tokens;\n delete c.tokensClientId;\n }\n await persist();\n },\n async tokens() {\n const c = await loadCache();\n const clientId = activeClientId(c);\n if (clientId === undefined || c.tokensClientId !== clientId)\n return undefined;\n return c.tokens;\n },\n async saveTokens(tokens) {\n const c = await loadCache();\n c.tokens = tokens;\n const clientId = activeClientId(c);\n if (clientId) c.tokensClientId = clientId;\n else delete c.tokensClientId;\n delete c.state;\n await persist();\n },\n async redirectToAuthorization(url) {\n onAuthorizationUrl(url);\n },\n async saveCodeVerifier(codeVerifier) {\n const c = await loadCache();\n c.codeVerifier = codeVerifier;\n if (pendingState) {\n c.state = pendingState;\n pendingState = undefined;\n }\n await persist();\n },\n async codeVerifier() {\n const c = await loadCache();\n if (!c.codeVerifier) {\n throw new Error(\"No code verifier saved for this OAuth flow\");\n }\n return c.codeVerifier;\n },\n async saveDiscoveryState(discoveryState) {\n const c = await loadCache();\n c.discoveryState = discoveryState;\n await persist();\n },\n async discoveryState() {\n const c = await loadCache();\n return c.discoveryState;\n },\n async invalidateCredentials(scope) {\n const c = await loadCache();\n if (scope === \"all\" || scope === \"tokens\") {\n delete c.tokens;\n delete c.tokensClientId;\n }\n if (scope === \"all\" || scope === \"client\") {\n delete c.clientInformation;\n delete c.clientInformationSource;\n if (!config.clientId) {\n delete c.tokens;\n delete c.tokensClientId;\n }\n clientInformationOverlay = configuredClientInformation();\n }\n if (scope === \"all\" || scope === \"verifier\") {\n delete c.codeVerifier;\n delete c.state;\n }\n if (scope === \"all\" || scope === \"discovery\") delete c.discoveryState;\n await persist();\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/auth/types.d.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { OAuthClientInformationFull, OAuthDiscoveryState, OAuthTokens } from "@modelcontextprotocol/client";
|
|
2
2
|
//#region src/auth/types.d.ts
|
|
3
3
|
type MCPPersistedAuthState = {
|
|
4
|
+
/** MCP server URL this authentication state belongs to. Required with credentials. */
|
|
5
|
+
serverUrl?: string;
|
|
4
6
|
tokens?: OAuthTokens;
|
|
7
|
+
tokensClientId?: string;
|
|
5
8
|
clientInformation?: OAuthClientInformationFull;
|
|
9
|
+
clientInformationSource?: "registered";
|
|
6
10
|
codeVerifier?: string;
|
|
7
11
|
state?: string;
|
|
8
12
|
discoveryState?: OAuthDiscoveryState;
|
|
9
|
-
/**
|
|
13
|
+
/** Host-persisted bearer token. Must be paired with serverUrl. */
|
|
10
14
|
token?: string;
|
|
11
15
|
};
|
|
12
16
|
//#endregion
|
package/dist/auth/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/auth/types.ts"],"mappings":";;KAMY;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/auth/types.ts"],"mappings":";;KAMY;;EAEV;EACA,SAAS;EACT;EACA,oBAAoB;EACpB;EACA;EACA;EACA,iBAAiB;;EAEjB"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { useAddForm } from "./context.js";
|
|
2
2
|
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
3
|
-
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
//#region src/primitives/addForm/McpAddFormAuthFields.tsx
|
|
5
5
|
const McpAddFormPrimitiveAuthFields = (t0) => {
|
|
6
|
-
const $ = c(
|
|
6
|
+
const $ = c(27);
|
|
7
7
|
const { children } = t0;
|
|
8
|
-
const { state, setField } = useAddForm();
|
|
8
|
+
const { state, ids, setField } = useAddForm();
|
|
9
9
|
if (children) {
|
|
10
10
|
const Render = children;
|
|
11
11
|
let t1;
|
|
@@ -19,47 +19,90 @@ const McpAddFormPrimitiveAuthFields = (t0) => {
|
|
|
19
19
|
}
|
|
20
20
|
if (state.authType === "bearer") {
|
|
21
21
|
let t1;
|
|
22
|
-
if ($[3] !==
|
|
23
|
-
t1 =
|
|
24
|
-
|
|
22
|
+
if ($[3] !== ids.bearerToken) {
|
|
23
|
+
t1 = /* @__PURE__ */ jsx("label", {
|
|
24
|
+
htmlFor: ids.bearerToken,
|
|
25
|
+
"data-mcp-auth-field-label": "bearer-token",
|
|
26
|
+
children: "Bearer token"
|
|
27
|
+
});
|
|
28
|
+
$[3] = ids.bearerToken;
|
|
25
29
|
$[4] = t1;
|
|
26
30
|
} else t1 = $[4];
|
|
27
31
|
let t2;
|
|
28
|
-
if ($[5] !==
|
|
29
|
-
t2 =
|
|
32
|
+
if ($[5] !== setField) {
|
|
33
|
+
t2 = (e) => setField("bearerToken", e.target.value);
|
|
34
|
+
$[5] = setField;
|
|
35
|
+
$[6] = t2;
|
|
36
|
+
} else t2 = $[6];
|
|
37
|
+
const t3 = state.errorField === "bearerToken" ? true : void 0;
|
|
38
|
+
const t4 = state.errorField === "bearerToken" ? ids.error : void 0;
|
|
39
|
+
let t5;
|
|
40
|
+
if ($[7] !== ids.bearerToken || $[8] !== state.bearerToken || $[9] !== t2 || $[10] !== t3 || $[11] !== t4) {
|
|
41
|
+
t5 = /* @__PURE__ */ jsx("input", {
|
|
42
|
+
id: ids.bearerToken,
|
|
30
43
|
type: "password",
|
|
31
|
-
placeholder: "Bearer token",
|
|
32
44
|
value: state.bearerToken,
|
|
33
|
-
onChange:
|
|
45
|
+
onChange: t2,
|
|
46
|
+
"aria-invalid": t3,
|
|
47
|
+
"aria-describedby": t4,
|
|
34
48
|
"data-mcp-auth-field": "bearer-token"
|
|
35
49
|
});
|
|
36
|
-
$[
|
|
37
|
-
$[
|
|
38
|
-
$[
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
$[7] = ids.bearerToken;
|
|
51
|
+
$[8] = state.bearerToken;
|
|
52
|
+
$[9] = t2;
|
|
53
|
+
$[10] = t3;
|
|
54
|
+
$[11] = t4;
|
|
55
|
+
$[12] = t5;
|
|
56
|
+
} else t5 = $[12];
|
|
57
|
+
let t6;
|
|
58
|
+
if ($[13] !== t1 || $[14] !== t5) {
|
|
59
|
+
t6 = /* @__PURE__ */ jsxs("div", { children: [t1, t5] });
|
|
60
|
+
$[13] = t1;
|
|
61
|
+
$[14] = t5;
|
|
62
|
+
$[15] = t6;
|
|
63
|
+
} else t6 = $[15];
|
|
64
|
+
return t6;
|
|
41
65
|
}
|
|
42
66
|
if (state.authType === "oauth") {
|
|
43
67
|
let t1;
|
|
44
|
-
if ($[
|
|
45
|
-
t1 =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
68
|
+
if ($[16] !== ids.scopes) {
|
|
69
|
+
t1 = /* @__PURE__ */ jsx("label", {
|
|
70
|
+
htmlFor: ids.scopes,
|
|
71
|
+
"data-mcp-auth-field-label": "oauth-scopes",
|
|
72
|
+
children: "OAuth scopes"
|
|
73
|
+
});
|
|
74
|
+
$[16] = ids.scopes;
|
|
75
|
+
$[17] = t1;
|
|
76
|
+
} else t1 = $[17];
|
|
49
77
|
let t2;
|
|
50
|
-
if ($[
|
|
51
|
-
t2 =
|
|
78
|
+
if ($[18] !== setField) {
|
|
79
|
+
t2 = (e_0) => setField("scopes", e_0.target.value);
|
|
80
|
+
$[18] = setField;
|
|
81
|
+
$[19] = t2;
|
|
82
|
+
} else t2 = $[19];
|
|
83
|
+
let t3;
|
|
84
|
+
if ($[20] !== ids.scopes || $[21] !== state.scopes || $[22] !== t2) {
|
|
85
|
+
t3 = /* @__PURE__ */ jsx("input", {
|
|
86
|
+
id: ids.scopes,
|
|
52
87
|
type: "text",
|
|
53
88
|
placeholder: "Scopes (space-separated, optional)",
|
|
54
89
|
value: state.scopes,
|
|
55
|
-
onChange:
|
|
90
|
+
onChange: t2,
|
|
56
91
|
"data-mcp-auth-field": "oauth-scopes"
|
|
57
92
|
});
|
|
58
|
-
$[
|
|
59
|
-
$[
|
|
60
|
-
$[
|
|
61
|
-
|
|
62
|
-
|
|
93
|
+
$[20] = ids.scopes;
|
|
94
|
+
$[21] = state.scopes;
|
|
95
|
+
$[22] = t2;
|
|
96
|
+
$[23] = t3;
|
|
97
|
+
} else t3 = $[23];
|
|
98
|
+
let t4;
|
|
99
|
+
if ($[24] !== t1 || $[25] !== t3) {
|
|
100
|
+
t4 = /* @__PURE__ */ jsxs("div", { children: [t1, t3] });
|
|
101
|
+
$[24] = t1;
|
|
102
|
+
$[25] = t3;
|
|
103
|
+
$[26] = t4;
|
|
104
|
+
} else t4 = $[26];
|
|
105
|
+
return t4;
|
|
63
106
|
}
|
|
64
107
|
return null;
|
|
65
108
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpAddFormAuthFields.js","names":["FC","AddFormAuthType","useAddForm","McpAddFormPrimitiveAuthFields","Props","children","authType","t0","$","_c","state","setField","Render","t1","e","target","value","
|
|
1
|
+
{"version":3,"file":"McpAddFormAuthFields.js","names":["FC","AddFormAuthType","useAddForm","McpAddFormPrimitiveAuthFields","Props","children","authType","t0","$","_c","state","ids","setField","Render","t1","bearerToken","t2","e","target","value","t3","errorField","undefined","t4","error","t5","t6","scopes","e_0","displayName"],"sources":["../../../src/primitives/addForm/McpAddFormAuthFields.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { type AddFormAuthType, useAddForm } from \"./context\";\n\nexport namespace McpAddFormPrimitiveAuthFields {\n export type Props = {\n /**\n * Optional render override. Receives the current auth type so apps can render\n * fully custom inputs. Defaults to a minimal built-in for bearer / oauth.\n */\n children?: FC<{ authType: AddFormAuthType }>;\n };\n}\n\nexport const McpAddFormPrimitiveAuthFields: FC<\n McpAddFormPrimitiveAuthFields.Props\n> = ({ children }) => {\n const { state, ids, setField } = useAddForm();\n\n if (children) {\n const Render = children;\n return <Render authType={state.authType} />;\n }\n\n if (state.authType === \"bearer\") {\n return (\n <div>\n <label\n htmlFor={ids.bearerToken}\n data-mcp-auth-field-label=\"bearer-token\"\n >\n Bearer token\n </label>\n <input\n id={ids.bearerToken}\n type=\"password\"\n value={state.bearerToken}\n onChange={(e) => setField(\"bearerToken\", e.target.value)}\n aria-invalid={state.errorField === \"bearerToken\" ? true : undefined}\n aria-describedby={\n state.errorField === \"bearerToken\" ? ids.error : undefined\n }\n data-mcp-auth-field=\"bearer-token\"\n />\n </div>\n );\n }\n\n if (state.authType === \"oauth\") {\n return (\n <div>\n <label htmlFor={ids.scopes} data-mcp-auth-field-label=\"oauth-scopes\">\n OAuth scopes\n </label>\n <input\n id={ids.scopes}\n type=\"text\"\n placeholder=\"Scopes (space-separated, optional)\"\n value={state.scopes}\n onChange={(e) => setField(\"scopes\", e.target.value)}\n data-mcp-auth-field=\"oauth-scopes\"\n />\n </div>\n );\n }\n\n return null;\n};\n\nMcpAddFormPrimitiveAuthFields.displayName = \"McpAddFormPrimitive.AuthFields\";\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpAddFormError.d.ts","names":[],"sources":["../../../src/primitives/addForm/McpAddFormError.tsx"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"McpAddFormError.d.ts","names":[],"sources":["../../../src/primitives/addForm/McpAddFormError.tsx"],"mappings":";;;kBASiB;OACH,UAAU,oBAAoB,UAAU;OACxC,QAAQ,gCAAgC,UAAU;;cAGnD,0CAAwB,0BAAA,qBAAA,gBAAA,kCAAA,eAAA;;4BAwBnC,cAAA"}
|
|
@@ -1,27 +1,47 @@
|
|
|
1
1
|
import { useAddForm } from "./context.js";
|
|
2
2
|
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
3
|
-
import { forwardRef } from "@assistant-ui/tap/react-shim";
|
|
3
|
+
import { forwardRef, isValidElement } from "@assistant-ui/tap/react-shim";
|
|
4
4
|
import { Primitive } from "@radix-ui/react-primitive";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region src/primitives/addForm/McpAddFormError.tsx
|
|
7
7
|
const McpAddFormPrimitiveError = forwardRef((props, ref) => {
|
|
8
|
-
const $ = c(
|
|
9
|
-
const { state } = useAddForm();
|
|
8
|
+
const $ = c(10);
|
|
9
|
+
const { state, ids } = useAddForm();
|
|
10
10
|
if (!state.error) return null;
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const customId = (props.asChild && isValidElement(props.children) ? props.children.props.id : void 0) ?? props.id;
|
|
12
|
+
const needsDescriptionWrapper = customId !== void 0 && customId !== ids.error;
|
|
13
|
+
const t0 = needsDescriptionWrapper ? props.id : ids.error;
|
|
14
|
+
const t1 = props.role ?? "alert";
|
|
15
|
+
const t2 = props.children ?? state.error;
|
|
16
|
+
let t3;
|
|
17
|
+
if ($[0] !== props || $[1] !== ref || $[2] !== t0 || $[3] !== t1 || $[4] !== t2) {
|
|
18
|
+
t3 = /* @__PURE__ */ jsx(Primitive.div, {
|
|
15
19
|
...props,
|
|
20
|
+
id: t0,
|
|
21
|
+
role: t1,
|
|
16
22
|
ref,
|
|
17
|
-
children:
|
|
23
|
+
children: t2
|
|
18
24
|
});
|
|
19
25
|
$[0] = props;
|
|
20
26
|
$[1] = ref;
|
|
21
27
|
$[2] = t0;
|
|
22
28
|
$[3] = t1;
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
$[4] = t2;
|
|
30
|
+
$[5] = t3;
|
|
31
|
+
} else t3 = $[5];
|
|
32
|
+
const error = t3;
|
|
33
|
+
let t4;
|
|
34
|
+
if ($[6] !== error || $[7] !== ids || $[8] !== needsDescriptionWrapper) {
|
|
35
|
+
t4 = needsDescriptionWrapper ? /* @__PURE__ */ jsx("div", {
|
|
36
|
+
id: ids.error,
|
|
37
|
+
children: error
|
|
38
|
+
}) : error;
|
|
39
|
+
$[6] = error;
|
|
40
|
+
$[7] = ids;
|
|
41
|
+
$[8] = needsDescriptionWrapper;
|
|
42
|
+
$[9] = t4;
|
|
43
|
+
} else t4 = $[9];
|
|
44
|
+
return t4;
|
|
25
45
|
});
|
|
26
46
|
McpAddFormPrimitiveError.displayName = "McpAddFormPrimitive.Error";
|
|
27
47
|
//#endregion
|