Releases: ygtalp/rawthink-mcp
Release list
v2.0.1: release plumbing
No functional change. Two release-plumbing defects, both found by publishing 2.0.0 for real rather than by reading the specification.
The MCP registry ownership marker was missing. The registry proves that a publisher controls a PyPI package by finding mcp-name: <server-name> in the package README. 2.0.0 shipped without it, and PyPI versions cannot be re-uploaded — so the fix costs a version. The publish workflow now checks for the marker before it waits on the release, not after.
The publish workflow assumed a tag ref. workflow_dispatch runs on a branch, so GITHUB_REF_NAME was main and every manual run died comparing a branch name against a version number. Tag and manual paths are handled separately now, and both verify that server.json, its package entry and pyproject.toml agree.
Both were verified against the published schema and a parsed workflow file before 2.0.0 went out. Neither check exercised the path that failed.
If you are on 2.0.0 there is nothing to do — the package behaves identically.
v2.0.0: stable BM25 term IDs, atomic writes, doctor
Requires a full reindex. After upgrading, run
reindex(full=True)from a session. A plain reindex skips unchanged chunks and leaves the old sparse encoding in place — which is how a corrupt index survived the documented remedy.
Coming from 0.x, migrate the graph first with
python -m rawthink_mcp.migrate --guess-domains --heal-dangling --apply.rawthink-doctortells you what is still pending.
Why this release exists
BM25 term IDs were positions in a sorted vocabulary. One new token sorting early shifted every ID after it, so sparse vectors written before a reindex stopped matching queries encoded after it.
Nothing failed. RRF kept returning good results off the dense side, so search felt fine while half the retrieval system scored noise.
Measured on a real vault of 1,841 chunks:
| before | after | |
|---|---|---|
| sparse MRR | 0.1596 | 0.6259 |
| sparse nDCG@10 | 0.1851 | 0.6320 |
| sparse hit@10 | 5/19 | 14/19 |
| dense MRR | 0.6842 | 0.6842 |
Dense staying identical is what makes the sparse delta attributable to the fix.
A second finding
The measurement that confirmed the bug also surfaced something the audit had not predicted: 40 of 69 sessions in that vault had never been indexed. The files were on disk, search could never find them, and nothing said so. After indexing the sessions the evaluation needed, dense MRR went 0.6842 → 0.9474 and sparse 0.6259 → 0.8395.
The stale index was costing more than the encoding bug. Both were invisible, and together they read as one vague sense that search could be better. rawthink-doctor now checks for exactly this.
New
rawthink-doctor— nine checks with a fix line for each failure: vault, graph schema, BM25 state format, Qdrant, index coverage, vector dimension, Ollama, MCP registration.- Concurrent writes are safe. Graph mutations take a file lock and a thread lock. Measured before the fix, with three processes writing: one writer's twelve updates all vanished, silently.
- Graceful shutdown releases the Qdrant directory lock and the graph file lock on SIGINT/SIGTERM. POSIX only — Windows terminates rather than signalling.
- 104 tests, no Docker and no Ollama required, running on 3.10–3.13 in CI.
index_vault(force=True), so a full reindex actually re-encodes.
Changed
Term IDs are a hash of the token; format_version is 2 and legacy state is rejected rather than loaded. BM25 state lives with the vault instead of the package directory. Diagnostics go to stderr — they were going to stdout, which is the JSON-RPC channel, so the record of what an indexing run skipped never arrived anywhere. Graph search matches prefixes, not substrings. open_nodes is a pure read. get_session_chunks pages.
Reading
docs/postmortem-bm25-term-drift.md — how a defect stayed invisible for months, and what made it visible.
Full detail in CHANGELOG.md.
v1.5.0: controlled vocabulary, single write path
Schema and packaging release. The graph gets a controlled vocabulary and a single validated write path; the sdist stops shipping the test suite.
Known issue in this version. Sparse retrieval is degraded by a term-ID defect that produces no error and is hidden by RRF fusion — measured on a real vault at MRR 0.16 where it should be 0.63. You will not notice it from search results. Fixed in 2.0.0; see the postmortem. If you are installing fresh, install 2.0.1 instead.
Why this release exists
A real vault reached 46 entity types and 66 relation types across 173 entities. Two causes.
entityType was answering two questions at once — what role does this node play, and what subject is it about — so the list grew by one entry per topic. Splitting subject into its own domain field collapses the type list to ten and keeps it there.
Non-canonical relation types were accepted with a warning. Nothing acted on the warning, so 56 one-off types accumulated unnoticed. The graph stayed writable and stopped being queryable.
Breaking
Existing vaults must be migrated before this version can write to them.
python -m rawthink_mcp.migrate --guess-domains --heal-dangling # dry run
python -m rawthink_mcp.migrate --guess-domains --heal-dangling --applyA timestamped backup is taken before anything is written.
Highlights
record(),record_decision()andrevise()— one validated, all-or-nothing write path.record_decisionstores what was rejected, which is the part that exists nowhere else once the code is written.entityTypeclosed to ten roles;domain,visibilityand observationkindadded.- Unknown relation types are rejected rather than warned about.
search_nodesis bounded and reportstotal_matched, so a truncated result is visible.- Tool profiles:
recall(4 tools, ~900 tokens),record(5, ~1750),full(17, ~4200). serverInfo.versionreports the package version instead of FastMCP's.- The published 0.1.4 sdist contained
tests/, whose fixtures hardcoded personal entity names and session dates.pyproject.tomlnow has an explicit allowlist and the evaluation set loads fromRAWTHINK_EVAL_GT.
Full detail in CHANGELOG.md.
v0.1.4
What's Changed
- Consistent project directory:
rawthink-installnow creates a self-contained project directory with vault, CLAUDE.md, THINKING_DIRECTIVES.md, SETUP.md, docker-compose.yml, and /rtclose command — same structure as git clone - Fix config.py MEMORY_FILE: default path now derives from RAWTHINK_VAULT instead of package location (broken for pip install users)
- Fix rtclose export path:
persist/session_export.py→rawthink-exportentry point - Upgrade-safe hooks: re-running
rawthink-installupdates vault path in settings.json instead of skipping
v0.1.2
Initial public release.
- 15-tool MCP server for Claude Code persistent memory
- Hybrid search: BGE-M3 dense + BM25 sparse with RRF fusion
- JSONL knowledge graph with belief revision and activation decay
- Session lifecycle: /rtclose export, entity extraction, handoff
- rawthink-install CLI for one-command setup
- Multi-terminal safe handoffs