opcua-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@opcua-mcpCheck the current temperature reading on the OPC-UA server"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
OPC-UA MCP Server
An MCP server that lets an LLM read, write, browse, search, and subscribe to live data on an OPC-UA industrial automation server - over stdio or HTTP, with a persistent cache and a searchable index of the address space built in.
https://github.com/user-attachments/assets/0b676e6e-17ce-42f5-918f-9a615e939008
Quick start
The fastest way to see it working end-to-end, using the bundled Microsoft OPC-UA test server and a public tunnel Claude can reach:
git clone https://github.com/mwieczorkiewicz/opcua-mcp.git
cd opcua-mcp
make compose-up # starts a test OPC-UA server, opcua-mcp, and a public HTTPS tunnel
make connector-url # prints a URL like https://xyz.trycloudflare.com/mcpPaste that URL into Claude at Settings → Connectors → Add custom
connector, then ask it to browse the server or read a value. Stop with
make compose-down when you're done - see
docs/deployment.md for what that tunnel exposes and
how to run against your own OPC-UA server instead.
Building and running locally
go build -o opcua-mcp ./cmd/opcua-mcp.go
# stdio (default) - no OPC-UA connection until the client calls opcua_connect
./opcua-mcp
# HTTP - connects eagerly at startup
SERVER_TRANSPORT=http OPCUA_ENDPOINT=opc.tcp://localhost:4840 ./opcua-mcpRequires Go 1.26+ and, optionally, Docker for the test server / containerized deployment.
Related MCP server: OT-AIops
What it does
Read / write node values, with type validation on writes so a mismatched value is rejected before it reaches the device.
Browse the address space one level at a time or recursively, and look nodes up by name instead of by node ID.
Subscribe to push-based live updates - subscriptions persist across restarts and are automatically re-established on reconnect.
Cache reads, browse results, and type info on disk (bbolt), so repeat lookups don't round-trip to the device; writes invalidate the relevant entry automatically.
Discover and search the address space in the background, indexed with Bleve for fuzzy/partial browse-name lookups.
Anonymous, username/password, or certificate auth, with configurable OPC-UA security policy and mode.
See docs/architecture.md for how the caching layer, subscription manager, and discovery index fit together.
MCP tools
Tool | Description |
| Read one or more node values. Subscribed nodes are served from the live cache; others go live unless |
| Write a value to a node. Validates the value's type against the node before writing. |
| Read a single node's value - a convenience wrapper over |
| Read a value by browse name instead of node ID, via the discovery index. |
| List a node's immediate children. |
| Recursively browse from a node up to a depth limit, nesting children under their parent. |
| Get a node's metadata (data type, access level, etc.). |
| Fuzzy-match browse names against the discovery index. |
| Start push-based updates for one or more nodes at a given interval. |
| Cancel a subscription, by ID or by naming one of its nodes. |
| List active subscriptions. |
| Manage the connection explicitly (mainly relevant in stdio mode). |
| Get OPC-UA server metadata. |
| Stats on the background discovery cache (node count, depth distribution, enabled flags). |
| Trigger an immediate discovery refresh instead of waiting for the next cycle. |
| Diagnostics for troubleshooting why a node isn't showing up in search. |
MCP resources
Resource | Description |
| Node data, e.g. |
| OPC-UA server information. |
Configuration
Configuration is loaded (via viper) from three sources, in ascending order of precedence:
Built-in defaults (shown in the tables below).
An optional config file - TOML, YAML, JSON, or any other format viper supports. By default
./config.{yaml,yml,toml,json,...}is read if present; point at an explicit path withCONFIG_FILE=/path/to/config.toml. A config file is entirely optional - env vars alone are still enough.Environment variables (
SERVER_*,OPCUA_*,MCP_*,SEARCH_*,STORE_*) - always win over the config file, so existing env-var-only deployments keep working unchanged.
A config file mirrors the env var names, lowercased and nested under each
prefix, e.g. SERVER_HTTP_PORT becomes:
server:
http_port: "8080"Server
Variable | Default | Description |
|
|
|
|
| Port for HTTP transport |
|
|
|
|
|
|
|
|
|
| - | Log file path, required if |
|
| Add source file/line to log entries |
OPC-UA connection
Variable | Default | Description |
|
| Server endpoint |
|
|
|
| - | Required if |
| - | Required if |
| - | Server certificate file path |
|
|
|
|
|
|
|
| Per-request timeout |
|
| Session timeout |
|
| Connection retry attempts |
|
| Delay between retries |
MCP
Variable | Default | Description |
|
| Server name reported to clients |
|
| Server version reported to clients |
|
| Enable tools |
|
| Enable resources |
|
| Enable prompts |
|
| HTTP endpoint path |
Discovery and search
Variable | Default | Description |
|
| Enable background node discovery |
|
| How often to re-crawl the address space |
|
| Root node to crawl from (Objects folder) |
|
| Maximum crawl depth |
|
| Cap on nodes returned per browse call |
|
| Enable the Bleve search index |
|
| Search index directory |
|
| Max results per search |
|
| Minimum match score |
|
| Master switch for read-through caching. |
Persistent store
Backs read-through caching and subscription persistence with an on-disk bbolt database.
Variable | Default | Description |
|
| Database file path |
|
| How long to wait for the file lock on open |
|
| Freshness window for cached type info |
|
| Freshness window for cached browse results |
|
| How often subscription notifications flush to the store |
|
| Max notifications flushed per batch |
|
| Buffer size for incoming subscription notifications |
If the store fails to open (e.g. a stale lock from a prior ungraceful shutdown, or a read-only filesystem), the server logs a warning and keeps running with caching forced off and subscription tools returning an error - every other tool is unaffected.
Telemetry
opcua-mcp collects anonymous, aggregate usage telemetry (which tools get used, cache hit rate, error categories - never node IDs, endpoint URLs, node values, or credentials) to help prioritize maintenance of this open-source project. It's on by default; see docs/telemetry.md for exactly what is and isn't collected.
Opt out with either:
Variable | Effect |
| The cross-project community convention (consoledonottrack.com) |
| This project's own switch |
Docker
docker build -t opcua-mcp .
docker run -p 8080:8080 -e SERVER_TRANSPORT=http -e OPCUA_ENDPOINT=opc.tcp://your-server:4840 opcua-mcpMulti-stage build on Chainguard's minimal Go image, running from scratch -
no shell, small attack surface. Mount ./search_index and
./mcp_opcua_store.db as volumes to persist discovery/cache/subscription
state across restarts. Full auth-mode examples, the Compose dev stack, and
the Claude-connector tunnel setup are in
docs/deployment.md.
Development
make start-opcua-server # Microsoft OPC-UA test server in Docker
make run-with-test-server # run the app against it (auto start/stop)
go test ./... # unit tests
go test -race ./...
make test-integration # real Subscribe/reconnect/cache behavior via testcontainers-go (needs Docker)VS Code launch configs are in .vscode/launch.example.json - copy to
.vscode/launch.json to get stdio/HTTP/auth debug targets that start and
stop the test server automatically. make help lists every available
target.
Tests are table-driven and mock the OPC-UA client at the opcuaClient
interface seam (internal/opcua/mock_client_test.go) rather than against a
live/simulated server - see docs/architecture.md for
how the pieces being tested fit together, and
docs/COMMIT_CONVENTION.md for this repo's
commit message format.
Contributing
Fork it, make your changes, open a PR - see CONTRIBUTING.md.
License
This server cannot be deployed
Maintenance
Related MCP Connectors
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Protocol-native energy infrastructure orchestration for AI data centers. Provides 46 MCP tools across 8 grid protocols (IEC-61850, DNP3, Modbus, OCPP, OpenADR, IEEE 2030.5, IEC 60870-5-104, ICCP) with 5 core API primitives: connect, dispatch, settle, comply, and intel. Enables AI agents to programmatically interact with substations, grid interfaces, and energy assets for real-time workload-grid coordination.
Cross-OEM industrial machine intelligence: identity, normalization, automation, attestation.
Provides cloud browser automation capabilities using Stagehand and Browserbase, enabling LLMs to i…
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceConnects AI agents to OPC UA-enabled industrial systems for real-time monitoring and control of operational data. It enables users to read, write, and browse industrial device nodes through natural language interactions.MIT
- AlicenseBqualityAmaintenanceProvides AI agents with safe, governed read access to industrial control systems (OPC-UA, Modbus, S7, Mitsubishi, MTConnect, MQTT/Sparkplug) plus cross-protocol diagnostics for troubleshooting data breaks, alarm floods, and unhealthy tags.21531MIT
- FlicenseBqualityBmaintenanceUniversal MCP server for industrial PLC communication, enabling AI agents to read sensors, alarms, status, setpoints, and write setpoints via adapters for Modbus, S7, or custom PLCs.6-
- AlicenseAqualityCmaintenanceEnables LLMs to connect to factory PLC sensors, read register data, analyze predictive maintenance, and monitor energy consumption in industrial environments.3MIT