actionfence
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Warn
- process.env — Environment variable access in examples/express-api/src/index.ts
- process.env — Environment variable access in examples/mcp-server/src/index.ts
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Embeddable AI action firewall for MCP servers and APIs
ActionFence
AI Action Firewall for MCP servers and APIs.
One line of code. Signed receipts. Simulation mode.
Why ActionFence?
AI agents can now book flights, send emails, and delete records in your system — often without you knowing until the invoice arrives. ActionFence lets you define exactly what they're allowed to do, and proves every decision with a signed receipt.
It sits in front of your MCP tools or HTTP routes and decides whether an incoming agent action is allowed before your real handler runs.
It gives you:
- Policy enforcement from
guard-policy.json - Identity tiers:
anonymous,token,verified - Built-in verified JWT support via JWKS
- Capability scope checks from JWT
capabilities - Per-action spend caps plus session/day spend limits
- Request and transaction rate limiting
- Signed, hash-chained receipts in SQLite
- Simulation mode for dry-run previews
Install
npm install actionfence
Quick Start
MCP Server
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { withGuard } from 'actionfence';
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
withGuard(server, {
policy: './guard-policy.json',
identityReaderOptions: {
jwksUri: 'https://issuer.example/.well-known/jwks.json',
issuer: 'https://issuer.example',
audience: 'bookflight-mcp',
},
});
server.registerTool('search_flights', {}, async () => {
return { content: [{ type: 'text', text: 'results...' }] };
});
Express / Fastify
import express from 'express';
import { guard } from 'actionfence';
const app = express();
app.use(express.json());
app.use(
guard({
policy: './guard-policy.json',
identityReaderOptions: {
jwksUri: 'https://issuer.example/.well-known/jwks.json',
issuer: 'https://issuer.example',
audience: 'bookflight-api',
},
actionResolver: (toolName) => {
if (/^GET \/bookings\/[^/]+$/.test(toolName)) {
return 'GET /bookings/:id';
}
return toolName;
},
spendExtractor: (params) => {
const body = (params as { body?: { amount?: number } })?.body;
return body?.amount ?? null;
},
}),
);
CLI
npx actionfence init
npx actionfence validate guard-policy.json
npx actionfence simulate guard-policy.json --action book_flight --identity verified --spend 250
Using an AI Coding Assistant?
Copy this prompt into Claude, Cursor, Copilot, or any LLM and let it handle the setup:
Install and integrate the "actionfence" npm package into my current project. Read the full integration guide at https://raw.githubusercontent.com/saifeldeen911/actionfence/main/llms-full.txt then: install the package, create a guard-policy.json for my use case, and wire up the middleware.
Policy File
guard-policy.json defines what agents can do in your system.
{
"$schema": "https://raw.githubusercontent.com/saifeldeen911/actionfence/main/schemas/guard-policy.schema.json",
"service": "BookFlight.com",
"version": "1.0",
"default_rule": "deny",
"actions": {
"search_flights": {
"allowed": true,
"identity": "any"
},
"book_flight": {
"allowed": true,
"identity": "verified",
"max_spend": 500,
"currency": "USD",
"requires_human_approval": true
},
"bulk_booking": {
"allowed": false
}
},
"rate_limits": {
"requests_per_minute": 30,
"transactions_per_day": 5
},
"spend_limits": {
"session_max": 1000,
"daily_max": 2500,
"currency": "USD"
},
"regulations": ["EU_AI_Act_Art50"]
}
Policy Reference
| Field | Type | Required | Notes |
|---|---|---|---|
service |
string |
Yes | Service name |
version |
string |
Yes | Policy version |
default_rule |
"allow" | "deny" |
No | Defaults to "deny" |
actions |
object |
Yes | Action rules keyed by action name |
rate_limits |
object |
No | Request and transaction limits |
spend_limits |
object |
No | Global session/day spend limits in major units |
regulations |
string[] |
No | Stored (persisted) in v0.1.0 but not enforced |
Action Rule Fields
| Field | Type | Default | Notes |
|---|---|---|---|
allowed |
boolean |
- | Required |
identity |
"any" | "token" | "verified" |
"any" |
Minimum identity tier |
max_spend |
number |
- | Per-invocation cap in major units |
currency |
string |
- | ISO 4217 currency code |
requires_human_approval |
boolean |
false |
In 0.1.0: flags the decision in the receipt and fires the onDecision callback so you can build your own approval flow. Built-in approval workflow is planned for a future release. |
Identity Tiers
| Tier | Meaning |
|---|---|
anonymous |
No credentials presented |
token |
Bearer token present but not signature-verified |
verified |
JWT passed JWKS verification |
Verified identity is built in when you configure identityReaderOptions.jwksUri and JWKS lookup succeeds from cache or the remote endpoint. If JWKS retrieval or network access fails, ActionFence may fall back to token identity; invalid signatures, wrong issuers or audiences, unknown kids, and other cryptographic verification failures stay anonymous or rejected.
Scope Enforcement
If a decoded or verified token includes a capabilities claim, ActionFence treats it as an exact allowlist of policy action names. A request that passes policy checks but is not listed in capabilities is blocked.
Simulation Mode
Simulation mode runs the full policy pipeline without executing the handler or storing a receipt.
MCP
withGuard(server, {
policy: './guard-policy.json',
simulate: true,
});
Express
app.use(
guard({
policy: './guard-policy.json',
simulate: true,
}),
);
CLI output
actionfence simulate guard-policy.json --action book_flight --identity verified --spend 250
SIMULATION - actionfence
Action: book_flight
Tool: book_flight
Identity: verified
Status: PASS
Spend: 250.00
Session total: 250.00
Daily total: 250.00
Human approval: required
Rate limit: 29/30 remaining
Action Receipts
Every enforced decision stores a signed receipt in SQLite.
receipt_id: a1b2c3d4-...
timestamp: 2026-05-07T14:02:11Z
agent_id: agt_7x9f2k...
action: book_flight
status: PASSED
payload_hash: 0x8f3a...
prev_hash: 0x7e2d...
receipt_sig: 0x4f9b...
Receipts are:
- Hash-chained
- HMAC-SHA256 signed
- Append-only
- Verifiable with
ReceiptStore.verifyChain()
Note: Receipts are stored in a local SQLite file (
.actionfence/receipts.db). This works perfectly for single-instance deployments. If you run multiple server instances, each will maintain its own receipt chain. PostgreSQL backend for multi-instance deployments is planned for v0.2.
Signing key resolution order:
options.secretACTIONFENCE_SECRET.actionfence/key
API Reference
withGuard(server, options)
const guardInstance = withGuard(server, {
policy: './guard-policy.json',
simulate: false,
silent: false,
secret: process.env.ACTIONFENCE_SECRET,
identityReaderOptions: {
jwksUri: 'https://issuer.example/.well-known/jwks.json',
issuer: 'https://issuer.example',
audience: 'bookflight-mcp',
},
actionResolver: (toolName, params) => toolName,
spendExtractor: (params) => null,
onDecision: (decision) => {},
watchPolicy: true,
});
guardInstance.dispose();
guard(options)
const middleware = guard({
policy: './guard-policy.json',
identityReaderOptions: {
jwksUri: 'https://issuer.example/.well-known/jwks.json',
},
});
GuardOptions
| Option | Type | Default | Notes |
|---|---|---|---|
policy |
string | GuardPolicy |
- | Required |
simulate |
boolean |
false |
Dry-run mode |
silent |
boolean |
false |
Suppress console output |
secret |
string |
- | HMAC secret override |
identityReaderOptions |
IdentityReaderOptions |
- | Built-in JWKS verification config |
identityReader |
IdentityReaderLike |
- | Full custom identity resolution override |
actionResolver |
(toolName, params) => string |
- | Map tool names to policy actions |
spendExtractor |
(params) => number | null |
- | Extract spend in major units |
transactionResolver |
(toolName, params, decision) => boolean |
- | Override transaction classification |
onDecision |
(decision) => void |
- | Metrics, logging, hooks |
watchPolicy |
boolean |
false |
Hot-reload file-backed policies |
IdentityReaderOptions
| Field | Type | Notes |
|---|---|---|
jwksUri |
string |
Remote JWKS endpoint |
issuer |
string | string[] |
Optional issuer check |
audience |
string | string[] |
Optional audience check |
0.1.0 Limits
- Capability checks are exact string matches only
- No APoP / LAS-WG adapters yet
- No wildcard scope patterns or path-policy DSL
requires_human_approvalflags the receipt and firesonDecision— no built-in approval workflow yet (use the callback to build your own)- SQLite receipt store is single-instance only — PostgreSQL backend coming in v0.2
- Money is major-unit only; mixed-currency accounting is out of scope for one policy
CLI Reference
actionfence init
actionfence init
actionfence init --service MyAPI
actionfence init --output ./policies/guard-policy.json
actionfence validate <path>
actionfence validate guard-policy.json
actionfence simulate <path>
actionfence simulate guard-policy.json --action search_flights
actionfence simulate guard-policy.json --action book_flight --identity verified --spend 250
Examples
Development
git clone https://github.com/saifeldeen911/actionfence.git
cd actionfence
npm install
npm run typecheck
npm run lint
npm test
npm run build
License
MIT (c) Saifeldeen
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found