@mcp-ts/sdk 1.0.0 → 1.1.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.
Files changed (77) hide show
  1. package/README.md +25 -13
  2. package/dist/adapters/agui-adapter.d.mts +21 -44
  3. package/dist/adapters/agui-adapter.d.ts +21 -44
  4. package/dist/adapters/agui-adapter.js +93 -67
  5. package/dist/adapters/agui-adapter.js.map +1 -1
  6. package/dist/adapters/agui-adapter.mjs +93 -68
  7. package/dist/adapters/agui-adapter.mjs.map +1 -1
  8. package/dist/adapters/agui-middleware.d.mts +32 -134
  9. package/dist/adapters/agui-middleware.d.ts +32 -134
  10. package/dist/adapters/agui-middleware.js +314 -350
  11. package/dist/adapters/agui-middleware.js.map +1 -1
  12. package/dist/adapters/agui-middleware.mjs +314 -351
  13. package/dist/adapters/agui-middleware.mjs.map +1 -1
  14. package/dist/adapters/ai-adapter.d.mts +2 -2
  15. package/dist/adapters/ai-adapter.d.ts +2 -2
  16. package/dist/adapters/langchain-adapter.d.mts +2 -2
  17. package/dist/adapters/langchain-adapter.d.ts +2 -2
  18. package/dist/adapters/mastra-adapter.d.mts +2 -2
  19. package/dist/adapters/mastra-adapter.d.ts +2 -2
  20. package/dist/client/index.d.mts +184 -57
  21. package/dist/client/index.d.ts +184 -57
  22. package/dist/client/index.js +535 -130
  23. package/dist/client/index.js.map +1 -1
  24. package/dist/client/index.mjs +535 -131
  25. package/dist/client/index.mjs.map +1 -1
  26. package/dist/client/react.d.mts +40 -6
  27. package/dist/client/react.d.ts +40 -6
  28. package/dist/client/react.js +587 -142
  29. package/dist/client/react.js.map +1 -1
  30. package/dist/client/react.mjs +586 -143
  31. package/dist/client/react.mjs.map +1 -1
  32. package/dist/client/vue.d.mts +5 -5
  33. package/dist/client/vue.d.ts +5 -5
  34. package/dist/client/vue.js +545 -140
  35. package/dist/client/vue.js.map +1 -1
  36. package/dist/client/vue.mjs +545 -141
  37. package/dist/client/vue.mjs.map +1 -1
  38. package/dist/{events-BP6WyRNh.d.mts → events-BgeztGYZ.d.mts} +12 -1
  39. package/dist/{events-BP6WyRNh.d.ts → events-BgeztGYZ.d.ts} +12 -1
  40. package/dist/index.d.mts +4 -4
  41. package/dist/index.d.ts +4 -4
  42. package/dist/index.js +779 -248
  43. package/dist/index.js.map +1 -1
  44. package/dist/index.mjs +775 -245
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/{multi-session-client-DMF3ED2O.d.mts → multi-session-client-CxogNckF.d.mts} +1 -1
  47. package/dist/{multi-session-client-BOFgPypS.d.ts → multi-session-client-cox_WXUj.d.ts} +1 -1
  48. package/dist/server/index.d.mts +44 -40
  49. package/dist/server/index.d.ts +44 -40
  50. package/dist/server/index.js +242 -116
  51. package/dist/server/index.js.map +1 -1
  52. package/dist/server/index.mjs +238 -112
  53. package/dist/server/index.mjs.map +1 -1
  54. package/dist/shared/index.d.mts +2 -2
  55. package/dist/shared/index.d.ts +2 -2
  56. package/dist/shared/index.js.map +1 -1
  57. package/dist/shared/index.mjs.map +1 -1
  58. package/dist/{types-SbDlA2VX.d.mts → types-CLccx9wW.d.mts} +1 -1
  59. package/dist/{types-SbDlA2VX.d.ts → types-CLccx9wW.d.ts} +1 -1
  60. package/package.json +8 -1
  61. package/src/adapters/agui-adapter.ts +121 -107
  62. package/src/adapters/agui-middleware.ts +474 -512
  63. package/src/client/core/app-host.ts +417 -0
  64. package/src/client/core/sse-client.ts +365 -212
  65. package/src/client/core/types.ts +31 -0
  66. package/src/client/index.ts +1 -0
  67. package/src/client/react/index.ts +1 -0
  68. package/src/client/react/use-mcp-app.ts +73 -0
  69. package/src/client/react/useMcp.ts +18 -0
  70. package/src/server/handlers/nextjs-handler.ts +8 -7
  71. package/src/server/handlers/sse-handler.ts +131 -164
  72. package/src/server/mcp/oauth-client.ts +32 -2
  73. package/src/server/storage/index.ts +17 -1
  74. package/src/server/storage/sqlite-backend.ts +185 -0
  75. package/src/server/storage/types.ts +1 -1
  76. package/src/shared/events.ts +12 -0
  77. package/src/shared/types.ts +4 -2
