Ahnlich MCP - #383
Conversation
- implemented tools matching ahnlich functionalities - add tests for tools - local setup instructions
High-level implementation - Add separate DB and AI profiles for raw-text and precomputed-embedding workflows. - Introduce shared gRPC lifecycle, validation, metadata, and error-handling behavior. - Build profile-specific tool schemas behind a consistent MCP tool catalog. - Add CLI and environment profile selection, service warnings, and the doctor command. - Manage MCP and local Python SDK dependencies with uv. - Add unit, backend integration, and real MCP stdio tests for both profiles. - Document architecture, source installation, configuration, tools, and development commands. - Ignore the root .vscode directory.
- centralize shared backend operations, formatting, validation and error handling - keep specific AI and DB behavior separate - expand backend test coverage - remove no longer used client.py file
|
After going through this implementation, there are some standards or optimization gaps that I think would be worth while to be implemented for this feature.
|
wizzywit
left a comment
There was a problem hiding this comment.
Overall the implementation looks solid.
- Transport errors are translated into domain exceptions carrying an actionable suggested_action, so a failing tool call tells the agent what to do rather than leaking a gRPC status.
- The server stays up when Ahnlich is unreachable (server.py:52-77) instead of dying at startup — right call for a stdio server whose client owns the process lifecycle.
- doctor is a genuinely useful operator affordance.
- Real end-to-end coverage through ClientSession in tests/integration/test_mcp_stdio.py, not just unit mocks.
- Reuses the in-repo sdk/ahnlich-client-py via [tool.uv.sources] rather than vendoring protobufs.
Preserve server-ranked search results, validate supported AI models, report protocol-level tool errors, and add MCP safety annotations
| f"Unsupported AI model {model!r}." | ||
| f"Supported models: {supported}" |
There was a problem hiding this comment.
NON-BLOCKING (introduced by the fix for #383 (comment) — the validation itself is correct):
Missing separator in the implicit string concatenation, so the two sentences run together:
AHNLICH_AI_MODEL=bogus uv run ahnlich-mcp
ahnlich-mcp: error: Unsupported AI model 'bogus'.Supported models: all-minilm-l12-v2, all-minilm-l6-v2, bge-base-en-v1.5, bge-large-en-v1.5, jina-embeddings-v2-base-code
| f"Unsupported AI model {model!r}." | |
| f"Supported models: {supported}" | |
| f"Unsupported AI model {model!r}. " | |
| f"Supported models: {supported}" |
I scanned the rest of mcp/src/ for the same pattern — this is the only occurrence, every other multi-line message keeps its trailing space.
While you're in this function: line 105 is whitespace-only. Same for backends/base.py:380,475,580. A ruff format --check step in mcp_test.yml would keep these from accumulating (raised in the review summary, not blocking).
This PR adds an MCP server for Ahnlich. Fixes #373
flowchart LR Agent["AI agent"] -->|"stdio"| MCP["ahnlich-mcp"] MCP -->|"DB profile: embeddings"| DB["ahnlich-db"] MCP -->|"AI profile: raw text"| AI["ahnlich-ai"] AI -->|"embeddings"| DBdbandaiprofiles with profile-specific tool schemas.doctorconnectivity command.uvwith Python 3.11 and the monorepo Python SDK.