@appsoftwareltd/etherpk-mcp 0.1.1 → 0.1.2

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
@@ -37,6 +37,10 @@ claude mcp add etherpk -- npx @appsoftwareltd/etherpk-mcp serve --graph <graph i
37
37
  `npx @appsoftwareltd/etherpk-mcp graphs` lists the graphs the token can reach, by name and id.
38
38
  For a scripted setup, `ETHERPK_PAT` and `ETHERPK_RECOVERY_CODE` stand in for the prompts.
39
39
 
40
+ Every command runs through `npx`, which fetches the package but never puts `etherpk-mcp` on your
41
+ PATH. If you'd rather type the short form, `npm install -g @appsoftwareltd/etherpk-mcp` once and
42
+ drop the `npx @appsoftwareltd/` prefix; the program's own hints follow whichever way you ran it.
43
+
40
44
  ## What the agent gets
41
45
 
42
46
  `list_documents`, `read_document`, `search`, `backlinks`, `tasks`, `edit_document` (an exact,
@@ -57,5 +61,30 @@ One running instance serves one graph.
57
61
  Revoke the token at the portal to cut the agent off, and `npx @appsoftwareltd/etherpk-mcp logout`
58
62
  to forget the keys and delete the cache on that computer.
59
63
 
64
+ ## Building and publishing
65
+
66
+ From the EtherPK monorepo (`apps/mcp`; the bundle compiles the Client's own sync, crypto and
67
+ index code in through a `$lib` alias, so it builds from the repo, not from this folder alone):
68
+
69
+ ```sh
70
+ pnpm install # once, at the repo root
71
+ pnpm --filter @appsoftwareltd/etherpk-mcp check # type-check
72
+ pnpm --filter @appsoftwareltd/etherpk-mcp test # unit tests (loopback relay, no server)
73
+ pnpm --filter @appsoftwareltd/etherpk-mcp build # dist/main.js; run it with node dist/main.js
74
+ ```
75
+
76
+ To release: bump `version` in `package.json` (the CLI reads its version from there), then from
77
+ `apps/mcp` in a real terminal (both the login and the publish need a browser or one-time code,
78
+ which needs a TTY):
79
+
80
+ ```sh
81
+ npm whoami || npm login # only if not already signed in (or the token has expired); needs publish rights on @appsoftwareltd
82
+ pnpm publish --access public --no-git-checks # prepack runs the build; pnpm rewrites workspace:* deps
83
+ npx -y @appsoftwareltd/etherpk-mcp@<version> --version # verify, once the registry lists it (a few minutes)
84
+ ```
85
+
86
+ The end-to-end specs in `tests-server/agents/` build and drive this bundle against a real Sync
87
+ Server; the technical notes are in the repo under `docs/docs/technical/Headless Client.md`.
88
+
60
89
  Full guide, including how the cache stays current and what an agent can and can't do:
61
90
  <https://docs.etherpk.com/using-ai-agents-with-your-notes>.
package/dist/main.js CHANGED
@@ -15,6 +15,61 @@ import { parser } from "@lezer/markdown";
15
15
  import { parse, stringify } from "yaml";
16
16
  import { deserialize, serialize } from "node:v8";
17
17
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
18
+ var package_default = {
19
+ name: "@appsoftwareltd/etherpk-mcp",
20
+ version: "0.1.2",
21
+ license: "Elastic-2.0",
22
+ description: "EtherPK Headless Client: an MCP server over a synced knowledge graph, run beside the agent on the user's own machine.",
23
+ type: "module",
24
+ "private": false,
25
+ bin: { "etherpk-mcp": "./bin/etherpk-mcp.js" },
26
+ files: ["bin", "dist"],
27
+ scripts: {
28
+ "build": "vite build",
29
+ "check": "tsc -p tsconfig.json --noEmit",
30
+ "test": "vitest run",
31
+ "test:watch": "vitest",
32
+ "prepack": "pnpm build"
33
+ },
34
+ dependencies: {
35
+ "@lezer/markdown": "^1.6.4",
36
+ "@modelcontextprotocol/sdk": "^1.30.0",
37
+ "@noble/curves": "^2.2.0",
38
+ "@noble/hashes": "^2.2.0",
39
+ "@sqlite.org/sqlite-wasm": "3.53.0-build1",
40
+ "fake-indexeddb": "^6.2.5",
41
+ "lib0": "^0.2.117",
42
+ "y-protocols": "^1.0.7",
43
+ "yaml": "^2.9.0",
44
+ "yjs": "^13.6.31",
45
+ "zod": "^4.3.6"
46
+ },
47
+ devDependencies: {
48
+ "@appsoftwareltd/etherpk-shared": "workspace:*",
49
+ "@codemirror/view": "^6.43.0",
50
+ "@types/node": "^25.6.0",
51
+ "typescript": "^6.0.2",
52
+ "vite": "^8.0.8",
53
+ "vitest": "^4.1.4"
54
+ },
55
+ publishConfig: { "access": "public" },
56
+ homepage: "https://docs.etherpk.com/using-ai-agents-with-your-notes",
57
+ repository: {
58
+ "type": "git",
59
+ "url": "https://github.com/appsoftwareltd/etherpk",
60
+ "directory": "apps/mcp"
61
+ },
62
+ keywords: [
63
+ "etherpk",
64
+ "mcp",
65
+ "model-context-protocol",
66
+ "knowledge-graph",
67
+ "notes",
68
+ "agent"
69
+ ],
70
+ engines: { "node": ">=22" }
71
+ };
72
+ //#endregion
18
73
  //#region ../client/src/lib/crypto/bytes.ts
19
74
  /**
20
75
  * Byte-array and encoding primitives for the crypto core. No cryptography here.
@@ -8343,22 +8398,29 @@ function createMcpServer(graph, info) {
8343
8398
  * `serve` speaks MCP over stdio, so everything for the human goes to stderr; stdout belongs
8344
8399
  * to the agent. `login` and `graphs` are interactive and print to stdout.
8345
8400
  */
8346
- var VERSION = "0.1.0";
8401
+ var VERSION = package_default.version;
8402
+ /**
8403
+ * How the user invokes this program, so every hint is one they can paste. Through npx - the way
8404
+ * the Agents tab, the README and the docs all say - the bin is never on their PATH, and an npx
8405
+ * run executes out of npm's `_npx` cache; a global install (`npm install -g`) runs from
8406
+ * anywhere else and does have `etherpk-mcp` on the PATH, so it gets the short spelling.
8407
+ */
8408
+ var CMD = /[\\/]_npx[\\/]/.test(process.argv[1] ?? "") ? "npx @appsoftwareltd/etherpk-mcp" : "etherpk-mcp";
8347
8409
  var USAGE = `etherpk-mcp - EtherPK Headless Client (an MCP server over one synced graph)
8348
8410
 
8349
- etherpk-mcp login --server <url> [--pat <token>] [--recovery-code]
8411
+ ${CMD} login --server <url> [--pat <token>] [--recovery-code]
8350
8412
  Sign this machine in as a device of your account. Prompts for a Personal Access
8351
8413
  Token (an account-wide one, from the Sync Server portal at <url>/account/tokens)
8352
8414
  unless --pat or ETHERPK_PAT is given, then unlocks your keys by Device Approval:
8353
8415
  open EtherPK in a browser signed in to the account with its graphs unlocked and
8354
8416
  confirm the code shown. Press r while waiting, or pass --recovery-code, to type
8355
8417
  your Recovery Code instead (or ETHERPK_RECOVERY_CODE, for a scripted setup).
8356
- etherpk-mcp graphs
8418
+ ${CMD} graphs
8357
8419
  List the synced graphs this account can reach, by name and id.
8358
- etherpk-mcp serve --graph <id or name>
8420
+ ${CMD} serve --graph <id or name>
8359
8421
  Serve one graph to an agent over stdio. For Claude Code:
8360
8422
  claude mcp add etherpk -- npx @appsoftwareltd/etherpk-mcp serve --graph <id>
8361
- etherpk-mcp logout
8423
+ ${CMD} logout
8362
8424
  Forget the token, keys and cached graphs on this machine.
8363
8425
 
8364
8426
  The config file is ${defaultConfigPath()} (override with ETHERPK_MCP_CONFIG); cached graphs live
@@ -8409,7 +8471,7 @@ async function ask(question, { secret = false } = {}) {
8409
8471
  }
8410
8472
  async function requireConfig(path) {
8411
8473
  const config = await readConfig(path);
8412
- if (!config) fail(`Not logged in on this machine. Run: etherpk-mcp login --server <url>`);
8474
+ if (!config) fail(`Not logged in on this machine. Run: ${CMD} login --server <url>`);
8413
8475
  return config;
8414
8476
  }
8415
8477
  async function login(args) {
@@ -8485,7 +8547,7 @@ async function approveOrFallBack(account, byRecoveryCode) {
8485
8547
  return byRecoveryCode();
8486
8548
  }
8487
8549
  async function listGraphs(config) {
8488
- if (!config.vaultKey) fail("Keys are not unlocked on this machine. Run: etherpk-mcp login");
8550
+ if (!config.vaultKey) fail(`Keys are not unlocked on this machine. Run: ${CMD} login`);
8489
8551
  const account = await connectAccount(config);
8490
8552
  const vault = await openAccountVault(account.api, fromBase64Url(config.vaultKey));
8491
8553
  const graphs = await account.api.listGraphs();
@@ -8507,13 +8569,14 @@ async function listGraphs(config) {
8507
8569
  console.log(` ${record.id} ${label} [${record.role}]`);
8508
8570
  }
8509
8571
  console.log("");
8510
- console.log("Serve one to an agent with: etherpk-mcp serve --graph <id>");
8572
+ console.log(`Serve one to an agent with: ${CMD} serve --graph <id>`);
8573
+ console.log(`For Claude Code: claude mcp add etherpk -- ${CMD} serve --graph <id>`);
8511
8574
  }
8512
8575
  async function serve(args) {
8513
8576
  const wanted = args.graph?.trim();
8514
8577
  if (!wanted) fail("serve needs --graph <id or name>.");
8515
8578
  const config = await requireConfig(defaultConfigPath());
8516
- if (!config.vaultKey) fail("Keys are not unlocked on this machine. Run: etherpk-mcp login");
8579
+ if (!config.vaultKey) fail(`Keys are not unlocked on this machine. Run: ${CMD} login`);
8517
8580
  const account = await connectAccount(config);
8518
8581
  const vault = await openAccountVault(account.api, fromBase64Url(config.vaultKey));
8519
8582
  const graphs = await account.api.listGraphs();
@@ -8535,7 +8598,7 @@ async function serve(args) {
8535
8598
  break;
8536
8599
  }
8537
8600
  }
8538
- if (!graphId) fail(`No synced graph is named or identified by "${wanted}". Run: etherpk-mcp graphs`);
8601
+ if (!graphId) fail(`No synced graph is named or identified by "${wanted}". Run: ${CMD} graphs`);
8539
8602
  const { record, keyring } = resolveGraphById(graphs, vault, graphId);
8540
8603
  console.error(`etherpk-mcp: opening graph ${graphId} on ${account.serverBaseUrl}…`);
8541
8604
  const graph = await openHeadlessGraph({