Building Web Apps with Laravel Module 18 – AI features and AI-assisted development
MCP servers and Laravel Boost
Build a Laravel MCP server whose tools authorise each caller with Sanctum abilities and centre scoping, and use Laravel Boost while you code.
What you will learn
- Build a Laravel MCP server with a read tool and a write tool that authorises each caller
- Protect every MCP tool with Sanctum abilities, centre scoping and a per-token rate limit
- Choose between a custom MCP tool, a plain REST route and Laravel Boost's own tools
- Review AI-written code with tests, static analysis and your own reading
Before you start
What you’ll learn · Before you start
What you will learn
- Build a Laravel MCP server with a read tool and a write tool that authorises each caller
- Protect every MCP tool with Sanctum abilities, centre scoping and a per-token rate limit
- Choose between a custom MCP tool, a plain REST route and Laravel Boost's own tools
- Review AI-written code with tests, static analysis and your own reading
Before you start
On this page
Pathshala’s North centre has two overdue fee instalments worth 7,500 rupees, and its accountant wants an AI assistant that finds them without a developer writing a report. The assistant cannot be handed the database: it must call a few named actions that each check who is asking. MCP servers publish those actions as tools an AI client can call, and Laravel Boost gives the coding agent you build with its own tools, guidelines and skills.
This lesson builds that server, protects each tool with Sanctum abilities and a centre scope, and opens what Laravel Boost installs.
What an MCP server is, and why a Laravel app would publish one
An agent that helps run a business must do things: read overdue fees, send a reminder. Raw database access is unsafe and unversioned. The Model Context Protocol: An open standard for connecting AI models to external tools and data through JSON-RPC messages between a host, its clients and servers, so a model can run named actions instead of touching systems directly.’s specification says MCP “provides a standardized way to connect LLMs with the context they need”, over JSON-RPC 2.0. MCP servers let a Laravel app offer a few named, checked actions instead of a database login.
A server offers three kinds of thing:
| Primitive | What it is | A Pathshala example |
|---|---|---|
| MCP tool: An action an AI model can run through an MCP server, with a name, a description and an input schema. In laravel/mcp it is a class extending Laravel\Mcp\Server\Tool with a handle method. | An action the model can run | list-overdue-fees, send-reminder |
| MCP resource: Data an MCP server exposes for a client to read as context, identified by a URI and a MIME type, such as a document or a configuration value. | Data the client can read as context | the fee-policy document |
| MCP prompt: A reusable message template an MCP server offers, which a client can fill with arguments to start a common interaction with the model. | A reusable message template | “draft a polite reminder” |
A MCP server: A service that exposes tools, resources and prompts to AI clients over the Model Context Protocol. In Laravel it is a class registered with Mcp::web or Mcp::local in routes/ai.php. runs over a MCP transport: How MCP messages travel between a client and a server: a web server answers an HTTP POST, and a local server exchanges messages over its standard input and output as a command.: a web server answers an HTTP POST, a local one runs as a command. Because tools “represent arbitrary code execution”, the specification wants a human able to deny a call, and the server must validate inputs and rate-limit calls:
The drawing shows the whole scene; its 7 steps are listed below.
Every step as text
- The call arrives. An AI client the user connected sends a tools/call request for list-overdue-fees over the web transport, with a bearer token in the Authorization header.
- The server authenticates. The route's auth:sanctum middleware reads the token. A missing or unknown token is refused with 401 before any tool runs.
- The rate limit is checked. The throttle:mcp limiter counts this call, so a client that bursts past its budget gets a 429 before any tool runs.
- The server checks the ability. Each tool's shouldRegister() checks the token's abilities. A tool the token may not use is left out of tools/list, and a call to it fails as not found.
- The arguments are validated. The handler validates the arguments with Laravel rules; the input schema advertises them to the client so the model knows what to send, and a bad value comes back as a clear message.
- The handler runs, scoped. The handler reads rows only where centre_id is the acting user's centre, taken from the token's user, never from an argument the model chose.
- The result goes back. The handler returns a JSON result the client gives the model. A read tool is marked read-only; a write tool is marked destructive, so the client can confirm first.
Checkpoint
Check: Tools, resources and prompts
Registering a server and writing a tool that authorises each caller
composer require laravel/mcp, then php artisan make:mcp-server PathshalaMcpServer writes a server in app/Mcp/Servers. Register it in routes/ai.php with Mcp::web('/mcp/pathshala', PathshalaMcpServer::class), or Mcp::local(...) for a command server such as Boost’s. A tool extends Laravel\Mcp\Server\Tool: an input schema, a read-only or destructive annotation, and a handle(). Its name comes from the class, so ListOverdueFees is list-overdue-fees.
The route takes auth:sanctum, so inside a tool $request->user() is the user of the personal access token: A Sanctum API token issued to one user for one named client, with a list of abilities. The client sends it as a bearer token, and deleting its row revokes it. More in “API auth with Sanctum and Passport”, and the tool reads only that user’s centre. Each tool’s shouldRegister() checks a token token ability: A string on a Sanctum token that names an action the token may take, such as fees:read. The ability and abilities middleware refuse a request whose token lacks what the route requires. More in “API auth with Sanctum and Passport”; a tool that says no is left out of tools/list and cannot be called. MCP’s spec documents OAuth 2.1; Pathshala already issues Sanctum tokens. A client sends JSON-RPC requests with three tokens, and once with none:
from session import run
# Pathshala's MCP server answering a client over HTTP. The project is the course's Pathshala with laravel/mcp
# installed (its routes/ai.php published). rpc.php sends each JSON-RPC request through the app's own HTTP kernel, so
# auth:sanctum, throttle:mcp and the MCP header checks run exactly as for a request from the network:
# * a fees:read token lists one tool and reads its own centre's two overdue rows (Kabir's paid row left out);
# * a fees:read + fees:write token also lists send-reminder;
# * an attendance:read token lists no tool, and calling list-overdue-fees by name fails;
# * no token at all is refused by auth:sanctum with 401 before the server runs.
run(
"""
composer require laravel/sanctum --no-interaction --quiet
php artisan vendor:publish --tag=sanctum-migrations --no-interaction
php artisan migrate --no-interaction
php seed.php
# The server's route: POST carries JSON-RPC; GET and DELETE answer 405.
php artisan route:list --path=mcp
# A client with a fees:read token asks which tools it may use, then calls one.
php rpc.php --token tok-read.txt tools/list
php rpc.php --token tok-read.txt tools/call list-overdue-fees
# A token that may also write sees the reminder tool as well.
php rpc.php --token tok-write.txt tools/list
# A token with no fee ability sees no fee tool, and naming one does not help.
php rpc.php --token tok-att.txt tools/list
php rpc.php --token tok-att.txt tools/call list-overdue-fees
# No token: auth:sanctum answers before the MCP server runs.
php rpc.php tools/list
""",
app=True,
fixture="pathshala-mcp",
overlay=("pathshala",),
repos=("repo-ai",),
) Output
$ composer require laravel/sanctum --no-interaction --quiet
$ php artisan vendor:publish --tag=sanctum-migrations --no-interaction
INFO Publishing [sanctum-migrations] assets.
Copying directory [vendor/laravel/sanctum/database/migrations] to [database/migrations] DONE
$ php artisan migrate --no-interaction
INFO Running migrations.
2026_02_01_000000_create_pathshala_fee_tables ......................... DONE
YYYY_MM_DD_HHMMSS_create_personal_access_tokens_table ................. DONE
$ php seed.php
Seeded: North 3 students, South 1 students.
Tokens for Asha (North): fees:read x2, fees:read+fees:write, attendance:read.
# The server's route: POST carries JSON-RPC; GET and DELETE answer 405.
$ php artisan route:list --path=mcp
GET|HEAD mcp/pathshala .... vendor/laravel/mcp/src/Server/Registrar.php:45
DELETE mcp/pathshala .... vendor/laravel/mcp/src/Server/Registrar.php:47
POST mcp/pathshala .... vendor/laravel/mcp/src/Server/Registrar.php:49
Showing [3] routes
# A client with a fees:read token asks which tools it may use, then calls one.
$ php rpc.php --token tok-read.txt tools/list
POST /mcp/pathshala tools/list -> HTTP 200
list-overdue-fees [readOnlyHint] arguments: as_of, limit
(1 tools; * = required)
$ php rpc.php --token tok-read.txt tools/call list-overdue-fees
POST /mcp/pathshala tools/call list-overdue-fees -> HTTP 200
isError: false
{
"count": 2,
"total_paise": 750000,
"rows": [
{
"instalment_id": 1,
"student": "Aarav Shah",
"amount_paise": 450000,
"days_overdue": 40
},
{
"instalment_id": 2,
"student": "Diya Rao",
"amount_paise": 300000,
"days_overdue": 12
}
]
}
# A token that may also write sees the reminder tool as well.
$ php rpc.php --token tok-write.txt tools/list
POST /mcp/pathshala tools/list -> HTTP 200
list-overdue-fees [readOnlyHint] arguments: as_of, limit
send-reminder [destructiveHint] arguments: instalment_id*, confirm*
(2 tools; * = required)
# A token with no fee ability sees no fee tool, and naming one does not help.
$ php rpc.php --token tok-att.txt tools/list
POST /mcp/pathshala tools/list -> HTTP 200
(0 tools; * = required)
$ php rpc.php --token tok-att.txt tools/call list-overdue-fees
POST /mcp/pathshala tools/call list-overdue-fees -> HTTP 400
JSON-RPC error -32602: Tool [list-overdue-fees] not found.
# No token: auth:sanctum answers before the MCP server runs.
$ php rpc.php tools/list
POST /mcp/pathshala tools/list -> HTTP 401
{
"message": "Unauthenticated."
}
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 mcp_client_session.py
The fees:read token sees one tool and reads two overdue rows, 750,000 paise; the write token also sees send-reminder. The attendance token sees none, and naming one returns “Tool [list-overdue-fees] not found.”; no token gets a 401.
Key idea
An MCP tool is an API endpoint the model can discover: validate its arguments, authorise the acting user, and read only that user’s data, exactly as you would for a route.
Checkpoint
Check: Registering a server and authorising a tool
What Laravel Boost gives a coding agent
Laravel Boost: A first-party development package that gives a coding agent an MCP server, AI guidelines and skills for your Laravel app's packages, so it writes version-specific code. It starts only when the app is local or debug is on. points the other way: instead of your app serving an outside agent, Boost serves the coding agent you build with. After composer require laravel/boost --dev and php artisan boost:install, Boost runs a local MCP server that reads your package versions and database schema, runs read-only queries and searches version-specific documentation.
It also writes instruction files: agent guideline: An instruction file a coding agent reads at the start of every task, with broad conventions for the Laravel packages an app uses. Boost writes it into the editor's guidelines file, adding custom ones from .ai/guidelines. load upfront, agent skill: A knowledge module a coding agent loads on demand for one domain, such as testing: a SKILL.md that Boost installs into the editor's skills folder, with custom skills kept under .ai/skills. load on demand, and a project rule: Committed Markdown in .ai/rules that teaches a coding agent your own application's decisions and traps, scoped to file globs, with an index agents read to find which rule applies to a file. you record captures your own app’s conventions, which the ecosystem guidelines never describe. One question an agent asks Boost before it writes code:
The drawing shows the whole scene; its 5 steps are listed below.
Every step as text
- The task arrives. You ask the agent to add a guardian phone number to students. Before it edits, Boost's guidelines tell it to inspect the table with the database-schema tool.
- The agent calls a tool. The agent calls Boost's database-schema tool over MCP. Boost runs as a local server the editor started with php artisan boost:mcp, so the call stays on your machine.
- Boost reads the schema. Boost reads the tables, columns, types and indexes from the app's own database connection, not from a guess about what the migrations made.
- A tool result comes back. Boost returns the schema as a JSON tool result, so the agent sees that students already has centre_id, name and guardian_email.
- The agent writes the code. The agent writes a migration that adds only the missing column to the real table, instead of re-creating columns it imagined.
Boost is a development dependency that starts only when the environment is local or debug is on, so it stays out of production.
Choosing a tool, a route, or Boost’s own tools
Three surfaces are not interchangeable: a custom MCP tool an outside AI client discovers, a plain REST route for your own apps, and Laravel Boost’s development-only tools. Answer two questions about the caller:
Answer the questions above: the table then marks what fits your case and says why the rest does not.
| Surface | Who calls it | Agent discovery | Per-user authorisation | Runs in production |
|---|---|---|---|---|
| Custom MCP tool Who builds and ships it: you write it; shipped to production | Good An AI client the user points at your server, through the MCP protocol. | Good tools/list advertises its name, description and input schema to the client. | Good auth:sanctum or OAuth on the route; each tool's shouldRegister() checks the token's ability. | Good A production feature you own and version, like any other endpoint. |
| Plain REST route Who builds and ships it: you write it; shipped to production | Mixed Your own apps over HTTP; an agent needs glue code to find and call it. | Poor No MCP listing: the client cannot discover it or read its schema. | Good The same Sanctum abilities and middleware an MCP tool uses. | Good A production endpoint; the MCP tool can wrap this same handler. |
| Boost's built-in tools Who builds and ships it: installed with laravel/boost; development only | Mixed Your coding agent, about THIS app, while you build it. | Good Boost's MCP server lists its own tools to the agent the editor starts. | Poor Runs as the developer; the database-query tool is read-only on purpose. | Poor Development only: it starts only when the app is local or debug is on. |
How the answers decide
- “Who calls this capability?” Your coding agent, while you build the app: rules out Custom MCP tool and Plain REST route. Inspecting your own app as you build it is what Boost's development-only tools are for; you write nothing.
- “Who calls this capability?” Your own mobile or web app and “Must the caller discover the capability and read its schema by itself?” No, the caller is coded against it: rules out Custom MCP tool and Boost's built-in tools. A client you write and ship with needs only a REST route with its Sanctum abilities, not MCP discovery.
- “Who calls this capability?” An AI client a user connects to the running app: adds a caveat to Plain REST route. An AI client the user connects needs the tool advertised; a REST route fits only if a tool wraps it.
- “Must the caller discover the capability and read its schema by itself?” Yes, the agent should find and call it: rules out Plain REST route. A plain route is not listed over MCP, so an agent cannot discover it or read its input schema.
In short: a tool for an AI client, a route for an app you code, Boost’s tools while you build.
The first in-depth part writes the server’s tools, catches a cross-centre leak with a test and measures a rate limit. The second runs boost:install, records a project rule and sets a review checklist.
Checkpoint
Check: What Laravel Boost gives a coding agent · Tool, route or Boost's tools
Writing the Pathshala MCP server: tools, a leak caught by a test, and a measured rate limit Pro: opens with a Pro, Premium or Ultimate pass
This part writes the server’s read and write tools, reproduces a cross-centre leak and fixes it under a feature test, and measures the server’s rate limit.
In this part:
- The server, a read tool, and a write tool that waits for approval
- Authorise an MCP tool call by ability and approval
- Results of the sample tests
- A cross-centre leak, caught by a feature test
- A bucket per token, and a rubric for a tool you would expose
4 runnable examples (ListOverdueFees.php, ListOverdueFees.php, first version, McpServerTest.php, PathshalaMcpServer.php, Python, SendReminder.php, routes/ai.php) · 1 exercise with sample tests · about 10 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
Boost's artefacts: what boost:install writes, a project rule, and reviewing AI-written code Pro: opens with a Pro, Premium or Ultimate pass
This part runs boost:install and opens what it writes, records one project rule through Boost’s own MCP server, and ends with a checklist for reviewing code an agent wrote.
In this part:
- What boost:install writes
- A project rule shapes a suggestion, with a diff
- Reviewing AI-written code: tests, static analysis and the human eye
6 runnable examples (.ai/guidelines/pathshala.md, .ai/skills/invoice-numbering/SKILL.md, DIFF, Python, boost.json, record-rule.json, reply.php) · about 7 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
Practise
In your Pathshala project, with Sanctum and laravel/mcp:
- Put the server behind
auth:sanctumand giveListOverdueFeesashouldRegister()that needsfees:read; list the tools with afees:readand anattendance:readtoken. - Run
php artisan boost:installand open the instruction files it writes. - For one capability, choose between a custom MCP tool, a plain REST route and Boost’s own tools.
Practice that adapts to you
Practise this lesson
8 questions about 10 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Interview questions
Warm-up (fresher to 2–5 years): when is an MCP tool a better choice than a plain REST route for the same capability?
When the caller is an AI client that must discover and read a schema itself. A tool is advertised through tools/list with its name, description and input schema; a REST route is invisible to that client. For your own app, coded against the endpoint, a route with the same Sanctum abilities is simpler. Often you keep both, with one handler behind them.
Three longer questions on these servers and on agent-written code:
-
Mid to senior
A Pathshala MCP tool took a centre_id argument and read fees for that centre. A North owner reports seeing a South student's fee on a card. Explain how a prompt could cause this, fix it, and prove the fix with a feature test that fails before the change and passes after.
-
Mid to staff
Design the send-reminder write tool so a person must approve each send, it still works smoothly for the coding agent, and it can never run with a read-only token. Say which checks live inside the tool and which the client is only asked to do.
-
Mid to staff
A teammate recorded a Boost project rule, "always cast model attributes as nullable", to stop an agent's type errors. Three weeks later, data that should never be null is null. Explain the harm, how you would catch such a rule in review, and what you would do instead.
Flashcards · 6 cards
Recall it, then check
Say the answer to yourself before you look: recalling it is what makes it stick.
-
What is an MCP server, and why would a Laravel app publish one?
A server that offers an AI client a few named, checked actions over the Model Context Protocol, using JSON-RPC 2.0, instead of a database login. It offers tools (actions the model can run), resources (data for context) and prompts (reusable message templates).
-
How is a Laravel MCP server created, registered and given a tool?
composer require laravel/mcp, then php artisan make:mcp-server PathshalaMcpServer writes it in app/Mcp/Servers; routes/ai.php registers it with Mcp::web for HTTP or Mcp::local for a command server. A tool class has an input schema, an annotation and handle(); ListOverdueFees becomes list-overdue-fees.
-
How does a token ability hide an MCP tool from a caller?
With the route behind auth:sanctum, each tool's shouldRegister() checks the token's ability; a tool that says no is left out of tools/list and cannot be called. The attendance token saw no tools, and no token got a 401.
-
How should you treat an MCP tool when securing it?
As an API endpoint the model can discover: validate its arguments, authorise the acting user, and return nothing but that user's own data, exactly as for a route. The specification also wants a person able to deny a call, and calls rate-limited.
-
What does Laravel Boost give a coding agent, and why does it stay out of production?
A local MCP server that reads your package versions and database schema, runs read-only queries and searches version-specific documentation, plus guidelines, skills and your project rules. It is a development dependency that starts only when the environment is local or debug is on.
-
When is an MCP tool a better choice than a REST route for the same capability?
When the caller is an AI client that must discover the capability and read its schema itself, through tools/list. For your own app, coded against the endpoint, a route with the same Sanctum abilities is simpler; often both sit on one handler.
Key takeaways
- An MCP server publishes tools, resources and prompts an AI client calls over JSON-RPC, so an agent runs named actions instead of touching the database.
- Every MCP tool is an API endpoint: it validates arguments, authorises the user with Sanctum abilities, reads only that user’s data, and is rate-limited.
- Three surfaces serve different callers: a custom MCP tool for an AI client, a plain REST route for an app you code, and Boost’s tools only while you build.
- Laravel Boost gives the coding agent you build with an MCP server, guidelines and skills for your app’s packages, and it runs only in development.
Terms in this lesson
- agent guideline
- An instruction file a coding agent reads at the start of every task, with broad conventions for the Laravel packages an app uses. Boost writes it into the editor's guidelines file, adding custom ones from .ai/guidelines.
- agent skill
- A knowledge module a coding agent loads on demand for one domain, such as testing: a SKILL.md that Boost installs into the editor's skills folder, with custom skills kept under .ai/skills.
- Laravel Boost
- A first-party development package that gives a coding agent an MCP server, AI guidelines and skills for your Laravel app's packages, so it writes version-specific code. It starts only when the app is local or debug is on.
- MCP Inspector
- An interactive tool for testing and debugging an MCP server by connecting to it and trying its tools, resources and prompts. Laravel runs it with php artisan mcp:inspector.
- MCP prompt
- A reusable message template an MCP server offers, which a client can fill with arguments to start a common interaction with the model.
- MCP resource
- Data an MCP server exposes for a client to read as context, identified by a URI and a MIME type, such as a document or a configuration value.
- MCP server
- A service that exposes tools, resources and prompts to AI clients over the Model Context Protocol. In Laravel it is a class registered with Mcp::web or Mcp::local in routes/ai.php.
- MCP tool
- An action an AI model can run through an MCP server, with a name, a description and an input schema. In laravel/mcp it is a class extending Laravel\Mcp\Server\Tool with a handle method.
- MCP transport
- How MCP messages travel between a client and a server: a web server answers an HTTP POST, and a local server exchanges messages over its standard input and output as a command.
- Model Context Protocol
- An open standard for connecting AI models to external tools and data through JSON-RPC messages between a host, its clients and servers, so a model can run named actions instead of touching systems directly.
- project rule
- Committed Markdown in .ai/rules that teaches a coding agent your own application's decisions and traps, scoped to file globs, with an index agents read to find which rule applies to a file.
References
- Laravel 13.x MCP (Laravel (laravel.com))
- Laravel 13.x Boost (Laravel (laravel.com))
- Laravel 13.x AI assisted development (Laravel (laravel.com))
- Laravel 13.x Sanctum (Laravel (laravel.com))
- Model Context Protocol specification (Model Context Protocol)
- laravel/mcp (v1.0.1) source (Laravel (GitHub))
- laravel/boost (v2.10.1) source (Laravel (GitHub))
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress