omouren/mcp-oauth-bundle
A PHP bundle that adds OAuth support to Model Context Protocol (MCP) servers, providing configurable authorization endpoints and token handling to help secure MCP clients without building OAuth plumbing from scratch.
Architecture fit. The package's stated purpose — OAuth 2.0 authorization-server behavior for MCP servers, covering discovery, Client ID Metadata Documents (CIMD), and resource-bound tokens — maps to a real, near-term gap. The MCP authorization spec requires protected-resource metadata (RFC 9728), authorization-server metadata (RFC 8414), resource indicators (RFC 8707) on token requests, and PKCE. Most teams standing up an MCP server will need exactly this layer, and doing it by hand on top of league/oauth2-server-bundle is non-trivial. The value proposition is legitimate.
The fit caveat is decisive, though: this is a Symfony bundle built on symfony/mcp-bundle and league/oauth2-server-bundle. The supplied description.md claims it "adds OAuth 2.0 protection to MCP servers in Laravel" and references Artisan commands and Laravel guards. That is inconsistent with the repository name, the repository description, and the dependency chain. The documentation package supplied here is not trustworthy as-is and must be re-validated against composer.json and source before any estimate is committed. For a Laravel shop, the answer is likely "reimplement the same spec surface on Laravel Passport or a hosted IdP" rather than adopt.
Integration feasibility. Low-to-moderate, gated on three things:
mcp-bundle + league/oauth2-server-bundle. If either is absent, the bundle's assumptions about kernel bootstrapping, security firewall wiring, and entity/model bindings will not transfer.Technical risk. Ranked:
redirect_uri validation, token audience binding, PKCE enforcement, and login redirect handling. The one documented feature we can verify — a configurable redirect query parameter on login (v1.2) — is the classic open-redirect vector. Even if implemented safely, it signals the threat model is being extended casually.Key questions to resolve before commitment.
league/oauth2-server-bundle v3 (new major) supported?resource audience binding on both access and refresh tokens, and reject tokens minted for a different MCP server?redirect parameter validated against an allowlist, and are relative/protocol-relative URLs (//evil.example) rejected?Stack fit. Treat this as a Symfony-only option. If the MCP servers are Symfony, fit is good: the bundle slots into the existing security firewall and DI container and composes with mcp-bundle's route/controller conventions. If the estate is Laravel-first, do not port it — the abstractions (bundles, compiler passes, firewalls, entity providers) do not translate, and a Laravel reimplementation against the same RFCs is the honest path. If the estate is polyglot, prefer a central IdP (Keycloak, Auth0, WorkOS, Stytch) issuing resource-bound tokens and keep only thin resource-server validation in each MCP server.
Migration path. Do not rip out existing auth. Stand the bundle up as a second authorization surface in front of a single, low-traffic MCP server:
resource, PKCE challenge, token exchange, and a rejected cross-resource token.Compatibility. Pin exactly — composer.lock plus a documented constraint on Symfony minor and league/oauth2-server-bundle major. Auth libraries have broken semver before. Verify PHP version floor against our runtime matrix and confirm the bundle's discovery metadata is served over the same host/origin as the MCP endpoint (clients are strict about this).
Sequencing.
Maintenance. Assume we own this, not the upstream. With 2 stars and one maintainer, plan for a vendored fork within 12 months, budgeted at roughly 10–15% of one backend engineer's time per quarter to track spec revisions and security patches. Keep the fork as a patch set on upstream rather than a hard divergence so we can rebase. Add a standing quarterly review: MCP spec diff, dependency CVEs, league/oauth2-server-bundle major bumps.
Support. No commercial support, no SLA, no visible issue triage. Internal ownership must be named explicitly — a single engineer accountable for the auth path, with a documented runbook. Escalation goes to the platform/security team, not upstream. Document the decision rationale (why a 2-star dependency was accepted, and what triggers removal) so it survives staff turnover.
Scaling. OAuth token endpoints are cheap but bursty; the real scaling concerns are:
Cache-Control and ETags.Failure modes and mitigations.
redirect parameter → allowlist hosts, reject protocol-relative URLs, prefer relative paths, log resolved vs. raw values at debug.resource binding server-side and add a negative test.Ramp-up. Realistic estimate for an engineer new to the package: 2–3 days to a working POC (if the Symfony stack matches and the docs are wrong in ways that cost a day), 1–2 weeks to production confidence including conformance and security testing. The documentation mismatch raises the floor — do not let anyone plan against the Laravel quickstart in description.md, because following it will produce a non-functional integration. Front-load the source read, and treat the maintainer conversation as a hard prerequisite rather than a nice-to-have.
How can I help you explore Laravel packages today?