@agentsid/proxy
v0.1.0
Published
MAP (Model Context Authorization Protocol) — enforcement proxy for MCP servers
Maintainers
Readme
@agentsid/proxy
MAP enforcement proxy for MCP servers.
MAP — Model Context Authorization Protocol — is an open policy format for controlling what AI agents are allowed to do.
@agentsid/proxysits between your AI client (Claude Desktop, Cursor, etc.) and any MCP server, evaluating every tool call against a MAP policy before it reaches the upstream server.
How it works
AI Client ──stdin/stdout──▶ agentsid-proxy ──stdin/stdout──▶ MCP Server
│
MAP Policy
Evaluator
│
Signed Audit LogEvery tools/call is intercepted. The proxy evaluates the call against your policy, then either:
- allows it (forwards to the upstream server)
- denies it (returns a JSON-RPC error
-32000) - gates it (returns a non-blocking approval request — human must approve before the call proceeds)
Non-tool-call methods (initialize, tools/list, etc.) pass through unchanged.
Install
npm install -g @agentsid/proxy
# or use without installing:
npx @agentsid/proxy run --policy ./policy.json -- npx @modelcontextprotocol/server-githubQuick start
1. Write a policy (policy.json):
{
"version": "1.0",
"rules": [
{
"tools": ["github.push_files"],
"action": "deny"
},
{
"tools": ["github.*"],
"action": "allow",
"conditions": {
"branch": { "enum": ["main", "develop"] }
}
},
{
"tools": ["filesystem.write_file"],
"action": "allow",
"conditions": {
"path": { "pattern": "^/home/user/projects/" }
}
},
{
"tools": ["shell.*"],
"action": "deny"
}
]
}2. Wrap your MCP server:
agentsid-proxy run \
--policy ./policy.json \
-- npx @modelcontextprotocol/server-github3. Point Claude Desktop at the proxy (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"github-guarded": {
"command": "agentsid-proxy",
"args": [
"run",
"--policy", "/path/to/policy.json",
"--",
"npx", "@modelcontextprotocol/server-github"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "<your-token>"
}
}
}
}Policy reference
Structure
{
"version": "1.0",
"expiresAt": "2026-12-31T00:00:00Z",
"rules": [ ...PermissionRule[] ]
}PermissionRule
| Field | Type | Description |
|-------|------|-------------|
| tools | string[] | Tool patterns to match (glob, negation, exact) |
| action | "allow" \| "deny" | Decision when rule matches |
| conditions | Record<string, ConditionDef> | Argument constraints (optional) |
| constraints | Constraint[] | Runtime constraints (optional) |
Tool patterns
| Pattern | Matches |
|---------|---------|
| ** | Any tool |
| github.* | All tools in the github namespace |
| github.push_files | Exact match |
| ["**", "!shell.*"] | Any tool except shell.* |
Rules are evaluated first-match wins. Default is deny.
Conditions (argument validation)
"conditions": {
"branch": { "enum": ["main", "develop"] },
"path": { "pattern": "^/home/user/" },
"query": { "maxLength": 500 },
"content": { "notContains": ["DROP TABLE", "rm -rf"] }
}| Condition | Description |
|-----------|-------------|
| pattern | Regex that the argument value must match |
| enum | Allowlist of permitted values |
| maxLength | Maximum string length |
| minLength | Minimum string length |
| notContains | Forbidden substrings |
Constraints (runtime enforcement)
Rate limit
{ "type": "rateLimit", "max": 10, "windowSeconds": 60 }Schedule
{ "type": "schedule", "hoursUTC": [9, 17], "daysOfWeek": [1, 2, 3, 4, 5] }hoursUTC: [startHour, endHour] (exclusive). daysOfWeek: ISO day numbers (1=Monday, 7=Sunday).
Approval gate
{
"type": "approvalGate",
"approvers": ["principal"],
"timeoutSeconds": 300,
"timeoutAction": "deny",
"message": "Production push requires approval"
}When a gate is triggered the tool call returns immediately with a gate ID. The agent can continue other work. Approve or deny from another terminal:
agentsid-proxy approve <gateId>
agentsid-proxy deny <gateId>Session limit
{ "type": "sessionLimit", "max": 50 }Cooldown
{ "type": "cooldown", "seconds": 30 }Policy loading precedence
--policy <path>flag- AgentsID cloud (
--api-key+--agent-id, orAGENTSID_API_KEY+AGENTSID_AGENT_IDenv vars) .agentsid/policy.jsonin the working directory- Deny-all (no policy = nothing gets through)
Cloud mode (AgentsID)
Store and manage policies centrally:
agentsid-proxy run \
--api-key $AGENTSID_API_KEY \
--agent-id my-coding-agent \
-- npx @modelcontextprotocol/server-filesystem /workspaceCloud mode also syncs audit entries to the AgentsID dashboard for centralized visibility.
Audit log
Every tool call produces a signed, hash-chained audit entry:
{
"entryId": "uuid",
"timestamp": "2026-03-29T12:00:00.000Z",
"agentId": "my-coding-agent",
"tool": "filesystem.write_file",
"arguments": { "path": "/home/user/projects/app.ts", "content": "..." },
"decision": "allow",
"matchedRule": 1,
"reason": "rule 1 matched",
"prevEntryHash": "sha256:abc123...",
"entryHash": "sha256:def456...",
"signature": "ed25519:..."
}- Arguments containing secrets are redacted before logging (keys:
password,token,secret,apiKey,credential,private; values matching OpenAI/GitHub/Slack/AWS patterns) - Each entry includes the previous entry's hash — tamper one entry and the whole chain fails verification
- Signatures use Ed25519 with an ephemeral key per session (or a persistent key for cloud mode)
Programmatic usage
import { evaluate, AuditWriter, generateSigningKey } from "@agentsid/proxy";
import type { MapPolicy, EvaluationContext } from "@agentsid/proxy";
const policy: MapPolicy = {
version: "1.0",
rules: [{ tools: ["github.*"], action: "allow" }],
};
const ctx: EvaluationContext = {
tool: "github.push_files",
arguments: { owner: "myorg", repo: "myrepo", branch: "main" },
agentId: "my-agent",
sessionId: "session-123",
requestId: "req-456",
timestamp: new Date(),
};
const result = evaluate(policy, ctx);
console.log(result.decision); // "allow"
const key = generateSigningKey();
const writer = new AuditWriter(key);
const entry = writer.write(ctx, result);
console.log(entry.entryHash); // "sha256:..."CLI reference
agentsid-proxy run [options] -- <upstream-command...>
Options:
-p, --policy <path> Path to MAP policy JSON file
-k, --api-key <key> AgentsID API key (or AGENTSID_API_KEY)
-a, --agent-id <id> Agent ID (or AGENTSID_AGENT_ID)
--api-url <url> AgentsID API base URL (default: https://api.agentsid.dev)
--log-level <level> silent|error|warn|info|debug (default: info)
agentsid-proxy approve <gateId> [--by <identity>]
agentsid-proxy deny <gateId> [--by <identity>]Development
npm install
npm run typecheck # TypeScript strict check
npm test # All tests (unit + conformance)
npm run test:unit # Unit tests only
npm run test:conformance # MAP spec conformance suite
npm run build # Compile to dist/Test coverage target: 80% lines / 75% branches.
MAP Specification
The full AgentsID Permission Specification v1.0 — which defines the policy format, evaluation algorithm, and conformance requirements — is published at:
License
MIT © AgentsID
