ViromeChat MCP server
MCP-сервер ViromeChat
Сервер FastMCP, который владеет всем доступом к наборам данных, внешними вызовами API и бизнес-логикой для Viromech@t. Клиент (бэкенд FastAPI / React-фронтенд, в отдельном репозитории viromechat) никогда не обращается напрямую ни к dataframe, ни к учётным данным S3, ни к именам колонок — он только общается с этим сервером по MCP/HTTP, обобщённо, читая те инструменты и ресурсы, которые сервер публикует в данный момент.
Этот репозиторий — автономный дом этого сервера. У него нет зависимости от репозитория приложения; единственный контракт между ними — набор MCP-инструментов и ресурсов, описанный ниже, который бэкенд использует через переменную окружения MCP_SERVER_URL.
Запуск
Предварительные требования: набор данных таксономии (data/TAXONOMY.csv, ~327 МБ) хранится через Git LFS. Выполните git lfs install один раз на каждой машине перед клонированием или git lfs pull после клонирования, чтобы материализовать его.
Локально
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.pyDocker
cp .env.example .env # fill in your S3 credentials
docker compose up --buildВ любом случае запускается HTTP-сервер на 0.0.0.0:8000, endpoint MCP на /mcp (http://localhost:8000/mcp — именно это бэкенд указывает через MCP_SERVER_URL). При запуске он:
Полностью загружает
data/TAXONOMY.csvв память какdf_taxo.Загружает два файла описания колонок (
data/v@_columns_description.csvиdata/TAXONOMY_columns_description.json), которые лежат в основе двух ресурсов MCP, описанных ниже.Открывает in-memory-соединение DuckDB, устанавливает расширения
httpfsиspatialи регистрирует представлениеhostповерх S3-набора данных Parquet — Parquet-файл никогда не загружается в память; каждый запросquery_host_printerвыполняется DuckDB прямо в S3 (отсечение по колонкам и группам строк).
Тесты
pip install pytest
pytestВспомогательные тесты покрывают чистые функции (_ok/_fail, построители figure/таблиц, SQL-защиты) и не требуют живого подключения к S3.
Related MCP server: Alma Atlas
Подключение клиента
Любой 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_reseources()) и выполнять диспетчеризацию по artifact["type"] — никогда не захардкоживать имена инструментов или знание о колонках. Именно это держит два репозитория развязанными: добавление инструмента, который переиспользует существующий тип артефакта, не требует изменения клиента.
Ресурсы
Ресурсы — это статическое знание, которое читается один раз, а не то, что LLM «вызывает» как инструмент. Клиент читает их один раз за диалог и встраивает их содержимое в системный промпт.
URI | Содержимое | Источник |
| JSON-карта |
|
| Полная 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 пуст. Две вспомогательные функции _ok(content, artifacts) / _fail(content) в начале server_mcp.py формируют эту структуру — всегда используйте их вместо ручной сборки dict.
Типы артефактов
| Источник производит | Структура | Использование клиентом |
|
|
| Ссылка на Википедию в панели «Sources» |
|
|
| Ссылки на PubMed + белый список PMID для защиты от галлюцинаций |
|
|
| Ссылка на NCBI Taxonomy в панели «Sources» |
|
|
| Отслеживается как выполненный SQL/код в «Sources»; |
|
|
| Отрисованный график plotly |
Клиент выполняет диспетчеризацию только по artifact["type"] — никогда по имени инструмента. Добавление инструмента, который переиспользует существующий тип артефакта (например, ещё одного инструмента, возвращающего "table"), вообще не требует изменений в клиенте.
Инструменты
wikipedia_search(search_term: str, wikipedia_limit: int = 4000) -> dict
Находит страницу в Википедии; при отсутствии точного совпадения по названию возвращает ближайший результат полнотекстового поиска (в содержимом это помечено как «нечёткое совпадение»). Возвращает артефакт url.
pubmed_search(query: str, max_results: int = 5) -> dict
Выполняет поиск по PubMed (NCBI E-utilities esearch + efetch, db=pubmed) и возвращает для каждого результата название, авторов, журнал, год, аннотацию, DOI и PMID. Возвращает артефакт pubmed со всеми реально найденными PMID — это единственный источник правды для защиты клиента от галлюцинаций по PMID.
ncbi_taxonomy_search(name: str) -> dict
Сопоставляет любое название организма — аббревиатуру, бытовое называние или научное название — с базой данных NCBI Taxonomy (E-utilities, db=taxonomy). Для каждого совпадения возвращает: научное название, ранг (вид/род/семейство/…), отдел, полную родословную и известные синонимы/аббревиатуры. Это авторитетный способ превратить HIV в Human immunodeficiency virus 1 / род Lentivirus или проверить, является ли название родом или семейством, не полагаясь на формулировку Википедии. Возвращает артефакт ncbi_taxonomy для лучшего совпадения.
Примечание к реализации: XML NCBI
efetchсодержит по одному<Taxon>на каждый ранг-предок внутри элемента<LineageEx>каждого результата. Парсер перебирает толькоroot.findall("Taxon")(прямые потомки) — использование.//Taxonзахватило бы каждого предка как отдельное совпадение.
query_host_sql(sql: str, preview_rows: int = 50) -> dict
Выполняет read-only запрос SELECT к представлению host (набор S3 Parquet) и возвращает артефакт table. Это обязательный первый шаг перед тем, как query_dataframe, create_visualization или create_map смогут использовать df_host, — эти инструменты работают с результатом последнего вызова query_host_sql (ctx.last_host_result), а не с полным набором данных.
Защиты, действующие перед выполнением:
Разрешается только одна операция
SELECT—INSERT/UPDATE/DELETE/DDL/PRAGMA/...отклоняются_FORBIDDEN_SQL_KEYWORDS.Голый
SELECT *отклоняется сразу. Вhostоколо ~65 колонок, включая тяжёлое бинарное полеgeometry; выбор всех колонок для всех подходящих строк через 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, df_host (= ctx.last_host_result, либо точную ошибку, если query_host_sql ещё не вызывался), pd и np. Код должен присвоить DataFrame переменной result. Возвращает артефакт table.
create_visualization(code: str) -> dict
Та же среда выполнения, что и у query_dataframe, плюс px/go. Код должен присвоить Plotly figure переменной fig. Пустые фигуры (0 точек данных) отклоняются с подсказкой, а не молча превращаются в пустой график. Возвращает артефакт plotly.
create_map(code: str) -> dict
То же, что и create_visualization, но требует px.scatter_mapbox(...) (никогда не scatter_map) и того, что предыдущий вызов query_host_sql уже извлёк lon/lat из geometry. Возвращает артефакт plotly.
Обязательный идентификатор образца: результирующая фигура отклоняется, если в hover_data не встречается primary_id (номер BioSample) — каждая нанесённая на график точка должна прослеживаться до конкретного образца. Это проверяется в коде (_check_hover_has_column(fig, "primary_id")), а не просто упоминается в docstring — карта без него получает жёсткий _fail(...).
Расширение сервера
Чтобы добавить новый инструмент:
Напишите его как обычную функцию с декоратором
@mcp.tool, возвращающую_ok(content, artifacts)или_fail(content)— никогда не вручную собранный dict.Если инструмент создаёт нечто, что клиент должен отрисовать особым образом (ссылку, таблицу, фигуру), используйте существующий
typeартефакта из таблицы выше, когда форма подходит, — это ноль изменений в клиенте. Вводите новыйtype(и подключайте его в диспетчерский цикл клиента), только если форма действительно новая.Все правила использования, предостережения и примеры пишете в docstring инструмента. Она передаётся LLM дословно как описание инструмента — это единственное место, где должна находиться специфичная для данных информация.
Если инструменту нужна настройка по умолчанию, принимаемая в интерфейсе (как
preview_rowsилиwikipedia_limit), дайте параметру именно то имя — клиент применит подходящую экспертную настройку любому инструменту, в JSON-схеме которого заявлен параметр с таким именем.
Конфигурация
server_mcp.py читает .env (см. .env.example) при импорте через load_env_file() из mcp_config.py:
Переменную | Обязательно | По умолчанию | Описание |
| да | — | Хост S3-совместимого endpoint |
| да | — | Ключ доступа S3 |
| да | — | Секретный ключ S3 |
| да | — | Имя бакета S3 |
| да |
| Ключ объекта Parquet-набора внутри бакета |
| нет |
| Регион S3 |
| нет |
| Настройка DuckDB |
| нет |
| Локальный путь к CSV-файлу таксономии |
Несекретные параметры находятся в mcp_config.py.
This server cannot be deployed
Maintenance
Related MCP Connectors
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Let AI agents query data and act across all your business apps via MCP.
Find, vet, and run MCP tools through a secure audited gateway with prompt-injection risk scoring
The OpenRouter for tools. One MCP connection gives any AI agent 254 hosted tools, pay per call.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to discover and execute tools via a secure MCP server with JWT authentication, RBAC, rate limiting, and audit logging.1MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to query live schema, lineage, and query-context across data warehouses, dbt projects, orchestration systems, and BI tools via MCP tools.Apache 2.0
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to access a unified catalog of tools from various APIs (OpenAPI, GraphQL, MCP, Google Discovery) through the MCP protocol.20 npmMIT
- AlicenseNot gradedqualityCmaintenanceMCP server that bridges AI agents with external tools, APIs, databases, and services, enabling standardized tool execution and resource access.MIT