feat(mcp): add search_memories to Python MCP server#7550
Conversation
Greptile SummaryThis PR closes the feature gap between the SSE MCP server (which already had
Confidence Score: 5/5Safe to merge — the new search route and vector-sync mutations are additive, auth-gated by the existing MCP API key dependency, and don't touch any shared state beyond what was already modified by other memory endpoints. The implementation correctly maps Pinecone memory_id metadata to Firestore document id fields. The 3x over-fetch strategy correctly absorbs locked/rejected filtering. Limit clamping, empty-query guard, and try/except vector-sync wrappers are all in place. No routing conflicts exist. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant Client as MCP Client
participant MCP as Python MCP Server
participant API as FastAPI Backend
participant Pinecone as Pinecone
participant Firestore as Firestore
Client->>MCP: call_tool search_memories
MCP->>MCP: validate api_key, guard empty query
MCP->>API: GET /v1/mcp/memories/search
API->>API: clamp limit, compute fetch_limit
API->>Pinecone: find_similar_memories
Pinecone-->>API: memory_id + score matches
API->>Firestore: get_memories_by_ids
Firestore-->>API: memory docs
API->>API: filter, sort, slice
API-->>MCP: SearchedMemory list
MCP-->>Client: JSON text response
Reviews (2): Last reviewed commit: "fix(mcp): overfetch Pinecone candidates ..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ca1d18fc57
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
ca1d18f to
28628dc
Compare
- MCP create_memory now calls upsert_memory_vector so newly created memories are immediately searchable (previously they were invisible to search_memories until a backfill ran). - Added max(1, ...) guard on limit to prevent 0 or negative values reaching Pinecone.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 24ea6f653e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
MCP delete_memory only removed the Firestore record, leaving a stale Pinecone vector. Now that search_memories is exposed over MCP, those stale vectors would occupy top-K slots and push valid results out. Mirror the canonical /v3/memories delete path (delete_memory_vector in a try/except). Adds tests covering the vector-delete call and the Firestore-deleted-but-vector-failed path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 275d77550c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Adding SEARCH_MEMORIES made OmiTools 8 members, breaking the len(OmiTools) == 7 assertion. Replace the brittle count with an explicit expected-members set and add a SEARCH_MEMORIES membership test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3c72eb5763
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
get_memories_by_ids returns raw Firestore docs without applying the user_review filter that memories_db.get_memories enforces. A memory the user explicitly rejected (user_review=False) had no vector removed, so it could surface in semantic search results. Mirror the DB-layer filter: skip any memory where user_review is False before appending to results. Unreviewed (field absent/None) memories are still included. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8ac995e9d4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
MCP edit_memory only updated Firestore, leaving the Pinecone vector pointing at the old content. Searching for the new text would miss the memory; searching for the old text could still rank it. Re-use the category already fetched by _validate_mcp_memory (edit doesn't change category) and call upsert_memory_vector with the new plaintext value, matching the pattern used in create_memory and delete_memory. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1f147bbe70
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Truncating content for locked hits still leaks existence and short content via MCP API keys. Both reference search implementations (utils/retrieval/tool_services/memories.py and utils/retrieval/tools/memory_tools.py) filter locked hits out entirely. Align search_memories to that policy: skip any memory where is_locked is True before appending to results, and update the test that previously asserted truncation behaviour. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f9701655d0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Fetching exactly limit candidates from Pinecone meant that skipped hits (locked or user_review=False) consumed the entire result budget. With limit=1, a locked top hit returned an empty list even though a valid memory was the next Pinecone match. Fetch fetch_limit = min(limit * 3, 60) candidates, apply all visibility filters, then trim to limit after sorting. The 3x multiplier covers typical filter rates while keeping the Pinecone top_k within a reasonable bound. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
kodjima33
left a comment
There was a problem hiding this comment.
Backend+MCP feature: adds search_memories to Python MCP server, mirrors existing SSE pattern. Approving (backend → approve only per policy).
|
@greptile-apps re-review |
Summary
search_memoriessemantic search tool to the Python MCP server (mcp/src/mcp_server_omi/server.py), enabling Claude Desktop, Cursor, ChatGPT, and other MCP clients to search the user's memories by meaning.GET /v1/mcp/memories/searchREST endpoint tobackend/routers/mcp.py, returning memories ranked by relevance withrelevance_score.The gap
The SSE MCP server (
mcp_sse.py) already hassearch_memories(added in PR #6572, fixed in #6609, requested in #6555). The Python MCP server — which is what developers connect from Claude Desktop, Cursor, and ChatGPT — only hasget_memories(paginated list) andsearch_conversations, but no semantic memory search.This PR closes that gap by wiring the same
vector_db.find_similar_memoriesbackend into the Python MCP path.Before/After
get_memoriesonly (paginated)search_memories("machine learning")returns ranked resultsImplementation
GET /v1/mcp/conversations/searchin the same filevector_db.find_similar_memories(uid, query, threshold=0.0, limit=limit)— same function the SSE server usesSearchedMemorywithid,content,category,relevance_scoreget_memoriesbehavior)limitat 20 to match the SSE server behaviorsearch_conversationstool pattern exactlyFiles
backend/routers/mcp.pySearchedMemorymodel andGET /v1/mcp/memories/searchroutemcp/src/mcp_server_omi/server.pySearchMemoriesmodel,search_memoriesfunction, tool registration, and handlerRelated
search_memoriesto the SSE MCP serversearch_memories500 bugsearch_conversationsto search transcripts (separate concern)🤖 Generated with OpenCode