@opentiny/next-sdk 0.1.4 → 0.1.6

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/WebMcpClient.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Client } from '@modelcontextprotocol/sdk/client/index.js'
2
2
  import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
3
3
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
4
+ import { WebSocketClientTransport } from '@modelcontextprotocol/sdk/client/websocket.js'
4
5
  import { z, ZodObject, ZodLiteral, ZodType } from 'zod'
5
6
  import {
6
7
  ElicitRequestSchema,
@@ -18,8 +19,9 @@ import {
18
19
  sseOptions,
19
20
  streamOptions,
20
21
  attemptConnection,
21
- createStreamProxy,
22
22
  createSseProxy,
23
+ createStreamProxy,
24
+ createSocketProxy,
23
25
  AuthClientProvider
24
26
  } from '@opentiny/next'
25
27
  import type {
@@ -60,7 +62,7 @@ export interface ClientConnectOptions {
60
62
  token?: string
61
63
  sessionId?: string
62
64
  authProvider?: AuthClientProvider
63
- type?: 'channel' | 'sse'
65
+ type?: 'channel' | 'sse' | 'stream' | 'socket'
64
66
  agent?: boolean
65
67
  onError?: (error: Error) => void
66
68
  onUnauthorized?: (connect: () => Promise<void>) => Promise<void>
@@ -126,7 +128,11 @@ export class WebMcpClient {
126
128
 
127
129
  const connectProxy = async () => {
128
130
  const { transport, sessionId } =
129
- type === 'sse' ? await createSseProxy(proxyOptions) : await createStreamProxy(proxyOptions)
131
+ type === 'sse'
132
+ ? await createSseProxy(proxyOptions)
133
+ : type === 'socket'
134
+ ? await createSocketProxy(proxyOptions)
135
+ : await createStreamProxy(proxyOptions)
130
136
 
131
137
  transport.onerror = async (error: Error) => {
132
138
  onError?.(error)
@@ -169,6 +175,12 @@ export class WebMcpClient {
169
175
  }
170
176
  }
171
177
 
178
+ if (type === 'socket') {
179
+ transport = new WebSocketClientTransport(new URL(`${url}?sessionId=${sessionId}&token=${token}`))
180
+ transport.sessionId = sessionId
181
+ await this.client.connect(transport)
182
+ }
183
+
172
184
  if (typeof transport === 'undefined') {
173
185
  if (authProvider) {
174
186
  const createTransport = () => new StreamableHTTPClientTransport(endpoint, { authProvider })
@@ -36,6 +36,8 @@ export class AgentModelProvider {
36
36
 
37
37
  /** chat 时,自动更新 所有的tools 后的事件 */
38
38
  onUpdatedTools: (() => void) | undefined
39
+ /** 内部报错时,抛出错误事件 */
40
+ onError: ((msg: string, err?: any) => void) | undefined
39
41
 
40
42
  constructor({ llmConfig, mcpServers, llm }: IAgentModelProviderOption) {
41
43
  // 1、保存 mcpServer
@@ -72,8 +74,11 @@ export class AgentModelProvider {
72
74
  transport = serverConfig as MCPClientConfig['transport']
73
75
  }
74
76
 
75
- return createMCPClient({ transport: transport as MCPClientConfig['transport'] })
77
+ return await createMCPClient({ transport: transport as MCPClientConfig['transport'] })
76
78
  } catch (error) {
79
+ if (this.onError) {
80
+ this.onError(`Failed to create MCP client`, error)
81
+ }
77
82
  console.error(`Failed to create MCP client`, serverConfig, error)
78
83
  return null
79
84
  }
@@ -94,6 +99,10 @@ export class AgentModelProvider {
94
99
  try {
95
100
  return client ? await client?.tools?.() : null
96
101
  } catch (error) {
102
+ if (this.onError) {
103
+ this.onError(`Failed to query tools`, error)
104
+ }
105
+ console.error(`Failed to query tools`, error)
97
106
  return null
98
107
  }
99
108
  })
@@ -122,7 +131,7 @@ export class AgentModelProvider {
122
131
  }
123
132
 
124
133
  async insertMcpServer(mcpServer: McpServerConfig) {
125
- const find = this.mcpServers.find((item: any) => item.url === mcpServer.url)
134
+ const find = this.mcpServers.find((item: any) => 'url' in item && 'url' in mcpServer && item.url === mcpServer.url)
126
135
 
127
136
  if (!find) {
128
137
  this.mcpServers = [...this.mcpServers, mcpServer]
@@ -167,7 +176,6 @@ export class AgentModelProvider {
167
176
  this.ignoreToolnames.forEach((name) => {
168
177
  delete toolsResult[name]
169
178
  })
170
-
171
179
  return toolsResult
172
180
  }
173
181
 
@@ -187,9 +195,9 @@ export class AgentModelProvider {
187
195
  return chatMethod({
188
196
  // @ts-ignore ProviderV2 是所有llm的父类, 在每一个具体的llm 类都有一个选择model的函数用法
189
197
  model: this.llm(model),
190
- tools: this.tempMergeTools(options.tools) as ToolSet,
191
198
  stopWhen: stepCountIs(maxSteps),
192
- ...options
199
+ ...options,
200
+ tools: this.tempMergeTools(options.tools) as ToolSet
193
201
  })
194
202
  }
195
203
 
package/agent/type.ts CHANGED
@@ -14,7 +14,7 @@ export interface IAgentModelProviderLlmConfig {
14
14
  }
15
15
 
16
16
  /** Mcp Server的配置对象 */
17
- export type McpServerConfig = { type: 'streamableHttp' | 'sse'; url: string } & { transport: MCPTransport }
17
+ export type McpServerConfig = { type: 'streamableHttp' | 'sse'; url: string } | { transport: MCPTransport }
18
18
 
19
19
  /** */
20
20
  export interface IAgentModelProviderOption {
@@ -18,7 +18,7 @@ export interface ClientConnectOptions {
18
18
  token?: string;
19
19
  sessionId?: string;
20
20
  authProvider?: AuthClientProvider;
21
- type?: 'channel' | 'sse';
21
+ type?: 'channel' | 'sse' | 'stream' | 'socket';
22
22
  agent?: boolean;
23
23
  onError?: (error: Error) => void;
24
24
  onUnauthorized?: (connect: () => Promise<void>) => Promise<void>;
@@ -10,8 +10,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
11
11
  import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
12
12
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
13
+ import { WebSocketClientTransport } from '@modelcontextprotocol/sdk/client/websocket.js';
13
14
  import { ElicitRequestSchema, CallToolResultSchema, ListRootsRequestSchema, CreateMessageRequestSchema, LoggingMessageNotificationSchema, ToolListChangedNotificationSchema, ResourceUpdatedNotificationSchema, PromptListChangedNotificationSchema, ResourceListChangedNotificationSchema } from '@modelcontextprotocol/sdk/types.js';
14
- import { MessageChannelClientTransport, sseOptions, streamOptions, attemptConnection, createStreamProxy, createSseProxy } from '@opentiny/next';
15
+ import { MessageChannelClientTransport, sseOptions, streamOptions, attemptConnection, createSseProxy, createStreamProxy, createSocketProxy } from '@opentiny/next';
15
16
  /**
16
17
  * An MCP client on top of a pluggable transport.
17
18
  * The client will automatically begin the initialization flow with the server when connect() is called.
@@ -56,7 +57,11 @@ export class WebMcpClient {
56
57
  let reconnect = false;
57
58
  let response;
58
59
  const connectProxy = () => __awaiter(this, void 0, void 0, function* () {
59
- const { transport, sessionId } = type === 'sse' ? yield createSseProxy(proxyOptions) : yield createStreamProxy(proxyOptions);
60
+ const { transport, sessionId } = type === 'sse'
61
+ ? yield createSseProxy(proxyOptions)
62
+ : type === 'socket'
63
+ ? yield createSocketProxy(proxyOptions)
64
+ : yield createStreamProxy(proxyOptions);
60
65
  transport.onerror = (error) => __awaiter(this, void 0, void 0, function* () {
61
66
  onError === null || onError === void 0 ? void 0 : onError(error);
62
67
  if (error.message === 'Unauthorized' && !reconnect) {
@@ -93,6 +98,11 @@ export class WebMcpClient {
93
98
  yield this.client.connect(transport);
94
99
  }
95
100
  }
101
+ if (type === 'socket') {
102
+ transport = new WebSocketClientTransport(new URL(`${url}?sessionId=${sessionId}&token=${token}`));
103
+ transport.sessionId = sessionId;
104
+ yield this.client.connect(transport);
105
+ }
96
106
  if (typeof transport === 'undefined') {
97
107
  if (authProvider) {
98
108
  const createTransport = () => new StreamableHTTPClientTransport(endpoint, { authProvider });
@@ -28,6 +28,8 @@ export declare class AgentModelProvider {
28
28
  autoUpdateTools: boolean;
29
29
  /** chat 时,自动更新 所有的tools 后的事件 */
30
30
  onUpdatedTools: (() => void) | undefined;
31
+ /** 内部报错时,抛出错误事件 */
32
+ onError: ((msg: string, err?: any) => void) | undefined;
31
33
  constructor({ llmConfig, mcpServers, llm }: IAgentModelProviderOption);
32
34
  /** 创建一个 ai-sdk的 mcpClient, 创建失败则返回 Null */
33
35
  private _createOneClient;
@@ -79,9 +79,12 @@ export class AgentModelProvider {
79
79
  else {
80
80
  transport = serverConfig;
81
81
  }
82
- return createMCPClient({ transport: transport });
82
+ return yield createMCPClient({ transport: transport });
83
83
  }
84
84
  catch (error) {
85
+ if (this.onError) {
86
+ this.onError(`Failed to create MCP client`, error);
87
+ }
85
88
  console.error(`Failed to create MCP client`, serverConfig, error);
86
89
  return null;
87
90
  }
@@ -105,6 +108,10 @@ export class AgentModelProvider {
105
108
  return client ? yield ((_a = client === null || client === void 0 ? void 0 : client.tools) === null || _a === void 0 ? void 0 : _a.call(client)) : null;
106
109
  }
107
110
  catch (error) {
111
+ if (this.onError) {
112
+ this.onError(`Failed to query tools`, error);
113
+ }
114
+ console.error(`Failed to query tools`, error);
108
115
  return null;
109
116
  }
110
117
  })));
@@ -137,7 +144,7 @@ export class AgentModelProvider {
137
144
  insertMcpServer(mcpServer) {
138
145
  return __awaiter(this, void 0, void 0, function* () {
139
146
  var _a;
140
- const find = this.mcpServers.find((item) => item.url === mcpServer.url);
147
+ const find = this.mcpServers.find((item) => 'url' in item && 'url' in mcpServer && item.url === mcpServer.url);
141
148
  if (!find) {
142
149
  this.mcpServers = [...this.mcpServers, mcpServer];
143
150
  const client = yield this._createOneClient(mcpServer);
@@ -190,9 +197,9 @@ export class AgentModelProvider {
190
197
  yield this._createMpcTools();
191
198
  (_b = this.onUpdatedTools) === null || _b === void 0 ? void 0 : _b.call(this);
192
199
  }
193
- return chatMethod(Object.assign({
200
+ return chatMethod(Object.assign(Object.assign({
194
201
  // @ts-ignore ProviderV2 是所有llm的父类, 在每一个具体的llm 类都有一个选择model的函数用法
195
- model: this.llm(model), tools: this.tempMergeTools(options.tools), stopWhen: stepCountIs(maxSteps) }, options));
202
+ model: this.llm(model), stopWhen: stepCountIs(maxSteps) }, options), { tools: this.tempMergeTools(options.tools) }));
196
203
  });
197
204
  }
198
205
  chat(options) {
@@ -15,7 +15,7 @@ export interface IAgentModelProviderLlmConfig {
15
15
  export type McpServerConfig = {
16
16
  type: 'streamableHttp' | 'sse';
17
17
  url: string;
18
- } & {
18
+ } | {
19
19
  transport: MCPTransport;
20
20
  };
21
21
  /** */