Enterprise Security
Security in AegisMCP is not an afterthought. It is woven into the very fabric of the ExecutionPipeline.
The Pipeline Architecture
When a request arrives at the AegisMCP server, it does not immediately execute a tool. It must first pass through the Middleware Pipeline:
- Authentication Middleware: Validates API keys, JWTs, or other credentials and resolves them into an
Identity. - Rate Limit Middleware: Checks the
Identityagainst a quota to prevent DOS attacks and exorbitant LLM costs. - Policy Middleware (RBAC): Checks the
Identity's roles against therequired_permissionsof the target Tool.
Role-Based Access Control (RBAC)
You can protect any tool by defining required_permissions.
import asyncio
from aegismcp.server.app import AegisMCP
from aegismcp.security.auth.apikey import ApiKeyAuth
from aegismcp.security.policy.rbac import RBACPolicyEngine
# 1. Define how to verify API keys and map them to Roles
async def verify_key(key: str):
if key == "sk-admin-secret":
return {"id": "user123", "roles": ["admin"]}
return None
auth = ApiKeyAuth(verify_key)
# 2. Define what permissions each Role grants
policy = RBACPolicyEngine(role_permissions={
"admin": frozenset(["users:read", "users:write", "system:reboot"])
})
# 3. Mount Security to the App
app = AegisMCP("SecureApp", auth=auth, policy=policy)
# 4. Protect Tools
@app.tool(
description="Deletes a user account",
required_permissions=frozenset(["users:write"])
)
async def delete_user(user_id: str) -> str:
return f"User {user_id} deleted securely."
If an LLM without the admin role attempts to call delete_user, the ExecutionPipeline instantly rejects the request with a 403 Forbidden error before the function code is ever reached.
Distributed Rate Limiting
If you are deploying AegisMCP across multiple workers or containers, the default in-memory rate limiter will not suffice. Instead, use the RedisRateLimiter to maintain a distributed token bucket.
import redis.asyncio as redis
from aegismcp.server.app import AegisMCP
from aegismcp.adapters.redis.ratelimit import RedisRateLimiter
# Connect to your Redis cluster
redis_client = redis.Redis.from_url("redis://localhost")
# 60 requests per minute per user identity
rate_limiter = RedisRateLimiter(redis_client, tokens_per_minute=60)
app = AegisMCP("EnterpriseApp", rate_limit=rate_limiter)
Custom Middleware Deep Dive
AegisMCP allows you to completely customize the pipeline by writing your own Middleware.
Middleware functions use a classic __call__ chaining pattern.
from typing import Any
from aegismcp.kernel.context import AegisContext
from aegismcp.execution.pipeline import Middleware, ToolHandler
from aegismcp.tools.descriptor import ToolDescriptor
class CustomAuditMiddleware(Middleware):
"""
A custom middleware that logs the start and end of every tool call.
"""
async def __call__(
self,
inputs: Any,
ctx: AegisContext,
descriptor: ToolDescriptor,
next_handler: ToolHandler
) -> Any:
# 1. PRE-EXECUTION (Before the tool runs)
print(f"[AUDIT] Starting {descriptor.name} for user {ctx.caller_identity.id}")
try:
# 2. CALL next middleware (or the Tool Executor)
result = await next_handler(inputs, ctx, descriptor)
# 3. POST-EXECUTION (After the tool finishes successfully)
print(f"[AUDIT] Successfully completed {descriptor.name}")
return result
except Exception as e:
# 4. ERROR HANDLING (If the tool crashed)
print(f"[AUDIT] Tool {descriptor.name} failed with error: {e}")
raise
To use it, just add it to your app: