ACAgentic Craft

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

Before you start

You will leave with

  • 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)

ThreatMitigation in HazelJS
Over-broad toolsRegister fewer tools; Skillgate include / deny destructive
Prompt injection via tool outputGuardrails on tool I/O; truncate/untrusted content policies
Credential exfiltrationHost-held secrets; never in DNA or model context
Irreversible writesrequiresApproval + durableSuspend + PolicyEngine
Confused deputy via MCPAuth 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

typescript
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

typescript
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

Sources

Continue learning