@@ -0,0 +1,31 @@
1
+ import { SessionListResult } from '../../shared/types';
2
+
3
+ /**
4
+ * Abstraction layer for the AppHost's network communication.
5
+ *
6
+ * This interface decouples the `AppHost` from the concrete networking implementation (like `SSEClient`).
7
+ * Implementation can be:
8
+ * 1. `SSEClient`: Direct connection to MCP Server (Browser -> Server).
9
+ * 2. `ProxyClient`: Connection via an intermediary API (Browser -> Next.js API -> Server).
10
+ */
11
+ export interface AppHostClient {
12
+ /**
13
+ * Check if the client is connected
14
+ */
15
+ isConnected(): boolean;
16
+
17
+ /**
18
+ * Get list of active sessions
19
+ */
20
+ getSessions(): Promise<SessionListResult>;
21
+
22
+ /**
23
+ * Call a tool on a specific session
24
+ */
25
+ callTool(sessionId: string, toolName: string, toolArgs: Record<string, unknown>): Promise<unknown>;
26
+
27
+ /**
28
+ * Read a resource from a specific session
29
+ */
30
+ readResource(sessionId: string, uri: string): Promise<unknown>;
31
+ }
@@ -5,6 +5,7 @@
5
5
 
6
6
  /** SSE client for real-time connections */
7
7
  export { SSEClient, type SSEClientOptions } from './core/sse-client';
8
+ export { AppHost } from './core/app-host';
8
9
 
9
10
 
10
11
 
@@ -5,6 +5,7 @@
5
5
 
6
6
  // React Hook
7
7
  export { useMcp, type UseMcpOptions, type McpClient, type McpConnection } from './useMcp';
8
+ export { useMcpApp } from './use-mcp-app';
8
9
 
9
10
  // Re-export shared types and client from main entry
10
11
  export * from '../index';
@@ -0,0 +1,73 @@
1
+ import { useEffect, useRef, useState, useCallback } from 'react';
2
+ import type { SSEClient } from '../core/sse-client';
3
+ import { AppHost } from '../core/app-host';
4
+
5
+ /**
6
+ * Hook to host an MCP App in a React component
7
+ *
8
+ * Optimized for instant loading:
9
+ * - Creates AppHost synchronously
10
+ * - Starts bridge connection immediately
11
+ * - Returns host before connection completes (ready to call launch)
12
+ *
13
+ * @param client - Connected SSEClient instance
14
+ * @param iframeRef - Reference to the iframe element
15
+ * @param options - Optional configuration
16
+ * @returns Object containing the AppHost instance (or null) and error state
17
+ */
18
+ export function useMcpApp(
19
+ client: SSEClient,
20
+ iframeRef: React.RefObject<HTMLIFrameElement>,
21
+ options?: {
22
+ /** Callback when the App sends a message (e.g. to chat) */
23
+ onMessage?: (params: { role: string; content: unknown }) => void;
24
+ }
25
+ ) {
26
+ const [host, setHost] = useState<AppHost | null>(null);
27
+ const [error, setError] = useState<Error | null>(null);
28
+ const initializingRef = useRef(false);
29
+
30
+ // Store latest callback in ref to avoid re-initializing AppHost on callback change
31
+ const onMessageRef = useRef(options?.onMessage);
32
+ useEffect(() => {
33
+ onMessageRef.current = options?.onMessage;
34
+ }, [options?.onMessage]);
35
+
36
+ useEffect(() => {
37
+ if (!client || !iframeRef.current || initializingRef.current) return;
38
+
39
+ // Prevent double initialization in strict mode
40
+ initializingRef.current = true;
41
+
42
+ const initHost = async () => {
43
+ try {
44
+ // Initialize AppHost with security enforcement
45
+ const appHost = new AppHost(client, iframeRef.current!);
46
+
47
+ // Register message handler
48
+ appHost.onAppMessage = (params) => {
49
+ onMessageRef.current?.(params);
50
+ };
51
+
52
+ // Set host immediately so launch can be called
53
+ // (launch will wait for bridge if needed)
54
+ setHost(appHost);
55
+
56
+ // Start bridge connection (this is fast, just sets up PostMessage)
57
+ await appHost.start();
58
+ } catch (err) {
59
+ console.error('[useMcpApp] Failed to initialize AppHost:', err);
60
+ setError(err instanceof Error ? err : new Error(String(err)));
61
+ }
62
+ };
63
+
64
+ initHost();
65
+
66
+ return () => {
67
+ initializingRef.current = false;
68
+ setHost(null);
69
+ };
70
+ }, [client, iframeRef]);
71
+
72
+ return { host, error };
73
+ }
@@ -58,6 +58,12 @@ export interface UseMcpOptions {
58
58
  * If provided, this will be called instead of window.location.href assignment
59
59
  */
60
60
  onRedirect?: (url: string) => void;
61
+
62
+ /**
63
+ * Request timeout in milliseconds
64
+ * @default 60000
65
+ */
66
+ requestTimeout?: number;
61
67
  }
