MCP server that wraps a FHIR Terminology Server, providing tools for code system lookups, ValueSet expansion, code validation, concept mapping, and hierarchical code relationships.
Six well-named, read-only FHIR terminology tools with comprehensive descriptions (150 - 250 chars each) and complete input schemas. All parameters are typed and described. Output schemas are documented in descriptions. However, no tool annotations (readOnlyHint), no error recovery guidance, and no pagination support for expand_valueset despite potentially large result sets. Naming follows verb_noun pattern (expand_, lookup_, subsumes_, translate_, validate_). Descriptions clearly state what each tool does, when to use it, and what it returns, LLM-optimized. Parameters include constraints (e.g., 'Must be a full URL', 'Must be non-empty'). Missing: actionable error messages, per-tool permission declarations, and batch variants.
List all codes contained in a ValueSet by expanding it. Returns: {url, contains: [{system, code, display}], total}. contains is a flat list of concepts; total is the full count when provided by the server. Defaults to returning at most 50 codes — set count to increase or decrease. Does NOT validate a specific code (use validate_code_in_valueset for that). Does NOT search for ValueSets by name — you must provide the exact canonical URL. Example: expand_valueset(url="http://hl7.org/fhir/ValueSet/administrative-gender") → contains: [{code: "male", display: "Male"}, {code: "female", display: "Female"}, ...].
Look up the display name and metadata for a single code in a FHIR code system. Returns: {system, code, display, code_system_name, version}. Use when you need to find what a code means or get its human-readable display name. Does NOT validate membership in a ValueSet (use validate_code_in_valueset). Does NOT check parent/child hierarchy (use subsumes_codes). Only supports one code per call. Example: lookup_code(system="http://snomed.info/sct", code="73211009") → display: "Diabetes mellitus".
Test the hierarchical (is-a) relationship between two codes in the same code system. Returns: {system, code_a, code_b, outcome}. outcome is one of: "equivalent" (same concept), "subsumes" (code_a is a parent of code_b), "subsumed-by" (code_a is a child of code_b), or "not-subsumed" (no hierarchical relationship). Both codes must belong to the same code system — cannot compare across systems. Does NOT look up code details (use lookup_code for that). Only works with code systems that have a hierarchy (e.g. SNOMED CT, ICD-10). Example: subsumes_codes(system="http://snomed.info/sct", code_a="404684003", code_b="73211009") → outcome: "subsumes" (Clinical finding subsumes Diabetes mellitus).
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). All six tools are read-only and idempotent, but this is not declared in the schema. LLMs cannot infer safety properties without explicit hints.
expand_valueset lacks pagination support. Description states 'Defaults to returning at most 50 codes' but no offset/cursor parameter or total count in response schema. Large ValueSets will be truncated silently, and agents cannot iterate.
Error handling lacks recovery guidance. No examples of what happens on invalid system URI, non-existent code, or server timeout. Descriptions do not explain retryability or user-fixable vs. fatal errors.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2025-06-18+ | v2 |
Translate a code from one code system to another using a ConceptMap. Returns: {system, code, concept_map_url, result (true/false), matches: [{equivalence, concept: {system, code, display}}]}. Each match includes an equivalence level (equivalent, wider, narrower, etc.) and the target concept. Does NOT discover ConceptMaps — you must provide the concept_map_url. Does NOT look up or validate codes (use lookup_code or validate_code for that). Example: translate_code(system="http://hl7.org/fhir/administrative-gender", code="male", concept_map_url="http://hl7.org/fhir/ConceptMap/cm-administrative-gender-v3") → matches with target code "M" in v3-AdministrativeGender.
Check whether a code exists and is valid within a code system. Returns: {system, code, result (true/false), display, message}. result=true means the code is recognized; result=false means it is not found or inactive. Does NOT check membership in a ValueSet (use validate_code_in_valueset for that). Does NOT return code properties or definitions (use lookup_code for that). Example: validate_code(system="http://loinc.org", code="718-7") → result: true, display: "Hemoglobin [Mass/volume] in Blood".
Check whether a specific code is a member of a ValueSet. Returns: {valueset_url, system, code, result (true/false), display, message}. result=true means the code belongs to the ValueSet; result=false means it does not. Does NOT validate the code against the entire code system (use validate_code for that). Does NOT list all codes in the ValueSet (use expand_valueset for that). Example: validate_code_in_valueset(valueset_url="http://hl7.org/fhir/ValueSet/administrative-gender", system="http://hl7.org/fhir/administrative-gender", code="male") → result: true.
No permission declarations. Tools do not state required scopes (e.g., 'read:terminology', 'read:valueset'). Agents cannot be configured with least-privilege access.
Parameter descriptions include example values (e.g., 'http://hl7.org/fhir/ValueSet/administrative-gender', 'SNOMED'). LLMs may reuse these literally instead of adapting to context.