古典音乐活动日程服务

Leporello是一个歌剧和古典音乐活动日程远程MCP服务,提供全球多个音乐厅的活动信息,支持通过MCP协议查询。

  • by philphilphil
  • HTML
  • 本地部署
  • 更新于
在 GitHub 查看 philphilphil/leporello-mcp

使用说明

Leporello

Opera & classical music event schedule remote MCP.
Also available as a web app at leporello.app.

支持的场地

错过你最喜欢的场地?PR欢迎!阅读 贡献.md 有关添加新场地刮板的分步说明。

地点 城市
斯图加特国家歌剧院 Stuttgart
斯图加特爱乐乐团 Stuttgart Philharmonic
维也纳国家歌剧院 维也纳
大都会歌剧院 纽约
法兰克福歌剧院法兰克福
旧金山歌剧院 旧金山
Gran Teatre del Liceu 巴塞罗那
森佩罗珀 德累斯顿
巴黎国家歌剧院 巴黎
卡内基音乐厅 纽约
皇家剧院 马德里
柏林国家歌剧院 Unter den Linden
悉尼歌剧院 悉尼
巴黎爱乐乐团 Paris Philharmonie
巴伐利亚国家歌剧院 慕尼黑
柏林爱乐乐团 Berlin Philharmonie
莱比锡 Leipzig
苏黎世音乐厅 苏黎世
芝加哥抒情歌剧院 芝加哥
巴塞罗那加泰罗尼亚音乐宫
皇家歌剧院 伦敦
斯卡拉剧院 米兰
国家音乐厅 马德里
萨尔茨堡音乐节 Salzburg Festival
Elbphilharmonie 汉堡
苏黎世歌剧院 苏黎世
阿姆斯特丹音乐厅
科隆爱乐乐团 Cologne Philharmonie
音乐俱乐部 维也纳
维也纳音乐厅 维也纳
巴比肯大厅 伦敦
汉堡国家歌剧院 汉堡

运作原理

特定场地的抓取器从歌剧院和音乐厅获取日程页面(HTML或JSON),用Cheerio解析它们,并将事件存储在本地SQLite数据库中。节点cron调度器每天03:00 UTC重新抓取所有场馆,用最新数据替换每个场馆的事件。服务器通过 模型上下文协议 (MCP)端点,因此任何兼容MCP的AI助手都可以查询即将到来的性能。静态Astro前端在构建时读取相同的数据库,并在以下位置提供可过滤的事件列表 Leporello.app.

MCP工具

工具 说明
list_countries 所有有城市/场馆数量的国家
list_cities 所有有场馆的城市,可选择按国家过滤
list_venues 所有场馆,可选择按国家或城市过滤
list_events 按国家、城市或地点筛选的即将举行的活动

隐私

托管实例位于 Leporello.app 日志聚合了MCP的使用情况(工具名称、参数、响应时间、用户代理和客户端IP的每日轮换盐哈希),这样我就可以看到哪些有效,哪些无效。没有原始IP,没有个人数据,没有身份验证令牌。

在本地运行

npm install
npm test          # run scraper tests

npm run scrape                       # one-off scrape all venues
#or
npm run scrape -- wiener-staatsoper  # scrape a single venue

npm run dev       # start server on http://localhost:3000
# or
npm run dev:fresh # scrape, then serve

每天03:00 UTC报废。跑 npm run scrape 首次使用时填充数据库。

码头工人

两个容器: 网络 (HTTP服务器+MCP+静态前端)和 爬虫 (将场地数据提取到SQLite中)。它们共享一个数据量。web堆栈是 docker-compose.yml;刮刀是一次性作业 docker-compose.scrape.yml 在自己的作曲项目下(leporello-scrape)因此,其退出的容器永远不会计入web堆栈的健康状况。用主机cron作业安排它。

# Start the web server
docker compose up -d

# Run all scrapers (one-off, container stops when done)
docker compose -f docker-compose.scrape.yml run --rm scraper

# Scrape a single venue
docker compose -f docker-compose.scrape.yml run --rm scraper node dist/scrape.js wiener-staatsoper

# Rebuild the Astro frontend (e.g. after a manual scrape)
docker compose exec web node -e "
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
await promisify(execFile)('npm', ['run', 'build', '--prefix', 'web'], { cwd: '/app', timeout: 60000 });
console.log('done');
"

# Tail logs
docker compose logs -f web

web容器在每次启动时都会重建Astro前端。要按计划运行抓取器,请添加一个抓取然后重新启动web的主机cron作业:

0 3 * * * cd /home/phil/docker/lep && docker compose -f docker-compose.scrape.yml build && docker compose -f docker-compose.scrape.yml run --rm scraper && docker compose restart web