About FastMCP ToolSecurityTrimming
FastMCP ToolSecurityTrimming is an MCP server published by anevjes in the Security category: a quick sample on how to implement tool security trimming based on user's role assignment with entraID using FastMCP Middleware.
The repository has 1 stars and 0 forks, with the last commit a year ago. Six months or more without a commit doesn't mean the server is broken, but check the open issues before depending on it in production.
Install
git clone https://github.com/anevjes/FastMCP-ToolSecurityTrimmingThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Tools (5)
clear_weather_dataDelete weather data
Parameters not published.
get_forecastGet weather forecast
Parameters not published.
get_weatherGet current weather
Parameters not published.
get_weather_statsSystem statistics
Parameters not published.
set_weather_alertSet weather alerts
Parameters not published.
Ask AI
Ask AI about FastMCP ToolSecurityTrimming
Powered by Claude · Grounded in docs
Security checks
- ✓README presentThe repository ships documentation.
5 checks have not been run yet.
README
Secure MCP Server with Azure AD and JWT-based Role Authorization
This project implements a secure Model Context Protocol (MCP) server using Azure AD authentication and JWT-based role authorization, as described in the Medium article by Saima Khan.
Features
- Azure AD Authentication: Secure login using Microsoft Azure Active Directory
- JWT Token Verification: FastMCP integration with JWT bearer authentication
- Role-Based Access Control (RBAC): Tools filtered by Azure AD App Roles
- Redis Token Storage: Secure token management with automatic expiration
- One-Time Auth Codes: Secure token exchange without browser storage
- Middleware-Based Authorization: Protocol-aware access control
Architecture
The solution implements a two-tier security approach:
Tier 1: App Role-Based Access Control (Implemented)
- Controls which tools users can see based on Azure AD App Roles
- Prevents access to dangerous operations before they're exposed
- Acts as a gatekeeper at the MCP Server level
Tier 2: API-Level Restrictions (Future Enhancement)
- Runtime permission checks using On-Behalf-Of (OBO) pattern
- Fine-grained access control for external API calls
- Delegated authentication for downstream services
Project Structure
secure-mcp-server/
├── shared/
│ ├── auth_context.py # Azure AD + MSAL integration
│ ├── redis_token_store.py # Token + auth code management
│ └── middleware/
│ └── authorization_middleware.py # Custom FastMCP RBAC enforcement
├── main.py # Main MCP server with weather tools
├── client.py # Example client implementation
├── requirements.txt # Python dependencies
├── .env.example # Environment variables template
└── README.md # This file
Azure AD Setup
1. Create App Registration
- Go to Azure Portal → Azure Active Directory → App registrations
- Click "New registration"
- Configure:
- Name: Your MCP Server name
- Redirect URI:
http://localhost:8000/auth/callback
2. Configure Authentication
- Go to Authentication blade
- Enable "ID tokens" under "Implicit grant and hybrid flows"
- Confirm redirect URI is correctly added
3. Create App Roles
- Go to App roles blade (or Manifest)
- Create roles:
{
"allowedMemberTypes": ["User"],
"displayName": "Task Read Access",
"id": "generate-unique-uuid",
"isEnabled": true,
"description": "Allows reading weather tools",
"value": "Task.Read"
}
Create additional roles:
Task.Write: Read + write accessTask.All: Read + write + admin accessAdmin: Full access including delete operations
4. Assign Users to Roles
- Go to Enterprise Applications → Your App → Users and groups
- Click "Add user/group"
- Select users and assign appropriate roles
5. Get Configuration Values
- Tenant ID: Azure AD → Overview → Tenant ID
- Client ID: App registrations → Your app → Application (client) ID
- Client Secret: App registrations → Your app → Certificates & secrets → New client secret
Redis Setup
Create an Azure Cache for Redis instance:
- Go to Azure Portal → Create resource → Azure Cache for Redis
- Configure basic settings (Standard tier recommended)
- Note the hostname and access keys
Installation & Setup
1. Clone and Install Dependencies
git clone <your-repo>
pip install -r requirements.txt
2. Configure Environment
cp .env.example .env
# Edit .env with your Azure AD and Redis configuration
Required environment variables:
# Azure AD Configuration
AZURE_TENANT_ID=""
AZURE_CLIENT_ID=""
AZURE_CLIENT_SECRET=""
# Redis Configuration
REDIS_HOST="<host>.australiaeast.redis.azure.net"
REDIS_PORT=10000
REDIS_USE_AAD=false
REDIS_USERNAME="default"
REDIS_PASSWORD="optional-if-not-using-aad"
REDIS_AAD_SCOPE="https://redis.azure.com/.default"
REDIS_AUTH_MODE=auto
REDIS_SSL=true
REDIS_DECODE=true
REDIS_USERNAME="default"
# Server Configuration
REDIRECT_URI=http://localhost:8000/auth/callback
DEBUG=true
# Optional: Custom port
PORT=8000
3. Start the Server
python main.py
The server will start on http://localhost:8000 with these endpoints:
- Authentication:
/auth/login - MCP Protocol:
/mcp- on port 9000!!! - Health Check:
/health
Usage
Authentication Flow
- Login: Navigate to
http://localhost:8000/auth/login - Azure AD: Complete Microsoft login
- Auth Code: Copy the one-time auth code from the callback page
- Token Exchange: Use the auth code to get access tokens
Using the Client
from client import SecureMCPClient
import asyncio
async def example():
client = SecureMCPClient()
# Authenticate with auth code
token_data = client.authenticate_with_auth_code("your-auth-code")
# List available tools (filtered by role)
tools = await client.list_tools()
print(f"Available tools: {[tool.name for tool in tools]}")
# Call tools based on permissions
weather = await client.get_weather("Perth")
print(weather)
asyncio.run(example())
Interactive Demo
python client.py
This will guide you through the authentication process and demonstrate different access levels.
Available Tools & Access Levels
| Tool | Description | Required Role | Tags |
|---|---|---|---|
get_weather |
Get current weather | Task.Read+ | read |
get_forecast |
Get weather forecast | Task.Read+ | read |
set_weather_alert |
Set weather alerts | Task.Write+ | write |
get_weather_stats |
System statistics | Task.All+ | admin |
clear_weather_data |
Delete weather data | Admin | delete |
Role Hierarchy
- Task.Read: Can access tools tagged with
read - Task.Write: Can access tools tagged with
read,write - Task.All: Can access tools tagged with
read,write,admin - Admin: Can access all tools including
deleteoperations
API Endpoints
Authentication Endpoints
GET /auth/login- Initiate OAuth loginGET /auth/callback- OAuth callback handlerPOST /auth/exchange- Exchange auth code for tokensPOST /auth/refresh- Refresh access token
MCP Protocol
POST /mcp/*- FastMCP protocol endpoints (requires JWT authentication)
Utility
GET /health- Health checkGET /- Service information
Security Features
Token Management
- Redis Storage: Tokens stored in Redis with automatic expiration
- One-Time Auth Codes: Secure token exchange without browser storage
- Refresh Tokens: Automatic token renewal capability
Access Control
- JWT Verification: JWKS-based token validation
- Role-Based Filtering: Tools filtered by Azure AD App Roles
- Protocol-Aware Middleware: FastMCP middleware for fine-grained control
Production Considerations
- HTTPS Required: Use TLS in production
- Token Rotation: Implement regular token refresh
- Audit Logging: Add comprehensive audit trails
- Rate Limiting: Implement API rate limiting
- Error Handling: Enhanced error responses
Development
Running Tests
# Start server
python main.py
# In another terminal, run client demo
python client.py
Adding New Tools
- Define tool function with appropriate
tags:
@mcp.tool(tags=["read"]) # or ["write"], ["admin"], ["delete"]
def my_new_tool(param: str) -> str:
return f"Result for {param}"
- Update role mappings in
authorization_middleware.pyif needed
Debugging
Enable debug mode in middleware:
mcp.add_middleware(AuthorizationMiddleware(auth_context, redis_token_store, debug=True))
Troubleshooting
Common Issues
- Import Errors: Install dependencies with
pip install -r requirements.txt - Authentication Failed: Check Azure AD configuration and tenant ID
- Token Expired: Use refresh token or re-authenticate
- No Tools Visible: Verify Azure AD App Role assignments
- Redis Connection: Check Redis host, port, and password
Debugging Steps
- Check server logs for detailed error messages
- Verify environment variables are correctly set
- Test Azure AD configuration with a simple OAuth flow
- Confirm Redis connectivity with
redis-cli
References
License
This project is for educational and demonstration purposes based on the referenced Medium article.
README copy captured when this server was indexed; it may lag the repository. The original is authoritative.