bunpro-mcp
The bunpro-mcp server manages a Japanese-learning spaced-repetition review queue backed by Markdown notes, accessible via a conversational AI interface.
Get your review queue: Retrieve grammar points and vocabulary most in need of review, ordered by priority, with retrievability scores, days since review, lapse counts, and past mistake notes.
Get a practice pool: Fetch already-mastered items for active-use practice (e.g., conversation scenarios) — the opposite of the review queue, returning your strongest-known items.
Look up a specific item: Retrieve full details about any grammar point or vocabulary word, including personal vault notes, memory state, reading, meaning, and JLPT level.
Submit grades after a session: Record performance (grades 1–4) with optional error notes so the spaced-repetition schedule updates accordingly.
Add a new item: File a newly encountered grammar point or vocabulary word with reading, meaning, JLPT level, tags, and an optional starting progress level (e.g., Beginner through Master).
Import a Bunpro CSV export: Bulk-load items from a Bunpro CSV export into the vault, with a dry-run mode to preview changes before committing.
Manages a Japanese-learning review queue using an Obsidian vault as the backing store, allowing notes for grammar and vocabulary to be stored and reviewed in Obsidian.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@bunpro-mcpquiz me on what's due"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
bunpro-mcp
An MCP server that manages a Japanese-learning review queue backed by a folder of Markdown notes. It runs on Cloud Run and connects to Claude on web, mobile, and desktop — so reviews work from a phone — while the notes stay plain .md files you can read in Obsidian.
For contributors: see .agent/ARCHITECTURE.md for the build rationale and .agent/CONTRACT.md for the data shapes and tool behaviour.
What you can do with it
Ask Claude in plain language — it picks the right tool:
Review what you're forgetting — "quiz me on what's due" pulls the items most in need of review and updates your schedule based on how you do.
Practice words you've already mastered — "test me on food words I already know" gathers solid items around a theme, proposes a short practice conversation, runs it, then records how it went.
Add something new — "I just learned 〜てしまう" files it, filling in the reading, meaning, and JLPT level for you.
Import your Bunpro export — paste in a CSV export and it bulk-loads it into the vault.
The six tools are get_review_queue, get_practice_pool, get_item, submit_grades, add_item, and import_export.
Related MCP server: FlashCardMCP
Configuration
Four environment variables. Copy .env.example to .env for local runs.
Variable | Required | What it does |
| one of these two | GCS bucket holding the notes. Wins if both are set. |
| one of these two | Local folder of notes. The local-development option. |
| yes | The one secret. See below. |
| in production | The externally reachable base URL. Defaults to |
| no | Injected by Cloud Run. Defaults to |
| no | Defaults to |
MCP_AUTH_TOKEN does three jobs: it's the password on the OAuth login page, the key every issued token is signed with, and a bearer token accepted directly by clients that can set a header. Rotating it invalidates every token already issued — intended, but it means reconnecting afterwards.
TZ is a correctness setting, not a display one. The container runs UTC. Without it set to your timezone, an evening review lands on tomorrow's date and the whole review schedule drifts a day.
Running it locally
1. Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh2. Install dependencies
cd bunpro-mcp
uv sync3. Run against a local folder
mkdir -p /tmp/test-vault
VAULT_PATH=/tmp/test-vault MCP_AUTH_TOKEN=dev uv run bunpro-mcpServes on http://localhost:8080. Grammar/ and Vocab/ subfolders are created on first write.
curl localhost:8080/health # {"status":"ok"}
curl -s -o /dev/null -w '%{http_code}\n' localhost:8080/mcp # 401 — auth worksTests
uv run pytestPoking at the tools by hand
The MCP Inspector talks to the tools directly, with no model in the loop:
VAULT_PATH=/tmp/test-vault uv run mcp dev src/bunpro_mcp/server.pyCall import_export with the contents of fixtures/sample_bunpro.csv (dry run first, then for real), then get_review_queue, get_item, and submit_grades, and confirm the queue ordering changes after grading.
To try get_practice_pool, first give it some well-known items — import the sample telling it you already know those words, or grade a few items 4 a couple of times. Then confirm it returns those mastered items, strongest-first, with weaker ones absent.
Deploying to Cloud Run
The scripted path
./deploy.sh --seed ~/Obsidian/Japanese --dry-run-seed # check what would upload
./deploy.sh --seed ~/Obsidian/Japanese # seed, then deploy
./deploy.sh # redeploy laterIt's idempotent — safe to re-run. It enables the required APIs, creates the bucket (with versioning) and the secret if they don't exist, optionally seeds the bucket from a local vault, deploys, sets MCP_PUBLIC_URL to the service URL, scopes the service account to that one bucket, and health-checks the result. An existing secret's value is left alone.
Config via env vars, defaults shown: PROJECT (current gcloud project), REGION (asia-southeast1), VAULT_BUCKET (<project>-bunpro-vault), SERVICE (bunpro-mcp), SECRET (bunpro-mcp-token), TZ_VALUE (Asia/Singapore).
The manual equivalent
gsutil mb -l asia-southeast1 gs://$VAULT_BUCKET
gsutil versioning set on gs://$VAULT_BUCKET
# tr -d '\n' matters: openssl appends a newline, and a secret with a trailing
# newline can never be typed into the login form.
openssl rand -base64 32 | tr -d '\n' | gcloud secrets create bunpro-mcp-token --data-file=-
python scripts/seed_bucket.py ~/Obsidian/Japanese --bucket $VAULT_BUCKET
gcloud run deploy bunpro-mcp --source . --region asia-southeast1 \
--allow-unauthenticated --max-instances=1 --memory 512Mi --timeout 300 \
--set-env-vars VAULT_BUCKET=$VAULT_BUCKET,TZ=Asia/Singapore \
--set-secrets MCP_AUTH_TOKEN=bunpro-mcp-token:latest
# The URL only exists after the first deploy, so this is a second step.
URL=$(gcloud run services describe bunpro-mcp --region asia-southeast1 --format='value(status.url)')
gcloud run services update bunpro-mcp --region asia-southeast1 \
--update-env-vars "MCP_PUBLIC_URL=$URL"Grant the runtime service account roles/storage.objectAdmin on that one bucket only, and roles/secretmanager.secretAccessor on the secret.
Two things that look wrong and aren't:
--allow-unauthenticated— Claude can't mint Google IAM tokens, so IAM can't be the gate. OAuth is. Every route except/healthand/loginreturns 401 without a valid token.--max-instances=1— the container is the bucket's only writer, and keeping it to one instance keeps write conflicts to the rare deploy-overlap case rather than the normal path.
Check it came up:
curl https://<your-service-url>/health # {"status":"ok"}Connecting Claude
Get the token — it's the password you'll type on the login page:
gcloud secrets versions access latest --secret=bunpro-mcp-tokenClaude on web or mobile
Settings → Connectors → Add custom connector:
URL:
https://<your-service-url>/mcpLeave the Advanced OAuth Client ID and Client Secret fields empty — the server registers Claude automatically.
Claude opens a login page. Paste the token, click Approve, and the six tools appear in the tools menu.
The connector authenticates by OAuth 2.1, which is the only method this dialog supports — there's no field for a fixed header outside enterprise-managed connectors. The server implements the full flow (dynamic registration, PKCE, authorization code, refresh) and issues its own tokens, so there's no third-party identity provider involved.
Claude Code, and other header-capable clients
The server also accepts the token directly as a bearer credential, so any client that lets you set a request header can skip the OAuth flow entirely:
Authorization: Bearer <token>In Claude Code that's roughly claude mcp add --transport http bunpro https://<your-service-url>/mcp --header "Authorization: Bearer <token>" — check claude mcp add --help for the flags your version uses, as they have changed between releases.
Claude Desktop can also use the connector UI above, which is the same OAuth flow and needs no config file.
You can confirm the header path works before wiring any client to it:
curl -s -X POST https://<your-service-url>/mcp \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'That should list all six tools. The same request without the header returns 401.
Rotating the token
openssl rand -base64 32 | tr -d '\n' | gcloud secrets versions add bunpro-mcp-token --data-file=-
./deploy.shCloud Run picks up the new version on the next revision. Every issued token stops working, because the signing key derives from this secret — so reconnect the web connector and update any header-based config. That's the intended behaviour: rotating the secret is how you revoke access.
Reading your notes in Obsidian
Mirror the bucket down on a timer (OnBootSec=1min, OnUnitActiveSec=2h, or an equivalent crontab pair):
gsutil -m rsync -r gs://$VAULT_BUCKET/ ~/Obsidian/Japanese/Download only — never sync back up. The container is the bucket's only writer, which is what keeps write conflicts rare; pushing local edits up would need real conflict resolution that isn't built. The consequence, knowingly accepted: prose you edit locally in Obsidian stays local. Also don't pass -d with a destination above the vault folder, or it will delete unrelated files.
Troubleshooting
The connector won't connect, with no useful error. Almost always MCP_PUBLIC_URL not matching the URL Claude dialled — it's advertised as the OAuth issuer and clients compare it. Check it:
curl https://<your-service-url>/.well-known/oauth-authorization-serverThe issuer must be your service URL. If it says http://localhost:8080, the variable was never set — run ./deploy.sh, or set it manually as shown above.
The login page rejects the correct token. Check the stored secret for a trailing newline:
gcloud secrets versions access latest --secret=bunpro-mcp-token | xxd | tail -1If it ends 0a, it was created without tr -d '\n'. The server strips whitespace, so this should no longer bite, but a secret created before that fix and never rotated is worth checking.
Tools don't appear after connecting. Confirm the server sees the vault — /health returns 200 even when the bucket is unreachable, deliberately, so that a transient storage error doesn't take down a healthy revision. Check the logs:
gcloud run services logs read bunpro-mcp --region asia-southeast1 --limit 50Reviews land on the wrong day. TZ isn't set. See Configuration.
Notes
Nothing is ever deleted. Items you're done with are suspended, never removed from the vault. Bucket versioning is on as a backstop.
Revocation is rotation. The server issues signed, self-contained tokens with no revocation list —
/revokeis advertised for spec compliance but can't invalidate a token early. RotatingMCP_AUTH_TOKENinvalidates all of them at once.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to interact with Obsidian vaults for creating, reading, searching, and managing notes, daily notes, TODOs, session reports, and backlinks through both stdio and HTTP/SSE transports.Last updated103,7934MIT
- Flicense-qualityDmaintenanceConverts JSON/CSV Markdown content into interactive flashcard pages with multiple templates, PDF export, and voice support for language learning.Last updated
- AlicenseAqualityCmaintenanceAn unofficial MCP server for Bunpro that exposes its review queue, search, statistics, and SRS management as tools, enabling an LLM agent to read study data and add grammar points or vocabulary to reviews.Last updated232MIT
- Alicense-qualityBmaintenanceEnables to interact with your Anki collection through natural language, allowing you to study, edit, and analyze flashcards without external dependencies.Last updatedMIT
Related MCP Connectors
Voice-led, FSRS-scheduled flashcards from YouTube, PDFs, web, or text. Auto-graded quizzes.
Turn AI chats into vocabulary: capture words and grammar into spaced-repetition flashcards.
Search your Obsidian vault to quickly find notes by title or keyword, summarize related content, a…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Muslinmin/Japanese_MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server