@smartbear/mcp 0.2.0 → 0.2.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 CHANGED
@@ -32,6 +32,7 @@ If setting up manually, add the following configuration to `.vscode/mcp.json`:
32
32
  ],
33
33
  "env": {
34
34
  "INSIGHT_HUB_AUTH_TOKEN": "${input:insight_hub_auth_token}",
35
+ "INSIGHT_HUB_PROJECT_API_KEY": "${input:insight_hub_project_api_key}",
35
36
  "REFLECT_API_TOKEN": "${input:reflect_api_token}",
36
37
  "API_HUB_API_KEY": "${input:api_hub_api_key}"
37
38
  }
@@ -41,19 +42,25 @@ If setting up manually, add the following configuration to `.vscode/mcp.json`:
41
42
  {
42
43
  "id": "insight_hub_auth_token",
43
44
  "type": "promptString",
44
- "description": "Insight Hub Auth Token",
45
+ "description": "Insight Hub Auth Token - leave blank to disable Insight Hub tools",
45
46
  "password": true
46
47
  },
48
+ {
49
+ "id": "insight_hub_project_api_key",
50
+ "type": "promptString",
51
+ "description": "Insight Hub Project API Key - for single project interactions",
52
+ "password": false
53
+ },
47
54
  {
48
55
  "id": "reflect_api_token",
49
56
  "type": "promptString",
50
- "description": "Reflect API Token",
57
+ "description": "Reflect API Token - leave blank to disable Reflect tools",
51
58
  "password": true
52
59
  },
53
60
  {
54
61
  "id": "api_hub_api_key",
55
62
  "type": "promptString",
56
- "description": "API Hub API Key",
63
+ "description": "API Hub API Key - leave blank to disable API Hub tools",
57
64
  "password": true
58
65
  }
59
66
  ]
@@ -113,9 +120,7 @@ Update your `.vscode/mcp.json` to point to your local build:
113
120
  "command": "node",
114
121
  "args": ["<PATH_TO_SMARTBEAR_MCP>/dist/index.js"],
115
122
  "env": {
116
- "INSIGHT_HUB_AUTH_TOKEN": "${input:insight_hub_auth_token}",
117
- "REFLECT_API_TOKEN": "${input:reflect_api_token}",
118
- "API_HUB_API_KEY": "${input:api_hub_api_key}"
123
+ // ...same as above...
119
124
  }
120
125
  }
121
126
  },
@@ -0,0 +1,54 @@
1
+ export function toolDescriptionTemplate(params) {
2
+ const { summary, useCases, examples, parameters, hints } = params;
3
+ let description = summary;
4
+ // Parameters (essential)
5
+ if (parameters.length > 0) {
6
+ description += `\n\n**Parameters:** ${parameters.map(p => `${p.name} (${p.type})${p.required ? ' *required*' : ''}`).join(', ')}`;
7
+ }
8
+ // Use Cases
9
+ if (useCases.length > 0) {
10
+ description += `\n\n**Use Cases:** ${useCases.map((uc, i) => `${i + 1}. ${uc}`).join(' ')}`;
11
+ }
12
+ // Examples
13
+ if (examples.length > 0) {
14
+ description += `\n\n**Examples:**\n` + examples.map((ex, idx) => `${idx + 1}. ${ex.description}\n\`\`\`json\n${JSON.stringify(ex.parameters, null, 2)}\n\`\`\`${ex.expectedOutput ? `\nExpected Output: ${ex.expectedOutput}` : ''}`).join('\n\n');
15
+ }
16
+ // Hints
17
+ if (hints.length > 0) {
18
+ description += `\n\n**Tips:** ${hints.map((hint, i) => `${i + 1}. ${hint}`).join(' ')}`;
19
+ }
20
+ return description.trim();
21
+ }
22
+ // Backward-compatible version of the original function
23
+ export function simpleToolDescriptionTemplate(summary, useCases, examples, hints) {
24
+ return toolDescriptionTemplate({
25
+ summary,
26
+ purpose: summary,
27
+ useCases,
28
+ examples: examples.map(example => ({
29
+ description: example,
30
+ parameters: {}
31
+ })),
32
+ parameters: [],
33
+ hints
34
+ });
35
+ }
36
+ // Helper function to create parameter descriptions
37
+ export function createParameter(name, type, required, description, options = {}) {
38
+ return {
39
+ name,
40
+ type,
41
+ required,
42
+ description,
43
+ examples: options.examples,
44
+ constraints: options.constraints
45
+ };
46
+ }
47
+ // Helper function to create examples with proper structure
48
+ export function createExample(description, parameters, expectedOutput) {
49
+ return {
50
+ description,
51
+ parameters,
52
+ expectedOutput
53
+ };
54
+ }
@@ -6,6 +6,7 @@ import Bugsnag from "../common/bugsnag.js";
6
6
  import NodeCache from "node-cache";
7
7
  import { ProjectAPI } from "./client/api/Project.js";
8
8
  import { FilterObjectSchema } from "./client/api/filters.js";
9
+ import { toolDescriptionTemplate, createParameter, createExample } from "../common/templates.js";
9
10
  const HUB_PREFIX = "00000";
10
11
  const HUB_API_ENDPOINT = "https://api.insighthub.smartbear.com";
11
12
  const DEFAULT_API_ENDPOINT = "https://api.bugsnag.com";
@@ -35,6 +36,8 @@ export class InsightHubClient {
35
36
  headers: {
36
37
  "User-Agent": `${MCP_SERVER_NAME}/${MCP_SERVER_VERSION}`,
37
38
  "Content-Type": "application/json",
39
+ "X-Bugsnag-API": "true",
40
+ "X-Version": "2",
38
41
  },
39
42
  basePath: endpoint,
40
43
  });
@@ -117,9 +120,39 @@ export class InsightHubClient {
117
120
  }
118
121
  registerTools(server) {
119
122
  if (!this.projectApiKey) {
120
- server.tool("list_insight_hub_projects", "List all projects in an organization.", {
121
- page_size: z.number().optional().describe("Number of projects to return per page"),
122
- page: z.number().optional().describe("Page number to return"),
123
+ server.registerTool("list_insight_hub_projects", {
124
+ description: toolDescriptionTemplate({
125
+ summary: "List all projects in the organization with optional pagination",
126
+ purpose: "Retrieve available projects for browsing and selecting which project to analyze",
127
+ useCases: [
128
+ "Browse available projects when no specific project API key is configured",
129
+ "Find project IDs needed for other tools",
130
+ "Get an overview of all projects in the organization"
131
+ ],
132
+ parameters: [
133
+ createParameter("page_size", "number", false, "Number of projects to return per page for pagination", {
134
+ examples: ["10", "25", "50"]
135
+ }),
136
+ createParameter("page", "number", false, "Page number to return (starts from 1)", {
137
+ examples: ["1", "2", "3"]
138
+ })
139
+ ],
140
+ examples: [
141
+ createExample("Get first 10 projects", {
142
+ page_size: 10,
143
+ page: 1
144
+ }, "JSON array of project objects with IDs, names, and metadata"),
145
+ createExample("Get all projects (no pagination)", {}, "JSON array of all available projects")
146
+ ],
147
+ hints: [
148
+ "Use pagination for organizations with many projects to avoid large responses",
149
+ "Project IDs from this list can be used with other tools when no project API key is configured"
150
+ ]
151
+ }),
152
+ inputSchema: {
153
+ page_size: z.number().optional().describe("Number of projects to return per page"),
154
+ page: z.number().optional().describe("Page number to return"),
155
+ }
123
156
  }, async (args, _extra) => {
124
157
  try {
125
158
  let projects = await this.getProjects();
@@ -143,9 +176,37 @@ export class InsightHubClient {
143
176
  }
144
177
  });
145
178
  }
146
- server.tool("get_insight_hub_error", "Get error details from a project", {
147
- errorId: z.string().describe("ID of the error to fetch"),
148
- ...(!this.projectApiKey ? { projectId: z.string().optional().describe("ID of the project") } : {}),
179
+ server.registerTool("get_insight_hub_error", {
180
+ description: toolDescriptionTemplate({
181
+ summary: "Get detailed information about a specific error from a project",
182
+ purpose: "Retrieve error details including metadata, events, and context for debugging",
183
+ useCases: [
184
+ "Investigate a specific error found through list_insight_hub_project_errors",
185
+ "Get error details for debugging and root cause analysis",
186
+ "Retrieve error metadata for incident reports and documentation"
187
+ ],
188
+ parameters: [
189
+ createParameter("errorId", "string", true, "Unique identifier of the error to retrieve", {
190
+ examples: ["6863e2af8c857c0a5023b411"]
191
+ }),
192
+ ...(!this.projectApiKey ? [
193
+ createParameter("projectId", "string", false, "ID of the project containing the error (optional if project API key is configured)")
194
+ ] : [])
195
+ ],
196
+ examples: [
197
+ createExample("Get details for a specific error", {
198
+ errorId: "6863e2af8c857c0a5023b411"
199
+ }, "JSON object with error details including message, stack trace, occurrence count, and metadata")
200
+ ],
201
+ hints: [
202
+ "Error IDs can be found using the list_insight_hub_project_errors tool",
203
+ "Use this after filtering errors to get detailed information about specific errors"
204
+ ]
205
+ }),
206
+ inputSchema: {
207
+ errorId: z.string().describe("ID of the error to fetch"),
208
+ ...(!this.projectApiKey ? { projectId: z.string().optional().describe("ID of the project") } : {}),
209
+ }
149
210
  }, async (args, _extra) => {
150
211
  try {
151
212
  const projectId = typeof args.projectId === 'string' ? args.projectId : this.cache.get(cacheKeys.CURRENT_PROJECT)?.id;
@@ -161,8 +222,33 @@ export class InsightHubClient {
161
222
  throw e;
162
223
  }
163
224
  });
164
- server.tool("get_insight_hub_error_latest_event", "Get the latest event for an error", {
165
- errorId: z.string().describe("ID of the error to get the latest event for"),
225
+ server.registerTool("get_insight_hub_error_latest_event", {
226
+ description: toolDescriptionTemplate({
227
+ summary: "Get the most recent event of a specific error",
228
+ purpose: "Retrieve the latest event (occurrence) of an error to understand when it last happened and its details",
229
+ useCases: [
230
+ "Get the most recent occurrence of an error for immediate debugging",
231
+ "Understand the latest context and stack trace for an ongoing issue",
232
+ "Check when an error last occurred and with what parameters"
233
+ ],
234
+ parameters: [
235
+ createParameter("errorId", "string", true, "Unique identifier of the error to get the latest event for", {
236
+ examples: ["6863e2af8c857c0a5023b411"]
237
+ })
238
+ ],
239
+ examples: [
240
+ createExample("Get the latest event for an error", {
241
+ errorId: "6863e2af8c857c0a5023b411"
242
+ }, "JSON object with the most recent event details including timestamp, stack trace, and context")
243
+ ],
244
+ hints: [
245
+ "This shows the most recent occurrence - use get_insight_hub_error for aggregated details of all events grouped into the error",
246
+ "The event includes detailed context like user information, request data, and environment details"
247
+ ]
248
+ }),
249
+ inputSchema: {
250
+ errorId: z.string().describe("ID of the error to get the latest event for"),
251
+ }
166
252
  }, async (args, _extra) => {
167
253
  try {
168
254
  if (!args.errorId)
@@ -177,8 +263,38 @@ export class InsightHubClient {
177
263
  throw e;
178
264
  }
179
265
  });
180
- server.tool("get_insight_hub_event_details", "Get details of a specific event on Insight Hub", {
181
- link: z.string().describe("Link to the event details"),
266
+ server.registerTool("get_insight_hub_event_details", {
267
+ description: toolDescriptionTemplate({
268
+ summary: "Get detailed information about a specific event using its Insight Hub dashboard URL",
269
+ purpose: "Retrieve event details directly from an Insight Hub web interface URL for quick debugging",
270
+ useCases: [
271
+ "Get event details when given an Insight Hub dashboard URL from a user or notification",
272
+ "Extract event information from shared links or browser URLs",
273
+ "Quick lookup of event details without needing separate project and event IDs"
274
+ ],
275
+ parameters: [
276
+ createParameter("link", "string", true, "Full URL to the event details page in the Insight Hub dashboard (web interface)", {
277
+ examples: [
278
+ "https://app.bugsnag.com/my-org/my-project/errors/6863e2af8c857c0a5023b411?event_id=6863e2af012caf1d5c320000"
279
+ ],
280
+ constraints: [
281
+ "Must be a valid Insight Hub dashboard URL containing project slug and event_id parameter"
282
+ ]
283
+ })
284
+ ],
285
+ examples: [
286
+ createExample("Get event details from Insight Hub URL", {
287
+ link: "https://app.bugsnag.com/my-org/my-project/errors/6863e2af8c857c0a5023b411?event_id=6863e2af012caf1d5c320000"
288
+ }, "JSON object with complete event details including stack trace, metadata, and context")
289
+ ],
290
+ hints: [
291
+ "The URL must contain both project slug in the path and event_id in query parameters",
292
+ "This is useful when users share Insight Hub dashboard URLs and you need to extract the event data"
293
+ ]
294
+ }),
295
+ inputSchema: {
296
+ link: z.string().describe("Link to the event details"),
297
+ }
182
298
  }, async (args, _extra) => {
183
299
  try {
184
300
  if (!args.link)
@@ -208,12 +324,56 @@ export class InsightHubClient {
208
324
  }
209
325
  });
210
326
  // Dynamically infer the filters schema from cached project event fields
211
- server.tool("list_insight_hub_project_errors", "List errors in the current project based on a set of event filters. Use this tool to find or list errors based on user-provided search filters. You can use the `get_project_event_filters` tool to find valid filters for the current project.", {
212
- filters: FilterObjectSchema.optional().describe("Filters to apply to the error list. Valid filters for a project can be found in the `get_project_event_filters` tool."),
213
- // Conditionally add projectId only when no project API key is configured
214
- ...(this.projectApiKey ? {} : {
215
- projectId: z.string().describe("ID of the project"),
327
+ server.registerTool("list_insight_hub_project_errors", {
328
+ description: toolDescriptionTemplate({
329
+ summary: "List and search errors in a project using customizable filters",
330
+ purpose: "Retrieve filtered list of errors from a project for analysis, debugging, and reporting",
331
+ useCases: [
332
+ "Debug recent application errors by filtering for open errors in the last 7 days",
333
+ "Generate error reports for stakeholders by filtering specific error types or severity levels",
334
+ "Monitor error trends over time using date range filters",
335
+ "Find errors affecting specific users or environments using metadata filters"
336
+ ],
337
+ parameters: [
338
+ createParameter("filters", "FilterObject", false, "Apply filters to narrow down the error list. Use get_project_event_filters to discover available filter fields", {
339
+ examples: [
340
+ '{"error.status": [{"type": "eq", "value": "open"}]}',
341
+ '{"event.since": [{"type": "eq", "value": "7d"}]} // Relative time: last 7 days',
342
+ '{"event.since": [{"type": "eq", "value": "2018-05-20T00:00:00Z"}]} // ISO 8601 UTC format',
343
+ '{"user.email": [{"type": "eq", "value": "user@example.com"}]}'
344
+ ],
345
+ constraints: [
346
+ "Time filters support ISO 8601 format (e.g. 2018-05-20T00:00:00Z) or relative format (e.g. 7d, 24h)",
347
+ "ISO 8601 times must be in UTC and use extended format",
348
+ "Relative time periods: h (hours), d (days)"
349
+ ]
350
+ }),
351
+ ...(this.projectApiKey ? [] : [
352
+ createParameter("projectId", "string", true, "ID of the project to query for errors")
353
+ ])
354
+ ],
355
+ examples: [
356
+ createExample("Find errors affecting a specific user in the last 24 hours", {
357
+ filters: {
358
+ "user.email": [{ "type": "eq", "value": "user@example.com" }],
359
+ "event.since": [{ "type": "eq", "value": "24h" }]
360
+ }
361
+ })
362
+ ],
363
+ hints: [
364
+ "Use get_project_event_filters tool first to discover valid filter field names for your project",
365
+ "Combine multiple filters to narrow results - filters are applied with AND logic",
366
+ "For time filters: use relative format (7d, 24h) for recent periods or ISO 8601 UTC format (2018-05-20T00:00:00Z) for specific dates",
367
+ "Common time filters: event.since (from this time), event.before (until this time)"
368
+ ]
216
369
  }),
370
+ inputSchema: {
371
+ filters: FilterObjectSchema.optional().describe("Filters to apply to the error list. Valid filters for a project can be found in the `get_project_event_filters` tool."),
372
+ // Conditionally add projectId only when no project API key is configured
373
+ ...(this.projectApiKey ? {} : {
374
+ projectId: z.string().describe("ID of the project"),
375
+ }),
376
+ }
217
377
  }, async (args, _extra) => {
218
378
  try {
219
379
  const projectId = typeof args.projectId === 'string' ? args.projectId : this.cache.get(cacheKeys.CURRENT_PROJECT)?.id;
@@ -239,7 +399,26 @@ export class InsightHubClient {
239
399
  throw e;
240
400
  }
241
401
  });
242
- server.tool("get_project_event_filters", "Get the available event filters for the current project. Use this tool to find valid filters for the `list_insight_hub_project_errors` tool.", {}, async (_args, _extra) => {
402
+ server.registerTool("get_project_event_filters", {
403
+ description: toolDescriptionTemplate({
404
+ summary: "Get available event filter fields for the current project",
405
+ purpose: "Discover valid filter field names and options that can be used with list_insight_hub_project_errors",
406
+ useCases: [
407
+ "Discover what filter fields are available before searching for errors",
408
+ "Find the correct field names for filtering by user, environment, or custom metadata",
409
+ "Understand filter options and data types for building complex queries"
410
+ ],
411
+ parameters: [],
412
+ examples: [
413
+ createExample("Get all available filter fields", {}, "JSON array of EventField objects containing display_id, custom flag, and filter/pivot options")
414
+ ],
415
+ hints: [
416
+ "Use this tool before list_insight_hub_project_errors to understand available filters",
417
+ "Look for display_id field in the response - these are the field names to use in filters"
418
+ ]
419
+ }),
420
+ inputSchema: {}
421
+ }, async (_args, _extra) => {
243
422
  try {
244
423
  const eventFields = this.cache.get(cacheKeys.PROJECT_EVENT_FILTERS);
245
424
  if (!eventFields)
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartbear/mcp",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "MCP server for interacting SmartBear Products",
5
5
  "keywords": [
6
6
  "smartbear",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@bugsnag/js": "^8.2.0",
38
- "@modelcontextprotocol/sdk": "1.12.1",
38
+ "@modelcontextprotocol/sdk": "^1.15.0",
39
39
  "node-cache": "^5.1.2"
40
40
  },
41
41
  "devDependencies": {
@@ -2,17 +2,20 @@
2
2
 
3
3
  Fetch details of your app crashes and errors from your [Insight Hub](https://www.smartbear.com/insight-hub) dashboard for your LLM to help you diagnose and fix.
4
4
 
5
- To connect an MCP server, you will need to create a personal auth token from the user settings page on your Insight Hub dashboard. If you wish to interact with only one Insight Hub project, we also recommend setting `INSIGHT_HUB_PROJECT_API_KEY` to reduce the scope of the conversation.
5
+ To connect an MCP server, you will need to create a personal auth token from the user settings page on your Insight Hub dashboard.
6
+
7
+ If you wish to interact with only one Insight Hub project, we also recommend setting `INSIGHT_HUB_PROJECT_API_KEY` to reduce the scope of the conversation. This allows the MCP server to pre-cache your project's custom filters for better filtering prompts.
6
8
 
7
9
  ## Example prompts
8
10
 
9
- - "Help me fix this crash from Insight Hub: https://app.bugsnag.com/my-org/my-project/errors/1a2b3c4d5e6f7g8h9i0j1k2l?&event_id=1a2b3c4d5e6f7g8h9i0j1k2l"
10
- - "What are my top events for the 'example' project in insight hub?"
11
+ - "Help me fix this crash: https://app.bugsnag.com/my-org/my-project/errors/1a2b3c4d5e6f7g8h9i0j1k2l?&event_id=1a2b3c4d5e6f7g8h9i0j1k2l"
12
+ - "What are my latest events my project?"
13
+ - "Which errors occurred in the last 7 days?"
11
14
 
12
15
  ## Environment Variables
13
16
 
14
17
  - `INSIGHT_HUB_AUTH_TOKEN`: (Required) The auth token for your account from your Insight Hub dashboard, under **Personal auth tokens** in user settings.
15
- - `INSIGHT_HUB_PROJECT_API_KEY`: (Optional) The API key for the Insight Hub project you wish to interact with. Use this to scope all operations to a single project.
18
+ - `INSIGHT_HUB_PROJECT_API_KEY`: (Recommended) The API key for the Insight Hub project you wish to interact with. Use this to scope all operations to a single project.
16
19
  - `INSIGHT_HUB_ENDPOINT`: (Optional) The API server to connect to. Use this for on-premise installations to point to your own endpoint (e.g. `https://your.api.server`).
17
20
 
18
21
  ## Tools
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartbear/mcp",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "MCP server for interacting SmartBear Products",
5
5
  "keywords": [
6
6
  "smartbear",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@bugsnag/js": "^8.2.0",
38
- "@modelcontextprotocol/sdk": "1.12.1",
38
+ "@modelcontextprotocol/sdk": "^1.15.0",
39
39
  "node-cache": "^5.1.2"
40
40
  },
41
41
  "devDependencies": {