Skip to content

Develop with a coding agent

Tokori is built to be hacked on. The plugin SDK, the local HTTP API, and the bundled MCP server compose into a comfortable loop for extending the app with the help of a coding agent — Claude Code, Codex, opencode, Cursor, or anything else that speaks MCP.

This guide assumes you've already wired up the Tokori MCP server. If you haven't, do that first — every recipe below relies on the agent being able to read your live workspace.

The loop

  1. Open the cloned repo in your terminal.
  2. Launch your agent.
  3. Ask it to do something — write a study plugin, add a reader feature, scrape vocab from a source.
  4. The agent reads your live state via the MCP tools, edits files in src/, and tells you what to test.
  5. You hit npm run tauri dev, try it, give feedback. Loop.

The MCP server is what makes step 4 useful: the agent doesn't need to guess what your data looks like, it can call list_workspaces, list_collections, list_vocab and see.

Recipe 1 — write a new study plugin

Plugins live under src/lib/study/plugins/. The contract is in Plugin SDK — short version: export a StudyPlugin with a StudyView React component, register it in src/lib/study/registry.ts.

A productive prompt looks like this:

"I want a new study plugin for the Reverse Cloze drill — show the sentence with one word blanked out, the user types the missing word. Pull example sentences from existing vocab entries' cardNotes field. Use ctx.reviewVocab for grading. Look at src/lib/study/plugins/vocab-recall.tsx for the lifecycle pattern. Also call list_vocab for my Chinese workspace so you know what words I have."

The agent will read the existing plugin, sample your live vocab via MCP, draft the new plugin, and walk you through registering it.

Recipe 2 — bulk-curate a collection

You don't need to write code at all to use the MCP surface. With the Tokori MCP server installed, just ask:

"Pull every Chinese word from this Wikipedia article that I don't already know, fill in pinyin and English glosses from CC-CEDICT, and save them as a collection called 'Beijing Subway System'."

The agent will:

  1. Fetch the article (web tool or pasted text).
  2. Tokenise into Chinese words.
  3. Call list_vocab with q to skip what you already have.
  4. Call search_dict per remaining word to fill readings/glosses.
  5. Call import_collection once with the full batch.

Counts from the response are the source of truth — the agent reports { added, existed, skipped } so you know what actually changed.

Recipe 3 — extend the local HTTP API

The MCP server is a thin proxy over the local HTTP API in src-tauri/src/api_server.rs. To expose a new capability to the agent you change two files in lockstep:

  1. Add the route in api_server.rs under /v1/.
  2. Add a matching tool in mcp-server/src/index.ts (and a typed wrapper in mcp-server/src/api.ts).

A productive prompt:

"Add a /v1/workspaces/:id/vocab/:vid PATCH endpoint that updates the gloss and front_extra fields. Mirror it as an update_vocab tool in mcp-server/src/index.ts. Match the validation pattern used by create_vocab."

The agent edits both surfaces, you cargo check + npm run build in the two directories, restart the desktop app + the MCP server, and the new tool appears in your MCP client.

Recipe 4 — debug a bug with live state

"When I open the character detail page for 餐, the stroke order panel never loads. Look at src/components/character-detail.tsx and tell me where the loader is. Also call list_vocab for my Chinese workspace and find a word containing 餐 — I want to test against a real entry."

The agent has the code, your live data, and the codebase conventions all in one place. Most "hunt the bug" sessions collapse to a 5-minute exchange.

What the agent should always do

  • Use npm run dev for fast UI iteration; switch to npm run tauri dev only when touching Rust.
  • Run npm run build + cargo check before declaring a feature done.
  • Run npm test if it touched anything in src/lib/.

What the agent should never do

  • Mutate your DB without asking. The MCP server intentionally exposes no delete endpoints — if the agent wants to clean up a botched import, it should ask you to delete the collection from the desktop UI.
  • Fabricate readings or glosses. If search_dict returns nothing, leave the field empty.
  • Hard-code provider keys. Provider config flows through the ChatProvider abstraction; never write a provider URL or key into a plugin.

Next steps

MIT licensed.