Skip to main content
Glama
baller-coder

mcp-federated-data

mcp-federated-data

联邦式 MCP 服务器,将关系型元数据 (MySQL) 与时序值 (InfluxDB) 结合在一个对 LLM 友好的单一实体层之后。

License: MIT Version Node MCP

语言: English · 中文


问题所在

当 LLM 需要回答如下问题时:

“显示 A 区活跃传感器过去 7 天的温度趋势”

它必须遍历两个存储

  • 关系型元数据(传感器有哪些、位置、类型、单位)— MySQL

  • 时序值(随时间变化的读数)— InfluxDB

插入两个独立的 MCP 服务器会迫使 LLM 执行以下操作:

  1. 查询 MySQL → 查找匹配的实体 → 提取它们的 ID

  2. 将这些 ID 放入 InfluxDB 查询中

  3. 在自己的上下文中拼接两个结果集

LLM 在第 3 步很容易出错——尤其是当连接键是复合键时(例如,InfluxDB 标签是两个关系字段的拼接)。

此服务器将所有三个步骤合并为一次工具调用


LLM 的视角

五个工具,提示词中没有 SQL 或 Flux:

工具

用途

list_entities

按字段过滤业务实体

get_entity

通过主键查找单个实体

list_related

遍历实体之间配置好的关系

get_entity_timeseries

联邦式 — 一次调用获取元数据 + 时序数据

compare_timeseries

在同一时间窗口内比较 2–20 个特定实体

每个工具都附带丰富的 JSON-Schema 描述,因此 LLM 无需提示技巧即可选择正确的参数。


它与简单的双服务器设置有何不同

场景

两个独立的 MCP 服务器

mcp-federated-data

“A 区传感器的趋势”

LLM:查询 MySQL → 提取 ID → 推入 Flux → 在脑中连接

一次 get_entity_timeseries 调用

复合标签如 {deviceId}.{signalId}

LLM 在提示词中组合字符串 — 容易出错

YAML 中配置 composer: "{deviceId}.{signalId}",由服务器处理

元数据 ↔ 时序对齐

LLM 进行连接,经常配对错误

服务器按配置的键进行连接

数据量激增

无保护

强制最大实体数 + 自动降采样 + 每个实体的点数上限

LLM 的业务语义

仅原始 CREATE TABLE

带有 description 的 YAML 字段

审计追踪

结构化的单次调用审计日志


快速入门

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_bucket

2. 实体

每个实体绑定到一个关系表或视图,具有可选的关系和可选的时序绑定。

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_id

3. 默认值(护栏)

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}"

服务器执行以下操作:

  1. 从 MySQL 拉取元数据(composer 的本地字段会自动包含在 SELECT 中)。

  2. 使用模板组合每一行的标签值。

  3. 将组合后的列表推送到 InfluxDB 标签过滤器中。

  4. 通过相同的模板将结果连接回来。

单字段绑定(v0.1 形式)继续正常工作——服务器将它们视为单元素复合体,因此所有路径保持统一。


工作原理 — 50 行核心代码

每个联邦工具都遵循相同的三个步骤:

  1. 获取元数据 — 针对业务存储进行关系查询,具有安全标识符检查和参数化 WHERE。允许的过滤字段仅限于实体配置中声明的字段。

  2. 获取时序数据 — 从第 1 步拉取连接键值,将它们推送到针对时序存储的标签过滤器中,并带有可选的聚合和单次调用点数上限。

  3. 合并 — 按远程标签值对时序点进行分组,然后将每个元数据行与其排序后的序列拼接起来。

没有 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 必须在次要版本内保持向后兼容性。


致谢


许可证

MIT

A
license - permissive license
-
quality - not tested
C
maintenance

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