内容
# opcua-mcp
**An MCP server that exposes OPC-UA industrial data sources as safe, permissioned tools for AI agents.**
Agents are good at reasoning over data, but the factory floor speaks OPC-UA, not JSON-RPC. `opcua-mcp` sits in between. It connects to any OPC-UA server (PLCs, SCADA gateways, historians, simulators) and publishes selected tags as [Model Context Protocol](https://modelcontextprotocol.io) tools, so any MCP-capable agent can read live process values and, when you allow it, write setpoints back.
It is read-only by default, allowlist-driven, and treats writes as a deliberate, gated exception. The goal is to let agents observe and assist on the plant floor without handing them the keys to the line.
## Why this exists
Most MCP tooling targets SaaS and developer workflows. Industrial environments have been left out, even though they are exactly where a well-scoped, auditable agent interface is most valuable. `opcua-mcp` brings the two worlds together with safety as the first-class concern, not an afterthought.
## Features
- Connects to any OPC-UA endpoint, with optional user/password and certificate-based security.
- Exposes friendly tag names so agents work with `line1_temperature`, not `ns=2;i=2`.
- Read a single tag, batch-read many, browse the address space, or query server health.
- Read-only by default. Writes require both a global switch and a per-tag allowlist.
- Optional allowlist lock that blocks free browsing entirely for locked-down deployments.
- Reuses one connection and reconnects transparently if the session drops.
## Install
```bash
pip install -e .
```
Or with the dev extras for tests:
```bash
pip install -e ".[dev]"
```
## Configure
Copy the example and edit it for your endpoint and tags:
```bash
cp examples/config.example.yaml config.yaml
```
```yaml
endpoint: "opc.tcp://localhost:4840/freeopcua/server/"
tags:
line1_temperature: "ns=2;i=2"
line1_pressure: "ns=2;i=3"
lock_to_allowlist: true
write_enabled: false
writable_tags:
- line1_setpoint
```
Secrets can reference environment variables with `${VAR}` so you never commit credentials.
## Run
```bash
opcua-mcp
```
The server speaks MCP over stdio, so it drops straight into Claude Desktop, Goose, or any MCP client. Example Claude Desktop entry:
```json
{
"mcpServers": {
"opcua": {
"command": "opcua-mcp",
"env": { "OPCUA_MCP_CONFIG": "/absolute/path/to/config.yaml" }
}
}
}
```
## Tools
| Tool | Purpose |
| --- | --- |
| `list_tags` | List the friendly names and node ids the agent may read. |
| `read_tag` | Read one tag by friendly name or raw node id. |
| `read_many` | Batch-read several tags in one call. |
| `browse` | Walk child nodes (disabled when the allowlist lock is on). |
| `write_tag` | Write a value, gated by `write_enabled` and `writable_tags`. |
| `server_info` | Endpoint, connection state, namespaces, and the write policy. |
## Safety model
1. **Read-only by default.** `write_enabled` starts false, so a fresh install cannot change anything on the line.
2. **Two locks on every write.** A write needs the global `write_enabled` switch and the specific tag in `writable_tags`. Missing either one is refused.
3. **Allowlist lock.** With `lock_to_allowlist: true`, the agent can only touch tags you named and cannot browse the address space at all.
4. **Typed writes.** Values are written using the node's existing datatype, so a stray string cannot corrupt an integer register.
## Try it without hardware
The [asyncua](https://github.com/FreeOpcUa/opcua-asyncio) project ships an example server you can run locally to exercise the bridge before pointing it at real equipment. Point `endpoint` at that server, list a couple of its node ids as tags, and you are reading "live" values in a minute.
## Roadmap
- Modbus TCP connector alongside OPC-UA.
- Subscription and change-notification tools for event-driven agents.
- Optional per-tag rate limits and a call audit log.
## License
Apache-2.0.
---
Built as an open-source contribution to the [Agentic AI Foundation](https://agent-ai.foundation) ecosystem.