Skip to main content
Glama
mwieczorkiewicz

opcua-mcp

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/mcp

Paste 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-mcp

Requires 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

opcua_read

Read one or more node values. Subscribed nodes are served from the live cache; others go live unless max_age_ms allows a cached value.

opcua_write

Write a value to a node. Validates the value's type against the node before writing.

opcua_get_value

Read a single node's value - a convenience wrapper over opcua_read.

opcua_get_value_by_name

Read a value by browse name instead of node ID, via the discovery index.

opcua_browse

List a node's immediate children.

opcua_browse_nodes

Recursively browse from a node up to a depth limit, nesting children under their parent.

opcua_node_info

Get a node's metadata (data type, access level, etc.).

opcua_find_similar_nodes

Fuzzy-match browse names against the discovery index.

opcua_subscribe

Start push-based updates for one or more nodes at a given interval.

opcua_unsubscribe

Cancel a subscription, by ID or by naming one of its nodes.

opcua_list_subscriptions

List active subscriptions.

opcua_connect / opcua_disconnect

Manage the connection explicitly (mainly relevant in stdio mode).

opcua_server_info

Get OPC-UA server metadata.

opcua_discovery_stats

Stats on the background discovery cache (node count, depth distribution, enabled flags).

opcua_force_discovery

Trigger an immediate discovery refresh instead of waiting for the next cycle.

opcua_debug_search / opcua_ensure_server_nodes

Diagnostics for troubleshooting why a node isn't showing up in search.

MCP resources

Resource

Description

opcua://node/{node_id}

Node data, e.g. opcua://node/ns=2;i=1. Accepts a comma-separated list for multiple nodes.

opcua://server

OPC-UA server information.

Configuration

Configuration is loaded (via viper) from three sources, in ascending order of precedence:

  1. Built-in defaults (shown in the tables below).

  2. 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 with CONFIG_FILE=/path/to/config.toml. A config file is entirely optional - env vars alone are still enough.

  3. 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

SERVER_TRANSPORT

stdio

stdio or http

SERVER_HTTP_PORT

8080

Port for HTTP transport

SERVER_LOG_LEVEL

info

debug, info, warn, error

SERVER_LOG_FORMAT

json

json or text

SERVER_LOG_OUTPUT

stdout

stdout, stderr, or file (forced to stderr in stdio mode, since stdout carries the MCP stream)

SERVER_LOG_FILE

-

Log file path, required if SERVER_LOG_OUTPUT=file

SERVER_LOG_ADD_SOURCE

false

Add source file/line to log entries

OPC-UA connection

Variable

Default

Description

OPCUA_ENDPOINT

opc.tcp://localhost:4840

Server endpoint

OPCUA_AUTH_MODE

anonymous

anonymous, username, or certificate

OPCUA_USERNAME / OPCUA_PASSWORD

-

Required if AUTH_MODE=username

OPCUA_CERT_FILE / OPCUA_KEY_FILE

-

Required if AUTH_MODE=certificate

OPCUA_SERVER_CERT

-

Server certificate file path

OPCUA_SECURITY_POLICY

None

None, Basic128Rsa15, Basic256, Basic256Sha256, Aes128_Sha256_RsaOaep

OPCUA_SECURITY_MODE

None

None, Sign, SignAndEncrypt

OPCUA_REQUEST_TIMEOUT

30s

Per-request timeout

OPCUA_SESSION_TIMEOUT

60s

Session timeout

OPCUA_MAX_RETRIES

3

Connection retry attempts

OPCUA_RETRY_DELAY

1s

Delay between retries

MCP

Variable

Default

Description

MCP_NAME

OPC-UA MCP Server

Server name reported to clients

MCP_VERSION

1.0.0

Server version reported to clients

MCP_ENABLE_TOOLS

true

Enable tools

MCP_ENABLE_RESOURCES

true

Enable resources

MCP_ENABLE_PROMPTS

false

Enable prompts

MCP_HTTP_PATH

/mcp

HTTP endpoint path

Variable

Default

Description

SEARCH_ENABLE_DISCOVERY

true

Enable background node discovery

SEARCH_DISCOVERY_INTERVAL

30s

How often to re-crawl the address space

SEARCH_DISCOVERY_ROOT_NODE

i=85

Root node to crawl from (Objects folder)

SEARCH_MAX_DISCOVERY_DEPTH

10

Maximum crawl depth

SEARCH_MAX_NODES_PER_BROWSE

10000

Cap on nodes returned per browse call

SEARCH_ENABLE_SEARCH

true

Enable the Bleve search index

SEARCH_INDEX_PATH

./search_index

Search index directory

SEARCH_MAX_RESULTS

100

Max results per search

SEARCH_MIN_SCORE

0.1

Minimum match score

SEARCH_ENABLE_CACHE

true

Master switch for read-through caching. false makes every opcua_read/opcua_write/opcua_browse_nodes call go live, matching pre-cache behavior exactly

Persistent store

Backs read-through caching and subscription persistence with an on-disk bbolt database.

Variable

Default

Description

STORE_DB_PATH

mcp_opcua_store.db

Database file path

STORE_OPEN_TIMEOUT

5s

How long to wait for the file lock on open

STORE_TYPEINFO_TTL

24h

Freshness window for cached type info

STORE_BROWSE_TTL

5m

Freshness window for cached browse results

STORE_BATCH_WINDOW

25ms

How often subscription notifications flush to the store

STORE_BATCH_MAX_ITEMS

250

Max notifications flushed per batch

STORE_NOTIFY_CHAN_BUFFER

1024

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

DO_NOT_TRACK=1

The cross-project community convention (consoledonottrack.com)

OPCUA_MCP_TELEMETRY=false

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-mcp

Multi-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

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
<1hResponse time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    -
    quality
    D
    maintenance
    Connects 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.
    Last updated
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Provides 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.
    Last updated
    100
    MIT
  • F
    license
    B
    quality
    B
    maintenance
    Universal 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.
    Last updated
    6
  • A
    license
    A
    quality
    C
    maintenance
    Enables LLMs to connect to factory PLC sensors, read register data, analyze predictive maintenance, and monitor energy consumption in industrial environments.
    Last updated
    3
    MIT

View all related MCP servers

Related MCP Connectors

  • Provides cloud browser automation capabilities using Stagehand and Browserbase, enabling LLMs to i…

  • AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.

  • Give your agent live data from Twitter, Reddit, the web and GitHub. No API keys, no scraping stack.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mwieczorkiewicz/opcua-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server