Install
$ agentstack add mcp-drandrewlaw-agentgate Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Destructive filesystem operation.
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
agentgate
The missing safety layer for AI agents.
[](https://www.npmjs.com/package/agentgate) [](https://opensource.org/licenses/MIT) [](https://www.typescriptlang.org/)
Your agent can call tools. But should it?
agentgate gives you declarative permission rules, lifecycle hooks, and tool execution control for any AI agent — extracted from battle-tested patterns in production AI systems serving millions of users.
Your Agent (LangChain / CrewAI / OpenAI / Custom)
│
┌────▼─────────────────┐
│ agentgate │
│ permissions + hooks │
└────┬─────────────────┘
│
Actual Tools (filesystem, bash, APIs, databases)
Why agentgate?
Every AI agent framework gives you tools. None gives you governance.
| Feature | agentgate | LangChain | CrewAI | OpenAI Agents | ShipAny | |---------|:---------:|:---------:|:------:|:-------------:|:-------:| | Permission DSL (allow/deny/ask) | Yes | No | No | No | No | | Lifecycle hooks (pre/post/error) | Yes | No | No | No | No | | Provider-agnostic | Yes | Yes | Yes | No | No | | MCP support | Yes | No | No | No | Yes | | Type-safe tools (Zod) | Yes | Partial | No | Partial | Yes | | Zero runtime deps | Yes | No | No | No | No |
Install
npm install agentgate zod
Quick Start — 5 lines to safety
import { agentgate, buildTool, matchPattern } from 'agentgate'
import { z } from 'zod'
const Bash = buildTool({
name: 'Bash',
inputSchema: z.object({ command: z.string() }),
call: async (input) => ({ data: `ran: ${input.command}` }),
preparePermissionMatcher: (input) => (pattern) => matchPattern(pattern, input.command),
})
const gate = agentgate({
permissions: {
mode: 'default',
rules: [
{ allow: 'Bash(git *)' }, // ✅ Allow git commands
{ deny: 'Bash(rm *)' }, // ❌ Block rm commands
],
},
tools: [Bash],
})
await gate.execute('Bash', { command: 'git status' }) // ✅ allowed
await gate.execute('Bash', { command: 'rm -rf /' }) // ❌ denied
Core Concepts
1. Permission Engine
Declarative rules control what your agent can do. Rules use a compact DSL:
import { createPermissionEngine } from 'agentgate'
const permissions = createPermissionEngine({
mode: 'default', // 'strict' | 'default' | 'permissive' | 'bypass'
rules: [
{ allow: 'Read' }, // Allow entire tool
{ allow: 'Bash(git *)' }, // Allow by input pattern
{ deny: 'Bash(rm *)' }, // Deny by input pattern
{ ask: 'Write' }, // Require approval
{ allow: 'mcp__github__*' }, // Allow all MCP server tools
{ deny: 'mcp__filesystem__write_*' }, // Deny MCP write tools
],
})
Permission modes:
strict— Deny by default. Only explicitly allowed tools run.default— Allow reads, ask for writes/destructive actions.permissive— Allow unless explicitly denied.bypass— Allow everything (testing only).
2. Lifecycle Hooks
Hooks fire before/after tool execution for logging, validation, and control:
import { agentgate } from 'agentgate'
const gate = agentgate({
hooks: {
preToolUse: [{
matcher: 'Write', // Only for Write tool
hooks: [{
type: 'callback',
fn: async (input) => {
const { path } = input.toolInput as { path: string }
if (path.startsWith('/etc/')) {
return { continue: false, decision: 'block', reason: 'Cannot write to /etc/' }
}
return { continue: true, decision: 'approve' }
},
}],
}],
postToolUse: [{
hooks: [{
type: 'http',
url: 'https://audit.company.com/log', // Webhook for audit trail
}],
}],
},
})
Hook types:
callback— In-process async function (fastest)command— Shell command (stdin: JSON input, exit code 0=approve, 2=block)http— HTTP POST webhook (JSON request/response)
Hook events: preToolUse, postToolUse, toolError, permissionDenied, sessionStart, sessionEnd, beforeCompact, afterCompact, configChange, custom
3. Type-Safe Tools
Build tools with Zod schemas and built-in safety classification:
import { buildTool } from 'agentgate'
import { z } from 'zod'
const DatabaseQuery = buildTool({
name: 'DatabaseQuery',
inputSchema: z.object({
query: z.string(),
database: z.enum(['production', 'staging', 'dev']),
}),
// Safety classification
isReadOnly: (input) => /^\s*SELECT\b/i.test(input.query),
isDestructive: (input) => /\b(DROP|TRUNCATE)\b/i.test(input.query),
// Tool-specific permission check
checkPermissions: async (input) => {
if (input.database === 'production' && !/^\s*SELECT\b/i.test(input.query)) {
return { behavior: 'deny', message: 'Only SELECT on production' }
}
return { behavior: 'allow', updatedInput: input }
},
call: async (input) => {
const result = await db.query(input.query)
return { data: result }
},
})
4. Tool Executor
The executor wires permissions + hooks + tools into a single lifecycle:
import { createToolExecutor, createPermissionEngine, createHookEngine } from 'agentgate'
const executor = createToolExecutor({
permissions: createPermissionEngine({ mode: 'default', rules: [...] }),
hooks: createHookEngine({ preToolUse: [...] }),
tools: [ReadTool, WriteTool, BashTool],
maxConcurrency: 10,
// Handle 'ask' permission decisions interactively
onPermissionRequest: async (toolName, message, input) => {
const approved = await promptUser(`Allow ${toolName}? ${message}`)
return approved
? { behavior: 'allow', updatedInput: input }
: { behavior: 'deny', message: 'User rejected' }
},
})
const result = await executor.execute('Bash', { command: 'git push' })
// result.status: 'allowed' | 'denied' | 'error' | 'blocked_by_hook'
5. MCP Integration (Optional)
Connect to MCP servers and govern their tools with the same permission system:
import { createPermissionEngine } from 'agentgate'
import { createMCPClient } from 'agentgate/mcp'
const mcp = createMCPClient({
servers: {
filesystem: {
type: 'stdio',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
},
},
})
await mcp.connect()
const tools = mcp.discoverTools()
// tools: [{ name: 'mcp__filesystem__read_file', ... }, ...]
// Same permission rules work for MCP tools
const perms = createPermissionEngine({
rules: [
{ allow: 'mcp__filesystem__read_file' },
{ deny: 'mcp__filesystem__write_file' },
],
})
API Reference
Main Exports
| Export | Description | |--------|------------| | agentgate(config) | One-liner: creates a configured ToolExecutor | | buildTool(def) | Create a type-safe tool with defaults | | createPermissionEngine(config) | Create a permission engine | | createHookEngine(config) | Create a hook engine | | createToolExecutor(config) | Create an executor (permissions + hooks + tools) | | defineConfig(config) | Type-safe config helper | | createMCPClient(config) | Create an MCP client (from agentgate/mcp) |
Permission Rule DSL
"ToolName" → matches entire tool
"ToolName(pattern)" → matches tool + input pattern
"mcp__server__tool" → matches specific MCP tool
"mcp__server__*" → matches all tools from MCP server
"mcp__server" → matches all tools from MCP server
Patterns support wildcards:
"git *" → prefix match
"*.ts" → suffix match
"src/*.ts" → prefix + suffix
"*" → matches everything
Architecture
agentgate is designed as middleware, not a framework. It sits between your agent and its tools:
- Agent requests tool call → agentgate receives
(toolName, input) - Permission engine evaluates rules →
allow,deny, orask - PreToolUse hooks fire → can approve, block, or modify input
- Tool executes with validated input
- PostToolUse hooks fire → logging, audit, side effects
- Result returns to agent
This works with any LLM provider and any agent framework because agentgate only cares about the tool layer, not the model layer.
Dependencies
- Runtime: Zero. No dependencies.
- Peer:
zod>= 3.23 (you likely already have it) - Optional peer:
@modelcontextprotocol/sdk>= 1.0 (only for MCP module)
Examples
See the [examples/](./examples) directory — all runnable with npx tsx examples/:
| # | Example | Use Case | |---|---------|----------| | 01 | [Basic Permissions](./examples/01-basic-permissions.ts) | Quick start with allow/deny/ask rules | | 02 | [Hooks and Lifecycle](./examples/02-hooks-and-lifecycle.ts) | Pre/post hooks for logging and validation | | 03 | [Custom Tools](./examples/03-custom-tools.ts) | Type-safe tools with Zod schemas | | 04 | [MCP Integration](./examples/04-mcp-integration.ts) | Govern MCP server tools | | 05 | [Infrastructure Safety](./examples/05-infrastructure-safety.ts) | Prevent agents from destroying your infra | | 06 | [Database Safety](./examples/06-database-safety.ts) | Tiered DB access (prod read-only, staging read-write) | | 07 | [Audit Trail](./examples/07-audit-trail.ts) | SOC2/HIPAA/GDPR compliance logging with PII detection | | 08 | [Human-in-the-Loop](./examples/08-human-in-the-loop.ts) | Interactive approval for risky actions | | 09 | [Input Validation](./examples/09-input-validation.ts) | SQL injection blocking, PII redaction, email safety | | 10 | [Rate Limiting](./examples/10-rate-limiting.ts) | Per-tool limits, budget caps, cost tracking |
Contributing
Contributions welcome! Please open an issue first to discuss what you'd like to change.
git clone https://github.com/agentgate/agentgate
cd agentgate
npm install
npm test
License
[MIT](./LICENSE)
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: drandrewlaw
- Source: drandrewlaw/agentgate
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.