Rbac Demo
ASP.NET Core MCP server with Role-Based Access Control - a working demo using the official MCP C# SDK
Ask AI about Rbac Demo
Powered by Claude Β· Grounded in docs
I know everything about Rbac Demo. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
MCP RBAC Demo
A working example of a Model Context Protocol (MCP) server built with ASP.NET Core that enforces Role-Based Access Control on every tool call. The idea is simple: different users get access to different tools depending on their role, and the server rejects anything they shouldn't be touching.
This is meant as a reference project. It's small enough to read in one sitting but covers the patterns you'd actually use in a real system β EF Core for persistence, a clean RBAC service, and the official MCP C# SDK for the protocol layer.
What's inside
The server exposes four MCP tools over HTTP (Streamable HTTP transport). Each tool is gated by role:
| Tool | What it does | Allowed roles |
|---|---|---|
inventory_lookup | Search products by SKU or name | Admin, Manager |
generate_report | Sales summary for a date range | Manager, Viewer |
manage_users | List, add, or deactivate users | Admin |
system_status | Health check, uptime, runtime info | Admin, Manager, Viewer |
Three demo users are seeded on first run:
| User | Role | Can use |
|---|---|---|
alice | Admin | All four tools |
bob | Manager | inventory_lookup, generate_report, system_status |
carol | Viewer | generate_report, system_status |
Authentication is intentionally simple β pass an X-User-Id header with the username. No JWT, no OAuth. This keeps the focus on the RBAC pattern rather than auth plumbing.
Prerequisites
- .NET 8 SDK (or later)
- That's it. SQLite is embedded β no database server needed.
Getting started
cd McpRbacDemo
dotnet run
The server starts on http://localhost:5000 by default (check console output for the actual URL). The MCP endpoint is at /mcp.
Testing with curl
The MCP protocol uses JSON-RPC over HTTP. Here are some quick examples.
Initialize the session:
curl -X POST http://localhost:5000/mcp \
-H "Content-Type: application/json" \
-H "X-User-Id: alice" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": { "name": "curl-test", "version": "1.0" }
}
}'
List available tools:
curl -X POST http://localhost:5000/mcp \
-H "Content-Type: application/json" \
-H "X-User-Id: alice" \
-H "Mcp-Session-Id: <session-id-from-init>" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}'
Call a tool (as alice β Admin):
curl -X POST http://localhost:5000/mcp \
-H "Content-Type: application/json" \
-H "X-User-Id: alice" \
-H "Mcp-Session-Id: <session-id-from-init>" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "system_status",
"arguments": {}
}
}'
Try a tool carol can't access:
curl -X POST http://localhost:5000/mcp \
-H "Content-Type: application/json" \
-H "X-User-Id: carol" \
-H "Mcp-Session-Id: <session-id-from-init>" \
-d '{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "inventory_lookup",
"arguments": { "query": "mouse" }
}
}'
Carol is a Viewer, so this returns an error: "Access denied. User 'carol' does not have permission to use 'inventory_lookup'."
Testing with MCP Inspector
If you have MCP Inspector installed, point it at http://localhost:5000/mcp and set the X-User-Id header to one of the demo users. You'll be able to browse tools and call them interactively.
Project structure
McpRbacDemo/
Program.cs β App startup, DI wiring, MCP + EF Core config
appsettings.json β Connection string and logging config
Data/
AppDbContext.cs β EF Core context (Users, Roles, UserRoles)
SeedData.cs β Creates demo users and roles on first run
Models/
User.cs β User entity
Role.cs β Role entity
UserRole.cs β Many-to-many join entity
Services/
IRbacService.cs β Interface for the RBAC service
RbacService.cs β Role lookups and tool-permission checks
Tools/
InventoryTools.cs β inventory_lookup tool
ReportTools.cs β generate_report tool
UserManagementTools.cs β manage_users tool
StatusTools.cs β system_status tool
Middleware/
RbacToolFilter.cs β MCP CallTool filter that enforces RBAC
McpRbacDemo.Tests/ β xUnit test project (39 tests)
RbacServiceTests.cs β Permission map and role lookup tests
SeedDataTests.cs β Database seeding and idempotency tests
InventoryToolsTests.cs β Inventory search tests
ReportToolsTests.cs β Report generation and validation tests
StatusToolsTests.cs β System status output tests
UserManagementToolsTests.cs β User CRUD operation tests
Running the tests
dotnet test
How the RBAC works
- Every HTTP request to the MCP endpoint includes an
X-User-Idheader. - When a
tools/callrequest arrives, theRbacToolFilterfires before the tool executes. - The filter reads the header, looks up the user's roles in SQLite via
RbacService, and checks whether any of those roles are allowed for the requested tool. - If the check fails, the filter returns an error result directly β the tool never runs.
The permission map lives in RbacService.cs as a simple dictionary. In a real project you'd probably move this to configuration or a database table, but for a demo it keeps things readable.
Extending it
Add a new tool: Create a class in Tools/, decorate it with [McpServerToolType], and add methods with [McpServerTool(Name = "your_tool_name")]. Then add the tool name and allowed roles to the ToolPermissions dictionary in RbacService.cs.
Add a new role: Insert it in SeedData.cs (or at runtime via manage_users), then reference it in the permission map.
Switch to real auth: Replace the X-User-Id header check in RbacToolFilter with ASP.NET Core's built-in [Authorize] attributes and AddAuthorizationFilters(). The MCP C# SDK supports this natively.
Tech stack
- ASP.NET Core 8 β Web host and HTTP transport
- MCP C# SDK v1.1.0 β Model Context Protocol implementation
- Entity Framework Core 8 + SQLite β Persistence for users and roles
- xUnit + EF Core InMemory β Unit testing
License
This is a demo project. Use it however you like.
