使用说明
Bunpro MCP
概述
此FastAPI/uvicorn服务器通过HTTP流将Bunpro MCP包暴露给其他代理 /mcp.它注册代理Bunpro API端点的语法、词汇、阅读、用户统计和评论工具。
这是一个个人学习项目,旨在:
- 探索MCP(模型上下文协议)服务器的工作原理
- 通过Bunpro集成协助日语学习
与Bunpro无关。为教育目的而建。
需求
- Python 3.14或更高版本(匹配Bunpro MCP依赖项)
- 阿斯特拉
uvCLI。通过安装pip install uv或跟随https://github.com/astral-sh/uv,然后运行uv sync在启动服务器之前,从repo根目录开始。
设置
- 复制
.env.example到.env并提供您的Bunpro前端API代币(BUNPRO_FRONTEND_API_TOKEN=线)。像对待其他秘密一样对待令牌;不要承诺。 - 如果请求通过HTTP到达,服务器首先读取Bunpro的
frontend_api_tokencookie,并将该令牌用于出站Bunpro API调用。 - 对于没有该cookie的本地运行,服务器将回退到
BUNPRO_FRONTEND_API_TOKEN,然后是遗产BUNPRO_JWT.
环境变量
BUNPRO_FRONTEND_API_TOKEN(首选):当不存在请求cookie时,每个工具使用Bunpro前端API令牌。BUNPRO_JWT(旧别名):向后兼容的回退BUNPRO_FRONTEND_API_TOKEN.BUNPRO_API_BASE_URL(可选):覆盖Bunpro API根(默认为内置客户端值)。BUNPRO_HOST(可选):服务器监听的主机(默认为127.0.0.1).BUNPRO_PORT(可选):服务器监听的端口(默认为8000).BUNPRO_STREAM_PATH(可选):MCP流路径(默认为/mcp).
运行服务器
在回购根目录中,在同一行运行带有前端API令牌的FastAPI应用程序,以便服务器立即获取该令牌。 uv run 重复利用环境 uv sync 为这次回购做准备。
BUNPRO_FRONTEND_API_TOKEN=your_frontend_api_token_here uv run server.py
使用OpenCode(MCP客户端)
开源代码 可以作为MCP客户端连接到此服务器。服务器运行在 http://127.0.0.1:8000/mcp 默认情况下。
设置
- 安装OpenCode(请参阅 OpenCode文档)
- 使用
.env.example创建a.env使用Bunpro API令牌文件 - 启动MCP服务器:
uv --env-file .env run server.py - 配置OpenCode以连接到服务器。添加到您的
opencode.jsonc:{ "mcpServers": { "bunpro": { "url": "http://127.0.0.1:8000/mcp" } } } - 跑
opencode使用Bunpro工具开始聊天
可选:Bunpro导师代理
此仓库包括一个预配置的代理,位于 .opencode/agent/bunpro-tutor.md 提供日语辅导服务。要使用它:
- 确保
.opencode/目录在您的项目中 - 在OpenCode中,切换到 bunpro导师 代理
- 询问有关日语学习进展的问题
示例提示:
I'm currently reviewing. Why is 行きませんか used instead of 行きましょうか here?
使用MCP检查员检查工具
在服务器运行时,使用捆绑的MCP检查器列出和调用工具:
BUNPRO_FRONTEND_API_TOKEN=your_frontend_api_token_here uv run mcp dev server.py
运行检查器后,您可以浏览已注册的工具,查看它们的签名,并从UI以交互方式传递参数。
工具参考+示例
在MCP检查器和Python脚本之间进行选择以调用工具。每次运行时,MCP检查器都会显示已注册的工具列表 uv run mcp dev server.py;您选择一个工具名称,填写其参数,并以交互方式发送请求。自动化或调试可以直接调用异步工具函数 uv run python.
Python代码片段
替换 your_frontend_api_token_here 使用您导出的值(并将其置于版本控制之外):
search_grammar(query)uv run python - <<'PY' import asyncio from src.tools.grammar import search_grammar async def main(): print(await search_grammar("particles")) asyncio.run(main()) PYget_grammar_point(slug)uv run python - <<'PY' import asyncio from src.tools.grammar import get_grammar_point async def main(): print(await get_grammar_point("particles-1")) asyncio.run(main()) PYget_vocab_level()uv run python - <<'PY' import asyncio from src.tools.vocabulary import get_vocab_level async def main(): print(await get_vocab_level()) asyncio.run(main()) PYget_vocab_items(vocab_slug_or_id)uv run python - <<'PY' import asyncio from src.tools.vocabulary import get_vocab_items async def main(): print(await get_vocab_items("genki-lesson-1")) asyncio.run(main()) PYsearch_vocab(query, result_limit=None)uv run python - <<'PY' import asyncio from src.tools.vocabulary import search_vocab async def main(): print(await search_vocab("greetings", result_limit=10)) asyncio.run(main()) PYget_reading_passages()uv run python - <<'PY' import asyncio from src.tools.reading import get_reading_passages async def main(): print(await get_reading_passages()) asyncio.run(main()) PYsearch_reading_passages(query)uv run python - <<'PY' import asyncio from src.tools.reading import search_reading_passages async def main(): print(await search_reading_passages("vacation")) asyncio.run(main()) PYget_user_stats()uv run python - <<'PY' import asyncio from src.tools.user_stats import get_user_stats async def main(): print(await get_user_stats()) asyncio.run(main()) PYget_jlpt_progress()uv run python - <<'PY' import asyncio from src.tools.user_stats import get_jlpt_progress async def main(): print(await get_jlpt_progress()) asyncio.run(main()) PYget_srs_forecast(granularity="daily")uv run python - <<'PY' import asyncio from src.tools.user_stats import get_srs_forecast async def main(): print(await get_srs_forecast(granularity="daily")) asyncio.run(main()) PYget_study_configuration()uv run python - <<'PY' import asyncio from src.tools.review import get_study_configuration async def main(): print(await get_study_configuration()) asyncio.run(main()) PYget_due_count()uv run python - <<'PY' import asyncio from src.tools.review import get_due_count async def main(): print(await get_due_count()) asyncio.run(main()) PYget_pending_reviews()uv run python - <<'PY' import asyncio from src.tools.review import get_pending_reviews async def main(): print(await get_pending_reviews()) asyncio.run(main()) PY