How to use the GuardiAgent Framework

Use the GuardiAgent Framework to secure your AI Agent. Encapsulate the least common denominator in agentic software: the MCP server.

Attack on Titan

Prevent Mistakes
Even well-intentioned MCP servers can contain bugs that lead to unintended consequences. GuardiAgent's sandbox ensures that configuration errors, coding mistakes, or unexpected behavior can't escalate into system-wide issues. Catch problems before they impact your production environment.
Prevent Attacks
Malicious actors can compromise MCP servers to exfiltrate data, inject code, or abuse system resources. GuardiAgent provides defense-in-depth by isolating each server in a containerized sandbox, preventing attackers from pivoting to other parts of your infrastructure even if a server is compromised.
Limit Access
Apply the principle of least privilege to your AI agents. Define granular permissions that specify exactly what files, directories, and network resources each MCP server can access. No more giving blanket access to your entire filesystem or network.
Users Consent
Put your users in control of their data. GuardiAgent prompts for explicit consent before granting runtime permissions, ensuring users understand and approve what their AI agents can access. Build trust through transparency and give users the final say on sensitive access.

Quick Start

To use the GuardiAgent Security Sandbox, use the following quick start steps. GuardiAgent is not dependent on a specific AI framework, it works with all SDKs. However, this quickstart shows how to use GuardiAgent with the OpenAI Agent SDK. Currently, we support the OpenAI Agent SDK out of the box with an SDK specific implementation.

Prerequisities

To create and run this hello world example with an AI agent, make sure you have the following tools and runtimes installed:

  • Python > 3.10
  • Docker
  • Optionally, but recommended: "uv" - the Python package manager
  • OpenAI API Key

Project Setup

To setup a new project and use the openAI Agent SDK, you'll need to initialize the project and add its dependencies.

uv init
uv add openai-agents
uv add https://github.com/GuardiAgent/python-mcp-sandbox-openai-sdk.git

Walk-through Example

Below, there is a ready to run example (with an OpenAI API key), that utilizes the sandbox to encapsulate the official Filesystem MCP server.

import os

from agents import Agent, Runner

from mcp_sandbox_openai_sdk import (
    FSAccess,
    MCPManifest,
    MCPServers,
    Permission,
    Registry,
    SandboxedMCPStdio,
)

manifest = MCPManifest( 
    name="Filesystem Server",
    description="A server that access the local filesystem and allows interaction with all sorts of files.",
    registry=Registry.NPM,
    package_name="@modelcontextprotocol/server-filesystem",
    permissions=[
        Permission.MCP_AC_FILESYSTEM_READ,
        Permission.MCP_AC_FILESYSTEM_WRITE,
        Permission.MCP_AC_FILESYSTEM_DELETE,
    ],
)


async def main():
    async with MCPServers(
        SandboxedMCPStdio( 
            manifest=manifest,
            runtime_args=[os.path.abspath("./")],
            runtime_permissions=[FSAccess(os.path.abspath("./"))],
        )
    ) as servers:
        agent = Agent(
            name="MCP Sandbox Test",
            model="gpt-5-mini",
            mcp_servers=servers,
        )

        prompt = f"""
            Read the files in the {os.path.abspath("./")} directory and
            list all the found files and directories of the first level.
            Do not decend recursively.
            Use the provided mcp servers to access the filesystem.
        """
        result = await Runner.run(
            agent,
            input=prompt,
        )
        print(result.final_output)


if __name__ == "__main__":
    import asyncio

    print("Execute Sandbox Demo")
    asyncio.run(main())

Deep-Dive

Lines 14 - 24 show how an MCP security manifest can be created inside your own code. The manifests should be part of the MCP server implementation, but since the practice is not yet widespread, you may also create the manifest inside your own code. The manifest (as described below), allows the engineer of an MCP server to define what general intentions the MCP server has - like an Android or iPhone app.

