@assistant-ui/react-mcp 0.1.21 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/createOAuthProvider.d.ts.map +1 -1
- package/dist/auth/createOAuthProvider.js +7 -1
- package/dist/auth/createOAuthProvider.js.map +1 -1
- package/dist/primitives/addForm/McpAddFormRoot.d.ts.map +1 -1
- package/dist/primitives/addForm/McpAddFormRoot.js +14 -5
- package/dist/primitives/addForm/McpAddFormRoot.js.map +1 -1
- package/dist/resources/McpCustomServerPersistence.d.ts +17 -0
- package/dist/resources/McpCustomServerPersistence.d.ts.map +1 -0
- package/dist/resources/McpCustomServerPersistence.js +192 -0
- package/dist/resources/McpCustomServerPersistence.js.map +1 -0
- package/dist/resources/McpElicitationLifecycle.d.ts +12 -0
- package/dist/resources/McpElicitationLifecycle.d.ts.map +1 -0
- package/dist/resources/McpElicitationLifecycle.js +144 -0
- package/dist/resources/McpElicitationLifecycle.js.map +1 -0
- package/dist/resources/McpManagerResource.d.ts.map +1 -1
- package/dist/resources/McpManagerResource.js +28 -205
- package/dist/resources/McpManagerResource.js.map +1 -1
- package/dist/resources/McpServerResource.d.ts.map +1 -1
- package/dist/resources/McpServerResource.js +24 -101
- package/dist/resources/McpServerResource.js.map +1 -1
- package/dist/resources/storage/McpLocalStorage.d.ts +1 -4
- package/dist/resources/storage/McpLocalStorage.d.ts.map +1 -1
- package/dist/resources/storage/McpLocalStorage.js +1 -100
- package/dist/resources/storage/McpLocalStorage.js.map +1 -1
- package/dist/resources/storage/McpStoredDataNormalization.d.ts +5 -0
- package/dist/resources/storage/McpStoredDataNormalization.d.ts.map +1 -0
- package/dist/resources/storage/McpStoredDataNormalization.js +95 -0
- package/dist/resources/storage/McpStoredDataNormalization.js.map +1 -0
- package/dist/utils/serverUrl.d.ts +1 -0
- package/dist/utils/serverUrl.d.ts.map +1 -1
- package/dist/utils/serverUrl.js +15 -1
- package/dist/utils/serverUrl.js.map +1 -1
- package/package.json +10 -9
- package/src/auth/createOAuthProvider.test.ts +30 -1
- package/src/auth/createOAuthProvider.ts +12 -4
- package/src/primitives/addForm/McpAddFormRoot.test.tsx +66 -0
- package/src/primitives/addForm/McpAddFormRoot.tsx +11 -1
- package/src/resources/McpCustomServerPersistence.test.ts +56 -0
- package/src/resources/McpCustomServerPersistence.ts +233 -0
- package/src/resources/McpElicitationLifecycle.test.ts +83 -0
- package/src/resources/McpElicitationLifecycle.ts +156 -0
- package/src/resources/McpManagerResource.test.ts +36 -0
- package/src/resources/McpManagerResource.ts +25 -248
- package/src/resources/McpServerResource.test.ts +123 -10
- package/src/resources/McpServerResource.ts +29 -149
- package/src/resources/storage/McpLocalStorage.ts +9 -209
- package/src/resources/storage/McpStoredDataNormalization.test.ts +24 -0
- package/src/resources/storage/McpStoredDataNormalization.ts +201 -0
- package/src/utils/serverUrl.test.ts +30 -0
- package/src/utils/serverUrl.ts +26 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { createMcpId } from "../utils/createMcpId.js";
|
|
2
|
+
import { validateElicitationContent } from "./validateElicitationContent.js";
|
|
3
|
+
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
4
|
+
import { useRef, useState } from "@assistant-ui/tap/react-shim";
|
|
5
|
+
//#region src/resources/McpElicitationLifecycle.ts
|
|
6
|
+
const useMcpElicitationLifecycle = () => {
|
|
7
|
+
const $ = c(9);
|
|
8
|
+
let t0;
|
|
9
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
10
|
+
t0 = [];
|
|
11
|
+
$[0] = t0;
|
|
12
|
+
} else t0 = $[0];
|
|
13
|
+
const [pendingElicitations, setPendingElicitations] = useState(t0);
|
|
14
|
+
let t1;
|
|
15
|
+
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
|
16
|
+
t1 = /* @__PURE__ */ new Map();
|
|
17
|
+
$[1] = t1;
|
|
18
|
+
} else t1 = $[1];
|
|
19
|
+
const elicitationResolversRef = useRef(t1);
|
|
20
|
+
let t2;
|
|
21
|
+
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
|
22
|
+
t2 = (id, result) => {
|
|
23
|
+
const entry = elicitationResolversRef.current.get(id);
|
|
24
|
+
if (!entry) return false;
|
|
25
|
+
elicitationResolversRef.current.delete(id);
|
|
26
|
+
entry.signal.removeEventListener("abort", entry.onAbort);
|
|
27
|
+
setPendingElicitations((current) => current.filter((elicitation) => elicitation.id !== id));
|
|
28
|
+
entry.resolve(result);
|
|
29
|
+
return true;
|
|
30
|
+
};
|
|
31
|
+
$[2] = t2;
|
|
32
|
+
} else t2 = $[2];
|
|
33
|
+
const resolvePendingElicitation = t2;
|
|
34
|
+
let t3;
|
|
35
|
+
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
|
|
36
|
+
t3 = (id_0, error) => {
|
|
37
|
+
if (!elicitationResolversRef.current.has(id_0)) return false;
|
|
38
|
+
setPendingElicitations((current_0) => current_0.map((elicitation_0) => elicitation_0.id === id_0 ? {
|
|
39
|
+
...elicitation_0,
|
|
40
|
+
error
|
|
41
|
+
} : elicitation_0));
|
|
42
|
+
return true;
|
|
43
|
+
};
|
|
44
|
+
$[3] = t3;
|
|
45
|
+
} else t3 = $[3];
|
|
46
|
+
const setPendingElicitationError = t3;
|
|
47
|
+
let t4;
|
|
48
|
+
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
|
|
49
|
+
t4 = () => {
|
|
50
|
+
for (const [id_1] of elicitationResolversRef.current) resolvePendingElicitation(id_1, { action: "cancel" });
|
|
51
|
+
};
|
|
52
|
+
$[4] = t4;
|
|
53
|
+
} else t4 = $[4];
|
|
54
|
+
const cancelPendingElicitations = t4;
|
|
55
|
+
let t5;
|
|
56
|
+
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
|
57
|
+
t5 = (request, signal, isCurrentConnection) => {
|
|
58
|
+
if (!isCurrentConnection()) return Promise.resolve({ action: "cancel" });
|
|
59
|
+
if (!("requestedSchema" in request.params)) return Promise.resolve({ action: "cancel" });
|
|
60
|
+
const { message, requestedSchema } = request.params;
|
|
61
|
+
const id_2 = createMcpId();
|
|
62
|
+
const promise = new Promise((resolve) => {
|
|
63
|
+
const onAbort = () => {
|
|
64
|
+
resolvePendingElicitation(id_2, { action: "cancel" });
|
|
65
|
+
};
|
|
66
|
+
elicitationResolversRef.current.set(id_2, {
|
|
67
|
+
resolve,
|
|
68
|
+
signal,
|
|
69
|
+
onAbort,
|
|
70
|
+
requestedSchema
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
setPendingElicitations((current_1) => [...current_1, {
|
|
74
|
+
id: id_2,
|
|
75
|
+
message,
|
|
76
|
+
requestedSchema
|
|
77
|
+
}]);
|
|
78
|
+
const entry_0 = elicitationResolversRef.current.get(id_2);
|
|
79
|
+
if (entry_0) {
|
|
80
|
+
if (signal.aborted) entry_0.onAbort();
|
|
81
|
+
else signal.addEventListener("abort", entry_0.onAbort, { once: true });
|
|
82
|
+
}
|
|
83
|
+
return promise;
|
|
84
|
+
};
|
|
85
|
+
$[5] = t5;
|
|
86
|
+
} else t5 = $[5];
|
|
87
|
+
const requestElicitation = t5;
|
|
88
|
+
let t6;
|
|
89
|
+
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
|
|
90
|
+
t6 = (id_3, response) => {
|
|
91
|
+
if (response.action === "accept") {
|
|
92
|
+
const entry_1 = elicitationResolversRef.current.get(id_3);
|
|
93
|
+
if (!entry_1) return;
|
|
94
|
+
if (typeof response.content !== "object" || response.content === null || Array.isArray(response.content)) {
|
|
95
|
+
const errors = [{
|
|
96
|
+
property: "content",
|
|
97
|
+
message: "Response content must be an object."
|
|
98
|
+
}];
|
|
99
|
+
setPendingElicitationError(id_3, {
|
|
100
|
+
message: "Invalid elicitation content: content.",
|
|
101
|
+
properties: ["content"]
|
|
102
|
+
});
|
|
103
|
+
return errors;
|
|
104
|
+
}
|
|
105
|
+
const errors_0 = validateElicitationContent(entry_1.requestedSchema, response.content);
|
|
106
|
+
if (errors_0.length > 0) {
|
|
107
|
+
const properties = [...new Set(errors_0.map(_temp))];
|
|
108
|
+
setPendingElicitationError(id_3, {
|
|
109
|
+
message: `Invalid elicitation content: ${properties.join(", ")}.`,
|
|
110
|
+
properties
|
|
111
|
+
});
|
|
112
|
+
return errors_0;
|
|
113
|
+
}
|
|
114
|
+
const result_0 = {
|
|
115
|
+
action: "accept",
|
|
116
|
+
content: response.content
|
|
117
|
+
};
|
|
118
|
+
resolvePendingElicitation(id_3, result_0);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
resolvePendingElicitation(id_3, { action: response.action });
|
|
122
|
+
};
|
|
123
|
+
$[6] = t6;
|
|
124
|
+
} else t6 = $[6];
|
|
125
|
+
let t7;
|
|
126
|
+
if ($[7] !== pendingElicitations) {
|
|
127
|
+
t7 = {
|
|
128
|
+
pendingElicitations,
|
|
129
|
+
cancelPendingElicitations,
|
|
130
|
+
requestElicitation,
|
|
131
|
+
answerElicitation: t6
|
|
132
|
+
};
|
|
133
|
+
$[7] = pendingElicitations;
|
|
134
|
+
$[8] = t7;
|
|
135
|
+
} else t7 = $[8];
|
|
136
|
+
return t7;
|
|
137
|
+
};
|
|
138
|
+
function _temp(error_0) {
|
|
139
|
+
return error_0.property;
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
export { useMcpElicitationLifecycle };
|
|
143
|
+
|
|
144
|
+
//# sourceMappingURL=McpElicitationLifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpElicitationLifecycle.js","names":["useRef","useState","ElicitRequest","ElicitResult","MCPElicitation","MCPElicitationResponse","createMcpId","validateElicitationContent","useMcpElicitationLifecycle","$","_c","t0","Symbol","for","pendingElicitations","setPendingElicitations","t1","Map","elicitationResolversRef","t2","id","result","entry","current","get","delete","signal","removeEventListener","onAbort","filter","elicitation","resolve","resolvePendingElicitation","t3","id_0","error","has","current_0","map","elicitation_0","setPendingElicitationError","t4","id_1","action","cancelPendingElicitations","t5","request","isCurrentConnection","Promise","params","message","requestedSchema","id_2","promise","set","current_1","entry_0","aborted","addEventListener","once","requestElicitation","t6","id_3","response","entry_1","content","Array","isArray","errors","property","properties","errors_0","length","Set","_temp","join","result_0","t7","answerElicitation","error_0","_c"],"sources":["../../src/resources/McpElicitationLifecycle.ts"],"sourcesContent":["import { useRef, useState } from \"react\";\nimport type { ElicitRequest, ElicitResult } from \"@modelcontextprotocol/client\";\nimport type { MCPElicitation, MCPElicitationResponse } from \"../mcp-scope\";\nimport { createMcpId } from \"../utils/createMcpId\";\nimport { validateElicitationContent } from \"./validateElicitationContent\";\n\nexport const useMcpElicitationLifecycle = () => {\n const [pendingElicitations, setPendingElicitations] = useState<\n MCPElicitation[]\n >([]);\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 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 requestElicitation = (\n request: ElicitRequest,\n signal: AbortSignal,\n isCurrentConnection: () => boolean,\n ): Promise<ElicitResult> => {\n if (!isCurrentConnection()) {\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,\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 (signal.aborted) {\n entry.onAbort();\n } else {\n signal.addEventListener(\"abort\", entry.onAbort, {\n once: true,\n });\n }\n }\n return promise;\n };\n\n return {\n pendingElicitations,\n cancelPendingElicitations,\n requestElicitation,\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"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpManagerResource.d.ts","sourceRoot":"","sources":["../../src/resources/McpManagerResource.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"McpManagerResource.d.ts","sourceRoot":"","sources":["../../src/resources/McpManagerResource.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAc7B,OAAO,KAAK,EAAE,iBAAiB,EAAE,2BAAwB;AAEzD,OAAO,KAAK,EAEV,YAAY,EAGb,wBAAqB;AAEtB,MAAM,MAAM,uBAAuB,GAAG;IACpC,UAAU,CAAC,EAAE,YAAY,EAAE,GAAG,SAAS,CAAC;IACxC,OAAO,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACxC,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,8DAA8D;IAC9D,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC,CAAC;AA4OF,eAAO,MAAM,kBAAkB,6FAAkC,CAAC"}
|
|
@@ -3,10 +3,11 @@ import { assertUniqueServerIds } from "../utils/serverId.js";
|
|
|
3
3
|
import { createMcpId } from "../utils/createMcpId.js";
|
|
4
4
|
import { withMcpServerRemovalFence } from "./McpServerRemovalFence.js";
|
|
5
5
|
import { McpServerResource } from "./McpServerResource.js";
|
|
6
|
+
import { McpCustomServersResource, holdCustomServerPersistence } from "./McpCustomServerPersistence.js";
|
|
6
7
|
import { McpLocalStorage } from "./storage/McpLocalStorage.js";
|
|
7
8
|
import { c } from "@assistant-ui/tap/react-shim/compiler-runtime";
|
|
8
9
|
import { attachTransformScopes, useAssistantClientRef, useClientLookup } from "@assistant-ui/store";
|
|
9
|
-
import {
|
|
10
|
+
import { useState } from "@assistant-ui/tap/react-shim";
|
|
10
11
|
import { resource, useResource, withKey } from "@assistant-ui/tap";
|
|
11
12
|
import { useAssistantScopeEffect } from "@assistant-ui/store/client";
|
|
12
13
|
import { ModelContext } from "@assistant-ui/core/store";
|
|
@@ -16,184 +17,6 @@ function defaultRedirectUri() {
|
|
|
16
17
|
return `${window.location.origin}/mcp/callback`;
|
|
17
18
|
}
|
|
18
19
|
const NO_CONNECTORS = [];
|
|
19
|
-
const reportCustomStorageFailure = (operation, error) => {
|
|
20
|
-
console.error(`[assistant-ui/react-mcp] failed to ${operation} custom servers:`, error);
|
|
21
|
-
};
|
|
22
|
-
const reportBlockedCustomServerPersistence = () => {
|
|
23
|
-
console.error("[assistant-ui/react-mcp] custom server changes remain in memory because loading the persisted list failed; remount the manager to retry");
|
|
24
|
-
};
|
|
25
|
-
const persistCustomServers = async (storage, records) => {
|
|
26
|
-
try {
|
|
27
|
-
await storage.saveCustomServers(records);
|
|
28
|
-
} catch (error) {
|
|
29
|
-
reportCustomStorageFailure("save", error);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
const enqueueCustomServerTask = (persistenceQueues, scopeKey, task) => {
|
|
33
|
-
const next = (persistenceQueues.get(scopeKey) ?? Promise.resolve()).then(task);
|
|
34
|
-
persistenceQueues.set(scopeKey, next);
|
|
35
|
-
next.then(() => {
|
|
36
|
-
if (persistenceQueues.get(scopeKey) === next) persistenceQueues.delete(scopeKey);
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
const enqueueCustomServerPersistence = (persistenceQueues, scopeKey, storage, records) => enqueueCustomServerTask(persistenceQueues, scopeKey, () => persistCustomServers(storage, records));
|
|
40
|
-
const holdCustomServerPersistence = (persistenceQueues, scopeKey) => {
|
|
41
|
-
let release = () => {};
|
|
42
|
-
const gate = new Promise((resolve) => {
|
|
43
|
-
release = resolve;
|
|
44
|
-
});
|
|
45
|
-
enqueueCustomServerTask(persistenceQueues, scopeKey, () => gate);
|
|
46
|
-
return release;
|
|
47
|
-
};
|
|
48
|
-
const deduplicateCustomServers = (records) => {
|
|
49
|
-
const seen = /* @__PURE__ */ new Set();
|
|
50
|
-
return records.filter((record) => {
|
|
51
|
-
if (seen.has(record.id)) {
|
|
52
|
-
console.error(`[assistant-ui/react-mcp] ignored duplicate custom server id "${record.id}" loaded from storage`);
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
seen.add(record.id);
|
|
56
|
-
return true;
|
|
57
|
-
});
|
|
58
|
-
};
|
|
59
|
-
const useMcpCustomServersResource = (t0) => {
|
|
60
|
-
const $ = c(22);
|
|
61
|
-
const { storage, scopeKey, persistenceQueues } = t0;
|
|
62
|
-
let t1;
|
|
63
|
-
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
64
|
-
t1 = [];
|
|
65
|
-
$[0] = t1;
|
|
66
|
-
} else t1 = $[0];
|
|
67
|
-
const [customServers, setCustomServers] = useState(t1);
|
|
68
|
-
const [isHydrated, setIsHydrated] = useState(false);
|
|
69
|
-
let t2;
|
|
70
|
-
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
|
|
71
|
-
t2 = [];
|
|
72
|
-
$[1] = t2;
|
|
73
|
-
} else t2 = $[1];
|
|
74
|
-
const customServersRef = useRef(t2);
|
|
75
|
-
const hydrationStateRef = useRef("pending");
|
|
76
|
-
const hasPendingMutationRef = useRef(false);
|
|
77
|
-
const [removedBeforeHydration] = useState(_temp);
|
|
78
|
-
const reportedBlockedPersistenceRef = useRef(false);
|
|
79
|
-
let t3;
|
|
80
|
-
if ($[2] !== persistenceQueues || $[3] !== removedBeforeHydration || $[4] !== scopeKey || $[5] !== storage) {
|
|
81
|
-
t3 = async (signal) => {
|
|
82
|
-
while (true) {
|
|
83
|
-
const pendingPersistence = persistenceQueues.get(scopeKey);
|
|
84
|
-
if (!pendingPersistence) break;
|
|
85
|
-
await pendingPersistence;
|
|
86
|
-
if (signal.cancelled) return;
|
|
87
|
-
if (persistenceQueues.get(scopeKey) === pendingPersistence) break;
|
|
88
|
-
}
|
|
89
|
-
let records;
|
|
90
|
-
try {
|
|
91
|
-
const loadedRecords = await storage.loadCustomServers();
|
|
92
|
-
records = deduplicateCustomServers(loadedRecords);
|
|
93
|
-
} catch (t4) {
|
|
94
|
-
const error = t4;
|
|
95
|
-
if (!signal.cancelled) {
|
|
96
|
-
reportCustomStorageFailure("load", error);
|
|
97
|
-
hydrationStateRef.current = "failed";
|
|
98
|
-
if (hasPendingMutationRef.current) {
|
|
99
|
-
reportBlockedCustomServerPersistence();
|
|
100
|
-
reportedBlockedPersistenceRef.current = true;
|
|
101
|
-
}
|
|
102
|
-
setIsHydrated(true);
|
|
103
|
-
}
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
const hadPendingMutation = hasPendingMutationRef.current;
|
|
107
|
-
const hydratedRecords = records.filter((record) => !removedBeforeHydration.has(record.id));
|
|
108
|
-
const mergedRecords = (() => {
|
|
109
|
-
const prev = customServersRef.current;
|
|
110
|
-
if (prev.length === 0) return hydratedRecords;
|
|
111
|
-
const persistedIds = new Set(hydratedRecords.map(_temp2));
|
|
112
|
-
return [...hydratedRecords, ...prev.filter((r_0) => !persistedIds.has(r_0.id))];
|
|
113
|
-
})();
|
|
114
|
-
customServersRef.current = mergedRecords;
|
|
115
|
-
hydrationStateRef.current = "succeeded";
|
|
116
|
-
hasPendingMutationRef.current = false;
|
|
117
|
-
if (hadPendingMutation) enqueueCustomServerPersistence(persistenceQueues, scopeKey, storage, mergedRecords);
|
|
118
|
-
if (signal.cancelled) return;
|
|
119
|
-
setCustomServers(mergedRecords);
|
|
120
|
-
setIsHydrated(true);
|
|
121
|
-
};
|
|
122
|
-
$[2] = persistenceQueues;
|
|
123
|
-
$[3] = removedBeforeHydration;
|
|
124
|
-
$[4] = scopeKey;
|
|
125
|
-
$[5] = storage;
|
|
126
|
-
$[6] = t3;
|
|
127
|
-
} else t3 = $[6];
|
|
128
|
-
const hydrate = useEffectEvent(t3);
|
|
129
|
-
let t4;
|
|
130
|
-
if ($[7] !== hydrate) {
|
|
131
|
-
t4 = () => {
|
|
132
|
-
const signal_0 = { cancelled: false };
|
|
133
|
-
hydrate(signal_0);
|
|
134
|
-
return () => {
|
|
135
|
-
signal_0.cancelled = true;
|
|
136
|
-
};
|
|
137
|
-
};
|
|
138
|
-
$[7] = hydrate;
|
|
139
|
-
$[8] = t4;
|
|
140
|
-
} else t4 = $[8];
|
|
141
|
-
let t5;
|
|
142
|
-
if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
|
|
143
|
-
t5 = [];
|
|
144
|
-
$[9] = t5;
|
|
145
|
-
} else t5 = $[9];
|
|
146
|
-
useEffect(t4, t5);
|
|
147
|
-
let t6;
|
|
148
|
-
if ($[10] !== persistenceQueues || $[11] !== scopeKey || $[12] !== storage) {
|
|
149
|
-
t6 = (updater) => {
|
|
150
|
-
const next = updater(customServersRef.current);
|
|
151
|
-
customServersRef.current = next;
|
|
152
|
-
setCustomServers(next);
|
|
153
|
-
if (hydrationStateRef.current === "succeeded") {
|
|
154
|
-
enqueueCustomServerPersistence(persistenceQueues, scopeKey, storage, next);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
hasPendingMutationRef.current = true;
|
|
158
|
-
if (hydrationStateRef.current === "failed" && !reportedBlockedPersistenceRef.current) {
|
|
159
|
-
reportBlockedCustomServerPersistence();
|
|
160
|
-
reportedBlockedPersistenceRef.current = true;
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
$[10] = persistenceQueues;
|
|
164
|
-
$[11] = scopeKey;
|
|
165
|
-
$[12] = storage;
|
|
166
|
-
$[13] = t6;
|
|
167
|
-
} else t6 = $[13];
|
|
168
|
-
const updateCustomServers = t6;
|
|
169
|
-
let t7;
|
|
170
|
-
if ($[14] !== removedBeforeHydration || $[15] !== updateCustomServers) {
|
|
171
|
-
t7 = (id) => {
|
|
172
|
-
if (hydrationStateRef.current === "pending") removedBeforeHydration.add(id);
|
|
173
|
-
updateCustomServers((prev_0) => prev_0.filter((record_0) => record_0.id !== id));
|
|
174
|
-
};
|
|
175
|
-
$[14] = removedBeforeHydration;
|
|
176
|
-
$[15] = updateCustomServers;
|
|
177
|
-
$[16] = t7;
|
|
178
|
-
} else t7 = $[16];
|
|
179
|
-
const removeCustomServer = t7;
|
|
180
|
-
let t8;
|
|
181
|
-
if ($[17] !== customServers || $[18] !== isHydrated || $[19] !== removeCustomServer || $[20] !== updateCustomServers) {
|
|
182
|
-
t8 = {
|
|
183
|
-
customServers,
|
|
184
|
-
isHydrated,
|
|
185
|
-
updateCustomServers,
|
|
186
|
-
removeCustomServer
|
|
187
|
-
};
|
|
188
|
-
$[17] = customServers;
|
|
189
|
-
$[18] = isHydrated;
|
|
190
|
-
$[19] = removeCustomServer;
|
|
191
|
-
$[20] = updateCustomServers;
|
|
192
|
-
$[21] = t8;
|
|
193
|
-
} else t8 = $[21];
|
|
194
|
-
return t8;
|
|
195
|
-
};
|
|
196
|
-
const McpCustomServersResource = resource(useMcpCustomServersResource);
|
|
197
20
|
const useMcpManagerResource = (props) => {
|
|
198
21
|
const $ = c(75);
|
|
199
22
|
const connectors = props.connectors ?? NO_CONNECTORS;
|
|
@@ -213,7 +36,7 @@ const useMcpManagerResource = (props) => {
|
|
|
213
36
|
$[3] = t1;
|
|
214
37
|
} else t1 = $[3];
|
|
215
38
|
const storage = useResource(t1);
|
|
216
|
-
const [persistenceQueues] = useState(
|
|
39
|
+
const [persistenceQueues] = useState(_temp);
|
|
217
40
|
const storageScopeKey = storage.scopeId === void 0 ? "unscoped" : `scoped:${storage.scopeId}`;
|
|
218
41
|
let t2;
|
|
219
42
|
if ($[4] !== persistenceQueues || $[5] !== storage || $[6] !== storageScopeKey) {
|
|
@@ -228,7 +51,7 @@ const useMcpManagerResource = (props) => {
|
|
|
228
51
|
$[7] = t2;
|
|
229
52
|
} else t2 = $[7];
|
|
230
53
|
const { customServers, isHydrated, updateCustomServers, removeCustomServer } = useResource(t2);
|
|
231
|
-
assertUniqueServerIds([...connectors.map(
|
|
54
|
+
assertUniqueServerIds([...connectors.map(_temp2), ...customServers.map(_temp3)]);
|
|
232
55
|
let t3;
|
|
233
56
|
if ($[8] !== autoConnect || $[9] !== connectionTimeout || $[10] !== connectors || $[11] !== customServers || $[12] !== persistenceQueues || $[13] !== redirectUri || $[14] !== removeCustomServer || $[15] !== storage || $[16] !== storageScopeKey) {
|
|
234
57
|
let t4;
|
|
@@ -246,7 +69,7 @@ const useMcpManagerResource = (props) => {
|
|
|
246
69
|
connectionTimeout: c_0.connectionTimeout ?? connectionTimeout,
|
|
247
70
|
...c_0.cache !== void 0 ? { cache: c_0.cache } : {},
|
|
248
71
|
...c_0.elicitation !== void 0 ? { elicitation: c_0.elicitation } : {},
|
|
249
|
-
onRemove:
|
|
72
|
+
onRemove: _temp4
|
|
250
73
|
}));
|
|
251
74
|
$[18] = autoConnect;
|
|
252
75
|
$[19] = connectionTimeout;
|
|
@@ -299,13 +122,13 @@ const useMcpManagerResource = (props) => {
|
|
|
299
122
|
const all = lookup.state;
|
|
300
123
|
let t4;
|
|
301
124
|
if ($[31] !== all) {
|
|
302
|
-
t4 = all.filter(
|
|
125
|
+
t4 = all.filter(_temp5);
|
|
303
126
|
$[31] = all;
|
|
304
127
|
$[32] = t4;
|
|
305
128
|
} else t4 = $[32];
|
|
306
129
|
let t5;
|
|
307
130
|
if ($[33] !== all) {
|
|
308
|
-
t5 = all.filter(
|
|
131
|
+
t5 = all.filter(_temp6);
|
|
309
132
|
$[33] = all;
|
|
310
133
|
$[34] = t5;
|
|
311
134
|
} else t5 = $[34];
|
|
@@ -434,20 +257,26 @@ const useMcpManagerResource = (props) => {
|
|
|
434
257
|
if ($[61] !== lookup || $[62] !== persistenceQueues || $[63] !== removeCustomServer || $[64] !== state || $[65] !== storage || $[66] !== storageScopeKey) {
|
|
435
258
|
t15 = async (id) => {
|
|
436
259
|
if (state.connectors.some((c_1) => c_1.id === id)) throw new Error(`Cannot remove connector "${id}" — connectors are app-defined and not removable. Use a custom server id instead.`);
|
|
260
|
+
let server_0;
|
|
437
261
|
try {
|
|
438
|
-
|
|
262
|
+
server_0 = lookup.get({ key: id });
|
|
439
263
|
} catch {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
264
|
+
server_0 = void 0;
|
|
265
|
+
}
|
|
266
|
+
if (server_0) {
|
|
267
|
+
await server_0.remove();
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const releasePersistence = holdCustomServerPersistence(persistenceQueues, storageScopeKey);
|
|
271
|
+
try {
|
|
272
|
+
await clearOAuthProviderAuthState(storage, id);
|
|
273
|
+
removeCustomServer(id);
|
|
274
|
+
} catch (t16) {
|
|
275
|
+
const error = t16;
|
|
449
276
|
releasePersistence();
|
|
277
|
+
throw error;
|
|
450
278
|
}
|
|
279
|
+
releasePersistence();
|
|
451
280
|
};
|
|
452
281
|
$[61] = lookup;
|
|
453
282
|
$[62] = persistenceQueues;
|
|
@@ -482,25 +311,19 @@ attachTransformScopes(useMcpManagerResource, (scopes, parent) => {
|
|
|
482
311
|
if (!scopes.modelContext && parent.modelContext.source === null) scopes.modelContext = ModelContext();
|
|
483
312
|
});
|
|
484
313
|
function _temp() {
|
|
485
|
-
return /* @__PURE__ */ new Set();
|
|
486
|
-
}
|
|
487
|
-
function _temp2(r) {
|
|
488
|
-
return r.id;
|
|
489
|
-
}
|
|
490
|
-
function _temp3() {
|
|
491
314
|
return /* @__PURE__ */ new Map();
|
|
492
315
|
}
|
|
493
|
-
function
|
|
316
|
+
function _temp2(c) {
|
|
494
317
|
return c.id;
|
|
495
318
|
}
|
|
496
|
-
function
|
|
319
|
+
function _temp3(s) {
|
|
497
320
|
return s.id;
|
|
498
321
|
}
|
|
499
|
-
async function
|
|
500
|
-
function
|
|
322
|
+
async function _temp4() {}
|
|
323
|
+
function _temp5(s_1) {
|
|
501
324
|
return s_1.kind === "connector";
|
|
502
325
|
}
|
|
503
|
-
function
|
|
326
|
+
function _temp6(s_2) {
|
|
504
327
|
return s_2.kind === "custom";
|
|
505
328
|
}
|
|
506
329
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpManagerResource.js","names":["useState","useEffect","useMemo","useEffectEvent","useRef","useCallback","useResource","resource","withKey","useClientLookup","useAssistantClientRef","attachTransformScopes","ClientOutput","useAssistantScopeEffect","ModelContext","createMcpId","clearOAuthProviderAuthState","Tool","McpServerResource","withMcpServerRemovalFence","McpLocalStorage","MCPStorage","MCPStorageElement","assertUniqueServerIds","MCPAuthConfig","MCPConnector","MCPCustomServerRecord","MCPManagerState","McpManagerResourceProps","connectors","storage","oauthRedirectUri","autoConnect","connectionTimeout","defaultRedirectUri","window","location","origin","NO_CONNECTORS","reportCustomStorageFailure","operation","error","console","reportBlockedCustomServerPersistence","persistCustomServers","records","saveCustomServers","CustomServerPersistenceQueues","Map","Promise","enqueueCustomServerTask","persistenceQueues","scopeKey","task","previous","get","next","resolve","then","set","delete","enqueueCustomServerPersistence","holdCustomServerPersistence","release","gate","deduplicateCustomServers","seen","Set","filter","record","has","id","add","McpCustomServersResourceProps","useMcpCustomServersResource","t0","$","_c","t1","Symbol","for","customServers","setCustomServers","isHydrated","setIsHydrated","t2","customServersRef","hydrationStateRef","hasPendingMutationRef","removedBeforeHydration","_temp","reportedBlockedPersistenceRef","t3","signal","pendingPersistence","cancelled","loadedRecords","loadCustomServers","t4","current","hadPendingMutation","hydratedRecords","mergedRecords","prev","length","persistedIds","map","_temp2","r_0","r","hydrate","signal_0","t5","t6","updater","updateCustomServers","t7","prev_0","record_0","removeCustomServer","t8","McpCustomServersResource","useMcpManagerResource","props","redirectUri","storageElement","_temp3","storageScopeKey","scopeId","undefined","_temp4","_temp5","c_0","c","kind","name","url","icon","auth","cache","elicitation","onRemove","_temp6","connectorElements","s_0","s","customElements","serverElements","lookup","all","state","_temp7","_temp8","servers","out","server","connectionState","tool","tools","fullName","type","description","parameters","inputSchema","execute","args","key","callTool","toolkit","clientRef","client","modelContext","register","getModelContext","t9","index","list","entry","Error","serverByKind","t10","t11","query","t12","t13","t14","index_0","t15","index_1","connectionTimeout_0","createdAt","Date","now","some","c_1","remove","releasePersistence","t16","getState","connector","customServer","addCustomServer","removeServer","McpManagerResource","scopes","parent","source","s_1","s_2","_c","storageElement","serverElements"],"sources":["../../src/resources/McpManagerResource.ts"],"sourcesContent":["import {\n useState,\n useEffect,\n useMemo,\n useEffectEvent,\n useRef,\n useCallback,\n} from \"react\";\nimport { useResource, resource, withKey } from \"@assistant-ui/tap\";\nimport {\n useClientLookup,\n useAssistantClientRef,\n attachTransformScopes,\n type ClientOutput,\n} from \"@assistant-ui/store\";\nimport { useAssistantScopeEffect } from \"@assistant-ui/store/client\";\nimport { ModelContext } from \"@assistant-ui/core/store\";\nimport { createMcpId } from \"../utils/createMcpId\";\nimport { clearOAuthProviderAuthState } from \"../auth/createOAuthProvider\";\nimport type { Tool } from \"assistant-stream\";\nimport { McpServerResource } from \"./McpServerResource\";\nimport { withMcpServerRemovalFence } from \"./McpServerRemovalFence\";\nimport { McpLocalStorage } from \"./storage/McpLocalStorage\";\nimport type { MCPStorage, MCPStorageElement } from \"./storage/types\";\nimport { assertUniqueServerIds } from \"../utils/serverId\";\nimport type {\n MCPAuthConfig,\n MCPConnector,\n MCPCustomServerRecord,\n MCPManagerState,\n} from \"../mcp-scope\";\n\nexport type McpManagerResourceProps = {\n connectors?: MCPConnector[] | undefined;\n storage?: MCPStorageElement | undefined;\n /** OAuth redirect target. Defaults to `${origin}/mcp/callback`. */\n oauthRedirectUri?: string | undefined;\n /** Connect on mount when usable auth exists. Default true. */\n autoConnect?: boolean | undefined;\n /** Optional timeout in milliseconds for connect/listTools calls. Disabled by default. */\n connectionTimeout?: number | undefined;\n};\n\nfunction defaultRedirectUri(): string {\n if (typeof window === \"undefined\") return \"\";\n return `${window.location.origin}/mcp/callback`;\n}\n\n// Stable empty fallback so an absent `connectors` prop doesn't produce a fresh\n// array each render (which would invalidate the serverElements memo below).\nconst NO_CONNECTORS: MCPConnector[] = [];\n\nconst reportCustomStorageFailure = (\n operation: \"load\" | \"save\",\n error: unknown,\n) => {\n console.error(\n `[assistant-ui/react-mcp] failed to ${operation} custom servers:`,\n error,\n );\n};\n\nconst reportBlockedCustomServerPersistence = () => {\n console.error(\n \"[assistant-ui/react-mcp] custom server changes remain in memory because loading the persisted list failed; remount the manager to retry\",\n );\n};\n\nconst persistCustomServers = async (\n storage: MCPStorage,\n records: MCPCustomServerRecord[],\n) => {\n try {\n await storage.saveCustomServers(records);\n } catch (error) {\n reportCustomStorageFailure(\"save\", error);\n }\n};\n\ntype CustomServerPersistenceQueues = Map<string, Promise<void>>;\n\nconst enqueueCustomServerTask = (\n persistenceQueues: CustomServerPersistenceQueues,\n scopeKey: string,\n task: () => Promise<void>,\n) => {\n const previous = persistenceQueues.get(scopeKey);\n const next = (previous ?? Promise.resolve()).then(task);\n persistenceQueues.set(scopeKey, next);\n void next.then(() => {\n if (persistenceQueues.get(scopeKey) === next) {\n persistenceQueues.delete(scopeKey);\n }\n });\n};\n\nconst enqueueCustomServerPersistence = (\n persistenceQueues: CustomServerPersistenceQueues,\n scopeKey: string,\n storage: MCPStorage,\n records: MCPCustomServerRecord[],\n) =>\n enqueueCustomServerTask(persistenceQueues, scopeKey, () =>\n persistCustomServers(storage, records),\n );\n\nconst holdCustomServerPersistence = (\n persistenceQueues: CustomServerPersistenceQueues,\n scopeKey: string,\n) => {\n let release = () => {};\n const gate = new Promise<void>((resolve) => {\n release = resolve;\n });\n enqueueCustomServerTask(persistenceQueues, scopeKey, () => gate);\n return release;\n};\n\nconst deduplicateCustomServers = (records: MCPCustomServerRecord[]) => {\n const seen = new Set<string>();\n return records.filter((record) => {\n if (seen.has(record.id)) {\n console.error(\n `[assistant-ui/react-mcp] ignored duplicate custom server id \"${record.id}\" loaded from storage`,\n );\n return false;\n }\n seen.add(record.id);\n return true;\n });\n};\n\ntype McpCustomServersResourceProps = {\n storage: MCPStorage;\n scopeKey: string;\n persistenceQueues: CustomServerPersistenceQueues;\n};\n\nconst useMcpCustomServersResource = ({\n storage,\n scopeKey,\n persistenceQueues,\n}: McpCustomServersResourceProps) => {\n const [customServers, setCustomServers] = useState<MCPCustomServerRecord[]>(\n [],\n );\n const [isHydrated, setIsHydrated] = useState(false);\n\n const customServersRef = useRef<MCPCustomServerRecord[]>([]);\n const hydrationStateRef = useRef<\"pending\" | \"succeeded\" | \"failed\">(\n \"pending\",\n );\n const hasPendingMutationRef = useRef(false);\n const [removedBeforeHydration] = useState(() => new Set<string>());\n const reportedBlockedPersistenceRef = useRef(false);\n\n const hydrate = useEffectEvent(async (signal: { cancelled: boolean }) => {\n // A revisited scope must not read behind writes still queued against it.\n while (true) {\n const pendingPersistence = persistenceQueues.get(scopeKey);\n if (!pendingPersistence) break;\n await pendingPersistence;\n if (signal.cancelled) return;\n if (persistenceQueues.get(scopeKey) === pendingPersistence) break;\n }\n\n let records: Awaited<ReturnType<typeof storage.loadCustomServers>>;\n try {\n const loadedRecords = await storage.loadCustomServers();\n records = deduplicateCustomServers(loadedRecords);\n } catch (error) {\n if (!signal.cancelled) {\n reportCustomStorageFailure(\"load\", error);\n hydrationStateRef.current = \"failed\";\n if (hasPendingMutationRef.current) {\n reportBlockedCustomServerPersistence();\n reportedBlockedPersistenceRef.current = true;\n }\n setIsHydrated(true);\n }\n return;\n }\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 const hadPendingMutation = hasPendingMutationRef.current;\n const hydratedRecords = records.filter(\n (record) => !removedBeforeHydration.has(record.id),\n );\n const mergedRecords = (() => {\n const prev = customServersRef.current;\n if (prev.length === 0) return hydratedRecords;\n const persistedIds = new Set(hydratedRecords.map((r) => r.id));\n return [\n ...hydratedRecords,\n ...prev.filter((r) => !persistedIds.has(r.id)),\n ];\n })();\n customServersRef.current = mergedRecords;\n hydrationStateRef.current = \"succeeded\";\n hasPendingMutationRef.current = false;\n if (hadPendingMutation) {\n enqueueCustomServerPersistence(\n persistenceQueues,\n scopeKey,\n storage,\n mergedRecords,\n );\n }\n if (signal.cancelled) return;\n setCustomServers(mergedRecords);\n setIsHydrated(true);\n });\n\n useEffect(() => {\n const signal = { cancelled: false };\n // Hydration reads persisted records asynchronously; there is no earlier\n // point than mount at which to start it.\n // eslint-disable-next-line react-hooks/set-state-in-effect\n void hydrate(signal);\n return () => {\n signal.cancelled = true;\n };\n }, []);\n\n const updateCustomServers = useCallback(\n (\n updater: (records: MCPCustomServerRecord[]) => MCPCustomServerRecord[],\n ) => {\n const next = updater(customServersRef.current);\n customServersRef.current = next;\n setCustomServers(next);\n\n if (hydrationStateRef.current === \"succeeded\") {\n enqueueCustomServerPersistence(\n persistenceQueues,\n scopeKey,\n storage,\n next,\n );\n return;\n }\n\n hasPendingMutationRef.current = true;\n if (\n hydrationStateRef.current === \"failed\" &&\n !reportedBlockedPersistenceRef.current\n ) {\n reportBlockedCustomServerPersistence();\n reportedBlockedPersistenceRef.current = true;\n }\n },\n [persistenceQueues, scopeKey, storage],\n );\n\n const removeCustomServer = useCallback(\n (id: string) => {\n if (hydrationStateRef.current === \"pending\") {\n removedBeforeHydration.add(id);\n }\n updateCustomServers((prev) => prev.filter((record) => record.id !== id));\n },\n [removedBeforeHydration, updateCustomServers],\n );\n\n return {\n customServers,\n isHydrated,\n updateCustomServers,\n removeCustomServer,\n };\n};\n\nconst McpCustomServersResource = resource(useMcpCustomServersResource);\n\nconst useMcpManagerResource = (\n props: McpManagerResourceProps,\n): ClientOutput<\"mcp\"> => {\n const connectors = props.connectors ?? NO_CONNECTORS;\n const autoConnect = props.autoConnect ?? true;\n const redirectUri = props.oauthRedirectUri ?? defaultRedirectUri();\n const connectionTimeout = props.connectionTimeout;\n\n const storageElement = props.storage ?? McpLocalStorage();\n const storage = useResource(storageElement);\n const [persistenceQueues] = useState<CustomServerPersistenceQueues>(\n () => new Map(),\n );\n const storageScopeKey =\n storage.scopeId === undefined ? \"unscoped\" : `scoped:${storage.scopeId}`;\n const { customServers, isHydrated, updateCustomServers, removeCustomServer } =\n useResource(\n withKey(\n storageScopeKey,\n McpCustomServersResource({\n storage,\n scopeKey: storageScopeKey,\n persistenceQueues,\n }),\n ),\n );\n\n const serverElements = useMemo(() => {\n assertUniqueServerIds([\n ...connectors.map((c) => c.id),\n ...customServers.map((s) => s.id),\n ]);\n\n const connectorElements = connectors.map((c) =>\n withKey(\n c.id,\n McpServerResource({\n id: c.id,\n kind: \"connector\",\n name: c.name,\n url: c.url,\n icon: c.icon,\n auth: c.auth,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout: c.connectionTimeout ?? connectionTimeout,\n ...(c.cache !== undefined ? { cache: c.cache } : {}),\n ...(c.elicitation !== undefined\n ? { elicitation: c.elicitation }\n : {}),\n onRemove: async () => {\n // connectors cannot be removed\n },\n }),\n ),\n );\n const customElements = customServers.map((s) =>\n withKey(\n s.id,\n McpServerResource(\n withMcpServerRemovalFence(\n {\n id: s.id,\n kind: \"custom\",\n name: s.name,\n url: s.url,\n auth: s.auth,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout: s.connectionTimeout ?? connectionTimeout,\n ...(s.cache !== undefined ? { cache: s.cache } : {}),\n ...(s.elicitation !== undefined\n ? { elicitation: s.elicitation }\n : {}),\n onRemove: async () => {\n removeCustomServer(s.id);\n },\n },\n () =>\n holdCustomServerPersistence(persistenceQueues, storageScopeKey),\n ),\n ),\n ),\n );\n return [...connectorElements, ...customElements];\n }, [\n connectors,\n customServers,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout,\n removeCustomServer,\n persistenceQueues,\n storageScopeKey,\n ]);\n\n const lookup = useClientLookup(serverElements);\n\n const state = useMemo<MCPManagerState>(() => {\n const all = lookup.state;\n return {\n servers: all,\n connectors: all.filter((s) => s.kind === \"connector\"),\n customServers: all.filter((s) => s.kind === \"custom\"),\n isHydrated,\n };\n }, [lookup.state, isHydrated]);\n\n // ─── Auto-register MCP tools as frontend tools in modelContext ─────\n // Build the toolkit from connected servers; re-register when the visible\n // tool surface changes. Tool names are prefixed with the server id to\n // avoid collisions across connected servers — connector ids must not\n // contain `__` (enforced by `defineConnector`); `addCustomServer`\n // generates UUIDs that satisfy the constraint by construction.\n const toolkit = useMemo<Record<string, Tool<any, any>>>(() => {\n const out: Record<string, Tool<any, any>> = {};\n for (const server of state.servers) {\n if (server.connectionState !== \"connected\") continue;\n for (const tool of server.tools) {\n const fullName = `${server.id}__${tool.name}`;\n out[fullName] = {\n type: \"frontend\",\n ...(tool.description !== undefined\n ? { description: tool.description }\n : {}),\n parameters: tool.inputSchema as never,\n execute: (args) =>\n lookup.get({ key: server.id }).callTool(tool.name, args as unknown),\n };\n }\n }\n return out;\n }, [state, lookup]);\n\n const clientRef = useAssistantClientRef();\n\n useAssistantScopeEffect(\n \"modelContext\",\n () => {\n const client = clientRef.current;\n if (!client) return;\n return client.modelContext.register({\n getModelContext: () => ({ tools: toolkit }),\n });\n },\n [toolkit],\n );\n\n const serverByKind = (kind: \"connector\" | \"custom\", index: number) => {\n const list = kind === \"connector\" ? state.connectors : state.customServers;\n const entry = list[index];\n if (!entry) {\n throw new Error(\n `McpManagerResource: no ${kind} at index ${index} (length ${list.length})`,\n );\n }\n return lookup.get({ key: entry.id });\n };\n\n return {\n getState: () => state,\n server: (query) => {\n if (\"id\" in query) return lookup.get({ key: query.id });\n return serverByKind(query.kind, query.index);\n },\n connector: ({ index }) => serverByKind(\"connector\", index),\n customServer: ({ index }) => serverByKind(\"custom\", index),\n addCustomServer: async ({\n name,\n url,\n auth,\n connectionTimeout,\n cache,\n elicitation,\n }) => {\n const record: MCPCustomServerRecord = {\n id: createMcpId(),\n name,\n url,\n auth: auth as MCPAuthConfig,\n connectionTimeout,\n ...(cache !== undefined ? { cache } : {}),\n ...(elicitation !== undefined ? { elicitation } : {}),\n createdAt: Date.now(),\n };\n updateCustomServers((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 const releasePersistence = holdCustomServerPersistence(\n persistenceQueues,\n storageScopeKey,\n );\n try {\n await clearOAuthProviderAuthState(storage, id);\n removeCustomServer(id);\n } catch (error) {\n releasePersistence();\n throw error;\n }\n releasePersistence();\n }\n },\n };\n};\n\nexport const McpManagerResource = resource(useMcpManagerResource);\n\n// Ensure modelContext exists as a sibling when the manager mounts. If an\n// ancestor (e.g. a chat runtime) already provides modelContext, this is a\n// no-op; otherwise it's auto-mounted alongside `mcp`.\nattachTransformScopes(useMcpManagerResource, (scopes, parent) => {\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"McpManagerResource.js","names":["useState","useMemo","useResource","resource","withKey","useClientLookup","useAssistantClientRef","attachTransformScopes","ClientOutput","useAssistantScopeEffect","ModelContext","createMcpId","clearOAuthProviderAuthState","Tool","McpServerResource","McpCustomServersResource","holdCustomServerPersistence","CustomServerPersistenceQueues","withMcpServerRemovalFence","McpLocalStorage","MCPStorageElement","assertUniqueServerIds","MCPAuthConfig","MCPConnector","MCPCustomServerRecord","MCPManagerState","McpManagerResourceProps","connectors","storage","oauthRedirectUri","autoConnect","connectionTimeout","defaultRedirectUri","window","location","origin","NO_CONNECTORS","useMcpManagerResource","props","$","_c","t0","redirectUri","t1","storageElement","persistenceQueues","_temp","storageScopeKey","scopeId","undefined","t2","scopeKey","customServers","isHydrated","updateCustomServers","removeCustomServer","map","_temp2","_temp3","t3","t4","c_0","c","id","kind","name","url","icon","auth","cache","elicitation","onRemove","_temp4","connectorElements","t5","s_0","s","customElements","serverElements","lookup","all","state","filter","_temp5","_temp6","t6","servers","out","server","connectionState","tool","tools","fullName","type","description","parameters","inputSchema","execute","args","get","key","callTool","toolkit","clientRef","t7","client","current","modelContext","register","getModelContext","t8","t9","index","list","entry","Error","length","serverByKind","t10","t11","query","t12","t13","t14","index_0","t15","index_1","connectionTimeout_0","record","createdAt","Date","now","prev","some","c_1","remove","releasePersistence","t16","error","getState","connector","customServer","addCustomServer","removeServer","McpManagerResource","scopes","parent","source","Map","s_1","s_2","_c","storageElement","serverElements"],"sources":["../../src/resources/McpManagerResource.ts"],"sourcesContent":["import { useState, useMemo } from \"react\";\nimport { useResource, resource, withKey } from \"@assistant-ui/tap\";\nimport {\n useClientLookup,\n useAssistantClientRef,\n attachTransformScopes,\n type ClientOutput,\n} from \"@assistant-ui/store\";\nimport { useAssistantScopeEffect } from \"@assistant-ui/store/client\";\nimport { ModelContext } from \"@assistant-ui/core/store\";\nimport { createMcpId } from \"../utils/createMcpId\";\nimport { clearOAuthProviderAuthState } from \"../auth/createOAuthProvider\";\nimport type { Tool } from \"assistant-stream\";\nimport { McpServerResource } from \"./McpServerResource\";\nimport {\n McpCustomServersResource,\n holdCustomServerPersistence,\n type CustomServerPersistenceQueues,\n} from \"./McpCustomServerPersistence\";\nimport { withMcpServerRemovalFence } from \"./McpServerRemovalFence\";\nimport { McpLocalStorage } from \"./storage/McpLocalStorage\";\nimport type { MCPStorageElement } from \"./storage/types\";\nimport { assertUniqueServerIds } from \"../utils/serverId\";\nimport type {\n MCPAuthConfig,\n MCPConnector,\n MCPCustomServerRecord,\n MCPManagerState,\n} from \"../mcp-scope\";\n\nexport type McpManagerResourceProps = {\n connectors?: MCPConnector[] | undefined;\n storage?: MCPStorageElement | undefined;\n /** OAuth redirect target. Defaults to `${origin}/mcp/callback`. */\n oauthRedirectUri?: string | undefined;\n /** Connect on mount when usable auth exists. Default true. */\n autoConnect?: boolean | undefined;\n /** Optional timeout in milliseconds for connect/listTools calls. Disabled by default. */\n connectionTimeout?: number | undefined;\n};\n\nfunction defaultRedirectUri(): string {\n if (typeof window === \"undefined\") return \"\";\n return `${window.location.origin}/mcp/callback`;\n}\n\n// Stable empty fallback so an absent `connectors` prop doesn't produce a fresh\n// array each render (which would invalidate the serverElements memo below).\nconst NO_CONNECTORS: MCPConnector[] = [];\n\nconst useMcpManagerResource = (\n props: McpManagerResourceProps,\n): ClientOutput<\"mcp\"> => {\n const connectors = props.connectors ?? NO_CONNECTORS;\n const autoConnect = props.autoConnect ?? true;\n const redirectUri = props.oauthRedirectUri ?? defaultRedirectUri();\n const connectionTimeout = props.connectionTimeout;\n\n const storageElement = props.storage ?? McpLocalStorage();\n const storage = useResource(storageElement);\n const [persistenceQueues] = useState<CustomServerPersistenceQueues>(\n () => new Map(),\n );\n const storageScopeKey =\n storage.scopeId === undefined ? \"unscoped\" : `scoped:${storage.scopeId}`;\n const { customServers, isHydrated, updateCustomServers, removeCustomServer } =\n useResource(\n withKey(\n storageScopeKey,\n McpCustomServersResource({\n storage,\n scopeKey: storageScopeKey,\n persistenceQueues,\n }),\n ),\n );\n\n const serverElements = useMemo(() => {\n assertUniqueServerIds([\n ...connectors.map((c) => c.id),\n ...customServers.map((s) => s.id),\n ]);\n\n const connectorElements = connectors.map((c) =>\n withKey(\n c.id,\n McpServerResource({\n id: c.id,\n kind: \"connector\",\n name: c.name,\n url: c.url,\n icon: c.icon,\n auth: c.auth,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout: c.connectionTimeout ?? connectionTimeout,\n ...(c.cache !== undefined ? { cache: c.cache } : {}),\n ...(c.elicitation !== undefined\n ? { elicitation: c.elicitation }\n : {}),\n onRemove: async () => {\n // connectors cannot be removed\n },\n }),\n ),\n );\n const customElements = customServers.map((s) =>\n withKey(\n s.id,\n McpServerResource(\n withMcpServerRemovalFence(\n {\n id: s.id,\n kind: \"custom\",\n name: s.name,\n url: s.url,\n auth: s.auth,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout: s.connectionTimeout ?? connectionTimeout,\n ...(s.cache !== undefined ? { cache: s.cache } : {}),\n ...(s.elicitation !== undefined\n ? { elicitation: s.elicitation }\n : {}),\n onRemove: async () => {\n removeCustomServer(s.id);\n },\n },\n () =>\n holdCustomServerPersistence(persistenceQueues, storageScopeKey),\n ),\n ),\n ),\n );\n return [...connectorElements, ...customElements];\n }, [\n connectors,\n customServers,\n storage,\n redirectUri,\n autoConnect,\n connectionTimeout,\n removeCustomServer,\n persistenceQueues,\n storageScopeKey,\n ]);\n\n const lookup = useClientLookup(serverElements);\n\n const state = useMemo<MCPManagerState>(() => {\n const all = lookup.state;\n return {\n servers: all,\n connectors: all.filter((s) => s.kind === \"connector\"),\n customServers: all.filter((s) => s.kind === \"custom\"),\n isHydrated,\n };\n }, [lookup.state, isHydrated]);\n\n // ─── Auto-register MCP tools as frontend tools in modelContext ─────\n // Build the toolkit from connected servers; re-register when the visible\n // tool surface changes. Tool names are prefixed with the server id to\n // avoid collisions across connected servers — connector ids must not\n // contain `__` (enforced by `defineConnector`); `addCustomServer`\n // generates UUIDs that satisfy the constraint by construction.\n const toolkit = useMemo<Record<string, Tool<any, any>>>(() => {\n const out: Record<string, Tool<any, any>> = {};\n for (const server of state.servers) {\n if (server.connectionState !== \"connected\") continue;\n for (const tool of server.tools) {\n const fullName = `${server.id}__${tool.name}`;\n out[fullName] = {\n type: \"frontend\",\n ...(tool.description !== undefined\n ? { description: tool.description }\n : {}),\n parameters: tool.inputSchema as never,\n execute: (args) =>\n lookup.get({ key: server.id }).callTool(tool.name, args as unknown),\n };\n }\n }\n return out;\n }, [state, lookup]);\n\n const clientRef = useAssistantClientRef();\n\n useAssistantScopeEffect(\n \"modelContext\",\n () => {\n const client = clientRef.current;\n if (!client) return;\n return client.modelContext.register({\n getModelContext: () => ({ tools: toolkit }),\n });\n },\n [toolkit],\n );\n\n const serverByKind = (kind: \"connector\" | \"custom\", index: number) => {\n const list = kind === \"connector\" ? state.connectors : state.customServers;\n const entry = list[index];\n if (!entry) {\n throw new Error(\n `McpManagerResource: no ${kind} at index ${index} (length ${list.length})`,\n );\n }\n return lookup.get({ key: entry.id });\n };\n\n return {\n getState: () => state,\n server: (query) => {\n if (\"id\" in query) return lookup.get({ key: query.id });\n return serverByKind(query.kind, query.index);\n },\n connector: ({ index }) => serverByKind(\"connector\", index),\n customServer: ({ index }) => serverByKind(\"custom\", index),\n addCustomServer: async ({\n name,\n url,\n auth,\n connectionTimeout,\n cache,\n elicitation,\n }) => {\n const record: MCPCustomServerRecord = {\n id: createMcpId(),\n name,\n url,\n auth: auth as MCPAuthConfig,\n connectionTimeout,\n ...(cache !== undefined ? { cache } : {}),\n ...(elicitation !== undefined ? { elicitation } : {}),\n createdAt: Date.now(),\n };\n updateCustomServers((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 let server;\n try {\n server = lookup.get({ key: id });\n } catch {\n server = undefined;\n }\n if (server) {\n await server.remove();\n return;\n }\n const releasePersistence = holdCustomServerPersistence(\n persistenceQueues,\n storageScopeKey,\n );\n try {\n await clearOAuthProviderAuthState(storage, id);\n removeCustomServer(id);\n } catch (error) {\n releasePersistence();\n throw error;\n }\n releasePersistence();\n },\n };\n};\n\nexport const McpManagerResource = resource(useMcpManagerResource);\n\n// Ensure modelContext exists as a sibling when the manager mounts. If an\n// ancestor (e.g. a chat runtime) already provides modelContext, this is a\n// no-op; otherwise it's auto-mounted alongside `mcp`.\nattachTransformScopes(useMcpManagerResource, (scopes, parent) => {\n if (!scopes.modelContext && parent.modelContext.source === null) {\n scopes.modelContext = ModelContext();\n }\n});\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpServerResource.d.ts","sourceRoot":"","sources":["../../src/resources/McpServerResource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"McpServerResource.d.ts","sourceRoot":"","sources":["../../src/resources/McpServerResource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAqBxD,OAAO,KAAK,EAAE,UAAU,EAAE,2BAAwB;AAClD,OAAO,KAAK,EACV,aAAa,EAEb,aAAa,EAGd,wBAAqB;AAItB,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,UAAU,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B,CAAC;AAMF,eAAO,MAAM,yBAAyB,GACpC,OAAO,sBAAsB,KAC5B,SAAS,OAAO,EA2BlB,CAAC;AAikBF,eAAO,MAAM,iBAAiB,kGAwB5B,CAAC"}
|