BugMojoBugMojoBugMojo
FeaturesPricingBlogGuidesAbout
Log inGet started
BugMojoBugMojo

Bug reports that actually help fix bugs — capture, replay, share.

A product of Softech Infra.

Product

  • Features
  • Pricing
  • Get started
  • Log in

Resources

  • Blog
  • Guides
  • Compare
  • Glossary

Company

  • About
  • Contact
  • Privacy
  • Sitemap
  • Engineering
  • Playbooks
© 2026 BugMojo. All rights reserved.
AllGuidesEngineeringPlaybooksCompareGlossaryAlternativesBy roleBug tracking by framework
  1. Home
  2. Blog
  3. Engineering
  4. How the BugMojo MCP Server Works: Bugs Your AI Agent Can Actually Read
Engineering deep dive

How the BugMojo MCP Server Works: Bugs Your AI Agent Can Actually Read

A senior-engineer deep dive into the BugMojo MCP server: the 14 tools it exposes, the polymorphic AGENT assignee that makes an AI a first-class bug owner, and a live JSON-RPC wire transcript of what crosses between Claude and BugMojo.

Hrishikesh BaidyaHrishikesh Baidya·Jun 5, 2026·11 min read
Engineering
Isometric line-art schematic of the BugMojo MCP server routing a JSON-RPC tools/call from an AI agent node into a bug record, lime glow on a dark canvas
TL;DR
  • The BugMojo MCP server exposes 14 typed JSON-RPC tools in three families: 6 core bug tools, 5 regression tools, 3 agent-task tools.
  • It is a thin client over REST — no business logic; every tool forwards to BugMojo's /api/v1 as a Bearer request and returns the JSON verbatim in content[].text.
  • The wedge is the data model: a bug's owner is assignee_type (MEMBER | AGENT) + assignee_id, so an AI agent is a first-class assignee, not a read-only caller.
  • It runs as a local stdio subprocess via npx -y @bugmojo/mcp-server; your bm_key_ API key never leaves your machine except on outbound HTTPS.

Plenty of bug trackers now ship an MCP server. That is no longer a differentiator. The interesting questions are narrower: what crosses the wire on a tool call, what the payload actually carries, and whether the AI on the other end is a guest with read access or a team member that can own work. This is an architecture deep dive into the BugMojo MCP server — the 14 tools, the thin-client-over-REST design, the polymorphic AGENT assignee, and a real JSON-RPC transcript. It assumes you already know what MCP is; if you don't, start with our developer's primer on MCP. And if you just want to wire it up, the connect-Claude-Code guide is the install walkthrough — this page is the why, not the how.

What the BugMojo MCP server actually is

The BugMojo MCP server is a local stdio program that exposes 14 model-controlled tools over JSON-RPC. It holds no business logic. Each tool is a thin wrapper that turns a tools/call into one authenticated HTTP request against BugMojo's REST API and returns the response JSON verbatim. The data model, not the protocol, is what makes it different from other bug-tracker MCP servers.

MCP tools are model-controlled: the LLM discovers them and decides when to call them, with no glue code from you. The spec also asks the client to keep a human in the loop — to surface a tool's inputs and request confirmation before the server is hit. BugMojo leans on that exactly. Write tools like create_bug and update_bug surface their JSON arguments in Claude Code before anything commits, so you approve the precise mutation, not a vague intent.

The server itself is deliberately boring. The entry file describes it as "a thin client that translates MCP tool calls into HTTP API calls to the BugMojo backend. All business logic lives on the backend, not here." That sentence is the whole design philosophy, and the rest of this article is the consequences of taking it seriously.

Key takeaway

The one-line thesis: competitors' MCP servers differ on which tools they expose. BugMojo differs on what the payload carries (rrweb replay + console + network) and who can own the bug (a polymorphic AGENT assignee). The protocol is table stakes; the model is the moat.

The 14 tools, grouped

Every tool is registered with a Zod input schema, so the model receives a typed inputSchema in tools/list and knows the valid fields and enums before it ever calls. The 14 split cleanly into three families:

FeatureToolFamilyRead / Write
list_bugslist_bugsCoreRead
get_bugget_bugCoreRead
search_bugssearch_bugsCoreRead
create_bugcreate_bugCoreWrite
update_bugupdate_bugCoreWrite
add_commentadd_commentCoreWrite
list_regression_suiteslist_regression_suitesRegressionRead
get_regression_suiteget_regression_suiteRegressionRead
create_regression_runcreate_regression_runRegressionWrite
submit_test_resultsubmit_test_resultRegressionWrite
get_run_summaryget_run_summaryRegressionRead
get_agent_tasksget_agent_tasksAgentRead
claim_agent_taskclaim_agent_taskAgentWrite
update_agent_taskupdate_agent_taskAgentWrite
The BugMojo MCP surface: 14 tools across three families. Read tools pull context; write tools mutate state.

