vector-mcp 2.1.0__tar.gz → 2.1.2__tar.gz

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.
Files changed (84) hide show
  1. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/AGENTS.md +12 -1
  2. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/PKG-INFO +2 -2
  3. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/README.md +1 -1
  4. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/pyproject.toml +1 -1
  5. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/agent_server.py +1 -1
  6. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/mcp_server.py +1 -1
  7. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/vectordb/epistemic_graph.py +56 -14
  8. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp.egg-info/PKG-INFO +2 -2
  9. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/.pre-commit-config.yaml +0 -0
  10. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/CHANGELOG.md +0 -0
  11. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/CLAUDE.md +0 -0
  12. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/LICENSE +0 -0
  13. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/MANIFEST.in +0 -0
  14. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/a2a.json +0 -0
  15. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/mcp_config.json +0 -0
  16. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/mkdocs.yml +0 -0
  17. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/opencode.json +0 -0
  18. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/requirements.txt +0 -0
  19. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/scripts/investigate_timeout.py +0 -0
  20. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/scripts/security_sanitizer.py +0 -0
  21. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/scripts/validate_a2a_agent.py +0 -0
  22. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/scripts/validate_agents.py +0 -0
  23. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/scripts/validate_all_dbs.py +0 -0
  24. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/scripts/verify_deps.py +0 -0
  25. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/setup.cfg +0 -0
  26. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/conftest.py +0 -0
  27. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/reproduce_chunking.py +0 -0
  28. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_action_discovery.py +0 -0
  29. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_agent_server.py +0 -0
  30. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_all_backends.py +0 -0
  31. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_auth.py +0 -0
  32. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_concept_parity.py +0 -0
  33. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_databases.py +0 -0
  34. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_init_dynamics.py +0 -0
  35. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_mcp_server.py +0 -0
  36. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_optional_dependencies.py +0 -0
  37. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_placeholder.py +0 -0
  38. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_protocol_compliance.py +0 -0
  39. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_pruning.py +0 -0
  40. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_retrievers.py +0 -0
  41. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_startup.py +0 -0
  42. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_vector_mcp.py +0 -0
  43. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/tests/test_vectordbs_mock.py +0 -0
  44. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/__init__.py +0 -0
  45. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/__main__.py +0 -0
  46. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/auth.py +0 -0
  47. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/connectors/__init__.py +0 -0
  48. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/connectors/mcp_source_presets.json +0 -0
  49. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/mcp/__init__.py +0 -0
  50. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/mcp/mcp_collection_management.py +0 -0
  51. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/mcp/mcp_search.py +0 -0
  52. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/mcp_config.json +0 -0
  53. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/ontology/__init__.py +0 -0
  54. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/ontology/vector.ttl +0 -0
  55. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/prompts/__init__.py +0 -0
  56. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/prompts/main_agent.json +0 -0
  57. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/prompts/retrieval_specialist.json +0 -0
  58. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/retriever/__init__.py +0 -0
  59. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/retriever/chromadb_retriever.py +0 -0
  60. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/retriever/couchbase_retriever.py +0 -0
  61. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/retriever/epistemic_graph_retriever.py +0 -0
  62. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/retriever/llamaindex_retriever.py +0 -0
  63. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/retriever/mongodb_retriever.py +0 -0
  64. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/retriever/postgres_retriever.py +0 -0
  65. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/retriever/qdrant_retriever.py +0 -0
  66. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/retriever/retriever.py +0 -0
  67. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/skills/__init__.py +0 -0
  68. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/skills/vector-backend-operations/SKILL.md +0 -0
  69. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/skills/vector-collection-management/SKILL.md +0 -0
  70. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/skills/vector-hybrid-search/SKILL.md +0 -0
  71. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/vector_api.py +0 -0
  72. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/vectordb/__init__.py +0 -0
  73. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/vectordb/base.py +0 -0
  74. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/vectordb/chromadb.py +0 -0
  75. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/vectordb/couchbase.py +0 -0
  76. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/vectordb/db_utils.py +0 -0
  77. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/vectordb/mongodb.py +0 -0
  78. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/vectordb/postgres.py +0 -0
  79. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp/vectordb/qdrant.py +0 -0
  80. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp.egg-info/SOURCES.txt +0 -0
  81. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp.egg-info/dependency_links.txt +0 -0
  82. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp.egg-info/entry_points.txt +0 -0
  83. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp.egg-info/requires.txt +0 -0
  84. {vector_mcp-2.1.0 → vector_mcp-2.1.2}/vector_mcp.egg-info/top_level.txt +0 -0
@@ -179,13 +179,24 @@ async def my_tool(param: str) -> str:
179
179
  ## Vector Database Backends
180
180
 
181
181
  ### Supported Backends
