bugherd-mcp 0.1.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/.env.example ADDED
@@ -0,0 +1,3 @@
1
+ # BugHerd API Key
2
+ # Get your API key from BugHerd: Settings > General Settings
3
+ BUGHERD_API_KEY=your-api-key-here
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Berckan Guerrero
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,195 @@
1
+ # BugHerd MCP Server
2
+
3
+ An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that integrates [BugHerd](https://bugherd.com) bug tracking with AI assistants like Claude.
4
+
5
+ ## Features
6
+
7
+ - **List Projects** - View all BugHerd projects accessible to your account
8
+ - **List Tasks** - Browse bugs and feedback with filtering by status, priority, and tags
9
+ - **Get Task Details** - View complete task information including screenshots and element selectors
10
+ - **List Comments** - Read conversation threads on tasks
11
+
12
+ ## Installation
13
+
14
+ ### Prerequisites
15
+
16
+ - Node.js 18+ or Bun
17
+ - A BugHerd account with API access
18
+ - BugHerd API key (get it from Settings > General Settings)
19
+
20
+ ### Setup
21
+
22
+ 1. Clone the repository:
23
+
24
+ ```bash
25
+ git clone https://github.com/berckan/bugherd-mcp.git
26
+ cd bugherd-mcp
27
+ ```
28
+
29
+ 2. Install dependencies:
30
+
31
+ ```bash
32
+ bun install
33
+ # or
34
+ npm install
35
+ ```
36
+
37
+ 3. Build the server:
38
+
39
+ ```bash
40
+ bun run build
41
+ # or
42
+ npm run build
43
+ ```
44
+
45
+ 4. Set your API key:
46
+
47
+ ```bash
48
+ export BUGHERD_API_KEY=your-api-key-here
49
+ ```
50
+
51
+ ## Configuration
52
+
53
+ ### Claude Code
54
+
55
+ Add to your `~/.claude.json`:
56
+
57
+ ```json
58
+ {
59
+ "mcpServers": {
60
+ "bugherd": {
61
+ "type": "stdio",
62
+ "command": "node",
63
+ "args": ["/path/to/bugherd-mcp/dist/index.js"],
64
+ "env": {
65
+ "BUGHERD_API_KEY": "your-api-key-here"
66
+ }
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### Claude Desktop
73
+
74
+ Add to your Claude Desktop config:
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "bugherd": {
80
+ "command": "node",
81
+ "args": ["/path/to/bugherd-mcp/dist/index.js"],
82
+ "env": {
83
+ "BUGHERD_API_KEY": "your-api-key-here"
84
+ }
85
+ }
86
+ }
87
+ }
88
+ ```
89
+
90
+ ## Available Tools
91
+
92
+ ### `bugherd_list_projects`
93
+
94
+ List all BugHerd projects accessible to the authenticated user.
95
+
96
+ **Parameters:** None
97
+
98
+ **Example:**
99
+
100
+ ```
101
+ List my BugHerd projects
102
+ ```
103
+
104
+ ### `bugherd_list_tasks`
105
+
106
+ List tasks for a specific project with optional filters.
107
+
108
+ **Parameters:**
109
+ | Name | Type | Required | Description |
110
+ |------|------|----------|-------------|
111
+ | `project_id` | number | Yes | The BugHerd project ID |
112
+ | `status` | string | No | Filter: backlog, todo, doing, done, closed |
113
+ | `priority` | string | No | Filter: critical, important, normal, minor |
114
+ | `tag` | string | No | Filter by tag name |
115
+ | `page` | number | No | Page number for pagination |
116
+
117
+ **Example:**
118
+
119
+ ```
120
+ Show me all critical bugs in project 12345
121
+ ```
122
+
123
+ ### `bugherd_get_task`
124
+
125
+ Get detailed information about a specific task.
126
+
127
+ **Parameters:**
128
+ | Name | Type | Required | Description |
129
+ |------|------|----------|-------------|
130
+ | `project_id` | number | Yes | The BugHerd project ID |
131
+ | `task_id` | number | Yes | The task ID |
132
+
133
+ **Example:**
134
+
135
+ ```
136
+ Get details for task 678 in project 12345
137
+ ```
138
+
139
+ ### `bugherd_list_comments`
140
+
141
+ List all comments on a specific task.
142
+
143
+ **Parameters:**
144
+ | Name | Type | Required | Description |
145
+ |------|------|----------|-------------|
146
+ | `project_id` | number | Yes | The BugHerd project ID |
147
+ | `task_id` | number | Yes | The task ID |
148
+
149
+ **Example:**
150
+
151
+ ```
152
+ Show comments on task 678 in project 12345
153
+ ```
154
+
155
+ ## Development
156
+
157
+ ### Run in development mode:
158
+
159
+ ```bash
160
+ bun run dev
161
+ ```
162
+
163
+ ### Test with MCP Inspector:
164
+
165
+ ```bash
166
+ BUGHERD_API_KEY=xxx bun run inspector
167
+ ```
168
+
169
+ ### Build for production:
170
+
171
+ ```bash
172
+ bun run build
173
+ ```
174
+
175
+ ## API Rate Limits
176
+
177
+ BugHerd allows an average of 60 requests per minute with bursts of up to 10 in quick succession. The server handles rate limiting errors gracefully.
178
+
179
+ ## License
180
+
181
+ MIT
182
+
183
+ ## Author
184
+
185
+ [Berckan Guerrero](https://github.com/berckan) (hi@berck.io)
186
+
187
+ ## Contributing
188
+
189
+ Contributions are welcome! Please open an issue or submit a pull request.
190
+
191
+ ## Related
192
+
193
+ - [BugHerd API Documentation](https://www.bugherd.com/api_v2)
194
+ - [Model Context Protocol](https://modelcontextprotocol.io/)
195
+ - [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
@@ -0,0 +1,40 @@
1
+ /**
2
+ * BugHerd API v2 Client
3
+ * @see https://www.bugherd.com/api_v2
4
+ *
5
+ * Authentication: Basic HTTP Auth with API key as user, 'x' as password
6
+ * Rate Limit: 60 requests/minute average, bursts of 10
7
+ */
8
+ import type { BugherdProjectsResponse, BugherdProjectResponse, BugherdTasksResponse, BugherdTaskResponse, BugherdCommentsResponse } from "../types/bugherd.js";
9
+ /**
10
+ * List all projects accessible to the authenticated user
11
+ */
12
+ export declare function listProjects(): Promise<BugherdProjectsResponse>;
13
+ /**
14
+ * Get a single project by ID
15
+ */
16
+ export declare function getProject(projectId: number): Promise<BugherdProjectResponse>;
17
+ export interface ListTasksOptions {
18
+ status?: "backlog" | "todo" | "doing" | "done" | "closed";
19
+ priority?: "critical" | "important" | "normal" | "minor";
20
+ tag?: string;
21
+ assignedTo?: number;
22
+ page?: number;
23
+ }
24
+ /**
25
+ * List tasks for a project with optional filters
26
+ */
27
+ export declare function listTasks(projectId: number, options?: ListTasksOptions): Promise<BugherdTasksResponse>;
28
+ /**
29
+ * Get a single task by ID
30
+ */
31
+ export declare function getTask(projectId: number, taskId: number): Promise<BugherdTaskResponse>;
32
+ /**
33
+ * List comments for a task
34
+ */
35
+ export declare function listComments(projectId: number, taskId: number): Promise<BugherdCommentsResponse>;
36
+ /**
37
+ * Verify API connection by fetching organization info
38
+ */
39
+ export declare function verifyConnection(): Promise<boolean>;
40
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAkE7B;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAErE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,sBAAsB,CAAC,CAEjC;AAMD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC1D,QAAQ,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAc/B;AAED;;GAEG;AACH,wBAAsB,OAAO,CAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,mBAAmB,CAAC,CAI9B;AAMD;;GAEG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,uBAAuB,CAAC,CAIlC;AAMD;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAOzD"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * BugHerd API v2 Client
3
+ * @see https://www.bugherd.com/api_v2
4
+ *
5
+ * Authentication: Basic HTTP Auth with API key as user, 'x' as password
6
+ * Rate Limit: 60 requests/minute average, bursts of 10
7
+ */
8
+ const BUGHERD_BASE_URL = "https://www.bugherd.com/api_v2";
9
+ /**
10
+ * Get the API key from environment variables
11
+ */
12
+ function getApiKey() {
13
+ const apiKey = process.env.BUGHERD_API_KEY;
14
+ if (!apiKey) {
15
+ throw new Error("BUGHERD_API_KEY environment variable is required. " +
16
+ "Get your API key from BugHerd Settings > General Settings.");
17
+ }
18
+ return apiKey;
19
+ }
20
+ /**
21
+ * Make an authenticated request to the BugHerd API
22
+ */
23
+ async function bugherdRequest(endpoint, options = {}) {
24
+ const apiKey = getApiKey();
25
+ const auth = Buffer.from(`${apiKey}:x`).toString("base64");
26
+ const url = `${BUGHERD_BASE_URL}${endpoint}`;
27
+ const response = await fetch(url, {
28
+ ...options,
29
+ headers: {
30
+ Authorization: `Basic ${auth}`,
31
+ "Content-Type": "application/json",
32
+ Accept: "application/json",
33
+ ...options.headers,
34
+ },
35
+ });
36
+ if (!response.ok) {
37
+ if (response.status === 429) {
38
+ throw new Error("BugHerd API rate limit exceeded. Wait a moment and try again.");
39
+ }
40
+ if (response.status === 401) {
41
+ throw new Error("BugHerd API authentication failed. Check your BUGHERD_API_KEY.");
42
+ }
43
+ if (response.status === 404) {
44
+ throw new Error(`BugHerd resource not found: ${endpoint}`);
45
+ }
46
+ const errorText = await response.text();
47
+ throw new Error(`BugHerd API error (${response.status}): ${errorText}`);
48
+ }
49
+ return response.json();
50
+ }
51
+ // ============================================================================
52
+ // Projects
53
+ // ============================================================================
54
+ /**
55
+ * List all projects accessible to the authenticated user
56
+ */
57
+ export async function listProjects() {
58
+ return bugherdRequest("/projects.json");
59
+ }
60
+ /**
61
+ * Get a single project by ID
62
+ */
63
+ export async function getProject(projectId) {
64
+ return bugherdRequest(`/projects/${projectId}.json`);
65
+ }
66
+ /**
67
+ * List tasks for a project with optional filters
68
+ */
69
+ export async function listTasks(projectId, options = {}) {
70
+ const params = new URLSearchParams();
71
+ if (options.status)
72
+ params.set("status", options.status);
73
+ if (options.priority)
74
+ params.set("priority", options.priority);
75
+ if (options.tag)
76
+ params.set("tag", options.tag);
77
+ if (options.assignedTo)
78
+ params.set("assigned_to_id", options.assignedTo.toString());
79
+ if (options.page)
80
+ params.set("page", options.page.toString());
81
+ const query = params.toString();
82
+ const endpoint = `/projects/${projectId}/tasks.json${query ? `?${query}` : ""}`;
83
+ return bugherdRequest(endpoint);
84
+ }
85
+ /**
86
+ * Get a single task by ID
87
+ */
88
+ export async function getTask(projectId, taskId) {
89
+ return bugherdRequest(`/projects/${projectId}/tasks/${taskId}.json`);
90
+ }
91
+ // ============================================================================
92
+ // Comments
93
+ // ============================================================================
94
+ /**
95
+ * List comments for a task
96
+ */
97
+ export async function listComments(projectId, taskId) {
98
+ return bugherdRequest(`/projects/${projectId}/tasks/${taskId}/comments.json`);
99
+ }
100
+ // ============================================================================
101
+ // Health Check
102
+ // ============================================================================
103
+ /**
104
+ * Verify API connection by fetching organization info
105
+ */
106
+ export async function verifyConnection() {
107
+ try {
108
+ await listProjects();
109
+ return true;
110
+ }
111
+ catch {
112
+ return false;
113
+ }
114
+ }
115
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * BugHerd MCP Server
4
+ *
5
+ * An MCP server that provides tools to interact with BugHerd's bug tracking API.
6
+ * Enables Claude to list projects, view tasks, and read feedback from BugHerd.
7
+ *
8
+ * @author Berckan Guerrero <hi@berck.io>
9
+ * @license MIT
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG"}
package/dist/index.js ADDED
@@ -0,0 +1,350 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * BugHerd MCP Server
4
+ *
5
+ * An MCP server that provides tools to interact with BugHerd's bug tracking API.
6
+ * Enables Claude to list projects, view tasks, and read feedback from BugHerd.
7
+ *
8
+ * @author Berckan Guerrero <hi@berck.io>
9
+ * @license MIT
10
+ */
11
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
12
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
14
+ import { z } from "zod/v4";
15
+ import { listProjects, listTasks, getTask, listComments, verifyConnection, } from "./api/client.js";
16
+ import { getStatusName, getPriorityName } from "./types/bugherd.js";
17
+ // ============================================================================
18
+ // Server Setup
19
+ // ============================================================================
20
+ const server = new Server({
21
+ name: "bugherd-mcp",
22
+ version: "0.1.0",
23
+ }, {
24
+ capabilities: {
25
+ tools: {},
26
+ },
27
+ });
28
+ // ============================================================================
29
+ // Tool Schemas (Zod)
30
+ // ============================================================================
31
+ const ListProjectsSchema = z.object({});
32
+ const ListTasksSchema = z.object({
33
+ project_id: z.number().describe("The BugHerd project ID"),
34
+ status: z
35
+ .enum(["backlog", "todo", "doing", "done", "closed"])
36
+ .optional()
37
+ .describe("Filter by task status"),
38
+ priority: z
39
+ .enum(["critical", "important", "normal", "minor"])
40
+ .optional()
41
+ .describe("Filter by priority"),
42
+ tag: z.string().optional().describe("Filter by tag name"),
43
+ page: z.number().optional().describe("Page number for pagination"),
44
+ });
45
+ const GetTaskSchema = z.object({
46
+ project_id: z.number().describe("The BugHerd project ID"),
47
+ task_id: z.number().describe("The task ID to retrieve"),
48
+ });
49
+ const ListCommentsSchema = z.object({
50
+ project_id: z.number().describe("The BugHerd project ID"),
51
+ task_id: z.number().describe("The task ID to get comments for"),
52
+ });
53
+ // ============================================================================
54
+ // Tool Definitions
55
+ // ============================================================================
56
+ const TOOLS = [
57
+ {
58
+ name: "bugherd_list_projects",
59
+ description: "List all BugHerd projects accessible to the authenticated user. Returns project names, URLs, and IDs.",
60
+ inputSchema: {
61
+ type: "object",
62
+ properties: {},
63
+ required: [],
64
+ },
65
+ },
66
+ {
67
+ name: "bugherd_list_tasks",
68
+ description: "List tasks (bugs/feedback) for a specific BugHerd project. Can filter by status, priority, or tag.",
69
+ inputSchema: {
70
+ type: "object",
71
+ properties: {
72
+ project_id: {
73
+ type: "number",
74
+ description: "The BugHerd project ID",
75
+ },
76
+ status: {
77
+ type: "string",
78
+ enum: ["backlog", "todo", "doing", "done", "closed"],
79
+ description: "Filter by task status",
80
+ },
81
+ priority: {
82
+ type: "string",
83
+ enum: ["critical", "important", "normal", "minor"],
84
+ description: "Filter by priority",
85
+ },
86
+ tag: {
87
+ type: "string",
88
+ description: "Filter by tag name",
89
+ },
90
+ page: {
91
+ type: "number",
92
+ description: "Page number for pagination (default: 1)",
93
+ },
94
+ },
95
+ required: ["project_id"],
96
+ },
97
+ },
98
+ {
99
+ name: "bugherd_get_task",
100
+ description: "Get detailed information about a specific task including description, screenshot URL, selector info, and metadata.",
101
+ inputSchema: {
102
+ type: "object",
103
+ properties: {
104
+ project_id: {
105
+ type: "number",
106
+ description: "The BugHerd project ID",
107
+ },
108
+ task_id: {
109
+ type: "number",
110
+ description: "The task ID to retrieve",
111
+ },
112
+ },
113
+ required: ["project_id", "task_id"],
114
+ },
115
+ },
116
+ {
117
+ name: "bugherd_list_comments",
118
+ description: "List all comments on a specific task. Returns comment text, author, and timestamp.",
119
+ inputSchema: {
120
+ type: "object",
121
+ properties: {
122
+ project_id: {
123
+ type: "number",
124
+ description: "The BugHerd project ID",
125
+ },
126
+ task_id: {
127
+ type: "number",
128
+ description: "The task ID to get comments for",
129
+ },
130
+ },
131
+ required: ["project_id", "task_id"],
132
+ },
133
+ },
134
+ ];
135
+ // ============================================================================
136
+ // Request Handlers
137
+ // ============================================================================
138
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
139
+ return { tools: TOOLS };
140
+ });
141
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
142
+ const { name, arguments: args } = request.params;
143
+ try {
144
+ // Verify connection on first call
145
+ const connected = await verifyConnection();
146
+ if (!connected) {
147
+ return {
148
+ content: [
149
+ {
150
+ type: "text",
151
+ text: "Error: Unable to connect to BugHerd API. Check your BUGHERD_API_KEY environment variable.",
152
+ },
153
+ ],
154
+ isError: true,
155
+ };
156
+ }
157
+ switch (name) {
158
+ // ====================================================================
159
+ // bugherd_list_projects
160
+ // ====================================================================
161
+ case "bugherd_list_projects": {
162
+ const result = await listProjects();
163
+ const projects = result.projects;
164
+ if (projects.length === 0) {
165
+ return {
166
+ content: [
167
+ {
168
+ type: "text",
169
+ text: "No projects found. Make sure your API key has access to at least one project.",
170
+ },
171
+ ],
172
+ };
173
+ }
174
+ const projectList = projects
175
+ .map((p) => `- **${p.name}** (ID: ${p.id})\n URL: ${p.devurl}\n Active: ${p.is_active ? "Yes" : "No"}`)
176
+ .join("\n\n");
177
+ return {
178
+ content: [
179
+ {
180
+ type: "text",
181
+ text: `## BugHerd Projects (${projects.length})\n\n${projectList}`,
182
+ },
183
+ ],
184
+ };
185
+ }
186
+ // ====================================================================
187
+ // bugherd_list_tasks
188
+ // ====================================================================
189
+ case "bugherd_list_tasks": {
190
+ const parsed = ListTasksSchema.parse(args);
191
+ const options = {
192
+ status: parsed.status,
193
+ priority: parsed.priority,
194
+ tag: parsed.tag,
195
+ page: parsed.page,
196
+ };
197
+ const result = await listTasks(parsed.project_id, options);
198
+ const tasks = result.tasks;
199
+ const meta = result.meta;
200
+ if (tasks.length === 0) {
201
+ return {
202
+ content: [
203
+ {
204
+ type: "text",
205
+ text: "No tasks found matching the criteria.",
206
+ },
207
+ ],
208
+ };
209
+ }
210
+ const taskList = tasks
211
+ .map((t) => {
212
+ const status = getStatusName(t.status_id);
213
+ const priority = getPriorityName(t.priority_id);
214
+ const tags = t.tag_names.length > 0 ? t.tag_names.join(", ") : "none";
215
+ const description = t.description.length > 100
216
+ ? t.description.substring(0, 100) + "..."
217
+ : t.description;
218
+ return `### Task #${t.local_task_id} (ID: ${t.id})
219
+ - **Status:** ${status}
220
+ - **Priority:** ${priority}
221
+ - **Tags:** ${tags}
222
+ - **Created:** ${t.created_at}
223
+ - **Description:** ${description}
224
+ - [View in BugHerd](${t.admin_link})`;
225
+ })
226
+ .join("\n\n");
227
+ const pagination = `Page ${meta.current_page} of ${meta.total_pages} (${meta.count} total tasks)`;
228
+ return {
229
+ content: [
230
+ {
231
+ type: "text",
232
+ text: `## Tasks for Project ${parsed.project_id}\n\n${pagination}\n\n${taskList}`,
233
+ },
234
+ ],
235
+ };
236
+ }
237
+ // ====================================================================
238
+ // bugherd_get_task
239
+ // ====================================================================
240
+ case "bugherd_get_task": {
241
+ const parsed = GetTaskSchema.parse(args);
242
+ const result = await getTask(parsed.project_id, parsed.task_id);
243
+ const task = result.task;
244
+ const status = getStatusName(task.status_id);
245
+ const priority = getPriorityName(task.priority_id);
246
+ const tags = task.tag_names.length > 0 ? task.tag_names.join(", ") : "none";
247
+ let selectorInfo = "Not available";
248
+ if (task.selector_info) {
249
+ selectorInfo = `URL: ${task.selector_info.url}\nSelector: \`${task.selector_info.selector}\``;
250
+ }
251
+ const output = `## Task #${task.local_task_id}
252
+
253
+ **Status:** ${status}
254
+ **Priority:** ${priority}
255
+ **Tags:** ${tags}
256
+ **Created:** ${task.created_at}
257
+ **Updated:** ${task.updated_at}
258
+ **Requester:** ${task.requester_email}
259
+ **Assigned To:** ${task.assigned_to_id ?? "Unassigned"}
260
+
261
+ ### Description
262
+ ${task.description}
263
+
264
+ ### Screenshot
265
+ ${task.screenshot ?? "No screenshot available"}
266
+
267
+ ### Element Info
268
+ ${selectorInfo}
269
+
270
+ ### Links
271
+ - [View in BugHerd](${task.admin_link})`;
272
+ return {
273
+ content: [
274
+ {
275
+ type: "text",
276
+ text: output,
277
+ },
278
+ ],
279
+ };
280
+ }
281
+ // ====================================================================
282
+ // bugherd_list_comments
283
+ // ====================================================================
284
+ case "bugherd_list_comments": {
285
+ const parsed = ListCommentsSchema.parse(args);
286
+ const result = await listComments(parsed.project_id, parsed.task_id);
287
+ const comments = result.comments;
288
+ if (comments.length === 0) {
289
+ return {
290
+ content: [
291
+ {
292
+ type: "text",
293
+ text: "No comments on this task.",
294
+ },
295
+ ],
296
+ };
297
+ }
298
+ const commentList = comments
299
+ .map((c) => `**${c.user.display_name}** (${c.created_at}):\n> ${c.text}`)
300
+ .join("\n\n---\n\n");
301
+ return {
302
+ content: [
303
+ {
304
+ type: "text",
305
+ text: `## Comments on Task ${parsed.task_id} (${comments.length})\n\n${commentList}`,
306
+ },
307
+ ],
308
+ };
309
+ }
310
+ // ====================================================================
311
+ // Unknown Tool
312
+ // ====================================================================
313
+ default:
314
+ return {
315
+ content: [
316
+ {
317
+ type: "text",
318
+ text: `Unknown tool: ${name}`,
319
+ },
320
+ ],
321
+ isError: true,
322
+ };
323
+ }
324
+ }
325
+ catch (error) {
326
+ const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
327
+ return {
328
+ content: [
329
+ {
330
+ type: "text",
331
+ text: `Error: ${errorMessage}`,
332
+ },
333
+ ],
334
+ isError: true,
335
+ };
336
+ }
337
+ });
338
+ // ============================================================================
339
+ // Start Server
340
+ // ============================================================================
341
+ async function main() {
342
+ const transport = new StdioServerTransport();
343
+ await server.connect(transport);
344
+ console.error("BugHerd MCP Server started");
345
+ }
346
+ main().catch((error) => {
347
+ console.error("Fatal error:", error);
348
+ process.exit(1);
349
+ });
350
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * BugHerd API v2 TypeScript Types
3
+ * @see https://www.bugherd.com/api_v2
4
+ */
5
+ export interface BugherdUser {
6
+ id: number;
7
+ email: string;
8
+ display_name: string;
9
+ avatar_url: string | null;
10
+ }
11
+ export interface BugherdProject {
12
+ id: number;
13
+ name: string;
14
+ devurl: string;
15
+ is_active: boolean;
16
+ is_public: boolean;
17
+ created_at: string;
18
+ updated_at: string;
19
+ }
20
+ export interface BugherdProjectsResponse {
21
+ projects: BugherdProject[];
22
+ }
23
+ export interface BugherdProjectResponse {
24
+ project: BugherdProject;
25
+ }
26
+ export type BugherdTaskStatus = "backlog" | "todo" | "doing" | "done" | "closed";
27
+ export type BugherdTaskPriority = "not set" | "critical" | "important" | "normal" | "minor";
28
+ export interface BugherdTask {
29
+ id: number;
30
+ local_task_id: number;
31
+ priority_id: number | null;
32
+ status_id: number;
33
+ description: string;
34
+ created_at: string;
35
+ updated_at: string;
36
+ external_id: string | null;
37
+ requester_id: number;
38
+ requester_email: string;
39
+ assigned_to_id: number | null;
40
+ tag_names: string[];
41
+ admin_link: string;
42
+ screenshot: string | null;
43
+ selector_info: {
44
+ selector: string;
45
+ url: string;
46
+ } | null;
47
+ status?: BugherdTaskStatus;
48
+ priority?: BugherdTaskPriority;
49
+ }
50
+ export interface BugherdTasksResponse {
51
+ tasks: BugherdTask[];
52
+ meta: {
53
+ count: number;
54
+ total_pages: number;
55
+ current_page: number;
56
+ };
57
+ }
58
+ export interface BugherdTaskResponse {
59
+ task: BugherdTask;
60
+ }
61
+ export interface BugherdComment {
62
+ id: number;
63
+ user_id: number;
64
+ text: string;
65
+ created_at: string;
66
+ user: BugherdUser;
67
+ }
68
+ export interface BugherdCommentsResponse {
69
+ comments: BugherdComment[];
70
+ }
71
+ export interface BugherdApiError {
72
+ error: string;
73
+ message?: string;
74
+ }
75
+ export declare const STATUS_MAP: Record<number, BugherdTaskStatus>;
76
+ export declare const PRIORITY_MAP: Record<number, BugherdTaskPriority>;
77
+ export declare function getStatusName(statusId: number): BugherdTaskStatus;
78
+ export declare function getPriorityName(priorityId: number | null): BugherdTaskPriority;
79
+ //# sourceMappingURL=bugherd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bugherd.d.ts","sourceRoot":"","sources":["../../src/types/bugherd.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAMD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,cAAc,CAAC;CACzB;AAMD,MAAM,MAAM,iBAAiB,GACzB,SAAS,GACT,MAAM,GACN,OAAO,GACP,MAAM,GACN,QAAQ,CAAC;AAEb,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,UAAU,GACV,WAAW,GACX,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;KACb,GAAG,IAAI,CAAC;IAET,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,QAAQ,CAAC,EAAE,mBAAmB,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,WAAW,CAAC;CACnB;AAMD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B;AAMD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAMD,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAMxD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAM5D,CAAC;AAEF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAEjE;AAED,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,mBAAmB,CAGrB"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * BugHerd API v2 TypeScript Types
3
+ * @see https://www.bugherd.com/api_v2
4
+ */
5
+ // ============================================================================
6
+ // Status and Priority Mappings
7
+ // ============================================================================
8
+ export const STATUS_MAP = {
9
+ 0: "backlog",
10
+ 1: "todo",
11
+ 2: "doing",
12
+ 3: "done",
13
+ 4: "closed",
14
+ };
15
+ export const PRIORITY_MAP = {
16
+ 0: "not set",
17
+ 1: "critical",
18
+ 2: "important",
19
+ 3: "normal",
20
+ 4: "minor",
21
+ };
22
+ export function getStatusName(statusId) {
23
+ return STATUS_MAP[statusId] ?? "backlog";
24
+ }
25
+ export function getPriorityName(priorityId) {
26
+ if (priorityId === null)
27
+ return "not set";
28
+ return PRIORITY_MAP[priorityId] ?? "not set";
29
+ }
30
+ //# sourceMappingURL=bugherd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bugherd.js","sourceRoot":"","sources":["../../src/types/bugherd.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmHH,+EAA+E;AAC/E,+BAA+B;AAC/B,+EAA+E;AAE/E,MAAM,CAAC,MAAM,UAAU,GAAsC;IAC3D,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,MAAM;IACT,CAAC,EAAE,OAAO;IACV,CAAC,EAAE,MAAM;IACT,CAAC,EAAE,QAAQ;CACZ,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAwC;IAC/D,CAAC,EAAE,SAAS;IACZ,CAAC,EAAE,UAAU;IACb,CAAC,EAAE,WAAW;IACd,CAAC,EAAE,QAAQ;IACX,CAAC,EAAE,OAAO;CACX,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,UAAU,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,UAAyB;IAEzB,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,YAAY,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC;AAC/C,CAAC"}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "bugherd-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for BugHerd integration - manage bugs and feedback from Claude",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "bugherd-mcp": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "bun run src/index.ts",
13
+ "start": "node dist/index.js",
14
+ "inspector": "npx @modelcontextprotocol/inspector bun run src/index.ts"
15
+ },
16
+ "keywords": [
17
+ "mcp",
18
+ "bugherd",
19
+ "claude",
20
+ "bug-tracking",
21
+ "feedback"
22
+ ],
23
+ "author": "Berckan Guerrero <hi@berck.io>",
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/berckan/bugherd-mcp"
28
+ },
29
+ "dependencies": {
30
+ "@modelcontextprotocol/sdk": "^1.25.2",
31
+ "zod": "^4.3.5"
32
+ },
33
+ "devDependencies": {
34
+ "@types/bun": "^1.3.5",
35
+ "@types/node": "^20.0.0",
36
+ "typescript": "^5.9.3"
37
+ },
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ }
41
+ }
package/server.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.Berckan/bugherd-mcp",
4
+ "description": "BugHerd bug tracking integration. List projects, tasks, comments with filtering.",
5
+ "repository": {
6
+ "url": "https://github.com/Berckan/bugherd-mcp",
7
+ "source": "github"
8
+ },
9
+ "version": "0.1.0",
10
+ "packages": [
11
+ {
12
+ "registryType": "npm",
13
+ "identifier": "bugherd-mcp",
14
+ "version": "0.1.0",
15
+ "transport": {
16
+ "type": "stdio"
17
+ },
18
+ "environmentVariables": [
19
+ {
20
+ "description": "BugHerd API key from Settings > General Settings",
21
+ "isRequired": true,
22
+ "format": "string",
23
+ "isSecret": true,
24
+ "name": "BUGHERD_API_KEY"
25
+ }
26
+ ]
27
+ }
28
+ ]
29
+ }