@mcp-ts/sdk 1.3.9 → 1.3.10
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/README.md +0 -1
- package/dist/client/react.d.mts +9 -27
- package/dist/client/react.d.ts +9 -27
- package/dist/client/react.js +99 -73
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +100 -74
- package/dist/client/react.mjs.map +1 -1
- package/dist/index.js +78 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +73 -6
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js +78 -6
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +73 -6
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client/react/index.ts +5 -1
- package/src/client/react/use-app-host.ts +5 -4
- package/src/client/react/use-mcp-apps.tsx +89 -112
- package/src/client/react/use-mcp.ts +52 -24
- package/src/server/storage/crypto.ts +92 -0
- package/src/server/storage/supabase-backend.ts +7 -6
package/README.md
CHANGED
package/dist/client/react.d.mts
CHANGED
|
@@ -172,10 +172,11 @@ declare function useMcp(options: UseMcpOptions): McpClient$1;
|
|
|
172
172
|
/**
|
|
173
173
|
* Hook to host an MCP App in a React component
|
|
174
174
|
*
|
|
175
|
-
*
|
|
176
|
-
* -
|
|
177
|
-
* -
|
|
178
|
-
* -
|
|
175
|
+
* Initialization is async but optimized for instant availability:
|
|
176
|
+
* - Constructor runs synchronously (sandbox + bridge handler setup)
|
|
177
|
+
* - Host is set in state immediately so launch() can be called right away
|
|
178
|
+
* - start() is a lightweight no-op reserved for future async pre-init work
|
|
179
|
+
* - The real async work (iframe load, bridge connect) happens inside launch()
|
|
179
180
|
*
|
|
180
181
|
* @param client - Connected SSEClient instance
|
|
181
182
|
* @param iframeRef - Reference to the iframe element
|
|
@@ -222,8 +223,8 @@ interface McpAppMetadata {
|
|
|
222
223
|
resourceUri: string;
|
|
223
224
|
sessionId: string;
|
|
224
225
|
}
|
|
226
|
+
/** Props for {@link useMcpApps}'s `McpAppRenderer` (client is supplied via the hook). */
|
|
225
227
|
interface McpAppRendererProps {
|
|
226
|
-
mcpClient: McpClient | null;
|
|
227
228
|
name: string;
|
|
228
229
|
input?: Record<string, unknown>;
|
|
229
230
|
result?: unknown;
|
|
@@ -232,32 +233,13 @@ interface McpAppRendererProps {
|
|
|
232
233
|
className?: string;
|
|
233
234
|
}
|
|
234
235
|
/**
|
|
235
|
-
*
|
|
236
|
+
* Helpers scoped to one `mcpClient`. Pass the client here once; `McpAppRenderer` only needs per-tool props (`name`, `input`, `result`, `status`).
|
|
236
237
|
*
|
|
237
|
-
* @param mcpClient -
|
|
238
|
-
* @returns Object with getAppMetadata function and McpAppRenderer component
|
|
239
|
-
*
|
|
240
|
-
* @example
|
|
241
|
-
* ```tsx
|
|
242
|
-
* function ToolRenderer(props) {
|
|
243
|
-
* const { getAppMetadata, McpAppRenderer } = useMcpApps(mcpClient);
|
|
244
|
-
* const metadata = getAppMetadata(props.name);
|
|
245
|
-
*
|
|
246
|
-
* if (!metadata) return null;
|
|
247
|
-
* return (
|
|
248
|
-
* <McpAppRenderer
|
|
249
|
-
* metadata={metadata}
|
|
250
|
-
* input={props.args}
|
|
251
|
-
* result={props.result}
|
|
252
|
-
* status={props.status}
|
|
253
|
-
* />
|
|
254
|
-
* );
|
|
255
|
-
* }
|
|
256
|
-
* ```
|
|
238
|
+
* @param mcpClient - From `useMcp()` or context (for example `useMcpContext()`).
|
|
257
239
|
*/
|
|
258
240
|
declare function useMcpApps(mcpClient: McpClient | null): {
|
|
259
241
|
getAppMetadata: (toolName: string) => McpAppMetadata | undefined;
|
|
260
242
|
McpAppRenderer: React$1.NamedExoticComponent<McpAppRendererProps>;
|
|
261
243
|
};
|
|
262
244
|
|
|
263
|
-
export { AppHost, type McpClient$1 as McpClient, type McpConnection, McpConnectionEvent, McpConnectionState, SSEClient, ToolInfo, type UseMcpOptions, useAppHost, useMcp, useMcpApps };
|
|
245
|
+
export { AppHost, type McpAppMetadata, type McpAppRendererProps, type McpClient$1 as McpClient, type McpConnection, McpConnectionEvent, McpConnectionState, SSEClient, ToolInfo, type UseMcpOptions, useAppHost, useMcp, useMcpApps };
|
package/dist/client/react.d.ts
CHANGED
|
@@ -172,10 +172,11 @@ declare function useMcp(options: UseMcpOptions): McpClient$1;
|
|
|
172
172
|
/**
|
|
173
173
|
* Hook to host an MCP App in a React component
|
|
174
174
|
*
|
|
175
|
-
*
|
|
176
|
-
* -
|
|
177
|
-
* -
|
|
178
|
-
* -
|
|
175
|
+
* Initialization is async but optimized for instant availability:
|
|
176
|
+
* - Constructor runs synchronously (sandbox + bridge handler setup)
|
|
177
|
+
* - Host is set in state immediately so launch() can be called right away
|
|
178
|
+
* - start() is a lightweight no-op reserved for future async pre-init work
|
|
179
|
+
* - The real async work (iframe load, bridge connect) happens inside launch()
|
|
179
180
|
*
|
|
180
181
|
* @param client - Connected SSEClient instance
|
|
181
182
|
* @param iframeRef - Reference to the iframe element
|
|
@@ -222,8 +223,8 @@ interface McpAppMetadata {
|
|
|
222
223
|
resourceUri: string;
|
|
223
224
|
sessionId: string;
|
|
224
225
|
}
|
|
226
|
+
/** Props for {@link useMcpApps}'s `McpAppRenderer` (client is supplied via the hook). */
|
|
225
227
|
interface McpAppRendererProps {
|
|
226
|
-
mcpClient: McpClient | null;
|
|
227
228
|
name: string;
|
|
228
229
|
input?: Record<string, unknown>;
|
|
229
230
|
result?: unknown;
|
|
@@ -232,32 +233,13 @@ interface McpAppRendererProps {
|
|
|
232
233
|
className?: string;
|
|
233
234
|
}
|
|
234
235
|
/**
|
|
235
|
-
*
|
|
236
|
+
* Helpers scoped to one `mcpClient`. Pass the client here once; `McpAppRenderer` only needs per-tool props (`name`, `input`, `result`, `status`).
|
|
236
237
|
*
|
|
237
|
-
* @param mcpClient -
|
|
238
|
-
* @returns Object with getAppMetadata function and McpAppRenderer component
|
|
239
|
-
*
|
|
240
|
-
* @example
|
|
241
|
-
* ```tsx
|
|
242
|
-
* function ToolRenderer(props) {
|
|
243
|
-
* const { getAppMetadata, McpAppRenderer } = useMcpApps(mcpClient);
|
|
244
|
-
* const metadata = getAppMetadata(props.name);
|
|
245
|
-
*
|
|
246
|
-
* if (!metadata) return null;
|
|
247
|
-
* return (
|
|
248
|
-
* <McpAppRenderer
|
|
249
|
-
* metadata={metadata}
|
|
250
|
-
* input={props.args}
|
|
251
|
-
* result={props.result}
|
|
252
|
-
* status={props.status}
|
|
253
|
-
* />
|
|
254
|
-
* );
|
|
255
|
-
* }
|
|
256
|
-
* ```
|
|
238
|
+
* @param mcpClient - From `useMcp()` or context (for example `useMcpContext()`).
|
|
257
239
|
*/
|
|
258
240
|
declare function useMcpApps(mcpClient: McpClient | null): {
|
|
259
241
|
getAppMetadata: (toolName: string) => McpAppMetadata | undefined;
|
|
260
242
|
McpAppRenderer: React$1.NamedExoticComponent<McpAppRendererProps>;
|
|
261
243
|
};
|
|
262
244
|
|
|
263
|
-
export { AppHost, type McpClient$1 as McpClient, type McpConnection, McpConnectionEvent, McpConnectionState, SSEClient, ToolInfo, type UseMcpOptions, useAppHost, useMcp, useMcpApps };
|
|
245
|
+
export { AppHost, type McpAppMetadata, type McpAppRendererProps, type McpClient$1 as McpClient, type McpConnection, McpConnectionEvent, McpConnectionState, SSEClient, ToolInfo, type UseMcpOptions, useAppHost, useMcp, useMcpApps };
|
package/dist/client/react.js
CHANGED
|
@@ -277,6 +277,7 @@ function useMcp(options) {
|
|
|
277
277
|
"disconnected"
|
|
278
278
|
);
|
|
279
279
|
const [isInitializing, setIsInitializing] = react.useState(false);
|
|
280
|
+
const [sseClient, setSseClient] = react.useState(null);
|
|
280
281
|
react.useEffect(() => {
|
|
281
282
|
isMountedRef.current = true;
|
|
282
283
|
const clientOptions = {
|
|
@@ -299,6 +300,7 @@ function useMcp(options) {
|
|
|
299
300
|
};
|
|
300
301
|
const client = new SSEClient(clientOptions);
|
|
301
302
|
clientRef.current = client;
|
|
303
|
+
setSseClient(client);
|
|
302
304
|
if (autoConnect) {
|
|
303
305
|
client.connect();
|
|
304
306
|
if (autoInitialize) {
|
|
@@ -532,29 +534,54 @@ function useMcp(options) {
|
|
|
532
534
|
},
|
|
533
535
|
[getConnection]
|
|
534
536
|
);
|
|
535
|
-
return
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
537
|
+
return react.useMemo(
|
|
538
|
+
() => ({
|
|
539
|
+
connections,
|
|
540
|
+
status,
|
|
541
|
+
isInitializing,
|
|
542
|
+
connect,
|
|
543
|
+
disconnect,
|
|
544
|
+
getConnection,
|
|
545
|
+
getConnectionByServerId,
|
|
546
|
+
isServerConnected,
|
|
547
|
+
getTools,
|
|
548
|
+
refresh,
|
|
549
|
+
connectSSE,
|
|
550
|
+
disconnectSSE,
|
|
551
|
+
finishAuth,
|
|
552
|
+
resumeAuth,
|
|
553
|
+
callTool,
|
|
554
|
+
listTools,
|
|
555
|
+
listPrompts,
|
|
556
|
+
getPrompt,
|
|
557
|
+
listResources,
|
|
558
|
+
readResource,
|
|
559
|
+
sseClient
|
|
560
|
+
}),
|
|
561
|
+
[
|
|
562
|
+
connections,
|
|
563
|
+
status,
|
|
564
|
+
isInitializing,
|
|
565
|
+
connect,
|
|
566
|
+
disconnect,
|
|
567
|
+
getConnection,
|
|
568
|
+
getConnectionByServerId,
|
|
569
|
+
isServerConnected,
|
|
570
|
+
getTools,
|
|
571
|
+
refresh,
|
|
572
|
+
connectSSE,
|
|
573
|
+
disconnectSSE,
|
|
574
|
+
finishAuth,
|
|
575
|
+
resumeAuth,
|
|
576
|
+
callTool,
|
|
577
|
+
listTools,
|
|
578
|
+
listPrompts,
|
|
579
|
+
getPrompt,
|
|
580
|
+
listResources,
|
|
581
|
+
readResource,
|
|
582
|
+
sseClient
|
|
583
|
+
]
|
|
584
|
+
);
|
|
558
585
|
}
|
|
559
586
|
var HOST_INFO = { name: "mcp-ts-host", version: "1.0.0" };
|
|
560
587
|
var SANDBOX_PERMISSIONS = [
|
|
@@ -886,37 +913,19 @@ function useAppHost(client, iframeRef, options) {
|
|
|
886
913
|
}, [client, iframeRef]);
|
|
887
914
|
return { host, error };
|
|
888
915
|
}
|
|
889
|
-
var
|
|
890
|
-
|
|
916
|
+
var McpAppView = react.memo(function McpAppView2({
|
|
917
|
+
clientRef,
|
|
891
918
|
name,
|
|
892
919
|
input,
|
|
893
920
|
result,
|
|
894
921
|
status,
|
|
895
922
|
className
|
|
896
923
|
}) {
|
|
897
|
-
const
|
|
898
|
-
|
|
899
|
-
const extractedName = extractToolName(name);
|
|
900
|
-
for (const conn of mcpClient.connections) {
|
|
901
|
-
for (const tool of conn.tools) {
|
|
902
|
-
const candidateName = extractToolName(tool.name);
|
|
903
|
-
const resourceUri = tool.mcpApp?.resourceUri ?? tool._meta?.ui?.resourceUri ?? tool._meta?.["ui/resourceUri"];
|
|
904
|
-
if (resourceUri && candidateName === extractedName) {
|
|
905
|
-
return {
|
|
906
|
-
toolName: candidateName,
|
|
907
|
-
resourceUri,
|
|
908
|
-
sessionId: conn.sessionId
|
|
909
|
-
};
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
return void 0;
|
|
914
|
-
}, [mcpClient, name]);
|
|
915
|
-
const metadata = getAppMetadata();
|
|
924
|
+
const mcpClient = clientRef.current;
|
|
925
|
+
const metadata = getMcpAppMetadata(mcpClient, name);
|
|
916
926
|
const sseClient = mcpClient?.sseClient ?? null;
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
}
|
|
927
|
+
const resourceUri = metadata?.resourceUri;
|
|
928
|
+
const appSessionId = metadata?.sessionId;
|
|
920
929
|
const iframeRef = react.useRef(null);
|
|
921
930
|
const { host, error: hostError } = useAppHost(sseClient, iframeRef);
|
|
922
931
|
const [isLaunched, setIsLaunched] = react.useState(false);
|
|
@@ -927,19 +936,23 @@ var McpAppRenderer = react.memo(function McpAppRenderer2({
|
|
|
927
936
|
const lastResultRef = react.useRef(result);
|
|
928
937
|
const lastStatusRef = react.useRef(status);
|
|
929
938
|
react.useEffect(() => {
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
}, [
|
|
939
|
+
setIsLaunched(false);
|
|
940
|
+
setError(null);
|
|
941
|
+
}, [resourceUri, appSessionId]);
|
|
942
|
+
react.useEffect(() => {
|
|
943
|
+
if (!host || !resourceUri || !appSessionId) return;
|
|
944
|
+
host.launch(resourceUri, appSessionId).then(() => setIsLaunched(true)).catch((err) => setError(err instanceof Error ? err : new Error(String(err))));
|
|
945
|
+
}, [host, resourceUri, appSessionId]);
|
|
933
946
|
react.useEffect(() => {
|
|
934
|
-
if (!host || !isLaunched || !input) return;
|
|
947
|
+
if (!host || !isLaunched || !resourceUri || !appSessionId || !input) return;
|
|
935
948
|
if (!sentInputRef.current || JSON.stringify(input) !== JSON.stringify(lastInputRef.current)) {
|
|
936
949
|
sentInputRef.current = true;
|
|
937
950
|
lastInputRef.current = input;
|
|
938
951
|
host.sendToolInput(input);
|
|
939
952
|
}
|
|
940
|
-
}, [host, isLaunched, input]);
|
|
953
|
+
}, [host, isLaunched, input, resourceUri, appSessionId, name]);
|
|
941
954
|
react.useEffect(() => {
|
|
942
|
-
if (!host || !isLaunched || result === void 0) return;
|
|
955
|
+
if (!host || !isLaunched || !resourceUri || !appSessionId || result === void 0) return;
|
|
943
956
|
if (status !== "complete") return;
|
|
944
957
|
if (!sentResultRef.current || JSON.stringify(result) !== JSON.stringify(lastResultRef.current)) {
|
|
945
958
|
sentResultRef.current = true;
|
|
@@ -947,7 +960,7 @@ var McpAppRenderer = react.memo(function McpAppRenderer2({
|
|
|
947
960
|
const formattedResult = typeof result === "string" ? { content: [{ type: "text", text: result }] } : result;
|
|
948
961
|
host.sendToolResult(formattedResult);
|
|
949
962
|
}
|
|
950
|
-
}, [host, isLaunched, result, status]);
|
|
963
|
+
}, [host, isLaunched, result, status, resourceUri, appSessionId, name]);
|
|
951
964
|
react.useEffect(() => {
|
|
952
965
|
if (status === "executing" && lastStatusRef.current !== "executing") {
|
|
953
966
|
sentInputRef.current = false;
|
|
@@ -955,6 +968,9 @@ var McpAppRenderer = react.memo(function McpAppRenderer2({
|
|
|
955
968
|
}
|
|
956
969
|
lastStatusRef.current = status;
|
|
957
970
|
}, [status]);
|
|
971
|
+
if (!metadata || !sseClient) {
|
|
972
|
+
return null;
|
|
973
|
+
}
|
|
958
974
|
const displayError = error || hostError;
|
|
959
975
|
if (displayError) {
|
|
960
976
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `p-4 bg-red-900/20 border border-red-700 rounded text-red-200 ${className || ""}`, children: [
|
|
@@ -977,33 +993,43 @@ var McpAppRenderer = react.memo(function McpAppRenderer2({
|
|
|
977
993
|
] });
|
|
978
994
|
});
|
|
979
995
|
function useMcpApps(mcpClient) {
|
|
996
|
+
const clientRef = react.useRef(mcpClient);
|
|
997
|
+
clientRef.current = mcpClient;
|
|
980
998
|
const getAppMetadata = react.useCallback(
|
|
981
|
-
(toolName) =>
|
|
982
|
-
|
|
983
|
-
const extractedName = extractToolName(toolName);
|
|
984
|
-
for (const conn of mcpClient.connections) {
|
|
985
|
-
for (const tool of conn.tools) {
|
|
986
|
-
const candidateName = extractToolName(tool.name);
|
|
987
|
-
const resourceUri = tool.mcpApp?.resourceUri ?? tool._meta?.ui?.resourceUri ?? tool._meta?.["ui/resourceUri"];
|
|
988
|
-
if (resourceUri && candidateName === extractedName) {
|
|
989
|
-
return {
|
|
990
|
-
toolName: candidateName,
|
|
991
|
-
resourceUri,
|
|
992
|
-
sessionId: conn.sessionId
|
|
993
|
-
};
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
return void 0;
|
|
998
|
-
},
|
|
999
|
-
[mcpClient]
|
|
999
|
+
(toolName) => getMcpAppMetadata(clientRef.current, toolName),
|
|
1000
|
+
[]
|
|
1000
1001
|
);
|
|
1002
|
+
const McpAppRenderer = react.useMemo(() => {
|
|
1003
|
+
const Renderer = react.memo(function McpAppRenderer2(props) {
|
|
1004
|
+
return /* @__PURE__ */ jsxRuntime.jsx(McpAppView, { clientRef, ...props });
|
|
1005
|
+
});
|
|
1006
|
+
Renderer.displayName = "McpAppRenderer";
|
|
1007
|
+
return Renderer;
|
|
1008
|
+
}, []);
|
|
1001
1009
|
return { getAppMetadata, McpAppRenderer };
|
|
1002
1010
|
}
|
|
1003
1011
|
function extractToolName(fullName) {
|
|
1004
1012
|
const match = fullName.match(/(?:tool_[^_]+_)?(.+)$/);
|
|
1005
1013
|
return match?.[1] || fullName;
|
|
1006
1014
|
}
|
|
1015
|
+
function getMcpAppMetadata(mcpClient, toolName) {
|
|
1016
|
+
if (!mcpClient) return void 0;
|
|
1017
|
+
const extractedName = extractToolName(toolName);
|
|
1018
|
+
for (const conn of mcpClient.connections) {
|
|
1019
|
+
for (const tool of conn.tools) {
|
|
1020
|
+
const candidateName = extractToolName(tool.name);
|
|
1021
|
+
const resourceUri = tool.mcpApp?.resourceUri ?? tool._meta?.ui?.resourceUri ?? tool._meta?.["ui/resourceUri"];
|
|
1022
|
+
if (resourceUri && candidateName === extractedName) {
|
|
1023
|
+
return {
|
|
1024
|
+
toolName: candidateName,
|
|
1025
|
+
resourceUri,
|
|
1026
|
+
sessionId: conn.sessionId
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
return void 0;
|
|
1032
|
+
}
|
|
1007
1033
|
|
|
1008
1034
|
exports.AppHost = AppHost;
|
|
1009
1035
|
exports.SSEClient = SSEClient;
|