11# Halo MCP Server
22
3- A [ Model Context Protocol] ( https://modelcontextprotocol.io/ ) server for Halo.
4- It exposes native post, single-page, taxonomy, and attachment tools to MCP clients
5- through scoped MCP access keys. Enabled Halo plugins can
6- also contribute their own tools through the small, protocol-neutral MCP Server API.
3+ Halo 的 [ Model Context Protocol(MCP)] ( https://modelcontextprotocol.io/ ) 服务端插件,
4+ 让 Codex、Claude Code、Cursor、VS Code 等 AI 客户端通过受控的访问密钥管理 Halo 网站。
75
8- ## Requirements
6+ ## 功能特性
97
10- - Halo 2.26.0 or later
11- - Java 21 for local development
12- - An HTTPS endpoint for production use
13- - An MCP client that supports Streamable HTTP and custom bearer tokens
8+ - 搜索、读取、创建、更新、发布和回收文章及独立页面
9+ - 查询和管理文章分类、标签、评论及评论回复
10+ - 查询、上传和删除附件
11+ - 按访问密钥选择可用工具,并支持有效期、禁用、轮换和 IP 白名单
12+ - 在 Halo 控制台查看工具来源和最近调用记录
13+ - 自动发现其他 Halo 插件贡献的 MCP 工具
1414
15- The plugin uses MCP Java SDK 2.0.0 and supports protocol versions ` 2024-11-05 ` ,
16- ` 2025-03-26 ` , ` 2025-06-18 ` , and ` 2025-11-25 ` . It does not implement the legacy
17- HTTP+SSE transport, the 2026 protocol era, or MCP OAuth discovery.
15+ ## 使用要求
1816
19- ## Endpoint and authentication
17+ - Halo 2.26.0 或更高版本
18+ - 生产环境使用 HTTPS
19+ - 支持 Streamable HTTP 和自定义 Bearer Token 的 MCP 客户端
2020
21- After installing and enabling the plugin, the MCP endpoint is:
21+ ## 快速开始
22+
23+ 1 . 在 Halo 控制台中安装并启用 MCP Server 插件。
24+ 2 . 打开「工具 → MCP 服务」。
25+ 3 . 创建访问密钥,并选择该密钥可以调用的工具。
26+ 4 . 复制页面提供的客户端配置,并按提示通过环境变量或安全输入保存密钥。
27+
28+ MCP 端点为:
2229
2330``` text
2431https://halo.example.com/mcp
2532```
2633
27- Open ** Tools → MCP 服务** in Halo Console, generate a key, and select the exact
28- tools that key may call. The page also shows the endpoint, a quick client
29- configuration, and each tool's built-in or provider-plugin source. The management
30- page and API are restricted to Halo super administrators. The generated key is
31- displayed only once.
32-
33- Requests must include the generated MCP key:
34+ 访问密钥只会在创建或轮换后显示一次。新安装的工具默认不会加入已有密钥,需要管理员手动
35+ 选择。MCP 服务管理入口仅对 Halo 超级管理员开放。
3436
35- ``` http
36- Authorization: Bearer hmcp_...
37- ```
37+ ## 客户端配置
3838
39- Tool access is independent of Halo content RBAC: the key's exact tool allowlist
40- is the authorization boundary. Newly installed tools are denied until an
41- administrator explicitly adds them to a key. Disabled and expired keys are
42- rejected, and rotating a key invalidates its previous secret immediately.
43- Each key can optionally restrict access to exact IPv4 or IPv6 addresses and CIDR
44- ranges. An empty IP allowlist means unrestricted access. Requests from an
45- unmatched or unknown source are rejected as unauthorized and do not update the
46- key's last-used time.
47-
48- IP restrictions use the remote address normalized by Halo's HTTP stack. When
49- Halo is behind a reverse proxy, configure the proxy and Halo so that untrusted
50- clients cannot supply or preserve ` Forwarded ` or ` X-Forwarded-* ` headers, and
51- prevent direct access that bypasses the trusted proxy. An IP allowlist is an
52- additional control, not a replacement for TLS and least-privilege tool access.
53-
54- Requests carrying an MCP Bearer token are limited to 600 per minute per observed
55- network source before key validation. This is an overall source-level ceiling and
56- includes successful requests. Tool calls are additionally limited to 120 per
57- minute for each access-key and tool pair. Limits are process-local and therefore
58- apply independently to each Halo replica.
59-
60- Authenticated request handling is cancelled after a 30-second deadline, and
61- concurrent authenticated requests are capped at 100 globally and 16 per access
62- key; requests beyond the cap receive ` 429 Too Many Requests ` . Attachment uploads
63- reserve their decoded size against in-flight byte budgets of 64 MiB globally and
64- 32 MiB per key before decoding, and excess uploads fail with ` RATE_LIMITED ` .
65-
66- Use a dedicated, least-privilege key. Do not put keys in URLs, configuration
67- files committed to source control, shell history, or logs.
68-
69- Direct browser requests are rejected because the transport does not allow an
70- ` Origin ` header by default. CLI clients and server-side Inspector connections
71- normally omit that header.
72-
73- ## Tools
74-
75- | Tool | Purpose |
76- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
77- | ` halo_search_content ` | Search posts and single pages. |
78- | ` halo_list_posts ` / ` halo_get_post ` | List posts or read HEAD/RELEASE content. |
79- | ` halo_create_post ` / ` halo_update_post ` | Create or update a post and its content snapshots. |
80- | ` halo_set_post_publish_state ` / ` halo_recycle_post ` | Set a post's publication state or recycle it. |
81- | ` halo_list_single_pages ` / ` halo_get_single_page ` | List single pages or read HEAD/RELEASE content. |
82- | ` halo_create_single_page ` / ` halo_update_single_page ` | Create or update a single page and its content snapshots. |
83- | ` halo_set_single_page_publish_state ` / ` halo_recycle_single_page ` | Set a page's publication state or recycle it. |
84- | ` halo_list_categories ` / ` halo_create_category ` / ` halo_update_category ` | List, create, or update post categories. |
85- | ` halo_list_tags ` / ` halo_create_tag ` / ` halo_update_tag ` | List, create, or update post tags. |
86- | ` halo_list_comments ` / ` halo_set_comment_approval ` / ` halo_delete_comment ` | List, moderate, or delete comments. |
87- | ` halo_list_comment_replies ` / ` halo_set_reply_approval ` / ` halo_delete_reply ` | List, moderate, or delete comment replies. |
88- | ` halo_list_attachments ` / ` halo_get_attachment ` | List or inspect attachments. |
89- | ` halo_upload_attachment ` / ` halo_delete_attachment ` | Upload a Base64 attachment (up to 8 MiB) or delete an attachment. |
90-
91- Native and plugin-contributed tools are exposed directly in ` tools/list ` ; there
92- are no discovery or execution gateway tools. The response contains only the
93- tools selected for the current key. Category and tag updates, comment and reply
94- moderation, and attachment deletion accept an optional ` expectedVersion ` ; a stale
95- version returns ` CONFLICT ` instead of overwriting a newer resource. Post and
96- single-page writes instead re-read and retry the latest resource because Halo
97- reconcilers may advance their metadata versions independently. Attachment uploads
98- intentionally accept inline Base64 only, avoiding server-side URL fetching and
99- SSRF exposure.
100-
101- ## Plugin integration
102-
103- Halo plugins can contribute tools without making MCP Server a required runtime
104- dependency. See the [ plugin integration guide] ( ./dev/dev.md ) for the Gradle
105- dependency, optional plugin manifest entry, provider implementation, lifecycle,
106- and verification steps.
107-
108- Search, list, and lookup tools are read-only. Create, update, publish, unpublish,
109- and comment moderation tools are non-destructive writes; only recycle and delete
110- tools are annotated as destructive. Recycled content and attachments are excluded
111- from lists by default. ` halo_get_post ` and ` halo_get_single_page ` limit each
112- returned content field to 65,536 characters and report whether truncation occurred.
113-
114- ## Client configuration
115-
116- Export the token in the client process environment:
39+ 先在客户端进程的环境变量中设置密钥:
11740
11841``` bash
11942export HALO_MCP_TOKEN=' hmcp_replace_me'
12043```
12144
12245### Codex
12346
124- Add the following to ` ~/.codex/config.toml ` or a trusted project's
125- ` .codex/config.toml ` :
47+ 将以下配置加入 ` ~/.codex/config.toml ` ,或可信项目中的 ` .codex/config.toml ` :
12648
12749``` toml
12850[mcp_servers .halo ]
12951url = " https://halo.example.com/mcp"
13052bearer_token_env_var = " HALO_MCP_TOKEN"
13153```
13254
133- See the [ official Codex MCP documentation] ( https://developers.openai.com/codex/mcp/ )
134- for other client options.
55+ 其他选项参阅 [ Codex 官方 MCP 文档] ( https://developers.openai.com/codex/mcp/ ) 。
13556
13657### Claude Code
13758
138- Add a project-scoped ` .mcp.json ` that reads the token from the environment:
59+ 在项目级 ` .mcp.json ` 中通过环境变量读取密钥:
13960
14061``` json
14162{
@@ -151,12 +72,11 @@ Add a project-scoped `.mcp.json` that reads the token from the environment:
15172}
15273```
15374
154- See the [ official Claude Code MCP documentation ] ( https://code.claude.com/docs/en/mcp ) .
75+ 其他选项参阅 [ Claude Code 官方 MCP 文档 ] ( https://code.claude.com/docs/en/mcp ) 。
15576
15677### MCP Inspector
15778
158- The current Inspector accepts an ad-hoc Streamable HTTP target and repeated
159- headers:
79+ Inspector 支持临时指定 Streamable HTTP 端点和 Bearer 请求头:
16080
16181``` bash
16282npx @modelcontextprotocol/inspector \
@@ -165,74 +85,20 @@ npx @modelcontextprotocol/inspector \
16585 --header " Authorization: Bearer ${HALO_MCP_TOKEN} "
16686```
16787
168- Keep the Inspector protocol era on ` legacy ` or ` auto ` ; Java SDK 2.0.0 does not
169- implement the 2026 protocol era.
170-
171- ## Development
172-
173- Run the tests and build the plugin JAR:
174-
175- ``` bash
176- bash gradlew test
177- bash gradlew build
178- ```
179-
180- Regenerate the Console API client after changing an API route or DTO:
181-
182- ``` bash
183- bash gradlew generateApiClient
184- ```
185-
186- The generated OpenAPI document is written to
187- ` api-docs/openapi/v3_0/mcpV1alpha1Api.json ` , and the TypeScript Axios client is
188- written to ` ui/src/api/generated ` . Do not edit generated client files manually.
189-
190- Run a compatible Halo development server:
191-
192- ``` bash
193- bash gradlew haloServer
194- ```
195-
196- The official conformance CLI cannot add the custom Bearer header required by
197- this plugin. For local protocol checks, start the loopback-only authentication
198- proxy with a temporary least-privilege key, then run applicable server scenarios:
199-
200- ``` bash
201- HALO_MCP_TOKEN=' hmcp_...' node dev/conformance-proxy.mjs
202- npx @modelcontextprotocol/conformance@0.1.11 server \
203- --url http://127.0.0.1:8091/mcp \
204- --scenario server-initialize
205- ```
206-
207- Run scenarios matching the plugin's advertised capabilities, such as
208- ` server-initialize ` , ` ping ` , and ` tools-list ` . The complete conformance server
209- suite targets an everything-server fixture and also requires optional resources,
210- prompts, audio, image, sampling, and elicitation features that this plugin does
211- not advertise. Its localhost DNS-rebinding scenario is also scoped to servers
212- without authentication, whereas this endpoint always requires an MCP key and
213- rejects browser ` Origin ` headers.
214-
215- The distributable JAR is generated under ` build/libs/ ` .
88+ Inspector 的协议版本请选择 ` legacy ` 或 ` auto ` 。
21689
217- ## Error model
90+ ## 安全提醒
21891
219- Tool failures return ` isError: true ` with a stable structured error code:
92+ - 为每个客户端创建专用的最小权限密钥,不要把密钥提交到版本库或写入日志。
93+ - IP 白名单是附加防护,不能替代 HTTPS 和最小权限的工具授权。
94+ - Halo 位于反向代理之后时,只信任由可信代理写入的 ` Forwarded ` 和 ` X-Forwarded-* ` 请求头,并阻止客户端绕过代理直接访问 Halo。
95+ - 默认不允许携带 ` Origin ` 请求头的浏览器直连请求,请使用 MCP 客户端或 Inspector。
22096
221- - ` INVALID_ARGUMENT `
222- - ` INVALID_ARGUMENTS `
223- - ` NOT_FOUND `
224- - ` FORBIDDEN `
225- - ` CONFLICT `
226- - ` SEARCH_UNAVAILABLE `
227- - ` CONTENT_UNAVAILABLE `
228- - ` ATTACHMENT_UNAVAILABLE `
229- - ` INVALID_TOOL_RESULT `
230- - ` RATE_LIMITED `
231- - ` INTERNAL `
97+ ## 插件开发
23298
233- Search can be unavailable when Halo has no active search engine. Listing and
234- direct content reads remain available in that situation.
99+ 其他 Halo 插件可以通过协议无关的 API 贡献 MCP 工具,接入方式参阅
100+ [ 插件工具 Provider 接入指南 ] ( ./dev/dev.md ) 。
235101
236- ## License
102+ ## 许可证
237103
238104[ GPL-3.0] ( ./LICENSE ) © Halo
0 commit comments