mcp-federated-data
mcp-federated-data
联邦式 MCP 服务器,将关系型元数据 (MySQL) 与时序值 (InfluxDB) 结合在一个对 LLM 友好的单一实体层之后。
问题所在
当 LLM 需要回答如下问题时:
“显示 A 区活跃传感器过去 7 天的温度趋势”
它必须遍历两个存储:
关系型元数据(传感器有哪些、位置、类型、单位)— MySQL
时序值(随时间变化的读数)— InfluxDB
插入两个独立的 MCP 服务器会迫使 LLM 执行以下操作:
查询 MySQL → 查找匹配的实体 → 提取它们的 ID
将这些 ID 放入 InfluxDB 查询中
在自己的上下文中拼接两个结果集
LLM 在第 3 步很容易出错——尤其是当连接键是复合键时(例如,InfluxDB 标签是两个关系字段的拼接)。
此服务器将所有三个步骤合并为一次工具调用。
LLM 的视角
五个工具,提示词中没有 SQL 或 Flux:
工具 | 用途 |
| 按字段过滤业务实体 |
| 通过主键查找单个实体 |
| 遍历实体之间配置好的关系 |
| 联邦式 — 一次调用获取元数据 + 时序数据 |
| 在同一时间窗口内比较 2–20 个特定实体 |
每个工具都附带丰富的 JSON-Schema 描述,因此 LLM 无需提示技巧即可选择正确的参数。
它与简单的双服务器设置有何不同
场景 | 两个独立的 MCP 服务器 |
|
“A 区传感器的趋势” | LLM:查询 MySQL → 提取 ID → 推入 Flux → 在脑中连接 | 一次 |
复合标签如 | 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 文件中。分为三个部分。
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 标签值是多个关系字段的复合体时(在物联网/工业系统中很常见,例如标签 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 拉取元数据(composer 的本地字段会自动包含在
SELECT中)。使用模板组合每一行的标签值。
将组合后的列表推送到 InfluxDB 标签过滤器中。
通过相同的模板将结果连接回来。
单字段绑定(v0.1 形式)继续正常工作——服务器将它们视为单元素复合体,因此所有路径保持统一。
工作原理 — 50 行核心代码
每个联邦工具都遵循相同的三个步骤:
获取元数据 — 针对业务存储进行关系查询,具有安全标识符检查和参数化
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 是模式驱动的,而非特定于领域的。它适用于任何业务元数据存在于关系存储中,而观测值存在于时序存储中的场景:
物联网设备遥测
工业过程监控
资产性能管理
楼宇自动化
能源/电力监控
环境传感器网络
网络设备监控
如果您的技术栈是 MySQL + InfluxDB 并且您希望 LLM 对其进行推理 — 此服务器非常适合您。
与相关项目的比较
mcp-federated-data | mcp-server-mysql | mcp-server-influxdb | Wren AI / Vanna | |
跨存储连接 | ✅ | ❌ | ❌ | 部分 (自有引擎) |
复合标签组合器 | ✅ | 不适用 | ❌ | ❌ |
LLM 安全的 SQL 护栏 | ✅ | 不一 | 不适用 | ✅ |
作为语义层的模式 | ✅ | ❌ | ❌ | ✅ |
配置 | YAML | 环境变量/参数 | 环境变量/参数 | 专用 DSL |
范围 | 小而精 | 轻量封装 | 轻量封装 | 完整 BI 平台 |
贡献
欢迎提交 Issue 和 PR。在提交之前:
对于新的数据源适配器 — 请先提交 Issue,以便我们对接口达成一致。
对于新工具 — 请匹配现有的 JSON-Schema + 审计日志模式。
公共 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