DEV Community

Cover image for I brought KIOKU to Claude Desktop — one .mcpb drag, no Node setup
megaphone
megaphone

Posted on

I brought KIOKU to Claude Desktop — one .mcpb drag, no Node setup

Context

Last week I shipped KIOKU — an OSS memory system for Claude Code. The short version: every session you have with Claude Code gets distilled into a structured Obsidian wiki, and that wiki gets fed back into the next session's system prompt. Your Claude remembers.

One question kept coming up after that post:

Can I use this with Claude Desktop too?

Fair question. And as I looked into it, I realized I'd been drawing an artificial line. Claude Code is where I write code, but Claude Desktop is where I actually think — reading, brainstorming, planning. Half my "second brain" was walking out the door because I only captured one side.

So I shipped Desktop support. This post is the write-up.

https://github.com/megaphone-tokyo/kioku

Why Desktop was the right next step

Three reasons it couldn't wait:

  1. The Claude Code Max barrier. KIOKU's auto-ingest pipeline runs claude -p on a schedule, which effectively gates you on Claude Code Max. "I'd love to try it but I don't have Max" was a recurring theme in early feedback.

  2. Most of my thinking happens in Desktop. Research, early-stage design, brainstorming. If those don't land in the vault, the wiki is only capturing code changes — not the reasoning behind them.

  3. Desktop has way more users. Claude Code is a slice of the Claude user base. The underlying idea — "don't lose the knowledge you create in conversation" — has nothing to do with whether you write code.

Once I framed it that way, Desktop support stopped feeling like an extension and started feeling like the actual target. Code-only was the MVP.

What I built

Two phases:

Phase M: the kioku-wiki MCP server

Claude Desktop doesn't have a Hook system. There's no equivalent to SessionStart / SessionEnd I can latch onto. So auto-capture à la Claude Code was off the table.

The alternative: make it explicit. Give the user a handful of MCP tools, and let Claude decide when to call them based on what the user asks.

Six tools:

Tool What it does
kioku_search Full-text search the wiki (delegates to qmd if installed, falls back to Node grep)
kioku_read Read a specific wiki/<path>.md file
kioku_list List the wiki directory tree
kioku_write_note Append a note to session-logs/ (recommended path)
kioku_write_wiki Write directly to wiki/ (advanced; bypasses auto-ingest structuring)
kioku_delete Move a wiki page to wiki/.archive/ (recoverable)

Implementation: a stdio MCP server in mcp/server.mjs, one dependency (@modelcontextprotocol/sdk), zero network exposure.

Phase N: the .mcpb bundle

Phase M worked, but installing it was painful: git clone, npm install, hand-edit claude_desktop_config.json, restart Desktop. That's fine for developers. It's a cliff for everyone else.

Enter the MCPB format. A .mcpb file is essentially a zip that contains your MCP server and its production dependencies — Claude Desktop runs it via its bundled Node runtime.

So now the install looks like this:

  1. Download kioku-wiki-<version>.mcpb from Releases
  2. Open Claude Desktop
  3. Double-click the .mcpb (or drag it into Settings → Connectors)
  4. Pick your vault directory in the dialog → Install

No Node on the user's machine. No config file editing. About 3.2 MB, start to finish.

The part most people get wrong: Code vs. Desktop

Worth its own section because the difference trips people up.

Claude Code Claude Desktop
Session logging Automatic (via Hooks) None
Wiki writes Scheduled ingest (claude -p) MCP tools (kioku_write_note / kioku_write_wiki)
Typical usage (no command needed) "save this", "remember that", "log this decision"
Context injection Yes (wiki/index.md at SessionStart) Not yet

Code captures by default. Desktop captures when asked. This is a feature, not a bug — Desktop conversations range from "help me draft an email" to "let's think about the architecture." You don't want all of that in your wiki. You want the parts you decide matter.

In my own usage: Code auto-accumulates the implementation work, Desktop gets "summarize what we just figured out and save it" when I hit something worth keeping. Both write to the same vault. The second brain is unified.

Design decision: why MCP?

I considered other options. Chrome extension. Custom HTTP API. AppleScript. MCP won for three reasons:

1. It's Anthropic's own protocol.
Custom APIs don't get native treatment inside Desktop. MCP does. Tools show up as part of the client, not as an outside thing the user has to trust.

2. stdio means zero network surface.
MCP servers talk to the parent over standard in/out. No port to open, no HTTP server to run, no firewall conversation. Matches KIOKU's "your data stays on your machine" principle cleanly.

3. It composes with other MCP servers.
Specifically, qmd (BM25 + semantic search for Markdown) ships as an MCP server. Clients run multiple MCP servers at once, so the user gets qmd's high-precision search and KIOKU's write tools in the same conversation.

That last point also let me scope kioku_search down: it's the fallback for environments without qmd. If qmd is installed, Claude reaches for it first.

Technical notes

Path boundaries

MCP tools write to session-logs/ or wiki/, but never across the boundary. Cross-writes (e.g. kioku_write_wiki trying to write into session-logs/) are rejected.

