mcp-federated-data
mcp-federated-data
관계형 메타데이터(MySQL)와 시계열 값(InfluxDB)을 단일 LLM 친화적 엔티티 계층 뒤에서 결합하는 연합 MCP 서버입니다.
문제점
LLM이 다음과 같은 질문에 답해야 할 때:
"A 구역에서 활성화된 센서의 지난 7일간 온도 추이를 보여줘"
LLM은 두 개의 저장소를 탐색해야 합니다:
관계형 메타데이터 (어떤 센서가 존재하는지, 위치, 종류, 단위 등) — MySQL
시계열 값 (시간에 따른 측정값) — InfluxDB
두 개의 독립적인 MCP 서버를 연결하면 LLM은 다음과 같은 과정을 거쳐야 합니다:
MySQL 쿼리 → 일치하는 엔티티 찾기 → ID 추출
해당 ID를 InfluxDB 쿼리에 삽입
자신의 컨텍스트 내에서 두 결과 집합을 결합
LLM은 3단계에서 자주 오류를 범합니다. 특히 조인 키가 복합적인 경우(예: InfluxDB 태그가 두 개의 관계형 필드를 결합한 형태)에는 더욱 그렇습니다.
이 서버는 이 세 단계를 하나의 도구 호출로 통합합니다.
LLM이 보는 것
프롬프트에 SQL이나 Flux 없이 5개의 도구만 제공됩니다:
도구 | 목적 |
| 필드별로 비즈니스 엔티티 필터링 |
| 기본 키로 단일 엔티티 조회 |
| 엔티티 간 구성된 관계 탐색 |
| 연합 — 한 번의 호출로 메타데이터 + 시계열 데이터 조회 |
| 동일한 기간 동안 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}를 인코딩하는 IoT/산업 시스템에서 흔함) 다음과 같이 선언하세요:
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줄의 핵심 코드
모든 연합 도구는 동일한 세 단계를 따릅니다:
메타데이터 가져오기 — 비즈니스 저장소에 대한 관계형 쿼리 수행(안전한 식별자 확인 및 매개변수화된
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 | |
저장소 간 조인 | ✅ | ❌ | ❌ | 부분적 (자체 엔진) |
복합 태그 컴포저 | ✅ | 해당 없음 | ❌ | ❌ |
LLM 안전 SQL 가드 | ✅ | 다양함 | 해당 없음 | ✅ |
의미 계층으로서의 스키마 | ✅ | ❌ | ❌ | ✅ |
구성 | YAML | env / args | env / args | 전용 DSL |
범위 | 좁지만 깊음 | 얇은 래퍼 | 얇은 래퍼 | 전체 BI 플랫폼 |
기여
이슈와 PR을 환영합니다. 오픈하기 전에 다음을 확인하세요:
새로운 데이터 소스 어댑터의 경우 — 인터페이스를 맞출 수 있도록 먼저 이슈를 열어주세요.
새로운 도구의 경우 — 기존 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