Skip to main content
Glama

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_type strings 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_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.

  • 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.

Related MCP server: AgentGuard MCP Server

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)

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.

Tools

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.

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:

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.

  • The registered MCP tool set is exactly the 6 read-mostly tools above -- no sign/append_signoff/revoke_signoff tool exists, checked in tests/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.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.

Env vars

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.

Config file shape

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.

Testing

.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.

Install / connect

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.

Handshake check

.venv/Scripts/python.exe scripts/list_tools.py

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.py specifically (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.json deny rules, no graduation gates. You wire classify_action/is_action_registered into 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_budget tells you the number; nothing here intercepts a call before it happens.

  • Ledger rotation/capping. record_spend_intent appends 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

Available Tools

6 tools
classify_actionA

Default-deny classification for an action_type: ALWAYS returns GATED, whether or not the action_type is registered. There is no fail-open branch and no argument that can change this -- it is the one invariant this server refuses to make configurable. Use is_action_registered to check whether an action_type has a known enforcement entry; that is a separate, informational question.

ParametersJSON Schema
NameRequiredDescriptionDefault
action_typeYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It fully discloses the invariant behavior: always returns GATED, no fail-open, no configurable argument. This is exceptionally transparent and removes any guesswork about the tool's behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences, front-loaded with the core behavior, and every sentence adds value without redundancy. It is appropriately concise for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is inherently simple, and the description covers behavior, usage, and alternatives. It addresses potential confusion about registration and provides a clear reference to the sibling tool. Nothing significant is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter action_type is implicitly explained as the identifier for the action. The description states that no argument can change the result, clarifying the parameter's role is nominal. This fully compensates for the 0% schema description coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool performs default-deny classification for an action_type and always returns GATED. It distinguishes itself from is_action_registered by explicitly noting that registration status does not affect the result.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance: use this tool for enforcement classification (always GATED), and use is_action_registered for informational checks about registration. This effectively directs the agent to the appropriate sibling tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

evaluate_budgetA

Sum spend_intent amounts recorded within the last window_days and compare against limit_usd. Never raises -- an empty ledger reads as total_spent_usd=0.0, within_budget=True.

ParametersJSON Schema
NameRequiredDescriptionDefault
limit_usdYes
window_daysNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses that the tool never raises exceptions and that an empty ledger yields total_spent_usd=0.0 and within_budget=True, which is valuable non-obvious behavior. However, it does not discuss other potential behaviors like rounding or timezone handling, so a 4 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no redundant words. The first sentence states the core operation, and the second adds a critical edge-case behavior. It is well-structured and front-loaded, earning a 5.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple with two parameters and an output schema. The description covers the operation and a key edge case. Since an output schema exists, it need not describe return values in detail. However, it lacks explicit usage context (when to use vs. alternatives), which is a minor gap. Thus a 4.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must explain parameters. It does explain that window_days is a time window and limit_usd is a comparison threshold, adding meaning beyond the bare schema. It does not specify units or constraints beyond what the schema already provides (e.g., default for window_days). Given the partial explanation, a 4 is suitable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'Sum' and identifies the resources 'spend_intent amounts' and 'limit_usd', making the tool's function unambiguous. It clearly differs from sibling tools such as record_spend_intent (which records) and classify_action (which classifies), so it earns a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives, nor does it mention exclusions or prerequisites. It only implies usage for budget evaluation, so it receives a 3 for implied usage rather than explicit guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_rails_hashA

12-hex sha256 digest of the currently loaded action registry, plus its entry count. Changes iff the registry's contents change -- this is the value a human sign-off (rails-mcp sign, CLI-only, never an MCP tool) records into the audit ledger.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, but the description discloses that the value changes iff the registry contents change and mentions the sign-off process is CLI-only. The read-only nature is implicit for a digest, and it adds meaningful context about the hash's role.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences with no redundant text. The core output is front-loaded, followed by the change condition and sign-off context; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple no-parameter tool with an output schema, the description covers what it returns, when it changes, and why it matters. No gaps apparent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Tool has zero parameters and an empty schema, so baseline 4 applies. The description correctly omits parameter-specific details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the output: a 12-hex sha256 digest of the action registry plus entry count. Distinct from siblings like classify_action or evaluate_budget, making its purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides context that the hash changes when registry contents change and that it is the value recorded in the audit ledger by human sign-off, note that sign-off is CLI-only and never an MCP tool. This implies when to use it, though it does not explicitly contrast with sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_signoff_stateA

Current active human sign-off of the registry (operator, signedAt, the registryHash they signed, optional note), or null if never signed or most-recently revoked. Read-only -- signing itself is a CLI-only ceremony (rails-mcp sign --operator ...), never something reachable from this or any MCP tool call.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does it well. It discloses the read-only nature, the null conditions (never signed or most-recently revoked), and that signing is inaccessible via MCP. This goes beyond basic operation to explain side effects and limitations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences, front-loaded with the return value and states key edge cases and constraints. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema exists and no parameters, the description fully covers what an agent needs to know: what the tool returns, when it may return null, and that it cannot perform signing. It is complete for a zero-parameter read-only tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters and 100% schema coverage (empty schema). Baseline for zero parameters is 4; the description adds meaningful context about the return value but correctly does not need to document parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: retrieves the current active human sign-off of the registry with specific fields (operator, signedAt, registryHash, optional note) or null. It is specific and distinct from sibling tools, all of which serve different purposes (classification, registration, hashing, spending, budgeting).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly notes this is a read-only operation and that signing is a CLI-only ceremony not reachable via any MCP tool. This provides a clear exclusion for when not to use it, though it does not explicitly name alternative tools for other sign-off-related tasks.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

is_action_registeredA

Whether action_type has an entry in the loaded rails registry, plus its enforcement_layer / enforcement_pointer / ceremony when present. Registration is informational only -- classify_action's GATED verdict never depends on it.

ParametersJSON Schema
NameRequiredDescriptionDefault
action_typeYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral disclosure burden. It states the tool is informational only, implying a read-only, non-mutating operation. It also discloses that it returns enforcement_layer/enforcement_pointer/ceremony when present. However, it does not explicitly mention side effects or error behaviors, though for a simple lookup this is less critical.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the primary purpose. Every clause adds value: the first defines the query, the second clarifies its informational nature. No redundant or filler content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity and the presence of an output schema, the description is largely complete. It explains the relationship with classify_action and what data is returned. However, it does not define 'loaded rails registry' or specify edge cases, which would be helpful for full context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It only uses the parameter name 'action_type' in context without explaining valid values, format, or examples. The meaning is partially implied, but the description does not add sufficient semantic value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: checking whether an action_type is registered in the rails registry. It specifies the exact resource (loaded rails registry) and the action (has an entry), and distinguishes itself from classify_action by clarifying that registration is informational only.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly mentions classify_action as an alternative and clarifies that this tool's results do not affect classification (GATED verdict). This tells the agent when to use this tool (for informational lookup) and when not to rely on it (not for gating decisions).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

record_spend_intentA

Append one spend-intent record to the append-only ledger. This RECORDS intent to spend -- it never calls a vendor, a paid API, or a broker, and it cannot itself authorize or block a spend.

ParametersJSON Schema
NameRequiredDescriptionDefault
actorYes
vendorYes
purposeYes
amount_usdYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It transparently discloses that the ledger is append-only, that no external calls are made, and that the tool cannot authorize or block spend – all essential behavioral traits that go beyond the tool's name.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, two sentences, with no filler. It front-loads the core action and then provides critical behavioral exclusions, making it easy to scan and understand quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity, the description covers the main behavioral aspects and is supplemented by an output schema. However, the lack of parameter semantics and explicit usage guidance prevents it from being fully complete for a tool with 4 required parameters and no annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description does not explain any parameters. While 'amount_usd' and 'vendor' are self-explanatory, 'actor' and 'purpose' are ambiguous (e.g., who is the actor and what exactly is recorded in purpose). The description fails to compensate for the schema's lack of parameter details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly specifies the action ('Append one spend-intent record') and the resource ('append-only ledger'). It distinguishes this tool from its siblings by emphasizing that it only records intent and does not execute, authorize, or block spend – a unique purpose among the given sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool (when you need to log an intent to spend) but does not explicitly state when not to use it or name alternative tools. The phrase 'never calls a vendor... cannot authorize or block a spend' hints at boundaries but lacks direct guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 6 tool updatesv0.1.0
    • First observedclassify_action
    • First observedevaluate_budget
    • First observedget_rails_hash
    • First observedget_signoff_state
    • First observedis_action_registered
    • First observedrecord_spend_intent

TDQS

A4.4/5.0
Disambiguation5/5

Each tool targets a distinct operation: classification, registry lookup, hash digest, sign-off state, spend recording, and budget evaluation. Even the two action-related tools are explicitly differentiated: one always returns a fixed verdict, the other is purely informational.

Naming Consistency5/5

All tool names follow a clear verb_noun pattern (classify_, is_, get_, record_, evaluate_). The 'is_' prefix for a boolean check is consistent with common naming conventions, and there is no mixing of styles.

Tool Count5/5

Six tools is well within the ideal range for a focused governance/guardrail server. Each tool has a clear responsibility, and the set feels neither sparse nor bloated.

Completeness4/5

The surface covers the core lifecycle: classification, registry status, hash verification, sign-off state, spend intent recording, and budget evaluation. Minor gaps exist (e.g., no tool to inspect individual ledger entries or revoke sign-off), but these are intentionally delegated to CLI or aggregate operations, so the coverage is reasonable.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Provides policy-driven runtime authorization and security evaluation for MCP-based agents, including MCP streaming HTTP gateway, mock MCP servers, deterministic agent demos, and audited tool invocation with redacted PostgreSQL audit chains.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server that gates agent tool calls by normalizing intent, denying unknown/unattended destructive actions, and requiring HITL prove approval for high-risk operations. It maintains an append-only hash-chained Action Ledger and exposes gate_check and ledger_verify tools without ever executing tools.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enforces deterministic security policies as an inline firewall for MCP server tool calls, with AST-based validation, cryptographic audit logging, and CLI-based evaluation and verification.
    MIT

Latest Blog Posts

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/jaimenbell/rails-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server