
Rails Mcp
io.github.jaimenbellPublished by GitHub account jaimenbellv0.1.0Updated Oct 24, 2026
Default-deny action registry, append-only spend ledger, and human sign-off audit trail (MCP tools).
The publisher's own server: Job Bot by Agent Rails
Overview
A self-hosted governance server that gives an assistant a default-deny action classifier, a spend-intent ledger and a read-only sign-off state.
- What you can do
- Classify action types with a verdict that is always GATED, regardless of configuration or registration status, and check whether an action type has a registry entry with its enforcement layer, pointer and ceremony details. Read a short hash of the loaded registry plus its entry count, and read the current human sign-off state or null. Append spend-intent records with amount, vendor, purpose and actor, and compare rolling-window spend totals against a budget limit. Load the action registry from a YAML or JSON config file, or run with an empty registry.
- When to use it
- Use it when you want an assistant to consult a self-hosted registry of irreversible actions and keep an audit trail of spend intents and human sign-offs. It suits teams that already have their own interceptor, hook or CI gate and want a small, inspectable schema and ledger alongside it. It does not enforce anything by itself.
- Requirements
- Runs locally as a stdio process, installed from PyPI (pip install rails-mcp) or launched as python -m rails_mcp. Optional environment variables: RAILS_MCP_CONFIG_PATH for the registry config file, RAILS_MCP_SIGNOFF_LEDGER_PATH and RAILS_MCP_SPEND_LEDGER_PATH for ledger locations. No accounts, API keys or network access are needed.
Installation
In SourceWeft
- Open Rails Mcp in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
rails-mcp
[PyPI] [MCP Registry] [License: MIT] [Tests] [CI]
A self-hosted, caller-configured default-deny action registry + append-only spend ledger + CLI-only sign-off audit trail, exposed as MCP tools. Different category from this author's other six MCP servers (mcp-factory, rag-mcp, bus-mcp, desktop-mcp, github-mcp, discord-mcp) -- those are devtools ("connect an agent to X"); this one is governance and safety: "stop an agent from doing something irreversible without a human noticing."
Ported and generalized from a live internal registry (shared/rails/,
31 tests, running against a real multi-bot fleet since 2026-07-06) --
this pattern shipped internally before it shipped publicly.
What this is / is not
Is:
- A schema + pure logic for classifying
action_typestrings as unconditionally GATED (default-deny), registered or not. - A place to register what you know about an action-type's current
enforcement (
enforcement_layer,enforcement_pointer,ceremony) -- informational, never permissive. - An append-only spend-intent ledger + rolling-window budget check.
- An append-only human sign-off ledger, recording who blessed the registry's current hash and when.
Is NOT:
- Not an enforcer.
classify_actionreturningGATEDdoes not block anything by itself. You still wire it into your own PreToolUse hook, permission deny-list, or CI gate -- rails-mcp gives you the schema and the audit trail, not the interceptor.record_spend_intentrecords intent to spend; it never calls a vendor, a paid API, or a broker, and nothing here stops an over-budget spend from happening. - Not pre-loaded with any action-type data. Every adopter supplies their own registry (a YAML/JSON config file, or a plain dict). No fleet's specific action-types ship with this package.
- Not multi-tenant. The sign-off ledger assumes one human operator string per registry; fine for v1, a known limitation for later.
The one invariant that is never configurable
classify_action(action_type) always returns "GATED" -- registered
or not, whatever config was loaded, no argument or config field can change
it. This is the whole product. A config-driven fail-open knob would defeat
the entire pitch, so classify() (rails_mcp/registry.py) takes only an
action_type argument: there is no parameter through which a caller could
ever make it return anything permissive. is_action_registered answers a
separate, purely informational question -- "do I know something about this
action-type's enforcement?" -- and never feeds back into the GATED verdict.
Quickstart (60 seconds)
Add to your Claude Desktop/Code MCP config:
No console script on PATH? Fall back to "command": "python", "args": ["-m", "rails_mcp"].
By default the registry loads empty (honest-empty, not fail-open --
classify_action is still unconditionally GATED for everything). Point
it at your own action-type config:
See examples/rails.config.example.yaml (or .example.json) for the
config shape.
Tools
All six are read-mostly -- none of them can write to the sign-off ledger.
The CLI-only sign-off boundary -- and why it exists
append_signoff -- the function that records a human blessing the
registry's current hash -- is deliberately not an MCP tool, and never
will be. It is exposed only as a CLI command a human runs by hand:
Why: the boundary exists to prevent an agent holding only this
server's MCP tool connection from self-approving an irreversible action.
If append_signoff were reachable as an MCP tool, any agent holding this
server's connection could sign its own registry -- silently defeating the
one thing the boundary exists to enforce. This mirrors the internal design
rule the original shared/rails/ implementation was built around: the
lane that builds the auditor never signs the registry it ships. An
auditor that can also sign isn't an auditor.
What this boundary does not prove: the sign-off ledger has no
cryptographic tamper-evidence and no binding to a real human identity --
its integrity rests entirely on filesystem ACLs and the self-hosted
deployment model, not on cryptography. An agent (or anyone) with shell or
file-write access to the ledger's path can run rails-mcp sign itself, or
hand-append a forged {"type": "signoff", ...} JSONL line straight into
the file -- the ledger has no way to tell that apart from a real CLI
invocation. The MCP-only boundary stops the narrower case of an agent that
has only this server's MCP tool connection; it is not proof that a human
reviewed anything, and shouldn't be read as one.
This boundary is enforced structurally, not just by convention:
rails_mcp/server.pyandrails_mcp/routes.pynever import or callappend_signoff, anywhere -- proven by an AST-based check (not a naive string grep, which would false-positive on this very explanation appearing in their docstrings) intests/test_server.py::test_append_signoff_unreachable_via_any_mcp_tool.- The registered MCP tool set is exactly the 6 read-mostly tools above --
no
sign/append_signoff/revoke_signofftool exists, checked intests/test_server.py::test_all_six_rails_tools_registered. - A behavioral test drives every registered tool and confirms the sign-off
ledger file is never created
(
test_no_registered_tool_can_create_a_signoff_record). run_server.py(the entrypoint~/.claude.jsoninvokes) imports onlyrails_mcp.server, neverrails_mcp.cli-- so even the process that serves MCP tools has no code path to thesignsubcommand.
Env vars
Config file shape
Or the more compact 3-element form (matches the internal registry's native shape):
JSON works identically ({"actions": {"deploy_prod": [...]}}). See
examples/ for full examples of both.
enforcement_layer should be honest, not aspirational -- "prose"
(no structural rail exists yet, just a doc) is a legitimate, correct value.
Rounding a "prose" entry up to "L1" because it feels better defeats the
entire point of an honest registry.
Testing
CI (.github/workflows/ci.yml) runs this suite on every push/PR and fails
the build if the Tests badge above drifts from what the suite actually
reports -- see scripts/check_readme_counts.py.
106 tests, all hermetic (every ledger/config path goes through tmp_path +
an autouse env-isolation fixture in tests/conftest.py; nothing touches a
real ./rails_data/). No network, no live-smoke gate needed -- this
server has no external API to fake.
tests/test_registry.py(24) -- the ported + generalized registry logic: default-deny property tests, immutability, hash determinism, sign-off ledger fold/append/load, structural no-shell-out proof.tests/test_spend_ledger.py(14) -- ported near-verbatim from the internal suite: append/load roundtrips, budget window math, naive- datetime honest-degrade, structural no-effector proof.tests/test_config.py(18) -- new: env-var resolution, YAML/JSON loading in both entry shapes, honest-empty-when-unconfigured, loud failure on an explicit missing path.tests/test_routes.py(14) -- the MCP tool surface's business logic, exercised directly.tests/test_server.py(17) -- tool registration, passthrough correctness, and the CLI-only sign-off structural + behavioral proof.tests/test_cli.py(8) -- theserve/signsubcommands, including thatsignis genuinely append-only and prints a human-readable confirmation.tests/test_check_readme_counts.py(11) -- this CI gate's own TDD suite: parse-claimed, parse-actual, compare, andmain()end-to-end against match/drift/missing fixtures.
Install / connect
Registered in ~/.claude.json under mcpServers.rails-mcp as a stdio
server invoking run_server.py by absolute path (no cwd needed -- the
entrypoint adds its own directory to sys.path), OR via the rails-mcp
console script once installed from PyPI.
Handshake check
Prints the six registered tool names with no transport started.
Competitive picture (fact-checked 2026-07-16)
The closest prior art is not a hosted dead-man's-switch product -- that's a different problem ("is the operator still alive and watching"). The closer comparisons, once actually verified:
- Microsoft Agent Governance Toolkit -- MIT-licensed, backed by Microsoft, broader/heavier policy-enforcement scope covering the OWASP Agentic Top 10. The "big-name, well-resourced" adjacent entrant.
- Marchward -- the closest feature-for-feature match: server-side credential injection, spend caps, human-approval gates for irreversible actions, tamper-evident logging, Apache-2.0 open-source proxy.
- AgentLedger -- AGPL-3.0, overlaps
spend_ledger.pyspecifically (budgets, approvals, audit trail).
rails-mcp's narrower bet: a small, inspectable, self-hosted
registry+ledger+audit-trail schema with one hard invariant (default-deny
classification can never be configured away) and one hard boundary
(sign-off is CLI-only, never MCP-reachable) -- not a full policy-engine
product.
Out of scope
- Actual enforcement. No git hooks, no
settings.jsondeny rules, no graduation gates. You wireclassify_action/is_action_registeredinto your own interceptor. - A coverage auditor that checks whether your specific enforcement
mechanism (a hook, a CI gate) actually does what your registry claims.
That is real, separate engineering (this author's internal
coverage_audit.py) and is not part of this package. - Multi-tenant / multi-operator sign-off. One operator string per ledger for v1.
- Blocking an over-budget spend.
evaluate_budgettells you the number; nothing here intercepts a call before it happens. - Ledger rotation/capping.
record_spend_intentappends forever -- there's no rotation, size cap, or archival built in. A known limitation, not yet a problem at v1 scale.
Commercial support
Maintained by Jaimen Bell. For production MCP integrations, agent-governance rails, or agent-reliability work, see jaimenbell.dev.
Building your own MCP server? The MCP Starter Kit has templates, a build playbook, and packaging war-stories from shipping this one.
mcp-name: io.github.jaimenbell/rails-mcp
Source: README.md at commit 6bfb355
Tools
0Version history
1- v0.1.0LatestSep 16, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts
Other Rails integrations
Job Bot by Agent Rails
so.railsOfficial publisher
Remote job-search MCP server that builds documents where every line cites a verifiable fact, without sending anything on your behalf.
Unblock by Agent Rails
so.railsOfficial publisher
Lets an agent ask you a question on your phone, wait for your answer, and then resume its work.
Language Tutor by Agent Rails
so.railsOfficial publisher
Lets an assistant practice Spanish, French or Russian in short conversations, with corrections.
Rolodex by Agent Rails
so.railsOfficial publisher
Remote MCP server that keeps relationship memory: who owes the next move, with the evidence behind every line.
Recruiter by Agent Rails
so.railsOfficial publisher
Remote MCP server that takes a job role and returns candidates matched with evidence per requirement, plus outreach drafts for approval.