@easbot/mcp 0.2.22 → 0.2.23

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/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var chunk4DCCWUIJ_cjs=require('./chunks/chunk-4DCCWUIJ.cjs'),mcp=require('@modelcontextprotocol/sdk/server/mcp'),stdio=require('@modelcontextprotocol/sdk/server/stdio'),events=require('events'),l=require('zod/v4'),z=require('http'),streamableHttp=require('@modelcontextprotocol/sdk/server/streamableHttp'),index_js=require('@modelcontextprotocol/sdk/client/index.js'),stdio_js=require('@modelcontextprotocol/sdk/client/stdio.js'),streamableHttp_js=require('@modelcontextprotocol/sdk/client/streamableHttp.js'),sse_js=require('@modelcontextprotocol/sdk/client/sse.js'),types_js=require('@modelcontextprotocol/sdk/types.js'),auth_js=require('@modelcontextprotocol/sdk/client/auth.js'),utils=require('@easbot/utils'),v=require('zod');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var l__default=/*#__PURE__*/_interopDefault(l);var z__default=/*#__PURE__*/_interopDefault(z);var v__default=/*#__PURE__*/_interopDefault(v);var H={STDIO:"stdio",HTTP:"http"},c={STOPPED:"stopped",STARTING:"starting",RUNNING:"running",STOPPING:"stopping",ERROR:"error"};var j=chunk4DCCWUIJ_cjs.b.create({service:"tool-registry"}),T={REGISTERED:"mcp.tool.registered",UNREGISTERED:"mcp.tool.unregistered",CLEARED:"mcp.tool.cleared"},x=class extends events.EventEmitter{constructor(){super();chunk4DCCWUIJ_cjs.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)){j?.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 x;var g=chunk4DCCWUIJ_cjs.b.create({service:"mcp.server.stdio"}),w=class{constructor(t){chunk4DCCWUIJ_cjs.a(this,"config");chunk4DCCWUIJ_cjs.a(this,"server",null);chunk4DCCWUIJ_cjs.a(this,"info");chunk4DCCWUIJ_cjs.a(this,"isStarting",false);chunk4DCCWUIJ_cjs.a(this,"isStopping",false);chunk4DCCWUIJ_cjs.a(this,"toolEventCleanup",null);chunk4DCCWUIJ_cjs.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__default.default.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__default.default.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__default.default.object(u)}if(e.type==="string")return l__default.default.string();if(e.type==="number")return l__default.default.number();if(e.type==="boolean")return l__default.default.boolean();if(e.type==="array"){let r=e.items;return r?l__default.default.array(this.jsonSchemaToZod(r)):l__default.default.array(l__default.default.unknown())}}return l__default.default.unknown()}jsonSchemaToZod(t){switch(t.type){case "string":return l__default.default.string();case "number":return l__default.default.number();case "integer":return l__default.default.number().int();case "boolean":return l__default.default.boolean();case "null":return l__default.default.null();case "array":{let r=t.items;return r?l__default.default.array(this.jsonSchemaToZod(r)):l__default.default.array(l__default.default.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__default.default.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__default.default.object(u)}default:return l__default.default.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 stdio.StdioServerTransport;await t.start(),this.server=new mcp.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 L(m){return new w(m)}async function Z(m){let t=new w(m);return await t.start(),t.createInstance()}var h=chunk4DCCWUIJ_cjs.b.create({service:"mcp.server.http"}),E=class{constructor(t){chunk4DCCWUIJ_cjs.a(this,"config");chunk4DCCWUIJ_cjs.a(this,"server",null);chunk4DCCWUIJ_cjs.a(this,"transport",null);chunk4DCCWUIJ_cjs.a(this,"httpServer",null);chunk4DCCWUIJ_cjs.a(this,"info");chunk4DCCWUIJ_cjs.a(this,"isStarting",false);chunk4DCCWUIJ_cjs.a(this,"isStopping",false);chunk4DCCWUIJ_cjs.a(this,"toolCleanup",null);chunk4DCCWUIJ_cjs.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__default.default.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__default.default.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__default.default.object(u)}if(e.type==="string")return l__default.default.string();if(e.type==="number")return l__default.default.number();if(e.type==="boolean")return l__default.default.boolean();if(e.type==="array"){let r=e.items;return r?l__default.default.array(this.jsonSchemaToZod(r)):l__default.default.array(l__default.default.unknown())}}return l__default.default.unknown()}jsonSchemaToZod(t){switch(t.type){case "string":return l__default.default.string();case "number":return l__default.default.number();case "integer":return l__default.default.number().int();case "boolean":return l__default.default.boolean();case "null":return l__default.default.null();case "array":{let r=t.items;return r?l__default.default.array(this.jsonSchemaToZod(r)):l__default.default.array(l__default.default.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__default.default.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__default.default.object(u)}default:return l__default.default.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 streamableHttp.StreamableHTTPServerTransport({sessionIdGenerator:()=>crypto.randomUUID()}),this.server=new mcp.McpServer({name:this.config.name,version:this.config.version}),this.loadTools(),this.subscribeTools(),await this.server.connect(this.transport),this.httpServer=z__default.default.createServer((o,n)=>{let b=o.headers.origin,u=(f,a,A)=>{n.writeHead(f,a),A?n.end(A):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
1
+ 'use strict';var chunk4DCCWUIJ_cjs=require('./chunks/chunk-4DCCWUIJ.cjs'),mcp_js=require('@modelcontextprotocol/sdk/server/mcp.js'),stdio_js=require('@modelcontextprotocol/sdk/server/stdio.js'),events=require('events'),d=require('zod/v4'),z=require('http'),streamableHttp_js=require('@modelcontextprotocol/sdk/server/streamableHttp.js'),index_js=require('@modelcontextprotocol/sdk/client/index.js'),stdio_js$1=require('@modelcontextprotocol/sdk/client/stdio.js'),streamableHttp_js$1=require('@modelcontextprotocol/sdk/client/streamableHttp.js'),sse_js=require('@modelcontextprotocol/sdk/client/sse.js'),types_js=require('@modelcontextprotocol/sdk/types.js'),auth_js=require('@modelcontextprotocol/sdk/client/auth.js'),utils=require('@easbot/utils'),v=require('zod');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var d__default=/*#__PURE__*/_interopDefault(d);var z__default=/*#__PURE__*/_interopDefault(z);var v__default=/*#__PURE__*/_interopDefault(v);var I={STDIO:"stdio",HTTP:"http"},l={STOPPED:"stopped",STARTING:"starting",RUNNING:"running",STOPPING:"stopping",ERROR:"error"};var N=chunk4DCCWUIJ_cjs.b.create({service:"tool-registry"}),b={REGISTERED:"mcp.tool.registered",UNREGISTERED:"mcp.tool.unregistered",CLEARED:"mcp.tool.cleared"},A=class extends events.EventEmitter{constructor(){super();chunk4DCCWUIJ_cjs.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)){N?.debug("tool already registered, skipping",{tool:e.name});return}this.tools.set(e.name,e),this.emit(b.REGISTERED,e);}unregister(e){return this.tools.has(e)?(this.tools.delete(e),this.emit(b.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(b.CLEARED);}},C=new A;var S=chunk4DCCWUIJ_cjs.b.create({service:"mcp.server.stdio"}),R=class{constructor(t){chunk4DCCWUIJ_cjs.a(this,"config");chunk4DCCWUIJ_cjs.a(this,"server",null);chunk4DCCWUIJ_cjs.a(this,"info");chunk4DCCWUIJ_cjs.a(this,"isStarting",false);chunk4DCCWUIJ_cjs.a(this,"isStopping",false);chunk4DCCWUIJ_cjs.a(this,"toolEventCleanup",null);chunk4DCCWUIJ_cjs.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),S.info("tool registered",{tool:t.name});}});this.config=t,this.info={id:t.id,name:t.name,version:t.version,transportType:t.transportType,status:l.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 C.getAll()){let e=this.convertToZodSchema(t.inputSchema),r=this.adaptToolHandler(t.handler);this.server.registerTool(t.name,{description:t.description,inputSchema:e},r),S.info("tool loaded",{tool:t.name});}}subscribeToolEvents(){this.toolEventCleanup=()=>{C.off(b.REGISTERED,this.handleToolRegistered);},C.on(b.REGISTERED,this.handleToolRegistered);}adaptToolHandler(t){return async(e,r)=>{let n={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,n)}}unsubscribeToolEvents(){this.toolEventCleanup&&(this.toolEventCleanup(),this.toolEventCleanup=null);}convertToZodSchema(t){if(t instanceof d__default.default.ZodType)return t;if(typeof t=="object"&&t!==null){let e=t;if(e.type==="object"){let r=e.properties||{},n=e.required||[],o={};for(let[i,h]of Object.entries(r))o[i]=this.jsonSchemaToZod(h);if(Object.keys(r).filter(i=>!n.includes(i)).length===0)return d__default.default.object(o);let f={};for(let[i,h]of Object.entries(r)){let c=o[i];c&&(n.includes(i)?f[i]=c:f[i]=c.optional());}return d__default.default.object(f)}if(e.type==="string")return d__default.default.string();if(e.type==="number")return d__default.default.number();if(e.type==="boolean")return d__default.default.boolean();if(e.type==="array"){let r=e.items;return r?d__default.default.array(this.jsonSchemaToZod(r)):d__default.default.array(d__default.default.unknown())}}return d__default.default.unknown()}jsonSchemaToZod(t){switch(t.type){case "string":return d__default.default.string();case "number":return d__default.default.number();case "integer":return d__default.default.number().int();case "boolean":return d__default.default.boolean();case "null":return d__default.default.null();case "array":{let r=t.items;return r?d__default.default.array(this.jsonSchemaToZod(r)):d__default.default.array(d__default.default.unknown())}case "object":{let r=t.properties||{},n=t.required||[],o={};for(let[i,h]of Object.entries(r))o[i]=this.jsonSchemaToZod(h);if(Object.keys(r).filter(i=>!n.includes(i)).length===0)return d__default.default.object(o);let f={};for(let[i,h]of Object.entries(r)){let c=o[i];c&&(n.includes(i)?f[i]=c:f[i]=c.optional());}return d__default.default.object(f)}default:return d__default.default.unknown()}}async start(){if(this.isStarting){S.warn("server is already starting",{id:this.info.id});return}if(this.info.status===l.RUNNING){S.debug("server is already running",{id:this.info.id});return}this.isStarting=true,this.info.status=l.STARTING;try{S.info("starting stdio mcp server",{id:this.info.id,name:this.info.name,command:this.config.command,args:this.config.args});let t=new stdio_js.StdioServerTransport;this.server=new mcp_js.McpServer({name:this.config.name,version:this.config.version}),this.loadTools(),this.subscribeToolEvents(),await this.server.connect(t),this.info.status=l.RUNNING,this.info.lastActivityAt=Date.now(),S.info("stdio mcp server started successfully",{id:this.info.id,name:this.info.name,toolCount:C.getSize()});}catch(t){throw this.info.status=l.ERROR,S.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){S.warn("server is already stopping",{id:this.info.id});return}if(this.info.status!==l.RUNNING&&this.info.status!==l.ERROR){S.debug("server is not running",{id:this.info.id,status:this.info.status});return}this.isStopping=true,this.info.status=l.STOPPING;try{S.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=l.STOPPED,S.info("stdio mcp server stopped",{id:this.info.id,name:this.info.name});}catch(t){this.info.status=l.ERROR,S.error("error stopping stdio mcp server",{id:this.info.id,error:t instanceof Error?t.message:String(t)});}finally{this.isStopping=false;}}async restart(){S.info("restarting stdio mcp server",{id:this.info.id}),await this.stop(),await this.start();}};function U(s){return new R(s)}async function Z(s){let t=new R(s);return await t.start(),t.createInstance()}var g=chunk4DCCWUIJ_cjs.b.create({service:"mcp.server.http"}),w=class{constructor(t){chunk4DCCWUIJ_cjs.a(this,"config");chunk4DCCWUIJ_cjs.a(this,"server",null);chunk4DCCWUIJ_cjs.a(this,"transport",null);chunk4DCCWUIJ_cjs.a(this,"httpServer",null);chunk4DCCWUIJ_cjs.a(this,"info");chunk4DCCWUIJ_cjs.a(this,"isStarting",false);chunk4DCCWUIJ_cjs.a(this,"isStopping",false);chunk4DCCWUIJ_cjs.a(this,"toolCleanup",null);chunk4DCCWUIJ_cjs.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),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:l.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 C.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});}}subscribeTools(){this.toolCleanup=()=>{C.off(b.REGISTERED,this.handleTool);},C.on(b.REGISTERED,this.handleTool);}convertToZodSchema(t){if(t instanceof d__default.default.ZodType)return t;if(typeof t=="object"&&t!==null){let e=t;if(e.type==="object"){let r=e.properties||{},n=e.required||[],o={};for(let[i,h]of Object.entries(r))o[i]=this.jsonSchemaToZod(h);if(Object.keys(r).filter(i=>!n.includes(i)).length===0)return d__default.default.object(o);let f={};for(let[i,h]of Object.entries(r)){let c=o[i];c&&(n.includes(i)?f[i]=c:f[i]=c.optional());}return d__default.default.object(f)}if(e.type==="string")return d__default.default.string();if(e.type==="number")return d__default.default.number();if(e.type==="boolean")return d__default.default.boolean();if(e.type==="array"){let r=e.items;return r?d__default.default.array(this.jsonSchemaToZod(r)):d__default.default.array(d__default.default.unknown())}}return d__default.default.unknown()}jsonSchemaToZod(t){switch(t.type){case "string":return d__default.default.string();case "number":return d__default.default.number();case "integer":return d__default.default.number().int();case "boolean":return d__default.default.boolean();case "null":return d__default.default.null();case "array":{let r=t.items;return r?d__default.default.array(this.jsonSchemaToZod(r)):d__default.default.array(d__default.default.unknown())}case "object":{let r=t.properties||{},n=t.required||[],o={};for(let[i,h]of Object.entries(r))o[i]=this.jsonSchemaToZod(h);if(Object.keys(r).filter(i=>!n.includes(i)).length===0)return d__default.default.object(o);let f={};for(let[i,h]of Object.entries(r)){let c=o[i];c&&(n.includes(i)?f[i]=c:f[i]=c.optional());}return d__default.default.object(f)}default:return d__default.default.unknown()}}adaptToolHandler(t){return async(e,r)=>{let n={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,n)}}unsubscribeTools(){this.toolCleanup&&(this.toolCleanup(),this.toolCleanup=null);}async start(){if(this.isStarting){g.warn("already starting",{id:this.info.id});return}if(this.info.status===l.RUNNING){g.debug("already running",{id:this.info.id});return}this.isStarting=true,this.info.status=l.STARTING;try{g.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 streamableHttp_js.StreamableHTTPServerTransport({sessionIdGenerator:()=>crypto.randomUUID()}),this.server=new mcp_js.McpServer({name:this.config.name,version:this.config.version}),this.loadTools(),this.subscribeTools(),await this.server.connect(this.transport),this.httpServer=z__default.default.createServer((n,o)=>{let m=n.headers.origin,f=(h,c,k)=>{o.writeHead(h,c),k?o.end(k):o.end();},i={"Access-Control-Allow-Origin":m||"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, mcpsessionid, mcp-protocol-version","Access-Control-Max-Age":"86400"};if(n.method==="OPTIONS"){f(204,i);return}if(n.method==="POST"){let h="";n.setEncoding("utf8"),n.on("data",c=>{h+=c;}),n.on("end",()=>{let c;if(h)try{c=JSON.parse(h);}catch{c=void 0;}this.transport&&this.transport.handleRequest(n,o,c);}),n.on("error",c=>{g.error("HTTP request error",{error:c.message}),f(500,i,JSON.stringify({jsonrpc:"2.0",error:{code:-32603,message:"Internal error"}}));});}else n.method==="GET"?this.transport&&this.transport.handleRequest(n,o,void 0):f(405,i,JSON.stringify({jsonrpc:"2.0",error:{code:-32601,message:"Method not found"}}));}),this.httpServer.on("error",n=>{g.error("HTTP server error",{error:n.message}),this.info.status=l.ERROR;}),this.httpServer.on("clientError",(n,o)=>{g.warn("HTTP client error",{error:n.message}),o.writable&&o.end(`HTTP/1.1 400 Bad Request\r
2
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 U(m){return new E(m)}async function V(m){let t=new E(m);return await t.start(),t.createInstance()}var M={version:"0.2.22"};function P(){return M.version}var d=chunk4DCCWUIJ_cjs.b.create({service:"mcp.client"}),I=3e4,Vt=v__default.default.discriminatedUnion("status",[v__default.default.object({status:v__default.default.literal("connected")}).meta({ref:"MCPStatusConnected"}),v__default.default.object({status:v__default.default.literal("disconnected")}).meta({ref:"MCPStatusDisconnected"}),v__default.default.object({status:v__default.default.literal("failed"),error:v__default.default.string()}).meta({ref:"MCPStatusFailed"}),v__default.default.object({status:v__default.default.literal("needs_auth")}).meta({ref:"MCPStatusNeedsAuth"}),v__default.default.object({status:v__default.default.literal("needs_client_registration"),error:v__default.default.string()}).meta({ref:"MCPStatusNeedsClientRegistration"})]),k=class{constructor(){chunk4DCCWUIJ_cjs.a(this,"id","");chunk4DCCWUIJ_cjs.a(this,"client",null);chunk4DCCWUIJ_cjs.a(this,"_info");chunk4DCCWUIJ_cjs.a(this,"notificationCleanup",null);chunk4DCCWUIJ_cjs.a(this,"pendingTransport",null);chunk4DCCWUIJ_cjs.a(this,"oauthState","");chunk4DCCWUIJ_cjs.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 utils.withTimeout(this.client.callTool({name:t,arguments:e},types_js.CallToolResultSchema,{resetTimeoutOnProgress:!0,timeout:r}),r??I);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 utils.withTimeout(this.client.listTools(),I);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 utils.withTimeout(this.client.listTools(),I);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 utils.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 utils.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 stdio_js.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 index_js.Client({name:"easbot-mcp",version:P()});return await utils.withTimeout(n.connect(o),t.timeout??I),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 sse_js.SSEClientTransport(new URL(t.url),{requestInit:r});return this.connectWithTransport(n,t)}else {d.info("using StreamableHTTP transport",{url:t.url});let n=new streamableHttp_js.StreamableHTTPClientTransport(new URL(t.url),{requestInit:r});return this.connectWithTransport(n,t)}}async connectWithTransport(t,e){try{let r=new index_js.Client({name:"easbot-mcp",version:P()});return await utils.withTimeout(r.connect(t),e.timeout??I),this.registerNotificationHandler(r),r}catch(r){if(r instanceof auth_js.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(types_js.ToolListChangedNotificationSchema,e),this.notificationCleanup=()=>{t.removeNotificationHandler("notifications/tools/list_changed");};}createInitialInfo(){return {id:"",name:"",status:{status:"disconnected"},tools:[],resources:[],prompts:[]}}};function Bt(){return new k}var Wt="0.2.20",$t="@easbot/mcp";async function Qt(m){let{Log:t}=await import('./chunks/log-WXSBDTHF.cjs'),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")});}Object.defineProperty(exports,"Log",{enumerable:true,get:function(){return chunk4DCCWUIJ_cjs.b}});exports.HttpServerAdapter=E;exports.MCPClient=k;exports.NAME=$t;exports.ServerStatus=c;exports.ServerTransportType=H;exports.Status=Vt;exports.StdioServerAdapter=w;exports.VERSION=Wt;exports.createAndStartHttpServer=V;exports.createAndStartStdioServer=Z;exports.createHttpServer=U;exports.createMCPClient=Bt;exports.createStdioServer=L;exports.getVersion=P;exports.initLog=Qt;
3
+ `);}),this.httpServer.listen(e,r),g.info("HTTP server listening",{hostname:r,port:e}),this.info.status=l.RUNNING,this.info.lastActivityAt=Date.now(),g.info("started",{id:this.info.id,name:this.info.name,toolCount:C.getSize()});}catch(t){throw this.info.status=l.ERROR,g.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){g.warn("already stopping",{id:this.info.id});return}if(this.info.status!==l.RUNNING&&this.info.status!==l.ERROR){g.debug("not running",{id:this.info.id,status:this.info.status});return}this.isStopping=true,this.info.status=l.STOPPING;try{g.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=l.STOPPED,g.info("stopped",{id:this.info.id});}catch(t){this.info.status=l.ERROR,g.error("failed to stop",{id:this.info.id,error:t instanceof Error?t.message:String(t)});}finally{this.isStopping=false;}}async restart(){g.info("restarting",{id:this.info.id}),await this.stop(),await this.start();}};function V(s){return new w(s)}async function F(s){let t=new w(s);return await t.start(),t.createInstance()}var H={version:"0.2.23"};function E(){return H.version}var O=chunk4DCCWUIJ_cjs.b.create({service:"mcp.server.factory"});function K(s){return s.type==="local"}function $(s){return s.type==="remote"}function J(s,t){if(!t.command)throw new Error(`MCP server ${s} has no command specified`);return {id:s,name:s,version:"1.0.0",transportType:I.STDIO,enabled:t.enabled,timeout:t.timeout,command:t.command,args:t.args?.length?t.args:void 0,env:t.env}}function W(s,t){return {id:s,name:s,version:"1.0.0",transportType:I.HTTP,enabled:t.enabled,timeout:t.timeout,url:t.url,headers:t.headers}}async function Q(s,t){if(O.debug("creating server from config",{name:s,type:t.type}),K(t)){let e=J(s,t),r=new R(e);return await r.start(),r.createInstance()}if($(t)){let e=W(s,t),r=new w(e);return await r.start(),r.createInstance()}throw new Error(`Unsupported MCP config type: ${t.type}`)}async function Zt(s){let t={};for(let[e,r]of Object.entries(s))try{let n=await Q(e,r);t[e]=n;}catch(n){O.error("failed to create server from config",{name:e,error:n instanceof Error?n.message:String(n)});}return t}var p=chunk4DCCWUIJ_cjs.b.create({service:"mcp.client"}),x=3e4,M=class{constructor(){chunk4DCCWUIJ_cjs.a(this,"id","");chunk4DCCWUIJ_cjs.a(this,"client",null);chunk4DCCWUIJ_cjs.a(this,"_info");chunk4DCCWUIJ_cjs.a(this,"notificationCleanup",null);chunk4DCCWUIJ_cjs.a(this,"pendingTransport",null);chunk4DCCWUIJ_cjs.a(this,"oauthState","");chunk4DCCWUIJ_cjs.a(this,"capturedRedirectUrl",null);chunk4DCCWUIJ_cjs.a(this,"oauthConfig");chunk4DCCWUIJ_cjs.a(this,"toolListChangedHandler",null);chunk4DCCWUIJ_cjs.a(this,"oauthProvider",null);this._info=this.createInitialInfo();}get info(){return {...this._info}}get status(){return this._info.status}get tools(){return [...this._info.tools]}get resources(){return [...this._info.resources]}get prompts(){return [...this._info.prompts]}get clientId(){return this.id}setToolListChangedHandler(t){this.toolListChangedHandler=t;}setOAuthProvider(t){this.oauthProvider=t;}async connect(t,e){p.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(e.type==="remote"&&(this.oauthConfig=e.oauth===!1?void 0:e.oauth??{}),this.client=await this.createClient(e),!this.client)return;this._info.status={status:"connected"},this._info.connectedAt=Date.now(),await this.fetchCapabilities(),p.info("connected to MCP server",{id:t,toolCount:this._info.tools.length});}catch(r){let n=r instanceof Error?r.message:String(r);this._info.status={status:"failed",error:n},this._info.error=n,p.error("failed to connect to MCP server",{id:t,error:n});}}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(""),this.oauthProvider&&await this.oauthProvider.saveState(this.oauthState),{authorizationUrl:this.capturedRedirectUrl?.toString()??"",state:this.oauthState}}async finishAuth(t){if(!this.pendingTransport)throw new Error("No pending OAuth flow.");try{await this.pendingTransport.finishAuth?.(t);}catch(e){throw p.error("failed to finish OAuth",{id:this.id,error:e}),e}this.pendingTransport=null,this.capturedRedirectUrl=null,p.info("OAuth completed, ready to reconnect",{id:this.id});}isAuthRequired(){return this._info.status.status==="needs_auth"}isClientRegistrationRequired(){return this._info.status.status==="needs_client_registration"}getPendingTransport(){return this.pendingTransport}getAuthorizationUrl(){return this.capturedRedirectUrl?.toString()??""}async disconnect(){this.notificationCleanup&&(this.notificationCleanup(),this.notificationCleanup=null),this.client&&(await this.client.close().catch(t=>{p.error("Failed to close MCP client",{id:this.id,error:t});}),this.client=null),this.pendingTransport=null,this.capturedRedirectUrl=null,this.toolListChangedHandler=null,this._info.status.status==="connected"&&(this._info.status={status:"disconnected"}),p.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 n=Date.now();if(!this.client||this._info.status.status!=="connected")return {toolName:t,args:e,content:[],success:false,error:"Client not connected",duration:Date.now()-n};try{let o=await utils.withTimeout(this.client.callTool({name:t,arguments:e},types_js.CallToolResultSchema,{resetTimeoutOnProgress:!0,timeout:r}),r??x);return {toolName:t,args:e,content:o.content.map(m=>m.type==="text"?{type:"text",text:m.text}:m.type==="image"?{type:"image",data:m.data,mimeType:m.mimeType}:m.type==="resource"?{type:"resource",resource:m.resource}:{type:"text",text:String(m)}),success:!0,duration:Date.now()-n,metadata:o.metadata}}catch(o){return {toolName:t,args:e,content:[],success:false,error:o instanceof Error?o.message:String(o),duration:Date.now()-n}}}async listResources(){return [...this._info.resources]}async readResource(t){if(!this.client||this._info.status.status!=="connected"){p.warn("client not connected for readResource",{id:this.id});return}return this.client.readResource({uri:t}).catch(e=>{p.error("failed to read resource",{id:this.id,uri:t,error:e.message});})}async listPrompts(){return [...this._info.prompts]}async getPrompt(t,e){if(!this.client||this._info.status.status!=="connected"){p.warn("client not connected for getPrompt",{id:this.id});return}return this.client.getPrompt({name:t,arguments:e}).catch(r=>{p.error("failed to get prompt",{id:this.id,name:t,error:r.message});})}async refreshTools(){if(!(!this.client||this._info.status.status!=="connected"))try{let t=await utils.withTimeout(this.client.listTools(),x);this._info.tools=t.tools.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema})),p.info("tools refreshed",{id:this.id,count:this._info.tools.length});}catch(t){p.error("failed to refresh tools",{id:this.id,error:t instanceof Error?t.message:String(t)});}}async createClient(t){return t.type==="local"?await this.createLocalClient(t):t.type==="remote"?await this.createRemoteClient(t):null}async fetchCapabilities(){if(this.client){try{let t=await utils.withTimeout(this.client.listTools(),x);this._info.tools=t.tools.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema}));}catch(t){p.debug("failed to get tools",{id:this.id,error:t instanceof Error?t.message:String(t)});}try{let t=await utils.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{p.debug("failed to get resources",{id:this.id});}try{let t=await utils.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{p.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 n=new stdio_js$1.StdioClientTransport({stderr:"pipe",command:e,args:r.length>0?r:void 0,cwd:t.cwd??process.cwd(),env:Object.fromEntries(Object.entries({...process.env,...t.environment}).filter(([,o])=>o!==void 0))});n.stderr?.on("data",o=>{p.info(`mcp stderr: ${o.toString()}`,{id:this.id});});try{let o=new index_js.Client({name:"easbot-mcp",version:E()});return await utils.withTimeout(o.connect(n),t.timeout??x),this.registerNotificationHandler(o),o}catch(o){let m=o instanceof Error?o.message:String(o);return this._info.status={status:"failed",error:m},p.error("local mcp startup failed",{id:this.id,command:[e,...r],error:m}),null}}async createRemoteClient(t){let e={headers:t.headers};if((t.transport||"streamable-http")==="sse"){p.info("using SSE transport",{id:this.id,url:t.url});let n=new sse_js.SSEClientTransport(new URL(t.url),{requestInit:e});return await this.connectWithTransport(n,t)}else {p.info("using StreamableHTTP transport",{id:this.id,url:t.url});let n=new streamableHttp_js$1.StreamableHTTPClientTransport(new URL(t.url),{requestInit:e});return await this.connectWithTransport(n,t)}}async connectWithTransport(t,e){try{let r=new index_js.Client({name:"easbot-mcp",version:E()});return await r.connect(t),this.registerNotificationHandler(r),r}catch(r){return this.handleConnectionError(r,t,e),null}}handleConnectionError(t,e,r){if(t instanceof auth_js.UnauthorizedError){let n=t instanceof Error?t.message:String(t);n.includes("registration")||n.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=e,this.capturedRedirectUrl=this.extractRedirectUrl(t));}else {let n=t instanceof Error?t.message:String(t);this._info.status={status:"failed",error:n};}p.error("remote mcp connection failed",{id:this.id,url:r.url,status:this._info.status});}extractRedirectUrl(t){let r=t.message.match(/https?:\/\/[^\s]+/);if(r)try{return new URL(r[0])}catch{return null}return null}registerNotificationHandler(t){let e=async()=>{p.info("tools list changed notification received",{id:this.id}),await this.refreshTools(),this.toolListChangedHandler&&await this.toolListChangedHandler();};t.setNotificationHandler(types_js.ToolListChangedNotificationSchema,e),this.notificationCleanup=()=>{t.removeNotificationHandler("notifications/tools/list_changed");};}createInitialInfo(){return {id:"",name:"",status:{status:"disconnected"},tools:[],resources:[],prompts:[]}}};function ot(){return new M}var ce=v__default.default.discriminatedUnion("status",[v__default.default.object({status:v__default.default.literal("connected")}).meta({ref:"MCPStatusConnected"}),v__default.default.object({status:v__default.default.literal("disconnected")}).meta({ref:"MCPStatusDisconnected"}),v__default.default.object({status:v__default.default.literal("failed"),error:v__default.default.string()}).meta({ref:"MCPStatusFailed"}),v__default.default.object({status:v__default.default.literal("needs_auth")}).meta({ref:"MCPStatusNeedsAuth"}),v__default.default.object({status:v__default.default.literal("needs_client_registration"),error:v__default.default.string()}).meta({ref:"MCPStatusNeedsClientRegistration"}),v__default.default.object({status:v__default.default.literal("disabled")}).meta({ref:"MCPStatusDisabled"})]);var he="@easbot/mcp";async function ge(s){let{Log:t}=await import('./chunks/log-WXSBDTHF.cjs'),e=false;await t.init({logDir:s.logDir??process.env.EASBOT_LOG_PATH??process.cwd(),print:s.print??false,dev:s.dev??e,level:s.level??("INFO")});}exports.HttpServerAdapter=w;exports.MCPClient=M;exports.NAME=he;exports.ServerStatus=l;exports.ServerTransportType=I;exports.Status=ce;exports.StdioServerAdapter=R;exports.ToolRegistry=A;exports.ToolRegistryEvent=b;exports.createAndStartHttpServer=F;exports.createAndStartStdioServer=Z;exports.createHttpServer=V;exports.createMCPClient=ot;exports.createServerFromConfig=Q;exports.createServersFromConfigMap=Zt;exports.createStdioServer=U;exports.getVersion=E;exports.initLog=ge;exports.tools=C;
package/dist/index.d.cts CHANGED
@@ -1,12 +1,18 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp';
2
- import z from 'zod';
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
4
+ import z, { ZodType } from 'zod';
5
+ import { EventEmitter } from 'node:events';
6
+ import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
3
7
 
