Skip to content

About

Aegis β€” an MCP server that audits the blast radius of AI agents. Maps an agent's full capability graph across connected tools, detects toxic permission combinations (like read-private-data + send-external), and applies policy fixes automatically. Built on the NitroStack SDK. πŸ† 1st place, NitroStack Γ— MCP To The Moon Buildathon, SRMIST 2026.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Β 
Β 

Repository files navigation

Aegis πŸ›‘οΈ

NitroStack Framework MCP Server Zero Token Core Live Demo License

A Blast-Radius Auditor for AI Agents Track 03: Enterprise AI & Workplace Automation β€” NitroStack Hackathon

Aegis is a Model Context Protocol (MCP) server built on NitroStack that audits the combined effective permissions of an AI agent across all connected tools. It deterministically detects toxic capability combinations and data-exfiltration vectors before deployment β€” at zero LLM token cost.

πŸ”΄ Live server: https://aegis-6a6d76ee-teamx-srmist.app.nitrocloud.ai/mcp β€” connect it to Claude, ChatGPT, or NitroStack Studio and try the walkthrough below for real.


πŸ“‹ Table of Contents


πŸ† The Problem

Enterprises connect AI agents to dozens of tools β€” Gmail, Dropbox, Postgres databases, Slack, filesystem execution. Each integration gets approved individually on its own merits, but nobody audits what the agent can do when tools are combined.

  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚  Dropbox MCP   β”‚        β”‚   Gmail MCP    β”‚
  β”‚ (Read Private) β”‚        β”‚ (Send External)β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚                         β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚      Support Agent      β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β–Ό
   🚨 TOXIC COMBINATION: DATA EXFILTRATION PATH

Warning

  • READ_PRIVATE_DATA (Dropbox) + SEND_EXTERNAL (Gmail) = πŸ”΄ Data Exfiltration Path
  • READ_PRIVATE_DATA (Postgres) + WRITE_PUBLIC (Slack) = 🟠 Public Leak Path
  • DELETE_DATA (Postgres) + EXECUTE (Filesystem) = 🟠 Destructive Automation Vector

This isn't hypothetical β€” it's how the Supabase MCP leak happened (an agent with legitimate database read access was steered via prompt injection into exfiltrating private records through an external channel), how the postmark-mcp supply-chain compromise turned an ordinary "send email" tool into a covert BCC-to-attacker exfiltration path, and the exact mechanism behind documented tool-poisoning attacks, where malicious instructions hidden in a tool's own description hijack agent behavior without ever calling an obviously malicious endpoint. Individually-reasonable permissions become dangerous the moment they're combined, and nothing in the stack today computes that union before it's exploited.


πŸ“Έ See It Work

Real, live-rendered screenshots β€” the actual widgets, fed the actual output of get_capability_graph / detect_attack_paths after connecting gmail + dropbox to one agent.

The graph β€” dangerous capability paths render in red:

Capability graph showing a critical exfiltration path between Gmail and Dropbox

The alert β€” severity, affected tools, and one-click remediation:

Attack path alert showing a critical exfiltration finding with a terminate button

After clicking Fix, apply_policy_fix disconnects every tool supplying the sink capability and the graph goes back to riskScore: 0 β€” no attack paths, clean state.


πŸ“ System Architecture

flowchart TD
    subgraph Host["Chat Host / Client"]
        Client["User / AI Agent Host\n(NitroStudio, ChatGPT, Claude)"]
    end

    subgraph MCP["Aegis MCP Server (NitroStack)"]
        Tools["Governance Tools Controller\n(connect_tool, get_capability_graph,\ndetect_attack_paths, apply_policy_fix)"]
        Guard["OAuthGuard\n(scaffolded, opt-in via OAUTH_REQUIRED β€”\nopen by default for the hackathon build)"]
        Resources["Resource Server\n(aegis://policies)"]
        Prompts["Prompt Controller\n(explain_attack_path)"]

        Guard -. wraps connect_tool only .-> Tools
    end

    subgraph Engine["Deterministic Engine β€” 0 Tokens"]
        Registry["Tool Capability Registry\n(gmail, dropbox, postgres, slack,\nfilesystem, calendar)"]
        Store["Per-Agent Connected-Tool Store\n(in-memory)"]
        Union["Effective Capability Union\n(getEffectiveCapabilities)"]
        Detector["Policy Rule Matcher\n(detectAttackPaths)"]

        Registry --> Store --> Union --> Detector
    end

    subgraph UI["NitroStack Widgets"]
        GraphWidget["capability-graph\n(live risk graph)"]
        AlertWidget["attack-path-alert\n(severity + one-click Fix)"]
    end

    subgraph LLM["Groq Explanation Layer β€” only LLM spend"]
        Groq["Llama 3.1 8B Instant\ncached by SHA-256(ruleId + sorted(viaTools))"]
    end

    Client -->|STDIO / HTTP JSON-RPC| Tools
    Tools --> Engine
    Detector -->|risk score + danger edges| GraphWidget
    Detector -->|threat path list| AlertWidget
    Prompts -->|only on a detected path, cache miss| Groq
    Groq -->|plain-English finding| Client
    AlertWidget -->|Fix click| Tools
