-
Notifications
You must be signed in to change notification settings - Fork 57
Description
MCP Version
0.3.4
Laravel Version
12.x
PHP Version
8.4
Description
The OAuth client registration endpoint returns redirect_uris: [] (empty array) even though the data is correctly stored in the database. This breaks OAuth 2.1 dynamic client registration for MCP clients like Claude Desktop.
Root Cause
In OAuthRegisterController.php, the response uses camelCase to access Passport Client attributes:
return response()->json([
// ...
'grant_types' => $client->grantTypes, // camelCase
'redirect_uris' => $client->redirectUris, // camelCase
// ...
]);But Laravel's Attribute accessor system has a quirk: when you access $client->redirectUris (camelCase), it looks for $this->attributes['redirectUris'] to pass as $value to the accessor. Since the actual key is redirect_uris (snake_case), $value is null and the accessor returns an empty array.
Reproduction
$client = new \Laravel\Passport\Client();
$client->setRawAttributes([
'redirect_uris' => json_encode(['https://example.com']),
]);
$client->redirectUris; // [] - empty (camelCase BROKEN)
$client->redirect_uris; // ['https://example.com'] - works (snake_case)Suggested Fix
Use snake_case attribute access in OAuthRegisterController.php:
return response()->json([
'client_id' => (string) $client->id,
'grant_types' => $client->grant_types, // snake_case
'response_types' => ['code'],
'redirect_uris' => $client->redirect_uris, // snake_case
'scope' => 'mcp:use',
'token_endpoint_auth_method' => 'none',
]);Workaround
Create a custom Passport Client model that reads from $attributes directly instead of relying on $value:
// app/Models/Passport/Client.php
class Client extends \Laravel\Passport\Client
{
protected function redirectUris(): Attribute
{
return Attribute::make(
get: function (mixed $value, array $attributes): array {
$redirectUris = $attributes['redirect_uris'] ?? $value;
// ... rest of accessor logic
},
);
}
}
// AppServiceProvider
Passport::useClientModel(Client::class);