feat(mcp): MCP server exposing memory tools#35
Conversation
5 tools: search_memory, add_memory, add_conversation, list_memories, delete_memory. Server runs via `memv-mcp` CLI entry point over stdio. - `memvee[mcp]` optional dependency - Config-level default_user_id, optional per-call override - `dev.py` entry point for MCP Inspector (`mcp dev`) - Accepts pre-built embedding/LLM clients for programmatic use - 13 tests covering tool logic + full add/search/delete cycle
- New advanced/mcp-server.md covers install, CLI flags, tools, client setup (Claude Desktop / Code / Cursor), HTTP transport, and programmatic embedding. - mkdocs nav: add MCP Server under Advanced. - Pin griffe>=1.0,<2 — griffe 2.0 split into griffe/griffecli/griffelib and the new wheel ships no public API surface mkdocstrings expects.
- Move griffe pin from core dependencies to the docs group — it's a mkdocstrings transitive, not a runtime dep. - Add include_expired param to list_memories so the [expired] status branch is reachable; default off keeps current behavior. - Document add_conversation latency (inline LLM round-trip) in the tool docstring and the MCP docs page.
- do_add_conversation: reword extraction message to "from all pending messages" — process() drains the whole user buffer, not just the freshly-added exchange, so the prior wording overclaimed.
- test_mcp: switch top_k assertion to line-level matching ('- ' could match inside a statement body).
- test_mcp: add test_add_conversation_with_llm_extracts_knowledge covering the has_llm=True path end-to-end via MockLLM.
delete_knowledge in the storage layer keys only on UUID — without an explicit ownership check at the MCP boundary, any caller knowing another user's knowledge UUID could delete it. - do_delete_memory now requires user_id and verifies ownership via get_knowledge before deleting; unknown UUIDs and foreign-user UUIDs both return "not found" to avoid leaking existence. - delete_memory MCP tool gains an optional user_id arg (falls back to the server's default), matching the rest of the surface. - New test_delete_rejects_cross_user covers the isolation guarantee.
ReviewTwo issues found; everything else looks good. Bug — concurrent
|
…ertion - do_add_conversation: switch memory.process() -> memory.flush(), which routes through TaskManager.schedule_processing's per-user guard. Concurrent add_conversation calls for the same user now coalesce onto a single task instead of racing through the pipeline and double-charging the LLM. - test_search_respects_top_k: tighten upper bound to a closed range so the assertion can't pass trivially when the retriever returns zero results.
Summary
memv-mcpCLI exposing memory operations over MCP (stdio + streamable-http) with 5 tools:search_memory,add_memory,add_conversation,list_memories,delete_memory.mcpextra (pip install memvee[mcp]); LLM model is optional — knowledge extraction stays off without it.memv.mcp.server.create_server) accepts injected embedding/LLM clients; tool logic split into plaindo_*coroutines for direct unit testing.advanced/mcp-server.mdwith install, CLI flags, client configs (Claude Desktop / Code / Cursor), and HTTP-transport notes.griffe>=1.0,<2— griffe 2.0 split intogriffe/griffecli/griffeliband breaks mkdocstrings.Test plan
make all— ruff format/check, ty, 242 pytest passed (incl.tests/test_mcp.py)make docsbuilds clean under--strictmemv-mcp --helploads via themcpextraadd_conversation→search_memoryreturns expected statement