@mcp-ts/sdk 1.1.0 → 1.2.0
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 +21 -10
- package/dist/adapters/agui-adapter.js +0 -1
- package/dist/adapters/agui-adapter.js.map +1 -1
- package/dist/adapters/agui-adapter.mjs +0 -1
- package/dist/adapters/agui-adapter.mjs.map +1 -1
- package/dist/adapters/agui-middleware.d.mts +5 -0
- package/dist/adapters/agui-middleware.d.ts +5 -0
- package/dist/adapters/agui-middleware.js +12 -23
- package/dist/adapters/agui-middleware.js.map +1 -1
- package/dist/adapters/agui-middleware.mjs +12 -23
- package/dist/adapters/agui-middleware.mjs.map +1 -1
- package/dist/client/react.d.mts +351 -3
- package/dist/client/react.d.ts +351 -3
- package/dist/client/react.js +308 -6
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +302 -7
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.js +1 -1
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs +1 -1
- package/dist/client/vue.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +18 -1
- package/dist/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +38 -2
- package/dist/shared/index.d.ts +38 -2
- package/dist/shared/index.js +19 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +18 -1
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/adapters/agui-adapter.ts +2 -4
- package/src/adapters/agui-middleware.ts +15 -27
- package/src/client/react/agui-subscriber.ts +275 -0
- package/src/client/react/index.ts +23 -4
- package/src/client/react/use-agui-subscriber.ts +270 -0
- package/src/client/react/{use-mcp-app.ts → use-app-host.ts} +2 -2
- package/src/client/react/use-mcp-app-iframe.ts +164 -0
- package/src/client/react/{useMcp.ts → use-mcp.ts} +2 -2
- package/src/client/vue/index.ts +1 -1
- package/src/shared/index.ts +6 -1
- package/src/shared/tool-utils.ts +61 -0
- /package/src/client/vue/{useMcp.ts → use-mcp.ts} +0 -0
package/dist/client/react.js
CHANGED
|
@@ -329,7 +329,7 @@ var SSEClient = class {
|
|
|
329
329
|
}
|
|
330
330
|
};
|
|
331
331
|
|
|
332
|
-
// src/client/react/
|
|
332
|
+
// src/client/react/use-mcp.ts
|
|
333
333
|
function useMcp(options) {
|
|
334
334
|
const {
|
|
335
335
|
url,
|
|
@@ -595,7 +595,7 @@ function useMcp(options) {
|
|
|
595
595
|
getPrompt,
|
|
596
596
|
listResources,
|
|
597
597
|
readResource,
|
|
598
|
-
|
|
598
|
+
sseClient: clientRef.current
|
|
599
599
|
};
|
|
600
600
|
}
|
|
601
601
|
var HOST_INFO = { name: "mcp-ts-host", version: "1.0.0" };
|
|
@@ -895,8 +895,8 @@ var AppHost = class {
|
|
|
895
895
|
}
|
|
896
896
|
};
|
|
897
897
|
|
|
898
|
-
// src/client/react/use-
|
|
899
|
-
function
|
|
898
|
+
// src/client/react/use-app-host.ts
|
|
899
|
+
function useAppHost(client, iframeRef, options) {
|
|
900
900
|
const [host, setHost] = react.useState(null);
|
|
901
901
|
const [error, setError] = react.useState(null);
|
|
902
902
|
const initializingRef = react.useRef(false);
|
|
@@ -916,7 +916,7 @@ function useMcpApp(client, iframeRef, options) {
|
|
|
916
916
|
setHost(appHost);
|
|
917
917
|
await appHost.start();
|
|
918
918
|
} catch (err) {
|
|
919
|
-
console.error("[
|
|
919
|
+
console.error("[useAppHost] Failed to initialize AppHost:", err);
|
|
920
920
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
921
921
|
}
|
|
922
922
|
};
|
|
@@ -928,10 +928,312 @@ function useMcpApp(client, iframeRef, options) {
|
|
|
928
928
|
}, [client, iframeRef]);
|
|
929
929
|
return { host, error };
|
|
930
930
|
}
|
|
931
|
+
function useMcpAppIframe({
|
|
932
|
+
resourceUri,
|
|
933
|
+
sessionId,
|
|
934
|
+
toolInput,
|
|
935
|
+
toolResult,
|
|
936
|
+
toolStatus,
|
|
937
|
+
sseClient
|
|
938
|
+
}) {
|
|
939
|
+
const iframeRef = react.useRef(null);
|
|
940
|
+
const { host, error: hostError } = useAppHost(sseClient, iframeRef);
|
|
941
|
+
const [isLaunched, setIsLaunched] = react.useState(false);
|
|
942
|
+
const [error, setError] = react.useState(null);
|
|
943
|
+
const launchAttemptedRef = react.useRef(false);
|
|
944
|
+
const toolInputSentRef = react.useRef(false);
|
|
945
|
+
const toolResultSentRef = react.useRef(false);
|
|
946
|
+
react.useEffect(() => {
|
|
947
|
+
if (hostError) {
|
|
948
|
+
setError(hostError);
|
|
949
|
+
}
|
|
950
|
+
}, [hostError]);
|
|
951
|
+
react.useEffect(() => {
|
|
952
|
+
if (!host || !resourceUri || !sessionId || launchAttemptedRef.current) return;
|
|
953
|
+
launchAttemptedRef.current = true;
|
|
954
|
+
host.launch(resourceUri, sessionId).then(() => {
|
|
955
|
+
setIsLaunched(true);
|
|
956
|
+
}).catch((err) => {
|
|
957
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
958
|
+
setError(error2);
|
|
959
|
+
});
|
|
960
|
+
}, [host, resourceUri, sessionId]);
|
|
961
|
+
react.useEffect(() => {
|
|
962
|
+
if (!host || !isLaunched || !toolInput || toolInputSentRef.current) return;
|
|
963
|
+
toolInputSentRef.current = true;
|
|
964
|
+
host.sendToolInput(toolInput);
|
|
965
|
+
}, [host, isLaunched, toolInput]);
|
|
966
|
+
react.useEffect(() => {
|
|
967
|
+
if (!host || !isLaunched || toolResult === void 0 || toolResultSentRef.current) return;
|
|
968
|
+
if (toolStatus !== "complete") return;
|
|
969
|
+
toolResultSentRef.current = true;
|
|
970
|
+
const formattedResult = typeof toolResult === "string" ? { content: [{ type: "text", text: toolResult }] } : toolResult;
|
|
971
|
+
host.sendToolResult(formattedResult);
|
|
972
|
+
}, [host, isLaunched, toolResult, toolStatus]);
|
|
973
|
+
return {
|
|
974
|
+
iframeRef,
|
|
975
|
+
isLaunched,
|
|
976
|
+
error
|
|
977
|
+
};
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// src/client/react/agui-subscriber.ts
|
|
981
|
+
function createMcpAppSubscriber(config) {
|
|
982
|
+
const eventName = config.eventName || "mcp-apps-ui";
|
|
983
|
+
const subscriber = {
|
|
984
|
+
// Listen for custom MCP app events from middleware
|
|
985
|
+
onCustomEvent: ({ event }) => {
|
|
986
|
+
if (event.name === eventName && config.onMcpApp) {
|
|
987
|
+
const payload = event.value;
|
|
988
|
+
config.onMcpApp(payload);
|
|
989
|
+
}
|
|
990
|
+
},
|
|
991
|
+
// Listen for tool call lifecycle events
|
|
992
|
+
onToolCallStartEvent: (params) => {
|
|
993
|
+
if (config.onToolCall && params.event.toolCallName) {
|
|
994
|
+
config.onToolCall({
|
|
995
|
+
toolCallId: params.event.toolCallId || "",
|
|
996
|
+
toolName: params.event.toolCallName,
|
|
997
|
+
status: "start"
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
},
|
|
1001
|
+
onToolCallArgsEvent: (params) => {
|
|
1002
|
+
if (config.onToolCall) {
|
|
1003
|
+
const args = params.partialToolCallArgs;
|
|
1004
|
+
config.onToolCall({
|
|
1005
|
+
toolCallId: params.event.toolCallId || "",
|
|
1006
|
+
toolName: params.toolCallName || "",
|
|
1007
|
+
// toolCallName is in params, not event
|
|
1008
|
+
args,
|
|
1009
|
+
status: "args"
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
},
|
|
1013
|
+
onToolCallEndEvent: (params) => {
|
|
1014
|
+
if (config.onToolCall && params.event.toolCallId) {
|
|
1015
|
+
config.onToolCall({
|
|
1016
|
+
toolCallId: params.event.toolCallId,
|
|
1017
|
+
toolName: params.toolCallName || "",
|
|
1018
|
+
// toolCallName is in params, not event
|
|
1019
|
+
status: "end"
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
},
|
|
1023
|
+
onToolCallResultEvent: (params) => {
|
|
1024
|
+
if (config.onToolCall && params.event.toolCallId) {
|
|
1025
|
+
config.onToolCall({
|
|
1026
|
+
toolCallId: params.event.toolCallId,
|
|
1027
|
+
toolName: "",
|
|
1028
|
+
// Not available in result event
|
|
1029
|
+
result: params.event.content,
|
|
1030
|
+
// content contains the result
|
|
1031
|
+
status: "result"
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
return subscriber;
|
|
1037
|
+
}
|
|
1038
|
+
function subscribeMcpAppEvents(agent, config) {
|
|
1039
|
+
const subscriber = createMcpAppSubscriber(config);
|
|
1040
|
+
const { unsubscribe } = agent.subscribe(subscriber);
|
|
1041
|
+
return unsubscribe;
|
|
1042
|
+
}
|
|
1043
|
+
var McpAppEventManager = class {
|
|
1044
|
+
constructor() {
|
|
1045
|
+
__publicField(this, "events", /* @__PURE__ */ new Map());
|
|
1046
|
+
__publicField(this, "toolCalls", /* @__PURE__ */ new Map());
|
|
1047
|
+
__publicField(this, "listeners", /* @__PURE__ */ new Set());
|
|
1048
|
+
__publicField(this, "unsubscribe");
|
|
1049
|
+
__publicField(this, "cachedSnapshot", {});
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Attach to an AG-UI agent
|
|
1053
|
+
*/
|
|
1054
|
+
attach(agent) {
|
|
1055
|
+
if (this.unsubscribe) {
|
|
1056
|
+
this.unsubscribe();
|
|
1057
|
+
}
|
|
1058
|
+
this.unsubscribe = subscribeMcpAppEvents(agent, {
|
|
1059
|
+
onMcpApp: (event) => {
|
|
1060
|
+
this.events.set(event.toolName, event);
|
|
1061
|
+
this.cachedSnapshot = Object.fromEntries(this.events);
|
|
1062
|
+
this.notify();
|
|
1063
|
+
},
|
|
1064
|
+
onToolCall: (event) => {
|
|
1065
|
+
if (event.toolCallId) {
|
|
1066
|
+
this.toolCalls.set(event.toolCallId, event);
|
|
1067
|
+
this.notify();
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* Detach from the current agent
|
|
1074
|
+
*/
|
|
1075
|
+
detach() {
|
|
1076
|
+
if (this.unsubscribe) {
|
|
1077
|
+
this.unsubscribe();
|
|
1078
|
+
this.unsubscribe = void 0;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Get MCP app event for a specific tool
|
|
1083
|
+
*/
|
|
1084
|
+
getEvent(toolName) {
|
|
1085
|
+
return this.events.get(toolName);
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Get all MCP app events (cached for useSyncExternalStore)
|
|
1089
|
+
*/
|
|
1090
|
+
getAllEvents() {
|
|
1091
|
+
return this.cachedSnapshot;
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Get tool call event by ID
|
|
1095
|
+
*/
|
|
1096
|
+
getToolCall(toolCallId) {
|
|
1097
|
+
return this.toolCalls.get(toolCallId);
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Subscribe to event changes
|
|
1101
|
+
*/
|
|
1102
|
+
subscribe(listener) {
|
|
1103
|
+
this.listeners.add(listener);
|
|
1104
|
+
return () => this.listeners.delete(listener);
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Clear all events
|
|
1108
|
+
*/
|
|
1109
|
+
clear() {
|
|
1110
|
+
this.events.clear();
|
|
1111
|
+
this.toolCalls.clear();
|
|
1112
|
+
this.cachedSnapshot = {};
|
|
1113
|
+
this.notify();
|
|
1114
|
+
}
|
|
1115
|
+
notify() {
|
|
1116
|
+
this.listeners.forEach((listener) => listener());
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
|
|
1120
|
+
// src/client/react/use-agui-subscriber.ts
|
|
1121
|
+
function useAguiSubscriber(agent, config) {
|
|
1122
|
+
react.useEffect(() => {
|
|
1123
|
+
if (!agent) return;
|
|
1124
|
+
const subscriber = createMcpAppSubscriber(config);
|
|
1125
|
+
const { unsubscribe } = agent.subscribe(subscriber);
|
|
1126
|
+
return () => unsubscribe();
|
|
1127
|
+
}, [agent, config]);
|
|
1128
|
+
}
|
|
1129
|
+
function useMcpApps(agent, mcpClient) {
|
|
1130
|
+
const [manager] = react.useState(() => new McpAppEventManager());
|
|
1131
|
+
react.useEffect(() => {
|
|
1132
|
+
if (!agent) {
|
|
1133
|
+
manager.detach();
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
manager.attach(agent);
|
|
1137
|
+
return () => manager.detach();
|
|
1138
|
+
}, [agent, manager]);
|
|
1139
|
+
const agentApps = react.useSyncExternalStore(
|
|
1140
|
+
(callback) => manager.subscribe(callback),
|
|
1141
|
+
() => manager.getAllEvents(),
|
|
1142
|
+
() => ({})
|
|
1143
|
+
// Server-side snapshot
|
|
1144
|
+
);
|
|
1145
|
+
const apps = react.useMemo(() => {
|
|
1146
|
+
const combined = {};
|
|
1147
|
+
if (mcpClient) {
|
|
1148
|
+
for (const conn of mcpClient.connections) {
|
|
1149
|
+
for (const tool of conn.tools) {
|
|
1150
|
+
const meta = tool._meta;
|
|
1151
|
+
if (!meta?.ui) continue;
|
|
1152
|
+
const ui = meta.ui;
|
|
1153
|
+
if (typeof ui !== "object" || !ui) continue;
|
|
1154
|
+
if (ui.visibility && !ui.visibility.includes("app")) continue;
|
|
1155
|
+
const resourceUri = typeof ui.resourceUri === "string" ? ui.resourceUri : typeof ui.uri === "string" ? ui.uri : void 0;
|
|
1156
|
+
if (resourceUri) {
|
|
1157
|
+
combined[tool.name] = {
|
|
1158
|
+
toolCallId: "",
|
|
1159
|
+
resourceUri,
|
|
1160
|
+
sessionId: conn.sessionId,
|
|
1161
|
+
toolName: tool.name
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
for (const [toolName, event] of Object.entries(agentApps)) {
|
|
1168
|
+
if (combined[toolName]) {
|
|
1169
|
+
combined[toolName] = {
|
|
1170
|
+
...combined[toolName],
|
|
1171
|
+
toolCallId: event.toolCallId || combined[toolName].toolCallId,
|
|
1172
|
+
result: event.result,
|
|
1173
|
+
input: event.input,
|
|
1174
|
+
status: event.status
|
|
1175
|
+
};
|
|
1176
|
+
} else {
|
|
1177
|
+
combined[toolName] = event;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
return new Proxy(combined, {
|
|
1181
|
+
get(target, prop) {
|
|
1182
|
+
if (typeof prop !== "string") return void 0;
|
|
1183
|
+
if (prop in target) return target[prop];
|
|
1184
|
+
const match = prop.match(/^tool_[^_]+_(.+)$/);
|
|
1185
|
+
if (match && match[1] in target) {
|
|
1186
|
+
return target[match[1]];
|
|
1187
|
+
}
|
|
1188
|
+
return void 0;
|
|
1189
|
+
},
|
|
1190
|
+
// Support Object.entries, Object.keys, etc. by returning base names
|
|
1191
|
+
ownKeys(target) {
|
|
1192
|
+
return Reflect.ownKeys(target);
|
|
1193
|
+
},
|
|
1194
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
1195
|
+
return Reflect.getOwnPropertyDescriptor(target, prop);
|
|
1196
|
+
}
|
|
1197
|
+
});
|
|
1198
|
+
}, [agentApps, mcpClient]);
|
|
1199
|
+
return {
|
|
1200
|
+
apps,
|
|
1201
|
+
// getApp handles both base and prefixed names transparently via the Proxy
|
|
1202
|
+
getApp: (toolName) => apps[toolName],
|
|
1203
|
+
clear: () => manager.clear()
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
function useToolCallEvents(agent) {
|
|
1207
|
+
const [toolCalls, setToolCalls] = react.useState({});
|
|
1208
|
+
react.useEffect(() => {
|
|
1209
|
+
if (!agent) {
|
|
1210
|
+
setToolCalls({});
|
|
1211
|
+
return;
|
|
1212
|
+
}
|
|
1213
|
+
const subscriber = createMcpAppSubscriber({
|
|
1214
|
+
onToolCall: (event) => {
|
|
1215
|
+
setToolCalls((prev) => ({
|
|
1216
|
+
...prev,
|
|
1217
|
+
[event.toolCallId]: event
|
|
1218
|
+
}));
|
|
1219
|
+
}
|
|
1220
|
+
});
|
|
1221
|
+
const { unsubscribe } = agent.subscribe(subscriber);
|
|
1222
|
+
return () => unsubscribe();
|
|
1223
|
+
}, [agent]);
|
|
1224
|
+
return { toolCalls };
|
|
1225
|
+
}
|
|
931
1226
|
|
|
932
1227
|
exports.AppHost = AppHost;
|
|
1228
|
+
exports.McpAppEventManager = McpAppEventManager;
|
|
933
1229
|
exports.SSEClient = SSEClient;
|
|
1230
|
+
exports.createMcpAppSubscriber = createMcpAppSubscriber;
|
|
1231
|
+
exports.subscribeMcpAppEvents = subscribeMcpAppEvents;
|
|
1232
|
+
exports.useAguiSubscriber = useAguiSubscriber;
|
|
1233
|
+
exports.useAppHost = useAppHost;
|
|
934
1234
|
exports.useMcp = useMcp;
|
|
935
|
-
exports.
|
|
1235
|
+
exports.useMcpAppIframe = useMcpAppIframe;
|
|
1236
|
+
exports.useMcpApps = useMcpApps;
|
|
1237
|
+
exports.useToolCallEvents = useToolCallEvents;
|
|
936
1238
|
//# sourceMappingURL=react.js.map
|
|
937
1239
|
//# sourceMappingURL=react.js.map
|