MCP Server (AI Interface)
The Studio includes a built-in MCP Server (Model Context Protocol). This allows AI assistants such as Claude Code, Claude Desktop, or ChatGPT to directly access and edit an open project — creating pages, placing widgets, connecting function blocks, managing addresses, and much more.
The MCP Server runs only in Studio mode (not in the App) and listens locally on a configurable TCP port. Two HTTP transports are supported:
POST http://localhost:7420/mcpGET http://localhost:7420/sseFor most AI clients a Python proxy script is used as a bridge (stdio ↔ HTTP), since not all clients support HTTP MCP servers directly.
The MCP Server settings are located under Extras → Settings → Tab “General”.
| Setting | Description |
| MCP Server Port | TCP port of the server. Default value: 7420. Value 0 = MCP Server disabled. Changes take effect only after restarting the Studio. |
| MCP Server Debug | Enables or disables debug logging. When set to On, all incoming
connections, method calls and tool invocations are written to the
application log via qInfo(). Takes effect immediately —
no restart required. |
The MCP Server provides a total of 52 tools in ten groups:
| Tool | Description |
get_project_info |
Get project name, filename, version and timestamp |
list_widget_pages |
List all visualization pages |
get_widget_page |
Get details of a visualization page including all its widgets |
add_widget_page |
Create a new visualization page |
delete_widget_page |
Delete a visualization page |
add_widget |
Place a widget on a page. Default size is set automatically based on
widget type (e.g. 144×144 for block widgets, 152×40 for text
widgets). Only specify w/h to override the default. |
update_widget |
Change position, size and parameters of a widget |
delete_widget |
Delete a widget |
list_fb_pages |
List all program pages (function block pages) |
get_fb_page |
Get details of a program page including all function blocks |
add_fb_page |
Create a new program page |
add_function_block |
Place a function block on a program page |
delete_function_block |
Delete a function block |
list_addresses |
Retrieve the complete KNX address hierarchy |
save_project |
Save the project to disk |
| Tool | Description |
get_widget_detail |
Get complete widget data: all parameters with comment, tooltip, value and type, plus all IO addresses |
set_widget_addresses |
Set a KNX address for a widget IO slot (index, main group, middle group, sub group) |
get_widget_type_info |
Get name and parameter list of a widget type (static information) |
list_widget_types |
List all known widget types with decimal value, hex value and name.
Use before every add_widget call to determine
the correct type value. |
connect_widget_to_fb |
Connect a block widget to a function block. Automatically sets the
FB-GUID parameter at the correct param index for the widget type.
sync_label=true: widget caption (Param 0) is automatically
copied from the FB comment — saves a subsequent
update_widget call. |
| Tool | Description |
get_fb_detail |
Get complete function block data: GUID, type, type name, comment, position, parameters, inputs and outputs with connection status and addresses |
update_fb |
Change position, comment and parameters of a function block |
get_fb_type_info |
Get the name of a function block type by its numeric type value |
list_fb_types |
Return the complete list of all known function block types with
decimal value, hex value and name. Call this before
add_function_block to look up the correct type
value (e.g. Modbus Master = 1917 = 0x077d). |
| Tool | Description |
connect_fb_io |
Connect an output of one function block to the input of another. Internal connections require no KNX address — they are linked via a shared internal identifier. |
disconnect_fb_io |
Disconnect a connection at a function block input or output |
list_fb_connections |
List all internal and external connections on a program page |
| Tool | Description |
create_address |
Create a new KNX address in the address list (main, middle and sub group, comment, data type). Missing parent groups are created automatically. |
update_address |
Change the comment or data type of an existing address |
delete_address |
Remove an address from the address list |
assign_fb_io_address |
Assign a KNX address to a function block input or output.
For multiple assignments to the same FB:
use assign_fb_io_addresses_batch. |
assign_fb_io_addresses_batch |
Assign multiple KNX addresses in a single API call.
assignments array with
io_type, io_index,
main, middle, sub per entry.
Up to 10× faster than individual calls (e.g. 4 addresses per FB
→ 1 call instead of 4).
Returns: total, succeeded, errors. |
ui_navigate |
Navigate the Studio view to the given page and synchronize the sidebar
and tab display. Fixes the bug where page display and navigation can
get out of sync after API calls. Auto-detects whether the GUID belongs
to an FB page or a widget page.
Returns: found, page_type_detected. |
import_knx_addresses |
Import KNX group addresses from an ESF or XML file (ETS export).
Input: file_path (local path) or
file_content (file content as string — no file access
needed, ideal for sandbox environments). Format is auto-detected.
Options: keep_type, keep_comment,
import_new_only, connected_addresses,
uncertain_1byte/2byte/4byte.
Returns: imported, updated, skipped, total. |
generate_fb_addresses |
Automatically generates KNX addresses for a function block and assigns
them to its inputs and outputs — equivalent to the
“Generate variables” button in the Studio. Works for all
Block FBs (light, blind, switch, scene, RGBW, …) and many common
and heating FBs.
conflict_mode: "append" (default) = use next free
middle group, "overwrite" = replace existing addresses.
Returns: has_generate_variable, addresses_created. |
| Tool | Description |
get_modbus_master_config |
Read the configuration and registers of a Modbus Master function block.
Supports pagination: offset and limit parameters
for large configurations (>50 registers). Each register includes
datatype (readable enum:
INT16/UINT16/INT32/UINT32/FLOAT32)
and word_count (number of 16-bit words). |
set_modbus_master_config |
Change general configuration parameters (node ID, protocol, IP address,
port, timeout …). address_offset is added to every
register address. Convention: addresses are 0-based (FC3/FC4 address 0
= device address 40001/30001). For 1-based devices:
address_offset=-1. |
set_modbus_master_registers |
Replace the complete register list. Recommendation: use
datatype as a string enum
(INT16/UINT16/INT32/UINT32/FLOAT32)
– automatically sets word_count, signed and
internal types. factor accepts decimal values (e.g. 0.01).
Response includes a warnings array listing automatic
corrections. |
add_modbus_master_register |
Add a single register at the end of the list. write_mode:
0 = ReadOnly, 1 = FC6 WriteSingle,
2 = FC16 WriteMultiple. |
update_modbus_master_register |
Update an existing register (only supplied fields are changed). Also
supports the datatype shorthand and write_mode. |
delete_modbus_master_register |
Remove a register from the list. Output IOs are automatically resized accordingly. |
| Tool | Description |
list_help_topics |
List all available help topics. Returns topic IDs that can be fetched
with get_help. Topics are grouped by category:
program/fb_xxx for function blocks,
visu/widget_xxx for widgets,
common/variable for data types etc.
Optional parameter: language (de or en). |
get_help |
Retrieve a help page as plain text. Either specify a topic ID
(e.g. program/fb_modbus_master), or reference a placed
function block via fb_guid / widget via widget_guid
– the correct help file is then resolved automatically via
onProcesssHelp() resp. urlHelpBrowser().
Optional parameter: language. |
The Block Clock tools read and write the switching schedules of a Block Clock
function block. Prerequisite: A Widget_Block_Clock must be placed
on a visualization page and connected to the function block
(mParamConnectedFbId = fb_guid). Changes are
transferred to the runtime via saveWidgetSettings().
| Tool | Description |
get_block_clock_schedules |
Read all schedule entries of a Block Clock FB. Returns
schedules (list), count,
brightness_active and brightness_inactive.
Each entry contains:
type (week / date / astro),
hour, minute, value,
days_sun/mon/tue/wed/thu/fri/sat,
day, month, single_shot,
brightness (always / day / night),
astro_type, astro_offset,
switch_mode (value / active). |
set_block_clock_schedules |
Replace the complete schedule list of a Block Clock FB.
All existing entries are deleted. Optional:
brightness_active and brightness_inactive
(defaults: 1000 / 100). Maximum: 128 entries. |
add_block_clock_schedule |
Add a new schedule entry at the end of the list.
Required fields: fb_guid, type,
hour, minute, value. |
update_block_clock_schedule |
Update an existing schedule entry by its index (0-based). Only specified fields are changed; unspecified fields remain unchanged. |
delete_block_clock_schedule |
Delete a schedule entry by its index (0-based). |
These tools send values directly to the connected runtime (e.g. switch lights,
dim, set target temperature). Prerequisite: PT2020-Studio must be connected to a
running runtime via the network connection. Addresses can be found using
list_addresses (fields main, middle,
sub).
| Tool | Description |
|---|---|
set_address_value |
Sends a value to a KNX group address of the connected runtime.
Parameters: main, middle, sub,
value (0/1 for switching, 0–100 for dimming,
degrees for temperature). Returns a warning if the runtime is not
connected; in that case the value is stored locally only. |
get_address_value |
Reads the last received or set value of a KNX group address.
Returns value (numeric), value_str (readable),
comment and datatype. |
The list_addresses tool additionally returns value
and value_str for each address entry, making the current state of
all addresses visible at a glance.
These tools allow writing and reading Lua script code for the Lua Interpreter
function block (type 0x0384). The get_lua_api_reference tool returns
the complete API reference including callbacks, IO variables and all
sys_* functions — enabling the AI assistant to generate correct
Lua code directly.
| Tool | Description |
set_lua_script |
Writes Lua source code into a Lua Interpreter function block. Parameters:
fb_guid (GUID of the block), code (Lua source text),
optional inputs (1–64, number of inputs),
outputs (1–64, number of outputs). |
get_lua_api_reference |
Returns the complete Lua API reference: callbacks
(onCreate, onInputChanged, onTimer,
onEvent), IO variables (E1–E64,
A1–A64), all sys_* functions
grouped by category (Timer, KNX, Persistence, Network, PID, System …)
and a complete blink example. No parameters required. |
Claude Code is the AI command-line tool from Anthropic. Integration
is done via the Python proxy script and the claude mcp add command.
uni_pro_mcp_proxy.py in a convenient
location (e.g. C:\Users\<user>\)The script forwards stdio messages to the Studio's HTTP MCP server:
import sys, json, urllib.request, urllib.error
MCP_URL = "http://localhost:7420/mcp"
def send_error(id_, msg):
sys.stdout.write(json.dumps({"jsonrpc":"2.0","id":id_,"error":{"code":-32603,"message":msg}})+"\n")
sys.stdout.flush()
def main():
for line in sys.stdin:
line = line.strip()
if not line: continue
try: id_ = json.loads(line).get("id")
except: id_ = None
try:
req = urllib.request.Request(MCP_URL, data=line.encode(), headers={"Content-Type":"application/json"})
with urllib.request.urlopen(req, timeout=10) as r:
body = r.read().decode().strip()
if body and body != "{}":
sys.stdout.write(body+"\n"); sys.stdout.flush()
except urllib.error.URLError as e: send_error(id_, "Studio not reachable: "+str(e.reason))
except Exception as e: send_error(id_, str(e))
if __name__ == "__main__": main()
Run once in a terminal (replaces manual settings.json configuration):
claude mcp add --scope user uni-pro python "C:/Users/<user>/uni_pro_mcp_proxy.py"
claude./mcp — uni-pro should appear as connected.
Claude Desktop is the desktop application from Anthropic. The configuration file is located at:
%APPDATA%\Claude\claude_desktop_config.json~/Library/Application Support/Claude/claude_desktop_config.jsonAdd the following section to the configuration file:
{
"mcpServers": {
"uni-pro": {
"command": "python",
"args": ["C:/Users/<user>/uni_pro_mcp_proxy.py"]
}
}
}
Restart Claude Desktop. A tool icon will appear in the chat input field — clicking it shows the available MCP tools.
Note: The Studio must be started before Claude Desktop so the proxy can reach the HTTP server on the first connection attempt.
ChatGPT Desktop (Windows/macOS) also supports MCP servers via the stdio proxy script.
pythonC:/Users/<user>/uni_pro_mcp_proxy.pyuni-proNote: The exact configuration depends on the installed version of ChatGPT Desktop. Current information is available in the OpenAI documentation.
The connection can be tested directly from the command line using curl, without any AI application. Open a Command Prompt and run the following commands (Studio must be running):
curl -X POST http://localhost:7420/mcp ^
-H "Content-Type: application/json" ^
-d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"0\"}}}"
Expected response (abbreviated):
{"jsonrpc":"2.0","id":1,"result":{"serverInfo":{"name":"PT2020-Studio-MCP","version":"1.0"},...}}
curl -X POST http://localhost:7420/mcp ^
-H "Content-Type: application/json" ^
-d "{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\",\"params\":{}}"
curl -X POST http://localhost:7420/mcp ^
-H "Content-Type: application/json" ^
-d "{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\"params\":{\"name\":\"get_project_info\",\"arguments\":{}}}"
Tip: On Windows, curl is available from the Command
Prompt starting with Windows 10 (Build 1803).
The following examples show typical requests you can ask the AI assistant. The assistant automatically calls the appropriate MCP tools.
"What visualization pages does the current project have?"
"Show me all KNX addresses in the project."
"What is the project name and which version is being used?"
"Create a new visualization page called 'Main Menu' with a size of 1024×768 pixels."
"Create three pages: 'Ground Floor', 'First Floor' and 'Basement', each 1280×800 pixels."
"Add a button (type 100) labeled 'Light On' to the top left of the 'Main Menu' page, 200×80 pixels."
"Place four switches side by side on the 'Ground Floor' page, each 150×60 pixels, for the living room blinds."
"Move the button with ID 42 on the 'Main Menu' page to the bottom right (position 800, 600)."
"Show me all parameters and addresses of widget ID 15 on the 'Ground Floor' page."
"Assign KNX address 1/2/10 to the first IO slot of widget 15."
"Create a new program page called 'Lighting Control' and add an AND function block and a timer."
"What function blocks are on the 'Heating' page?"
"Show me all parameters and inputs of the function block with GUID 'abc-123'."
"Connect output 0 of the AND block to input 0 of the timer on the 'Lighting Control' page."
"What connections exist on the 'Lighting Control' program page?"
"Disconnect the connection at input 0 of the timer."
"Set the comment of function block 'abc-123' to 'Checks presence and brightness'."
"Create a new KNX address 1/2/50 with the comment 'Living Room Light'."
"Update the comment of address 1/2/50 to 'Living Room Main Light'."
"Delete address 1/2/99 from the address list."
"Assign KNX address 1/2/50 to output 0 of function block 'abc-123'."
"Are all KNX addresses in the project assigned? List any unused addresses."
"Analyze the structure of all visualization pages and create an overview of the widget types used."
"Check all function blocks on the 'Heating' page for unconnected inputs and outputs."
"Copy the layout of the 'Ground Floor' page and create a new 'First Floor' page with the same widget positions."
"Save the project."
"Apply all changes and then save the project."
claude mcp add command only needs to be run once.MCP_URL = "http://localhost:7421/mcp").localhost
(127.0.0.1) — no firewall rules are needed.