CCloud Releases
Home
Following

Cloud Releases

Service catalogues and updates come from each provider's public product listing and announcements.

Explore

  • Home
  • Latest updates
  • Following

About

  • About
  • Contact
  • Privacy Policy
  • Terms of Use

Providers

  • Amazon Web Services
  • Microsoft Azure
  • Google Cloud
  • Cloudflare

Not affiliated with any cloud provider. Product names and logos belong to their owners.

  1. Providers
  2. ›Cloudflare
  3. ›Workers
  4. ›Update

Feature•Oct 1, 2026

The best way to do MCP auth just got better: Workers OAuth Provider goes v1, with a new split API and full support for MCP 2026-07-28

WorkersCloudflare · Developer platform

@cloudflare/workers-oauth-provider is now v1, with a new split API. One Worker acts as the authorization server: it signs users in and issues tokens. Your MCP server acts as the resource server, and can run in another Worker. It validates each token with the authorization server over a Service Binding, without crossing the public Internet.

  • It supports the MCP 2026-07-28 authorization specification, including Client ID Metadata Documents and issuer identification. It still works with older clients, including those using Dynamic Client Registration.
  • insufficientScope() gives you step-up authorization in one line.
  • The authorization server and the resource server can run in different Workers with different WAF and rate limiting rules.
  • One authorization server can issue tokens for many MCP servers.
  • A migration skill ships in the npm package so a coding agent can perform the upgrade.

The split API

import { OAuthAuthorizationServer, OAuthResourceServer, insufficientScope, } from "@cloudflare/workers-oauth-provider"; import { WorkerEntrypoint } from "cloudflare:workers"; // auth-server Worker: signs users in and issues tokens for both MCP servers. const authorizationServer = new OAuthAuthorizationServer({ issuer: "https://auth.example.com", resources: [ "https://calendar.example.com/mcp", "https://drive.example.com/mcp", ], scopesSupported: ["calendar:read", "calendar:write", "offline_access"], clientIdMetadataDocumentEnabled: true, }); export class AuthServer extends WorkerEntrypoint { fetch(request) { if (new URL(request.url).pathname === "/authorize") { return showConsent(request, this.env); } return authorizationServer.fetch(request, this.env, this.ctx); } validateToken(resource, token) { return authorizationServer.validateToken(resource, token, this.env); } } // calendar MCP Worker: checks tokens with AuthServer over a Service Binding. export const calendar = new OAuthResourceServer({ resourceMetadata: { resource: "https://calendar.example.com/mcp", authorization_servers: ["https://auth.example.com"], }, requiredScopes: ["calendar:read"], validateToken: (env) => env.AUTH_SERVER.validateToken, handler: { fetch(request, env, ctx) { if ( request.method === "POST" && !ctx.auth.scope.includes("calendar:write") ) { return insufficientScope(ctx.auth, ["calendar:read", "calendar:write"]); } return handleMcp(request, ctx.props); }, }, });

import { OAuthAuthorizationServer, OAuthResourceServer, insufficientScope, } from "@cloudflare/workers-oauth-provider"; import { WorkerEntrypoint } from "cloudflare:workers"; // auth-server Worker: signs users in and issues tokens for both MCP servers. const authorizationServer = new OAuthAuthorizationServer<Env>({ issuer: "https://auth.example.com", resources: [ "https://calendar.example.com/mcp", "https://drive.example.com/mcp", ], scopesSupported: ["calendar:read", "calendar:write", "offline_access"], clientIdMetadataDocumentEnabled: true, }); export class AuthServer extends WorkerEntrypoint<Env> { fetch(request: Request) { if (new URL(request.url).pathname === "/authorize") { return showConsent(request, this.env); } return authorizationServer.fetch(request, this.env, this.ctx); } validateToken(resource: string, token: string) { return authorizationServer.validateToken(resource, token, this.env); } } // calendar MCP Worker: checks tokens with AuthServer over a Service Binding. export const calendar = new OAuthResourceServer<Env, AuthProps>({ resourceMetadata: { resource: "https://calendar.example.com/mcp", authorization_servers: ["https://auth.example.com"], }, requiredScopes: ["calendar:read"], validateToken: (env) => env.AUTH_SERVER.validateToken, handler: { fetch(request, env, ctx) { if ( request.method === "POST" && !ctx.auth.scope.includes("calendar:write") ) { return insufficientScope(ctx.auth, ["calendar:read", "calendar:write"]); } return handleMcp(request, ctx.props); }, }, });

In the example, env.AUTH_SERVER.validateToken is that Service Binding call. The calendar Worker needs no KV namespace of its own.

{ "name": "calendar-mcp", "main": "src/index.ts", // Set this to today's date "compatibility_date": "2026-10-14", "services": [ { "binding": "AUTH_SERVER", "service": "auth-server", "entrypoint": "AuthServer", }, ], }

name = "calendar-mcp" main = "src/index.ts" # Set this to today's date compatibility_date = "2026-10-14" [[services]] binding = "AUTH_SERVER" service = "auth-server" entrypoint = "AuthServer"

OAuthResourceServer publishes the RFC 9728 protected resource metadata that MCP clients use to find your authorization server. It answers requests without a token with a 401 challenge that points to that metadata. It also rejects tokens issued for any other resource.

You can still use OAuthProvider as both the authorization server and the MCP server. For most 0.x deployments, the only required change is to add resourceMetadata: { resource }.

Other updates and helpers

  • Consent page and upstream sign-in helpers implement the MCP confused deputy protections.
  • Sliding refresh token expiry with refreshTokenIdleTTL.
  • Resumable KV cleanup with purgeExpiredData().
  • An internal reason on every error passed to onError.

Upgrade with the migration skill

Read the original announcement↗

More from Workers

All Workers updates →
  1. Workers subrequests now preserve context for BYOIP destinations

    Cloudflare now preserves Workers context when a subrequest targets a Cloudflare-proxied hostname using Bring Your Own IP (BYOIP). These requests are identified as Cloudflare-to-Cloudflare traffic instead of external Internet traffic.

    Workers•Feature•Oct 13, 2026
  2. Cloudflare API MCP server sends Workers Issues as MCP Events

    Workers Issues provides built-in error monitoring for Cloudflare Workers. It detects production failures and groups related failures into issues without an SDK or application wrapper.

    Workers•Feature•Oct 13, 2026
  3. Workers Builds now posts preview URLs in seconds

    Workers Builds now consistently posts preview URLs to GitHub pull requests and GitLab merge requests within a few seconds of a build completing, so you can start testing and reviewing your changes sooner. Previously, posting preview URLs could often take minutes.

    Workers•Preview•Oct 12, 2026
  4. More time for requests to finish during Workers runtime updates

    Pending requests and connections to Workers now have a grace period of up to 20 minutes during Workers runtime updates. Previously, the grace period was up to 30 seconds.

    Workers•Feature•Oct 12, 2026
  5. Run OpenCode 2.0 on Cloudflare with the Agents SDK

    The Agents SDK now supports OpenCode 2.0 through the experimental OpenCodeHarness. Run OpenCode inside a plain Durable Object, with sessions stored in SQLite and Lifecycle jobs that wake interrupted work after eviction.

    Workers•Feature•Oct 12, 2026