首页
/ Coolify 的 Laravel MCP Server 开发指南:从 SKILL.md 技能规范到 44 个 Tool 的落地实现

Coolify 的 Laravel MCP Server 开发指南:从 SKILL.md 技能规范到 44 个 Tool 的落地实现

2026-09-04 13:44:24作者:宣海椒Queenly

本文以 Coolify 仓库中的 MCP 开发技能文档 .agents/skills/mcp-development/SKILL.md 为主体,完整讲解 Laravel MCP 框架的注册、原语(Tool/Resource/Prompt)创建、Server 装配与验证流程,并结合 Coolify 自身 app/Mcp 目录下的真实源码,展示一个生产级 MCP Server 是如何从规范走向 44 个工具、2 个资源、2 个提示词的完整实现。读完本文,你将掌握在 Laravel 项目中搭建、调试并安全暴露 MCP 端点的全部关键步骤。

SKILL.md 的定位与适用边界

该技能文档以 YAML frontmatter 声明了自己的元信息:name: mcp-developmentlicense: MITauthor: laravel,并在 description 中明确了两点边界:

  • 只在 Laravel MCP 开发场景触发:创建或编辑 MCP 工具、资源、提示词、Server 时启用,覆盖 artisan make:mcp-* 生成器、mcp:inspectorroutes/ai.php、Tool/Resource/Prompt 类、schema 校验、shouldRegister()、OAuth 配置、URI 模板、只读属性与 MCP 调试;
  • 明确排除非 Laravel 的 MCP 项目,以及不含 MCP 的泛化 AI 功能。

这说明文档是一份“开发者操作手册”而非产品说明:它假定你已经引入 laravel/mcp 包(Coolify 在 composer.json 中声明依赖 "laravel/mcp": "^0.6.7"),接下来只讲怎么把它用对。

在 routes/ai.php 中注册 MCP Server

文档给出的最基础用法是在 routes/ai.php 中通过 Mcp 门面注册 Web 端点:

use Laravel\Mcp\Facades\Mcp;

Mcp::web();

Coolify 的实际注册比最小示例多两个关键点——指定了 URI 前缀并挂上了一组中间件(见 routes/ai.php):

use App\Mcp\Servers\CoolifyServer;
use Laravel\Mcp\Facades\Mcp;

Mcp::web('/mcp', CoolifyServer::class)
    ->middleware(['mcp.enabled', 'auth:sanctum', 'api.token.team', 'mcp.team.enabled']);

两个值得注意的事实:

  1. routes/ai.php 不需要手动注册。文档在 Common Pitfalls 中特别警告“不要在 bootstrap 中注册 ai.php,它是被框架自动注册的”。如果你按 Laravel 常规习惯去 bootstrap/app.php 里补一条 ->withRouting( ..., ai: ...),反而会出问题。
  2. 中间件是 MCP 端点的“门禁”。Coolify 用四个中间件构成纵深防御:mcp.enabled 检查实例级开关,auth:sanctum 要求 Sanctum 令牌,api.token.team 校验令牌归属,mcp.team.enabled 检查团队级 MCP 开关。其中 app/Http/Middleware/EnsureMcpEnabled.php 的实现非常简洁——读取 InstanceSettings::get()->is_mcp_server_enabled,未开启则直接 abort(404),让端点对未启用的实例“彻底隐身”,而不是返回 403 暴露端点存在。中间件别名在 app/Http/Kernel.php 中注册:
'mcp.enabled' => EnsureMcpEnabled::class,
'mcp.team.enabled' => EnsureTeamMcpEnabled::class,

用 artisan 命令生成 MCP 原语

Laravel MCP 框架为三类原语和 Server 本体都提供了生成器,这是文档给出的完整命令集:

php artisan make:mcp-tool ToolName         # 创建工具
php artisan make:mcp-resource ResourceName  # 创建资源
php artisan make:mcp-prompt PromptName      # 创建提示词
php artisan make:mcp-server ServerName      # 创建 Server

生成之后,必须在 Server 的 $tools$resources$prompts 属性中显式注册——框架不会自动发现这些类。Coolify 的目录结构印证了这一组织方式:app/Mcp/ 下按类型分为 Tools/(44 个工具类)、Resources/(2 个)、Prompts/(2 个)、Servers/(1 个),另有 Concerns/ 存放共享 Trait。

Tool:最小实现到带 schema 的完整实现

文档给出的最小 Tool 示例:

use Laravel\Mcp\Server\Tool;
use Laravel\Mcp\Server\Request;
use Laravel\Mcp\Server\Response;

class MyTool extends Tool
{
    public function handle(Request $request): Response
    {
        return new Response(['result' => 'success']);
    }
}

结构上就是一个“继承 Laravel\Mcp\Server\Tool、实现 handle(Request): Response”的类。Coolify 中的 app/Mcp/Tools/CoolifyHelp.php 则展示了生产级 Tool 补足了哪些要素:

  • $name$descriptioncoolify_help 及其面向 LLM 的描述文本("Call first when unsure which Coolify MCP tool to use"),这段描述本身就是提示词工程的一部分;
  • schema() 方法:接收 Illuminate\Contracts\JsonSchema\JsonSchema,以数组形式声明入参,例如 'intent' => $schema->string()->description(...)——这就是文档提到的 schema 校验在 Coolify 侧的落点;
  • 权限前置检查handle() 第一行先调 $this->ensureAbility($request, 'read', $this->name),令牌能力不足时直接返回结构化的 missing_ability 错误,再走 resolveTeamId 解析团队作用域。Coolify 的所有 Tool 都通过 BuildsResponseResolvesTeamConcerns 共享这套逻辑(见 app/Mcp/Concerns/);
  • 响应信封:统一走 mcpSuccess/mcpError/respond,最终输出 { data, _actions?, _pagination? } 结构,与 Server 级 $instructions 中向客户端声明的契约一致。

Resource:URI 模板与团队作用域查询

文档要点之一是 Resource 支持 URI 模板(URI templates)。Coolify 的 app/Mcp/Resources/ApplicationResource.php 是完整示例:

class ApplicationResource extends Resource implements HasUriTemplate
{
    protected string $name = 'coolify-application';
    protected string $mimeType = 'application/json';

    public function uriTemplate(): UriTemplate
    {
        return new UriTemplate('coolify://application/{uuid}');
    }

    public function handle(Request $request): Response
    {
        // 权限检查 → 解析 uuid → 按团队作用域查询 → 脱敏后返回 JSON
    }
}

三个实现细节值得借鉴:

  1. 通过 use Laravel\Mcp\Server\Contracts\HasUriTemplate 实现接口并返回 UriTemplate,让客户端可以用 coolify://application/{uuid} 这样的地址引用资源;
  2. 查询使用 Application::ownedByCurrentTeamAPI($teamId) 这类“按当前团队限定”的作用域,MCP 令牌只能看到自己团队的数据——这正是 CoolifyServer.php $instructions 中 "Every tool enforces team ownership" 承诺的落地方式;
  3. 返回前经过 scrubSensitive() 脱敏,且 Server 级说明明确 "Env values, configuration snapshots, and full deploy logs are never returned"——敏感数据在 Resource 层就被拦下。

Prompt:参数化模板与引导式工作流

文档中 Prompt 的生成命令是 php artisan make:mcp-prompt,对应 Laravel\Mcp\Server\Prompt 基类。Coolify 的 app/Mcp/Prompts/TroubleshootApplication.php 展示了 Prompt 的真正价值:它不只是返回一段文本,而是把一套“DB 优先、日志兜底”的排障 SOP 固化下来——

  • arguments() 方法声明参数:new Argument(name: 'uuid', description: ..., required: true)
  • handle() 将用户传入的 uuid 注入一段多行 Markdown 模板(<<<MD ... MD),生成分三阶段(Phase A 数据库元数据 → Phase B 容器运行中才取活日志 → Phase C 有 deploy 权限才做生命周期操作)的排查步骤,并规定 get_logs 失败时要读 reason + next_tools 而不要盲目重试。

另一个 Prompt explain_failed_deploy 与之配合,覆盖了“应用故障”和“部署失败”两个高频场景。

Server 装配:CoolifyServer 的完整声明

把原语注册进 Server 是文档强调的“显式声明”原则,Coolify 的 app/Mcp/Servers/CoolifyServer.php#L56-L91 是仓库中可直接对照的完整样板:

class CoolifyServer extends Server
{
    protected string $name = 'Coolify';
    protected string $version = '0.2.0';

    /**
     * Return all registered tools in a single tools/list page (default package limit is 15).
     */
    public int $maxPaginationLength = 100;
    public int $defaultPaginationLength = 100;

    protected string $instructions = <<<'MD'
Coolify MCP for the authenticated team token. Every tool enforces team ownership.
Start here (prefer these before deep get_*):
1. coolify_help — tool catalog by intent ...
MD;

    protected array $tools = [ CoolifyHelp::class, /* ... 共 44 个 */ CancelDeployment::class ];
    protected array $resources = [ InfrastructureOverviewResource::class, ApplicationResource::class ];
    protected array $prompts = [ TroubleshootApplication::class, ExplainFailedDeploy::class ];
}

这里有三个文档未展开、但源码里体现得很清楚的增强点:

  • $instructions:一段写给 MCP 客户端(即 LLM Agent)的“使用说明书”,规定了推荐调用顺序(先 coolify_helpget_infrastructure_overviewsearch_resources)、调试策略(DB 优先、失败时读 reason + next_tools 不循环重试)以及响应契约。这是 MCP 框架下“把产品知识写进协议元数据”的典型做法;
  • 分页调优laravel/mcp 默认 tools/list 单页上限是 15 个,Coolify 注册了 44 个 Tool,因此把 $maxPaginationLength$defaultPaginationLength 都调到 100,保证客户端一次性拿到完整工具清单;
  • 能力分层$tools 列表里 controldeploycancel_deployment 属于生命周期操作,要求令牌具备 deploy ability,只读令牌调用时会收到明确的 missing_ability 错误——权限粒度做到了工具级别。

验证:确认注册与客户端实测

文档的 Verification 一节给出两步:检查 routes/ai.php 注册是否正确,再用 MCP 客户端实测 Tool。结合仓库,验证清单可以细化为:

  1. 打开 routes/ai.php:确认 Mcp::web() 的目标 Server 类存在、中间件链完整;
  2. 确认 Server 类的 $tools/$resources/$prompts 中每个类都已 use 导入且文件存在——Coolify 的 44 个 Tool 全部位于 app/Mcp/Tools/
  3. 打开实例级 MCP 开关(is_mcp_server_enabled),否则 mcp.enabled 中间件会让 /mcp 直接 404(见 app/Http/Middleware/EnsureMcpEnabled.php);
  4. 用 MCP 客户端(或 mcp:inspector)连接端点,先调用 coolify_help 验证意图目录返回,再抽查一个 list_* 工具确认数据作用域正确。

常见陷阱:六条来自实践的血泪教训

SKILL.md 的 Common Pitfalls 一节浓缩了调试 MCP 时最常踩的坑,逐条对照仓库说明:

陷阱 说明
运行 mcp:start 命令 该命令会挂起等待输入(stdin),在自动化/远程环境里表现为“卡死”,调试请改用 Web 端点 + 客户端
本地用 HTTPS 配 Node 系 MCP 客户端 本地开发用 HTTP 即可,HTTPS 自签证书常导致 Node 客户端握手失败
不用 search-docs 查最新文档 MCP 框架迭代快,本地过时的认知是主要事故源
未把 MCP 路由注册进 routes/ai.php 端点不存在,客户端连接直接失败
在 bootstrap 中注册 ai.php 它是框架自动注册的,重复注册反而出错
OAuth 注册不支持自定义 URI scheme 桌面原生客户端(如 cursor://vscode://)需要自定义 scheme 回调,通过 mcp.custom_schemes 配置项支持

小结

这份 SKILL.md 的价值在于把 Laravel MCP 的开发路径压缩成一条可执行主线:生成器出骨架 → routes/ai.php 挂端点 → Server 显式装配 → 客户端验证。而 Coolify 仓库的 app/Mcp 目录则证明这条主线在真实项目中能长出多复杂的形态——44 个带 JSON Schema 的工具、按团队作用域查询并脱敏的资源、把排障 SOP 固化成 Prompt 的引导式模板,外加实例/团队/令牌三层中间件门禁与工具级 ability 校验。对于要在自己的 Laravel 应用中暴露 MCP 服务的开发者,建议先照 SKILL.md 的最小示例跑通 Mcp::web(),再对照 app/Mcp/Servers/CoolifyServer.php 逐步补齐 $instructions、分页与权限分层。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
docsdocs
暂无描述
Markdown
889
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341