关于 IYT Test
IYT Test 通过 Telegram 迷你应用、网站内容和公开只读 MCP 服务提供帆船认证与竞赛规则练习,面向帆船学员及 AI 助手,提供题库、理论文章、模拟考试、答案检查和帆船示意图,内容支持英语和俄语。
主要功能
- 01涵盖多个帆船级别的题库
- 02模拟考试和答案检查
- 03理论文章及章节搜索
- 04SVG 帆船示意图
- 05英语和俄语内容
适用场景
- 01练习帆船级别题目
- 02进行认证模拟考试
- 03复习答案关联的理论内容
- 04获取学习用帆船示意图
MCP 相关
公开的远程 MCP 服务通过只读工具提供题库、理论文章、答案、考试和示意图。无需登录,不保存用户状态,并支持 `en` 和 `ru` 语言参数。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://iyt.rycrentals.com/api/mcpclaude mcp add --transport http nikolai-shilin-iyt-test https://iyt.rycrentals.com/api/mcp{"mcpServers":{"nikolai-shilin-iyt-test":{"type":"http","url":"https://iyt.rycrentals.com/api/mcp"}}}在 Cursor 中打开{"servers":{"nikolai-shilin-iyt-test":{"type":"http","url":"https://iyt.rycrentals.com/api/mcp"}}}在 VS Code 中打开{"mcpServers":{"nikolai-shilin-iyt-test":{"type":"http","url":"https://iyt.rycrentals.com/api/mcp"}}}{"mcpServers":{"nikolai-shilin-iyt-test":{"serverUrl":"https://iyt.rycrentals.com/api/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
IYT 测试
用于练习 IYT 认证级别的题目——Telegram 迷你应用和网站。每道题都是一个情境(“前方看到这个标志——哪里是安全水域?”);适合用图示呈现时,会配上图示,并提供四个选项和一句说明,指出所依据的规则。第一级:Bareboat Skipper(100 道题,10 个主题)。
状态(2026-11-02):设计和题库已完成;Telegram 迷你应用(练习、模拟考试、进度、个人资料)和小型机器人已构建并部署(Vercel)。网站尚未开始。
仓库内容
README.md this file
docs/
PLAN.md goal, decisions, next steps
question-bank.md JSON format of a bank, authoring rules, how to build it
figures.md the figure spec: every type, its fields, an example
figure-style.md the agreed look of the rendered figures (cameras, looks, own boat, lights, annotations)
design.md look & feel, components, the 21 screens, how to use the viewer
data-model.md proposed database (Supabase) and how progress is computed
theory.md the theory articles: format of an article, authoring rules, check and build
superpowers/plans/ implementation plans (theory articles: 2026-11-05-theory-articles.md)
design/
flows.html hi-fi user flows (viewer: pages / overview, day / night)
questions.html the whole bank as the student sees it, filter by topic
flows.css flows.js viewer + test UI pieces
app.css app tokens and base components (day and night)
test-icons.js the app's icon set (24 grid, 2 px line) + svg()/paintIcons(), shared by the viewer and the app
icons.html the icon sheet: every glyph at 24 px and in the topic circle, day / night
icons.js older base set (Telegram chrome in the mockups; a few basics follow Lucide)
figures.js figure generator (JSON spec → SVG)
figure-style-spike.html reference renderer for figure-style.md (three.js from a CDN; open over HTTP)
figure-schematic.js plan-view schematic renderer (the companion diagram to every realistic figure)
figure-style/ sample renders of the ten example questions; hires/ at 2560 × 1600, schematic/ their plan views
logo-black.svg RYC logo
data/
build_bank.py source of the Bareboat Skipper bank — edit here, then run
build_level.py builds the other levels from bank/<level>/<topic>.json (+ .ru.json)
bank/<level>/<topic>.json VHF Radio Operator, International Crew, Flotilla Skipper: 20 questions per topic; Charter Check-in: 50; Yachtmaster Coastal, Offshore and Ocean, Racing Rules of Sailing: 100
questions/<level>.json the built banks the apps read
questions/<level>.ru.json Russian translation of each bank (overlay)
i18n.py extract strings to translate / check an overlay
theory/<level>/<topic>.json theory articles, one per topic of every level (+ .ru.json): 90 in all, each with figures
check_theory.mjs checks the articles against docs/theory.md and the banks (npm run check:theory)
miniapp/
index.html app.js app.css the Telegram mini app (static, no framework, no backend)
build.mjs builds miniapp/dist (the folder to host): the app, design files, fonts and minified banks,
each linked file renamed after its content (h/…) so phones cache it for good, and the
list of banks written into index.html so only the current level's bank loads at start
fonts/ Merriweather and Carlito (woff2, Latin + Cyrillic, OFL), served with the app
pages.mjs site.css the site around the app: a page per level and per theory article (EN + RU), sitemap, llms.txt
site.mjs the public address, the bot and the IndexNow key
indexnow.mjs npm run seo:ping: tells Bing and Yandex which pages changed
bot/
core.mjs the bot's replies: /start /exam /progress /settings open the app, /daily asks a question
daily.mjs the daily question of the day to everyone who has it on
bot.mjs runs core.mjs by long polling (local testing)
scripts/setup.mjs sets the bot's name, descriptions, commands and menu button
scripts/webhook.mjs points Telegram at the Vercel webhook, or removes it
api/
telegram.mjs Vercel function: Telegram's webhook, runs core.mjs
daily.mjs Vercel cron (09:00 UTC daily): runs bot/daily.mjs
settings.mjs the app's question-of-the-day switch (users.daily_question), checked with Telegram initData
admin.mjs every student's results, flagged and reported questions (admins can take a flag off), joins/answers/wrong answers per hour and day for the admins (ADMINS in settings.mjs — @fullcrimp; ADMIN_USERNAMES adds more)
mcp.mjs the MCP server: the banks and the theory articles as tools for AI assistants (public, read-only)
迷你应用
npm run dev # http://localhost:5173 — works in a normal browser too
界面遵循 docs/design/flows.html:A1–A9 练习(设置面板、“检查” → 原因 →“下一题”、结果、错题),
B1–B5 模拟考试(40 道题,涵盖所有主题;应用关闭时会暂停计时器;标记 + 题目网格;通过/未通过),C1 进度,C2 个人资料(主题、随机排序、重置)。掌握 = 连续答对两次。进度按用户保存在 Telegram CloudStorage 中(在浏览器中使用 localStorage),因此目前还没有服务器或数据库。在 Telegram 内,应用使用原生的“返回”“主菜单”和“次要”按钮以及触觉反馈;在 Telegram 外则自行绘制相同的按钮栏。
深层链接:?screen=exam|progress|profile|practice|level,或使用相同值的 startapp=。
语言:英语和俄语界面(默认跟随 Telegram 语言,直到在个人资料中切换;选择会像主题一样保存)。全部 1000 道题的翻译位于 data/questions/bareboat-skipper.ru.json(术语表:docs/glossary-ru.md);另请参阅
docs/question-bank.md。
应用已上线,地址为 https://iyt.rycrentals.com,并已连接到 @iyt_test_bot:机器人的
菜单按钮会打开应用,机器人本身则作为 webhook 运行在同一个 Vercel 项目中(api/telegram.mjs)。
如需从头重新设置:
- 将
TELEGRAM_BOT_TOKEN、WEBAPP_URL和TELEGRAM_WEBHOOK_SECRET(openssl rand -hex 32)填入.env.local, 并将相同的三个变量填入 Vercel 项目的 Production 环境变量。 - 执行
npx vercel deploy --prod— 构建miniapp/dist,并在其旁边部署 webhook 函数。 - 执行
npm run bot:setup— 设置名称、描述、命令和菜单按钮 → 应用。 然后在 @BotFather 中将其设为机器人的 Main Mini App(Bot Settings → Configure Mini App → Enable Mini App, 发送WEBAPP_URL):机器人的个人资料中会出现“打开”按钮,而t.me/iyt_test_bot?startapp=<screen>链接 会直接打开应用。Telegram 没有用于此操作的 API;npm run bot:setup -- --check会显示该功能是否已启用。 - 执行
npm run bot:webhook— 告知 Telegram 将更新发送到WEBAPP_URL/api/telegram(-- --check会显示当前状态)。
若要在本地测试机器人更改:执行 npm run bot:webhook -- --delete,然后执行 npm run bot(长轮询);完成后再次执行
npm run bot:webhook — Telegram 会将更新发送到 webhook 或轮询,不会同时发送到两者。
每日问题
每天(Vercel cron,0 9 * * * UTC——迪拜时间 13:00,莫斯科时间 12:00),机器人会向开启此功能的每位用户发送一道带有 A–D 按钮的文字问题;答案和说明会在同一条消息中返回。当日所有人收到的问题都相同。机器人会在 Supabase 的 users 表中保存每位给它发过消息的用户(daily_question 默认开启)。
- 单个用户:每日问题下方以及
/settings中都有一个切换按钮(“每日问题:开/关”)。 - 整个机器人:在 Vercel 环境变量中设置
DAILY_QUESTION=off,即可停止向所有人发送(用户自己的开关状态不变)。 - 拉黑机器人的用户会被标记(
blocked_at),在他们再次发消息前会跳过。
Vercel 上需要设置:SUPABASE_URL、SUPABASE_SECRET_KEY、CRON_SECRET(openssl rand -hex 32),并应用迁移文件
supabase/migrations/20261102150000_daily_question.sql。试用:npm run bot:daily -- --to <your chat id>(添加
--ru 可发送俄语版),会向一个聊天发送今天的问题;npm run bot:daily -- --dry 会统计符合发送条件的用户数量。
此版本暂不支持(需要在 docs/data-model.md 中实现 Supabase 后端):德语/西班牙语、连续答题提醒、与网站跨设备同步、理论说明、分享图片。
搜索引擎和 AI 助手
搜索引擎和大多数 AI 爬虫不会运行 JavaScript 来读取页面,因此除了应用本身,构建过程还会将网站写成纯页面(miniapp/pages.mjs,使用应用自己的 CSS,并由 miniapp/site.css 设置样式),网址为
https://iyt.rycrentals.com(`miniapp/site.mjs` 中的 SITE):
| 地址 | 页面 |
|---|---|
/ | 应用;其中 <noscript> 版本的 Home 页面链接到所有级别 |
/<level> | 级别页面:问题、主题、模拟考试,以及每个主题的文章 |
/<level>/<topic> | 主题理论文章及其插图,之后是示例问题(每个章节一道;如果有插图题则选用插图题),包含答案、说明,以及指向解释该问题的章节的链接 |
/about | IYT Test 是什么、不是什麼,作者,以及 MCP 服务 |
/ru、/ru/<level>、/ru/<level>/<topic>、/ru/about | 俄语版对应页面;/ru 列出所有级别 |
每个页面都有自己的标题和描述、规范链接、指向另一种语言版本的 hreflang 链接、链接预览标签和结构化数据(面包屑;主题页面包含 Article 和 Quiz)。除 pages.mjs 中的字符串外,所有内容都由构建过程自动生成:新增文章或级别后,下次构建就会生成对应页面。章节开头的说明(docs/theory.md 中的 qa:学生可能提出的问题,以及一两句话的回答)会放在章节标题下方,并写入页面的 FAQPage 数据中;搜索引擎和 AI 助手会引用这段内容。构建过程还会生成
robots.txt(列出 AI 爬虫并允许其访问;搜索和训练均可,因为内容免费开放,而且 MCP 服务也会提供这些内容)、sitemap.xml(包含每个页面及其另一种语言版本)、llms.txt(供 AI 助手使用的网站地图)、
404.html、IndexNow 密钥文件和 pages.json(每个地址及其页面哈希值)。npm run dev 会像 Vercel 一样(cleanUrls)通过简洁地址提供页面。
生产环境部署后:
npm run seo:ping会告知 Bing 和 Yandex(IndexNow)自上次通知以来哪些页面新增、变更或删除(对比线上pages.json和miniapp/.indexnow-sent.json;后者不纳入 git);-- --dry会列出这些页面,-- --all会发送所有页面,-- --check只检查密钥文件是否可访问。- 手动操作一次(每项操作都需要你的账号):在 Google Search Console 中添加
iyt.rycrentals.com, 使用 Google 提供的 DNS TXT 记录验证(添加到rycrentals.com区域),然后提交sitemap.xml;接着前往 Bing Webmaster Tools → 从 Google Search Console 导入;然后前往 Yandex Webmaster → 添加网站、完成验证(DNS 或 meta 标签),再添加站点地图。
MCP 服务
api/mcp.mjs 会向 AI 助手(Claude、ChatGPT 以及其他支持模型上下文协议的工具)提供题库和理论文章:学生将 https://iyt.rycrentals.com/api/mcp 添加为远程 MCP 服务(自定义连接器),就可以在自己的助手中练习。它是公开的,只读:无需登录,不会保存任何内容,返回的内容仅限应用已有的数据。连接方法见 https://iyt.rycrentals.com/mcp(`miniapp/pages.mjs` 中的 mcpBody,以及工具列表:新增工具时在此添加一行);应用主页会在反馈卡片上方的卡片中链接到该页面。网站、应用、机器人和服务会保存哪些用户信息,见 https://iyt.rycrentals.com/privacy(`miniapp/pages.mjs` 中的字符串、privBody):其中任何一方开始保存新的信息时,都要在此更新。
| 工具 | 提供内容 |
|---|---|
list_levels | 各级别、对应主题、考试设置,以及哪些主题有文章 |
get_questions | 按级别、主题或难度随机抽取题目,不含答案 |
check_answer | 答对或答错、正确选项、说明,以及讲解该题的理论章节 |
search_questions | 按词语搜索题目 |
start_mock_exam, grade_exam | 一套覆盖各主题、题量与考试相当的试题;然后提供分数、通过或未通过、错题以及推荐阅读内容 |
question_of_the_day | 机器人当天发送的题目 |
list_theory, get_theory, search_theory | 文章及其章节,以文本形式呈现,并附上插图链接 |
explain_question | 一道题及其答案和相关章节 |
practice_section | 理论章节涵盖的题目 |
get_figure | 以 SVG 标记呈现的插图 |
每个工具都接受 lang(en 或 ru);尚未翻译的内容会以英文提供。每幅插图都有自己的地址:题目插图使用 /api/mcp?figure=bs-001,理论章节中的第 n 幅插图使用 /api/mcp?figure=<level>/<topic>/<section>/<n>:这是由 docs/design/figures.js 绘制的 SVG 图片,其中写入了日间配色。卡片类插图(如脚本、清单)会以文本形式提供。
没有依赖,也不保存状态:该函数通过 HTTP 处理 JSON-RPC(initialize、tools/list、tools/call),并读取随其打包的题库、文章和 figures.js(vercel.json → includeFiles),因此部署后,助手就能获取新文章。可以通过部署进行测试:
curl -s https://iyt.rycrentals.com/api/mcp -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_questions","arguments":{"level":"bareboat-skipper","count":1}}}'
它已在官方 MCP Registry中列出,名称为 io.github.nikolai-shilin/iyt-test,信息来自 server.json(Glama 和 PulseMCP 会复制 Registry 中的信息)。新增工具或更改描述时,需要发布新的 version(api/mcp.mjs 中的 serverInfo.version 也要更新):已发布的版本不能更改。
brew install mcp-publisher
mcp-publisher validate
mcp-publisher login github # as nikolai-shilin: the name must start with io.github.<your GitHub login>/
mcp-publisher publish
查看页面
在浏览器中直接打开 docs/design/flows.html 查看各个界面。questions.html 会加载题库 JSON,因此需要本地服务:
npx serve docs/design # then http://localhost:3000/questions.html
在流程图中使用方向键翻页;#A4、#D1 可跳转到相应界面;“Overview”会同时显示所有泳道。
编辑题目
题目以 Python 调用的形式存储在 data/build_bank.py 中(题目、正确答案、三个错误答案、说明、参考资料、插图规格)。运行它即可重新生成 JSON,并使答案均匀分布在 A–D 之间:
python3 data/build_bank.py
然后重新加载 questions.html 查看题目。格式和规则见:docs/question-bank.md。
插图类型见:docs/figures.md。
等级
| 等级 | 题目数 | 状态 |
|---|---|---|
| VHF 无线电操作员 | 200(10 个主题 × 20) | 已完成 — data/questions/vhf-radio-operator.json |
| 国际船员 | 200(10 个主题 × 20) | 已完成 — data/questions/international-crew.json |
| 船队船长 | 200(10 个主题 × 20) | 已完成 — data/questions/flotilla-skipper.json |
| 光船船长 | 1000(10 个主题 × 100) | 已完成 — data/questions/bareboat-skipper.json |
| 帆船竞赛规则(非 IYT 课程) | 1000(10 个主题 × 100) | 已完成 — data/questions/racing-rules.json |
| 包船报到(非 IYT 课程) | 500(10 个主题 × 50) | 已完成 — data/questions/charter-checkin.json |
| ICC(国际适任证书) | — | 计划中 |
| 沿岸游艇船长 | 1000(10 个主题 × 100) | 已完成 — data/questions/yachtmaster-coastal.json |
| 近海游艇船长 | 1000(10 个主题 × 100) | 已完成 — data/questions/yachtmaster-offshore.json |
| 远洋游艇船长 | 1000(10 个主题 × 100) | 已完成 — data/questions/yachtmaster-ocean.json |
顺序遵循 IYT 课程进阶路径; 帆船竞赛规则(World Sailing,2025–2028;俄罗斯帆船联合会的俄文版 ППГ-25)排在 IYT 等级之后,涵盖比赛航程中的情境——优先权、标志物空间、起航、处罚、抗议。包船报到涵盖周六在基地办理的事项:文件和合同、环船检查、帆、发动机、电气系统、水和 燃气、仪器、安全装备、锚泊设备和小艇、物品清单、押金以及周五的退船检查。
题目供学习使用,并非 IYT 官方考试内容。模拟考试的默认设置(光船船长和船队船长:60 分钟内答 40 题;沿岸和近海游艇船长:90 分钟内答 50 题;远洋游艇船长:120 分钟内答 50 题;VHF 和国际船员:45 分钟内答 30 题;70 % 为及格线)必须在发布前根据 IYT 当前考试要求进行核实。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。