内容
# mcp-laravel
[](https://github.com/NarimanGardi/mcp-laravel/actions/workflows/tests.yml)
[](https://packagist.org/packages/gardi/mcp-laravel)
[](LICENSE)
一个 MCP 服务器,允许 AI 编码代理检查 Laravel 应用程序 — 其路由、模型、数据库模式和(可选)只读查询结果 — 通过 stdio 或 HTTP。
我一直看着代理猜测 Laravel 代码库:发明模型属性、半记得路由名称、假设存在列。他们从训练集工作,而不是面前的应用程序。这将实际的东西暴露为代理可以调用的一系列工具,因此它读取您的模式而不是幻觉它。
它故意很小。四个工具,没有守护进程,没有额外的服务 — 只是一个 artisan 命令,通过 stdin/stdout 讲话。
## 需求
- PHP 8.2+(Laravel 13 为 8.3+)
- Laravel 12 或 13
## 安装
```bash
composer require gardi/mcp-laravel --dev
```
服务提供者是自动发现的。运行安装程序以发布配置并为您打印客户端代码片段:
```bash
php artisan mcp:install
```
(或者,如果您只想要配置,则运行 `php artisan vendor:publish --tag=mcp-config`)。
## 连接代理
服务器通过 stdio 运行,因此任何 MCP 客户端都可以通过指向此应用程序的目录并运行 `php artisan mcp:serve` 来启动它。例如,在 MCP 客户端的服务器配置中:
```json
{
"mcpServers": {
"laravel": {
"command": "php",
"args": ["artisan", "mcp:serve"],
"cwd": "/absolute/path/to/your/laravel/app"
}
}
}
```
就这样 — 代理现在可以列出和调用下面的工具。适用于 Claude Code、Cursor、Windsurf 和 Cline 的现成配置位于 [`examples/`](examples/) 中。
## 看看它的实际效果
一个真实的会话(握手 → 工具列表 → `relationship_graph` 调用)被捕获在 [`demo/session.md`](demo/session.md) 中,可以通过 `./demo/run.sh` 重现 — 它通过 Testbench 启动真实的服务器,没有模拟。简要的预览(演示使用包的 Post/Comment 固定装置;您会看到您自己的应用程序模型):
```json
// 初始化 → 服务器宣布自己
{ "protocolVersion": "2024-11-05", "serverInfo": { "name": "mcp-laravel", "version": "0.3.0" } }
// relationship_graph → 领域,作为代理可以读取的图
{
"modelCount": 2,
"edges": [
{ "from": "App\\Models\\Post", "relation": "comments", "type": "HasMany", "to": "App\\Models\\Comment" },
{ "from": "App\\Models\\Comment", "relation": "post", "type": "BelongsTo", "to": "App\\Models\\Post" }
]
}
```
使用 [VHS](https://github.com/charmbracelet/vhs) 记录会话的 GIF:`vhs demo/demo.tape`。
## HTTP 传输
更喜欢将其作为服务运行而不是 stdio?启用 HTTP 传输,服务器在单个带有身份验证的端点处暴露:
```env
MCP_HTTP_ENABLED=true
MCP_HTTP_TOKEN=a-long-random-secret
# MCP_HTTP_PATH=mcp # 默认值
```
然后将支持 HTTP 的 MCP 客户端指向 `POST https://your-app.test/mcp` 并带有 `Authorization: Bearer <token>` 头。它**默认关闭,不带令牌不会注册** — 永远不要在未经身份验证的情况下公开您的模式。两个传输运行相同的协议处理程序(传输无关的 `Dispatcher`)。
## 工具
| 工具 | 返回内容 |
|------|-----------------|
| `list_routes` | 方法、URI、名称、操作和中间件(可选的子字符串筛选)。 |
| `list_models` | 在 `app/Models` 下找到的 Eloquent 模型及其表。 |
| `describe_model` | 模型的表、列、可填充/隐藏、转换和关系。 |
| `relationship_graph` | 每个模型及其关系作为图(节点 + 边)。 |
| `describe_table` | 任何表的列、索引和外键(不仅限于模型)。 |
| `database_schema` | 每个表及其列 — 整个模式概览。 |
| `explain_query` | 只读 SELECT 的查询计划(EXPLAIN)— 不运行它。 |
| `tail_logs` | 日志文件的最后一行(默认为 `storage/logs` 中的最新日志)。 |
| `config_get` | 配置值,敏感值已编辑。 |
| `migration_status` | 已运行的迁移与待处理的迁移,带有批次编号。 |
| `list_commands` | 已注册的 Artisan 命令及其描述。 |
| `model_query` | 来自只读 Eloquent 查询的行(筛选、列、关系)。需选择加入。 |
| `database_query` | 来自单个 **只读** SELECT 的行。需选择加入(见下文)。 |
## 数据工具说明
`model_query` 和 `database_query` 都返回行数据,因此**默认关闭** — 通过 `MCP_MODEL_QUERY=true` / `MCP_DATABASE_QUERY=true` 启用它们。`model_query` 不能运行原始 SQL(它从结构化参数构建 Eloquent 查询),这使其成为两者中较安全的。
对于 `database_query` 具体来说:启用后,每个查询都被验证为单个只读语句 *和* 在始终回滚的交易中运行。这是深度防御,而不是保证 — 正确的方法是针对特权最少的只读数据库用户运行它。通过以下方式启用:
```env
MCP_DATABASE_QUERY=true
MCP_DB_CONNECTION=readonly # 可选:只读连接
```
## 资源
除了工具之外,服务器还暴露只读**资源** — 客户端可以将上下文附加到对话中,而不是按需调用:
| URI | 内容 |
|-----|---------|
| `laravel://schema` | 整个数据库模式(表 + 列)。 |
| `laravel://routes` | 每个路由(方法、URI、名称、操作、中间件)。 |
| `laravel://models` | 模型关系图。 |
它们通过 `resources/list` / `resources/read` 提供,是同名工具的薄适配器。在 `resources` 配置块中切换它们。
## 提示
服务器还附带**提示**(`prompts/list` / `prompts/get`)— 客户端可以作为斜杠命令显示的参数化模板。每个提示都指向上面的工具,因此一键提示变成有根据的工作:
| 提示 | 功能 |
|--------|------|
| `explain_app` | 通过路由、模型图和模式浏览应用程序。 |
| `review_model` | 审查模型(参数:`model`)— 关系、转换、N+1、大量赋值。 |
| `write_test` | 编写 Pest 测试(参数:`subject`),在检查路由/模型之前。 |
| `debug_recent_error` | 读取最近的日志并跟踪最新的错误。 |
在 `prompts` 配置块中切换它们。
## 限制
在使用它之前需要注意:
- `list_models` / `relationship_graph` 假设 Laravel 默认的 PSR-4 映射(`App\Models` → `app/Models`)。对于其他位置的模型,请在配置中设置 `models_path` / `models_namespace`(或 `MCP_MODELS_PATH` / `MCP_MODELS_NAMESPACE` 环境变量)。
- `describe_model` 仅在关系方法声明返回类型时检测关系(例如 `public function posts(): HasMany`)。未类型化的关系方法不会列出 — 调用每个方法来查找是不安全的。
- `database_query` / `explain_query` 只读检查是关键字/结构启发式,而不是 SQL 解析器。与只读 DB 用户配对;不要将启发式视为您的唯一防御线。
- `tail_logs` 返回日志文件中的内容,可能包括敏感数据(异常有效载荷、令牌)。禁用它或如果这很重要,请擦除日志。
## 开发
```bash
composer install
./vendor/bin/pest
```
## 许可证
MIT — 请参阅 [LICENSE](LICENSE)。