Skip to main content
Glama
Romumrn

ViromeChat MCP server

by Romumrn

Я(?)——等等,这是翻译任务。我只需输出译文。开始。

ViromeChat MCP 服务器(ViromeChat MCP 服务器)

一个 FastMCP 服务器,负责并拥有 Viromech@t所有数据集访问、外部 API 调用和业务逻辑。客户端(位于独立 viromechat 仓库中的 FastAPI 后端 / React 前端)从不直接接触 dataframe、S3 凭据或列名——它只通过 MCP/HTTP 与该服务器进行泛化交流,即读取它当前发布的任何工具和资源。

本仓库是该服务器的独立所在。它不依赖 app 仓库;两者之间的唯一契约是下文记录的那组 MCP 工具/资源,由后端通过其 MCP_SERVER_URL 环境变量来消费。


运行方式

前置要求: taxonomy 数据集(data/TAXONOMY.csv,约 327 MB)通过 Git LFS 存储。克隆前在每台机器上运行一次 git lfs install,或者克隆后运行 git lfs pull,以将其物化。

本地(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

无论哪种方式,它都会在 0.0.0.0:8000 上启动一个 HTTP 服务器,MCP 端点为 /mcphttp://localhost:8000/mcp —— 这是后端 MCP_SERVER_URL 指向的地址)。启动时它:

  1. data/TAXONOMY.csv 完整加载进内存,作为 df_taxo

  2. 加载构建下面两个 MCP 资源所需的两个列描述文件(data/v@_columns_description.csvdata/TAXONOMY_columns_description.json)。

  3. 打开一个进程内 DuckDB 连接,安装 httpfsspatial 扩展,并在 S3 Parquet 数据集之上注册一个 host 视图 — Parquet 文件从不加载进内存;每一次 query_host_sql 调用都由 DuckDB 下推到 S3(列剪枝 / 行组剪枝)。

测试

pip install pytest
pytest

辅助测试会覆盖纯函数(_ok/_fail、图表/表格构建器、SQL 防护),并且不需要真实的 S3 连接。


Related MCP server: OpenCode LLM Wiki MCP Server

集成客户端

任何 MCP 客户端的都可以消费这个服务器。Viromech@t 后端通过 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"})

客户端应该动态地发现工具和资源(list_tools() / list_resources()),并分配对 artifact["type"] 进行分发——绝不硬编码工具名称或列知识。这正是两个仓库保持解耦的原因:在这里新增一个复用现有 artifact 类型的工具,不需要客户端做任何改动。


资源

资源是静态的、读取一次的知识 — 不是像工具那样被 LLM “调用”的东西。客户端的每个对话读取一次,并将其内容并入系统提示。

URI

内容

来源

resource://datasets/host/schema

host 表的每一列的 JSON 映射 {column_name: {description, Type}}

data/v@_columns_description.csv

resource://datasets/taxonomy/schema

df_taxo 的完整 JSON 模式(名称、描述、列、方主键、行定义)

data/TAXONOMY_columns_description.json

再加一个新资源(例如第三个数据集)不要求任何客户端改动:客户端通过 list_resources() 发现资源,并统一地读取每一个资源。


响应契约

每个工具都返回这个形状,无论它做什么:

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

失败时,content 持有错误消息(尽可能附重试指引),artifacts 为空。server_mcp.py 顶部的两个辅助函数 _ok(content, artifacts) / _fail(content) 用于构建这个形状—请始终使用它们,而不是手动构造一个 dict。

Artifact 类型

type

由以下产生

结构

客户端消费为

url

wikipedia_search

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

“Sources” 面板中的 Wikipedia 链接

pubmed

pubmed_search

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

PubMed 链接 + 供给发生幻觉防护的 PMID 白名单

ncbi_taxonomy

ncbi_taxonomy_search

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

“Sources” 面板中的 NCBI Taxonomy 链接

table

query_host_sql, query_dataframe

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

在 “Sources” 中作为已执行 SQL/代码追踪;rowspreview_rows 为上限

plotly

create_visualization, create_map

{"type": "plotly", "figure": {...}}(来自 fig.to_json(),已被解析回 dict)

渲染出的 plotly 图表

客户端完全根据 artifact["type"] 分发——绝不做任何标识对工具的名称。添加一个复用现有 artifact 类型的工具(例如另一个返回 "table" 的工具)不需要客户端做任何改动。


工具集合

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

在 Wikipedia 上查找某个页面;如果没有完全匹配的标题,就回退到最接近的全文搜索匹配(内容中标为“模糊匹配”提示)。返回一个 url artifact。

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

在 PubMed(NCBI E-utilities esearch + efetch,db=pubmed)中搜索,并返回每条命中的标题、作者、期刊、年份、摘要、DOI 和 PMID。返回一个包含所有真实 PMID 的 pubmed artifact——这是客并端 PMID 幻觉防护的权威唯一来源。

ncbi_taxonomy_search(name: str) -> dict

把任意生物物种名称——缩写、常用名或学名——解析到 NCBI Taxonomy 数据库(E-utilities,db=taxonomy)。返回每个匹配结果:学名、分类层级(species/genus/family/……)、门(division)、完整谱系学及已行知同义/缩写。这就是把 HIV 变成 Human immunodeficiency virus 1 / 属 Lentivirus,或者检查某个名称究竟是一个属还是一个科,而不依赖 Wikipedia 措辞的权威途径。对最佳匹配返回一个 ncbi_taxonomy artifact。

实现说明:NCBI 的 efetch XML 在每个结果的 <LineageEx> 内为每个祖先级别嵌套一个 <Taxon>。解析器只遍历 root.findall(" entirely, that(直接子元素就好了)—— 如果使用.//Taxon` 会把每个祖先循环都当作是另一个独立匹配项。

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

针对 host 视图执行一个只读的 SELECT 语句(S3 Parquet 数据集),返回一个 table artifact。这必要的第一步必须先执行,然后 query_dataframecreate_visualizationcreate_map 才能使用 df_host —— 这些工具操作的是最近的**一次 query_host_sql 调用的结果(ctx.last_host_result),而不是整个数据集。

执行前后强制执行以下保护网:

  • 只能一条 SELECT 语句——INSERT/UPDATE/DELETE/DDL/PRAGMA/... 会被 _FORBIDDEN_SQL_KEYWORDS 拒绝。

  • 单点 SELECT * 会被直接拒绝。 host 约有 65 列,其中包含一个较重的 geometry blob;在该防护存在之前,从 S3 拉取每个匹配行的全部列正导致了多分钟超时。调用者必须只投影他们需要的列。

  • 坐标位于本地的 GEOMETRY 点列中,而不是普通字段普通 lat/lon —— 请用 ST_X(geometry) AS lon, ST_Y(geometry) AS lat 提取它们(spatial 扩展在启动时已加载)。

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

执行 pandas 代码,作用域中包含 df_taxo原型末 frame(不可用,等于 ctx.last_host_client,如果尚未调用 query_host_sql 则返回明确错误)、pdnp。必须将 DataFrame 指派给 result。返回一个 table artifact。

create_visualization(code: str) -> dict

query_dataframe 相同的执行环境不同点在于多了 px/go。必须把 Figure 赋值给 fig。空图(0 个数据点)会带指引信息地被拒绝,而不是静默返回一张空图表发出一个 plotly artifact。

create_map(code: str) -> dict

create_visualization 相同,但强制只能使用 px.scatter_mapbox(...)(不可用 scatter_map),并强制之前的 query_host_sql 调用已从 geometry 提取出 longitude/latitude。返回一个 plotly artifact。

必需样本标识符:除非 primary_id(BioSample 登录号)出现在 hover_data 中,否则图形会被拒绝——每个绘制点必须能够追溯到具体的样本。这一条在代码中强制实现(_check_hover_has_column(fig, "primary_id")),不只是写在 docstring 中——缺少该列的 map 会无可争辩地 _fail(...)


扩展服务器

要添加一个新工具,请按照以下步骤:

  1. 把它写成普通函数,用 @mcp.tool 装饰,返回 _ok(content, artifacts)_fail(content)——不要手写 dict。

  2. 如果它得出可供客户端特殊渲染的输出(链接、表格、图形),就要复用上表中已有的 artifact 类型,只要其结构相符即可——这可以使客户端改动为零。如果结构确实是新出现,才发明新 type(并把接入到客户端的在分布循环中)。

  3. 把每条使用规则、注意事项和示例写在 docstring 中。工具的描述会原样发给 LLM——这是唯一应该存储该数据集特有指引的地方。

  4. 如果某工具需要一个可配置的 UI 默认值(如 preview_rowswikipedia_limit),就一直给参数命名;客户端会将匹配的专家设置作用到 JSON schema 中声明了同名参数的任意工具。


配置

server_mcp.py 在 import 时通过 mcp_config.pyload_env_file() 读取 .env(另有 .env.example):

变量

必需

默认值

含义

ENDPOINT

S3 兼容性 endpoint 主机名

ACCESS_KEY

S3 访问密钥

SECRET_KEY

S3 私密密钥

BUCKET

S3 存储桶名称

VIRAL_HOST_DATASET

*.parquet

Bucket 中 Parquet 数据的对象键

REGION

fr

S3 区域

S3_URL_STYLE

path

DuckDB s3_url_style 设置

TAXO_DB_PATH

data/TAXONOMY.csv

taxonomy CSV 的本地路径

非敏感设置位于 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