Lines 29 - 33 are the heart of the SDK. Instead of using the MCPServerStdio from the OpenAI Agent SDK directly, you must use our wrapper class. This wrapper has the following functions:

  1. Takes a list of runtime permissions
  2. Validates the runtime permissions against the defined manifest permissions
  3. Asks the user for consent for each runtime permission (e.g. for specific file access to a directory)
  4. Uses Docker to start the MCP server sandboxed with the acknowledged permissions attached

As soon as the async with statement starts the MCP server(s), the user will be asked for each runtime permission, if they want to allow the access or not. This currently happens on the shell and looks like this:

Runtime Permission: File System Access Permission
Allow access to file system path: .../example (read: True, write: False)
Do you want to give the agent the requested access? (yes/no):

Depending on your answer, the example agent will have access or not.

The Security Manifest

One key ingredient of the GuardiAgent framework is the security manifest (in our research, we call it the policy). It is a JSON file, that is bundled together with the MCP server that defines what general intentions an MCP server may have. This defines overarching intentions like file-access or internet access. It is inspired by the Android Permissions Manifest for apps.

What a manifest looks like

{
  "name": "Filesystem Server",
  "description": "A server that access the local filesystem and allows interaction with all sorts of files.",
  "registry": "npm",
  "package_name": "@modelcontextprotocol/server-filesystem",
  "permissions": [ 
    "mcp.ac.filesystem.read",
    "mcp.ac.filesystem.write",
    "mcp.ac.filesystem.delete"
  ]
}

The manifest contains a description of the server and on which package system it runs. Based on the package system, the runtime is inferred. The list of permissions defines what general intentions an MCP server has. This does not mean that the server will have read and write access to your whole system, just that it does require read and write to some directories to function properly.

SandboxedMCPStdio(
    manifest=manifest,
    runtime_args=[os.path.abspath("./")],
    runtime_permissions=[FSAccess(os.path.abspath("./"))],
)

The manifest, in conjunction with the custom wrapper ensures that the server only has the least possible privileges. In the example above, the filesystem manifest is used to start the MCP server. Then the server receives runtime arguments (implementation detail, the server needs to know where the files are). Finally, the runtime permissions - if consented by the user - are the effective permissions that the server will receive.

Runtime Permissions

FSAccess

- Grant read/write access to specific filesystem paths. Define exactly which directories or files an MCP server can interact with.

EnvironmentVariable

- Allow access to specific environment variables by name. Control which configuration values the server can read.

DomainPort

- Enable network access to specific domains and ports. Restrict outbound connections to approved external services.

HostPort

- Allow network access to IP addresses and ports. Define precise network endpoints the server can communicate with.

Sandboxed Container Images

The sandbox currently works with Docker underneath. There is a base image that you can use to create your own customized runtime image. The custom entrypoint performs the following tasks:

  1. Check setup variables
  2. Download and setup the server package
  3. Check hostnames and setup iptables
  4. Execute the MCP server

The following configuration environment variables are available during setup:

  • PRE_INSTALLED: Skip package installation and use a pre-installed/mounted MCP server. Requires EXE to be set.
  • RUNTIME: Specifies the package manager runtime, either "pypi" for Python packages or "npm" for Node.js packages.
  • PACKAGE: The name of the MCP server package to install from the specified registry (npm or PyPI).
  • EXE: The command to execute the MCP server. Required when PRE_INSTALLED is set, otherwise auto-configured.
  • ALLOWED_EGRESS: Space or comma-separated list of allowed outbound connections in "host:port" or "ip:port" format. Empty by default (no outbound access).
  • EXTRA_DNS: Additional DNS servers to allow for resolution beyond those in /etc/resolv.conf.
  • ALLOW_LOOPBACK: Enable loopback traffic (localhost). Defaults to "1" (enabled). Set to "0" to disable.

Note that after the download of the server package from the official package repository, only outbound connections allowed by DOMAIN/PORT or IP/PORT are possible. IPTABLES will block everything else.