Skip to content

sct mcp

Start a local MCP (Model Context Protocol) server backed by the SNOMED CT SQLite database. Exposes SNOMED CT as a set of tools for Claude Desktop, Claude Code, Cursor, and any other MCP-compatible AI client.

Single binary, no runtime dependencies, starts in under 5 ms. The SNOMED CT database is always read-only; codelist tools can read and write .codelist files.


Usage

sct mcp --db <DB> [--embeddings <ARROW>] [--model <MODEL>] [--ollama-url <URL>]

Options

Flag Default Description
--db <FILE> (required) SQLite database produced by sct sqlite.
--embeddings <FILE> Arrow IPC embeddings file produced by sct embed. When supplied, the snomed_semantic_search tool is registered.
--model <MODEL> nomic-embed-text Ollama embedding model (must match the model used by sct embed).
--ollama-url <URL> http://localhost:11434 Ollama API base URL.

Tools exposed

SNOMED CT lookup

Tool Available Description
snomed_search Always Free-text search — returns concept ID, preferred term, FSN, hierarchy
snomed_concept Always Full concept detail by SCTID
snomed_children Always Immediate IS-A children of a concept
snomed_ancestors Always Full ancestor chain up to root
snomed_hierarchy Always List all concepts in a named top-level hierarchy
snomed_map Always (UK edition only) Bidirectional SNOMED↔CTV3/Read v2 cross-map
snomed_semantic_search Requires --embeddings Nearest-neighbour semantic search via vector embeddings

Code list management

Tool Description
codelist_list List .codelist files in a directory, with title, status, and concept count
codelist_read Read a codelist — returns metadata and concept lists (active, excluded, pending)
codelist_new Scaffold a new .codelist file with YAML front-matter template
codelist_add Add concept(s) by SCTID — resolves preferred terms from the database
codelist_remove Move a concept to explicitly excluded, preserving the audit trail
codelist_validate Validate against the database — inactive concepts, term drift, pending items
codelist_stats Concept count, hierarchy breakdown, leaf/intermediate ratio, release age
codelist_export Export the codelist as csv, opencodelists-csv, or markdown

Claude Desktop configuration

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent on your platform:

{
  "mcpServers": {
    "snomed": {
      "command": "sct",
      "args": ["mcp", "--db", "/path/to/snomed.db"]
    }
  }
}

With semantic search enabled:

{
  "mcpServers": {
    "snomed": {
      "command": "sct",
      "args": ["mcp", "--db", "/path/to/snomed.db",
               "--embeddings", "/path/to/snomed-embeddings.arrow"]
    }
  }
}

Example interactions

Terminology lookup

"What are the subtypes of type 2 diabetes mellitus?"

Claude calls snomed_children with SCTID 44054006, receives the list, and answers with accurate SNOMED-grounded terminology.

"Find me concepts related to difficulty swallowing"

Claude calls snomed_semantic_search with the query text, gets back cosine-similarity-ranked concepts, and can explore them further.

UK CTV3 cross-mapping

"What's the CTV3 code for myocardial infarction?"

Claude calls snomed_map with SCTID 22298006 and terminology snomed, receives:

{
  "snomed_id": "22298006",
  "ctv3_codes": ["X200E"],
  "read2_codes": []
}

"I have a legacy CTV3 code X200E. What's the current SNOMED concept?"

Claude calls snomed_map with code X200E and terminology ctv3, receives the full SNOMED concept details.

Building a codelist interactively

"Create a codelist for asthma diagnosis codes in codelists/asthma.codelist, then find the main asthma concepts and add them."

Claude: 1. Calls codelist_new to scaffold the file 2. Calls snomed_search with "asthma" to find candidate concepts 3. Calls snomed_children on the top-level asthma concept to explore subtypes 4. Calls codelist_add with the chosen SCTIDs 5. Calls codelist_validate to confirm everything is active and correct 6. Calls codelist_stats to summarise the result

"The occupational asthma concept shouldn't be in there — exclude it with a note."

Claude calls codelist_remove with the SCTID and comment: "occupational pathway — separate codelist".

"Export this as CSV for upload."

Claude calls codelist_export with format: "opencodelists-csv" and returns the content.


Verifying startup

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
  | (stdbuf -o0 sct mcp --db snomed.db & sleep 0.3; kill %1) 2>/dev/null

Transport and protocol

  • Transport: stdio only (JSON-RPC 2.0 over stdin/stdout)
  • Protocol versions supported: MCP 2024-11-05 (Content-Length framing) and MCP 2025-03-26+ (newline-delimited JSON). The version is negotiated on initialize.
  • Database access: read-only — the SNOMED CT database is never modified
  • Codelist files: codelist_new, codelist_add, and codelist_remove write .codelist files on disk; all other tools are read-only
  • Startup time: < 5 ms (well under the 100 ms MCP budget)
  • Schema version check: validates schema_version on startup; warns if the database is newer than the binary, refuses to start if the gap exceeds 5 versions