Skip to main content
Glama
Romumrn

ViromeChat MCP server

by Romumrn

ViromeChat MCP-Server

Ein FastMCP-Server, der den gesamten Datensatzzugriff, externe API-Aufrufe und die Geschäftslogik für Viromech@t besitzt. Der Client (das FastAPI-Backend / React-Frontend, im separaten viromechat-Repository) fasst niemals ein DataFrame, eine S3-Zugangsberechtigung oder einen Spaltennamen direkt an – er spricht nur generisch über MCP/HTTP mit diesem Server, indem er die Tools und Ressourcen liest, die dieser gerade veröffentlicht.

Dieses Repository ist das eigenständige Zuhause dieses Servers. Es hat keine Abhängigkeit vom App-Repository; der einzige Vertrag zwischen ihnen ist die Reihe von unten dokumentierten MCP-Tools/Ressourcen, die das Backend über seine Umgebungsvariable MCP_SERVER_URL konsumiert.


Ausführung

Voraussetzungen: Der Taxonomie-Datensatz (data/TAXONOMY.csv, ~327 MB) wird über Git LFS gespeichert. Führen Sie git lfs install einmal pro Rechner aus, bevor Sie klonen, oder git lfs pull nach dem Klonen, um ihn zu materialisieren.

Lokal (Python)

git lfs pull                      # fetch data/TAXONOMY.csv
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env              # fill in your S3 credentials
python server_mcp.py

Docker

cp .env.example .env              # fill in your S3 credentials
docker compose up --build

