mcp-federated-data
mcp-federated-data
フェデレーションMCPサーバー。リレーショナルメタデータ(MySQL)と時系列値(InfluxDB)を、LLMフレンドリーな単一のエンティティレイヤーの背後で結合します。
課題
LLMが次のような質問に答える必要がある場合:
「ゾーンAのアクティブなセンサーの過去7日間の温度トレンドを表示して」
LLMは2つのストアを横断する必要があります:
リレーショナルメタデータ(どのセンサーが存在し、どこにあり、種類や単位は何か) — MySQL
時系列値(時間の経過に伴う測定値) — InfluxDB
2つの独立したMCPサーバーを接続すると、LLMは以下の手順を強いられます:
MySQLをクエリ → 一致するエンティティを検索 → IDを抽出
それらのIDをInfluxDBのクエリに投入
自身のコンテキスト内で2つの結果セットを結合する
LLMはステップ3で確実につまずきます。特に結合キーが複合的な場合(例:InfluxDBのタグが2つのリレーショナルフィールドを連結したもの)は顕著です。
このサーバーは、これら3つのステップを1回のツール呼び出しに集約します。
LLMから見えるもの
5つのツール。プロンプト内にSQLやFluxは不要です:
ツール | 目的 |
| ビジネスエンティティをフィールドでフィルタリング |
| プライマリキーで単一のエンティティを検索 |
| エンティティ間の設定されたリレーションを辿る |
| フェデレーション — メタデータと時系列データを1回の呼び出しで取得 |
| 2〜20個の特定のエンティティを同じ期間で比較 |
すべてのツールには詳細なJSONスキーマ記述が付属しているため、LLMはプロンプトの工夫なしで適切な引数を選択できます。
単純な2サーバー構成との違い
シナリオ | 2つの独立したMCPサーバー |
|
「ゾーンAのセンサーのトレンド」 | LLM: MySQLクエリ → ID抽出 → Fluxに投入 → 頭の中で結合 | 1回の |
| LLMがプロンプト内で文字列を構成 — エラーが発生しやすい | YAMLで |
メタデータ ↔ 時系列の整合性 | LLMが結合を行うため、ペアリングミスが頻発 | サーバーが設定されたキーで結合 |
データ量の爆発 | 無防備 | 最大エンティティ数制限 + 自動ダウンサンプリング + エンティティごとのポイント上限 |
LLM向けのビジネスセマンティクス | 生の |
|
監査証跡 | なし | 呼び出しごとの構造化された監査ログ |
クイックスタート
git clone https://github.com/baller-coder/mcp-federated-data.git
cd mcp-federated-data
pnpm install
# Sample environment (MySQL + InfluxDB in Docker, with seeded data)
docker compose -f examples/industrial-monitoring/docker-compose.yml up -d
pnpm seed
# Start the MCP server over stdio
pnpm dev -- --config examples/industrial-monitoring/config.yaml任意のMCPクライアント(Claude Desktop、Cursor、mcp-inspector)から接続します。
試してみる
// list active sites
{
"name": "list_entities",
"arguments": {
"entity": "site",
"filters": [{ "field": "status", "op": "eq", "value": "active" }]
}
}
// list sensors attached to site 1
{
"name": "list_related",
"arguments": {
"source_entity": "site",
"source_id": 1,
"target_entity": "sensor"
}
}
// federated query — metadata + timeseries in ONE call
{
"name": "get_entity_timeseries",
"arguments": {
"entity": "sensor",
"filters": [
{ "field": "site_id", "op": "eq", "value": 1 },
{ "field": "kind", "op": "eq", "value": "temperature" }
],
"time_range": { "start": "-7d" },
"aggregation": { "window": "1h", "fn": "mean" }
}
}
// compare 3 specific sensors over the same window
{
"name": "compare_timeseries",
"arguments": {
"entity": "sensor",
"ids": [101, 201, 301],
"time_range": { "start": "-24h" },
"aggregation": { "window": "10m", "fn": "mean" }
}
}設定
サーバーの動作全体は単一のYAMLファイルで定義されます。3つのセクションがあります。
1. データソース
datasources:
- name: business
type: mysql
host: localhost
port: 3306
database: my_db
username: readonly_user
password: secret
- name: timeseries
type: influxdb
url: http://localhost:8086
token: my-token
org: my_org
bucket: my_bucket2. エンティティ
各エンティティはリレーショナルテーブルまたはビューにバインドされ、オプションのリレーションと時系列バインディングを持つことができます。
entities:
- name: site
description: Physical monitoring location.
source:
datasource: business
table: sites
primary_key: id
fields:
- { name: id, type: number }
- { name: name, type: string, description: Display name }
- { name: region, type: string }
- { name: status, type: string, description: "active / inactive / maintenance" }
- name: sensor
description: A sensor attached to a site.
source:
datasource: business
table: sensors
primary_key: id
fields:
- { name: id, type: number }
- { name: site_id, type: number }
- { name: name, type: string }
- { name: kind, type: string, description: "temperature / humidity / voltage / ..." }
- { name: unit, type: string }
relations:
- target: site
type: many-to-one
local_key: site_id
foreign_key: id
timeseries:
datasource: timeseries
measurement: sensor_data
value_field: value
join_key:
local: id
remote_tag: sensor_id3. デフォルト(ガードレール)
defaults:
max_entities_per_query: 50
max_points_per_entity: 500
query_timeout_ms: 15000複合結合キー(v0.2のハイライト)
InfluxDBのタグ値が複数のリレーショナルフィールドの複合体である場合(IoT/産業システムで一般的。400001240.438000066 のようなタグが {deviceId}.{signalId} をエンコードしている場合など)、以下のように宣言します:
timeseries:
measurement: sensor_data
value_field: value
join_key:
local: [device_id, signal_id]
remote_tag: signal_id
composer: "{device_id}.{signal_id}"サーバーの動作:
MySQLからメタデータを取得(コンポーザーのローカルフィールドは
SELECTに自動的に含まれます)。テンプレートを使用して各行のタグ値を構成します。
構成されたリストをInfluxDBのタグフィルターに投入します。
同じテンプレートを使用して結果を結合します。
単一フィールドのバインディング(v0.1の形式)もそのまま動作します。サーバーはそれらを1要素の複合体として扱うため、すべてのパスが統一されます。
仕組み — 50行のコア
すべてのフェデレーションツールは、同じ3つのステップに従います:
メタデータの取得 — ビジネスストアに対するリレーショナルクエリ。安全な識別子チェックとパラメータ化された
WHEREを使用。許可されるフィルターフィールドは、エンティティ設定で宣言されたものに制限されます。時系列データの取得 — ステップ1から結合キー値を取得し、時系列ストアに対するタグフィルターに投入。オプションの集計と呼び出しごとのポイント上限が適用されます。
マージ — 時系列ポイントをリモートタグ値でグループ化し、各メタデータ行とソートされた系列を結合します。
SQLパーサーはありません。ストア横断のクエリプランナーもありません。意図的な設計です。
アーキテクチャ
┌──────────────────────────────────┐
│ MCP client (Claude / Cursor) │
└────────────┬─────────────────────┘
│ stdio (JSON-RPC)
▼
┌──────────────────────────────────┐
│ mcp-federated-data │
│ ┌────────────────────────────┐ │
│ │ Tools (5 tools) │ │
│ ├────────────────────────────┤ │
│ │ Entity registry │ │
│ │ Join-key normalizer │ │
│ │ Composer engine │ │
│ │ Guards (limits/timeout) │ │
│ │ Audit logger │ │
│ ├────────────────────────────┤ │
│ │ Datasource adapters │ │
│ └─────────┬────────┬─────────┘ │
└────────────┼────────┼────────────┘
▼ ▼
┌──────┐ ┌──────────┐
│MySQL │ │InfluxDB │
└──────┘ └──────────┘適用範囲
mcp-federated-data はスキーマ駆動型であり、ドメイン固有ではありません。ビジネスメタデータがリレーショナルストアにあり、観測値が時系列ストアにあるあらゆる場所で適用可能です:
IoTデバイスのテレメトリ
産業プロセスの監視
資産パフォーマンス管理
ビルオートメーション
エネルギー/電力監視
環境センサーネットワーク
ネットワークデバイス監視
スタックが MySQL + InfluxDB であり、LLMにそれらを推論させたい場合、このサーバーが最適です。
関連プロジェクトとの比較
mcp-federated-data | mcp-server-mysql | mcp-server-influxdb | Wren AI / Vanna | |
ストア横断結合 | ✅ | ❌ | ❌ | 部分的 (独自エンジン) |
複合タグコンポーザー | ✅ | n/a | ❌ | ❌ |
LLM安全なSQLガード | ✅ | 様々 | n/a | ✅ |
セマンティックレイヤーとしてのスキーマ | ✅ | ❌ | ❌ | ✅ |
設定 | YAML | 環境変数 / 引数 | 環境変数 / 引数 | 専用DSL |
スコープ | 狭いが深い | 薄いラッパー | 薄いラッパー | フルBIプラットフォーム |
コントリビューション
IssueやPRを歓迎します。作成前に以下を確認してください:
新しいデータソースアダプターの場合 — インターフェースを合わせるため、まずIssueを作成してください。
新しいツールの場合 — 既存のJSONスキーマ + 監査ログパターンに従ってください。
公開APIは、マイナーバージョン内での後方互換性を維持する必要があります。
謝辞
Model Context Protocol — このサーバーが準拠する標準
@modelcontextprotocol/sdk— TypeScriptリファレンスSDK
ライセンス
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/baller-coder/mcp-federated-data'
If you have feedback or need assistance with the MCP directory API, please join our Discord server