// mcp/lib/path-boundary.mjs (abridged; imports omitted)
export async function assertInsideWiki(vault, relPath) {
  const wikiRoot = await realpath(join(vault, 'wiki'));
  const resolved = await realpath(join(wikiRoot, relPath));
  if (resolved !== wikiRoot && !resolved.startsWith(wikiRoot + path.sep)) {
    throw new PathBoundaryError('path_outside_boundary');
  }
  return resolved;
}
Enter fullscreen mode Exit fullscreen mode

The realpath calls matter. String-based checks get bypassed by symlink escape. I found that one the hard way writing the tests.

Avoiding races with auto-ingest

Claude Code's auto-ingest rewrites wiki/ on a cron schedule. If a kioku_write_wiki call from Desktop lands in the middle of that, one of them loses.

Fix: an advisory flock at $VAULT/.kioku-mcp.lock with a 30-second TTL. Both the MCP server and auto-ingest respect it. Writes serialize.

Keeping the bundle small

.mcpb files are zipped and shipped to end users. To keep install fast, I had to decide what went in.

@modelcontextprotocol/sdk pulls in express, zod, and friends. A full node_modules/ install is several times larger than what actually needs to ship. Trimming to production-only dependencies gets the bundle to ~3.2 MB. scripts/build-mcpb.sh automates the build and supports --validate for manifest checking.

What this unlocks

The happy side effect of Phase M/N is that one vault is now reachable from both clients.

Claude Code ───┐
               │
               ▼
           Vault ($OBSIDIAN_VAULT)
               ▲
               │
Claude Desktop ┘
Enter fullscreen mode Exit fullscreen mode

Knowledge auto-captured on the Code side is immediately available in Desktop. Fragments I "save" via Desktop get picked up by Code's next auto-ingest run and restructured.

In practice this looks like:

Saving:

User: summarize the RAG approaches from that paper and save it

Claude: [calls kioku_write_note]
  Saved to session-logs/20260419-123456-mcp-rag-summary.md.
  It'll be ingested into wiki/ on the next auto-ingest.
Enter fullscreen mode Exit fullscreen mode

Recalling:

User: where did we land on Prisma vs Drizzle?

Claude: [calls kioku_search]
  wiki/analyses/prisma-vs-drizzle-comparison.md has the comparison.
  TL;DR: Prisma for DX, Drizzle when...
Enter fullscreen mode Exit fullscreen mode

No special syntax. Claude picks the right tool based on what you asked for.

Things that surprised me

⌘Q, not ⌘W, after installing a new .mcpb

Biggest gotcha I hit.

If you install a new .mcpb and then close Desktop with ⌘W and reopen it, the old process sticks around in memory. tools/list picks up the new tool names, but internal logic changes (bug fixes, validation tweaks) don't apply. You're running the new schema over the old code. Confusing.

The fix: ⌘Q, full quit, then reopen. Now prominently in the README.

The "Unverified extension" banner

Desktop warns on unsigned .mcpb files. For a solo OSS author there's no good story here yet — mcpb sign exists but there's no analog to Apple's Developer Program for key management. So users see "Install Anyway." I document it.

macOS TCC and where your vault lives

TCC (Transparency, Consent, Control) can block Desktop's sandbox from reading ~/Documents or iCloud Drive. A lot of Obsidian users keep their vault in iCloud by default. I recommend somewhere else (e.g. ~/_PROJECT/kioku-vault) in the README, but I know people will hit this.

What's next

Phase N is the usable baseline. Three things I want next:

Wiki context injection on Desktop.
Code injects wiki/index.md at SessionStart. Desktop has no equivalent hook. Right now Desktop users have to ask Claude to check the wiki first. I'm looking at Claude Skills and possibly a Chrome extension to automate that.

MCPB signing.
When mcpb sign gets production-ready, I'll ship signed bundles. The "unverified" banner goes away.

Pluggable LLM backend.
Still the long-term bet. Swap claude -p in auto-ingest for OpenAI API, Ollama, whatever. Lowers the barrier for users who aren't on Claude Code Max.

Summary

  • Claude Desktop now works with KIOKU
  • Install is one .mcpb drag, no Node toolchain required
  • Six MCP tools cover search, read, list, write, and archive
  • Code and Desktop write to the same vault — auto-capture on one side, explicit save on the other
  • Fully local stdio, no data leaves your machine
  • MIT licensed, feedback very welcome

https://github.com/megaphone-tokyo/kioku

Read together with the first post, this should give you the full picture of how KIOKU's come together.

Things I'd especially like input on:

  • How does "say save this" feel in actual Desktop use? Is the word choice natural?
  • What's your preferred place to put the vault on macOS? TCC makes this fiddlier than it should be.
  • Ideas for Desktop-side context injection without a full Hook system?

Other projects

hello from the seasons.

A gallery of seasonal photos I take, with a small twist: you can upload your own image and compose yourself into one of the season shots using AI. Cherry blossoms, autumn leaves, wherever. Built it for fun — photography is a long-running hobby, and mixing AI into the workflow felt right.


Built by @megaphone_tokyo — building things with code and AI. Freelance engineer, 10 years in. Tokyo, Japan.

Top comments (0)