In jedem Fall startet es einen HTTP-Server auf 0.0.0.0:8000, mit MCP-Endpunkt auf /mcp (http://localhost:8000/mcp – genau darauf zeigt das Backend mit MCP_SERVER_URL). Beim Start:

  1. Lädt data/TAXONOMY.csv vollständig in den Arbeitsspeicher als df_taxo.

  2. Lädt die beiden Spaltenbeschreibungsdateien (data/v@_columns_description.csv und data/TAXONOMY_columns_description.json), die die beiden unten folgenden MCP-Ressourcen untermauern.

  3. Öffnet eine In-Memory-DuckDB-Verbindung, installiert die httpfs- und spatial-Erweiterungen und registriert eine host-Ansicht über den S3-Parquet-Datensatz – die Parquet-Datei wird nie in den Speicher geladen; jeder query_host_sql-Aufruf wird von DuckDB nach S3 geschoben (Spalten-/Zeilengruppen-Pruning).

Tests

pip install pytest
pytest

Die Hilfstests testen die reinen Funktionen (_ok/_fail, Figure-/Tabellen-Builder, SQL-Guards) und benötigen keine echte S3-Verbindung.


Related MCP server: OpenCode LLM Wiki MCP Server

Einbinden eines Clients

Jeder MCP-Client kann diesen Server nutzen. Das Backend von Viromech@t macht es mit einem fastmcp.Client:

from fastmcp import Client

async with Client("http://localhost:8000/mcp") as mcp:
    tools = await mcp.list_tools()
    result = await mcp.call_tool("wikipedia_search", {"search_term": "Lentivirus"})

Der Client soll Tools und Ressourcen dynamisch entdecken (list_tools() / list_resources()) und anhand von artifact["type"] weiterleiten – niemals Tool-Namen oder Spaltenwissen hartkodieren. Genau das hält die beiden Repositories entkoppelt: Ein hier hinzugefügtes Werkzeug, das eine bestehende Artefaktart wiederverwendet, benötigt keine Client-Änderung.


Ressourcen

Ressourcen sind statisches, einmal gelesenes Wissen – nicht etwas, das das LLM wie ein Werkzeug „aufruft“. Der Client liest sie einmal pro Unterhaltung und bindet ihren Inhalt in den Systemprompt ein.

URI

Inhalt

Quelle

resource://datasets/host/schema

JSON-Zuordnung {column_name: {description, Type}} für jede Spalte der host-Tabelle

data/v@_columns_description.csv

resource://datasets/taxonomy/schema

Volles JSON-Schema (Name, Beschreibung, Spalten, Primärschlüssel, Zeilendefinition) von df_taxo

data/TAXONOMY_columns_description.json

Eine neue Ressource (z. B. einen dritten Datensatz) hinzuzufügen erfordert keine clientseitige Änderung: Der Client findet Ressourcen über list_resources() und liest jede einzelne generisch.


Der Antwort-Kontrakt

Jedes Tool gibt genau diese Form zurück, ungeachtet dessen, was es tut:

{
  "success": true,           // or false
  "content": "human-readable text — this is what the LLM reads back as the tool result",
  "artifacts": [ ... ]        // structured extras the client can render; [] if none
}

Im Fehlerfall enthält content die Fehlermeldung (wo möglich mit Wiederholungshinweisen) und artifacts ist leer. Die beiden Helfer _ok(content, artifacts) und _fail(content) am Anfang von server_mcp.py bauen diese Form auf – verwenden Sie immer diese, statt ein Dict von Hand zu bauen.

Artefakt-Typen

type

Erzeugt von

Form

Vom Client verwendet als

url

wikipedia_search

{"type": "url", "url": "..."}

Wikipedia-Link im Bereich „Sources"

pubmed

pubmed_search

{"type": "pubmed", "pmids": [123, 456]}

PubMed-Links + PMID-Whitelist für den Halluzinationsschutz

ncbi_taxonomy

ncbi_taxonomy_search

{"type": "ncbi_taxonomy", "url": "...", "tax_id": "..."}

NCBI-Taxonomy-Link im Bereich „Sources"

table

query_host_sql, query_dataframe

{"type": "table", "rows": [...], "columns": [...], "total_rows": N}

Wird als ausgeführtes SQL/Code in „Sources" protokolliert; rows ist auf preview_rows begrenzt

plotly

create_visualization, create_map

{"type": "plotly", "figure": {...}} (aus fig.to_json(), zurück in ein Dict)

Gerendertes Plotly-Diagramm

Der Client leitet rein über artifact["type"] weiter – niemals über den Werkzeugnamen. Ein Werkzeug, das einen bestehenden Artefakt-Typ wiederverwendet (z. B. ein weiteres Werkzeug, das "table" zurückgibt), erfordert keine Client-Änderung überhaupt.


Werkzeuge

wikipedia_search(search_term: str, wikipedia_limit: int = 4000) -> dict

Sucht eine Seite auf Wikipedia; falls es keinen exakten Titel gibt, nutzt sie den nächsten Volltextsuchtreffer (im Inhalt als Hinweis „fuzzy match" gekennzeichnet). Gibt ein url-Artefakt zurück.

pubmed_search(query: str, max_results: int = 5) -> dict

Durchsucht PubMed (NCBI-E-utilities esearch + efetch, db=pubmed) und gibt für jeden Treffer Titel, Autoren, Zeitschrift, Jahr, Abstract, DOI und PMID zurück. Gibt ein pubmed-Artefakt mit jeder echten PMID zurück, die. das ist die alleinige Quelle für den PMID-Halluzinationsschutz des Clients.

ncbi_taxonomy_search(name: str) -> dict

Löst einen beliebigen Organismennamen – Akronym, Trivialname oder wissenschaftlich Name – gegen die NCBI-Taxonomie-Datenbank auf (E-utilities, db=taxonomie). Für jeden Treffer werden ausgegeben: wissenschaftlicher Name, Rang (Spezies/Gattung/Familie/…), Abteilung, vollständige Abstammungslinie und bekannte Synonyme/Akronyme. Das ist die maßgebliche Methode, um HIV in Human immunodeficiency virus 1 / Gattung Lentil zu verwandeln oder um zu prüfen, ob ein Name eine Gattung oder eine Familie ist, ohne auf Wikipedia-Sprachübung angewiesen zu sein. Liefert für den besten Treffer ein ncbi_taxonomy-Artefakt.

Implementierungshinweis: Das efetch-XML von NCBI verschachtelt ein <Taxon> pro Vorfahrsebene in <LineageEx> jedes Ergebnisses. Der Parser iteriert nur über direkt untergeordnete root.findall("Taxon") – mit .//Taxon würde auch jeder Vorfahr als eigener Treffer mitgenommen.

query_host_sql(sql: str, preview_rows: int = 50) -> dict

Führt ein schreibgeschütztes SELECT gegen die host-Ansicht aus (den S3-Parquet-Datensatz) und gibt ein table-Artefakt zurück. Das ist der erforderliche, erste Schritt, bevor query_dataframe, create_visualization oder create_map df_host verwenden können – diese Werkzeuge arbeiten auf dem Ergebnis des letzten query_host_sql-Aufrufs (ctx.last_host_result), nie auf dem vollständigen Datensatz.

Vor der Ausführung gelten folgende Schutzvorgaben:

  • Es ist nur eine einzige SELECT-Anweisung erlaubt – INSERT/UPDATE/DELETE/DDL/PRAGMA/... werden durch _FORBIDDEN_SQL_KEYWORDS abgelehnt.

  • Ein nacktes SELECT * wird abgelehnt. host hat ungefähr 65 Spalten einschließlich eines großen geometry-Blobs; jede Spalte nur noch übereinstimmende Zeilen über S3 zu laden verursachte früher Multi-Minuten-Timeoute, bevor dieser Schutz existierte. Aufrufer müssen ausschließlich die Spalten projiziem, die sie benötigen.

  • Koordinaten leben in einer nativen GEOMETRY-Punktspalte und nicht in einfachen lat/lon; extrahieren Sie sie mit ST_X(geometry) AS lon, ST_Y(geometry) AS lat (die spatial-Erweiterung wird beim Start geladen).

query_dataframe(code: str, preview_rows: int = 50) -> dict

Führt Pandas-Code aus, mit df_taxo, df_host (= ctx.last_host_result oder eine klare Fehlermeldung, falls query_host_sql noch nicht aufgerufen wurde), pd und np im Scope. Sie müssen result ein DataFrame zuweisen. Gibt ein table-Artefakt zurück.

create_visualization(code: str) -> dict

Gleiche Ausführungsumgebung wie query_dataframe, zusätzlich px/go. Sie müssen eine Plotly-Figur der Variablen fig zuweisen. Leert Figuren (0 Datenpunkte) werden abgelehnt, mit einer Hinweismeldung, statt ein leeres Diagramm schwenkt zurückzugeben. Gibt ein plotly-Artefakt zurück.

create_map(code: str) -> dict

Wie create_visualization, erzwingt aber px.scatter_mapbox(...) (kein scatter_map) und dass der vorherige query_host_sql-Aufruf lon/lat aus geometry extrahiert hat. Gibt ein plotly-Artefakt zurück.

Pflicht-Identifikator für Stichproben : Die erzeugte Figur wird abgelehnt, wenn primary_id (die BioSample-Accession) nicht in hover_data auftaucht – jeder aufgetragene Punkt muss zu seiner exakten Probe rückverfolgbar sein. Das wird im Code erzwungen (_check_hover_has_column(fig, "primary_id")), nicht nur in der Doku erfragt – eine Karte mit fehlendem Kennzeichen ist ein harter _fail(...).


Erweiterung des Servers

Um ein neues Werkzeug hinzuzufügen:

  1. Schreiben Sie es als einfache, mit @mcp.tool dekorierte Funktion, die _ok(content, artifacts) oder _fail(content) zurückgibt – niemals ein handgebautes Dict.

  2. Wenn etwas entsteht, das der Client speziell rendern soll (ein Link, eine Tabelle, eine Figur), verwenden sie eine vorhandene Artefakt-type aus vorher Tabelle, wenn die Form passt – das bedeutet keine Client-Änderungen. Nur wenn die Form wirklich neu ist, erfinden Sie eine neuen type (und binden Sie ihn in die Dispatch-Schleife des Clients ein).

  3. Setzen Sie alle Nutzungsregeln, Hinweise und Beispiele in den Docstring des Werkzeugs. Er wird unverändert als Beschreibung des Werkzeugs an das LLM gesendet – das ist der einzige Ort, an dem datenspezifische-Webs leben.

  4. Wenn das Werkzeug einen UI-konfigurierbaren Standard benötigt (wie preview_rows oder wikipedia_limit), benennen Sie den Parameter genau so; der Client wendet die entsprechenden Experteneinstellung auf dieses Tool an, dessen JSON-Schema einen Parameter mit diesem Namen deklariert.


Konfiguration

server_mcp.py liest beim Import .env (siehe .env.example) über load_env_file() aus mcp_config.py:

Variable

Erforderlich

Standardwert

Bedeutung

ENDPOINT

ja

Hostname des S3-komprimierenden Endpunkts

ACCESS_KEY

ja

S3-Zugriffsschlüssel

SECRET_KEY

ja

S3-Geheimschlüssel

BUCKET

ja

S3-Bucket-Name

VIRAL_HOST_DATASET

ja

*.parquet

Objekt-Schlüssel des Parquet-Datensatzes im Bucket

REGION

nein

fr

S3-Region

S3_URL_STYLE

nein

path

DuckDB-Einstellung s3_url_style

TAXO_DB_PATH

nein

data/TAXONOMY.csv

Lokaler Pfad zur Taxonomy-CSV

Geheimzuhinterlegte Einstellungen stehen in mcp_config.py.

F
license - not found
Not graded
quality - not tested
C
maintenance

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Free public MCP for AI agents — 193 tools, 44 workflows. No API key.

  • Real-time Amazon, WIPO & PACER data for AI agents — 19 tools via the MCP protocol.

  • OCR, transcription, file extraction, and image generation for AI agents via MCP.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Romumrn/viromeatlas_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server