182
- - **ChromaDB**: Local filesystem-based vector database (no container required)
182
+ - **Epistemic-Graph** (**DEFAULT**): the native local AI-native engine — durable
183
+ (redb-authoritative) with a native ANN/HNSW index, so semantic search is the engine's
184
+ O(log N) vector search. Zero external infra (autostarts). Selected when `db_type` is
185
+ unspecified (override with `VECTOR_DB_TYPE`).
186
+ - **ChromaDB**: Local filesystem-based vector database (no container required). Opt-in via the `[chromadb]` extra.
183
187
  - **PostgreSQL/PGVector**: PostgreSQL with pgvector extension (container required)
184
188
  - **MongoDB**: MongoDB with manual cosine similarity calculation (container required)
185
189
  - **Qdrant**: Qdrant vector database (container required)
186
190
  - **Couchbase**: Couchbase with REST API fallback and manual cosine similarity (container required, partially functional)
187
191
 
188
192
  ### Implementation Notes
193
+ - **Epistemic-Graph**: stores each chunk as an engine node (text in the indexed
194
+ `description` property, plus metadata) with its embedding in the engine's native ANN
195
+ index via `SyncEpistemicGraphClient` (`.nodes.add` + `.graph.add_embedding`). Semantic
196
+ search is `.graph.semantic_search` (native ANN); lexical/keyword search is the engine's
197
+ one-round-trip `.graph.discover` (keyword overlap + semantic, scalable — a client-side
198
+ term scan is only a fallback for an engine too old for `discover`). A collection maps to
199
+ an engine graph (`graph_name`); embeddings come from the shared `create_embedding_model`.
189
200
  - **MongoDB**: Uses raw MongoClient instead of MongoDBAtlasVectorSearch to avoid authentication issues with local test containers. Implements manual cosine similarity calculation for semantic search.
190
201
  - **Couchbase**: Uses simple client approach with REST API fallback to bypass SDK authentication issues. Implements manual cosine similarity calculation for semantic search. Core search functionality working (10/14 tests passing), CRUD operations limited by N1QL service configuration.
191
202
  - **PostgreSQL**: Uses native PGVector with proper JSONB querying for get_documents_by_ids.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vector-mcp
3
- Version: 2.1.0
3
+ Version: 2.1.2
4
4
  Summary: Integrate RAG into AI Agents via MCP Server. Supports multiple Vector database technologies.
5
5
  Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
6
  License: MIT
@@ -83,7 +83,7 @@ Dynamic: license-file
83
83
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/vector-mcp)
84
84
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/vector-mcp)
85
85
 
86
- *Version: 2.1.0*
86
+ *Version: 2.1.2*
87
87
 
88
88
  ---
89
89
 
@@ -20,7 +20,7 @@
20
20
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/vector-mcp)
21
21
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/vector-mcp)
22
22
 
23
- *Version: 2.1.0*
23
+ *Version: 2.1.2*
24
24
 
25
25
  ---
26
26
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vector-mcp"
7
- version = "2.1.0"
7
+ version = "2.1.2"
8
8
  description = "Integrate RAG into AI Agents via MCP Server. Supports multiple Vector database technologies."
9
9
  readme = "README.md"
