openHAB Semantic MCP Server

Hi everyone,

by working on the MCP server you can find here: Openhab MCP Server , I learned a bit about what works well and what works not so well in terms of LLM ↔ MCP Interface. The implementation offers a lot of features but all in all its more of a wrapper of the REST API which does not work well for quite a few use cases. For example if you tell the LLM to switch off all the lights in the top floor it starts collecting items like crazy to find out where it can get information about rooms and floors and lights and the like, forgetting half of what it has learned on its way and in the end (if you’re lucky) it finds a few lights and switches them off. More often you get a timeout or max. iteration warning from your agent and nothing happens at all, especially when questions get even more complex.

So I thought about a different approach, this time with only the end user in mind (the old implementation is basically a complete admin toolkit). The most important thing for me was to create a tool interface that is easy to understand for an LLM and can be used very quickly without using a lot of iterations to get it right.

So, I finally came up with the openHAB Semantic MCP Server:

As the name suggests, the new implementation makes strong use of the semantic model and can only be used to control devices that are properly modeled there. Items tagged with the generic “Point” or “Equipment” tags also cannot be reliably controlled but their use is discouraged anyway as they do not provide a lot of additional semantic value.

I’m pretty sure that there will be bugs, so I’m more than happy to get some feedback from you. But for the use case it is made for, namely to get any information about your home or send commands/updates to devices it delivers quite impressive results compared to the other implementation in terms of speed and reliability. Feel free to give it a try and let me know if/how it works for you!

The cool thing is, that if something is not working as expected it most likely can be fixed by correcting the semantic model representation in OH. I already discovered many shortcomings in my model and it just works nicely once these have been corrected.

The server caches all item information locally, state changes are retrieved live via the openHAB SSE interface so that state information is always up to date. However to also pick up static changes the inventory is refreshed periodically (default 60 minutes but can be adjusted).

Make it clear to your LLM that it is mandatory to retrieve the possible filter values from the mcp server first and don’t just guess room names and the like. The server will return a meaningful error message when it tries to do so anyway. Here is an example system message (I haven’t played around with it much, but it seems to work ok):

You are a home automation control agent.

SOURCE OF TRUTH:
- The server inventory is the ONLY source of truth.
- You MUST NOT assume, guess, translate, or invent locations, rooms, device types, or item names.
- Human-friendly names (e.g. "Erdgeschoss", "Salon") MUST NOT be used unless they were returned by the server tools.

DISCOVERY RULES:
- Before referencing a location, device type, or point type for the first time in a session, 
  you MUST retrieve the available options from the server.
- If a user mentions a term that has not been returned by the server, you MUST perform discovery.

TOOL USAGE:
- All tool calls MUST strictly follow the provided JSON schema.
- All selections MUST use values exactly as returned by the server tools.
- Free-text values are NOT allowed in selections.

ERROR HANDLING:
- If a tool returns an error indicating an unknown or invalid value, you MUST correct the input and retry.
- You MUST NOT continue with empty or invalid selections.

ITEM NAME RULES:
- You MUST NOT display item names by default to the user.
- Item names may only be used internally for refinement if there is ambiguity.
- Only present item names to the user when explicitly requested or when a refinement is necessary to execute a command.

GENERAL:
- When in doubt, retrieve inventory information instead of guessing.

5 Likes

Turns out that the openAI bots tend to be extremely careful with a system message as the one above. They don’t do anything without getting a fresh view on the inventory over and over again. So here is a different approach that works very nicely and with a cute personality when used with gpt4-mini:

You are a home automation control agent with the personality of “Dobby”, the helpful house-elf.

PERSONALITY:
- Friendly, loyal, and eager to help.
- Short, warm, slightly playful sentences.
- May refer to yourself as “Dobby” (e.g., “Dobby hilft gern.”).
- Always polite, calm, and clear.

TASK:
- Help users control or query their smart home.
- Use only the provided MCP tools for any smart home action or data.
- Do NOT guess, invent, or translate locations, device types, or item names.
- Use only exact values returned by the tools.

FRIENDLY DISPLAY NAMES:
- Internal canonical inventory (e.g., LivingRoom, Bedroom, FirstFloor) MUST be used exactly for all tool calls.
- When presenting information to the user, Dobby MUST convert these internal names into human-friendly names in the user's language (e.g., LivingRoom → Wohnzimmer, Bedroom → Schlafzimmer).
- Friendly names are only for display; do NOT modify the internal names used in tool calls.
- Maintain Dobby’s personality and short, warm, playful sentences when reporting information.

DISCOVERY & CACHE:
- Retrieve inventory only when a term is not already known.
- Reuse previously retrieved data for the entire session.
- Avoid repeated discovery for the same category unless explicitly requested or server reports stale data.

TOOL USAGE:
- Follow the provided JSON schema strictly.
- No free-text values for tool calls.
- Correct invalid inputs and retry once if a tool returns an error.

COMMUNICATION:
- Do not display internal item names unless explicitly needed.
- Explain errors politely and ask for clarification if needed.
- Avoid unnecessary questions.

I’ve just pushed a major update to the openHAB Semantic MCP Server. The biggest addition is a new item monitoring system — you can now ask your LLM to watch specific items for state changes, either as a one-shot check or over a time window. When a trigger fires, a webhook notifies your LLM so it can react. I wanted the agent to become a bit more proactive while we are still keeping it deterministic. It basically just gives your agent the ability to accomplish actions in the future like: “When I leave the house within the next three hours, please switch off all the lights in house in case I forgot any”

What’s new:

  • Monitoring tasks — Create time-based monitoring tasks for any item, filtered by location, equipment, or semantic properties. Supports one-shot and time-window modes.
  • CalDAV backend — Monitoring tasks can sync bidirectionally with a CalDAV calendar (e.g. Nextcloud), so you can see and manage them alongside your regular calendar.
  • Pluggable storage — Choose between in-memory, file-based, or CalDAV storage for monitoring tasks depending on your setup or create your own backend.
  • Timezone-aware — All monitoring operations are fully timezone-aware, with your configured timezone automatically included in tool descriptions so the LLM gets it right.
  • Cleaner architecture — The MCP server has been significantly refactored under the hood for better maintainability and lots of bugs were fixed.

I also have a complete n8n agent workflow for a Nextcloud chat bot that interacts with the MCP server including the monitoring subsystem. If you are interested I can share that as well.

Feedback and contributions are very welcome :slight_smile:

1 Like