@awarecorp/mcp-logger 0.0.3-dev.1 → 0.0.3-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/cli/main.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -152,6 +152,8 @@ mcp-logger [options] <command...>
|
|
|
152
152
|
- `-e, --endpoint <url>`: Custom OTLP endpoint (optional, default: `https://aware.mcypher.com/v1/traces`)
|
|
153
153
|
- Send traces to any OTLP/HTTP compatible backend
|
|
154
154
|
- Examples: Jaeger, Grafana Tempo, New Relic, Honeycomb, etc.
|
|
155
|
+
- `-d, --debug`: Enable debug logging (optional)
|
|
156
|
+
- Shows detailed information about message processing and span creation
|
|
155
157
|
|
|
156
158
|
### Examples
|
|
157
159
|
|
package/dist/cli/main.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
function e(e){return!h.includes(e)}function r(){return y}function s(){return q}async function t(){if(f)try{await f.shutdown(),f=null,y=null,S=!1,q=null}catch(e){console.error("[MCP Logger] Error shutting down telemetry:",e)}}function o(e,r){for(const[s,t]of Object.entries(r))null!=t&&e.setAttribute(s,t)}function n(e,r=1e4){try{const s=JSON.stringify(e);return s.length>r?s.slice(0,r)+"... (truncated)":s}catch(e){return null}}import{spawn as i}from"child_process";import{program as c}from"commander";import{NodeSDK as a}from"@opentelemetry/sdk-node";import{OTLPTraceExporter as p}from"@opentelemetry/exporter-trace-otlp-http";import{Resource as m}from"@opentelemetry/resources";import{trace as l,SpanStatusCode as g}from"@opentelemetry/api";import{Transform as u}from"stream";const d="1.0.0",h=["notifications/initialized"];let f=null,y=null,S=!1,q=null;class C extends u{buffer="";direction;logger;debug;constructor(e,r,s=!1){super(),this.direction=e,this.logger=r,this.debug=s}_transform(e,r,s){try{this.push(e),this.buffer+=e.toString(),this.buffer.length>1e6&&(this.debug&&console.error("[mcp-logger CLI] Buffer size exceeded, clearing..."),this.buffer=""),this.tryParseMessages(),s()}catch(e){s(e)}}tryParseMessages(){const e=this.buffer.split("\n");this.buffer=e.pop()||"";for(const r of e){const e=r.trim();if(e)try{const r=JSON.parse(e);this.handleMessage(r)}catch(r){this.debug&&console.error("[mcp-logger CLI] Failed to parse:",e.slice(0,100))}}}handleMessage(e){console.error("[mcp-logger CLI] Handling message:",JSON.stringify(e).slice(0,100)),"request"===this.direction&&e.method?this.logger.onRequest(e):"response"===this.direction&&(void 0===e.id||e.method?e.method&&!e.id&&this.logger.onNotification(e):this.logger.onResponse(e))}_flush(e){try{if(this.buffer.trim())try{const e=JSON.parse(this.buffer);this.handleMessage(e)}catch(e){this.debug&&console.error("[mcp-logger CLI] Failed to parse final buffer")}if(this.debug){const e=this.logger.getStats();console.error("[mcp-logger CLI] Stream closed. Pending requests: "+e.pending)}e()}catch(r){e(r)}}}class v{pendingRequests=new Map;debug;TIMEOUT=3e4;constructor(e=!1){this.debug=e}onRequest(r){if(this.debug&&console.error(`[mcp-logger CLI] 📥 REQUEST: method="${r.method}", id=${r.id}, params=${JSON.stringify(r.params)?.slice(0,100)}`),e(r.method)){if(!r.id)return this.debug&&console.error(`[mcp-logger CLI] 🔔 Notification detected: ${r.method} → Creating request-only span`),void this.createRequestOnlySpan(r,Date.now());this.pendingRequests.set(r.id,{request:r,timestamp:Date.now()}),this.debug&&console.error(`[mcp-logger CLI] Request stored: ${r.method} (ID: ${r.id})`),setTimeout(()=>this.cleanupStale(r.id),this.TIMEOUT)}else this.debug&&console.error("[mcp-logger CLI] 🚫 Skipping excluded method: "+r.method)}onResponse(e){if(this.debug&&console.error(`[mcp-logger CLI] 📤 RESPONSE: id=${e.id}, hasResult=${!!e.result}, result=${JSON.stringify(e.result)?.slice(0,100)}, hasError=${!!e.error}`),!e.id)return void(this.debug&&console.error("[mcp-logger CLI] Response without ID, skipping"));const r=this.pendingRequests.get(e.id);if(!r)return this.debug&&console.error(`[mcp-logger CLI] ⏭️ No matching request for response ID: ${e.id} → Creating response-only span`),void this.createResponseOnlySpan(e,Date.now());const s=Date.now(),t=s-r.timestamp;this.debug&&console.error(`[mcp-logger CLI] ✅ Pairing success: ${r.request.method} (${t}ms)`),this.createPairedSpan(r.request,e,r.timestamp,s,t),this.pendingRequests.delete(e.id)}onNotification(r){this.debug&&console.error(`[mcp-logger CLI] 📢 NOTIFICATION (Server→Client): method="${r.method}", params=${JSON.stringify(r.params)?.slice(0,100)}`),e(r.method)?this.createResponseOnlySpan({jsonrpc:"2.0",id:`notification-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,method:r.method},Date.now()):this.debug&&console.error("[mcp-logger CLI] 🚫 Skipping excluded method: "+r.method)}createPairedSpan(e,t,i,c,a){!function(e){const t=r();if(!t)return void console.error("[MCP Logger] Tracer not initialized, cannot create span");const i="mcp."+e.method;t.startActiveSpan(i,r=>{try{const t={"mcp.source":e.source,"mcp.transport":e.transport,"mcp.request.id":e.request.id+"","mcp.request.method":e.method,"mcp.request.timestamp":e.request.timestamp,"mcp.request.params":n(e.request.params)||"{}","mcp.request.params.size":JSON.stringify(e.request.params||{}).length,"mcp.response.id":e.request.id+"","mcp.response.timestamp":e.response.timestamp,"mcp.duration_ms":e.duration};if("tools/call"===e.method&&e.request.params){const r=e.request.params.name,s=e.request.params.arguments;if(r&&(t["mcp.tool.name"]=r),s){const e=n(s);e&&(t["mcp.tool.arguments"]=e,t["mcp.tool.arguments.size"]=JSON.stringify(s).length)}}if(void 0!==e.response.result){const r=n(e.response.result);r&&(t["mcp.response.result"]=r,t["mcp.response.result.size"]=JSON.stringify(e.response.result).length)}if(e.request.headers){const r=n(e.request.headers);r&&(t["mcp.headers"]=r,t["mcp.headers.size"]=JSON.stringify(e.request.headers).length)}if("cli"===e.source){const e=s();e&&(t["mcp.cli.server"]=JSON.stringify({command:e.command,args:e.args,env:e.env}))}if(e.customEvents&&e.customEvents.length>0&&(t["mcp.events"]=JSON.stringify(e.customEvents),t["mcp.events.count"]=e.customEvents.length,e.customEvents.forEach(e=>{r.addEvent("custom."+(e.level||"info"),{message:e.message,metadata:JSON.stringify(e.metadata||{}),timestamp:e.timestamp||Date.now()})})),e.response.error){let s;t["mcp.error"]=!0,s=e.response.error instanceof Error?e.response.error.message:"string"==typeof e.response.error?e.response.error:n(e.response.error)||"Unknown error",t["mcp.error.message"]=s,e.response.error instanceof Error&&r.recordException(e.response.error),r.setStatus({code:g.ERROR,message:s})}else r.setStatus({code:g.OK});o(r,t)}catch(e){console.error("[MCP Logger] Error creating paired span:",e),r.setStatus({code:g.ERROR,message:e+""})}finally{r.end()}})}({method:e.method,source:"cli",transport:"stdio",request:{id:e.id,timestamp:i,params:e.params},response:{timestamp:c,result:t.result,error:t.error},duration:a})}cleanupStale(e){const r=this.pendingRequests.get(e);r&&Date.now()-r.timestamp>this.TIMEOUT&&(this.debug&&console.error(`[mcp-logger CLI] ⏰ Request timeout: ${r.request.method} (ID: ${e}) → Creating request-only span`),this.createRequestOnlySpan(r.request,r.timestamp),this.pendingRequests.delete(e))}createRequestOnlySpan(e,t){!function(e){const t=r();if(!t)return void console.error("[MCP Logger] Tracer not initialized, cannot create span");const i="mcp."+e.method;t.startActiveSpan(i,r=>{try{const t={"mcp.source":e.source,"mcp.transport":e.transport,"mcp.request.id":e.request.id+"","mcp.request.method":e.method,"mcp.request.timestamp":e.request.timestamp,"mcp.request.params":n(e.request.params)||"{}","mcp.request.params.size":JSON.stringify(e.request.params||{}).length};if("tools/call"===e.method&&e.request.params){const r=e.request.params.name,s=e.request.params.arguments;if(r&&(t["mcp.tool.name"]=r),s){const e=n(s);e&&(t["mcp.tool.arguments"]=e,t["mcp.tool.arguments.size"]=JSON.stringify(s).length)}}if("cli"===e.source){const e=s();e&&(t["mcp.cli.server"]=JSON.stringify({command:e.command,args:e.args,env:e.env}))}r.setStatus({code:g.OK}),o(r,t)}catch(e){console.error("[MCP Logger] Error creating request-only span:",e),r.setStatus({code:g.ERROR,message:e+""})}finally{r.end()}})}({method:e.method,source:"cli",transport:"stdio",request:{id:e.id,timestamp:t,params:e.params}})}createResponseOnlySpan(e,t){!function(e){const t=r();if(!t)return void console.error("[MCP Logger] Tracer not initialized, cannot create span");const i="mcp."+e.method;t.startActiveSpan(i,r=>{try{const t={"mcp.source":e.source,"mcp.transport":e.transport,"mcp.response.id":e.response.id+"","mcp.response.method":e.method,"mcp.response.timestamp":e.response.timestamp};if(void 0!==e.response.result){const r=n(e.response.result);r&&(t["mcp.response.result"]=r,t["mcp.response.result.size"]=JSON.stringify(e.response.result).length)}if(e.response.error){let s;t["mcp.error"]=!0,s=e.response.error instanceof Error?e.response.error.message:"string"==typeof e.response.error?e.response.error:n(e.response.error)||"Unknown error",t["mcp.error.message"]=s,e.response.error instanceof Error&&r.recordException(e.response.error),r.setStatus({code:g.ERROR,message:s})}else r.setStatus({code:g.OK});if("cli"===e.source){const e=s();e&&(t["mcp.cli.server"]=JSON.stringify({command:e.command,args:e.args,env:e.env}))}o(r,t)}catch(e){console.error("[MCP Logger] Error creating response-only span:",e),r.setStatus({code:g.ERROR,message:e+""})}finally{r.end()}})}({method:e.method||"same_request_method",source:"cli",transport:"stdio",response:{id:e.id,timestamp:t,result:e.result,error:e.error}})}getStats(){return{pending:this.pendingRequests.size}}clear(){this.debug&&console.error(`[mcp-logger CLI] Clearing ${this.pendingRequests.size} pending requests`),this.pendingRequests.clear()}}c.name("mcp-logger").description("Add observability to any MCP server without code changes").version("1.0.0").requiredOption("-k, --api-key <key>","Aware API key").option("-s, --service-name <name>","Service name for identification").option("-e, --endpoint <url>","Custom OTLP endpoint").argument("<command...>","MCP server command to wrap").action(async(e,r)=>{try{const s=!0;!function(e){if(S)return console.error("[MCP Logger] Telemetry already initialized, returning existing tracer"),y;const r=e.endpoint||"https://aware.mcypher.com/v1/traces",s=e.serviceName||"mcp-server-"+Math.random().toString(36).slice(2,8);console.error("[MCP Logger] Initializing telemetry..."),console.error("[MCP Logger] Endpoint: "+r),console.error("[MCP Logger] Service: "+s),f=new a({resource:new m({"service.name":s,"service.version":d}),traceExporter:new p({url:r,headers:{"x-api-key":e.apiKey}})}),f.start(),y=l.getTracer("mcp-logger",d),S=!0,console.error("[MCP Logger] Telemetry initialized successfully");const o=async()=>{console.error("[MCP Logger] Shutting down telemetry..."),await t()};process.once("SIGTERM",o),process.once("SIGINT",o)}({...r,debug:s}),console.error("[MCP Logger CLI] Starting MCP server:",e.join(" "));const[o,...n]=e;!function(e,r){q={command:e,args:r,env:{}}}(o,n);const c=i(o,n,{stdio:["pipe","pipe","inherit"],env:{...process.env,MCP_LOGGER_ENABLED:"true"}}),g=new v(s),u=new C("request",g,s);process.stdin.pipe(u).pipe(c.stdin);const h=new C("response",g,s);c.stdout.pipe(h).pipe(process.stdout),c.on("error",async e=>{console.error("[MCP Logger CLI] Failed to start MCP server:",e),g.clear(),await t(),process.exit(1)}),c.on("exit",async(e,r)=>{console.error(`[MCP Logger CLI] MCP server exited with code ${e}, signal ${r}`),g.clear(),await t(),process.exit(e||0)});let R=!1;const I=async e=>{R||(R=!0,console.error(`[MCP Logger CLI] Received ${e}, shutting down...`),c.kill(e),await Promise.race([new Promise(e=>c.once("exit",e)),new Promise(e=>setTimeout(e,5e3))]),await t(),process.exit(0))};process.on("SIGTERM",()=>I("SIGTERM")),process.on("SIGINT",()=>I("SIGINT"))}catch(e){console.error("[MCP Logger CLI] Fatal error:",e),await t(),process.exit(1)}}),c.parse();
|
|
2
|
+
function e(e){return!h.includes(e)}function r(){return y}function s(){return S}async function t(){if(f)try{await f.shutdown(),f=null,y=null,q=!1,S=null}catch(e){console.error("[MCP Logger] Error shutting down telemetry:",e)}}function o(e,r){for(const[s,t]of Object.entries(r))null!=t&&e.setAttribute(s,t)}function n(e,r=1e4){try{const s=JSON.stringify(e);return s.length>r?s.slice(0,r)+"... (truncated)":s}catch(e){return null}}import{spawn as i}from"child_process";import{program as c}from"commander";import{NodeSDK as a}from"@opentelemetry/sdk-node";import{OTLPTraceExporter as p}from"@opentelemetry/exporter-trace-otlp-http";import{Resource as m}from"@opentelemetry/resources";import{trace as u,SpanStatusCode as d}from"@opentelemetry/api";import{Transform as l}from"stream";const g="1.0.0",h=["notifications/initialized"];let f=null,y=null,q=!1,S=null;class v extends l{buffer="";direction;logger;debug;constructor(e,r,s=!1){super(),this.direction=e,this.logger=r,this.debug=s}_transform(e,r,s){try{this.push(e),this.buffer+=e.toString(),this.buffer.length>1e6&&(this.debug&&console.error("[mcp-logger CLI] Buffer size exceeded, clearing..."),this.buffer=""),this.tryParseMessages(),s()}catch(e){s(e)}}tryParseMessages(){const e=this.buffer.split("\n");this.buffer=e.pop()||"";for(const r of e){const e=r.trim();if(e)try{const r=JSON.parse(e);this.handleMessage(r)}catch(r){this.debug&&console.error("[mcp-logger CLI] Failed to parse:",e.slice(0,100))}}}handleMessage(e){console.error("[mcp-logger CLI] Handling message:",JSON.stringify(e).slice(0,100)),"request"===this.direction&&e.method?this.logger.onRequest(e):"response"===this.direction&&(void 0===e.id||e.method?e.method&&!e.id&&this.logger.onNotification(e):this.logger.onResponse(e))}_flush(e){try{if(this.buffer.trim())try{const e=JSON.parse(this.buffer);this.handleMessage(e)}catch(e){this.debug&&console.error("[mcp-logger CLI] Failed to parse final buffer")}if(this.debug){const e=this.logger.getStats();console.error("[mcp-logger CLI] Stream closed. Pending requests: "+e.pending)}e()}catch(r){e(r)}}}class C{pendingRequests=new Map;debug;TIMEOUT=3e4;constructor(e=!1){this.debug=e}onRequest(r){if(this.debug&&console.error(`[mcp-logger CLI] 📥 REQUEST: method="${r.method}", id=${r.id}, params=${JSON.stringify(r.params)?.slice(0,100)}`),e(r.method)){if(!r.id)return this.debug&&console.error(`[mcp-logger CLI] 🔔 Notification detected: ${r.method} → Creating request-only span`),void this.createRequestOnlySpan(r,Date.now());this.pendingRequests.set(r.id,{request:r,timestamp:Date.now()}),this.debug&&console.error(`[mcp-logger CLI] Request stored: ${r.method} (ID: ${r.id})`),setTimeout(()=>this.cleanupStale(r.id),this.TIMEOUT)}else this.debug&&console.error("[mcp-logger CLI] 🚫 Skipping excluded method: "+r.method)}onResponse(e){if(this.debug&&console.error(`[mcp-logger CLI] 📤 RESPONSE: id=${e.id}, hasResult=${!!e.result}, result=${JSON.stringify(e.result)?.slice(0,100)}, hasError=${!!e.error}`),!e.id)return void(this.debug&&console.error("[mcp-logger CLI] Response without ID, skipping"));const r=this.pendingRequests.get(e.id);if(!r)return this.debug&&console.error(`[mcp-logger CLI] ⏭️ No matching request for response ID: ${e.id} → Creating response-only span`),void this.createResponseOnlySpan(e,Date.now());const s=Date.now(),t=s-r.timestamp;this.debug&&console.error(`[mcp-logger CLI] ✅ Pairing success: ${r.request.method} (${t}ms)`),this.createPairedSpan(r.request,e,r.timestamp,s,t),this.pendingRequests.delete(e.id)}onNotification(r){this.debug&&console.error(`[mcp-logger CLI] 📢 NOTIFICATION (Server→Client): method="${r.method}", params=${JSON.stringify(r.params)?.slice(0,100)}`),e(r.method)?this.createResponseOnlySpan({jsonrpc:"2.0",id:`notification-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,method:r.method},Date.now()):this.debug&&console.error("[mcp-logger CLI] 🚫 Skipping excluded method: "+r.method)}createPairedSpan(e,t,i,c,a){!function(e){const t=r();if(!t)return void console.error("[MCP Logger] Tracer not initialized, cannot create span");const i="mcp."+e.method;t.startActiveSpan(i,r=>{try{const t={"mcp.source":e.source,"mcp.transport":e.transport,"mcp.request.id":e.request.id+"","mcp.request.method":e.method,"mcp.request.timestamp":e.request.timestamp,"mcp.request.params":n(e.request.params)||"{}","mcp.request.params.size":JSON.stringify(e.request.params||{}).length,"mcp.response.id":e.request.id+"","mcp.response.timestamp":e.response.timestamp,"mcp.duration_ms":e.duration};if("tools/call"===e.method&&e.request.params){const r=e.request.params.name,s=e.request.params.arguments;if(r&&(t["mcp.tool.name"]=r),s){const e=n(s);e&&(t["mcp.tool.arguments"]=e,t["mcp.tool.arguments.size"]=JSON.stringify(s).length)}}if(void 0!==e.response.result){const r=n(e.response.result);r&&(t["mcp.response.result"]=r,t["mcp.response.result.size"]=JSON.stringify(e.response.result).length)}if(e.request.headers){const r=n(e.request.headers);r&&(t["mcp.headers"]=r,t["mcp.headers.size"]=JSON.stringify(e.request.headers).length)}if("cli"===e.source){const e=s();e&&(t["mcp.cli.server"]=JSON.stringify({command:e.command,args:e.args,env:e.env}))}if(e.customEvents&&e.customEvents.length>0&&(t["mcp.events"]=JSON.stringify(e.customEvents),t["mcp.events.count"]=e.customEvents.length,e.customEvents.forEach(e=>{r.addEvent("custom."+(e.level||"info"),{message:e.message,metadata:JSON.stringify(e.metadata||{}),timestamp:e.timestamp||Date.now()})})),e.response.error){let s;t["mcp.error"]=!0,s=e.response.error instanceof Error?e.response.error.message:"string"==typeof e.response.error?e.response.error:n(e.response.error)||"Unknown error",t["mcp.error.message"]=s,e.response.error instanceof Error&&r.recordException(e.response.error),r.setStatus({code:d.ERROR,message:s})}else r.setStatus({code:d.OK});o(r,t)}catch(e){console.error("[MCP Logger] Error creating paired span:",e),r.setStatus({code:d.ERROR,message:e+""})}finally{r.end()}})}({method:e.method,source:"cli",transport:"stdio",request:{id:e.id,timestamp:i,params:e.params},response:{timestamp:c,result:t.result,error:t.error},duration:a})}cleanupStale(e){const r=this.pendingRequests.get(e);r&&Date.now()-r.timestamp>this.TIMEOUT&&(this.debug&&console.error(`[mcp-logger CLI] ⏰ Request timeout: ${r.request.method} (ID: ${e}) → Creating request-only span`),this.createRequestOnlySpan(r.request,r.timestamp),this.pendingRequests.delete(e))}createRequestOnlySpan(e,t){!function(e){const t=r();if(!t)return void console.error("[MCP Logger] Tracer not initialized, cannot create span");const i="mcp."+e.method;t.startActiveSpan(i,r=>{try{const t={"mcp.source":e.source,"mcp.transport":e.transport,"mcp.request.id":e.request.id+"","mcp.request.method":e.method,"mcp.request.timestamp":e.request.timestamp,"mcp.request.params":n(e.request.params)||"{}","mcp.request.params.size":JSON.stringify(e.request.params||{}).length};if("tools/call"===e.method&&e.request.params){const r=e.request.params.name,s=e.request.params.arguments;if(r&&(t["mcp.tool.name"]=r),s){const e=n(s);e&&(t["mcp.tool.arguments"]=e,t["mcp.tool.arguments.size"]=JSON.stringify(s).length)}}if("cli"===e.source){const e=s();e&&(t["mcp.cli.server"]=JSON.stringify({command:e.command,args:e.args,env:e.env}))}r.setStatus({code:d.OK}),o(r,t)}catch(e){console.error("[MCP Logger] Error creating request-only span:",e),r.setStatus({code:d.ERROR,message:e+""})}finally{r.end()}})}({method:e.method,source:"cli",transport:"stdio",request:{id:e.id,timestamp:t,params:e.params}})}createResponseOnlySpan(e,t){!function(e){const t=r();if(!t)return void console.error("[MCP Logger] Tracer not initialized, cannot create span");const i="mcp."+e.method;t.startActiveSpan(i,r=>{try{const t={"mcp.source":e.source,"mcp.transport":e.transport,"mcp.response.id":e.response.id+"","mcp.response.method":e.method,"mcp.response.timestamp":e.response.timestamp};if(void 0!==e.response.result){const r=n(e.response.result);r&&(t["mcp.response.result"]=r,t["mcp.response.result.size"]=JSON.stringify(e.response.result).length)}if(e.response.error){let s;t["mcp.error"]=!0,s=e.response.error instanceof Error?e.response.error.message:"string"==typeof e.response.error?e.response.error:n(e.response.error)||"Unknown error",t["mcp.error.message"]=s,e.response.error instanceof Error&&r.recordException(e.response.error),r.setStatus({code:d.ERROR,message:s})}else r.setStatus({code:d.OK});if("cli"===e.source){const e=s();e&&(t["mcp.cli.server"]=JSON.stringify({command:e.command,args:e.args,env:e.env}))}o(r,t)}catch(e){console.error("[MCP Logger] Error creating response-only span:",e),r.setStatus({code:d.ERROR,message:e+""})}finally{r.end()}})}({method:e.method||"same_request_method",source:"cli",transport:"stdio",response:{id:e.id,timestamp:t,result:e.result,error:e.error}})}getStats(){return{pending:this.pendingRequests.size}}clear(){this.debug&&console.error(`[mcp-logger CLI] Clearing ${this.pendingRequests.size} pending requests`),this.pendingRequests.clear()}}c.name("mcp-logger").description("Add observability to any MCP server without code changes").version("1.0.0").requiredOption("-k, --api-key <key>","Aware API key").option("-s, --service-name <name>","Service name for identification").option("-e, --endpoint <url>","Custom OTLP endpoint").argument("<command...>","MCP server command to wrap").action(async(e,r)=>{try{const s=!1;!function(e){if(q)return y;const r=e.endpoint||"https://aware.mcypher.com/v1/traces",s=e.serviceName||"mcp-server-"+Math.random().toString(36).slice(2,8);f=new a({resource:new m({"service.name":s,"service.version":g}),traceExporter:new p({url:r,headers:{"x-api-key":e.apiKey}})}),f.start(),y=u.getTracer("mcp-logger",g),q=!0;const o=async()=>{await t()};process.once("SIGTERM",o),process.once("SIGINT",o)}({...r,debug:s}),console.error("[MCP Logger CLI] Starting MCP server:",e.join(" "));const[o,...n]=e;!function(e,r){S={command:e,args:r,env:{}}}(o,n);const c=i(o,n,{stdio:["pipe","pipe","inherit"],env:{...process.env,MCP_LOGGER_ENABLED:"true"}}),d=new C(s),l=new v("request",d,s);process.stdin.pipe(l).pipe(c.stdin);const h=new v("response",d,s);c.stdout.pipe(h).pipe(process.stdout),c.on("error",async e=>{console.error("[MCP Logger CLI] Failed to start MCP server:",e),d.clear(),await t(),process.exit(1)}),c.on("exit",async(e,r)=>{console.error(`[MCP Logger CLI] MCP server exited with code ${e}, signal ${r}`),d.clear(),await t(),process.exit(e||0)});let R=!1;const O=async e=>{R||(R=!0,console.error(`[MCP Logger CLI] Received ${e}, shutting down...`),c.kill(e),await Promise.race([new Promise(e=>c.once("exit",e)),new Promise(e=>setTimeout(e,5e3))]),await t(),process.exit(0))};process.on("SIGTERM",()=>O("SIGTERM")),process.on("SIGINT",()=>O("SIGINT"))}catch(e){console.error("[MCP Logger CLI] Fatal error:",e),await t(),process.exit(1)}}),c.parse();
|
package/package.json
CHANGED