@s-tier-building-automation/stier-mcp-server
v1.8.1
Published
MCP server for STier Web API - Niagara 4 building automation
Maintainers
Readme
STier MCP Server
A Model Context Protocol (MCP) server that provides tools for interacting with the STier Web API on Niagara 4 building automation stations.
Features
Read Operations
- list_histories - List all available history IDs
- get_history - Query history trend data with time range and pagination
- list_alarms - List all alarm source names
- get_alarms - Query alarms with filtering
- get_point - Get control point details (by history ID for STierAPI, by path for OBIX)
- get_stats - Get station statistics and system info
- list_wiresheets - List wire sheets (component containers) in the station
- get_wiresheet - Get detailed wire sheet with components and connections
- get_component_slots - Get available slots for a component
- list_component_types - List available component types by category
- get_component_tree - Browse the component hierarchy
- search_components - Search for components by name or type
- execute_bql - Execute BQL (Baja Query Language) queries
Write Operations
- create_wiresheet - Create a new wire sheet with optional components and connections
- create_component - Add a component to an existing wire sheet
- create_connection - Create wiring connections between components
- delete_wiresheet - Delete a wire sheet or component
- delete_component - Delete a component
- set_value - Set a value on a control point
- bulk_read - Read multiple points in one call
- bulk_write - Write multiple points in one call
Multi-Station Operations
- list_stations - List all configured stations (multi-station mode)
- test_connection - Test connectivity to a station
- obix_info - Get OBIX server information
- obix_browse - Browse OBIX object hierarchy
Authentication & Connection
- Supports both Basic and Digest authentication (auto-detection)
- Automatic HTTP-to-HTTPS redirect handling
- Self-signed certificate support for development environments
Protocol Support
The server supports two protocols for connecting to Niagara stations:
- STierAPI - Custom module with extended features (recommended when available)
- OBIX - Standard Niagara protocol (works with any Niagara station)
Prerequisites
- Node.js 18 or later
- A Niagara 4 station with the STier API module installed
- Valid credentials for the station
Required Station Connection Type: TLS WebSocket
The STier API module is served by the station's HTTPS web service (port 443 by default). The STIER_STATION_URL must point to this HTTPS port.
⚠️ Fox ports are not supported. Niagara's Fox protocol ports (1911 for Fox, 4911 for FoxS) use a binary protocol that does not expose HTTP endpoints. The STier API and OBIX endpoints are only accessible via the HTTPS web service.
In Niagara Workbench, this corresponds to the TLS WebSocket connection type. If you see your station configured with Fox or FoxS only, ensure the HTTPSWebService is also enabled on the station and use its port in STIER_STATION_URL.
Setup
Option 1: Install via npx (Recommended)
Configure in Cursor MCP (~/.cursor/mcp.json):
{
"mcpServers": {
"stier-api": {
"command": "npx",
"args": ["@s-tier-building-automation/stier-mcp-server"],
"env": {
"STIER_STATION_URL": "http://localhost:8080",
"STIER_USERNAME": "your-username",
"STIER_PASSWORD": "your-password",
"STIER_REJECT_UNAUTHORIZED": "false"
}
}
}
}Option 2: Local Installation
If you have the source code:
cd mcp-server
npm install
npm run buildThen configure in Cursor MCP:
{
"mcpServers": {
"stier-api": {
"command": "node",
"args": ["<path-to-repo>/mcp-server/dist/index.js"],
"env": {
"STIER_STATION_URL": "http://localhost:8080",
"STIER_USERNAME": "your-username",
"STIER_PASSWORD": "your-password",
"STIER_REJECT_UNAUTHORIZED": "false"
}
}
}
}Note:
- The server handles HTTP-to-HTTPS redirects automatically
- Restart Cursor or toggle the MCP server after configuration changes
Environment Variables
The server supports two modes: Legacy Mode (single station) and Multi-Station Mode.
Legacy Mode (Single Station)
| Variable | Required | Description |
|----------|----------|-------------|
| STIER_STATION_URL | Yes | URL to the Niagara station (e.g., http://localhost:8080 or https://192.168.1.100) |
| STIER_USERNAME | Yes | Username for station authentication |
| STIER_PASSWORD | Yes | Password for station authentication |
| STIER_REJECT_UNAUTHORIZED | No | Set to true to reject self-signed certificates (default: false) |
Multi-Station Mode
Multi-station mode uses a PostgreSQL database shared with the stier-chat web app. Stations are managed through the web UI and credentials are encrypted.
| Variable | Required | Description |
|----------|----------|-------------|
| DATABASE_URL | Yes | PostgreSQL connection string |
| ENCRYPTION_KEY | Yes | 32-character key for decrypting station credentials (must match stier-chat) |
| STIER_ENABLE_WRITES | No | Set to true to enable write operations (default: false) |
| STIER_RATE_LIMIT | No | Requests per second per station (default: 5) |
| STIER_TIMEOUT_READ_MS | No | Read operation timeout in ms (default: 5000) |
| STIER_TIMEOUT_HISTORY_MS | No | History query timeout in ms (default: 30000) |
| STIER_TIMEOUT_BULK_MS | No | Bulk operation timeout in ms (default: 60000) |
Note: Multi-station mode requires running from the monorepo context where Prisma has been generated for stier-chat. See
.env.examplefor a complete template.
Available Tools
list_histories
List all available history IDs from the station.
Parameters:
station(optional): Filter by station name
Example:
list_histories()
list_histories(station: "MyStation")get_history
Query history trend data with time range and pagination.
Parameters:
id(required): History ID to querystation(optional): Station namestart(optional): Start time in ISO 8601 formatend(optional): End time in ISO 8601 formatpage(optional): Page number (default: 1)pageSize(optional): Records per page (default: 500)
Example:
get_history(id: "AHU1_SupplyTemp")
get_history(id: "AHU1_SupplyTemp", start: "2025-01-01T00:00:00Z", end: "2025-01-02T00:00:00Z")list_alarms
List all alarm source names from the station.
Parameters:
station(optional): Filter by station name
get_alarms
Query alarms with filtering options.
Parameters:
id(optional): Filter by alarm source nameackState(optional): Filter by acknowledgment statealarmState(optional): Filter by alarm statepage(optional): Page number (default: 1)pageSize(optional): Records per page (default: 500)
Example:
get_alarms()
get_alarms(ackState: "unacked")
get_alarms(id: "AHU1_HighTemp", alarmState: "offnormal")get_point
Get control point details.
Parameters:
path(required): Point path or history ID (e.g., "/AHU1/SupplyTemp" or "AHU1_SupplyTemp")station(optional): Station name (for multi-station mode)
Protocol-Specific Behavior:
- STierAPI stations: The
pathcan be a history ID fromlist_historiesor a slot path. The API resolves the point via history configuration. - OBIX stations: The
pathis treated as a point path (e.g.,/config/AHU1/SupplyTemp). The API reads the point directly.
Returns: Point information including name, path, units, precision, and range facets.
get_stats
Get station statistics and system information.
Parameters: None
Returns: Object with memory usage, OS info, Java version, timezone, and other system details.
list_wiresheets
List wire sheets (component containers with control logic) in the station.
Parameters:
pathPrefix(optional): Filter by path prefix (e.g., "/Drivers" to list only driver wiresheets)filterByType(optional): Filter by component type (e.g., "program", "control", "folder")
Example:
list_wiresheets()
list_wiresheets(pathPrefix: "/Drivers")
list_wiresheets(filterByType: "folder")Returns: Object with success, count, and wiresheets array containing path and type for each wire sheet.
get_wiresheet
Get detailed wire sheet information including all components, their properties, positions, and wiring connections.
Parameters:
path(required): Full path to the wire sheet container (e.g., "/Logic/AHU1")
Example:
get_wiresheet(path: "/Drivers/NiagaraNetwork/Controller")
get_wiresheet(path: "/Logic/TemperatureControl")Returns: Object containing:
exists: Whether the wire sheet was foundpath: The wire sheet pathtype: Component typecomponents: Array of components with name, path, type, properties, position, and childrenconnections: Array of connections with fromComponent, fromSlot, toComponent, toSlot
create_wiresheet
Create a new wire sheet with optional components and connections.
Parameters:
stationPath(required): Path where the wiresheet should be created (e.g., "/Logic")wiresheetName(required): Name for the new wiresheetwiresheetType(optional): Type of wiresheet to create (default: "baja:Folder")components(optional): Array of components to createconnections(optional): Array of connections to create between components
Example:
create_wiresheet(
stationPath: "/Logic",
wiresheetName: "AHU_Control",
wiresheetType: "baja:Folder",
components: [
{ name: "SetPoint", type: "control:NumericPoint", position: { x: 10, y: 10 } },
{ name: "Adder", type: "kitControl:Add", position: { x: 30, y: 10 } }
],
connections: [
{ fromComponent: "SetPoint", fromSlot: "out", toComponent: "Adder", toSlot: "in" }
]
)Returns: Object with success, wiresheetPath, componentsCreated, and any errors.
create_component
Add a single component to an existing wire sheet.
Parameters:
wiresheetPath(required): Path to the parent wiresheetname(required): Name for the new componenttype(required): Component type (e.g., "control:NumericPoint", "kitControl:Add")position(optional): Visual position{ x, y, width, height }properties(optional): Component properties to set
Example:
create_component(
wiresheetPath: "/Logic/AHU_Control",
name: "TempSensor",
type: "control:NumericPoint",
position: { x: 20, y: 30, width: 8, height: 0 },
properties: { out: 72.5 }
)Returns: Object with success, componentPath, and message.
create_connection
Create a wiring connection between two components.
Parameters:
wiresheetPath(required): Path to the wiresheet containing both componentsfromComponent(required): Name of the source componentfromSlot(optional): Output slot name (default: "out")toComponent(required): Name of the target componenttoSlot(optional): Input slot name (default: "in")
Example:
create_connection(
wiresheetPath: "/Logic/AHU_Control",
fromComponent: "SetPoint",
fromSlot: "out",
toComponent: "Controller",
toSlot: "in1"
)Returns: Object with success, message, linkName, and available slots if errors occur.
delete_wiresheet
Delete a wire sheet or component at the specified path.
Parameters:
path(required): Full path to the wiresheet/component to delete
Example:
delete_wiresheet(path: "/Logic/OldController")Returns: Object with success and message.
set_value
Set a value on a control point.
Parameters:
path(required): Path to the control pointvalue(required): Value to setstation(optional): Station name (for multi-station mode)
Example:
set_value(path: "/Drivers/AHU1/SupplyTempSP", value: 72.5)list_stations
List all configured stations (multi-station mode only).
Returns: Array of stations with id, name, url, protocol, and isActive status.
test_connection
Test connectivity to a station.
Parameters:
station(required): Station name or ID
Returns: Connection status and any error details.
obix_info
Get OBIX server information (for OBIX stations).
Parameters:
station(optional): Station name
Returns: OBIX server version and capabilities.
obix_browse
Browse the OBIX object hierarchy.
Parameters:
path(optional): Path to browse (default: root)station(optional): Station name
Returns: List of child objects with their types and values.
bulk_read
Read multiple points in a single call.
Parameters:
paths(required): Array of point paths to readstation(optional): Station name
Returns: Object with values for each path.
bulk_write
Write multiple points in a single call. Requires STIER_ENABLE_WRITES=true.
Parameters:
values(required): Object mapping paths to valuesstation(optional): Station name
Returns: Object with success status for each write.
Development
Building
npm run buildRunning in Development
npm run devTroubleshooting
Empty Response or JSON Parse Error
This usually indicates a connection or authentication issue:
- Test with Postman/curl first - Verify the API works with your credentials
- Check the URL - Try both HTTP and HTTPS; the server follows redirects automatically
- Verify credentials - Ensure username/password are correct
Connection Refused
Ensure:
- The station URL and port are correct — use the HTTPS web service port (typically 443), not a Fox port
- ❌
https://192.168.1.100:1911— Fox port (binary protocol, HTTP not supported) - ❌
https://192.168.1.100:4911— FoxS port (binary protocol, HTTP not supported) - ✅
https://192.168.1.100:443— HTTPS web service (TLS WebSocket in Workbench)
- ❌
- The station is running
- The STier API servlet is enabled in Niagara Workbench
- The
HTTPSWebServiceis enabled on the station (not justFoxService) - Your firewall allows the connection
SSL Certificate Errors
For self-signed certificates (common in development):
- Set
STIER_REJECT_UNAUTHORIZEDto"false"in your config
Authentication Failed (Login Page Returned)
If you receive an HTML login page instead of JSON:
- Username and password are incorrect
- The user doesn't have API access permissions
- The STier service is not licensed
MCP Server Not Starting
- Ensure you've run
npm run buildafter any code changes - Verify the path in your MCP config points to
dist/index.js(notsrc/index.ts) - Check Cursor's MCP logs for error details
License
MIT
