Skip to content
Putting technology to work.
Insights to guide decisions and action.

Search articles

Protecting custom MCP servers with OAuth 2.1 — authentication design for custom MCP integrations (2026)

Table of contents · 9 items

In late April 2026, "My Notes on Thoroughly Learning OAuth 2.1 to Build an MCP Server" hit the Zenn Trending list. As projects involving public exposure or client-facing delivery of MCP (Model Context Protocol) servers grow, "How should we handle authentication?" has become a question raised in nearly every consultation.

In our custom development practice, we handled four consecutive projects over the past six months aimed at "turning internal corporate systems into MCP servers to allow secure invocation by client AI agents." In this article, we break down how to protect custom-built MCP servers with OAuth 2.1 from the practical perspective of custom development.

Why OAuth 2.1 is becoming the de facto standard for MCP servers

While the specification offers several authentication methods for MCP servers, OAuth 2.1 is rapidly becoming virtually the sole option when building on the premise of integrating into a client's production environment in custom development.

Authentication methodViability in custom developmentRationale
API KeyRotation and auditing are weak
Basic authenticationPlaintext password transmission, out of the question
mTLSDistributing client certificates across client environments is cumbersome
OAuth 2.0Older specification causing confusion around PKCE and Implicit flow
OAuth 2.1Unified on the secure side by mandating PKCE and deprecating Implicit flow
OIDCAuthentication also possible via OAuth 2.1 + ID token

OAuth 2.1 is a specification that mandates OAuth 2.0 best practices, offering the advantage that modern baseline assumptions—such as mandatory PKCE and removal of the Implicit flow—can be taken for granted when exposing MCP servers in custom development.

Minimal flow for MCP × OAuth 2.1

Here is the minimal access flow architecture for an MCP server exposed in custom development.

[顧客側AIエージェント]              [認可サーバー]              [MCPサーバー]
   ↓ 1. 認可リクエスト + PKCE
   ────────────────────────────────→
                                    ↓ 2. ユーザ認証
                                    ↓ 3. 同意画面(スコープ表示)
   ←────────────────────────────────
   ↓ 4. 認可コード受領
   ↓ 5. トークンエンドポイント呼び出し(PKCE verifier)
   ────────────────────────────────→
                                    ↓ 6. アクセストークン発行
   ←────────────────────────────────
   ↓ 7. MCPツール呼び出し(Bearer)
   ──────────────────────────────────────────────────────────────→
                                                                    ↓ 8. トークン検証
                                                                    ↓ 9. スコープ確認
                                                                    ↓ 10. ツール実行
   ←──────────────────────────────────────────────────────────────

The key is an architecture that separates the authorization server from the MCP server. Because MCP tools will be added or removed over time in custom development, centralizing the authorization server ensures that authentication implementations do not need to be rebuilt every time a new tool is added.

Scope design tips to master in custom development

OAuth scopes directly correlate to MCP tool and resource granularity. Below is standard scope design for operation in custom development.

Scope namingExamplesUsage split in custom development
mcp:tool:*mcp:tool:db.queryFine-grained permission for individual tools
mcp:resource:*mcp:resource:customer.readResource-level (combined with CRUD)
mcp:scope:*mcp:scope:read-onlyPresets (read-only, etc.)
mcp:tenant:*mcp:tenant:acme-corpMulti-tenant isolation

In particular, multi-tenant isolation (mcp:tenant:*) is critical when running MCP servers for multiple clients on a single infrastructure in custom development. Unless you mandate the tenant claim in tokens and implement logic where the MCP server immediately rejects requests with mismatched claims, incidents crossing tenant boundaries will occur.

This represents the authentication and authorization layer counterpart to the "API-to-MCP bridging" discussed in Design Patterns for Converting Existing APIs into MCP Servers.

Token lifetimes and refresh: Operationally viable configurations for custom development

Because MCP servers are invoked by long-running agents, token lifetime design directly affects operations.

Token typeRecommended lifetimeOperational design in custom development
Access token5–15 minutesPremised on the agent refreshing as needed
Refresh token30–90 daysRotated on each use (revoked upon reuse detection)
Consent expiration1 yearPrompt user for re-consent annually
MCP sessionEquivalent to access tokenStateless per session/request

Refresh Token Rotation is strongly recommended as an OAuth 2.1 best practice and should be included in project estimates as a mandatory implementation whenever public MCP servers are delivered in custom development.

