Serve the database the MCP command selected
`run_mcp` passed `_path`, the local stand-in a URI-backed ref resolves to for display. A path overrides `lancedb.uri`, so `--db-name` on an S3 database served the local default. It passes the ref's own path now, None where a URI placed the database, and `create_mcp_server` accepts that. The client opened around the server is gone. It never served a request, and it opened the scope rather than the derived path, so startup validated the remote database while the server read the local one.
This commit is contained in:
parent
9ed66e3a06
commit
474245ab59
3 changed files with 66 additions and 19 deletions
|
|
@ -918,20 +918,25 @@ class HaikuRAGApp:
|
|||
host: str = "127.0.0.1",
|
||||
port: int = 8001,
|
||||
):
|
||||
"""Run the MCP server until interrupted."""
|
||||
async with HaikuRAG._covering(
|
||||
self.scope, self.config, read_only=self.read_only
|
||||
):
|
||||
server = create_mcp_server(
|
||||
self._path, config=self._store_config, read_only=self.read_only
|
||||
)
|
||||
try:
|
||||
if transport == "stdio":
|
||||
await server.run_stdio_async()
|
||||
else:
|
||||
logger.info(f"Starting MCP server on {host}:{port}")
|
||||
await server.run_http_async(
|
||||
transport="streamable-http", host=host, port=port
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
"""Run the MCP server until interrupted.
|
||||
|
||||
The server opens its own client and validates it on startup, so nothing
|
||||
is opened here first.
|
||||
"""
|
||||
# The ref's own path, not `_path`: a URI-backed database has none, and
|
||||
# the local stand-in would override the URI in `_store_config`.
|
||||
server = create_mcp_server(
|
||||
self._one.db_path,
|
||||
config=self._store_config,
|
||||
read_only=self.read_only,
|
||||
)
|
||||
try:
|
||||
if transport == "stdio":
|
||||
await server.run_stdio_async()
|
||||
else:
|
||||
logger.info(f"Starting MCP server on {host}:{port}")
|
||||
await server.run_http_async(
|
||||
transport="streamable-http", host=host, port=port
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -22,12 +22,16 @@ def _decode_images(images_base64: list[str] | None) -> list[bytes] | None:
|
|||
|
||||
|
||||
def create_mcp_server(
|
||||
db_path: Path, config: AppConfig | None = None, read_only: bool = False
|
||||
db_path: Path | None = None,
|
||||
config: AppConfig | None = None,
|
||||
read_only: bool = False,
|
||||
) -> FastMCP:
|
||||
"""Create an MCP server with the specified database path.
|
||||
|
||||
Args:
|
||||
db_path: Path to the database file.
|
||||
db_path: Path to the database file, or None to let `config` place it. A
|
||||
path overrides a configured `lancedb.uri`, so a URI-backed database
|
||||
must pass None rather than a local stand-in.
|
||||
config: Configuration to use.
|
||||
read_only: If True, write tools (add_document_*, delete_document) are not registered.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -603,6 +603,44 @@ class TestMCPClientLifetime:
|
|||
|
||||
assert opens == 1
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_a_uri_backed_database_is_not_replaced_by_a_local_path(
|
||||
self, monkeypatch
|
||||
):
|
||||
"""A path overrides `lancedb.uri`, so the server gets the database's own
|
||||
path — None where a URI placed it — not the local stand-in a URI-backed
|
||||
ref resolves to for display."""
|
||||
from haiku.rag.app import HaikuRAGApp
|
||||
from haiku.rag.client.scope import DatabaseScope
|
||||
from haiku.rag.config.models import AppConfig, LanceDBConfig
|
||||
|
||||
config = AppConfig(
|
||||
lancedb=LanceDBConfig(databases={"prod": "s3://bucket/prod.lancedb"})
|
||||
)
|
||||
seen: dict = {}
|
||||
|
||||
class _Server:
|
||||
async def run_stdio_async(self):
|
||||
return None
|
||||
|
||||
def fake_create(db_path=None, config=None, read_only=False):
|
||||
seen["db_path"] = db_path
|
||||
seen["config"] = config
|
||||
return _Server()
|
||||
|
||||
monkeypatch.setattr("haiku.rag.app.create_mcp_server", fake_create)
|
||||
app = HaikuRAGApp(
|
||||
scope=DatabaseScope.resolve(config, database_name="prod"), config=config
|
||||
)
|
||||
|
||||
await app.run_mcp(transport="stdio")
|
||||
|
||||
assert seen["db_path"] is None
|
||||
[ref] = DatabaseScope.resolve(
|
||||
seen["config"], database_path=seen["db_path"]
|
||||
).databases
|
||||
assert ref.uri == "s3://bucket/prod.lancedb"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_startup_fails_when_the_database_cannot_open(self, tmp_path):
|
||||
mcp = create_mcp_server(tmp_path / "does-not-exist.lancedb", read_only=True)
|
||||
|
|
|
|||
Loading…
Reference in a new issue