Loading

πŸ”„ Detection & Remediation Lifecycle

flowchart LR
    A["1. Connect Gmail"] -->|connect_tool| B["READ_PRIVATE_DATA + SEND_EXTERNAL"]
    B --> C["🟒 SAFE β€” riskScore 0"]
    C --> D["2. Connect Dropbox"]
    D -->|connect_tool| E["+ WRITE_DATA"]
    E --> F["Detector checks policy table"]
    F -->|source+sink both present| G["🚨 exfiltration DETECTED"]
    G --> H["3. Render widgets"]
    H -->|get_capability_graph| I["Graph edge turns RED β€” riskScore 1"]
    H -->|explain_attack_path| J["Groq: plain-English summary"]
    I --> K["4. Remediate"]
    K -->|apply_policy_fix| L["Every tool supplying the sink\ncapability is disconnected"]
    L --> M["Status cleared β€” riskScore 0"]
Loading

πŸ› οΈ Tool & Capability Registry

Tool Tool ID Granted Capabilities Risk Profile
πŸ“§ gmail READ_PRIVATE_DATA, SEND_EXTERNAL 🟠 High
πŸ“¦ dropbox READ_PRIVATE_DATA, WRITE_DATA, SEND_EXTERNAL 🟠 High
πŸ—„οΈ postgres READ_PRIVATE_DATA, WRITE_DATA, DELETE_DATA πŸ”΄ Critical
πŸ’¬ slack WRITE_PUBLIC, SEND_EXTERNAL 🟑 Medium
πŸ’» filesystem READ_PRIVATE_DATA, WRITE_DATA, EXECUTE πŸ”΄ Critical
πŸ“… calendar READ_PRIVATE_DATA, WRITE_DATA 🟒 Low

🎯 Toxic-Combination Policy Rules

Rule ID Source Sink Severity Violation
exfiltration READ_PRIVATE_DATA SEND_EXTERNAL πŸ”΄ Critical Agent can read private data AND transmit it externally.
public-leak READ_PRIVATE_DATA WRITE_PUBLIC 🟠 High Agent can read private records AND post them publicly.
destructive DELETE_DATA EXECUTE 🟠 High Agent can delete data AND execute unvalidated actions.

Both tables are just data (TOOL_REGISTRY and POLICY_RULES) β€” adding a 7th tool or a 4th rule is a one-line change, not new logic.


πŸ”Œ MCP Interface Reference

Tools

  • connect_tool β€” connects a tool (gmail, dropbox, postgres, slack, filesystem, calendar) to an agent. Wrapped in OAuthGuard (scaffolded β€” enforced only if OAUTH_REQUIRED=true is set; open by default for local/demo use).
  • get_capability_graph β€” @Widget('capability-graph'). Returns nodes, danger edges, active attack paths, and risk score.
  • detect_attack_paths β€” @Widget('attack-path-alert'). Runs the deterministic rule engine.
  • apply_policy_fix β€” disconnects every tool supplying a detected rule's sink capability.

Resource

  • aegis://policies β€” the toxic-combination policy table as JSON.

Prompt

  • explain_attack_path β€” takes agentId + ruleId, returns a plain-English explanation via Groq (llama-3.1-8b-instant). Only fires on an already-detected path, cached by SHA-256(ruleId + sorted(viaTools)) β€” this is the only step in the entire system that spends a token.

MCP surface map

flowchart LR
    Agent(("πŸ›‘οΈ Aegis"))

    Agent --> T1["πŸ”§ connect_tool"]
    Agent --> T2["πŸ”§ get_capability_graph"]
    Agent --> T3["πŸ”§ detect_attack_paths"]
    Agent --> T4["πŸ”§ apply_policy_fix"]
    Agent --> R1["πŸ“„ aegis://policies"]
    Agent --> P1["πŸ’¬ explain_attack_path"]

    T2 -.renders.-> W1["🎨 capability-graph widget"]
    T3 -.renders.-> W2["🎨 attack-path-alert widget"]
