Production-Ready Governance for MCP Servers
Add production-grade Identity, RBAC, Secrets Management, and Auditing to your Model Context Protocol applications with @ithena-one/mcp-governance
.
$ npm install @ithena-one/mcp-governance
Use the open-source SDK (GitHub) to self-host, or skip infrastructure setup by joining the Managed Platform waitlist.
The Missing Layer for Production MCP
While the core MCP SDK handles communication, deploying it to production demands critical governance capabilities:
- Authentication: Verifying who is making a request.
- Authorization (RBAC): Defining and enforcing what authenticated users or services can do.
- Credential Management: Securely providing secrets to MCP handlers only when needed.
- Auditing & Compliance: Recording what happened for security monitoring, debugging, and compliance.
- Consistency: Implementing these features uniformly without duplicating security-sensitive code.
The Ithena Solution: SDK + Optional Platform
Ithena streamlines MCP governance with a flexible, two-part approach:
- Open-Source SDK (
@ithena-one/mcp-governance
): A TypeScript library providing a robust governance pipeline and pluggable interfaces (Identity, Roles, Permissions, Credentials, Audit, Logging) to wrap your base MCP server. - Ithena Managed Platform (Waitlist Open): A secure, scalable cloud service providing production-ready backend implementations for the SDK's interfaces. Skip the infra setup and offload the complexity of operating audit logs, RBAC engines, and secret stores.
Grounded in AWS Security Research
Ithena provides the practical framework and actionable security patterns identified by AWS researchers as essential for enterprise MCP adoption. Our implementation addresses key controls for RBAC, secrets, and auditing outlined in their analysis (arXiv:2504.08623).
Who Needs Ithena?
Role | Pain Points | Ithena Solution |
---|---|---|
AI/Backend Engineers | Security boilerplate in every handler | Focus on tool/resource logic; governance handled by SDK |
Platform/DevOps | Inconsistent governance across deployments | Standardized pipeline, logs, metrics across all MCP servers |
Security Engineers | No audit trails, loose access controls | Fine-grained RBAC, comprehensive audit records |
Enterprises | Compliance, governance silos | Standardized controls, SSO integration, audit exports |
SDK Key Features
Core Governance Interfaces
-
IdentityResolver
: JWT validation, API key lookup -
RoleStore
: Map identities to roles (LDAP, DB) -
PermissionStore
: Define what roles can do -
CredentialResolver
: Fetch secrets securely -
AuditLogStore
: Record detailed audit events -
Logger
: Structured logging with trace context
Pipeline Features
- Request-scoped identity & authorization
- Fine-grained permission control
- Just-in-time secret resolution
- Auto-sanitized audit records
- Distributed tracing support
- Configurable denial policies
Easy Integration: Get Started Quickly
Integrating Ithena is straightforward. Follow these steps to add robust governance to your MCP server without the boilerplate:
Install the SDK
Add the core package to your project.
npm install @ithena-one/mcp-governance
Import Necessary Components
Import the GovernedServer
and your base MCP server.
import { GovernedServer } from '@ithena-one/mcp-governance';
Instantiate & Configure
Instantiate GovernedServer
, passing your base server and your chosen implementations for the governance interfaces (e.g., JWT, DB roles) or simply use the Ithena Platform clients.
const governedServer = new GovernedServer(baseServer, { ...config });
Register Your Handlers
Register handlers using setToolHandler
or setRequestHandler
. Focus on your tool's logic; the pipeline automatically enforces governance.
governedServer.setToolHandler('myTool', ..., handlerFn);
Connect Transport
Attach your MCP transport layer as usual.
governedServer.connect(transport);
Focus on Features, Not Boilerplate
Compare adding robust governance manually within each handler versus letting the Ithena SDK manage the complexity.
1// BEFORE: Handling slack_post_message Manually (Full Complexity)
2import { SlackClient, MyAuth, MyRBAC, MySecrets, MyAudit, MySanitize } from './utils';
3import { CallToolRequest } from '@modelcontextprotocol/sdk/types';
4
5baseServer.setRequestHandler(
6CallToolRequestSchema, // Assuming base schema validation
7async (request: CallToolRequest, baseExtra) => {
8if (request.params.name !== 'slack_post_message') return; // Basic routing
9
10// --- Governance Boilerplate STARTS ---
11const eventId = MyAudit.generateEventId();
12const startTime = Date.now();
13let userId = null;
14let roles = [];
15let outcome = 'failure';
16let errorDetails = null;
17let slackToken = null;
18let handlerResult = null;
19
20try {
21 // 1. Manual Authentication
22 const authToken = MyAuth.extractToken(baseExtra.transportContext?.headers);
23 if (!authToken) { throw new MyAuth.AuthError('Missing token'); }
24 const decoded = await MyAuth.validateToken(authToken); // Verify sig, expiry...
25 userId = decoded.userId;
26 if (!userId) { throw new MyAuth.AuthError('Invalid user'); }
27
28 // 2. Manual Authorization (RBAC)
29 roles = await MyRBAC.getUserRoles(userId); // Fetch roles
30 const channelId = request.params.arguments?.channel_id;
31 if (!channelId) { throw new Error('channel_id missing'); }
32 const perm = `slack:channel:${channelId}:postMessage`; // Derive permission
33 const isAllowed = await MyRBAC.checkPermission(roles, perm); // Check policy
34 if (!isAllowed) { throw new MyRBAC.ForbiddenError(`Denied: ${perm}`); }
35
36 // 3. Manual Argument Validation
37 const args = request.params.arguments;
38 if (!args || typeof args.text !== 'string' || !args.text) {
39 throw new Error('Invalid or missing text argument');
40 }
41
42 // 4. Manual Credential Fetching
43 try {
44 // Potentially complex logic based on user/context
45 slackToken = await MySecrets.getSlackTokenForUser(userId);
46 } catch (credErr) {
47 throw new Error(`Credential fetch failed: ${credErr.message}`);
48 }
49 if (!slackToken) { throw new Error('Credential not found'); }
50
51 // --- FINALLY, Your Core Logic ---
52 const slackClient = new SlackClient(slackToken);
53 handlerResult = await slackClient.postMessage(
54 args.channel_id, args.text
55 );
56 // --- End Core Logic ---
57
58 outcome = 'success';
59 return { content: [{ type:'text', text:JSON.stringify(handlerResult) }] };
60
61} catch (err) {
62 // 5. Manual Error Handling & Mapping
63 console.error(`Handler failed [${eventId}]:`, err);
64 errorDetails = { message: err.message, stack: err.stack, type: err.name };
65 if (err instanceof MyRBAC.ForbiddenError) {
66 outcome = 'denied';
67 // Need to map to appropriate MCP error response
68 throw new McpError(ErrorCode.InternalError, "Access Denied", errorDetails);
69 }
70 // ... more error mapping ...
71 throw new McpError(ErrorCode.InternalError, "Handler Failed", errorDetails);
72
73} finally {
74 // --- Governance Boilerplate ENDS ---
75 // 6. Manual Auditing Finalization (Complex!)
76 const endTime = Date.now();
77 const auditRecord = {
78 eventId, timestamp: new Date().toISOString(),
79 userId, roles, method: request.method, tool: request.params?.name,
80 transport: baseExtra.transportContext,
81 outcome, durationMs: endTime - startTime,
82 // CRITICAL: Must sanitize *everything* manually & correctly!
83 params: MySanitize.deepSanitize(request.params?.arguments),
84 result: MySanitize.deepSanitize(handlerResult),
85 error: MySanitize.deepSanitize(errorDetails),
86 };
87 try {
88 await MyAudit.log(auditRecord); // Send to audit system
89 } catch (auditErr) {
90 console.error(`!! FAILED TO LOG AUDIT [${eventId}] !!:`, auditErr);
91 }
92}
93}
94);
1// AFTER: Using Ithena SDK
2import { GovernedServer, GovernedRequestHandlerExtra } from '@ithena-one/mcp-governance';
3import { z } from 'zod';
4import { SlackClient } from './utils'; // Your Slack logic
5
6// --- Configuration (Once) ---
7const governedServer = new GovernedServer(baseServer, {
8 identityResolver: /*...*/, // Validates JWT/API keys
9 roleStore: /*...*/, // Maps identities to roles
10 permissionStore: /*...*/, // Defines role permissions
11 credentialResolver: /*...*/, // Securely provides secrets
12 auditStore: /*...*/, // Records audit events
13 enableRbac: true, // Enable authorization
14 auditDeniedRequests: true, // Log denied requests
15});
16
17// Define Zod schema for validation
18const postMessageSchema = z.object({
19 jsonrpc: z.literal("2.0"),
20 id: z.union([z.string(), z.number()]),
21 method: z.literal('tools/slack_post_message'),
22 params: z.object({
23 arguments: z.object({
24 channel_id: z.string(),
25 text: z.string()
26 })
27 })
28});
29
30// --- Register Tool Handler (Clean & Focused) ---
31governedServer.setRequestHandler(
32 postMessageSchema,
33 async (request, extra: GovernedRequestHandlerExtra) => {
34 const { identity, roles, logger } = extra;
35 logger.info(`Executing slack_post_message for ${identity?.id}`, { roles });
36
37 // Get credential securely injected by pipeline
38 const token = extra.resolvedCredentials?.slackBotToken;
39 if (!token) throw new Error('Slack Token Missing');
40
41 // ---> Focus ONLY on the core logic <---
42 const slackClient = new SlackClient(token);
43 const slackResponse = await slackClient.postMessage(
44 request.params.arguments.channel_id,
45 request.params.arguments.text
46 );
47
48 // Return result; Audit automatically logged
49 return { content: [{ type: 'text', text: JSON.stringify(slackResponse) }] };
50 }
51);
The True Cost of DIY Governance
Building MCP governance features from scratch involves significant hidden engineering effort, security risks, and ongoing maintenance, diverting focus from core product development:
Feature | DIY Approach | Ithena Solution (SDK + Platform) |
---|---|---|
🔐 Identity & Auth | Build/integrate token validation, IdP logic, session mgmt. Effort: 1-3+ Weeks Risks: Auth bypass, protocol misuse. | ✅ Plug in IdentityResolver (e.g., JWT, API Key).✅ Managed Platform provides ready-to-use auth API. Benefit: Faster, secure, less code. |
🔑 RBAC Engine | Design policy model, build evaluation engine, secure storage. Effort: 2-4+ Weeks Risks: Privilege escalation, logic errors. | ✅ Plug in RoleStore /PermissionStore .✅ Managed Platform provides RBAC API & UI. Benefit: Fine-grained control, reduced complexity. |
🔏 Secret Management | Integrate secret managers, handle caching, rotation, injection. Effort: 1-2+ Weeks Risks: Secret leakage, insecure injection. | ✅ Plug in CredentialResolver for JIT secrets.✅ Managed Platform provides secure secret store API. Benefit: Secure access, eliminates hardcoding. |
📜 Audit Logging | Build pipeline, ensure sanitization, manage storage/indexing. Effort: 3-6+ Weeks Risks: Compliance failure, data loss/tampering. | ✅ Plug in AuditLogStore ; pipeline handles sanitization.✅ Managed Platform provides scalable audit storage & UI. Benefit: Reliable, compliant, easier debugging. |
🔄 Consistency & Pipeline | Build custom request pipeline for consistent checks, context mgmt. Effort: 1-2+ Weeks Risks: Inconsistent security, complex logic. | ✅ Use GovernedServer pipeline out-of-the-box.✅ Ensures consistent application of all checks. Benefit: Standardized, less boilerplate. |
🔧 Maintenance | Patching dependencies, updating security practices, fixing bugs, scaling. Significant Ongoing Cost Risks: Outdated security, bottlenecks, burden. | ✅ SDK maintained by Ithena. ✅ Managed Platform handles all infra ops. Benefit: Reduced operational load & risk. |
💰 Total | Est. 8-17+ Weeks Initial Build + Significant Ongoing Maintenance Cost & High Risk (Security breaches, compliance fines, slow dev) | ✅ Rapid Integration (Hours/Days) ✅ Minimal Maintenance (SDK) or Zero (Platform) Reduced Risk, Faster Development |
Accelerate your development, reduce security risks, and save months of engineering effort.
Architecture Overview
The GovernedServer
wraps the base MCP Server
, intercepting requests with its GovernancePipeline
. This pipeline sequentially runs your configured Identity, RBAC, and Credential resolution steps. If checks pass, it invokes your handler with enriched context (GovernedRequestHandlerExtra
), automatically generating and logging detailed audit records.
GovernedServer
(Ithena SDK) Wraps Base Server & Runs Pipeline:- ID
IdentityResolver (e.g., JWT)
- RBAC
RoleStore (e.g., DB)
- RBAC
PermissionStore (e.g., OPA)
- Cred
CredentialResolver (e.g., Vault)
- Audit
AuditLogStore (e.g., SIEM)
- Log
Logger (Your Choice)
- IDManaged Identity API
- RBACManaged RBAC API
- CredManaged Credential API
- AuditManaged Audit Log API
- (Provides API implementations for SDK interfaces)
Shape the Ithena Managed Platform (Early Adopter Program)
While the open-source SDK provides the core governance framework, implementing and operating the required backend services (audit logs, RBAC engines, secret stores) involves significant infrastructure effort.
Want a production-ready managed solution without the operational burden? The Ithena Managed Platform is currently under active development, driven by feedback from our partners. Join the Early Adopter Program to influence its direction, get early access, and secure exclusive benefits.
Platform Vision (Shaped by Early Adopters):
Planned Service | Will Provide Managed Backend For: | Target Features |
---|---|---|
Audit Service | AuditLogStore | Secure ingestion, configurable retention, UI exploration, forwarding (Datadog/Splunk/etc.). |
RBAC Service | RoleStore , PermissionStore | UI/API for roles/permissions, low-latency authz API, config audit trail. |
Secrets Service | CredentialResolver | Encrypted storage, context-based retrieval, access auditing. |
Console + SSO | Management & Teams | Web UI for config, enterprise SSO, team controls. |