@opentiny/next 0.0.1 → 0.1.1

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 CHANGED
@@ -1 +1,437 @@
1
- OpenTiny NEXT
1
+ # OpenTiny NEXT
2
+
3
+ OpenTiny NEXT 是一个基于 Model Context Protocol(MCP)的 TypeScript 库,提供了多种传输方式来支持 MCP 客户端与服务端的通信。本库支持三种主要的传输方式:
4
+
5
+ 1. MessageChannel API - 用于浏览器内部不同上下文之间的通信
6
+ 2. SSE (Server-Sent Events) Client Proxy - 基于 HTTP 长连接实现单向数据推送的 Client 连接代理
7
+ 3. Streamable HTTP Client Proxy - 通过分块传输编码实现任意数据的流式传输的 Client 连接代理
8
+
9
+ ## 安装
10
+
11
+ ```bash
12
+ npm install @opentiny/next
13
+ ```
14
+
15
+ ## 客户端 API (client.js)
16
+
17
+ 客户端 API 主要用于在浏览器环境中的 MCP 通信。
18
+
19
+ ### MessageChannel API
20
+
21
+ #### 在同一浏览器窗口内互相通信的场景
22
+
23
+ 使用 `createTransportPair` 创建一对可互通的 Transport 服务的和客户端实例来进行通信。
24
+
25
+ ```typescript
26
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
27
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
28
+ import { createTransportPair } from '@opentiny/next';
29
+
30
+ // 创建一对可互通的 Transport 实例
31
+ const [serverTransport, clientTransport] = createTransportPair();
32
+
33
+ // 创建 MCP 服务端和客户端实例
34
+ const capabilities = { prompts: {}, resources: {}, tools: {}, logging: {} };
35
+ const server = new McpServer({ name: 'mcp-server', version: '1.0.0' }, { capabilities });
36
+ const client = new Client({ name: 'mcp-client', version: '1.0.0' }, { capabilities });
37
+
38
+ // 建立服务端和客户端的通信连接
39
+ await server.connect(serverTransport);
40
+ await client.connect(clientTransport);
41
+
42
+ // 将客户端实例存储到状态中
43
+ state.client = client;
44
+ ```
45
+
46
+ #### 在浏览器主线程与iframe、Web Worker等互相通信的场景
47
+
48
+ 使用 `MessageChannelServerTransport` 和 `MessageChannelClientTransport` 创建用于监听的 Transport 服务端实例,以及用于连接的 Transport 客户端实例来进行通信。
49
+
50
+ 以下是在浏览器主线程的代码:
51
+
52
+ ```typescript
53
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
54
+ import { MessageChannelServerTransport } from '@opentiny/next';
55
+
56
+ // 创建用于监听的 Transport 服务端实例
57
+ const serverTransport = new MessageChannelServerTransport('endpoint');
58
+
59
+ // 创建 MCP 服务端实例
60
+ const capabilities = { prompts: {}, resources: {}, tools: {}, logging: {} };
61
+ const server = new McpServer({ name: 'mcp-server', version: '1.0.0' }, { capabilities });
62
+
63
+ // 监听 endpoint 端点,等待客户端连接
64
+ await serverTransport.listen();
65
+
66
+ // 建立服务端和客户端的通信连接
67
+ await server.connect(serverTransport);
68
+ ```
69
+
70
+ 以下是在 iframe、Web Worker 的代码:
71
+
72
+ ```typescript
73
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
74
+ import { MessageChannelClientTransport } from '@opentiny/next';
75
+
76
+ // 创建用于连接的 Transport 客户端实例
77
+ const clientTransport = new MessageChannelClientTransport('endpoint');
78
+
79
+ // 创建 MCP 客户端实例
80
+ const capabilities = { prompts: {}, resources: {}, tools: {}, logging: {} };
81
+ const client = new Client({ name: 'mcp-client', version: '1.0.0' }, { capabilities });
82
+
83
+ // 建立服务端和客户端的通信连接
84
+ await client.connect(clientTransport);
85
+
86
+ // 将客户端实例存储到状态中
87
+ state.client = client;
88
+ ```
89
+
90
+ 请注意:创建 `MessageChannelServerTransport` 实例必须在创建 `MessageChannelClientTransport` 实例之前,确保客户端连接之前服务端已经开始监听。由于 iframe、Web Worker 等代码运行通常在浏览器主线程之后,所以上述示例代码执行顺序一般是先创建 `MessageChannelServerTransport` 实例,后创建 `MessageChannelClientTransport` 实例。
91
+
92
+ ### SSE (Server-Sent Events) Client Proxy
93
+
94
+ 使用 `MessageChannel API` 创建的 `Client` 客户端实例运行在浏览器环境中,为了能够被后端服务的 AI 调用,需要借助 `createSseProxy` 方法创建该 `Client` 的代理。
95
+
96
+ ```typescript
97
+ import { createSseProxy, ProxySSEClientTransport } from '@opentiny/next';
98
+ import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
99
+
100
+ // 定义页面的状态
101
+ const state: {
102
+ sseTransport: ProxySSEClientTransport | undefined;
103
+ client: Client | undefined;
104
+ } = {
105
+ sseTransport: undefined,
106
+ client: undefined
107
+ };
108
+
109
+ // 使用 SSE 代理连接到服务端
110
+ const connectSseProxy = async () => {
111
+ if (!state.sseTransport) {
112
+ const { transport, sessionId } = await createSseProxy({
113
+ client: state.client as Client,
114
+ url: location + 'agent/sse',
115
+ token: process.env.USER_TOKEN as string
116
+ });
117
+
118
+ state.sseTransport = transport;
119
+ }
120
+ };
121
+
122
+ // 使用 SSE 代理调用工具方法
123
+ const callSseProxy = async (question: string) => {
124
+ if (!state.sseTransport) {
125
+ console.error('You need to connect SSE Proxy first!');
126
+ return;
127
+ }
128
+
129
+ const sessionId = state.sseTransport.sessionId;
130
+ return await request('/question', { question, sessionId });
131
+ };
132
+
133
+ // 发送 HTTP 请求
134
+ const request = async (url: string, data: string) => {
135
+ const response = await fetch(url, {
136
+ method: 'POST',
137
+ headers: {
138
+ 'Content-Type': 'application/json',
139
+ Authorization: `Bearer ${process.env.USER_TOKEN}`
140
+ },
141
+ body: JSON.stringify(data)
142
+ });
143
+
144
+ if (!response.ok) {
145
+ throw new Error(response.statusText);
146
+ }
147
+
148
+ return await response.json();
149
+ };
150
+ ```
151
+
152
+ 请注意:在调用 `callSseProxy` 之前需要调用 `connectSseProxy`,只有代理连接成功后,后端服务的 AI 才能通过该代理调用浏览器环境下的 `Client` 客户端的工具方法。为了让后端服务能够找到当前浏览器的 `Client` 客户端连接,需要向后端服务传递 `sseTransport` 的 `sessionId`。
153
+
154
+ ### Streamable HTTP Client Proxy
155
+
156
+ 使用 `MessageChannel API` 创建的 `Client` 客户端实例运行在浏览器环境中,为了能够被后端服务的 AI 调用,需要借助 `createStreamProxy` 方法创建该 `Client` 的代理。
157
+
158
+ ```typescript
159
+ import { createStreamProxy, ProxyStreamClientTransport } from '@opentiny/next';
160
+ import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
161
+
162
+ // 定义页面的状态
163
+ const state: {
164
+ streamTransport: ProxyStreamClientTransport | undefined;
165
+ client: Client | undefined;
166
+ } = {
167
+ streamTransport: undefined,
168
+ client: undefined
169
+ };
170
+
171
+ // 使用 Stream 代理连接到服务端
172
+ const connectStreamProxy = async () => {
173
+ if (!state.streamTransport) {
174
+ const { transport, sessionId } = await createStreamProxy({
175
+ client: state.client as Client,
176
+ url: location + 'agent/mcp',
177
+ token: process.env.USER_TOKEN as string
178
+ });
179
+
180
+ state.streamTransport = transport;
181
+ }
182
+ };
183
+
184
+ // 使用 Streamable HTTP 代理调用工具方法
185
+ const callStreamProxy = async (question: string) => {
186
+ if (!state.streamTransport) {
187
+ console.error('You need to connect Streamable HTTP Proxy first!');
188
+ return;
189
+ }
190
+
191
+ const sessionId = state.streamTransport.sessionId;
192
+ return await request('/question', { question, sessionId });
193
+ };
194
+
195
+ // 关闭 Streamable HTTP 代理连接
196
+ const closeStreamProxy = async () => {
197
+ if (state.streamTransport) {
198
+ await state.streamTransport.terminateSession();
199
+ state.streamTransport = undefined;
200
+ }
201
+ };
202
+
203
+ // 在页面窗口装载时注册关闭 Streamable HTTP 连接的事件
204
+ window.addEventListener('beforeunload', closeStreamProxy);
205
+
206
+ // 在页面窗口卸载时移除注册关闭 Streamable HTTP 连接的事件
207
+ window.removeEventListener('beforeunload', closeStreamProxy);
208
+ ```
209
+
210
+ 请注意:在调用 `callStreamProxy` 之前需要调用 `connectStreamProxy`,只有代理连接成功后,后端服务的 AI 才能通过该代理调用浏览器环境下的 `Client` 客户端的工具方法。为了让后端服务能够找到当前浏览器的 `Client` 客户端连接,需要向后端服务传递 `streamTransport` 的 `sessionId`。
211
+
212
+ 与 `SSE` 的连接可以自动关闭不同,`Streamable HTTP` 的连接需要手动关闭,即要调用 `streamTransport.terminateSession()` 方法来中断连接。
213
+
214
+ ## 服务端 API (server.js)
215
+
216
+ 服务端 API 主要用于在 Node.js 环境中创建 MCP 服务端,处理来自客户端的连接请求。
217
+
218
+ ### SSE (Server-Sent Events) Server Proxy
219
+
220
+ 以下是 Express 环境 Node.js 服务端连接代理的示例代码:
221
+
222
+ ```typescript
223
+ import express from 'express';
224
+ import session from 'express-session';
225
+ import cors from 'cors';
226
+ import { auth, useProxyHandles } from '@opentiny/next/server.js';
227
+ import type { Request, Response } from 'express';
228
+ import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
229
+
230
+ const { handleSseProxy, handleSseInspector, handleSseMessage, clients } = useProxyHandles();
231
+
232
+ const app = express();
233
+
234
+ // 启用跨域资源共享
235
+ app.use(cors());
236
+
237
+ // 获取代理背后真实的 IP 地址
238
+ app.set('trust proxy', 1);
239
+
240
+ // 配置 session 中间件,支持会话管理
241
+ app.use(
242
+ session({
243
+ secret: process.env.SECRET_KEY as string, // 会话密钥
244
+ cookie: { maxAge: 60000 }, // 会话有效期
245
+ resave: false,
246
+ saveUninitialized: true
247
+ })
248
+ );
249
+
250
+ // 获取所有客户端的 sessionId
251
+ app.get('/list', async (req: Request, res: Response) => {
252
+ const sessions: Record<string, object> = {};
253
+ for (const sessionId in clients) {
254
+ const { user, device, type } = clients[sessionId];
255
+ sessions[sessionId] = { user, device, type };
256
+ }
257
+ res.json(sessions);
258
+ });
259
+
260
+ // 启用认证中间件
261
+ app.use(auth({ secret: process.env.SECRET_KEY as string }));
262
+
263
+ // MCP inspector url http://localhost:5173/agent/inspector?sessionId=
264
+ app.get('/inspector', async (req: Request, res: Response) => {
265
+ try {
266
+ await handleSseInspector(req, res, '/agent/messages');
267
+ } catch (error) {
268
+ console.error('AI Agent inspector error:', (error as Error).message);
269
+ }
270
+ });
271
+
272
+ // SSE 端点,支持 inspector 和 proxy 两种模式,inspector url http://localhost:8001/sse?sessionId=
273
+ app.get('/sse', async (req: Request, res: Response) => {
274
+ try {
275
+ if (req.query.sessionId) {
276
+ await handleSseInspector(req, res, '/messages');
277
+ } else {
278
+ await handleSseProxy(req, res, '/agent/messages');
279
+ }
280
+ } catch (error) {
281
+ console.error('AI Agent proxy error:', (error as Error).message);
282
+ }
283
+ });
284
+
285
+ // 消息转发端点,根据 sessionId 找到对应 transport 处理消息
286
+ app.post('/messages', async (req: Request, res: Response) => {
287
+ try {
288
+ await handleSseMessage(req, res);
289
+ } catch (error) {
290
+ console.error('AI Agent message error:', (error as Error).message);
291
+ }
292
+ });
293
+
294
+ // 用户提问端点,支持带 sessionId 的上下文调用
295
+ app.post('/question', express.json(), async (req: Request, res: Response) => {
296
+ try {
297
+ const sessionId = req.body.sessionId as string;
298
+ const client = clients[sessionId]?.client;
299
+ const question = req.body.question as string;
300
+ const answer = await ask(question, client); // 需自行实现 AI 调用 Client 的工具
301
+ res.json({ answer });
302
+ } catch (error) {
303
+ console.error('AI Agent question error:', (error as Error).message);
304
+ }
305
+ });
306
+
307
+ app.listen(8001, () => {
308
+ console.log('AI Agent listening on port 8001');
309
+ });
310
+ ```
311
+
312
+ ### Streamable HTTP Server Proxy
313
+
314
+ 以下是 Express 环境 Node.js 服务端连接代理的示例代码:
315
+
316
+ ```typescript
317
+ import express from 'express';
318
+ import session from 'express-session';
319
+ import cors from 'cors';
320
+ import { auth, useProxyHandles } from '@opentiny/next/server.js';
321
+ import type { Request, Response } from 'express';
322
+ import type { Client } from '@modelcontextprotocol/sdk/client/index.js';
323
+
324
+ const { handleStreamRequest, handleStreamInspector, clients } = useProxyHandles();
325
+
326
+ const app = express();
327
+
328
+ // 启用跨域资源共享
329
+ app.use(cors());
330
+
331
+ // 获取代理背后真实的 IP 地址
332
+ app.set('trust proxy', 1);
333
+
334
+ // 配置 session 中间件,支持会话管理
335
+ app.use(
336
+ session({
337
+ secret: process.env.SECRET_KEY as string, // 会话密钥
338
+ cookie: { maxAge: 60000 }, // 会话有效期
339
+ resave: false,
340
+ saveUninitialized: true
341
+ })
342
+ );
343
+
344
+ // 获取所有客户端的 sessionId
345
+ app.get('/list', async (req: Request, res: Response) => {
346
+ const sessions: Record<string, object> = {};
347
+ for (const sessionId in clients) {
348
+ const { user, device, type } = clients[sessionId];
349
+ sessions[sessionId] = { user, device, type };
350
+ }
351
+ res.json(sessions);
352
+ });
353
+
354
+ // 启用认证中间件
355
+ app.use(auth({ secret: process.env.SECRET_KEY as string }));
356
+
357
+ // 处理 Streamable HTTP 服务端 POST/GET/DELETE 连接
358
+ // 可以使用 MCP inspector 连接调试,方式与 SSE 连接相同,如下:
359
+ // http://localhost:8001/mcp?sessionId= 或 http://localhost:5173/agent/mcp?sessionId=
360
+ app.all('/mcp', express.json(), async (req: Request, res: Response) => {
361
+ try {
362
+ if (req.query.sessionId) {
363
+ await handleStreamInspector(req, res);
364
+ } else {
365
+ await handleStreamRequest(req, res);
366
+ }
367
+ } catch (error) {
368
+ console.error('AI Agent mcp error:', (error as Error).message);
369
+ }
370
+ });
371
+
372
+ // 用户提问端点,支持带 sessionId 的上下文调用
373
+ app.post('/question', express.json(), async (req: Request, res: Response) => {
374
+ try {
375
+ const sessionId = req.body.sessionId as string;
376
+ const client = clients[sessionId]?.client;
377
+ const question = req.body.question as string;
378
+ const answer = await ask(question, client); // 需自行实现 AI 调用 Client 的工具
379
+ res.json({ answer });
380
+ } catch (error) {
381
+ console.error('AI Agent question error:', (error as Error).message);
382
+ }
383
+ });
384
+
385
+ app.listen(8001, () => {
386
+ console.log('AI Agent listening on port 8001');
387
+ });
388
+ ```
389
+
390
+ ## Vite 工程配置示例
391
+
392
+ 以上示例代码均基于 Vite 工程配置运行,增加了环境变量以及代理转发等,以下是 `vite.config.ts` 示例:
393
+
394
+ ```typescript
395
+ import { defineConfig } from 'vite';
396
+ import vue from '@vitejs/plugin-vue';
397
+ import dotenv from 'dotenv';
398
+ import path from 'path';
399
+
400
+ // Vite 配置文件
401
+ export default defineConfig(() => {
402
+ // 加载 .env 文件中的环境变量
403
+ dotenv.config({ path: '.env' });
404
+
405
+ return {
406
+ // 注入环境变量到前端代码
407
+ define: {
408
+ 'process.env': {
409
+ USER_TOKEN: process.env.USER_TOKEN
410
+ }
411
+ },
412
+ plugins: [vue()],
413
+ server: {
414
+ proxy: {
415
+ // 代理 /agent 开头的请求到本地 8001 端口(AI Agent 服务)
416
+ '/agent': {
417
+ target: 'http://localhost:8001',
418
+ changeOrigin: true,
419
+ rewrite: (path) => path.replace(/^\/agent/, '')
420
+ }
421
+ }
422
+ }
423
+ };
424
+ });
425
+ ```
426
+
427
+ ## 注意事项
428
+
429
+ 1. 确保在服务端使用时安装 `express` 作为依赖
430
+ 2. 使用 JWT 令牌认证时,请保护好密钥
431
+ 3. 在生产环境中,应该设置适当的 CORS 配置
432
+ 4. SSE 连接会保持打开状态,请确保适当处理资源释放
433
+ 5. 使用 Streamable HTTP 时,记得在会话结束时调用 `terminateSession()` 方法关闭连接
434
+
435
+ ## 许可证
436
+
437
+ MIT
package/client.d.ts ADDED
@@ -0,0 +1,237 @@
1
+ import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
2
+ import { AuthInfo } from '@modelcontextprotocol/sdk/server/auth/types.js';
3
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
4
+ import { SSEClientTransport, SSEClientTransportOptions } from '@modelcontextprotocol/sdk/client/sse.js';
5
+ import { StreamableHTTPClientTransport, StreamableHTTPClientTransportOptions } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
6
+
7
+ /**
8
+ * MessageChannelTransport 是一个用于在浏览器上下文之间传输消息的类。
9
+ * 它使用 MessageChannel API 来实现不同上下文(如 iframe、worker、标签页、窗口等)之间的通信。
10
+ * 该类提供了初始化、发送消息、关闭通道等功能。
11
+ */
12
+ declare class MessageChannelTransport {
13
+ protected _port: MessagePort | undefined;
14
+ protected _sessionId: string | undefined;
15
+ protected _started: boolean;
16
+ protected _closed: boolean;
17
+ onclose?: () => void;
18
+ onerror?: (error: Error) => void;
19
+ onmessage?: (message: JSONRPCMessage, extra?: {
20
+ authInfo?: AuthInfo;
21
+ }) => void;
22
+ /**
23
+ * 构造函数,初始化 MessageChannelTransport。
24
+ *
25
+ * @param port - 用于通信的 MessagePort。
26
+ * @param sessionId - 会话 ID。
27
+ */
28
+ constructor(port?: MessagePort, sessionId?: string);
29
+ /**
30
+ * 初始化 MessageChannelTransport。
31
+ * 该方法会创建一个新的 MessageChannel,并将其端口传递给指定的全局对象。
32
+ * 如果传输已关闭,则抛出错误。
33
+ */
34
+ start(): Promise<void>;
35
+ /**
36
+ * 发送消息到 MessagePort。
37
+ * 如果传输已关闭,则抛出错误。
38
+ *
39
+ * @param message - 要发送的 JSON-RPC 消息。
40
+ */
41
+ send(message: JSONRPCMessage): Promise<void>;
42
+ /**
43
+ * 关闭 MessageChannelTransport。
44
+ * 该方法会关闭 MessagePort,并触发关闭回调。
45
+ * 如果传输已关闭,则不执行任何操作。
46
+ */
47
+ close(): Promise<void>;
48
+ /**
49
+ * 获取当前会话的 sessionId。
50
+ */
51
+ get sessionId(): string;
52
+ }
53
+ /**
54
+ * 在浏览器端实现基于 MessageChannel API 的客户端传输类,
55
+ * 用于不同浏览器上下文(如 iframe、worker、标签页、窗口等)之间通信。
56
+ */
57
+ declare class MessageChannelClientTransport extends MessageChannelTransport {
58
+ private _endpoint;
59
+ private _globalObject;
60
+ /**
61
+ * 创建一个监听通信的服务端实例。
62
+ *
63
+ * @param endpoint - 用于通信的端点。
64
+ * @param [globalObject] - 用于通信的全局对象(可选,默认当前全局对象)。
65
+ */
66
+ constructor(endpoint: string, globalObject?: object);
67
+ }
68
+ /**
69
+ * 在浏览器端实现基于 MessageChannel API 的服务端传输类,
70
+ * 用于不同浏览器上下文(如 iframe、worker、标签页、窗口等)之间通信。
71
+ */
72
+ declare class MessageChannelServerTransport extends MessageChannelTransport {
73
+ private _endpoint;
74
+ private _globalObject;
75
+ private _listen;
76
+ /**
77
+ * 创建一个监听通信的服务端实例。
78
+ *
79
+ * @param endpoint - 用于通信的端点。
80
+ * @param [globalObject] - 用于通信的全局对象(可选,默认当前全局对象)。
81
+ */
82
+ constructor(endpoint: string, globalObject?: object);
83
+ /**
84
+ * 监听等待客户端连接。
85
+ * 该方法会返回一个 Promise,当客户端连接时解析。
86
+ */
87
+ listen(): Promise<void>;
88
+ }
89
+ /**
90
+ * 创建一对 MessageChannelTransport 实例,返回两个端口的传输实例。
91
+ * 这两个实例可以用于在不同的浏览器上下文之间进行通信。
92
+ *
93
+ * @returns 返回一对 MessageChannelTransport 实例。
94
+ */
95
+ declare const createTransportPair: () => [MessageChannelTransport, MessageChannelTransport];
96
+
97
+ /**
98
+ * ProxySSEClientTransport(SSE 代理客户端传输类)
99
+ * 该类用于通过 Server-Sent Events(SSE)协议从服务端接收消息,主要应用于浏览器等客户端环境,实现与服务端的实时消息通信。
100
+ * 消息到达时会自动调用 forward.js 进行 method 分发交由代理处理。
101
+ */
102
+ declare class ProxySSEClientTransport extends SSEClientTransport {
103
+ _client: Client;
104
+ /**
105
+ * 构造函数
106
+ * @param url - SSE 服务端地址
107
+ * @param opts - 传输配置参数(如认证、请求头等)
108
+ * @param client - 客户端代理实例
109
+ */
110
+ constructor(url: URL, opts: SSEClientTransportOptions, client: Client);
111
+ /**
112
+ * 启动 SSE 连接或进行认证
113
+ * 重写父类方法,增加消息自动分发处理逻辑
114
+ *
115
+ * 收到 SSE 消息后,自动解析并转发到 forward.js 进行 method 分发。
116
+ * 若 forward 返回 undefined,则调用自定义 onmessage 回调。
117
+ */
118
+ _startOrAuth(): Promise<void>;
119
+ /**
120
+ * 获取当前会话 sessionId
121
+ */
122
+ get sessionId(): string;
123
+ }
124
+
125
+ /**
126
+ * SSE 连接的启动或认证选项
127
+ */
128
+ interface StartSSEOptions {
129
+ resumptionToken?: string;
130
+ onresumptiontoken?: (token: string) => void;
131
+ replayMessageId?: string | number;
132
+ }
133
+ /**
134
+ * ProxyStreamClientTransport(Streamable HTTP 代理客户端传输类)
135
+ * 该类用于通过 Streamable HTTP 协议从服务端接收消息,主要应用于浏览器等客户端环境,实现与服务端的实时消息通信。
136
+ * 消息到达时会自动调用 forward.js 进行 method 分发和业务处理。
137
+ */
138
+ declare class ProxyStreamClientTransport extends StreamableHTTPClientTransport {
139
+ _client: Client;
140
+ /**
141
+ * 构造函数
142
+ * @param url - Streamable HTTP 服务端地址
143
+ * @param opts - 传输配置参数(如认证、请求头等)
144
+ * @param client - 客户端代理实例
145
+ */
146
+ constructor(url: URL, opts: StreamableHTTPClientTransportOptions, client: Client);
147
+ /**
148
+ * 处理 SSE 数据流
149
+ * 重写父类方法,增加消息自动分发处理逻辑
150
+ *
151
+ * 收到 SSE 消息后,自动解析并转发到 forward.js 进行 method 分发。
152
+ * 若 forward 返回 undefined,则调用自定义 onmessage 回调。
153
+ *
154
+ * @param stream - SSE 可读数据流
155
+ * @param options - 启动 SSE 的配置参数
156
+ */
157
+ _handleSseStream(stream: ReadableStream, options: StartSSEOptions): void;
158
+ }
159
+
160
+ /**
161
+ * 客户端代理选项接口
162
+ */
163
+ interface ClientProxyOption {
164
+ /**
165
+ * MCP 客户端实例
166
+ */
167
+ client: Client;
168
+ /**
169
+ * 代理服务器的 URL
170
+ */
171
+ url: string;
172
+ /**
173
+ * 代理服务器的身份验证令牌
174
+ */
175
+ token: string;
176
+ }
177
+ /**
178
+ * 创建一个 SSE 客户端代理
179
+ *
180
+ * @param options - 客户端代理选项
181
+ * @returns - 返回一个包含 transport 和 sessionId 的对象
182
+ */
183
+ declare const createSseProxy: (option: ClientProxyOption) => Promise<{
184
+ transport: ProxySSEClientTransport;
185
+ sessionId: string;
186
+ }>;
187
+ /**
188
+ * 创建一个 Streamable HTTP 客户端代理
189
+ *
190
+ * @param options - 客户端代理选项
191
+ * @returns - 返回一个包含 transport 和 sessionId 的对象
192
+ */
193
+ declare const createStreamProxy: (option: ClientProxyOption) => Promise<{
194
+ transport: ProxyStreamClientTransport;
195
+ sessionId: string;
196
+ }>;
197
+
198
+ /**
199
+ * 生成 SSEClientTransport 构造函数所需的第二个可选参数(传输配置)。
200
+ * 用于为 SSE 连接和 HTTP 请求统一设置认证头(Authorization)。
201
+ *
202
+ * @param token - 用于认证的 Bearer Token。
203
+ * @returns 返回传输配置对象,包含 requestInit 和 eventSourceInit 两部分:
204
+ * - requestInit:fetch 请求的初始化配置,自动带上认证头。
205
+ * - eventSourceInit:自定义 fetch 方法,确保 SSE 连接也带上认证头。
206
+ */
207
+ declare const sseOptions: (token: string) => {
208
+ requestInit: {
209
+ headers: {
210
+ Authorization: string;
211
+ };
212
+ };
213
+ eventSourceInit: {
214
+ fetch: (input: string | URL, init?: RequestInit) => Promise<Response>;
215
+ };
216
+ };
217
+
218
+ /**
219
+ * 生成 StreamableHTTPServerTransport 构造函数所需的第二个可选参数(传输配置)。
220
+ * 用于为 Streamable HTTP 连接和 HTTP 请求统一设置认证头(Authorization)。
221
+ *
222
+ * @param token - 用于认证的 Bearer Token。
223
+ * @param sessionId - 可选的 sessionId,用于标识会话。
224
+ * @returns 返回传输配置对象,包含以下内容:
225
+ * - requestInit:fetch 请求的初始化配置,自动带上认证头,并设置 Streamable HTTP 代理的会话 ID。
226
+ */
227
+ declare const streamOptions: (token: string, sessionId?: `${string}-${string}-${string}-${string}-${string}`) => {
228
+ requestInit: {
229
+ headers: {
230
+ Authorization: string;
231
+ "stream-session-id": string;
232
+ };
233
+ };
234
+ };
235
+
236
+ export { MessageChannelClientTransport, MessageChannelServerTransport, MessageChannelTransport, ProxySSEClientTransport, ProxyStreamClientTransport, createSseProxy, createStreamProxy, createTransportPair, sseOptions, streamOptions };
237
+ export type { ClientProxyOption };