Koskamo

HANRIA Agent Mandate Check MCP

This MCP server allows AI agents to check proposed actions against an operator's written mandate rules before execution. It returns permit, deny, or escalate decisions with named clauses, validates mandate schemas, and provides signed receipts for auditability. It supports various mandate templates for payments, deployments, and research.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

HANRIA Agent Mandate Check MCP logo, by HANRIAVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-07Operated by HANRIA
MCP endpoint (Streamable HTTP)
https://check.hanria.ai/v1/mcp
Vendor documentation

What its tools do

2 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

2 of 2 have a description · 2 of 2 declare behavior hints · 2 of 2 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Passed Official MCP Registry namespace is tied to hanria.ai ·
  • Passed Endpoint is on the registry namespace domain ·
  • Warning Advertises resources/templates/list but does not implement it
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Check if an agent's proposed action is permitted by its mandate
  • Validate the structure and logic of a written mandate
  • Retrieve standard mandate templates for common use cases
  • Generate signed receipts for audit trails of decisions

Source and maintenance

Vendor evidenceRegistry 0.7.4

Protocol and capabilities

Server
hanria-check 0.7.4
MCP protocol negotiated in check
2025-11-25
Tools
2 advertised
Resources
5 advertised
Resource templates
Not advertised
Prompts
1 advertised
Server-advertised capabilities
{
  "tools": {},
  "prompts": {},
  "resources": {}
}

Tools

2 advertised

check_action — Check an agent action against a mandate
Advertised by the server during the last successful anonymous check.
Advertised read-only

