About Opcua MCP
Opcua MCP is an MCP server published by IndustriAgents in the Developer Tools category: mCP server that connects AI agents ( Claude, ChatGPT, Gemini, Cursor etc.) to OPC UA systems - read, browse, history, subscriptions, events and alarms.
The repository has 29 stars and 10 forks, with the last commit 5 days ago. Recent commit activity is the strongest signal that reported issues will get attention.
Install
git clone https://github.com/IndustriAgents/OPCUA-MCPThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Tools (14)
acknowledge_alarmAcknowledge one of them, with a comment
Parameters not published.
browse_opcua_node_childrenList a node's children
Parameters not published.
call_opcua_methodInvoke a method on an object node
Parameters not published.
get_all_variablesInventory every variable in the address space
Parameters not published.
list_active_alarmsThe alarms the server is currently retaining
Parameters not published.
list_subscriptionsThe active subscriptions, each with its buffered changes
Parameters not published.
read_eventsRead the events collected since the last read
Parameters not published.
read_multiple_opcua_nodesBatch read
Parameters not published.
read_opcua_nodeRead a single node's value
Parameters not published.
subscribe_eventsStart collecting events from a notifier node
Parameters not published.
Show all 14 tools
subscribe_opcua_nodeWatch a node for data changes instead of polling it
Parameters not published.
unsubscribe_opcua_nodeCancel one subscription
Parameters not published.
write_multiple_opcua_nodesBatch write
Parameters not published.
write_opcua_nodeWrite a value to a node
Parameters not published.
Ask AI
Ask AI about Opcua MCP
Powered by Claude · Grounded in docs
Security checks
Static checks derived from the repository 4 days ago. Heuristics on the source, not an audit.
- ✓README presentThe repository ships documentation.
- ✓License declaredUsable under a stated license.
- ✓Tests presentA test suite exists in the repository.
- ✓Dependencies pinnedA lockfile pins dependency versions.
- ✓No dynamic code executionSource scan found no eval, dynamic Function, or shell execution.
- !Scoped permissionsDoesn't declare a permission scope. Assume it can do anything its process can.
Releases
README
🏭 OPC UA MCP Server
Let Claude, Codex, Gemini and any other MCP agent read sensors, browse the plant and — only when you allow it — control equipment on any OPC UA server.
Quick start · Connect your agent · Tools · Production · Docs

One local MCP stdio process connects one client context to one OPC UA endpoint. Use a separate process for each endpoint. Remote MCP and shared multi-client operation are gated by the identity and isolation RFC.
Features
- 🔌 Any OPC UA server — PLC, SCADA gateway or historian. Nothing to install on the plant side.
- 🧰 The whole operator toolkit — read, browse, history and aggregates, subscriptions, events and alarms, writes and method calls.
- 🛡️ Read-only by default — writes and method calls need an explicit profile, an allowlist and an authenticated server (pinned certificate or CA trust store), and every control call is audited.
- 🐍 Python or Node — two first-class runtimes with the same tools and the same answers. Use whichever you have.
- 📦 One-file Claude Desktop install — a
.mcpbbundle with nothing else to set up.
flowchart LR
A["AI agent<br/>(Claude, Codex, Gemini, Cursor…)"] -->|MCP over stdio| B["OPC UA MCP Server<br/>(Python or Node)"]
B -->|OPC UA| C["OPC UA server<br/>(PLC / SCADA / historian)"]
Quick start
Every MCP client runs the same command, with your endpoint in OPCUA_SERVER_URL:
npx -y opcua-mcp-server # Node 22.13+
uvx opcua-mcp-server # Python 3.10+
- Add it to your agent — pick yours below.
- Point it at a server —
opc.tcp://<host>:4840, or start the bundled mock plant. - Ask — "What's the current temperature in the reactor vessel?"
Connect your agent
Replace opc.tcp://localhost:4840 with your endpoint. To use the Python runtime,
swap npx -y opcua-mcp-server for uvx opcua-mcp-server.
Easiest — the bundle. Download opcua-mcp-server-<version>.mcpb from the
latest release,
drag it into Settings → Extensions, and fill in OPC UA endpoint. No
Node, no Python, no JSON.
Or let the server write the config (needs Node or Python):
npm install -g opcua-mcp-server # or: uv tool install opcua-mcp-server
opcua-mcp-server --install claude-desktop --url opc.tcp://192.168.0.10:4840 --dry-run
It checks the config with the server's own startup validation and writes absolute
paths, because Claude Desktop does not inherit your shell's PATH. The profile
defaults to read-only; encryption, a pinned server certificate, a control profile,
a policy file and an audit file are all flags, and passwords are never taken as
flags. Drop --dry-run to write. Every flag and safety rule, editing
claude_desktop_config.json by hand, and fixing a server that fails to start:
docs/install.md.
claude mcp add opcua -e OPCUA_SERVER_URL=opc.tcp://localhost:4840 -- npx -y opcua-mcp-server
Add --scope project to share it with your team through .mcp.json.
codex mcp add opcua --env OPCUA_SERVER_URL=opc.tcp://localhost:4840 -- npx -y opcua-mcp-server
Or add it to ~/.codex/config.toml:
[mcp_servers.opcua]
command = "npx"
args = ["-y", "opcua-mcp-server"]
env = { OPCUA_SERVER_URL = "opc.tcp://localhost:4840" }
Or let the server write that entry, with the same checks as for Claude Desktop:
opcua-mcp-server --install codex --url opc.tcp://localhost:4840 --dry-run.
Add to ~/.gemini/settings.json, or .gemini/settings.json in a project:
{
"mcpServers": {
"opcua": {
"command": "npx",
"args": ["-y", "opcua-mcp-server"],
"env": { "OPCUA_SERVER_URL": "opc.tcp://localhost:4840" }
}
}
}
In the agent panel, open ⋯ → MCP Servers → Manage MCP Servers → View raw
config, add the entry below to mcp_config.json, and restart Antigravity:
{
"mcpServers": {
"opcua": {
"command": "npx",
"args": ["-y", "opcua-mcp-server"],
"env": { "OPCUA_SERVER_URL": "opc.tcp://localhost:4840" }
}
}
}
Add to ~/.cursor/mcp.json, or .cursor/mcp.json in a project:
{
"mcpServers": {
"opcua": {
"command": "npx",
"args": ["-y", "opcua-mcp-server"],
"env": { "OPCUA_SERVER_URL": "opc.tcp://localhost:4840" }
}
}
}
Add to .vscode/mcp.json — note the top-level key is servers:
{
"servers": {
"opcua": {
"type": "stdio",
"command": "npx",
"args": ["-y", "opcua-mcp-server"],
"env": { "OPCUA_SERVER_URL": "opc.tcp://localhost:4840" }
}
}
}
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"opcua": {
"command": "npx",
"args": ["-y", "opcua-mcp-server"],
"env": { "OPCUA_SERVER_URL": "opc.tcp://localhost:4840" }
}
}
}
Most clients accept this mcpServers entry. The server speaks MCP over stdio.
{
"mcpServers": {
"opcua": {
"command": "npx",
"args": ["-y", "opcua-mcp-server"],
"env": { "OPCUA_SERVER_URL": "opc.tcp://localhost:4840" }
}
}
}
[!TIP] No Node or Python on the machine? Download a single-file executable from the latest release and use its path as the
command— see docs/install.md. Several PLCs? Each entry talks to one endpoint, so add one entry per PLC (why).
Try it without a plant
The repo ships a simulated industrial plant — sensors, actuators, methods, history and events — so you can try every tool without touching real equipment:
git clone https://github.com/IndustriAgents/OPCUA-MCP.git && cd OPCUA-MCP
uv sync --all-packages
uv run --no-sync opcua-mock-server # opc.tcp://localhost:4840/freeopcua/server/
Point your agent at that URL. The MCP Inspector walkthrough has prompts to try, and the compatibility matrix lists two smaller mocks for aggregates and alarms.
What you can ask
- "Show me all the variables in the system."
- "What was the temperature over the last hour? Give me the hourly average."
- "Watch the tank level and tell me what it does over the next minute."
- "What alarms are active right now?"
- "Set the valve position to 80%." — needs the
operatorprofile - "Start production on line 1 at 100 units/hour." — needs the
operatorprofile
Every reading comes back with its data type, status, timestamps and engineering units — never a bare number. What a result looks like.
Tools
15 tools, identical on both runtimes and defined once in contract/tools.json. Arguments, results and limits: docs/tools.md.
| Access | Offered under | Tools |
|---|---|---|
| read | every profile, including the default observe |
read_opcua_nodes · browse_opcua_nodes · read_opcua_history † · read_event_history † · get_server_status · list_subscriptions · list_active_alarms |
| monitor | every profile, including the default observe |
subscribe_opcua_nodes · unsubscribe_opcua_nodes · subscribe_events · read_events |
| alarm-action | operator with OPCUA_ALLOW_ACKNOWLEDGE_ALARMS, or full |
acknowledge_alarm · act_on_alarm |
| control | operator, for allowlisted targets only, or full |
write_opcua_nodes · call_opcua_method |
Control and alarm tools also need a verified server (a secured channel and a pinned OPCUA_SERVER_CERT or an OPCUA_SERVER_TRUST_STORE) unless a lab override is set. † Works only on a server that advertises the feature it needs, such as historical access.
Going to production
[!WARNING] Out of the box the agent can only read, but the OPC UA channel is unencrypted and anonymous — fine for the mock or a lab, not for real equipment. Secure the channel before connecting to anything that matters.
1. Secure the channel and pin the server — add these to the env block:
OPCUA_SECURITY_POLICY=Basic256Sha256 # implies SignAndEncrypt
OPCUA_CLIENT_CERT=/etc/opcua/client.pem # this client's identity
OPCUA_CLIENT_KEY=/etc/opcua/client_key.pem
OPCUA_SERVER_CERT=/etc/opcua/server.pem # pin the server you meant to reach
OPCUA_USERNAME=mcp-operator # or OPCUA_USER_CERT for X.509
OPCUA_PASSWORD=…
2. Decide what the agent may do with OPCUA_PROFILE:
| Profile | What the agent can do |
|---|---|
observe (default) |
Read, browse, history, subscriptions, events. No writes, no method calls. |
operator |
The above, plus only the nodes and methods you allowlist in OPCUA_ALLOWED_WRITE_NODES / OPCUA_ALLOWED_METHODS. |
full |
Every tool. Only for a tightly scoped OPC UA account. |
3. Keep a record — set OPCUA_AUDIT_FILE for an append-only log of every
control call.
Misconfiguration stops the server at startup with a message naming the variable, rather than failing later against live equipment. The MCP policy is defence in depth, not a replacement for OPC UA authorisation: scope the OPC UA account to the same nodes and methods.
Every setting, value bounds on writes and allowlists that survive a server restart: docs/configuration.md. Threat model: SECURITY.md. Certificates: docs/certificates.md.
Documentation
| Guide | What's inside |
|---|---|
| Install | The .mcpb bundle, single-file executables, choosing a runtime, troubleshooting |
| Configuration | Every setting, profiles, allowlists, value bounds, secure connections, reconnection |
| Tools | Full tool reference, result shapes, request limits, partial results |
| Examples | Every tool with real calls and responses against the mock plant |
| Security | What is and is not verified, the audit trail, reporting a vulnerability |
| Certificates | Generating a client certificate a server will accept |
| Compatibility | Servers tested, and where the Python and Node runtimes differ |
| Architecture | How it fits together, and why |
| Testing | The test suite, MCP Inspector and agent walkthroughs |
| Roadmap · Changelog | What is next, and what has landed |
Contributing
Contributions are welcome — see CONTRIBUTING.md for the project layout, local development and adding a tool to both runtimes.
The most useful thing you can send is a result from a real OPC UA server: open a compatibility report saying which server, which version and which tools worked. Test only on equipment you are authorised to use, and keep writes and method calls to a simulator or lab.
License
MIT — see LICENSE.
Tool inputs and structured results use JSON Schema draft 2020-12 with generated TypeScript/Python types and CI drift checks. See contract generation for the authoring workflow.
README fetched from the repository 4 days ago. The original is authoritative.