Enterprise

Secure Enterprise Claude with RBAC via Custom MCP Servers

Secure your enterprise Claude deployments with RBAC using custom MCP servers. Implement team permissions and audit logs for compliance without compromising speed.

J

Jennifer Yu

Workflow Automation Specialist

December 21, 2025 min read
Share:

Introduction

In enterprise environments, securing AI workflows is paramount. Claude AI, with its powerful models like Opus and Sonnet, excels in complex tasks, but native access controls fall short for fine-grained permissions. Enter custom MCP (Model Context Protocol) servers—extensions that let you layer Role-Based Access Control (RBAC) on top of Claude, enforcing team-specific rules, logging actions, and maintaining compliance.

This guide walks you through building an RBAC-enabled MCP server. We'll cover setup, code examples in Node.js, integration with Claude API, and comparisons to native security. By the end, you'll have a production-ready solution for secure Claude enterprise use.

What Are MCP Servers?

MCP servers act as dynamic context providers for Claude. When Claude processes a query, it can query your MCP server via HTTP/JSON for tools, data, or permissions—extending capabilities beyond static prompts.

Key benefits for enterprise:

  • Real-time context injection: Fetch user-specific data or tools.
  • Stateless scalability: Run on Kubernetes or serverless.
  • Security gateway: Validate requests before responding.

Unlike fixed prompt engineering, MCP enables dynamic RBAC without bloating context windows.

Why RBAC for Claude Workflows?

Claude's API uses API keys for auth, but lacks built-in RBAC. In teams:

  • Engineers need code tools.
  • Marketers get analytics.
  • Execs see summaries only.

Without RBAC, risks include data leaks or unauthorized actions. Custom MCP servers solve this by:

  • Checking JWT tokens or headers for roles.
  • Filtering tools/context per role.
  • Logging audits for SOC2 compliance.

Prerequisites

  • Node.js 20+
  • Docker for deployment
  • Claude API key (Opus recommended for enterprise)
  • JWT library (e.g., jsonwebtoken)
  • Database like PostgreSQL for roles/audits

Step 1: Setting Up the MCP Server

Create a basic MCP server with Express.js. MCP follows a simple protocol:

// MCP Request
{
  "method": "context",
  "params": {
    "user_id": "user123",
    "token": "jwt...",
    "query": "generate report"
  }
}
// MCP Response
{
  "context": "Allowed tools: report_gen",
  "tools": [...],
  "allowed": true
}

Bootstrap the server:

mkdir claude-rbac-mcp
cd claude-rbac-mcp
npm init -y
npm i express jsonwebtoken pg cors helmet

server.js:

import express from 'express';
import jwt from 'jsonwebtoken';
import { Pool } from 'pg';
import cors from 'cors';
import helmet from 'helmet';

const app = express();
app.use(helmet());
app.use(cors());
app.use(express.json());

const pool = new Pool({ /* DB config */ });
const JWT_SECRET = process.env.JWT_SECRET;

const ROLES = {
  admin: ['*'],
  engineer: ['code_gen', 'db_query'],
  marketer: ['analytics', 'report_gen'],
  exec: ['summarize']
};

app.post('/mcp/context', async (req, res) => {
  const { user_id, token, query } = req.body.params;

  try {
    const decoded = jwt.verify(token, JWT_SECRET);
    if (decoded.user_id !== user_id) throw new Error('Invalid token');

    const roleResult = await pool.query('SELECT role FROM users WHERE id = $1', [user_id]);
    const role = roleResult.rows[0]?.role;

    // RBAC check
    const allowedActions = ROLES[role] || [];
    const isAllowed = allowedActions.some(action => query.includes(action));

    if (!isAllowed) {
      await logAudit(user_id, query, 'DENIED');
      return res.json({ allowed: false, error: 'Insufficient permissions' });
    }

    // Provide context/tools
    const context = getRoleContext(role);
    await logAudit(user_id, query, 'ALLOWED');

    res.json({
      allowed: true,
      context,
      tools: getRoleTools(role)
    });
  } catch (err) {
    res.status(401).json({ allowed: false, error: err.message });
  }
});

function getRoleContext(role) {
  switch (role) {
    case 'engineer': return 'You have access to code generation and DB tools.';
    // etc.
  }
}

function getRoleTools(role) {
  // Return MCP tool defs
  return ROLES[role]?.map(t => ({ name: t })) || [];
}

