Inspiration
Most MCP servers hand an LLM a tool, and that's it. Calling delete_x has the same friction as calling list_x. With Alexa+ about to let agents act on real accounts, real messages, and real smart-home devices, that felt like the wrong default. Given my interest in AI security, I wanted to buildwhat'ss usually missing: a server that knows which of its own tools are dangerous.
What it does
Guardian MCP is a self-hosted MCP server (spec 2025-11-25) that tags every tool with a risk tier: safe, moderate, or high. Safe and moderate tools run immediately. High-risk tools (deleting a reminder, sending a message, unlocking a smart lock) never execute on the first call; the server returns a confirmation ID instead, and the action only runs if a human confirms it within 60 seconds. Every call, pending or executed, is written to an append-only audit log exposed as an MCP resource. I also built a web simulator of the Alexa+ experience: a real tool-calling LLM drives the conversation, but it's never given the confirm/cancel tools itself; only a human clicking a button in the UI can approve a high-risk action, so the guardrail can't be talked around.
How we built it
Python backend: FastAPI for the Streamable HTTP transport, Pydantic for the MCP JSON-RPC message shapes, and a declarative policy.py that maps each tool name to a risk tier — the single source of truth the whole guardrail reads from. State (reminders, devices, audit log) is plain JSON file storage, kept intentionally simple for the hackathon scope. The web simulator runs a tool-calling model locally via Ollama, with the agent's tool schema pulled directly from the same MCP tool definitions the server advertises, so the demo is provably exercising the real server, not a mock.
Challenges we ran into
Getting a small local model to reliably call tools with correct arguments took real iteration; early on, it invented reminder IDs instead of looking them up first, and once even hallucinated a companion app that doesn't exist. Tightening the system prompt to force it to fetch real IDs before acting, and to treat tool errors as something to correct rather than talk around, fixed most of it. On the infra side, making the confirmation flow correctly handle expiry and cancellation without a real database took a few passes.
Accomplishments that we're proud of
The guardrail is enforced at one choke point; every tool call passes through a single risk check, rather than scattered per-tool conditionals, so adding a new tool automatically inherits the safety behavior instead of requiring it to be remembered. The audit log captures the full lifecycle of a risky action: requested, pending, confirmed, cancelled, or expired, each as its own timestamped entry.
What we learned
MCP protocol compliance is mostly plumbing: JSON-RPC dispatch, schema shapes, session headers. The actual engineering work is in what you build on top of it. I also learned how unforgiving small local LLMs are about tool-calling unless you prompt almost defensively.
What's next for Guardian MCP
Anomaly detection (flagging repeated high-risk attempts in a short window), real integrations behind the stub tools (an actual messaging provider, an actual smart-lock API), and packaging the policy layer as middleware any MCP server could import, rather than something you reimplement per project.
Built With
- fastapi
- html5
- javascript
- python

Log in or sign up for Devpost to join the conversation.