ViromeChat MCP server
ViromeChat MCP サーバー
データセットへのアクセス、外部 API 呼び出し、ビジネスロジックのすべてを担う FastMCP サーバーです。Viromech@t のために動作します。クライアント(別リポジトリ viromechat 内の FastAPI バックエンド / React フロントエンド)は、データフレーム、S3 認証情報、カラム名に直接触れることは一切ありません。MCP / HTTP 経由で、このサーバーが現在公開しているツールやリソースを読み取るという形で、汎用的に通信するだけです。
このリポジトリは、そのサーバーを単体で管理する場所です。アプリのリポジトリには依存しません。両者の間の唯一の契約は、以下に文書化された MCP ツール/リソース一式であり、バックエンドは MCP_SERVER_URL 環境変数を介してこれを利用します。
実行方法
前提条件: 分類学データセット(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として保持します。下記の 2 つの MCP リソースを支える、2 つのカラム説明ファイル(
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"] でディスパッチする必要があります。ツール名やカラムの知識をハードコードしてはいけません。これが 2 つのリポジトリの分離を保っています。既存のアーティファクトタイプを再利用するツールをここに追加しても、クライアント側の変更は不要です。
リソース
リソースは静的で一度だけ読み込まれる知識であり、ツールのように LLM が「呼び出す」ものではありません。クライアントは会話ごとにリソースを一度読み取り、その内容をシステムプロンプトに組み込みます。
URI | 内容 | ソース |
| JSON マップ |
|
|
|
|
新しいリソース(例: 3 つ目のデータセット)を追加しても、クライアント側の変更は不要です。クライアントは 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 の先頭にある 2 つのヘルパー _ok(content, artifacts) / _fail(content) がこの形を構築します。手書きの dict ではなく、常にこれらを使ってください。
アーティファクトタイプ
| 生成元 | 形状 | クライアント側での利用用途 |
|
|
| くSivesources」パネル内の Wikipedia リンク |
|
|
| PubMed リンク + 幻覚ガード用の PMID ホワイトリスト |
|
|
| for "Sources" リンクパネルのNCBI Taxonomy リンク |
|
|
| "Sources" で実行済み SQL/コードとして追跡。 |
|
|
| 描画された Plotly チャート |
クライアントはツール名ではなく、artifact["type"] だけでディスパッチします。既存のアーティファクトタイプを再利用するツール(例: 別の "table" を返すツール)を追加しても、クライアント側の変更は一切不要です。
ツール
wikipedia_search(search_term: str, wikipedia_limit: int = 4000) -> dict
Wikipedia 上のページを検索します。タイトルが完全一致しない場合は、最も近い全文検索結果にフォールバックし、それはコンテンツ内に「fuzzy match」ノートとして記されます。url アーティファクトを返します。
pubmed_search(query: str, max_results: int = 5) -> dict
PubMed(NCBI E-utilities の esearch + efetch、db=pubmed)を検索し、各ヒットの title、authors、journal、year、abstract、DOI、PMID を返します。実際に見つかったすべての PMID を含む pubmed アーティファクトを返します。これは、クライアントの PMID 幻覚防止の唯一の情報源です。
ncbi_taxonomy_search(name: str) -> dict
あらゆる生物名、すなわち略称・通用名・学名を、NCBI Taxonomy データベース(E-utilities、db=taxonomy)に対して解決します。一致する各項目について、学名、ランク(species / genus / family / …)、division、完全な系統、既知の別名・省略形を返します。これは、Wikipedia の表現に頼らずに、HIV を Human immunodeficiency Virus 1 や属 Lentivirus に変換したり、名前が属なのか, Family な のを確認したりするための、信頼できる方法です。最上位一致に対応する ncbi_taxonomy アーティファクトを返します。
実装上の注記: NCBI の
efetchXML は、各結果の<LineageEx>内に、それぞれの祖先ランクごとに 1 つの<Taxon>をネストします。パーサーはroot.findall("Taxon")(直接の子のみ)を走査します。.//Taxonを使うと、すべての祖先も別の一致として拾われるためです。
query_host_sql(sql: str, preview_rows: int = 50) -> dict
host ビュー(S3 Parquet データセット)に対して読み取り専用の 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には重いgeometryブロブを含む約 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 / go があります。Plotly figure を fig に代入する必要があります。空の figure(データポイント 0)は、黙って空のチャートを返すのではなく、ガイダンスメッセージとともに拒否されます。plotly アーティファクトを返します。
create_map(code: str) -> dict
create_visualization と同じですが、px.scatter_mapbox(...) を強制し(scatter_map は不可)、直前の query_host_sql 呼び出しが既に geometry から lon / lat を抽出していることを要求します。plotly アーティファクトを返します。
必須のサンプル識別子: 生成された figure は、primary_id(BioSample アクセッション番号)が hover_data に現れない限り拒否されます。プロットされるすべての点は、正確なサンプルまで遡れる必要があります。これは単に docstring に書かれているだけでなく、コード上でも(_check_hover_has_column(fig, "primary_id"))強制されます。これを含まない map は、確実に失敗する _fail(...) になります。
サーバーの拡張
新しいツールを追加するには:
@mcp.toolで装飾された普通の関数として書き、_ok(content, artifacts)または_fail(content)を返します — 決して手書きの dict ではありません。クライアントが特別に描画すべきもの(リンク、テーブル、figure)を生成する場合、形が合うときは既存のアーティファクト
typeを再利用します。これはクライアントの変更ゼロを意味します。形が本当に新しい場合のみ、新しいtypeを発明します(そしてクライアントのディスパッチループに接続します)。すべての使用ルール、注意点、例をツールの docstring に書いてください。それがそのままツールの説明として LLM に送信されます。データセット固有のガイダンスはここにだけ置くべきです。
ツールに UI 設定可能なデフォルト(
preview_rowsやwikipedia_limitのような)が必要な場合は、そのパラメータをそのまま名付けてください。クライアントは、JSON スキーマがその名前のパラメータを宣言している任意のツールに対して、対応するエキスパート設定を適用します。
設定
server_mcp.py は、インポート時に mcp_config.py の load_env_file() を介して .env(.env.example を参照します)を読み取ります。
変数 | 必須 | デフォルト | 意味 |
| はい | — | S3 互換エンドポイントのホスト名 |
| はい | — | S3 アクセスキー |
| はい | — | S3 シークレットキー |
| はい | — | S3 バケット名 |
| はい |
| バケット内の Parquet データセットのキー |
| いいえ |
| S3 リージョン |
| いいえ |
| DuckDB の |
| いいえ |
| 分類学データセットのローカルパス |
非秘密の設定は 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