Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Web Mcp Laravel Package

fosseva/laravel-web-mcp

fosseva/laravel-web-mcp helps Laravel applications act as web-based MCP servers, exposing tools and resources to AI clients through the Model Context Protocol. It simplifies adding MCP endpoints using familiar Laravel conventions.

View on GitHub
Deep Wiki
Context7

Getting Started

This is the first public release (v0.1.0-alpha.1) of fosseva/laravel-web-mcp, an alpha-tagged package that exposes a Laravel application over the Model Context Protocol (MCP) so MCP clients (Claude Desktop, MCP Inspector, IDE agents) can call into your app as tools/resources. There are no release notes beyond the changelog link, so treat the README and the package source as the source of truth — nothing below should be taken as a guaranteed API contract for an alpha.

  1. Install with an explicit alpha constraint. Composer will not pick up an alpha automatically:
    composer require fosseva/laravel-web-mcp:0.1.0-alpha.1
    
    Pin the exact version. Do not use ^0.1 while in alpha.
  2. Publish and read the config first. php artisan vendor:publish --tag="web-mcp-config" (confirm the tag name in the README), then open config/web-mcp.php. This is where transport, route prefix, middleware, and tool registration almost certainly live. Read it before writing any tool code — it tells you more about the package's shape than the docs will.
  3. Confirm the routes exist. php artisan route:list | grep -i mcp. You want to know the endpoint path, the HTTP verbs, and which middleware stack it sits behind. This is the single most useful debugging step.
  4. Find the registration surface. Look in src/ for the service provider and any Tools/, Resources/, Prompts/, or Server directories. That tells you whether tools are classes, closures, or config entries.
  5. First use case: one read-only tool. Expose something small and safe — "look up an order by ID" — and wire it to an existing Eloquent query or Action class. Do not start with a write path. Point MCP Inspector (or a Claude Desktop mcpServers entry using the HTTP transport) at the endpoint and confirm the tool appears in tools/list and returns a well-formed result from tools/call.

Implementation Patterns

Wrap existing application logic, don't reimplement it. The healthiest pattern is a thin tool class that validates input, delegates to an existing Action/Service/Query class, and formats the response. Your MCP surface should be a second adapter over the same domain code your HTTP controllers use — never a parallel implementation with its own business rules.

Separate read and write tool namespaces. Name tools by intent and scope: orders.get, orders.list, orders.cancel. Prefixing by domain makes it obvious to both humans and models which tools are related, and makes it trivial to gate a whole namespace behind a permission check or feature flag.

Gate write tools behind explicit authorization, per tool. Route-level middleware authenticates the connection; it does not authorize the action. Resolve the acting user in middleware, then assert permission inside each mutating tool ($user->can('cancel', $order)). Agents will call the tool you gave them — the tool is the security boundary.

Treat input schemas as validation contracts. Define the JSON input schema and the Laravel validation rules from the same shape. Validate with the Validator facade and translate failures into MCP tool errors rather than letting a ValidationException bubble up and produce an HTML/JSON error page the client can't parse.

Keep transports simple in dev. If the package supports both stateless HTTP POST and a streaming/SSE transport, start with the stateless path — it behaves like a normal Laravel request, works behind your existing middleware, and is far easier to reproduce with curl. Move to streaming only when you actually need server-initiated messages or long-running tool output.

Test with raw JSON-RPC. Feature tests are cheap here: $this->postJson('/mcp', ['jsonrpc' => '2.0', 'id' => 1, 'method' => 'tools/list']) and assert the tool appears; then call each tool with valid and invalid payloads. Cover the auth path explicitly — an unauthenticated tools/call must fail with a structured error, not a redirect to a login page.

Use resources for context, prompts for workflows. Read-only data the model needs repeatedly (schemas, enum lists, current user profile, config) belongs in resources. Multi-step templated workflows belong in prompts. Reserve tools for actions with side effects or parameters.

Environment-gate the whole surface. Register the routes and service provider behind a config flag so production only exposes what you intend, and staging can be permissive. An MCP endpoint is an API — it deserves the same deliberate exposure decision as any other route group.

Gotchas and Tips

  • Alpha means breaking changes without a major bump. 0.1.0-alpha.1 is a naming convention, not a stability promise. Pin the exact version in composer.json, and read the diff — not just the changelog — before bumping. Expect constructor signatures, config keys, and route names to move.
  • CSRF will bite you on POST. Laravel's web middleware group includes VerifyCsrfToken. A machine client has no session and no token. Ensure the MCP route sits on api middleware or is explicitly CSRF-exempt; otherwise every call returns 419 and the failure looks like an auth problem.
  • Error shape matters more than error text. MCP clients parse JSON-RPC errors with a code and message. Unhandled exceptions go through Laravel's exception handler and may return a redirect, an HTML error page, or a non-conforming JSON body. Catch broad exceptions in the tool layer and return structured errors; log the full trace server-side where the client can't see it.
  • Watch response size. Models have context budgets. A tool that dumps 500 Eloquent rows will silently degrade every subsequent turn. Paginate hard, cap result counts, and select explicit columns. Return summaries with IDs the model can use to drill in.
  • Execution time and memory are the real limits. Long tool calls run inside a PHP request. Keep tools fast; move anything slow to a queued job that returns a handle, and expose a second tool to poll it. Set an explicit timeout expectation in your tool descriptions.
  • Descriptions are prompt engineering. The tool description and parameter descriptions are what the model uses to decide when to call. Vague descriptions produce wrong tool selection. State preconditions and side effects plainly: "Cancels an order. Irreversible. Requires the order to be in pending status."
  • Log every tool call with a correlation ID. Include tool name, resolved user, argument hash (not raw PII), duration, and outcome. When a model does something surprising, this log is the only way to reconstruct what happened. Laravel's Log context plus a middleware is enough.
  • Session and state don't survive between calls in stateless mode. Don't cache per-conversation state in a singleton or the session. If you need state, key it on an explicit token or conversation ID passed as a tool parameter.
  • Extension points to look for: tool discovery paths/namespaces in config, the middleware applied to the MCP route group, and any contract/interface a tool class must implement. Those three determine how much you can customize without forking. If the package doesn't document them, read the service provider — it's usually 50 lines and answers everything.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource