@assistant-ui/react-mcp 0.1.16 → 0.1.17
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/resources/McpManagerResource.d.ts.map +1 -1
- package/dist/resources/McpManagerResource.js.map +1 -1
- package/dist/resources/McpServerResource.d.ts.map +1 -1
- package/dist/resources/McpServerResource.js +36 -15
- package/dist/resources/McpServerResource.js.map +1 -1
- package/dist/resources/storage/McpLocalStorage.d.ts.map +1 -1
- package/dist/resources/storage/McpLocalStorage.js +14 -0
- package/dist/resources/storage/McpLocalStorage.js.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 +6 -6
- package/src/auth/createOAuthProvider.test.ts +544 -35
- package/src/auth/createOAuthProvider.ts +201 -46
- package/src/auth/types.ts +5 -1
- package/src/resources/McpManagerResource.ts +3 -0
- package/src/resources/McpServerResource.test.ts +252 -17
- package/src/resources/McpServerResource.ts +35 -14
- package/src/resources/storage/McpLocalStorage.test.ts +26 -0
- package/src/resources/storage/McpLocalStorage.ts +21 -0
- 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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpManagerResource.d.ts","names":[],"sources":["../../src/resources/McpManagerResource.ts"],"mappings":";;;;KAwBY;EACV,aAAa;EACb,UAAU;;EAEV;;EAEA;;EAEA;;
|
|
1
|
+
{"version":3,"file":"McpManagerResource.d.ts","names":[],"sources":["../../src/resources/McpManagerResource.ts"],"mappings":";;;;KAwBY;EACV,aAAa;EACb,UAAU;;EAEV;;EAEA;;EAEA;;cA4RW,gDAAkB,SAAA,sBAAA,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpManagerResource.js","names":["useState","useEffect","useMemo","useEffectEvent","useRef","useResource","resource","withKey","useClientLookup","useAssistantClientRef","attachTransformScopes","ClientOutput","useAssistantScopeEffect","ModelContext","createMcpId","clearOAuthProviderAuthState","Tool","McpServerResource","McpLocalStorage","MCPStorage","MCPStorageElement","assertUniqueServerIds","MCPAuthConfig","MCPConnector","MCPCustomServerRecord","MCPManagerState","McpManagerResourceProps","connectors","storage","oauthRedirectUri","autoConnect","connectionTimeout","defaultRedirectUri","window","location","origin","NO_CONNECTORS","reportCustomStorageFailure","operation","error","console","persistCustomServers","records","saveCustomServers","useMcpManagerResource","props","$","_c","t0","redirectUri","t1","storageElement","t2","Symbol","for","customServers","setCustomServers","isHydrated","setIsHydrated","hydratedRef","storageRef","t3","Promise","resolve","persistenceQueueRef","t4","t5","current","t6","signal","markHydrated","cancelled","loadCustomServers","t7","prev","length","persistedIds","Set","map","_temp","filter","r_0","has","r","id","hydrate","signal_0","t8","t10","t9","targetStorage","then","_temp2","_temp3","t11","t12","c_0","c","kind","name","url","icon","auth","cache","undefined","elicitation","onRemove","_temp4","connectorElements","t13","s_0","s","prev_0","x","customElements","serverElements","lookup","all","state","_temp5","_temp6","t14","servers","out","server","connectionState","tool","tools","fullName","type","description","parameters","inputSchema","execute","args","get","key","callTool","toolkit","clientRef","t15","client","modelContext","register","getModelContext","t16","t17","index","list","entry","Error","serverByKind","t18","t19","query","t20","t21","t22","index_0","t23","index_1","connectionTimeout_0","record","createdAt","Date","now","prev_1","some","c_1","remove","prev_2","s_3","t24","getState","connector","customServer","addCustomServer","removeServer","McpManagerResource","scopes","parent","source","s_1","s_2"],"sources":["../../src/resources/McpManagerResource.ts"],"sourcesContent":["import { useState, useEffect, useMemo, useEffectEvent, useRef } from \"react\";\nimport { useResource, resource, withKey } from \"@assistant-ui/tap\";\nimport {\n useClientLookup,\n useAssistantClientRef,\n attachTransformScopes,\n type ClientOutput,\n} from \"@assistant-ui/store\";\nimport { useAssistantScopeEffect } from \"@assistant-ui/store/client\";\nimport { ModelContext } from \"@assistant-ui/core/store\";\nimport { createMcpId } from \"../utils/createMcpId\";\nimport { clearOAuthProviderAuthState } from \"../auth/createOAuthProvider\";\nimport type { Tool } from \"assistant-stream\";\nimport { McpServerResource } from \"./McpServerResource\";\nimport { McpLocalStorage } from \"./storage/McpLocalStorage\";\nimport type { MCPStorage, MCPStorageElement } from \"./storage/types\";\nimport { assertUniqueServerIds } from \"../utils/serverId\";\nimport type {\n MCPAuthConfig,\n MCPConnector,\n MCPCustomServerRecord,\n MCPManagerState,\n} from \"../mcp-scope\";\n\nexport type McpManagerResourceProps = {\n connectors?: MCPConnector[] | undefined;\n storage?: MCPStorageElement | undefined;\n /** OAuth redirect target. Defaults to `${origin}/mcp/callback`. */\n oauthRedirectUri?: string | undefined;\n /** Connect on mount when usable auth exists. Default true. */\n autoConnect?: boolean | undefined;\n /** Optional timeout in milliseconds for connect/listTools calls. Disabled by default. */\n connectionTimeout?: number | undefined;\n};\n\nfunction defaultRedirectUri(): string {\n if (typeof window === \"undefined\") return \"\";\n return `${window.location.origin}/mcp/callback`;\n}\n\n// Stable empty fallback so an absent `connectors` prop doesn't produce a fresh\n// array each render (which would invalidate the serverElements memo below).\nconst NO_CONNECTORS: MCPConnector[] = [];\n\nconst reportCustomStorageFailure = (\n operation: \"load\" | \"save\",\n error: unknown,\n) => {\n console.error(\n `[assistant-ui/react-mcp] failed to ${operation} custom servers:`,\n error,\n );\n};\n\nconst persistCustomServers = async (\n storage: MCPStorage,\n records: MCPCustomServerRecord[],\n) => {\n try {\n await storage.saveCustomServers(records);\n } catch (error) {\n reportCustomStorageFailure(\"save\", error);\n }\n};\n\nconst useMcpManagerResource = (\n props: McpManagerResourceProps,\n): ClientOutput<\"mcp\"> => {\n const connectors = props.connectors ?? NO_CONNECTORS;\n const autoConnect = props.autoConnect ?? true;\n const redirectUri = props.oauthRedirectUri ?? defaultRedirectUri();\n const connectionTimeout = props.connectionTimeout;\n\n const storageElement = props.storage ?? McpLocalStorage();\n const storage = useResource(storageElement);\n\n const [customServers, setCustomServers] = useState<MCPCustomServerRecord[]>(\n [],\n );\n const [isHydrated, setIsHydrated] = useState(false);\n\n const hydratedRef = useRef(false);\n const storageRef = useRef(storage);\n const persistenceQueueRef = useRef(Promise.resolve());\n\n useEffect(() => {\n storageRef.current = storage;\n }, [storage]);\n\n const hydrate = useEffectEvent(async (signal: { cancelled: boolean }) => {\n const markHydrated = () => {\n if (!signal.cancelled) {\n hydratedRef.current = true;\n setIsHydrated(true);\n }\n };\n\n let records: Awaited<ReturnType<typeof storage.loadCustomServers>>;\n try {\n records = await storage.loadCustomServers();\n } catch (error) {\n if (!signal.cancelled) {\n reportCustomStorageFailure(\"load\", error);\n }\n markHydrated();\n return;\n }\n\n if (signal.cancelled) return;\n // Merge rather than replace so any addCustomServer calls that\n // happened before hydration resolved aren't silently overwritten.\n // Persisted order wins; pre-hydration locals append.\n setCustomServers((prev) => {\n if (prev.length === 0) return records;\n const persistedIds = new Set(records.map((r) => r.id));\n return [...records, ...prev.filter((r) => !persistedIds.has(r.id))];\n });\n markHydrated();\n });\n\n useEffect(() => {\n const signal = { cancelled: false };\n void hydrate(signal);\n return () => {\n signal.cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n if (!hydratedRef.current) return;\n const targetStorage = storageRef.current;\n persistenceQueueRef.current = persistenceQueueRef.current.then(() =>\n persistCustomServers(targetStorage, customServers),\n );\n }, [customServers]);\n\n const serverElements = useMemo(() => {\n assertUniqueServerIds([\n ...connectors.map((c) => c.id),\n ...customServers.map((s) => s.id),\n ]);\n\n const connectorElements = connectors.map((c) =>\n withKey(\n c.id,\n McpServerResource({\n id: c.id,\n kind: \"connector\",\n name: c.name,\n url: c.url,\n icon: c.icon,\n auth: c.auth,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout: c.connectionTimeout ?? connectionTimeout,\n ...(c.cache !== undefined ? { cache: c.cache } : {}),\n ...(c.elicitation !== undefined\n ? { elicitation: c.elicitation }\n : {}),\n onRemove: async () => {\n // connectors cannot be removed\n },\n }),\n ),\n );\n const customElements = customServers.map((s) =>\n withKey(\n s.id,\n McpServerResource({\n id: s.id,\n kind: \"custom\",\n name: s.name,\n url: s.url,\n auth: s.auth,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout: s.connectionTimeout ?? connectionTimeout,\n ...(s.cache !== undefined ? { cache: s.cache } : {}),\n ...(s.elicitation !== undefined\n ? { elicitation: s.elicitation }\n : {}),\n onRemove: async () => {\n setCustomServers((prev) => prev.filter((x) => x.id !== s.id));\n },\n }),\n ),\n );\n return [...connectorElements, ...customElements];\n }, [\n connectors,\n customServers,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout,\n ]);\n\n const lookup = useClientLookup(serverElements);\n\n const state = useMemo<MCPManagerState>(() => {\n const all = lookup.state;\n return {\n servers: all,\n connectors: all.filter((s) => s.kind === \"connector\"),\n customServers: all.filter((s) => s.kind === \"custom\"),\n isHydrated,\n };\n }, [lookup.state, isHydrated]);\n\n // ─── Auto-register MCP tools as frontend tools in modelContext ─────\n // Build the toolkit from connected servers; re-register when the visible\n // tool surface changes. Tool names are prefixed with the server id to\n // avoid collisions across connected servers — connector ids must not\n // contain `__` (enforced by `defineConnector`); `addCustomServer`\n // generates UUIDs that satisfy the constraint by construction.\n const toolkit = useMemo<Record<string, Tool<any, any>>>(() => {\n const out: Record<string, Tool<any, any>> = {};\n for (const server of state.servers) {\n if (server.connectionState !== \"connected\") continue;\n for (const tool of server.tools) {\n const fullName = `${server.id}__${tool.name}`;\n out[fullName] = {\n type: \"frontend\",\n ...(tool.description !== undefined\n ? { description: tool.description }\n : {}),\n parameters: tool.inputSchema as never,\n execute: (args) =>\n lookup.get({ key: server.id }).callTool(tool.name, args as unknown),\n };\n }\n }\n return out;\n }, [state, lookup]);\n\n const clientRef = useAssistantClientRef();\n\n useAssistantScopeEffect(\n \"modelContext\",\n () => {\n const client = clientRef.current;\n if (!client) return;\n return client.modelContext.register({\n getModelContext: () => ({ tools: toolkit }),\n });\n },\n [toolkit],\n );\n\n const serverByKind = (kind: \"connector\" | \"custom\", index: number) => {\n const list = kind === \"connector\" ? state.connectors : state.customServers;\n const entry = list[index];\n if (!entry) {\n throw new Error(\n `McpManagerResource: no ${kind} at index ${index} (length ${list.length})`,\n );\n }\n return lookup.get({ key: entry.id });\n };\n\n return {\n getState: () => state,\n server: (query) => {\n if (\"id\" in query) return lookup.get({ key: query.id });\n return serverByKind(query.kind, query.index);\n },\n connector: ({ index }) => serverByKind(\"connector\", index),\n customServer: ({ index }) => serverByKind(\"custom\", index),\n addCustomServer: async ({\n name,\n url,\n auth,\n connectionTimeout,\n cache,\n elicitation,\n }) => {\n const record: MCPCustomServerRecord = {\n id: createMcpId(),\n name,\n url,\n auth: auth as MCPAuthConfig,\n connectionTimeout,\n ...(cache !== undefined ? { cache } : {}),\n ...(elicitation !== undefined ? { elicitation } : {}),\n createdAt: Date.now(),\n };\n setCustomServers((prev) => [...prev, record]);\n return record.id;\n },\n removeServer: async (id) => {\n // removeServer is custom-server only — connectors are app-defined\n // and not user-removable. Refuse rather than silently no-op.\n if (state.connectors.some((c) => c.id === id)) {\n throw new Error(\n `Cannot remove connector \"${id}\" — connectors are app-defined and not removable. Use a custom server id instead.`,\n );\n }\n // Delegate to McpServerResource.remove() which disconnects,\n // clears auth state, and unregisters from customServers in one\n // place. Fallback to manual cleanup if the lookup is empty\n // (server already gone).\n try {\n await lookup.get({ key: id }).remove();\n } catch {\n await clearOAuthProviderAuthState(storage, id);\n setCustomServers((prev) => prev.filter((s) => s.id !== id));\n }\n },\n };\n};\n\nexport const McpManagerResource = resource(useMcpManagerResource);\n\n// Ensure modelContext exists as a sibling when the manager mounts. If an\n// ancestor (e.g. a chat runtime) already provides modelContext, this is a\n// no-op; otherwise it's auto-mounted alongside `mcp`.\nattachTransformScopes(useMcpManagerResource, (scopes, parent) => {\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"McpManagerResource.js","names":["useState","useEffect","useMemo","useEffectEvent","useRef","useResource","resource","withKey","useClientLookup","useAssistantClientRef","attachTransformScopes","ClientOutput","useAssistantScopeEffect","ModelContext","createMcpId","clearOAuthProviderAuthState","Tool","McpServerResource","McpLocalStorage","MCPStorage","MCPStorageElement","assertUniqueServerIds","MCPAuthConfig","MCPConnector","MCPCustomServerRecord","MCPManagerState","McpManagerResourceProps","connectors","storage","oauthRedirectUri","autoConnect","connectionTimeout","defaultRedirectUri","window","location","origin","NO_CONNECTORS","reportCustomStorageFailure","operation","error","console","persistCustomServers","records","saveCustomServers","useMcpManagerResource","props","$","_c","t0","redirectUri","t1","storageElement","t2","Symbol","for","customServers","setCustomServers","isHydrated","setIsHydrated","hydratedRef","storageRef","t3","Promise","resolve","persistenceQueueRef","t4","t5","current","t6","signal","markHydrated","cancelled","loadCustomServers","t7","prev","length","persistedIds","Set","map","_temp","filter","r_0","has","r","id","hydrate","signal_0","t8","t10","t9","targetStorage","then","_temp2","_temp3","t11","t12","c_0","c","kind","name","url","icon","auth","cache","undefined","elicitation","onRemove","_temp4","connectorElements","t13","s_0","s","prev_0","x","customElements","serverElements","lookup","all","state","_temp5","_temp6","t14","servers","out","server","connectionState","tool","tools","fullName","type","description","parameters","inputSchema","execute","args","get","key","callTool","toolkit","clientRef","t15","client","modelContext","register","getModelContext","t16","t17","index","list","entry","Error","serverByKind","t18","t19","query","t20","t21","t22","index_0","t23","index_1","connectionTimeout_0","record","createdAt","Date","now","prev_1","some","c_1","remove","prev_2","s_3","t24","getState","connector","customServer","addCustomServer","removeServer","McpManagerResource","scopes","parent","source","s_1","s_2"],"sources":["../../src/resources/McpManagerResource.ts"],"sourcesContent":["import { useState, useEffect, useMemo, useEffectEvent, useRef } from \"react\";\nimport { useResource, resource, withKey } from \"@assistant-ui/tap\";\nimport {\n useClientLookup,\n useAssistantClientRef,\n attachTransformScopes,\n type ClientOutput,\n} from \"@assistant-ui/store\";\nimport { useAssistantScopeEffect } from \"@assistant-ui/store/client\";\nimport { ModelContext } from \"@assistant-ui/core/store\";\nimport { createMcpId } from \"../utils/createMcpId\";\nimport { clearOAuthProviderAuthState } from \"../auth/createOAuthProvider\";\nimport type { Tool } from \"assistant-stream\";\nimport { McpServerResource } from \"./McpServerResource\";\nimport { McpLocalStorage } from \"./storage/McpLocalStorage\";\nimport type { MCPStorage, MCPStorageElement } from \"./storage/types\";\nimport { assertUniqueServerIds } from \"../utils/serverId\";\nimport type {\n MCPAuthConfig,\n MCPConnector,\n MCPCustomServerRecord,\n MCPManagerState,\n} from \"../mcp-scope\";\n\nexport type McpManagerResourceProps = {\n connectors?: MCPConnector[] | undefined;\n storage?: MCPStorageElement | undefined;\n /** OAuth redirect target. Defaults to `${origin}/mcp/callback`. */\n oauthRedirectUri?: string | undefined;\n /** Connect on mount when usable auth exists. Default true. */\n autoConnect?: boolean | undefined;\n /** Optional timeout in milliseconds for connect/listTools calls. Disabled by default. */\n connectionTimeout?: number | undefined;\n};\n\nfunction defaultRedirectUri(): string {\n if (typeof window === \"undefined\") return \"\";\n return `${window.location.origin}/mcp/callback`;\n}\n\n// Stable empty fallback so an absent `connectors` prop doesn't produce a fresh\n// array each render (which would invalidate the serverElements memo below).\nconst NO_CONNECTORS: MCPConnector[] = [];\n\nconst reportCustomStorageFailure = (\n operation: \"load\" | \"save\",\n error: unknown,\n) => {\n console.error(\n `[assistant-ui/react-mcp] failed to ${operation} custom servers:`,\n error,\n );\n};\n\nconst persistCustomServers = async (\n storage: MCPStorage,\n records: MCPCustomServerRecord[],\n) => {\n try {\n await storage.saveCustomServers(records);\n } catch (error) {\n reportCustomStorageFailure(\"save\", error);\n }\n};\n\nconst useMcpManagerResource = (\n props: McpManagerResourceProps,\n): ClientOutput<\"mcp\"> => {\n const connectors = props.connectors ?? NO_CONNECTORS;\n const autoConnect = props.autoConnect ?? true;\n const redirectUri = props.oauthRedirectUri ?? defaultRedirectUri();\n const connectionTimeout = props.connectionTimeout;\n\n const storageElement = props.storage ?? McpLocalStorage();\n const storage = useResource(storageElement);\n\n const [customServers, setCustomServers] = useState<MCPCustomServerRecord[]>(\n [],\n );\n const [isHydrated, setIsHydrated] = useState(false);\n\n const hydratedRef = useRef(false);\n const storageRef = useRef(storage);\n const persistenceQueueRef = useRef(Promise.resolve());\n\n useEffect(() => {\n storageRef.current = storage;\n }, [storage]);\n\n const hydrate = useEffectEvent(async (signal: { cancelled: boolean }) => {\n const markHydrated = () => {\n if (!signal.cancelled) {\n hydratedRef.current = true;\n setIsHydrated(true);\n }\n };\n\n let records: Awaited<ReturnType<typeof storage.loadCustomServers>>;\n try {\n records = await storage.loadCustomServers();\n } catch (error) {\n if (!signal.cancelled) {\n reportCustomStorageFailure(\"load\", error);\n }\n markHydrated();\n return;\n }\n\n if (signal.cancelled) return;\n // Merge rather than replace so any addCustomServer calls that\n // happened before hydration resolved aren't silently overwritten.\n // Persisted order wins; pre-hydration locals append.\n setCustomServers((prev) => {\n if (prev.length === 0) return records;\n const persistedIds = new Set(records.map((r) => r.id));\n return [...records, ...prev.filter((r) => !persistedIds.has(r.id))];\n });\n markHydrated();\n });\n\n useEffect(() => {\n const signal = { cancelled: false };\n // Hydration reads persisted records asynchronously; there is no earlier\n // point than mount at which to start it.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n void hydrate(signal);\n return () => {\n signal.cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n if (!hydratedRef.current) return;\n const targetStorage = storageRef.current;\n persistenceQueueRef.current = persistenceQueueRef.current.then(() =>\n persistCustomServers(targetStorage, customServers),\n );\n }, [customServers]);\n\n const serverElements = useMemo(() => {\n assertUniqueServerIds([\n ...connectors.map((c) => c.id),\n ...customServers.map((s) => s.id),\n ]);\n\n const connectorElements = connectors.map((c) =>\n withKey(\n c.id,\n McpServerResource({\n id: c.id,\n kind: \"connector\",\n name: c.name,\n url: c.url,\n icon: c.icon,\n auth: c.auth,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout: c.connectionTimeout ?? connectionTimeout,\n ...(c.cache !== undefined ? { cache: c.cache } : {}),\n ...(c.elicitation !== undefined\n ? { elicitation: c.elicitation }\n : {}),\n onRemove: async () => {\n // connectors cannot be removed\n },\n }),\n ),\n );\n const customElements = customServers.map((s) =>\n withKey(\n s.id,\n McpServerResource({\n id: s.id,\n kind: \"custom\",\n name: s.name,\n url: s.url,\n auth: s.auth,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout: s.connectionTimeout ?? connectionTimeout,\n ...(s.cache !== undefined ? { cache: s.cache } : {}),\n ...(s.elicitation !== undefined\n ? { elicitation: s.elicitation }\n : {}),\n onRemove: async () => {\n setCustomServers((prev) => prev.filter((x) => x.id !== s.id));\n },\n }),\n ),\n );\n return [...connectorElements, ...customElements];\n }, [\n connectors,\n customServers,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout,\n ]);\n\n const lookup = useClientLookup(serverElements);\n\n const state = useMemo<MCPManagerState>(() => {\n const all = lookup.state;\n return {\n servers: all,\n connectors: all.filter((s) => s.kind === \"connector\"),\n customServers: all.filter((s) => s.kind === \"custom\"),\n isHydrated,\n };\n }, [lookup.state, isHydrated]);\n\n // ─── Auto-register MCP tools as frontend tools in modelContext ─────\n // Build the toolkit from connected servers; re-register when the visible\n // tool surface changes. Tool names are prefixed with the server id to\n // avoid collisions across connected servers — connector ids must not\n // contain `__` (enforced by `defineConnector`); `addCustomServer`\n // generates UUIDs that satisfy the constraint by construction.\n const toolkit = useMemo<Record<string, Tool<any, any>>>(() => {\n const out: Record<string, Tool<any, any>> = {};\n for (const server of state.servers) {\n if (server.connectionState !== \"connected\") continue;\n for (const tool of server.tools) {\n const fullName = `${server.id}__${tool.name}`;\n out[fullName] = {\n type: \"frontend\",\n ...(tool.description !== undefined\n ? { description: tool.description }\n : {}),\n parameters: tool.inputSchema as never,\n execute: (args) =>\n lookup.get({ key: server.id }).callTool(tool.name, args as unknown),\n };\n }\n }\n return out;\n }, [state, lookup]);\n\n const clientRef = useAssistantClientRef();\n\n useAssistantScopeEffect(\n \"modelContext\",\n () => {\n const client = clientRef.current;\n if (!client) return;\n return client.modelContext.register({\n getModelContext: () => ({ tools: toolkit }),\n });\n },\n [toolkit],\n );\n\n const serverByKind = (kind: \"connector\" | \"custom\", index: number) => {\n const list = kind === \"connector\" ? state.connectors : state.customServers;\n const entry = list[index];\n if (!entry) {\n throw new Error(\n `McpManagerResource: no ${kind} at index ${index} (length ${list.length})`,\n );\n }\n return lookup.get({ key: entry.id });\n };\n\n return {\n getState: () => state,\n server: (query) => {\n if (\"id\" in query) return lookup.get({ key: query.id });\n return serverByKind(query.kind, query.index);\n },\n connector: ({ index }) => serverByKind(\"connector\", index),\n customServer: ({ index }) => serverByKind(\"custom\", index),\n addCustomServer: async ({\n name,\n url,\n auth,\n connectionTimeout,\n cache,\n elicitation,\n }) => {\n const record: MCPCustomServerRecord = {\n id: createMcpId(),\n name,\n url,\n auth: auth as MCPAuthConfig,\n connectionTimeout,\n ...(cache !== undefined ? { cache } : {}),\n ...(elicitation !== undefined ? { elicitation } : {}),\n createdAt: Date.now(),\n };\n setCustomServers((prev) => [...prev, record]);\n return record.id;\n },\n removeServer: async (id) => {\n // removeServer is custom-server only — connectors are app-defined\n // and not user-removable. Refuse rather than silently no-op.\n if (state.connectors.some((c) => c.id === id)) {\n throw new Error(\n `Cannot remove connector \"${id}\" — connectors are app-defined and not removable. Use a custom server id instead.`,\n );\n }\n // Delegate to McpServerResource.remove() which disconnects,\n // clears auth state, and unregisters from customServers in one\n // place. Fallback to manual cleanup if the lookup is empty\n // (server already gone).\n try {\n await lookup.get({ key: id }).remove();\n } catch {\n await clearOAuthProviderAuthState(storage, id);\n setCustomServers((prev) => prev.filter((s) => s.id !== id));\n }\n },\n };\n};\n\nexport const McpManagerResource = resource(useMcpManagerResource);\n\n// Ensure modelContext exists as a sibling when the manager mounts. If an\n// ancestor (e.g. a chat runtime) already provides modelContext, this is a\n// no-op; otherwise it's auto-mounted alongside `mcp`.\nattachTransformScopes(useMcpManagerResource, (scopes, parent) => {\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n});\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpServerResource.d.ts","names":[],"sources":["../../src/resources/McpServerResource.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"McpServerResource.d.ts","names":[],"sources":["../../src/resources/McpServerResource.ts"],"mappings":";;;;KAqCY;EACV;EACA,MAAM;EACN;EACA;EACA;EACA,MAAM;EACN,SAAS;EACT;EACA;EACA;EACA;aAAmB;;WACV;EACT,gBAAgB;;cAOL,4BACX,OAAO;cA8rBI,+CAAiB,SAAA,4BAAA,OAAA"}
|