Files
kb/openspec/changes/kb-v3-mcp-server/specs/note-mutation/spec.md
T
steve e7136a4a20 Add MCP server, note mutation endpoint, and updated_at tracking (v3.0.0)
New MCP server (mcp/) exposes kb operations as native MCP tools over
Streamable HTTP with Bearer token auth. Supports collections via tag
conventions, chunked file uploads, and agent-side search patterns.

Engine gains PATCH /api/v1/notes/{id} for in-place note updates with
transactional re-chunk/re-embed, and updated_at column on documents.

Go client adds updatenote command and Patch HTTP method.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:34:55 +01:00

44 lines
2.6 KiB
Markdown

# Note Mutation
## Purpose
Note mutation allows existing notes to be updated in place without requiring delete and re-add, preserving document identity (ID, creation timestamp) while updating content, embeddings, and the full-text index.
## Requirements
### Requirement: Note update endpoint
The engine SHALL provide a `PATCH /api/v1/notes/{id}` endpoint that accepts new text for an existing note, re-chunks and re-embeds it, and returns the updated document.
#### Scenario: Update an existing note
- **WHEN** a client sends `PATCH /api/v1/notes/42` with body `{"text": "Updated note content"}`
- **THEN** the engine SHALL delete existing chunks and embeddings for document 42, run the new text through the note chunking pipeline, generate embeddings for each chunk, insert new chunks and embeddings, update the document's `content_hash` and `updated_at`, and return the updated document with HTTP 200
#### Scenario: Update preserves document identity
- **WHEN** a note is updated via PATCH
- **THEN** the document SHALL retain its original `id` and `created_at` values, and `updated_at` SHALL be set to the current timestamp
#### Scenario: Update with long text that produces multiple chunks
- **WHEN** a client sends `PATCH /api/v1/notes/42` with text longer than the embedding model's token window
- **THEN** the engine SHALL chunk the text using the same note chunking pipeline as ingestion, producing multiple chunks, and embed each chunk separately
#### Scenario: Update a non-existent document
- **WHEN** a client sends `PATCH /api/v1/notes/999` and document 999 does not exist
- **THEN** the engine SHALL return HTTP 404
#### Scenario: Update a non-note document
- **WHEN** a client sends `PATCH /api/v1/notes/42` and document 42 has `doc_type = 'pdf'`
- **THEN** the engine SHALL return HTTP 422 with an error indicating that only notes can be updated via this endpoint
#### Scenario: Embedding failure during update
- **WHEN** a client sends `PATCH /api/v1/notes/42` but the embedding step fails
- **THEN** the engine SHALL roll back the entire transaction, preserving the original note content, chunks, and embeddings, and return HTTP 500
#### Scenario: FTS5 index updated on note mutation
- **WHEN** a note is updated via PATCH
- **THEN** the FTS5 virtual table SHALL be updated via the existing chunk triggers (`chunks_ad` for deletes, `chunks_ai` for inserts), keeping the full-text index consistent with the new content
#### Scenario: Tags preserved on update
- **WHEN** a note with tags `["feedback", "collection:memory"]` is updated via PATCH
- **THEN** the document's tags SHALL be unchanged — only the text content, chunks, and embeddings are replaced