@assistant-ui/react-mcp 0.1.18 → 0.1.20
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/buildHeaders.d.ts +3 -6
- package/dist/auth/buildHeaders.d.ts.map +1 -1
- package/dist/auth/createOAuthProvider.d.ts +24 -26
- package/dist/auth/createOAuthProvider.d.ts.map +1 -1
- package/dist/auth/types.d.ts +13 -16
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/connector.d.ts +2 -5
- package/dist/connector.d.ts.map +1 -1
- package/dist/context/McpConnectorByIndexProvider.d.ts +3 -6
- package/dist/context/McpConnectorByIndexProvider.d.ts.map +1 -1
- package/dist/context/McpConnectorByIndexProvider.js +1 -1
- package/dist/context/McpCustomServerByIndexProvider.d.ts +3 -6
- package/dist/context/McpCustomServerByIndexProvider.d.ts.map +1 -1
- package/dist/context/McpCustomServerByIndexProvider.js +1 -1
- package/dist/context/McpServerByIdProvider.d.ts +3 -6
- package/dist/context/McpServerByIdProvider.d.ts.map +1 -1
- package/dist/context/McpServerByIdProvider.js +1 -1
- package/dist/hooks/useMcpOAuthCallback.d.ts +14 -17
- package/dist/hooks/useMcpOAuthCallback.d.ts.map +1 -1
- package/dist/hooks/useMcpOAuthCallback.js +6 -2
- package/dist/hooks/useMcpOAuthCallback.js.map +1 -1
- package/dist/index.d.ts +19 -18
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -4
- package/dist/mcp-scope.d.ts +124 -127
- package/dist/mcp-scope.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormAuthFields.d.ts +14 -16
- package/dist/primitives/addForm/McpAddFormAuthFields.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormAuthFields.js +18 -71
- package/dist/primitives/addForm/McpAddFormAuthFields.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormAuthSelect.d.ts +5 -8
- package/dist/primitives/addForm/McpAddFormAuthSelect.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormAuthSelect.js +1 -1
- package/dist/primitives/addForm/McpAddFormBearerTokenField.d.ts +8 -0
- package/dist/primitives/addForm/McpAddFormBearerTokenField.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormBearerTokenField.js +50 -0
- package/dist/primitives/addForm/McpAddFormBearerTokenField.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormCancel.d.ts +6 -9
- package/dist/primitives/addForm/McpAddFormCancel.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormCancel.js +1 -1
- package/dist/primitives/addForm/McpAddFormError.d.ts +6 -9
- package/dist/primitives/addForm/McpAddFormError.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormError.js +1 -1
- package/dist/primitives/addForm/McpAddFormNameField.d.ts +5 -8
- package/dist/primitives/addForm/McpAddFormNameField.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormNameField.js +1 -1
- package/dist/primitives/addForm/McpAddFormRoot.d.ts +11 -14
- package/dist/primitives/addForm/McpAddFormRoot.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormRoot.js +2 -2
- package/dist/primitives/addForm/McpAddFormScopesField.d.ts +8 -0
- package/dist/primitives/addForm/McpAddFormScopesField.d.ts.map +1 -0
- package/dist/primitives/addForm/McpAddFormScopesField.js +38 -0
- package/dist/primitives/addForm/McpAddFormScopesField.js.map +1 -0
- package/dist/primitives/addForm/McpAddFormSubmit.d.ts +6 -9
- package/dist/primitives/addForm/McpAddFormSubmit.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormSubmit.js +1 -1
- package/dist/primitives/addForm/McpAddFormUrlField.d.ts +5 -8
- package/dist/primitives/addForm/McpAddFormUrlField.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormUrlField.js +1 -1
- package/dist/primitives/addForm/context.d.ts +25 -28
- package/dist/primitives/addForm/context.d.ts.map +1 -1
- package/dist/primitives/addForm.d.ts +10 -13
- package/dist/primitives/addForm.d.ts.map +1 -1
- package/dist/primitives/addForm.js +5 -1
- package/dist/primitives/addForm.js.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveAccept.d.ts +6 -9
- package/dist/primitives/elicitation/McpElicitationPrimitiveAccept.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveAccept.js +2 -2
- package/dist/primitives/elicitation/McpElicitationPrimitiveCancel.d.ts +6 -9
- package/dist/primitives/elicitation/McpElicitationPrimitiveCancel.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveCancel.js +2 -2
- package/dist/primitives/elicitation/McpElicitationPrimitiveDecline.d.ts +6 -9
- package/dist/primitives/elicitation/McpElicitationPrimitiveDecline.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveDecline.js +2 -2
- package/dist/primitives/elicitation/McpElicitationPrimitiveError.d.ts +6 -9
- package/dist/primitives/elicitation/McpElicitationPrimitiveError.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveError.js +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveFields.d.ts +8 -10
- package/dist/primitives/elicitation/McpElicitationPrimitiveFields.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveFields.js +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveItems.d.ts +8 -11
- package/dist/primitives/elicitation/McpElicitationPrimitiveItems.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveItems.js +2 -2
- package/dist/primitives/elicitation/McpElicitationPrimitiveMessage.d.ts +6 -9
- package/dist/primitives/elicitation/McpElicitationPrimitiveMessage.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveMessage.js +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveRoot.d.ts +6 -9
- package/dist/primitives/elicitation/McpElicitationPrimitiveRoot.d.ts.map +1 -1
- package/dist/primitives/elicitation/McpElicitationPrimitiveRoot.js +1 -1
- package/dist/primitives/elicitation/context.d.ts +15 -18
- package/dist/primitives/elicitation/context.d.ts.map +1 -1
- package/dist/primitives/elicitation/initialElicitationDraft.d.ts +1 -4
- package/dist/primitives/elicitation/initialElicitationDraft.d.ts.map +1 -1
- package/dist/primitives/elicitation/prepareElicitationContent.d.ts +4 -7
- package/dist/primitives/elicitation/prepareElicitationContent.d.ts.map +1 -1
- package/dist/primitives/elicitation/prepareElicitationContent.js +5 -1
- package/dist/primitives/elicitation/prepareElicitationContent.js.map +1 -1
- package/dist/primitives/elicitation.d.ts +8 -14
- package/dist/primitives/elicitation.d.ts.map +1 -1
- package/dist/primitives/manager/McpManagerAddCustomTrigger.d.ts +6 -9
- package/dist/primitives/manager/McpManagerAddCustomTrigger.d.ts.map +1 -1
- package/dist/primitives/manager/McpManagerAddCustomTrigger.js +1 -1
- package/dist/primitives/manager/McpManagerConnectors.d.ts +14 -17
- package/dist/primitives/manager/McpManagerConnectors.d.ts.map +1 -1
- package/dist/primitives/manager/McpManagerConnectors.js +1 -1
- package/dist/primitives/manager/McpManagerCustomServers.d.ts +14 -17
- package/dist/primitives/manager/McpManagerCustomServers.d.ts.map +1 -1
- package/dist/primitives/manager/McpManagerCustomServers.js +1 -1
- package/dist/primitives/manager/McpManagerRoot.d.ts +6 -9
- package/dist/primitives/manager/McpManagerRoot.d.ts.map +1 -1
- package/dist/primitives/manager/McpManagerRoot.js +2 -2
- package/dist/primitives/manager.d.ts +4 -9
- package/dist/primitives/manager.d.ts.map +1 -1
- package/dist/primitives/server/McpServerConnectButton.d.ts +6 -9
- package/dist/primitives/server/McpServerConnectButton.d.ts.map +1 -1
- package/dist/primitives/server/McpServerConnectButton.js +2 -2
- package/dist/primitives/server/McpServerDisconnectButton.d.ts +6 -9
- package/dist/primitives/server/McpServerDisconnectButton.d.ts.map +1 -1
- package/dist/primitives/server/McpServerDisconnectButton.js +2 -2
- package/dist/primitives/server/McpServerError.d.ts +6 -9
- package/dist/primitives/server/McpServerError.d.ts.map +1 -1
- package/dist/primitives/server/McpServerError.js +2 -2
- package/dist/primitives/server/McpServerIcon.d.ts +12 -15
- package/dist/primitives/server/McpServerIcon.d.ts.map +1 -1
- package/dist/primitives/server/McpServerIcon.js +2 -2
- package/dist/primitives/server/McpServerName.d.ts +6 -9
- package/dist/primitives/server/McpServerName.d.ts.map +1 -1
- package/dist/primitives/server/McpServerName.js +2 -2
- package/dist/primitives/server/McpServerOAuthLink.d.ts +11 -14
- package/dist/primitives/server/McpServerOAuthLink.d.ts.map +1 -1
- package/dist/primitives/server/McpServerOAuthLink.js +2 -2
- package/dist/primitives/server/McpServerRemoveButton.d.ts +6 -9
- package/dist/primitives/server/McpServerRemoveButton.d.ts.map +1 -1
- package/dist/primitives/server/McpServerRemoveButton.js +2 -2
- package/dist/primitives/server/McpServerRoot.d.ts +6 -9
- package/dist/primitives/server/McpServerRoot.d.ts.map +1 -1
- package/dist/primitives/server/McpServerRoot.js +2 -2
- package/dist/primitives/server/McpServerStatus.d.ts +6 -9
- package/dist/primitives/server/McpServerStatus.d.ts.map +1 -1
- package/dist/primitives/server/McpServerStatus.js +2 -2
- package/dist/primitives/server/McpServerToolName.d.ts +6 -9
- package/dist/primitives/server/McpServerToolName.d.ts.map +1 -1
- package/dist/primitives/server/McpServerToolName.js +1 -1
- package/dist/primitives/server/McpServerTools.d.ts +8 -11
- package/dist/primitives/server/McpServerTools.d.ts.map +1 -1
- package/dist/primitives/server/McpServerTools.js +2 -2
- package/dist/primitives/server.d.ts +11 -16
- package/dist/primitives/server.d.ts.map +1 -1
- package/dist/resources/McpManagerResource.d.ts +13 -16
- package/dist/resources/McpManagerResource.d.ts.map +1 -1
- package/dist/resources/McpManagerResource.js +95 -64
- package/dist/resources/McpManagerResource.js.map +1 -1
- package/dist/resources/McpServerRemovalFence.d.ts +3 -6
- package/dist/resources/McpServerRemovalFence.d.ts.map +1 -1
- package/dist/resources/McpServerResource.d.ts +21 -24
- package/dist/resources/McpServerResource.d.ts.map +1 -1
- package/dist/resources/McpServerResource.js +55 -47
- package/dist/resources/McpServerResource.js.map +1 -1
- package/dist/resources/storage/McpCustomStorage.d.ts +2 -5
- package/dist/resources/storage/McpCustomStorage.d.ts.map +1 -1
- package/dist/resources/storage/McpLocalStorage.d.ts +18 -21
- package/dist/resources/storage/McpLocalStorage.d.ts.map +1 -1
- package/dist/resources/storage/McpLocalStorage.js +1 -1
- package/dist/resources/storage/McpMemoryStorage.d.ts +2 -5
- package/dist/resources/storage/McpMemoryStorage.d.ts.map +1 -1
- package/dist/resources/storage/types.d.ts +24 -27
- package/dist/resources/storage/types.d.ts.map +1 -1
- package/dist/resources/validateElicitationContent.d.ts +4 -6
- package/dist/resources/validateElicitationContent.d.ts.map +1 -1
- package/dist/utils/createMcpId.d.ts +1 -4
- package/dist/utils/createMcpId.d.ts.map +1 -1
- package/dist/utils/invokeMcpCallback.d.ts +1 -4
- package/dist/utils/invokeMcpCallback.d.ts.map +1 -1
- package/dist/utils/serverId.d.ts +2 -5
- package/dist/utils/serverId.d.ts.map +1 -1
- package/dist/utils/serverUrl.d.ts +4 -7
- package/dist/utils/serverUrl.d.ts.map +1 -1
- package/package.json +11 -10
- package/src/hooks/useMcpOAuthCallback.test.ts +53 -0
- package/src/hooks/useMcpOAuthCallback.tsx +12 -0
- package/src/index.ts +2 -1
- package/src/primitives/addForm/McpAddFormAccessibility.test.tsx +49 -0
- package/src/primitives/addForm/McpAddFormAuthFields.tsx +7 -15
- package/src/primitives/addForm/McpAddFormBearerTokenField.tsx +46 -0
- package/src/primitives/addForm/McpAddFormRoot.test.tsx +65 -0
- package/src/primitives/addForm/McpAddFormScopesField.tsx +34 -0
- package/src/primitives/addForm.ts +2 -0
- package/src/primitives/elicitation/prepareElicitationContent.ts +8 -6
- package/src/resources/McpManagerResource.test.ts +85 -0
- package/src/resources/McpManagerResource.ts +56 -23
- package/src/resources/McpServerResource.test.ts +121 -6
- package/src/resources/McpServerResource.ts +28 -12
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createMcpId } from "../utils/createMcpId.js";
|
|
1
|
+
import { buildHeaders } from "../auth/buildHeaders.js";
|
|
3
2
|
import { hasPersistedCredentials, isAuthStateForServerUrl } from "../utils/serverUrl.js";
|
|
4
3
|
import { clearOAuthProviderAuthState, createOAuthProvider, hasUsableOAuthTokens } from "../auth/createOAuthProvider.js";
|
|
5
|
-
import {
|
|
4
|
+
import { assertValidServerId } from "../utils/serverId.js";
|
|
5
|
+
import { createMcpId } from "../utils/createMcpId.js";
|
|
6
6
|
import { validateElicitationContent } from "./validateElicitationContent.js";
|
|
7
7
|
import { beginMcpServerRemovalFence } from "./McpServerRemovalFence.js";
|
|
8
8
|
import { useEffect, useEffectEvent, useMemo, useRef, useState } from "@assistant-ui/tap/react-shim";
|
|
@@ -46,6 +46,7 @@ const useMcpServerResourceInstance = (props) => {
|
|
|
46
46
|
const clientRef = useRef(null);
|
|
47
47
|
const transportRef = useRef(null);
|
|
48
48
|
const pendingTransportRef = useRef(null);
|
|
49
|
+
const transportGenerationRef = useRef(/* @__PURE__ */ new WeakMap());
|
|
49
50
|
const connectionGenerationRef = useRef(0);
|
|
50
51
|
const pendingAuthValidationRef = useRef(null);
|
|
51
52
|
const elicitationResolversRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -129,17 +130,22 @@ const useMcpServerResourceInstance = (props) => {
|
|
|
129
130
|
unbound: hasPersistedCredentials(state)
|
|
130
131
|
};
|
|
131
132
|
});
|
|
132
|
-
const buildTransport = useEffectEvent(async () => {
|
|
133
|
+
const buildTransport = useEffectEvent(async (generation_0) => {
|
|
133
134
|
if (props.auth.type === "oauth") {
|
|
135
|
+
const generationOwner = { current: generation_0 };
|
|
134
136
|
const authProvider = createOAuthProvider({
|
|
135
137
|
serverId: props.id,
|
|
136
138
|
serverUrl: props.url,
|
|
137
139
|
config: props.auth,
|
|
138
140
|
storage: props.storage,
|
|
139
141
|
redirectUri: props.redirectUri,
|
|
140
|
-
onAuthorizationUrl: (url) =>
|
|
142
|
+
onAuthorizationUrl: (url) => {
|
|
143
|
+
if (isCurrentConnection(generationOwner.current)) setAuthorizationUrl(url.toString());
|
|
144
|
+
}
|
|
141
145
|
});
|
|
142
|
-
|
|
146
|
+
const transport_2 = new StreamableHTTPClientTransport(new URL(props.url), { authProvider });
|
|
147
|
+
transportGenerationRef.current.set(transport_2, generationOwner);
|
|
148
|
+
return transport_2;
|
|
143
149
|
}
|
|
144
150
|
if (props.auth.type === "bearer") {
|
|
145
151
|
const { state: state_0, unbound } = await loadAuthState();
|
|
@@ -161,21 +167,21 @@ const useMcpServerResourceInstance = (props) => {
|
|
|
161
167
|
return info;
|
|
162
168
|
}));
|
|
163
169
|
});
|
|
164
|
-
const syncTools = useEffectEvent(async (client,
|
|
170
|
+
const syncTools = useEffectEvent(async (client, generation_1, options) => {
|
|
165
171
|
const listPromise = client.listTools();
|
|
166
172
|
const list_0 = options?.startedAt === void 0 ? await listPromise : await withConnectionTimeout(listPromise, "listing tools", options.startedAt);
|
|
167
|
-
if (!isCurrentConnection(
|
|
173
|
+
if (!isCurrentConnection(generation_1)) return false;
|
|
168
174
|
applyToolsList(list_0);
|
|
169
175
|
return true;
|
|
170
176
|
});
|
|
171
|
-
const finalizeConnect = useEffectEvent(async (
|
|
177
|
+
const finalizeConnect = useEffectEvent(async (transport_3, generation_2) => {
|
|
172
178
|
const clientOptions = {
|
|
173
179
|
...props.elicitation === false ? {} : { capabilities: { elicitation: {} } },
|
|
174
180
|
listChanged: { tools: {
|
|
175
181
|
autoRefresh: true,
|
|
176
182
|
debounceMs: 300,
|
|
177
183
|
onChanged: (error_0, items) => {
|
|
178
|
-
if (!isCurrentConnection(
|
|
184
|
+
if (!isCurrentConnection(generation_2)) return;
|
|
179
185
|
if (error_0 !== null) {
|
|
180
186
|
setLastError({ message: error_0.message });
|
|
181
187
|
return;
|
|
@@ -192,7 +198,7 @@ const useMcpServerResourceInstance = (props) => {
|
|
|
192
198
|
version: "0.0.0"
|
|
193
199
|
}, clientOptions);
|
|
194
200
|
if (props.elicitation !== false) client_0.setRequestHandler("elicitation/create", (request, context) => {
|
|
195
|
-
if (!isCurrentConnection(
|
|
201
|
+
if (!isCurrentConnection(generation_2)) return Promise.resolve({ action: "cancel" });
|
|
196
202
|
if (!("requestedSchema" in request.params)) return Promise.resolve({ action: "cancel" });
|
|
197
203
|
const { message, requestedSchema } = request.params;
|
|
198
204
|
const id_2 = createMcpId();
|
|
@@ -202,7 +208,7 @@ const useMcpServerResourceInstance = (props) => {
|
|
|
202
208
|
};
|
|
203
209
|
elicitationResolversRef.current.set(id_2, {
|
|
204
210
|
resolve,
|
|
205
|
-
signal: context.signal,
|
|
211
|
+
signal: context.mcpReq.signal,
|
|
206
212
|
onAbort,
|
|
207
213
|
requestedSchema
|
|
208
214
|
});
|
|
@@ -214,49 +220,49 @@ const useMcpServerResourceInstance = (props) => {
|
|
|
214
220
|
}]);
|
|
215
221
|
const entry_0 = elicitationResolversRef.current.get(id_2);
|
|
216
222
|
if (entry_0) {
|
|
217
|
-
if (context.signal.aborted) entry_0.onAbort();
|
|
218
|
-
else context.signal.addEventListener("abort", entry_0.onAbort, { once: true });
|
|
223
|
+
if (context.mcpReq.signal.aborted) entry_0.onAbort();
|
|
224
|
+
else context.mcpReq.signal.addEventListener("abort", entry_0.onAbort, { once: true });
|
|
219
225
|
}
|
|
220
226
|
return promise_0;
|
|
221
227
|
});
|
|
222
228
|
const startedAt_0 = Date.now();
|
|
223
|
-
await withConnectionTimeout(client_0.connect(
|
|
224
|
-
if (!isCurrentConnection(
|
|
225
|
-
if (!await syncTools(client_0,
|
|
229
|
+
await withConnectionTimeout(client_0.connect(transport_3), "connecting", startedAt_0);
|
|
230
|
+
if (!isCurrentConnection(generation_2)) return false;
|
|
231
|
+
if (!await syncTools(client_0, generation_2, { startedAt: startedAt_0 })) return false;
|
|
226
232
|
pendingTransportRef.current = null;
|
|
227
233
|
clientRef.current = client_0;
|
|
228
|
-
transportRef.current =
|
|
234
|
+
transportRef.current = transport_3;
|
|
229
235
|
setConnectionState("connected");
|
|
230
236
|
return true;
|
|
231
237
|
});
|
|
232
238
|
const doConnect = useEffectEvent(async () => {
|
|
233
|
-
const
|
|
239
|
+
const generation_3 = ++connectionGenerationRef.current;
|
|
234
240
|
await closeTransports();
|
|
235
|
-
if (!isCurrentConnection(
|
|
241
|
+
if (!isCurrentConnection(generation_3)) return;
|
|
236
242
|
setConnectionState("connecting");
|
|
237
243
|
setLastError(null);
|
|
238
244
|
setAuthorizationUrl(null);
|
|
239
245
|
setTools([]);
|
|
240
|
-
let
|
|
246
|
+
let transport_4 = null;
|
|
241
247
|
try {
|
|
242
|
-
|
|
243
|
-
if (!isCurrentConnection(
|
|
244
|
-
await closeQueuedTransports([
|
|
248
|
+
transport_4 = await buildTransport(generation_3);
|
|
249
|
+
if (!isCurrentConnection(generation_3)) {
|
|
250
|
+
await closeQueuedTransports([transport_4]);
|
|
245
251
|
return;
|
|
246
252
|
}
|
|
247
|
-
pendingTransportRef.current =
|
|
248
|
-
await finalizeConnect(
|
|
253
|
+
pendingTransportRef.current = transport_4;
|
|
254
|
+
await finalizeConnect(transport_4, generation_3);
|
|
249
255
|
} catch (err) {
|
|
250
|
-
if (!isCurrentConnection(
|
|
256
|
+
if (!isCurrentConnection(generation_3)) return;
|
|
251
257
|
if (err instanceof UnauthorizedError) {
|
|
252
258
|
pendingTransportRef.current = null;
|
|
253
|
-
transportRef.current =
|
|
259
|
+
transportRef.current = transport_4;
|
|
254
260
|
setConnectionState("authRequired");
|
|
255
261
|
} else {
|
|
256
262
|
cancelPendingElicitations();
|
|
257
|
-
if (
|
|
263
|
+
if (transport_4) {
|
|
258
264
|
pendingTransportRef.current = null;
|
|
259
|
-
await closeQueuedTransports([
|
|
265
|
+
await closeQueuedTransports([transport_4]);
|
|
260
266
|
}
|
|
261
267
|
setLastError({ message: err instanceof Error ? err.message : String(err) });
|
|
262
268
|
setConnectionState("error");
|
|
@@ -302,31 +308,33 @@ const useMcpServerResourceInstance = (props) => {
|
|
|
302
308
|
pendingAuthValidation.resolve();
|
|
303
309
|
}
|
|
304
310
|
}
|
|
305
|
-
const
|
|
311
|
+
const generation_4 = ++connectionGenerationRef.current;
|
|
306
312
|
cancelPendingElicitations();
|
|
307
313
|
await closePendingTransport();
|
|
308
|
-
if (!isCurrentConnection(
|
|
314
|
+
if (!isCurrentConnection(generation_4)) throw createInterruptedAuthError();
|
|
309
315
|
setConnectionState("authPending");
|
|
310
316
|
setLastError(null);
|
|
311
317
|
try {
|
|
312
|
-
let
|
|
313
|
-
if (!
|
|
314
|
-
|
|
315
|
-
if (!isCurrentConnection(
|
|
316
|
-
await closeQueuedTransports([
|
|
318
|
+
let transport_5 = transportRef.current;
|
|
319
|
+
if (!transport_5) {
|
|
320
|
+
transport_5 = await buildTransport(generation_4);
|
|
321
|
+
if (!isCurrentConnection(generation_4)) {
|
|
322
|
+
await closeQueuedTransports([transport_5]);
|
|
317
323
|
throw createInterruptedAuthError();
|
|
318
324
|
}
|
|
319
325
|
}
|
|
326
|
+
const generationOwner_0 = transportGenerationRef.current.get(transport_5);
|
|
327
|
+
if (generationOwner_0) generationOwner_0.current = generation_4;
|
|
320
328
|
transportRef.current = null;
|
|
321
329
|
clientRef.current = null;
|
|
322
|
-
pendingTransportRef.current =
|
|
323
|
-
await
|
|
324
|
-
if (!isCurrentConnection(
|
|
330
|
+
pendingTransportRef.current = transport_5;
|
|
331
|
+
await transport_5.finishAuth(url_0.searchParams);
|
|
332
|
+
if (!isCurrentConnection(generation_4)) throw createInterruptedAuthError();
|
|
325
333
|
setAuthorizationUrl(null);
|
|
326
|
-
if (!await finalizeConnect(
|
|
334
|
+
if (!await finalizeConnect(transport_5, generation_4)) throw createInterruptedAuthError();
|
|
327
335
|
} catch (err_0) {
|
|
328
336
|
const error_1 = err_0 instanceof Error ? err_0 : new Error(String(err_0));
|
|
329
|
-
if (!isCurrentConnection(
|
|
337
|
+
if (!isCurrentConnection(generation_4)) throw createInterruptedAuthError(error_1);
|
|
330
338
|
await closeTransports();
|
|
331
339
|
setLastError({ message: error_1.message });
|
|
332
340
|
setConnectionState("error");
|
|
@@ -343,18 +351,18 @@ const useMcpServerResourceInstance = (props) => {
|
|
|
343
351
|
doConnect();
|
|
344
352
|
return;
|
|
345
353
|
}
|
|
346
|
-
const
|
|
354
|
+
const generation_5 = connectionGenerationRef.current;
|
|
347
355
|
let loaded;
|
|
348
356
|
try {
|
|
349
357
|
loaded = await loadAuthState();
|
|
350
358
|
} catch (error_2) {
|
|
351
|
-
if (signal.cancelled || !isCurrentConnection(
|
|
359
|
+
if (signal.cancelled || !isCurrentConnection(generation_5)) return;
|
|
352
360
|
const message_0 = error_2 instanceof Error ? error_2.message : String(error_2);
|
|
353
361
|
setLastError({ message: `MCP server "${props.id}" failed to load saved authentication: ${message_0}` });
|
|
354
362
|
setConnectionState("error");
|
|
355
363
|
return;
|
|
356
364
|
}
|
|
357
|
-
if (signal.cancelled || !isCurrentConnection(
|
|
365
|
+
if (signal.cancelled || !isCurrentConnection(generation_5)) return;
|
|
358
366
|
if (loaded.unbound) {
|
|
359
367
|
setLastError({ message: unboundAuthMessage() });
|
|
360
368
|
return;
|
|
@@ -366,7 +374,7 @@ const useMcpServerResourceInstance = (props) => {
|
|
|
366
374
|
const pendingAuthValidation_0 = pendingAuthValidationRef.current;
|
|
367
375
|
if (pendingAuthValidation_0) {
|
|
368
376
|
await pendingAuthValidation_0.promise;
|
|
369
|
-
if (signal.cancelled || !isCurrentConnection(
|
|
377
|
+
if (signal.cancelled || !isCurrentConnection(generation_5)) return;
|
|
370
378
|
}
|
|
371
379
|
doConnect();
|
|
372
380
|
});
|
|
@@ -453,7 +461,7 @@ const useMcpServerResourceInstance = (props) => {
|
|
|
453
461
|
answerElicitation: (id_3, response) => {
|
|
454
462
|
if (response.action === "accept") {
|
|
455
463
|
const entry_1 = elicitationResolversRef.current.get(id_3);
|
|
456
|
-
if (!entry_1) return;
|
|
464
|
+
if (!entry_1) return void 0;
|
|
457
465
|
if (typeof response.content !== "object" || response.content === null || Array.isArray(response.content)) {
|
|
458
466
|
const errors = [{
|
|
459
467
|
property: "content",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpServerResource.js","names":["useState","useRef","useEffect","useMemo","useEffectEvent","resource","useResource","withKey","ClientOutput","shallowEqual","Client","StreamableHTTPClientTransport","UnauthorizedError","ClientOptions","ElicitRequest","ElicitResult","StreamableHTTPClientTransportOptions","clearOAuthProviderAuthState","createOAuthProvider","hasUsableOAuthTokens","buildHeaders","assertValidServerId","hasPersistedCredentials","isAuthStateForServerUrl","validateElicitationContent","MCPStorage","MCPAuthConfig","MCPConnectionState","MCPElicitation","MCPElicitationResponse","MCPServerKind","MCPServerState","MCPToolInfo","createMcpId","beginMcpServerRemovalFence","McpServerResourceProps","id","kind","name","url","icon","auth","storage","redirectUri","autoConnect","connectionTimeout","cache","defaultTtlMs","elicitation","onRemove","Promise","McpServerResourceInstanceProps","transportCloseQueueRef","current","getConnectionDependencies","props","authDependencies","type","token","scopeId","scopes","length","authorizationEndpoint","tokenEndpoint","registrationEndpoint","clientId","clientSecret","useMcpServerResourceInstance","connectionState","setConnectionState","tools","setTools","lastError","setLastError","message","authorizationUrl","setAuthorizationUrl","pendingElicitations","setPendingElicitations","clientRef","transportRef","pendingTransportRef","connectionGenerationRef","pendingAuthValidationRef","count","promise","resolve","elicitationResolversRef","Map","result","signal","AbortSignal","onAbort","requestedSchema","pendingDisposalRef","cancelled","mountedRef","closeTransportSafely","transport","close","closeQueuedTransports","transports","task","then","all","map","closePendingTransport","resolvePendingElicitation","entry","get","delete","removeEventListener","filter","setPendingElicitationError","error","NonNullable","has","cancelPendingElicitations","action","detachTransports","pendingTransport","activeTransport","Set","closeTransports","isCurrentConnection","generation","createInterruptedAuthError","cause","Error","undefined","withConnectionTimeout","T","phase","startedAt","timeoutMs","remainingMs","Date","now","timeoutError","timeout","ReturnType","setTimeout","race","_","reject","clearTimeout","unboundAuthMessage","loadAuthState","state","unbound","buildTransport","authProvider","serverId","serverUrl","config","onAuthorizationUrl","toString","URL","headers","transportOpts","requestInit","applyToolsList","list","Array","description","inputSchema","t","info","syncTools","client","options","listPromise","listTools","finalizeConnect","clientOptions","capabilities","listChanged","autoRefresh","debounceMs","onChanged","items","defaultCacheTtlMs","version","setRequestHandler","request","context","params","set","aborted","addEventListener","once","connect","synced","doConnect","err","String","doDisconnect","doCompleteAuth","callbackUrl","validationGeneration","searchParams","pendingAuthValidation","resolvePromise","persisted","finishAuth","connected","tryAutoConnect","loaded","Awaited","previousDisposal","pendingDisposal","queueMicrotask","getState","disconnect","remove","releaseRemovalFence","callTool","args","arguments","Record","listResources","readResource","uri","completeAuth","answerElicitation","response","property","content","isArray","errors","properties","join","McpServerResourceInstance","McpServerResource","useMcpServerResource","dependencies","connection","setConnection","currentConnection"],"sources":["../../src/resources/McpServerResource.ts"],"sourcesContent":["import { useState, useRef, useEffect, useMemo, useEffectEvent } from \"react\";\nimport { resource, useResource, withKey } from \"@assistant-ui/tap\";\nimport type { ClientOutput } from \"@assistant-ui/store\";\nimport { shallowEqual } from \"@assistant-ui/store/internal\";\nimport {\n Client,\n StreamableHTTPClientTransport,\n UnauthorizedError,\n type ClientOptions,\n type ElicitRequest,\n type ElicitResult,\n type StreamableHTTPClientTransportOptions,\n} from \"@modelcontextprotocol/client\";\nimport {\n clearOAuthProviderAuthState,\n createOAuthProvider,\n hasUsableOAuthTokens,\n} from \"../auth/createOAuthProvider\";\nimport { buildHeaders } from \"../auth/buildHeaders\";\nimport { assertValidServerId } from \"../utils/serverId\";\nimport {\n hasPersistedCredentials,\n isAuthStateForServerUrl,\n} from \"../utils/serverUrl\";\nimport { validateElicitationContent } from \"./validateElicitationContent\";\nimport type { MCPStorage } from \"./storage/types\";\nimport type {\n MCPAuthConfig,\n MCPConnectionState,\n MCPElicitation,\n MCPElicitationResponse,\n MCPServerKind,\n MCPServerState,\n MCPToolInfo,\n} from \"../mcp-scope\";\nimport { createMcpId } from \"../utils/createMcpId\";\nimport { beginMcpServerRemovalFence } from \"./McpServerRemovalFence\";\n\nexport type McpServerResourceProps = {\n id: string;\n kind: MCPServerKind;\n name: string;\n url: string;\n icon?: string | undefined;\n auth: MCPAuthConfig;\n storage: MCPStorage;\n redirectUri: string;\n autoConnect: boolean;\n connectionTimeout?: number | undefined;\n cache?: { readonly defaultTtlMs?: number } | undefined;\n readonly elicitation?: boolean;\n onRemove: () => Promise<void>;\n};\n\ntype McpServerResourceInstanceProps = McpServerResourceProps & {\n transportCloseQueueRef: { current: Promise<void> };\n};\n\nexport const getConnectionDependencies = (\n props: McpServerResourceProps,\n): readonly unknown[] => {\n const auth = props.auth;\n const authDependencies =\n auth.type === \"bearer\"\n ? [auth.type, auth.token, props.storage.scopeId]\n : auth.type === \"oauth\"\n ? [\n auth.type,\n auth.scopes?.length,\n ...(auth.scopes ?? []),\n auth.authorizationEndpoint,\n auth.tokenEndpoint,\n auth.registrationEndpoint,\n auth.clientId,\n auth.clientSecret,\n props.storage.scopeId,\n ]\n : [auth.type];\n\n return [\n props.id,\n props.url,\n ...authDependencies,\n props.redirectUri,\n props.cache?.defaultTtlMs,\n props.elicitation !== false,\n ];\n};\n\nconst useMcpServerResourceInstance = (\n props: McpServerResourceInstanceProps,\n): ClientOutput<\"mcpServer\"> => {\n assertValidServerId(props.id);\n const [connectionState, setConnectionState] =\n useState<MCPConnectionState>(\"disconnected\");\n const [tools, setTools] = useState<MCPToolInfo[]>([]);\n const [lastError, setLastError] = useState<{ message: string } | null>(null);\n const [authorizationUrl, setAuthorizationUrl] = useState<string | null>(null);\n const [pendingElicitations, setPendingElicitations] = useState<\n MCPElicitation[]\n >([]);\n\n const clientRef = useRef<Client | null>(null);\n const transportRef = useRef<StreamableHTTPClientTransport | null>(null);\n const pendingTransportRef = useRef<StreamableHTTPClientTransport | null>(\n null,\n );\n const connectionGenerationRef = useRef(0);\n const pendingAuthValidationRef = useRef<{\n count: number;\n promise: Promise<void>;\n resolve: () => void;\n } | null>(null);\n const elicitationResolversRef = useRef(\n new Map<\n string,\n {\n resolve: (result: ElicitResult) => void;\n signal: AbortSignal;\n onAbort: () => void;\n requestedSchema: unknown;\n }\n >(),\n );\n const pendingDisposalRef = useRef<{ cancelled: boolean } | null>(null);\n const mountedRef = useRef(true);\n\n const closeTransportSafely = async (\n transport: StreamableHTTPClientTransport,\n ): Promise<void> => {\n try {\n await transport.close();\n } catch {\n // ignore close errors\n }\n };\n\n const closeQueuedTransports = (\n transports: StreamableHTTPClientTransport[],\n ): Promise<void> => {\n const task = props.transportCloseQueueRef.current.then(async () => {\n await Promise.all(transports.map(closeTransportSafely));\n });\n props.transportCloseQueueRef.current = task;\n return task;\n };\n\n const closePendingTransport = async () => {\n const transport = pendingTransportRef.current;\n pendingTransportRef.current = null;\n await closeQueuedTransports(transport ? [transport] : []);\n };\n\n const resolvePendingElicitation = (id: string, result: ElicitResult) => {\n const entry = elicitationResolversRef.current.get(id);\n if (!entry) return false;\n elicitationResolversRef.current.delete(id);\n entry.signal.removeEventListener(\"abort\", entry.onAbort);\n setPendingElicitations((current) =>\n current.filter((elicitation) => elicitation.id !== id),\n );\n entry.resolve(result);\n return true;\n };\n\n const setPendingElicitationError = (\n id: string,\n error: NonNullable<MCPElicitation[\"error\"]>,\n ) => {\n if (!elicitationResolversRef.current.has(id)) return false;\n setPendingElicitations((current) =>\n current.map((elicitation) =>\n elicitation.id === id ? { ...elicitation, error } : elicitation,\n ),\n );\n return true;\n };\n\n const cancelPendingElicitations = () => {\n for (const [id] of elicitationResolversRef.current) {\n resolvePendingElicitation(id, { action: \"cancel\" });\n }\n };\n\n const detachTransports = () => {\n cancelPendingElicitations();\n const pendingTransport = pendingTransportRef.current;\n const activeTransport = transportRef.current;\n pendingTransportRef.current = null;\n transportRef.current = null;\n clientRef.current = null;\n\n return [\n ...new Set(\n [pendingTransport, activeTransport].filter(\n (transport): transport is StreamableHTTPClientTransport =>\n transport !== null,\n ),\n ),\n ];\n };\n\n const closeTransports = async () => {\n await closeQueuedTransports(detachTransports());\n };\n\n const isCurrentConnection = (generation: number) =>\n mountedRef.current && generation === connectionGenerationRef.current;\n\n const createInterruptedAuthError = (cause?: unknown) =>\n new Error(\n `MCP server \"${props.id}\" authorization was interrupted before completion.`,\n cause === undefined ? undefined : { cause },\n );\n\n const withConnectionTimeout = useEffectEvent(\n async <T>(\n promise: Promise<T>,\n phase: \"connecting\" | \"listing tools\",\n startedAt: number,\n ): Promise<T> => {\n const timeoutMs = props.connectionTimeout;\n if (timeoutMs === undefined) return await promise;\n const remainingMs = timeoutMs - (Date.now() - startedAt);\n const timeoutError = () =>\n new Error(\n `MCP server \"${props.id}\" timed out while ${phase} after ${timeoutMs}ms.`,\n );\n if (remainingMs <= 0) throw timeoutError();\n\n let timeout: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timeout = setTimeout(() => reject(timeoutError()), remainingMs);\n }),\n ]);\n } finally {\n if (timeout !== undefined) clearTimeout(timeout);\n }\n },\n );\n\n const unboundAuthMessage = () =>\n `MCP server \"${props.id}\" has saved authentication for a different URL. Authenticate again to connect to ${props.url}.`;\n\n const loadAuthState = useEffectEvent(async () => {\n const state = await props.storage.loadAuthState(props.id);\n if (isAuthStateForServerUrl(state, props.url)) {\n return { state, unbound: false };\n }\n return { state: null, unbound: hasPersistedCredentials(state) };\n });\n\n const buildTransport = useEffectEvent(\n async (): Promise<StreamableHTTPClientTransport> => {\n if (props.auth.type === \"oauth\") {\n const authProvider = createOAuthProvider({\n serverId: props.id,\n serverUrl: props.url,\n config: props.auth,\n storage: props.storage,\n redirectUri: props.redirectUri,\n onAuthorizationUrl: (url) => setAuthorizationUrl(url.toString()),\n });\n return new StreamableHTTPClientTransport(new URL(props.url), {\n authProvider,\n });\n }\n if (props.auth.type === \"bearer\") {\n const { state, unbound } = await loadAuthState();\n const headers = buildHeaders(props.auth, state);\n if (!headers && unbound) throw new Error(unboundAuthMessage());\n const transportOpts: StreamableHTTPClientTransportOptions = {};\n if (headers) transportOpts.requestInit = { headers };\n return new StreamableHTTPClientTransport(\n new URL(props.url),\n transportOpts,\n );\n }\n return new StreamableHTTPClientTransport(new URL(props.url));\n },\n );\n\n const applyToolsList = useEffectEvent(\n (list: {\n tools: Array<{\n name: string;\n description?: string | undefined;\n inputSchema: unknown;\n }>;\n }) => {\n setTools(\n list.tools.map((t) => {\n const info: MCPToolInfo = {\n name: t.name,\n inputSchema: t.inputSchema,\n };\n if (t.description !== undefined) info.description = t.description;\n return info;\n }),\n );\n },\n );\n\n const syncTools = useEffectEvent(\n async (\n client: Client,\n generation: number,\n options?: { startedAt?: number | undefined },\n ): Promise<boolean> => {\n const listPromise = client.listTools();\n const list =\n options?.startedAt === undefined\n ? await listPromise\n : await withConnectionTimeout(\n listPromise,\n \"listing tools\",\n options.startedAt,\n );\n if (!isCurrentConnection(generation)) return false;\n applyToolsList(list);\n return true;\n },\n );\n\n const finalizeConnect = useEffectEvent(\n async (\n transport: StreamableHTTPClientTransport,\n generation: number,\n ): Promise<boolean> => {\n const clientOptions: ClientOptions = {\n ...(props.elicitation === false\n ? {}\n : { capabilities: { elicitation: {} } }),\n listChanged: {\n tools: {\n autoRefresh: true,\n debounceMs: 300,\n onChanged: (error, items) => {\n if (!isCurrentConnection(generation)) return;\n if (error !== null) {\n setLastError({ message: error.message });\n return;\n }\n if (items === null) return;\n setLastError(null);\n applyToolsList({ tools: items });\n },\n },\n },\n };\n if (props.cache?.defaultTtlMs !== undefined) {\n clientOptions.defaultCacheTtlMs = props.cache.defaultTtlMs;\n }\n const client = new Client(\n {\n name: \"assistant-ui-mcp\",\n version: \"0.0.0\",\n },\n clientOptions,\n );\n if (props.elicitation !== false) {\n client.setRequestHandler(\n \"elicitation/create\",\n (request: ElicitRequest, context): Promise<ElicitResult> => {\n if (!isCurrentConnection(generation)) {\n return Promise.resolve({ action: \"cancel\" });\n }\n if (!(\"requestedSchema\" in request.params)) {\n return Promise.resolve({ action: \"cancel\" });\n }\n const { message, requestedSchema } = request.params;\n\n const id = createMcpId();\n const promise = new Promise<ElicitResult>((resolve) => {\n const onAbort = () => {\n resolvePendingElicitation(id, { action: \"cancel\" });\n };\n elicitationResolversRef.current.set(id, {\n resolve,\n signal: context.signal,\n onAbort,\n requestedSchema,\n });\n });\n setPendingElicitations((current) => [\n ...current,\n {\n id,\n message,\n requestedSchema,\n },\n ]);\n const entry = elicitationResolversRef.current.get(id);\n if (entry) {\n if (context.signal.aborted) {\n entry.onAbort();\n } else {\n context.signal.addEventListener(\"abort\", entry.onAbort, {\n once: true,\n });\n }\n }\n return promise;\n },\n );\n }\n const startedAt = Date.now();\n await withConnectionTimeout(\n client.connect(transport),\n \"connecting\",\n startedAt,\n );\n if (!isCurrentConnection(generation)) return false;\n // Defer ref assignment until listTools() also succeeds — otherwise a\n // post-connect failure leaves stale refs that `callTool()` would\n // happily walk into, producing confusing SDK errors instead of\n // \"not connected\".\n const synced = await syncTools(client, generation, { startedAt });\n if (!synced) return false;\n\n pendingTransportRef.current = null;\n clientRef.current = client;\n transportRef.current = transport;\n setConnectionState(\"connected\");\n return true;\n },\n );\n\n const doConnect = useEffectEvent(async () => {\n const generation = ++connectionGenerationRef.current;\n // Close any prior transport/client so a re-connect doesn't leak.\n await closeTransports();\n if (!isCurrentConnection(generation)) return;\n\n setConnectionState(\"connecting\");\n setLastError(null);\n setAuthorizationUrl(null);\n // Clear tools so a reconnect (error → connect, or authRequired\n // → connect) doesn't expose the previous attempt's tool list.\n setTools([]);\n let transport: StreamableHTTPClientTransport | null = null;\n try {\n transport = await buildTransport();\n if (!isCurrentConnection(generation)) {\n await closeQueuedTransports([transport]);\n return;\n }\n pendingTransportRef.current = transport;\n // Don't assign to transportRef until connect succeeds — otherwise a\n // failed `listTools()` leaves an orphaned transport that future\n // doConnect / doDisconnect calls treat as live.\n await finalizeConnect(transport, generation);\n } catch (err) {\n if (!isCurrentConnection(generation)) return;\n\n if (err instanceof UnauthorizedError) {\n // OAuth: keep the transport alive so completeAuth can call\n // finishAuth on it. Closing it before storing would leave a\n // closed transport on transportRef.\n pendingTransportRef.current = null;\n transportRef.current = transport;\n setConnectionState(\"authRequired\");\n } else {\n cancelPendingElicitations();\n if (transport) {\n pendingTransportRef.current = null;\n await closeQueuedTransports([transport]);\n }\n setLastError({\n message: err instanceof Error ? err.message : String(err),\n });\n setConnectionState(\"error\");\n }\n }\n });\n\n const doDisconnect = useEffectEvent(async () => {\n connectionGenerationRef.current += 1;\n setTools([]);\n setAuthorizationUrl(null);\n setConnectionState(\"disconnected\");\n await closeTransports();\n });\n\n const doCompleteAuth = useEffectEvent(async (callbackUrl: string) => {\n const validationGeneration = connectionGenerationRef.current;\n const url = new URL(callbackUrl);\n const state = url.searchParams.get(\"state\");\n if (!state) throw new Error('missing \"state\" parameter');\n let pendingAuthValidation = pendingAuthValidationRef.current;\n if (!pendingAuthValidation) {\n let resolve!: () => void;\n const promise = new Promise<void>((resolvePromise) => {\n resolve = resolvePromise;\n });\n pendingAuthValidation = { count: 0, promise, resolve };\n pendingAuthValidationRef.current = pendingAuthValidation;\n }\n pendingAuthValidation.count += 1;\n try {\n const { state: persisted, unbound } = await loadAuthState();\n if (!isCurrentConnection(validationGeneration)) {\n throw createInterruptedAuthError();\n }\n if (unbound) throw new Error(unboundAuthMessage());\n if (!persisted?.state) {\n throw new Error(\n \"no pending OAuth authorization request for this server\",\n );\n }\n if (persisted.state !== state) {\n throw new Error(\"OAuth state does not match the authorization request\");\n }\n if (!url.searchParams.get(\"code\") && !url.searchParams.get(\"error\")) {\n throw new Error(\"missing authorization code in callback URL\");\n }\n } finally {\n pendingAuthValidation.count -= 1;\n if (pendingAuthValidation.count === 0) {\n pendingAuthValidationRef.current = null;\n pendingAuthValidation.resolve();\n }\n }\n\n // Claim the generation before a waiting auto-connect can resume.\n const generation = ++connectionGenerationRef.current;\n cancelPendingElicitations();\n await closePendingTransport();\n if (!isCurrentConnection(generation)) throw createInterruptedAuthError();\n\n setConnectionState(\"authPending\");\n setLastError(null);\n try {\n let transport = transportRef.current;\n if (!transport) {\n transport = await buildTransport();\n if (!isCurrentConnection(generation)) {\n await closeQueuedTransports([transport]);\n throw createInterruptedAuthError();\n }\n }\n transportRef.current = null;\n clientRef.current = null;\n pendingTransportRef.current = transport;\n await transport.finishAuth(url.searchParams);\n if (!isCurrentConnection(generation)) throw createInterruptedAuthError();\n setAuthorizationUrl(null);\n const connected = await finalizeConnect(transport, generation);\n if (!connected) throw createInterruptedAuthError();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n if (!isCurrentConnection(generation))\n throw createInterruptedAuthError(error);\n\n await closeTransports();\n setLastError({\n message: error.message,\n });\n setConnectionState(\"error\");\n throw error;\n }\n });\n\n const tryAutoConnect = useEffectEvent(\n async (signal: { cancelled: boolean }) => {\n if (!props.autoConnect) return;\n if (props.auth.type === \"none\") {\n void doConnect();\n return;\n }\n // Static connector token short-circuits the storage read.\n if (props.auth.type === \"bearer\" && props.auth.token) {\n void doConnect();\n return;\n }\n const generation = connectionGenerationRef.current;\n let loaded: Awaited<ReturnType<typeof loadAuthState>>;\n try {\n loaded = await loadAuthState();\n } catch (error) {\n if (signal.cancelled || !isCurrentConnection(generation)) return;\n const message = error instanceof Error ? error.message : String(error);\n setLastError({\n message: `MCP server \"${props.id}\" failed to load saved authentication: ${message}`,\n });\n setConnectionState(\"error\");\n return;\n }\n if (signal.cancelled || !isCurrentConnection(generation)) return;\n if (loaded.unbound) {\n setLastError({ message: unboundAuthMessage() });\n return;\n }\n const persisted = loaded.state;\n if (props.auth.type === \"oauth\") {\n if (!hasUsableOAuthTokens(persisted, props.auth)) return;\n } else if (!persisted?.token) {\n return;\n }\n const pendingAuthValidation = pendingAuthValidationRef.current;\n if (pendingAuthValidation) {\n await pendingAuthValidation.promise;\n if (signal.cancelled || !isCurrentConnection(generation)) return;\n }\n void doConnect();\n },\n );\n\n // Auto-connect on mount when usable auth exists.\n useEffect(() => {\n const transportCloseQueueRef = props.transportCloseQueueRef;\n const previousDisposal = pendingDisposalRef.current;\n if (previousDisposal) previousDisposal.cancelled = true;\n const pendingDisposal = { cancelled: false };\n pendingDisposalRef.current = pendingDisposal;\n mountedRef.current = true;\n const signal = { cancelled: false };\n // Auto-connect opens a transport, so it belongs to the same effect as the\n // disposal that closes it.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n void tryAutoConnect(signal);\n return () => {\n mountedRef.current = false;\n signal.cancelled = true;\n const task = transportCloseQueueRef.current.then(async () => {\n await new Promise<void>((resolve) => queueMicrotask(resolve));\n if (pendingDisposal.cancelled) return;\n connectionGenerationRef.current += 1;\n await Promise.all(detachTransports().map(closeTransportSafely));\n });\n transportCloseQueueRef.current = task;\n };\n }, [props.transportCloseQueueRef]);\n\n const state = useMemo<MCPServerState>(\n () => ({\n id: props.id,\n kind: props.kind,\n name: props.name,\n url: props.url,\n icon: props.icon,\n connectionState,\n lastError,\n tools,\n authorizationUrl,\n pendingElicitations,\n }),\n [\n props.id,\n props.kind,\n props.name,\n props.url,\n props.icon,\n connectionState,\n lastError,\n tools,\n authorizationUrl,\n pendingElicitations,\n ],\n );\n\n return {\n getState: () => state,\n connect: doConnect,\n disconnect: doDisconnect,\n remove: async () => {\n const releaseRemovalFence = beginMcpServerRemovalFence(props);\n try {\n await doDisconnect();\n await clearOAuthProviderAuthState(props.storage, props.id);\n await props.onRemove();\n } catch (err) {\n releaseRemovalFence?.();\n setLastError({\n message: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n releaseRemovalFence?.();\n },\n callTool: async (name, args) => {\n const client = clientRef.current;\n if (!client) {\n throw new Error(`MCP server \"${props.id}\" is not connected`);\n }\n return await client.callTool({\n name,\n arguments: args as Record<string, unknown> | undefined,\n });\n },\n listResources: async (params) => {\n const client = clientRef.current;\n if (!client) {\n throw new Error(`MCP server \"${props.id}\" is not connected`);\n }\n return await client.listResources(params);\n },\n readResource: async (uri) => {\n const client = clientRef.current;\n if (!client) {\n throw new Error(`MCP server \"${props.id}\" is not connected`);\n }\n return await client.readResource({ uri });\n },\n completeAuth: doCompleteAuth,\n answerElicitation: (\n id: string,\n response: MCPElicitationResponse,\n ): readonly { property: string; message: string }[] | undefined => {\n if (response.action === \"accept\") {\n const entry = elicitationResolversRef.current.get(id);\n if (!entry) return;\n\n if (\n typeof response.content !== \"object\" ||\n response.content === null ||\n Array.isArray(response.content)\n ) {\n const errors = [\n {\n property: \"content\",\n message: \"Response content must be an object.\",\n },\n ];\n setPendingElicitationError(id, {\n message: \"Invalid elicitation content: content.\",\n properties: [\"content\"],\n });\n return errors;\n }\n\n const errors = validateElicitationContent(\n entry.requestedSchema,\n response.content,\n );\n if (errors.length > 0) {\n const properties = [\n ...new Set(errors.map((error) => error.property)),\n ];\n setPendingElicitationError(id, {\n message: `Invalid elicitation content: ${properties.join(\", \")}.`,\n properties,\n });\n return errors;\n }\n\n const result: ElicitResult = {\n action: \"accept\",\n content: response.content as ElicitResult[\"content\"],\n };\n resolvePendingElicitation(id, result);\n return;\n }\n\n resolvePendingElicitation(id, { action: response.action });\n },\n };\n};\n\nconst McpServerResourceInstance = resource(useMcpServerResourceInstance);\n\nexport const McpServerResource = resource(function useMcpServerResource(\n props: McpServerResourceProps,\n): ClientOutput<\"mcpServer\"> {\n const transportCloseQueueRef = useRef(Promise.resolve());\n const dependencies = getConnectionDependencies(props);\n const [connection, setConnection] = useState({ dependencies, generation: 0 });\n let currentConnection = connection;\n if (!shallowEqual(connection.dependencies, dependencies)) {\n currentConnection = {\n dependencies,\n generation: connection.generation + 1,\n };\n setConnection(currentConnection);\n }\n\n // Storage keys remounts through its optional scopeId rather than object\n // identity, because a defaulted storage element is rebuilt on ordinary\n // renders.\n return useResource(\n withKey(\n currentConnection.generation,\n McpServerResourceInstance({ ...props, transportCloseQueueRef }),\n ),\n );\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"McpServerResource.js","names":["useState","useRef","useEffect","useMemo","useEffectEvent","resource","useResource","withKey","ClientOutput","shallowEqual","Client","StreamableHTTPClientTransport","UnauthorizedError","ClientOptions","ElicitRequest","ElicitResult","StreamableHTTPClientTransportOptions","clearOAuthProviderAuthState","createOAuthProvider","hasUsableOAuthTokens","buildHeaders","assertValidServerId","hasPersistedCredentials","isAuthStateForServerUrl","validateElicitationContent","MCPStorage","MCPAuthConfig","MCPConnectionState","MCPElicitation","MCPElicitationResponse","MCPServerKind","MCPServerState","MCPToolInfo","createMcpId","beginMcpServerRemovalFence","McpServerResourceProps","id","kind","name","url","icon","auth","storage","redirectUri","autoConnect","connectionTimeout","cache","defaultTtlMs","elicitation","onRemove","Promise","McpServerResourceInstanceProps","transportCloseQueueRef","current","getConnectionDependencies","props","authDependencies","type","token","scopeId","scopes","length","authorizationEndpoint","tokenEndpoint","registrationEndpoint","clientId","clientSecret","useMcpServerResourceInstance","connectionState","setConnectionState","tools","setTools","lastError","setLastError","message","authorizationUrl","setAuthorizationUrl","pendingElicitations","setPendingElicitations","clientRef","transportRef","pendingTransportRef","transportGenerationRef","WeakMap","connectionGenerationRef","pendingAuthValidationRef","count","promise","resolve","elicitationResolversRef","Map","result","signal","AbortSignal","onAbort","requestedSchema","pendingDisposalRef","cancelled","mountedRef","closeTransportSafely","transport","close","closeQueuedTransports","transports","task","then","all","map","closePendingTransport","resolvePendingElicitation","entry","get","delete","removeEventListener","filter","setPendingElicitationError","error","NonNullable","has","cancelPendingElicitations","action","detachTransports","pendingTransport","activeTransport","Set","closeTransports","isCurrentConnection","generation","createInterruptedAuthError","cause","Error","undefined","withConnectionTimeout","T","phase","startedAt","timeoutMs","remainingMs","Date","now","timeoutError","timeout","ReturnType","setTimeout","race","_","reject","clearTimeout","unboundAuthMessage","loadAuthState","state","unbound","buildTransport","generationOwner","authProvider","serverId","serverUrl","config","onAuthorizationUrl","toString","URL","set","headers","transportOpts","requestInit","applyToolsList","list","Array","description","inputSchema","t","info","syncTools","client","options","listPromise","listTools","finalizeConnect","clientOptions","capabilities","listChanged","autoRefresh","debounceMs","onChanged","items","defaultCacheTtlMs","version","setRequestHandler","request","context","params","mcpReq","aborted","addEventListener","once","connect","synced","doConnect","err","String","doDisconnect","doCompleteAuth","callbackUrl","validationGeneration","searchParams","pendingAuthValidation","resolvePromise","persisted","finishAuth","connected","tryAutoConnect","loaded","Awaited","previousDisposal","pendingDisposal","queueMicrotask","getState","disconnect","remove","releaseRemovalFence","callTool","args","arguments","Record","listResources","readResource","uri","completeAuth","answerElicitation","response","property","content","isArray","errors","properties","join","McpServerResourceInstance","McpServerResource","useMcpServerResource","dependencies","connection","setConnection","currentConnection"],"sources":["../../src/resources/McpServerResource.ts"],"sourcesContent":["import { useState, useRef, useEffect, useMemo, useEffectEvent } from \"react\";\nimport { resource, useResource, withKey } from \"@assistant-ui/tap\";\nimport type { ClientOutput } from \"@assistant-ui/store\";\nimport { shallowEqual } from \"@assistant-ui/store/internal\";\nimport {\n Client,\n StreamableHTTPClientTransport,\n UnauthorizedError,\n type ClientOptions,\n type ElicitRequest,\n type ElicitResult,\n type StreamableHTTPClientTransportOptions,\n} from \"@modelcontextprotocol/client\";\nimport {\n clearOAuthProviderAuthState,\n createOAuthProvider,\n hasUsableOAuthTokens,\n} from \"../auth/createOAuthProvider\";\nimport { buildHeaders } from \"../auth/buildHeaders\";\nimport { assertValidServerId } from \"../utils/serverId\";\nimport {\n hasPersistedCredentials,\n isAuthStateForServerUrl,\n} from \"../utils/serverUrl\";\nimport { validateElicitationContent } from \"./validateElicitationContent\";\nimport type { MCPStorage } from \"./storage/types\";\nimport type {\n MCPAuthConfig,\n MCPConnectionState,\n MCPElicitation,\n MCPElicitationResponse,\n MCPServerKind,\n MCPServerState,\n MCPToolInfo,\n} from \"../mcp-scope\";\nimport { createMcpId } from \"../utils/createMcpId\";\nimport { beginMcpServerRemovalFence } from \"./McpServerRemovalFence\";\n\nexport type McpServerResourceProps = {\n id: string;\n kind: MCPServerKind;\n name: string;\n url: string;\n icon?: string | undefined;\n auth: MCPAuthConfig;\n storage: MCPStorage;\n redirectUri: string;\n autoConnect: boolean;\n connectionTimeout?: number | undefined;\n cache?: { readonly defaultTtlMs?: number } | undefined;\n readonly elicitation?: boolean;\n onRemove: () => Promise<void>;\n};\n\ntype McpServerResourceInstanceProps = McpServerResourceProps & {\n transportCloseQueueRef: { current: Promise<void> };\n};\n\nexport const getConnectionDependencies = (\n props: McpServerResourceProps,\n): readonly unknown[] => {\n const auth = props.auth;\n const authDependencies =\n auth.type === \"bearer\"\n ? [auth.type, auth.token, props.storage.scopeId]\n : auth.type === \"oauth\"\n ? [\n auth.type,\n auth.scopes?.length,\n ...(auth.scopes ?? []),\n auth.authorizationEndpoint,\n auth.tokenEndpoint,\n auth.registrationEndpoint,\n auth.clientId,\n auth.clientSecret,\n props.storage.scopeId,\n ]\n : [auth.type];\n\n return [\n props.id,\n props.url,\n ...authDependencies,\n props.redirectUri,\n props.cache?.defaultTtlMs,\n props.elicitation !== false,\n ];\n};\n\nconst useMcpServerResourceInstance = (\n props: McpServerResourceInstanceProps,\n): ClientOutput<\"mcpServer\"> => {\n assertValidServerId(props.id);\n const [connectionState, setConnectionState] =\n useState<MCPConnectionState>(\"disconnected\");\n const [tools, setTools] = useState<MCPToolInfo[]>([]);\n const [lastError, setLastError] = useState<{ message: string } | null>(null);\n const [authorizationUrl, setAuthorizationUrl] = useState<string | null>(null);\n const [pendingElicitations, setPendingElicitations] = useState<\n MCPElicitation[]\n >([]);\n\n const clientRef = useRef<Client | null>(null);\n const transportRef = useRef<StreamableHTTPClientTransport | null>(null);\n const pendingTransportRef = useRef<StreamableHTTPClientTransport | null>(\n null,\n );\n const transportGenerationRef = useRef(\n new WeakMap<StreamableHTTPClientTransport, { current: number }>(),\n );\n const connectionGenerationRef = useRef(0);\n const pendingAuthValidationRef = useRef<{\n count: number;\n promise: Promise<void>;\n resolve: () => void;\n } | null>(null);\n const elicitationResolversRef = useRef(\n new Map<\n string,\n {\n resolve: (result: ElicitResult) => void;\n signal: AbortSignal;\n onAbort: () => void;\n requestedSchema: unknown;\n }\n >(),\n );\n const pendingDisposalRef = useRef<{ cancelled: boolean } | null>(null);\n const mountedRef = useRef(true);\n\n const closeTransportSafely = async (\n transport: StreamableHTTPClientTransport,\n ): Promise<void> => {\n try {\n await transport.close();\n } catch {\n // ignore close errors\n }\n };\n\n const closeQueuedTransports = (\n transports: StreamableHTTPClientTransport[],\n ): Promise<void> => {\n const task = props.transportCloseQueueRef.current.then(async () => {\n await Promise.all(transports.map(closeTransportSafely));\n });\n props.transportCloseQueueRef.current = task;\n return task;\n };\n\n const closePendingTransport = async () => {\n const transport = pendingTransportRef.current;\n pendingTransportRef.current = null;\n await closeQueuedTransports(transport ? [transport] : []);\n };\n\n const resolvePendingElicitation = (id: string, result: ElicitResult) => {\n const entry = elicitationResolversRef.current.get(id);\n if (!entry) return false;\n elicitationResolversRef.current.delete(id);\n entry.signal.removeEventListener(\"abort\", entry.onAbort);\n setPendingElicitations((current) =>\n current.filter((elicitation) => elicitation.id !== id),\n );\n entry.resolve(result);\n return true;\n };\n\n const setPendingElicitationError = (\n id: string,\n error: NonNullable<MCPElicitation[\"error\"]>,\n ) => {\n if (!elicitationResolversRef.current.has(id)) return false;\n setPendingElicitations((current) =>\n current.map((elicitation) =>\n elicitation.id === id ? { ...elicitation, error } : elicitation,\n ),\n );\n return true;\n };\n\n const cancelPendingElicitations = () => {\n for (const [id] of elicitationResolversRef.current) {\n resolvePendingElicitation(id, { action: \"cancel\" });\n }\n };\n\n const detachTransports = () => {\n cancelPendingElicitations();\n const pendingTransport = pendingTransportRef.current;\n const activeTransport = transportRef.current;\n pendingTransportRef.current = null;\n transportRef.current = null;\n clientRef.current = null;\n\n return [\n ...new Set(\n [pendingTransport, activeTransport].filter(\n (transport): transport is StreamableHTTPClientTransport =>\n transport !== null,\n ),\n ),\n ];\n };\n\n const closeTransports = async () => {\n await closeQueuedTransports(detachTransports());\n };\n\n const isCurrentConnection = (generation: number) =>\n mountedRef.current && generation === connectionGenerationRef.current;\n\n const createInterruptedAuthError = (cause?: unknown) =>\n new Error(\n `MCP server \"${props.id}\" authorization was interrupted before completion.`,\n cause === undefined ? undefined : { cause },\n );\n\n const withConnectionTimeout = useEffectEvent(\n async <T>(\n promise: Promise<T>,\n phase: \"connecting\" | \"listing tools\",\n startedAt: number,\n ): Promise<T> => {\n const timeoutMs = props.connectionTimeout;\n if (timeoutMs === undefined) return await promise;\n const remainingMs = timeoutMs - (Date.now() - startedAt);\n const timeoutError = () =>\n new Error(\n `MCP server \"${props.id}\" timed out while ${phase} after ${timeoutMs}ms.`,\n );\n if (remainingMs <= 0) throw timeoutError();\n\n let timeout: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timeout = setTimeout(() => reject(timeoutError()), remainingMs);\n }),\n ]);\n } finally {\n if (timeout !== undefined) clearTimeout(timeout);\n }\n },\n );\n\n const unboundAuthMessage = () =>\n `MCP server \"${props.id}\" has saved authentication for a different URL. Authenticate again to connect to ${props.url}.`;\n\n const loadAuthState = useEffectEvent(async () => {\n const state = await props.storage.loadAuthState(props.id);\n if (isAuthStateForServerUrl(state, props.url)) {\n return { state, unbound: false };\n }\n return { state: null, unbound: hasPersistedCredentials(state) };\n });\n\n const buildTransport = useEffectEvent(\n async (generation: number): Promise<StreamableHTTPClientTransport> => {\n if (props.auth.type === \"oauth\") {\n const generationOwner = { current: generation };\n const authProvider = createOAuthProvider({\n serverId: props.id,\n serverUrl: props.url,\n config: props.auth,\n storage: props.storage,\n redirectUri: props.redirectUri,\n onAuthorizationUrl: (url) => {\n if (isCurrentConnection(generationOwner.current)) {\n setAuthorizationUrl(url.toString());\n }\n },\n });\n const transport = new StreamableHTTPClientTransport(\n new URL(props.url),\n {\n authProvider,\n },\n );\n transportGenerationRef.current.set(transport, generationOwner);\n return transport;\n }\n if (props.auth.type === \"bearer\") {\n const { state, unbound } = await loadAuthState();\n const headers = buildHeaders(props.auth, state);\n if (!headers && unbound) throw new Error(unboundAuthMessage());\n const transportOpts: StreamableHTTPClientTransportOptions = {};\n if (headers) transportOpts.requestInit = { headers };\n return new StreamableHTTPClientTransport(\n new URL(props.url),\n transportOpts,\n );\n }\n return new StreamableHTTPClientTransport(new URL(props.url));\n },\n );\n\n const applyToolsList = useEffectEvent(\n (list: {\n tools: Array<{\n name: string;\n description?: string | undefined;\n inputSchema: unknown;\n }>;\n }) => {\n setTools(\n list.tools.map((t) => {\n const info: MCPToolInfo = {\n name: t.name,\n inputSchema: t.inputSchema,\n };\n if (t.description !== undefined) info.description = t.description;\n return info;\n }),\n );\n },\n );\n\n const syncTools = useEffectEvent(\n async (\n client: Client,\n generation: number,\n options?: { startedAt?: number | undefined },\n ): Promise<boolean> => {\n const listPromise = client.listTools();\n const list =\n options?.startedAt === undefined\n ? await listPromise\n : await withConnectionTimeout(\n listPromise,\n \"listing tools\",\n options.startedAt,\n );\n if (!isCurrentConnection(generation)) return false;\n applyToolsList(list);\n return true;\n },\n );\n\n const finalizeConnect = useEffectEvent(\n async (\n transport: StreamableHTTPClientTransport,\n generation: number,\n ): Promise<boolean> => {\n const clientOptions: ClientOptions = {\n ...(props.elicitation === false\n ? {}\n : { capabilities: { elicitation: {} } }),\n listChanged: {\n tools: {\n autoRefresh: true,\n debounceMs: 300,\n onChanged: (error, items) => {\n if (!isCurrentConnection(generation)) return;\n if (error !== null) {\n setLastError({ message: error.message });\n return;\n }\n if (items === null) return;\n setLastError(null);\n applyToolsList({ tools: items });\n },\n },\n },\n };\n if (props.cache?.defaultTtlMs !== undefined) {\n clientOptions.defaultCacheTtlMs = props.cache.defaultTtlMs;\n }\n const client = new Client(\n {\n name: \"assistant-ui-mcp\",\n version: \"0.0.0\",\n },\n clientOptions,\n );\n if (props.elicitation !== false) {\n client.setRequestHandler(\n \"elicitation/create\",\n (request: ElicitRequest, context): Promise<ElicitResult> => {\n if (!isCurrentConnection(generation)) {\n return Promise.resolve({ action: \"cancel\" });\n }\n if (!(\"requestedSchema\" in request.params)) {\n return Promise.resolve({ action: \"cancel\" });\n }\n const { message, requestedSchema } = request.params;\n\n const id = createMcpId();\n const promise = new Promise<ElicitResult>((resolve) => {\n const onAbort = () => {\n resolvePendingElicitation(id, { action: \"cancel\" });\n };\n elicitationResolversRef.current.set(id, {\n resolve,\n signal: context.mcpReq.signal,\n onAbort,\n requestedSchema,\n });\n });\n setPendingElicitations((current) => [\n ...current,\n {\n id,\n message,\n requestedSchema,\n },\n ]);\n const entry = elicitationResolversRef.current.get(id);\n if (entry) {\n if (context.mcpReq.signal.aborted) {\n entry.onAbort();\n } else {\n context.mcpReq.signal.addEventListener(\"abort\", entry.onAbort, {\n once: true,\n });\n }\n }\n return promise;\n },\n );\n }\n const startedAt = Date.now();\n await withConnectionTimeout(\n client.connect(transport),\n \"connecting\",\n startedAt,\n );\n if (!isCurrentConnection(generation)) return false;\n // Defer ref assignment until listTools() also succeeds — otherwise a\n // post-connect failure leaves stale refs that `callTool()` would\n // happily walk into, producing confusing SDK errors instead of\n // \"not connected\".\n const synced = await syncTools(client, generation, { startedAt });\n if (!synced) return false;\n\n pendingTransportRef.current = null;\n clientRef.current = client;\n transportRef.current = transport;\n setConnectionState(\"connected\");\n return true;\n },\n );\n\n const doConnect = useEffectEvent(async () => {\n const generation = ++connectionGenerationRef.current;\n // Close any prior transport/client so a re-connect doesn't leak.\n await closeTransports();\n if (!isCurrentConnection(generation)) return;\n\n setConnectionState(\"connecting\");\n setLastError(null);\n setAuthorizationUrl(null);\n // Clear tools so a reconnect (error → connect, or authRequired\n // → connect) doesn't expose the previous attempt's tool list.\n setTools([]);\n let transport: StreamableHTTPClientTransport | null = null;\n try {\n transport = await buildTransport(generation);\n if (!isCurrentConnection(generation)) {\n await closeQueuedTransports([transport]);\n return;\n }\n pendingTransportRef.current = transport;\n // Don't assign to transportRef until connect succeeds — otherwise a\n // failed `listTools()` leaves an orphaned transport that future\n // doConnect / doDisconnect calls treat as live.\n await finalizeConnect(transport, generation);\n } catch (err) {\n if (!isCurrentConnection(generation)) return;\n\n if (err instanceof UnauthorizedError) {\n // OAuth: keep the transport alive so completeAuth can call\n // finishAuth on it. Closing it before storing would leave a\n // closed transport on transportRef.\n pendingTransportRef.current = null;\n transportRef.current = transport;\n setConnectionState(\"authRequired\");\n } else {\n cancelPendingElicitations();\n if (transport) {\n pendingTransportRef.current = null;\n await closeQueuedTransports([transport]);\n }\n setLastError({\n message: err instanceof Error ? err.message : String(err),\n });\n setConnectionState(\"error\");\n }\n }\n });\n\n const doDisconnect = useEffectEvent(async () => {\n connectionGenerationRef.current += 1;\n setTools([]);\n setAuthorizationUrl(null);\n setConnectionState(\"disconnected\");\n await closeTransports();\n });\n\n const doCompleteAuth = useEffectEvent(async (callbackUrl: string) => {\n const validationGeneration = connectionGenerationRef.current;\n const url = new URL(callbackUrl);\n const state = url.searchParams.get(\"state\");\n if (!state) throw new Error('missing \"state\" parameter');\n let pendingAuthValidation = pendingAuthValidationRef.current;\n if (!pendingAuthValidation) {\n let resolve!: () => void;\n const promise = new Promise<void>((resolvePromise) => {\n resolve = resolvePromise;\n });\n pendingAuthValidation = { count: 0, promise, resolve };\n pendingAuthValidationRef.current = pendingAuthValidation;\n }\n pendingAuthValidation.count += 1;\n try {\n const { state: persisted, unbound } = await loadAuthState();\n if (!isCurrentConnection(validationGeneration)) {\n throw createInterruptedAuthError();\n }\n if (unbound) throw new Error(unboundAuthMessage());\n if (!persisted?.state) {\n throw new Error(\n \"no pending OAuth authorization request for this server\",\n );\n }\n if (persisted.state !== state) {\n throw new Error(\"OAuth state does not match the authorization request\");\n }\n if (!url.searchParams.get(\"code\") && !url.searchParams.get(\"error\")) {\n throw new Error(\"missing authorization code in callback URL\");\n }\n } finally {\n pendingAuthValidation.count -= 1;\n if (pendingAuthValidation.count === 0) {\n pendingAuthValidationRef.current = null;\n pendingAuthValidation.resolve();\n }\n }\n\n // Claim the generation before a waiting auto-connect can resume.\n const generation = ++connectionGenerationRef.current;\n cancelPendingElicitations();\n await closePendingTransport();\n if (!isCurrentConnection(generation)) throw createInterruptedAuthError();\n\n setConnectionState(\"authPending\");\n setLastError(null);\n try {\n let transport = transportRef.current;\n if (!transport) {\n transport = await buildTransport(generation);\n if (!isCurrentConnection(generation)) {\n await closeQueuedTransports([transport]);\n throw createInterruptedAuthError();\n }\n }\n const generationOwner = transportGenerationRef.current.get(transport);\n if (generationOwner) generationOwner.current = generation;\n transportRef.current = null;\n clientRef.current = null;\n pendingTransportRef.current = transport;\n await transport.finishAuth(url.searchParams);\n if (!isCurrentConnection(generation)) throw createInterruptedAuthError();\n setAuthorizationUrl(null);\n const connected = await finalizeConnect(transport, generation);\n if (!connected) throw createInterruptedAuthError();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n if (!isCurrentConnection(generation))\n throw createInterruptedAuthError(error);\n\n await closeTransports();\n setLastError({\n message: error.message,\n });\n setConnectionState(\"error\");\n throw error;\n }\n });\n\n const tryAutoConnect = useEffectEvent(\n async (signal: { cancelled: boolean }) => {\n if (!props.autoConnect) return;\n if (props.auth.type === \"none\") {\n void doConnect();\n return;\n }\n // Static connector token short-circuits the storage read.\n if (props.auth.type === \"bearer\" && props.auth.token) {\n void doConnect();\n return;\n }\n const generation = connectionGenerationRef.current;\n let loaded: Awaited<ReturnType<typeof loadAuthState>>;\n try {\n loaded = await loadAuthState();\n } catch (error) {\n if (signal.cancelled || !isCurrentConnection(generation)) return;\n const message = error instanceof Error ? error.message : String(error);\n setLastError({\n message: `MCP server \"${props.id}\" failed to load saved authentication: ${message}`,\n });\n setConnectionState(\"error\");\n return;\n }\n if (signal.cancelled || !isCurrentConnection(generation)) return;\n if (loaded.unbound) {\n setLastError({ message: unboundAuthMessage() });\n return;\n }\n const persisted = loaded.state;\n if (props.auth.type === \"oauth\") {\n if (!hasUsableOAuthTokens(persisted, props.auth)) return;\n } else if (!persisted?.token) {\n return;\n }\n const pendingAuthValidation = pendingAuthValidationRef.current;\n if (pendingAuthValidation) {\n await pendingAuthValidation.promise;\n if (signal.cancelled || !isCurrentConnection(generation)) return;\n }\n void doConnect();\n },\n );\n\n // Auto-connect on mount when usable auth exists.\n useEffect(() => {\n const transportCloseQueueRef = props.transportCloseQueueRef;\n const previousDisposal = pendingDisposalRef.current;\n if (previousDisposal) previousDisposal.cancelled = true;\n const pendingDisposal = { cancelled: false };\n pendingDisposalRef.current = pendingDisposal;\n mountedRef.current = true;\n const signal = { cancelled: false };\n // Auto-connect opens a transport, so it belongs to the same effect as the\n // disposal that closes it.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n void tryAutoConnect(signal);\n return () => {\n mountedRef.current = false;\n signal.cancelled = true;\n const task = transportCloseQueueRef.current.then(async () => {\n await new Promise<void>((resolve) => queueMicrotask(resolve));\n if (pendingDisposal.cancelled) return;\n connectionGenerationRef.current += 1;\n await Promise.all(detachTransports().map(closeTransportSafely));\n });\n transportCloseQueueRef.current = task;\n };\n }, [props.transportCloseQueueRef]);\n\n const state = useMemo<MCPServerState>(\n () => ({\n id: props.id,\n kind: props.kind,\n name: props.name,\n url: props.url,\n icon: props.icon,\n connectionState,\n lastError,\n tools,\n authorizationUrl,\n pendingElicitations,\n }),\n [\n props.id,\n props.kind,\n props.name,\n props.url,\n props.icon,\n connectionState,\n lastError,\n tools,\n authorizationUrl,\n pendingElicitations,\n ],\n );\n\n return {\n getState: () => state,\n connect: doConnect,\n disconnect: doDisconnect,\n remove: async () => {\n const releaseRemovalFence = beginMcpServerRemovalFence(props);\n try {\n await doDisconnect();\n await clearOAuthProviderAuthState(props.storage, props.id);\n await props.onRemove();\n } catch (err) {\n releaseRemovalFence?.();\n setLastError({\n message: err instanceof Error ? err.message : String(err),\n });\n throw err;\n }\n releaseRemovalFence?.();\n },\n callTool: async (name, args) => {\n const client = clientRef.current;\n if (!client) {\n throw new Error(`MCP server \"${props.id}\" is not connected`);\n }\n return await client.callTool({\n name,\n arguments: args as Record<string, unknown> | undefined,\n });\n },\n listResources: async (params) => {\n const client = clientRef.current;\n if (!client) {\n throw new Error(`MCP server \"${props.id}\" is not connected`);\n }\n return await client.listResources(params);\n },\n readResource: async (uri) => {\n const client = clientRef.current;\n if (!client) {\n throw new Error(`MCP server \"${props.id}\" is not connected`);\n }\n return await client.readResource({ uri });\n },\n completeAuth: doCompleteAuth,\n answerElicitation: (\n id: string,\n response: MCPElicitationResponse,\n ): readonly { property: string; message: string }[] | undefined => {\n if (response.action === \"accept\") {\n const entry = elicitationResolversRef.current.get(id);\n if (!entry) return undefined;\n\n if (\n typeof response.content !== \"object\" ||\n response.content === null ||\n Array.isArray(response.content)\n ) {\n const errors = [\n {\n property: \"content\",\n message: \"Response content must be an object.\",\n },\n ];\n setPendingElicitationError(id, {\n message: \"Invalid elicitation content: content.\",\n properties: [\"content\"],\n });\n return errors;\n }\n\n const errors = validateElicitationContent(\n entry.requestedSchema,\n response.content,\n );\n if (errors.length > 0) {\n const properties = [\n ...new Set(errors.map((error) => error.property)),\n ];\n setPendingElicitationError(id, {\n message: `Invalid elicitation content: ${properties.join(\", \")}.`,\n properties,\n });\n return errors;\n }\n\n const result: ElicitResult = {\n action: \"accept\",\n content: response.content as ElicitResult[\"content\"],\n };\n resolvePendingElicitation(id, result);\n return undefined;\n }\n\n resolvePendingElicitation(id, { action: response.action });\n return undefined;\n },\n };\n};\n\nconst McpServerResourceInstance = resource(useMcpServerResourceInstance);\n\nexport const McpServerResource = resource(function useMcpServerResource(\n props: McpServerResourceProps,\n): ClientOutput<\"mcpServer\"> {\n const transportCloseQueueRef = useRef(Promise.resolve());\n const dependencies = getConnectionDependencies(props);\n const [connection, setConnection] = useState({ dependencies, generation: 0 });\n let currentConnection = connection;\n if (!shallowEqual(connection.dependencies, dependencies)) {\n currentConnection = {\n dependencies,\n generation: connection.generation + 1,\n };\n setConnection(currentConnection);\n }\n\n // Storage keys remounts through its optional scopeId rather than object\n // identity, because a defaulted storage element is rebuilt on ordinary\n // renders.\n return useResource(\n withKey(\n currentConnection.generation,\n McpServerResourceInstance({ ...props, transportCloseQueueRef }),\n ),\n );\n});\n"],"mappings":"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"}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { MCPStorage } from "./types.js";
|
|
2
|
-
|
|
3
|
-
declare const McpCustomStorage: import("@assistant-ui/tap").Resource<MCPStorage, [impl: MCPStorage]>;
|
|
4
|
-
//#endregion
|
|
5
|
-
export { McpCustomStorage };
|
|
1
|
+
import type { MCPStorage } from "./types.js";
|
|
2
|
+
export declare const McpCustomStorage: import("@assistant-ui/tap").Resource<MCPStorage, [impl: MCPStorage]>;
|
|
6
3
|
//# sourceMappingURL=McpCustomStorage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpCustomStorage.d.ts","
|
|
1
|
+
{"version":3,"file":"McpCustomStorage.d.ts","sourceRoot":"","sources":["../../../src/resources/storage/McpCustomStorage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAgB;AAM1C,eAAO,MAAM,gBAAgB,sEAAgC,CAAC"}
|
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
import { MCPCustomServerRecord } from "../../mcp-scope.js";
|
|
2
|
-
import { MCPPersistedAuthState } from "../../auth/types.js";
|
|
3
|
-
import { MCPStorage } from "./types.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
scopeId?: string;
|
|
1
|
+
import type { MCPCustomServerRecord } from "../../mcp-scope.js";
|
|
2
|
+
import type { MCPPersistedAuthState } from "../../auth/types.js";
|
|
3
|
+
import type { MCPStorage } from "./types.js";
|
|
4
|
+
export type McpLocalStorageOptions = {
|
|
5
|
+
/** Namespace prefix for keys. Default "aui-mcp". */
|
|
6
|
+
keyPrefix?: string;
|
|
7
|
+
/** Override the underlying Storage. Defaults to globalThis.localStorage. */
|
|
8
|
+
storage?: Storage;
|
|
9
|
+
/**
|
|
10
|
+
* Stable identity for the backing data, used to key server reconnects.
|
|
11
|
+
* Required to get reconnect-on-swap behavior when `storage` is overridden;
|
|
12
|
+
* without it a custom backing store declares no scope, since a prefix
|
|
13
|
+
* alone cannot distinguish two different stores.
|
|
14
|
+
*/
|
|
15
|
+
scopeId?: string;
|
|
17
16
|
};
|
|
18
|
-
declare const normalizeCustomServerRecords: (value: unknown) => MCPCustomServerRecord[];
|
|
19
|
-
declare const normalizePersistedAuthState: (value: unknown) => MCPPersistedAuthState | null;
|
|
20
|
-
declare const McpLocalStorage: import("@assistant-ui/tap").Resource<MCPStorage, [opts?: McpLocalStorageOptions | undefined]>;
|
|
21
|
-
//#endregion
|
|
22
|
-
export { McpLocalStorage, McpLocalStorageOptions, normalizeCustomServerRecords, normalizePersistedAuthState };
|
|
17
|
+
export declare const normalizeCustomServerRecords: (value: unknown) => MCPCustomServerRecord[];
|
|
18
|
+
export declare const normalizePersistedAuthState: (value: unknown) => MCPPersistedAuthState | null;
|
|
19
|
+
export declare const McpLocalStorage: import("@assistant-ui/tap").Resource<MCPStorage, [opts?: McpLocalStorageOptions | undefined]>;
|
|
23
20
|
//# sourceMappingURL=McpLocalStorage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpLocalStorage.d.ts","
|
|
1
|
+
{"version":3,"file":"McpLocalStorage.d.ts","sourceRoot":"","sources":["../../../src/resources/storage/McpLocalStorage.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAiB,qBAAqB,EAAE,2BAAwB;AAC5E,OAAO,KAAK,EAAE,qBAAqB,EAAE,4BAAyB;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAgB;AAE1C,MAAM,MAAM,sBAAsB,GAAG;IACnC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAgGF,eAAO,MAAM,4BAA4B,GACvC,OAAO,OAAO,KACb,qBAAqB,EAMvB,CAAC;AA2EF,eAAO,MAAM,2BAA2B,GACtC,OAAO,OAAO,KACb,qBAAqB,GAAG,IA8B1B,CAAC;AAmEF,eAAO,MAAM,eAAe,+FAA+B,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { assertValidServerId } from "../../utils/serverId.js";
|
|
2
1
|
import { normalizeMcpServerUrl } from "../../utils/serverUrl.js";
|
|
2
|
+
import { assertValidServerId } from "../../utils/serverId.js";
|
|
3
3
|
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
4
4
|
import "@assistant-ui/tap/react-shim";
|
|
5
5
|
import { resource } from "@assistant-ui/tap";
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { MCPStorage } from "./types.js";
|
|
2
|
-
|
|
3
|
-
declare const McpMemoryStorage: import("@assistant-ui/tap").Resource<MCPStorage, []>;
|
|
4
|
-
//#endregion
|
|
5
|
-
export { McpMemoryStorage };
|
|
1
|
+
import type { MCPStorage } from "./types.js";
|
|
2
|
+
export declare const McpMemoryStorage: import("@assistant-ui/tap").Resource<MCPStorage, []>;
|
|
6
3
|
//# sourceMappingURL=McpMemoryStorage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpMemoryStorage.d.ts","
|
|
1
|
+
{"version":3,"file":"McpMemoryStorage.d.ts","sourceRoot":"","sources":["../../../src/resources/storage/McpMemoryStorage.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAgB;AAwB1C,eAAO,MAAM,gBAAgB,sDAAgC,CAAC"}
|
|
@@ -1,29 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
clearAuthState: (serverId: string) => Promise<void>;
|
|
1
|
+
import { type ResourceElement } from "@assistant-ui/tap";
|
|
2
|
+
import type { MCPCustomServerRecord } from "../../mcp-scope.js";
|
|
3
|
+
import type { MCPPersistedAuthState } from "../../auth/types.js";
|
|
4
|
+
export type MCPStorage = {
|
|
5
|
+
/**
|
|
6
|
+
* Stable identity of the backing store. Two storages with the same scopeId
|
|
7
|
+
* must read and write the same persisted data. When present, custom servers,
|
|
8
|
+
* server connections, and the OAuth write fence key on it. Swapping to a
|
|
9
|
+
* differently-scoped storage rehydrates its custom servers and reconnects
|
|
10
|
+
* authenticated servers instead of retaining data or a live OAuth flow from
|
|
11
|
+
* the replaced store. Clearing through a same-scoped replacement still waits
|
|
12
|
+
* for writes queued against the storage it replaced. When absent, the fence
|
|
13
|
+
* falls back to object identity while custom servers and connections never
|
|
14
|
+
* re-key. Replacing an unscoped storage can therefore persist the previous
|
|
15
|
+
* store's custom servers into the replacement, and a clear runs unfenced
|
|
16
|
+
* against writes queued by the object it replaced.
|
|
17
|
+
*/
|
|
18
|
+
scopeId?: string;
|
|
19
|
+
loadCustomServers: () => Promise<MCPCustomServerRecord[]>;
|
|
20
|
+
saveCustomServers: (records: MCPCustomServerRecord[]) => Promise<void>;
|
|
21
|
+
loadAuthState: (serverId: string) => Promise<MCPPersistedAuthState | null>;
|
|
22
|
+
saveAuthState: (serverId: string, state: MCPPersistedAuthState) => Promise<void>;
|
|
23
|
+
clearAuthState: (serverId: string) => Promise<void>;
|
|
25
24
|
};
|
|
26
|
-
type MCPStorageElement = ResourceElement<MCPStorage>;
|
|
27
|
-
//#endregion
|
|
28
|
-
export { MCPStorage, MCPStorageElement };
|
|
25
|
+
export type MCPStorageElement = ResourceElement<MCPStorage>;
|
|
29
26
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/resources/storage/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,2BAAwB;AAC7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,4BAAyB;AAE9D,MAAM,MAAM,UAAU,GAAG;IACvB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAC1D,iBAAiB,EAAE,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IAC3E,aAAa,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,qBAAqB,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC"}
|