Loading

▢️ Try It Yourself

Every step below works against the live server β€” no local setup needed. Connect https://aegis-6a6d76ee-teamx-srmist.app.nitrocloud.ai/mcp to Claude (Settings β†’ Connectors β†’ Add custom connector) or ChatGPT (Developer Mode β†’ Plugins β†’ Add), or point NitroStack Studio at this repo locally, then walk through the same scenario the screenshots above were taken from:

  1. Connect a tool. "Connect gmail to demo-agent." β†’ connect_tool fires. One tool, nothing alarming yet.
  2. Connect a second tool. "Now connect dropbox to demo-agent." β†’ the agent can now both read private data and send it externally.
  3. See the risk. "Show me its capability graph." β†’ get_capability_graph renders β€” the exfiltration edge is red. This step is pure deterministic rule matching: zero LLM tokens spent to catch it.
  4. Get a plain-English explanation. "What does this mean?" β†’ explain_attack_path fires β€” the only step in the whole system that calls an LLM, and only because a rule already matched.
  5. Fix it. "Fix it." β†’ apply_policy_fix disconnects every tool supplying the dangerous capability. The graph goes back to riskScore: 0.

Use any agentId you like β€” it's just an in-memory key, not a real account.


πŸš€ Quickstart (run it locally)

git clone https://github.com/prince-rai88/aegis-mcp.git
cd aegis-mcp
npm install
cp .env.example .env   # add GROQ_API_KEY β€” free at console.groq.com
npm run dev

Verify without any GUI:

bash scripts/test-mcp.sh

Or connect NitroStack Studio β†’ Add Server β†’ Nitro Project β†’ select this folder, then run through the walkthrough above against your local server instead of the live one.


❓ FAQ

Why deterministic rules instead of having the model decide what's risky? Because then the audit trail is "the model thought so." Detection here is a fixed rule table (source capability β†’ sink capability), so every flag is reproducible and explainable without re-running an LLM.

Does this scale beyond 6 tools and 3 rules? TOOL_REGISTRY and the policy rules are both just data β€” adding a 7th tool or a 4th rule is a one-line addition, not new logic.

What does the LLM actually do, then? Only explain_attack_path, only after a rule has already fired, cached by SHA-256(ruleId + sorted(viaTools)) so the same finding is never re-explained twice.


πŸ“ Project Structure

aegis-mcp/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app.module.ts                  # NitroStack root module
β”‚   β”œβ”€β”€ index.ts                       # Server bootstrap
β”‚   β”œβ”€β”€ modules/governance/            # Security governance engine
β”‚   β”‚   β”œβ”€β”€ capability.ts              # Capability model + TOOL_REGISTRY
β”‚   β”‚   β”œβ”€β”€ detector.ts                # 0-token deterministic detector
β”‚   β”‚   β”œβ”€β”€ policies.ts                # Toxic-combination policy rules
β”‚   β”‚   β”œβ”€β”€ oauth.guard.ts             # Scaffolded OAuth guard
β”‚   β”‚   β”œβ”€β”€ governance.tools.ts        # The 4 MCP tools
β”‚   β”‚   β”œβ”€β”€ governance.resources.ts    # aegis://policies
β”‚   β”‚   β”œβ”€β”€ governance.prompts.ts      # Groq explanation prompt
β”‚   β”‚   └── governance.module.ts
β”‚   └── widgets/app/
β”‚       β”œβ”€β”€ capability-graph/          # Capability graph widget
β”‚       └── attack-path-alert/         # Attack path alert widget
β”œβ”€β”€ docs/screenshots/                  # Real rendered widget screenshots
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ test-mcp.sh                    # Stdio JSON-RPC smoke test
β”‚   └── preview-widgets.html           # Local widget preview, no Studio needed
└── README.md

πŸ“œ License

MIT

About

Aegis β€” an MCP server that audits the blast radius of AI agents. Maps an agent's full capability graph across connected tools, detects toxic permission combinations (like read-private-data + send-external), and applies policy fixes automatically. Built on the NitroStack SDK. πŸ† 1st place, NitroStack Γ— MCP To The Moon Buildathon, SRMIST 2026.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages