A MCP (Model Context Protocol) server that interacts with a real openHAB instance.
This project provides an implementation of an MCP server that connects to a real openHAB instance via its REST API. It enables AI assistants like Claude and Cline to interact with your openHAB smart home system.
The server provides comprehensive access to openHAB's core components:
- List, get, create, update, and delete items
- Update item states
- List all things
- Get, create, update, and delete things
- Update thing configurations
- Get thing configuration status
- Set thing enabled/disabled status
- Get thing status and firmware information
- Get available firmware updates
- List, get, create, update, and delete rules
- Update rule script actions
- Run rules on demand
- List, get, create, update, and delete scripts
When connected to Claude or Cline in VSCode, you can use natural language to control and manage your openHAB system, making home automation more accessible and intuitive.
- Python 3.7+
The official image is published to the GitHub Container Registry (ghcr.io/tdeckers/openhab-mcp). Pulling this image is the fastest way to get the MCP server running.
By default the server uses stdio for MCP. For remote HTTP clients, set MCP_MODE=remote to expose both Streamable HTTP at http://HOST:PORT/mcp and SSE at http://HOST:PORT/sse from the same container. The container examples below use remote mode; for stdio, omit MCP_MODE and the port mapping. Streamable HTTP supports session headers like Mcp-Session-Id for stateful clients.
-
(Optional for private registries) Authenticate with GHCR:
podman login ghcr.io # or: docker login ghcr.io -
Run the container with Podman (add
-e OPENHAB_USERNAME=...and-e OPENHAB_PASSWORD=...if your OpenHAB instance requires basic authentication):podman run -d --rm -p 8081:8000 \ -e MCP_MODE=remote \ -e OPENHAB_URL=http://your-openhab-host:8080 \ -e OPENHAB_API_TOKEN=your-api-token \ --name openhab-mcp \ ghcr.io/tdeckers/openhab-mcp:latest
Using Docker instead?
docker run -d --rm -p 8081:8000 \ -e MCP_MODE=remote \ -e OPENHAB_URL=http://your-openhab-host:8080 \ -e OPENHAB_API_TOKEN=your-api-token \ --name openhab-mcp \ ghcr.io/tdeckers/openhab-mcp:latest
-
Stop the container when you are done:
podman stop openhab-mcp # or: docker stop openhab-mcp
When running with MCP_MODE=remote, the container listens on port 8000 internally, but the examples map it to port 8081 on the host to avoid conflicts with an existing OpenHAB installation. Streamable HTTP clients connect to http://HOST:PORT/mcp, while SSE clients connect to http://HOST:PORT/sse.
If you need to modify the code, build and tag the image locally instead:
-
Build the image:
make docker-build # or directly: podman build -t openhab-mcp . -
Run your custom image:
make docker-run # or directly: podman run -d --rm -p 8081:8000 \ -e MCP_MODE=remote \ -e OPENHAB_URL=http://your-openhab-host:8080 \ -e OPENHAB_API_TOKEN=your-api-token \ --name openhab-mcp \ openhab-mcpEnsure the
OPENHAB_URL,OPENHAB_API_TOKEN, and optionalOPENHAB_USERNAME/OPENHAB_PASSWORDvariables are set in your shell before invokingmake docker-run. -
Stop the custom container:
make docker-stop # or directly: podman stop openhab-mcp
You can connect this OpenHAB MCP server to Claude or Cline in VSCode to interact with your OpenHAB instance through AI assistants.
- For Claude: Claude Desktop app installed
- For Cline: Cline VSCode extension installed
- Run the container using the steps in "Quick Start" (published image) or "Optional: Build and run a custom image".
- Create a configuration file for Claude Desktop:
Save the following as claude_desktop_config.json in your Claude Desktop configuration directory:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
{
"mcp_servers": [
{
"name": "openhab-mcp",
"command": "podman",
"args": [
"run",
"-d",
"-p",
"8081:8000",
"-e",
"MCP_MODE=remote",
"-e",
"OPENHAB_URL=http://your-openhab-host:8080",
"-e",
"OPENHAB_API_TOKEN=your-api-token",
"--name",
"openhab-mcp",
"ghcr.io/tdeckers/openhab-mcp:latest"
]
}
]
}- Run the container using the steps in "Quick Start" (published image) or "Optional: Build and run a custom image".
- Create a configuration file for Cline:
Save the following as mcp.json in your Cline configuration directory:
- macOS/Linux:
~/.cursor/mcp.json - Windows:
%USERPROFILE%\.cursor\mcp.json
{
"mcp_servers": [
{
"name": "openhab-mcp",
"command": "podman",
"args": [
"run",
"-d",
"-p",
"8081:8000",
"-e",
"MCP_MODE=remote",
"-e",
"OPENHAB_URL=http://your-openhab-host:8080",
"-e",
"OPENHAB_API_TOKEN=your-api-token",
"--name",
"openhab-mcp",
"ghcr.io/tdeckers/openhab-mcp:latest"
]
}
]
}- After creating the configuration file, restart Claude Desktop or VSCode
- Open a new conversation with Claude or Cline
- You should now be able to interact with your OpenHAB instance through the AI assistant
Example prompt to test the connection:
Can you list all the items in my OpenHAB system?
If configured correctly, Claude/Cline will use the MCP server to fetch and display your OpenHAB items.
- Remote mode: set
MCP_MODE=remoteand connect tohttp://HOST:PORT/mcp(Streamable HTTP) orhttp://HOST:PORT/sse(SSE)
If a Streamable HTTP client POSTs to /sse, the server should return 405 Method Not Allowed because /sse only accepts SSE GET/subscribe requests (verify against your FastMCP version).
Use these quick checks after deployment:
-
Streamable HTTP
-
Ensure
MCP_MODE=remoteis set. -
Initialize with a POST to
/mcp(client libraries handle this automatically). -
Manual probe (GET typically returns
405; POST should succeed — verify against your FastMCP version):curl -i http://HOST:PORT/mcp
-
-
SSE
-
Ensure
MCP_MODE=remoteis set. -
The SSE endpoint accepts GET at
/ssefor subscriptions. -
Manual probe (expects an SSE stream):
curl -i http://HOST:PORT/sse
-
These checks validate that the list_items tool works in stdio, Streamable HTTP, and SSE modes using a locally built container. They assume a reachable openHAB instance (use make dev-env for a local one).
-
Build the image:
make docker-build
-
Start openHAB (optional if you already have one):
make dev-env
-
stdio: run the server locally and call
list_itemsvia stdio:OPENHAB_URL=http://localhost:18080 \ OPENHAB_API_TOKEN=your-api-token \ uv run python scripts/mcp_client_stdio_list_items.py
-
remote: run the container in remote mode:
podman run -d --rm -p 8081:8000 \ -e MCP_MODE=remote \ -e OPENHAB_URL=http://localhost:18080 \ -e OPENHAB_API_TOKEN=your-api-token \ --name openhab-mcp \ openhab-mcp
-
Streamable HTTP: call
list_itemsvia/mcp:uv run python scripts/mcp_client_streamable_list_items.py
-
SSE: call
list_itemsvia/sse:uv run python scripts/mcp_client_sse_list_items.py
-
Stop the container:
podman stop openhab-mcp
The server provides the following tools:
list_items- Paginated list of openHAB items with optional tag, type, name, and label filtersget_item- Get a specific openHAB item by namecreate_item- Create a new openHAB itemupdate_item- Update an existing openHAB itemdelete_item- Delete an openHAB itemupdate_item_state- Update just the state of an openHAB item
list_things- Paginated list of openHAB things with optional UID and label filtersget_thing- Get a specific openHAB thing by UIDcreate_thing- Create a new openHAB thingupdate_thing- Update an existing openHAB thingdelete_thing- Delete an openHAB thingupdate_thing_config- Update an openHAB thing's configurationget_thing_config_status- Get openHAB thing configuration statusset_thing_enabled- Set the enabled status of an openHAB thingget_thing_status- Get openHAB thing statusget_thing_firmware_status- Get openHAB thing firmware statusget_available_firmwares- Get available firmwares for an openHAB thing
list_rules- List all openHAB rules, optionally filtered by tagget_rule- Get a specific openHAB rule by UIDcreate_rule- Create a new openHAB ruleupdate_rule- Update an existing openHAB rule with partial updatesupdate_rule_script_action- Update a script action in an openHAB ruledelete_rule- Delete an openHAB rulerun_rule_now- Run an openHAB rule immediately
list_scripts- List all openHAB scripts (rules with tag 'Script' and no trigger)get_script- Get a specific openHAB script by IDcreate_script- Create a new openHAB scriptupdate_script- Update an existing openHAB scriptdelete_script- Delete an openHAB script
list_links- List all openHAB item-channel links, optionally filtered by channel UID or item nameget_link- Get a specific openHAB item-channel linkcreate_or_update_link- Create or update an openHAB item-channel linkdelete_link- Delete a specific openHAB item-channel linkget_orphan_links- Get orphaned openHAB item-channel links (links to non-existent channels)purge_orphan_links- Remove all orphaned openHAB item-channel linksdelete_all_links_for_object- Delete all openHAB links for a specific item or thing
The server provides the following resources:
openhab://items- List of all items in the openHAB systemopenhab://items/{item_name}- Get a specific item by name
{
"name": "LivingRoom_Light",
"type": "Switch",
"label": "Living Room Light",
"state": "OFF",
"tags": ["Lighting", "LivingRoom"],
"groups": ["gLights", "gLivingRoom"]
}For development purposes, please refer to the DEVELOPER.md file for more information on the Podman-based development workflow.
This implementation connects to a real openHAB instance via its REST API. For production use, you might want to enhance it with:
- More comprehensive error handling and logging
- Additional authentication and security features
- More sophisticated caching mechanisms
- Support for more openHAB features (rules, things, etc.)
MIT