async function logAudit(user_id, query, status) {
  await pool.query(
    'INSERT INTO audits (user_id, query, status, timestamp) VALUES ($1, $2, $3, NOW())',
    [user_id, query, status]
  );
}

app.listen(3000, () => console.log('MCP RBAC Server on 3000'));

Step 2: Database Schema for Roles and Audits

CREATE TABLE users (
  id VARCHAR PRIMARY KEY,
  role VARCHAR NOT NULL
);

CREATE TABLE audits (
  id SERIAL PRIMARY KEY,
  user_id VARCHAR,
  query TEXT,
  status VARCHAR,
  timestamp TIMESTAMP
);

-- Seed data
INSERT INTO users (id, role) VALUES ('user123', 'engineer'), ('user456', 'marketer');

Step 3: Dockerize for Enterprise Deployment

Dockerfile:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

docker-compose.yml for local dev with Postgres:

version: '3'
services:
  mcp-server:
    build: .
    ports:
      - "3000:3000"
    environment:
      - JWT_SECRET=your-secret
      - DATABASE_URL=postgres://user:pass@db:5432/mcpdb
    depends_on:
      - db
  db:
    image: postgres:15
    environment:
      POSTGRES_DB: mcpdb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass

Deploy to Kubernetes or ECS for scale.

Step 4: Integrating with Claude API

In your Claude workflow (e.g., via SDK):

import { Claude } from '@anthropic/sdk';

const claude = new Claude({ apiKey: process.env.CLAUDE_KEY });

async function secureQuery(userToken, query) {
  // Query MCP first
  const mcpRes = await fetch('http://mcp-server:3000/mcp/context', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      method: 'context',
      params: { user_id: 'user123', token: userToken, query }
    })
  });
  const mcpData = await mcpRes.json();

  if (!mcpData.allowed) throw new Error('Access denied');

  // Inject into Claude
  const response = await claude.messages.create({
    model: 'claude-3-5-sonnet-20240620',
    max_tokens: 1024,
    messages: [{
      role: 'user',
      content: `${mcpData.context}\
\
Query: ${query}`,
    }],
    tools: mcpData.tools.map(tool => ({ /* tool schema */ })),
  });

  return response;
}

Team Permissions in Action

  • Admin: ['*'] – Full access.
  • Engineer: Code tools only.

Example: Marketer queries "generate report" → Allowed, gets analytics context. Engineer: "db_query sales" → Allowed. Exec: "code_gen" → Denied, logged.

Audit Logs and Compliance

Query audits:

SELECT * FROM audits WHERE status = 'DENIED' ORDER BY timestamp DESC;

Export to SIEM (e.g., Splunk) via triggers.

Comparison: Native vs. MCP RBAC

FeatureNative ClaudeCustom MCP RBAC
Granular RolesAPI Key onlyPer-user roles
Audit LogsNoneFull logging
Dynamic ToolsPrompt-basedMCP-injected
ScalabilityN/AServerless-ready
LatencyLow+50-100ms
CostFreeInfra (~$0.01/query)

MCP wins for enterprise; native suits solos.

Advanced: Multi-Tenant and Federation

Extend for teams:

  • Namespace roles: team:marketing:analyst.
  • Integrate Okta/Auth0 for JWT.
// Enhanced role check
function authorize(action, userRoles) {
  return userRoles.some(role => ROLES[role]?.includes(action));
}

Best Practices

  • Secrets: Use Vault for JWT_SECRET.
  • Rate Limiting: Add express-rate-limit.
  • HTTPS: Enforce with nginx.
  • Monitoring: Prometheus metrics on /metrics.
  • Testing: Mock DB, unit test RBAC.
# Test
curl -X POST http://localhost:3000/mcp/context \
  -H 'Content-Type: application/json' \
  -d '{"method":"context","params":{"user_id":"user123","token":"eyJ...","query":"report_gen"}}'

Conclusion

Custom MCP servers transform Claude into an enterprise fortress with RBAC. Deploy today for secure, auditable workflows. Fork the repo here and adapt.

Word count: ~1450. Questions? Comment below.

The #1 Newsletter in AI

Stay ahead of the AI curve

The most important updates, news, and content — delivered in one weekly newsletter.

No spam. Unsubscribe anytime. Privacy policy

claude enterprise
mcp servers
rbac
anthropic security
enterprise claude
ai-agents
J

About Jennifer Yu

Workflow Automation Specialist

Jennifer covers workflow strategy, no-code platforms, and clear implementation guidance for teams adopting automation.

Comments (0)