klypix-mcp 1.49.1 → 1.50.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/A2A.md +37 -16
- package/FORMAT.md +24 -2
- package/README.md +34 -27
- package/bin/klypix-a2a.mjs +340 -146
- package/bin/klypix-conformance.mjs +36 -0
- package/bin/klypix-install.mjs +1 -1
- package/bin/klypix-mcp.mjs +2 -2
- package/bin/klypix-worker.mjs +12 -1
- package/package.json +2 -2
- package/src/agent-presence.mjs +12 -2
- package/src/brain-doctor.mjs +27 -4
- package/src/brain-write-lock.mjs +78 -0
- package/src/finding-routing.mjs +579 -0
- package/src/global-brain-hook.mjs +151 -5
- package/src/klypix-core.mjs +140 -50
- package/src/klypix-format.mjs +96 -9
- package/src/mcp-presence.mjs +6 -15
- package/src/merge-brains.mjs +22 -7
package/A2A.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# KLYPIX speaks A2A
|
|
1
|
+
# KLYPIX speaks A2A protocol v0.3.0
|
|
2
2
|
|
|
3
3
|
KLYPIX is the **shared, human-owned memory node** for a multi-agent stack.
|
|
4
4
|
**A2A moves the messages between agents; `.klypix` holds the context they read
|
|
@@ -23,11 +23,13 @@ KLYPIX_VAULT=./canvases KLYPIX_A2A_PORT=41241 npx -p klypix-mcp klypix-a2a
|
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Flags / env: `--vault` (`KLYPIX_VAULT`), `--port` (`KLYPIX_A2A_PORT`, default
|
|
26
|
-
`41241`), `--host` (`KLYPIX_A2A_HOST`,
|
|
26
|
+
`41241`), `--host` (`KLYPIX_A2A_HOST`, loopback only), and
|
|
27
|
+
`--allow-cross-project` (opt in to machine-wide registered-brain search).
|
|
27
28
|
|
|
28
|
-
It is **local-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
It is **local-only**: it binds loopback and needs no auth because callers are on
|
|
30
|
+
the same machine. Non-loopback `--host` values are refused. Remote exposure is
|
|
31
|
+
unsupported until authentication, TLS, a real identity model, and cross-process
|
|
32
|
+
write coordination exist together.
|
|
31
33
|
|
|
32
34
|
## Discover it
|
|
33
35
|
|
|
@@ -45,12 +47,14 @@ the skills below.
|
|
|
45
47
|
| Skill `id` | Does | Returns |
|
|
46
48
|
|---|---|---|
|
|
47
49
|
| `make_board` | Create a new `.klypix` from cards + connections | a `.klypix` **FilePart** + summary |
|
|
48
|
-
| `remember` | Append cards/decisions to an existing canvas (positions preserved) |
|
|
50
|
+
| `remember` | Append cards/decisions to an existing canvas (positions preserved) | result summary; flat card appends also return a `.klypix` FilePart |
|
|
51
|
+
| `learn_skill` | Capture a reusable how-to / gotcha as a 🛠 skill card — resurfaces every session | result summary |
|
|
49
52
|
| `recall` | Search card text/titles/`#tags` across the vault | matching cards (text) |
|
|
50
53
|
| `read_canvas` | Read one canvas (cards, graph, `[[links]]`) + its images | markdown + image FileParts |
|
|
51
54
|
| `list_canvases` | List canvases with counts | text |
|
|
52
55
|
| `brain_insights` | Hubs / orphans / stale questions in a brain | text |
|
|
53
|
-
| `search_all_brains` | Cross-project memory search (semantic + lexical) | text |
|
|
56
|
+
| `search_all_brains` | Cross-project memory search (semantic + lexical); advertised only with `--allow-cross-project` | text |
|
|
57
|
+
| `brain_connect` | Find and draw related-but-unlinked cards (proposes before it applies) | text |
|
|
54
58
|
|
|
55
59
|
## Talk to it (JSON-RPC 2.0)
|
|
56
60
|
|
|
@@ -84,7 +88,8 @@ POST /
|
|
|
84
88
|
|
|
85
89
|
The result is an A2A `Task` whose `artifacts[0].parts` contains a
|
|
86
90
|
`{ kind: "file", file: { mimeType: "application/vnd.klypix+zip", bytes } }` — the
|
|
87
|
-
board itself.
|
|
91
|
+
board itself. If `configuration.acceptedOutputModes` excludes that MIME type,
|
|
92
|
+
the server honors the negotiation and does not send the FilePart.
|
|
88
93
|
|
|
89
94
|
**Free-text invocation** — a plain message is routed by intent (a convenience
|
|
90
95
|
for chat-style callers):
|
|
@@ -107,11 +112,27 @@ server resumes it with a stable id and accumulated history).
|
|
|
107
112
|
returns a terminal `Task`. `message/stream` emits a **monotonic** lifecycle in
|
|
108
113
|
one burst — a non-terminal `Task` (`submitted`), then (for completed work) an
|
|
109
114
|
`artifact-update`, then exactly one terminal `status-update` with `final:true`.
|
|
110
|
-
- The server
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
- The server validates the request `Host`, rejects foreign browser `Origin`
|
|
116
|
+
headers, accepts only `application/json` POST bodies (maximum 1 MiB), and emits
|
|
117
|
+
no permissive CORS header. The Agent Card and health endpoint do not disclose
|
|
118
|
+
the local vault path.
|
|
119
|
+
- For every caller-supplied canvas reference — including a path supplied in a
|
|
120
|
+
text part — the server resolves the effective target once, follows symlinks,
|
|
121
|
+
and refuses it if the resulting file is outside the configured vault. The
|
|
122
|
+
project brain selected by the operator's launch `cwd` remains a separate,
|
|
123
|
+
intentional default for brain-specific operations.
|
|
124
|
+
- Provenance is a claim, not authentication: supplied agent names are bounded,
|
|
125
|
+
slugged, and stamped as `a2a:<name>` so they cannot render like an attested
|
|
126
|
+
local `createdVia` identity.
|
|
127
|
+
- `search_all_brains` is absent from the default Agent Card and rejected unless
|
|
128
|
+
the operator starts the server with `--allow-cross-project`; it intentionally
|
|
129
|
+
reads the machine-wide brain registry and cannot be made vault-scoped.
|
|
130
|
+
- A2A writes are serialized **within the server process only**. The desktop app,
|
|
131
|
+
hooks, and other processes are not coordinated by that lock. Any move off
|
|
132
|
+
loopback or to concurrent multi-process callers requires the shared
|
|
133
|
+
cross-process lock first. Do not describe this as conflict-free or lossless
|
|
134
|
+
across processes.
|
|
135
|
+
- A2A does not provide `brain_sync`, presence registration, `brain_message`, or
|
|
136
|
+
`brain_garden` apply. HTTP has no reliable session-close lifecycle for presence,
|
|
137
|
+
messaging would be send-only, and garden's out-of-band human approval gate must
|
|
138
|
+
not be weakened for protocol symmetry.
|
package/FORMAT.md
CHANGED
|
@@ -47,7 +47,8 @@ writer guarantees the content-addressed `images/ files/ thumbs/` split.
|
|
|
47
47
|
"updatedAt": "ISO-8601",
|
|
48
48
|
"title": "My board",
|
|
49
49
|
"stats": { "itemCount": 12, "assetCount": 3, "totalBytes": 0 },
|
|
50
|
-
"sync": { "enabled": false, "lastSyncRev": null, "lastSyncAt": null, "deviceId": "dev_…" }
|
|
50
|
+
"sync": { "enabled": false, "lastSyncRev": null, "lastSyncAt": null, "deviceId": "dev_…" },
|
|
51
|
+
"cloud": { "blobId": "702ecfe0-…", "linkedAt": "ISO-8601", "linkedBy": "Sara Ali" }
|
|
51
52
|
}
|
|
52
53
|
```
|
|
53
54
|
|
|
@@ -65,6 +66,13 @@ writer guarantees the content-addressed `images/ files/ thumbs/` split.
|
|
|
65
66
|
`items/`. Never use `stats` as an integrity check.
|
|
66
67
|
- `sync` records whether the file is opted into the app's cloud sync; it carries no
|
|
67
68
|
content and no credentials.
|
|
69
|
+
- **`cloud`** — optional and additive; written by the KLYPIX app when a brain is
|
|
70
|
+
shared, naming the encrypted cloud copy this file pairs with. It exists so the
|
|
71
|
+
mapping **travels inside the file**: clone the repo, or email the `.klypix`, and the
|
|
72
|
+
copy that arrives already knows its cloud twin — no server lookup, works offline.
|
|
73
|
+
**The encryption key is never here.** The `blobId` alone reaches nothing: the cloud
|
|
74
|
+
copy is ciphertext, and the key travels only in a share link's URL fragment. A
|
|
75
|
+
reader that does not care about cloud sync should ignore this object.
|
|
68
76
|
|
|
69
77
|
## `canvas.json`
|
|
70
78
|
|
|
@@ -115,13 +123,27 @@ strings: `text`, `box`, `image`, `file`, `container`, `approval`, `link`,
|
|
|
115
123
|
"border": true,
|
|
116
124
|
"heading": false,
|
|
117
125
|
"createdBy": "agent",
|
|
118
|
-
"createdVia": "claude-code"
|
|
126
|
+
"createdVia": "claude-code",
|
|
127
|
+
"author": "Sara Ali",
|
|
128
|
+
"updatedAt": 1785500000000
|
|
119
129
|
}
|
|
120
130
|
```
|
|
121
131
|
|
|
122
132
|
`createdBy` (`user` | `agent`) and the optional `createdVia` (which agent/channel
|
|
123
133
|
captured it) are the provenance bits the brain surfaces as badges and lenses.
|
|
124
134
|
|
|
135
|
+
The optional **`author`** answers the question a team actually asks: `createdBy` says
|
|
136
|
+
*what* wrote a card, `author` says *whose*. It is resolved from `git config user.name`
|
|
137
|
+
so brain attribution matches commit attribution with no configuration (override with
|
|
138
|
+
`KLYPIX_AUTHOR`; falls back to the OS user; simply absent if neither resolves).
|
|
139
|
+
|
|
140
|
+
**`updatedAt` is VOLATILE — never treat it as content.** It is restamped by the act of
|
|
141
|
+
writing, so two copies of an identical card differ in it. Any comparison that decides
|
|
142
|
+
"did this card change" must strip `updatedAt` (and the derived `zIndex` in
|
|
143
|
+
`positions`) before comparing, or a plain re-save reads as an edit. The merge engine
|
|
144
|
+
learned this the hard way: a byte-compare spawned conflict twins for cards nobody
|
|
145
|
+
touched. `mergeBrains` exports `sameMeaning(a, b)` as the single correct comparison.
|
|
146
|
+
|
|
125
147
|
## Bytes: when they are embedded vs referenced
|
|
126
148
|
|
|
127
149
|
**Embedded** — the bytes live inside the ZIP under `assets/`, and the item JSON
|
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ npx klypix-mcp conformance
|
|
|
79
79
|
|
|
80
80
|
It runs in a temporary fixture and touches nothing else. It checks tool discovery, task memory,
|
|
81
81
|
truthful peer reporting, overlap surfacing, proactive logging, and in-band delivery of a peer note.
|
|
82
|
-
It verifies
|
|
82
|
+
It verifies 12 required coordination behaviours — not the 18 tools, and not the retrieval engine.
|
|
83
83
|
|
|
84
84
|
---
|
|
85
85
|
|
|
@@ -133,9 +133,9 @@ content.
|
|
|
133
133
|
npx klypix-mcp link --check # audits without writing; exits non-zero on drift
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
>
|
|
137
|
-
>
|
|
138
|
-
>
|
|
136
|
+
> Either form works, and both are safe in CI: `npx -p klypix-mcp klypix-link --check` used to
|
|
137
|
+
> drop `--check` and write anyway — fixed, and locked by `test/cli-args.mjs`, which asserts the
|
|
138
|
+
> standalone bin and the dispatcher parse arguments identically.
|
|
139
139
|
|
|
140
140
|
**Give a project a brain** by dropping a `brain.klypix` into it — the
|
|
141
141
|
[KLYPIX app](https://klypix.com) does it in one click (*Save canvas as project brain*), or
|
|
@@ -435,20 +435,21 @@ echo '{ "title": "Plan", "cards": [{ "text": "kickoff" }] }' \
|
|
|
435
435
|
| npx -p klypix-mcp klypix-write --out plan.klypix
|
|
436
436
|
```
|
|
437
437
|
|
|
438
|
-
## Also speaks A2A
|
|
438
|
+
## Also speaks A2A protocol v0.3.0 — experimental
|
|
439
439
|
|
|
440
440
|
```bash
|
|
441
441
|
npx -p klypix-mcp klypix-a2a --vault ./canvases # 127.0.0.1:41241
|
|
442
442
|
# Agent Card: http://127.0.0.1:41241/.well-known/agent-card.json
|
|
443
443
|
```
|
|
444
444
|
|
|
445
|
-
|
|
446
|
-
`
|
|
447
|
-
|
|
445
|
+
Eight vault/project skills by default: `make_board`, `remember`, `learn_skill`, `recall`,
|
|
446
|
+
`read_canvas`, `list_canvases`, `brain_insights`, `brain_connect`. Machine-wide
|
|
447
|
+
`search_all_brains` is a ninth, explicit opt-in via `--allow-cross-project`. Unlike a typical A2A
|
|
448
|
+
agent that returns text, KLYPIX returns the `.klypix` board itself as a multimodal artifact. Details:
|
|
448
449
|
[A2A.md](A2A.md).
|
|
449
450
|
|
|
450
|
-
Treat this as a preview: the A2A smoke test
|
|
451
|
-
been exercised against a third-party A2A client.
|
|
451
|
+
Treat this as a preview: the adversarial A2A smoke test runs in the default `npm test` chain, but
|
|
452
|
+
the server has not been exercised against a third-party A2A client.
|
|
452
453
|
|
|
453
454
|
## Updates — the propagation contract
|
|
454
455
|
|
|
@@ -494,7 +495,10 @@ Read this section before you build on any of it.
|
|
|
494
495
|
|
|
495
496
|
- **Coordination is machine-local and OS-user-local.** The presence lane is a file in your home
|
|
496
497
|
directory. Two developers on two machines do not see each other's sessions, peers, overlaps or
|
|
497
|
-
messages.
|
|
498
|
+
messages. This package ships the cross-machine presence *core* (`./presence-relay` — versioned
|
|
499
|
+
metadata-only frames, a symmetric default-off consent gate, loop prevention and message dedup),
|
|
500
|
+
but no transport: carrying frames between machines is the desktop app's job. With `klypix-mcp`
|
|
501
|
+
alone, coordination is machine-local.
|
|
498
502
|
- **Overlap matching is exact-path, and both sides must declare.** A session that never declares
|
|
499
503
|
its expected files is invisible to overlap detection, and `src/auth/token.ts` does not match a
|
|
500
504
|
rename or a parent directory.
|
|
@@ -502,10 +506,9 @@ Read this section before you build on any of it.
|
|
|
502
506
|
`blocking`; the mechanism is not.
|
|
503
507
|
- **Codex has no automatic capture**, with or without `--codex-hooks`. The Codex hook never writes
|
|
504
508
|
the brain.
|
|
505
|
-
- **
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
them yet.
|
|
509
|
+
- **Uninstall does not remove per-project files.** `npx klypix-mcp uninstall` handles the
|
|
510
|
+
machine-global install; the 14 files `link` wrote into each project are listed by
|
|
511
|
+
`npx klypix-mcp link --check` and removed by `uninstall unlink` **per project**, one at a time.
|
|
509
512
|
- **Drift detection is single-host and opt-in per card.** It needs an `ev:` anchor written by the
|
|
510
513
|
card's author, and it runs only in the Claude Code hook path — the MCP tools do not compute
|
|
511
514
|
freshness.
|
|
@@ -517,8 +520,10 @@ Read this section before you build on any of it.
|
|
|
517
520
|
- **A fresh `npx klypix-mcp install` gets lexical retrieval.** The optional on-device model is
|
|
518
521
|
deliberately not installed.
|
|
519
522
|
- **The capture lock is fail-open** past ~3.6 seconds of contention (see *Git and concurrency*).
|
|
520
|
-
-
|
|
521
|
-
|
|
523
|
+
- **`test/` is not in the published tarball.** Run the suite from a clone. The publish workflow
|
|
524
|
+
*does* gate on it — a `gate` job runs `npm ci`, asserts the test chain is intact, runs `npm test`,
|
|
525
|
+
validates the version/tag, and checks the packed tarball; `publish` declares `needs: gate`, so a
|
|
526
|
+
red gate means npm never sees a tarball.
|
|
522
527
|
- **`canvas_view`'s MCP Apps UI has never been verified on a real Apps host.**
|
|
523
528
|
|
|
524
529
|
## Numbers and methodology
|
|
@@ -542,25 +547,27 @@ independently validated.
|
|
|
542
547
|
|
|
543
548
|
## Uninstall
|
|
544
549
|
|
|
545
|
-
There is no uninstall command yet. To remove Klypix by hand:
|
|
546
|
-
|
|
547
550
|
```bash
|
|
548
|
-
|
|
549
|
-
# then
|
|
550
|
-
|
|
551
|
-
npx klypix-mcp link --check # lists the 14 managed files in a project, so you know what to delete
|
|
551
|
+
npx klypix-mcp uninstall --check # full inventory — writes nothing
|
|
552
|
+
npx klypix-mcp uninstall # asks, then removes the machine-global install
|
|
553
|
+
npx klypix-mcp uninstall unlink # run inside a project: removes the files `link` wrote there
|
|
552
554
|
```
|
|
553
555
|
|
|
556
|
+
It strips only KLYPIX's own entries — every other hook and setting in
|
|
557
|
+
`~/.claude/settings.json` stays — backs up each file it edits, and **never deletes a `.klypix`**.
|
|
558
|
+
`--yes` skips the prompt for scripted removal.
|
|
559
|
+
|
|
554
560
|
Your `brain.klypix` is yours — it is a plain ZIP and stays readable with or without this package.
|
|
555
561
|
|
|
556
562
|
## Contributing
|
|
557
563
|
|
|
558
564
|
Issues and pull requests: [github.com/dahshanlabs/klypix-mcp](https://github.com/dahshanlabs/klypix-mcp).
|
|
559
565
|
|
|
560
|
-
The repository carries
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
566
|
+
The repository carries 38 test files, 34 of them in the `npm test` chain, covering the presence
|
|
567
|
+
lane and its cross-machine relay, the Context Gateway, supervisor hot-swap, auto-update, retrieval
|
|
568
|
+
quality, decay, challenge, lenses, the format guard, the git tools (including a real `git merge`
|
|
569
|
+
through the merge driver), uninstall, and conformance. Run them with `npm test` from a clone — they
|
|
570
|
+
are not in the published tarball, though the publish workflow does run them as a gate. There is a known intermittent Windows `EPERM` flake on rename in
|
|
564
571
|
`test/mcp-supervisor.mjs`.
|
|
565
572
|
|
|
566
573
|
## Why this exists
|