Skip to main content
Glama
pravin-khandke

identity-aware-mcp-server

Identity-Aware MCP Server — Companion Project

A production-ready reference implementation of an MCP server that requires OAuth 2.1 Bearer tokens, validates them against a JWKS endpoint, enforces tool-level scopes and roles, and logs every access decision with the full delegation chain.

Companion project for: "Building an Identity-Aware MCP Server" (DZone, June 2026)

What this server does

  • Authenticates every agent — no anonymous or shared-key access

  • Validates JWTs using stateless JWKS-based validation (no DB lookups)

  • Enforces tool-level authorization — each tool declares required scopes and roles

  • Maintains a tool allow-list — infrastructure-level enforcement (not prompt-level)

  • Logs the full delegation chain — every action traces back to a human identity

  • Serves MCP discovery endpoints — clients auto-discover auth configuration

Related MCP server: enterprise-auth-mcp-server

Architecture

Agent (Bearer Token)
    │
    ▼
┌─────────────────────────────┐
│  1. Token Validation (JWKS) │  ← Is this a valid token?
├─────────────────────────────┤
│  2. Tool Allow-List Gate    │  ← Is this tool allowed at all?
├─────────────────────────────┤
│  3. Scope + Role Check      │  ← Can THIS agent call THIS tool?
├─────────────────────────────┤
│  4. Tool Handler            │  ← Execute the actual operation
├─────────────────────────────┤
│  5. Audit Log               │  ← Who did what, on whose behalf?
└─────────────────────────────┘

Requirements

  • Python 3.12+

  • An OIDC-compatible identity provider (Auth0 free tier works)

Quick Start

# 1. Clone and set up
cd code
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

# 2. Configure (edit with your Auth0/Okta details)
cp .env.example .env

# 3. Run the server
python src/server.py

# 4. In another terminal — run the demo agent
python demo/agent.py --demo

Demo Mode

The --demo flag generates self-signed tokens locally so you can test the full flow without configuring an OAuth provider:

python demo/agent.py --demo

This runs three simulated agents:

  • Alice (developer, database.read + email.send scopes) → can read, cannot write

  • Bob (admin, full scopes) → can do everything

  • Carol (contractor, zero scopes) → blocked from everything

Testing

python -m pytest tests/ -v

Expected output:

tests/test_server.py::test_protected_resource_endpoint PASSED
tests/test_server.py::test_authorization_server_endpoint PASSED
tests/test_server.py::test_no_token_returns_401 PASSED
tests/test_server.py::test_invalid_token_returns_401 PASSED
tests/test_server.py::test_expired_token_returns_401 PASSED
tests/test_server.py::test_valid_token_read_customer_succeeds PASSED
tests/test_server.py::test_missing_scope_returns_403 PASSED
tests/test_server.py::test_write_scope_required_for_update PASSED
tests/test_server.py::test_missing_role_returns_403 PASSED
tests/test_server.py::test_admin_role_succeeds PASSED
tests/test_server.py::test_unknown_tool_returns_404 PASSED
tests/test_server.py::test_audit_log_entries PASSED

Key Files

File

Purpose

src/server.py

Main MCP server — configuration, routing, auth enforcement

src/auth/middleware.py

JWKS cache, TokenValidator, require_auth decorator

src/auth/discovery.py

OAuth 2.1 discovery endpoints (RFC 8414 + RFC 9728)

src/tools/database.py

Example tools with scope and role declarations

src/audit/logger.py

JSON Lines audit log with delegation-chain tracing

demo/agent.py

Demo agent that connects with scoped tokens

Production Hardening

Before deploying:

  • Use a real OAuth 2.1 provider (Auth0, Okta, Entra ID) — not demo keys

  • Enforce HTTPS only — reject HTTP at the network level

  • Set short token lifetimes (15-60 minutes) with refresh token rotation

  • Sanitize Bearer tokens from request logs

  • Run behind a reverse proxy with rate limiting

  • Use PostgreSQL-backed token storage for multi-instance deployments

Article Reference

  • Title: Building an Identity-Aware MCP Server

  • Publication: DZone

  • Date: June 2026

  • Author: Pravin Khandke

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers