Skip to main content

Event-sourced ticket system with a Jira reconciler — CLI, Python library, and MCP server.

Project description

rebar

An event-sourced ticket system with a Jira reconciler, exposed three ways:

  • CLI — the rebar command
  • Python libraryimport rebar
  • MCP serverrebar-mcp (stdio)

Tickets are stored as an append-only event log on a dedicated tickets git orphan branch (worktree at .tickets-tracker/); state is computed by replaying events. A level-triggered reconciler bidirectionally syncs tickets with Jira.

This project was extracted from the digital-service-orchestra Claude Code plugin. The bash + Python engine is wrapped verbatim under src/rebar/_engine/; the three interfaces are thin layers over it.

Requirements

  • Python ≥ 3.10
  • System binaries: git, jq, flock, bash
  • acli (Atlassian CLI) — only for live Jira reconciliation

Install

Published to PyPI as nava-rebar (the import package and commands stay rebar / rebar-mcp):

pipx install nava-rebar              # isolated CLI: rebar
pip install 'nava-rebar[mcp]'        # + MCP server: rebar-mcp
pip install nava-rebar               # library: import rebar

brew install navapbc/rebar/rebar     # Homebrew tap (CLI)

From a source checkout:

pip install .            # library + CLI
pip install '.[mcp]'     # + MCP server (FastMCP)

The engine (bash dispatcher + ticket-*.sh + python helpers) is exec'd as real files, so rebar must be installed unpacked to a real on-disk directory: zipimport / zip-safe installs are unsupported. Standard wheel installs (hatchling builds unpacked) and editable installs satisfy this; engine_dir() asserts it at the first engine call and fails loudly otherwise.

CLI

rebar init                                   # create the tickets branch + worktree
rebar create story "Add login page"          # prints the ticket id
rebar list [--status=open] [--has-tag=...]   # JSON array
rebar show <id|alias>                         # compiled ticket state (JSON)
rebar transition <id> <current> <target>      # optimistic-concurrency status change
rebar comment <id> "<body>"
rebar link <id1> <id2> blocks|depends_on|relates_to
rebar deps <id>                               # dependency graph
rebar ready                                   # tickets with all blockers closed
rebar next-batch <epic-id>                    # unblocked tickets under an epic's hierarchy
rebar reconcile [--mode dry-run|reconcile-check|live]   # Jira sync (default: dry-run)

Repo root is resolved from REBAR_ROOT (or PROJECT_ROOT), falling back to the git toplevel of the working directory.

Python library

import rebar

rebar.init_repo(repo_root="/path/to/repo")
tid = rebar.create_ticket("story", "Add login page", priority=2)
ticket = rebar.show_ticket(tid)                 # dict
tickets = rebar.list_tickets(status="open")     # list[dict]
try:
    rebar.transition(tid, "open", "in_progress")
except rebar.ConcurrencyError:
    ...                                          # ticket changed since last read

result = rebar.reconcile("dry-run")              # Jira sync (non-mutating)

# Native, in-process reads (no subprocess):
from rebar import reduce_all_tickets, reduce_ticket

MCP server

rebar-mcp          # stdio transport

Exposes ticket operations as MCP tools. reconcile defaults to dry-run (live requires REBAR_MCP_ALLOW_RECONCILE_LIVE=1). Set REBAR_MCP_READONLY=1 to expose only the read tools (no write/mutation tools).

Register it in an MCP client (e.g. Claude Desktop/Code) — zero-preinstall via uvx:

{
  "mcpServers": {
    "rebar": {
      "command": "uvx",
      "args": ["--from", "nava-rebar[mcp]", "rebar-mcp"],
      "env": { "REBAR_ROOT": "/path/to/your/repo" }
    }
  }
}

A registry manifest for the MCP Registry lives in server.json (io.github.navapbc/rebar); publish it with the mcp-publisher CLI (mcp-publisher login githubmcp-publisher publish). The registry verifies PyPI-package ownership via this annotation:

mcp-name: io.github.navapbc/rebar

License

Apache-2.0 — see LICENSE.

Configuration

Optional .rebar/config.conf (or .rebar.conf) at the repo root, flat key=value:

ticket.display_mode=auto          # auto | canonical | alias | short
ticket_clarity.threshold=70
verify.require_verdict_for_close=true

Tests

pip install '.[dev]'                          # includes the mcp extra for interface tests
pytest                                        # full Python suite
pytest tests/interfaces                       # interface-parity tier only
bash tests/scripts/test-ticket-create.sh      # bash engine tests

The Python suite is sub-divided by concern:

  • tests/scripts, tests/unit — the engine (reducer, graph, reconciler) and bash scripts.
  • tests/interfaces — proves the library, CLI, and MCP interfaces behave identically over one git-backed store:
    • test_parity.py runs each operation through all three interfaces (and a cross-interface coherence check: write via one, read via the others);
    • test_surface.py pins the per-interface capability surface (e.g. MCP has no init; there is no classify);
    • test_library.py / test_cli.py / test_mcp.py cover per-interface specifics (typed exceptions, exit-code passthrough, read-only/live gates).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nava_rebar-0.1.1.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nava_rebar-0.1.1-py3-none-any.whl (514.5 kB view details)

Uploaded Python 3

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page