关于 AGHIST
AGHIST 是农业、食品与环境史搜索门户,其 MCP 服务面向研究者及其他探索农村历史档案馆和合作机构馆藏的人士。工具支持全文检索、馆藏层级浏览及多类档案材料的文档查询。
主要功能
- 01跨馆藏全文搜索
- 02按人物和机构搜索
- 03搜索照片与影片
- 04搜索指定数字版藏品
- 05获取文档元数据
- 06浏览馆藏层级
适用场景
- 01查找农村历史主题资料
- 02探索档案照片和影片
- 03搜索特定数字版藏品
- 04获取文档元数据与链接
MCP 相关
基于 Streamable HTTP 的 MCP 服务向客户端提供搜索、实体与视听资料查询、特定版本搜索、文档获取、层级浏览及服务信息工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
afa-mcp
面向伯尔尼(CH)农业史档案馆(AfA) AGHIST 搜索门户的 MCP 服务(Archives d'histoire rurale AHR / Archives of Rural History ARH)。
AGHIST 是农业、食品与环境史搜索门户,可访问由 AfA 及其国内外合作机构公开提供的在线资源(影片、照片、书面资料,以及编目数据、学术文本、视频随笔等)。
AGHIST MCP 服务通过 Model Context Protocol(Streamable HTTP)提供全文搜索和层级检索,因此 Claude、ChatGPT、Cursor 或 Perplexity 等支持 MCP 的客户端可以直接搜索 AfA 馆藏。
在线端点:https://mcp.histoirerurale.ch/mcp
工具
各馆藏的当前命中数由工具 list_hierarchy 提供;本说明有意不静态列出这些数据。
search — 通用全文搜索
搜索所有 AfA 馆藏(个人、机构、农场、照片/影片馆藏、档案、数字版、出版物、媒体报道)。可选按任意层级 ID 限定范围。
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
query | str | * | Lucene 查询字符串。短语使用 "...",支持 AND/OR/NOT、通配符 * 和 ?。默认运算符:AND。 |
language | de|fr|it|en | — | 标题/高亮内容的首选语言(不是筛选条件;无匹配时会回退)。 |
sort | relevance|date|id | relevance | 排序方式。 |
size | int (1–100) | 20 | 每页命中数。 |
search_after | list | — | 使用上一条响应中的 next_cursor 作为游标。 |
hierarchy | list[str] | — | 用于限定范围的层级 ID(以 OR 连接)。从 list_hierarchy 获取。 |
include_aggregations | bool | false | 返回层级聚合数据。 |
返回值(SearchResponse):
| 字段 | 类型 | 描述 |
|---|---|---|
total | int | 命中总数(可能超过 size)。 |
hits | list[SearchHit] | 命中列表(最多 size 条)。 |
next_cursor | list | null | 传给下一个请求的 search_after;null = 没有更多命中。 |
aggregations | dict | null | 层级分桶数据,仅当 include_aggregations=true 时返回。 |
SearchHit 字段: id、title、abstract、text(高亮片段)、meta、hierarchy(路径)、collection(标签)、date(ISO 格式,可选)、is_pdf、document_url(搜索门户深层链接)、original_url(来源 URL)、sort(内部游标)。
search_entities — 个人/机构/农场
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
query | str | * | Lucene 查询字符串。 |
entity_type | person|institution|farm|any | any | 类型筛选器。company 仍作为已弃用的 farm 别名保留。 |
language | de|fr|it|en | — | 首选语言。 |
sort | relevance|date|id | relevance | 排序方式。 |
size | int (1–100) | 20 | 每页命中数。 |
search_after | list | — | 分页游标。 |
返回值: SearchResponse(参见 search)— hits 仅包含个人/机构/农场。
search_audiovisual — 照片和影片馆藏
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
query | str | * | Lucene 查询字符串。 |
media_type | photos|films | — | photos = 仅照片,films = 仅影片,否则两者均包括。 |
language | de|fr|it|en | — | 首选语言。 |
sort | relevance|date|id | relevance | 排序方式。 |
size | int (1–100) | 20 | 每页命中数。 |
search_after | list | — | 分页游标。 |
返回值: SearchResponse(参见 search)— hits 仅包含照片/影片馆藏。
search_edition_hofstetter · search_edition_gillabert_randin · search_edition_bobbett
分别在三个数字版(Mina Hofstetter、Augusta Gillabert-Randin、Elizabeth Bobbett)之一中进行全文搜索。
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
query | str | * | Lucene 查询字符串。 |
language | de|fr|it|en | — | 首选语言。 |
sort | relevance|date|id | relevance | 排序方式。 |
size | int (1–100) | 20 | 每页结果数。 |
search_after | list | — | 分页游标。 |
返回值: SearchResponse(参见 search)——hits 限定为对应的数字版。
fetch_document — 获取单个文档(含全文)
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
id | str | 必填 | 文档 ID,例如 AfA_Personen_001_DB9920 或 AfA_Edition_003_BobbettE_1933_01。 |
language | de|fr|it|en | — | 首选语言。 |
返回值: 单个 SearchHit,包含文档元数据,不含全文。重要字段:
- 元数据:
id、title、abstract、meta、hierarchy(合集路径)、collection(标签)、date(ISO 格式,可选)、is_pdf。 document_url— 搜索门户(recherche2.histoirerurale.ch)中的 PDF 或 HTML 文件链接。original_url— 源门户的深层链接,即抓取工具获取文档的网站(例如histoirerurale.ch——可能因馆藏而异)。
如果找不到该 ID,则返回 null。
list_hierarchy — 列出含结果数量的层级分组
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
query | str | * | 可选的全文查询。 |
size | int (1–10000) | 200 | 层级条目的最大数量。 |
language | de|fr|it|en | — | 标签语言。 |
返回值(HierarchyResponse):
| 字段 | 类型 | 描述 |
|---|---|---|
entries | list[HierarchyEntry] | 层级条目。 |
HierarchyEntry 字段: id(层级 ID,可用于搜索工具的 hierarchy 参数)、count(结果数量)、label(请求语言中易于阅读的名称,如有)。
server_info — 版本和端点信息
无参数。
返回值(dict):
| 字段 | 类型 | 描述 |
|---|---|---|
name | str | 服务名称(afa-mcp)。 |
version | str | Semver。 |
elasticsearch_url | str | ES 后端的上游 URL。 |
languages | list[str] | de、fr、it、en。 |
sort_orders | list[str] | sort 可接受的值。 |
hierarchy_constants | dict | 易读的常量(例如 PERSONS、EDITION_BOBBETT)→ 层级 ID 字符串。 |
本地开发
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
# Streamable HTTP — Default auf 127.0.0.1:8766/mcp
python -m afa_mcp
# Stdio (für lokale CLI-Clients)
python -m afa_mcp --transport stdio
# Tests
pytest -q
# Live-Smoke-Test
python scripts/smoke_test.py
配置(环境变量)
参见 .env.example。主要变量:
| 变量 | 默认值 | 含义 |
|---|---|---|
AFA_ES_URL | https://agrargeschichte.pansoft.de:9210/*/_search | Elasticsearch 端点 |
PUBLIC_BASE_URL | https://mcp.histoirerurale.ch | Discovery 基础 URL |
MCP_STATELESS_HTTP | true | 无需服务器端会话 |
MCP_JSON_RESPONSE | true | 接受仅支持 application/json 的客户端 |
MCP_DNS_REBINDING_PROTECTION | true | Host/Origin 过滤器 |
CORS_ALLOW_ORIGINS | * | 浏览器 Origin 列表 |
AFA_ACCESS_LOG | true | 启用 JSON-RPC 访问日志(方法/工具统计) |
AFA_ACCESS_LOG_ARGS_MAX | 200 | 日志行中每个 args 表示的最大字符数 |
AFA_ACCESS_LOG_FILE | (stdout) | 专用日志文件的可选路径 |
访问日志格式
每个 MCP 方法都会在日志记录器 afa_mcp.access 中生成一行:
2026-06-10 14:30:01,234 INFO afa_mcp.access — method=tools/call tool=search id=42 status=200 size=8543 ms=145 client=160.79.106.37 args={"query":"Bäuerin Emmental","size":3}
通常通过 awk / grep 进行分析,例如:
# Top-10 Tools nach Häufigkeit
grep 'afa_mcp.access' ~/afa-mcp/server.log \
| grep -oE 'tool=[a-z_]+' | sort | uniq -c | sort -rn | head
# Latenz-Quantile pro Tool
grep 'method=tools/call' ~/afa-mcp/server.log \
| awk -F'tool=' '{print $2}' | awk '{print $1, $NF}' \
| sort | awk '{a[$1]++; s[$1]+=$2} END {for (t in a) printf "%-30s n=%4d avg=%dms\n", t, a[t], s[t]/a[t]}'
生产环境(Debian)
sudo bash deploy/install.sh
sudo certbot --nginx -d mcp.histoirerurale.ch
sudo install -m 644 /opt/afa-mcp/deploy/nginx.conf \
/etc/nginx/sites-available/mcp.histoirerurale.ch
sudo nginx -t && sudo systemctl reload nginx
该脚本会安装:
- 系统用户
afa和/opt/afa-mcp目录 - 含依赖项的 Python 虚拟环境
- systemd 单元
afa-mcp.service(经过强化,无状态 HTTP) - 带有 OAuth/MCP/Agent 发现、路径重定向和 llms.txt 的 nginx vHost
更新部署脚本
sudo tee /usr/local/sbin/deploy-afa-mcp > /dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
sudo -u afa git -C /opt/afa-mcp pull --ff-only
install -m 644 /opt/afa-mcp/deploy/nginx.conf \
/etc/nginx/sites-available/mcp.histoirerurale.ch
nginx -t && systemctl reload nginx
systemctl restart afa-mcp
systemctl status --no-pager afa-mcp | head -5
EOF
sudo chmod +x /usr/local/sbin/deploy-afa-mcp
调用方式:sudo deploy-afa-mcp。
生产环境(Plesk,无 root 权限)
如果——如当前在 mcp.histoirerurale.ch 上的安装一样——
没有 root 权限,也无法使用 systemd,服务器将在用户空间中运行,
由 Plesk 定时任务(Cron,每分钟运行一次)启动:
# einmalig:
mkdir -p ~/afa-mcp && cd ~/afa-mcp
git clone https://github.com/Archiv-fur-Agrargeschichte/AfA-MCP-Server.git .
virtualenv .venv
.venv/bin/pip install -e .
install -m 755 deploy/plesk/start.sh ~/afa-mcp/start.sh
Plesk → 域名 → 定时任务 → 新建任务 ~/afa-mcp/start.sh,
每分钟运行一次。脚本行为:
- 如果存在正在运行的 PID → 退出码为 0(不执行任何操作)。
- 否则:设置环境变量,通过
nohup在虚拟环境中启动python -m afa_mcp, 并将 PID 写入~/afa-mcp/afa-mcp.pid。
通过 mcp.histoirerurale.ch/httpdocs/.htaccess 在前面添加 Apache mod_proxy
(参见仓库中的 Apache 文档),Plesk 负责提供 TLS 和 vHost 路由。
更新:运行 git -C ~/afa-mcp pull --ff-only,然后手动结束一次旧实例——
Cron 会在下一次运行时启动新实例。
统计页面(/statistik,实时生成)
MCP 服务器会在 /statistik 下提供使用统计信息——
每次访问时实时生成。过去日期的数据会固定保存在 JSON 缓存
(~/afa-mcp/stats-cache.json)中,因此只需从日志重新汇总当天的数据。
无需 Cron 任务。
通过环境变量进行 Basic Auth(在 start.sh 中):
export AFA_STATS_USER=admin
export AFA_STATS_PASS=DEIN_PASSWORT
如果两项都为空,则可不受保护地访问 /statistik(开发模式)。
Apache 设置:mcp.histoirerurale.ch/httpdocs/.htaccess 需要包含
/statistik 的 mod_proxy 规则(模板位于
deploy/plesk/mcp-htaccess.example):
RewriteRule ^statistik$ http://127.0.0.1:8766/statistik [P,L]
RewriteRule ^statistik/(.*)$ http://127.0.0.1:8766/statistik/$1 [P,L]
Authorization 标头会通过 mod_proxy 原样转发;身份验证由 Python 服务器执行
(使用 hmac.compare_digest 与环境变量进行比对)。页面显示:
- 今天 · 工具调用次数 / 会话数(从日志实时读取)
- 最近 7 天和总计(过去日期的数据来自缓存)
- 每日概览,按天显示小时级迷你趋势图
- 热门工具、AI 客户端(来自
clientInfo.name) - 24 小时活动图
- 方法分布(技术性开销)
内容仅包含汇总数据——只要设置 AFA_ACCESS_LOG_ARGS_MAX=0,
用户的搜索查询就不会进入日志或统计信息。
备用方案 / 离线渲染:deploy/plesk/statistik/generate_stats.py
会将相同页面一次性写入静态文件——适用于初始化旧缓存,或在服务器未运行时进行测试。
发现端点(供 MCP 目录使用)
| 路径 | 内容 |
|---|---|
/.well-known/mcp.json | MCP 服务清单 |
/.well-known/agent-card.json | A2A Agent Card |
/.well-known/oauth-protected-resource | RFC 9728(表明:无需身份验证) |
/llms.txt | 面向大模型 / 爬虫的站点说明 |
架构
src/afa_mcp/search.py 包含 Elasticsearch 客户端和基于 Pydantic 的响应解析。
src/afa_mcp/server.py 定义 FastMCP 工具、专用搜索包装器(版本、实体、音频-视觉)以及带有 OAuth/发现路由的 ASGI 应用。src/afa_mcp/hierarchy.py 集中管理层级 ID,以便工具代码和测试无需使用魔法字符串。
着陆页(deploy/)
位于 https://mcp.histoirerurale.ch 的静态页面,无需构建步骤:
deploy/index.html nur Markup
deploy/assets/css/style.css Design-System der Hauptseite histoirerurale.ch/afa
deploy/assets/js/i18n.js Übersetzungen (de, fr, it, en)
deploy/assets/js/app.js Sprachwahl und Textersetzung
deploy/assets/img/logo-afa.png Logo der Hauptseite
deploy/assets/fonts/ Merriweather (Überschriften)
颜色、字体和组件沿用主站的 Joomla 模板(Cassiopeia 加上 user.css):红色 #a00000,悬停色 #870000,正文为 15px Helvetica Neue,标题为红色 Merriweather,容器宽度 1170px。
nginx 会直接提供 /assets/(规则位于 deploy/nginx.conf 和
deploy/nginx-http.conf);在 Plesk 上,文件位于 httpdocs 中,无需额外规则即可提供。
Quellen
- Website: https://histoirerurale.ch
- Recherche-Frontend: https://www.recherche2.histoirerurale.ch
- Schwesterprojekt: https://github.com/entscheidsuche/entscheidsuche-mcp
Lizenz
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。