Advanced~55 minHazelJS
Secure MCP Servers and Agent Tools
Threat-model HazelJS MCP and ToolRegistry surfaces: least tools, guardrails on I/O, Skillgate curation, PolicyEngine, and HITL—not model trust.
- Authors
- editorial-team
- Published
- Last reviewed
- Tool-using agent loop lesson completed
- Access to @hazeljs/mcp and guardrails docs
- Curate MCP/ToolRegistry surfaces without inventing an MCP allow-list API
- Wire GuardrailsModule with AgentModule for tool I/O hygiene
- Apply Skillgate include/deny and PolicyEngine for write classes
On this page
Goal
Treat every MCP server and @Tool as a permission boundary. The model proposes; the host executes. Secure the registry, not the prompt.
Comparison of integration styles: /compare/mcp-vs-skillgate-vs-direct-api.
Threat model (short)
| Threat | Mitigation in HazelJS |
|---|---|
| Over-broad tools | Register fewer tools; Skillgate include / deny destructive |
| Prompt injection via tool output | Guardrails on tool I/O; truncate/untrusted content policies |
| Credential exfiltration | Host-held secrets; never in DNA or model context |
| Irreversible writes | requiresApproval + durableSuspend + PolicyEngine |
| Confused deputy via MCP | Auth on MCP transport; least-privilege tool export |
There is no documented MCP-native allow-list API. Curation = what you put on ToolRegistry / Skillgate opt-in.
Step 1Curate the tool surface
import { ToolRegistry } from '@hazeljs/agent';
import { Skillgate } from '@hazeljs/skillgate';
const gate = Skillgate.fromOpenApi(spec, {
include: { tags: ['agent'] }, // opt-in, not “all operations”
// deny destructive/admin unless classify.allowDestructive / allowAdmin
});
const registry = new ToolRegistry();
gate.register(registry, 'api-concierge');
const report = gate.report(); // included / denied / warnings — review in CI
For MCP: export only the curated registry (createMcpServer({ registry }) / gate.toMcpServer). Do not mirror your entire REST surface.
Step 2Guardrails on agent + tool I/O
Import GuardrailsModule alongside AgentModule so tool inputs/outputs can be screened (PII redact, injection blocklists) per guardrails docs.
Configure deliberately: redactPIIByDefault, blockInjectionByDefault, blocklists. Guardrails complement—not replace—tool allow-lists.
Step 3PolicyEngine + HITL on writes
policyEngine: new PolicyEngine([
...defaultPiiMaskPolicies(),
{
id: 'writes-need-approval',
tool: 'processRefund',
effect: 'require_approval',
priority: 20,
},
]),
Pair with /guides/add-human-approval-without-breaking-the-run.
Step 4Observation hygiene
Cap tool-result size; strip HTML/scripts; never echo secrets into timelines or Slack approval payloads. Lesson: /learn/agentic-development/context-windows-as-scarce-resources.
Step 5Verify
-
gate.report()reviewed; no surprise admin tools - MCP server exports read-mostly by default
- GuardrailsModule imported in the same app as AgentModule
- Write tools gated; describeAgent forbidden-tool cases pass
- OWASP LLM Top 10 reviewed for your threat model