mcp-gatehouse
This server for order management demonstrates permission tiers, approval gates, and audit logging.
Look up orders (
lookup_order): Read-only status check with no side effects.Add notes (
add_note): Write operation to attach a note; the optionalapi_keyargument is redacted in logs and approval requests.Cancel orders (
cancel_order): Destructive operation requiring explicit human approval; fails closed if no approver is configured, with all attempts recorded.
Key features:
Tools are assigned access tiers (
READ,WRITE,DESTRUCTIVE) for fine-grained control.DESTRUCTIVE(and optionallyWRITE) operations go through approval gates, denying if approval is missing.Every call—approved, denied, or failed—is logged in a JSONL audit trail with timestamps, redacted arguments, and outcomes.
Sensitive arguments like
api_keyare automatically masked before logging or reaching an approver.
mcp-gatehouse
Permission tiers, approval gates, and audit logging for MCP servers. The server is the gatekeeper: you decide what an AI can read, what it can write, and what's off-limits — and every action gets logged.
Most MCP servers hand the model every tool at full strength and keep no
record of what it did. That's fine for a demo. It's not fine the day an
agent has write access to your CRM, your books, or your order system.
mcp-gatehouse is the missing gate, enforced inside the server — no
proxy, no external policy service, no dependencies beyond the official
mcp SDK.
pip install mcp-gatehouseWhat you get
Permission tiers | Every tool is declared |
Approval gates | Tiers you choose require a sign-off before the tool runs. Your approver is any callable — a terminal prompt, a Slack ping, a ticket. Fails closed: a gated tool with no approver configured is denied, not waved through. |
Audit log | Append-only JSONL, one line per call — allowed, denied, or failed — with UTC timestamps and durations. The answer to "what did the AI actually do?" six months later. |
Redaction | Argument keys you name ( |
Denylist | Block a tool outright, whatever its tier. |
Related MCP server: Agentrim MCP
Quickstart
from mcp.server.fastmcp import FastMCP
from mcp_gatehouse import AccessTier, AuditLog, Gatehouse, Policy
mcp = FastMCP("order-desk")
gatehouse = Gatehouse(
mcp,
policy=Policy(approver=lambda req: input(f"allow {req.tool}? [y/N] ") == "y"),
audit=AuditLog(path="audit.jsonl"),
)
@gatehouse.tool(tier=AccessTier.READ)
def lookup_order(order_id: str) -> str:
"""Look up an order's status."""
...
@gatehouse.tool(tier=AccessTier.DESTRUCTIVE)
def cancel_order(order_id: str) -> str:
"""Cancel an order. Runs only if the approver says yes."""
...
mcp.run()That's the whole integration: build your FastMCP server exactly as the
SDK docs show, but register tools through the gatehouse. Schema generation,
transports, and everything else work unchanged — the guard preserves the
function's signature.
Under the default policy, DESTRUCTIVE requires approval and everything
is audited. Gate writes too with one line:
Policy(require_approval=frozenset({AccessTier.WRITE, AccessTier.DESTRUCTIVE}), ...)What the audit trail looks like:
{"ts": "2026-07-16T14:02:11+00:00", "tool": "lookup_order", "tier": "read", "outcome": "ok", "arguments": {"order_id": "4417"}, "duration_ms": 0.42}
{"ts": "2026-07-16T14:02:38+00:00", "tool": "add_note", "tier": "write", "outcome": "ok", "arguments": {"order_id": "4417", "note": "call back", "api_key": "«redacted»"}, "duration_ms": 1.08}
{"ts": "2026-07-16T14:03:05+00:00", "tool": "cancel_order", "tier": "destructive", "outcome": "denied", "reason": "approver refused", "arguments": {"order_id": "4417"}}Try the demo
The package ships a runnable order-desk server with all three tiers wired up and a terminal-prompt approver:
mcp-gatehouse-demoPoint any MCP client at it over stdio (Claude Desktop, etc.), ask the model
to cancel an order, and watch the approval land in your terminal — and the
verdict land in audit.jsonl either way. examples/orders_server.py is
the same server as a copyable template.
Design notes
Enforcement lives inside the server, at the tool boundary. A proxy can't see your tools' semantics, and a policy service is one more thing to deploy. A 40-person plant doesn't have a platform team; this is a few small classes and a JSONL file.
Fail closed. Security defaults that quietly allow are worse than none. That includes redaction: argument values the scrubber can't take apart (arbitrary objects, bytes) are replaced with an opaque placeholder rather than passed through, and exception messages stay out of the log — only the exception type is recorded, because error text loves to embed the very values you just redacted.
The audit log records denials and errors, not just successes — the calls that didn't happen are half the story.
A blocking terminal approver and the stdio transport don't mix — stdout/stdin are the protocol pipe. The demo's approver prompts on
/dev/ttyfor exactly that reason (and denies when no terminal exists). Real deployments should approve out-of-band: Slack, a ticket, a queue.What this is not: authentication, transport encryption, or a sandbox. It's a gate inside your server, not a perimeter around it. See SECURITY.md.
Compatibility
Targets the official mcp Python SDK
v1.x (mcp>=1.27,<2) and Python 3.10+. When SDK v2 ships for the
2026-07-28 spec revision, a v2-compatible release will follow — the
public API here (Gatehouse, Policy, AuditLog, AccessTier) will
not change.
Who built this
Nick George — I design and run MCP servers in production for a mid-market reverse logistics-tech company, and build them for businesses at nickgeorgeai.com. This library is the permission-and-audit discipline from those builds, extracted.
If you're an owner or operator wondering what MCP even is, start with the plain-English guide: What is an MCP server?
License
Available Tools
3 toolsadd_noteC
Attach a note to an order. (The api_key never reaches the log.)
| Name | Required | Description | Default |
|---|---|---|---|
| note | Yes | ||
| api_key | No | ||
| order_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate not read-only and not destructive; description adds that api_key is not logged, which is valuable. But lacks other behavioral details like whether notes append or overwrite.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely short, but under-specified. It is concise but fails to provide necessary information, so not truly effective conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having an output schema, the description lacks parameter explanations and usage context. With 3 parameters and no parameter descriptions, it is incomplete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and description provides no parameter details. None of the three parameters (note, api_key, order_id) are explained beyond their names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Attach a note to an order,' which is a specific verb and resource. It is distinct from sibling tools lookup_order and cancel_order.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives. The parenthetical about api_key is a security note, not usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cancel_orderADestructive
Cancel an order. Requires approval — the gate fails closed.
| Name | Required | Description | Default |
|---|---|---|---|
| order_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true, but the description adds valuable context about an approval gate that fails closed, which is critical for the agent to understand operational behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences: one for purpose, one for behavioral constraint. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple cancellation tool with one parameter and an output schema (not shown), the description covers the core purpose and a key constraint. It does not discuss prerequisites like existence of the order, but that is often implied.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description does not explain the order_id parameter beyond its name. The agent must infer its meaning from context, which is inadequate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the action ('Cancel') and resource ('an order'), distinguishing it from siblings lookup_order and add_note which serve different purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description mentions a key constraint ('Requires approval — the gate fails closed'), implying when to use it is when canceling an order, but does not explicitly contrast with siblings or provide exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lookup_orderBRead-only
Look up an order's status.
| Name | Required | Description | Default |
|---|---|---|---|
| order_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the description adds minimal behavioral context beyond specifying 'status'. No contradictions but also no additional depth.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: one sentence with no unnecessary words. It is front-loaded with the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The output schema likely explains return values, and siblings give context. However, the missing parameter description is a significant gap given the zero coverage in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description does nothing to explain the 'order_id' parameter. It does not mention format, source, or constraints, leaving the agent without needed context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('look up') and the resource ('an order's status'). It distinguishes from siblings like 'add_note' and 'cancel_order' which are mutation operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives. While the name and description imply it's for read-only status checks, there is no mention of scenarios or exclusions.
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.
3 tool updates
v1.0.0- First observed
add_note - First observed
cancel_order - First observed
lookup_order
TDQS
Each tool has a clearly distinct purpose: looking up status, adding a note, and canceling an order. No overlap.
All three tools follow a consistent verb_noun pattern in snake_case (lookup_order, add_note, cancel_order).
Three tools is well-scoped for an order management server, covering essential operations without unnecessary bloat.
Covers core order operations (read, update via note, delete via cancel), but missing an update_order or list_orders tool, which are minor gaps.
Maintenance
Related MCP Connectors
Create, deploy, and operate MCP servers directly from your GitHub repositories.
A MCP server built for developers enabling Git based project management with project and personal…
Independent A-F trust grade for any MCP server, watched for drift. Free, never for sale.
Trust, freshness, policy, and discovery layer for public MCP servers.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceSecurity gateway for MCP servers. Wraps any MCP server with per-tool policies (Cedar + JSON), Ed25519-signed decision receipts, human approval gates, and trust tiers. Shadow mode by default — logs everything, blocks nothing.6939MIT
- AlicenseNot gradedqualityBmaintenanceA least-privilege enforcement proxy for MCP servers. It sits between MCP clients and upstream servers, enforcing tool policies, hiding denied tools, requiring human approval for risky actions, and providing a structured audit trail.MIT
- AlicenseBqualityBmaintenanceLocal MCP server for inspecting and managing an allowlisted Discord server via Discord's REST API, with safety modes, idempotent JSON blueprints, and destructive-operation safeguards.271MIT
- AlicenseAqualityBmaintenanceA security-first MCP server for managing Whatbox slots with structured read-only inspection and approval-gated mutations, including storage, services, website deployment, and torrent control.30MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/nickgeorgeseo/mcp-gatehouse'
If you have feedback or need assistance with the MCP directory API, please join our Discord server