Call this before your agent does something consequential (sends, pays, deletes, publishes, installs or changes access). Pass mandate (the operator's rules; the first matching clause decides) and action (kind, verb, target, optional counterparty and amount). Returns permit, deny or escalate with the governing clause, a reason, an action digest and a signed receipt; treat error as deny. Advisory: it cannot stop an action, and it keeps no request content. To check a new mandate first, call validate_mandate. Examples: inputSchema. Docs: https://hanria.ai/llms.txt

check_action input schema
{
  "type": "object",
  "examples": [
    {
      "action": {
        "operation": {
          "kind": "file",
          "verb": "read",
          "target": "/tmp/example"
        },
        "requested_by": {
          "agent": "example-agent"
        },
        "justification": "Read the permitted file.",
        "schema_version": "0.1-draft"
      },
      "mandate": {
        "clauses": [
          {
            "id": "permit-file",
            "match": {
              "kind": [
                "file"
              ]
            },
            "effect": "permit"
          }
        ],
        "default": "deny",
        "purpose": "Permit one file action.",
        "mandate_id": "minimal-permit",
        "schema_version": "0.2-draft"
      }
    },
    {
      "action": {
        "operation": {
          "kind": "transaction",
          "verb": "transfer",
          "amount": {
            "value": "25",
            "currency": "USDC"
          },
          "target": "eip155:11155111/0x1111111111111111111111111111111111111111/transfer",
          "counterparty": "0x2222222222222222222222222222222222222222"
        },
        "requested_by": {
          "agent": "example-agent"
        },
        "justification": "Pay the invoiced supplier.",
        "schema_version": "0.1-draft"
      },
      "mandate": {
        "clauses": [
          {
            "id": "small-transfers",
            "match": {
              "kind": [
                "transaction"
              ],
              "verb": [
                "transfer"
              ],
              "max_amount": {
                "value": "100",
                "currency": "USDC"
              },
              "counterparty": [
                "0x2222222222222222222222222222222222222222"
              ],
              "target_prefix": [
                "eip155:11155111/0x1111111111111111111111111111111111111111/"
              ]
            },
            "effect": "permit"
          }
        ],
        "default": "escalate",
        "purpose": "Permit small transfers to one named recipient on a test network.",
        "mandate_id": "example-payments",
        "schema_version": "0.2-draft"
      }
    }
  ],
  "required": [
    "mandate",
    "action"
  ],
  "properties": {
    "action": {
      "type": "object",
      "title": "HANRIA action request",
      "$comment": "Forbidden anywhere in an instance: credential, secret, private_key, token, password, api_key. A runtime is expected to refuse a request containing them rather than strip them.",
      "required": [
        "schema_version",
        "requested_by",
        "operation",
        "justification"
      ],
      "properties": {
        "operation": {
          "type": "object",
          "required": [
            "kind",
            "verb",
            "target"
          ],
          "properties": {
            "kind": {
              "enum": [
                "file",
                "process",
                "package",
                "network",
                "device",
                "credential_use",
                "transaction",
                "administrative"
              ]
            },
            "verb": {
              "type": "string",
              "minLength": 1,
              "description": "What is to be done to the target, e.g. read, write, execute, install, connect, sign, transfer. Required: an operation named only by its kind does not describe a proposed action well enough to be judged."
            },
            "amount": {
              "type": "object",
              "required": [
                "value",
                "currency"
              ],
              "properties": {
                "value": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Decimal as a string, to avoid float error."
                },
                "currency": {
                  "type": "string",
                  "minLength": 1
                }
              },
              "description": "An amount. Both fields are required: a bare amount object describes nothing a ceiling could be compared against.",
              "additionalProperties": false
            },
            "target": {
              "type": "string",
              "minLength": 1,
              "description": "What the operation acts on. A path, host, package name, or resource identifier. NEVER a secret. Required for the same reason as the verb."
            },
            "parameters": {
              "type": "object",
              "description": "Non-secret parameters. A runtime MUST reject any request whose parameters appear to contain a credential."
            },
            "counterparty": {
              "type": "string"
            }
          },
          "additionalProperties": false
        },
        "mandate_ref": {
          "type": "string",
          "description": "Optional reference to the owner-defined mandate the agent believes authorizes this."
        },
        "requested_by": {
          "type": "object",
          "required": [
            "agent"
          ],
          "properties": {
            "agent": {
              "type": "string",
              "description": "Identifier of the requesting agent."
            },
            "session": {
              "type": "string",
              "description": "Optional session or task identifier."
            },
            "on_behalf_of": {
              "type": "string",
              "description": "Optional identifier of the human or system the agent acts for."
            }
          },
          "additionalProperties": false
        },
        "justification": {
          "type": "string",
          "minLength": 1,
          "description": "Why the agent believes this is within its mandate. Free text, for the record."
        },
        "schema_version": {
          "const": "0.1-draft",
          "description": "Draft. The runtime does not exist; this shape may change."
        },
        "idempotency_key": {
          "type": "string",
          "description": "Optional. Lets a runtime refuse a duplicate rather than perform an operation twice."
        }
      },
      "description": "A typed description of a proposed operation, submitted by an agent to a local HANRIA runtime. MUST NOT contain credentials, secrets, private keys, or tokens.",
      "additionalProperties": false
    },
    "mandate": {
      "type": "object",
      "title": "HANRIA mandate",
      "$comment": "A mandate names what may be done, not the means of doing it, and must never contain a credential, secret, key or token. The checker refuses a mandate carrying recognizable credential material rather than evaluating it, because anything in a clause note is copied into the decision record. That detection is a heuristic and cannot be complete.",
      "required": [
        "schema_version",
        "mandate_id",
        "purpose",
        "default",
        "clauses"
      ],
      "properties": {
        "clauses": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "effect",
              "match"
            ],
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "Identifier for this clause. Returned with every decision so a reviewer can see which sentence of the mandate was relied on."
              },
              "note": {
                "type": "string",
                "description": "Why this clause exists. Carried into the decision record verbatim."
              },
              "match": {
                "type": "object",
                "required": [
                  "kind"
                ],
                "properties": {
                  "kind": {
                    "type": "array",
                    "items": {
                      "enum": [
                        "file",
                        "process",
                        "package",
                        "network",
                        "device",
                        "credential_use",
                        "transaction",
                        "administrative"
                      ]
                    },
                    "minItems": 1,
                    "description": "Operation kinds this clause covers."
                  },
                  "verb": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "description": "Permitted verbs, matched case-insensitively and exactly. Absent means any verb."
                  },
                  "max_amount": {
                    "type": "object",
                    "required": [
                      "value",
                      "currency"
                    ],
                    "properties": {
                      "value": {
                        "type": "string",
                        "description": "Decimal as a string, to avoid float error."
                      },
                      "currency": {
                        "type": "string"
                      }
                    },
                    "description": "Ceiling for an operation carrying an amount. A request above it does not match this clause.",
                    "additionalProperties": false
                  },
                  "counterparty": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "description": "Permitted counterparties, matched exactly. Absent means any counterparty."
                  },
                  "target_prefix": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "description": "The operation target must begin with one of these strings. Absent means any target. Prefix matching is deliberately literal: it does not resolve symlinks, normalize paths, or understand hostnames, so a target is compared as written."
                  }
                },
                "description": "All present conditions must hold for the clause to match.",
                "additionalProperties": false
              },
              "effect": {
                "enum": [
                  "permit",
                  "deny",
                  "escalate"
                ],
                "description": "What this clause does when it matches."
              }
            },
            "additionalProperties": false
          },
          "minItems": 1,
          "description": "Evaluated in order. The first matching clause decides. A request matching no clause takes the mandate default."
        },
        "default": {
          "enum": [
            "deny",
            "escalate"
          ],
          "description": "What happens when no clause matches. 'permit' is deliberately not an option: a mandate that permits by default cannot express a limit."
        },
        "purpose": {
          "type": "string",
          "minLength": 1,
          "description": "What the agent is authorized to accomplish, in the operator's own words. Not evaluated mechanically; it is the human-readable statement against which a reviewer judges whether the clauses actually express the intent."
        },
        "issued_by": {
          "type": "string",
          "description": "Who wrote this mandate. Free text; not authenticated by anything in this skill."
        },
        "mandate_id": {
          "type": "string",
          "minLength": 1,
          "description": "Stable identifier for this mandate. Appears in every decision record made against it."
        },
        "requires_human": {
          "type": "array",
          "items": {
            "enum": [
              "file",
              "process",
              "package",
              "network",
              "device",
              "credential_use",
              "transaction",
              "administrative"
            ]
          },
          "minItems": 0,
          "description": "Operation kinds that always require a person, even where a clause permits them. These escalate rather than permit."
        },
        "schema_version": {
          "const": "0.2-draft",
          "description": "Draft. The shape may change while the runtime is in development."
        },
        "not_valid_after": {
          "type": "string",
          "format": "date-time",
          "description": "RFC 3339 timestamp. After this instant every action is denied. Absent means no expiry, which is discouraged: an unbounded mandate is the condition that lets delegated authority outlive the task it was granted for."
        }
      },
      "description": "An operator-authored statement of what an agent may do. Written by a person, read by an agent, evaluated locally. A mandate is advisory: it describes intended authority and supports a local check, but it does not enforce anything. Enforcement requires a component that exclusively holds the credentials and can refuse.",
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
check_action output schema
{
  "type": "object",
  "required": [
    "schema_version",
    "outcome",
    "reason"
  ],
  "properties": {
    "clause": {
      "type": "string",
      "description": "The clause that decided, when one did."
    },
    "reason": {
      "type": "string"
    },
    "outcome": {
      "enum": [
        "permit",
        "deny",
        "escalate",
        "error"
      ],
      "type": "string",
      "description": "Treat error as deny."
    },
    "receipt": {
      "type": "object",
      "required": [
        "type",
        "kid",
        "outcome",
        "action_digest",
        "mandate_digest",
        "issued_at",
        "not_after",
        "signature"
      ],
      "properties": {
        "kid": {
          "type": "string"
        },
        "type": {
          "type": "string",
          "const": "hanria-receipt-v1"
        },
        "clause": {
          "type": "string"
        },
        "outcome": {
          "enum": [
            "permit",
            "deny",
            "escalate"
          ],
          "type": "string"
        },
        "issued_at": {
          "type": "string",
          "format": "date-time"
        },
        "not_after": {
          "type": "string",
          "format": "date-time"
        },
        "signature": {
          "type": "string"
        },
        "mandate_ref": {
          "type": "string"
        },
        "action_digest": {
          "type": "string"
        },
        "mandate_digest": {
          "type": "string"
        }
      },
      "description": "Ed25519-signed receipt binding the outcome to this action and mandate for 15 minutes. Keys and the signed-bytes rule: https://check.hanria.ai/.well-known/hanria-receipt-keys.json",
      "additionalProperties": false
    },
    "clause_note": {
      "type": "string"
    },
    "mandate_ref": {
      "type": "string"
    },
    "action_digest": {
      "type": "string",
      "description": "SHA-256 of hanria-action-v1 followed by the action's canonical JSON."
    },
    "schema_version": {
      "type": "string",
      "const": "0.1-draft"
    }
  },
  "additionalProperties": false
}
check_action annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true
}
validate_mandate — Check a mandate for errors
Advertised by the server during the last successful anonymous check.
Advertised read-only

