19. MCP 서버 (AI 어시스턴트 연동)
MCP(Model Context Protocol) 서버는 Claude 같은 AI 어시스턴트가 플랫폼의 현장 데이터를 자연어로 묻고 진단하게 하는 통로입니다. 어시스턴트가 태그 값을 읽고, 알람 맥락을 모으고, 자산 계층을 훑고, 확인 처리(ack)까지 합니다.
REST API 를 대신하는 것이 아닙니다 — 같은 V5 서비스 계층을 같은 JVM 안에서 부르고, 인증 · 감사 · 요율 제한도 /api/v5/* 의 것을 그대로 씁니다.
| 항목 | 값 |
|---|---|
| 엔드포인트 | POST https://<서버>/api/v5/mcp |
| 전송 | Streamable HTTP, stateless — 세션을 만들지 않아 재시작에 안전합니다 |
| 스펙 | MCP 2025-11-25 안정판 |
| 제공 | 도구 32종 · 리소스 7종 · 프롬프트 3종 · 자동완성 · 진행률 · Elicitation |
붙이는 법
1단계 — api_key 발급
MCP 는 별도 인증 체계를 두지 않고 V5 API 키를 그대로 씁니다. 관리자가 발급한 api_token 으로 교환합니다.
curl -s -X POST "https://<서버>/api/v5/auth" \
-H "Content-Type: application/json; charset=UTF-8" \
-d '{"token":"<api_token>"}'
# 200: { "data": { "api_key": "..." }, "meta": { "status": "OK" }, "errors": null }
meta.status 가 OK 이면서 data.api_key 가 비어 있지 않아야 성공입니다. 그리고 503 은
자격증명이 틀렸다는 뜻이 아닙니다 — 토큰 저장소에 닿지 못해 판정 자체가 없는 상태입니다.
응답별로 어디를 고칠지는 시작하기 §1.8 에 표로 있습니다.
MCP 는 읽기 호출까지 전부 POST 로 실어 보냅니다. V5 필터는 POST·PUT·DELETE·PATCH 를 ADMIN/API 역할에만 허용하므로, 토큰의 역할이 USER 면 읽기 도구조차 403 으로 거부됩니다. 읽기 전용으로 쓸 계획이어도 토큰 자체는 ADMIN/API 로 발급하십시오.
2단계 — 클라이언트에 등록
# Claude Code
claude mcp add --transport http plantpulse "https://<서버>/api/v5/mcp" \
--header "X-API-Key: <api_key>"
// Claude Desktop — .mcp.json
{
"mcpServers": {
"plantpulse": {
"type": "http",
"url": "https://<서버>/api/v5/mcp",
"headers": { "X-API-Key": "<api_key>" }
}
}
}
X-API-Key 대신 Authorization: Bearer <api_key> 도 됩니다. 인증에 실패하면 401 과 함께 WWW-Authenticate: Bearer 헤더가 옵니다.
DNS 리바인딩을 막기 위해 Origin 헤더를 화이트리스트로 검사합니다. Claude Desktop · Claude Code 처럼 Origin 을 보내지 않는 네이티브 클라이언트는 항상 허용되지만, 브라우저 기반 클라이언트는 AI_MCP_ALLOWED_ORIGINS 에 등록해야 합니다. 기본값이 비어 있어 등록 전에는 전부 403 입니다.
도구 32종
읽기 31종 + 쓰기 1종(acknowledge_alarm) 입니다. 삭제 · 제어 · 설정 변경 도구는 설계 차원에서 없습니다.
| 도구 | 하는 일 | 필수 인자 |
|---|---|---|
search_entities | 이름 · ID · 설명으로 도메인 객체 찾기(이름 → ID). ID 가 없을 때 먼저 부릅니다 | query |
list_latest_tag_values | 태그 현재값 | tag_ids |
get_tag_history | 태그 기간 이력 | tag_id, from |
get_asset_snapshot | 설비 전 태그 스냅샷 | asset_id |
list_alarms | 알람 목록 | — |
acknowledge_alarm | 알람 확인 — 사유(comment) 필수, 감사에 남습니다 | alarm_seq, comment |
get_alarm_context | 알람 원인 진단 묶음 | alarm_seq |
list_alarm_suppressions | 숨긴 알람(숨김 · 억제 · 서비스 제외) | — |
get_alarm_performance | 알람 시스템 성능 — GET /alarm/performance 와 같은 값 | scope_type, scope_id |
get_edge_status | 엣지 게이트웨이 하나의 상태 | edge_id |
list_edge_status | 엣지 게이트웨이 목록 | — |
get_edge_connection_history | 엣지 건강 이력(일별 구간) | edge_id, date |
list_opc_connections | OPC 수집 연결 목록 | — |
get_asset_tree | 설비 계층 트리 | asset_id |
get_asset_by_external | MES · EAM 번호로 계층 노드 찾기 | external_system, external_id |
get_site_overview | 사이트 온톨로지 개요 | site_id |
trace_asset_relations | 관계 추적 — 상류 · 하류 영향 | entity_id |
query_knowledge_graph | 온톨로지 SPARQL 질의 | sparql |
list_asset_documents | 설비 첨부 문서 | asset_id |
get_asset_timeline | 설비 사건 타임라인 | asset_id |
list_work_orders | 워크오더 목록 | — |
get_work_order_kpi | 워크오더 상세 + KPI | order_id |
get_work_order_by_external | MES · ERP 번호로 워크오더 찾기 | external_system, external_id |
get_asset_kpi | 설비 기간 KPI 요약(상태 · 알람 · OEE) | asset_id, from |
get_asset_schedule | 설비 · 사이트 달력(교대 · 정지 · 휴일) | asset_id |
list_maintenance_orders | 정비 오더(호출 · 수리 · 부품 · ISO 코드) | scope_id |
get_maintenance_summary | 정비 요약(부위 · 고장 모드 · 대기/수리 · 반복) | scope_id |
get_maintenance_order_by_external | CMMS 번호로 정비 오더 찾기 | external_system, external_id |
get_connection_health | 설비 계층 건강 롤업 | — |
get_current_time | 서버 현재 시각 | — |
get_eql_reference | 콘솔 입력칸의 EQL 참조(문법 · 이벤트 종류 · 함수 · 예시) | surface |
validate_eql | EQL 컴파일 검사(배포하지 않음) | surface, eql |
정비 행의 키는 V5 정비 오더와 같습니다 — maintenance_order_id(문자) · maintenance_kind_code · status_code · failure_record_seq · maintenance_plan_id(문자) · failure_mode_code · maintainable_item_code 입니다. maintenance_order_id 는 MAINTENANCE_ORDER_000001 또는 옛 행의 숫자 문자열("12")이므로 숫자로 다루지 마세요.
ERROR · WARN · INFO 입니다get_connection_health 화면 라벨에 보이는 critical/major/minor 는 표시용 버킷입니다. list_alarms(severity=) 필터에는 정준값을 써야 걸립니다.
리소스 7종
어시스턴트가 도구를 부르기 전에 「무엇이 있는지」를 훑는 읽기 전용 통로입니다.
pp://sites · pp://ontology/{site_id} · pp://assets/{site_id}/tree · pp://uns/{site_id} · pp://catalog/{store}/tables · pp://catalog/{store}/{table}/schema · pp://domain-graph
{store} 는 metastore · eventstore · analytics 만 허용합니다.
프롬프트 3종
| 이름 | 절차 |
|---|---|
diagnose-asset | 자산 장애 진단 — 알람 → 맥락 → 태그 이력 → 연결 → 하류 영향 → 원인 후보 |
shift-briefing | 교대 브리핑 — 건강 → 알람 → 오더/KPI → 인계 요약 |
alarm-triage | 알람 분류 — 목록 → 우선순위 → 권고 → (승인 시) 확인 처리 |
설정 — pp.mm_config 의 AI_MCP_*
정본은 PostgreSQL pp.mm_config 표입니다. plantpulse-ai.properties 는 삭제됐고 읽는 경로도 없어졌습니다 — 프로퍼티 레퍼런스를 보십시오.
| 키 | 기본값 | 뜻 |
|---|---|---|
AI_MCP_ENABLED | true | false 면 /api/v5/mcp 가 404 를 냅니다 |
AI_MCP_ALLOWED_ORIGINS | (빈 값) | 브라우저 클라이언트 Origin 화이트리스트(콤마 구분) |
AI_MCP_TREE_MAX_NODES | 2000 | 트리 응답 노드 상한 |
AI_MCP_TREE_DEFAULT_DEPTH | 2 | get_asset_tree 기본 깊이 |
AI_MCP_TREE_MAX_NODE_TAGS | 100 | 노드 하나에 실을 태그 수 |
AI_MCP_TREE_ONTOLOGY_MAX_CHARS | 200000 | 온톨로지 응답 문자 수 상한 |
AI_MCP_TREE_ONTOLOGY_DEFAULT_DEPTH | 3 | trace_asset_relations 기본 깊이 |
AI_MCP_TREE_ONTOLOGY_MAX_TAGS | 500 | 온톨로지 응답 전체의 태그 행 예산 |
값을 바꾸는 길은 하나입니다 — 설정 화면(/config/index)이나 pp.mm_config 를 고치는 것. MCP 는 매 요청 캐시를 읽으므로 재기동이 필요 없습니다.
PP_AI_MCP_* 환경변수는 아무 일도 하지 않습니다첫 부팅이든 아니든 마찬가지입니다. 환경변수를 표로 옮기던 시더와 ${PP_AI_*} 치환 층이
2026-09-18 에 없어졌습니다. 주어도 오류 없이 조용히 무시됩니다 — 「설정해 뒀는데 왜 안 되지」가
제일 잡기 어려운 고장이라 적어 둡니다. 행이 없는 키는 위 표의 기본값으로 읽힙니다.
감사와 안전장치
- 인증 · 요율 제한 · 감사는
/api/v5/*필터 체인을 그대로 탑니다. acknowledge_alarm은 자체 감사를 남깁니다(행위자MCP). 사유가 빠지면 어시스턴트에게 되물어 보완하게 하고, 그 기능이 없는 클라이언트에는 「사유 필수」로 알려 줍니다.- 일반 변경 감사 훅에서는 제외됩니다. 읽기까지 전부
POST라 훅을 걸면 매 호출이 변경으로 잘못 기록되기 때문입니다. - 토큰 전달 경로가 없습니다 — 같은 JVM 서비스 계층을 직접 부르므로 받은 자격증명을 다른 시스템으로 넘기는 길 자체가 없습니다.
함께 보기
시작하기 · 엔드포인트 전체 목록 · Asset 서비스