Laravel MCP Server
by marcelosmbr2
README.md
# Project Manager — Laravel MCP Server
A small **project & task manager** exposed as a [Model Context Protocol](https://modelcontextprotocol.io)
(MCP) server, built with [`laravel/mcp`](https://github.com/laravel/mcp). It is a learning-oriented
reference that exercises every core MCP primitive — **Tools**, **Resources**, and **Prompts** —
over a deliberately simple domain (projects that contain tasks).
An MCP client (Claude Desktop, Cursor, Claude Code, or the built-in inspector) connects to the
server over **stdio** and lets an AI create and track tasks, pull read-only context, and run
reusable prompt templates.
## Domain
- **Project** — `name`, `description`, and many tasks.
- **Task** — belongs to a project; has a `title`, `description`, `due_date`, a `status`
(`pending`, `in_progress`, `done`) and a `priority` (`low`, `medium`, `high`, `critical`).
A task is **overdue** when its due date has passed and it is not yet done.
Priorities carry a numeric `weight` (low = 1 … critical = 4) used to sort reports and triage
overdue work.
## Project structure
```
app/
├── Enums/ TaskStatus, TaskPriority (with label() / weight() helpers)
├── Models/ Project, Task
├── Mcp/
│ ├── Servers/ ProjectManagerServer — registers all primitives
│ ├── Tools/ The 5 callable actions
│ ├── Resources/ The 5 read-only resources
│ └── Prompts/ The 4 prompt templates
└── Support/ ReportBuilder — shared report aggregation
```
## MCP primitives
### 🔧 Tools — actions the AI can invoke
| Tool | Description |
| --- | --- |
| `create-task-tool` | Create a task under a project (title, description, priority, due date). |
| `list-tasks-tool` | List tasks with optional filters: project, status, priority, overdue. |
| `update-task-status-tool` | Move a task to a new status and report the before → after change. |
| `delete-task-tool` | Delete a task by id. |
| `generate-report-tool` | Aggregate tasks into a portfolio report as **Markdown** or **JSON**. |
### 📚 Resources — read-only context addressed by URI
| Resource | URI | Description |
| --- | --- | --- |
| System documentation | `documentation` | Onboarding overview of the server and its entities. |
| Priority rules | `priority-rules` | The priority levels, their weights, and when to use each. |
| Task details | `task://tasks/{task_id}` | Full detail for a single task (templated). |
| Project summary | `project://projects/{project_id}` | Task counts by status, overdue count, next due (templated). |
| Report | `report://reports/{format}` | Whole-portfolio report in `json` or `markdown` (templated). |
The report tool and the report resource share a single [`ReportBuilder`](app/Support/ReportBuilder.php)
so their numbers can never drift apart.
### 💬 Prompts — reusable, argument-driven templates
| Prompt | Arguments | Description |
| --- | --- | --- |
| `plan-project-prompt` | `goal` (required), `deadline` | Break a goal into a project plus milestone tasks. |
| `decompose-task-prompt` | `task_id` (required) | Split one real task into concrete subtasks. |
| `review-overdue-tasks-prompt` | `project_id` | Triage and re-prioritize overdue tasks. |
| `daily-summary-prompt` | `project_id` | Produce a stand-up style daily summary. |
## Getting started
```bash
composer install
php artisan migrate
# Seed at least one project so tasks have somewhere to live:
php artisan tinker --execute "App\Models\Project::factory()->create(['name' => 'Website Redesign']);"
```
The server is registered in [`routes/ai.php`](routes/ai.php) and exposed over stdio:
```php
Mcp::local('project-manager', ProjectManagerServer::class);
```
## Running & testing the server
```bash
# Interactive debugging — drive tools, resources and prompts by hand:
php artisan mcp:inspector project-manager
# Run the server over stdio (this is the command MCP clients launch;
# on its own it will appear to hang, waiting for JSON-RPC on stdin):
php artisan mcp:start project-manager
```
### Connecting from an AI client
**Claude Code**
```bash
claude mcp add project-manager -- php "<full-path>/artisan" mcp:start project-manager
```
**Claude Desktop** — add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"project-manager": {
"command": "php",
"args": ["<full-path>/artisan", "mcp:start", "project-manager"]
}
}
}
```
Passing the full path to `artisan` lets Laravel resolve the project root regardless of the
client's working directory.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues