Finance Toolkit
500+ transparent financial methods calculated from raw statements, not third-party endpoints.
Description from the maker (original English)
Default-deny action registry, append-only spend ledger, and human sign-off audit trail (MCP tools).
These three are never merged into one score: opinions, measurements and popularity are different things.
We have not written a plain-language summary for this one yet. Below are the facts we read from the registry.
Pick the AI app you use, then copy the settings.
You need
Which app do you use?
Pick your app above. We remember it, so next time the button says “Install in …”.
Open Claude Desktop → Settings → Developer → Edit Config, and paste this into claude_desktop_config.json
{
"mcpServers": {
"rails": {
"command": "uvx",
"args": [
"rails-mcp"
]
}
}
}Run this in your terminal
claude mcp add rails -- uvx rails-mcpPaste into .cursor/mcp.json in your project, or ~/.cursor/mcp.json
{
"mcpServers": {
"rails": {
"command": "uvx",
"args": [
"rails-mcp"
]
}
}
}Your browser asks to open the app, then the app shows the settings and asks you to confirm. Key values are left empty for you to fill in.
Paste into .vscode/mcp.json in your project
{
"servers": {
"rails": {
"type": "stdio",
"command": "uvx",
"args": [
"rails-mcp"
]
}
}
}Your browser asks to open the app, then the app shows the settings and asks you to confirm. Key values are left empty for you to fill in.
This one runs on your computer, and ChatGPT can only connect to servers on the internet. Pick another app.
Your choice stays on this device in a cookie; no account needed.
These settings are generated from the maker’s registry entry. If the README says otherwise, follow the README.
Runs on your computer; the tool list appears in your AI app after you install it.
We check information anyone can see; we have not read the code. Checks that do not apply are left out of the count. · Checked Nov 8, 2026
The registry name was verified with the GitHub account jaimenbell, which owns the repo
We have not read this repo from GitHub yet
We have not read this repo from GitHub yet
This one runs on your computer; there is no internet endpoint
Runs on your computer and uses local settings instead
Runs on your computer; we can only read tool lists from internet endpoints
Compared with every active server in this category in the registry. Stars count only when the publisher owns the repo.
It passed 1 of 1 applicable basic checks. We have not read the code. Before adding a key or token, see what access the server asks for and use a key with only the permissions you need.
The registry does not list a required key, though some servers ask you to sign in on first use.
It runs on your computer. Your AI app starts it when needed, and data does not pass through the maker’s servers (unless it calls an online service itself).
The GitHub repo last changed –, and the latest version (0.1.0) reached the registry 4 months ago.
Apps that support MCP, such as Claude Desktop, Claude Code, Cursor and VS Code. You also need Python (uv) on your computer.
In the same category: Finance Toolkit, SolidInvoice, Korea Tax Calculator
Servers in the same category from other makers, sorted by stars.
Reading a card:↓ Downloads per weeki★ GitHub starsiThree pillars: reviews · checks · usageiUpdated = latest version published to the registryi
500+ transparent financial methods calculated from raw statements, not third-party endpoints.
Create and send invoices and quotes, manage clients, and track payments in SolidInvoice.
Korean tax calculation and tax-audit judgment MCP: 96 tools with statutory citations.
Copied from the maker’s repo as written. PopNx MCP has not reviewed or endorsed it. HTML, images and scripts are removed. Links lead off this site.
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.
Is:
action_type strings as unconditionally GATED (default-deny), registered or not.enforcement_layer, enforcement_pointer, ceremony) -- informational, never permissive.Is NOT:
classify_action returning GATED does 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_intent records intent to spend; it never calls a vendor, a paid API, or a broker, and nothing here stops an over-budget spend from happening.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.
pip install rails-mcp
Add to your Claude Desktop/Code MCP config:
{
"mcpServers": { "rails-mcp": { "command": "rails-mcp" } } }
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:
{
"mcpServers": { "rails-mcp": { "command": "rails-mcp", "env": { "RAILS_MCP_CONFIG_PATH": "C:\\path\\to\\rails.config.yaml" } } } }
See examples/rails.config.example.yaml (or .example.json) for the config shape.
All six are read-mostly -- none of them can write to the sign-off ledger.
| Tool | Purpose |
|---|---|
classify_action(action_type) | Default-deny verdict: always "GATED". Implemented in rails_mcp/registry.py::classify, tested in tests/test_registry.py + tests/test_server.py. |
is_action_registered(action_type) | Whether the loaded registry has an entry, plus enforcement_layer/enforcement_pointer/ceremony when present. rails_mcp/routes.py::is_action_registered, tested in tests/test_routes.py. |
get_rails_hash() | 12-hex sha256 digest of the loaded registry + entry count -- the value a human sign-off records. rails_mcp/registry.py::rails_hash, tested in tests/test_registry.py. |
get_signoff_state() | Current active human sign-off, or null. Read-only. rails_mcp/registry.py::load_signoff_state, tested in tests/test_registry.py + tests/test_routes.py. |
record_spend_intent(amount_usd, vendor, purpose, actor) | Append one spend-intent record. Never calls a vendor or paid API. rails_mcp/spend_ledger.py::record_spend_intent, tested in tests/test_spend_ledger.py. |
evaluate_budget(limit_usd, window_days=30.0) | Rolling-window spend total vs. limit. Never raises. rails_mcp/spend_ledger.py::evaluate_budget, tested in tests/test_spend_ledger.py. |
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:
rails-mcp sign --operator "jaime" --note "reviewed 2026-07-16 config"
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.py and rails_mcp/routes.py never import or call append_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) in tests/test_server.py::test_append_signoff_unreachable_via_any_mcp_tool.sign/append_signoff/revoke_signoff tool exists, checked in tests/test_server.py::test_all_six_rails_tools_registered.test_no_registered_tool_can_create_a_signoff_record).run_server.py (the entrypoint ~/.claude.json invokes) imports only rails_mcp.server, never rails_mcp.cli -- so even the process that serves MCP tools has no code path to the sign subcommand.| Var | Default | Purpose |
|---|---|---|
RAILS_MCP_CONFIG_PATH | unset | Path to your rails.config.{yaml,yml,json}. Unset = honest-empty registry (nothing registered, classify_action still unconditionally GATED). |
RAILS_MCP_SIGNOFF_LEDGER_PATH | ./rails_data/signoff.jsonl | Where the append-only sign-off ledger lives. |
RAILS_MCP_SPEND_LEDGER_PATH | ./rails_data/spend.jsonl | Where the append-only spend-intent ledger lives. |
actions:
deploy_prod: enforcement_layer: "L1" enforcement_pointer: "CI gate requires a passing e2e suite + a manual approve step" ceremony: "operator hand"
Or the more compact 3-element form (matches the internal registry's native shape):
actions:
deploy_prod: ["L1", "CI gate requires a passing e2e suite + a manual approve step", "operator hand"]
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.
.venv/Scripts/python.exe -m pytest -q
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) -- the serve/sign subcommands, including that sign is 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, and main() end-to-end against match/drift/missing fixtures.python -m venv .venv
.venv/Scripts/python.exe -m pip install -e ".[test]"
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.
.venv/Scripts/python.exe scripts/list_tools.py
Prints the six registered tool names with no transport started.
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:
spend_ledger.py sOnly the beginning is shown; read the rest in the repo