mcp icon indicating copy to clipboard operation
mcp copied to clipboard

Bug: maybeAddMcpScope not executed in production when route caching is enabled

Open jsandfordhughescoop opened this issue 2 months ago • 2 comments

Laravel Package Version

0.3.0

Laravel Version

12.34

PHP Version

8.3

Database Driver & Version

MySQL

Description

When MCP registers its OAuth routes via Registrar::oauthRoutes(), it calls maybeAddMcpScope() internally to ensure the mcp:use Passport scope exists.

However, when route caching is enabled (php artisan route:cache), the mcp:use scope isn’t registered in production, and /oauth/authorize requests that include scope=mcp:use fail — typically returning a 302 redirect without creating an auth code or token.

This works fine in local environments without route caching, which makes it a subtle, production-only bug.

Expected Behavior

The mcp:use scope should be registered consistently, even when routes are cached.

Root Cause

maybeAddMcpScope() runs as part of route registration. When routes are cached, that logic no longer executes, so Passport::tokensCan() never runs in production.

Potential Fix

The straightforward fix would be to move Passport::tokensCan(['mcp:use' => 'Use MCP server']) into a provider’s boot() method so it executes at application boot time instead of during route registration.

Hesitation / Design Consideration

However, doing this inside a provider introduces behavioral changes: • This could override or merge incorrectly with user-defined scopes and may cause unexpected scope pollution in non-MCP OAuth setups. • Therefore, it could be considered a breaking change for applications using Passport with their own scope definitions.

Steps To Reproduce

Steps to Reproduce 1. Install MCP in a Laravel app with Passport. 2. Run php artisan route:cache. 3. Attempt an /oauth/authorize request with scope=mcp:use. 4. Observe a 302 redirect or invalid_scope behavior. 5. Clear the route cache (php artisan route:clear) — it starts working again.

jsandfordhughescoop avatar Oct 21 '25 09:10 jsandfordhughescoop

Experienced this today. Found this one which cut down my troubleshooting time. Thank you!

Solved it by just adding the scope myself to my list of Passport scopes using Passport::tokensCan().

ErikBernskiold avatar Oct 27 '25 09:10 ErikBernskiold

Experienced this today. Found this one which cut down my troubleshooting time. Thank you!

Solved it by just adding the scope myself to my list of Passport scopes using Passport::tokensCan().

Glad it helped. Thats exactly what we did.

jsandfordhughescoop avatar Oct 27 '25 10:10 jsandfordhughescoop