butchr
Watches Jira tickets assigned to the account, detects active (In Progress/In Review) tickets, and notifies agents of ticket, comment, and link changes.
Click on "Deploy 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., "@butchrlist my active Jira tickets and their agent status"
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.
butchr
Agents support selectable Claude (default) and Codex providers. See provider configuration and deployment.
New here? Start with Getting started — install, first-time setup in the dashboard, and your first rule.
The software factory, rewritten. A single local daemon that:
Runs your resource-agent rules — each rule is a JQL query plus a brief and agent preferences, read from
BUTCHR_RULES_FILEor$XDG_CONFIG_HOME/butchr/rules.json(when the default file is absent, or itsrulesarray is empty, nothing is staffed — there are no built-in rules; aBUTCHR_RULES_FILEthat does not exist stops the daemon at startup). Seesrc/rules/rules.tsfor the schema, and provision a new deploy's rules file starting fromdocs/rules.example.json— see "Rules file" below for the convention it encodes and how to apply an edit. Rules may also nameresourceProvider: "github-issue"with a GitHub issue search query; those are staffed only whenGITHUB_TOKEN_FILEandBUTCHR_GITHUB_ORGSare set, in<workspace root>/github-issue/<rule>/<owner%2Frepo%23n>, and their agents work the issue with thegithub_get_issueandgithub_add_commenttools, which act only on the agent's own issue — a limit on the tools, not on a shell-capable agent that can readGITHUB_TOKEN_FILE(seesrc/rules/github-issue-type.tsandsrc/tools/github-issue.ts). Rules namingresourceProvider: "github-pr"(FACTORY-57) are the same shape one level over: a GitHub pull-request search query (is:pris applied automatically; a query asking for plain issues is rejected at rule-load time, the mirror image ofgithub-issue's ownis:issuerestriction), staffed only under the SAMEGITHUB_TOKEN_FILE/BUTCHR_GITHUB_ORGS(no second token needed — see.env.example's ownGITHUB_TOKEN_FILEcomment block for the scope finding), in<workspace root>/github-pr/<rule>/<owner%2Frepo%23n>, with thegithub_get_prandgithub_pr_add_commenttools, acting only on the agent's own PR. A PR's agent is stopped the same way a closed issue's already is: purely because the rule's own query (e.g. one that includesis:open) stops matching it once GitHub reports it merged or closed — no special-cased merge/close code (seesrc/rules/github-pr-type.tsandsrc/tools/github-pr.ts).github-issueandgithub-prare separate providers even though a PR shares GitHub's own issue/PR number namespace with plain issues in the same repo — seesrc/resources/github-pr-ref.ts's own header for how the two never collide. Rules namingresourceProvider: "jira-idea"take JQL but staff only Jira Product Discovery ideas (issue typeIdeain aproduct_discoveryproject), in<workspace root>/jira-idea/<rule>/<IDEA>, with thejira_idea_get,jira_idea_github_issuesandjira_idea_add_commenttools. Ajira-idearule'sinwardConnectionRulesmay namegithub-issuerules: its agents then hear changes to GitHub issues those rules match that the idea links to through a Jira remote link (read-only). When both providers run,github_link_jira_ideaandjira_idea_link_github_issuelet an agent create that remote link on request, only between resources those same rules currently match (src/tools/idea-github-link.ts).jira-workrules never staff an idea however broad their JQL (seesrc/resources/jira-idea.tsanddocs/jira-idea.md). Rules namingresourceProvider: "zendesk-ticket"take Zendesk search syntax and are staffed only whenBUTCHR_ZENDESK_ACCEPT_SHELL_CREDENTIAL_RISK=agents-can-read-the-zendesk-token,ZENDESK_SUBDOMAINand an owner-onlyZENDESK_OAUTH_TOKEN_FILE(an OAuth token; email/API-token auth is refused) are set, in<workspace root>/zendesk-ticket/<rule>/<subdomain%23id>, withzendesk_get_ticketandzendesk_add_internal_note, whose only write is a private internal note. Agents run shell commands as the daemon's user and can read that token, so the tool limit is not a security boundary; Zendesk's account permissions are (seedocs/zendesk-ticket.md). Rules namingresourceProvider: "filesystem"take a small JSON query (root, file-or-directorykind, an optional basename glob, a recursion depth, and an optional extension/hasEntry predicate — seedocs/filesystem.md) and need no external credential, staffed in<workspace root>/filesystem/<rule>/<percent-encoded-canonical-path>; there is no general-purpose butchr MCP tool for it — an agent reads and edits its file or directory directly with its own file tools, and Jira/Confluence/GitHub/Zendesk tools all refuse it (the one exception,freeze_session/unfreeze_session, is scoped to managed-session agents specifically — see below). The daemon refuses to start while agents from the old<workspace root>/<ISSUE>layout are still running (seesrc/daemon/legacy-preflight.ts). Alongside your own rules, the daemon always runs one BUILT-INfilesystemquery (never read fromrules.json, not user-editable) over a well-known managed-session definitions directory (BUTCHR_SESSION_DEFINITIONS_DIR, else$XDG_CONFIG_HOME/butchr/session-definitions) — one JSON manifest per Butchr-managed agent (a Bakr directory agent, a Candlestix session), each defining its own working directory, vendor, model tier, permission mode and more; one agent per eligible (valid, not frozen) manifest, invalid ones logged and skipped rather than staffed or silently dropped. A definition's ownfreezeControllers/unfreezeControllersfields may name OTHER managed-session definitions whose agent may call the butchrfreeze_session/unfreeze_sessionMCP tools against it — the only butchr MCP tools any filesystem-provider agent ever gets, scoped per-definition and server-side by caller identity, never by anything the caller argues (src/tools/session-freeze-tools.ts). Seedocs/managed-sessions.md. For the concrete Bakr/Candlestix → managed-session mapping and cutover runbook this feeds (BUTCHR-391/BUTCHR-396), seedocs/codey-migration-runbook.mdand the staged example definitions indocs/codey-session-definitions.example/. For a managed session on a Windows host running Butchr inside WSL —.exeinterop conventions, theworkingDirectorychoice between the WSL home and/mnt/c/..., and path translation between them — seedocs/windows-wsl-agent-guide.md.Runs one agent per (rule, matched ticket) — while a rule's query returns a ticket, a herdr agent works it via
@brooswit/drovr, in<workspace root>/jira-work/<rule>/<ISSUE>; when the query stops returning it, the agent is stopped. Two rules matching one ticket run two independent agents. A boss hears its implementer overImplementson the link alone (routed to every rule matching the boss ticket; no rule configuration is consulted) — a rule'schildRuledoes NOT gate this (PR #372; see theBUTCHR-388header comment insrc/rules/resource-type.ts) and today only names, for documentation/validation purposes, which rule a child created by this rule's agent is meant to match.inwardConnectionRulesstill gates the sideways case: over an existingRelateslink, one way only — the rules it lists do not hear it back unless they list it too (read-only; Butchr never creates links). AchildRule/inwardConnectionRulesvalue naming a rule id absent from the same rules file is a hard load error today (src/rules/rules.ts'sparseRulesrefuses to start the daemon, naming the bad id) — a typo can't reach runtime, though today no rules file declareschildRuleat all, so this check cannot fire from a real rules file.unresolvedRelationships(also insrc/rules/rules.ts), logged once at startup and listed under/health, is a separate, purely existence-based safety net over any enabledjira-workrule set, including one assembled some other way than a singleloadRules()call — it does not ask whether the missing id is staffed, observed, or enabled, and it does not restore any routing effect tochildRule. It is expected to be empty/absent under every rules file that loads today; it starts finding real gaps once something (e.g. cross-daemonBUTCHR-402observer rules) lets a rule set carry a referenceparseRulesdoesn't reject. Workspaces from before rules (<workspace root>/<ISSUE>) are left untouched and never adopted.Pushes updates to those agents — over MCP (
@brooswit/thatch): agents connect to the daemon identifying which issue they work on, and the daemon channels ticket/comment/link changes up the Implements chain to the right one.Shows a live view — a webapp listing the active agents; click one and butchr opens a terminal window running
herdr agent attachon it, so you drop straight into that agent's shell. No browser extension, no embedded terminal — terminals are real herdr terminals.
Change detection is @brooswit/sundry's watch over a Jira JQL feed. Blocking agent prompts are handled through herdr's own blocked detection + send_keys (herdr owns the terminal; butchr reads and answers).
First run
The very first time the daemon starts with no rules file at all, AND its rules directory is absent or genuinely empty (no BUTCHR_RULES_FILE override, no prior .bak-* backup, and no other state already sitting in that directory — see src/rules/seed-first-run.ts), it seeds one ui-first-rule template rule itself: disabled, execution: "swarm" (one agent per matching ticket), with a real @builtin:task brief and a placeholder query enabling is refused against until it's edited. Open the dashboard, edit that rule's query, then enable it — no hand-edited JSON and no restart needed for this one field (FACTORY-663's web write path covers any ui--prefixed rule's query/enabled/agentPreferences, this rule included). Enabling it (like enabling any swarm rule through the dashboard) asks you to confirm first, naming how many tickets it would staff. The rule's brief is file-only, same as every other rule's — the dashboard never edits it; change it in rules.json by hand if you want different instructions than the shipped task brief. This happens only once, at true first run; it never recreates the file if you delete it while the daemon keeps running (though a daemon RESTART with the file still absent and no prior state seeds again — this is a per-process guarantee, not a permanent one), and an established install whose rules file has simply vanished — or whose config directory already holds other state — gets a warning and an alert instead of a fresh template.
A new rules file is risky to just restart the daemon with: docs/rules.example.json's convention is assignee = currentUser(), so a typo-free but overly broad rule can staff up to BUTCHR_MAX_AGENTS real tickets on your own account the very first poll, with no preview beforehand. Do this instead:
Write one rule first, scoped to a single ticket you own, before trying anything broader — e.g.
"query": "key = XYZ-1"(swap in a real ticket key). This proves the whole pipeline — file location, JSON syntax, field names, brief — against exactly one match before any query is allowed to touch more.Check it with
butchr rules check [file](omitfileto validate the same path the daemon would read:BUTCHR_RULES_FILE, else$XDG_CONFIG_HOME/butchr/rules.json, else~/.config/butchr/rules.json). This is read-only — it starts no agent, writes no label, posts no comment — and does two things: validates the file with the daemon's own loader (every problem named with its rule and field), then dry-runs each enabledjira-work/jira-idearule's JQL against your configured Jira site and prints, per rule, exactly which tickets it would staff (key, status, summary) and how many, flagging plainly when a rule matches more thanBUTCHR_MAX_AGENTS. Widen the query (drop thekey = ...clause for the real one you want) and re-runbutchr rules checkuntil the match list looks right — repeat as many times as you like; nothing is staffed until you apply the file (see step 3 below).Apply it once the dry-run output looks right: send the running daemon
SIGHUP(kill -HUP <pid>, orsystemctl --user kill -s HUP butchr.serviceunder the systemd unit) to re-read the file in place, or restart it (bun run start, or restart the systemd unit) — see "Applying a change" below for what either actually does and does not touch.
butchr rules check --help shows the full usage.
Related MCP server: Jira MCP Server
Rules file
Convention: every ticket-worker (jira-work) rule in the example defaults to In Progress / In Review. A query like assignee = currentUser() AND issuetype = Task AND statusCategory != Done also matches To Do — it takes a capacity slot for a ticket nobody is working yet, and a ticket moved into To Do wakes that agent instead of stopping it. status IN ("In Progress", "In Review") avoids that by default. docs/rules.example.json is the canonical starting point: one jira-work rule per role (epics, stories, tasks, bugs, subtasks), each assignee = currentUser() plus an issuetype clause plus status IN ("In Progress", "In Review"). It loads through the real loader/validator in test/unit/rules-example.test.ts, which also asserts every rule in it keeps this shape — copy it as your rules file's starting point and add provider rules (github-issue, github-pr, jira-idea, zendesk-ticket) or adjust the JQL as needed. The query is the only place a status choice lives, and it stays fully operator-configurable: an operator who wants a rule to also match To Do (or any other status) simply writes that query. Butchr does not gate, prevent, or warn against it — there is no code-level status gate in jira-work staffing and none is planned.
Capacity naming. Every rule above carries no capacity flag: the schema's role: "worker" | "sentinel" field (src/rules/rules.ts) defaults to "worker", so a ticket-worker rule needs no field at all — that is why docs/rules.example.json has no role on any rule, and it should stay that way. Only an always-on agent is ever flagged role: "sentinel". This is the ONLY input to the capacity decision for a jira-work rule (FACTORY-757): issue type plays no part, so epics/stories/bugs above count toward BUTCHR_MAX_AGENTS exactly like tasks/subtasks unless you add role: "sentinel" to the ones you want exempt — capacity inclusion is an explicit per-rule choice you are expected to set on any NEW rule. jira-project rules are the one documented exception — see docs/execution-modes.md's "Fleet capacity role" section. An upgrade from before FACTORY-757 does this for you once, automatically, for any EXISTING epics/stories/bugs-shaped rule it can recognize (an upgrade-time migration, FACTORY-810) — see that doc's "Upgrade migration" section right below it for exactly what it migrates, what it deliberately leaves alone, and how it handles a query it cannot classify.
Where the file actually lives — resolving a discrepancy on purpose. The code's own default, unconditionally, straight from src/rules/rules.ts's rulesPath() (the only place this is decided): BUTCHR_RULES_FILE when set, else $XDG_CONFIG_HOME/butchr/rules.json, else ~/.config/butchr/rules.json. That is what an unconfigured daemon reads, and it is what this README described before this section existed. Separately, ~/.config/butchr-new/resource-rules.json has been cited elsewhere (BUTCHR-399's own description; a test comment at the time of writing, test/unit/rule-engine.test.ts, calls the live rules file resource-rules.json) as what booswrit's and wroosbit's live daemons actually run with — a different directory name and filename from the code's default. rulesPath() has no butchr-new or resource-rules.json branch anywhere, so that path is not a second default the code knows about; the only way a daemon reads from it is an explicit BUTCHR_RULES_FILE set in that daemon's own unit/environment, which this repository cannot see or verify. Do not assume either path for a deploy you don't operate — read that daemon's actual BUTCHR_RULES_FILE (or its unit's environment) yourself; a stale line number or a since-changed unit make both citations above worth re-checking rather than trusting verbatim.
Applying a change. The file is read once at startup (loadRules, called from src/daemon/index.ts) into a live holder every provider reads through on each of its own polls (RulesHolder, src/rules/rules.ts) — send the daemon SIGHUP and it re-reads the file and swaps the holder's contents in place, with no restart. A problem in the edited file (bad JSON, a schema violation) is logged once (butchr: rules reload from <path> failed; keeping the running rules: plus each problem) and the running rules are left exactly as they were — nothing is torn, nothing is staffed from a half-applied edit. A successful reload logs butchr: rules reloaded from <path>: N enabled (ids) plus which ids were added, removed, or changed. Either way — SIGHUP or a full restart — nothing is torn down as a side effect of the reload/restart itself: each reconcile poll — including the very next poll after either one — diffs the rules' current matches against herdr's own live agent list, not against any daemon-side memory of what was running before (src/reconcile/plan.ts, src/daemon/loop.ts). A resident agent whose ticket still matches the same rule is therefore simply never touched — left running, pane and all, exactly as if nothing happened; only an agent whose ticket no longer matches any enabled rule is stopped (on the normal reconcile/reap path, never killed mid-ticket by the reload itself), and a newly-matching ticket gets a freshly spawned agent. Tightening a rule's JQL to exclude To Do and reloading (or restarting) stops only the agents working To Do tickets under that rule — every In Progress/In Review agent it already had stays up. One restart-only limitation SIGHUP does not lift: a provider with zero enabled rules at startup (so no credentialed client and no running loop for it at all — github-issue/github-pr/zendesk-ticket/jira-idea/jira-project/filesystem) still needs a restart to begin staffing that provider's very first rule; a reload only updates rules for a provider whose loop is already running. zendesk-ticket's credential (its OAuth token file) is likewise read only at startup — a reload never re-reads it, since credentials don't change via a rules edit.
A missing rules file is treated differently depending on whether anything is currently running: if the holder is already empty (nothing it could wipe), a missing file is a normal, valid "zero rules" reload — the same as loadRules treats it at startup. But if the daemon currently has any enabled rules, a SIGHUP arriving while the file is momentarily absent (a bad mount, an editor that writes via rename-then-delete) is refused rather than swapped in: the running rules are left exactly as they were, and the problem is logged (rules file missing at <path>; keeping the running N rule(s)). A present file that parses to genuinely zero rules is still accepted over a non-empty holder — that is an operator's deliberate "disable everything", distinguishable from a vanished file — and is logged loudly (0 enabled (was N) — every rule-having agent will stop on the next reconcile poll) rather than reading like any other reload.
Reload itself is per-poll, not instantaneous: every rule-reading site reads the live holder, and some do so at more than one point within a single poll. A SIGHUP landing mid-poll can be visible partway through that one poll's own work; it is always fully applied by the next poll — the same timing an edit followed by a restart already has today, not a new kind of tear.
Architecture
one Elysia process
├── /mcp agents connect here (thatch), identifying via x-issue (ticket) + x-butchr-agent (rule agent) headers
├── /agents,/health read-only live view
└── loops (landing incrementally)
├── rules every enabled rule's JQL → one desired agent per (rule, ticket)
├── reconcile desired rule agents ↔ herdr agents: spawn / stop
└── notify ticket/comment/link change → thatch channel → the agent for whatever that ticket implementssrc/: config · atlassian (Jira client) · daemon (the app + notify) · web (live view). More loops land as their own modules.
Install & run
No npm package is published — Brooswit's decision: no npm publishing for now; clone and run from source on each machine:
git clone https://github.com/brooswit-factory/butchr.git
cd butchr
bun install
bun run build
cp .env.example .env # fill in ATLASSIAN_SITE / EMAIL / TOKEN_FILE
bun run start # reads .env / the environmentbun run build (or standalone bun run build:web) is what produces the dashboard app's assets (dist/web) — bun run start alone runs from source and never builds anything. Skip it and /dashboard-app/ 503s with a message naming the remedy; the daemon logs a [butchr:dashboard-app] line and /health's dashboardApp field says so too, but the old server-rendered pages (/, /configurations) work either way.
As of 0.10.0, also set BUTCHR_ASSIGNEE_STORY and BUTCHR_ASSIGNEE_TASK (Atlassian accountIds) in .env before deploying — jira_create_issue assigns a Story/Task by role from these, and REFUSES to create one of that type if its role is unset and the caller passed no explicit assignee. Epics are unaffected.
Optionally set BUTCHR_CAPTURE_DIR to change where the session-limit watcher durably captures a pane's ANSI-stripped text when its own detection is inconclusive (the phrase is present but unrecognised, or recognised with no parseable reset time) — default .captures under the workspace root (BUTCHR_WORKSPACES, or ~/butchr-workspaces). Bounded to at most one capture per issue/trigger/pane incarnation and 50 files total (oldest evicted first); an operator turns a capture into a test fixture by deleting its # -prefixed header block.
herdr's own blocked classification is not the only blocked-detector: a pane herdr reports idle/done continuously for BUTCHR_IDLE_DIALOG_MINUTES (default 2) whose text parses as a dialog at the END of the pane is treated as blocked too — read, auto-answered if the shape is known, escalated to the pane's own ticket otherwise (an unrecognised idle-blocked dialog escalating, rather than freezing the agent silently, is the whole point — see src/agents/idle-dialog.ts). Every escalation additionally captures the full pane text to the same BUTCHR_CAPTURE_DIR, under an <ISSUE>-escalation-<timestamp>.txt name, and the Jira comment references that path (never the raw text) so the next unrecognised dialog can be fixtured from the escalation itself.
Since FACTORY-127/FACTORY-138 (operator decision, FACTORY-67), butchr's own default for a Claude agent (managed-session or rule-launched) that sets neither field is permissionMode: "acceptEdits" paired with lizard-eligible together — an agent that sets nothing gets both; an explicit permissionMode or lizardMode: false still wins. There is no global switch for this default: rolling one agent back means setting permissionMode: "bypassPermissions" explicitly on it — jira-project agents inherit this default like every other rule kind too, since FACTORY-129 removed their own unconditional permissionMode: "auto" override. "Lizard mode" (lizardMode) is a separate toggle that pairs with any permissionMode that prompts, not only "default": a standalone 20s sweep (src/agents/permission-answer-loop.ts), plus an event-driven fast path that answers an eligible pane in about a second, auto-answers Claude's own tool-permission dialog ("Do you want to proceed?") on that agent's pane only — no other pane is ever touched — by pressing the plain "Yes" option (allow once), and only when it is unambiguously that option (@brooswit/drovr's autoAnswerPermissions, scope: "once"); it never presses the "always allow" stored-rule option, and no rule persists past that one answer. permissionMode: "acceptEdits" auto-accepts file EDITS only — Bash and MCP tool prompts still appear, and those are what lizard mode answers, so it stays useful even in modes that already skip some prompts. Manual (permissionMode: "default") plus lizard remains valid as an alternative pairing — Claude prompts before every tool call, and lizard mode still clears the tool-permission dialog unattended. Every attempt is audited to BUTCHR_PERMISSION_AUDIT_PATH (default .permission-audit.jsonl under the workspace root), and the journal names the agent and tool for each one. See docs/managed-sessions.md's "Lizard mode" section and docs/permission-answer-loop.md for the field, cadence/timeout reasoning, and how this avoids double-answering with the two detectors above.
Optionally set BUTCHR_LIZARD_APPROVAL_SOUND (any non-empty value; OFF/absent by default) to play a sound on this daemon's own host every time lizard mode auto-approves a prompt — the operator hears each unattended approval as it happens, not just from the audit log. With no override, the sound is @brooswit/drovr's own bundled asset, resolved straight out of the installed package; set BUTCHR_LIZARD_APPROVAL_SOUND_PATH to a local file path (~ expanded) instead. A burst of approvals within ~1.5s plays at most one sound. Never blocks, delays, or fails an approval — every failure mode (source unresolvable, no local player found) logs at most one warning and degrades to silence rather than retrying. Tries gst-play-1.0, afplay (macOS), mpv, ffplay, paplay, pw-play, then aplay (wav only), whichever is found on PATH first, remembering the first one that actually works. See docs/permission-answer-loop.md's "Approval sound" section (src/agents/approval-sound.ts) for player selection, default-source resolution, and degrade-behaviour details.
python3 on the daemon's PATH. The file-execution veto (FACTORY-625) is a Claude PreToolUse hook that runs python3 on every Bash call an agent makes, so the host needs a working python3. Without one the hook is skipped, the agent still launches, and the daemon logs [veto-hook] NOT installed naming the reason. On a stock Mac, /usr/bin/python3 is Apple's installer stub until the Xcode Command Line Tools are installed (xcode-select --install); the daemon recognises it without running it. A daemon started by launchd or systemd needs python3 on that PATH, not just the login shell's.
Label-write permission. butchr writes agent:*/pr:* labels quietly (notifyUsers=false) so watchers aren't spammed on every status flip — but Jira Cloud only honours that for an account holding the Administrator project role (or global Administer Jira) on the board's project. Grant the daemon's Atlassian account that role on each project it labels tickets in. Without it, labels still sync — nothing is disabled — but every label change sends the ticket's watchers a Jira notification, and the daemon says so once at startup, e.g.:
[labels] KAN: account booswrit@gmail.com lacks ADMINISTER_PROJECTS — label writes will NOTIFY watchers. Remedy: grant booswrit@gmail.com the Administrator project role on KAN, or accept notifying label writes.No config knob is needed — the daemon detects this per project automatically. Current state as of 2026-08-28: brooswit is a site admin (has it everywhere); booswrit was granted the KAN Administrator role.
Development
bun run check # generate + typecheck + tests + coverage ≥90% (what CI runs)bun run check is the single verification command — run it in full, not step by step. It runs tsc under bun --bun rather than through a shebang-resolved node, so no particular node version is required. Before the gate runs, it prints a one-line preflight naming the runtimes actually in use (e.g. preflight: bun 1.4.0, node v12.22.9, tsc 5.6.3 (typecheck runs under bun)); paste that line along with the rest of the output when reporting a gate result.
Every src/ change needs a changelog.d/<TICKET>.md fragment (CI enforces it) — see changelog.d/README.md. The version is assigned at merge, not on a branch: do not bump package.json or add a dated CHANGELOG.md heading yourself.
Predecessor (300 releases of history) preserved at brooswit/butchr-legacy.
Free-form project resource agents are available through jira-project rules;
see project selection, interactive use, and optional MCP connections.
A resource agent (or an operator, via butchr link list|add|remove) can
maintain its own butchr-managed sensor set — typed references across seven
provider kinds (jira-work-item, jira-project, confluence-page,
github-issue, github-pr, filesystem, webpage) — independent of any
provider-native links a future adapter may merge in; see
ResourceRef, the managed-link collection, and the merge contract.
A resource's provider can be asked which capability categories it actually
supports today (query, read, snapshot, comments, links,
createTask) via supports/capabilitiesOf
(src/resources/capabilities.ts); invoking an unsupported capability throws
a typed UnsupportedCapabilityError. Comments (readComments/addComment,
src/resources/comments.ts) are implemented for jira-work-item only today.
See provider capability declaration, the comments capability, and the
8×6 provider inventory.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.
Minimal issue tracker: projects, objectives and trackable plans, written by agents over MCP.
Your agents' cloud. MCP server with search, execute, packages, jobs, secrets, and integrations.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables interaction with Jira to fetch issues by key and perform JQL searches. It provides a foundation for integrating multiple work systems, with planned support for Slack and GitHub.454 npmMIT
- AlicenseNot gradedqualityDmaintenanceA comprehensive, production-ready MCP server for seamless Jira Cloud integration, enabling AI agents and custom applications to manage boards, issues, users, projects, and workflows via natural language commands.292 npm4MIT
- FlicenseNot gradedqualityDmaintenanceManages Atlassian Jira Cloud projects, issues, sprints, boards, worklogs, comments, and workflow transitions from MCP-compatible clients.-
- AlicenseAqualityFmaintenanceA local MCP server for Jira Cloud-driven development. Connects MCP clients to Jira for searching issues, reading tasks, parsing attachments, and mapping projects to local repos.107 npmMIT