@mackerel/mcp-server 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/build/index.js +107 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,3 +63,5 @@ The MCP server can be run either via Docker or npx.
|
|
|
63
63
|
* `list_monitors` - Retrieve monitor configurations.
|
|
64
64
|
* `get_monitor` - Retrieve a specific monitor configuration.
|
|
65
65
|
* `get_trace` - Retrieve trace data by trace ID for distributed tracing analysis.
|
|
66
|
+
* `list_http_server_stats` - Retrieve HTTP server statistics.
|
|
67
|
+
* `list_db_query_stats` - Retrieve database query statistics.
|
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())},_=class{constructor(e){this.mackerelClient=e}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}})},v=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}`)}},y=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`)},b=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`)};async function x(){let n=new v(`https://api.mackerelio.com`,S()),r=new f(n),i=new p(n),a=new m(n),o=new h(n),s=new b(n),c=new g(n),l=new y(n),u=new _(n),d=new e({name:`@mackerel/mcp-server`,version:`0.0.1`});d.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{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())},_=class{constructor(e){this.mackerelClient=e}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}})},v=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})}},y=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`)},b=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`)},x=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 S(){let n=new v(`https://api.mackerelio.com`,C()),r=new f(n),i=new p(n),a=new m(n),o=new h(n),s=new b(n),c=new g(n),l=new y(n),u=new _(n),d=new x(n),S=new e({name:`@mackerel/mcp-server`,version:`0.0.1`});S.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
|
|
@@ -142,7 +142,7 @@ list_alerts()
|
|
|
142
142
|
list_alerts(withClosed=true)
|
|
143
143
|
\`\`\`
|
|
144
144
|
</examples>
|
|
145
|
-
`,inputSchema:f.ListAlertsToolInput.shape},r.listAlerts),
|
|
145
|
+
`,inputSchema:f.ListAlertsToolInput.shape,annotations:{readOnlyHint:!0}},r.listAlerts),S.registerTool(`get_alert`,{title:`Get Alert`,description:`Retrieve a specific alert by ID from Mackerel.
|
|
146
146
|
|
|
147
147
|
🔍 USE THIS TOOL WHEN USERS:
|
|
148
148
|
- Investigate a particular alert
|
|
@@ -153,7 +153,7 @@ list_alerts(withClosed=true)
|
|
|
153
153
|
get_alert(alertId=3Yr)
|
|
154
154
|
\`\`\`
|
|
155
155
|
</example>
|
|
156
|
-
`,inputSchema:f.GetAlertToolInput.shape},r.getAlert),
|
|
156
|
+
`,inputSchema:f.GetAlertToolInput.shape,annotations:{readOnlyHint:!0}},r.getAlert),S.registerTool(`get_alert_logs`,{title:`Get Alert Logs`,description:`Retrieve logs for a specific alert by ID from Mackerel.
|
|
157
157
|
|
|
158
158
|
🔍 USE THIS TOOL WHEN USERS:
|
|
159
159
|
- View status change history for a specific alert
|
|
@@ -165,7 +165,7 @@ get_alert(alertId=3Yr)
|
|
|
165
165
|
get_alert_logs(alertId=3Yr)
|
|
166
166
|
\`\`\`
|
|
167
167
|
</example>
|
|
168
|
-
`,inputSchema:f.GetAlertLogsToolInput.shape},r.getAlertLogs),
|
|
168
|
+
`,inputSchema:f.GetAlertLogsToolInput.shape,annotations:{readOnlyHint:!0}},r.getAlertLogs),S.registerTool(`list_dashboards`,{title:`List Dashboards`,description:`Retrieve all dashboards from Mackerel.
|
|
169
169
|
|
|
170
170
|
🔍 USE THIS TOOL WHEN USERS:
|
|
171
171
|
- Get a list of dashboards
|
|
@@ -177,7 +177,7 @@ get_alert_logs(alertId=3Yr)
|
|
|
177
177
|
list_dashboards()
|
|
178
178
|
\`\`\`
|
|
179
179
|
</example>
|
|
180
|
-
`,inputSchema:p.ListDashboardsToolInput.shape},i.listDashboards),
|
|
180
|
+
`,inputSchema:p.ListDashboardsToolInput.shape,annotations:{readOnlyHint:!0}},i.listDashboards),S.registerTool(`get_dashboard`,{title:`Get Dashboard`,description:`Retrieve a specific dashboard by ID from Mackerel.
|
|
181
181
|
|
|
182
182
|
🔍 USE THIS TOOL WHEN USERS:
|
|
183
183
|
- Get details of a specific dashboard
|
|
@@ -189,7 +189,7 @@ list_dashboards()
|
|
|
189
189
|
get_dashboard(dashboardId="3Yr")
|
|
190
190
|
\`\`\`
|
|
191
191
|
</examples>
|
|
192
|
-
`,inputSchema:p.GetDashboardToolInput.shape},i.getDashboard),
|
|
192
|
+
`,inputSchema:p.GetDashboardToolInput.shape,annotations:{readOnlyHint:!0}},i.getDashboard),S.registerTool(`update_dashboard`,{title:`Update Dashboard`,description:`Update a specific dashboard by ID in Mackerel.
|
|
193
193
|
|
|
194
194
|
🔍 USE THIS TOOL WHEN USERS:
|
|
195
195
|
- Modify dashboard title, memo, or URL path
|
|
@@ -212,7 +212,7 @@ update_dashboard(
|
|
|
212
212
|
)
|
|
213
213
|
\`\`\`
|
|
214
214
|
</examples>
|
|
215
|
-
`,inputSchema:p.UpdateDashboardToolInput.shape},i.updateDashboard),
|
|
215
|
+
`,inputSchema:p.UpdateDashboardToolInput.shape},i.updateDashboard),S.registerTool(`list_hosts`,{title:`List Hosts`,description:`Retrieve hosts from Mackerel.
|
|
216
216
|
|
|
217
217
|
🔍 USE THIS TOOL WHEN USERS:
|
|
218
218
|
- Get a list of hosts
|
|
@@ -245,7 +245,7 @@ list_hosts(summary=true)
|
|
|
245
245
|
list_hosts(limit=20, offset=20)
|
|
246
246
|
\`\`\`
|
|
247
247
|
</examples>
|
|
248
|
-
`,inputSchema:h.ListHostsToolInput.shape},o.listHosts),
|
|
248
|
+
`,inputSchema:h.ListHostsToolInput.shape,annotations:{readOnlyHint:!0}},o.listHosts),S.registerTool(`get_host_metrics`,{title:`Get Host Metrics`,description:`Retrieve metrics data for a specific host from Mackerel.
|
|
249
249
|
|
|
250
250
|
🔍 USE THIS TOOL WHEN USERS:
|
|
251
251
|
- Get metrics data for a specific host
|
|
@@ -274,7 +274,7 @@ get_host_metrics(hostId="host123", name="custom.myapp.response_time", from=16094
|
|
|
274
274
|
get_host_metrics(hostId="host123", name="ec2.cpu.used", from=1609459200, to=1609462800)
|
|
275
275
|
\`\`\`
|
|
276
276
|
</examples>
|
|
277
|
-
`,inputSchema:b.GetHostMetricsToolInput.shape},s.getHostMetrics),
|
|
277
|
+
`,inputSchema:b.GetHostMetricsToolInput.shape,annotations:{readOnlyHint:!0}},s.getHostMetrics),S.registerTool(`list_services`,{title:`List Services`,description:`Retrieve all services from Mackerel.
|
|
278
278
|
|
|
279
279
|
🔍 USE THIS TOOL WHEN USERS:
|
|
280
280
|
- Get a list of services
|
|
@@ -286,7 +286,7 @@ get_host_metrics(hostId="host123", name="ec2.cpu.used", from=1609459200, to=1609
|
|
|
286
286
|
list_services()
|
|
287
287
|
\`\`\`
|
|
288
288
|
</examples>
|
|
289
|
-
`,inputSchema:g.ListServicesToolInput.shape},c.listServices),
|
|
289
|
+
`,inputSchema:g.ListServicesToolInput.shape,annotations:{readOnlyHint:!0}},c.listServices),S.registerTool(`get_service_metrics`,{title:`Get Service Metrics`,description:`Retrieve metrics data for a specific service from Mackerel.
|
|
290
290
|
|
|
291
291
|
🔍 USE THIS TOOL WHEN USERS:
|
|
292
292
|
- "Service metrics" are metrics that correspond to a service that consists of multiple hosts and their collective roles
|
|
@@ -310,7 +310,7 @@ get_service_metrics(serviceName="web", name="__externalhttp.responsetime.<monito
|
|
|
310
310
|
get_service_metrics(serviceName="web", name="analytics.page_view", from=1609459200, to=1609462800)
|
|
311
311
|
\`\`\`
|
|
312
312
|
|
|
313
|
-
</examples>`,inputSchema:y.GetServiceMetricsToolInput.shape},l.getServiceMetrics),
|
|
313
|
+
</examples>`,inputSchema:y.GetServiceMetricsToolInput.shape,annotations:{readOnlyHint:!0}},l.getServiceMetrics),S.registerTool(`list_monitors`,{title:`List Monitors`,description:`Retrieve all monitor configurations from Mackerel.
|
|
314
314
|
|
|
315
315
|
🔍 USE THIS TOOL WHEN USERS:
|
|
316
316
|
- Get a list of all monitors
|
|
@@ -322,7 +322,7 @@ get_service_metrics(serviceName="web", name="analytics.page_view", from=16094592
|
|
|
322
322
|
list_monitors()
|
|
323
323
|
\`\`\`
|
|
324
324
|
</examples>
|
|
325
|
-
`,inputSchema:m.ListMonitorsToolInput.shape},a.listMonitors),
|
|
325
|
+
`,inputSchema:m.ListMonitorsToolInput.shape,annotations:{readOnlyHint:!0}},a.listMonitors),S.registerTool(`get_monitor`,{title:`Get Monitor`,description:`Retrieve a specific monitor configuration by ID from Mackerel.
|
|
326
326
|
|
|
327
327
|
🔍 USE THIS TOOL WHEN USERS:
|
|
328
328
|
- Get details of a specific monitor
|
|
@@ -333,7 +333,7 @@ list_monitors()
|
|
|
333
333
|
get_monitor(monitorId="2cSZzK3XfmB")
|
|
334
334
|
\`\`\`
|
|
335
335
|
</examples>
|
|
336
|
-
`,inputSchema:m.GetMonitorToolInput.shape},a.getMonitor),
|
|
336
|
+
`,inputSchema:m.GetMonitorToolInput.shape,annotations:{readOnlyHint:!0}},a.getMonitor),S.registerTool(`get_trace`,{title:`Get Trace`,description:`Retrieve trace data by trace ID from Mackerel for distributed tracing analysis.
|
|
337
337
|
|
|
338
338
|
🔍 USE THIS TOOL WHEN USERS:
|
|
339
339
|
- Analyze performance bottlenecks in distributed systems
|
|
@@ -379,4 +379,97 @@ get_trace(traceId="abc123def456", limit=20, offset=20) # Second page
|
|
|
379
379
|
get_trace(traceId="abc123def456", errorSpansOnly=true, limit=10, offset=0)
|
|
380
380
|
\`\`\`
|
|
381
381
|
</examples>
|
|
382
|
-
`,inputSchema:_.GetTraceToolInput.shape},u.getTrace)
|
|
382
|
+
`,inputSchema:_.GetTraceToolInput.shape,annotations:{readOnlyHint:!0}},u.getTrace),S.registerTool(`list_http_server_stats`,{title:`List HTTP Server Statistics`,description:`Retrieve HTTP server statistics from Mackerel.
|
|
383
|
+
|
|
384
|
+
🔍 USE THIS TOOL WHEN USERS:
|
|
385
|
+
- Analyze slow HTTP endpoints
|
|
386
|
+
- Identify high-traffic routes
|
|
387
|
+
- Monitor error rates for HTTP requests
|
|
388
|
+
- Investigate API performance issues
|
|
389
|
+
|
|
390
|
+
<examples>
|
|
391
|
+
### Get HTTP server stats
|
|
392
|
+
\`\`\`
|
|
393
|
+
list_http_server_stats(serviceName="my-service", from=1700000000, to=1700001800)
|
|
394
|
+
\`\`\`
|
|
395
|
+
|
|
396
|
+
### Filter by environment and version
|
|
397
|
+
\`\`\`
|
|
398
|
+
list_http_server_stats(
|
|
399
|
+
serviceName="my-service",
|
|
400
|
+
from=1700000000,
|
|
401
|
+
to=1700001800,
|
|
402
|
+
environment="production",
|
|
403
|
+
version="v1.2.3"
|
|
404
|
+
)
|
|
405
|
+
\`\`\`
|
|
406
|
+
|
|
407
|
+
### Filter by HTTP method and route
|
|
408
|
+
\`\`\`
|
|
409
|
+
list_http_server_stats(
|
|
410
|
+
serviceName="my-service",
|
|
411
|
+
from=1700000000,
|
|
412
|
+
to=1700001800,
|
|
413
|
+
method="GET",
|
|
414
|
+
route="/api/users"
|
|
415
|
+
)
|
|
416
|
+
\`\`\`
|
|
417
|
+
|
|
418
|
+
### Pagination
|
|
419
|
+
\`\`\`
|
|
420
|
+
list_http_server_stats(
|
|
421
|
+
serviceName="my-service",
|
|
422
|
+
from=1700000000,
|
|
423
|
+
to=1700001800,
|
|
424
|
+
page=2,
|
|
425
|
+
perPage=50
|
|
426
|
+
)
|
|
427
|
+
\`\`\`
|
|
428
|
+
</examples>
|
|
429
|
+
`,inputSchema:x.ListHttpServerStatsToolInput.shape,annotations:{readOnlyHint:!0}},d.listHttpServerStats),S.registerTool(`list_db_query_stats`,{title:`List Database Query Statistics`,description:`Retrieve database query statistics from Mackerel.
|
|
430
|
+
|
|
431
|
+
🔍 USE THIS TOOL WHEN USERS:
|
|
432
|
+
- Analyze slow database queries
|
|
433
|
+
- Identify high-frequency queries
|
|
434
|
+
- Investigate database performance issues
|
|
435
|
+
- Monitor query execution patterns
|
|
436
|
+
|
|
437
|
+
<examples>
|
|
438
|
+
### Get DB stats
|
|
439
|
+
\`\`\`
|
|
440
|
+
list_db_query_stats(serviceName="my-service", from=1700000000, to=1700001800)
|
|
441
|
+
\`\`\`
|
|
442
|
+
|
|
443
|
+
### Filter by environment and version
|
|
444
|
+
\`\`\`
|
|
445
|
+
list_db_query_stats(
|
|
446
|
+
serviceName="my-service",
|
|
447
|
+
from=1700000000,
|
|
448
|
+
to=1700001800,
|
|
449
|
+
environment="production",
|
|
450
|
+
version="v1.2.3"
|
|
451
|
+
)
|
|
452
|
+
\`\`\`
|
|
453
|
+
|
|
454
|
+
### Search for specific queries
|
|
455
|
+
\`\`\`
|
|
456
|
+
list_db_query_stats(
|
|
457
|
+
serviceName="my-service",
|
|
458
|
+
from=1700000000,
|
|
459
|
+
to=1700001800,
|
|
460
|
+
query="SELECT * FROM users"
|
|
461
|
+
)
|
|
462
|
+
\`\`\`
|
|
463
|
+
|
|
464
|
+
### Pagination
|
|
465
|
+
\`\`\`
|
|
466
|
+
list_db_query_stats(
|
|
467
|
+
serviceName="my-service",
|
|
468
|
+
from=1700000000,
|
|
469
|
+
to=1700001800,
|
|
470
|
+
page=10,
|
|
471
|
+
perPage=50
|
|
472
|
+
)
|
|
473
|
+
\`\`\`
|
|
474
|
+
</examples>
|
|
475
|
+
`,inputSchema:x.ListDbQueryStatsToolInput.shape,annotations:{readOnlyHint:!0}},d.listDbQueryStats);let w=new t;await S.connect(w),console.error(`Mackerel MCP Server running on stdio`)}function C(){let e=process.env.MACKEREL_APIKEY;if(!e)throw Error(`MACKEREL_APIKEY environment variable is not set.`);return e}S().catch(e=>{console.error(`Fatal error in main():`,e),process.exit(1)});export{};
|