The split matters for safety. An agent doing read-only triage only needs the read tools; an agent that fixes and verifies needs the write tools. Because the family boundary is explicit, you can scope an API key to exactly the surface a given agent should touch — more on that in the security section.

The differentiator: an AI agent is a first-class assignee

BugMojo records bug ownership as two columns: assignee_type, which is MEMBER or AGENT, and assignee_id. An AI agent is therefore a first-class assignee, not a read-only API consumer. A bug can be assigned to an agent the same way it is assigned to a human, and that agent picks the work up through the same MCP tools, comments on it, and moves its status.

This is the row no other issue-tracker MCP has. When Anthropic open-sourced MCP in November 2024, the reference servers covered Google Drive, Slack, GitHub, Git, Postgres, and Puppeteer. None of them — and none of the early adopters since — model an AI agent as a thing a task can be assigned to. They model the agent as a thing that calls the API. That distinction sounds academic until you watch a workflow run end to end.

In BugMojo, both create_bug and update_bug accept an assignee_type enum alongside the assignee_id. Set it to AGENT and the bug is owned by, say, a QA agent. The agent finds its work with get_agent_tasks, takes it with claim_agent_task (an atomic QUEUED → RUNNING transition so two agents can't grab the same task), and reports back with update_agent_task. The same add_comment a human uses is the channel the agent uses. There is no separate "bot API"; the polymorphism is the whole point.

create_bug — the assignee is polymorphicts
// From the create_bug input schema (Zod).
// The same two fields appear on update_bug — assignment is uniform.
assignee_id: z.string().optional()
  .describe("ID of the member or AI agent to assign this bug to"),
assignee_type: z.enum(["MEMBER", "AGENT"]).optional()
  .describe("MEMBER (human) or AGENT (AI). Required if assignee_id is set"),

This mirrors a pattern that runs through the whole platform, not just the MCP layer: a polymorphic (assignee_type, assignee_id) pair everywhere ownership is expressed. The MCP server doesn't invent the concept — it exposes a data model that already treats agents and humans as peers.

A live JSON-RPC transcript

Every MCP tool call rides one JSON-RPC method, tools/call. On connect the client sends tools/list and the server returns all 14 definitions with their inputSchema. When the model acts, it sends tools/call with a tool name and arguments. The server replies with a result whose content[].text holds the BugMojo REST JSON, and sets isError true on a recoverable failure so the model can self-correct.

Abstractions are easy to nod along to. Here is the actual wire. Three messages, in order: the discovery handshake, the call, and a self-correction round where the model fixes its own bad argument. This is the shape you'll see if you turn on MCP debug logging in Claude Code.

1. Discovery. The client asks what's available. The server answers with typed schemas (truncated here to one tool for space):

→ tools/list (client → server) and the replyjson
// request
{ "jsonrpc": "2.0", "id": 1, "method": "tools/list" }

// response (one of 14 tools shown)
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "search_bugs",
        "description": "Full-text search across all bugs in the workspace...",
        "inputSchema": {
          "type": "object",
          "properties": {
            "query":    { "type": "string", "minLength": 1 },
            "priority": { "enum": ["CRITICAL","HIGH","MEDIUM","LOW","NONE"] },
            "status":   { "enum": ["OPEN","IN_PROGRESS","IN_REVIEW","RESOLVED","CLOSED","REOPENED"] },
            "limit":    { "type": "integer", "default": 20, "maximum": 100 }
          },
          "required": ["query"]
        }
      }
    ]
  }
}

2. The call. The model decides to search for open high-priority checkout bugs and emits a tools/call. The server forwards it to GET /api/v1/bugs/search and returns the REST JSON inside content[].text — a string, because MCP tool results are content blocks, not raw objects:

→ tools/call search_bugs and the successful resultjson
// request
{
  "jsonrpc": "2.0", "id": 2, "method": "tools/call",
  "params": {
    "name": "search_bugs",
    "arguments": { "query": "checkout 500", "priority": "HIGH", "status": "OPEN" }
  }
}

// response — REST payload is serialized into content[].text
{
  "jsonrpc": "2.0", "id": 2,
  "result": {
    "content": [{
      "type": "text",
      "text": "{\n  \"bugs\": [{\n    \"id\": \"bug_7Fq2\",\n    \"number\": 412,\n    \"title\": \"Checkout returns 500 on coupon apply\",\n    \"status\": \"OPEN\",\n    \"priority\": \"HIGH\",\n    \"assignee_type\": \"AGENT\",\n    \"assignee_id\": \"agent_qa_01\"\n  }],\n  \"total\": 1\n}"
    }]
  }
}

