19. MCP Server (AI Assistant Integration)
The MCP (Model Context Protocol) server is a gateway that allows AI assistants, such as Claude, to query and diagnose field data from the Platform using natural language. The assistant can read tag values, gather alarm contexts, browse asset hierarchies, and perform acknowledgement (ack) processing.
It is not a replacement for the REST API — it calls the same V5 service layer within the same JVM, and it uses the same authentication, auditing, and rate limiting as /api/v5/*.
| Item | Value |
|---|---|
| Endpoint | POST https://<server>/api/v5/mcp |
| Transport | Streamable HTTP, stateless — safe for restarts as it does not create sessions |
| Specification | MCP 2025-11-25 Stable |
| Provided | 32 Tools · 7 Resources · 3 Prompts · Autocomplete · Progress · Elicitation |
How to Connect
Step 1 — Issuing api_key
MCP does not have a separate authentication system and uses the V5 API key as is. Exchange it for the api_token issued by the administrator.
curl -s -X POST "https://<server>/api/v5/auth" \
-H "Content-Type: application/json; charset=UTF-8" \
-d '{"token":"<api_token>"}'
# 200: { "data": { "api_key": "..." }, "meta": { "status": "OK" }, "errors": null }
Success is achieved only when meta.status is OK and data.api_key is not empty. Additionally, 503 does not mean the credentials are incorrect — it indicates a state where no determination was made because the token store could not be reached. A table detailing what to fix for each response is available in Getting Started §1.8.
MCP sends all calls, including read calls, as POST. Since the V5 filter only allows POST·PUT·DELETE·PATCH for the ADMIN/API roles, if the token role is USER, even read tools will be rejected with a 403. Even if you plan to use it for read-only purposes, issue the token as ADMIN/API.
Step 2 — Registering with the Client
# Claude Code
claude mcp add --transport http plantpulse "https://<server>/api/v5/mcp" \
--header "X-API-Key: <api_key>"
// Claude Desktop — .mcp.json
{
"mcpServers": {
"plantpulse": {
"type": "http",
"url": "https://<server>/api/v5/mcp",
"headers": { "X-API-Key": "<api_key>" }
}
}
}
Authorization: Bearer <api_key> can be used instead of X-API-Key. If authentication fails, the WWW-Authenticate: Bearer header is returned along with 401.
To prevent DNS rebinding, the Origin header is checked against a whitelist. Native clients that do not send Origin, such as Claude Desktop or Claude Code, are always allowed, but browser-based clients must be registered in AI_MCP_ALLOWED_ORIGINS. Since the default value is empty, all such clients are 403 before registration.
32 Tools
There are 31 read tools and 1 write tool (acknowledge_alarm). Tools for deletion, control, or configuration changes do not exist by design.
| Tool | Function | Required Arguments |
|---|---|---|
search_entities | Find domain object by name, ID, or description (Name → ID). Called first when ID is missing | query |
list_latest_tag_values | Current tag value | tag_ids |
get_tag_history | Tag historical data for a period | tag_id, from |
get_asset_snapshot | Tag snapshot for all equipment | asset_id |
list_alarms | Alarm list | — |
acknowledge_alarm | Alarm acknowledgement — Reason (comment) is required and recorded in the audit trail | alarm_seq, comment |
get_alarm_context | Alarm cause diagnosis bundle | alarm_seq |
list_alarm_suppressions | Hidden alarms (Hidden · Suppressed · Out of Service) | — |
get_alarm_performance | Alarm system performance — same value as GET /alarm/performance | scope_type, scope_id |
get_edge_status | Status of a single Edge gateway | edge_id |
list_edge_status | Edge gateway list | — |
get_edge_connection_history | Edge health history (Daily interval) | edge_id, date |
list_opc_connections | OPC collection connection list | — |
get_asset_tree | Equipment hierarchy tree | asset_id |
get_asset_by_external | Find hierarchy node by MES · EAM number | external_system, external_id |
get_site_overview | Site ontology overview | site_id |
trace_asset_relations | Relationship tracking — Upstream · Downstream impact | entity_id |
query_knowledge_graph | Ontology SPARQL query | sparql |
list_asset_documents | Equipment attached documents | asset_id |
get_asset_timeline | Equipment event timeline | asset_id |
list_work_orders | Work order list | — |
get_work_order_kpi | Work order details + KPI | order_id |
get_work_order_by_external | Find work order by MES · ERP number | external_system, external_id |
get_asset_kpi | Equipment period KPI summary (Status · Alarm · OEE) | asset_id, from |
get_asset_schedule | Equipment · Site calendar (Shift · Stop · Holiday) | asset_id |
list_maintenance_orders | Maintenance order (Call · Repair · Part · ISO code) | scope_id |
get_maintenance_summary | Maintenance summary (Part · Failure mode · Waiting/Repair · Recurrence) | scope_id |
get_maintenance_order_by_external | Find maintenance order by CMMS number | external_system, external_id |
get_connection_health | Equipment hierarchy health rollup | — |
get_current_time | Current server time | — |
get_eql_reference | EQL reference for console input (Syntax · Event types · Functions · Examples) | surface |
validate_eql | EQL compilation check (Does not deploy) | surface, eql |
The keys for maintenance rows are identical to V5 Maintenance Order — maintenance_order_id (character) · maintenance_kind_code · status_code · failure_record_seq · maintenance_plan_id (character) · failure_mode_code · maintainable_item_code. Since maintenance_order_id is either MAINTENANCE_ORDER_000001 or a numeric string from an old row ("12"), do not treat it as a number.
ERROR · WARN · INFOThe critical/major/minor seen on the get_connection_health screen labels are display buckets. You must use the canonical value in the list_alarms(severity=) filter for it to be caught.
7 Resources
These are read-only channels that allow the assistant to browse «what is available» before calling a tool.
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} only allows metastore · eventstore · analytics.
3 Prompts
| Name | Procedure |
|---|---|
diagnose-asset | Asset failure diagnosis — Alarm → Context → Tag history → Connection → Downstream impact → Cause candidates |
shift-briefing | Shift briefing — Health → Alarm → Order/KPI → Handover summary |
alarm-triage | Alarm classification — List → Priority → Recommendation → (Upon approval) Acknowledgement |
Configuration — AI_MCP_* of pp.mm_config
The authoritative source is the PostgreSQL pp.mm_config table. plantpulse-ai.properties has been deleted and the read path is gone — refer to the Properties Reference.
| Key | Default Value | Meaning |
|---|---|---|
AI_MCP_ENABLED | true | If false, then /api/v5/mcp returns 404 |
AI_MCP_ALLOWED_ORIGINS | (Empty) | Browser client Origin whitelist (comma separated) |
AI_MCP_TREE_MAX_NODES | 2000 | Tree response node limit |
AI_MCP_TREE_DEFAULT_DEPTH | 2 | get_asset_tree default depth |
AI_MCP_TREE_MAX_NODE_TAGS | 100 | Number of tags per node |
AI_MCP_TREE_ONTOLOGY_MAX_CHARS | 200000 | Ontology response character limit |
AI_MCP_TREE_ONTOLOGY_DEFAULT_DEPTH | 3 | trace_asset_relations default depth |
AI_MCP_TREE_ONTOLOGY_MAX_TAGS | 500 | Total tag row budget for ontology response |
There is only one way to change the values — modifying the configuration screen (/config/index) or pp.mm_config. Since MCP reads the cache for every request, no restart is required.
PP_AI_MCP_* environment variables do nothingThis applies regardless of whether it is the first boot or not. The seeder that moved environment variables to the table and the ${PP_AI_*} substitution layer were removed on 2026-09-18. Even if provided, they are silently ignored without error — this is noted because «I configured it, so why isn't it working» is the most difficult failure to diagnose. Keys without a row are read using the default values in the table above.
Auditing and Safety
- Authentication, rate limiting, and auditing follow the same
/api/v5/*filter chain. acknowledge_alarmleaves its own audit trail (ActorMCP). If a reason is missing, the assistant is asked to supplement it; for clients without this capability, it is notified that «Reason is required».- Excluded from general change audit hooks. Since everything up to reading is
POST, applying a hook would cause every call to be incorrectly recorded as a change. - No token transmission path — because it calls the same JVM service layer directly, there is no path to pass the received credentials to another system.