Use the time-series MCP server#

The optional Model Context Protocol (MCP) server exposes wind-turbine analytics to MCP clients. It uses Python/FastMCP and Streamable HTTP through the existing HTTPS gateway. Grafana and the sensor ingestion paths remain unchanged.

Prerequisites#

  • Complete the Get Started prerequisites.

  • Use Python 3.12 or later for the example client.

  • Set the existing database and Grafana credentials.

  • Set HOST_IP to the gateway’s IPv4 address.

  • Use an analytics image with /config, /udfs/package, and the native Kapacitor task API.

The server uses Kapacitor directly for task status and stop operations. It does not require the newer microservice /pipeline_status or /stop_pipeline endpoints.

Deploy#

Caution: Deployment targets stop the existing stack and remove its volumes. Use them only on a deployment that you intend to replace.

  1. Set MCP credentials in the same shell:

    Set MCP_USERNAME and MCP_PASSWORD in .env:

    MCP_USERNAME=mcpuser
    MCP_PASSWORD=<your-password>
    

    The username must contain only alphabets and be at least 5 characters long. The password must be at least 10 alphanumeric characters with at least one letter and one digit. make check_env_variables MCP=true validates both values. Never commit credentials.

  2. Build the server:

    make build
    

    The MCP image is built locally; a published MCP image is not required. Runtime package versions are pinned in mcp-server/requirements.txt, but transitive dependencies are not hash-locked. DOCKER_REGISTRY and TIME_SERIES_MCP_IMAGE control its registry and repository. Its default tag is 2026.1.0.

  3. Select one ingestion path:

    make up_mqtt_ingestion MCP=true
    # Or:
    make up_opcua_ingestion MCP=true
    

    Analytics waits for start_pipeline; these commands do not upload or activate the UDF. Without MCP=true, both commands retain automatic analytics startup.

  4. For batch processing, append batch during deployment:

    make up_mqtt_ingestion batch MCP=true
    

    The server selects the batch UDF and creates its model alias inside the upload archive. It does not modify application assets. Batch results use a 20-minute window.

num_of_streams and INCLUDE=validation retain their existing behavior. System metrics remain available in Grafana when collected; this MCP version does not expose host metrics.

Trust the gateway certificate#

All MCP requests require Basic authentication over verified HTTPS, including initialization and discovery. There is no insecure client option.

The local gateway creates a self-signed certificate with localhost and HOST_IP subject alternative names. Obtain this certificate through a trusted local connection:

docker compose -f docker-compose.yml -f docker-compose-mcp.yml \
  exec -T nginx cat /opt/nginx/certs/cert.pem > ./mcp-gateway-ca.pem
export MCP_CA_FILE="$PWD/mcp-gateway-ca.pem"
export MCP_URL="https://127.0.0.1:3000/mcp"

Replace the address and port with the configured HOST_IP and GRAFANA_PORT. Store the certificate outside version control. The gateway regenerates its certificate on restart; obtain the new certificate after a restart. For production, provision an organization-trusted certificate and key instead of the local certificate-generation step.

Use the example client#

From the component root:

python3 -m venv mcp-server/example/.venv
mcp-server/example/.venv/bin/pip install -r mcp-server/requirements.txt
mcp-server/example/.venv/bin/python mcp-server/example/example_client.py describe
mcp-server/example/.venv/bin/python mcp-server/example/example_client.py get_pipeline_status
mcp-server/example/.venv/bin/python mcp-server/example/example_client.py start_pipeline \
  --arguments '{"time_series_inf_device":"CPU"}'
mcp-server/example/.venv/bin/python mcp-server/example/example_client.py list_insights_data \
  --arguments '{"severity":"anomaly","page":1,"page_size":20}'
mcp-server/example/.venv/bin/python mcp-server/example/example_client.py get_anomaly_summary
mcp-server/example/.venv/bin/python mcp-server/example/example_client.py get_processing_metrics
mcp-server/example/.venv/bin/python mcp-server/example/example_client.py list_sources
mcp-server/example/.venv/bin/python mcp-server/example/example_client.py stop_pipeline

GPU is also supported by start_pipeline when the analytics container has suitable hardware. The MCP container itself does not require a GPU. Device changes retain the active alert configuration. The server rejects control requests when a different UDF task is configured.

Caution: stop_pipeline disables analytics only. Sensor ingestion and containers continue running. Streaming input received while analytics is disabled is not replayed automatically. One-shot simulators can exhaust their input before analytics starts; use continuous ingestion for interactive demonstrations.

Tool data contract#

Tool

Result

describe

Tools, schemas, processing mode, classification codes, and operational guidance

get_pipeline_status

Daemon health and selected task state, including not_configured

start_pipeline

Verified enabled state, selected device, and change indicator

stop_pipeline

Verified disabled state or an explicit unconfigured state

list_sources

Paginated source identifiers observed in the requested time window

list_insights_data

Paginated points, classification, analysis flag, and timing values in seconds

get_anomaly_summary

Processed, analysed, unanalysed, anomalous, and per-severity counts

get_processing_metrics

Counts, window-average rates, mean latencies, and last-observed timestamps

Data tools accept start_time and end_time as timezone-aware timestamps. The default window covers the preceding 30 minutes; the maximum window is 24 hours. The start is inclusive and the end is exclusive. Use an explicit, fixed window while paging through results. List tools accept page and page_size, with at most 100 entries per page. They return has_more and next_page, not an expensive unrestricted total count. Point, summary, and metrics tools support an exact source filter. Source identifiers support up to 128 letters, digits, underscores, dots, colons, and hyphens. list_insights_data supports all, anomaly, normal, low, medium, and high severity filters.

Classification codes are 0, 0.3, 0.6, and 1.0; they are not confidence scores. The analysis flag distinguishes unanalysed points from analysed points. Anomaly percentage uses analysed points as its denominator. Missing timing values and percentages without analysed points are null, not zero. Rates divide retained point counts by the requested window duration in minutes. They differ from Grafana’s fixed three-minute rolling queries. Counts cannot include expired data; the stack defaults to one-hour retention.

The server does not expose arbitrary InfluxQL, uploads from clients, shell commands, vision, fusion, or LLM explanations. Database and analytics errors are explicit, sanitized tool failures. Partial startup failures identify the completed deployment stages. The existing database user has broad privileges; provision a separate read-only database identity for MCP when deployment policy requires it.

Validate and stop#

make status MCP=true
make down MCP=true

Use MCP=true consistently for deployment, status, and shutdown. The server port is internal; only nginx exposes /mcp. Its internal /health endpoint provides liveness and does not require credentials. Browser origins must match the configured HTTPS gateway origin.

For tests, see the MCP testing instructions.