@awarecorp/mcp-logger 0.0.11 → 0.0.13
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/cli/index.js +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
function t(...t){console.error("[mcp-logger]",...t)}function e(...t){M&&console.error("[mcp-logger]",...t)}function s(...t){C&&console.error("[mcp-logger]",...t)}function i(t){return!D.includes(t)}function n(t,e=2e5){try{const s=JSON.stringify(t);return s.length>e?s.slice(0,e)+"... (truncated)":s}catch{return null}}function r(t,e){return t.startsWith("resources/")?{type:t.split("/")[1],uri:e?.uri||e?.path||e?.resource}:t.startsWith("prompts/")?{type:"prompt",uri:e?.name||e?.promptId}:"tools/call"===t?{type:"tool",uri:e?.name}:e?.resourceType&&e?.resourceUri?{type:e.resourceType,uri:e.resourceUri}:{type:void 0,uri:void 0}}function o(t,e,s,i,n){const o=function(t,e){const s=t?.getClientInfo();if(s?.name||s?.version)return{name:s.name,version:s.version};const i=t?.getHeaders()||e;if(i){const t=i["user-agent"]||i["User-Agent"];if(t){const e=t.match(/^([^\/]+)\/([^\s]+)/);if(e)return{name:e[1],version:e[2]}}}return{name:void 0,version:void 0}}(i,n),a=`${o.name||"unknown"}-${o.version||"0"}`,p=T.getOrCreateSessionId(a),c=T.getOrCreateConversationId(p,t),u=function(t,e){return t?.userId||t?.user_id?t.userId||t.user_id:e?e["x-user-id"]||e["X-User-Id"]:void 0}(e,n),h=function(t){if(t?.permission||t?.permissionLevel)return t.permission||t.permissionLevel}(e),d=r(t,e);d.uri&&T.trackResourceAccess(d.uri);const m=function(t,e){return void 0!==t?.cost?t.cost:void 0!==e?.cost?e.cost:void 0}(e,s),l={};return p&&(l.sessionId=p),c&&(l.conversationId=c),u&&(l.userId=u),o.name&&(l.clientName=o.name),o.version&&(l.clientVersion=o.version),h&&(l.permissionLevel=h),void 0!==m&&(l.cost=m),l}function a(t){O.build(t)}import{program as p}from"commander";import{NodeSDK as c}from"@opentelemetry/sdk-node";import{OTLPTraceExporter as u}from"@opentelemetry/exporter-trace-otlp-http";import{Resource as h}from"@opentelemetry/resources";import{trace as d,SpanStatusCode as m}from"@opentelemetry/api";import{readFileSync as l}from"fs";import{fileURLToPath as f}from"url";import{dirname as v,join as g}from"path";import{execSync as I,spawn as y}from"child_process";import{Transform as S}from"stream";import{ulid as x}from"ulid";const M="true"===process.env.AWARE_DEBUG||"1"===process.env.AWARE_DEBUG,C="true"===process.env.AWARE_RAW_DEBUG||"1"===process.env.AWARE_RAW_DEBUG,w={ENDPOINT:"https://api.awarecorp.io/traces",SDK_VERSION:function(){try{const t=f(import.meta.url),e=v(t),s=g(e,"..","..","package.json");return JSON.parse(l(s,"utf-8")).version||"1.0.0"}catch{return"1.0.0"}}(),SERVICE_NAME_PREFIX:"mcp-server"},D=["notifications/initialized"],E=new class{sdk=null;tracer=null;initialized=!1;cliServerInfo=null;initialize(t){if(this.initialized)return e("Telemetry already initialized, returning existing tracer"),this.tracer;const s=t.endpoint||w.ENDPOINT,i=t.serviceName||`${w.SERVICE_NAME_PREFIX}-${Math.random().toString(36).slice(2,8)}`,n=t.serviceVersion||"unknown";e("Initializing telemetry..."),e("Endpoint: "+s),e("Service: "+i),e("Version: "+n),this.sdk=new c({resource:new h({"service.name":i,"service.version":n}),traceExporter:new u({url:s,headers:{"x-api-key":t.apiKey}})}),this.sdk.start(),this.tracer=d.getTracer("mcp-logger",w.SDK_VERSION),this.initialized=!0,e("Telemetry initialized successfully");const r=async()=>{e("Shutting down telemetry..."),await this.shutdown()};return process.once("SIGTERM",r),process.once("SIGINT",r),this.tracer}getTracer(){return this.tracer}isInitialized(){return this.initialized}setCLIServerInfo(t,e,s){this.cliServerInfo={command:t,args:e,env:s}}getCLIServerInfo(){return this.cliServerInfo}async shutdown(){if(this.sdk)try{await this.sdk.shutdown(),this.sdk=null,this.tracer=null,this.initialized=!1,this.cliServerInfo=null}catch(t){console.error("[mcp-logger] Error shutting down telemetry:",t)}}},R=new Set(["npx","node","uvx","python","python3","pip","pipx","deno","bun"]),q=new Set(["uvx","python","python3","pip","pipx"]);class N extends S{buffer="";direction;logger;sessionContextStore;constructor(t,e,s){super(),this.direction=t,this.logger=e,this.sessionContextStore=s}_transform(t,s,i){try{if("request"===this.direction)return this.push(t),this.buffer+=t.toString(),this.processBuffer(!1),void i();this.buffer+=t.toString(),this.buffer.length>1e6&&(e("Buffer size exceeded, clearing..."),this.buffer=""),this.processBuffer(!0),i()}catch(t){i(t)}}processBuffer(t){const i=this.buffer.split("\n");this.buffer=i.pop()||"";for(const n of i){const i=n.trim();if(i)try{const n=JSON.parse(i);if(t){if("2.0"!==n.jsonrpc){e("Non-JSON-RPC JSON ignored:",i.slice(0,100));continue}this.push(i+"\n")}s(`[${this.direction}] Raw message:`,i),this.handleMessage(n)}catch{e(t?"Non-JSON output filtered:":"Failed to parse:",i.slice(0,100))}}}isValidInfo(t){return!(!t?.name||!t?.version)}handleMessage(t){if("request"===this.direction&&"initialize"===t.method&&t.params?.clientInfo&&!this.isValidInfo(this.sessionContextStore.getClientInfo())){const e=t.params;this.sessionContextStore.setClientInfo({name:e.clientInfo?.name,version:e.clientInfo?.version})}if("response"===this.direction&&void 0!==t.id&&!t.method){const e=t;if(e.result?.serverInfo&&!this.isValidInfo(this.sessionContextStore.getServerInfo())){const t=e.result.serverInfo;this.sessionContextStore.setServerInfo({name:t.name,version:t.version})}}"request"===this.direction&&t.method?this.logger.onRequest(t):"response"===this.direction&&(void 0===t.id||t.method?t.method&&null==t.id&&this.logger.onNotification(t):this.logger.onResponse(t))}_flush(t){try{if(this.buffer.trim())try{const t=JSON.parse(this.buffer);"response"===this.direction&&"2.0"===t.jsonrpc&&this.push(this.buffer.trim()+"\n"),this.handleMessage(t)}catch{"request"===this.direction&&this.push(this.buffer),e("Failed to parse final buffer")}M&&e("Stream closed. Pending requests: "+this.logger.getStats().pending),t()}catch(e){t(e)}}}const T=new class{sessionMap=new Map;sessionCounter=0;conversationMap=new Map;conversationCounter=0;resourceAccessCount=new Map;getOrCreateSessionId(t){if(!this.sessionMap.has(t)){const e=x();this.sessionMap.set(t,e),this.sessionCounter++}return this.sessionMap.get(t)}getOrCreateConversationId(t,e){const s=`${t}-${e}`;return this.conversationMap.has(s)||this.conversationMap.set(s,"conv-"+ ++this.conversationCounter),this.conversationMap.get(s)}trackResourceAccess(t){const e=(this.resourceAccessCount.get(t)||0)+1;return this.resourceAccessCount.set(t,e),e}getResourceAccessCount(t){return this.resourceAccessCount.get(t)||0}clear(){this.sessionMap.clear(),this.conversationMap.clear(),this.resourceAccessCount.clear(),this.sessionCounter=0,this.conversationCounter=0}},O=new class{spanData;input;contextMetadata;build(t){const e=E.getTracer();e&&(this.input=t,e.startActiveSpan("mcp."+t.method,t=>{try{this.spanData=this.buildBase(),this.resolveContextMetadata(),this.applyTraceId(),this.applyRequestFields(),this.applyResponseFields(),this.applyDuration(),this.applyCLIServerInfo(),this.applyMCPServerInfo(),this.applyContextMetadata(),this.applyResourceMetadata(),this.applyCustomEvents(t),this.applyError(t),function(t,e){for(const[s,i]of Object.entries(e))null!=i&&t.setAttribute(s,i)}(t,this.spanData),s("[OTLP] Span data:",JSON.stringify(this.spanData,null,2))}catch{t.setStatus({code:m.ERROR,message:"Error creating span"})}finally{t.end()}}))}buildBase(){return{"ingest.type":"mcp","mcp.type":this.input.type,"mcp.transport":this.input.transport,"mcp.method":this.input.method,"mcp.source":this.input.source}}resolveContextMetadata(){this.contextMetadata=this.input.contextMetadata||o(this.input.method,this.input.params,this.input.result,void 0,this.input.headers)}applyTraceId(){this.contextMetadata.sessionId&&this.contextMetadata.conversationId&&(this.spanData["mcp.trace.id"]=`${this.contextMetadata.sessionId}:${this.contextMetadata.conversationId}`)}applyRequestFields(){if("paired"===this.input.type||"request"===this.input.type||"notification"===this.input.type){if(void 0!==this.input.requestId&&(this.spanData["mcp.request.id"]=this.input.requestId+""),this.spanData["mcp.request.method"]=this.input.method,void 0!==this.input.requestTimestamp&&(this.spanData["mcp.request.timestamp"]=this.input.requestTimestamp),void 0!==this.input.params&&(this.spanData["mcp.request.params"]=n(this.input.params)||"{}",this.spanData["mcp.request.params.size"]=JSON.stringify(this.input.params||{}).length),"tools/call"===this.input.method&&this.input.params){const t=this.input.params.name,e=this.input.params.arguments;if(t&&(this.spanData["mcp.tool.name"]=t),e){const t=n(e);t&&(this.spanData["mcp.tool.arguments"]=t,this.spanData["mcp.tool.arguments.size"]=JSON.stringify(e).length)}}if(this.input.headers){const t=n(this.input.headers);t&&(this.spanData["mcp.headers"]=t,this.spanData["mcp.headers.size"]=JSON.stringify(this.input.headers).length)}}}applyResponseFields(){if(("paired"===this.input.type||"response"===this.input.type)&&(void 0!==this.input.responseId&&(this.spanData["mcp.response.id"]=this.input.responseId+""),this.spanData["mcp.response.method"]=this.input.method,void 0!==this.input.responseTimestamp&&(this.spanData["mcp.response.timestamp"]=this.input.responseTimestamp),void 0!==this.input.result)){const t=n(this.input.result);t&&(this.spanData["mcp.response.result"]=t,this.spanData["mcp.response.result.size"]=JSON.stringify(this.input.result).length)}}applyDuration(){void 0!==this.input.durationMs&&(this.spanData["mcp.duration_ms"]=this.input.durationMs)}applyCLIServerInfo(){const t=E.getCLIServerInfo();t&&(this.spanData["mcp.cli"]=JSON.stringify({command:t.command,args:t.args,env:t.env}))}applyMCPServerInfo(){this.input.serverInfo&&(this.input.serverInfo.name&&(this.spanData["mcp.sdk.name"]=this.input.serverInfo.name),this.input.serverInfo.version&&(this.spanData["mcp.sdk.version"]=this.input.serverInfo.version))}applyContextMetadata(){this.contextMetadata.sessionId&&(this.spanData["mcp.session.id"]=this.contextMetadata.sessionId),this.contextMetadata.conversationId&&(this.spanData["mcp.conversation.id"]=this.contextMetadata.conversationId),this.contextMetadata.userId&&(this.spanData["mcp.user.id"]=this.contextMetadata.userId),this.contextMetadata.clientName&&(this.spanData["mcp.client.name"]=this.contextMetadata.clientName),this.contextMetadata.clientVersion&&(this.spanData["mcp.client.version"]=this.contextMetadata.clientVersion),this.contextMetadata.permissionLevel&&(this.spanData["mcp.permission.level"]=this.contextMetadata.permissionLevel),void 0!==this.contextMetadata.cost&&(this.spanData["mcp.cost"]=this.contextMetadata.cost)}applyResourceMetadata(){const t=function(t,e){const s=r(t,e);if(!s.uri)return{};const i=T.getResourceAccessCount(s.uri);return{resourceType:s.type,resourceUri:s.uri,resourceAccessCount:i}}(this.input.method,this.input.params);t.resourceType&&(this.spanData["mcp.resource.type"]=t.resourceType),t.resourceUri&&(this.spanData["mcp.resource.uri"]=t.resourceUri),t.resourceAccessCount&&(this.spanData["mcp.resource.access_count"]=t.resourceAccessCount)}applyCustomEvents(t){this.input.customEvents&&0!==this.input.customEvents.length&&(this.spanData["mcp.events"]=JSON.stringify(this.input.customEvents),this.spanData["mcp.events.count"]=this.input.customEvents.length,this.input.customEvents.forEach(e=>{t.addEvent("custom."+(e.level||"info"),{message:e.message,metadata:JSON.stringify(e.metadata||{}),timestamp:e.timestamp||Date.now()})}))}applyError(t){if(this.input.error){let e;this.spanData["mcp.error"]=!0,this.input.error instanceof Error?(e=this.input.error.message,t.recordException(this.input.error)):e="string"==typeof this.input.error?this.input.error:n(this.input.error)||"Unknown error",this.spanData["mcp.error.message"]=e,t.setStatus({code:m.ERROR,message:e})}else t.setStatus({code:m.OK})}};class k{pendingRequests=new Map;TIMEOUT=3e4;sessionContextStore;constructor(t){this.sessionContextStore=t}onRequest(t){if(i(t.method)){if(null==t.id){const e=o(t.method,t.params,void 0,this.sessionContextStore,void 0);return void a({type:"notification",method:t.method,transport:"stdio",source:"cli",params:t.params,contextMetadata:e})}"initialize"===t.method&&t.params?.clientInfo&&this.sessionContextStore.setClientInfo({name:t.params.clientInfo.name,version:t.params.clientInfo.version}),this.pendingRequests.set(t.id,{request:t,timestamp:Date.now()}),setTimeout(()=>this.handleTimeout(t.id),this.TIMEOUT)}}onResponse(t){if(null==t.id)return;const e=this.pendingRequests.get(t.id),s=Date.now(),i=e?.request.method||t.method||"unknown";let n=this.sessionContextStore.getServerInfo();"initialize"===e?.request.method&&t.result?.serverInfo&&(n={name:t.result.serverInfo.name,version:t.result.serverInfo.version});const r=o(i,e?.request.params,t.result,this.sessionContextStore,void 0);e?(a({type:"paired",method:i,transport:"stdio",source:"cli",requestId:e.request.id,requestTimestamp:e.timestamp,params:e.request.params,responseId:t.id,responseTimestamp:s,result:t.result,error:t.error,durationMs:s-e.timestamp,contextMetadata:r,serverInfo:n}),this.pendingRequests.delete(t.id)):a({type:"response",method:i,transport:"stdio",source:"cli",responseId:t.id,responseTimestamp:s,result:t.result,error:t.error,contextMetadata:r,serverInfo:n})}onNotification(t){if(!i(t.method))return;const e=o(t.method,t.params,void 0,this.sessionContextStore,void 0);a({type:"notification",method:t.method,transport:"stdio",source:"cli",params:t.params,contextMetadata:e})}handleTimeout(t){const e=this.pendingRequests.get(t);if(e&&Date.now()-e.timestamp>this.TIMEOUT){const s=o(e.request.method,e.request.params,void 0,this.sessionContextStore,void 0);a({type:"request",method:e.request.method,transport:"stdio",source:"cli",requestId:e.request.id,requestTimestamp:e.timestamp,params:e.request.params,contextMetadata:s}),this.pendingRequests.delete(t)}}getStats(){return{pending:this.pendingRequests.size}}clear(){this.pendingRequests.clear()}}class A{context={};getClientInfo(){return this.context.clientInfo}setClientInfo(t){this.context.clientInfo=t}getServerInfo(){return this.context.serverInfo}setServerInfo(t){this.context.serverInfo=t}getHeaders(){return this.context.headers}setHeaders(t){this.context.headers=t}snapshot(){return{clientInfo:this.context.clientInfo?{...this.context.clientInfo}:void 0,serverInfo:this.context.serverInfo?{...this.context.serverInfo}:void 0,headers:this.context.headers?{...this.context.headers}:void 0}}}class b{process;logger;isShuttingDown=!1;constructor(t,e){const s=new A;this.logger=new k(s),this.process=y(t,e,{stdio:["pipe","pipe","inherit"],env:{...process.env,MCP_LOGGER_ENABLED:"true"}});const i=new N("request",this.logger,s),n=new N("response",this.logger,s);process.stdin.pipe(i).pipe(this.process.stdin),this.process.stdout.pipe(n).pipe(process.stdout),this.process.on("error",t=>this.handleError(t)),this.process.on("exit",(t,e)=>this.handleExit(t,e)),process.on("SIGTERM",()=>this.shutdown("SIGTERM")),process.on("SIGINT",()=>this.shutdown("SIGINT"))}async handleError(e){t("Failed to start MCP server:",e),await this.cleanup(),process.exit(1)}async handleExit(t,s){e(`MCP server exited with code ${t}, signal ${s}`),await this.cleanup(),process.exit(t||0)}async shutdown(t){this.isShuttingDown||(this.isShuttingDown=!0,e(`Received ${t}, shutting down...`),this.process.kill(t),await Promise.race([new Promise(t=>this.process.once("exit",t)),new Promise(t=>setTimeout(t,5e3))]),await this.cleanup(),process.exit(0))}async cleanup(){this.logger.clear(),await async function(){await E.shutdown()}()}}p.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("-e, --endpoint <url>","Custom OTLP endpoint").argument("<command...>","MCP server command to wrap").action(async(e,s)=>{const i=function(t){const e={};for(const s of t){const t=process.env[s];void 0!==t&&(e[s]=t)}return e}(function(){try{return I("aware mcpenv sync",{encoding:"utf-8",timeout:1e4,stdio:["pipe","pipe","pipe"]}),I("aware mcpenv keys",{encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim().split("\n").filter(t=>t.length>0)}catch{return[]}}()),[n,...r]=e,o=function(t,e){const s=function(t){for(const e of t){if(R.has(e))continue;const t=e.match(/^(@[^@]+\/[^@]+)@(.+)$/);if(t)return{packageName:t[1],version:t[2]};const s=e.match(/^([^@]+)@(.+)$/);if(s)return{packageName:s[1],version:s[2]};const i=e.match(/^(@[^@]+\/[^@]+)$/);if(i)return{packageName:i[1],version:"latest"};if(e.match(/^[a-z0-9-]+$/)&&!e.includes("/"))return{packageName:e,version:"latest"}}return null}(e.filter(t=>!t.startsWith("-")));let i,n;if(i=s?.packageName?s.packageName:t.split("/").pop()||t||w.SERVICE_NAME_PREFIX+"-unknown",s&&(n=s.version,"latest"===s.version)){const e=q.has(t)?"pip":"npm",i=function(t,e){try{if("pip"===e){let e=null;for(const s of["pip3","pip"])try{e=I(`${s} index versions ${t}`,{encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]});break}catch{continue}if(!e)return null;const s=e.match(/\(([^)]+)\)/);if(s)return s[1];const i=e.match(/Available versions:\s*([^\s,]+)/);return i?i[1]:null}{const e=I(`npm view ${t} version --json`,{encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim().replace(/^["']|["']$/g,""),s=e.match(/^(\d+\.\d+\.\d+(?:-[\w.]+)?)/);return s?s[1]:e}}catch{return null}}(s.packageName,e);i&&(n=i)}return{name:i,version:n}}(n,r);!function(t){E.initialize(t)}({...s,serviceName:o.name,serviceVersion:o.version}),t("Starting MCP server: "+e.join(" ")),t(`Service: ${o.name} = ${o.version||"unknown"}`),function(t,e,s){E.setCLIServerInfo(t,e,s)}(n,r,i),new b(n,r)}),p.parse();
|
|
2
|
+
function e(...e){console.error("[mcp-logger]",...e)}function t(...e){R&&console.error("[mcp-logger]",...e)}function s(...e){N&&console.error("[mcp-logger]",...e)}function i(e){return!E.includes(e)}function n(e){return b.includes(e)}function r(){let e=null,t=null;try{e=w("pinta identity id",{encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim()||null}catch{}try{t=w("pinta identity email",{encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim()||null}catch{}return{id:e,email:t}}function o(e,t=2e5){try{const s=JSON.stringify(e);return s.length>t?s.slice(0,t)+"... (truncated)":s}catch{return null}}function a(e,t){return e.startsWith("resources/")?{type:e.split("/")[1],uri:t?.uri||t?.path||t?.resource}:e.startsWith("prompts/")?{type:"prompt",uri:t?.name||t?.promptId}:"tools/call"===e?{type:"tool",uri:t?.name}:t?.resourceType&&t?.resourceUri?{type:t.resourceType,uri:t.resourceUri}:{type:void 0,uri:void 0}}function c(e,t,s,i,n){const r=function(e,t){const s=e?.getClientInfo();if(s?.name||s?.version)return{name:s.name,version:s.version};const i=e?.getHeaders()||t;if(i){const e=i["user-agent"]||i["User-Agent"];if(e){const t=e.match(/^([^\/]+)\/([^\s]+)/);if(t)return{name:t[1],version:t[2]}}}return{name:void 0,version:void 0}}(i,n),o=`${r.name||"unknown"}-${r.version||"0"}`,c=k.getOrCreateSessionId(o),p=k.getOrCreateConversationId(c,e),u=function(e,t){return e?.userId||e?.user_id?e.userId||e.user_id:t?t["x-user-id"]||t["X-User-Id"]:void 0}(t,n),d=function(e){if(e?.permission||e?.permissionLevel)return e.permission||e.permissionLevel}(t),h=a(e,t);h.uri&&k.trackResourceAccess(h.uri);const l=function(e,t){return void 0!==e?.cost?e.cost:void 0!==t?.cost?t.cost:void 0}(t,s),m={};return c&&(m.sessionId=c),p&&(m.conversationId=p),u&&(m.userId=u),r.name&&(m.clientName=r.name),r.version&&(m.clientVersion=r.version),d&&(m.permissionLevel=d),void 0!==l&&(m.cost=l),m}function p(e){$.build(e)}function u(e){const t=new Uint8Array(e/2);return crypto.getRandomValues(t),Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}import{program as d}from"commander";import{NodeSDK as h}from"@opentelemetry/sdk-node";import{OTLPTraceExporter as l}from"@opentelemetry/exporter-trace-otlp-http";import{Resource as m}from"@opentelemetry/resources";import{trace as f,SpanStatusCode as g}from"@opentelemetry/api";import{readFileSync as v}from"fs";import{fileURLToPath as y}from"url";import{dirname as I,join as S}from"path";import{execSync as w,spawn as x}from"child_process";import{Transform as M}from"stream";import{ulid as C}from"ulid";const R="true"===process.env.PINTA_DEBUG||"1"===process.env.PINTA_DEBUG,N="true"===process.env.PINTA_RAW_DEBUG||"1"===process.env.PINTA_RAW_DEBUG,D={ENDPOINT:"https://api.awarecorp.io",SDK_VERSION:function(){try{const e=y(import.meta.url),t=I(e),s=S(t,"..","..","package.json");return JSON.parse(v(s,"utf-8")).version||"1.0.0"}catch{return"1.0.0"}}(),SERVICE_NAME_PREFIX:"mcp-server"},E=["notifications/initialized"],b=["tools/call","resources/read"],q=new class{sdk=null;tracer=null;initialized=!1;cliServerInfo=null;initialize(e){if(this.initialized)return t("Telemetry already initialized, returning existing tracer"),this.tracer;const s=e.endpoint||D.ENDPOINT,i=e.serviceName||`${D.SERVICE_NAME_PREFIX}-${Math.random().toString(36).slice(2,8)}`,n=e.serviceVersion||"unknown";t("Initializing telemetry..."),t("Endpoint: "+s),t("Service: "+i),t("Version: "+n);const r={"service.name":i,"service.version":n};e.memberIdentity?.id&&(r["member.identity.id"]=e.memberIdentity.id),e.memberIdentity?.email&&(r["member.identity.email"]=e.memberIdentity.email),this.sdk=new h({resource:new m(r),traceExporter:new l({url:s.replace(/\/$/,"")+"/traces",headers:{"x-api-key":e.apiKey}})}),this.sdk.start(),this.tracer=f.getTracer("mcp-logger",D.SDK_VERSION),this.initialized=!0,t("Telemetry initialized successfully");const o=async()=>{t("Shutting down telemetry..."),await this.shutdown()};return process.once("SIGTERM",o),process.once("SIGINT",o),this.tracer}getTracer(){return this.tracer}isInitialized(){return this.initialized}setCLIServerInfo(e,t,s){this.cliServerInfo={command:e,args:t,env:s}}getCLIServerInfo(){return this.cliServerInfo}async shutdown(){if(this.sdk)try{await this.sdk.shutdown(),this.sdk=null,this.tracer=null,this.initialized=!1,this.cliServerInfo=null}catch(e){console.error("[mcp-logger] Error shutting down telemetry:",e)}}},T=new Set(["npx","node","uvx","python","python3","pip","pipx","deno","bun"]),O=new Set(["uvx","python","python3","pip","pipx"]),k=new class{sessionMap=new Map;sessionCounter=0;conversationMap=new Map;conversationCounter=0;resourceAccessCount=new Map;getOrCreateSessionId(e){if(!this.sessionMap.has(e)){const t=C();this.sessionMap.set(e,t),this.sessionCounter++}return this.sessionMap.get(e)}getOrCreateConversationId(e,t){const s=`${e}-${t}`;return this.conversationMap.has(s)||this.conversationMap.set(s,"conv-"+ ++this.conversationCounter),this.conversationMap.get(s)}trackResourceAccess(e){const t=(this.resourceAccessCount.get(e)||0)+1;return this.resourceAccessCount.set(e,t),t}getResourceAccessCount(e){return this.resourceAccessCount.get(e)||0}clear(){this.sessionMap.clear(),this.conversationMap.clear(),this.resourceAccessCount.clear(),this.sessionCounter=0,this.conversationCounter=0}};class A{spanData;input;contextMetadata;buildAttributes(e){if(this.input=e,this.spanData=this.buildBase(),this.resolveContextMetadata(),this.applyTraceId(),this.applyRequestFields(),this.applyResponseFields(),this.applyDuration(),this.applyCLIServerInfo(),this.applyMCPServerInfo(),this.applyContextMetadata(),this.applyResourceMetadata(),this.input.customEvents&&this.input.customEvents.length>0&&(this.spanData["mcp.events"]=JSON.stringify(this.input.customEvents),this.spanData["mcp.events.count"]=this.input.customEvents.length),e.error){this.spanData["mcp.error"]=!0;const t="string"==typeof e.error?e.error:e.error instanceof Error?e.error.message:o(e.error)||"Unknown error";this.spanData["mcp.error.message"]=t}return{...this.spanData}}build(e){const t=q.getTracer();t&&(this.input=e,t.startActiveSpan("mcp."+e.method,e=>{try{this.spanData=this.buildBase(),this.resolveContextMetadata(),this.applyTraceId(),this.applyRequestFields(),this.applyResponseFields(),this.applyDuration(),this.applyCLIServerInfo(),this.applyMCPServerInfo(),this.applyContextMetadata(),this.applyResourceMetadata(),this.applyCustomEvents(e),this.applyError(e),function(e,t){for(const[s,i]of Object.entries(t))null!=i&&e.setAttribute(s,i)}(e,this.spanData),s("[OTLP] Span data:",JSON.stringify(this.spanData,null,2))}catch{e.setStatus({code:g.ERROR,message:"Error creating span"})}finally{e.end()}}))}buildBase(){return{"ingest.type":"mcp","mcp.type":this.input.type,"mcp.transport":this.input.transport,"mcp.method":this.input.method,"mcp.source":this.input.source}}resolveContextMetadata(){this.contextMetadata=this.input.contextMetadata||c(this.input.method,this.input.params,this.input.result,void 0,this.input.headers)}applyTraceId(){this.contextMetadata.sessionId&&this.contextMetadata.conversationId&&(this.spanData["mcp.trace.id"]=`${this.contextMetadata.sessionId}:${this.contextMetadata.conversationId}`)}applyRequestFields(){if("paired"===this.input.type||"request"===this.input.type||"notification"===this.input.type){if(void 0!==this.input.requestId&&(this.spanData["mcp.request.id"]=this.input.requestId+""),this.spanData["mcp.request.method"]=this.input.method,void 0!==this.input.requestTimestamp&&(this.spanData["mcp.request.timestamp"]=this.input.requestTimestamp),void 0!==this.input.params&&(this.spanData["mcp.request.params"]=o(this.input.params)||"{}",this.spanData["mcp.request.params.size"]=JSON.stringify(this.input.params||{}).length),"tools/call"===this.input.method&&this.input.params){const e=this.input.params.name,t=this.input.params.arguments;if(e&&(this.spanData["mcp.tool.name"]=e),t){const e=o(t);e&&(this.spanData["mcp.tool.arguments"]=e,this.spanData["mcp.tool.arguments.size"]=JSON.stringify(t).length)}}if(this.input.headers){const e=o(this.input.headers);e&&(this.spanData["mcp.headers"]=e,this.spanData["mcp.headers.size"]=JSON.stringify(this.input.headers).length)}}}applyResponseFields(){if(("paired"===this.input.type||"response"===this.input.type)&&(void 0!==this.input.responseId&&(this.spanData["mcp.response.id"]=this.input.responseId+""),this.spanData["mcp.response.method"]=this.input.method,void 0!==this.input.responseTimestamp&&(this.spanData["mcp.response.timestamp"]=this.input.responseTimestamp),void 0!==this.input.result)){const e=o(this.input.result);e&&(this.spanData["mcp.response.result"]=e,this.spanData["mcp.response.result.size"]=JSON.stringify(this.input.result).length)}}applyDuration(){void 0!==this.input.durationMs&&(this.spanData["mcp.duration_ms"]=this.input.durationMs)}applyCLIServerInfo(){const e=q.getCLIServerInfo();e&&(this.spanData["mcp.cli"]=JSON.stringify({command:e.command,args:e.args,env:e.env}))}applyMCPServerInfo(){this.input.serverInfo&&(this.input.serverInfo.name&&(this.spanData["mcp.sdk.name"]=this.input.serverInfo.name),this.input.serverInfo.version&&(this.spanData["mcp.sdk.version"]=this.input.serverInfo.version))}applyContextMetadata(){this.contextMetadata.sessionId&&(this.spanData["mcp.session.id"]=this.contextMetadata.sessionId),this.contextMetadata.conversationId&&(this.spanData["mcp.conversation.id"]=this.contextMetadata.conversationId),this.contextMetadata.userId&&(this.spanData["mcp.user.id"]=this.contextMetadata.userId),this.contextMetadata.clientName&&(this.spanData["mcp.client.name"]=this.contextMetadata.clientName),this.contextMetadata.clientVersion&&(this.spanData["mcp.client.version"]=this.contextMetadata.clientVersion),this.contextMetadata.permissionLevel&&(this.spanData["mcp.permission.level"]=this.contextMetadata.permissionLevel),void 0!==this.contextMetadata.cost&&(this.spanData["mcp.cost"]=this.contextMetadata.cost)}applyResourceMetadata(){const e=function(e,t){const s=a(e,t);if(!s.uri)return{};const i=k.getResourceAccessCount(s.uri);return{resourceType:s.type,resourceUri:s.uri,resourceAccessCount:i}}(this.input.method,this.input.params);e.resourceType&&(this.spanData["mcp.resource.type"]=e.resourceType),e.resourceUri&&(this.spanData["mcp.resource.uri"]=e.resourceUri),e.resourceAccessCount&&(this.spanData["mcp.resource.access_count"]=e.resourceAccessCount)}applyCustomEvents(e){this.input.customEvents&&0!==this.input.customEvents.length&&(this.spanData["mcp.events"]=JSON.stringify(this.input.customEvents),this.spanData["mcp.events.count"]=this.input.customEvents.length,this.input.customEvents.forEach(t=>{e.addEvent("custom."+(t.level||"info"),{message:t.message,metadata:JSON.stringify(t.metadata||{}),timestamp:t.timestamp||Date.now()})}))}applyError(e){if(this.input.error){let t;this.spanData["mcp.error"]=!0,this.input.error instanceof Error?(t=this.input.error.message,e.recordException(this.input.error)):t="string"==typeof this.input.error?this.input.error:o(this.input.error)||"Unknown error",this.spanData["mcp.error.message"]=t,e.setStatus({code:g.ERROR,message:t})}else e.setStatus({code:g.OK})}}const $=new A,P=new Set(["initialize","ping","tools/list","resources/list","resources/templates/list","prompts/list"]);class G extends M{buffer="";direction;logger;sessionContextStore;guardClient;guardRequestIds;guardRequestMethods;configError;writeToStdout=null;constructor(e,t,s,i,n,r,o){super(),this.direction=e,this.logger=t,this.sessionContextStore=s,this.guardClient=i||null,this.guardRequestIds=n||null,this.guardRequestMethods=r||null,this.configError=o||null}_transform(e,i,n){try{if("request"===this.direction){this.buffer+=e.toString();const i=this.buffer.split("\n");if(this.buffer=i.pop()||"",this.configError)return this.processRequestWithConfigError(i),void n();if(!this.guardClient){this.push(e);for(const e of i){const i=e.trim();if(i)try{const e=JSON.parse(i);s(`[${this.direction}] Raw message:`,i),this.handleMessage(e)}catch{t("Failed to parse:",i.slice(0,100))}}return void n()}return void this.processRequestWithGuard(i).then(()=>n()).catch(e=>n(e))}if(this.buffer+=e.toString(),this.buffer.length>1e6&&(t("Buffer size exceeded, clearing..."),this.buffer=""),this.guardClient&&this.guardRequestIds)return void this.processResponseWithGuard().then(()=>n()).catch(e=>n(e));this.processBuffer(!0),n()}catch(e){n(e)}}processBuffer(e){const i=this.buffer.split("\n");this.buffer=i.pop()||"";for(const n of i){const i=n.trim();if(i)try{const n=JSON.parse(i);if(e){if("2.0"!==n.jsonrpc){t("Non-JSON-RPC JSON ignored:",i.slice(0,100));continue}this.push(i+"\n")}s(`[${this.direction}] Raw message:`,i),this.handleMessage(n)}catch{t(e?"Non-JSON output filtered:":"Failed to parse:",i.slice(0,100))}}}isValidInfo(e){return!(!e?.name||!e?.version)}handleMessage(e){if("request"===this.direction&&"initialize"===e.method&&e.params?.clientInfo&&!this.isValidInfo(this.sessionContextStore.getClientInfo())){const t=e.params;this.sessionContextStore.setClientInfo({name:t.clientInfo?.name,version:t.clientInfo?.version})}if("response"===this.direction&&void 0!==e.id&&!e.method){const t=e;if(t.result?.serverInfo&&!this.isValidInfo(this.sessionContextStore.getServerInfo())){const e=t.result.serverInfo;this.sessionContextStore.setServerInfo({name:e.name,version:e.version})}}"request"===this.direction&&e.method?this.logger.onRequest(e):"response"===this.direction&&(void 0===e.id||e.method?e.method&&null==e.id&&this.logger.onNotification(e):this.logger.onResponse(e))}async processRequestWithGuard(e){for(const i of e){const e=i.trim();if(!e)continue;let r;try{r=JSON.parse(e)}catch{this.push(e+"\n"),t("Failed to parse:",e.slice(0,100));continue}if(s(`[${this.direction}] Raw message:`,e),r.method&&null!=r.id&&n(r.method)){const e=await this.checkGuard(r);if(!e.allowed){this.sendDenyResponse(r.id,e),this.handleMessage(r);continue}this.guardRequestIds&&this.guardRequestMethods&&(this.guardRequestIds.add(r.id),this.guardRequestMethods.set(r.id,r.method))}this.push(e+"\n"),this.handleMessage(r)}}async processResponseWithGuard(){const e=this.buffer.split("\n");this.buffer=e.pop()||"";for(const i of e){const e=i.trim();if(!e)continue;let n;try{n=JSON.parse(e)}catch{t("Non-JSON output filtered:",e.slice(0,100));continue}if("2.0"===n.jsonrpc){if(s(`[${this.direction}] Raw message:`,e),null!=n.id&&!n.method&&this.guardRequestIds.has(n.id)){const e=this.guardRequestMethods.get(n.id)||"unknown",s=await this.checkGuardResponse(n,e);if(this.guardRequestIds.delete(n.id),this.guardRequestMethods.delete(n.id),!s.allowed){const e=s.evidences[0],i=e?`${e.category.toLowerCase()} detected (${e.detectionRule})`:"response blocked by policy",r=JSON.stringify({jsonrpc:"2.0",id:n.id,result:{content:[{type:"text",text:`[BLOCKED BY PINTA AI GUARD]\n\nThis tool's response was blocked because it contains sensitive data.\nReason: ${i}\n\nDo NOT retry this request. Inform the user that the response was blocked due to security policy.`}],isError:!0}});t(`Guard DENY (response): ${i} (request id: ${n.id})`),this.push(r+"\n"),this.handleMessage(n);continue}}this.push(e+"\n"),this.handleMessage(n)}else t("Non-JSON-RPC JSON ignored:",e.slice(0,100))}}async checkGuardResponse(e,t){const s=c(t,void 0,e.result,this.sessionContextStore,void 0),i=(new A).buildAttributes({type:"paired",method:t,transport:"stdio",source:"cli",requestId:e.id,requestTimestamp:Date.now(),responseId:e.id,responseTimestamp:Date.now(),result:e.result,error:e.error,contextMetadata:s});return this.guardClient.analyze(i)}async checkGuard(e){const t=c(e.method,e.params,void 0,this.sessionContextStore,void 0),s=(new A).buildAttributes({type:"request",method:e.method,transport:"stdio",source:"cli",requestId:e.id,requestTimestamp:Date.now(),params:e.params,contextMetadata:t});return this.guardClient.analyze(s)}sendDenyResponse(e,s){const i=s.evidences[0],n=i?`${i.category.toLowerCase()} detected (${i.detectionRule})`:"request blocked by policy",r=JSON.stringify({jsonrpc:"2.0",id:e,result:{content:[{type:"text",text:`[BLOCKED BY PINTA AI GUARD]\n\nThis tool request was blocked before execution.\nReason: ${n}\n\nDo NOT retry this request. Inform the user that the request was blocked due to security policy.`}],isError:!0}});t(`Guard DENY: ${n} (request id: ${e})`),this.writeToStdout&&this.writeToStdout(r+"\n")}processRequestWithConfigError(e){for(const t of e){const e=t.trim();if(!e)continue;let s;try{s=JSON.parse(e)}catch{this.push(e+"\n");continue}null==s.id||P.has(s.method)?this.push(e+"\n"):this.sendConfigErrorResponse(s.id)}}sendConfigErrorResponse(e){const s=JSON.stringify({jsonrpc:"2.0",id:e,result:{content:[{type:"text",text:`[PINTA AI CONFIGURATION ERROR]\n\n${this.configError}\n\nDo NOT retry this request. Inform the user about this configuration error.`}],isError:!0}});t(`Config error response sent (request id: ${e})`),this.writeToStdout&&this.writeToStdout(s+"\n")}_flush(e){try{if(this.buffer.trim())try{const e=JSON.parse(this.buffer);"response"===this.direction&&"2.0"===e.jsonrpc&&this.push(this.buffer.trim()+"\n"),this.handleMessage(e)}catch{"request"===this.direction&&this.push(this.buffer),t("Failed to parse final buffer")}R&&t("Stream closed. Pending requests: "+this.logger.getStats().pending),e()}catch(t){e(t)}}}class J{pendingRequests=new Map;TIMEOUT=3e4;sessionContextStore;constructor(e){this.sessionContextStore=e}onRequest(e){if(i(e.method)){if(null==e.id){const t=c(e.method,e.params,void 0,this.sessionContextStore,void 0);return void p({type:"notification",method:e.method,transport:"stdio",source:"cli",params:e.params,contextMetadata:t})}"initialize"===e.method&&e.params?.clientInfo&&this.sessionContextStore.setClientInfo({name:e.params.clientInfo.name,version:e.params.clientInfo.version}),this.pendingRequests.set(e.id,{request:e,timestamp:Date.now()}),setTimeout(()=>this.handleTimeout(e.id),this.TIMEOUT)}}onResponse(e){if(null==e.id)return;const t=this.pendingRequests.get(e.id),s=Date.now(),i=t?.request.method||e.method||"unknown";let n=this.sessionContextStore.getServerInfo();"initialize"===t?.request.method&&e.result?.serverInfo&&(n={name:e.result.serverInfo.name,version:e.result.serverInfo.version});const r=c(i,t?.request.params,e.result,this.sessionContextStore,void 0);t?(p({type:"paired",method:i,transport:"stdio",source:"cli",requestId:t.request.id,requestTimestamp:t.timestamp,params:t.request.params,responseId:e.id,responseTimestamp:s,result:e.result,error:e.error,durationMs:s-t.timestamp,contextMetadata:r,serverInfo:n}),this.pendingRequests.delete(e.id)):p({type:"response",method:i,transport:"stdio",source:"cli",responseId:e.id,responseTimestamp:s,result:e.result,error:e.error,contextMetadata:r,serverInfo:n})}onNotification(e){if(!i(e.method))return;const t=c(e.method,e.params,void 0,this.sessionContextStore,void 0);p({type:"notification",method:e.method,transport:"stdio",source:"cli",params:e.params,contextMetadata:t})}handleTimeout(e){const t=this.pendingRequests.get(e);if(t&&Date.now()-t.timestamp>this.TIMEOUT){const s=c(t.request.method,t.request.params,void 0,this.sessionContextStore,void 0);p({type:"request",method:t.request.method,transport:"stdio",source:"cli",requestId:t.request.id,requestTimestamp:t.timestamp,params:t.request.params,contextMetadata:s}),this.pendingRequests.delete(e)}}getStats(){return{pending:this.pendingRequests.size}}clear(){this.pendingRequests.clear()}}class V{context={};getClientInfo(){return this.context.clientInfo}setClientInfo(e){this.context.clientInfo=e}getServerInfo(){return this.context.serverInfo}setServerInfo(e){this.context.serverInfo=e}getHeaders(){return this.context.headers}setHeaders(e){this.context.headers=e}snapshot(){return{clientInfo:this.context.clientInfo?{...this.context.clientInfo}:void 0,serverInfo:this.context.serverInfo?{...this.context.serverInfo}:void 0,headers:this.context.headers?{...this.context.headers}:void 0}}}class z{guardUrl;apiKey;timeoutMs;serviceName;serviceVersion;memberIdentityId;memberIdentityEmail;constructor(e,t,s=1e3){this.guardUrl=e.replace(/\/$/,""),this.apiKey=t,this.timeoutMs=s}setServiceInfo(e,t){this.serviceName=e,this.serviceVersion=t}setMemberIdentity(e,t){e&&(this.memberIdentityId=e),t&&(this.memberIdentityEmail=t)}async analyze(e){try{const i=new AbortController,n=setTimeout(()=>i.abort(),this.timeoutMs),r=function(e,t,s,i,n){const r=Object.entries(e).filter(([e,t])=>null!=t).map(([e,t])=>({key:e,value:"string"==typeof t?{stringValue:t}:"number"==typeof t?Number.isInteger(t)?{intValue:t}:{doubleValue:t}:"boolean"==typeof t?{boolValue:t}:{stringValue:t+""}})),o=[];t&&o.push({key:"service.name",value:{stringValue:t}}),s&&o.push({key:"service.version",value:{stringValue:s}}),i&&o.push({key:"member.identity.id",value:{stringValue:i}}),n&&o.push({key:"member.identity.email",value:{stringValue:n}});const a=u(16),c=u(32),p=1e6*Date.now()+"";return{resourceSpans:[{resource:{attributes:o},scopeSpans:[{scope:{name:"mcp-logger"},spans:[{traceId:c,spanId:a,name:"mcp."+(e["mcp.method"]||"unknown"),kind:1,startTimeUnixNano:p,endTimeUnixNano:p,attributes:r,status:{code:0}}]}]}]}}(e,this.serviceName,this.serviceVersion,this.memberIdentityId,this.memberIdentityEmail);s("[Guard] OTLP body:",JSON.stringify(r,null,2));const o=await fetch(this.guardUrl+"/guard",{method:"POST",headers:{"Content-Type":"application/json","x-api-key":this.apiKey},body:JSON.stringify(r),signal:i.signal});if(clearTimeout(n),!o.ok){const e=await o.text().catch(()=>"");return t(`Guard API returned ${o.status}, fail-open`,e),{allowed:!0,evidences:[]}}const a=await o.json();if(t("Guard decision: "+a.decision),"DENY"===a.decision){const e=a.spans.find(e=>"DENY"===e.decision);return{allowed:!1,evidences:e?.evidences||[]}}return{allowed:!0,evidences:[]}}catch(e){return t("Guard API error, fail-open:",e instanceof Error?e.message:e),{allowed:!0,evidences:[]}}}}class U{process;logger;isShuttingDown=!1;constructor(e,s,i,n,r,o,a,c){const p=new V;this.logger=new J(p);let u=null;if(!c&&i){const e=n||D.ENDPOINT;u=new z(e,i),t("Guard enabled: "+e),r&&u.setServiceInfo(r,o||"unknown"),a&&u.setMemberIdentity(a.id,a.email)}this.process=x(e,s,{stdio:["pipe","pipe","inherit"],env:{...process.env,MCP_LOGGER_ENABLED:"true"}});const d=new Set,h=new Map,l=new G("request",this.logger,p,u,d,h,c),m=new G("response",this.logger,p,u,d,h);process.stdin.pipe(l).pipe(this.process.stdin),this.process.stdout.pipe(m).pipe(process.stdout),l.writeToStdout=e=>{process.stdout.write(e)},this.process.on("error",e=>this.handleError(e)),this.process.on("exit",(e,t)=>this.handleExit(e,t)),process.on("SIGTERM",()=>this.shutdown("SIGTERM")),process.on("SIGINT",()=>this.shutdown("SIGINT"))}async handleError(t){e("Failed to start MCP server:",t),await this.cleanup(),process.exit(1)}async handleExit(e,s){t(`MCP server exited with code ${e}, signal ${s}`),await this.cleanup(),process.exit(e||0)}async shutdown(e){this.isShuttingDown||(this.isShuttingDown=!0,t(`Received ${e}, shutting down...`),this.process.kill(e),await Promise.race([new Promise(e=>this.process.once("exit",e)),new Promise(e=>setTimeout(e,5e3))]),await this.cleanup(),process.exit(0))}async cleanup(){this.logger.clear(),await async function(){await q.shutdown()}()}}d.name("mcp-logger").description("Add observability to any MCP server without code changes").version("1.0.0").option("-k, --api-key <key>","Aware API key").option("-e, --endpoint <url>","Custom OTLP endpoint").argument("<command...>","MCP server command to wrap").action(async(t,s)=>{const[i,...n]=t,o=function(e){const t=[];e.apiKey||t.push("API key is missing.");const s=r();return s.id&&s.email||t.push("Member identity is not configured."),0===t.length?null:[t.join(" "),"\nTo resolve this, follow these steps:\n1. Run `pintasec login` to set your API key and verify your email.\n2. Run `pintasec configure` or manually register the mcp-logger configuration.\n3. Restart your MCP server."].join("\n")}(s);if(o)return void new U(i,n,s.apiKey,s.endpoint,void 0,void 0,void 0,o);const a=function(e){const t={};for(const s of e){const e=process.env[s];void 0!==e&&(t[s]=e)}return t}(function(){try{return w("pinta mcpenv sync",{encoding:"utf-8",timeout:1e4,stdio:["pipe","pipe","pipe"]}),w("pinta mcpenv keys",{encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim().split("\n").filter(e=>e.length>0)}catch{return[]}}()),c=r(),p=function(e,t){const s=function(e){for(const t of e){if(T.has(t))continue;const e=t.match(/^(@[^@]+\/[^@]+)@(.+)$/);if(e)return{packageName:e[1],version:e[2]};const s=t.match(/^([^@]+)@(.+)$/);if(s)return{packageName:s[1],version:s[2]};const i=t.match(/^(@[^@]+\/[^@]+)$/);if(i)return{packageName:i[1],version:"latest"};if(t.match(/^[a-z0-9-]+$/)&&!t.includes("/"))return{packageName:t,version:"latest"}}return null}(t.filter(e=>!e.startsWith("-")));let i,n;if(i=s?.packageName?s.packageName:e.split("/").pop()||e||D.SERVICE_NAME_PREFIX+"-unknown",s&&(n=s.version,"latest"===s.version)){const t=O.has(e)?"pip":"npm",i=function(e,t){try{if("pip"===t){let t=null;for(const s of["pip3","pip"])try{t=w(`${s} index versions ${e}`,{encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]});break}catch{continue}if(!t)return null;const s=t.match(/\(([^)]+)\)/);if(s)return s[1];const i=t.match(/Available versions:\s*([^\s,]+)/);return i?i[1]:null}{const t=w(`npm view ${e} version --json`,{encoding:"utf-8",timeout:5e3,stdio:["pipe","pipe","pipe"]}).trim().replace(/^["']|["']$/g,""),s=t.match(/^(\d+\.\d+\.\d+(?:-[\w.]+)?)/);return s?s[1]:t}}catch{return null}}(s.packageName,t);i&&(n=i)}return{name:i,version:n}}(i,n);!function(e){q.initialize(e)}({apiKey:s.apiKey,endpoint:s.endpoint,serviceName:p.name,serviceVersion:p.version,memberIdentity:c}),e("Starting MCP server: "+t.join(" ")),e(`Service: ${p.name} = ${p.version||"unknown"}`),function(e,t,s){q.setCLIServerInfo(e,t,s)}(i,n,a),new U(i,n,s.apiKey,s.endpoint,p.name,p.version,c)}),d.parse();
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,14 @@ interface TelemetryOptions {
|
|
|
26
26
|
* 기본값: CONFIG.ENDPOINT
|
|
27
27
|
*/
|
|
28
28
|
endpoint?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Member identity (옵션)
|
|
31
|
+
* aware CLI에서 가져온 identity 정보
|
|
32
|
+
*/
|
|
33
|
+
memberIdentity?: {
|
|
34
|
+
id: string | null;
|
|
35
|
+
email: string | null;
|
|
36
|
+
};
|
|
29
37
|
}
|
|
30
38
|
/**
|
|
31
39
|
* 커스텀 로그 엔트리
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function t(...t){v&&console.error("[mcp-logger]",...t)}function e(t,e=2e5){try{const s=JSON.stringify(t);return s.length>e?s.slice(0,e)+"... (truncated)":s}catch{return null}}function s(t,e){return t.startsWith("resources/")?{type:t.split("/")[1],uri:e?.uri||e?.path||e?.resource}:t.startsWith("prompts/")?{type:"prompt",uri:e?.name||e?.promptId}:"tools/call"===t?{type:"tool",uri:e?.name}:e?.resourceType&&e?.resourceUri?{type:e.resourceType,uri:e.resourceUri}:{type:void 0,uri:void 0}}function i(t,e,i,n,r){const a=function(t,e){const s=e;if(s){const t=s["user-agent"]||s["User-Agent"];if(t){const e=t.match(/^([^\/]+)\/([^\s]+)/);if(e)return{name:e[1],version:e[2]}}}return{name:void 0,version:void 0}}(0,r),o=`${a.name||"unknown"}-${a.version||"0"}`,p=I.getOrCreateSessionId(o),c=I.getOrCreateConversationId(p,t),u=function(t,e){return t?.userId||t?.user_id?t.userId||t.user_id:e?e["x-user-id"]||e["X-User-Id"]:void 0}(e,r),h=function(t){if(t?.permission||t?.permissionLevel)return t.permission||t.permissionLevel}(e),m=s(t,e);m.uri&&I.trackResourceAccess(m.uri);const d=function(t,e){return void 0!==t?.cost?t.cost:void 0!==e?.cost?e.cost:void 0}(e,i),l={};return p&&(l.sessionId=p),c&&(l.conversationId=c),u&&(l.userId=u),a.name&&(l.clientName=a.name),a.version&&(l.clientVersion=a.version),h&&(l.permissionLevel=h),void 0!==d&&(l.cost=d),l}import{trace as n,SpanStatusCode as r,context as a}from"@opentelemetry/api";import{NodeSDK as o}from"@opentelemetry/sdk-node";import{OTLPTraceExporter as p}from"@opentelemetry/exporter-trace-otlp-http";import{Resource as c}from"@opentelemetry/resources";import{readFileSync as u}from"fs";import{fileURLToPath as h}from"url";import{dirname as m,join as d}from"path";import{ulid as l}from"ulid";const v="true"===process.env.AWARE_DEBUG||"1"===process.env.AWARE_DEBUG,f="true"===process.env.AWARE_RAW_DEBUG||"1"===process.env.AWARE_RAW_DEBUG,g={ENDPOINT:"https://api.awarecorp.io/traces",SDK_VERSION:function(){try{const t=h(import.meta.url),e=m(t),s=d(e,"..","..","package.json");return JSON.parse(u(s,"utf-8")).version||"1.0.0"}catch{return"1.0.0"}}(),SERVICE_NAME_PREFIX:"mcp-server"},y=new class{sdk=null;tracer=null;initialized=!1;cliServerInfo=null;initialize(e){if(this.initialized)return t("Telemetry already initialized, returning existing tracer"),this.tracer;const s=e.endpoint||g.ENDPOINT,i=e.serviceName||`${g.SERVICE_NAME_PREFIX}-${Math.random().toString(36).slice(2,8)}`,r=e.serviceVersion||"unknown";t("Initializing telemetry..."),t("Endpoint: "+s),t("Service: "+i),t("Version: "+r),this.sdk=new o({resource:new c({"service.name":i,"service.version":r}),traceExporter:new p({url:s,headers:{"x-api-key":e.apiKey}})}),this.sdk.start(),this.tracer=n.getTracer("mcp-logger",g.SDK_VERSION),this.initialized=!0,t("Telemetry initialized successfully");const a=async()=>{t("Shutting down telemetry..."),await this.shutdown()};return process.once("SIGTERM",a),process.once("SIGINT",a),this.tracer}getTracer(){return this.tracer}isInitialized(){return this.initialized}setCLIServerInfo(t,e,s){this.cliServerInfo={command:t,args:e,env:s}}getCLIServerInfo(){return this.cliServerInfo}async shutdown(){if(this.sdk)try{await this.sdk.shutdown(),this.sdk=null,this.tracer=null,this.initialized=!1,this.cliServerInfo=null}catch(t){console.error("[mcp-logger] Error shutting down telemetry:",t)}}},I=new class{sessionMap=new Map;sessionCounter=0;conversationMap=new Map;conversationCounter=0;resourceAccessCount=new Map;getOrCreateSessionId(t){if(!this.sessionMap.has(t)){const e=l();this.sessionMap.set(t,e),this.sessionCounter++}return this.sessionMap.get(t)}getOrCreateConversationId(t,e){const s=`${t}-${e}`;return this.conversationMap.has(s)||this.conversationMap.set(s,"conv-"+ ++this.conversationCounter),this.conversationMap.get(s)}trackResourceAccess(t){const e=(this.resourceAccessCount.get(t)||0)+1;return this.resourceAccessCount.set(t,e),e}getResourceAccessCount(t){return this.resourceAccessCount.get(t)||0}clear(){this.sessionMap.clear(),this.conversationMap.clear(),this.resourceAccessCount.clear(),this.sessionCounter=0,this.conversationCounter=0}},D=new class{spanData;input;contextMetadata;build(t){const e=y.getTracer();e&&(this.input=t,e.startActiveSpan("mcp."+t.method,t=>{try{this.spanData=this.buildBase(),this.resolveContextMetadata(),this.applyTraceId(),this.applyRequestFields(),this.applyResponseFields(),this.applyDuration(),this.applyCLIServerInfo(),this.applyMCPServerInfo(),this.applyContextMetadata(),this.applyResourceMetadata(),this.applyCustomEvents(t),this.applyError(t),function(t,e){for(const[s,i]of Object.entries(e))null!=i&&t.setAttribute(s,i)}(t,this.spanData),function(...t){f&&console.error("[mcp-logger]",...t)}("[OTLP] Span data:",JSON.stringify(this.spanData,null,2))}catch{t.setStatus({code:r.ERROR,message:"Error creating span"})}finally{t.end()}}))}buildBase(){return{"ingest.type":"mcp","mcp.type":this.input.type,"mcp.transport":this.input.transport,"mcp.method":this.input.method,"mcp.source":this.input.source}}resolveContextMetadata(){this.contextMetadata=this.input.contextMetadata||i(this.input.method,this.input.params,this.input.result,0,this.input.headers)}applyTraceId(){this.contextMetadata.sessionId&&this.contextMetadata.conversationId&&(this.spanData["mcp.trace.id"]=`${this.contextMetadata.sessionId}:${this.contextMetadata.conversationId}`)}applyRequestFields(){if("paired"===this.input.type||"request"===this.input.type||"notification"===this.input.type){if(void 0!==this.input.requestId&&(this.spanData["mcp.request.id"]=this.input.requestId+""),this.spanData["mcp.request.method"]=this.input.method,void 0!==this.input.requestTimestamp&&(this.spanData["mcp.request.timestamp"]=this.input.requestTimestamp),void 0!==this.input.params&&(this.spanData["mcp.request.params"]=e(this.input.params)||"{}",this.spanData["mcp.request.params.size"]=JSON.stringify(this.input.params||{}).length),"tools/call"===this.input.method&&this.input.params){const t=this.input.params.name,s=this.input.params.arguments;if(t&&(this.spanData["mcp.tool.name"]=t),s){const t=e(s);t&&(this.spanData["mcp.tool.arguments"]=t,this.spanData["mcp.tool.arguments.size"]=JSON.stringify(s).length)}}if(this.input.headers){const t=e(this.input.headers);t&&(this.spanData["mcp.headers"]=t,this.spanData["mcp.headers.size"]=JSON.stringify(this.input.headers).length)}}}applyResponseFields(){if(("paired"===this.input.type||"response"===this.input.type)&&(void 0!==this.input.responseId&&(this.spanData["mcp.response.id"]=this.input.responseId+""),this.spanData["mcp.response.method"]=this.input.method,void 0!==this.input.responseTimestamp&&(this.spanData["mcp.response.timestamp"]=this.input.responseTimestamp),void 0!==this.input.result)){const t=e(this.input.result);t&&(this.spanData["mcp.response.result"]=t,this.spanData["mcp.response.result.size"]=JSON.stringify(this.input.result).length)}}applyDuration(){void 0!==this.input.durationMs&&(this.spanData["mcp.duration_ms"]=this.input.durationMs)}applyCLIServerInfo(){const t=y.getCLIServerInfo();t&&(this.spanData["mcp.cli"]=JSON.stringify({command:t.command,args:t.args,env:t.env}))}applyMCPServerInfo(){this.input.serverInfo&&(this.input.serverInfo.name&&(this.spanData["mcp.sdk.name"]=this.input.serverInfo.name),this.input.serverInfo.version&&(this.spanData["mcp.sdk.version"]=this.input.serverInfo.version))}applyContextMetadata(){this.contextMetadata.sessionId&&(this.spanData["mcp.session.id"]=this.contextMetadata.sessionId),this.contextMetadata.conversationId&&(this.spanData["mcp.conversation.id"]=this.contextMetadata.conversationId),this.contextMetadata.userId&&(this.spanData["mcp.user.id"]=this.contextMetadata.userId),this.contextMetadata.clientName&&(this.spanData["mcp.client.name"]=this.contextMetadata.clientName),this.contextMetadata.clientVersion&&(this.spanData["mcp.client.version"]=this.contextMetadata.clientVersion),this.contextMetadata.permissionLevel&&(this.spanData["mcp.permission.level"]=this.contextMetadata.permissionLevel),void 0!==this.contextMetadata.cost&&(this.spanData["mcp.cost"]=this.contextMetadata.cost)}applyResourceMetadata(){const t=function(t,e){const i=s(t,e);if(!i.uri)return{};const n=I.getResourceAccessCount(i.uri);return{resourceType:i.type,resourceUri:i.uri,resourceAccessCount:n}}(this.input.method,this.input.params);t.resourceType&&(this.spanData["mcp.resource.type"]=t.resourceType),t.resourceUri&&(this.spanData["mcp.resource.uri"]=t.resourceUri),t.resourceAccessCount&&(this.spanData["mcp.resource.access_count"]=t.resourceAccessCount)}applyCustomEvents(t){this.input.customEvents&&0!==this.input.customEvents.length&&(this.spanData["mcp.events"]=JSON.stringify(this.input.customEvents),this.spanData["mcp.events.count"]=this.input.customEvents.length,this.input.customEvents.forEach(e=>{t.addEvent("custom."+(e.level||"info"),{message:e.message,metadata:JSON.stringify(e.metadata||{}),timestamp:e.timestamp||Date.now()})}))}applyError(t){if(this.input.error){let s;this.spanData["mcp.error"]=!0,this.input.error instanceof Error?(s=this.input.error.message,t.recordException(this.input.error)):s="string"==typeof this.input.error?this.input.error:e(this.input.error)||"Unknown error",this.spanData["mcp.error.message"]=s,t.setStatus({code:r.ERROR,message:s})}else t.setStatus({code:r.OK})}},M=Symbol("mcp-logger.customEvents"),E=Object.assign(function(e,s){if(!s.apiKey)throw Error("[mcp-logger] apiKey is required");if(!e)throw Error("[mcp-logger] server instance is required");!function(t){y.initialize(t)}(s),function(e){const s=e.setRequestHandler;e.setRequestHandler=function(n,r){const o=n.shape?.method,p=o?._def?.value||"unknown";return t("Instrumenting handler: "+p),s.call(e,n,async(e,s)=>{const n=Date.now(),o=`${p}-${n}-${Math.random().toString(36).slice(2,8)}`,c=[],u=a.active().setValue(M,c);let h,m;try{h=await a.with(u,()=>r(e,s))}catch(t){m=t}const d=Date.now(),l=d-n,v=i(p,e.params,m?void 0:h,0,void 0);var f;if(f={type:"paired",method:p,transport:"stdio",source:"sdk",requestId:o,requestTimestamp:n,params:e.params,responseId:o,responseTimestamp:d,result:m?void 0:h,error:m||void 0,durationMs:l,customEvents:c.length>0?c:void 0,contextMetadata:v},D.build(f),t(`Request ${m?"failed":"completed"} (${l}ms):`,{method:p,customEvents:c.length}),m)throw m;return h})},t("Server instrumentation complete")}(e)},{addLog(t){const e=a.active().getValue(M);if(!e)return;const s={level:t.level||"info",message:t.message,metadata:t.metadata,timestamp:t.timestamp||Date.now()};e.push(s);const i=n.getSpan(a.active());i&&i.addEvent("custom."+s.level,{message:s.message,metadata:JSON.stringify(s.metadata||{}),timestamp:s.timestamp})},async shutdown(){await async function(){await y.shutdown()}()}});export{E as trace};
|
|
1
|
+
function t(...t){v&&console.error("[mcp-logger]",...t)}function e(t,e=2e5){try{const s=JSON.stringify(t);return s.length>e?s.slice(0,e)+"... (truncated)":s}catch{return null}}function s(t,e){return t.startsWith("resources/")?{type:t.split("/")[1],uri:e?.uri||e?.path||e?.resource}:t.startsWith("prompts/")?{type:"prompt",uri:e?.name||e?.promptId}:"tools/call"===t?{type:"tool",uri:e?.name}:e?.resourceType&&e?.resourceUri?{type:e.resourceType,uri:e.resourceUri}:{type:void 0,uri:void 0}}function i(t,e,i,n,r){const a=function(t,e){const s=e;if(s){const t=s["user-agent"]||s["User-Agent"];if(t){const e=t.match(/^([^\/]+)\/([^\s]+)/);if(e)return{name:e[1],version:e[2]}}}return{name:void 0,version:void 0}}(0,r),o=`${a.name||"unknown"}-${a.version||"0"}`,p=I.getOrCreateSessionId(o),c=I.getOrCreateConversationId(p,t),u=function(t,e){return t?.userId||t?.user_id?t.userId||t.user_id:e?e["x-user-id"]||e["X-User-Id"]:void 0}(e,r),h=function(t){if(t?.permission||t?.permissionLevel)return t.permission||t.permissionLevel}(e),m=s(t,e);m.uri&&I.trackResourceAccess(m.uri);const d=function(t,e){return void 0!==t?.cost?t.cost:void 0!==e?.cost?e.cost:void 0}(e,i),l={};return p&&(l.sessionId=p),c&&(l.conversationId=c),u&&(l.userId=u),a.name&&(l.clientName=a.name),a.version&&(l.clientVersion=a.version),h&&(l.permissionLevel=h),void 0!==d&&(l.cost=d),l}import{trace as n,SpanStatusCode as r,context as a}from"@opentelemetry/api";import{NodeSDK as o}from"@opentelemetry/sdk-node";import{OTLPTraceExporter as p}from"@opentelemetry/exporter-trace-otlp-http";import{Resource as c}from"@opentelemetry/resources";import{readFileSync as u}from"fs";import{fileURLToPath as h}from"url";import{dirname as m,join as d}from"path";import{ulid as l}from"ulid";const v="true"===process.env.PINTA_DEBUG||"1"===process.env.PINTA_DEBUG,y="true"===process.env.PINTA_RAW_DEBUG||"1"===process.env.PINTA_RAW_DEBUG,f={ENDPOINT:"https://api.awarecorp.io",SDK_VERSION:function(){try{const t=h(import.meta.url),e=m(t),s=d(e,"..","..","package.json");return JSON.parse(u(s,"utf-8")).version||"1.0.0"}catch{return"1.0.0"}}(),SERVICE_NAME_PREFIX:"mcp-server"},g=new class{sdk=null;tracer=null;initialized=!1;cliServerInfo=null;initialize(e){if(this.initialized)return t("Telemetry already initialized, returning existing tracer"),this.tracer;const s=e.endpoint||f.ENDPOINT,i=e.serviceName||`${f.SERVICE_NAME_PREFIX}-${Math.random().toString(36).slice(2,8)}`,r=e.serviceVersion||"unknown";t("Initializing telemetry..."),t("Endpoint: "+s),t("Service: "+i),t("Version: "+r);const a={"service.name":i,"service.version":r};e.memberIdentity?.id&&(a["member.identity.id"]=e.memberIdentity.id),e.memberIdentity?.email&&(a["member.identity.email"]=e.memberIdentity.email),this.sdk=new o({resource:new c(a),traceExporter:new p({url:s.replace(/\/$/,"")+"/traces",headers:{"x-api-key":e.apiKey}})}),this.sdk.start(),this.tracer=n.getTracer("mcp-logger",f.SDK_VERSION),this.initialized=!0,t("Telemetry initialized successfully");const u=async()=>{t("Shutting down telemetry..."),await this.shutdown()};return process.once("SIGTERM",u),process.once("SIGINT",u),this.tracer}getTracer(){return this.tracer}isInitialized(){return this.initialized}setCLIServerInfo(t,e,s){this.cliServerInfo={command:t,args:e,env:s}}getCLIServerInfo(){return this.cliServerInfo}async shutdown(){if(this.sdk)try{await this.sdk.shutdown(),this.sdk=null,this.tracer=null,this.initialized=!1,this.cliServerInfo=null}catch(t){console.error("[mcp-logger] Error shutting down telemetry:",t)}}},I=new class{sessionMap=new Map;sessionCounter=0;conversationMap=new Map;conversationCounter=0;resourceAccessCount=new Map;getOrCreateSessionId(t){if(!this.sessionMap.has(t)){const e=l();this.sessionMap.set(t,e),this.sessionCounter++}return this.sessionMap.get(t)}getOrCreateConversationId(t,e){const s=`${t}-${e}`;return this.conversationMap.has(s)||this.conversationMap.set(s,"conv-"+ ++this.conversationCounter),this.conversationMap.get(s)}trackResourceAccess(t){const e=(this.resourceAccessCount.get(t)||0)+1;return this.resourceAccessCount.set(t,e),e}getResourceAccessCount(t){return this.resourceAccessCount.get(t)||0}clear(){this.sessionMap.clear(),this.conversationMap.clear(),this.resourceAccessCount.clear(),this.sessionCounter=0,this.conversationCounter=0}},D=new class{spanData;input;contextMetadata;buildAttributes(t){if(this.input=t,this.spanData=this.buildBase(),this.resolveContextMetadata(),this.applyTraceId(),this.applyRequestFields(),this.applyResponseFields(),this.applyDuration(),this.applyCLIServerInfo(),this.applyMCPServerInfo(),this.applyContextMetadata(),this.applyResourceMetadata(),this.input.customEvents&&this.input.customEvents.length>0&&(this.spanData["mcp.events"]=JSON.stringify(this.input.customEvents),this.spanData["mcp.events.count"]=this.input.customEvents.length),t.error){this.spanData["mcp.error"]=!0;const s="string"==typeof t.error?t.error:t.error instanceof Error?t.error.message:e(t.error)||"Unknown error";this.spanData["mcp.error.message"]=s}return{...this.spanData}}build(t){const e=g.getTracer();e&&(this.input=t,e.startActiveSpan("mcp."+t.method,t=>{try{this.spanData=this.buildBase(),this.resolveContextMetadata(),this.applyTraceId(),this.applyRequestFields(),this.applyResponseFields(),this.applyDuration(),this.applyCLIServerInfo(),this.applyMCPServerInfo(),this.applyContextMetadata(),this.applyResourceMetadata(),this.applyCustomEvents(t),this.applyError(t),function(t,e){for(const[s,i]of Object.entries(e))null!=i&&t.setAttribute(s,i)}(t,this.spanData),function(...t){y&&console.error("[mcp-logger]",...t)}("[OTLP] Span data:",JSON.stringify(this.spanData,null,2))}catch{t.setStatus({code:r.ERROR,message:"Error creating span"})}finally{t.end()}}))}buildBase(){return{"ingest.type":"mcp","mcp.type":this.input.type,"mcp.transport":this.input.transport,"mcp.method":this.input.method,"mcp.source":this.input.source}}resolveContextMetadata(){this.contextMetadata=this.input.contextMetadata||i(this.input.method,this.input.params,this.input.result,0,this.input.headers)}applyTraceId(){this.contextMetadata.sessionId&&this.contextMetadata.conversationId&&(this.spanData["mcp.trace.id"]=`${this.contextMetadata.sessionId}:${this.contextMetadata.conversationId}`)}applyRequestFields(){if("paired"===this.input.type||"request"===this.input.type||"notification"===this.input.type){if(void 0!==this.input.requestId&&(this.spanData["mcp.request.id"]=this.input.requestId+""),this.spanData["mcp.request.method"]=this.input.method,void 0!==this.input.requestTimestamp&&(this.spanData["mcp.request.timestamp"]=this.input.requestTimestamp),void 0!==this.input.params&&(this.spanData["mcp.request.params"]=e(this.input.params)||"{}",this.spanData["mcp.request.params.size"]=JSON.stringify(this.input.params||{}).length),"tools/call"===this.input.method&&this.input.params){const t=this.input.params.name,s=this.input.params.arguments;if(t&&(this.spanData["mcp.tool.name"]=t),s){const t=e(s);t&&(this.spanData["mcp.tool.arguments"]=t,this.spanData["mcp.tool.arguments.size"]=JSON.stringify(s).length)}}if(this.input.headers){const t=e(this.input.headers);t&&(this.spanData["mcp.headers"]=t,this.spanData["mcp.headers.size"]=JSON.stringify(this.input.headers).length)}}}applyResponseFields(){if(("paired"===this.input.type||"response"===this.input.type)&&(void 0!==this.input.responseId&&(this.spanData["mcp.response.id"]=this.input.responseId+""),this.spanData["mcp.response.method"]=this.input.method,void 0!==this.input.responseTimestamp&&(this.spanData["mcp.response.timestamp"]=this.input.responseTimestamp),void 0!==this.input.result)){const t=e(this.input.result);t&&(this.spanData["mcp.response.result"]=t,this.spanData["mcp.response.result.size"]=JSON.stringify(this.input.result).length)}}applyDuration(){void 0!==this.input.durationMs&&(this.spanData["mcp.duration_ms"]=this.input.durationMs)}applyCLIServerInfo(){const t=g.getCLIServerInfo();t&&(this.spanData["mcp.cli"]=JSON.stringify({command:t.command,args:t.args,env:t.env}))}applyMCPServerInfo(){this.input.serverInfo&&(this.input.serverInfo.name&&(this.spanData["mcp.sdk.name"]=this.input.serverInfo.name),this.input.serverInfo.version&&(this.spanData["mcp.sdk.version"]=this.input.serverInfo.version))}applyContextMetadata(){this.contextMetadata.sessionId&&(this.spanData["mcp.session.id"]=this.contextMetadata.sessionId),this.contextMetadata.conversationId&&(this.spanData["mcp.conversation.id"]=this.contextMetadata.conversationId),this.contextMetadata.userId&&(this.spanData["mcp.user.id"]=this.contextMetadata.userId),this.contextMetadata.clientName&&(this.spanData["mcp.client.name"]=this.contextMetadata.clientName),this.contextMetadata.clientVersion&&(this.spanData["mcp.client.version"]=this.contextMetadata.clientVersion),this.contextMetadata.permissionLevel&&(this.spanData["mcp.permission.level"]=this.contextMetadata.permissionLevel),void 0!==this.contextMetadata.cost&&(this.spanData["mcp.cost"]=this.contextMetadata.cost)}applyResourceMetadata(){const t=function(t,e){const i=s(t,e);if(!i.uri)return{};const n=I.getResourceAccessCount(i.uri);return{resourceType:i.type,resourceUri:i.uri,resourceAccessCount:n}}(this.input.method,this.input.params);t.resourceType&&(this.spanData["mcp.resource.type"]=t.resourceType),t.resourceUri&&(this.spanData["mcp.resource.uri"]=t.resourceUri),t.resourceAccessCount&&(this.spanData["mcp.resource.access_count"]=t.resourceAccessCount)}applyCustomEvents(t){this.input.customEvents&&0!==this.input.customEvents.length&&(this.spanData["mcp.events"]=JSON.stringify(this.input.customEvents),this.spanData["mcp.events.count"]=this.input.customEvents.length,this.input.customEvents.forEach(e=>{t.addEvent("custom."+(e.level||"info"),{message:e.message,metadata:JSON.stringify(e.metadata||{}),timestamp:e.timestamp||Date.now()})}))}applyError(t){if(this.input.error){let s;this.spanData["mcp.error"]=!0,this.input.error instanceof Error?(s=this.input.error.message,t.recordException(this.input.error)):s="string"==typeof this.input.error?this.input.error:e(this.input.error)||"Unknown error",this.spanData["mcp.error.message"]=s,t.setStatus({code:r.ERROR,message:s})}else t.setStatus({code:r.OK})}},M=Symbol("mcp-logger.customEvents"),E=Object.assign(function(e,s){if(!s.apiKey)throw Error("[mcp-logger] apiKey is required");if(!e)throw Error("[mcp-logger] server instance is required");!function(t){g.initialize(t)}(s),function(e){const s=e.setRequestHandler;e.setRequestHandler=function(n,r){const o=n.shape?.method,p=o?._def?.value||"unknown";return t("Instrumenting handler: "+p),s.call(e,n,async(e,s)=>{const n=Date.now(),o=`${p}-${n}-${Math.random().toString(36).slice(2,8)}`,c=[],u=a.active().setValue(M,c);let h,m;try{h=await a.with(u,()=>r(e,s))}catch(t){m=t}const d=Date.now(),l=d-n,v=i(p,e.params,m?void 0:h,0,void 0);var y;if(y={type:"paired",method:p,transport:"stdio",source:"sdk",requestId:o,requestTimestamp:n,params:e.params,responseId:o,responseTimestamp:d,result:m?void 0:h,error:m||void 0,durationMs:l,customEvents:c.length>0?c:void 0,contextMetadata:v},D.build(y),t(`Request ${m?"failed":"completed"} (${l}ms):`,{method:p,customEvents:c.length}),m)throw m;return h})},t("Server instrumentation complete")}(e)},{addLog(t){const e=a.active().getValue(M);if(!e)return;const s={level:t.level||"info",message:t.message,metadata:t.metadata,timestamp:t.timestamp||Date.now()};e.push(s);const i=n.getSpan(a.active());i&&i.addEvent("custom."+s.level,{message:s.message,metadata:JSON.stringify(s.metadata||{}),timestamp:s.timestamp})},async shutdown(){await async function(){await g.shutdown()}()}});export{E as trace};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awarecorp/mcp-logger",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "Unified MCP observability solution - SDK for code integration and CLI for zero-config wrapping",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@opentelemetry/resources": "^1.25.0",
|
|
66
66
|
"@opentelemetry/sdk-node": "^0.52.0",
|
|
67
67
|
"@opentelemetry/semantic-conventions": "^1.25.0",
|
|
68
|
-
"@pinta-ai/types": "^0.0.
|
|
68
|
+
"@pinta-ai/types": "^0.0.4",
|
|
69
69
|
"commander": "^11.1.0",
|
|
70
70
|
"ulid": "^3.0.1"
|
|
71
71
|
},
|