Guwah
OfficialClick on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@GuwahValidate this tools/call payload against my policy before dispatch."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
GUWAH Protocol Extension
Gateway User-Whitelist Agent Hub
Local, fail-closed policy enforcement for Model Context Protocol tools/call payloads.
Purpose
Guwah is a local, client-side policy enforcement layer for Model Context Protocol tool execution. It intercepts the complete candidate tools/call envelope and the separately supplied arguments, then evaluates both against a fail-closed JSON Schema policy before an integrating runtime may serialize any network request. The primary threat model is Client-Runtime Payload Mutation: agent-generated or mutated arguments that would otherwise authorize an unintended transfer or destructive operation. Guwah does not transmit, sign, or settle transactions, and local validation does not eliminate financial liability.
Property | Binding |
Execution locus | Local process |
Trust posture | Default deny |
Transport | None in the core validator; stdio in the gateway entry |
Provider coupling | None; MCP SDK agnostic |
Financial units | Integer minor units ( |
Failure mode | Throw |
Related MCP server: arc-gate-mcp
Execution Model
The core validator terminates at local approval or denial. The gateway entry speaks MCP over stdio and completes the official initialize / initialized handshake. Advertised capabilities stay limited to surfaces the gateway actually mediates; tools/list returns only the authorized mediated tool set. tools/call runs local Guwah validation before any downstream send. Unimplemented resources, prompts, and sampling are not claimed. Downstream tool execution is not configured by default.
[ Agent runtime ]
|
| untrusted MCP tools/call payload
| + candidate arguments
v
+--------------------------------------------------+
| GuwahGuard |
| 1. JSON-compatible bounded graph validation |
| 2. Policy load, size check, structural bounds |
| 3. Tool resolution (default deny) |
| 4. Embedded vs candidate argument parity |
| 5. Ajv argument validation (no coercion) |
+----------------------+---------------------------+
|
+--------------+--------------+
| |
v v
GuwahSecurityViolation Frozen approved envelope
(blocked; do not send) (defensive copy only)
|
| integrator serializes
| the approved value only
v
[ Integrator-owned transport ]
|
v
[ External tool server ]params._meta, when present, is optional MCP protocol metadata. It is preserved in the approved copy, included in JSON-graph and resource-limit checks, and is not validated against the tool argsSchema or compared with candidate arguments.
Vendor APIs (for example, a Coinbase-named mock tool in the sample policy) are downstream of the integrator. The core validator does not import Stripe, Coinbase, or MCP vendor SDKs and does not open sockets. The protocol adapter imports the official MCP TypeScript SDK for host tools/call shaping only and still delegates every approval to GuwahGuard. The gateway entry uses the official SDK Server and stdio transport so a conforming client can complete initialize and initialized. tools/call is refused until that handshake completes successfully, so a malformed or failed initialize cannot reach downstream dispatch. Capability negotiation returns only registered surfaces. tools/list returns the gateway-mediated catalog only and never an unfiltered downstream tool dump. When downstream discovery is configured, host-facing tool names are deterministically namespaced as guwah__ plus the raw downstream name so they cannot collide with raw downstream names in the host session; names that already use that prefix or fail the allowed character pattern are rejected rather than silently aliased. tools/call runs GuwahGuard.validateToolCall on the complete envelope and candidate arguments before any downstream send; rejected calls never dispatch. In-flight tools/call request ids are tracked explicitly; duplicate ids are rejected and completed ids are removed. MCP notifications/cancelled cancels in-flight work and suppresses late success responses without automatic retry. Optional per-request deadlines (requestTimeoutMs) expire fail-closed so expired calls do not dispatch after expiry and are not retried. Results that arrive after cancel, deadline expiry, or shutdown abort are dropped so a client never receives a success after a terminal error for the same request id. Optional maxConcurrentCalls rejects excess in-flight tools/call requests fail-closed without queuing. When that bound is set, the stdio gateway pauses stdin reading at saturation and resumes when a slot frees; framing intake is capped by maxBufferSize (10 MiB when omitted). Buffer overflow or stdin pause/resume failure closes fail-closed rather than dropping validations. Protocol and security failures return JSON-RPC error objects; each GuwahSecurityViolation code maps to a fixed sanitized MCP error with an operator guwahCode, and unexpected handler exceptions become a generic internal error without rejected values. JSON-RPC is read from stdin and written to stdout only; stdout is reserved for protocol frames during startup, list, call, and shutdown. Malformed stdio framing fails closed without dispatch. Clean shutdown stops accepting work, waits or times out in-flight approved dispatches, then closes transports without corrupting stdout. Stdin EOF and SIGINT/SIGTERM begin that ordered shutdown. Broken stdout (including EPIPE) is a terminal transport failure; further protocol writes are suppressed. Diagnostics use a redacted stderr logger that omits detail by default and never emits credentials, full payloads, or policy text. Transport failures terminate fail-closed. HTTP and SSE transports are not used.
Quick Start and Verification
Requires Node.js ^20.19.0 || >=22.12.0.
git clone <repository-url> guwah-mcp-extension
cd guwah-mcp-extension
npm ci
npm testImplementation verification:
npm run typecheck
npm run build
npm testThe suite covers approved transfers, amount and destination policy failures, payload-mutation detection, JSON-compatibility rejection, MCP _meta handling, policy-load failures, resource limits, and immutability of approved envelopes. A passing suite is necessary for local development. It does not prove the implementation secure against every threat.
Core Architecture
src/guwahGuard.ts Runtime validation engine
src/guwahMcpAdapter.ts Host tools/call adapter; calls GuwahGuard
src/guwahGateway.ts Node stdio gateway entry
test/guwahGuard.test.ts
test/guwahMcpAdapter.test.ts
test/guwahGateway.test.ts
guwah-policy.json Local operator policy
package.json
tsconfig.json Shared typecheck configuration
tsconfig.build.json Production emit (src only)
vitest.config.ts
LICENSEnpm run build writes runtime artifacts under dist/ (guwahGuard.js, guwahMcpAdapter.js, guwahGateway.js, and corresponding declarations and source maps). Test sources are not emitted. The package export remains the validator module. npm run gateway (or node dist/guwahGateway.js) starts the stdio gateway.
Host deployment boundary
Intended deployment exposes only the Guwah gateway process to the host MCP client. Start that process with npm run gateway or node dist/guwahGateway.js. Configured downstream MCP servers are attached as gateway-owned clients over a separate transport and are not registered by this package as additional host-visible MCP servers. Pointing a host client at an unprotected downstream process bypasses Guwah and is outside the intended deployment.
src/guwahGuard.ts
Runtime exports include GuwahGuard, GuwahSecurityViolation, and DEFAULT_GUWAH_RESOURCE_LIMITS. The module also exports TypeScript interfaces and violation-code types for integration. The public method accepts runtime-unknown values because agent and host objects cannot be trusted at the type boundary:
validateToolCall(
payload: unknown,
args: unknown,
): Readonly<McpToolCallPayload>Before cloning, comparing, freezing, or invoking Ajv, both graphs must be JSON-compatible: null, booleans, strings, finite numbers, dense arrays, and plain objects. Accessors, symbol keys, sparse arrays, cycles, class instances, and non-finite numbers are rejected.
Contract after JSON-graph admission:
Require a plain MCP-compatible
tools/callenvelope.Require plain-object candidate arguments.
Load
guwah-policy.jsonfrom disk on every validation (SHA-256 cache identity only; not a signature).Bound the parsed policy object graph, then validate the policy document and each tool
argsSchema.Reject unknown tools and tools not configured with
ENFORCE.Compare
payload.params.argumentstoargswhen embedded arguments exist.Validate exact values with Ajv (
coerceTypes: false,useDefaults: false,removeAdditional: false).Return a deep-frozen defensive copy, or throw
GuwahSecurityViolation.
Default policy path: path.resolve(process.cwd(), "guwah-policy.json").
Resource limits
Constructor overrides must be positive safe integers. Invalid overrides are rejected immediately.
Limit | Default | Accounting |
| 1,048,576 | Policy file bytes actually read |
| 32 | Parsed policy graph depth |
| 10,000 | Parsed policy graph nodes |
| 1,000 | Arrays in the parsed policy |
| 1,000 | Properties per policy object |
| 128 |
|
| 32 | Payload or argument graph depth |
| 10,000 | Payload or argument graph nodes |
| 1,048,576 | UTF-8 bytes of string values and object keys only |
| 10,000 | Arrays in payload or arguments |
| 1,000 | Properties per input object |
maxInputBytes does not count JSON punctuation, numeric representations, booleans, null, or container overhead. Each of the payload graph and the candidate-argument graph is measured independently against the same limits.
Schema patterns
String pattern values must be fully anchored. The sample policy uses:
^0x[0-9a-fA-F]{40}$^[A-Za-z0-9 .,_:-]+$
Admitted forms are concatenations of literals and character classes. Groups, alternation, lookarounds, backreferences, wildcards, and arbitrary escapes are rejected. At most one variable-width quantifier is permitted. Multiple exact fixed-width quantifiers may be used.
guwah-policy.json
Local constraint document. It is operator-editable and is not integrity-protected by this package.
Sample mapping for the example tool coinbase_cdp_transfer:
{
"version": "1.0.0",
"posture": "default-deny",
"tools": {
"coinbase_cdp_transfer": {
"action": "ENFORCE",
"argsSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"additionalProperties": false,
"required": [
"amountMinor",
"assetId",
"destinationAddress",
"memo"
],
"properties": {
"amountMinor": {
"type": "integer",
"minimum": 1,
"maximum": 5000
},
"assetId": {
"type": "string",
"enum": ["USDC"]
},
"destinationAddress": {
"type": "string",
"pattern": "^0x[0-9a-fA-F]{40}$",
"enum": [
"0x1111111111111111111111111111111111111111",
"0x2222222222222222222222222222222222222222"
]
},
"memo": {
"type": "string",
"minLength": 1,
"maxLength": 80,
"pattern": "^[A-Za-z0-9 .,_:-]+$"
}
}
}
}
}
}Package Scope and Integration
The published package export is the local validation engine (GuwahGuard). It is not a network proxy, wallet, or signing system. The gateway entry is the only host-facing MCP server this package starts; it does not ship a second host-visible server for unprotected downstream tools.
Integrators may wrap GuwahGuard.validateToolCall at an MCP client boundary. Any such wrapper must:
pass the complete payload and the candidate arguments;
serialize the approved return value, never the original candidate object;
treat
GuwahSecurityViolationas a denied execution, not as an HTTP status code, unless a real HTTP adapter exists.
Ajv compiles operator schemas to validators internally. Application source does not call eval or the Function constructor. That distinction is not a claim that the package executes no generated code at runtime.
License
Apache License 2.0. See LICENSE.
The extension is designed to run in a local runtime. The core validation module performs no network requests and does not export telemetry. Operator policy and candidate arguments remain on the local host unless an integrator later transmits an approved payload.
Local enforcement reduces exposure to Client-Runtime Payload Mutation. It is not a wallet, custody system, payment processor, authorization server, or substitute for server-side authorization. It does not eliminate client-side or counterparty transaction liability.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP enforcement layer that intercepts AI agent actions and blocks rule violations before execution.
Security firewall for AI agents — scans MCP calls for injection, secrets, and risks.
- gatewayOAuthai.sealgate
MCP gateway with runtime security policy, tool-call-level control, and audit of agent actions.
Security & DLP proxy for MCP: tool-poisoning scans, PII redaction on tool args/results. Beta.
Related MCP Servers
AlicenseNot gradedqualityCmaintenancePolicy enforcement gateway for MCP tool calls, evaluating every tool invocation against declarative YAML policies (allow/deny/escalate-to-human), generating cryptographic hash-chained audit receipts, and including built-in content safety scanning.2MIT- AlicenseAqualityCmaintenanceRuntime governance proxy for MCP tool calls. Inspects tool results for prompt injection and capability abuse before they reach your agent, blocking attacks that exploit the MCP trust boundary.12AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceRuntime proxy that intercepts and blocks MCP tool calls based on YAML-defined policies, enforcing security rules for AI agents like Claude Code or Cursor.44 npm1Apache 2.0
- AlicenseAqualityAmaintenanceAn MCP proxy that enforces policy on every tool call, blocking or flagging actions before they reach downstream MCP servers.118 npmMIT