Five major operational pitfalls

Here we review the pitfalls commonly encountered during implementation in the field.

PitfallConsequenceMeasure
Co-locating authorization server within applicationOutages take down MCP alongside the appSeparate authorization server into a distinct process or service
Embedding excessive claims into access tokenSize bloat triggers HTTP 426 or exceeds API gateway limitsKeep claims minimal; distribute only verification keys via JWKS
Reusing refresh tokensExpands blast radius during leaksRotation + reuse detection mandatory
Refining scopes after releaseBreaks all existing integrationsStart with coarse granularity and split into *:read and *:write later
Tokens remaining in plaintext in logsCatastrophic impact if logs leakOverride OAuth library loggers and mask values in structured logging

In particular, "co-locating the authorization server inside the application" is an anti-pattern frequently seen in early-stage custom development. Separating them once operations have begun requires structural refactoring, so agreeing to place it in a separate layer from the start within the SOW is prudent.

Permission boundaries for multi-tenant MCP servers

When designing architectures where multiple clients share the same MCP infrastructure in custom development, OAuth scopes and claim-based permission boundaries are critical lifelines. Here is the minimal implementation setup:

// MCP サーバー側のミドルウェア(疑似コード)
async function authenticate(request) {
  const token = extractBearer(request);
  const claims = await verifyJWT(token, jwksUri);

  // 1. スコープ確認
  if (!claims.scope?.includes(`mcp:tool:${request.toolName}`)) {
    throw new ForbiddenError('insufficient_scope');
  }

  // 2. テナント境界
  if (claims.tenant !== request.tenantId) {
    throw new ForbiddenError('tenant_mismatch');
  }

  // 3. 監査ログ(テナント / 呼び出し者 / ツール)
  await auditLog({
    tenant: claims.tenant,
    sub: claims.sub,
    tool: request.toolName,
    timestamp: Date.now(),
  });

  return claims;
}

The key is ensuring the three-stage check (scope → tenant → audit log) executes first in middleware. Missing even one check leads to tenant boundary violations or compliance failures.

This serves as the authorization-layer counterpart to the "guardrails against destructive operations" discussed in Production DB Deletion Guardrails for AI Agents. In the era of AI agents, systems must be architected to physically block actions on the machine side under the premise that "agents, not just humans, might connect to the wrong tenant."

Delivery checklist — 12 immediately usable items for custom development

  • Authorization flow is implemented with OAuth 2.1 (PKCE mandatory)
  • Implicit Flow and ROPC are completely eliminated
  • Authorization server runs as a separate process or service from MCP server
  • Access token lifetime is set to 5–15 minutes
  • Refresh Token Rotation is active; immediate revocation upon reuse detection
  • MCP middleware executes three-stage check: scope → tenant → audit
  • Public key distribution via JWKS is operational
  • Audit logs are isolated and stored per tenant
  • OAuth library loggers mask tokens
  • Scope naming conventions are documented
  • Defenses against known vulnerabilities (CSRF, open redirect, etc.) are verified
  • Budget for annual security review is specified in SOW

Conclusion: MCP authentication is the foundation supporting trust in custom development

Because an MCP server sits on the shortest path between "tools and client data," the quality of the authentication layer directly governs the overall reliability of systems built through custom development. Designing modern configurations—OAuth 2.1 + PKCE + Refresh Token Rotation + audit logs—from the outset falls squarely within the custom development team's responsibility.

At GleamHub, we provide a standardized package that comprehensively executes "authentication design → implementation → operational design" across three steps when launching new MCP server projects. Whether you are thinking, "We want to expose an MCP server externally but are stuck on authentication," or "We want an audit of an authentication layer implemented by another vendor," please feel free to reach out through our contact form.

Sources

Share this articleXFacebook
Kakeru Suzuki

Fascinated by the possibilities of technology, has had a deep interest in programming and digital art since student days

Turn this article's theme into your company's next step

Concrete steps forward for your organization.

We organize your desired architecture, legacy systems, and operational requirements to formulate your next steps toward execution.

  • Desired architecture
  • Integration with existing environments
  • Operational requirements
Consult on development & operations initiatives

You can consult with us from the initial conceptual stage. Details from this article will be carried over to the inquiry form.

Receive the latest articles by email