内容
# 主要诺福克音乐服务器
一个基于 [主要诺福克音乐](https://www.mainlynorfolk.info/folk/) 的 MCP 服务器,
这是 Reinhard Zierke 的英国民谣音乐百科全书式存档,以及
[水道歌曲](https://www.waterwaysongs.info) 用于运河和内陆水道歌曲。
这两个网站都没有 API;这个项目提供了一个可组合的 GraphQL 模式,
并通过 MCP 服务器提供。
两个工具,而不是一个操作工具:`folk_schema` 返回 SDL,`folk` 运行查询。
模式有几千个令牌,因此它保留在工具调用后面 -
一个会话永远不会提及民谣音乐,几乎不需要付出任何代价。
## 安装
```bash
cargo install mainlynorfolk-mcp # 安装 `folk` 二进制文件
```
或者拉取镜像,或从
[发布页面](https://github.com/radiosilence/mainlynorfolk-mcp/releases) 获取二进制文件:
```bash
docker pull ghcr.io/radiosilence/mainlynorfolk-mcp
```
## 连接
克劳德桌面,在 `claude_desktop_config.json` 中:
```json
{
"mcpServers": {
"folk": {
"command": "folk"
}
}
}
```
克劳德代码:
```bash
claude mcp add --scope user folk -- folk
```
如果没有参数,它通过 stdio 发送 MCP,这是两者启动的方式。
## 图谱
模式是可内省的 - 将 `--graphiql` 指向它,而不是在这里读取字段列表,
因为其中一个可能会过时:
```bash
folk --graphiql --browser
```
使其值得查询而不是爬取的是边缘是真实的。
一首歌曲知道声称它的艺术家,它出现的发行版,以及引用它的书籍;
一个发行版知道它的曲目,一个曲目知道它的歌曲。图表有循环设计,
深度是关键 - `artist → discography → album → tracks → song → recordings → album`
是七个层次,直到它重复。
```graphql
{
song(path: "/lloyd/songs/sailorcutdowninhisprime.html") {
title
refs { roud child masterTitle }
lyrics { performer text }
sameRoud(first: 5) { # 其他页面共享此 Roud 编号
nodes { title }
}
}
}
```
`sameRoud` 是值得了解的边缘。Roud 编号是存档自己的“这些是相同的歌曲”密钥,
因此它重新组装一个家庭:Roud 2 收集
*Young Sailor Cut Down in His Prime*,*Bright Shiny Morning*,*When I Was on Horseback*
和 *Young Girl Cut Down in Her Prime* - 成为 *Streets of Laredo* 的民谣。
它花费一个搜索而不是爬取,并且通过 `SongSummary.song` 递归。
读取是中继连接:`first`/`after`,以及免费的 `totalCount`,
因为这些列表从一个请求中完整到达。光标是路径,因此过时的光标告诉您重新启动
而不是悄悄返回不同的页面。
搜索使用存档自己的 `search.php` 端点,而不是获取索引:
完整的歌曲索引是 670KB 的 HTML,而同一个查询服务器端是 10KB。
引用搜索接受 Roud、Child、Laws、Greig-Duncan 和 Sam Henry 编号。
## 在其他地方提供服务
```bash
folk --http # MCP 通过可流式 HTTP 在 /mcp
folk --http 0.0.0.0:8080 # 显式地址
folk --graphql # 普通 GraphQL-over-HTTP 在 /graphql
folk --graphiql --browser # 为您打开的 IDE
```
`--http`, `--graphql` 和 `--graphiql` 是独立的表面,它们恰好共享一个端口。
`--http` 将 MCP 的可流式 HTTP 传输放在 `/mcp` 上;
`--graphql` 直接为任何说 GraphQL 的内容提供服务,而不是通过 MCP 的 JSON-RPC 信封;
`--graphiql` 在 `/` 上添加 IDE。请求任何一个都绑定一个监听器,
因为没有地方可以通过 stdio 挂载 HTTP 路由。
内省是从模式中回答的,而无需触摸存档,因此 IDE 的文档和自动完成在获取单个页面之前有效。
## 缓存和礼貌
mainlynorfolk.info 是一个人的数十年来的劳动成果,手工维护,没有 API 和已发布的速率限制,
其内容每月更改几次 - 因此几乎每次读取都应该留在进程中。
四个层强制执行,从最便宜的开始:
- **内存缓存**,限定在 512 页。一个深查询不断访问相同的中心页 -
子索引,一个艺术家的唱片目录,专辑每个曲目指向的专辑 -
这使得第二次访问免费。
- **磁盘缓存** 在平台缓存目录下(Linux 上的 `~/.cache/mainlynorfolk`,
macOS 上的 `~/Library/Caches/mainlynorfolk`),在进程退出时存活,
因此长时间运行的服务器在重启期间保持收益。
- **条件重新验证**,一旦磁盘条目超过 24 小时:请求携带 `If-None-Match`/`If-Modified-Since`,
存档以 `304` 无正文回复。
- **实际获取**,上限为 4 个并发项。一个查询可以扩展为数十个页面加载;
这就是停止所有页面一次性到达的原因。
每个请求都携带一个 `User-Agent`,命名工具和此存储库。它不假装成浏览器。
`folk clear-cache` 清空磁盘缓存;`folk completions <shell>` 编写 shell 补全。
## 开发
```bash
cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --all
```
解析器是纯 `&str` → 模型函数,针对 `tests/fixtures/` 中的保存夹具进行测试,
因此测试套件不需要网络。
`tests/live_archive.rs` 检查运行假设与实际站点 -
`search.php` 仍然回答,入口点仍然存在。它被 `#[ignore]` 忽略,
并在 CI 中排除:这些打击志愿者运行的站点,
而计划的流量与此工具的其他方式相反。手动运行它,当某些东西看起来不正确:
```bash
cargo test --test live_archive -- --ignored --test-threads=1
```
## 鸣谢
由于 Reinhard Zierke 几十年来一直在编目英国民谣音乐,
这个存档才得以存在,而 [主要诺福克音乐](https://www.mainlynorfolk.info/folk/) 就是结果。
这是一个读者阅读这些作品的工具,仅此而已。
## 许可证
MIT