Tools here appear and disappear with their source data, so a visible tool is one whose dataset actually loaded — a far better signal than a tool that exists and returns empty results. The project is careful about the boundary too: it warns that availability does not mean embeddings are complete, and that search will quietly fall back to keyword matching until they are. The single write tool is fenced three ways — administrator-registered server, allow-list, and an explicit confirmation flag.
A Node.js MCP server covering Taiwanese health data — TFDA drugs with their leaflets and appearance, health supplements, food nutrition, TWCore IG — alongside the international terminologies clinical work depends on: ICD-10-CM/PCS 2025, SNOMED CT International, LOINC 2.80 and FHIR R4. It exposes 49 tools across 11 groups, and mirrors them as an OpenAPI surface for clients that cannot speak MCP.
- Diagnosis coding work: search codes, infer complications, list nearby codes, check for conflicts, and browse a category — `search_medical_codes`, `infer_complications`, `get_nearby_codes`, `check_medical_conflict`, `browse_icd_category`
- TFDA drug data including identifying an unknown pill from its appearance — `search_drug`, `identify_unknown_pill`, `get_drug_details`, `get_drug_asset_links`
- Lab results interpreted against LOINC, one at a time or in a batch — `search_loinc`, `query_loinc`, `interpret_lab_result`, `batch_interpret_lab_results`
- SNOMED CT concepts, their relationships and their mappings — `search_snomed_concept`, `query_snomed_concept`, `get_snomed_relationships`, `query_snomed_mapping`
- A full FHIR IG authoring and validation surface: list and search artifacts across package-scoped IGs, rank and read profiles and their elements, expand ValueSets, look up and validate codes, resolve references, build and validate bundles, and generate a resource skeleton to fill — `fhir_list_igs`, `fhir_search_artifacts`, `fhir_rank_resource_profiles`, `fhir_get_profile_elements`, `fhir_expand_valueset`, `fhir_validate_code`, `fhir_build_bundle`, `fhir_validate_bundle`, `fhir_get_resource_skeleton`, `fhir_finalize_resource`
- Condition and Medication resources queried and validated directly — `query_fhir_condition`, `validate_fhir_condition`, `query_fhir_medication`, `validate_fhir_medication`
- Nutrition data: a food's profile, a single ingredient, foods ranked by a nutrient, and a whole meal analysed — `query_food_nutrition`, `query_food_ingredient`, `search_foods_by_nutrient`, `analyze_meal_nutrition`
- Registered external FHIR servers, their status, and read/write access to them — `list_fhir_servers`, `get_fhir_server_status`, `crud_fhir_server`
- Semantic or hybrid search backed by an embedding model, falling back to keyword search when embeddings are not yet built
- Tools that register and deregister themselves as each module's data finishes loading, so an available tool means its source data is present
This is a deployment, not an install: clone, copy `.env.example`, set `POSTGRES_PASSWORD` and the admin variables, and `docker compose up -d`. That brings up nginx as the single entry point on port 8080, the Node MCP server and admin REST API, a background worker, PostgreSQL 16 with pgvector, pgBouncer, Redis and MinIO. The app container deliberately does not publish port 8000 to the host — all traffic goes through nginx. Clients connect over streamable-http at `http://<host>:8080/mcp`, or through the OpenAPI bridge at `/openapi.json`, where each tool is a POST endpoint under `/tools/`. Data is loaded from the Admin Console, which is off until you set `ADMIN_ENABLED=true` with a username, a password hash and a session secret. Every tool is read-only except `crud_fhir_server`, which can write only to servers an administrator registered, only if that server's allow-list permits it, and only when the caller passes `confirm_write=true`. Both interfaces ship without enforced authentication — put a reverse proxy or a token in front before exposing them. Licensed MIT.
One command — docker compose up -d