62
68
 
63
69
  export interface McpConnection {
@@ -177,6 +183,11 @@ export interface McpClient {
177
183
  * Read a specific resource
178
184
  */
179
185
  readResource: (sessionId: string, uri: string) => Promise<unknown>;
186
+
187
+ /**
188
+ * Access the underlying SSEClient instance (for advanced usage like AppHost)
189
+ */
190
+ client: SSEClient | null;
180
191
  }
181
192
 
182
193
  /**
@@ -228,6 +239,7 @@ export function useMcp(options: UseMcpOptions): McpClient {
228
239
  setStatus(newStatus);
229
240
  }
230
241
  },
242
+ requestTimeout: options.requestTimeout,
231
243
  };
232
244
 
233
245
  const client = new SSEClient(clientOptions);
@@ -276,6 +288,11 @@ export function useMcp(options: UseMcpOptions): McpClient {
276
288
  }
277
289
 
278
290
  case 'tools_discovered': {
291
+ // Preload UI resources for instant loading when tools are discovered
292
+ if (clientRef.current && event.tools?.length) {
293
+ clientRef.current.preloadToolUiResources(event.sessionId, event.tools);
294
+ }
295
+
279
296
  return prev.map((c: McpConnection) =>
280
297
  c.sessionId === event.sessionId ? { ...c, tools: event.tools, state: 'READY' } : c
281
298
  );
@@ -554,5 +571,6 @@ export function useMcp(options: UseMcpOptions): McpClient {
554
571
  getPrompt,
555
572
  listResources,
556
573
  readResource,
574
+ client: clientRef.current,
557
575
  };
558
576
  }
@@ -100,9 +100,6 @@ export function createNextMcpHandler(options: NextMcpHandlerOptions = {}) {
100
100
  });
101
101
  };
102
102
 
103
- // Send initial connection event
104
- sendSSE('connected', { timestamp: Date.now() });
105
-
106
103
  // Clean up previous manager if exists (prevents memory leaks on reconnect)
107
104
  const previousManager = managers.get(identity);
108
105
  if (previousManager) {
@@ -138,6 +135,10 @@ export function createNextMcpHandler(options: NextMcpHandlerOptions = {}) {
138
135
 
139
136
  managers.set(identity, manager);
140
137
 
138
+ // Send connected event AFTER manager is registered (prevents race condition
139
+ // where client sends POST before manager is available)
140
+ sendSSE('connected', { timestamp: Date.now() });
141
+
141
142
  // Handle client disconnect
142
143
  const abortController = new AbortController();
143
144
  request.signal?.addEventListener('abort', () => {
@@ -194,11 +195,11 @@ export function createNextMcpHandler(options: NextMcpHandlerOptions = {}) {
194
195
  );
195
196
  }
196
197
 
197
- // Handle the request - response will be sent via SSE
198
- await manager.handleRequest(body);
198
+ // Handle the request and return response directly (bypasses SSE latency)
199
+ const response = await manager.handleRequest(body);
199
200
 
200
- // Return acknowledgment (actual response goes through SSE)
201
- return Response.json({ acknowledged: true });
201
+ // Return the actual RPC response for immediate use by client
202
+ return Response.json(response);
202
203
  } catch (error) {
203
204
  return Response.json(
204
205
  {