@easbot/mcp 0.2.21
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/LICENSE +21 -0
- package/README.en.md +112 -0
- package/README.md +112 -0
- package/dist/chunks/chunk-4DCCWUIJ.cjs +7 -0
- package/dist/chunks/chunk-PJM3ON7Z.mjs +7 -0
- package/dist/chunks/log-2GAL6FAC.mjs +1 -0
- package/dist/chunks/log-WXSBDTHF.cjs +1 -0
- package/dist/index.cjs +3 -0
- package/dist/index.d.cts +408 -0
- package/dist/index.d.ts +408 -0
- package/dist/index.mjs +3 -0
- package/package.json +78 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp';
|
|
2
|
+
import z from 'zod';
|
|
3
|
+
|
|
4
|
+
interface McpLocalConfig {
|
|
5
|
+
type: 'local';
|
|
6
|
+
command: string[];
|
|
7
|
+
environment?: Record<string, string>;
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
}
|
|
11
|
+
interface McpOAuthConfig {
|
|
12
|
+
clientId?: string;
|
|
13
|
+
clientSecret?: string;
|
|
14
|
+
scope?: string;
|
|
15
|
+
}
|
|
16
|
+
interface McpRemoteConfig {
|
|
17
|
+
type: 'remote';
|
|
18
|
+
url: string;
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
oauth?: McpOAuthConfig | false;
|
|
22
|
+
timeout?: number;
|
|
23
|
+
}
|
|
24
|
+
type McpConfig = McpLocalConfig | McpRemoteConfig;
|
|
25
|
+
declare const ServerTransportType: {
|
|
26
|
+
readonly STDIO: "stdio";
|
|
27
|
+
readonly HTTP: "http";
|
|
28
|
+
};
|
|
29
|
+
type ServerTransportType = (typeof ServerTransportType)[keyof typeof ServerTransportType];
|
|
30
|
+
declare const ServerStatus: {
|
|
31
|
+
readonly STOPPED: "stopped";
|
|
32
|
+
readonly STARTING: "starting";
|
|
33
|
+
readonly RUNNING: "running";
|
|
34
|
+
readonly STOPPING: "stopping";
|
|
35
|
+
readonly ERROR: "error";
|
|
36
|
+
};
|
|
37
|
+
type ServerStatus = (typeof ServerStatus)[keyof typeof ServerStatus];
|
|
38
|
+
interface ServerInfo {
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
version: string;
|
|
42
|
+
transportType: ServerTransportType;
|
|
43
|
+
status: ServerStatus;
|
|
44
|
+
createdAt: number;
|
|
45
|
+
lastActivityAt: number;
|
|
46
|
+
enabled?: boolean;
|
|
47
|
+
}
|
|
48
|
+
interface StdioServerConfig {
|
|
49
|
+
id: string;
|
|
50
|
+
name: string;
|
|
51
|
+
version: string;
|
|
52
|
+
transportType: typeof ServerTransportType.STDIO;
|
|
53
|
+
command: string;
|
|
54
|
+
args?: string[];
|
|
55
|
+
env?: Record<string, string>;
|
|
56
|
+
cwd?: string;
|
|
57
|
+
enabled?: boolean;
|
|
58
|
+
timeout?: number;
|
|
59
|
+
}
|
|
60
|
+
interface HttpServerConfig {
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
version: string;
|
|
64
|
+
transportType: typeof ServerTransportType.HTTP;
|
|
65
|
+
url: string;
|
|
66
|
+
headers?: Record<string, string>;
|
|
67
|
+
enabled?: boolean;
|
|
68
|
+
timeout?: number;
|
|
69
|
+
}
|
|
70
|
+
interface ServerInstance$2 {
|
|
71
|
+
info: ServerInfo;
|
|
72
|
+
get server(): McpServer | null;
|
|
73
|
+
start(): Promise<void>;
|
|
74
|
+
stop(): Promise<void>;
|
|
75
|
+
restart(): Promise<void>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface ServerInstance$1 {
|
|
79
|
+
info: ServerInfo;
|
|
80
|
+
get server(): McpServer | null;
|
|
81
|
+
start(): Promise<void>;
|
|
82
|
+
stop(): Promise<void>;
|
|
83
|
+
restart(): Promise<void>;
|
|
84
|
+
}
|
|
85
|
+
declare class StdioServerAdapter {
|
|
86
|
+
private config;
|
|
87
|
+
private server;
|
|
88
|
+
private info;
|
|
89
|
+
private isStarting;
|
|
90
|
+
private isStopping;
|
|
91
|
+
private toolEventCleanup;
|
|
92
|
+
constructor(config: StdioServerConfig);
|
|
93
|
+
getInfo(): ServerInfo;
|
|
94
|
+
getConfig(): StdioServerConfig;
|
|
95
|
+
createInstance(): ServerInstance$1;
|
|
96
|
+
private loadTools;
|
|
97
|
+
private subscribeToolEvents;
|
|
98
|
+
private handleToolRegistered;
|
|
99
|
+
private adaptToolHandler;
|
|
100
|
+
private unsubscribeToolEvents;
|
|
101
|
+
private convertToZodSchema;
|
|
102
|
+
private jsonSchemaToZod;
|
|
103
|
+
start(): Promise<void>;
|
|
104
|
+
stop(): Promise<void>;
|
|
105
|
+
restart(): Promise<void>;
|
|
106
|
+
}
|
|
107
|
+
declare function createStdioServer(config: StdioServerConfig): StdioServerAdapter;
|
|
108
|
+
declare function createAndStartStdioServer(config: StdioServerConfig): Promise<ServerInstance$1>;
|
|
109
|
+
|
|
110
|
+
interface ServerInstance {
|
|
111
|
+
info: ServerInfo;
|
|
112
|
+
get server(): McpServer | null;
|
|
113
|
+
start(): Promise<void>;
|
|
114
|
+
stop(): Promise<void>;
|
|
115
|
+
restart(): Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
declare class HttpServerAdapter {
|
|
118
|
+
private config;
|
|
119
|
+
private server;
|
|
120
|
+
private transport;
|
|
121
|
+
private httpServer;
|
|
122
|
+
private info;
|
|
123
|
+
private isStarting;
|
|
124
|
+
private isStopping;
|
|
125
|
+
private toolCleanup;
|
|
126
|
+
constructor(config: HttpServerConfig);
|
|
127
|
+
getInfo(): ServerInfo;
|
|
128
|
+
getConfig(): HttpServerConfig;
|
|
129
|
+
createInstance(): ServerInstance;
|
|
130
|
+
private loadTools;
|
|
131
|
+
private subscribeTools;
|
|
132
|
+
private handleTool;
|
|
133
|
+
private convertToZodSchema;
|
|
134
|
+
private jsonSchemaToZod;
|
|
135
|
+
private adaptToolHandler;
|
|
136
|
+
private unsubscribeTools;
|
|
137
|
+
start(): Promise<void>;
|
|
138
|
+
stop(): Promise<void>;
|
|
139
|
+
restart(): Promise<void>;
|
|
140
|
+
}
|
|
141
|
+
declare function createHttpServer(config: HttpServerConfig): HttpServerAdapter;
|
|
142
|
+
declare function createAndStartHttpServer(config: HttpServerConfig): Promise<ServerInstance>;
|
|
143
|
+
|
|
144
|
+
interface OAuthConfig {
|
|
145
|
+
clientId?: string;
|
|
146
|
+
clientSecret?: string;
|
|
147
|
+
scope?: string;
|
|
148
|
+
metadataUrl?: string;
|
|
149
|
+
}
|
|
150
|
+
interface LocalMCPConfig {
|
|
151
|
+
type: 'local';
|
|
152
|
+
command: string[];
|
|
153
|
+
environment?: Record<string, string>;
|
|
154
|
+
timeout?: number;
|
|
155
|
+
}
|
|
156
|
+
interface RemoteMCPConfig {
|
|
157
|
+
type: 'remote';
|
|
158
|
+
url: string;
|
|
159
|
+
headers?: Record<string, string>;
|
|
160
|
+
transport?: 'streamable-http' | 'sse';
|
|
161
|
+
oauth?: OAuthConfig | false;
|
|
162
|
+
timeout?: number;
|
|
163
|
+
}
|
|
164
|
+
type MCPConfig = LocalMCPConfig | RemoteMCPConfig;
|
|
165
|
+
declare const Status: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
166
|
+
status: z.ZodLiteral<"connected">;
|
|
167
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
168
|
+
status: z.ZodLiteral<"disconnected">;
|
|
169
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
170
|
+
status: z.ZodLiteral<"failed">;
|
|
171
|
+
error: z.ZodString;
|
|
172
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
173
|
+
status: z.ZodLiteral<"needs_auth">;
|
|
174
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
175
|
+
status: z.ZodLiteral<"needs_client_registration">;
|
|
176
|
+
error: z.ZodString;
|
|
177
|
+
}, z.core.$strip>], "status">;
|
|
178
|
+
type Status = z.infer<typeof Status>;
|
|
179
|
+
interface ToolMetadata {
|
|
180
|
+
name: string;
|
|
181
|
+
description?: string;
|
|
182
|
+
inputSchema: unknown;
|
|
183
|
+
}
|
|
184
|
+
interface ResourceMetadata {
|
|
185
|
+
name: string;
|
|
186
|
+
uri: string;
|
|
187
|
+
description?: string;
|
|
188
|
+
mimeType?: string;
|
|
189
|
+
}
|
|
190
|
+
interface PromptMetadata {
|
|
191
|
+
name: string;
|
|
192
|
+
description?: string;
|
|
193
|
+
arguments?: Array<{
|
|
194
|
+
name: string;
|
|
195
|
+
description?: string;
|
|
196
|
+
required?: boolean;
|
|
197
|
+
}>;
|
|
198
|
+
}
|
|
199
|
+
interface ClientInfo {
|
|
200
|
+
id: string;
|
|
201
|
+
name: string;
|
|
202
|
+
status: Status;
|
|
203
|
+
connectedAt?: number;
|
|
204
|
+
serverVersion?: string;
|
|
205
|
+
protocolVersion?: string;
|
|
206
|
+
tools: ToolMetadata[];
|
|
207
|
+
resources: ResourceMetadata[];
|
|
208
|
+
prompts: PromptMetadata[];
|
|
209
|
+
error?: string;
|
|
210
|
+
}
|
|
211
|
+
interface ToolCallResult {
|
|
212
|
+
toolName: string;
|
|
213
|
+
args: Record<string, unknown>;
|
|
214
|
+
result: unknown;
|
|
215
|
+
success: boolean;
|
|
216
|
+
error?: string;
|
|
217
|
+
duration: number;
|
|
218
|
+
}
|
|
219
|
+
interface AuthResult {
|
|
220
|
+
authorizationUrl: string;
|
|
221
|
+
state?: string;
|
|
222
|
+
}
|
|
223
|
+
declare class MCPClient {
|
|
224
|
+
private id;
|
|
225
|
+
private client;
|
|
226
|
+
private _info;
|
|
227
|
+
private notificationCleanup;
|
|
228
|
+
private pendingTransport;
|
|
229
|
+
private oauthState;
|
|
230
|
+
private toolListChangedHandler;
|
|
231
|
+
constructor();
|
|
232
|
+
get info(): ClientInfo;
|
|
233
|
+
get status(): Status;
|
|
234
|
+
get tools(): ToolMetadata[];
|
|
235
|
+
connect(id: string, config: MCPConfig): Promise<void>;
|
|
236
|
+
startAuth(): Promise<AuthResult>;
|
|
237
|
+
finishAuth(authorizationCode?: string): Promise<void>;
|
|
238
|
+
disconnect(): Promise<void>;
|
|
239
|
+
listTools(): Promise<Record<string, unknown>>;
|
|
240
|
+
callTool(toolName: string, args: Record<string, unknown>, timeout?: number): Promise<ToolCallResult>;
|
|
241
|
+
listResources(): Promise<ResourceMetadata[]>;
|
|
242
|
+
readResource(uri: string): Promise<{
|
|
243
|
+
[x: string]: unknown;
|
|
244
|
+
contents: ({
|
|
245
|
+
uri: string;
|
|
246
|
+
text: string;
|
|
247
|
+
mimeType?: string | undefined;
|
|
248
|
+
_meta?: Record<string, unknown> | undefined;
|
|
249
|
+
} | {
|
|
250
|
+
uri: string;
|
|
251
|
+
blob: string;
|
|
252
|
+
mimeType?: string | undefined;
|
|
253
|
+
_meta?: Record<string, unknown> | undefined;
|
|
254
|
+
})[];
|
|
255
|
+
_meta?: {
|
|
256
|
+
[x: string]: unknown;
|
|
257
|
+
progressToken?: string | number | undefined;
|
|
258
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
259
|
+
taskId: string;
|
|
260
|
+
} | undefined;
|
|
261
|
+
} | undefined;
|
|
262
|
+
} | undefined>;
|
|
263
|
+
listPrompts(): Promise<PromptMetadata[]>;
|
|
264
|
+
getPrompt(name: string, args?: Record<string, string>): Promise<{
|
|
265
|
+
[x: string]: unknown;
|
|
266
|
+
messages: {
|
|
267
|
+
role: "user" | "assistant";
|
|
268
|
+
content: {
|
|
269
|
+
type: "text";
|
|
270
|
+
text: string;
|
|
271
|
+
annotations?: {
|
|
272
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
273
|
+
priority?: number | undefined;
|
|
274
|
+
lastModified?: string | undefined;
|
|
275
|
+
} | undefined;
|
|
276
|
+
_meta?: Record<string, unknown> | undefined;
|
|
277
|
+
} | {
|
|
278
|
+
type: "image";
|
|
279
|
+
data: string;
|
|
280
|
+
mimeType: string;
|
|
281
|
+
annotations?: {
|
|
282
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
283
|
+
priority?: number | undefined;
|
|
284
|
+
lastModified?: string | undefined;
|
|
285
|
+
} | undefined;
|
|
286
|
+
_meta?: Record<string, unknown> | undefined;
|
|
287
|
+
} | {
|
|
288
|
+
type: "audio";
|
|
289
|
+
data: string;
|
|
290
|
+
mimeType: string;
|
|
291
|
+
annotations?: {
|
|
292
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
293
|
+
priority?: number | undefined;
|
|
294
|
+
lastModified?: string | undefined;
|
|
295
|
+
} | undefined;
|
|
296
|
+
_meta?: Record<string, unknown> | undefined;
|
|
297
|
+
} | {
|
|
298
|
+
type: "resource";
|
|
299
|
+
resource: {
|
|
300
|
+
uri: string;
|
|
301
|
+
text: string;
|
|
302
|
+
mimeType?: string | undefined;
|
|
303
|
+
_meta?: Record<string, unknown> | undefined;
|
|
304
|
+
} | {
|
|
305
|
+
uri: string;
|
|
306
|
+
blob: string;
|
|
307
|
+
mimeType?: string | undefined;
|
|
308
|
+
_meta?: Record<string, unknown> | undefined;
|
|
309
|
+
};
|
|
310
|
+
annotations?: {
|
|
311
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
312
|
+
priority?: number | undefined;
|
|
313
|
+
lastModified?: string | undefined;
|
|
314
|
+
} | undefined;
|
|
315
|
+
_meta?: Record<string, unknown> | undefined;
|
|
316
|
+
} | {
|
|
317
|
+
uri: string;
|
|
318
|
+
name: string;
|
|
319
|
+
type: "resource_link";
|
|
320
|
+
description?: string | undefined;
|
|
321
|
+
mimeType?: string | undefined;
|
|
322
|
+
size?: number | undefined;
|
|
323
|
+
annotations?: {
|
|
324
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
325
|
+
priority?: number | undefined;
|
|
326
|
+
lastModified?: string | undefined;
|
|
327
|
+
} | undefined;
|
|
328
|
+
_meta?: {
|
|
329
|
+
[x: string]: unknown;
|
|
330
|
+
} | undefined;
|
|
331
|
+
icons?: {
|
|
332
|
+
src: string;
|
|
333
|
+
mimeType?: string | undefined;
|
|
334
|
+
sizes?: string[] | undefined;
|
|
335
|
+
theme?: "light" | "dark" | undefined;
|
|
336
|
+
}[] | undefined;
|
|
337
|
+
title?: string | undefined;
|
|
338
|
+
};
|
|
339
|
+
}[];
|
|
340
|
+
_meta?: {
|
|
341
|
+
[x: string]: unknown;
|
|
342
|
+
progressToken?: string | number | undefined;
|
|
343
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
344
|
+
taskId: string;
|
|
345
|
+
} | undefined;
|
|
346
|
+
} | undefined;
|
|
347
|
+
description?: string | undefined;
|
|
348
|
+
} | undefined>;
|
|
349
|
+
refreshTools(): Promise<void>;
|
|
350
|
+
private createClient;
|
|
351
|
+
private fetchCapabilities;
|
|
352
|
+
private createLocalClient;
|
|
353
|
+
private createRemoteClient;
|
|
354
|
+
private connectWithTransport;
|
|
355
|
+
registerToolListChangedHandler(handler: () => void | Promise<void>): void;
|
|
356
|
+
private registerNotificationHandler;
|
|
357
|
+
private createInitialInfo;
|
|
358
|
+
}
|
|
359
|
+
declare function createMCPClient(): MCPClient;
|
|
360
|
+
|
|
361
|
+
declare namespace Log {
|
|
362
|
+
const Level: z.ZodEnum<{
|
|
363
|
+
DEBUG: "DEBUG";
|
|
364
|
+
INFO: "INFO";
|
|
365
|
+
WARN: "WARN";
|
|
366
|
+
ERROR: "ERROR";
|
|
367
|
+
}>;
|
|
368
|
+
type Level = z.infer<typeof Level>;
|
|
369
|
+
function getLevel(): Level;
|
|
370
|
+
type Logger = {
|
|
371
|
+
debug(message?: any, extra?: Record<string, any>): void;
|
|
372
|
+
info(message?: any, extra?: Record<string, any>): void;
|
|
373
|
+
error(message?: any, extra?: Record<string, any>): void;
|
|
374
|
+
warn(message?: any, extra?: Record<string, any>): void;
|
|
375
|
+
tag(key: string, value: string): Logger;
|
|
376
|
+
clone(): Logger;
|
|
377
|
+
time(message: string, extra?: Record<string, any>): {
|
|
378
|
+
stop(): void;
|
|
379
|
+
[Symbol.dispose](): void;
|
|
380
|
+
};
|
|
381
|
+
};
|
|
382
|
+
const Default: Logger;
|
|
383
|
+
interface Options {
|
|
384
|
+
print: boolean;
|
|
385
|
+
logDir: string;
|
|
386
|
+
logFile?: string;
|
|
387
|
+
dev?: boolean;
|
|
388
|
+
level?: Level;
|
|
389
|
+
}
|
|
390
|
+
function file(): string;
|
|
391
|
+
function init(options: Options): Promise<void>;
|
|
392
|
+
function close(): Promise<void>;
|
|
393
|
+
function create(tags?: Record<string, any>): Logger;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
declare function getVersion(): string;
|
|
397
|
+
|
|
398
|
+
declare const VERSION = "0.2.20";
|
|
399
|
+
declare const NAME = "@easbot/mcp";
|
|
400
|
+
declare function initLog(options: {
|
|
401
|
+
print: boolean;
|
|
402
|
+
logDir?: string;
|
|
403
|
+
logFile?: string;
|
|
404
|
+
dev?: boolean;
|
|
405
|
+
level?: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
|
|
406
|
+
}): Promise<void>;
|
|
407
|
+
|
|
408
|
+
export { type AuthResult, type ClientInfo, HttpServerAdapter, type HttpServerConfig, type LocalMCPConfig, Log, MCPClient, type MCPConfig, type McpConfig, type McpLocalConfig, type McpOAuthConfig, type McpRemoteConfig, NAME, type OAuthConfig, type PromptMetadata, type RemoteMCPConfig, type ResourceMetadata, type ServerInfo, type ServerInstance$2 as ServerInstance, ServerStatus, ServerTransportType, Status, StdioServerAdapter, type StdioServerConfig, type ToolCallResult, type ToolMetadata, VERSION, createAndStartHttpServer, createAndStartStdioServer, createHttpServer, createMCPClient, createStdioServer, getVersion, initLog };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import {b,a}from'./chunks/chunk-PJM3ON7Z.mjs';export{b as Log}from'./chunks/chunk-PJM3ON7Z.mjs';import {McpServer}from'@modelcontextprotocol/sdk/server/mcp';import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio';import {EventEmitter}from'events';import l from'zod/v4';import q from'http';import {StreamableHTTPServerTransport}from'@modelcontextprotocol/sdk/server/streamableHttp';import {Client}from'@modelcontextprotocol/sdk/client/index.js';import {StdioClientTransport}from'@modelcontextprotocol/sdk/client/stdio.js';import {StreamableHTTPClientTransport}from'@modelcontextprotocol/sdk/client/streamableHttp.js';import {SSEClientTransport}from'@modelcontextprotocol/sdk/client/sse.js';import {CallToolResultSchema,ToolListChangedNotificationSchema}from'@modelcontextprotocol/sdk/types.js';import {UnauthorizedError}from'@modelcontextprotocol/sdk/client/auth.js';import {withTimeout}from'@easbot/utils';import v from'zod';var N={STDIO:"stdio",HTTP:"http"},c={STOPPED:"stopped",STARTING:"starting",RUNNING:"running",STOPPING:"stopping",ERROR:"error"};var _=b.create({service:"tool-registry"}),T={REGISTERED:"mcp.tool.registered",UNREGISTERED:"mcp.tool.unregistered",CLEARED:"mcp.tool.cleared"},k=class extends EventEmitter{constructor(){super();a(this,"tools",new Map);}register(e){if(!e.name||typeof e.name!="string")throw new Error("\u5DE5\u5177\u540D\u79F0\u65E0\u6548\uFF1A\u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");if(this.tools.has(e.name)){_?.debug("tool already registered, skipping",{tool:e.name});return}this.tools.set(e.name,e),this.emit(T.REGISTERED,e);}unregister(e){return this.tools.has(e)?(this.tools.delete(e),this.emit(T.UNREGISTERED,e),true):false}get(e){return this.tools.get(e)}getAll(){return Array.from(this.tools.values())}getTools(){return Array.from(this.tools.values()).map(({handler:e,...r})=>r)}has(e){return this.tools.has(e)}getSize(){return this.tools.size}clear(){this.tools.clear(),this.emit(T.CLEARED);}},y=new k;var g=b.create({service:"mcp.server.stdio"}),E=class{constructor(t){a(this,"config");a(this,"server",null);a(this,"info");a(this,"isStarting",false);a(this,"isStopping",false);a(this,"toolEventCleanup",null);a(this,"handleToolRegistered",t=>{if(this.server){let e=this.convertToZodSchema(t.inputSchema),r=this.adaptToolHandler(t.handler);this.server.registerTool(t.name,{description:t.description,inputSchema:e},r),g.info("tool registered",{tool:t.name});}});this.config=t,this.info={id:t.id,name:t.name,version:t.version,transportType:t.transportType,status:c.STOPPED,createdAt:Date.now(),lastActivityAt:Date.now(),enabled:t.enabled};}getInfo(){return this.info}getConfig(){return this.config}createInstance(){let t=this;return {info:this.info,get server(){return t.server},start:()=>this.start(),stop:()=>this.stop(),restart:()=>this.restart()}}loadTools(){if(this.server)for(let t of y.getAll()){let e=this.convertToZodSchema(t.inputSchema),r=this.adaptToolHandler(t.handler);this.server.registerTool(t.name,{description:t.description,inputSchema:e},r),g.info("tool loaded",{tool:t.name});}}subscribeToolEvents(){this.toolEventCleanup=()=>{y.off(T.REGISTERED,this.handleToolRegistered);},y.on(T.REGISTERED,this.handleToolRegistered);}adaptToolHandler(t){return async(e,r)=>{let o={signal:r.signal,sessionId:r.sessionId,requestId:r.requestId,taskId:r.taskId,_meta:r._meta,authInfo:r.authInfo?{type:"bearer",claims:{clientId:r.authInfo.clientId,scopes:r.authInfo.scopes}}:void 0};return t(e,o)}}unsubscribeToolEvents(){this.toolEventCleanup&&(this.toolEventCleanup(),this.toolEventCleanup=null);}convertToZodSchema(t){if(t instanceof l.ZodType)return t;if(typeof t=="object"&&t!==null){let e=t;if(e.type==="object"){let r=e.properties||{},o=e.required||[],n={};for(let[i,f]of Object.entries(r))n[i]=this.jsonSchemaToZod(f);if(Object.keys(r).filter(i=>!o.includes(i)).length===0)return l.object(n);let u={};for(let[i,f]of Object.entries(r)){let a=n[i];a&&(o.includes(i)?u[i]=a:u[i]=a.optional());}return l.object(u)}if(e.type==="string")return l.string();if(e.type==="number")return l.number();if(e.type==="boolean")return l.boolean();if(e.type==="array"){let r=e.items;return r?l.array(this.jsonSchemaToZod(r)):l.array(l.unknown())}}return l.unknown()}jsonSchemaToZod(t){switch(t.type){case "string":return l.string();case "number":return l.number();case "integer":return l.number().int();case "boolean":return l.boolean();case "null":return l.null();case "array":{let r=t.items;return r?l.array(this.jsonSchemaToZod(r)):l.array(l.unknown())}case "object":{let r=t.properties||{},o=t.required||[],n={};for(let[i,f]of Object.entries(r))n[i]=this.jsonSchemaToZod(f);if(Object.keys(r).filter(i=>!o.includes(i)).length===0)return l.object(n);let u={};for(let[i,f]of Object.entries(r)){let a=n[i];a&&(o.includes(i)?u[i]=a:u[i]=a.optional());}return l.object(u)}default:return l.unknown()}}async start(){if(this.isStarting){g.warn("server is already starting",{id:this.info.id});return}if(this.info.status===c.RUNNING){g.debug("server is already running",{id:this.info.id});return}this.isStarting=true,this.info.status=c.STARTING;try{g.info("starting stdio mcp server",{id:this.info.id,name:this.info.name,command:this.config.command,args:this.config.args});let t=new StdioServerTransport;await t.start(),this.server=new McpServer({name:this.config.name,version:this.config.version}),this.loadTools(),this.subscribeToolEvents(),await this.server.connect(t),this.info.status=c.RUNNING,this.info.lastActivityAt=Date.now(),g.info("stdio mcp server started successfully",{id:this.info.id,name:this.info.name,toolCount:y.getSize()});}catch(t){throw this.info.status=c.ERROR,g.error("failed to start stdio mcp server",{id:this.info.id,error:t instanceof Error?t.message:String(t)}),t}finally{this.isStarting=false;}}async stop(){if(this.isStopping){g.warn("server is already stopping",{id:this.info.id});return}if(this.info.status!==c.RUNNING&&this.info.status!==c.ERROR){g.debug("server is not running",{id:this.info.id,status:this.info.status});return}this.isStopping=true,this.info.status=c.STOPPING;try{g.info("stopping stdio mcp server",{id:this.info.id,name:this.info.name}),this.unsubscribeToolEvents(),this.server&&(await this.server.close(),this.server=null),this.info.status=c.STOPPED,g.info("stdio mcp server stopped",{id:this.info.id,name:this.info.name});}catch(t){this.info.status=c.ERROR,g.error("error stopping stdio mcp server",{id:this.info.id,error:t instanceof Error?t.message:String(t)});}finally{this.isStopping=false;}}async restart(){g.info("restarting stdio mcp server",{id:this.info.id}),await this.stop(),await this.start();}};function Z(m){return new E(m)}async function z(m){let t=new E(m);return await t.start(),t.createInstance()}var h=b.create({service:"mcp.server.http"}),I=class{constructor(t){a(this,"config");a(this,"server",null);a(this,"transport",null);a(this,"httpServer",null);a(this,"info");a(this,"isStarting",false);a(this,"isStopping",false);a(this,"toolCleanup",null);a(this,"handleTool",t=>{if(this.server){let e=this.convertToZodSchema(t.inputSchema),r=this.adaptToolHandler(t.handler);this.server.registerTool(t.name,{description:t.description,inputSchema:e},r),h.info("tool registered",{tool:t.name});}});this.config=t,this.info={id:t.id,name:t.name,version:t.version,transportType:t.transportType,status:c.STOPPED,createdAt:Date.now(),lastActivityAt:Date.now()};}getInfo(){return this.info}getConfig(){return this.config}createInstance(){let t=this;return {info:this.info,get server(){return t.server},start:()=>this.start(),stop:()=>this.stop(),restart:()=>this.restart()}}loadTools(){if(this.server)for(let t of y.getAll()){let e=this.convertToZodSchema(t.inputSchema),r=this.adaptToolHandler(t.handler);this.server.registerTool(t.name,{description:t.description,inputSchema:e},r),h.info("tool loaded",{tool:t.name});}}subscribeTools(){this.toolCleanup=()=>{y.off(T.REGISTERED,this.handleTool);},y.on(T.REGISTERED,this.handleTool);}convertToZodSchema(t){if(t instanceof l.ZodType)return t;if(typeof t=="object"&&t!==null){let e=t;if(e.type==="object"){let r=e.properties||{},o=e.required||[],n={};for(let[i,f]of Object.entries(r))n[i]=this.jsonSchemaToZod(f);if(Object.keys(r).filter(i=>!o.includes(i)).length===0)return l.object(n);let u={};for(let[i,f]of Object.entries(r)){let a=n[i];a&&(o.includes(i)?u[i]=a:u[i]=a.optional());}return l.object(u)}if(e.type==="string")return l.string();if(e.type==="number")return l.number();if(e.type==="boolean")return l.boolean();if(e.type==="array"){let r=e.items;return r?l.array(this.jsonSchemaToZod(r)):l.array(l.unknown())}}return l.unknown()}jsonSchemaToZod(t){switch(t.type){case "string":return l.string();case "number":return l.number();case "integer":return l.number().int();case "boolean":return l.boolean();case "null":return l.null();case "array":{let r=t.items;return r?l.array(this.jsonSchemaToZod(r)):l.array(l.unknown())}case "object":{let r=t.properties||{},o=t.required||[],n={};for(let[i,f]of Object.entries(r))n[i]=this.jsonSchemaToZod(f);if(Object.keys(r).filter(i=>!o.includes(i)).length===0)return l.object(n);let u={};for(let[i,f]of Object.entries(r)){let a=n[i];a&&(o.includes(i)?u[i]=a:u[i]=a.optional());}return l.object(u)}default:return l.unknown()}}adaptToolHandler(t){return async(e,r)=>{let o={signal:r.signal,sessionId:r.sessionId,requestId:r.requestId,taskId:r.taskId,_meta:r._meta,authInfo:r.authInfo?{type:"bearer",claims:{clientId:r.authInfo.clientId,scopes:r.authInfo.scopes}}:void 0};return t(e,o)}}unsubscribeTools(){this.toolCleanup&&(this.toolCleanup(),this.toolCleanup=null);}async start(){if(this.isStarting){h.warn("already starting",{id:this.info.id});return}if(this.info.status===c.RUNNING){h.debug("already running",{id:this.info.id});return}this.isStarting=true,this.info.status=c.STARTING;try{h.info("starting",{id:this.info.id,name:this.info.name,url:this.config.url});let t;try{t=new URL(this.config.url);}catch{throw new Error(`\u65E0\u6548\u7684 URL: ${this.config.url}`)}let e=parseInt(t.port||"3000",10),r=t.hostname||"0.0.0.0";if(Number.isNaN(e)||e<1||e>65535)throw new Error(`\u65E0\u6548\u7684\u7AEF\u53E3\u53F7: ${t.port}`);this.transport=new StreamableHTTPServerTransport({sessionIdGenerator:()=>crypto.randomUUID()}),this.server=new McpServer({name:this.config.name,version:this.config.version}),this.loadTools(),this.subscribeTools(),await this.server.connect(this.transport),this.httpServer=q.createServer((o,n)=>{let b=o.headers.origin,u=(f,a,M)=>{n.writeHead(f,a),M?n.end(M):n.end();},i={"Access-Control-Allow-Origin":b||"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, mcpsessionid, mcp-protocol-version","Access-Control-Max-Age":"86400"};if(o.method==="OPTIONS"){u(204,i);return}if(o.method==="POST"){let f="";o.setEncoding("utf8"),o.on("data",a=>{f+=a;}),o.on("end",()=>{let a;if(f)try{a=JSON.parse(f);}catch{a=void 0;}this.transport&&this.transport.handleRequest(o,n,a);}),o.on("error",a=>{h.error("HTTP request error",{error:a.message}),u(500,i,JSON.stringify({jsonrpc:"2.0",error:{code:-32603,message:"Internal error"}}));});}else o.method==="GET"?this.transport&&this.transport.handleRequest(o,n,void 0):u(405,i,JSON.stringify({jsonrpc:"2.0",error:{code:-32601,message:"Method not found"}}));}),this.httpServer.on("error",o=>{h.error("HTTP server error",{error:o.message}),this.info.status=c.ERROR;}),this.httpServer.on("clientError",(o,n)=>{h.warn("HTTP client error",{error:o.message}),n.writable&&n.end(`HTTP/1.1 400 Bad Request\r
|
|
2
|
+
\r
|
|
3
|
+
`);}),this.httpServer.listen(e,r),h.info("HTTP server listening",{hostname:r,port:e}),this.info.status=c.RUNNING,this.info.lastActivityAt=Date.now(),h.info("started",{id:this.info.id,name:this.info.name,toolCount:y.getSize()});}catch(t){throw this.info.status=c.ERROR,h.error("failed to start",{id:this.info.id,error:t instanceof Error?t.message:String(t)}),t}finally{this.isStarting=false;}}async stop(){if(this.isStopping){h.warn("already stopping",{id:this.info.id});return}if(this.info.status!==c.RUNNING&&this.info.status!==c.ERROR){h.debug("not running",{id:this.info.id,status:this.info.status});return}this.isStopping=true,this.info.status=c.STOPPING;try{h.info("stopping",{id:this.info.id,name:this.info.name}),this.unsubscribeTools(),this.httpServer&&(await new Promise(t=>{this.httpServer.close(()=>t());}),this.httpServer=null),this.transport&&(await this.transport.close(),this.transport=null),this.server&&(await this.server.close(),this.server=null),this.info.status=c.STOPPED,h.info("stopped",{id:this.info.id});}catch(t){this.info.status=c.ERROR,h.error("failed to stop",{id:this.info.id,error:t instanceof Error?t.message:String(t)});}finally{this.isStopping=false;}}async restart(){h.info("restarting",{id:this.info.id}),await this.stop(),await this.start();}};function V(m){return new I(m)}async function B(m){let t=new I(m);return await t.start(),t.createInstance()}var O={version:"0.2.21"};function x(){return O.version}var d=b.create({service:"mcp.client"}),P=3e4,Bt=v.discriminatedUnion("status",[v.object({status:v.literal("connected")}).meta({ref:"MCPStatusConnected"}),v.object({status:v.literal("disconnected")}).meta({ref:"MCPStatusDisconnected"}),v.object({status:v.literal("failed"),error:v.string()}).meta({ref:"MCPStatusFailed"}),v.object({status:v.literal("needs_auth")}).meta({ref:"MCPStatusNeedsAuth"}),v.object({status:v.literal("needs_client_registration"),error:v.string()}).meta({ref:"MCPStatusNeedsClientRegistration"})]),A=class{constructor(){a(this,"id","");a(this,"client",null);a(this,"_info");a(this,"notificationCleanup",null);a(this,"pendingTransport",null);a(this,"oauthState","");a(this,"toolListChangedHandler",null);this._info=this.createInitialInfo();}get info(){return {...this._info}}get status(){return this._info.status}get tools(){return [...this._info.tools]}async connect(t,e){d.info("connecting to MCP server",{id:t,type:e.type}),await this.disconnect(),this.id=t,this._info=this.createInitialInfo(),this._info.id=t,this._info.name=t;try{if(this.client=await this.createClient(e),!this.client)return;this._info.status={status:"connected"},this._info.connectedAt=Date.now(),await this.fetchCapabilities(),d.info("connected to MCP server",{id:t,toolCount:this._info.tools.length});}catch(r){let o=r instanceof Error?r.message:String(r);this._info.status={status:"failed",error:o},this._info.error=o,d.error("failed to connect to MCP server",{id:t,error:o});}}async startAuth(){if(!this.pendingTransport)throw new Error("No pending OAuth flow. Please connect to a server that requires authentication first.");return this.oauthState=Array.from(crypto.getRandomValues(new Uint8Array(32))).map(t=>t.toString(16).padStart(2,"0")).join(""),{authorizationUrl:"",state:this.oauthState}}async finishAuth(t){if(!this.pendingTransport)throw new Error("No pending OAuth flow.");t&&await this.pendingTransport.finishAuth?.(t),this.pendingTransport=null,d.info("OAuth completed, reconnecting...",{id:this.id});}async disconnect(){this.notificationCleanup&&(this.notificationCleanup(),this.notificationCleanup=null),this.client&&(await this.client.close().catch(t=>{d.error("Failed to close MCP client",{error:t});}),this.client=null),this.pendingTransport=null,this.toolListChangedHandler=null,this._info.status.status==="connected"&&(this._info.status={status:"disconnected"}),d.info("disconnected from MCP server",{id:this.id});}async listTools(){if(!this.client||this._info.status.status!=="connected")return {};let t={};for(let e of this._info.tools)t[e.name]={name:e.name,description:e.description,inputSchema:e.inputSchema};return t}async callTool(t,e,r){let o=Date.now();if(!this.client||this._info.status.status!=="connected")return {toolName:t,args:e,result:null,success:false,error:"Client not connected",duration:Date.now()-o};try{let n=await withTimeout(this.client.callTool({name:t,arguments:e},CallToolResultSchema,{resetTimeoutOnProgress:!0,timeout:r}),r??P);return {toolName:t,args:e,result:n.content,success:!0,duration:Date.now()-o}}catch(n){return {toolName:t,args:e,result:null,success:false,error:n instanceof Error?n.message:String(n),duration:Date.now()-o}}}async listResources(){return [...this._info.resources]}async readResource(t){if(!this.client||this._info.status.status!=="connected"){d.warn("client not connected for readResource");return}return this.client.readResource({uri:t}).catch(e=>{d.error("failed to read resource",{uri:t,error:e.message});})}async listPrompts(){return [...this._info.prompts]}async getPrompt(t,e){if(!this.client||this._info.status.status!=="connected"){d.warn("client not connected for getPrompt");return}return this.client.getPrompt({name:t,arguments:e}).catch(r=>{d.error("failed to get prompt",{name:t,error:r.message});})}async refreshTools(){if(!(!this.client||this._info.status.status!=="connected"))try{let t=await withTimeout(this.client.listTools(),P);this._info.tools=t.tools.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema})),d.info("tools refreshed",{id:this.id,count:this._info.tools.length});}catch(t){d.error("failed to refresh tools",{id:this.id,error:t instanceof Error?t.message:String(t)});}}async createClient(t){return t.type==="local"?this.createLocalClient(t):t.type==="remote"?this.createRemoteClient(t):null}async fetchCapabilities(){if(this.client){try{let t=await withTimeout(this.client.listTools(),P);this._info.tools=t.tools.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema}));}catch(t){d.debug("failed to get tools",{id:this.id,error:t instanceof Error?t.message:String(t)});}try{let t=await withTimeout(this.client.listResources(),5e3);this._info.resources=t.resources.map(e=>({name:e.name,uri:e.uri,description:e.description,mimeType:e.mimeType}));}catch{d.debug("failed to get resources",{id:this.id});}try{let t=await withTimeout(this.client.listPrompts(),5e3);this._info.prompts=t.prompts.map(e=>({name:e.name,description:e.description,arguments:e.arguments?.map(r=>({name:r.name,description:r.description,required:r.required}))}));}catch{d.debug("failed to get prompts",{id:this.id});}}}async createLocalClient(t){let[e,...r]=t.command;if(!e)return this._info.status={status:"failed",error:"Command is empty"},null;let o=new StdioClientTransport({stderr:"pipe",command:e,args:r.length>0?r:void 0,cwd:process.cwd(),env:Object.fromEntries(Object.entries({...process.env,...t.environment}).filter(([,n])=>n!==void 0))});o.stderr?.on("data",n=>{d.info(`mcp stderr: ${n.toString()}`,{id:this.id});});try{let n=new Client({name:"easbot-mcp",version:x()});return await withTimeout(n.connect(o),t.timeout??P),this.registerNotificationHandler(n),n}catch(n){let b=n instanceof Error?n.message:String(n);return this._info.status={status:"failed",error:b},d.error("local mcp startup failed",{command:[e,...r],error:b}),null}}async createRemoteClient(t){t.oauth===false;let r={headers:t.headers};if((t.transport||"streamable-http")==="sse"){d.info("using SSE transport",{url:t.url});let n=new SSEClientTransport(new URL(t.url),{requestInit:r});return this.connectWithTransport(n,t)}else {d.info("using StreamableHTTP transport",{url:t.url});let n=new StreamableHTTPClientTransport(new URL(t.url),{requestInit:r});return this.connectWithTransport(n,t)}}async connectWithTransport(t,e){try{let r=new Client({name:"easbot-mcp",version:x()});return await withTimeout(r.connect(t),e.timeout??P),this.registerNotificationHandler(r),r}catch(r){if(r instanceof UnauthorizedError){let o=r instanceof Error?r.message:String(r);o.includes("registration")||o.includes("client_id")?this._info.status={status:"needs_client_registration",error:"Server does not support dynamic client registration. Please provide clientId in config."}:(this._info.status={status:"needs_auth"},this.pendingTransport=t);}else {let o=r instanceof Error?r.message:String(r);this._info.status={status:"failed",error:o};}return d.error("remote mcp connection failed",{url:e.url,error:this._info.status}),null}}registerToolListChangedHandler(t){this.toolListChangedHandler=t;}registerNotificationHandler(t){let e=async()=>{d.info("tools list changed notification received",{id:this.id}),await this.refreshTools(),this.toolListChangedHandler&&await this.toolListChangedHandler();};t.setNotificationHandler(ToolListChangedNotificationSchema,e),this.notificationCleanup=()=>{t.removeNotificationHandler("notifications/tools/list_changed");};}createInitialInfo(){return {id:"",name:"",status:{status:"disconnected"},tools:[],resources:[],prompts:[]}}};function Kt(){return new A}var $t="0.2.20",Qt="@easbot/mcp";async function Xt(m){let{Log:t}=await import('./chunks/log-2GAL6FAC.mjs'),e=false;await t.init({logDir:m.logDir??process.env.EASBOT_LOG_PATH??process.cwd(),print:m.print??false,dev:m.dev??e,level:m.level??("INFO")});}export{I as HttpServerAdapter,A as MCPClient,Qt as NAME,c as ServerStatus,N as ServerTransportType,Bt as Status,E as StdioServerAdapter,$t as VERSION,B as createAndStartHttpServer,z as createAndStartStdioServer,V as createHttpServer,Kt as createMCPClient,Z as createStdioServer,x as getVersion,Xt as initLog};
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@easbot/mcp",
|
|
3
|
+
"version": "0.2.21",
|
|
4
|
+
"description": "MCP (Model Context Protocol) integration library for EASBOT ecosystem",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"ai",
|
|
19
|
+
"agent",
|
|
20
|
+
"mcp",
|
|
21
|
+
"protocol",
|
|
22
|
+
"library",
|
|
23
|
+
"typescript",
|
|
24
|
+
"integration"
|
|
25
|
+
],
|
|
26
|
+
"author": "houjallen",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/houjallen/easbot.git",
|
|
31
|
+
"directory": "packages/mcp"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/houjallen/easbot/tree/main/packages/mcp#readme",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/houjallen/easbot/issues"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"README.md",
|
|
40
|
+
"README.en.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
],
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"ai": "^6.0.176",
|
|
45
|
+
"zod": "^4.4.3",
|
|
46
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
47
|
+
"@easbot/types": "0.2.21",
|
|
48
|
+
"@easbot/utils": "0.2.21"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@biomejs/biome": "^2.4.14",
|
|
52
|
+
"@types/node": "^25.6.2",
|
|
53
|
+
"tsup": "^8.5.1",
|
|
54
|
+
"typescript": "^6.0.3",
|
|
55
|
+
"vitest": "^4.1.5"
|
|
56
|
+
},
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=22.22.3"
|
|
59
|
+
},
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"dev": "tsup --watch --env.NODE_ENV development",
|
|
65
|
+
"build": "tsup --env.NODE_ENV production",
|
|
66
|
+
"test": "vitest",
|
|
67
|
+
"test:run": "vitest run",
|
|
68
|
+
"lint": "biome check .",
|
|
69
|
+
"lint:fix": "biome check --write .",
|
|
70
|
+
"lint:report": "biome check --reporter=summary .",
|
|
71
|
+
"format": "biome format .",
|
|
72
|
+
"format:fix": "biome format --write .",
|
|
73
|
+
"type-check": "tsc --noEmit",
|
|
74
|
+
"clean": "npx rimraf dist node_modules",
|
|
75
|
+
"publish:npm": "bash scripts/publish.sh",
|
|
76
|
+
"publish:npm:win": "powershell -ExecutionPolicy Bypass -File scripts/publish.ps1"
|
|
77
|
+
}
|
|
78
|
+
}
|