4
8
  interface McpLocalConfig {
5
9
  type: 'local';
6
- command: string[];
7
- environment?: Record<string, string>;
10
+ command: string;
11
+ args?: string[];
12
+ env?: Record<string, string>;
8
13
  enabled?: boolean;
9
14
  timeout?: number;
15
+ description?: string;
10
16
  }
11
17
  interface McpOAuthConfig {
12
18
  clientId?: string;
@@ -20,6 +26,7 @@ interface McpRemoteConfig {
20
26
  headers?: Record<string, string>;
21
27
  oauth?: McpOAuthConfig | false;
22
28
  timeout?: number;
29
+ description?: string;
23
30
  }
24
31
  type McpConfig = McpLocalConfig | McpRemoteConfig;
25
32
  declare const ServerTransportType: {
@@ -50,7 +57,7 @@ interface StdioServerConfig {
50
57
  name: string;
51
58
  version: string;
52
59
  transportType: typeof ServerTransportType.STDIO;
53
- command: string;
60
+ command?: string;
54
61
  args?: string[];
55
62
  env?: Record<string, string>;
56
63
  cwd?: string;
@@ -141,6 +148,9 @@ declare class HttpServerAdapter {
141
148
  declare function createHttpServer(config: HttpServerConfig): HttpServerAdapter;
142
149
  declare function createAndStartHttpServer(config: HttpServerConfig): Promise<ServerInstance>;
143
150
 
151
+ declare function createServerFromConfig(name: string, config: McpConfig): Promise<ServerInstance$2>;
152
+ declare function createServersFromConfigMap(configs: Record<string, McpConfig>): Promise<Record<string, ServerInstance$2>>;
153
+
144
154
  interface OAuthConfig {
145
155
  clientId?: string;
146
156
  clientSecret?: string;
@@ -150,6 +160,7 @@ interface OAuthConfig {
150
160
  interface LocalMCPConfig {
151
161
  type: 'local';
152
162
  command: string[];
163
+ cwd?: string;
153
164
  environment?: Record<string, string>;
154
165
  timeout?: number;
155
166
  }
@@ -162,6 +173,7 @@ interface RemoteMCPConfig {
162
173
  timeout?: number;
163
174
  }
164
175
  type MCPConfig = LocalMCPConfig | RemoteMCPConfig;
176
+ type ToolListChangedHandler = () => void | Promise<void>;
165
177
  declare const Status: z.ZodDiscriminatedUnion<[z.ZodObject<{
166
178
  status: z.ZodLiteral<"connected">;
167
179
  }, z.core.$strip>, z.ZodObject<{
@@ -174,6 +186,8 @@ declare const Status: z.ZodDiscriminatedUnion<[z.ZodObject<{
174
186
  }, z.core.$strip>, z.ZodObject<{
175
187
  status: z.ZodLiteral<"needs_client_registration">;
176
188
  error: z.ZodString;
189
+ }, z.core.$strip>, z.ZodObject<{
190
+ status: z.ZodLiteral<"disabled">;
177
191
  }, z.core.$strip>], "status">;
178
192
  type Status = z.infer<typeof Status>;
179
193
  interface ToolMetadata {
@@ -196,6 +210,60 @@ interface PromptMetadata {
196
210
  required?: boolean;
197
211
  }>;
198
212
  }
213
+ interface ToolContentItem {
214
+ type: 'text' | 'image' | 'resource';
215
+ text?: string;
216
+ data?: string;
217
+ mimeType?: string;
218
+ resource?: {
219
+ uri: string;
220
+ mimeType?: string;
221
+ blob?: string;
222
+ text?: string;
223
+ };
224
+ }
225
+ interface ToolCallResult {
226
+ toolName: string;
227
+ args: Record<string, unknown>;
228
+ content: ToolContentItem[];
229
+ success: boolean;
230
+ error?: string;
231
+ duration: number;
232
+ metadata?: Record<string, unknown>;
233
+ }
234
+ interface AuthResult {
235
+ authorizationUrl: string;
236
+ state: string;
237
+ }
238
+ interface OAuthClientProviderAdapter {
239
+ saveState(state: string): Promise<void>;
240
+ getState(): Promise<string | undefined>;
241
+ clearState(): Promise<void>;
242
+ saveCodeVerifier(verifier: string): Promise<void>;
243
+ getCodeVerifier(): Promise<string | undefined>;
244
+ saveClientInfo(info: {
245
+ clientId: string;
246
+ clientSecret?: string;
247
+ clientIdIssuedAt?: number;
248
+ clientSecretExpiresAt?: number;
249
+ }): Promise<void>;
250
+ getClientInfo(): Promise<{
251
+ clientId: string;
252
+ clientSecret?: string;
253
+ } | undefined>;
254
+ saveTokens(tokens: {
255
+ accessToken: string;
256
+ refreshToken?: string;
257
+ expiresAt?: number;
258
+ scope?: string;
259
+ }): Promise<void>;
260
+ getTokens(): Promise<{
261
+ accessToken: string;
262
+ refreshToken?: string;
263
+ expiresAt?: number;
264
+ scope?: string;
265
+ } | undefined>;
266
+ }
199
267
  interface ClientInfo {
200
268
  id: string;
201
269
  name: string;
@@ -208,18 +276,7 @@ interface ClientInfo {
208
276
  prompts: PromptMetadata[];
209
277
  error?: string;
210
278
  }
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
- }
279
+
223
280
  declare class MCPClient {
224
281
  private id;
225
282
  private client;
@@ -227,14 +284,26 @@ declare class MCPClient {
227
284
  private notificationCleanup;
228
285
  private pendingTransport;
229
286
  private oauthState;
287
+ private capturedRedirectUrl;
288
+ private oauthConfig;
230
289
  private toolListChangedHandler;
290
+ private oauthProvider;
231
291
  constructor();
232
292
  get info(): ClientInfo;
233
293
  get status(): Status;
234
294
  get tools(): ToolMetadata[];
295
+ get resources(): ResourceMetadata[];
296
+ get prompts(): PromptMetadata[];
297
+ get clientId(): string;
298
+ setToolListChangedHandler(handler: ToolListChangedHandler | null): void;
299
+ setOAuthProvider(provider: OAuthClientProviderAdapter | null): void;
235
300
  connect(id: string, config: MCPConfig): Promise<void>;
236
301
  startAuth(): Promise<AuthResult>;
237
- finishAuth(authorizationCode?: string): Promise<void>;
302
+ finishAuth(authorizationCode: string): Promise<void>;
303
+ isAuthRequired(): boolean;
304
+ isClientRegistrationRequired(): boolean;
305
+ getPendingTransport(): StreamableHTTPClientTransport | SSEClientTransport | null;
306
+ getAuthorizationUrl(): string;
238
307
  disconnect(): Promise<void>;
239
308
  listTools(): Promise<Record<string, unknown>>;
240
309
  callTool(toolName: string, args: Record<string, unknown>, timeout?: number): Promise<ToolCallResult>;
@@ -352,57 +421,60 @@ declare class MCPClient {
352
421
  private createLocalClient;
353
422
  private createRemoteClient;
354
423
  private connectWithTransport;
355
- registerToolListChangedHandler(handler: () => void | Promise<void>): void;
424
+ private handleConnectionError;
425
+ private extractRedirectUrl;
356
426
  private registerNotificationHandler;
357
427
  private createInitialInfo;
358
428
  }
359
429
  declare function createMCPClient(): MCPClient;
360
430
 
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
- };
431
+ type ToolInputSchema = ZodType | Record<string, unknown>;
432
+ type RequestId = string | number;
433
+ interface ToolContext {
434
+ signal?: AbortSignal;
435
+ sessionId?: string;
436
+ requestId: RequestId;
437
+ taskId?: string;
438
+ _meta?: Record<string, unknown>;
439
+ authInfo?: {
440
+ type: string;
441
+ claims?: Record<string, unknown>;
381
442
  };
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
443
  }
444
+ type ToolHandler = (args: unknown, ctx: ToolContext) => Promise<CallToolResult>;
445
+ interface ToolDefinition extends Omit<Tool, 'inputSchema'> {
446
+ inputSchema?: ToolInputSchema;
447
+ handler: ToolHandler;
448
+ }
449
+ declare const ToolRegistryEvent: {
450
+ readonly REGISTERED: "mcp.tool.registered";
451
+ readonly UNREGISTERED: "mcp.tool.unregistered";
452
+ readonly CLEARED: "mcp.tool.cleared";
453
+ };
454
+ type ToolRegistryEvent = (typeof ToolRegistryEvent)[keyof typeof ToolRegistryEvent];
455
+ declare class ToolRegistry extends EventEmitter {
456
+ private tools;
457
+ constructor();
458
+ register(tool: ToolDefinition): void;
459
+ unregister(name: string): boolean;
460
+ get(name: string): ToolDefinition | undefined;
461
+ getAll(): ToolDefinition[];
462
+ getTools(): Omit<ToolDefinition, 'handler'>[];
463
+ has(name: string): boolean;
464
+ getSize(): number;
465
+ clear(): void;
466
+ }
467
+ declare const tools: ToolRegistry;
395
468
 
396
469
  declare function getVersion(): string;
397
470
 
398
- declare const VERSION = "0.2.20";
399
471
  declare const NAME = "@easbot/mcp";
400
472
  declare function initLog(options: {
401
473
  print: boolean;
402
- logDir?: string;
474
+ logDir: string;
403
475
  logFile?: string;
404
476
  dev?: boolean;
405
477
  level?: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
406
478
  }): Promise<void>;
407
479
 
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 };
480
+ export { type AuthResult, type ClientInfo, HttpServerAdapter, type HttpServerConfig, type LocalMCPConfig, MCPClient, type MCPConfig, type McpConfig, type McpLocalConfig, type McpOAuthConfig, type McpRemoteConfig, NAME, type OAuthClientProviderAdapter, type OAuthConfig, type PromptMetadata, type RemoteMCPConfig, type RequestId, type ResourceMetadata, type ServerInfo, type ServerInstance$2 as ServerInstance, ServerStatus, ServerTransportType, Status, StdioServerAdapter, type StdioServerConfig, type ToolCallResult, type ToolContentItem, type ToolContext, type ToolDefinition, type ToolHandler, type ToolInputSchema, type ToolListChangedHandler, type ToolMetadata, ToolRegistry, ToolRegistryEvent, createAndStartHttpServer, createAndStartStdioServer, createHttpServer, createMCPClient, createServerFromConfig, createServersFromConfigMap, createStdioServer, getVersion, initLog, tools };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,18 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp';
2
- import z from 'zod';
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3
+ import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
4
+ import z, { ZodType } from 'zod';
5
+ import { EventEmitter } from 'node:events';
6
+ import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
3
7
 
4
8
  interface McpLocalConfig {
5
9
  type: 'local';
6
- command: string[];
7
- environment?: Record<string, string>;
10
+ command: string;
11
+ args?: string[];
12
+ env?: Record<string, string>;
8
13
  enabled?: boolean;
9
14
  timeout?: number;
15
+ description?: string;
10
16
  }
11
17
  interface McpOAuthConfig {
12
18
  clientId?: string;
@@ -20,6 +26,7 @@ interface McpRemoteConfig {
20
26
  headers?: Record<string, string>;
21
27
  oauth?: McpOAuthConfig | false;
22
28
  timeout?: number;
29
+ description?: string;
23
30
  }
24
31
  type McpConfig = McpLocalConfig | McpRemoteConfig;
25
32
  declare const ServerTransportType: {
@@ -50,7 +57,7 @@ interface StdioServerConfig {
50
57
  name: string;
51
58
  version: string;
52
59
  transportType: typeof ServerTransportType.STDIO;
53
- command: string;
60
+ command?: string;
54
61
  args?: string[];
55
62
  env?: Record<string, string>;
56
63
  cwd?: string;
@@ -141,6 +148,9 @@ declare class HttpServerAdapter {
141
148
  declare function createHttpServer(config: HttpServerConfig): HttpServerAdapter;
142
149
  declare function createAndStartHttpServer(config: HttpServerConfig): Promise<ServerInstance>;
143
150
 
151
+ declare function createServerFromConfig(name: string, config: McpConfig): Promise<ServerInstance$2>;
152
+ declare function createServersFromConfigMap(configs: Record<string, McpConfig>): Promise<Record<string, ServerInstance$2>>;
153
+
144
154
  interface OAuthConfig {
145
155
  clientId?: string;
146
156
  clientSecret?: string;
@@ -150,6 +160,7 @@ interface OAuthConfig {
150
160
  interface LocalMCPConfig {
151
161
  type: 'local';
152
162
  command: string[];
163
+ cwd?: string;
153
164
  environment?: Record<string, string>;
154
165
  timeout?: number;
155
166
  }
@@ -162,6 +173,7 @@ interface RemoteMCPConfig {
162
173
  timeout?: number;
163
174
  }
164
175
  type MCPConfig = LocalMCPConfig | RemoteMCPConfig;
176
+ type ToolListChangedHandler = () => void | Promise<void>;
165
177
  declare const Status: z.ZodDiscriminatedUnion<[z.ZodObject<{
166
178
  status: z.ZodLiteral<"connected">;
167
179
  }, z.core.$strip>, z.ZodObject<{
@@ -174,6 +186,8 @@ declare const Status: z.ZodDiscriminatedUnion<[z.ZodObject<{
174
186
  }, z.core.$strip>, z.ZodObject<{
175
187
  status: z.ZodLiteral<"needs_client_registration">;
176
188
  error: z.ZodString;
189
+ }, z.core.$strip>, z.ZodObject<{
190
+ status: z.ZodLiteral<"disabled">;
177
191
  }, z.core.$strip>], "status">;
178
192
  type Status = z.infer<typeof Status>;
179
193
  interface ToolMetadata {
@@ -196,6 +210,60 @@ interface PromptMetadata {
196
210
  required?: boolean;
197
211
  }>;
198
212
  }
213
+ interface ToolContentItem {
214
+ type: 'text' | 'image' | 'resource';
215
+ text?: string;
216
+ data?: string;
217
+ mimeType?: string;
218
+ resource?: {
219
+ uri: string;
220
+ mimeType?: string;
221
+ blob?: string;
222
+ text?: string;
223
+ };
224
+ }
225
+ interface ToolCallResult {
226
+ toolName: string;
227
+ args: Record<string, unknown>;
228
+ content: ToolContentItem[];
229
+ success: boolean;
230
+ error?: string;
231
+ duration: number;
232
+ metadata?: Record<string, unknown>;
233
+ }
234
+ interface AuthResult {
235
+ authorizationUrl: string;
236
+ state: string;
237
+ }
238
+ interface OAuthClientProviderAdapter {
239
+ saveState(state: string): Promise<void>;
240
+ getState(): Promise<string | undefined>;
241
+ clearState(): Promise<void>;
242
+ saveCodeVerifier(verifier: string): Promise<void>;
243
+ getCodeVerifier(): Promise<string | undefined>;
244
+ saveClientInfo(info: {
245
+ clientId: string;
246
+ clientSecret?: string;
247
+ clientIdIssuedAt?: number;
248
+ clientSecretExpiresAt?: number;
249
+ }): Promise<void>;
250
+ getClientInfo(): Promise<{
251
+ clientId: string;
252
+ clientSecret?: string;
253
+ } | undefined>;
254
+ saveTokens(tokens: {
255
+ accessToken: string;
256
+ refreshToken?: string;
257
+ expiresAt?: number;
258
+ scope?: string;
259
+ }): Promise<void>;
260
+ getTokens(): Promise<{
261
+ accessToken: string;
262
+ refreshToken?: string;
263
+ expiresAt?: number;
264
+ scope?: string;
265
+ } | undefined>;
266
+ }
199
267
  interface ClientInfo {
200
268
  id: string;
201
269
  name: string;
@@ -208,18 +276,7 @@ interface ClientInfo {
208
276
  prompts: PromptMetadata[];
209
277
  error?: string;
210
278
  }
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
- }
279
+
223
280
  declare class MCPClient {
224
281
  private id;
225
282
  private client;
@@ -227,14 +284,26 @@ declare class MCPClient {
227
284
  private notificationCleanup;
228
285
  private pendingTransport;
229
286
  private oauthState;
287
+ private capturedRedirectUrl;
288
+ private oauthConfig;
230
289
  private toolListChangedHandler;
290
+ private oauthProvider;
231
291
  constructor();
232
292
  get info(): ClientInfo;
233
293
  get status(): Status;
234
294
  get tools(): ToolMetadata[];
295
+ get resources(): ResourceMetadata[];
296
+ get prompts(): PromptMetadata[];
297
+ get clientId(): string;
298
+ setToolListChangedHandler(handler: ToolListChangedHandler | null): void;
299
+ setOAuthProvider(provider: OAuthClientProviderAdapter | null): void;
235
300
  connect(id: string, config: MCPConfig): Promise<void>;
236
301
  startAuth(): Promise<AuthResult>;
237
- finishAuth(authorizationCode?: string): Promise<void>;
302
+ finishAuth(authorizationCode: string): Promise<void>;
303
+ isAuthRequired(): boolean;
304
+ isClientRegistrationRequired(): boolean;
305
+ getPendingTransport(): StreamableHTTPClientTransport | SSEClientTransport | null;
306
+ getAuthorizationUrl(): string;
238
307
  disconnect(): Promise<void>;
239
308
  listTools(): Promise<Record<string, unknown>>;
240
309
  callTool(toolName: string, args: Record<string, unknown>, timeout?: number): Promise<ToolCallResult>;
@@ -352,57 +421,60 @@ declare class MCPClient {
352
421
  private createLocalClient;
353
422
  private createRemoteClient;
354
423
  private connectWithTransport;
355
- registerToolListChangedHandler(handler: () => void | Promise<void>): void;
424
+ private handleConnectionError;
425
+ private extractRedirectUrl;
356
426
  private registerNotificationHandler;
357
427
  private createInitialInfo;
358
428
  }
359
429
  declare function createMCPClient(): MCPClient;
360
430
 
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
- };
431
+ type ToolInputSchema = ZodType | Record<string, unknown>;
432
+ type RequestId = string | number;
433
+ interface ToolContext {
434
+ signal?: AbortSignal;
435
+ sessionId?: string;
436
+ requestId: RequestId;
437
+ taskId?: string;
438
+ _meta?: Record<string, unknown>;
439
+ authInfo?: {
440
+ type: string;
441
+ claims?: Record<string, unknown>;
381
442
  };
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
443
  }
444
+ type ToolHandler = (args: unknown, ctx: ToolContext) => Promise<CallToolResult>;
445
+ interface ToolDefinition extends Omit<Tool, 'inputSchema'> {
446
+ inputSchema?: ToolInputSchema;
447
+ handler: ToolHandler;
448
+ }
449
+ declare const ToolRegistryEvent: {
450
+ readonly REGISTERED: "mcp.tool.registered";
451
+ readonly UNREGISTERED: "mcp.tool.unregistered";
452
+ readonly CLEARED: "mcp.tool.cleared";
453
+ };
454
+ type ToolRegistryEvent = (typeof ToolRegistryEvent)[keyof typeof ToolRegistryEvent];
455
+ declare class ToolRegistry extends EventEmitter {
456
+ private tools;
457
+ constructor();
458
+ register(tool: ToolDefinition): void;
459
+ unregister(name: string): boolean;
460
+ get(name: string): ToolDefinition | undefined;
461
+ getAll(): ToolDefinition[];
462
+ getTools(): Omit<ToolDefinition, 'handler'>[];
463
+ has(name: string): boolean;
464
+ getSize(): number;
465
+ clear(): void;
466
+ }
467
+ declare const tools: ToolRegistry;
395
468
 
396
469
  declare function getVersion(): string;
397
470
 
398
- declare const VERSION = "0.2.20";
399
471
  declare const NAME = "@easbot/mcp";
400
472
  declare function initLog(options: {
401
473
  print: boolean;
402
- logDir?: string;
474
+ logDir: string;
403
475
  logFile?: string;
404
476
  dev?: boolean;
405
477
  level?: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR';
406
478
  }): Promise<void>;
407
479
 
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 };
480
+ export { type AuthResult, type ClientInfo, HttpServerAdapter, type HttpServerConfig, type LocalMCPConfig, MCPClient, type MCPConfig, type McpConfig, type McpLocalConfig, type McpOAuthConfig, type McpRemoteConfig, NAME, type OAuthClientProviderAdapter, type OAuthConfig, type PromptMetadata, type RemoteMCPConfig, type RequestId, type ResourceMetadata, type ServerInfo, type ServerInstance$2 as ServerInstance, ServerStatus, ServerTransportType, Status, StdioServerAdapter, type StdioServerConfig, type ToolCallResult, type ToolContentItem, type ToolContext, type ToolDefinition, type ToolHandler, type ToolInputSchema, type ToolListChangedHandler, type ToolMetadata, ToolRegistry, ToolRegistryEvent, createAndStartHttpServer, createAndStartStdioServer, createHttpServer, createMCPClient, createServerFromConfig, createServersFromConfigMap, createStdioServer, getVersion, initLog, tools };
package/dist/index.mjs CHANGED
@@ -1,3 +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
1
+ import {b as b$1,a}from'./chunks/chunk-PJM3ON7Z.mjs';import {McpServer}from'@modelcontextprotocol/sdk/server/mcp.js';import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {EventEmitter}from'events';import d from'zod/v4';import q from'http';import {StreamableHTTPServerTransport}from'@modelcontextprotocol/sdk/server/streamableHttp.js';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 E={STDIO:"stdio",HTTP:"http"},l={STOPPED:"stopped",STARTING:"starting",RUNNING:"running",STOPPING:"stopping",ERROR:"error"};var D=b$1.create({service:"tool-registry"}),R={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)){D?.debug("tool already registered, skipping",{tool:e.name});return}this.tools.set(e.name,e),this.emit(R.REGISTERED,e);}unregister(e){return this.tools.has(e)?(this.tools.delete(e),this.emit(R.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(R.CLEARED);}},b=new k;var S=b$1.create({service:"mcp.server.stdio"}),w=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),S.info("tool registered",{tool:t.name});}});this.config=t,this.info={id:t.id,name:t.name,version:t.version,transportType:t.transportType,status:l.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 b.getAll()){let e=this.convertToZodSchema(t.inputSchema),r=this.adaptToolHandler(t.handler);this.server.registerTool(t.name,{description:t.description,inputSchema:e},r),S.info("tool loaded",{tool:t.name});}}subscribeToolEvents(){this.toolEventCleanup=()=>{b.off(R.REGISTERED,this.handleToolRegistered);},b.on(R.REGISTERED,this.handleToolRegistered);}adaptToolHandler(t){return async(e,r)=>{let n={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,n)}}unsubscribeToolEvents(){this.toolEventCleanup&&(this.toolEventCleanup(),this.toolEventCleanup=null);}convertToZodSchema(t){if(t instanceof d.ZodType)return t;if(typeof t=="object"&&t!==null){let e=t;if(e.type==="object"){let r=e.properties||{},n=e.required||[],o={};for(let[i,h]of Object.entries(r))o[i]=this.jsonSchemaToZod(h);if(Object.keys(r).filter(i=>!n.includes(i)).length===0)return d.object(o);let f={};for(let[i,h]of Object.entries(r)){let c=o[i];c&&(n.includes(i)?f[i]=c:f[i]=c.optional());}return d.object(f)}if(e.type==="string")return d.string();if(e.type==="number")return d.number();if(e.type==="boolean")return d.boolean();if(e.type==="array"){let r=e.items;return r?d.array(this.jsonSchemaToZod(r)):d.array(d.unknown())}}return d.unknown()}jsonSchemaToZod(t){switch(t.type){case "string":return d.string();case "number":return d.number();case "integer":return d.number().int();case "boolean":return d.boolean();case "null":return d.null();case "array":{let r=t.items;return r?d.array(this.jsonSchemaToZod(r)):d.array(d.unknown())}case "object":{let r=t.properties||{},n=t.required||[],o={};for(let[i,h]of Object.entries(r))o[i]=this.jsonSchemaToZod(h);if(Object.keys(r).filter(i=>!n.includes(i)).length===0)return d.object(o);let f={};for(let[i,h]of Object.entries(r)){let c=o[i];c&&(n.includes(i)?f[i]=c:f[i]=c.optional());}return d.object(f)}default:return d.unknown()}}async start(){if(this.isStarting){S.warn("server is already starting",{id:this.info.id});return}if(this.info.status===l.RUNNING){S.debug("server is already running",{id:this.info.id});return}this.isStarting=true,this.info.status=l.STARTING;try{S.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;this.server=new McpServer({name:this.config.name,version:this.config.version}),this.loadTools(),this.subscribeToolEvents(),await this.server.connect(t),this.info.status=l.RUNNING,this.info.lastActivityAt=Date.now(),S.info("stdio mcp server started successfully",{id:this.info.id,name:this.info.name,toolCount:b.getSize()});}catch(t){throw this.info.status=l.ERROR,S.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){S.warn("server is already stopping",{id:this.info.id});return}if(this.info.status!==l.RUNNING&&this.info.status!==l.ERROR){S.debug("server is not running",{id:this.info.id,status:this.info.status});return}this.isStopping=true,this.info.status=l.STOPPING;try{S.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=l.STOPPED,S.info("stdio mcp server stopped",{id:this.info.id,name:this.info.name});}catch(t){this.info.status=l.ERROR,S.error("error stopping stdio mcp server",{id:this.info.id,error:t instanceof Error?t.message:String(t)});}finally{this.isStopping=false;}}async restart(){S.info("restarting stdio mcp server",{id:this.info.id}),await this.stop(),await this.start();}};function Z(s){return new w(s)}async function z(s){let t=new w(s);return await t.start(),t.createInstance()}var g=b$1.create({service:"mcp.server.http"}),P=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),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:l.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 b.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});}}subscribeTools(){this.toolCleanup=()=>{b.off(R.REGISTERED,this.handleTool);},b.on(R.REGISTERED,this.handleTool);}convertToZodSchema(t){if(t instanceof d.ZodType)return t;if(typeof t=="object"&&t!==null){let e=t;if(e.type==="object"){let r=e.properties||{},n=e.required||[],o={};for(let[i,h]of Object.entries(r))o[i]=this.jsonSchemaToZod(h);if(Object.keys(r).filter(i=>!n.includes(i)).length===0)return d.object(o);let f={};for(let[i,h]of Object.entries(r)){let c=o[i];c&&(n.includes(i)?f[i]=c:f[i]=c.optional());}return d.object(f)}if(e.type==="string")return d.string();if(e.type==="number")return d.number();if(e.type==="boolean")return d.boolean();if(e.type==="array"){let r=e.items;return r?d.array(this.jsonSchemaToZod(r)):d.array(d.unknown())}}return d.unknown()}jsonSchemaToZod(t){switch(t.type){case "string":return d.string();case "number":return d.number();case "integer":return d.number().int();case "boolean":return d.boolean();case "null":return d.null();case "array":{let r=t.items;return r?d.array(this.jsonSchemaToZod(r)):d.array(d.unknown())}case "object":{let r=t.properties||{},n=t.required||[],o={};for(let[i,h]of Object.entries(r))o[i]=this.jsonSchemaToZod(h);if(Object.keys(r).filter(i=>!n.includes(i)).length===0)return d.object(o);let f={};for(let[i,h]of Object.entries(r)){let c=o[i];c&&(n.includes(i)?f[i]=c:f[i]=c.optional());}return d.object(f)}default:return d.unknown()}}adaptToolHandler(t){return async(e,r)=>{let n={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,n)}}unsubscribeTools(){this.toolCleanup&&(this.toolCleanup(),this.toolCleanup=null);}async start(){if(this.isStarting){g.warn("already starting",{id:this.info.id});return}if(this.info.status===l.RUNNING){g.debug("already running",{id:this.info.id});return}this.isStarting=true,this.info.status=l.STARTING;try{g.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((n,o)=>{let m=n.headers.origin,f=(h,c,H)=>{o.writeHead(h,c),H?o.end(H):o.end();},i={"Access-Control-Allow-Origin":m||"*","Access-Control-Allow-Methods":"GET, POST, OPTIONS","Access-Control-Allow-Headers":"Content-Type, mcpsessionid, mcp-protocol-version","Access-Control-Max-Age":"86400"};if(n.method==="OPTIONS"){f(204,i);return}if(n.method==="POST"){let h="";n.setEncoding("utf8"),n.on("data",c=>{h+=c;}),n.on("end",()=>{let c;if(h)try{c=JSON.parse(h);}catch{c=void 0;}this.transport&&this.transport.handleRequest(n,o,c);}),n.on("error",c=>{g.error("HTTP request error",{error:c.message}),f(500,i,JSON.stringify({jsonrpc:"2.0",error:{code:-32603,message:"Internal error"}}));});}else n.method==="GET"?this.transport&&this.transport.handleRequest(n,o,void 0):f(405,i,JSON.stringify({jsonrpc:"2.0",error:{code:-32601,message:"Method not found"}}));}),this.httpServer.on("error",n=>{g.error("HTTP server error",{error:n.message}),this.info.status=l.ERROR;}),this.httpServer.on("clientError",(n,o)=>{g.warn("HTTP client error",{error:n.message}),o.writable&&o.end(`HTTP/1.1 400 Bad Request\r
2
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.22"};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};
3
+ `);}),this.httpServer.listen(e,r),g.info("HTTP server listening",{hostname:r,port:e}),this.info.status=l.RUNNING,this.info.lastActivityAt=Date.now(),g.info("started",{id:this.info.id,name:this.info.name,toolCount:b.getSize()});}catch(t){throw this.info.status=l.ERROR,g.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){g.warn("already stopping",{id:this.info.id});return}if(this.info.status!==l.RUNNING&&this.info.status!==l.ERROR){g.debug("not running",{id:this.info.id,status:this.info.status});return}this.isStopping=true,this.info.status=l.STOPPING;try{g.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=l.STOPPED,g.info("stopped",{id:this.info.id});}catch(t){this.info.status=l.ERROR,g.error("failed to stop",{id:this.info.id,error:t instanceof Error?t.message:String(t)});}finally{this.isStopping=false;}}async restart(){g.info("restarting",{id:this.info.id}),await this.stop(),await this.start();}};function F(s){return new P(s)}async function B(s){let t=new P(s);return await t.start(),t.createInstance()}var O={version:"0.2.23"};function x(){return O.version}var j=b$1.create({service:"mcp.server.factory"});function $(s){return s.type==="local"}function J(s){return s.type==="remote"}function W(s,t){if(!t.command)throw new Error(`MCP server ${s} has no command specified`);return {id:s,name:s,version:"1.0.0",transportType:E.STDIO,enabled:t.enabled,timeout:t.timeout,command:t.command,args:t.args?.length?t.args:void 0,env:t.env}}function Q(s,t){return {id:s,name:s,version:"1.0.0",transportType:E.HTTP,enabled:t.enabled,timeout:t.timeout,url:t.url,headers:t.headers}}async function X(s,t){if(j.debug("creating server from config",{name:s,type:t.type}),$(t)){let e=W(s,t),r=new w(e);return await r.start(),r.createInstance()}if(J(t)){let e=Q(s,t),r=new P(e);return await r.start(),r.createInstance()}throw new Error(`Unsupported MCP config type: ${t.type}`)}async function zt(s){let t={};for(let[e,r]of Object.entries(s))try{let n=await X(e,r);t[e]=n;}catch(n){j.error("failed to create server from config",{name:e,error:n instanceof Error?n.message:String(n)});}return t}var p=b$1.create({service:"mcp.client"}),M=3e4,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,"capturedRedirectUrl",null);a(this,"oauthConfig");a(this,"toolListChangedHandler",null);a(this,"oauthProvider",null);this._info=this.createInitialInfo();}get info(){return {...this._info}}get status(){return this._info.status}get tools(){return [...this._info.tools]}get resources(){return [...this._info.resources]}get prompts(){return [...this._info.prompts]}get clientId(){return this.id}setToolListChangedHandler(t){this.toolListChangedHandler=t;}setOAuthProvider(t){this.oauthProvider=t;}async connect(t,e){p.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(e.type==="remote"&&(this.oauthConfig=e.oauth===!1?void 0:e.oauth??{}),this.client=await this.createClient(e),!this.client)return;this._info.status={status:"connected"},this._info.connectedAt=Date.now(),await this.fetchCapabilities(),p.info("connected to MCP server",{id:t,toolCount:this._info.tools.length});}catch(r){let n=r instanceof Error?r.message:String(r);this._info.status={status:"failed",error:n},this._info.error=n,p.error("failed to connect to MCP server",{id:t,error:n});}}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(""),this.oauthProvider&&await this.oauthProvider.saveState(this.oauthState),{authorizationUrl:this.capturedRedirectUrl?.toString()??"",state:this.oauthState}}async finishAuth(t){if(!this.pendingTransport)throw new Error("No pending OAuth flow.");try{await this.pendingTransport.finishAuth?.(t);}catch(e){throw p.error("failed to finish OAuth",{id:this.id,error:e}),e}this.pendingTransport=null,this.capturedRedirectUrl=null,p.info("OAuth completed, ready to reconnect",{id:this.id});}isAuthRequired(){return this._info.status.status==="needs_auth"}isClientRegistrationRequired(){return this._info.status.status==="needs_client_registration"}getPendingTransport(){return this.pendingTransport}getAuthorizationUrl(){return this.capturedRedirectUrl?.toString()??""}async disconnect(){this.notificationCleanup&&(this.notificationCleanup(),this.notificationCleanup=null),this.client&&(await this.client.close().catch(t=>{p.error("Failed to close MCP client",{id:this.id,error:t});}),this.client=null),this.pendingTransport=null,this.capturedRedirectUrl=null,this.toolListChangedHandler=null,this._info.status.status==="connected"&&(this._info.status={status:"disconnected"}),p.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 n=Date.now();if(!this.client||this._info.status.status!=="connected")return {toolName:t,args:e,content:[],success:false,error:"Client not connected",duration:Date.now()-n};try{let o=await withTimeout(this.client.callTool({name:t,arguments:e},CallToolResultSchema,{resetTimeoutOnProgress:!0,timeout:r}),r??M);return {toolName:t,args:e,content:o.content.map(m=>m.type==="text"?{type:"text",text:m.text}:m.type==="image"?{type:"image",data:m.data,mimeType:m.mimeType}:m.type==="resource"?{type:"resource",resource:m.resource}:{type:"text",text:String(m)}),success:!0,duration:Date.now()-n,metadata:o.metadata}}catch(o){return {toolName:t,args:e,content:[],success:false,error:o instanceof Error?o.message:String(o),duration:Date.now()-n}}}async listResources(){return [...this._info.resources]}async readResource(t){if(!this.client||this._info.status.status!=="connected"){p.warn("client not connected for readResource",{id:this.id});return}return this.client.readResource({uri:t}).catch(e=>{p.error("failed to read resource",{id:this.id,uri:t,error:e.message});})}async listPrompts(){return [...this._info.prompts]}async getPrompt(t,e){if(!this.client||this._info.status.status!=="connected"){p.warn("client not connected for getPrompt",{id:this.id});return}return this.client.getPrompt({name:t,arguments:e}).catch(r=>{p.error("failed to get prompt",{id:this.id,name:t,error:r.message});})}async refreshTools(){if(!(!this.client||this._info.status.status!=="connected"))try{let t=await withTimeout(this.client.listTools(),M);this._info.tools=t.tools.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema})),p.info("tools refreshed",{id:this.id,count:this._info.tools.length});}catch(t){p.error("failed to refresh tools",{id:this.id,error:t instanceof Error?t.message:String(t)});}}async createClient(t){return t.type==="local"?await this.createLocalClient(t):t.type==="remote"?await this.createRemoteClient(t):null}async fetchCapabilities(){if(this.client){try{let t=await withTimeout(this.client.listTools(),M);this._info.tools=t.tools.map(e=>({name:e.name,description:e.description,inputSchema:e.inputSchema}));}catch(t){p.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{p.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{p.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 n=new StdioClientTransport({stderr:"pipe",command:e,args:r.length>0?r:void 0,cwd:t.cwd??process.cwd(),env:Object.fromEntries(Object.entries({...process.env,...t.environment}).filter(([,o])=>o!==void 0))});n.stderr?.on("data",o=>{p.info(`mcp stderr: ${o.toString()}`,{id:this.id});});try{let o=new Client({name:"easbot-mcp",version:x()});return await withTimeout(o.connect(n),t.timeout??M),this.registerNotificationHandler(o),o}catch(o){let m=o instanceof Error?o.message:String(o);return this._info.status={status:"failed",error:m},p.error("local mcp startup failed",{id:this.id,command:[e,...r],error:m}),null}}async createRemoteClient(t){let e={headers:t.headers};if((t.transport||"streamable-http")==="sse"){p.info("using SSE transport",{id:this.id,url:t.url});let n=new SSEClientTransport(new URL(t.url),{requestInit:e});return await this.connectWithTransport(n,t)}else {p.info("using StreamableHTTP transport",{id:this.id,url:t.url});let n=new StreamableHTTPClientTransport(new URL(t.url),{requestInit:e});return await this.connectWithTransport(n,t)}}async connectWithTransport(t,e){try{let r=new Client({name:"easbot-mcp",version:x()});return await r.connect(t),this.registerNotificationHandler(r),r}catch(r){return this.handleConnectionError(r,t,e),null}}handleConnectionError(t,e,r){if(t instanceof UnauthorizedError){let n=t instanceof Error?t.message:String(t);n.includes("registration")||n.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=e,this.capturedRedirectUrl=this.extractRedirectUrl(t));}else {let n=t instanceof Error?t.message:String(t);this._info.status={status:"failed",error:n};}p.error("remote mcp connection failed",{id:this.id,url:r.url,status:this._info.status});}extractRedirectUrl(t){let r=t.message.match(/https?:\/\/[^\s]+/);if(r)try{return new URL(r[0])}catch{return null}return null}registerNotificationHandler(t){let e=async()=>{p.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 it(){return new A}var le=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"}),v.object({status:v.literal("disabled")}).meta({ref:"MCPStatusDisabled"})]);var ge="@easbot/mcp";async function ve(s){let{Log:t}=await import('./chunks/log-2GAL6FAC.mjs'),e=false;await t.init({logDir:s.logDir??process.env.EASBOT_LOG_PATH??process.cwd(),print:s.print??false,dev:s.dev??e,level:s.level??("INFO")});}export{P as HttpServerAdapter,A as MCPClient,ge as NAME,l as ServerStatus,E as ServerTransportType,le as Status,w as StdioServerAdapter,k as ToolRegistry,R as ToolRegistryEvent,B as createAndStartHttpServer,z as createAndStartStdioServer,F as createHttpServer,it as createMCPClient,X as createServerFromConfig,zt as createServersFromConfigMap,Z as createStdioServer,x as getVersion,ve as initLog,b as tools};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easbot/mcp",
3
- "version": "0.2.22",
3
+ "version": "0.2.23",
4
4
  "description": "MCP (Model Context Protocol) integration library for EASBOT ecosystem",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -44,8 +44,8 @@
44
44
  "ai": "^6.0.176",
45
45
  "zod": "^4.4.3",
46
46
  "@modelcontextprotocol/sdk": "^1.29.0",
47
- "@easbot/types": "0.2.22",
48
- "@easbot/utils": "0.2.22"
47
+ "@easbot/types": "0.2.23",
48
+ "@easbot/utils": "0.2.23"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@biomejs/biome": "^2.4.14",