PHPackages                             shaxzodbek-uzb/laravel-mcp-auth - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. shaxzodbek-uzb/laravel-mcp-auth

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

shaxzodbek-uzb/laravel-mcp-auth
===============================

Bring-your-own-IdP OAuth 2.1 resource server for the official laravel/mcp package: external token validation (JWT/JWKS + RFC 7662 introspection), RFC 8707 audience binding, scope enforcement, and RFC 9728 discovery.

v0.1.1(today)00[1 PRs](https://github.com/shaxzodbek-uzb/laravel-mcp-auth/pulls)MITPHPPHP ^8.2CI passing

Since Jun 20Pushed todayCompare

[ Source](https://github.com/shaxzodbek-uzb/laravel-mcp-auth)[ Packagist](https://packagist.org/packages/shaxzodbek-uzb/laravel-mcp-auth)[ Docs](https://github.com/shaxzodbek-uzb/laravel-mcp-auth)[ RSS](/packages/shaxzodbek-uzb-laravel-mcp-auth/feed)WikiDiscussions main Synced today

READMEChangelog (2)Dependencies (10)Versions (4)Used By (0)

laravel-mcp-auth
================

[](#laravel-mcp-auth)

**Bring-your-own-IdP OAuth 2.1 resource server for [`laravel/mcp`](https://github.com/laravel/mcp).**Validate access tokens from Auth0, Keycloak, Clerk, WorkOS, Logto, Okta — or your own authorization server — with RFC 8707 audience binding, per-tool scope enforcement, and RFC 9728 discovery. No Passport required.

[![Packagist Version](https://camo.githubusercontent.com/0b1e1c9e7c8403aefe75153863d2e24ce67e9d80f5ad5088cdcd53673d4acfbf/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f736861787a6f6462656b2d757a622f6c61726176656c2d6d63702d617574682e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/shaxzodbek-uzb/laravel-mcp-auth)[![Total Downloads](https://camo.githubusercontent.com/d524562bdcce01f78625f03c64dbacf4d88fb640c8a31a2dea733af465e0d454/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f736861787a6f6462656b2d757a622f6c61726176656c2d6d63702d617574682e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/shaxzodbek-uzb/laravel-mcp-auth)[![PHP Version](https://camo.githubusercontent.com/60f0d5d2817110af0e9dd76972a5c0c4380f3e684d736386bae6056b51d47bf8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f736861787a6f6462656b2d757a622f6c61726176656c2d6d63702d617574682f7068703f7374796c653d666c61742d737175617265)](https://packagist.org/packages/shaxzodbek-uzb/laravel-mcp-auth)[![Laravel](https://camo.githubusercontent.com/79ada71b6ceb5b6ae3fe0a8fef339cc509adac828debbdc7bac22ea17526be4f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d3131253230253743253230313225323025374325323031332d4646324432303f7374796c653d666c61742d737175617265266c6f676f3d6c61726176656c)](https://laravel.com)[![Tests](https://camo.githubusercontent.com/1efc535fd1f7ad8190ead813a66de6cad506aef023765ebbbb2700156b4a6465/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d353425323070617373696e672d737563636573733f7374796c653d666c61742d737175617265)](https://github.com/shaxzodbek-uzb/laravel-mcp-auth/actions)[![License](https://camo.githubusercontent.com/a02c8fa23dc5ee7f11fe3f5bda948fbf4cbe6f472e79f7ecbf976010ab916bc3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f736861787a6f6462656b2d757a622f6c61726176656c2d6d63702d617574682e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)

---

🤔 Why this package?
-------------------

[](#-why-this-package)

The official `laravel/mcp` package already ships excellent OAuth scaffolding — `Mcp::oauthRoutes()`, the RFC 9728 / RFC 8414 / RFC 7591 discovery and dynamic-client-registration endpoints, and the `AddWwwAuthenticateHeader` middleware. It's the foundation this package is built on, and you should use it.

But that scaffolding is designed around **Laravel Passport acting as your authorization server**, and the protected MCP route is guarded by Laravel's stock `auth:api` / `auth:sanctum` guards. There is no built-in path to **accept tokens minted by an external identity provider** — the increasingly common setup where your IdP is Auth0, Keycloak, Clerk, WorkOS, Okta, Logto, or a homegrown OAuth server, and your Laravel app is purely a **resource server** that must verify those tokens.

`laravel-mcp-auth` fills exactly that gap. It is a drop-in **resource server**: it validates the bearer token itself — locally as a JWT (RFC 9068) against your IdP's JWKS or a static key, or remotely as an opaque token via RFC 7662 introspection — enforces the RFC 8707 audience binding so a token minted for another service can't be replayed against yours, applies per-route scope checks with proper `403 insufficient_scope` step-up, and serves RFC 9728 discovery so MCP clients can find your authorization server. It plugs into the *same* route names the framework's `AddWwwAuthenticateHeader` already looks for, so the official 401 → discovery handshake keeps working even on Sanctum or fully custom setups.

`laravel/mcp` built-in OAuth**`laravel-mcp-auth`**RFC 9728 Protected Resource Metadata✅✅`WWW-Authenticate` 401 handshake✅✅Authorization server = **Passport**✅ built-innot requiredAuthorization server = **external IdP**❌✅ *(the whole point)*Actually **verifies the token**❌ delegates to `auth:*`✅ JWT/JWKS + RFC 7662JWT (RFC 9068) via JWKS / public key❌✅Opaque token via RFC 7662 introspection❌✅RFC 8707 audience binding enforced❌✅Per-tool scope enforcement + step-up❌✅Works without Passport (Sanctum/custom)❌✅> Use `laravel/mcp` for the server framework and discovery primitives. Add `laravel-mcp-auth` when your tokens come from somewhere other than Passport.

---

✨ Features
----------

[](#-features)

- **Bring your own IdP.** Anything that issues standards-compliant OAuth 2.1 tokens: Auth0, Keycloak, Clerk, WorkOS, Logto, Okta, Azure AD, or your own server.
- **Two validation strategies.** Self-contained `jwt` tokens verified locally (RFC 9068, JWKS or static PEM), or opaque tokens via the IdP's `introspection` endpoint (RFC 7662) with short result caching for fast revocation.
- **RFC 8707 audience binding.** Tokens minted for a different resource are rejected — no cross-service token replay.
- **Per-tool scopes + step-up.** Declare scopes per route; missing scopes return `403` with `WWW-Authenticate: Bearer error="insufficient_scope", scope="..."`.
- **RFC 9728 discovery, drop-in.** Serves `/.well-known/oauth-protected-resource` under the route names the framework's `AddWwwAuthenticateHeader` expects — works with Sanctum or custom auth.
- **Hardened by default.** Bearer header only (query/body tokens rejected), SSRF-safe JWKS/introspection fetches (HTTPS-only, private-range blocked), strict claim canonicalization, constant-time audience comparison.
- **Quality bar.** 54 Pest tests, PHPStan level 6, Pint (strict types) — all green.

---

✅ Requirements
--------------

[](#-requirements)

- PHP **8.2+** (`ext-json`, `ext-openssl`)
- Laravel **11, 12, or 13**
- [`laravel/mcp`](https://github.com/laravel/mcp) (to expose MCP servers — listed as a suggested dependency)
- An external OAuth 2.1 authorization server / IdP

---

📦 Installation
--------------

[](#-installation)

```
composer require shaxzodbek-uzb/laravel-mcp-auth
```

Then run the installer to publish the config and print setup guidance:

```
php artisan mcp-auth:install
```

The service provider (`Blaze\McpAuth\McpAuthServiceProvider`) and the `McpAuth` facade are auto-discovered. The installer publishes `config/mcp-auth.php` and registers the `mcp-auth` middleware alias.

---

🚀 Quickstart
------------

[](#-quickstart)

### 1. Point at your IdP (`.env`)

[](#1-point-at-your-idp-env)

```
# Your authorization server (advertised in discovery metadata)
MCP_AUTH_AUTHORIZATION_SERVER=https://your-idp.example.com

# JWT strategy: validate tokens locally against the IdP's JWKS
MCP_AUTH_STRATEGY=jwt
MCP_AUTH_JWKS_URI=https://your-idp.example.com/.well-known/jwks.json
MCP_AUTH_ISSUER=https://your-idp.example.com/

# Optional but recommended behind a proxy / fixed public URL:
# the canonical identifier (= the audience tokens must be bound to)
MCP_AUTH_RESOURCE=https://api.example.com/mcp/demo
```

### 2. Protect your MCP server route (`routes/ai.php`)

[](#2-protect-your-mcp-server-route-routesaiphp)

```
use App\Mcp\Servers\DemoServer;
use Laravel\Mcp\Facades\Mcp;

Mcp::web('/mcp/demo', DemoServer::class)->middleware('mcp-auth');
```

That's it. Unauthenticated requests now receive a `401` with an RFC 9728 discovery challenge, valid tokens flow through, and your token's identity is available inside tools via `McpAuth::token()`.

> **Do not also call `Mcp::oauthRoutes()`.** This package owns discovery: it registers `/.well-known/oauth-protected-resource` under the same route names the framework's `AddWwwAuthenticateHeader` middleware looks for, so the handshake keeps working. Calling both would double-register those routes.

---

🔌 IdP recipes
-------------

[](#-idp-recipes)

### Auth0 (JWT / JWKS)

[](#auth0-jwt--jwks)

Auth0 issues RS256 JWTs and publishes a JWKS. Set the `audience` on your Auth0 API to your canonical resource identifier.

```
MCP_AUTH_STRATEGY=jwt
MCP_AUTH_AUTHORIZATION_SERVER=https://YOUR_TENANT.us.auth0.com/
MCP_AUTH_ISSUER=https://YOUR_TENANT.us.auth0.com/
MCP_AUTH_JWKS_URI=https://YOUR_TENANT.us.auth0.com/.well-known/jwks.json
MCP_AUTH_RESOURCE=https://api.example.com/mcp/demo
```

### Keycloak (JWT / JWKS + issuer)

[](#keycloak-jwt--jwks--issuer)

Keycloak's per-realm issuer and JWKS endpoint:

```
MCP_AUTH_STRATEGY=jwt
MCP_AUTH_AUTHORIZATION_SERVER=https://kc.example.com/realms/myrealm
MCP_AUTH_ISSUER=https://kc.example.com/realms/myrealm
MCP_AUTH_JWKS_URI=https://kc.example.com/realms/myrealm/protocol/openid-connect/certs
MCP_AUTH_RESOURCE=https://api.example.com/mcp/demo
```

Verifying the `iss` claim (`MCP_AUTH_ISSUER`) is strongly recommended — it's an extra check on top of the signature. The JWKS document is cached for `jwt.jwks_cache_ttl` seconds (default 3600) and refetched automatically as keys rotate.

### Opaque tokens via RFC 7662 introspection

[](#opaque-tokens-via-rfc-7662-introspection)

When your IdP issues opaque (non-JWT) tokens, validate them by calling its introspection endpoint with your resource-server credentials. Active results are cached briefly (`introspection.cache_ttl`, default 10s) so revocations take effect quickly.

```
MCP_AUTH_STRATEGY=introspection
MCP_AUTH_AUTHORIZATION_SERVER=https://your-idp.example.com
MCP_AUTH_INTROSPECTION_ENDPOINT=https://your-idp.example.com/oauth/introspect
MCP_AUTH_INTROSPECTION_CLIENT_ID=your-resource-server-client-id
MCP_AUTH_INTROSPECTION_CLIENT_SECRET=your-resource-server-secret
MCP_AUTH_RESOURCE=https://api.example.com/mcp/demo
```

The introspection POST is authenticated with HTTP Basic (`client_id` : `client_secret`) and sends `token_type_hint=access_token`. Inactive (`active: false`) responses are rejected and evicted from the cache immediately.

> **Static public key instead of JWKS?** Set `MCP_AUTH_PUBLIC_KEY` to a PEM string (or a path to a `.pem` file) and leave `MCP_AUTH_JWKS_URI` unset — the JWT strategy will verify against it directly.

---

🔐 Per-tool scopes &amp; 403 step-up
-----------------------------------

[](#-per-tool-scopes--403-step-up)

Pass the required scopes as middleware parameters. They're checked **on top of** any `required_scopes` configured globally.

```
use Laravel\Mcp\Facades\Mcp;

// Requires both files:read AND files:write on the access token
Mcp::web('/mcp/files', FileServer::class)
    ->middleware('mcp-auth:files:read,files:write');
```

A token missing any required scope gets a `403` whose challenge tells the client exactly what to request — enabling OAuth step-up (MCP SEP-835):

```
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope", error_description="The request requires higher privileges than provided by the access token.", scope="files:read files:write", resource_metadata="https://api.example.com/.well-known/oauth-protected-resource/mcp/files"
Content-Type: application/json

{
  "error": "insufficient_scope",
  "error_description": "The request requires higher privileges than provided by the access token."
}
```

To require a baseline scope on **every** MCP request, set it once in config:

```
// config/mcp-auth.php
'required_scopes' => ['mcp:use'],
```

---

👤 Reading identity &amp; scopes inside tools
--------------------------------------------

[](#-reading-identity--scopes-inside-tools)

The validated token is bound to the request after the middleware runs. Read it anywhere via the `McpAuth` facade:

```
use Blaze\McpAuth\Facades\McpAuth;

$token = McpAuth::token();           // ?Blaze\McpAuth\ValidatedToken

$token->subject;                     // ?string  — the "sub" claim
$token->scopes;                      // list
$token->audiences;                   // list (canonicalized)
$token->clientId;                    // ?string
$token->issuer;                      // ?string
$token->expiresAt;                   // ?int (unix timestamp)
$token->claims;                      // array — full claim bag

$token->hasScope('files:write');     // bool
$token->hasAllScopes(['a', 'b']);    // bool
$token->missingScopes(['a', 'b']);   // list
$token->hasAudience('https://api.example.com/mcp/demo'); // bool
$token->isExpired();                 // bool

McpAuth::hasScope('files:read');     // shortcut for the current request
```

### Resolve a Laravel user so `Request::user()` works

[](#resolve-a-laravel-user-so-requestuser-works)

To make `Laravel\Mcp\Request::user()` resolve a real model inside your tools, point `user_resolver` at a class implementing `Blaze\McpAuth\Contracts\UserResolver`, or at any callable.

```
namespace App\Mcp;

use App\Models\User;
use Blaze\McpAuth\Contracts\UserResolver;
use Blaze\McpAuth\ValidatedToken;
use Illuminate\Contracts\Auth\Authenticatable;

class ResolveUserFromToken implements UserResolver
{
    public function resolve(ValidatedToken $token): ?Authenticatable
    {
        return User::firstWhere('idp_subject', $token->subject);
    }
}
```

```
// config/mcp-auth.php
'user_resolver' => \App\Mcp\ResolveUserFromToken::class,

// ...or a closure:
'user_resolver' => fn (\Blaze\McpAuth\ValidatedToken $t) =>
    \App\Models\User::firstWhere('idp_subject', $t->subject),
```

When the resolver returns a user, the package sets it on the request and the default guard, so `$request->user()` resolves in your tools. Return `null` to leave the request unauthenticated at the guard level — scopes are still enforced and the token is still available via `McpAuth::token()`.

---

🛰 How discovery works (RFC 9728)
--------------------------------

[](#-how-discovery-works-rfc-9728)

MCP clients discover *who* can issue tokens for your server through the **401 handshake**:

1. The client calls your protected route without a token.
2. The middleware replies `401` with a `WWW-Authenticate` header pointing at the resource's metadata document:

    ```
    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: Bearer error="invalid_token", error_description="An access token is required.", resource_metadata="https://api.example.com/.well-known/oauth-protected-resource/mcp/demo"
    ```
3. The client fetches that metadata URL and reads the `authorization_servers` list:

    ```
    {
      "resource": "https://api.example.com/mcp/demo",
      "authorization_servers": ["https://your-idp.example.com"],
      "scopes_supported": ["mcp:use", "files:read", "files:write"],
      "bearer_methods_supported": ["header"]
    }
    ```
4. The client runs OAuth against that authorization server (PKCE, etc.), obtains a token bound to your `resource`, and retries — this time with `Authorization: Bearer `.

Discovery is served at both `/.well-known/oauth-protected-resource` and the path-scoped `/.well-known/oauth-protected-resource/{path}` (so each MCP server under your domain advertises its own canonical resource identifier). Add fields like `resource_name` via the `metadata` config key.

> **A note on the 401 header on `Mcp::web()` routes.** `laravel/mcp` attaches its own `AddWwwAuthenticateHeader` middleware to every `Mcp::web()` route, and it finalizes the `WWW-Authenticate` header on 401 responses. Because this package registers the discovery routes under the names that middleware expects, the resulting header still carries the correct `resource_metadata` link (discovery works end-to-end). On those routes the framework's header omits the optional `error="invalid_token"` / `error_description` attributes — but this package always includes them in the JSON response body, and the full RFC 6750 challenge header is emitted on non-`Mcp::web()` routes (custom routes, other MCP server packages). `403 insufficient_scope` challenges are never touched by the framework and always carry the full `scope=` step-up attributes.

---

⚙️ Configuration reference
--------------------------

[](#️-configuration-reference)

All keys live in `config/mcp-auth.php` (publish with `php artisan mcp-auth:install`).

KeyTypeDefaultDescription`resource``?string``env(MCP_AUTH_RESOURCE)`Canonical resource identifier (RFC 8707/9728). `null` derives it from the request URL. Set explicitly behind a proxy.`authorization_servers``string[]``[env(MCP_AUTH_AUTHORIZATION_SERVER)]`Issuer URL(s) advertised in discovery. At least one required.`strategy``'jwt' | 'introspection'``jwt`How tokens are validated.`scopes_supported``string[]``['mcp:use']`Scopes advertised in metadata. Keep minimal.`required_scopes``string[]``[]`Scopes required on **every** request, on top of per-route scopes.`enforce_audience``bool``true`Enforce RFC 8707 audience binding. Disable **only** if your IdP cannot bind an audience (e.g. an introspection endpoint that omits `aud`); doing so weakens confused-deputy protection.`jwt.jwks_uri``?string``env(MCP_AUTH_JWKS_URI)`IdP JWKS endpoint (preferred — keys rotate automatically).`jwt.public_key``?string``env(MCP_AUTH_PUBLIC_KEY)`Static PEM key (or path) when no JWKS is used.`jwt.algorithms``string[]``['RS256']`Acceptable signing algorithms.`jwt.issuer``?string``env(MCP_AUTH_ISSUER)`Expected `iss`. Strongly recommended; `null` skips the check.`jwt.leeway``int``60`Clock-skew tolerance (seconds) for `exp`/`nbf`/`iat`.`jwt.jwks_cache_ttl``int``3600`JWKS cache lifetime (seconds).`introspection.endpoint``?string``env(MCP_AUTH_INTROSPECTION_ENDPOINT)`RFC 7662 introspection endpoint.`introspection.client_id``?string``env(MCP_AUTH_INTROSPECTION_CLIENT_ID)`Resource-server client id (HTTP Basic).`introspection.client_secret``?string``env(MCP_AUTH_INTROSPECTION_CLIENT_SECRET)`Resource-server client secret.`introspection.cache_ttl``int``10`Cache lifetime for `active` results — keep short for fast revocation.`claims.subject``string``sub`Claim mapped to the token subject.`claims.audience``string``aud`Claim mapped to audiences.`claims.scope``string``scope`Space-delimited scope claim.`claims.scope_array``string``scp`Array scope fallback (e.g. Azure AD).`claims.client_id``string``client_id`Claim mapped to the client id.`bearer_methods_supported``string[]``['header']`Advertised bearer methods. Query/body tokens are always rejected.`user_resolver``class-string|callable|null``null`Maps a `ValidatedToken` to an `Authenticatable`.`register_routes``bool``true`Auto-register the discovery routes on boot (route-cache compatible).`compat_route_names``bool``true`Register under the names `AddWwwAuthenticateHeader` expects. Keep `true` unless you call `Mcp::oauthRoutes()` yourself.`metadata``array``['resource_name' => env(MCP_AUTH_RESOURCE_NAME)]`Extra fields merged into the metadata document.`ssrf_protection``bool``true`Enforce HTTPS + block private/reserved IPs for outbound JWKS/introspection calls.`http_timeout``int``5`Timeout (seconds) for outbound JWKS/introspection requests.**Environment variables:** `MCP_AUTH_AUTHORIZATION_SERVER`, `MCP_AUTH_STRATEGY`, `MCP_AUTH_RESOURCE`, `MCP_AUTH_RESOURCE_NAME`, `MCP_AUTH_JWKS_URI`, `MCP_AUTH_ISSUER`, `MCP_AUTH_PUBLIC_KEY`, `MCP_AUTH_INTROSPECTION_ENDPOINT`, `MCP_AUTH_INTROSPECTION_CLIENT_ID`, `MCP_AUTH_INTROSPECTION_CLIENT_SECRET`.

---

📐 Spec compliance
-----------------

[](#-spec-compliance)

SpecWhat it coversStatus**RFC 9728** — OAuth 2.0 Protected Resource Metadata`/.well-known/oauth-protected-resource` (+ path-scoped), `resource_metadata` link in `WWW-Authenticate`✅**RFC 8707** — Resource IndicatorsAudience binding: tokens not issued for this resource are rejected✅**RFC 9068** — JWT Profile for Access TokensLocal JWT validation via JWKS / public key✅**RFC 7662** — Token IntrospectionOpaque-token validation with client-credential auth✅**RFC 6750** — Bearer Token Usage`WWW-Authenticate` challenges, `invalid_token` / `insufficient_scope`✅**MCP Authorization** — resource-server 401 → discovery flow, scope step-up (SEP-835)End-to-end handshake on `laravel/mcp` routes✅---

🧪 Testing
---------

[](#-testing)

```
composer test       # Pest — 54 tests
composer analyse    # PHPStan level 6
composer lint:test  # Pint (Laravel preset, strict types)
```

🤝 Contributing
--------------

[](#-contributing)

Issues and PRs are welcome. Please keep the suite green (`composer test`), clear of static-analysis errors (`composer analyse`), and Pint-clean (`composer lint`) before opening a PR.

🔒 Security
----------

[](#-security)

If you discover a security vulnerability, please email **** rather than opening a public issue.

📝 License
---------

[](#-license)

MIT © [Shaxzodbek Qambaraliyev](https://github.com/shaxzodbek-uzb). See [LICENSE.md](LICENSE.md).

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity38

Early-stage or recently created project

 Bus Factor1

Top contributor holds 85.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/52601832881370c15b8c88de19f249fa511d46114d02d0a9d1fe2e51e2cb2f16?d=identicon)[Shaxzodbek](/maintainers/Shaxzodbek)

---

Top Contributors

[![shaxzodbek-uzb](https://avatars.githubusercontent.com/u/47610909?v=4)](https://github.com/shaxzodbek-uzb "shaxzodbek-uzb (6 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

authenticationauthorizationjwtlaravelmcpmodel-context-protocoloauthoauth2phpresource-serverjwtlaravelmcpaiAuthenticationoauthoauth2authorizationModel Context ProtocolJWKSRFC7662resource serveroauth2.1rfc9728rfc8707

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/shaxzodbek-uzb-laravel-mcp-auth/health.svg)

```
[![Health](https://phpackages.com/badges/shaxzodbek-uzb-laravel-mcp-auth/health.svg)](https://phpackages.com/packages/shaxzodbek-uzb-laravel-mcp-auth)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

76518.2M117](/packages/laravel-mcp)[auth0/login

Auth0 Laravel SDK. Straight-forward and tested methods for implementing authentication, and accessing Auth0's Management API endpoints.

2795.2M3](/packages/auth0-login)[api-platform/laravel

API Platform support for Laravel

59156.3k11](/packages/api-platform-laravel)[firevel/firebase-authentication

Firebase authentication driver for Laravel

2224.5k2](/packages/firevel-firebase-authentication)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
