Connects AI assistants to IP-Symcon via the Model Context Protocol (MCP).
1.8K
Connects AI assistants to IP-Symconโ via the Model Context Protocol (MCP).
Exposes the Symcon JSON-RPC API as MCP tools so that AI assistants (Claude, Cursor, VS Code Copilot, โฆ) can read and control your smart home.
Important
The Symcon JSON-RPC API **requires authentication**. You must provide both `SYMCON_API_USER` (your license email) and `SYMCON_API_PASSWORD`.
| Mode | Transport | When to use |
|---|---|---|
| Local (Node.js) | stdio | Development, no Docker |
| Docker / Remote | HTTP or HTTPS | Different host on the network |
| Variable | Default | Description |
|---|---|---|
MCP_PORT | 4096 | Port the server listens on |
MCP_HOST_PORT | 4096 | Docker host port |
MCP_TRANSPORT | streamable | streamable, sse, or stdio |
MCP_AUTH_TOKEN | (empty) | Bearer token; How to create?โ |
LOG_LEVEL | info | debug, info, warn, error |
SYMCON_API_URL | http://host.docker.internal:3777/api/ | Symcon JSON-RPC endpointโ |
SYMCON_API_USER | (empty) | Symcon license username (required) |
SYMCON_API_PASSWORD | (empty) | Symcon password (required) |
SYMCON_TLS_VERIFY | true | Set false for self-signed certs |
The image is available on Docker Hub:
docker pull tommi2day/symcon-mcp-server:latest
docker run -d --name symcon-mcp-server \
-p 4096:4096 \
-e SYMCON_API_URL=http://192.168.1.100:3777/api/ \
-e [email protected] \
-e SYMCON_API_PASSWORD=your-symcon-password \
-e MCP_AUTH_TOKEN=my-secret-token \
tommi2day/symcon-mcp-server:latest
services:
symcon-mcp-server:
image: tommi2day/symcon-mcp-server:latest
ports:
- "4096:4096"
environment:
- SYMCON_API_URL=http://192.168.1.100:3777/api/
- [email protected]
- SYMCON_API_PASSWORD=your-symcon-password
- MCP_AUTH_TOKEN=my-secret-token
When running the MCP server as an HTTP/SSE service, it's recommended to set a strong MCP_AUTH_TOKEN to prevent unauthorized access to your Symcon instance.
If you use the provided ./scripts/run.sh to start the server, it will automatically generate a strong 32-byte hex token for you on the first run and save it to a file named auth_token in the project root.
You can generate a secure token manually using openssl (available on Linux, macOS, and Git Bash for Windows):
openssl rand -hex 32
Then, set this value as the MCP_AUTH_TOKEN environment variable in your .env file or docker run command.
When authentication is enabled, all requests to the MCP server must include the following header:
Authorization: Bearer <your-mcp-auth-token>
Set MCP_TRANSPORT=stdio and run via Node.js or Docker.
claude_desktop_config.json){
"mcpServers": {
"symcon": {
"command": "docker",
"args": ["run", "-i", "--rm", "tommi2day/symcon-mcp-server"],
"env": {
"MCP_TRANSPORT": "stdio",
"SYMCON_API_URL": "http://192.168.1.100:3777/api/",
"SYMCON_API_USER": "[email protected]",
"SYMCON_API_PASSWORD": "your-symcon-password"
}
}
}
}
This mode runs the MCP server as a standalone container, exposing an HTTP endpoint for any compatible client.
If you have a Symcon instance running elsewhere, run just the MCP server:
docker run -d --name symcon-mcp-server \
-p 4096:4096 \
-e SYMCON_API_URL=http://192.168.1.100:3777/api/ \
-e [email protected] \
-e SYMCON_API_PASSWORD=your-symcon-password \
-e MCP_AUTH_TOKEN=my-secret-token \
tommi2day/symcon-mcp-server:latest
mcp.jsonTo use the server from an MCP client (like Cursor or VS Code), add it to your mcp.json configuration:
{
"mcpServers": {
"symcon": {
"url": "http://localhost:4096/mcp",
"headers": {
"Authorization": "Bearer my-secret-token"
}
}
}
}
claude_desktop_config.json) โ HTTP/RemoteWarning
**Claude Desktop only supports HTTPS for non-local (remote) MCP servers.** If your server runs on plain HTTP and is not on `localhost`, Claude Desktop will refuse the connection. Use one of the options below:Option A โ Preferred: Put the server behind a reverse proxy (Traefik, nginx, Caddy) with a valid TLS certificate and use
https://in the URL.Option B โ Quick workaround: Use
mcp-remoteโ as a local stdio bridge. It runs on your machine and forwards requests to the HTTP server, so Claude Desktop treats it like a stdio tool.
{
"mcpServers": {
"symcon": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"http://192.168.1.100:4096/mcp",
"--allow-http",
"--header", "Authorization:Bearer my-secret-token"
]
}
}
}
Health check:
curl http://localhost:4096/health
MCP initialize handshake (checks that the server responds to MCP requests):
curl -s -X POST http://localhost:4096/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer my-secret-token" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
Interactive browser UI via MCP Inspectorโ :
# Local server โ direct HTTP
npx @modelcontextprotocol/inspector http://localhost:4096/mcp
# Remote HTTP server โ via mcp-remote bridge
npx @modelcontextprotocol/inspector \
npx mcp-remote http://192.168.1.100:4096/mcp \
--allow-http \
--header "Authorization:Bearer my-secret-token"
The inspector opens a browser UI where you can list tools, call them individually, and inspect responses.
Use this if you want to run both IP-Symcon and the MCP Server together in a single stack (e.g., for testing or evaluation).
Clone and configure
git clone https://github.com/tommi2day/symcon-mcp-server.git
cd symcon-mcp-server
cp .env.example .env
Edit .env and set SYMCON_API_URL, SYMCON_API_USER, SYMCON_API_PASSWORD, and MCP_AUTH_TOKEN.
Start
# Starts both services
docker compose up -d
Verify
curl http://localhost:4096/health
Access Symcon GUI Open http://localhost:3777โ in your browser to access the IP-Symcon console.
AI Client (Claude / Cursor / โฆ)
โ HTTP POST /mcp
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ symcon-mcp-server โ :4096
โ (Docker container) โ
โ โ
โ MCP Tools โ
โ โโ get_value โ
โ โโ set_value โ
โ โโ request_action โ
โ โโ get_variable โ
โ โโ get_object โ
โ โโ get_children โ
โ โโ get_object_by_name โ
โ โโ get_variable_path โ
โ โโ snapshot_variables โ
โ โโ diff_variables โ
โ โโ run_script โ
โ โโ run_script_text โ
โ โโ run_script_text_ex โ
โ โโ get_script_content โ
โ โโ script_create โ
โ โโ script_set_content โ
โ โโ script_delete โ
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ [JSON-RPC](https://www.symcon.de/en/service/documentation/developer-area/data-exchange/)
โผ
IP-Symcon :3777/api/
| Tool | Description |
|---|---|
symcon_get_value | Read the current value of a variable |
symcon_set_value | Write a value directly to a variable |
symcon_request_action | Trigger a device action (use for real devices) |
symcon_get_variable | Get variable metadata (type, profile, timestamps) |
symcon_get_object | Get metadata for any object (category, instance, โฆ) |
symcon_get_children | List child object IDs (0 = root) |
symcon_get_object_id_by_name | Find an object ID by name |
symcon_get_variable_by_path | Resolve a variable by slash-separated path |
symcon_snapshot_variables | Snapshot all variable values under a root |
symcon_diff_variables | Detect changes since a previous snapshot |
symcon_run_script | Execute an existing Symcon script by ID |
symcon_run_script_text | Execute arbitrary PHP code in Symcon |
symcon_run_script_text_ex | Execute PHP and return structured output, return value, and errors as separate fields; output is byte-capped |
symcon_get_script_content | Read the PHP source of an existing script (read-only, no execution) |
symcon_script_create | Create a new PHP script in Symcon |
symcon_script_set_content | Update an existing script's PHP content |
symcon_script_delete | Delete a script by ID |
Use symcon_request_action with value true (on) or false (off)
Use symcon_request_action with value 0โ254 (0 = off, 254 = full brightness)
Ask the AI assistant:
"Find the object ID of my living room light"
symcon_snapshot_variables on the relevant roomsymcon_diff_variables to identify which variable changed| Endpoint | Method | Description |
|---|---|---|
/ | GET | Server info and available endpoints |
/health | GET | Health check (Symcon status, uptime, version) |
/info | GET | Detailed server configuration and Symcon version |
/mcp | POST/GET/DELETE | MCP Streamable HTTP transport |
/sse | GET | MCP SSE transport (if MCP_TRANSPORT=sse) |
/messages | POST | SSE message handler |
| Stdio | N/A | MCP Stdio transport (if MCP_TRANSPORT=stdio) |
# Install
npm install
# Unit tests
npm test
# Integration tests (starts a real Symcon Docker container)
npm run test:integration
# All tests
npm run test:all
./scripts/test.sh # unit tests via Docker
./scripts/test.sh --integration # unit + integration tests
./scripts/lint.sh # lint
| Test suite | File | Dependencies |
|---|---|---|
| Unit: SymconClient | tests/symcon-client.test.ts | MockSymconServer (in-process) |
| Unit: MCP tools | tests/tools.test.ts | MockSymconServer + InMemoryTransport |
| Unit: HTTP server | tests/http-server.test.ts | MockSymconServer + spawned Express |
| Unit: Info endpoint | tests/info.test.ts | MockSymconServer + spawned Express (auth, masking & Symcon version) |
| Integration | tests/integration.test.ts | Real symcon/symcon-server Docker container |
The repository uses two primary GitHub Actions workflows:
CI (ci.yml) โ runs on every push and pull request:
Release (release.yml) โ triggered by a semver tag or manual dispatch:
package.json and openapi.yaml, commits and pushes to main.tommi2day/symcon-mcp-server).MCP_AUTH_TOKEN/health from your monitoring systemMIT
Content type
Image
Digest
sha256:cd40e076dโฆ
Size
65.7 MB
Last updated
2 months ago
docker pull tommi2day/symcon-mcp-server