Skip to content
Start free evaluation

The MCP server

pdcomm-modbus-mcp provides the Modbus simulator as an MCP (Model Context Protocol) server. AI tools such as Claude Code and Cursor start the server and call the service commands as MCP tools. Commands and results are the same as in the headless simulator.

  • The transport is stdio: newline-delimited JSON-RPC 2.0 messages on standard input and output.
  • One server process is one session. It doesn’t see a GUI or any other process that’s already running. To move state, load a project file with modbus_project_import or communicate over real TCP.
  • Connected as a server, the MCP server keeps answering requests while it waits for input.

The server command is the absolute path of bin/pdcomm-modbus-mcp in the SDK (pdcomm-modbus-mcp.exe on Windows). It takes no arguments.

Add it to the project’s .mcp.json:

.mcp.json
{
"mcpServers": {
"pdcomm-modbus": {
"type": "stdio",
"command": "/opt/pdcomm/pdcomm-modbus/bin/pdcomm-modbus-mcp"
}
}
}

Enter /mcp in a session to check the connection.

/opt/pdcomm/pdcomm-modbus is an example; use the path where you extracted the SDK. For a diagnostic log, add PDCOMM_LOG and PDCOMM_LOG_FILE under env in the client configuration. Log records never go to standard output.

The server provides 22 tools, one per service command with a modbus_ prefix. A tool’s arguments are the command’s other members; the server sets action from the tool name.

Tool Example arguments Purpose
modbus_capabilities, modbus_state {} Build features; current configuration and connection
modbus_configure {"config":{...}} Change the configuration (while disconnected)
modbus_connect, modbus_disconnect {} Open and close the connection
modbus_request {"pdu":"0300000001","unit":1} Client request
modbus_execute {"pdu":"060000002A"} Run against the local model
modbus_data_get, modbus_data_set, modbus_model_set {"table":"holding_registers","address":0,"values":[1]} Read and change the data model
modbus_diagnostics, modbus_diagnostics_set {} Diagnostics counters and register
modbus_trace, modbus_trace_clear {} Request and frame record
modbus_project_export, modbus_project_import {"project":{...}} Save and load projects
modbus_fault {"transport":"rtu","bytes":"01030000000AC5CD"} Decode synthetic frames
modbus_serial_ports {} List serial ports
modbus_poll {} Serve once (the server polls by itself, so you rarely need it)
modbus_logging_configure, modbus_logging_status, modbus_logging_flush {"config":{"level":"debug"}} Diagnostic log control

JSON command reference describes every command’s members.

To check the server without an AI tool, enter JSON-RPC messages one line at a time:

터미널 창
"$MODBUS_SDK/bin/pdcomm-modbus-mcp"
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"tutorial","version":"1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"modbus_execute","arguments":{"pdu":"060000002A"}}}
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"modbus_execute","arguments":{"pdu":"0300000001"}}}
{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"modbus_request","arguments":{"pdu":"0300000001"}}}
{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"modbus_execute","arguments":{"pdu":"0300000001","unit":300}}}
{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"tools":{"listChanged":false}},"protocolVersion":"2025-11-25","serverInfo":{"name":"pdcomm-modbus","version":"1.0.0"}}}
{"id":2,"jsonrpc":"2.0","result":{"tools":[{"description":"Configure diagnostic logging.","inputSchema":{"$schema":"https://json-schema.org/draft/2020-12/schema","additionalProperties":false,"properties":{"config":{...}},"required":["config"],"type":"object"},"name":"modbus_logging_configure","title":"Configure logging"},...]}}
{"id":3,"jsonrpc":"2.0","result":{"content":[{"text":"{\"response\":[6,0,0,0,42],\"source\":\"local\",\"status\":\"success\"}","type":"text"}],"isError":false}}
{"id":4,"jsonrpc":"2.0","result":{"content":[{"text":"{\"response\":[3,2,0,42],\"source\":\"local\",\"status\":\"success\"}","type":"text"}],"isError":false}}
{"id":5,"jsonrpc":"2.0","result":{"content":[{"text":"Connect a client before sending a request","type":"text"}],"isError":true}}
{"id":6,"jsonrpc":"2.0","result":{"content":[{"text":"Invalid arguments: unit must be at most 255","type":"text"}],"isError":true}}
  • Notifications (notifications/initialized) get no reply.
  • The server accepts protocol versions 2025-11-25, 2025-06-18 and 2024-11-05, and answers any other requested version with 2025-11-25.
  • The tools/list reply above is shortened. Each tool has a closed input schema (JSON Schema 2020-12) with the type, range and description of every argument.
  • The result is a JSON string in content[0].text; parse it again on the client side.
  • Arguments that don’t match the input schema never reach the simulator. With protocol 2025-11-25 the call returns isError and a text that starts with Invalid arguments:, as in the reply to id 6. With 2025-06-18 and 2024-11-05 it returns the JSON-RPC error {"error":{"code":-32602,"message":"Invalid arguments: unit must be at most 255"},"id":6,"jsonrpc":"2.0"}.
  • Closing the input ends the server.

A failure in an MCP reply belongs to one of four layers:

Layer Shape Examples
Modbus exception isError is false; the result’s status is exception {"response":[131,2],...,"status":"exception"}
Service error isError is true; text holds the error message Connect a client before sending a request, Timeout
Invalid arguments isError is true with protocol 2025-11-25, or a -32602 error with earlier versions; the message starts with Invalid arguments: Invalid arguments: unit must be at most 255
JSON-RPC error An error object -32700 (JSON parse failure), -32601 (Unknown method or server is not initialized), -32602 (Unknown tool: <name>, Arguments must be an object)
  • tools/list or tools/call before initialize returns -32601.
  • A tool that doesn’t exist, such as modbus_shutdown, returns -32602 Unknown tool: modbus_shutdown.
  • After a JSON parse error, the server exits with code 1. Tool calls with isError don’t affect the exit code, so don’t judge every call by the process exit code alone.