3. Self-correction. Suppose the model first guessed a wrong enum (priority: "P1"). The Zod schema rejects it, the server returns a recoverable error with isError: true, the model reads the message, fixes the argument, and retries. The human never has to intervene:

← a recoverable error round (isError lets the model retry)json
// bad call: priority "P1" is not in the enum
{ "jsonrpc":"2.0", "id":3, "method":"tools/call",
  "params": { "name":"search_bugs", "arguments": { "query":"checkout", "priority":"P1" } } }

// recoverable failure — NOT a protocol error; the model sees it and adapts
{ "jsonrpc":"2.0", "id":3,
  "result": {
    "isError": true,
    "content": [{ "type":"text",
      "text": "Invalid 'priority': expected one of CRITICAL|HIGH|MEDIUM|LOW|NONE" }]
  }
}

// the model retries with a valid enum (id:4) → success
Note

The isError: true convention is doing real work here. A JSON-RPC protocol error (malformed request) aborts the call; a tool error inside the result is recoverable, so the model treats it as feedback and adjusts. That is why a typed schema plus a clear error string lets the agent debug itself instead of stalling.

The thin-client-over-REST design, and why

The server holds zero business logic. Each tool builds a path, calls one of get/post/patch on a tiny HTTP client, and serializes the result. The client adds a Bearer header and maps status codes to readable errors — 401 becomes "Authentication failed... check your BUGMOJO_API_KEY," 403 becomes "Permission denied... your API key may lack the required permissions." That is the entire client:

api-client.ts — the whole transport, condensedts
const url = `${this.baseUrl}/api/v1${path}`;
const headers = {
  Authorization: `Bearer ${this.apiKey}`,   // bm_key_...
  "Content-Type": "application/json",
  "User-Agent": "@bugmojo/mcp-server",
};
const response = await fetch(url, { method, headers, body });
if (response.status === 401) throw new Error("Authentication failed...");
if (response.status === 403) throw new Error("Permission denied...");

Three things fall out of this choice, and they're the reason it's worth defending. One: the protocol and the product evolve independently. Permissions, rate limits, validation, and audit logging live on the backend, where they're tested once and apply to every caller — the web UI, the extension, and the MCP server all hit the same /api/v1. Two: the published npm package stays tiny and auditable. A reviewer can read the entire server in one sitting and confirm it only talks to your configured host. Three: it honors a core BugMojo principle — every entity is reachable through the same tRPC/REST API, so a human in the dashboard and an agent over MCP are operating on identical surfaces, never a forked "agent backend" that drifts out of sync.

Transport and where your key lives

Claude Code supports four MCP transports: stdio for local subprocesses, HTTP streamable-http for remote servers, SSE which is deprecated, and WebSocket. BugMojo ships a local stdio server launched via npx. The API key sits in the local MCP config file and travels only on outbound HTTPS calls to your own BugMojo instance, never to a third-party relay.

The server connects over StdioServerTransport — it is a child process Claude Code spawns and talks to over stdin/stdout. Nothing listens on a port; nothing is exposed to the network beyond the outbound calls the tools make. Your bm_key_ key is read from the environment in the local config and used as a Bearer token against the base URL you set. There is no BugMojo-operated middle tier in the path.

One caveat worth stating plainly, because the Claude Code docs do: MCP servers can be a prompt-injection vector. A tool result is text the model reads, and a hostile bug title could in principle carry an instruction. BugMojo's mitigations are the human-in-the-loop confirmation on writes and API-key scoping on what an agent can reach — but you should still only connect MCP servers, and ingest bug data, from sources you trust.

Watch out

Treat the MCP config like any secrets file. The key is a Bearer credential; anything holding it can act as that agent within its scope. Add the config to .gitignore, scope each key to the smallest tool surface the agent needs, and rotate on exposure. Read-only triage agents should never hold a key that can call update_bug or claim_agent_task.

How it compares — honestly

Competitors already ship MCP servers, and some are more capable than BugMojo on their home turf. Sentry's MCP lets developers query production errors and issues straight from the IDE; Atlassian's Remote MCP Server lets Claude summarize work and create Jira issues inside permissioned boundaries. Both are legitimately good. The point of this table is not to claim BugMojo wins everywhere — it doesn't — but to isolate the one capability the issue-tracker MCP servers shipping today don't have.

FeatureBugMojo MCPSentry MCPAtlassian/Jira MCP
Ships an MCP server✓✓✓
Read issues from the IDE✓✓✓
Create / update issues via tools✓partial✓
rrweb session replay in the payload✓via web UI—
Console + network capture in the payload✓partial—
AI agent as a first-class ASSIGNEE✓——
Mature production error-monitoringearly✓—
Deep admin / workflow / governancebasicn/a✓
Marketplace & ecosystem breadthgrowing✓✓
Two-sided on purpose. BugMojo is behind on prod error-monitoring maturity and admin depth; it is alone on the payload and the agent-as-assignee model.

Read that table both directions. If your problem is production exception monitoring at scale, Sentry is more mature and you should use it. If your problem is enterprise workflow governance, Jira's admin depth is unmatched and BugMojo isn't trying to replace it — it pushes captured bugs into Jira (see BugMojo vs Jira). The single row that flips is the last conceptual one: a bug an agent can own, carrying a replayable repro, is a capability with no equivalent in the issue-tracker MCP servers shipping in mid-2026.

Where MCP itself is, in 2026

Some context for why this is worth building against now and not in two years. MCP turned one year old on 25 November 2025. By that anniversary the official registry held close to 2,000 server entries — a 407% jump from the first batch onboarded in September 2025 — with more than 2,900 contributors on the MCP Discord. The bug-tracker category inside that registry is exactly where BugMojo's 14-tool server competes, and the protocol is now stable enough that the November 2025 spec is the version to target, not the 2024 launch docs.

MCP registry server entries: Sept 2025 → Nov 2025 (407% growth)
First onboarded batch (Sept 2025)
393server entries
Registry at 1-yr anniversary (Nov 2025)
2000server entries
Source: Model Context Protocol Blog, 'One Year of MCP', 2025-11-25

The September figure is a public-source derivation, not BugMojo telemetry: the anniversary post states the registry reached ~2,000 entries at 407% growth over the first onboarded batch, which back-calculates to roughly 393 entries in that initial batch. Both numbers trace to the same cited Model Context Protocol post.

Key takeaways

Key takeaway
  • 14 typed tools, 3 families. Core bug ops, regression, and agent tasks — each Zod-validated so the model knows valid fields before it calls.
  • Thin client over REST. No business logic in the server; permissions and validation live on the backend, shared by the UI, extension, and MCP alike.
  • The wedge is the data model. A polymorphic (assignee_type, assignee_id) pair makes an AI agent a first-class bug owner — the row no issue-tracker MCP has.
  • The transcript is honest text. tools/list, then tools/call, then a result in content[].text; isError: true lets the model self-correct.
  • Local stdio, your key. The server is a subprocess; the bm_key_ key never touches a third party.
See an agent own a bug, end to end

BugMojo's extension captures rrweb replay, console, and network in one click — then your AI agent reads, triages, and closes it over MCP. The 10-minute setup is in our connect-Claude-Code guide.

Connect Claude Code to BugMojo

Frequently asked questions

Frequently asked questions

Sources

  1. MCP Server Tools specification (tools/list, tools/call, isError, model-controlled, human-in-the-loop) — Anthropic / Model Context Protocol (2025-11-25)
  2. One Year of MCP: November 2025 Spec Release (registry ~2,000 entries, 407% growth, 2,900+ Discord contributors) — Model Context Protocol Blog (2025-11-25)
  3. Introducing the Model Context Protocol (original launch announcement, reference servers) — Anthropic (2024-11-25)
  4. Connect Claude Code to tools via MCP (transports: stdio, HTTP/streamable-http, SSE deprecated, WebSocket; prompt-injection trust warning) — Anthropic (Claude Code docs) (2026)
  5. MCP Demo Day: How 10 leading AI companies built MCP servers on Cloudflare (Sentry MCP queries errors from the IDE) — Cloudflare (2025)
  6. Introducing Atlassian's Remote Model Context Protocol (MCP) Server (permissioned boundaries, create Jira issues) — Atlassian (2025)
Share:
Hrishikesh Baidya
Hrishikesh Baidya· Chief Technology Officer

Hrishikesh Baidya is the CTO at Softech Infra. He is drawn to architecture that is invisible — systems that simply work — and leads the engineering behind BugMojo.

On this page

  • What the BugMojo MCP server actually is
  • The 14 tools, grouped
  • The differentiator: an AI agent is a first-class assignee
  • A live JSON-RPC transcript
  • The thin-client-over-REST design, and why
  • Transport and where your key lives
  • How it compares — honestly
  • Where MCP itself is, in 2026
  • Key takeaways

Get bug-tracking insights, weekly.

Engineering deep-dives, QA playbooks, and honest tool comparisons. No spam — unsubscribe in one click.