Mohammad Salah

Infrastructure solutions engineer. Cloud architecture and enterprise deployments by day; building and taking apart retrieval systems the rest of the time.

Focus

Retrieval systems
Hybrid dense + lexical search, Reciprocal Rank Fusion, cross-encoder reranking, header-aware chunking, grounded answer synthesis with citations.
Agent tooling
MCP servers over Streamable HTTP, tool-level input validation, integration testing against live MCP clients.
Infrastructure & cloud
Enterprise architecture, hybrid networking, IAM security boundaries, API middleware.

Projects

Enterprise RAG pipeline

Python · FastAPI · Postgres/pgvector · Cohere Rerank · Claude

A document question-answering service built to be inspectable at every stage, rather than a single opaque call. Each retrieval step exposes its own score so you can see why a chunk surfaced.

  • Hybrid retrieval. Dense vector search over pgvector runs alongside Postgres full-text search on a GIN/tsvector index. The two result sets are combined with Reciprocal Rank Fusion (k=60), so a chunk can surface on either semantic or lexical grounds.
  • Reranking. The fused candidate pool is reordered by Cohere rerank-v3.5 before anything reaches the model.
  • Header-aware chunking. Documents split on Markdown heading structure first, with a token-aware recursive splitter as fallback for oversized sections. Each chunk is stored twice: the clean text for the model's context, and a breadcrumb-prefixed version for embedding, so heading hierarchy improves vector quality without polluting the prompt.
  • Grounded synthesis. Answers are constrained to retrieved context with required inline chunk citations, and an explicit refusal path when retrieval comes back empty.

MCP server and CI verification harness

MCP Python SDK · Streamable HTTP · GitHub Actions · Claude Code CLI

The same pipeline exposed to Claude Code and Claude Desktop as MCP tools, with continuous integration that verifies the tools actually ran.

  • One implementation, two surfaces. The HTTP endpoints and the MCP tools call identical underlying functions rather than the MCP layer proxying HTTP, so the two can't drift apart.
  • Transport debugging. The stdio transport hangs on Windows whenever a tool makes an outbound async HTTP call — reproducible independent of event-loop policy, and matching known open issues in the SDK tracker. Documented the failure and moved to Streamable HTTP, which runs on the same async stack the FastAPI app already uses.
  • CI that can't be fooled by a plausible answer. The workflow starts Postgres with pgvector, launches the MCP server, registers it with the Claude Code CLI, seeds a known document, and asks a question about it. It then asserts both that the response contains a fact only present in the seeded document, and that the server log records an actual CallToolRequest — so a fluent hallucination fails the build instead of passing it.
  • Pre-tool validation. Both MCP tools run input checks before any database or model call: length bounds plus pattern rejection for SQL and prompt-injection payloads. Defense in depth — the SQL itself is already parameterized.

Scope, honestly: this runs locally and in CI against a small corpus. There is no evaluation suite yet — retrieval quality is verified by integration test, not measured. Building a labeled question set and a Ragas-based harness to score faithfulness and context precision is the next piece of work, along with cost and latency instrumentation under load.