VITNA
MCP serverDev toolsYour AI checks each planned action against compliance rules and gets an allow or deny decision before it acts. It covers 24 statutes across 13 jurisdictions, including the EU AI Act, GDPR, and DPDP. Actions that fail the check are stopped before they happen.
Use VITNA in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add VITNA and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the vitna help tool from VITNA
No key or account is asked for. Not verified by us yet: Ahel has not run a call through it.
Details
Available today. Use it from your connected AI after setup.
No key or account is asked for. Not verified by us yet: Ahel has not run a call through it.
After adding it, have your AI run a planned action through a check and review the allow or deny result.
What your AI can do with it
- Check a planned action against compliance rules before it runs
- Get a clear allow or deny decision for each action
- Check actions against the EU AI Act, GDPR, and DPDP
- Apply rules from 13 jurisdictions
- Stop non-compliant actions before they happen
Install VITNA
The server’s own address, for the clients that take one directly. Or connect Ahel once and every client you use reads it from one address, with the account kept on Ahel rather than in each client’s config.
Claude Code
claude mcp add --transport http --scope user vitna 'https://vitna.costrinity.xyz/api/mcp'Run it once in your project, then open /mcp to approve any sign-in the server asks for.
Claude Desktop
https://vitna.costrinity.xyz/api/mcpAdd a custom connector in Settings, paste this address, and approve the sign-in.
Cursor
cursor://anysphere.cursor-deeplink/mcp/install?name=vitna&config=eyJ1cmwiOiJodHRwczovL3ZpdG5hLmNvc3RyaW5pdHkueHl6L2FwaS9tY3AifQ==Open the link and Cursor adds the server at that address.
ChatGPT
https://vitna.costrinity.xyz/api/mcpIn Settings, enable Developer mode, create an MCP app, and paste this address. Your plan and workspace must allow custom apps.
Codex
codex mcp add vitna --url 'https://vitna.costrinity.xyz/api/mcp'Run it once, then sign in with codex mcp login vitna if the server asks for an account.
From the project's README
As published by costrinity/vitna-compliance-mcp in README.md.
A containment layer for AI agents that go rogue.
Agents go rogue through their tools. VITNA sits on the tools you put behind it. Calls to the tools you mark as risky wait for a person. No answer, no run. No API key can decide a hold, including the agent's own. On a claimed account, every guarded session ends in a signed record you can check offline.
Try it in 60 seconds
npx -y @costrinity/vitna-compliance-mcp guard -- <your stdio MCP server command>
To see a hold, give the guard a policy file that lists the tools to hold. The
reference filesystem server has no delete tool: it destroys a file by
overwriting or moving it, so this policy.json holds those calls and allows
the rest:
{ "allowed_actions": ["*"], "hold_actions": ["write_file", "edit_file", "move_file"] }
VITNA_GUARD_POLICY=/path/to/policy.json npx -y @costrinity/vitna-compliance-mcp guard -- npx -y @modelcontextprotocol/server-filesystem /path/to/test-folder
In an MCP client config, put VITNA_GUARD_POLICY under env (see
Guard mode).
Every tools/call is checked by VITNA before it reaches the server. Anything not
allowed is refused with a tool error that says why. With no credentials you get a
trial key: a risky call is held, and with nobody able to approve it yet, it's
blocked when the window ends. To approve or deny holds and keep signed records,
claim the account with GitHub or a passkey. The claim link is printed in your MCP
server log and never sent to the agent; VITNA_OPEN_CLAIM=1 opens it in your
browser.
Try it on a test agent first.
Scope
VITNA sees only the servers it wraps. A built-in shell or an unwrapped server is outside it, so turn those off if you want every action to go through the guard. The session record lists what you declared as unwrapped. The remote endpoint offers the same checks as tools an agent calls itself; that's cooperative, not containment. Detection is heuristic pattern matching, not a sandbox.
What it doesn't do · Guard mode · Verify a record
Renamed from VIGIL
This package was formerly published as
@costrinity/vigil-compliance-mcp and this repo was formerly
COSTRINITY/vigil-compliance-mcp. The old package is still on npm at
0.2.4, deprecated with the message "Renamed: use
@costrinity/vitna-compliance-mcp". It gets no updates and has no guard
mode, so anything still pointing at it installs that old version. Directory
listings that show the VIGIL name are stale snapshots of this repo.
Current package: @costrinity/vitna-compliance-mcp
Registry entry: xyz.costrinity/vitna-compliance-preflight
Site: https://vitna.costrinity.xyz
Also included
The same package carries VITNA's compliance checks: 23 MCP tools across 24 named statutes in 13 jurisdictions, for an agent to call itself before it acts. Decision support, not legal advice; scorecards are not certifications.
Most compliance servers answer questions about regulations. This one answers one question about the action your agent is holding right now: may it run? Your agent calls a check, gets allowed / blocked / flagged back synchronously, and decides. VITNA evaluates and records; your system enforces.
The package
One package to install. This is the server your agent calls before it acts.
| Package | What it does | When you want it | Install |
|---|---|---|---|
@costrinity/vitna-compliance-mcp (this one) | Your agent asks before it acts. Returns allow / block / flag on a proposed action, and records a signed evidence record of the decision. | You want a guardrail your agent calls, and provable receipts that it did. | npx @costrinity/vitna-compliance-mcp — no credentials needed to start |
A passive observer that records existing MCP traffic without deciding anything is built in this repo but is not published to npm, so it is not documented here yet. Nothing above depends on it.
Coverage
| 24 named statutes | across 13 jurisdictions |
| EU AI Act (Reg 2024/1689) | risk-tier classification before you build or ship |
| GDPR + UK GDPR | DPIA thresholds, breach reportability, ROPA |
| DPDP (India, 2023) | §16 cross-border status, §8 breach path |
| LGPD · PDPA-SG · APPI · PIPEDA + Law 25 · PIPL · PIPA-KR · NDPA · APP-AU · CPRA | jurisdiction packs |
| HIPAA · GLBA · COPPA · FERPA · FCRA · SOX | US federal sectoral applicability |
| RBI · SEBI · IRDAI · TRAI/DoT · PFRDA | Indian sectoral regulators |
| 16 US state privacy laws | plus breach deadlines for 21 states |
| 23 MCP tools | 6 identifier validators, 15 stateless helpers |
Readiness scorecards (pre-audit, not certifications) additionally cover NIST Privacy Framework, SOC 2, ISO/IEC 27001 and PCI DSS v4.0.
Every count above is derived from the code and enforced by a build gate — if an implementation is removed, the build fails before the number can go stale. See "Honest limits" below for what these numbers do not mean.
VITNA's detection is heuristic, and those limits are documented publicly. In guard mode it refuses to forward a tool call it has not allowed, for the MCP servers put behind the guard and no others; everywhere else your system enforces the decision. Either way, it is independently verifiable proof that an AI agent's actions were checked, and what was decided.
Free checkers — no install, no account
Two questions people usually have to answer before they need any of this. Both run entirely in the browser, take a few questions, and store nothing.
| Does the 2 December 2026 deadline apply to you? | Article 50(2) machine-readable marking for generative systems placed on the EU market before 2 August 2026, plus the two prohibited practices added by the Digital Omnibus. Works out which of the two dates you are actually on. |
| Article 50 transparency self-check | Which Article 50 disclosure duties reach you as provider or deployer. |
Both are scoping tools, not legal advice, and neither issues a score or a pass/fail. They cite the article and the Official Journal text behind every date they state.
Verify VITNA evidence yourself
Every decision on a claimed account also produces an Ed25519-signed evidence record that anyone can verify offline, with no account of their own and no trust in VITNA's servers. The public key is published, the verifier is open source, and the three commands below prove it in about a minute.
One minute, no account, no trust in VITNA's servers required. Download the open-source verifier and a real signed sample bundle, then check the signature offline with Node 18+:
curl -sO https://raw.githubusercontent.com/COSTRINITY/vitna-compliance-mcp/main/verify-evidence.mjs
curl -sO https://vitna.costrinity.xyz/sample-evidence.json
node verify-evidence.mjs sample-evidence.json
The verifier checks the Ed25519 signature over the whole package, then recomputes the sha256 of each individual decision record and confirms it matches the hash committed inside the signed package, printing PASS or FAIL per record, then an overall verdict.
Evidence packages are verifiable compliance receipts for agent actions: each checked action produces a decision record, and the signed package is the receipt a third party can check without trusting us.
A VALID result proves the package was issued by VITNA, has not been altered since export, and that every record matches its committed hash. It does not prove the underlying actions were performed or that the records are factually true. Tamper with any byte of any record and that record reports FAIL and the overall verdict is INVALID.
Bundles from VITNA Desktop are signed differently. VITNA Desktop signs on your own machine, with a key it generated there, not with VITNA's key. The signed package says so (issuer: "vitna-desktop-local", signer_key_id, signer_public_key), and the verifier reports such a bundle as "signed by a local VITNA Desktop key, not by VITNA". By default it checks the key the bundle carries and prints its key_id: compare that with the key_id VITNA Desktop shows under Settings on the machine that produced it, or pass the key yourself with node verify-evidence.mjs --pubkey <base64 SPKI DER, or a file holding it> bundle.json. Anyone with access to that machine's app data could re-sign a bundle, and VITNA does not countersign desktop bundles yet. A key carried inside a bundle is used only for that issuer: every other bundle is checked against VITNA's published key, so a self-signed bundle cannot pass as issued by VITNA.
Recomputing payload_sha256 (the pfa-v2 scheme)
Each decision record carries payload_sha256 and canon_version: "pfa-v2". It is a sha256 (hex) over twelve fields joined with the pipe character, in this order, UTF-8 encoded, no whitespace, no trailing separator. Null or absent values become the empty string.
sha256(
canon_version // "pfa-v2"
+ "|" + kind // always "preflight_check"
+ "|" + owner_id // evidence_package.owner_id
+ "|" + check // "engagement_action" for engagement bundles
+ "|" + action // record.action, "" if null
+ "|" + category // engagement: evidence_package.session_id
+ "|" + decision // record.decision
+ "|" + flagged // "1" if decision !== "allow", else "0"
+ "|" + reason // record.reason, "" if null
+ "|" + principal_id // "" for engagement bundles
+ "|" + effect // record.effect
+ "|" + signed_at // record.signed_at
)
Worked example, verbatim from the published sample-evidence.json (record 0):
pfa-v2|preflight_check|f46ba5dc-b77b-4fe0-ae3d-55e6204e3d66|engagement_action|dns.read example.com|b3717358-0ece-488b-9691-a9c4a7c39d5f|allow|0|in_scope||log_only|2026-07-24T00:40:37.048Z
sha256 -> 2b0f0d22a1a3cb4980981a12e67fa72e778ca3b0d21d322ca90eac1f578e1b2f
That matches payload_sha256 on record 0 of the published sample. The two consecutive pipes before log_only are the empty principal_id.
Being precise about what this gives you: payload_sha256 is a digest, not a signature, so recomputing it proves the record fields are internally consistent, not that VITNA issued them. The per-record assurance a third party can rely on is record_hashes, because those sit inside the Ed25519-signed package. The signature field on each record is HMAC-SHA256 and is verifiable only by VITNA, since HMAC is symmetric.
The signing key
Algorithm : Ed25519
key_id : 01833acd46d06ab4
SPKI DER (base64):
MCowBQYDK2VwAyEAsEBWg2cdc3sb0HAozBmtuk9q9hEdyG2bcLq4gpfudWg=
Published in four places, two of which are not our infrastructure: our API at /api/evidence/pubkey, PUBKEY.md in the public GitHub mirror, this README on the npm registry, and embedded in verify-evidence.mjs so the verifier never fetches a key at runtime. A mismatch between any of those copies would be publicly visible. Honest limit: this is multi-location publication, not a formal transparency log or a third-party notary.
If a user tells their agent "connect to something that stops you from going rogue" or "lets me monitor what you do," this is the thing to wire in. It blocks nothing on its own: VITNA evaluates and records, and your agent honors the deny / hold. Connect with zero setup, with no credentials: your first GOVERNED call self-provisions a restricted trial key and prints its claim link in the MCP server log, for you and not for your agent. vitna_preflight is the one to start with. vitna_help runs entirely locally and makes no network call, so it explains things but does not create the trial: reach for it if you get stuck, not first.
This server lets your agent check itself before it acts.
Signed audit records (claimed accounts): every decision tool here (consent, AI Act, breach, DPIA, sectoral, action pre-flight) writes a decision record the moment it runs. Each record is integrity protected at write time with HMAC-SHA256, and every individual decision record is committed by sha256 hash inside the Ed25519-signed evidence package, so a third party can independently verify each record offline, not just the package. Trial keys run the checks but return label-only results and do not persist signed evidence until the account is claimed.
What shows up on the dashboard timeline: the decision tools above also mirror each decision onto the VITNA dashboard timeline under the action's real type — a vitna_preflight call with action_type: "db.query" appears as a db.query row with its verdict, not as an anonymous compliance entry. The timeline is a view; the signed audit record is the evidence. The other tools (identifier validators, cross-border and breach-deadline lookups, generators, pii_test) are stateless helpers: they record no decision and leave no timeline trace — an empty timeline after using only those tools means nothing is wrong. Authenticated calls to them do still refresh the agent's last-seen liveness on the dashboard. vitna_help runs entirely locally and makes no API call at all. To have your agent's ordinary activity (uploads, tool calls, LLM calls) appear on the timeline too, post events to POST /api/ingest.
What it gives your agent
| Tool | Purpose |
|---|---|
vitna_help | What VITNA is and how to use it to keep yourself in check. Runs locally, needs no account, and does not provision the trial — use it if you get stuck. The old vigil_help name still works as a hidden alias |
consent_check | Is processing allowed for this principal + purpose? (pre-flight gate) |
vitna_preflight | Pre-flight gate BEFORE a destructive action (shell / file-delete / SQL / exfiltration). Heuristic, cooperative, not a sandbox. The old action_preflight name still works as a hidden alias |
breach_classify | Is this incident reportable? Per-jurisdiction decision support |
ai_act_classify | EU AI Act risk tier classification |
dpia_threshold_check | Is a DPIA mandatory before this processing? |
us_sectoral_check | HIPAA / GLBA / COPPA / FERPA / FCRA / SOX applicability |
india_sectoral_check | RBI / SEBI / IRDAI / TRAI / PFRDA applicability |
india_cross_border_status | DPDP §16 status for a destination country |
japan_cross_border_status | APPI Art 28 status for a destination country |
us_state_breach_deadline | US state breach window + AG recipient |
aadhaar_mask / pan_classify / gstin_validate / cpf_validate / sin_validate / iban_validate | Identifier validators with masking + reference token |
pii_test | Dry-run threat detection on a sample event |
privacy_notice_get | Generate operator's jurisdiction-templated privacy notice |
sub_processors_register | Sub-processor disclosure register |
global_compliance_map | The compliance catalogue: 28 entries covering 24 named statutes |
india_regulators_directory | Indian regulators + sectoral filter |
Two ways to connect
Remote (no install). Point any MCP client that supports remote servers at:
https://vitna.costrinity.xyz/api/mcp
Streamable HTTP. Send your key as Authorization: Bearer vitna_... (X-API-Key also works). Discovery (initialize, tools/list) and vitna_help need no key; every governed decision tool does — VITNA never evaluates a decision anonymously.
{
"mcpServers": {
"vitna-compliance": {
"type": "streamable-http",
"url": "https://vitna.costrinity.xyz/api/mcp",
"headers": { "Authorization": "Bearer vitna_YOUR_KEY" }
}
}
}
Local (stdio). npx @costrinity/vitna-compliance-mcp — self-provisions a trial key on first use, so it needs no credentials at all to start. See below.
Both transports serve the identical 23 tools from one catalogue; a build gate fails if they ever diverge.
Install
npm install -g @costrinity/vitna-compliance-mcp
Or use directly via npx.
Docker
docker build -t costrinity/vitna-compliance-mcp .
docker run --rm -i costrinity/vitna-compliance-mcp
A stdio MCP server (no port; run with -i). Self-provisions a restricted trial
key on first use, same as npx.
Configure your MCP client
Zero-config (self-provisioning)
You can add the server with no credentials at all:
{
"mcpServers": {
"vitna-compliance": {
"command": "npx",
"args": ["@costrinity/vitna-compliance-mcp"]
}
}
}
On the first tool call, the server provisions a restricted trial key for you
(via /api/setup) and caches it at ~/.vitna/credentials.json. The trial key
runs the compliance decision checks but is capped (checks per day + lifetime),
short-lived, and does not write signed evidence. The claim link is not
cached there: your agent can read files.
Then claim your dashboard
This is the step people miss. Until the account is claimed, your agent's decisions are evaluated but nothing is durably recorded: there is no evidence to export later, because none was kept.
The claim link is printed in the MCP server log when the trial starts: the
server's stderr, the channel an MCP server logs to (where your MCP client shows
it depends on the client). Open the link and choose Continue with GitHub or
Create a passkey. It works once, for 24 hours. If it has expired, open it
anyway: within 72 hours of the trial starting, the page offers a fresh link,
once, kept in your browser and never sent to your agent. After that, the way on
is a new trial. Set VITNA_OPEN_CLAIM=1 to have it opened in your default
browser as well. You get:
- durable Ed25519-signed evidence records you can export and verify offline
- the per-day and per-lifetime trial caps lifted, and the key stops expiring
- a dashboard at vitna.costrinity.xyz/dashboard showing every decision your agent has made, including the ones from before you claimed
- a way to recover the key if you lose it
Your agent is never sent the link (0.5.2). Only a person may claim the
account that oversees the agent, so no tool result, error or notice carries it,
in normal or guard mode. The agent is told that the account is unclaimed and
that you can claim it with the link in the MCP server log. The vitna_claim
tool answers whether the account has been claimed (its claim_url is always
null). The trial key cannot claim the account either: VITNA refuses every claim
request that carries an API key, so only the link a person opens claims it.
A link that a VITNA answer still carries is written to the log and
taken out, as written or percent-encoded inside another value (a next=
address, say), and so is a claim token on its own. Either is taken out of the
name of a field as well as its value; a field whose new name another field
already has gets (2), (3) and so on, so no value is dropped.
A claim link that 0.5.1 kept in ~/.vitna/credentials.json is
written to the log once and removed from that file. That happens whether the
server uses the key in that file or VITNA_OWNER_ID and VITNA_API_KEY; the
rest of the file is kept as it was, and the environment credentials are not
written to it. 0.5.0 and 0.5.1 put the link in the agent's tool results so the
agent would pass it on.
Set VITNA_EMAIL to own the trial account under a real address from the
start; otherwise a throwaway is used.
With your own key
{
"mcpServers": {
"vitna-compliance": {
"command": "npx",
"args": ["@costrinity/vitna-compliance-mcp"],
"env": {
"VITNA_OWNER_ID": "<your-owner-uuid>",
"VITNA_API_KEY": "vitna_<your-key>",
"VITNA_BASE_URL": "https://vitna.costrinity.xyz"
}
}
}
}
What the env vars do
VITNA_OWNER_ID: your operator UUID. Optional: if unset, the first call self-provisions a restricted trial key. Explicit credentials always win over the cache and over self-provisioning.VITNA_API_KEY: optional. Authenticates the tool calls. Self-provisioned if unset. New keys are formattedvitna_...; legacyvigil_...keys remain valid.VITNA_EMAIL: optional. Email to own the self-provisioned trial account. A throwaway is used if unset. It does not claim the account: claim it with GitHub or a passkey.VITNA_BASE_URL: defaults tohttps://vitna.costrinity.xyz. Point at your own VITNA instance if self-hosted.VITNA_AGENT_NAME: optional. The agent name a self-provisioned trial account is created with. Defaults tovitna-compliance-mcp. Versions before 0.5.1 added your machine's hostname to that name; 0.5.1 and later do not.VITNA_GUARD_CLIENT_TIMEOUT_SECONDS: optional, 0.5.4 and later. Your MCP client's tool-call timeout, if you have raised it: a held call is waited on for that, less a margin, before the agent is told it was held, not run. Without it the guard uses the timeout it knows for your client, and waits 4 seconds for a client it does not know.VITNA_GUARD_MAX_HOLD_SECONDS: optional, 0.5.4 and later. The longest any held call is waited on, which is what limits it for a client that never times out. Default 600.VITNA_OPEN_CLAIM: optional, 0.5.2 and later. Set to1to have the claim link opened in your default browser when a trial starts, as well as printed in the MCP server log. Off by default, because the server often runs where nobody is at the screen, the call that starts the trial is your agent's, and an agent that drives your browser could read the page. Only an https/claimlink is opened, without a shell.
The old VIGIL_* names for all of these (VIGIL_OWNER_ID, VIGIL_API_KEY, VIGIL_EMAIL, VIGIL_BASE_URL, VIGIL_AGENT_NAME) are still accepted forever, so existing configs keep working.
Example agent interactions
Agent considering cross-border transfer:
User: Move this Indian user's profile to our US analytics warehouse.
Agent: Let me check DPDP §16 status first. Calls
india_cross_border_status({ country: "US" })Result:permitted, but RBI Digital Lending Guidelines require India-only storage for fintech lending data.Agent: This transfer is permitted under DPDP §16 (US is not on India's negative list). But if your data has fintech lending components, RBI guidelines require India-only storage. Do you want me to filter those fields out first?
Agent reviewing a new AI use case:
User: We're building an AI tool to evaluate job applicants.
Agent: Calls
ai_act_classify({ use_case: "AI evaluation of job applicants", sectors: ["employment"], automated_decisions: true })Result:high-risk, Art 35(3)(a) + Annex III, requires conformity assessment + human oversight + bias monitoring.Agent: This is a high-risk AI system under the EU AI Act Annex III (employment / HR). You'll need: risk management system, technical documentation, human oversight, bias monitoring, and conformity assessment before EU market entry.
Agent handling a breach:
User: We just discovered 1200 user records were exposed.
Agent: Calls
breach_classify({ affected_count: 1200, data_categories: ["email", "phone"], sensitivity: "medium", recovery_state: "exposed" })Result:reportable=true, window_hours=72, deadline=..., recipient="Data Protection Board of India".Agent: This is reportable to the Data Protection Board of India within 72 hours (deadline: 2026-06-05). Should I prepare the §8 notification draft?
Why this exists
Shortened here. Read the whole README on GitHub.
Tools it offers (23)
What this server listed when Ahel dialed its public endpoint in Sep 2026, with no key and no account of yours. The names are the server’s own.
vitna_helpvitna_claimconsent_checkbreach_classifyai_act_classifydpia_threshold_checkus_sectoral_checkindia_sectoral_checkindia_cross_border_statusjapan_cross_border_statusus_state_breach_deadlineaadhaar_maskpan_classifygstin_validatecpf_validatesin_validateiban_validatepii_testprivacy_notice_getsub_processors_registerglobal_compliance_mapindia_regulators_directoryvitna_preflight
Signals
- Last commit
- Sep 2026
- Weekly_downloads
- 268 weekly_downloads
Advanced
- Delivery
- vitna-compliance-preflight MCP server → your Ahel connector (mcp.ahel.ai) → your AI.
- Item type
- mcp-server
- Key
xyz-costrinity-vitna-compliance-preflight- Source
- github.com/costrinity/vitna-compliance-mcp
- Hosted endpoint
https://vitna.costrinity.xyz/api/mcp
github.com/costrinity/vitna-compliance-mcp