memgres 0.5.0__tar.gz → 0.5.1__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.
- {memgres-0.5.0 → memgres-0.5.1}/PKG-INFO +1 -1
- {memgres-0.5.0 → memgres-0.5.1}/memgres/_version.py +1 -1
- {memgres-0.5.0 → memgres-0.5.1}/memgres/mcp_server.py +12 -3
- {memgres-0.5.0 → memgres-0.5.1}/memgres.egg-info/PKG-INFO +1 -1
- {memgres-0.5.0 → memgres-0.5.1}/memgres.egg-info/SOURCES.txt +1 -0
- memgres-0.5.1/tests/test_mcp_http_transport.py +86 -0
- {memgres-0.5.0 → memgres-0.5.1}/LICENSE +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/README.md +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/__init__.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/admin_cli.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/blame.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/bootstrap.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/config.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/diffing.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/embed_worker.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/embeddings.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/identity.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/indexing.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/info.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/migrations/0001_core.sql +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/migrations/0002_identity.sql +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/migrations/0003_history_author.sql +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/migrations/0004_title.sql +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/migrations/0005_chunk_index.sql +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/migrations/0006_reader_floor.sql +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/migrations/0007_embed_retry.sql +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/migrations/0008_service_roles.sql +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/reembed.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/schema.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/search.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/segments.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/server.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/store.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/vector/__init__.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/vector/base.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/vector/pgvector.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/vector/qdrant.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres/worker.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres.egg-info/dependency_links.txt +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres.egg-info/entry_points.txt +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres.egg-info/requires.txt +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/memgres.egg-info/top_level.txt +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/pyproject.toml +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/setup.cfg +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_blame_integration.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_chunk_index.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_claim_and_reembed.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_config.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_diffing.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_embed_worker.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_embeddings.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_identity_integration.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_lexical_match.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_limits.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_list.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_mcp_instructions.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_mcp_recall_schema.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_migration_upgrade.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_qdrant_ca.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_qdrant_integration.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_replace_build.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_roles_bootstrap.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_search_integration.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_security_integration.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_segments.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_segments_store.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_server_info.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_server_integration.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_snippets.py +0 -0
- {memgres-0.5.0 → memgres-0.5.1}/tests/test_store_integration.py +0 -0
|
@@ -426,9 +426,18 @@ def main(): # pragma: no cover - entrypoint
|
|
|
426
426
|
server = build_server()
|
|
427
427
|
transport = os.environ.get("MEMGRES_MCP_TRANSPORT", "stdio").lower()
|
|
428
428
|
if transport in ("http", "streamable-http", "streamable_http"):
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
429
|
+
host = os.environ.get("MEMGRES_MCP_HOST", "0.0.0.0")
|
|
430
|
+
port = int(os.environ.get("MEMGRES_MCP_PORT", "8765"))
|
|
431
|
+
# mcp SDK 1.x (FastMCP) reads host/port from `settings`; 2.x (MCPServer)
|
|
432
|
+
# dropped those fields and takes them as run() kwargs (forwarded to
|
|
433
|
+
# run_streamable_http_async). Pick the path the installed SDK supports.
|
|
434
|
+
fields = getattr(type(server.settings), "model_fields", {})
|
|
435
|
+
if "host" in fields:
|
|
436
|
+
server.settings.host = host
|
|
437
|
+
server.settings.port = port
|
|
438
|
+
server.run(transport="streamable-http")
|
|
439
|
+
else:
|
|
440
|
+
server.run(transport="streamable-http", host=host, port=port)
|
|
432
441
|
else:
|
|
433
442
|
server.run()
|
|
434
443
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""The http transport must actually bind its port.
|
|
2
|
+
|
|
3
|
+
Regression guard for the mcp SDK 2.x drift: `main()` used to set
|
|
4
|
+
`server.settings.host`, which 2.x's MCPServer rejects ("Settings object has no
|
|
5
|
+
field host"), so the server crash-looped and never served. This spawns the real
|
|
6
|
+
entrypoint over HTTP and asserts the port answers.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import socket
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
import time
|
|
14
|
+
import urllib.error
|
|
15
|
+
import urllib.request
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
import pytest
|
|
19
|
+
|
|
20
|
+
psycopg = pytest.importorskip("psycopg")
|
|
21
|
+
|
|
22
|
+
DSN = os.environ.get("MEMGRES_TEST_DSN",
|
|
23
|
+
"postgresql://memgres:memgres@localhost:55432/memgres")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _reachable() -> bool:
|
|
27
|
+
try:
|
|
28
|
+
psycopg.connect(DSN, connect_timeout=2).close()
|
|
29
|
+
return True
|
|
30
|
+
except Exception:
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
pytestmark = pytest.mark.skipif(not _reachable(), reason="no test Postgres")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _free_port() -> int:
|
|
38
|
+
s = socket.socket()
|
|
39
|
+
s.bind(("127.0.0.1", 0))
|
|
40
|
+
port = s.getsockname()[1]
|
|
41
|
+
s.close()
|
|
42
|
+
return port
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_http_transport_binds_and_answers():
|
|
46
|
+
port = _free_port()
|
|
47
|
+
env = {**os.environ,
|
|
48
|
+
"MEMGRES_DATABASE_URL": DSN,
|
|
49
|
+
"MEMGRES_KEY_MODE": "single",
|
|
50
|
+
"MEMGRES_EMBED_PROVIDER": "none",
|
|
51
|
+
"MEMGRES_MCP_TRANSPORT": "http",
|
|
52
|
+
"MEMGRES_MCP_HOST": "127.0.0.1",
|
|
53
|
+
"MEMGRES_MCP_PORT": str(port)}
|
|
54
|
+
root = str(Path(__file__).resolve().parent.parent)
|
|
55
|
+
env["PYTHONPATH"] = root + os.pathsep + env.get("PYTHONPATH", "")
|
|
56
|
+
proc = subprocess.Popen([sys.executable, "-m", "memgres.mcp_server"],
|
|
57
|
+
env=env, stdout=subprocess.PIPE,
|
|
58
|
+
stderr=subprocess.STDOUT, text=True)
|
|
59
|
+
url = f"http://127.0.0.1:{port}/mcp"
|
|
60
|
+
try:
|
|
61
|
+
deadline = time.time() + 25
|
|
62
|
+
answered = False
|
|
63
|
+
while time.time() < deadline:
|
|
64
|
+
if proc.poll() is not None:
|
|
65
|
+
out = proc.stdout.read() if proc.stdout else ""
|
|
66
|
+
pytest.fail(f"server exited early (code {proc.returncode}):\n{out}")
|
|
67
|
+
try:
|
|
68
|
+
urllib.request.urlopen(url, timeout=2)
|
|
69
|
+
answered = True # 2xx (unlikely for a bare GET)
|
|
70
|
+
break
|
|
71
|
+
except urllib.error.HTTPError:
|
|
72
|
+
answered = True # bound and speaking HTTP (e.g. 400/406)
|
|
73
|
+
break
|
|
74
|
+
except (urllib.error.URLError, ConnectionError, OSError):
|
|
75
|
+
time.sleep(0.5) # not up yet — retry
|
|
76
|
+
assert answered, f"{url} never answered — the transport did not bind"
|
|
77
|
+
finally:
|
|
78
|
+
proc.terminate()
|
|
79
|
+
try:
|
|
80
|
+
proc.wait(timeout=10)
|
|
81
|
+
except subprocess.TimeoutExpired:
|
|
82
|
+
proc.kill()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if __name__ == "__main__": # pragma: no cover
|
|
86
|
+
sys.exit(pytest.main([__file__, "-v"]))
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|