@assistant-ui/react-mcp 0.0.10 → 0.0.11
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.js.map +1 -1
- package/dist/auth/createOAuthProvider.js.map +1 -1
- package/dist/connector.js.map +1 -1
- package/dist/context/McpConnectorByIndexProvider.js +29 -6
- package/dist/context/McpConnectorByIndexProvider.js.map +1 -1
- package/dist/context/McpCustomServerByIndexProvider.js +29 -6
- package/dist/context/McpCustomServerByIndexProvider.js.map +1 -1
- package/dist/context/McpServerByIdProvider.js +29 -6
- package/dist/context/McpServerByIdProvider.js.map +1 -1
- package/dist/hooks/useMcpOAuthCallback.js +30 -2
- package/dist/hooks/useMcpOAuthCallback.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormAuthFields.js +59 -16
- package/dist/primitives/addForm/McpAddFormAuthFields.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormAuthSelect.js +33 -9
- package/dist/primitives/addForm/McpAddFormAuthSelect.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormCancel.js +24 -7
- package/dist/primitives/addForm/McpAddFormCancel.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormError.js +16 -5
- package/dist/primitives/addForm/McpAddFormError.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormNameField.js +25 -8
- package/dist/primitives/addForm/McpAddFormNameField.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormRoot.js +10 -10
- package/dist/primitives/addForm/McpAddFormRoot.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormSubmit.js +20 -7
- package/dist/primitives/addForm/McpAddFormSubmit.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormUrlField.js +26 -9
- package/dist/primitives/addForm/McpAddFormUrlField.js.map +1 -1
- package/dist/primitives/addForm/context.js.map +1 -1
- package/dist/primitives/addForm.js.map +1 -1
- package/dist/primitives/manager/McpManagerAddCustomTrigger.js +14 -5
- package/dist/primitives/manager/McpManagerAddCustomTrigger.js.map +1 -1
- package/dist/primitives/manager/McpManagerConnectors.js.map +1 -1
- package/dist/primitives/manager/McpManagerCustomServers.js.map +1 -1
- package/dist/primitives/manager/McpManagerRoot.js +19 -6
- package/dist/primitives/manager/McpManagerRoot.js.map +1 -1
- package/dist/primitives/manager.js.map +1 -1
- package/dist/primitives/server/McpServerConnectButton.js +31 -9
- package/dist/primitives/server/McpServerConnectButton.js.map +1 -1
- package/dist/primitives/server/McpServerDisconnectButton.js +28 -8
- package/dist/primitives/server/McpServerDisconnectButton.js.map +1 -1
- package/dist/primitives/server/McpServerError.js +20 -6
- package/dist/primitives/server/McpServerError.js.map +1 -1
- package/dist/primitives/server/McpServerIcon.js +41 -9
- package/dist/primitives/server/McpServerIcon.js.map +1 -1
- package/dist/primitives/server/McpServerName.js +20 -6
- package/dist/primitives/server/McpServerName.js.map +1 -1
- package/dist/primitives/server/McpServerOAuthLink.js +35 -9
- package/dist/primitives/server/McpServerOAuthLink.js.map +1 -1
- package/dist/primitives/server/McpServerRemoveButton.js +28 -8
- package/dist/primitives/server/McpServerRemoveButton.js.map +1 -1
- package/dist/primitives/server/McpServerRoot.js +37 -12
- package/dist/primitives/server/McpServerRoot.js.map +1 -1
- package/dist/primitives/server/McpServerStatus.js +22 -7
- package/dist/primitives/server/McpServerStatus.js.map +1 -1
- package/dist/primitives/server/McpServerToolName.js +18 -6
- package/dist/primitives/server/McpServerToolName.js.map +1 -1
- package/dist/primitives/server/McpServerTools.js +31 -6
- package/dist/primitives/server/McpServerTools.js.map +1 -1
- package/dist/primitives/server.js.map +1 -1
- package/dist/resources/McpManagerResource.d.ts.map +1 -1
- package/dist/resources/McpManagerResource.js +286 -99
- package/dist/resources/McpManagerResource.js.map +1 -1
- package/dist/resources/McpServerResource.js +31 -31
- package/dist/resources/McpServerResource.js.map +1 -1
- package/dist/resources/storage/McpCustomStorage.js.map +1 -1
- package/dist/resources/storage/McpLocalStorage.js.map +1 -1
- package/dist/resources/storage/McpMemoryStorage.js.map +1 -1
- package/dist/utils/serverId.js.map +1 -1
- package/package.json +6 -6
- package/src/resources/McpManagerResource.ts +21 -13
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { McpServerResource } from "./McpServerResource.js";
|
|
2
2
|
import { McpLocalStorage } from "./storage/McpLocalStorage.js";
|
|
3
3
|
import { attachTransformScopes, useAssistantClientRef, useClientLookup } from "@assistant-ui/store";
|
|
4
|
-
import {
|
|
4
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
5
|
+
import { useEffect, useEffectEvent, useRef, useState } from "@assistant-ui/tap/react-shim";
|
|
5
6
|
import { resource, useResource, withKey } from "@assistant-ui/tap";
|
|
6
7
|
import { ModelContext } from "@assistant-ui/core/store";
|
|
7
8
|
//#region src/resources/McpManagerResource.ts
|
|
@@ -11,89 +12,187 @@ function defaultRedirectUri() {
|
|
|
11
12
|
}
|
|
12
13
|
const NO_CONNECTORS = [];
|
|
13
14
|
const useMcpManagerResource = (props) => {
|
|
15
|
+
const $ = c(69);
|
|
14
16
|
const connectors = props.connectors ?? NO_CONNECTORS;
|
|
15
17
|
const autoConnect = props.autoConnect ?? true;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
let t0;
|
|
19
|
+
if ($[0] !== props.oauthRedirectUri) {
|
|
20
|
+
t0 = props.oauthRedirectUri ?? defaultRedirectUri();
|
|
21
|
+
$[0] = props.oauthRedirectUri;
|
|
22
|
+
$[1] = t0;
|
|
23
|
+
} else t0 = $[1];
|
|
24
|
+
const redirectUri = t0;
|
|
25
|
+
let t1;
|
|
26
|
+
if ($[2] !== props.storage) {
|
|
27
|
+
t1 = props.storage ?? McpLocalStorage();
|
|
28
|
+
$[2] = props.storage;
|
|
29
|
+
$[3] = t1;
|
|
30
|
+
} else t1 = $[3];
|
|
31
|
+
const storage = useResource(t1);
|
|
32
|
+
let t2;
|
|
33
|
+
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
|
34
|
+
t2 = [];
|
|
35
|
+
$[4] = t2;
|
|
36
|
+
} else t2 = $[4];
|
|
37
|
+
const [customServers, setCustomServers] = useState(t2);
|
|
19
38
|
const [isHydrated, setIsHydrated] = useState(false);
|
|
20
39
|
const hydratedRef = useRef(false);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
40
|
+
let t3;
|
|
41
|
+
if ($[5] !== storage) {
|
|
42
|
+
t3 = async (signal) => {
|
|
43
|
+
const markHydrated = () => {
|
|
44
|
+
if (!signal.cancelled) {
|
|
45
|
+
hydratedRef.current = true;
|
|
46
|
+
setIsHydrated(true);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
let records;
|
|
50
|
+
try {
|
|
51
|
+
records = await storage.loadCustomServers();
|
|
52
|
+
} catch (t4) {
|
|
53
|
+
const error = t4;
|
|
54
|
+
markHydrated();
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
24
57
|
if (signal.cancelled) return;
|
|
25
58
|
setCustomServers((prev) => {
|
|
26
59
|
if (prev.length === 0) return records;
|
|
27
|
-
const persistedIds = new Set(records.map(
|
|
28
|
-
return [...records, ...prev.filter((
|
|
60
|
+
const persistedIds = new Set(records.map(_temp));
|
|
61
|
+
return [...records, ...prev.filter((r_0) => !persistedIds.has(r_0.id))];
|
|
29
62
|
});
|
|
30
|
-
|
|
31
|
-
if (!signal.cancelled) {
|
|
32
|
-
hydratedRef.current = true;
|
|
33
|
-
setIsHydrated(true);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
const signal = { cancelled: false };
|
|
39
|
-
hydrate(signal);
|
|
40
|
-
return () => {
|
|
41
|
-
signal.cancelled = true;
|
|
63
|
+
markHydrated();
|
|
42
64
|
};
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
customServers
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
65
|
+
$[5] = storage;
|
|
66
|
+
$[6] = t3;
|
|
67
|
+
} else t3 = $[6];
|
|
68
|
+
const hydrate = useEffectEvent(t3);
|
|
69
|
+
let t4;
|
|
70
|
+
if ($[7] !== hydrate) {
|
|
71
|
+
t4 = () => {
|
|
72
|
+
const signal_0 = { cancelled: false };
|
|
73
|
+
hydrate(signal_0);
|
|
74
|
+
return () => {
|
|
75
|
+
signal_0.cancelled = true;
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
$[7] = hydrate;
|
|
79
|
+
$[8] = t4;
|
|
80
|
+
} else t4 = $[8];
|
|
81
|
+
let t5;
|
|
82
|
+
if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
|
|
83
|
+
t5 = [];
|
|
84
|
+
$[9] = t5;
|
|
85
|
+
} else t5 = $[9];
|
|
86
|
+
useEffect(t4, t5);
|
|
87
|
+
let t6;
|
|
88
|
+
if ($[10] !== storage) {
|
|
89
|
+
t6 = async (records_0) => {
|
|
90
|
+
if (!hydratedRef.current) return;
|
|
91
|
+
await storage.saveCustomServers(records_0);
|
|
92
|
+
};
|
|
93
|
+
$[10] = storage;
|
|
94
|
+
$[11] = t6;
|
|
95
|
+
} else t6 = $[11];
|
|
96
|
+
const persistCustomServers = useEffectEvent(t6);
|
|
97
|
+
let t7;
|
|
98
|
+
if ($[12] !== customServers || $[13] !== persistCustomServers) {
|
|
99
|
+
t7 = () => {
|
|
100
|
+
persistCustomServers(customServers);
|
|
101
|
+
};
|
|
102
|
+
$[12] = customServers;
|
|
103
|
+
$[13] = persistCustomServers;
|
|
104
|
+
$[14] = t7;
|
|
105
|
+
} else t7 = $[14];
|
|
106
|
+
let t8;
|
|
107
|
+
if ($[15] !== customServers) {
|
|
108
|
+
t8 = [customServers];
|
|
109
|
+
$[15] = customServers;
|
|
110
|
+
$[16] = t8;
|
|
111
|
+
} else t8 = $[16];
|
|
112
|
+
useEffect(t7, t8);
|
|
113
|
+
let t9;
|
|
114
|
+
if ($[17] !== autoConnect || $[18] !== connectors || $[19] !== customServers || $[20] !== redirectUri || $[21] !== storage) {
|
|
115
|
+
let t10;
|
|
116
|
+
if ($[23] !== autoConnect || $[24] !== redirectUri || $[25] !== storage) {
|
|
117
|
+
t10 = (c) => withKey(c.id, McpServerResource({
|
|
118
|
+
id: c.id,
|
|
119
|
+
kind: "connector",
|
|
120
|
+
name: c.name,
|
|
121
|
+
url: c.url,
|
|
122
|
+
icon: c.icon,
|
|
123
|
+
auth: c.auth,
|
|
124
|
+
storage,
|
|
125
|
+
redirectUri,
|
|
126
|
+
autoConnect,
|
|
127
|
+
onRemove: _temp2
|
|
128
|
+
}));
|
|
129
|
+
$[23] = autoConnect;
|
|
130
|
+
$[24] = redirectUri;
|
|
131
|
+
$[25] = storage;
|
|
132
|
+
$[26] = t10;
|
|
133
|
+
} else t10 = $[26];
|
|
134
|
+
const connectorElements = connectors.map(t10);
|
|
135
|
+
let t11;
|
|
136
|
+
if ($[27] !== autoConnect || $[28] !== redirectUri || $[29] !== storage) {
|
|
137
|
+
t11 = (s) => withKey(s.id, McpServerResource({
|
|
138
|
+
id: s.id,
|
|
139
|
+
kind: "custom",
|
|
140
|
+
name: s.name,
|
|
141
|
+
url: s.url,
|
|
142
|
+
auth: s.auth,
|
|
143
|
+
storage,
|
|
144
|
+
redirectUri,
|
|
145
|
+
autoConnect,
|
|
146
|
+
onRemove: async () => {
|
|
147
|
+
setCustomServers((prev_0) => prev_0.filter((x) => x.id !== s.id));
|
|
148
|
+
}
|
|
149
|
+
}));
|
|
150
|
+
$[27] = autoConnect;
|
|
151
|
+
$[28] = redirectUri;
|
|
152
|
+
$[29] = storage;
|
|
153
|
+
$[30] = t11;
|
|
154
|
+
} else t11 = $[30];
|
|
155
|
+
const customElements = customServers.map(t11);
|
|
156
|
+
t9 = [...connectorElements, ...customElements];
|
|
157
|
+
$[17] = autoConnect;
|
|
158
|
+
$[18] = connectors;
|
|
159
|
+
$[19] = customServers;
|
|
160
|
+
$[20] = redirectUri;
|
|
161
|
+
$[21] = storage;
|
|
162
|
+
$[22] = t9;
|
|
163
|
+
} else t9 = $[22];
|
|
164
|
+
const lookup = useClientLookup(t9);
|
|
165
|
+
const all = lookup.state;
|
|
166
|
+
let t10;
|
|
167
|
+
if ($[31] !== all) {
|
|
168
|
+
t10 = all.filter(_temp3);
|
|
169
|
+
$[31] = all;
|
|
170
|
+
$[32] = t10;
|
|
171
|
+
} else t10 = $[32];
|
|
172
|
+
let t11;
|
|
173
|
+
if ($[33] !== all) {
|
|
174
|
+
t11 = all.filter(_temp4);
|
|
175
|
+
$[33] = all;
|
|
176
|
+
$[34] = t11;
|
|
177
|
+
} else t11 = $[34];
|
|
178
|
+
let t12;
|
|
179
|
+
if ($[35] !== all || $[36] !== isHydrated || $[37] !== t10 || $[38] !== t11) {
|
|
180
|
+
t12 = {
|
|
89
181
|
servers: all,
|
|
90
|
-
connectors:
|
|
91
|
-
customServers:
|
|
182
|
+
connectors: t10,
|
|
183
|
+
customServers: t11,
|
|
92
184
|
isHydrated
|
|
93
185
|
};
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
186
|
+
$[35] = all;
|
|
187
|
+
$[36] = isHydrated;
|
|
188
|
+
$[37] = t10;
|
|
189
|
+
$[38] = t11;
|
|
190
|
+
$[39] = t12;
|
|
191
|
+
} else t12 = $[39];
|
|
192
|
+
const state = t12;
|
|
193
|
+
let out;
|
|
194
|
+
if ($[40] !== lookup || $[41] !== state.servers) {
|
|
195
|
+
out = {};
|
|
97
196
|
for (const server of state.servers) {
|
|
98
197
|
if (server.connectionState !== "connected") continue;
|
|
99
198
|
for (const tool of server.tools) {
|
|
@@ -106,29 +205,81 @@ const useMcpManagerResource = (props) => {
|
|
|
106
205
|
};
|
|
107
206
|
}
|
|
108
207
|
}
|
|
109
|
-
|
|
110
|
-
|
|
208
|
+
$[40] = lookup;
|
|
209
|
+
$[41] = state.servers;
|
|
210
|
+
$[42] = out;
|
|
211
|
+
} else out = $[42];
|
|
212
|
+
const toolkit = out;
|
|
111
213
|
const clientRef = useAssistantClientRef();
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
214
|
+
let t13;
|
|
215
|
+
let t14;
|
|
216
|
+
if ($[43] !== clientRef || $[44] !== toolkit) {
|
|
217
|
+
t13 = () => {
|
|
218
|
+
const client = clientRef.current;
|
|
219
|
+
if (!client) return;
|
|
220
|
+
return client.modelContext().register({ getModelContext: () => ({ tools: toolkit }) });
|
|
221
|
+
};
|
|
222
|
+
t14 = [toolkit, clientRef];
|
|
223
|
+
$[43] = clientRef;
|
|
224
|
+
$[44] = toolkit;
|
|
225
|
+
$[45] = t13;
|
|
226
|
+
$[46] = t14;
|
|
227
|
+
} else {
|
|
228
|
+
t13 = $[45];
|
|
229
|
+
t14 = $[46];
|
|
230
|
+
}
|
|
231
|
+
useEffect(t13, t14);
|
|
232
|
+
let t15;
|
|
233
|
+
if ($[47] !== lookup || $[48] !== state) {
|
|
234
|
+
t15 = (kind, index) => {
|
|
235
|
+
const list = kind === "connector" ? state.connectors : state.customServers;
|
|
236
|
+
const entry = list[index];
|
|
237
|
+
if (!entry) throw new Error(`McpManagerResource: no ${kind} at index ${index} (length ${list.length})`);
|
|
238
|
+
return lookup.get({ key: entry.id });
|
|
239
|
+
};
|
|
240
|
+
$[47] = lookup;
|
|
241
|
+
$[48] = state;
|
|
242
|
+
$[49] = t15;
|
|
243
|
+
} else t15 = $[49];
|
|
244
|
+
const serverByKind = t15;
|
|
245
|
+
let t16;
|
|
246
|
+
if ($[50] !== state) {
|
|
247
|
+
t16 = () => state;
|
|
248
|
+
$[50] = state;
|
|
249
|
+
$[51] = t16;
|
|
250
|
+
} else t16 = $[51];
|
|
251
|
+
let t17;
|
|
252
|
+
if ($[52] !== lookup || $[53] !== serverByKind) {
|
|
253
|
+
t17 = (query) => {
|
|
126
254
|
if ("id" in query) return lookup.get({ key: query.id });
|
|
127
255
|
return serverByKind(query.kind, query.index);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
256
|
+
};
|
|
257
|
+
$[52] = lookup;
|
|
258
|
+
$[53] = serverByKind;
|
|
259
|
+
$[54] = t17;
|
|
260
|
+
} else t17 = $[54];
|
|
261
|
+
let t18;
|
|
262
|
+
let t19;
|
|
263
|
+
if ($[55] !== serverByKind) {
|
|
264
|
+
t18 = (t20) => {
|
|
265
|
+
const { index: index_0 } = t20;
|
|
266
|
+
return serverByKind("connector", index_0);
|
|
267
|
+
};
|
|
268
|
+
t19 = (t21) => {
|
|
269
|
+
const { index: index_1 } = t21;
|
|
270
|
+
return serverByKind("custom", index_1);
|
|
271
|
+
};
|
|
272
|
+
$[55] = serverByKind;
|
|
273
|
+
$[56] = t18;
|
|
274
|
+
$[57] = t19;
|
|
275
|
+
} else {
|
|
276
|
+
t18 = $[56];
|
|
277
|
+
t19 = $[57];
|
|
278
|
+
}
|
|
279
|
+
let t20;
|
|
280
|
+
if ($[58] === Symbol.for("react.memo_cache_sentinel")) {
|
|
281
|
+
t20 = async (t21) => {
|
|
282
|
+
const { name, url, auth } = t21;
|
|
132
283
|
const record = {
|
|
133
284
|
id: typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `mcp-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
134
285
|
name,
|
|
@@ -136,24 +287,60 @@ const useMcpManagerResource = (props) => {
|
|
|
136
287
|
auth,
|
|
137
288
|
createdAt: Date.now()
|
|
138
289
|
};
|
|
139
|
-
setCustomServers((
|
|
290
|
+
setCustomServers((prev_1) => [...prev_1, record]);
|
|
140
291
|
return record.id;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
292
|
+
};
|
|
293
|
+
$[58] = t20;
|
|
294
|
+
} else t20 = $[58];
|
|
295
|
+
let t21;
|
|
296
|
+
if ($[59] !== lookup || $[60] !== state || $[61] !== storage) {
|
|
297
|
+
t21 = async (id) => {
|
|
298
|
+
if (state.connectors.some((c_0) => c_0.id === id)) throw new Error(`Cannot remove connector "${id}" — connectors are app-defined and not removable. Use a custom server id instead.`);
|
|
144
299
|
try {
|
|
145
300
|
await lookup.get({ key: id }).remove();
|
|
146
301
|
} catch {
|
|
147
302
|
await storage.clearAuthState(id);
|
|
148
|
-
setCustomServers((
|
|
303
|
+
setCustomServers((prev_2) => prev_2.filter((s_2) => s_2.id !== id));
|
|
149
304
|
}
|
|
150
|
-
}
|
|
151
|
-
|
|
305
|
+
};
|
|
306
|
+
$[59] = lookup;
|
|
307
|
+
$[60] = state;
|
|
308
|
+
$[61] = storage;
|
|
309
|
+
$[62] = t21;
|
|
310
|
+
} else t21 = $[62];
|
|
311
|
+
let t22;
|
|
312
|
+
if ($[63] !== t16 || $[64] !== t17 || $[65] !== t18 || $[66] !== t19 || $[67] !== t21) {
|
|
313
|
+
t22 = {
|
|
314
|
+
getState: t16,
|
|
315
|
+
server: t17,
|
|
316
|
+
connector: t18,
|
|
317
|
+
customServer: t19,
|
|
318
|
+
addCustomServer: t20,
|
|
319
|
+
removeServer: t21
|
|
320
|
+
};
|
|
321
|
+
$[63] = t16;
|
|
322
|
+
$[64] = t17;
|
|
323
|
+
$[65] = t18;
|
|
324
|
+
$[66] = t19;
|
|
325
|
+
$[67] = t21;
|
|
326
|
+
$[68] = t22;
|
|
327
|
+
} else t22 = $[68];
|
|
328
|
+
return t22;
|
|
152
329
|
};
|
|
153
330
|
const McpManagerResource = resource(useMcpManagerResource);
|
|
154
331
|
attachTransformScopes(useMcpManagerResource, (scopes, parent) => {
|
|
155
332
|
if (!scopes.modelContext && parent.modelContext.source === null) scopes.modelContext = ModelContext();
|
|
156
333
|
});
|
|
334
|
+
function _temp(r) {
|
|
335
|
+
return r.id;
|
|
336
|
+
}
|
|
337
|
+
async function _temp2() {}
|
|
338
|
+
function _temp3(s_0) {
|
|
339
|
+
return s_0.kind === "connector";
|
|
340
|
+
}
|
|
341
|
+
function _temp4(s_1) {
|
|
342
|
+
return s_1.kind === "custom";
|
|
343
|
+
}
|
|
157
344
|
//#endregion
|
|
158
345
|
export { McpManagerResource };
|
|
159
346
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpManagerResource.js","names":[],"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 { ModelContext } from \"@assistant-ui/core/store\";\nimport type { Tool } from \"assistant-stream\";\nimport { McpServerResource } from \"./McpServerResource\";\nimport { McpLocalStorage } from \"./storage/McpLocalStorage\";\nimport type { MCPStorageElement } from \"./storage/types\";\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};\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 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\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\n const hydrate = useEffectEvent(async (signal: { cancelled: boolean }) => {\n try {\n const records = await storage.loadCustomServers();\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 } finally {\n if (!signal.cancelled) {\n hydratedRef.current = true;\n setIsHydrated(true);\n }\n }\n });\n\n useEffect(() => {\n const signal = { cancelled: false };\n void hydrate(signal);\n return () => {\n signal.cancelled = true;\n };\n }, []);\n\n const persistCustomServers = useEffectEvent(\n async (records: MCPCustomServerRecord[]) => {\n if (!hydratedRef.current) return;\n await storage.saveCustomServers(records);\n },\n );\n\n useEffect(() => {\n void persistCustomServers(customServers);\n }, [customServers]);\n\n const serverElements = useMemo(() => {\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 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 onRemove: async () => {\n setCustomServers((prev) => prev.filter((x) => x.id !== s.id));\n },\n }),\n ),\n );\n return [...connectorElements, ...customElements];\n }, [connectors, customServers, storage, redirectUri, autoConnect]);\n\n const lookup = useClientLookup(() => serverElements, [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 useEffect(() => {\n const client = clientRef.current;\n if (!client) return;\n return client.modelContext().register({\n getModelContext: () => ({ tools: toolkit }),\n });\n }, [toolkit, clientRef]);\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 ({ name, url, auth }) => {\n const record: MCPCustomServerRecord = {\n id:\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `mcp-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n name,\n url,\n auth: auth as MCPAuthConfig,\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 storage.clearAuthState(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":";;;;;;;AA6BA,SAAS,qBAA6B;CACpC,IAAI,OAAO,WAAW,aAAa,OAAO;CAC1C,OAAO,GAAG,OAAO,SAAS,OAAO;AACnC;AAIA,MAAM,gBAAgC,CAAC;AAEvC,MAAM,yBACJ,UACwB;CACxB,MAAM,aAAa,MAAM,cAAc;CACvC,MAAM,cAAc,MAAM,eAAe;CACzC,MAAM,cAAc,MAAM,oBAAoB,mBAAmB;CAGjE,MAAM,UAAU,YADO,MAAM,WAAW,gBAAgB,CACd;CAE1C,MAAM,CAAC,eAAe,oBAAoB,SACxC,CAAC,CACH;CACA,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAElD,MAAM,cAAc,OAAO,KAAK;CAEhC,MAAM,UAAU,eAAe,OAAO,WAAmC;EACvE,IAAI;GACF,MAAM,UAAU,MAAM,QAAQ,kBAAkB;GAChD,IAAI,OAAO,WAAW;GAItB,kBAAkB,SAAS;IACzB,IAAI,KAAK,WAAW,GAAG,OAAO;IAC9B,MAAM,eAAe,IAAI,IAAI,QAAQ,KAAK,MAAM,EAAE,EAAE,CAAC;IACrD,OAAO,CAAC,GAAG,SAAS,GAAG,KAAK,QAAQ,MAAM,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC,CAAC;GACpE,CAAC;EACH,UAAU;GACR,IAAI,CAAC,OAAO,WAAW;IACrB,YAAY,UAAU;IACtB,cAAc,IAAI;GACpB;EACF;CACF,CAAC;CAED,gBAAgB;EACd,MAAM,SAAS,EAAE,WAAW,MAAM;EAClC,QAAa,MAAM;EACnB,aAAa;GACX,OAAO,YAAY;EACrB;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,uBAAuB,eAC3B,OAAO,YAAqC;EAC1C,IAAI,CAAC,YAAY,SAAS;EAC1B,MAAM,QAAQ,kBAAkB,OAAO;CACzC,CACF;CAEA,gBAAgB;EACd,qBAA0B,aAAa;CACzC,GAAG,CAAC,aAAa,CAAC;CAElB,MAAM,iBAAiB,cAAc;EACnC,MAAM,oBAAoB,WAAW,KAAK,MACxC,QACE,EAAE,IACF,kBAAkB;GAChB,IAAI,EAAE;GACN,MAAM;GACN,MAAM,EAAE;GACR,KAAK,EAAE;GACP,MAAM,EAAE;GACR,MAAM,EAAE;GACR;GACA;GACA;GACA,UAAU,YAAY,CAEtB;EACF,CAAC,CACH,CACF;EACA,MAAM,iBAAiB,cAAc,KAAK,MACxC,QACE,EAAE,IACF,kBAAkB;GAChB,IAAI,EAAE;GACN,MAAM;GACN,MAAM,EAAE;GACR,KAAK,EAAE;GACP,MAAM,EAAE;GACR;GACA;GACA;GACA,UAAU,YAAY;IACpB,kBAAkB,SAAS,KAAK,QAAQ,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC;GAC9D;EACF,CAAC,CACH,CACF;EACA,OAAO,CAAC,GAAG,mBAAmB,GAAG,cAAc;CACjD,GAAG;EAAC;EAAY;EAAe;EAAS;EAAa;CAAW,CAAC;CAEjE,MAAM,SAAS,sBAAsB,gBAAgB,CAAC,cAAc,CAAC;CAErE,MAAM,QAAQ,cAA+B;EAC3C,MAAM,MAAM,OAAO;EACnB,OAAO;GACL,SAAS;GACT,YAAY,IAAI,QAAQ,MAAM,EAAE,SAAS,WAAW;GACpD,eAAe,IAAI,QAAQ,MAAM,EAAE,SAAS,QAAQ;GACpD;EACF;CACF,GAAG,CAAC,OAAO,OAAO,UAAU,CAAC;CAQ7B,MAAM,UAAU,cAA8C;EAC5D,MAAM,MAAsC,CAAC;EAC7C,KAAK,MAAM,UAAU,MAAM,SAAS;GAClC,IAAI,OAAO,oBAAoB,aAAa;GAC5C,KAAK,MAAM,QAAQ,OAAO,OAAO;IAC/B,MAAM,WAAW,GAAG,OAAO,GAAG,IAAI,KAAK;IACvC,IAAI,YAAY;KACd,MAAM;KACN,GAAI,KAAK,gBAAgB,KAAA,IACrB,EAAE,aAAa,KAAK,YAAY,IAChC,CAAC;KACL,YAAY,KAAK;KACjB,UAAU,SACR,OAAO,IAAI,EAAE,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,SAAS,KAAK,MAAM,IAAe;IACtE;GACF;EACF;EACA,OAAO;CACT,GAAG,CAAC,OAAO,MAAM,CAAC;CAElB,MAAM,YAAY,sBAAsB;CAExC,gBAAgB;EACd,MAAM,SAAS,UAAU;EACzB,IAAI,CAAC,QAAQ;EACb,OAAO,OAAO,aAAa,CAAC,CAAC,SAAS,EACpC,wBAAwB,EAAE,OAAO,QAAQ,GAC3C,CAAC;CACH,GAAG,CAAC,SAAS,SAAS,CAAC;CAEvB,MAAM,gBAAgB,MAA8B,UAAkB;EACpE,MAAM,OAAO,SAAS,cAAc,MAAM,aAAa,MAAM;EAC7D,MAAM,QAAQ,KAAK;EACnB,IAAI,CAAC,OACH,MAAM,IAAI,MACR,0BAA0B,KAAK,YAAY,MAAM,WAAW,KAAK,OAAO,EAC1E;EAEF,OAAO,OAAO,IAAI,EAAE,KAAK,MAAM,GAAG,CAAC;CACrC;CAEA,OAAO;EACL,gBAAgB;EAChB,SAAS,UAAU;GACjB,IAAI,QAAQ,OAAO,OAAO,OAAO,IAAI,EAAE,KAAK,MAAM,GAAG,CAAC;GACtD,OAAO,aAAa,MAAM,MAAM,MAAM,KAAK;EAC7C;EACA,YAAY,EAAE,YAAY,aAAa,aAAa,KAAK;EACzD,eAAe,EAAE,YAAY,aAAa,UAAU,KAAK;EACzD,iBAAiB,OAAO,EAAE,MAAM,KAAK,WAAW;GAC9C,MAAM,SAAgC;IACpC,IACE,OAAO,WAAW,eAAe,gBAAgB,SAC7C,OAAO,WAAW,IAClB,OAAO,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC;IAC7D;IACA;IACM;IACN,WAAW,KAAK,IAAI;GACtB;GACA,kBAAkB,SAAS,CAAC,GAAG,MAAM,MAAM,CAAC;GAC5C,OAAO,OAAO;EAChB;EACA,cAAc,OAAO,OAAO;GAG1B,IAAI,MAAM,WAAW,MAAM,MAAM,EAAE,OAAO,EAAE,GAC1C,MAAM,IAAI,MACR,4BAA4B,GAAG,kFACjC;GAMF,IAAI;IACF,MAAM,OAAO,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO;GACvC,QAAQ;IACN,MAAM,QAAQ,eAAe,EAAE;IAC/B,kBAAkB,SAAS,KAAK,QAAQ,MAAM,EAAE,OAAO,EAAE,CAAC;GAC5D;EACF;CACF;AACF;AAEA,MAAa,qBAAqB,SAAS,qBAAqB;AAKhE,sBAAsB,wBAAwB,QAAQ,WAAW;CAC/D,IAAI,CAAC,OAAO,gBAAgB,OAAO,aAAa,WAAW,MACzD,OAAO,eAAe,aAAa;AAEvC,CAAC"}
|
|
1
|
+
{"version":3,"file":"McpManagerResource.js","names":["useState","useEffect","useMemo","useEffectEvent","useRef","useResource","resource","withKey","useClientLookup","useAssistantClientRef","attachTransformScopes","ClientOutput","ModelContext","Tool","McpServerResource","McpLocalStorage","MCPStorageElement","MCPAuthConfig","MCPConnector","MCPCustomServerRecord","MCPManagerState","McpManagerResourceProps","connectors","storage","oauthRedirectUri","autoConnect","defaultRedirectUri","window","location","origin","NO_CONNECTORS","useMcpManagerResource","props","$","_c","t0","redirectUri","t1","storageElement","t2","Symbol","for","customServers","setCustomServers","isHydrated","setIsHydrated","hydratedRef","t3","signal","markHydrated","cancelled","current","records","loadCustomServers","t4","error","prev","length","persistedIds","Set","map","_temp","filter","r_0","has","r","id","hydrate","signal_0","t5","t6","records_0","saveCustomServers","persistCustomServers","t7","t8","t9","t10","c","kind","name","url","icon","auth","onRemove","_temp2","connectorElements","t11","s","prev_0","x","customElements","serverElements","lookup","all","state","_temp3","_temp4","t12","servers","out","server","connectionState","tool","tools","fullName","type","description","undefined","parameters","inputSchema","execute","args","get","key","callTool","toolkit","clientRef","t13","t14","client","modelContext","register","getModelContext","t15","index","list","entry","Error","serverByKind","t16","t17","query","t18","t19","t20","index_0","t21","index_1","record","crypto","randomUUID","Date","now","Math","random","toString","slice","createdAt","prev_1","some","c_0","remove","clearAuthState","prev_2","s_2","t22","getState","connector","customServer","addCustomServer","removeServer","McpManagerResource","scopes","parent","source","s_0","s_1"],"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 { ModelContext } from \"@assistant-ui/core/store\";\nimport type { Tool } from \"assistant-stream\";\nimport { McpServerResource } from \"./McpServerResource\";\nimport { McpLocalStorage } from \"./storage/McpLocalStorage\";\nimport type { MCPStorageElement } from \"./storage/types\";\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};\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 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\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\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 markHydrated();\n throw error;\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 const persistCustomServers = useEffectEvent(\n async (records: MCPCustomServerRecord[]) => {\n if (!hydratedRef.current) return;\n await storage.saveCustomServers(records);\n },\n );\n\n useEffect(() => {\n void persistCustomServers(customServers);\n }, [customServers]);\n\n const serverElements = useMemo(() => {\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 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 onRemove: async () => {\n setCustomServers((prev) => prev.filter((x) => x.id !== s.id));\n },\n }),\n ),\n );\n return [...connectorElements, ...customElements];\n }, [connectors, customServers, storage, redirectUri, autoConnect]);\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 useEffect(() => {\n const client = clientRef.current;\n if (!client) return;\n return client.modelContext().register({\n getModelContext: () => ({ tools: toolkit }),\n });\n }, [toolkit, clientRef]);\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 ({ name, url, auth }) => {\n const record: MCPCustomServerRecord = {\n id:\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID()\n : `mcp-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n name,\n url,\n auth: auth as MCPAuthConfig,\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 storage.clearAuthState(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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"}
|
|
@@ -55,11 +55,11 @@ const useMcpServerResource = (props) => {
|
|
|
55
55
|
setConnectionState("connected");
|
|
56
56
|
});
|
|
57
57
|
const closeTransport = async () => {
|
|
58
|
-
const
|
|
58
|
+
const t_0 = transportRef.current;
|
|
59
59
|
transportRef.current = null;
|
|
60
60
|
clientRef.current = null;
|
|
61
|
-
if (
|
|
62
|
-
await
|
|
61
|
+
if (t_0) try {
|
|
62
|
+
await t_0.close();
|
|
63
63
|
} catch {}
|
|
64
64
|
};
|
|
65
65
|
const doConnect = useEffectEvent(async () => {
|
|
@@ -68,17 +68,17 @@ const useMcpServerResource = (props) => {
|
|
|
68
68
|
setLastError(null);
|
|
69
69
|
setAuthorizationUrl(null);
|
|
70
70
|
setTools([]);
|
|
71
|
-
let
|
|
71
|
+
let transport_0 = null;
|
|
72
72
|
try {
|
|
73
|
-
|
|
74
|
-
await finalizeConnect(
|
|
73
|
+
transport_0 = await buildTransport();
|
|
74
|
+
await finalizeConnect(transport_0);
|
|
75
75
|
} catch (err) {
|
|
76
76
|
if (err instanceof UnauthorizedError) {
|
|
77
|
-
transportRef.current =
|
|
77
|
+
transportRef.current = transport_0;
|
|
78
78
|
setConnectionState("authRequired");
|
|
79
79
|
} else {
|
|
80
|
-
if (
|
|
81
|
-
await
|
|
80
|
+
if (transport_0) try {
|
|
81
|
+
await transport_0.close();
|
|
82
82
|
} catch {}
|
|
83
83
|
setLastError({ message: err instanceof Error ? err.message : String(err) });
|
|
84
84
|
setConnectionState("error");
|
|
@@ -97,17 +97,17 @@ const useMcpServerResource = (props) => {
|
|
|
97
97
|
try {
|
|
98
98
|
const code = new URL(callbackUrl).searchParams.get("code");
|
|
99
99
|
if (!code) throw new Error("missing authorization code in callback URL");
|
|
100
|
-
let
|
|
101
|
-
if (!
|
|
102
|
-
|
|
103
|
-
transportRef.current =
|
|
100
|
+
let transport_1 = transportRef.current;
|
|
101
|
+
if (!transport_1) {
|
|
102
|
+
transport_1 = await buildTransport();
|
|
103
|
+
transportRef.current = transport_1;
|
|
104
104
|
}
|
|
105
|
-
await
|
|
105
|
+
await transport_1.finishAuth(code);
|
|
106
106
|
setAuthorizationUrl(null);
|
|
107
|
-
await finalizeConnect(
|
|
108
|
-
} catch (
|
|
107
|
+
await finalizeConnect(transport_1);
|
|
108
|
+
} catch (err_0) {
|
|
109
109
|
await closeTransport();
|
|
110
|
-
setLastError({ message:
|
|
110
|
+
setLastError({ message: err_0 instanceof Error ? err_0.message : String(err_0) });
|
|
111
111
|
setConnectionState("error");
|
|
112
112
|
}
|
|
113
113
|
});
|
|
@@ -121,22 +121,22 @@ const useMcpServerResource = (props) => {
|
|
|
121
121
|
doConnect();
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
124
|
-
const
|
|
124
|
+
const persisted_0 = await props.storage.loadAuthState(props.id);
|
|
125
125
|
if (signal.cancelled) return;
|
|
126
126
|
if (props.auth.type === "oauth") {
|
|
127
|
-
if (!
|
|
128
|
-
} else if (!
|
|
127
|
+
if (!persisted_0?.tokens) return;
|
|
128
|
+
} else if (!persisted_0?.token) return;
|
|
129
129
|
doConnect();
|
|
130
130
|
});
|
|
131
131
|
useEffect(() => {
|
|
132
|
-
const
|
|
133
|
-
tryAutoConnect(
|
|
132
|
+
const signal_0 = { cancelled: false };
|
|
133
|
+
tryAutoConnect(signal_0);
|
|
134
134
|
return () => {
|
|
135
|
-
|
|
136
|
-
const
|
|
135
|
+
signal_0.cancelled = true;
|
|
136
|
+
const t_1 = transportRef.current;
|
|
137
137
|
transportRef.current = null;
|
|
138
138
|
clientRef.current = null;
|
|
139
|
-
if (
|
|
139
|
+
if (t_1) t_1.close().catch(() => {});
|
|
140
140
|
};
|
|
141
141
|
}, []);
|
|
142
142
|
const state = useMemo(() => ({
|
|
@@ -170,17 +170,17 @@ const useMcpServerResource = (props) => {
|
|
|
170
170
|
await props.onRemove();
|
|
171
171
|
},
|
|
172
172
|
callTool: async (name, args) => {
|
|
173
|
-
const
|
|
174
|
-
if (!
|
|
175
|
-
return await
|
|
173
|
+
const client_0 = clientRef.current;
|
|
174
|
+
if (!client_0) throw new Error(`MCP server "${props.id}" is not connected`);
|
|
175
|
+
return await client_0.callTool({
|
|
176
176
|
name,
|
|
177
177
|
arguments: args
|
|
178
178
|
});
|
|
179
179
|
},
|
|
180
180
|
readResource: async (uri) => {
|
|
181
|
-
const
|
|
182
|
-
if (!
|
|
183
|
-
return await
|
|
181
|
+
const client_1 = clientRef.current;
|
|
182
|
+
if (!client_1) throw new Error(`MCP server "${props.id}" is not connected`);
|
|
183
|
+
return await client_1.readResource({ uri });
|
|
184
184
|
},
|
|
185
185
|
completeAuth: doCompleteAuth
|
|
186
186
|
};
|