10
10
  classifiers = [ "Development Status :: 5 - Production/Stable", "License :: Public Domain", "Environment :: Console", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3",]
@@ -4,7 +4,7 @@ import os
4
4
  import sys
5
5
  import warnings
6
6
 
7
- __version__ = "2.1.0"
7
+ __version__ = "2.1.2"
8
8
 
9
9
  logging.basicConfig(
10
10
  level=logging.INFO,
@@ -37,7 +37,7 @@ from starlette.responses import JSONResponse
37
37
  from vector_mcp.auth import get_client
38
38
  from vector_mcp.vector_api import Api
39
39
 
40
- __version__ = "2.1.0"
40
+ __version__ = "2.1.2"
41
41
 
42
42
  logger = get_logger(name="vector-mcp")
43
43
  logger.setLevel(logging.INFO)
@@ -30,9 +30,12 @@ with optional_import_block():
30
30
 
31
31
  logger = get_logger(__name__)
32
32
 
33
- # Node property key the chunk text is stored under (metadata takes the rest).
34
- _CONTENT_KEY = "content"
35
- _RESERVED_KEYS = {_CONTENT_KEY, "label", "id", "_similarity"}
33
+ # The chunk text is stored under the engine's standard ``description`` property: it is
34
+ # the field the engine keyword-indexes and that ``graph.discover`` hydrates, so lexical
35
+ # search runs engine-side (scalable) instead of an O(N) client scan. Everything not in
36
+ # the reserved set is treated as user metadata.
37
+ _TEXT_KEY = "description"
38
+ _RESERVED_KEYS = {_TEXT_KEY, "label", "id", "_similarity", "name", "type", "score"}
36
39
 
37
40
 
38
41
  @require_optional_import(["epistemic_graph", "agent_utilities"], "epistemic-graph")
@@ -107,7 +110,7 @@ class EpistemicGraphVectorDB(VectorDB):
107
110
  @staticmethod
108
111
  def _props_to_doc(node_id: str, props: dict | None) -> Document:
109
112
  props = dict(props or {})
110
- content = props.pop(_CONTENT_KEY, "") or ""
113
+ content = props.get(_TEXT_KEY, "") or ""
111
114
  meta = {k: v for k, v in props.items() if k not in _RESERVED_KEYS}
112
115
  return Document(id=node_id, content=content, metadata=meta, embedding=None)
113
116
 
@@ -173,7 +176,7 @@ class EpistemicGraphVectorDB(VectorDB):
173
176
  embedding = doc.get("embedding")
174
177
  if embedding is None:
175
178
  embedding = self._embed(text)
176
- client.nodes.add(doc_id, {_CONTENT_KEY: text, "label": "Document", **meta})
179
+ client.nodes.add(doc_id, {_TEXT_KEY: text, "label": "Document", **meta})
177
180
  client.graph.add_embedding(doc_id, [float(x) for x in embedding])
178
181
 
179
182
  def update_documents(
@@ -271,27 +274,66 @@ class EpistemicGraphVectorDB(VectorDB):
271
274
  n_results: int = 10,
272
275
  **kwargs: Any,
273
276
  ) -> QueryResults:
277
+ """Keyword search over the engine's scalable index.
278
+
279
+ Routes through the engine's one-round-trip ``discover`` op — it ranks nodes by
280
+ keyword overlap over the indexed text (the chunk text lives in ``description``)
281
+ AND semantic similarity, returning a hydrated top-k. Falls back to a client-side
282
+ term scan only if the engine is too old to support ``discover``.
283
+ """
274
284
  client = self._client_for(collection_name)
275
285
  results: QueryResults = []
276
286
  for query in queries:
287
+ terms = list(dict.fromkeys(t for t in query.lower().split() if t))
288
+ try:
289
+ q_emb = self._embed(query, is_query=True)
290
+ except Exception:
291
+ q_emb = [] # discover degrades to a bounded keyword-only scan
277
292
  try:
278
- hits = client.graph.match_ontology_terms(query) or []
293
+ hits = client.graph.discover(terms, q_emb, n_results) or []
279
294
  except Exception as e:
280
- logger.info(f"lexical search: {e}")
281
- hits = []
295
+ logger.info(f"discover unavailable, using client scan: {e}")
296
+ results.append(self._lexical_scan(client, terms, n_results))
297
+ continue
282
298
  query_result: list[tuple[Document, float]] = []
283
299
  for item in hits[:n_results]:
284
300
  if isinstance(item, dict):
285
301
  node_id = str(item.get("id", ""))
286
- score = float(item.get("score", 1.0) or 1.0)
302
+ score = float(item.get("score", 0.0) or 0.0)
303
+ # discover hydrates text in-band; fetch full props for metadata.
304
+ try:
305
+ props = client.nodes.properties(node_id) or item
306
+ except Exception:
307
+ props = item
287
308
  else:
288
- node_id, score = str(item), 1.0
309
+ node_id, score, props = str(item), 0.0, None
289
310
  if not node_id:
290
311
  continue
291
- try:
292
- props = client.nodes.properties(node_id)
293
- except Exception:
294
- props = None
295
312
  query_result.append((self._props_to_doc(node_id, props), score))
296
313
  results.append(query_result)
297
314
  return results
315
+
316
+ def _lexical_scan(
317
+ self, client: Any, terms: list[str], n_results: int
318
+ ) -> list[tuple[Document, float]]:
319
+ """Fallback term-frequency scan (only when the engine lacks ``discover``)."""
320
+ try:
321
+ listing = client.nodes.list() or []
322
+ except Exception as e:
323
+ logger.info(f"lexical scan (list nodes): {e}")
324
+ return []
325
+ scored: list[tuple[Document, float]] = []
326
+ for entry in listing:
327
+ node_id = str(entry[0]) if isinstance(entry, list | tuple) else str(entry)
328
+ try:
329
+ props = client.nodes.properties(node_id) or {}
330
+ except Exception:
331
+ continue
332
+ content = str(props.get(_TEXT_KEY, "") or "").lower()
333
+ if not content:
334
+ continue
335
+ freq = sum(content.count(t) for t in terms)
336
+ if freq > 0:
337
+ scored.append((self._props_to_doc(node_id, props), float(freq)))
338
+ scored.sort(key=lambda x: x[1], reverse=True)
339
+ return scored[:n_results]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vector-mcp
3
- Version: 2.1.0
3
+ Version: 2.1.2
4
4
  Summary: Integrate RAG into AI Agents via MCP Server. Supports multiple Vector database technologies.
5
5
  Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
6
  License: MIT
@@ -83,7 +83,7 @@ Dynamic: license-file
83
83
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/vector-mcp)
84
84
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/vector-mcp)
85
85
 
86
- *Version: 2.1.0*
86
+ *Version: 2.1.2*
87
87
 
88
88
  ---
89
89
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes