An MCP server for genomic coordinate liftover and feature overlap using the UCSC REST API.
GenomicOps-MCP demonstrates solid foundational structure with 5 well-defined genomics tools, all with explicit verb-based naming (get_, list_, lift_) and clear descriptions. However, several critical gaps prevent a higher score: (1) Parameter descriptions are sparse or missing entirely, tools like `list_species()` and `get_overlapping_features()` have no parameter descriptions at all; (2) Input schemas are not visible in the provided code for 3 of 5 tools (list_species, list_assemblies appear to have schemas only in decorators, not in function signatures); (3) Output schemas are only partially documented, 2 tools have explicit output_schema decorators, but the others do not; (4) Error handling lacks recovery guidance, tools return dict/list with no indication of what the caller should do on failure; (5) The server mixes MCP tool definitions with FastAPI HTTP endpoints, creating ambiguity about what is actually exposed via MCP transport. Naming is strong (verb-first, domain-specific), and descriptions exist for tools themselves, but parameter-level documentation is incomplete.
Get overlapping features in a genomic region from UCSC.
Convert genomic coordinates between assemblies using UCSC liftOver.
Get assemblies for a given species (exact or fuzzy match)
List all available species from UCSC.
List all UCSC genome browser tracks for a given assembly/genome
Missing or incomplete parameter descriptions across multiple tools. `list_species()` has no parameters documented; `get_overlapping_features()` parameters have minimal descriptions (region: 'Genomic region in UCSC format' is too vague; does not explain what constitutes valid syntax).
Output schemas missing or incompletely specified. `get_overlapping_features()`, `list_species()` have no documented output schemas in code. `lift_over_coordinates()` output schema declares only 'from' and 'to' as required, but code returns 5 fields. LLM cannot infer structure of returned data, risking parsing failures and composition errors.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 64 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 55 | - | v1 |
Error handling lacks recovery guidance. All tools catch exceptions and return error fields (e.g., dict with 'error' key), but do not guide the LLM on what to do next. E.g., if `list_ucsc_tracks()` returns error 'Timeout fetching tracks for hg38', the LLM has no indication whether to retry, request a different assembly, or ask the user.
Parameter constraints not enforced or documented. `timeout` parameter in `list_ucsc_tracks()` has no min/max bounds; `region` parameters across tools accept free-form strings with minimal validation guidance. Rubric requires specifying range/format constraints in descriptions (e.g., 'timeout: integer, 1 - 300 seconds'). This invites LLMs to pass invalid values (e.g., timeout=999999).
Tool implementations depend on external binaries and files (liftOver binary, chain files) that must be pre-downloaded; this dependency is not surfaced in the tool description or error messages. If the binary is missing, `lift_over_coordinates()` will fail, but the error message may not guide the user/LLM toward solutions. The ensure_binary and ensure_chain flags hint at this, but are not fully documented.
Inconsistency between function signatures and declared schemas. E.g., `list_assemblies()` declares output_schema as a dict with specific structure, but function annotation shows `-> list`. `list_species()` has `-> list` but no output schema. This inconsistency may confuse callers about the actual return type.