内容
# grav-mcp
MCP 服务器,用于 [Grav CMS](https://getgrav.org) — 通过 Grav REST API 实现 AI 原生内容管理。
公开 11 个领域、5 种资源和 6 个工作流提示的 67 种语义工具。支持所有 Grav API 功能,包括页面、媒体、配置、用户、软件包、系统管理、网络钩子、蓝图、环境覆盖、仪表盘小部件和动态插件发现。
## 先决条件
- 安装并启用 [Grav CMS](https://getgrav.org) 和 [API 插件](https://github.com/getgrav/grav-plugin-api)
- 通过 `bin/plugin api keys:generate --user=admin --name="MCP"` 生成 API 密钥
- Node.js 18+
## 快速入门
### Claude 代码
将以下内容添加到您的 Claude Code MCP 配置中:
```json
{
"mcpServers": {
"grav": {
"command": "npx",
"args": ["-y", "grav-mcp"],
"env": {
"GRAV_API_URL": "https://mysite.com/api",
"GRAV_API_KEY": "grav_your_api_key_here"
}
}
}
}
```
### 运行 MCP 服务器
```bash
# 通过环境变量(推荐)
GRAV_API_URL=https://mysite.com/api GRAV_API_KEY=grav_abc123 npx grav-mcp
# 通过 CLI 参数
npx grav-mcp --url https://mysite.com/api --key grav_abc123
# HTTP 传输(用于远程部署)
npx grav-mcp --url https://mysite.com/api --key grav_abc123 --transport http --port 3100
```
## 配置
| 变量 | CLI 标志 | 必需 | 描述 |
|---|---|---|---|
| `GRAV_API_URL` | `--url` | 是 | Grav API 的基本 URL |
| `GRAV_API_KEY` | `--key` | 是 | API 密钥(以 `grav_` 开头) |
| `GRAV_ENVIRONMENT` | `--environment` | 否 | 多环境覆盖 |
## 工具参考
### 页面(10 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `list_pages` | 读取 | 列出/搜索页面,支持过滤、排序、分页 |
| `get_page` | 读取 | 获取完整页面:内容、头部、媒体、分类法 |
| `create_page` | 写入 | 创建页面,包含标题、内容、模板、头部 |
| `update_page` | 写入 | 更新页面字段(深度合并头部,ETag 支持) |
| `delete_page` | 写入 | 删除页面(可选:仅限特定语言) |
| `move_page` | 写入 | 将页面移动到新父级/重命名_slug |
| `copy_page` | 写入 | 复制页面和媒体 |
| `batch_pages` | 写入 | 批量发布/取消发布/删除/复制(最多 50 个) |
| `reorder_pages` | 写入 | 按_slug序列重新排序子页面 |
| `reorganize_pages` | 写入 | 原子化多页面移动 + 重新排序 |
### 多语言(5 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `list_languages` | 读取 | 配置的站点语言 |
| `get_page_translations` | 读取 | 哪些翻译存在/缺失(包括 `has_default_file`、`explicit_language_files`) |
| `create_translation` | 写入 | 创建页面的语言变体 |
| `adopt_page_language` | 写入 | 将未类型化的页面文件(`default.md`)重命名为 `default.{lang}.md` |
| `compare_translations` | 读取 | 两个版本的并排差异 |
### 媒体(8 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `list_page_media` | 读取 | 附加到页面的媒体文件 |
| `upload_page_media` | 写入 | 上传文件(base64)到页面 |
| `delete_page_media` | 写入 | 从页面删除媒体文件 |
| `list_site_media` | 读取 | 浏览站点媒体,支持文件夹/搜索 |
| `upload_site_media` | 写入 | 上传到站点媒体文件夹 |
| `delete_site_media` | 写入 | 删除站点媒体文件 |
| `create_media_folder` | 写入 | 创建媒体子文件夹 |
| `manage_media_folder` | 写入 | 重命名或删除文件夹 |
### 配置(3 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `list_config_scopes` | 读取 | 可用的配置部分 |
| `get_config` | 读取 | 按范围读取配置(带有 ETag) |
| `update_config` | 写入 | 更新配置(差异保存 vs 默认值,ETag,可选 `environment` 进行 `user/env/<name>/` 覆盖) |
### 用户(6 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `list_users` | 读取 | 列出用户,支持搜索 |
| `get_user` | 读取 | 用户详细信息,包含权限 |
| `create_user` | 写入 | 创建用户账户 |
| `update_user` | 写入 | 更新个人资料/权限 |
| `delete_user` | 写入 | 删除用户 |
| `manage_api_keys` | 写入 | 列出/创建/撤销 API 密钥 |
### 软件包管理器(9 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `list_packages` | 读取 | 已安装的插件/主题(包含 `is_symlink`、`description_html`) |
| `get_package_info` | 读取 | 插件/主题详细信息 + 说明文档 |
| `search_packages` | 读取 | 搜索 GPM 仓库 |
| `check_updates` | 读取 | 可用的更新(包括 Grav 核心,当 symlink 安全时) |
| `install_package` | 写入 | 安装插件/主题(自动解析蓝图依赖项) |
| `update_package` | 写入 | 更新单个软件包(自动检测插件 vs 主题) |
| `update_all_packages` | 写入 | 批量更新,验证依赖项;返回已更新/失败/跳过/级联的桶 |
| `upgrade_grav` | 写入 | 自我升级 Grav 核心(在 symlink 安装时拒绝) |
| `remove_package` | 写入 | 删除插件/主题 |
### 系统(10 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `get_system_info` | 读取 | Grav/PHP 版本、磁盘、环境 |
| `clear_cache` | 写入 | 清除缓存(全部/标准/图像/资产/临时) |
| `get_logs` | 读取 | 系统日志,支持日志级别过滤 |
| `create_backup` | 写入 | 创建完整备份 |
| `list_backups` | 读取 | 可用的备份 |
| `get_scheduler` | 读取 | 调度器作业/状态/历史记录 |
| `run_scheduler` | 写入 | 触发调度器运行 |
| `list_environments` | 读取 | 检测到的环境 + 可配置的 `user/env/*` 覆盖 |
| `create_environment` | 写入 | 创建新的 `user/env/<name>/config/` 文件夹 |
| `get_password_policy` | 读取 | 公共密码策略(正则表达式、最小长度、规则) |
### 网络钩子(4 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `list_webhooks` | 读取 | 配置的网络钩子 |
| `manage_webhook` | 写入 | 创建/更新/删除网络钩子 |
| `get_webhook_deliveries` | 读取 | 网络钩子交付日志 |
| `test_webhook` | 写入 | 发送测试负载 |
### 蓝图和模式(6 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `list_page_templates` | 读取 | 可用的页面类型 |
| `get_blueprint` | 读取 | 页面/插件/主题/配置的字段模式 |
| `get_permissions` | 读取 | 权限操作层次结构 |
| `get_taxonomy` | 读取 | 分类法类型和值 |
| `upload_blueprint_file` | 写入 | 将文件上传到蓝图的 `destination`(主题/插件/账户范围) |
| `delete_blueprint_file` | 写入 | 删除预先上传的蓝图文件,逻辑路径(幂等) |
### 仪表盘和报告(7 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `get_dashboard_stats` | 读取 | 站点概述统计信息 |
| `get_notifications` | 读取 | 系统通知(v2 模式:类型、图标、标题、Markdown、操作、依赖项) |
| `dismiss_notification` | 写入 | .dismiss 通知 |
| `get_dashboard_widgets` | 读取 | 解析的小部件列表(可见性、大小、顺序、允许的大小) |
| `update_dashboard_layout` | 写入 | 保存当前用户的小部件布局 |
| `update_site_dashboard_layout` | 写入 | 保存站点范围的默认布局(仅超级管理员) |
| `run_reports` | 读取 | 诊断报告 |
### 插件发现(2 个工具)
| 工具 | 类型 | 描述 |
|---|---|---|
| `discover_plugins` | 读取 | 插件提供的功能(侧边栏、小部件、面板、页面) |
| `plugin_action` | 写入 | 执行插件菜单栏操作 |
## 资源
| URI | 描述 |
|---|---|
| `grav://system/info` | 系统信息 |
| `grav://user/permissions` | 当前用户的权限 |
| `grav://languages` | 配置的语言 |
| `grav://templates` | 可用的页面模板 |
| `grav://taxonomy` | 分类法类型和值 |
## 提示
| 提示 | 描述 |
|---|---|
| `create_blog_post` | 引导博客文章创建工作流 |
| `translate_page` | 页面翻译工作流 |
| `site_health_check` | 全面的站点健康审计 |
| `content_audit` | 内容质量和元数据审计 |
| `plugin_setup` | 搜索、安装、配置插件 |
| `bulk_update` | 跨页面批量更新 frontmatter |
## 安全
- API 密钥仅从环境变量中读取 — 绝不记录、存储或包含在响应中
- 权限预检防止未经授权的请求到达服务器
- ETags 为写入操作提供乐观并发控制
- 所有工具参数的输入验证通过 Zod 模式
- 从 API 响应头跟踪速率限制
## 权限
每个工具都需要特定的 API 权限。服务器在发出请求之前会检查权限。 可用的权限:
```
api.access
├── api.pages.{read,write}
├── api.media.{read,write}
├── api.config.{read,write}
├── api.users.{read,write}
├── api.system.{read,write}
├── api.gpm.{read,write}
├── api.scheduler.{read,write}
├── api.reports.read
└── api.webhooks.{read,write}
```
具有 `access.api.super` 标志(从 `/me` 返回为 `super_admin: true`)的用户绕过所有检查。 旧版 `admin.super` 不受 `Grav 2.0` 保护 - 清晰地区分 admin-classic 和 API/Admin-Next 权限。
## 开发
```bash
git clone https://github.com/getgrav/grav-mcp.git
cd grav-mcp
npm install
npm run typecheck # 类型检查
npm test # 运行单元测试
npm run test:watch # 监视模式
npm run build # 编译到 dist/
```
### 使用 MCP 检测器测试
```bash
npx @modelcontextprotocol/inspector npx tsx src/index.ts
```
## 维护
Grav API 插件经常移动。两个脚本使 MCP 与之同步:
```bash
# 自上次审查以来,API 插件中发生了什么变化?
npm run changelog:since
# 审查后,标记一个版本为新的基准:
npm run changelog:since -- --bump 1.0.0-beta.16
# 是否有任何 API 端点没有 MCP 工具,或者任何工具的注释端点在路由器中不再存在?
npm run audit:api
```
`audit:api` 解析 `// @api METHOD /path` 注释,并在插件的 `ApiRouter.php` 中将它们与 `addRoute(...)` 条目进行比较。任何不应公开的端点(身份验证流程、2FA 设置、内部 admin-next 包等)都位于 `.audit-ignore` 中。 如果检测到偏差,脚本以非零退出。
添加新工具时,请在 `registerTool` 调用上方直接添加 `// @api METHOD /path` 行,以便自动更新覆盖率。
两个脚本默认查找位于 `../grav-api/user/plugins/api/` 的 API 插件。 如果本地布局不同,可以使用 `--router` / `--changelog` 标志覆盖。
## 许可证
MIT