dhur-gham/laravel-mcp-api-docs
Laravel package for documenting MCP servers: generates browsable API docs for your tools, resources, and prompts, with routing and auth that fit your existing Laravel app so docs stay close to the code they describe.
1. Confirm you can even upgrade. v2.0.0 is Laravel 12 only and requires laravel/mcp ^0.7 (through ^1.0). If you're on Laravel 11 or laravel/mcp 0.6, stay on 1.4.x until the app is upgraded — this is a hard floor, not a soft deprecation.
composer require dhur-gham/laravel-mcp-api-docs:^2.0
2. Point it at your spec. The package reads openapi.json either from disk (openapi.file) or over HTTP (openapi.url). In v2 the lookup order is local file → URL → fallback paths, and when both openapi.file and openapi.url are configured the file wins. If you only ever set one, nothing changes for you.
3. Register the MCP server. Wire the package's server into your MCP registration (in laravel/mcp that's typically routes/ai.php) and connect an agent — Claude Desktop, Cursor, or your own client — to the endpoint.
4. First use case: let an agent read your API. Ask the connected agent "list the endpoints" or "how do I create an invoice?". This is the core loop the package exists for — the MCP tools expose your endpoints and docs so the agent answers from your real spec instead of hallucinating.
5. Then opt into the changelog (the headline feature).
php artisan mcp-api-docs:install-changelog
The installer asks how openapi.json is kept current (manual export vs. Scramble) and writes the GitHub Actions workflow. Set MCP_API_DOCS_CHANGELOG_FILE afterwards — the changelog stays off until both steps are done.
Treat openapi.json as a committed build artifact. The changelog bot diffs the spec before and after each PR, so the file must live in the repo and be regenerated as part of the PR. Two modes:
openapi.json on every push. Least friction; the bot is forgiving if you forget to export.One entry per PR, reviewed with the code. The bot commits the entry onto the PR branch rather than a separate release branch. That means changelog prose goes through normal code review and conflicts show up in the PR — useful, but it also means the entry lands before the merge, so the workflow must run on the PR head, not on main.
Query the changelog from the agent side, not just the UI side. Two surfaces matter day-to-day:
get_changelog(since?) — "what changed since v1.3?" for release notes, upgrade planning, or briefing an agent before it writes a client.get_endpoint(...) now returns a changes list per endpoint — good for "is this endpoint stable, or was it just deprecated?" answered inline with the endpoint docs.A useful pattern: pin since to your last deployed tag in an agent system prompt so client-generating agents automatically avoid deprecated fields.
Conflict recovery is a slash command. If another PR merges first, comment /update-mcp-changelog on the PR and the bot rebases the entry. Only collaborators can trigger it — bake that into your team's PR etiquette doc so contributors know to ask rather than hand-edit the file.
Tune the spec cache per environment. MCP_API_DOCS_OPENAPI_CACHE_TTL defaults to 60s and applies between tool calls. In local dev against a file you're actively editing, that's a stale-window you'll notice; drop it to 0. In production 60s is fine. Failed loads are never cached, so a broken URL won't pin you to a bad state.
Use URL mode for a published spec, file mode for a PR-time spec. If you have a docs host serving openapi.json, URL mode keeps the MCP current without redeploys — but remember it will lose to a local file if one exists. Mixed setups (file for local, URL for prod) are common and now behave predictably, but they mean different spec sources across environments; verify before trusting an agent's answer.
The file-wins precedence change is the sneaky breaking change. On 1.x, a configured openapi.url behaved one way; on 2.0 a checked-in openapi.json silently takes over. If an agent starts answering from a six-month-old spec after upgrade, check for a stale committed file you'd forgotten about.
The changelog is off by default and needs both halves. Running mcp-api-docs:install-changelog alone does nothing for tool output — MCP_API_DOCS_CHANGELOG_FILE must point at the generated file. If get_changelog returns empty, check the env var before debugging the workflow.
Baseline behaviour is deliberate. The first openapi.json becomes the baseline, so the first PR won't produce a giant "everything added" entry. Don't treat that as a bug and try to backfill — you'll get a useless wall of green.
Fork PRs are skipped. Community contributions get no changelog entry and won't be command-refreshable by outsiders. Plan to regenerate on the merge commit or have a collaborator run /update-mcp-changelog in a follow-up branch.
Branch protection can break the bot. The workflow pushes a commit to the PR branch, so it needs contents: write and a branch that permits app-authored commits. On protected branches you'll see a red workflow rather than a changelog — check the token permissions before suspecting oasdiff.
The 🔴/🟡/🟢 classification is oasdiff's heuristic. It catches signature and schema breaks well, but a semantic change that keeps the shape intact will read 🟢. Don't let a green label substitute for a human reviewer on anything touching auth or billing.
Security posture is fine, but it is your repo now. Actions are SHA-pinned, the oasdiff download is SHA-256 verified, and the diff script is committed rather than fetched. That last part is an extension point: edit the committed script to change labels, ignore paths, or adjust the entry template. It also means a malicious PR can't swap the script mid-run — but it does mean you own its maintenance.
docs_folder reads are fixed. If you were previously working around broken feature-doc reads (returning empty or falling through), remove those workarounds — the fallback chain now resolves correctly.
Debugging order when docs look wrong: (1) which spec actually loaded — file or URL; (2) cache TTL, retry after 60s or set to 0; (3) the local → URL → fallback order, since a stray openapi.json in the project root can shadow your configured URL; (4) only then look at the MCP server registration.
How can I help you explore Laravel packages today?