内容
# starlight-mcp
为您的 [Astro](https://astro.build) 或 [Starlight](https://starlight.astro.build) 文档站点提供一个 [MCP](https://modelcontextprotocol.io) 服务器。
代理连接至 `https://your-site.com/mcp` 并获取三个工具 — `search_docs`、`get_doc`、`list_docs` — 直接从您的文档内容集合中获取答案。无需数据库,无需嵌入,无需独立服务:语料库是一个在构建时生成的 JSON 文件,服务器是一个无状态的 JSON-RPC 处理程序,小到可以在一坐下读完。
```bash
npm install starlight-mcp
```
**实时演示**:discountkit 文档在 `https://next.discountkit.app/mcp` 处提供服务 —
```bash
claude mcp add --transport http discountkit-docs https://next.discountkit.app/mcp
```
## 工作原理
1. **构建时** — Astro 集成在您的站点中注入了两个预渲染的路由:
- `/mcp/docs-index.json` — 您的文档集合的每一页(标题、描述、URL、清理后的 Markdown 正文)
- `/mcp-schema.json` — 一个机器可读的工具目录,代理可以在连接前发现(从您的 `llms.txt` 中链接)
2. **运行时** — 一个无依赖的处理程序通过无状态的 [可流式 HTTP](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http) 进行通信:纯 JSON-RPC 通过 POST。它在每个隔离区加载语料库一次,并回答 `initialize`、`tools/list` 和 `tools/call`。在 SSR 站点中,集成为您注入;在静态站点中,您在主机上添加一个小 shim(下面的 Cloudflare 配方)。
由于传输是无状态的 HTTP,因此它适用于 Claude Code、Cursor、VS Code、Windsurf 以及任何支持 MCP 的客户端 — 无需 SSE,无需会话,无需粘性路由。
## 快速入门
### 1. 添加集成
```js
// astro.config.mjs
import { defineConfig } from "astro/config";
import starlight from "@astrojs/starlight";
import starlightMcp from "starlight-mcp";
export default defineConfig({
site: "https://your-site.com", // 必需 — 结果中的 URL 是绝对的
integrations: [
starlight({ title: "我的文档" }),
starlightMcp({
serverName: "my-docs",
siteLabel: "我的产品",
docsRedirect: "/docs/ai-tools/", // 如果用户在浏览器中打开 /mcp,则跳转到此页面
}),
],
});
```
这就是 **SSR 站点**(`output: "server"`)的全部设置:实时端点被注入到 `/mcp`。
对于 **静态站点**,构建会生成语料库和模式,您通过几行主机胶水来提供端点:
### 2. Cloudflare Workers 上的静态站点
```ts
// worker/index.ts
import { createStaticMcpWorker } from "starlight-mcp/cloudflare";
export default createStaticMcpWorker({
serverName: "my-docs",
siteLabel: "我的产品",
docsRedirect: "/docs/ai-tools/",
});
```
```jsonc
// wrangler.jsonc
{
"name": "my-docs-site",
"main": "worker/index.ts",
"compatibility_date": "2025-06-01",
"assets": {
"directory": "./dist",
"binding": "ASSETS",
"run_worker_first": ["/mcp"] // 仅在 /mcp 上唤醒脚本
}
}
```
所有其他请求都从静态资产层提供,而无需调用 Worker — 您只需为 MCP 流量支付脚本执行费用。
### 3. 任意其他主机
`starlight-mcp/handler` 是一个纯粹的 `(Request) => Promise<Response>`,没有任何依赖 — 将其连接到任何支持 fetch 的东西:
```ts
import { createMcpHandler } from "starlight-mcp/handler";
const handler = createMcpHandler({
serverInfo: { name: "my-docs", version: "1.0.0" },
siteLabel: "我的产品",
loadIndex: async () => {
// 从构建放置 docs-index.json 的位置返回 DocEntry[]
const res = await fetch("https://your-site.com/mcp/docs-index.json");
return res.json();
},
});
```
## 连接客户端
```bash
# Claude Code
claude mcp add --transport http my-docs https://your-site.com/mcp
```
```jsonc
// Cursor — .cursor/mcp.json
{
"mcpServers": {
"my-docs": { "url": "https://your-site.com/mcp" }
}
}
```
仅支持 stdio 的客户端可以使用 [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) 进行桥接:
```jsonc
{
"mcpServers": {
"my-docs": {
"command": "npx",
"args": ["mcp-remote", "https://your-site.com/mcp"]
}
}
}
```
## 工具
| 工具 | 参数 | 返回 |
| --- | --- | --- |
| `search_docs` | `query` | 按加权项匹配(标题 ×6,描述 ×3,正文出现次数)排名前 5 的页面,每个页面包含 URL、描述和第一个命中周围的片段 |
| `get_doc` | `path`(文档 ID 或 URL) | 带有源 URL 的完整 Markdown 页面 |
| `list_docs` | — | 每个页面包含标题、描述和 URL |
## 选项
所有选项都是可选的。
| 选项 | 默认值 | 功能 |
| --- | --- | --- |
| `serverName` | `<site-host>-docs` | 报告给客户端的 MCP 服务器名称 |
| `serverVersion` | `"0.1.0"` | 报告给客户端的版本 |
| `path` | `"/mcp"` | 端点路径;语料库位于 `${path}/docs-index.json`,目录位于 `${path}-schema.json` |
| `collection` | `"docs"` | 要索引的内容集合(Starlight 的是 `docs`) |
| `siteLabel` | 站点主机 | 工具描述和 `initialize` 说明中使用的人类可读产品名称 |
| `instructions` | 生成 | 代理连接时看到的 `instructions` 字符串 |
| `include` | 全部 | 仅索引 ID 以这些前缀之一开头的文档 |
| `exclude` | 无 | 丢弃 ID 以这些前缀之一开头的文档 |
| `docsRedirect` | — | 302 在浏览器中打开端点的用户到此页面(否则:礼貌的 405 JSON 解释器) |
| `toolDescriptions` | 生成 | 替换任何工具的描述,例如 `{ search_docs: "搜索 Acme 文档(计费、Webhook、SDK)…" }` — 值得手动调整,以便代理知道何时调用它。对象形式还会覆盖参数描述: `{ search_docs: { description: "…", args: { query: "例如 'webhook 重试'" } } }` |
MDX 噪音(导入语句、独立的 `<Component>` 标签行)会自动从索引正文中剥离。
## 使其可发现
两个廉价的技巧可以让代理实际找到服务器:
- **llms.txt** — 在您的页面列表之前引导 MCP 端点,例如
```
## MCP 服务器
连接以获取结构化搜索而不是爬取:
claude mcp add --transport http my-docs https://your-site.com/mcp
工具目录:https://your-site.com/mcp-schema.json
```
- **人类文档页面** — 带有每个编辑器的安装代码片段的“AI 工具”页面,并将 `docsRedirect` 指向它,以便用户在浏览器中打开 `/mcp` 时会跳转到一个有用的位置。
## 注意
- **提供 TypeScript 源代码。** 包通过打包器 — Astro/Vite、wrangler 的 esbuild、Bun、tsx — 消费,它们都原生支持 `.ts`。没有打包器的普通 `node` 需要一个转译步骤(已编译的 dist 正在开发中)。
- **协议** — 实现用于协议版本 `2025-06-18` 和 `2025-03-26` 的无状态可流式 HTTP:`initialize`、`ping`、`notifications/*`(202)、`tools/list`、`tools/call`;CORS 是开放的,以便基于浏览器的客户端可以使用。
- **状态** — 无。无会话,无 KV,无 cookie。语料库在每个隔离区/进程中缓存,并在部署时刷新。
## 路线图
- 编译的 `dist/` + `.d.ts` 适用于无打包器的 Node 消费者
- 为大型文档集提供可选的 MiniSearch 支持的索引
- `extraTools` 出口,用于站点特定的工具
- 用于异国情调的 MDX 的自定义 `clean` 函数
- 针对官方 MCP SDK 客户端的一致性测试
- 从同一语料库生成 `llms.txt` / `llms-full.txt`
## 先前作品
- [Varity 的文档](https://github.com/varity-labs/varity-docs) — `/mcp-schema.json` + llms.txt 招募模式
- [mcpdoc](https://github.com/langchain-ai/mcpdoc) — 由 llms.txt 驱动的文档 MCP 作为本地 stdio 服务器
- 为(并在 [discountkit](https://next.discountkit.app) 文档上证明)构建
## 许可证
MIT © bkspace