ViromeChat MCP server
ViromeChat MCP server
Viromech@t를 위해 모든 데이터셋 액세스, 외부 API 호출, 비즈니스 로직을 담당하는 FastMCP 서버입니다. 클라이언트(별도 viromechat 저장소에 있는 FastAPI 백엔드 / React 프런트)는 데이터프레임, S3 자격 증명, 또는 컬럼 이름을 직접 건드리지 않습니다. 그 대신 MCP/HTTP를 통해 이 서버와만 통신하며, 현재 서버가 게시하는 도구와 리소스를 읽어서 제네릭하게 동작합니다.
이 저장소는 그 서버가 독립적으로 존재하는 저장소입니다. 앱 저장소에 대한 어떤 의존성도 없습니다. 둘 사이의 유일한 계약은 아래에 문서화된 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.pyDocker
cp .env.example .env # fill in your S3 credentials
docker compose up --build어느 쪽이든 0.0.0.0:8000에 HTTP 서버가 뜨고, MCP 엔드포인트는 /mcp(http://localhost:8000/mcp — 백엔드가 MCP_SERVER_URL로 지정하는 주소)입니다. 시작 시:
data/TAXONOMY.csv를df_taxo로 메모리에 완전히 로드합니다.아래 두 MCP 리소스를 뒷받침하는 두 컬럼 설명 파일(
data/v@_columns_description.csv와data/TAXONOMY_columns_description.json)을 로드합니다.인메모리 DuckDB 연결을 열고
httpfs와spatial확장을 설치한 다음, S3 Parquet 데이터셋 위에host뷰를 등록합니다 — Parquet 파일은 절대 메모리에 로드되지 않습니다. 모든query_host_sql호출은 DuckDB가 S3로 푸시다운합니다(컬럼/행그룹 프루닝).
테스트
pip install pytest
pytest헬퍼 테스트는 순수 함수(_ok/_fail, figure/table 빌더, 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"]에 따라 dispatch해야 합니다 — 도구 이름이나 컬럼 지식을 절대 하드코딩하면 안 됩니다. 덕분에 두 저장소가 분리됩니다: 기존 artifact 타입을 재사용하는 도구를 여기에 추가해도 클라이언트 변경은 필요 없습니다.
리소스
펼리는 대상 등 정적이고 한 번 읽는 지식입니다 — 도구처럼 LLM이 "호출"하는 것이 아닙니다. 클라이언트는 대화당 한 번 읽어 그 내용을 시스템 프롬프트에 포함합니다.
URI | 콘텐츠 | 소스 |
|
|
|
|
|
|
새 리소스(예: 세 번째 데이터셋)를 추가해도 클라이언트 측 변경은 필요 없습니다. 클라이언트는 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를 수기 생성하지 마세요.
아티팩트 타입
| 생성 도구 | 형태 | 클라이언트가 사용하는 방식 |
|
|
| "Sources" 패널의 Wikipedia 링크 |
|
|
| PubMed 링크 + PMID 안티셉션 가드용 PMID 화이트리스트 |
|
|
| "Sources" 패널의 NCBI Taxonomy 링크 |
|
|
| "Sources"에서 실행된 SQL/코드로 추적됨; |
|
|
| 렌더링된 Plotly 차트 |
클라이언트는 artifact["type"] 만으로 완전히 dispatch합니다 — 도구 이름이 아니라. 기존 artifact 타입을 재사용하는 도구(예: 또 다른 "table" 반환 도구)를 추가해도 클라이언트 변경이 전혀 없어집니다.
도구
wikipedia_search(search_term: str, wikipedia_limit: int = 4000) -> dict
Wikipedia에서 페이지를 찾습니다. 정확한 제목 일치가 없으면 가장 근접한 전문(full-text) 검색 결과로 대체합니다(콘텐츠에 "퍼지 매치" 노트로 표시됨). url 아티팩트를 반환합니다.
pubmed_search(query: str, max_results: int = 5) -> dict
PubMed(NCBI E-utilities의 esearch + efetch, db=pubmed)를 검색하여 각 결과에 대해 제목, 저자, 저널, 연도, 초록, DOI, PMID를 반환합니다. 실제 확인된 모든 PMID를 담은 pubmed 아티팩트를 반환하며, 이는 클라이언트의 PMID 환각조사에 유일한 판단 기준이 됩니다.
ncbi_taxonomy_search(name: str) -> dict
어떤생물학적 이름(약어, 일반명, 학명)이든 NCBI Taxonomy 데이터베이스(E-utilities, db=taxonomy)에 대비해 식별합니다. 모든 일치 항목에 대해 계명, 순위(species/genus/family/...), division(분류군), 전체 lineage(계통), 알려진 동의어/약어를 반환합니다. HIV를 Human 개복면역결핍바이러스 1 / 속 Lentivirus로 바꾸거나, 어떤 이름이 속인지 과인지 확인하는 정식 방법입니다. Wikipedia의 표현에 좌우되지 않습니다. 가장 높은 일치 항목에 대해 ncbi_taxonomy 아티팩트를 반환합니다.
구현 사항: NCBI의
efetchXML은 각 결과의<LineageEx>내부에 상위 계급(rank)마다 하나씩<Taxon>을 중첩시킵니다. 파서는root.findall("Taxon")(직접 자손만)만 반복합니다 —.//Taxon을 쓰면 모든 조상도 별도 일치 결과로 잡히므로 주의하세요.
query_host_sql(sql: str, preview_rows: int = 50) -> dict
S3 Parquet 데이터셋인 host 뷰에 대해 읽기 전용 SELECT를 실행하고 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에는 큰geometryblob을 포함한 ~65개의 열이 있습니다. 모든 행의 모든 열을 S3에서 가져오는 것은 이 안전장치가 도입되기 전에는 수분에 달하는 타임아웃을 일으키는 원인이었습니다. 호출자는 필요한 열만 지정해야 합니다.
좌표는 단순
lat/lon이 아니라 기본GEOMETRY포인트 열에 있습니다.ST_X(geometry) AS lon, ST_Y(geometry) AS lat로 추출해 사용하세요(spatial확장은 시작할때 로드됩니다).
query_dataframe(code: str, preview_rows: int = 50) -> dict
df_taxo, df_host(= ctx.last_host_result, 아직 query_host_sql이 호출되지 않았다면 명확한 오류), pd, np가 유효 범위에 있는 상태로 pandas 코드를 실행합니다. 반드시 result 변수에 DataFrame을 할당해야 합니다. table 아티팩트를 반환합니다.
create_visualization(code: str) -> dict
query_dataframe과 동일한 실행 환경에 px/grp가 추가됩니다. 반드시 fig 변수에 Plotly figure를 할당해야 합니다. 빈 figure(0개의 점)는 안내 메시지와 함께 거부하고, 빈 차트를 조용히 반환하지 않습니다. plotly 아티팩트를 반환합니다.
create_map(code: str) -> dict
create_visualization과 같지만 px.scatter_mapbox(...)을 강제합니다(scatter_map는 아님). 그리고 그 앞 query_host_sql 호출이 이미 geometry에서 lon/lat을 추출해 놓은 상태여야 합니다. plotly 아티팩트를 반환합니다.
필수 샘플 식별자: hover_data에 primary_id(BioSample accession)가 나타나지 않으면 결과 figure는 거부됩니다. 그려진 모든 점은 정확한 샘플까지 거슬러 갈 수 있어야 합니다. 이것은 docstring에 요청한 사항일 뿐 아니라 코드에서도 강제됩니다 (_check_hover_has_column(fig, "primary_id")). 이 식별자가 없는 지도는 무조건 _fail(...)입니다.
서버 확장
새 도구를 추가하려면:
@mcp.tool데코레이션된 순수 함수로 작성하고, 수제 dict가 아니라_ok(content, artifacts)또는_fail(content)을 반환합니다.클라이언트가 특별히 렌더링해야 할 것을 만들어낸다면(링크, 표, figure) 기존 artifact
type중에 해당 형태를 지원하는 것을 재사용하세요. 그러면 클라이언트 변경이 전혀 필요 없습니다. 정말 새로운 형태일 때만 새type을 만들고 그에 맞게 클라이언트 디스패치 루프도 수정해야 합니다.모든 사용 규칙, 주의사항, 예제는 도구의 docstring에 넣어라. 이 docstring은 그대로 LLM에게 도구의 설명으로 전달됩니다. 데이터셋별 안내가 들어갈 유일한 곳이 바로 여기입니다.
도구가 UI로 설정 가능한 기본값(예:
preview_row또는wikipedia_limit)이 필요하면 해당 매개변수를 그 이름으로 지정하세요. 클라이언트는 그 이름이 JSON 파라미터에 선언된 어떤 도구든 그에 맞는 전문가 설정을 적용할 수 있으므로.
환경설정
server_mcp.py는 import 시 mcp_config.py의 load_env_file()를 통해 .env( .env.example 참고)를 읽습니다:
Variable | 필수 | 기본값 | 의미 |
| 예 | — | S3 호환 엔드포인트 호스트 |
| 예 | — | S3 액세스 키 |
| 예 | — | S3 시크릿 키 |
| 예 | — | S3 버킷 이름 |
| 예 |
| 버킷 안에 있는 Parquet 데이터셋의 객체 키 |
| 아니 |
| S3 지역 |
| 아니 |
| DuckDB의 |
| 아니 |
| taxonomy CSV의 로컬 경로 |
비보안 설정은 mcp_config.py에 있습니다.
This server cannot be installed
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
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to discover and execute tools via a secure MCP server with JWT authentication, RBAC, rate limiting, and audit logging.1MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to interact with a persistent knowledge graph backend using MCP tools for reading, searching, and analyzing wiki pages with vector search and graph algorithms.4
- 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 gradedqualityBmaintenanceEnables AI agents to access a unified catalog of tools from various APIs (OpenAPI, GraphQL, MCP, Google Discovery) through the MCP protocol.MIT
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.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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