
Aegis is an MCP server that computes what an AI agent can actually do once its connected tools are combined, not just what each tool is approved to do on its own, and flags the combinations that create data exfiltration or destructive automation risk.
What this enables
- Computes the union of an agent's effective permissions across every connected MCP tool
- Flags source-and-sink capability pairs, such as read-private-data plus send-external, as toxic combinations
- Assigns a risk score and renders danger edges directly on a capability graph
- Fixes a detected path with one action, disconnecting the tool supplying the risky capability
- Detects every path deterministically, with zero LLM tokens spent on the detection step itself
The permission that nobody was auditing
Enterprises connect AI agents to a growing list of tools: Gmail, Dropbox, Postgres, Slack, local filesystem access. Each connection typically gets approved on its own, against its own scope. Read access to a database looks reasonable. Send access to email looks reasonable. What rarely gets checked is what the agent can do once both are wired into the same session.
Aegis, submitted to NitroStack's hackathon under the enterprise AI and workplace automation track, treats that gap as the actual attack surface. Its README points to real incidents as the motivating pattern: an agent with legitimate database read access steered through prompt injection into exfiltrating records through an external channel, and a popular email MCP tool compromised in a supply-chain attack so that a routine send-email call quietly BCC'd an attacker. In both cases, no single permission was the problem. The combination was.
Why this needed to be an MCP-level check, not a chatbot warning
MCP already forces every agent capability to pass through a typed, named tool. That's what makes the union computable in the first place. Because connect_tool is the single entry point for adding gmail, dropbox, postgres, slack, filesystem, or calendar to an agent, Aegis can intercept that call, look up each tool's granted capabilities in a shared registry, and keep a running effective-capability set per agent. A general-purpose chat safety layer has no equivalent chokepoint. It would have to infer intent from conversation rather than read a structured capability grant.
Turning a policy table into a live graph
The build is a NitroStack governance module with four tools, one resource, and one prompt. TOOL_REGISTRY maps each tool ID (gmail, dropbox, postgres, slack, filesystem, calendar) to the capabilities it grants, things like READ_PRIVATE_DATA, SEND_EXTERNAL, WRITE_DATA, DELETE_DATA, and EXECUTE. A separate POLICY_RULES table pairs a source capability with a sink capability and a severity: read-private plus send-external is critical, read-private plus write-public is high, delete-data plus execute is high.
The runtime sequence:
connect_tooladds a tool to an agent's in-memory store.getEffectiveCapabilitiesunions the capability sets of every tool that agent has connected.detectAttackPathschecks the union against the policy table for a matching source-and-sink pair.get_capability_graph, rendered through a NitroStack widget, plots the result and turns the dangerous edge red with a non-zero risk score.explain_attack_path, a prompt, asks Groq's Llama 3.1 8B Instant for a plain-English summary of the finding, cached by a SHA-256 hash of the rule ID and the sorted tool list so the same finding is never explained twice.apply_policy_fixdisconnects every tool supplying the sink capability, and the graph resets to a clean state.
Connecting Gmail alone leaves the risk score at zero. Adding Dropbox on top of it is what trips the exfiltration rule, because Dropbox contributes the write side of a path Gmail's send capability can already complete. That ordering is deliberate: the danger only exists once the second tool lands.
Where NitroStack fits
The governance logic is a NitroStack module: a tools controller for the four MCP tools, a resource serving the policy table at aegis://policies, and a prompt controller wired to the Groq call. An OAuthGuard wraps connect_tool specifically, scaffolded so it can be turned on with an environment flag rather than baked into every tool. The two widgets, a capability graph and an attack-path alert with a one-click Fix button, are built as NitroStack Widgets, which is what lets a JSON risk finding become something a security reviewer can act on without reading logs. The server itself runs live on NitroCloud, and the project documents connecting it to Claude, ChatGPT, or NitroStudio as three interchangeable clients against the same deployed instance.
The design choice that matters
The interesting part isn't the graph. It's what doesn't touch the model. Detection runs entirely as deterministic rule matching against two data tables, so every flagged path is reproducible without re-running an LLM and is explainable as "source capability X plus sink capability Y," not "the model thought this looked risky." The only step in the whole system that spends a token is the explanation prompt, and only after a rule has already matched. That separation means the audit trail behind a security finding is a rule ID, not a language model's judgment call. The trade-off is real too: the OAuth guard on connect_tool is opt-in and open by default in this build, which is a reasonable default for a hackathon demo but not one to carry into a production deployment unmodified.
What the build demonstrates
This is a working prototype with a public repository and a live deployed server, not a customer deployment. What it demonstrates is that the union of an agent's tool capabilities can be computed and checked against a policy table cheaply enough to run on every connect_tool call, and that a security finding can be pushed into a visual, one-click remediation without involving the model in the decision. Screenshots in the repository show the capability graph turning red on a real Gmail-plus-Dropbox connection and returning to a clean state after the fix is applied, which is the actual output of the deterministic engine rather than a mockup.
The reusable pattern
The transferable idea isn't "audit AI agent permissions." It's narrower and more useful: separate the safety-critical decision (does this combination of capabilities create a bad path) from the safety-adjacent decision (how do I explain this to a human). The first stays deterministic, auditable, and cheap. The second is the only place an LLM earns its keep, and only on a cache miss after the rule already fired. Any MCP server juggling multiple tool integrations with real read or write scope can apply the same split.
Explore the source on GitHub, connect the live server to test the walkthrough yourself, or start building your own governance layer with the NitroStack SDK.