Skip to main content
Glama
Romumrn

ViromeChat MCP server

by Romumrn

ViromeChat MCP server

Un servidor FastMCP que posee todo el acceso a los datasets, las llamadas a APIs externas y la lógica de negocio de Viromech@t. El cliente (el backend FastAPI / el frontend React, en el repositorio separado viromechat) nunca toca directamente un dataframe, una credencial de S3 o un nombre de columna; solo se comunica con este servidor por MCP/HTTP, de forma genérica, leyendo las herramientas y los recursos que este publique en cada momento.

Este repositorio es el hogar independiente de ese servidor. No tiene ninguna dependencia del repositorio de la app; el único contrato entre ambos es el conjunto de herramientas/recursos MCP documentado a continuación, que el backend consume mediante su variable de entorno MCP_SERVER_URL.


Ejecutarlo

Requisitos previos: el dataset de taxonomía (data/TAXONOMY.csv, ~327 MB) se almacena mediante Git LFS. Ejecuta git lfs install una vez por máquina antes de clonar, o git lfs pull después de clonar, para materializarlo.

Local (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

En cualquier caso se inicia un servidor HTTP en 0.0.0.0:8000, con endpoint MCP en /mcp (http://localhost:8000/mcp; aquí es a donde el backend apunta con MCP_SERVER_URL). Al arrancar:

  1. Carga data/TAXONOMY.csv completamente en memoria como df_taxo.

  2. Carga los dos archivos de descripción de columnas (data/v@_columns_description.csv y data/TAXONOMY_columns_description.json) que respaldan los dos recursos MCP siguientes.

  3. Abre una conexión DuckDB en memoria, instala las extensiones httpfs y spatial, y registra una vista host sobre el dataset Parquet en S3 — el archivo Parquet nunca se carga en memoria; cada llamada a query_host_sql se traslada a S3 con DuckDB (poda de columnas/grupos de filas).

Pruebas

pip install pytest
pytest

Las pruebas auxiliares ejercitan las funciones puras (_ok/_fail, constructores de figuras/tablas, guardas de SQL) y no necesitan una conexión real a S3.


Related MCP server: OpenCode LLM Wiki MCP Server

Integrar un cliente

Cualquier cliente MCP puede consumir este servidor. El backend de Viromech@t lo hace con un 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"})

El cliente debe descubrir las herramientas y los recursos dinámicamente (list_tools() / list_resources()) y despachar según artifact["type"]nunca fijar nombres de herramientas ni conocimiento de columnas. Eso es lo que mantiene desacoplados los dos repositorios: añadir aquí una herramienta que reutilice un tipo de artefacto existente no requiere ningún cambio en el cliente.


Recursos

Los recursos son conocimiento estático, de lectura única — no algo que el LLM “llame” como una herramienta. El cliente los lee una vez por conversación y mezcla su contenido en el prompt de sistema.

URI

Contenido

Fuente

resource://datasets/host/schema

Mapa JSON {column_name: {description, Type}} de cada columna de la tabla host

data/v@_columns_description.csv

resource://datasets/taxonomy/schema

Esquema JSON completo (nombre, descripción, columnas, clave primaria, definición de fila) de df_taxo

data/TAXONOMY_columns_description.json

Añadir un recurso nuevo (por ejemplo, un tercer dataset) no requiere ningún cambio del cliente: el cliente lo descubre mediante list_resources() y lo lee de forma genérica.


El contrato de respuesta

Cada herramienta devuelve exactamente esta forma, independientemente de lo que haga:

{
  "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
}

En caso de error, content contiene el mensaje de error (con orientación de retry) a cuando sea posible y artifacts estará vacío. Las dos funciones auxiliares _ok(content, artifacts) / _fail(content) al inicio de server_mcp.py construyen esta forma; úselas siempre en lugar de crear un dict manualmente.

Tipos de artefacto

type

Emitido por

Forma

Consumido por el cliente como

url

wikipedia_search

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

Enlace a página de Wikipedia en el panel “Sources”

pubmed

pubmed_search

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

Enlaces de PubMed + lista blanca de PMIDs para el guard contra alucinaciones

ncbi_taxonomy

ncbi_taxonomy_search

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

Enlace a NCBI Taxonomy en el panel “Sources”

table

query_host_sql, query_dataframe

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

Se registró si el SQL/código se ejecutó en bitácora; rows se limita a preview_rows

plotly

create_visualization, create_map

{"type": "plotly", "figure": {...}} (el resultado de fig.to_json(), convertido de vuelta en dict)

También se muestra en “Rendered plot” graph

El cliente despacha solo según artifact["type"], nunca según el nombre de la herramienta. Añadir una herramienta que reutilice un tipo de artefacto existente (p. ej., otra que devuelva "table") no requiere ningún cambio en el cliente.


Herramientas

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

Busca una página en Wikipedia; si no hay coincidencia exacta de título, recurre a la coincidencia más cercana en renderedización de texto completo (con comprobación de “coincidencia difusa”). Devuelve un artefacto url.

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

Busca en PubMed (NCBI E-utilities ESearch + efetch, db=pubmed) y devuelve para cada hallazgo título, autores, revista, año, abstract, DOI y PMID. Devuelve un artefacto pubmed con todos los PMID reales encontrados (fuente única de verdad para el módulo de guard contra alucinaciones del cliente).

ncbi_taxonomy_search(name: str) -> dict

Resolver, para cualquier nombre de organismo: acrónimo, nombre común o científico, contra base de datos NCBI Taxonomy (E-utilities, db=taxonomy). Cada coincidencia devuelve nombre científico, rango (especie/género/familia…), división y nombre rot y su clean lineage. Este es la manera correcta de convertir p.e. HIV en Human immunodeficiency virus 1 y su género Lentivirus, o, en el caso de comprobar (por ejemplo) si un nombre es de un género o de familia, y todo independiente de la definición de Wikipedia. ncbi_taxonomy artifact esqueleto.

Clave de implementación: el XML de efetch de NCBI anida un <Taxon> por cada rango antepasado dentro del <LineageEx> del resultado. El parser solo itera root.findall("Taxon") (hijos directos); utilizar .//Taxon nos traería también cada antepasado como si fuera matcheado por separado.

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

Ejecuta una consulta SELECT de solo input contra la vista history (porción Parquet en S3) y devuelve un artefacto table. Es el primer paso obligatorio antes de usar query_dataframe, create_map, create_map (que funcionan con el resultado de la última llamada a query_host_sql (last_host_context), no desde el dataset completo).

Guard debe:

  • Solo una statement SELECTINSERT/UPDATE/DELETE/DDL/PRAGMA/... quedan rechazadas por _FORBIDDEN_SQL_KEYWORDS.

  • SELECT * NO se acepta. host tiene ~65 columnas y un blob geometry pesado; leer todas las columnas de cada fila desde S3 es lo que provocaba timeouts de varios minutos antes de este guard. Quien pregunta debe especificar office solo de las columnas.

  • Las coordenadas están en un punto GEOMETRY, no en camp separados lat / lon; tú que les extra consulta con ST_X(geometry) AS lon, WHERE geometry vig.

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

Ejecuta código pandas en entorno con df_taxo, df_host (igual a ctx.last_host_result, o un error si aún no hubo query_host_sql), pd/np en el contexto. Debe asignar el DataFrame a result. Devuelve artefacto table.

create_visualization(code: str) -> dict

Mismo entorno de ejecución que query_dataframe, con px/go texto. Llama obligatoriamente asignar su dibujo a fig. Si la figure tiene 0 registros se rechaza con mensaje de orientación (no se devuelva silenciosa en blanco). Returns artefacto plotly.

create_map(code: str) -> dict

Igual que create_visualization pero obliga a usar port define:

  • única manera de scatter_mapbox, nunca scatter_map.

  • lon/lat ya extraído en la precedente llamada query_host_sql.

If primary_id (BioSample based) no está en hover_data del gráfico result, los rejected en código y no en docstring (_check_hover_has_column) — mapa sin primary_id para _fail(…).


Ampliar el servidor

Para añadir una nueva herramienta:

  1. Escribirá como función normal con el decorador @mcp.tool, que devuelva _ok(content, artifacts) o `_fail(content)» (prohibido mapa sin formato).

  2. Si produce algo específico para que el cliente lo renderice (enlace, tabla, figura), use un tipo de artefacto existente del cuadro siempre que instale el tipo — así = cero cambio en el cliente. Solo hay que inventar un nuevo tipo (y rozarlo en la salida del cliente) si la estructura difiere verdaderamente.

  3. Coloque cada regla de uso, advertencia y ejemplo **en el “docstring”. Al LLM se lo envía tal cual (texto de la herramienta); es el único sitio para la guía al detalle.

  4. Este with "preview_rows"... If un valor por defect't se debe confI-config (p ej preview_rows, wikipedia_limit), use solo nombre del parámetro. El cliente con UI habilita esa config correspondiente poniendo exactamente ese nombre en el JSON schema.


Configuración

server_mcp.py en import (import) debe cargar .env (look at .env.example) mediante load_env_file() import from mcp_config.py:

Variable

Obligatoria

Por defecto

Significado

ENDPOINT

Hostname del endpoint compatible con S3

ACCESS_KEY

S3 access key

SECRET_KEY

S3 secret key

BUCKET

Nombre del bucket S3

VIRAL_HOST_DATASET

*.parquet

Clave del objeto Parquet dentro del bucket

REGION

No

fr

Región S3

S3_URL_STYLE

No

path

Ajuste s3_url_style de DuckDB

TAXO_DB_PATH

No

data/TAXONOMY.csv

Ruta local al CSV de taxonomía

La configuración no secreta está en mcp_config.py.


Esta version ha sido traducida preserving the original structure.

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