Call this after writing or editing a mandate, before relying on it. Returns valid true or false with the reason: schema errors, clauses that can never run because an earlier clause already decides them, unbounded prefixes, credential material, and expiry. An invalid mandate makes every check_action call answer error. Once per mandate version is enough; there is no need to call it before every check_action. Free, and it keeps no request content. Docs: https://hanria.ai/llms.txt

validate_mandate input schema
{
  "type": "object",
  "examples": [
    {
      "mandate": {
        "clauses": [
          {
            "id": "permit-file",
            "match": {
              "kind": [
                "file"
              ]
            },
            "effect": "permit"
          }
        ],
        "default": "deny",
        "purpose": "Permit one file action.",
        "mandate_id": "minimal-permit",
        "schema_version": "0.2-draft"
      }
    }
  ],
  "required": [
    "mandate"
  ],
  "properties": {
    "mandate": {
      "type": "object",
      "title": "HANRIA mandate",
      "$comment": "A mandate names what may be done, not the means of doing it, and must never contain a credential, secret, key or token. The checker refuses a mandate carrying recognizable credential material rather than evaluating it, because anything in a clause note is copied into the decision record. That detection is a heuristic and cannot be complete.",
      "required": [
        "schema_version",
        "mandate_id",
        "purpose",
        "default",
        "clauses"
      ],
      "properties": {
        "clauses": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "id",
              "effect",
              "match"
            ],
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1,
                "description": "Identifier for this clause. Returned with every decision so a reviewer can see which sentence of the mandate was relied on."
              },
              "note": {
                "type": "string",
                "description": "Why this clause exists. Carried into the decision record verbatim."
              },
              "match": {
                "type": "object",
                "required": [
                  "kind"
                ],
                "properties": {
                  "kind": {
                    "type": "array",
                    "items": {
                      "enum": [
                        "file",
                        "process",
                        "package",
                        "network",
                        "device",
                        "credential_use",
                        "transaction",
                        "administrative"
                      ]
                    },
                    "minItems": 1,
                    "description": "Operation kinds this clause covers."
                  },
                  "verb": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "description": "Permitted verbs, matched case-insensitively and exactly. Absent means any verb."
                  },
                  "max_amount": {
                    "type": "object",
                    "required": [
                      "value",
                      "currency"
                    ],
                    "properties": {
                      "value": {
                        "type": "string",
                        "description": "Decimal as a string, to avoid float error."
                      },
                      "currency": {
                        "type": "string"
                      }
                    },
                    "description": "Ceiling for an operation carrying an amount. A request above it does not match this clause.",
                    "additionalProperties": false
                  },
                  "counterparty": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "description": "Permitted counterparties, matched exactly. Absent means any counterparty."
                  },
                  "target_prefix": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "description": "The operation target must begin with one of these strings. Absent means any target. Prefix matching is deliberately literal: it does not resolve symlinks, normalize paths, or understand hostnames, so a target is compared as written."
                  }
                },
                "description": "All present conditions must hold for the clause to match.",
                "additionalProperties": false
              },
              "effect": {
                "enum": [
                  "permit",
                  "deny",
                  "escalate"
                ],
                "description": "What this clause does when it matches."
              }
            },
            "additionalProperties": false
          },
          "minItems": 1,
          "description": "Evaluated in order. The first matching clause decides. A request matching no clause takes the mandate default."
        },
        "default": {
          "enum": [
            "deny",
            "escalate"
          ],
          "description": "What happens when no clause matches. 'permit' is deliberately not an option: a mandate that permits by default cannot express a limit."
        },
        "purpose": {
          "type": "string",
          "minLength": 1,
          "description": "What the agent is authorized to accomplish, in the operator's own words. Not evaluated mechanically; it is the human-readable statement against which a reviewer judges whether the clauses actually express the intent."
        },
        "issued_by": {
          "type": "string",
          "description": "Who wrote this mandate. Free text; not authenticated by anything in this skill."
        },
        "mandate_id": {
          "type": "string",
          "minLength": 1,
          "description": "Stable identifier for this mandate. Appears in every decision record made against it."
        },
        "requires_human": {
          "type": "array",
          "items": {
            "enum": [
              "file",
              "process",
              "package",
              "network",
              "device",
              "credential_use",
              "transaction",
              "administrative"
            ]
          },
          "minItems": 0,
          "description": "Operation kinds that always require a person, even where a clause permits them. These escalate rather than permit."
        },
        "schema_version": {
          "const": "0.2-draft",
          "description": "Draft. The shape may change while the runtime is in development."
        },
        "not_valid_after": {
          "type": "string",
          "format": "date-time",
          "description": "RFC 3339 timestamp. After this instant every action is denied. Absent means no expiry, which is discouraged: an unbounded mandate is the condition that lets delegated authority outlive the task it was granted for."
        }
      },
      "description": "An operator-authored statement of what an agent may do. Written by a person, read by an agent, evaluated locally. A mandate is advisory: it describes intended authority and supports a local check, but it does not enforce anything. Enforcement requires a component that exclusively holds the credentials and can refuse.",
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
validate_mandate output schema
{
  "type": "object",
  "required": [
    "schema_version",
    "valid",
    "reason"
  ],
  "properties": {
    "valid": {
      "type": "boolean"
    },
    "reason": {
      "type": "string"
    },
    "clauses": {
      "type": "integer"
    },
    "expired": {
      "type": "boolean",
      "description": "True when not_valid_after has passed; check_action then denies everything."
    },
    "mandate_ref": {
      "type": "string"
    },
    "mandate_digest": {
      "type": "string",
      "description": "SHA-256 of the mandate's canonical JSON; receipts carry the same value."
    },
    "schema_version": {
      "type": "string",
      "const": "0.1-draft"
    }
  },
  "additionalProperties": false
}
validate_mandate annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true
}

Prompts

1 advertised

write_mandate

Advertised by the server during the last successful anonymous check.

Write a mandate from the closest validated HANRIA template.

goal
What the mandate should allow and restrict.

Resources

5 advertised

payments-ceiling — Payments ceiling

Advertised by the server during the last successful anonymous check.

Permit bounded on-chain transfers to named recipients and escalate everything else.

payments-ceiling URI
hanria://mandates/payments-ceiling

MIME type: application/json

file-sandbox — File sandbox

Advertised by the server during the last successful anonymous check.

Deny sensitive directories and permit reads and writes under one bounded directory.

file-sandbox URI
hanria://mandates/file-sandbox

MIME type: application/json

outbound-email — Outbound email

Advertised by the server during the last successful anonymous check.

Permit network posts only to one mail API prefix.

outbound-email URI
hanria://mandates/outbound-email

MIME type: application/json

deploy-gate — Deploy gate

Advertised by the server during the last successful anonymous check.

Escalate administrative deploys to a person.

deploy-gate URI
hanria://mandates/deploy-gate

MIME type: application/json

read-only-research — Read only research

Advertised by the server during the last successful anonymous check.

Permit network gets to HTTPS targets and deny every other action.

read-only-research URI
hanria://mandates/read-only-research

MIME type: application/json

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
548 ms
95th percentile latency
548 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 548 ms · metadata changed · 2 tool(s), 5 resource(s), 1 prompt(s); warnings: Advertises resources/templates/list but does not implement it

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http hanria-agent-mandate-check-mcp https://check.hanria.ai/v1/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add hanria-agent-mandate-check-mcp --url https://check.hanria.ai/v1/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable hanria-agent-mandate-check-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "hanria-agent-mandate-check-mcp": {
      "url": "https://check.hanria.ai/v1/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "hanria-agent-mandate-check-mcp": {
      "type": "streamableHttp",
      "url": "https://check.hanria.ai/v1/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start hanria-agent-mandate-check-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "hanria-agent-mandate-check-mcp": {
      "type": "http",
      "url": "https://check.hanria.ai/v1/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http hanria-agent-mandate-check-mcp https://check.hanria.ai/v1/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://check.hanria.ai/v1/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "hanria-agent-mandate-check-mcp": {
      "serverUrl": "https://check.hanria.ai/v1/mcp"
    }
  }
}

Let your agent find its tools

Find servers like HANRIA Agent Mandate Check MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run HANRIA Agent Mandate Check MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing