mcp-error-handler
Allows receiving error reports from Bugsnag via webhook, funneling them into the automated fix pipeline.
Provides read-only access to the app's Confluence documentation for context when drafting fixes.
Creates pull requests with automated fixes, manages branches via persistent worktrees, and pushes changes to the repo.
Monitors CI status via the GitHub Checks API and retrieves failure logs to drive iterative fixes.
Creates tickets with root-cause analysis and assigns them automatically based on git blame.
Allows receiving error reports from Sentry via webhook, funneling them into the automated fix pipeline.
Posts notifications about new tickets and pull requests to the app's Slack channel.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-error-handlerCheckout service is failing with payment timeout, create a PR to fix it"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-error-handler
An MCP server that turns an application error into a reviewed pull request, with a human as the only gate before merge.
The idea
Wherever an error comes from — a Sentry alert, another tracker's webhook, or a developer just describing a bug — it lands on one entry point: report_error(app_id, data). The server doesn't know or care which tracker produced data; it can be a provider's raw JSON payload or a plain-text description, and the AI agent is responsible for reading whichever shape it gets.
The server talks to a repo host (GitHub by default), a work tracker (Jira), an app-docs source (Confluence), a messenger (Slack), and an AI provider (Claude/Codex) — each swappable per app via a small plugin interface (see Providers below). Defaults are GitHub + Jira + Confluence + Slack; the only thing that stays source-agnostic no matter what is where the error report itself comes from.
From there, for the app identified by app_id, the server:
Loads that app's config (its repo, Jira project, Slack channel, Confluence space, test command).
Updates its own persistent checkout of the repo (
git pull, then agit worktreefor a throwaway local branch,wip/<fingerprint>) instead of cloning from scratch each time. The fingerprint is deterministic — derived from the error itself, not random — so the same error always maps to the same fingerprint.Checks GitHub for a PR already tagged with that fingerprint (a marker embedded in the PR body, not a branch-name match — the public branch name is the Jira ticket key, which doesn't exist yet at this point). This is fetched either way, but nothing is decided from it yet in code — it's handed to the AI as context, not used as a hard pre-filter.
Has an AI agent read the error, that existing-PR info, the code, and the app's Confluence docs — and make the call: is this even worth acting on? Production or not, already handled or not. Nothing downstream happens until it says so — no ticket, no branch pushed, nothing. If it decides to proceed, it drafts a fix. If the AI provider isn't configured at all, the request just fails here; there's no ticket-without-AI fallback, because a ticket without that judgment isn't the intended behavior.
Runs the app's
test_cmdlocally, in the worktree. This is the fast, cheap check — no need to wait on a CI queue just to find out the fix doesn't even build. If it fails, the agent revises using the local failure output and reruns, up to a retry cap (default 3).Opens a Jira ticket with the root-cause analysis — whether or not a passing fix came out of step 5 (a tried-and-failed attempt still needs a human to know about it) — and assigns it automatically by running
git blameon the changed lines and resolving that author's email to a Jira account.If local tests passed, pushes the local branch to GitHub under the public name
fix/<jira-key>(e.g.fix/CHK-42) and opens a PR linked to the ticket — same key in both places, so they're obviously the same thing at a glance.GitHub Actions CI still has to pass — it's the authoritative check, since it can catch things a local run can't (environment differences, integration jobs, flaky infra). If CI fails despite the local pass, the server pulls the failing job's log via the GitHub Checks API, feeds it back to the agent for another revision, and pushes an update to the same branch — up to its own retry cap (default 3). If CI still isn't green after that, the PR is left open with a comment explaining what was tried, and it's now the developer's problem to finish.
Posts the ticket (and the PR link, once one exists) to the app's Slack channel so the team sees it land.
The developer's job stays the same either way: review and merge a PR that's already passing CI, pick up one that ran out of retries, or start from a ticket that never got a passing automated fix.
Every error source funnels into one authenticated ingestion call. The AI is the single decision point — skip, report itself incomplete, or draft a fix — with the previous attempt and its test output fed back on retry, so it isn't guessing blind and can tell a real test failure from a broken test environment. A ticket always gets created once the loop ends (unless it skipped entirely); only a passing fix goes on to become a branch named after that same ticket. Slack hears about it regardless of which path it took.
Related MCP server: Jira - GitHub MCP Server
Per-app config
The server holds one small config per onboarded app — nothing app-specific lives in the target repo itself:
app_id: checkout-service
repo_url: git@github.com:org/checkout-service.git
default_branch: main
repo_provider: github
tracker_provider: jira
docs_provider: confluence
messenger_provider: slack
jira_project_key: CHK
slack_channel: "#checkout-alerts"
confluence_space: CHK # app documentation the agent reads for context
ai_provider: claude # which coding agent drafts the fix — claude | codex | ...
install_cmd: npm ci # optional — auto-detected from the lockfile present if omitted
test_cmd: npm test # optional — omitting it skips straight to push + PR
default_assignee: jane@org.com # fallback when git blame can't resolve a Jira user
local_max_attempts: 3 # revise-and-rerun attempts against test_cmd before giving up
ci_max_attempts: 3 # revise-and-repush attempts against CI before flagging a developerDesign decisions worth remembering
Source-agnostic ingestion, pluggable tooling. The error report can come from anywhere (Sentry JSON, another tracker's webhook, a developer's sentence) via a thin per-provider webhook route that forwards into
report_error— no per-provider parsing lives in the server. GitHub/Jira/Confluence/Slack are just the defaults; see the Providers bullet below for how each is swapped. MCP itself only speaks JSON-RPC, so providers hit plain webhook routes on the same server, not the MCP endpoint.draftFixdecides via structured output, and commits its own work.providers/llm/claude.tsruns the Claude Agent SDK rooted at the fix worktree withoutputFormat: json_schema, so the skip/fix decision (and the fix summary + changed files) comes back as validated JSON, not parsed prose. The agent is instructed togit commitits own change; a safety-net auto-commit catches anything left uncommitted so a forgetful run can't produce an empty PR. Confluence context is fetched best-effort — sinceconfluence.tsis still a stub, the prompt just proceeds without it today.Persistent worktrees, not fresh clones. Each app's repo is checked out once at onboarding; every fix reuses it via
git pull+git worktree add, which also keeps concurrent fixes for the same app from clobbering each other's working state.Two gates, not one. Local
test_cmdruns first because waiting on a CI queue for feedback the repo can give you in seconds is wasteful — a fix that's obviously broken never leaves the worktree. GitHub Actions CI runs after, because it's the authoritative signal (integration jobs, environment differences a local run won't catch) and still gets its own revise loop when it disagrees with the local result. Each gate has its own retry cap so a genuinely broken app can't loop forever in either stage.No
test_cmdconfigured means no local gate, not "block everything" — the fix goes straight to a PR and CI becomes the only check. This is what keeps the pipeline usable for apps that don't have reliable tests.The worktree gets dependencies installed before the AI ever sees it.
git worktree addonly checks out tracked files —node_modulesis gitignored — so without an explicit install step the AI (andtest_cmdright after it) would hit a completely broken environment: no test runner, no linter, nothing actually runnable.install_cmdruns once per worktree, beforedraftFix, auto-detected from the lockfile if not set explicitly.Retries aren't blind. Each
draftFixcall gets the previous attempt's summary and test output, not just a fresh prompt — so on retry it can tell a real assertion failure caused by its own change apart fromtest_cmditself being broken (missing tooling, config errors, infrastructure unrelated to the bug). In the latter case it reportsincompletewith an explanation instead of repeating the same guess against a test command that was never going to pass regardless of the fix.Assignee comes from the code, not the alert.
git blameon the touched lines is source-agnostic (works whether the error arrived as Sentry JSON or a developer's sentence) and more reliable than trying to infer ownership from the tracker. It depends on git commit email, Jira account email, and Slack identity all lining up — worth checking before relying on it.Confluence is read-only context. The agent consults the app's Confluence space (architecture notes, runbooks) when drafting a fix, the same way it reads the repo — it's an input to the analysis, not something the server writes back to.
The coding agent is swappable per app.
ai_providerpicks which model/tool actually drafts the fix (Claude, Codex, …) — different apps can use different agents without changing any other part of the pipeline, since every downstream step (test gate, Jira, PR, Slack) only cares that a diff exists, not who wrote it.Every external integration is a plugin, not a hardcoded call.
orchestrator.tsnever talks to GitHub/Jira/Slack/Confluence/an LLM directly — it resolves aRepoProvider/TrackerProvider/DocsProvider/MessengerProvider/LLMProviderfromsrc/providers/*/index.tsbased on the app's config, and calls through that interface. Adding Bitbucket support means writingproviders/repo/bitbucket.tsagainst the existingRepoProviderinterface, registering it, and settingrepo_provider: bitbucketon the apps that use it —orchestrator.tsdoesn't change. PlaingitCLI plumbing (clone, worktree, blame) lives inproviders/repo/git.ts, shared by every repo-host provider rather than duplicated per host.
Stack
Node.js + TypeScript, an Express server, packaged as a Docker image.
src/
index.ts Express app: mounts /mcp and /webhooks, error handling, requireSharedSecret auth
mcp.ts MCP server — registers the report_error tool (Streamable HTTP, stateless)
webhooks.ts Plain HTTP routes: /webhooks/{sentry,bugsnag,generic}/:appId
orchestrator.ts The pipeline itself — reportError() and handleCIResult() — resolves providers, sequences the pipeline, no integration-specific code
auth.ts requireSharedSecret — bearer-token check on every inbound route
config.ts Loads config/apps/*.yaml into AppConfig
types.ts Shared cross-cutting types (ErrorReport, AppConfig, Ticket, PullRequest, …)
providers/
repo/ RepoProvider interface + git.ts (shared plumbing) + github.ts (default) + index.ts (registry)
tracker/ TrackerProvider interface + jira.ts (default) + index.ts
docs/ DocsProvider interface + confluence.ts (default, stub — not called by anything yet)
messenger/ MessengerProvider interface + slack.ts (default) + index.ts
llm/ LLMProvider interface + claude.ts (real — Claude Agent SDK) + not-implemented.ts (codex stub) + index.ts
registries.test.ts All five registries resolve/reject correctly (node:test)
config.test.ts Unit tests (node:test, via tsx — no separate test framework)
config/apps/ One YAML file per onboarded app (see Per-app config above)
.github/workflows/ci.yml typecheck + test + build, and a Docker build check, on every push/PRWhat's real vs. stubbed: git plumbing, the local test_cmd runner, the GitHub App auth + PR-dedup lookup, Jira ticket creation, Slack notification, and draftFix for ai_provider: claude (via the Claude Agent SDK — providers/llm/claude.ts) are all fully implemented — reportError runs the whole pipeline for real, right up to opening the PR. Opening the PR itself (RepoProvider.openPullRequest, in providers/repo/github.ts) and ai_provider: codex (providers/llm/not-implemented.ts) are the two remaining stubs, throwing NotImplementedError with what's missing. The webhook/MCP routes surface that as a 501 with a clear message rather than pretending to succeed.
Quick start
On a fresh server:
ssh root@your_server_ip
curl -o ~/start.sh https://raw.githubusercontent.com/4-life/mcp-error-handler/main/start.sh
chmod +x ~/start.sh && ./start.shstart.sh installs Docker if it's missing, clones the repo into ~/mcp-error-handler (or $APP_DIR), copies .env.example to .env if there isn't one yet, and runs docker compose up -d --build. It prints the server's /healthz, MCP, and webhook URLs when done — nothing is wired to real Jira/GitHub/Slack/AI credentials yet, so edit .env and config/apps/ afterward and re-run docker compose up -d --build to pick up the changes. Override APP_DIR or PORT as env vars before running the script if you need non-defaults.
Running it
cp .env.example .env # fill in credentials as integrations get wired up
cp config/apps/example.yaml config/apps/<your-app>.yaml
npm install
npm run dev # tsx watch, http://localhost:3000
npm test # node:test, via tsx
npm run typecheckOr as a container:
docker compose up --buildThe MCP endpoint is POST /mcp (Streamable HTTP). Webhook routes are POST /webhooks/sentry/:appId, /webhooks/bugsnag/:appId, /webhooks/generic/:appId — point your tracker's webhook config (or a curl from a developer) at one of these with the app's app_id in the URL.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- -licenseBqualityNot gradedmaintenanceEnables AI-driven orchestration of GitHub development workflows including automated issue analysis, code generation, code review, and PR creation through multiple specialized agents. Integrates with GitHub Actions to automate the complete development process from issue to pull request.7
- AlicenseNot gradedqualityDmaintenanceEnables end-to-end automation of developer workflows from Jira issue tracking to GitHub pull requests through natural language, allowing developers to search issues, create branches, commit changes, and manage PRs directly from their IDE.2MIT
- AlicenseAqualityDmaintenanceAn intelligent debugging assistant that automates the debugging process by analyzing bugs, injecting HTTP-based debug logs into code across multiple environments (browser, Node.js, mobile, etc.), and iteratively fixing issues based on real-time feedback.8MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to scan GitHub repositories for security vulnerabilities, deployment blockers, and code quality issues. It provides detailed findings and auto-generated code patches to help developers ensure their code is production-ready.60MIT
Related MCP Connectors
AI QA that runs your app in a browser on every pull request: projects, test targets, test cases.
Screens public GitHub repos and PRs to generate risk maps, findings, and merge-readiness signals.
Autonomous dev team steered from chat: plain-English requests in, tested merged PRs out.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/4-life/mcp-error-handler'
If you have feedback or need assistance with the MCP directory API, please join our Discord server