@mackerel/mcp-server 0.5.0 → 0.6.0

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/build/index.js CHANGED
@@ -125,7 +125,7 @@ ${e}
125
125
  ${c()}
126
126
 
127
127
  ## Valid Metric Name Examples
128
- - response_time, custom.my_metric, throughput`}async function d(e,t){try{let t=await e(),n=JSON.stringify(t),i=a(n);return i>r?{content:[{type:`text`,text:o(i)}],isError:!0}:{content:[{type:`text`,text:n}]}}catch(e){let n=e instanceof Error?e.message:String(e);if(t&&n.includes(`404`)&&(t===`get_host_metrics`||t===`get_service_metrics`)){let e;return e=t===`get_host_metrics`?l(n):u(n),{content:[{type:`text`,text:e}],isError:!0}}return{content:[{type:`text`,text:`Error occurred: ${n}`}],isError:!0}}}var f=class{constructor(e){this.mackerelClient=e}static ListAlertsToolInput=n.object({withClosed:n.boolean().optional().describe(`Whether or not to get resolved alerts. If true, resolved alerts as well as open alerts are retrieved`),nextId:n.string().optional().describe(`If specified, alerts older than the alert with the specified id are retrieved`),limit:n.number().min(1).max(100).optional().describe(`The maximum number of alerts to retrieve. When omitted, up to 100 cases are retrieved. The most that can be specified is 100`)});listAlerts=async({withClosed:e,nextId:t,limit:n})=>await d(async()=>await this.mackerelClient.getAlerts(e,t,n));static GetAlertToolInput=n.object({alertId:n.string().describe(`The ID of the alert to retrieve`)});getAlert=async({alertId:e})=>await d(async()=>await this.mackerelClient.getAlert(e));static GetAlertLogsToolInput=n.object({alertId:n.string().describe(`The ID of the alert to retrieve logs for`),nextId:n.string().optional().describe(`If specified, alert logs older than the specified are retrieved`),limit:n.number().min(1).max(100).optional().describe(`The maximum number of alert logs to retrieve. When omitted, up to 100 logs are retrieved. The most that can be specified is 100`)});getAlertLogs=async({alertId:e,nextId:t,limit:n})=>await d(async()=>await this.mackerelClient.getAlertLogs(e,t,n))},p=class e{constructor(e){this.mackerelClient=e}static ListDashboardsToolInput=n.object({limit:n.number().int().positive().optional().describe(`Maximum number of dashboards to return (default: 20)`),offset:n.number().int().min(0).optional().describe(`Number of dashboards to skip (default: 0)`),summary:n.boolean().optional().default(!0).describe(`If true, omit widget details to reduce response size (default: true)`)});listDashboards=async({limit:e,offset:t,summary:n=!0})=>await d(async()=>{let r=await this.mackerelClient.getDashboards(e,t);if(n){let e=r.dashboards.map(e=>({id:e.id,title:e.title,memo:e.memo,urlPath:e.urlPath,createdAt:e.createdAt,updatedAt:e.updatedAt,widgetCount:e.widgets?.length||0}));return{dashboards:e,pageInfo:r.pageInfo}}return r});static GetDashboardToolInput=n.object({dashboardId:n.string().describe(`The ID of the dashboard to retrieve`)});getDashboard=async({dashboardId:e})=>await d(async()=>await this.mackerelClient.getDashboard(e));static LayoutSchema=n.object({x:n.number().describe(`X coordinate of widget`),y:n.number().describe(`Y coordinate of widget`),width:n.number().describe(`Width of widget`),height:n.number().describe(`Height of widget`)});static RangeSchema=n.union([n.object({type:n.literal(`relative`).describe(`Relative time range`),period:n.number().describe(`Length of the period (in seconds)`),offset:n.number().describe(`Difference from the current time (in seconds)`)}),n.object({type:n.literal(`absolute`).describe(`Absolute time range`),start:n.number().describe(`Start time (in epoch seconds)`),end:n.number().describe(`End time (in epoch seconds)`)}),n.object({min:n.number().optional().describe(`Minimum value on vertical axis`),max:n.number().optional().describe(`Maximum value on vertical axis`)})]);static ValueRangeSchema=n.object({min:n.number().optional().describe(`Minimum value on vertical axis`),max:n.number().optional().describe(`Maximum value on vertical axis`)});static GraphSchema=n.discriminatedUnion(`type`,[n.object({type:n.literal(`host`).describe(`Host graph`),hostId:n.string().describe(`Host ID`),name:n.string().describe(`Graph name (e.g., loadavg, cpu)`)}),n.object({type:n.literal(`role`).describe(`Role graph`),roleFullname:n.string().describe("The service name and role name linked with `:`"),name:n.string().describe(`Graph name`),isStacked:n.boolean().optional().describe(`Whether the graph is stacked or line graph`)}),n.object({type:n.literal(`service`).describe(`Service graph`),serviceName:n.string().describe(`Service name`),name:n.string().describe(`Graph name`)}),n.object({type:n.literal(`expression`).describe(`Expression graph`),expression:n.string().describe(`Expression representing a graph`)}),n.object({type:n.literal(`query`).describe(`Query graph`),query:n.string().describe(`PromQL-style queries`),legend:n.string().optional().describe('Query legend. by specifiying the label key in `{{ }}`, it can be expanded to the value of the label. e.g. if you have a label `{ http.method: "GET" }` and you specify `method: {{http.method}}` in the `legend`, it will expand to `method: GET`.')}),n.object({type:n.literal(`unknown`).describe(`Unknown graph`)})]);static ReferenceLineSchema=n.object({label:n.string().describe(`Label of the reference line`),value:n.number().describe(`Value of the reference line`)});static MetricSchema=n.discriminatedUnion(`type`,[n.object({type:n.literal(`host`).describe(`Host metric`),hostId:n.string().describe(`Host ID`),name:n.string().describe("The name of the metric (`loadavg5` etc)")}),n.object({type:n.literal(`service`).describe(`Service metric`),serviceName:n.string().describe(`The name of the service`),name:n.string().describe(`The name of the metric`)}),n.object({type:n.literal(`expression`).describe(`Expression metric`),expression:n.string().describe(`An expression that represents a metric`)}),n.object({type:n.literal(`query`).describe(`Query metric`),query:n.string().describe(`PromQL-style queries`),legend:n.string().describe('Query legend. by specifying the label key in `{{ }}`, it can be expanded to the value of the label. e.g. if you have a label `{ http.method: "GET" }` and you specify `method: {{http.method}}` in the `legend`, it will expand to `method: GET`')}),n.object({type:n.literal(`unknown`).describe(`Unknown metric type (fallback when source is deleted)`)})]);static FormatRuleSchema=n.object({name:n.string().optional().describe(`Name of the format rule`),threshold:n.number().describe(`Base value of the conditional expression`),operator:n.enum([`>`,`<`]).describe(`Specify the conditions under which the emphasized style will be applied.`)});static WidgetSchema=n.discriminatedUnion(`type`,[n.object({type:n.literal(`graph`).describe(`Graph widget`),title:n.string().describe(`The title of the widget`),graph:e.GraphSchema.describe(`Object representing a graph`),range:e.RangeSchema.optional().describe(`Object representing the graph display range`),valueRange:e.ValueRangeSchema.optional().describe(`Object representing the value range of vertical axis`),referenceLines:n.array(e.ReferenceLineSchema).optional().describe(`Array of objects representing the reference line. If you want to remove the reference line setting, specify an empty array. If reference line is not set when get dashboards, an empty array is returned. Cannot specify more than one element in an array.`),layout:e.LayoutSchema.describe(`Object representing the layout`)}),n.object({type:n.literal(`value`).describe(`Value widget`),title:n.string().describe(`The title of the widget`),metric:e.MetricSchema.describe(`Object representing a metric`),fractionSize:n.number().optional().describe(`Decimal places displayed on the widget (0–16)`),suffix:n.string().optional().describe(`The units to be displayed after the value`),formatRules:n.array(e.FormatRuleSchema).optional().describe(`Array of objects representing the format rule. If you want to remove the format rule setting, specify an empty array. If format rule is not set when get dashboards, an empty array is returned. Cannot specify more than one element in an array.`),layout:e.LayoutSchema.describe(`Object representing the layout`)}),n.object({type:n.literal(`markdown`).describe(`Markdown widget`),title:n.string().describe(`The title of the widget`),markdown:n.string().describe(`A character string in Markdown format`),layout:e.LayoutSchema.describe(`Object representing the layout`)}),n.object({type:n.literal(`alertStatus`).describe(`Alert status widget`),title:n.string().describe(`The title of the widget`),roleFullname:n.string().describe("The service name and role name linked by `:`.However, if the relevant role or service has been deleted when the dashboard is retrieved, `roleFullname` will be set as `null`. "),layout:e.LayoutSchema.describe(`Object representing the layout`)})]);static UpdateDashboardToolInput=n.object({dashboardId:n.string().describe(`The ID of the dashboard to update`),title:n.string().describe(`Dashboard name`),memo:n.string().describe(`Dashboard notes`),urlPath:n.string().describe(`Dashboard URL path`),widgets:n.array(e.WidgetSchema).describe(`List of widget objects`)});updateDashboard=async({dashboardId:e,title:t,memo:n,urlPath:r,widgets:i})=>await d(async()=>await this.mackerelClient.updateDashboard(e,{title:t,memo:n,urlPath:r,widgets:i}))},m=class{constructor(e){this.mackerelClient=e}static ListMonitorsToolInput=n.object({});listMonitors=async({})=>await d(async()=>await this.mackerelClient.getMonitors());static GetMonitorToolInput=n.object({monitorId:n.string().describe(`Monitor ID`)});getMonitor=async({monitorId:e})=>await d(async()=>await this.mackerelClient.getMonitor(e))},h=class{constructor(e){this.mackerelClient=e}static ListHostsToolInput=n.object({service:n.string().optional().describe(`Service name`),role:n.array(n.string()).optional().describe(`Role names in the service, multiple assignments possible (result will be a unit of the hosts that belong to each role) if service has not been assigned it will be ignored.`),name:n.string().optional().describe(`Host name`),status:n.array(n.string()).optional().describe("Filters the host status. multiple specifications are possible. defaults are `working` and `standby`."),customIdentifier:n.string().optional().describe(`An identifier for the host that is user-specific and unique to the organization (registered at Register Host Information or Update Host Information API)`),limit:n.number().int().positive().max(100).optional().describe(`Maximum number of hosts to return (default: 20, max: 100)`),offset:n.number().int().min(0).optional().describe(`Number of hosts to skip (default: 0)`)});listHosts=async({service:e,role:t,name:n,status:r,customIdentifier:i,limit:a=20,offset:o=0})=>await d(async()=>{let s=await this.mackerelClient.getHosts(e,t,n,r,i,a,o);return s})},g=class{constructor(e){this.mackerelClient=e}static ListServicesToolInput=n.object({});listServices=async e=>await d(async()=>await this.mackerelClient.getServices())};const _=n.object({key:n.string().describe(`Attribute key`),value:n.string().describe(`Attribute value as a string`),type:n.enum([`string`,`int`,`double`,`bool`]).describe(`Value data type: string, int, double, or bool`),operator:n.enum([`EQ`,`NEQ`,`GT`,`GTE`,`LT`,`LTE`,`STARTS_WITH`]).describe(`Comparison operator. Available operators depend on type: string supports EQ, NEQ, STARTS_WITH; int/double support EQ, GT, GTE, LT, LTE; bool supports EQ, NEQ`)});var v=class{constructor(e){this.mackerelClient=e}static ListTracesToolInput=n.object({serviceName:n.string().describe("Service name. Corresponds to `service.name` in OpenTelemetry semantic conventions"),from:n.number().int().positive().describe(`Start time for trace search (Unix epoch seconds)`),to:n.number().int().positive().describe(`End time for trace search (Unix epoch seconds)`),serviceNamespace:n.string().optional().describe("Service namespace. Corresponds to `service.namespace` in OpenTelemetry semantic conventions"),environment:n.string().optional().describe("Environment name. Corresponds to `deployment.environment` or `deployment.environment.name` in OpenTelemetry semantic conventions"),traceId:n.string().optional().describe(`Filter by trace ID (32-digit hexadecimal string)`),spanName:n.string().optional().describe(`Filter by span name`),version:n.string().optional().describe("Version. Corresponds to `service.version` in OpenTelemetry semantic conventions"),issueFingerprint:n.string().optional().describe(`Filter by issue fingerprint`),minLatencyMillis:n.number().min(0).optional().describe(`Minimum latency in milliseconds`),maxLatencyMillis:n.number().min(0).optional().describe(`Maximum latency in milliseconds`),attributes:n.array(_).optional().describe(`Custom attribute filter conditions`),resourceAttributes:n.array(_).optional().describe(`Resource-level attribute filters`),page:n.number().int().positive().optional().describe(`Page number (starting from 1). Default is 1`),perPage:n.number().int().min(1).max(100).optional().describe(`Number of items per page (1-100). Default is 20`),order:n.object({column:n.enum([`LATENCY`,`START_AT`]).describe("Sort column. One of `LATENCY` (trace latency) or `START_AT` (trace timestamp)"),direction:n.enum([`ASC`,`DESC`]).describe("Sort order. Either `ASC` (ascending) or `DESC` (descending)")}).optional().describe(`Sort preferences. Default is { column: 'START_AT', direction: 'DESC' }`)});listTraces=async({serviceName:e,from:t,to:n,serviceNamespace:r,environment:i,traceId:a,spanName:o,version:s,issueFingerprint:c,minLatencyMillis:l,maxLatencyMillis:u,attributes:f,resourceAttributes:p,page:m,perPage:h,order:g})=>await d(async()=>await this.mackerelClient.listTraces({serviceName:e,from:t,to:n,serviceNamespace:r,environment:i,traceId:a,spanName:o,version:s,issueFingerprint:c,minLatencyMillis:l,maxLatencyMillis:u,attributes:f,resourceAttributes:p,page:m,perPage:h,order:g}));static GetTraceToolInput=n.object({traceId:n.string().describe(`The ID of the trace to retrieve`),includeAttributes:n.boolean().optional().default(!1).describe(`Whether to include span attributes. Default is false to reduce response size`),includeEvents:n.boolean().optional().default(!0).describe(`Whether to include span events. Default is true as events contain important error information`),limit:n.number().int().positive().max(100).optional().default(20).describe(`Maximum number of spans to return per page (default: 20, max: 100)`),offset:n.number().int().min(0).optional().default(0).describe(`Number of spans to skip (default: 0)`),duration:n.number().min(0).optional().describe(`Only return spans with duration (in milliseconds) equal to or greater than this value. Useful for identifying bottlenecks`),errorSpansOnly:n.boolean().optional().default(!1).describe(`If true, only return spans that have errors or status code indicating failure`)});optimizeSpan(e,t,n){let r=e.endTime-e.startTime,i=this.hasSpanError(e),a={spanId:e.spanId,name:e.name,startTime:e.startTime,endTime:e.endTime,duration:r,hasError:i};return t&&(a.attributes=e.attributes),n&&(a.events=e.events),e.status&&e.status.code.toLowerCase()===`error`&&(a.status=e.status),a}hasSpanError(e){return e.status&&e.status.code.toLowerCase()===`error`?!0:e.events?e.events.some(e=>e.name.toLowerCase().includes(`exception`)):!1}filterAndSortSpans(e,t,n){let r=e;return n&&(r=r.filter(e=>e.hasError)),t!==void 0&&(r=r.filter(e=>e.duration>=t)),r.sort((e,t)=>e.hasError&&!t.hasError?-1:!e.hasError&&t.hasError?1:t.duration-e.duration),r}createPageInfo(e,t,n){let r=Math.floor(n/t)+1,i=Math.ceil(e/t);return{hasNextPage:n+t<e,hasPrevPage:n>0,currentPage:r,totalPages:i}}getTrace=async({traceId:e,includeAttributes:t=!1,includeEvents:n=!0,limit:r=20,offset:a=0,duration:o,errorSpansOnly:s=!1})=>await d(async()=>{let c=await this.mackerelClient.getTrace(e),l=c.spans.map(e=>this.optimizeSpan(e,t,n)),u=this.filterAndSortSpans(l,o,s),d=i(u,{limit:r,offset:a}),f=this.createPageInfo(u.length,r,a),p=c.spans.length,m=d.some(e=>e.hasError),h=0;if(l.length>0){let e=Math.min(...l.map(e=>e.startTime)),t=Math.max(...l.map(e=>e.endTime));h=t-e}return{traceId:e,summary:{totalSpans:p,hasErrors:m,totalDuration:h,pageInfo:f},spans:d}})},y=class{baseUrl;apiKey;cacheMap=new Map;cacheTTL;constructor(e,t,n=300){this.baseUrl=e,this.apiKey=t,this.cacheTTL=n*1e3}getCacheKey(e,t,n){let r=n?n.toString():``;return`${e}:${t}:${r}`}getFromCache(e){let t=this.cacheMap.get(e);if(!t)return null;let n=Date.now();return n-t.timestamp>this.cacheTTL?(this.cacheMap.delete(e),null):t.data}setCache(e,t){this.cacheMap.set(e,{data:t,timestamp:Date.now()})}clearCache(){this.cacheMap.clear()}async request(e,t,{searchParams:n,body:r}={}){if(e===`GET`){let r=this.getCacheKey(e,t,n),i=this.getFromCache(r);if(i!==null)return i}let i=`${this.baseUrl}${t}${n?`?`+n.toString():``}`,a={"X-Api-Key":this.apiKey,"Content-Type":`application/json`},o={method:e,headers:a};r&&(o.body=JSON.stringify(r));let s=await fetch(i,o);if(!s.ok){let e=await s.text();throw Error(`Mackerel API error: ${s.status} ${e}`)}let c=await s.json();if(e===`GET`){let r=this.getCacheKey(e,t,n);this.setCache(r,c)}return c}async getAlerts(e,t,n){let r=new URLSearchParams;return e!==void 0&&r.append(`withClosed`,e.toString()),t&&r.append(`nextId`,t),n!==void 0&&r.append(`limit`,n.toString()),this.request(`GET`,`/api/v0/alerts`,{searchParams:r})}async getAlert(e){return this.request(`GET`,`/api/v0/alerts/${e}`)}async getAlertLogs(e,t,n){let r=new URLSearchParams;return t&&r.append(`nextId`,t),n!==void 0&&r.append(`limit`,n.toString()),this.request(`GET`,`/api/v0/alerts/${e}/logs`,{searchParams:r})}async getDashboards(e,t){let n=await this.request(`GET`,`/api/v0/dashboards`),r=e||20,a=t||0,o=n.dashboards.length,s=i(n.dashboards,{limit:r,offset:a}),c={hasPrevPage:a>0,hasNextPage:a+r<o};return{dashboards:s,pageInfo:c}}async getDashboard(e){return this.request(`GET`,`/api/v0/dashboards/${e}`)}static WidgetArray=n.array(p.WidgetSchema);async updateDashboard(e,t){return this.request(`PUT`,`/api/v0/dashboards/${e}`,{body:t})}async getHosts(e,t,n,r,a,o,s){let c=new URLSearchParams;if(e&&c.append(`service`,e),t)for(let e of t)c.append(`role`,e);if(n&&c.append(`name`,n),r)for(let e of r)c.append(`status`,e);a&&c.append(`customIdentifier`,a);let l=await this.request(`GET`,`/api/v0/hosts`,{searchParams:c}),u=o||20,d=s||0,f=l.hosts.length,p=i(l.hosts,{limit:u,offset:d}),m={hasPrevPage:d>0,hasNextPage:d+u<f};return{hosts:p,pageInfo:m}}async getHostMetrics(e,t,n,r){let i=new URLSearchParams;return i.append(`name`,t),i.append(`from`,n.toString()),i.append(`to`,r.toString()),this.request(`GET`,`/api/v0/hosts/${e}/metrics`,{searchParams:i})}async getServices(){return this.request(`GET`,`/api/v0/services`)}async getServiceMetrics(e,t,n,r){let i=new URLSearchParams;return i.append(`name`,t),i.append(`from`,n.toString()),i.append(`to`,r.toString()),this.request(`GET`,`/api/v0/services/${e}/metrics`,{searchParams:i})}async getMonitors(){return this.request(`GET`,`/api/v0/monitors`)}async getMonitor(e){return this.request(`GET`,`/api/v0/monitors/${e}`)}async getTrace(e){return this.request(`GET`,`/api/v0/traces/${e}`)}async getHttpServerStats(e,t,n,r,i,a,o,s,c,l,u,d){let f=new URLSearchParams;return f.append(`serviceName`,e),f.append(`from`,t.toString()),f.append(`to`,n.toString()),r&&f.append(`serviceNamespace`,r),i&&f.append(`environment`,i),a&&f.append(`version`,a),o&&f.append(`method`,o),s&&f.append(`route`,s),c&&f.append(`orderColumn`,c),l&&f.append(`orderDirection`,l),u!==void 0&&f.append(`page`,u.toString()),d!==void 0&&f.append(`perPage`,d.toString()),this.request(`GET`,`/api/v0/apm/http-server-stats`,{searchParams:f})}async getDbQueryStats(e,t,n,r,i,a,o,s,c,l,u){let d=new URLSearchParams;return d.append(`serviceName`,e),d.append(`from`,t.toString()),d.append(`to`,n.toString()),r&&d.append(`serviceNamespace`,r),i&&d.append(`environment`,i),a&&d.append(`version`,a),o&&d.append(`query`,o),s&&d.append(`orderColumn`,s),c&&d.append(`orderDirection`,c),l!==void 0&&d.append(`page`,l.toString()),u!==void 0&&d.append(`perPage`,u.toString()),this.request(`GET`,`/api/v0/apm/db-query-stats`,{searchParams:d})}async listTraces(e){let t={serviceName:e.serviceName,from:e.from,to:e.to};return e.serviceNamespace&&(t.serviceNamespace=e.serviceNamespace),e.environment&&(t.environment=e.environment),e.traceId&&(t.traceId=e.traceId),e.spanName&&(t.spanName=e.spanName),e.version&&(t.version=e.version),e.issueFingerprint&&(t.issueFingerprint=e.issueFingerprint),e.minLatencyMillis!==void 0&&(t.minLatencyMillis=e.minLatencyMillis),e.maxLatencyMillis!==void 0&&(t.maxLatencyMillis=e.maxLatencyMillis),e.attributes&&e.attributes.length>0&&(t.attributes=e.attributes),e.resourceAttributes&&e.resourceAttributes.length>0&&(t.resourceAttributes=e.resourceAttributes),e.page!==void 0&&(t.page=e.page),e.perPage!==void 0&&(t.perPage=e.perPage),e.order&&(t.order=e.order),this.request(`POST`,`/api/v0/traces`,{body:t})}},b=class{constructor(e){this.mackerelClient=e}static GetServiceMetricsToolInput=n.object({serviceName:n.string().describe(`Service name`),name:n.string().describe(`Metric name (e.g., __externalhttp.responsetime.<monitorId>, sales.count, analytics.page_view, etc.)`),from:n.number().describe(`The start of the time period you want metrics for (unix time)`),to:n.number().describe(`The end of the time period you want metrics for (unix time)`)});getServiceMetrics=async({serviceName:e,name:t,from:n,to:r})=>await d(async()=>await this.mackerelClient.getServiceMetrics(e,t,n,r),`get_service_metrics`)},x=class{constructor(e){this.mackerelClient=e}static GetHostMetricsToolInput=n.object({hostId:n.string().describe(`Host ID`),name:n.string().describe(`Metric name (e.g., loadavg5, cpu.user, memory.used, custom.myapp.*, ec2.cpu.used, etc.)`),from:n.number().describe(`The start of the time period you want metrics for (unix time)`),to:n.number().describe(`The end of the time period you want metrics for (unix time)`)});getHostMetrics=async({hostId:e,name:t,from:n,to:r})=>await d(async()=>await this.mackerelClient.getHostMetrics(e,t,n,r),`get_host_metrics`)},S=class{constructor(e){this.mackerelClient=e}static ListHttpServerStatsToolInput=n.object({serviceName:n.string().describe("Service name. Corresponds to `service.name` in OpenTelemetry semantic conventions"),from:n.number().int().positive().describe("Start time for retrieving statistics (Unix epoch seconds). The range between `to` is limited to 30 minutes"),to:n.number().int().positive().describe("End time for retrieving statistics (Unix epoch seconds). The range between `from` is limited to 30 minutes"),serviceNamespace:n.string().optional().describe("Service namespace. Corresponds to `service.namespace` in OpenTelemetry semantic conventions"),environment:n.string().optional().describe("Environment name. Corresponds to `deployment.environment` or `deployment.environment.name` in OpenTelemetry semantic conventions"),version:n.string().optional().describe("Version. Corresponds to `service.version` in OpenTelemetry semantic conventions"),method:n.string().optional().describe("Filter by HTTP method. Corresponds to `http.request.method` or `http.method` in OpenTelemetry semantic conventions. `http.request.method` is preferred"),route:n.string().optional().describe("Filter by route (partial match). Corresponds to `http.route`, `url.path`, `http.target`, or `http.url` in OpenTelemetry semantic conventions. Preferred in this order"),orderColumn:n.enum([`SUM`,`AVERAGE`,`P95`,`ERROR_RATE`,`REQUEST_COUNT`]).optional().describe("Sort column. One of `SUM` (total latency), `AVERAGE` (average latency), `P95` (95th percentile latency), `ERROR_RATE` (error rate percentage), or `REQUEST_COUNT` (request count). Default is `P95`"),orderDirection:n.enum([`ASC`,`DESC`]).optional().describe("Sort order. Either `ASC` (ascending) or `DESC` (descending). Default is `DESC`"),page:n.number().int().positive().optional().describe(`Page number (starting from 1). Default is 1`),perPage:n.number().int().min(1).max(100).optional().describe(`Number of items per page (1-100). Default is 20`)});listHttpServerStats=async({serviceName:e,from:t,to:n,serviceNamespace:r,environment:i,version:a,method:o,route:s,orderColumn:c,orderDirection:l,page:u,perPage:f})=>await d(async()=>await this.mackerelClient.getHttpServerStats(e,t,n,r,i,a,o,s,c,l,u,f));static ListDbQueryStatsToolInput=n.object({serviceName:n.string().describe("Service name. Corresponds to `service.name` in OpenTelemetry semantic conventions."),from:n.number().int().positive().describe("Start time for retrieving statistics (Unix epoch seconds). The range between `to` is limited to 30 minutes"),to:n.number().int().positive().describe("End time for retrieving statistics (Unix epoch seconds). The range between `from` is limited to 30 minutes"),serviceNamespace:n.string().optional().describe("Service namespace. Corresponds to `service.namespace` in OpenTelemetry semantic conventions"),environment:n.string().optional().describe("Environment name. Corresponds to `deployment.environment` or `deployment.environment.name` in OpenTelemetry semantic conventions"),version:n.string().optional().describe("Version. Corresponds to `service.version` in OpenTelemetry semantic conventions"),query:n.string().optional().describe("Filter by SQL query (partial match). Corresponds to `db.query.text` or `db.statement` in OpenTelemetry semantic conventions. db.query.text is preferred"),orderColumn:n.enum([`SUM`,`AVERAGE`,`P95`,`EXECUTION_COUNT`]).optional().describe("Sort column. One of `SUM` (total latency), `AVERAGE` (average latency), `P95` (95th percentile latency), or `EXECUTION_COUNT` (execution count). Default is `P95`."),orderDirection:n.enum([`ASC`,`DESC`]).optional().describe("Sort order. Either `ASC` (ascending) or `DESC` (descending). Default is `DESC`"),page:n.number().int().positive().optional().describe(`Page number (starting from 1). Default is 1`),perPage:n.number().int().min(1).max(100).optional().describe(`Number of items per page (1-100). Default is 20`)});listDbQueryStats=async({serviceName:e,from:t,to:n,serviceNamespace:r,environment:i,version:a,query:o,orderColumn:s,orderDirection:c,page:l,perPage:u})=>await d(async()=>await this.mackerelClient.getDbQueryStats(e,t,n,r,i,a,o,s,c,l,u))};async function C(){let n=new y(`https://api.mackerelio.com`,w()),r=new f(n),i=new p(n),a=new m(n),o=new h(n),s=new x(n),c=new g(n),l=new b(n),u=new v(n),d=new S(n),_=new e({name:`@mackerel/mcp-server`,version:`0.0.1`});_.registerTool(`list_alerts`,{title:`List Alerts`,description:`Retrieve alerts from Mackerel.
128
+ - response_time, custom.my_metric, throughput`}async function d(e,t){try{let t=await e(),n=JSON.stringify(t),i=a(n);return i>r?{content:[{type:`text`,text:o(i)}],isError:!0}:{content:[{type:`text`,text:n}]}}catch(e){let n=e instanceof Error?e.message:String(e);if(t&&n.includes(`404`)&&(t===`get_host_metrics`||t===`get_service_metrics`)){let e;return e=t===`get_host_metrics`?l(n):u(n),{content:[{type:`text`,text:e}],isError:!0}}return{content:[{type:`text`,text:`Error occurred: ${n}`}],isError:!0}}}var f=class{mackerelClient;constructor(e){this.mackerelClient=e}static ListAlertsToolInput=n.object({withClosed:n.boolean().optional().describe(`Whether or not to get resolved alerts. If true, resolved alerts as well as open alerts are retrieved`),nextId:n.string().optional().describe(`If specified, alerts older than the alert with the specified id are retrieved`),limit:n.number().min(1).max(100).optional().describe(`The maximum number of alerts to retrieve. When omitted, up to 100 cases are retrieved. The most that can be specified is 100`)});listAlerts=async({withClosed:e,nextId:t,limit:n})=>await d(async()=>await this.mackerelClient.getAlerts(e,t,n));static GetAlertToolInput=n.object({alertId:n.string().describe(`The ID of the alert to retrieve`)});getAlert=async({alertId:e})=>await d(async()=>await this.mackerelClient.getAlert(e));static GetAlertLogsToolInput=n.object({alertId:n.string().describe(`The ID of the alert to retrieve logs for`),nextId:n.string().optional().describe(`If specified, alert logs older than the specified are retrieved`),limit:n.number().min(1).max(100).optional().describe(`The maximum number of alert logs to retrieve. When omitted, up to 100 logs are retrieved. The most that can be specified is 100`)});getAlertLogs=async({alertId:e,nextId:t,limit:n})=>await d(async()=>await this.mackerelClient.getAlertLogs(e,t,n))},p=class e{mackerelClient;constructor(e){this.mackerelClient=e}static ListDashboardsToolInput=n.object({limit:n.number().int().positive().optional().describe(`Maximum number of dashboards to return (default: 20)`),offset:n.number().int().min(0).optional().describe(`Number of dashboards to skip (default: 0)`),summary:n.boolean().optional().default(!0).describe(`If true, omit widget details to reduce response size (default: true)`)});listDashboards=async({limit:e,offset:t,summary:n=!0})=>await d(async()=>{let r=await this.mackerelClient.getDashboards(e,t);return n?{dashboards:r.dashboards.map(e=>({id:e.id,title:e.title,memo:e.memo,urlPath:e.urlPath,createdAt:e.createdAt,updatedAt:e.updatedAt,widgetCount:e.widgets?.length||0})),pageInfo:r.pageInfo}:r});static GetDashboardToolInput=n.object({dashboardId:n.string().describe(`The ID of the dashboard to retrieve`)});getDashboard=async({dashboardId:e})=>await d(async()=>await this.mackerelClient.getDashboard(e));static LayoutSchema=n.object({x:n.number().describe(`X coordinate of widget`),y:n.number().describe(`Y coordinate of widget`),width:n.number().describe(`Width of widget`),height:n.number().describe(`Height of widget`)});static RangeSchema=n.union([n.object({type:n.literal(`relative`).describe(`Relative time range`),period:n.number().describe(`Length of the period (in seconds)`),offset:n.number().describe(`Difference from the current time (in seconds)`)}),n.object({type:n.literal(`absolute`).describe(`Absolute time range`),start:n.number().describe(`Start time (in epoch seconds)`),end:n.number().describe(`End time (in epoch seconds)`)}),n.object({min:n.number().optional().describe(`Minimum value on vertical axis`),max:n.number().optional().describe(`Maximum value on vertical axis`)})]);static ValueRangeSchema=n.object({min:n.number().optional().describe(`Minimum value on vertical axis`),max:n.number().optional().describe(`Maximum value on vertical axis`)});static GraphSchema=n.discriminatedUnion(`type`,[n.object({type:n.literal(`host`).describe(`Host graph`),hostId:n.string().describe(`Host ID`),name:n.string().describe(`Graph name (e.g., loadavg, cpu)`)}),n.object({type:n.literal(`role`).describe(`Role graph`),roleFullname:n.string().describe("The service name and role name linked with `:`"),name:n.string().describe(`Graph name`),isStacked:n.boolean().optional().describe(`Whether the graph is stacked or line graph`)}),n.object({type:n.literal(`service`).describe(`Service graph`),serviceName:n.string().describe(`Service name`),name:n.string().describe(`Graph name`)}),n.object({type:n.literal(`expression`).describe(`Expression graph`),expression:n.string().describe(`Expression representing a graph`)}),n.object({type:n.literal(`query`).describe(`Query graph`),query:n.string().describe(`PromQL-style queries`),legend:n.string().optional().describe('Query legend. by specifiying the label key in `{{ }}`, it can be expanded to the value of the label. e.g. if you have a label `{ http.method: "GET" }` and you specify `method: {{http.method}}` in the `legend`, it will expand to `method: GET`.')}),n.object({type:n.literal(`unknown`).describe(`Unknown graph`)})]);static ReferenceLineSchema=n.object({label:n.string().describe(`Label of the reference line`),value:n.number().describe(`Value of the reference line`)});static MetricSchema=n.discriminatedUnion(`type`,[n.object({type:n.literal(`host`).describe(`Host metric`),hostId:n.string().describe(`Host ID`),name:n.string().describe("The name of the metric (`loadavg5` etc)")}),n.object({type:n.literal(`service`).describe(`Service metric`),serviceName:n.string().describe(`The name of the service`),name:n.string().describe(`The name of the metric`)}),n.object({type:n.literal(`expression`).describe(`Expression metric`),expression:n.string().describe(`An expression that represents a metric`)}),n.object({type:n.literal(`query`).describe(`Query metric`),query:n.string().describe(`PromQL-style queries`),legend:n.string().describe('Query legend. by specifying the label key in `{{ }}`, it can be expanded to the value of the label. e.g. if you have a label `{ http.method: "GET" }` and you specify `method: {{http.method}}` in the `legend`, it will expand to `method: GET`')}),n.object({type:n.literal(`unknown`).describe(`Unknown metric type (fallback when source is deleted)`)})]);static FormatRuleSchema=n.object({name:n.string().optional().describe(`Name of the format rule`),threshold:n.number().describe(`Base value of the conditional expression`),operator:n.enum([`>`,`<`]).describe(`Specify the conditions under which the emphasized style will be applied.`)});static WidgetSchema=n.discriminatedUnion(`type`,[n.object({type:n.literal(`graph`).describe(`Graph widget`),title:n.string().describe(`The title of the widget`),graph:e.GraphSchema.describe(`Object representing a graph`),range:e.RangeSchema.optional().describe(`Object representing the graph display range`),valueRange:e.ValueRangeSchema.optional().describe(`Object representing the value range of vertical axis`),referenceLines:n.array(e.ReferenceLineSchema).optional().describe(`Array of objects representing the reference line. If you want to remove the reference line setting, specify an empty array. If reference line is not set when get dashboards, an empty array is returned. Cannot specify more than one element in an array.`),layout:e.LayoutSchema.describe(`Object representing the layout`)}),n.object({type:n.literal(`value`).describe(`Value widget`),title:n.string().describe(`The title of the widget`),metric:e.MetricSchema.describe(`Object representing a metric`),fractionSize:n.number().optional().describe(`Decimal places displayed on the widget (0–16)`),suffix:n.string().optional().describe(`The units to be displayed after the value`),formatRules:n.array(e.FormatRuleSchema).optional().describe(`Array of objects representing the format rule. If you want to remove the format rule setting, specify an empty array. If format rule is not set when get dashboards, an empty array is returned. Cannot specify more than one element in an array.`),layout:e.LayoutSchema.describe(`Object representing the layout`)}),n.object({type:n.literal(`markdown`).describe(`Markdown widget`),title:n.string().describe(`The title of the widget`),markdown:n.string().describe(`A character string in Markdown format`),layout:e.LayoutSchema.describe(`Object representing the layout`)}),n.object({type:n.literal(`alertStatus`).describe(`Alert status widget`),title:n.string().describe(`The title of the widget`),roleFullname:n.string().describe("The service name and role name linked by `:`.However, if the relevant role or service has been deleted when the dashboard is retrieved, `roleFullname` will be set as `null`. "),layout:e.LayoutSchema.describe(`Object representing the layout`)})]);static UpdateDashboardToolInput=n.object({dashboardId:n.string().describe(`The ID of the dashboard to update`),title:n.string().describe(`Dashboard name`),memo:n.string().describe(`Dashboard notes`),urlPath:n.string().describe(`Dashboard URL path`),widgets:n.array(e.WidgetSchema).describe(`List of widget objects`)});updateDashboard=async({dashboardId:e,title:t,memo:n,urlPath:r,widgets:i})=>await d(async()=>await this.mackerelClient.updateDashboard(e,{title:t,memo:n,urlPath:r,widgets:i}))},m=class{mackerelClient;constructor(e){this.mackerelClient=e}static ListMonitorsToolInput=n.object({});listMonitors=async({})=>await d(async()=>await this.mackerelClient.getMonitors());static GetMonitorToolInput=n.object({monitorId:n.string().describe(`Monitor ID`)});getMonitor=async({monitorId:e})=>await d(async()=>await this.mackerelClient.getMonitor(e))},h=class{mackerelClient;constructor(e){this.mackerelClient=e}static ListHostsToolInput=n.object({service:n.string().optional().describe(`Service name`),role:n.array(n.string()).optional().describe(`Role names in the service, multiple assignments possible (result will be a unit of the hosts that belong to each role) if service has not been assigned it will be ignored.`),name:n.string().optional().describe(`Host name`),status:n.array(n.string()).optional().describe("Filters the host status. multiple specifications are possible. defaults are `working` and `standby`."),customIdentifier:n.string().optional().describe(`An identifier for the host that is user-specific and unique to the organization (registered at Register Host Information or Update Host Information API)`),limit:n.number().int().positive().max(100).optional().describe(`Maximum number of hosts to return (default: 20, max: 100)`),offset:n.number().int().min(0).optional().describe(`Number of hosts to skip (default: 0)`)});listHosts=async({service:e,role:t,name:n,status:r,customIdentifier:i,limit:a=20,offset:o=0})=>await d(async()=>await this.mackerelClient.getHosts(e,t,n,r,i,a,o))},g=class{mackerelClient;constructor(e){this.mackerelClient=e}static ListServicesToolInput=n.object({});listServices=async e=>await d(async()=>await this.mackerelClient.getServices())};const _=n.object({key:n.string().describe(`Attribute key`),value:n.string().describe(`Attribute value as a string`),type:n.enum([`string`,`int`,`double`,`bool`]).describe(`Value data type: string, int, double, or bool`),operator:n.enum([`EQ`,`NEQ`,`GT`,`GTE`,`LT`,`LTE`,`STARTS_WITH`]).describe(`Comparison operator. Available operators depend on type: string supports EQ, NEQ, STARTS_WITH; int/double support EQ, GT, GTE, LT, LTE; bool supports EQ, NEQ`)});var v=class{mackerelClient;constructor(e){this.mackerelClient=e}static ListTracesToolInput=n.object({serviceName:n.string().describe("Service name. Corresponds to `service.name` in OpenTelemetry semantic conventions"),from:n.number().int().positive().describe(`Start time for trace search (Unix epoch seconds)`),to:n.number().int().positive().describe(`End time for trace search (Unix epoch seconds)`),serviceNamespace:n.string().optional().describe("Service namespace. Corresponds to `service.namespace` in OpenTelemetry semantic conventions"),environment:n.string().optional().describe("Environment name. Corresponds to `deployment.environment` or `deployment.environment.name` in OpenTelemetry semantic conventions"),traceId:n.string().optional().describe(`Filter by trace ID (32-digit hexadecimal string)`),spanName:n.string().optional().describe(`Filter by span name`),version:n.string().optional().describe("Version. Corresponds to `service.version` in OpenTelemetry semantic conventions"),issueFingerprint:n.string().optional().describe(`Filter by issue fingerprint`),minLatencyMillis:n.number().min(0).optional().describe(`Minimum latency in milliseconds`),maxLatencyMillis:n.number().min(0).optional().describe(`Maximum latency in milliseconds`),attributes:n.array(_).optional().describe(`Custom attribute filter conditions`),resourceAttributes:n.array(_).optional().describe(`Resource-level attribute filters`),page:n.number().int().positive().optional().describe(`Page number (starting from 1). Default is 1`),perPage:n.number().int().min(1).max(100).optional().describe(`Number of items per page (1-100). Default is 20`),order:n.object({column:n.enum([`LATENCY`,`START_AT`]).describe("Sort column. One of `LATENCY` (trace latency) or `START_AT` (trace timestamp)"),direction:n.enum([`ASC`,`DESC`]).describe("Sort order. Either `ASC` (ascending) or `DESC` (descending)")}).optional().describe(`Sort preferences. Default is { column: 'START_AT', direction: 'DESC' }`)});listTraces=async({serviceName:e,from:t,to:n,serviceNamespace:r,environment:i,traceId:a,spanName:o,version:s,issueFingerprint:c,minLatencyMillis:l,maxLatencyMillis:u,attributes:f,resourceAttributes:p,page:m,perPage:h,order:g})=>await d(async()=>await this.mackerelClient.listTraces({serviceName:e,from:t,to:n,serviceNamespace:r,environment:i,traceId:a,spanName:o,version:s,issueFingerprint:c,minLatencyMillis:l,maxLatencyMillis:u,attributes:f,resourceAttributes:p,page:m,perPage:h,order:g}));static GetTraceToolInput=n.object({traceId:n.string().describe(`The ID of the trace to retrieve`),includeAttributes:n.boolean().optional().default(!1).describe(`Whether to include span attributes. Default is false to reduce response size`),includeEvents:n.boolean().optional().default(!0).describe(`Whether to include span events. Default is true as events contain important error information`),limit:n.number().int().positive().max(100).optional().default(20).describe(`Maximum number of spans to return per page (default: 20, max: 100)`),offset:n.number().int().min(0).optional().default(0).describe(`Number of spans to skip (default: 0)`),duration:n.number().min(0).optional().describe(`Only return spans with duration (in milliseconds) equal to or greater than this value. Useful for identifying bottlenecks`),errorSpansOnly:n.boolean().optional().default(!1).describe(`If true, only return spans that have errors or status code indicating failure`)});optimizeSpan(e,t,n){let r=e.endTime-e.startTime,i=this.hasSpanError(e),a={spanId:e.spanId,name:e.name,startTime:e.startTime,endTime:e.endTime,duration:r,hasError:i};return t&&(a.attributes=e.attributes),n&&(a.events=e.events),e.status&&e.status.code.toLowerCase()===`error`&&(a.status=e.status),a}hasSpanError(e){return e.status&&e.status.code.toLowerCase()===`error`?!0:e.events?e.events.some(e=>e.name.toLowerCase().includes(`exception`)):!1}filterAndSortSpans(e,t,n){let r=e;return n&&(r=r.filter(e=>e.hasError)),t!==void 0&&(r=r.filter(e=>e.duration>=t)),r.sort((e,t)=>e.hasError&&!t.hasError?-1:!e.hasError&&t.hasError?1:t.duration-e.duration),r}createPageInfo(e,t,n){let r=Math.floor(n/t)+1,i=Math.ceil(e/t);return{hasNextPage:n+t<e,hasPrevPage:n>0,currentPage:r,totalPages:i}}getTrace=async({traceId:e,includeAttributes:t=!1,includeEvents:n=!0,limit:r=20,offset:a=0,duration:o,errorSpansOnly:s=!1})=>await d(async()=>{let c=await this.mackerelClient.getTrace(e),l=c.spans.map(e=>this.optimizeSpan(e,t,n)),u=this.filterAndSortSpans(l,o,s),d=i(u,{limit:r,offset:a}),f=this.createPageInfo(u.length,r,a),p=c.spans.length,m=d.some(e=>e.hasError),h=0;if(l.length>0){let e=Math.min(...l.map(e=>e.startTime));h=Math.max(...l.map(e=>e.endTime))-e}return{traceId:e,summary:{totalSpans:p,hasErrors:m,totalDuration:h,pageInfo:f},spans:d}})},y=class{baseUrl;apiKey;cacheMap=new Map;cacheTTL;constructor(e,t,n=300){this.baseUrl=e,this.apiKey=t,this.cacheTTL=n*1e3}getCacheKey(e,t,n){return`${e}:${t}:${n?n.toString():``}`}getFromCache(e){let t=this.cacheMap.get(e);return t?Date.now()-t.timestamp>this.cacheTTL?(this.cacheMap.delete(e),null):t.data:null}setCache(e,t){this.cacheMap.set(e,{data:t,timestamp:Date.now()})}clearCache(){this.cacheMap.clear()}async request(e,t,{searchParams:n,body:r}={}){if(e===`GET`){let r=this.getCacheKey(e,t,n),i=this.getFromCache(r);if(i!==null)return i}let i=`${this.baseUrl}${t}${n?`?`+n.toString():``}`,a={method:e,headers:{"X-Api-Key":this.apiKey,"Content-Type":`application/json`}};r&&(a.body=JSON.stringify(r));let o=await fetch(i,a);if(!o.ok){let e=await o.text();throw Error(`Mackerel API error: ${o.status} ${e}`)}let s=await o.json();if(e===`GET`){let r=this.getCacheKey(e,t,n);this.setCache(r,s)}return s}async getAlerts(e,t,n){let r=new URLSearchParams;return e!==void 0&&r.append(`withClosed`,e.toString()),t&&r.append(`nextId`,t),n!==void 0&&r.append(`limit`,n.toString()),this.request(`GET`,`/api/v0/alerts`,{searchParams:r})}async getAlert(e){return this.request(`GET`,`/api/v0/alerts/${e}`)}async getAlertLogs(e,t,n){let r=new URLSearchParams;return t&&r.append(`nextId`,t),n!==void 0&&r.append(`limit`,n.toString()),this.request(`GET`,`/api/v0/alerts/${e}/logs`,{searchParams:r})}async getDashboards(e,t){let n=await this.request(`GET`,`/api/v0/dashboards`),r=e||20,a=t||0,o=n.dashboards.length;return{dashboards:i(n.dashboards,{limit:r,offset:a}),pageInfo:{hasPrevPage:a>0,hasNextPage:a+r<o}}}async getDashboard(e){return this.request(`GET`,`/api/v0/dashboards/${e}`)}static WidgetArray=n.array(p.WidgetSchema);async updateDashboard(e,t){return this.request(`PUT`,`/api/v0/dashboards/${e}`,{body:t})}async getHosts(e,t,n,r,a,o,s){let c=new URLSearchParams;if(e&&c.append(`service`,e),t)for(let e of t)c.append(`role`,e);if(n&&c.append(`name`,n),r)for(let e of r)c.append(`status`,e);a&&c.append(`customIdentifier`,a);let l=await this.request(`GET`,`/api/v0/hosts`,{searchParams:c}),u=o||20,d=s||0,f=l.hosts.length;return{hosts:i(l.hosts,{limit:u,offset:d}),pageInfo:{hasPrevPage:d>0,hasNextPage:d+u<f}}}async getHostMetrics(e,t,n,r){let i=new URLSearchParams;return i.append(`name`,t),i.append(`from`,n.toString()),i.append(`to`,r.toString()),this.request(`GET`,`/api/v0/hosts/${e}/metrics`,{searchParams:i})}async getServices(){return this.request(`GET`,`/api/v0/services`)}async getServiceMetrics(e,t,n,r){let i=new URLSearchParams;return i.append(`name`,t),i.append(`from`,n.toString()),i.append(`to`,r.toString()),this.request(`GET`,`/api/v0/services/${e}/metrics`,{searchParams:i})}async getMonitors(){return this.request(`GET`,`/api/v0/monitors`)}async getMonitor(e){return this.request(`GET`,`/api/v0/monitors/${e}`)}async getTrace(e){return this.request(`GET`,`/api/v0/traces/${e}`)}async getHttpServerStats(e,t,n,r,i,a,o,s,c,l,u,d){let f=new URLSearchParams;return f.append(`serviceName`,e),f.append(`from`,t.toString()),f.append(`to`,n.toString()),r&&f.append(`serviceNamespace`,r),i&&f.append(`environment`,i),a&&f.append(`version`,a),o&&f.append(`method`,o),s&&f.append(`route`,s),c&&f.append(`orderColumn`,c),l&&f.append(`orderDirection`,l),u!==void 0&&f.append(`page`,u.toString()),d!==void 0&&f.append(`perPage`,d.toString()),this.request(`GET`,`/api/v0/apm/http-server-stats`,{searchParams:f})}async getDbQueryStats(e,t,n,r,i,a,o,s,c,l,u){let d=new URLSearchParams;return d.append(`serviceName`,e),d.append(`from`,t.toString()),d.append(`to`,n.toString()),r&&d.append(`serviceNamespace`,r),i&&d.append(`environment`,i),a&&d.append(`version`,a),o&&d.append(`query`,o),s&&d.append(`orderColumn`,s),c&&d.append(`orderDirection`,c),l!==void 0&&d.append(`page`,l.toString()),u!==void 0&&d.append(`perPage`,u.toString()),this.request(`GET`,`/api/v0/apm/db-query-stats`,{searchParams:d})}async listTraces(e){let t={serviceName:e.serviceName,from:e.from,to:e.to};return e.serviceNamespace&&(t.serviceNamespace=e.serviceNamespace),e.environment&&(t.environment=e.environment),e.traceId&&(t.traceId=e.traceId),e.spanName&&(t.spanName=e.spanName),e.version&&(t.version=e.version),e.issueFingerprint&&(t.issueFingerprint=e.issueFingerprint),e.minLatencyMillis!==void 0&&(t.minLatencyMillis=e.minLatencyMillis),e.maxLatencyMillis!==void 0&&(t.maxLatencyMillis=e.maxLatencyMillis),e.attributes&&e.attributes.length>0&&(t.attributes=e.attributes),e.resourceAttributes&&e.resourceAttributes.length>0&&(t.resourceAttributes=e.resourceAttributes),e.page!==void 0&&(t.page=e.page),e.perPage!==void 0&&(t.perPage=e.perPage),e.order&&(t.order=e.order),this.request(`POST`,`/api/v0/traces`,{body:t})}},b=class{mackerelClient;constructor(e){this.mackerelClient=e}static GetServiceMetricsToolInput=n.object({serviceName:n.string().describe(`Service name`),name:n.string().describe(`Metric name (e.g., __externalhttp.responsetime.<monitorId>, sales.count, analytics.page_view, etc.)`),from:n.number().describe(`The start of the time period you want metrics for (unix time)`),to:n.number().describe(`The end of the time period you want metrics for (unix time)`)});getServiceMetrics=async({serviceName:e,name:t,from:n,to:r})=>await d(async()=>await this.mackerelClient.getServiceMetrics(e,t,n,r),`get_service_metrics`)},x=class{mackerelClient;constructor(e){this.mackerelClient=e}static GetHostMetricsToolInput=n.object({hostId:n.string().describe(`Host ID`),name:n.string().describe(`Metric name (e.g., loadavg5, cpu.user, memory.used, custom.myapp.*, ec2.cpu.used, etc.)`),from:n.number().describe(`The start of the time period you want metrics for (unix time)`),to:n.number().describe(`The end of the time period you want metrics for (unix time)`)});getHostMetrics=async({hostId:e,name:t,from:n,to:r})=>await d(async()=>await this.mackerelClient.getHostMetrics(e,t,n,r),`get_host_metrics`)},S=class{mackerelClient;constructor(e){this.mackerelClient=e}static ListHttpServerStatsToolInput=n.object({serviceName:n.string().describe("Service name. Corresponds to `service.name` in OpenTelemetry semantic conventions"),from:n.number().int().positive().describe("Start time for retrieving statistics (Unix epoch seconds). The range between `to` is limited to 30 minutes"),to:n.number().int().positive().describe("End time for retrieving statistics (Unix epoch seconds). The range between `from` is limited to 30 minutes"),serviceNamespace:n.string().optional().describe("Service namespace. Corresponds to `service.namespace` in OpenTelemetry semantic conventions"),environment:n.string().optional().describe("Environment name. Corresponds to `deployment.environment` or `deployment.environment.name` in OpenTelemetry semantic conventions"),version:n.string().optional().describe("Version. Corresponds to `service.version` in OpenTelemetry semantic conventions"),method:n.string().optional().describe("Filter by HTTP method. Corresponds to `http.request.method` or `http.method` in OpenTelemetry semantic conventions. `http.request.method` is preferred"),route:n.string().optional().describe("Filter by route (partial match). Corresponds to `http.route`, `url.path`, `http.target`, or `http.url` in OpenTelemetry semantic conventions. Preferred in this order"),orderColumn:n.enum([`SUM`,`AVERAGE`,`P95`,`ERROR_RATE`,`REQUEST_COUNT`]).optional().describe("Sort column. One of `SUM` (total latency), `AVERAGE` (average latency), `P95` (95th percentile latency), `ERROR_RATE` (error rate percentage), or `REQUEST_COUNT` (request count). Default is `P95`"),orderDirection:n.enum([`ASC`,`DESC`]).optional().describe("Sort order. Either `ASC` (ascending) or `DESC` (descending). Default is `DESC`"),page:n.number().int().positive().optional().describe(`Page number (starting from 1). Default is 1`),perPage:n.number().int().min(1).max(100).optional().describe(`Number of items per page (1-100). Default is 20`)});listHttpServerStats=async({serviceName:e,from:t,to:n,serviceNamespace:r,environment:i,version:a,method:o,route:s,orderColumn:c,orderDirection:l,page:u,perPage:f})=>await d(async()=>await this.mackerelClient.getHttpServerStats(e,t,n,r,i,a,o,s,c,l,u,f));static ListDbQueryStatsToolInput=n.object({serviceName:n.string().describe("Service name. Corresponds to `service.name` in OpenTelemetry semantic conventions."),from:n.number().int().positive().describe("Start time for retrieving statistics (Unix epoch seconds). The range between `to` is limited to 30 minutes"),to:n.number().int().positive().describe("End time for retrieving statistics (Unix epoch seconds). The range between `from` is limited to 30 minutes"),serviceNamespace:n.string().optional().describe("Service namespace. Corresponds to `service.namespace` in OpenTelemetry semantic conventions"),environment:n.string().optional().describe("Environment name. Corresponds to `deployment.environment` or `deployment.environment.name` in OpenTelemetry semantic conventions"),version:n.string().optional().describe("Version. Corresponds to `service.version` in OpenTelemetry semantic conventions"),query:n.string().optional().describe("Filter by SQL query (partial match). Corresponds to `db.query.text` or `db.statement` in OpenTelemetry semantic conventions. db.query.text is preferred"),orderColumn:n.enum([`SUM`,`AVERAGE`,`P95`,`EXECUTION_COUNT`]).optional().describe("Sort column. One of `SUM` (total latency), `AVERAGE` (average latency), `P95` (95th percentile latency), or `EXECUTION_COUNT` (execution count). Default is `P95`."),orderDirection:n.enum([`ASC`,`DESC`]).optional().describe("Sort order. Either `ASC` (ascending) or `DESC` (descending). Default is `DESC`"),page:n.number().int().positive().optional().describe(`Page number (starting from 1). Default is 1`),perPage:n.number().int().min(1).max(100).optional().describe(`Number of items per page (1-100). Default is 20`)});listDbQueryStats=async({serviceName:e,from:t,to:n,serviceNamespace:r,environment:i,version:a,query:o,orderColumn:s,orderDirection:c,page:l,perPage:u})=>await d(async()=>await this.mackerelClient.getDbQueryStats(e,t,n,r,i,a,o,s,c,l,u))};async function C(){let n=new y(`https://api.mackerelio.com`,w()),r=new f(n),i=new p(n),a=new m(n),o=new h(n),s=new x(n),c=new g(n),l=new b(n),u=new v(n),d=new S(n),_=new e({name:`@mackerel/mcp-server`,version:`0.0.1`});_.registerTool(`list_alerts`,{title:`List Alerts`,description:`Retrieve alerts from Mackerel.
129
129
 
130
130
  🔍 USE THIS TOOL WHEN USERS:
131
131
  - Check currently active alerts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mackerel/mcp-server",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -50,6 +50,6 @@
50
50
  "tsdown": "^0.14.1",
51
51
  "tsx": "^4.20.3",
52
52
  "typescript": "^5.9.2",
53
- "vitest": "^3.2.4"
53
+ "vitest": "^4.1.0"
54
54
  }
55
55
  }
File without changes