@appsoftwareltd/etherpk-mcp 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,164 +1,186 @@
1
1
  # @appsoftwareltd/etherpk-mcp
2
2
 
3
3
  An [MCP](https://modelcontextprotocol.io) server that gives your AI agent (Claude Code, Codex,
4
- Cursor and the like) one of your synced [EtherPK](https://etherpk.com) knowledge graphs, run on
5
- the same computer as the agent.
4
+ Cursor and the like) one of your [EtherPK](https://etherpk.com) knowledge graphs, run on the same
5
+ computer as the agent. The agent can search your notes by words or by meaning, follow links,
6
+ list tasks, and read and edit documents without breaking EtherPK's format.
6
7
 
7
- EtherPK's Sync Server never sees your notes in the clear, so nothing hosted can serve them. This
8
- program is EtherPK's **Headless Client**: to the Sync Server it is one of your devices - so it can
9
- hold your keys, read a graph and keep it in sync. To your agent, it is an MCP server.
8
+ This is EtherPK's **Headless Client**: EtherPK with no editor. Set up depends on where the graph
9
+ lives:
10
10
 
11
- Protected documents are listed by name only, never served.
11
+ - **A local graph folder.** Point it at the folder. It reads and writes the markdown there and
12
+ keeps a search index of it. No sign-in, no server.
13
+ - **A synced graph.** EtherPK's Sync Server never sees your notes unencrypted. The Headless
14
+ Client signs in as one of your devices, holds your keys, keeps the graph in sync and serves it
15
+ from your own computer.
16
+
17
+ The agent gets the same tools either way. Protected documents are listed by name only and never
18
+ served.
12
19
 
13
20
  Needs Node.js 22 or later.
14
21
 
15
- ## Set up
22
+ ## Set up: a synced graph
16
23
 
17
24
  Open the graph in EtherPK, pick **Settings → Agents**, and copy the two commands it shows with your
18
- server and graph filled in. They are:
25
+ server and graph filled in:
19
26
 
20
27
  ```sh
21
- # Once per computer. Prompts for an account-wide Personal Access Token (make one at
22
- # https://sync.etherpk.com/account/tokens, also reachable from "Access tokens" in
23
- # EtherPK's account menu), then shows a short code and the address of your EtherPK:
24
- # open EtherPK there in a browser where you're signed in with your graphs unlocked -
25
- # any page will do - and confirm the code. The same step as adding a phone.
28
+ # Once per computer. Asks for an account-wide Personal Access Token (from
29
+ # https://sync.etherpk.com/account/tokens, or "Access tokens" in EtherPK's account menu),
30
+ # then shows a short code: confirm it in any browser tab where EtherPK is signed in and
31
+ # unlocked. The same step as adding a phone.
26
32
  npx @appsoftwareltd/etherpk-mcp login --sync-server https://sync.etherpk.com
27
33
 
28
- # Self-hosting your own Sync Server? Give its address instead:
29
- # npx @appsoftwareltd/etherpk-mcp login --sync-server https://sync.your-domain.example
30
-
31
- # No EtherPK to hand on this computer (a server you reach over SSH, say)? Press r while
32
- # login is waiting, or use your Recovery Code from the start:
33
- # npx @appsoftwareltd/etherpk-mcp login --sync-server https://sync.etherpk.com --recovery-code
34
-
35
34
  # Tell the agent about the graph (Claude Code shown; the Agents tab has the others).
36
35
  claude mcp add etherpk -- npx @appsoftwareltd/etherpk-mcp serve --sync-server https://sync.etherpk.com --graph <graph id>
37
- ```client
36
+ ```
38
37
 
39
- `npx @appsoftwareltd/etherpk-mcp graphs` lists the graphs each signed-in account can reach, by
40
- name and id. A graph listed as `(no name yet - open it in EtherPK once)` has not been opened by
41
- anyone since the Sync Server learned to carry an encrypted copy of each name; opening it once,
42
- in EtherPK or with `serve`, publishes it. For a scripted setup, `ETHERPK_PAT` and
38
+ Self-hosting? Give your own server's address to `login`. By default `login` gets your keys by
39
+ Device Approval: confirm the code it shows in EtherPK on any device where your account is
40
+ unlocked. If there's no EtherPK to hand, press `r` while `login` is waiting, or add
41
+ `--recovery-code`, and type your Recovery Code instead. For a scripted setup, `ETHERPK_PAT` and
43
42
  `ETHERPK_RECOVERY_CODE` stand in for the prompts.
44
43
 
45
- ## More than one Sync Server
44
+ `npx @appsoftwareltd/etherpk-mcp graphs` lists the graphs each signed-in account can reach, by
45
+ name and id. A graph nobody has opened since names started being stored on the server is opened
46
+ once to read its name; `(unnamed)` means it has none.
47
+
48
+ One computer can be signed in to several Sync Servers - your own beside the managed service, say.
49
+ Run `login` once per server. `--sync-server` then says which one a command means; it can be left
50
+ off while only one is signed in, and the commands the Agents tab shows always include it.
51
+
52
+ ## Set up: a local graph folder
46
53
 
47
- One computer can be signed in to several Sync Servers at once - your own self-hosted one beside
48
- the managed service, say. Run `login` once per server; every login lives in the one config file.
49
- `--sync-server <url>` then says which server a command means:
54
+ No sign-in and no Sync Server required. The agent gets the same tools over the folder's
55
+ markdown, beside the files themselves, which it can still read and write directly. **Settings → Agents** shows the
56
+ command with your folder's path filled in once you've recorded the path on the General tab:
50
57
 
51
58
  ```sh
52
- npx @appsoftwareltd/etherpk-mcp login --sync-server https://sync.your-domain.example
53
- npx @appsoftwareltd/etherpk-mcp graphs # every server, in turn
54
- npx @appsoftwareltd/etherpk-mcp serve --sync-server https://sync.your-domain.example --graph <graph id>
55
- npx @appsoftwareltd/etherpk-mcp logout --sync-server https://sync.your-domain.example
59
+ claude mcp add etherpk -- npx @appsoftwareltd/etherpk-mcp serve --folder /path/to/your/notes
56
60
  ```
57
61
 
58
- While only one server is signed in, `--sync-server` can be left off `graphs`, `serve` and
59
- `logout`. With two or more, `serve` and `logout` refuse to guess and ask for it. The commands
60
- the Agents tab shows always include it, so they stay right whatever else the computer is signed
61
- in to. `logout --all` forgets every server at once.
62
-
63
- Every command runs through `npx`, which fetches the package but never puts `etherpk-mcp` on your
64
- PATH. If you'd rather type the short form, `npm install -g @appsoftwareltd/etherpk-mcp` once and
65
- drop the `npx @appsoftwareltd/` prefix; the program's own hints follow whichever way you ran it.
62
+ The folder must already be an EtherPK graph (open it in EtherPK once). Edits made in an editor,
63
+ or by the agent writing files directly, are picked up before the next tool call, and the index
64
+ follows within a second or so. A tool's write is in the file when the tool returns; if a write
65
+ fails, the agent is told why and the edit is retried on the next write. The index lives under
66
+ the cache directory, never in the folder.
67
+
68
+ ## Commands and flags
69
+
70
+ Every command is `npx @appsoftwareltd/etherpk-mcp <command>`. `npx` never puts `etherpk-mcp` on
71
+ your PATH; for the short form, `npm install -g @appsoftwareltd/etherpk-mcp` once. `--help` (`-h`)
72
+ prints this reference, `--version` (`-v`) the version.
73
+
74
+ | Command | What it does |
75
+ | --- | --- |
76
+ | `login --sync-server <url> [--pat <token>] [--recovery-code]` | Sign this computer in as a device of your account on that Sync Server. Asks for a Personal Access Token unless given one, then unlocks your keys by Device Approval or, with `--recovery-code`, your Recovery Code. Lists the graphs it can reach when done. |
77
+ | `graphs [--sync-server <url>]` | List the synced graphs each signed-in account can reach, by name, id and your role. Without `--sync-server`, every signed-in server in turn. |
78
+ | `serve --graph <id or name> [--sync-server <url>] [--no-semantic]` | Serve one synced graph to the agent over stdio. |
79
+ | `serve --folder <path> [--no-semantic]` | Serve a local graph folder the same way. The folder must already be an EtherPK graph. |
80
+ | `logout [--sync-server <url> \| --all]` | Forget that server's token and keys and delete its cached graphs. `--all` forgets every server and clears the whole cache, semantic runtime and model included. Revoke the token at the portal too if the computer isn't yours to keep. |
81
+ | `semantic setup` | Install the embedding runtime (about 300 MB, through your npm) and the 23 MB model into the cache directory. Once per computer. |
82
+ | `semantic status` | Whether semantic search is set up here, and each cached graph's embedding progress. |
83
+ | `semantic remove` | Delete the runtime and model. Each graph's stored vectors stay in its cache and are reused if you set up again. |
84
+
85
+ | Flag | Applies to | Meaning |
86
+ | --- | --- | --- |
87
+ | `--sync-server <url>` | `login`, `graphs`, `serve --graph`, `logout` | Which Sync Server the command means. Required for `login`; elsewhere optional while only one server is signed in. `serve` and `logout` refuse to guess when several are. |
88
+ | `--pat <token>` | `login` | The Personal Access Token, instead of the prompt. |
89
+ | `--recovery-code` | `login` | Unlock with your Recovery Code instead of waiting for Device Approval. Pressing `r` while `login` waits does the same. |
90
+ | `--graph <id or name>` | `serve` | The synced graph to serve. Exclusive with `--folder`. |
91
+ | `--folder <path>` | `serve` | The local graph folder to serve. Exclusive with `--graph` and `--sync-server`. |
92
+ | `--no-semantic` | `serve` | Keep this agent text-only even when semantic search is set up. |
93
+ | `--all` | `logout` | Every server at once. |
94
+
95
+ | Environment variable | Meaning |
96
+ | --- | --- |
97
+ | `ETHERPK_PAT` | Stands in for the token prompt, for a scripted `login`. |
98
+ | `ETHERPK_RECOVERY_CODE` | Stands in for the Recovery Code prompt, for a scripted `login --recovery-code`. |
99
+ | `ETHERPK_MCP_CONFIG` | The config file holding the logins. Default `~/.config/etherpk/mcp.json` (`XDG_CONFIG_HOME` respected). |
100
+ | `ETHERPK_MCP_CACHE_DIR` | The cache root for graphs, the semantic runtime and the model. Default `~/.cache/etherpk/mcp` (`XDG_CACHE_HOME` respected). Set it in the agent registration's `env` as well as your shell: the agent starts `serve` with its own environment. |
101
+ | `ETHERPK_MCP_SEMANTIC_THREADS` | Threads for the embedding model. Default a quarter of the cores, at most four. |
102
+ | `ETHERPK_MCP_DEBUG_MEMORY` | `1` logs the process's memory use every 10 seconds and on every progress line. |
66
103
 
67
104
  ## What the agent gets
68
105
 
69
106
  `list_documents`, `read_document`, `search`, `backlinks`, `tasks`, `edit_document` (an exact,
70
- unique old→new replacement that merges with anyone typing elsewhere on the page),
71
- `append_document` (a page, or a day's journal entry, created if needed) and `create_page`.
72
- One running instance serves one graph.
107
+ unique old→new replacement; on a synced graph it merges with anyone typing elsewhere on the
108
+ page), `append_document` (a page, or a day's journal entry, created if needed) and
109
+ `create_page`. One running instance serves one graph.
73
110
 
74
- No skill or extra setup is needed for the agent to use it: the server describes its tools and
75
- the graph, and Claude Code reaches for them when you ask about your notes or journal. To make
76
- that a rule rather than a good guess, add one line to your `CLAUDE.md`: *"My notes live in
77
- EtherPK; use the etherpk MCP tools for anything I've written down, and `search` in semantic
78
- mode for questions."*
111
+ No skill or extra setup is needed: the server describes its tools and the graph, and Claude Code
112
+ reaches for them when you ask about your notes. To make that a rule rather than a good guess, add
113
+ one line to your `CLAUDE.md`: *"My notes live in EtherPK; use the etherpk MCP tools for anything
114
+ I've written down, and `search` in semantic mode for questions."*
79
115
 
80
116
  ## Searching by meaning
81
117
 
82
- `search` matches words. With one more step it can also match **meaning** - "when do I pay my
83
- taxes" finds the note that says "due 31 January" - by running a small embedding model on this
84
- computer; nothing is sent anywhere, and protected documents are never embedded. Once per
85
- computer:
118
+ `search` matches words. With one more step it also matches **meaning** - "when do I pay my taxes"
119
+ finds the note that says "due 31 January" - by running a small embedding model on this computer.
120
+ Nothing is sent anywhere, and protected documents are never embedded.
86
121
 
87
122
  ```sh
88
- npx @appsoftwareltd/etherpk-mcp semantic setup # ~300 MB runtime (via your npm) + a 23 MB model, into the cache dir
123
+ npx @appsoftwareltd/etherpk-mcp semantic setup
89
124
  ```
90
125
 
91
- Semantic setup installs the native runtime into `~/.cache/etherpk/mcp/runtime/` and the three
92
- model files into `~/.cache/etherpk/mcp/models/all-MiniLM-L6-v2-int8/`.
93
-
94
- - **Any order, no restart.** Run it before or after registering the agent, even while an agent
95
- is connected: a running `serve` notices within 30 seconds and starts building; until
96
- then a search by meaning is refused with this command in the message, so the agent can tell
97
- you what to run. Nothing in the registration changes (`--no-semantic` on `serve` is the only
98
- switch, to keep one agent text-only).
99
- - **What the agent gets.** `search` accepts `mode: "semantic"` (and `"hybrid"`, both groups
100
- side by side). Every result carries the document, its kind, the breadcrumb of headings and
101
- parent bullets, the passage's 0-based line range and its text with a similarity score - the
102
- agent is told to cite them. Passage text has bullet markers and `[[ ]]` stripped: right for
103
- quoting, wrong as the `old` text of `edit_document`, which should come from `read_document`.
104
- - **Progress.** The first pass over a large graph takes minutes and runs in the background;
105
- after that only edits are processed. `semantic status` lists each cached graph with how many
106
- passages are done; every semantic result says `embedded`/`total` and `complete`; run by
107
- hand, `serve` prints a line every 30 seconds. `semantic remove` deletes runtime and model.
108
- - **Load on the machine.** The first pass uses a quarter of the cores, at most four, and pauses
109
- between model calls; `ETHERPK_MCP_SEMANTIC_THREADS=8` in the registration's `env` makes it
110
- faster and hotter. `ETHERPK_MCP_DEBUG_MEMORY=1` logs the process's memory if you ever need
111
- to see it.
112
- - **Only while it runs.** The store is built and kept current by the `serve` process, which
113
- exists only while an agent session has it open (Claude Code starts it with the session and
114
- stops it after). Nothing runs in between. While it runs, the on-disk snapshot `semantic
115
- status` reads is refreshed 5 s after any change arrives, every 30 s during a build, and at
116
- shutdown, whether or not the agent is calling it. To keep a graph current without an agent
117
- open, run `serve` by hand: `npx @appsoftwareltd/etherpk-mcp serve --graph <id> </dev/null &`.
118
- - **One cache directory for both.** Setup and `serve` must see the same cache root - by default
119
- `~/.cache/etherpk/mcp` (`C:\Users\<you>\.cache\etherpk\mcp` on Windows). If you set
120
- `ETHERPK_MCP_CACHE_DIR` in your shell, put it in the agent registration's `env` too, since
121
- the agent spawns `serve` with its own environment.
126
+ - **Any order, no restart.** Run it before or after registering the agent, even while one is
127
+ connected: a running `serve` notices within 30 seconds and starts building. Until then a
128
+ search by meaning is refused with this command in the message, so the agent can tell you what
129
+ to run.
130
+ - **What changes.** `search` accepts `mode: "semantic"` (and `"hybrid"`, both groups side by
131
+ side). Each result carries the document, the breadcrumb of headings and parent bullets, the
132
+ passage's line range and its text with a similarity score. Passage text has bullet markers and
133
+ `[[ ]]` stripped, so it's right for quoting and wrong as the `old` text of `edit_document`,
134
+ which should come from `read_document`.
135
+ - **Progress.** The first pass over a large graph takes minutes, in the background; after that
136
+ only edits are processed. Every semantic result says `embedded` / `total` and `complete`, and
137
+ `semantic status` shows each cached graph's progress.
138
+ - **Only while it runs.** The store is built and kept current by `serve`, which exists only while
139
+ an agent session has it open. To keep a graph current without an agent, run it by hand:
140
+ `npx @appsoftwareltd/etherpk-mcp serve --graph <id> </dev/null &` (or `--folder <path>`).
141
+ - **Load.** The first pass uses a quarter of the cores, at most four, and pauses between model
142
+ calls. `ETHERPK_MCP_SEMANTIC_THREADS=8` in the registration's `env` makes it faster and hotter.
122
143
 
123
144
  ## What this client keeps on your computer
124
145
 
125
- - **Keys**: `~/.config/etherpk/mcp.json`, one entry per Sync Server, readable only by your user -
126
- the same trust as a browser you've signed in on. (On Windows both paths sit under your user
127
- folder: `C:\Users\<you>\.config\etherpk\` and `C:\Users\<you>\.cache\etherpk\`.)
128
- - **A cache of each graph you serve**: `~/.cache/etherpk/mcp/`, so a restart catches up on what
129
- changed instead of downloading everything again. It holds your notes readably, like a signed-in
130
- browser's own storage does. It is never the source of truth: on every start the Sync Server is
131
- asked what moved and only that is fetched, edits made elsewhere arrive as they happen, and a
132
- newer version of this program discards a cache it no longer understands and rebuilds it.
133
-
134
- Revoke the token at the portal to cut the agent off, and `npx @appsoftwareltd/etherpk-mcp logout`
135
- to forget that server's keys and delete its cache on that computer (`--all` for every server,
136
- which also removes the semantic runtime and model).
146
+ - **Keys** in `~/.config/etherpk/mcp.json`, one entry per Sync Server, readable only by your
147
+ user - the same trust as a browser you've signed in on.
148
+ - **A cache of each synced graph you serve** under `~/.cache/etherpk/mcp/`, so a restart fetches
149
+ what changed rather than everything. It holds your notes readably, as a signed-in browser's
150
+ storage does. It's never the source of truth: on every start the Sync Server is asked what
151
+ moved, edits made elsewhere arrive as they happen, and a newer version of this program
152
+ discards a cache it no longer understands and rebuilds it.
153
+ - **For a folder**, only its index and (once set up) its vectors, under
154
+ `local/<folder name>-<hash of its path>/` in the same cache directory. Nothing is written into
155
+ the folder. Moving or renaming the folder starts the index over.
156
+
157
+ On Windows both paths sit under your user folder: `C:\Users\<you>\.config\etherpk\` and
158
+ `C:\Users\<you>\.cache\etherpk\`. Revoke the token at the portal to cut an agent off; `logout`
159
+ forgets the keys and deletes the cache on this computer.
137
160
 
138
161
  ## Building and publishing
139
162
 
140
- From the EtherPK monorepo (`apps/mcp`; the bundle compiles the Client's own sync, crypto and
141
- index code in through a `$lib` alias, so it builds from the repo, not from this folder alone):
163
+ From the EtherPK monorepo (`apps/mcp`). The bundle compiles the Client's own sync, crypto and
164
+ index code in through a `$lib` alias, so it builds from the repo, not from this folder alone:
142
165
 
143
166
  ```sh
144
- pnpm install # once, at the repo root
167
+ pnpm install # once, at the repo root
145
168
  pnpm --filter @appsoftwareltd/etherpk-mcp check # type-check
146
- pnpm --filter @appsoftwareltd/etherpk-mcp test # unit tests (loopback relay, no server)
169
+ pnpm --filter @appsoftwareltd/etherpk-mcp test # unit tests, no server needed
147
170
  pnpm --filter @appsoftwareltd/etherpk-mcp build # dist/main.js; run it with node dist/main.js
148
171
  ```
149
172
 
150
- To release: bump `version` in `package.json` (the CLI reads its version from there), then from
151
- `apps/mcp` in a real terminal (both the login and the publish need a browser or one-time code,
152
- which needs a TTY):
173
+ To release, bump `version` in `package.json` (the CLI reads it from there), then from `apps/mcp`
174
+ in a real terminal, since both the login and the publish need a one-time code:
153
175
 
154
176
  ```sh
155
- npm whoami || npm login # only if not already signed in (or the token has expired); needs publish rights on @appsoftwareltd
156
- pnpm publish --access public --no-git-checks # prepack runs the build; pnpm rewrites workspace:* deps
157
- npx -y @appsoftwareltd/etherpk-mcp@<version> --version # verify, once the registry lists it (a few minutes)
177
+ npm whoami || npm login # needs publish rights on @appsoftwareltd
178
+ pnpm publish --access public --no-git-checks # prepack builds; pnpm rewrites workspace:* deps
179
+ npx -y @appsoftwareltd/etherpk-mcp@<version> --version # verify, once the registry lists it
158
180
  ```
159
181
 
160
182
  The end-to-end specs in `tests-sync/agents/` build and drive this bundle against a real Sync
161
- Server; the technical notes are in the repo under `docs/docs/technical/Headless Client.md`.
183
+ Server and a real folder; the technical notes are in the repo under
184
+ `docs/docs/technical/Headless Client.md`.
162
185
 
163
- Full guide, including how the cache stays current and what an agent can and can't do:
164
- <https://docs.etherpk.com/using-ai-agents-with-your-notes>.
186
+ Full guide: <https://docs.etherpk.com/using-ai-agents-with-your-notes>.