wontopos-mcp 1.0.25 → 1.0.27

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
@@ -6,11 +6,12 @@
6
6
 
7
7
  [Wontopos (WOS)](https://wontopos.com) long-term memory as an [MCP](https://modelcontextprotocol.io) server.
8
8
 
9
- Memory belongs to your **account**, not to a tool. The same store recalls in
9
+ Memory belongs to your **workspace**, not to a tool. The same store recalls in
10
10
  Claude Code, Claude Desktop, Cursor — and in ChatGPT via Actions with the same
11
11
  API ([openapi.json](https://api.wontopos.com/openapi.json)) — so a conversation
12
12
  started in one tool continues in another. The same recall in every language - no language
13
- is privileged - with bounded context (~1,000 tokens on `tablet-2`, the default engine) per recall.
13
+ is privileged - with bounded context per recall: the recent turns, at most 20 memories and at most
14
+ 20 rows of the surrounding conversation.
14
15
 
15
16
  ## Claude Code
16
17
 
@@ -50,12 +51,13 @@ The id must also match `[A-Za-z0-9][A-Za-z0-9._-]{0,63}`. An id outside that (an
50
51
  in a non-Latin script, an email address) cannot be used at all: creating it answers 400 and every
51
52
  other call 404s. Romanize it, or key the store on an internal id.
52
53
 
53
- Create a key in the [console](https://wontopos.com). Optional env:
54
+ Create a key in the [console](https://wontopos.com). The server needs a standard API key:
55
+ with an admin key (`wos-admin-...`) it exits at startup. Optional env:
54
56
 
55
57
  | Variable | What it sets |
56
58
  |---|---|
57
59
  | `WONTOPOS_USER_ID` | The store every tool call uses. Default `"default"`. |
58
- | `WONTOPOS_MODEL` | The engine. Default `tablet-2` — same token price as `tablet-1` and the one that can serve photos and re-ask. Also `tablet-1`, `scroll-1`, `scroll-1.2`. |
60
+ | `WONTOPOS_MODEL` | The engine. Default `tablet-2` — same token price as `tablet-1` and the one that can serve photos and re-ask. Also `tablet-1`, `scroll-1`, `scroll-1.2`, `scroll-2`. |
59
61
  | `WONTOPOS_VERIFY` | Default re-ask passes for `search`, 0-3. Default `0`. Each pass is another engine call, billed for what it delivers; the agent can raise it per call. |
60
62
  | `WONTOPOS_MAX_IMAGES` | Default photo results per `search`, 0-5. Default `0` — see below. |
61
63
  | `WONTOPOS_BASE_URL` | A different API host. Leave unset for the default. |
@@ -66,6 +68,10 @@ Create a key in the [console](https://wontopos.com). Optional env:
66
68
  | `WONTOPOS_HTTP_ALLOWED_HOSTS` | Comma-separated `Host` values to accept in HTTP mode. A tunnel forwards its own name, and an undeclared one is refused 403. |
67
69
  | `WONTOPOS_READ_ONLY` | `1` / `true` / `yes` / `on` / `y` / `t` = read tools only, see Security. A value that is none of those (and none of `0` / `false` / `no` / `off` / `n` / `f`) stops the server rather than being read as off. |
68
70
  | `WONTOPOS_ALLOW_STORE_OVERRIDE` | `1` (same spellings) = multi-store; default = pinned, see Security. |
71
+ | `WONTOPOS_MEMORY_SLEEP` | `1` (same spellings) = `think_back` begins with what the store's last sleep wrote: a note on how to read it, the core, and the names of the four boxes with when each last changed, read from the store each time it opens. Adds `open_box`, which opens a box by its number or name. A sleep itself runs on your own model through the SDK (`sleep`), not in this server. Default off. Comes with the working-memory tools (`scroll-2`). |
72
+ | `WONTOPOS_MEMORY_SEEN` | `1` (same spellings) = adds `memory_recent`, the recent conversation newest first with how many memories you held for each reply, and `memory_seen`, those memories for one line as they stand now. Default off. Comes with the working-memory tools (`scroll-2`). |
73
+
74
+ The working-memory, store-setup and router switches are listed by `npx -y wontopos-mcp --help`.
69
75
 
70
76
  **Why photos default to none.** Not because the model cannot see them - `view_image`
71
77
  hands over the actual picture - but because the rows ride on *every* search, and most
@@ -117,20 +123,25 @@ quietly ignored, and that refusal would otherwise land on every search.
117
123
 
118
124
  | Tool | What the agent does with it |
119
125
  |---|---|
120
- | `recall` | One-call context: the **last 20 turns** (oldest first, one entry per utterance, so ten exchanges) plus relevant long-term memories and surroundings. First call when past context matters. `limit` (5-20) widens the sweep; `context_limit` (0-20) sets how much surrounding conversation rides along, `0` for the memories alone. Both need a limit-aware engine — an older one refuses the whole call, and the tool says which argument to drop. |
121
- | `remember` | Store what the user said that is worth keeping. `speaker: "me"` = the agent's own spoken commitments. Fetched content (search results, files) is not a memory. |
126
+ | `recall` | One-call context: the **last 20 turns** (oldest first, one entry per utterance, so ten exchanges) plus relevant long-term memories and surroundings. First call when past context matters. `limit` (5-20) widens the sweep; `context_limit` (0-20) sets how much surrounding conversation rides along, `0` for the memories alone. |
127
+ | `remember` | Store what the user said that is worth keeping. `speaker: "me"` = the agent's own spoken commitments; a registered speaker's name = what that person said. Fetched content (search results, files) is not a memory. |
122
128
  | `store_turn` | Record one exchange as short-term history - what the user said and what the agent replied. This is what fills `recall`'s 20-turn window — one call appends two entries — and nothing else writes it, so the agent is told to call it after **each** exchange. A turn is billed like any write and is kept long-term as well, searchable afterwards. |
123
129
  | `search` | Search stored memories. `filters` narrows by TIME or topic (`event_from`/`event_to` = when the content happened, `categories`) — for "what did we decide in June?", which a query alone will not pin down. `verify` (0-3) spends extra passes to reach further back; `max_images` (0-5) asks for photos. Answers with `memories`, plus `self_memories` (the assistant's own words, which `filters` do not narrow), `images` and `verify_used` when those applied. |
124
130
  | `update` | Rewrite a memory the user's own words contradicted - keeps what is still true, adds what changed. |
125
131
  | `forget` | Delete one memory by id. |
126
132
  | `list_memories` | Browse everything stored (original text + metadata, paged) - "what do you know about me?", housekeeping. |
127
- | `engram` | Multi-hop retrieval, no LLM: `deep_recall` (thorough), `timeline` (when did X), `gather` (everything related), `equilibrium` (replies that have started to loop or flatten), `tone_stabilizer` (back to the assistant's usual register). The API is the authority - an unknown name answers with the list it accepts. |
133
+ | `engram` | Multi-hop retrieval: `deep_recall` (thorough), `timeline` (when did X), `gather` (everything related), `equilibrium` (replies that have started to loop or flatten), `tone_stabilizer` (back to the assistant's usual register). The API is the authority - an unknown name answers with the list it accepts. |
128
134
  | `view_image` | Fetch the actual picture behind an image memory, as an image the model can look at rather than a caption it can only paraphrase. One photo per call. |
129
135
  | `usage` | What this key has spent and what is left — its lifetime cost, its workspace and per-store cost over the last `days` days, and the account's prepaid balance. Free to call. Lets an agent decide whether to keep going. |
130
136
  | `stats` | Counts for a store. Not the number of things a person told you, so it is a cheap check rather than an answer to "how much do you remember about me?" - `list_memories` answers that. |
131
137
  | `revisions` | How much of the store has been changed since it was written: counts by default, up to 20 memories on request. |
132
138
  | `create_store` | Creates the pinned store after asking the user (any store with `ALLOW_STORE_OVERRIDE=1`). |
133
139
 
140
+ On Scroll 2 the working-memory tools join them: `think_back`, `think_further`,
141
+ `look_around`, `search_again`, `done_thinking`, `user_answered`, `why`, `settings`,
142
+ `update_settings`, and with their switches `timeline`, `look_at_photo`, `open_box`,
143
+ `memory_recent`, `memory_seen`. Each describes itself in `tools/list`.
144
+
134
145
  ## Running it over HTTP yourself
135
146
 
136
147
  Some hosts reach a URL rather than spawning a command. The same server answers over
@@ -147,7 +158,7 @@ WONTOPOS_HTTP_TOKEN="$TOKEN" \
147
158
  npx -y wontopos-mcp
148
159
  ```
149
160
 
150
- Same thirteen tools, same store, same 20-turn window. Callers send
161
+ Same store, same 20-turn window. Callers send
151
162
  `Authorization: Bearer <token>`.
152
163
 
153
164
  It binds `127.0.0.1` unless `WONTOPOS_HTTP_HOST` says otherwise, and **will not start without a token**: the reason to run this mode
@@ -190,17 +201,10 @@ connect to the hosted endpoint instead. Same memory, same stores, same account:
190
201
  by the model — the tools take no store argument, so a prompt-injected model cannot move
191
202
  to a sibling store.
192
203
 
193
- It offers six of the thirteen: `recall` · `search` · `remember` · `list_memories` ·
194
- `stats` · `engram` — the retrieval core plus one write. `update`, `forget`,
195
- `create_store`, `revisions`, `store_turn`, `view_image` and `usage` are local-only. This list
196
- has been wrong twice: it once accounted for nine tools with `revisions` in neither
197
- column, and then named `revisions` as hosted when the endpoint has never served it.
204
+ It offers six of the tools above: `recall` · `search` · `remember` · `list_memories` ·
205
+ `stats` · `engram` — the retrieval core plus one write. Every other tool is local-only.
198
206
  Six is what the endpoint answers `tools/list` with today.
199
207
 
200
- The endpoint is a protocol adapter, not a second way in: every tool call re-enters the
201
- ordinary `/api/v1/memory` routes carrying your key, so the same authentication, rate
202
- limits, billing gates and tenant isolation apply — the same code, not a copy of it.
203
-
204
208
  ## One memory, many tools
205
209
 
206
210
  Same `WONTOPOS_API_KEY` + same store id ⇒ the memory follows you:
@@ -225,6 +229,13 @@ advertise different limits.
225
229
 
226
230
  ## Changelog
227
231
 
232
+ - **1.0.27** - adds the `ask` tool for your skills, the working-memory tools, reading the sleep's files,
233
+ photos and `seen` on or off, a lock file for its dependencies, and the subscription week in `usage`.
234
+ An admin key is refused at start: this server needs a standard key.
235
+ - **1.0.26** - reads are retried on 408/502/503/504 and on an answer that dropped
236
+ mid-body: the `wontopos` SDK pin moves to **2.2.46**. `@modelcontextprotocol/sdk` 1.32.1 or later is
237
+ required, for the fixes it and its dependencies carry.
238
+
228
239
  - **1.0.25** - replies pass a host that checks them against their schemas. The output
229
240
  schemas were closed to fields they do not name, so a validating client refused most
230
241
  tools whenever the service added one. A reply over the byte cap now loses only what
@@ -240,10 +251,10 @@ advertise different limits.
240
251
  the person running the server to set `WONTOPOS_MODEL` to another model. Underneath,
241
252
  the `wontopos` SDK pin moves to **2.2.44**.
242
253
 
243
- - **1.0.23** - on a duplicate, `remember` now says how to find the memory the write
244
- matched: in `duplicate_of` when the reply has it, otherwise with `search`, before
245
- combining both facts or updating that memory. Underneath, the `wontopos` SDK pin moves
246
- to **2.2.43**.
254
+ - **1.0.23** - on a duplicate (models older than Scroll 2; Scroll 2 stores a repeat),
255
+ `remember` now says how to find the memory the write matched: in `duplicate_of` when
256
+ the reply has it, otherwise with `search`, before combining both facts or updating that
257
+ memory. Underneath, the `wontopos` SDK pin moves to **2.2.43**.
247
258
 
248
259
  - **1.0.22** - back to beta, and less for the model to read. 1.0.19 to 1.0.21 said this
249
260
  server was stable, but it is not ready yet, and this release changes the shape of
@@ -353,11 +364,7 @@ advertise different limits.
353
364
  URL" while the boot check said "continuing anyway" — the same situation as an
354
365
  unusable store id, which has exited since 1.0.12, and now so does this.
355
366
 
356
- The count range is no longer restated. `search` and `recall` build their bounds from
357
- the SDK's exported `SEARCH_LIMIT_MIN`/`MAX` and `CONTEXT_LIMIT_MIN`/`MAX` instead of
358
- spelling `5` and `20` into four places — this package has already shipped `search`
359
- declaring 1..60 while `recall` said 5..20 and the service capped at 50, and a copy is
360
- a copy whether or not it agrees today.
367
+ The count range is no longer restated.
361
368
 
362
369
  The oversized-reply path no longer produces unparseable text. A single memory too big to
363
370
  drop used to be handled by slicing the serialized JSON — no closing bracket,
@@ -370,10 +377,7 @@ advertise different limits.
370
377
  asked for. `WONTOPOS_VERIFY` or `WONTOPOS_MAX_IMAGES` set against an engine without
371
378
  that capability made *every* search fail with "needs Tablet 2 or newer … search
372
379
  without it" — advice the caller could not act on, having asked for nothing. A
373
- per-call ask is still refused; a default is dropped. `search`'s count is now 5-20,
374
- the range `recall` has always had, and out of range is refused rather than quietly
375
- adjusted — this schema used to accept 1-60 while the service capped at 50 with no
376
- floor. `create_store`'s description no longer interpolates the configured store id,
380
+ per-call ask is still refused; a default is dropped. `create_store`'s description no longer interpolates the configured store id,
377
381
  which handed the model a `WONTOPOS_USER_ID` like an email address every session.
378
382
  Six free-text arguments that declared a size limit but did not enforce one now do.
379
383
 
@@ -393,17 +397,14 @@ advertise different limits.
393
397
  of its arrays one level down, so the biggest reply this server produces was the one
394
398
  that fell through to a string cut, which is the one result that is not valid JSON.
395
399
  It now finds lists by shape, drops whole entries, and says how many went.
396
- Four more, found by auditing this server against fixes the SDKs already carry:
400
+ Three more, found by auditing this server against fixes the SDKs already carry:
397
401
  a date-only `event_date` in any spelling but zero-padded ISO (`2026-3-14`,
398
402
  `March 14, 2026`) was parsed as LOCAL midnight and stored **one day early** on
399
403
  every UTC+ host — the exact shift the padded path was written to avoid, reached
400
404
  through the one spelling it did not recognize. `WONTOPOS_READ_ONLY=on` read as
401
405
  OFF: an operator who believed they had installed a consult-only server got one
402
406
  whose agent can delete, with nothing in the boot output to say so, so an
403
- unrecognized value now stops the server instead of being guessed. Under
404
- `ALLOW_STORE_OVERRIDE` a `user_id` from the model is trimmed and checked the way
405
- the configured one always was — `"alice "` folds to the collection `alice_`, a
406
- store nothing else reads. And when a trimmed reply carries a paging cursor, the
407
+ unrecognized value now stops the server instead of being guessed. And when a trimmed reply carries a paging cursor, the
407
408
  note says the cursor points past what was dropped and names the `limit` to
408
409
  re-request with: those entries were not merely truncated, they were unreachable.
409
410
 
@@ -426,27 +427,13 @@ advertise different limits.
426
427
  configured one is only a default - there the server still has work to do, so it warns
427
428
  and serves.
428
429
  - **1.0.11** - fixes a regression 1.0.10 introduced, published the same day. 1.0.10 was
429
- right that the folded id should be *announced* and wrong to also *send* it. The API
430
- records the raw id next to the folded one on purpose: that is how it tells a genuine
431
- collision (`alice-smith` vs `alice.smith`, two people, one collection) from the same id
432
- typed again. Sending the pre-folded form destroyed the signal, so a store created as
433
- `My-Project` answered a later `create_store` for `my_project` with **409
434
- conflict_error** - the store reported colliding with itself. Now the raw id travels and
430
+ right that the folded id should be *announced* and wrong to also *send* it. Now the raw id travels and
435
431
  only the messages speak in folded terms. Also corrected: 1.0.10 warned that an id with
436
- no latin alphanumerics makes every such id share one store. Measured
437
- against the live rule, that is not what happens - store ids must match
438
- `[A-Za-z0-9][A-Za-z0-9._-]{0,63}`, so creating one answers 400 and every other call
439
- 404s. It is unusable, not shared, and the warning now says so. And the general fold
432
+ no latin alphanumerics makes every such id share one store. It is unusable, not shared, and the warning now says so. And the general fold
440
433
  warning was dropped from this package: the SDK emits its own on the boot call, and two
441
434
  near-identical lines in a host log is worse than one.
442
435
  - **1.0.10** - the store id is announced as the id that actually holds the memories.
443
- 1.0.8 fixed this for whitespace and stopped there: the API also lowercases an id and
444
- turns anything outside `[a-z0-9_]` into `_`, so `WONTOPOS_USER_ID=My-Project` read and
445
- wrote `my_project` while the ready line, the boot check and `create_store` all repeated
446
- the operator's own spelling back as confirmation. The fold mattered because it collided:
447
- ids differing only by case or punctuation reached ONE store then (case still does), and
448
- 1.0.10 also warned that an id with no latin alphanumerics folds to underscores that every
449
- such id shares, which 1.0.11 above corrects. Both were stated at boot. Underneath, the `wontopos` SDK floor
436
+ Underneath, the `wontopos` SDK floor
450
437
  moved to **2.2.27**: the declared range said `^2.2.24` while the lockfile still pinned
451
438
  **2.2.22**, so this package was built and tested against an SDK five releases old,
452
439
  including the one where store ids collapsed silently. A test now compares the LOCKED
@@ -457,20 +444,13 @@ advertise different limits.
457
444
  from a YAML block or heredoc made every call fail with an unparseable-URL error that
458
445
  named neither the variable nor the cause); MCP SDK bumped to 1.30 and a vulnerable
459
446
  transitive `fast-uri` patched.
460
- - **1.0.9** - the one axis meaning cannot narrow: time. `search` takes `filters` -
447
+ - **1.0.9** - `search` takes `filters` -
461
448
  `event_from`/`event_to` (when the content HAPPENED), `time_from`/`time_to` (when it was
462
- written), `categories`, `min_importance`. The API had supported this the whole time but
463
- it was in neither the spec nor any client, so "what did we decide in June?" ranked the
464
- whole store and hoped. A filter chooses what is searched, not what is kept
465
- afterwards, so a narrow filter still fills your `limit` from inside it. The object is
449
+ written), `categories`, `min_importance`. The object is
466
450
  `.strict()`: a typo like `catagories` is refused instead of silently widening the search
467
451
  back to everything.
468
- - **1.0.8** - two bugs found by driving the server over stdio rather than reading
469
- it. A store id with stray whitespace **split the store in two**: the client was
470
- built from the raw env while the boot check, the ready line and `create_store`
471
- used the trimmed value, so `create_store` made `alice` while every read and write
472
- went to `" alice \n"` — a different collection — and the console still printed
473
- `store "alice" verified`. And an oversized result was capped by slicing the
452
+ - **1.0.8** - a bug found by driving the server over stdio rather than reading
453
+ it: an oversized result was capped by slicing the
474
454
  serialized JSON, handing the model truncated JSON with no closing bracket and a final
475
455
  memory cut mid-sentence (measured: 131,041 bytes of unparseable text from a 764 KB
476
456
  search). Now whole entries are dropped instead, the reply stays valid JSON, and