mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-24 02:58:36 +08:00
0af7ae3a23
# Description The packages on nuget.org are stable 2.0.0 now. The guides still told readers to use `--prerelease` and preview-only versions, and kept caveats that applied only to 2.0.0-preview.5 and earlier previews. Getting started, Your first information model, and Source-generated data types: - Add the packages without `--prerelease` and name 2.0.0 as the verified version. - With 2.0.0, a client with no server reports `BadNotConnected`, so the troubleshooting row drops the preview.5 `SocketException`. - 2.0.0 generates code for methods that declare their arguments inline, so the tutorial drops the preview.5 workaround note and its troubleshooting row, and says both forms are possible. MCP server (`docs/McpServer.md` and the tool's NuGet README `tools/Opc.Ua.Mcp/McpREADME.md`): - Install and run commands use the stable tool: `dotnet tool exec OPCFoundation.NetStandard.Opc.Ua.Mcp`, `dnx …`, and `dotnet tool install --global …`, without `--prerelease` or `2.0.0-preview.*`. - The stable tool bundles `Opc.Ua.Mcp.Robotics` and `Opc.Ua.Mcp.Vision`, so the note that `vision` and `vision,robotics` need the current source is removed. The docs now state that only the standalone `Mcp.Robotics` and `Mcp.Vision` libraries are preview packages (`2.0.0-preview.200`). - Not changed: `tools/Opc.Ua.Mcp/.mcp/server.json` still declares `"version": "1.0.0"` and lists only the original profiles in its description. ### Validation | Command | Result | | --- | --- | | Getting started Route B, the first-model tutorial, and every troubleshooting row, run exactly as documented against the 2.0.0 packages | Output matches the guides; 0 warnings | | Native AOT publish of the Route B server and client | 0 warnings; the native executables completed the trust flow and connected | | `dotnet tool exec OPCFoundation.NetStandard.Opc.Ua.Mcp -- --version`, `dnx OPCFoundation.NetStandard.Opc.Ua.Mcp -- --version`, `dotnet tool exec "OPCFoundation.NetStandard.Opc.Ua.Mcp@2.0.*" -- --version` | `2.0.0+bc5da1006…` for each | | `dotnet tool install` of `OPCFoundation.NetStandard.Opc.Ua.Mcp` without `--prerelease` (into a temporary tool path) | Installs 2.0.0 | | `dotnet tool exec` of an uncached version with stdin redirected, as an MCP client launches it | Runs without a confirmation prompt | | MCP stdio `initialize` + `tools/list` against the 2.0.0 tool with `--profile vision,robotics`, `vision`, `robotics`, `full` | 64, 26, 42, and 138 tools | | Markdown link, anchor, contents, and fence checks over `docs/` | 0 issues | ## Related Issues - No tracking issue. Follow-up to #4555 after the 2.0.0 release. ## Checklist - [ ] I have signed the [CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf) and read the [CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md) doc. - [ ] I have added tests that prove my fix is effective or that my feature works and increased code coverage. - [x] I have added all necessary documentation. - [x] I have verified that my changes do not introduce (new) build or analyzer warnings. - [ ] I ran **all** tests locally using the **UA.slnx** solution against at least .net **framework** and .net **10**, and all passed. - [ ] I fixed **all** failing and flaky tests in the CI pipelines and **all** CodeQL warnings. - [ ] I have addressed **all** PR feedback received. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
682 lines
30 KiB
Markdown
682 lines
30 KiB
Markdown
# OPC UA MCP Server
|
|
|
|
The OPC UA MCP Server exposes OPC UA Part 4 service calls as
|
|
[Model Context Protocol (MCP)](https://modelcontextprotocol.io) tools. AI
|
|
assistants such as Claude, GitHub Copilot, VS Code Copilot, and Cursor can
|
|
use these tools to connect to OPC UA servers and interact with industrial
|
|
automation systems through natural language.
|
|
|
|
## Contents
|
|
|
|
- [What It Does](#what-it-does)
|
|
- [Tool Profiles](#tool-profiles)
|
|
- [Vision-guided Robotics](#vision-guided-robotics)
|
|
- [Resources](#resources)
|
|
- [Multi-Session Support](#multi-session-support)
|
|
- [Installation](#installation)
|
|
- [Option 1: Run without installing (.NET 10 SDK)](#option-1-run-without-installing-net-10-sdk)
|
|
- [Option 2: Install as a .NET global tool](#option-2-install-as-a-net-global-tool)
|
|
- [Option 3: Run from source](#option-3-run-from-source)
|
|
- [Option 4: Install from local build](#option-4-install-from-local-build)
|
|
- [Configuration](#configuration)
|
|
- [Run on demand without a global installation](#run-on-demand-without-a-global-installation)
|
|
- [Claude Desktop](#claude-desktop)
|
|
- [VS Code / GitHub Copilot](#vs-code--github-copilot)
|
|
- [Cursor](#cursor)
|
|
- [HTTP Transport (for remote clients)](#http-transport-for-remote-clients)
|
|
- [Usage](#usage)
|
|
- [Typical Workflow](#typical-workflow)
|
|
- [NodeId Formats](#nodeid-formats)
|
|
- [Common Well-Known NodeIds](#common-well-known-nodeids)
|
|
- [Error Handling](#error-handling)
|
|
- [PubSub Tools](#pubsub-tools)
|
|
- [Architecture](#architecture)
|
|
- [Packages](#packages)
|
|
- [Embedding the tools in your own MCP server](#embedding-the-tools-in-your-own-mcp-server)
|
|
- [Security Notes](#security-notes)
|
|
- [Agent-Usability Quality Gate](#agent-usability-quality-gate)
|
|
- [Requirements](#requirements)
|
|
|
|
## What It Does
|
|
|
|
The MCP server wraps the OPC UA .NET Standard client library, translating between JSON-based MCP tool calls and OPC UA binary protocol operations. The server exposes tools through a [tool profile](#tool-profiles) — a named, bounded catalog selected at startup — rather than a single fixed tool count. The default `full` profile currently registers every tool below; running a narrower profile (`core`, `services`, `administration`, `pubsub`, `diagnostics`, `robotics`, or `vision`) exposes only the subset relevant to that workflow. The tables below list the complete tool surface, organized by OPC UA Part 4 service set:
|
|
|
|
| Service Set | Tools | Description |
|
|
|---|---|---|
|
|
| **Connection** | `GetEndpoints`, `Connect`, `Disconnect`, `GetConnectionStatus` | Endpoint discovery and session lifecycle management |
|
|
| **Attribute** | `Read`, `Write`, `HistoryRead`, `HistoryUpdate` | Read/write node attributes and historical data |
|
|
| **View** | `Browse`, `BrowseNext`, `TranslateBrowsePaths`, `RegisterNodes`, `UnregisterNodes`, `QueryFirst`, `QueryNext` | Navigate and query the address space |
|
|
| **Node Management** | `AddNodes`, `AddReferences`, `DeleteNodes`, `DeleteReferences` | Modify the address space |
|
|
| **Method** | `Call` | Invoke OPC UA methods |
|
|
| **Subscription** | `CreateSubscription`, `ModifySubscription`, `SetPublishingMode`, `Publish`, `Republish`, `DeleteSubscriptions`, `TransferSubscriptions` | Manage notification subscriptions |
|
|
| **MonitoredItem** | `CreateMonitoredItems`, `ModifyMonitoredItems`, `SetMonitoringMode`, `SetTriggering`, `DeleteMonitoredItems` | Monitor data changes and events |
|
|
| **Discovery** | `FindServers`, `FindServersOnNetwork`, `RegisterServer`, `RegisterServer2` | Discover servers and register |
|
|
| **PKI Management** | `ListCertificates`, `TrustCertificate`, `RemoveCertificate`, `GetPkiStorePaths` | Manage certificate trust lists |
|
|
| **Configuration** | `GetConfiguration`, `SetTransportConfiguration`, `SetClientConfiguration`, `SetSecurityConfiguration`, `SetConfiguration` | View/modify in-memory client settings; `SetConfiguration` is the `full`-profile compatibility tool |
|
|
| **NodeSet Export** | `ExportNodeSet`, `ExportNodeSetPerNamespace` | Export address space to NodeSet2 XML |
|
|
| **Convenience** | `ReadValue`, `ReadValues`, `WriteValue`, `BrowseAll`, `CallMethod`, `ReadNode`, `Cancel` | Simplified high-level operations |
|
|
| **Packet Capture** | `list_interfaces`, `start_capture`, `stop_capture`, `list_captures`, `get_capture`, `capture_now`, `list_active_channels`, `dump_keys`, `decode_pcap_with_keys`, `summarize_service_calls`, `replay_pcap`, `stop_replay`, `list_replays` | OPC UA-aware packet capture, offline decode, service-call summaries, replay |
|
|
|
|
All OPC UA types (NodeId, DataValue, Variant, StatusCode, etc.) are represented as JSON for LLM-friendly interaction. Variant serialization dispatches by `BuiltInType`, so scalar defaults such as Boolean `false` and numeric `0` remain JSON `false` / `0` instead of being confused with `Variant.Null`.
|
|
|
|
The packet-capture tools are described in detail in [Diagnostics](Diagnostics.md#4-packet-capture-dissection-and-replay). For convenience the per-tool surface is:
|
|
|
|
| Tool | Description | Parameters |
|
|
|---|---|---|
|
|
| `list_interfaces` | Enumerates NICs available to SharpPcap; `linkType` may be `null` because enumeration does not open adapters. | None |
|
|
| `start_capture` | Starts a capture session. | `source`: `nic \| inproc-client \| inproc-server \| replay`; optional interface, filter, endpoint, limits, folder |
|
|
| `stop_capture` | Stops an active session and finalizes artifacts. | `sessionId` |
|
|
| `list_captures` | Lists capture sessions. | Optional `state` |
|
|
| `get_capture` | Returns an artifact or formatted analysis. | `sessionId`; `format`: `pcap \| pcapng \| json \| csv \| text \| service-timeline`; optional packet/partial controls |
|
|
| `capture_now` | Starts, waits, stops, and returns output. | Capture options plus the same output `format` values |
|
|
| `list_active_channels` | Lists in-process secure channels with current tokens. | None |
|
|
| `dump_keys` | Emits keylog data. | Optional `sessionId`, `format`, `includeExpired` |
|
|
| `decode_pcap_with_keys` | Decodes an existing pcap and keylog offline. | `pcapPath`, `keylogPath`, `format`, optional `maxFrames` |
|
|
| `summarize_service_calls` | Reports service counts, latency, and errors. | `sessionId` or `pcapPath` + `keylogPath`, optional `top` |
|
|
| `replay_pcap` | Replays as a mock server or mock client. | `pcapPath`, `keylogPath`, `mode`, endpoints, `speed` |
|
|
| `stop_replay` | Stops an active replay session. | `sessionId` |
|
|
| `list_replays` | Lists active and recently-completed replay sessions. | None |
|
|
|
|
The canonical hyphenated values above are emitted on output. CLR enum
|
|
names such as `InProcessClient` and `ServiceTimeline` remain accepted
|
|
on input.
|
|
|
|
## Tool Profiles
|
|
|
|
The server selects its tool catalog through a **tool profile** — a bounded set of tool classes registered at startup. Profiles let a client request only the tools it needs (smaller catalogs are easier for an LLM to reason about and reduce prompt size), while `full` preserves the complete surface for clients that want everything.
|
|
|
|
| Profile | Tool classes registered | Typical use case |
|
|
|---|---|---|
|
|
| `core` | Configuration, Connection, Convenience | Minimal footprint: connect, read/write values, adjust settings |
|
|
| `services` | Attribute, Configuration, Connection, Convenience, Discovery, Method, MonitoredItem, Node Management, Subscription, View | Full OPC UA Part 4 client workflows without PKI/PubSub/packet capture |
|
|
| `administration` | Configuration, Connection, NodeSet Export, PKI Management | Certificate trust management and NodeSet export |
|
|
| `pubsub` | PubSub runtime, discovery, action, and capture tools (plus PubSub decode when diagnostics tools are enabled) | Part 14 PubSub publish/subscribe, discovery, and capture workflows |
|
|
| `diagnostics` | Connection, Packet Capture (plus decode/replay when diagnostics tools are enabled) | OPC UA-aware packet capture, offline decode, and replay |
|
|
| `robotics` | Connection plus Robot Intent discovery, paged monitoring, control, mission and Vision-guided Pick tools | Commanding and monitoring a Robot Intent controller |
|
|
| `vision` | Connection plus the Vision discovery, monitoring, seeing, inference, feedback and geometry tools | Perception-driven agents that need to see through a Vision server, compose poses across the §5.12 frame graph, run or submit inference, and (when composed with `robotics`) act on what they see — see the [Vision developer guide](Vision.md) |
|
|
| `full` (default) | Every tool class above | Unrestricted access; the current-major default so existing integrations keep working unchanged |
|
|
|
|
`full` is the default for the current major version — `core` and the other bounded profiles are opt-in. Select a profile with:
|
|
|
|
- The `--profile` CLI option, e.g. `opcua-mcp --profile core`
|
|
- The `McpServer:ToolProfile` configuration value
|
|
- The `OPCUA_MCP_TOOL_PROFILE` environment variable
|
|
|
|
**Profiles compose.** A `--profile` value can name more than one bounded profile at a time — the `BinPickingClient` sample runs `--profile vision,robotics` and exposes both catalogs from the same MCP host, deduplicating the shared `Connection` tools. The composed set uses the `WithOpcUaCoreTools(McpToolProfileSet)` / `WithOpcUaVisionTools(McpToolProfileSet)` / `WithOpcUaRoboticsTools(McpToolProfileSet)` overloads, and the core-tools overload owns the single `ConnectionTools` registration across every package that references the same MCP server. See the [Vision developer guide](Vision.md#mcp-tools) for the composed 64-tool example and the [BinPickingClient sample](../samples/Robotics/BinPickingClient) for the running catalog.
|
|
|
|
Because the exact number of tools in each profile (and in `full`) changes as tools are added or removed, this document intentionally does not hard-code a tool count. Use the tables above (or `tools/list`) to enumerate the tools actually exposed by a running server.
|
|
|
|
### Vision-guided Robotics
|
|
|
|
`robotics_vision_pick` closes the common perception-to-action path without
|
|
making an agent copy a result NodeId and several resource NodeIds between tool
|
|
calls. It runs one detection inference through `Opc.Ua.Vision.Client`, on the
|
|
same named OPC UA session as the Robot Intent controller, then submits either
|
|
one Pick or a two-step Pick/Place mission:
|
|
|
|
```json
|
|
{
|
|
"request": {
|
|
"controller": "BinPickingController",
|
|
"pipeline": "BinPickingPipeline",
|
|
"source": "Bin",
|
|
"tool": "ParallelGripper",
|
|
"destination": "Fixture",
|
|
"classLabel": "RedCube",
|
|
"minimumConfidence": 0.9,
|
|
"missionId": "place-red-cube"
|
|
}
|
|
}
|
|
```
|
|
|
|
Detection selection is deterministic: exact DetectionId/ClassLabel filters and
|
|
the confidence threshold are applied first, then highest confidence wins with
|
|
ordinal DetectionId and original result order as tie-breakers. The result
|
|
contains Vision result/pipeline/sensor/model/frame provenance, the selected
|
|
pose, and the authoritative intent or mission handle. The helper does not
|
|
request authority, wait, retry, cancel, or reinterpret a server refusal.
|
|
|
|
## Resources
|
|
|
|
The MCP server exposes connected sessions as **MCP resources**, enabling the LLM to discover, inspect, and subscribe to session state.
|
|
|
|
| Resource URI | Type | Description |
|
|
|---|---|---|
|
|
| `opcua://sessions` | Direct | List all active sessions with connection status |
|
|
| `opcua://sessions/{name}` | Template | Full details of a named session (endpoint, security, namespaces) |
|
|
| `opcua://sessions/{name}/namespaces` | Template | Server namespace table for a session |
|
|
|
|
### Multi-Session Support
|
|
|
|
The server supports **multiple simultaneous sessions** to different OPC UA servers. Each session is identified by a name.
|
|
|
|
```
|
|
Tool: Connect
|
|
endpointUrl: "opc.tcp://server1:62541/ReferenceServer"
|
|
name: "refserver" (optional — auto-generated from hostname if omitted)
|
|
autoAcceptCerts: true
|
|
|
|
Tool: Connect
|
|
endpointUrl: "opc.tcp://plc1:4840"
|
|
name: "plc1"
|
|
|
|
Tool: Browse
|
|
nodeId: "i=85"
|
|
sessionName: "refserver" (optional — uses the only session if there's just one)
|
|
|
|
Tool: ReadValue
|
|
nodeId: "ns=2;s=Temperature"
|
|
sessionName: "plc1"
|
|
```
|
|
|
|
Sessions are listed via `resources/list` and detailed via `resources/read`.
|
|
|
|
## Installation
|
|
|
|
### Option 1: Run without installing (.NET 10 SDK)
|
|
|
|
Run the published tool directly from nuget.org. `dotnet tool exec` downloads
|
|
and caches the tool without adding a global tool installation:
|
|
|
|
```bash
|
|
# Run the latest release
|
|
dotnet tool exec OPCFoundation.NetStandard.Opc.Ua.Mcp
|
|
|
|
# Or stay on one release line, for example 2.0.x
|
|
dotnet tool exec "OPCFoundation.NetStandard.Opc.Ua.Mcp@2.0.*"
|
|
|
|
# Short form of dotnet tool exec
|
|
dnx OPCFoundation.NetStandard.Opc.Ua.Mcp
|
|
```
|
|
|
|
### Option 2: Install as a .NET global tool
|
|
|
|
```bash
|
|
dotnet tool install --global OPCFoundation.NetStandard.Opc.Ua.Mcp
|
|
```
|
|
|
|
After installation, the `opcua-mcp` command is available globally.
|
|
|
|
The tool includes every [tool profile](#tool-profiles), including `robotics`,
|
|
`vision`, and the composed `vision,robotics` profile. Only the libraries for
|
|
embedding the Robotics and Vision tools in your own server are preview
|
|
packages; see [Packages](#packages).
|
|
|
|
### Option 3: Run from source
|
|
|
|
```bash
|
|
cd tools/Opc.Ua.Mcp
|
|
dotnet run -c Release
|
|
```
|
|
|
|
### Option 4: Install from local build
|
|
|
|
```bash
|
|
dotnet pack tools/Opc.Ua.Mcp/Opc.Ua.Mcp.csproj -c Release
|
|
dotnet tool install --global --prerelease --add-source tools/Opc.Ua.Mcp/bin/Release OPCFoundation.NetStandard.Opc.Ua.Mcp
|
|
```
|
|
|
|
If multiple prerelease versions are visible from configured sources, add
|
|
`--version <the-version-produced-by-dotnet-pack>` to select the local package
|
|
explicitly.
|
|
|
|
## Configuration
|
|
|
|
### Run on demand without a global installation
|
|
|
|
MCP clients that accept an executable and argument array can launch the tool
|
|
through `dotnet tool exec`. Put MCP tool arguments after `--`:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"opcua": {
|
|
"command": "dotnet",
|
|
"args": [
|
|
"tool",
|
|
"exec",
|
|
"OPCFoundation.NetStandard.Opc.Ua.Mcp",
|
|
"--",
|
|
"--profile",
|
|
"core"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Claude Desktop
|
|
|
|
Add to your `claude_desktop_config.json` (typically at `%APPDATA%\Claude\claude_desktop_config.json` on Windows or `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"opcua": {
|
|
"command": "opcua-mcp"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### VS Code / GitHub Copilot
|
|
|
|
Add to your workspace `.vscode/mcp.json`:
|
|
|
|
```json
|
|
{
|
|
"servers": {
|
|
"opcua": {
|
|
"command": "opcua-mcp"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Cursor
|
|
|
|
Add to your Cursor MCP settings:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"opcua": {
|
|
"command": "opcua-mcp"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### HTTP Transport (for remote clients)
|
|
|
|
By default, the server uses stdio transport for local tool integration. For remote clients, use the Streamable HTTP transport, exposed only at the `/mcp` path (there is no root route):
|
|
|
|
```bash
|
|
opcua-mcp --transport http --port 5100
|
|
```
|
|
|
|
The server listens at `http://localhost:5100/mcp`. `--transport sse` is a deprecated alias for `http` kept for the current major version only — prefer `http` in new configurations.
|
|
|
|
## Usage
|
|
|
|
### Typical Workflow
|
|
|
|
**1. Discover endpoints (no session required):**
|
|
|
|
```
|
|
Tool: GetEndpoints
|
|
endpointUrl: "opc.tcp://localhost:62541/Quickstarts/ReferenceServer"
|
|
```
|
|
|
|
**2. Connect to an OPC UA server (auto-select most secure, anonymous):**
|
|
|
|
```
|
|
Tool: Connect
|
|
endpointUrl: "opc.tcp://localhost:62541/Quickstarts/ReferenceServer"
|
|
autoAcceptCerts: true
|
|
```
|
|
|
|
**Or connect with specific security and authentication:**
|
|
|
|
```
|
|
Tool: Connect
|
|
endpointUrl: "opc.tcp://localhost:62541/Quickstarts/ReferenceServer"
|
|
securityMode: "SignAndEncrypt"
|
|
securityPolicy: "Basic256Sha256"
|
|
authType: "Username"
|
|
username: "admin"
|
|
password: "password"
|
|
autoAcceptCerts: true
|
|
```
|
|
|
|
**2. Explore the address space:**
|
|
|
|
```
|
|
Tool: BrowseAll
|
|
nodeId: "i=85" (Objects folder)
|
|
maxDepth: 2
|
|
maxResults: 50
|
|
```
|
|
|
|
**3. Read values:**
|
|
|
|
```
|
|
Tool: ReadValue
|
|
nodeId: "ns=2;s=MyTemperatureSensor"
|
|
```
|
|
|
|
**4. Write values:**
|
|
|
|
```
|
|
Tool: WriteValue
|
|
nodeId: "ns=2;s=MySetpoint"
|
|
value: "72.5"
|
|
dataType: "Double"
|
|
```
|
|
|
|
**5. Call a method:**
|
|
|
|
```
|
|
Tool: CallMethod
|
|
objectId: "ns=2;s=MyMachine"
|
|
methodId: "ns=2;s=StartProcess"
|
|
inputArguments: ["fast", "true"]
|
|
```
|
|
|
|
**6. Monitor changes:**
|
|
|
|
```
|
|
Tool: CreateSubscription
|
|
publishingInterval: 1000
|
|
|
|
Tool: CreateMonitoredItems
|
|
subscriptionId: <from above>
|
|
nodeIds: ["ns=2;s=Temperature", "ns=2;s=Pressure"]
|
|
|
|
Tool: Publish
|
|
(retrieves queued notifications)
|
|
```
|
|
|
|
**7. Manage PKI (trust rejected certificates):**
|
|
|
|
```
|
|
Tool: ListCertificates
|
|
store: "Rejected"
|
|
|
|
Tool: TrustCertificate
|
|
thumbprint: "A1B2C3..." (from ListCertificates results)
|
|
|
|
Tool: GetPkiStorePaths
|
|
(shows where certificate stores are located on disk)
|
|
```
|
|
|
|
**8. Adjust configuration for current session:**
|
|
|
|
```
|
|
Tool: GetConfiguration
|
|
(view current settings)
|
|
|
|
Tool: SetConfiguration
|
|
operationTimeout: 60000
|
|
maxArrayLength: 131072
|
|
autoAcceptUntrustedCertificates: true
|
|
```
|
|
|
|
**9. Export the server's address space to NodeSet2 XML:**
|
|
|
|
```
|
|
Tool: ExportNodeSet
|
|
filePath: "C:\\export\\server-nodeset.xml"
|
|
startingNodeId: "i=85" (Objects folder)
|
|
exportMode: "Complete" (includes values)
|
|
```
|
|
|
|
Or export split by namespace (one file per companion spec):
|
|
|
|
```
|
|
Tool: ExportNodeSetPerNamespace
|
|
outputDirectory: "C:\\export\\namespaces"
|
|
```
|
|
|
|
**10. Disconnect:**
|
|
|
|
```
|
|
Tool: Disconnect
|
|
```
|
|
|
|
### NodeId Formats
|
|
|
|
The MCP server accepts NodeIds in standard OPC UA string format:
|
|
|
|
| Format | Example | Description |
|
|
|---|---|---|
|
|
| Numeric | `i=2258` | Numeric identifier in namespace 0 |
|
|
| Numeric with namespace | `ns=2;i=1001` | Numeric identifier in namespace 2 |
|
|
| String | `ns=2;s=MyVariable` | String identifier |
|
|
| GUID | `ns=2;g=12345678-1234-1234-1234-123456789abc` | GUID identifier |
|
|
| Opaque | `ns=2;b=Base64EncodedData` | ByteString identifier |
|
|
|
|
### Common Well-Known NodeIds
|
|
|
|
| NodeId | Description |
|
|
|---|---|
|
|
| `i=84` | Root node |
|
|
| `i=85` | Objects folder |
|
|
| `i=86` | Types folder |
|
|
| `i=87` | Views folder |
|
|
| `i=2253` | Server object |
|
|
| `i=2258` | Server/ServerStatus/CurrentTime |
|
|
|
|
### Error Handling
|
|
|
|
When an OPC UA service returns an error, tools return a structured JSON response:
|
|
|
|
```json
|
|
{
|
|
"error": true,
|
|
"statusCode": "BadNodeIdUnknown",
|
|
"message": "The node id refers to a node that does not exist in the server address space."
|
|
}
|
|
```
|
|
|
|
This is normal behavior — not all servers support all services. Common status codes:
|
|
|
|
| Status Code | Meaning |
|
|
|---|---|
|
|
| `BadServiceUnsupported` | Server doesn't implement this service |
|
|
| `BadNodeIdUnknown` | NodeId doesn't exist |
|
|
| `BadNotWritable` | Node attribute is read-only |
|
|
| `BadMethodInvalid` | Method not found on the specified object |
|
|
| `BadUserAccessDenied` | Insufficient permissions |
|
|
|
|
## PubSub Tools
|
|
|
|
In addition to the client services above, the server exposes OPC UA PubSub
|
|
(Part 14) tools, backed by `Opc.Ua.PubSub` and
|
|
`Opc.Ua.PubSub.Diagnostics`. See
|
|
[Diagnostics.md §5](Diagnostics.md#5-pubsub-packet-capture-and-dissection) for
|
|
the capture / dissection details.
|
|
|
|
**Configuration and Security Key Service methods.** PubSub configuration
|
|
(`AddConnection`, `AddWriterGroup`, `AddReaderGroup`, `AddDataSetWriter`,
|
|
`AddDataSetReader`, `Status.Enable` / `Disable`) and the Security Key Service
|
|
(`GetSecurityKeys`, `AddSecurityGroup` / `RemoveSecurityGroup`) are standard
|
|
server-side `PublishSubscribe` object methods, so they are invoked with the
|
|
generic [`Call`](#usage) tool rather than dedicated wrappers — pass the
|
|
`PublishSubscribe` object NodeId (or the target connection / group NodeId) and
|
|
the corresponding method NodeId (e.g. `i=14443` for
|
|
`PublishSubscribe_AddConnection`, `i=15215` for
|
|
`PublishSubscribe_GetSecurityKeys`).
|
|
|
|
**In-process publish/subscribe runtime:**
|
|
|
|
| Tool | Purpose |
|
|
| --- | --- |
|
|
| `pubsub_runtime_start_publisher` / `pubsub_runtime_start_subscriber` | Start an in-process UDP publisher / subscriber |
|
|
| `pubsub_runtime_publish` | Publish a DataSet update |
|
|
| `pubsub_runtime_read_received` | Read DataSets received by the subscriber |
|
|
| `pubsub_runtime_status` / `pubsub_runtime_stop` | Status / stop the runtime |
|
|
|
|
**Discovery** (Part 14 §7.2.4.6 — send a discovery request from the active
|
|
runtime and collect publisher responses):
|
|
|
|
| Tool | Purpose |
|
|
| --- | --- |
|
|
| `pubsub_discover_metadata` | Learn the field-level schema of a DataSetWriter (names, field count) |
|
|
| `pubsub_discover_writer_config` | Learn a publisher's WriterGroupId and DataSetWriterIds |
|
|
| `pubsub_discover_publisher_endpoints` | Learn a publisher's transport endpoint URLs |
|
|
|
|
**Actions** (Part 14 §7.2.5.6 — request/response over PubSub):
|
|
|
|
| Tool | Purpose |
|
|
| --- | --- |
|
|
| `pubsub_invoke_action` | Invoke an action target and await the correlated response |
|
|
| `pubsub_register_action_responder` | Register a demo/echo responder for round-trip testing |
|
|
| `pubsub_bind_action_method` | Bind an action to a server method (ObjectId/MethodId) |
|
|
| `pubsub_list_action_targets` / `pubsub_list_action_responders` | List known targets / registered responders |
|
|
|
|
**Capture and dissection:**
|
|
|
|
| Tool | Purpose |
|
|
| --- | --- |
|
|
| `pubsub_start_capture` / `pubsub_stop_capture` / `pubsub_capture_status` | Manage an in-process PubSub capture session |
|
|
| `pubsub_write_pcap` | Flush captured frames to `.pcap` / `.pcapng` |
|
|
| `pubsub_dissect_capture` | Dissect captured frames (decrypts encrypted UADP when a key log is supplied) |
|
|
| `pubsub_decode_pcap` | Decode a libpcap file of UDP PubSub traffic |
|
|
| `pubsub_load_keylog` | Load a PubSub key log for offline decryption |
|
|
|
|
## Architecture
|
|
|
|
The MCP tools ship as six libraries plus the executable that composes them.
|
|
The executable owns only transport, logging and CLI plumbing; every tool lives
|
|
in a library that an application can reference on its own.
|
|
|
|
```
|
|
tools/
|
|
├── Opc.Ua.Mcp.Core/ # Part 4 service tools, session manager, options, filters
|
|
│ ├── OpcUaMcpCoreExtensions.cs # AddOpcUaMcpCore, WithOpcUaCoreTools, WithOpcUaMcpFilters
|
|
│ ├── OpcUaSessionManager.cs # OPC UA client session lifecycle
|
|
│ ├── McpCapturePath.cs # Path-traversal guard shared by the capture packages
|
|
│ ├── Tools/
|
|
│ │ ├── ConnectionTools.cs # GetEndpoints, Connect, Disconnect, GetConnectionStatus
|
|
│ │ ├── AttributeServiceTools.cs # Read, Write, HistoryRead, HistoryUpdate
|
|
│ │ ├── ViewServiceTools.cs # Browse, BrowseNext, TranslateBrowsePaths, etc.
|
|
│ │ ├── NodeManagementServiceTools.cs# AddNodes, AddReferences, DeleteNodes, etc.
|
|
│ │ ├── MethodServiceTools.cs # Call
|
|
│ │ ├── SubscriptionServiceTools.cs # CreateSubscription, Publish, etc.
|
|
│ │ ├── MonitoredItemServiceTools.cs # CreateMonitoredItems, etc.
|
|
│ │ ├── DiscoveryServiceTools.cs # FindServers, RegisterServer, etc.
|
|
│ │ ├── PkiTools.cs # ListCertificates, TrustCertificate, etc.
|
|
│ │ ├── ConfigurationTools.cs # Full-profile compatibility configuration tools
|
|
│ │ ├── ConfigurationReadTools.cs # Profile-safe configuration reader
|
|
│ │ ├── ConfigurationUpdateTools.cs # Focused transport/client/security setters
|
|
│ │ ├── NodeSetExportTools.cs # ExportNodeSet, ExportNodeSetPerNamespace
|
|
│ │ └── ConvenienceTools.cs # ReadValue, BrowseAll, CallMethod, etc.
|
|
│ └── Serialization/
|
|
│ └── OpcUaJsonHelper.cs # OPC UA ↔ JSON type conversion
|
|
├── Opc.Ua.Mcp.PubSub/ # PubSub runtime, actions and discovery
|
|
│ ├── PubSubRuntimeManager.cs
|
|
│ └── Tools/{PubSubRuntime,PubSubAction,PubSubDiscovery}Tools.cs
|
|
├── Opc.Ua.Mcp.Diagnostics/ # UA-TCP capture, decode and replay
|
|
│ └── Tools/{PacketCapture,PacketDecode,PacketReplay}Tools.cs
|
|
├── Opc.Ua.Mcp.PubSub.Diagnostics/ # PubSub capture and decode
|
|
│ └── Tools/{PubSubCapture,PubSubDecode}Tools.cs
|
|
├── Opc.Ua.Mcp.Robotics/ # Robot Intent plus same-session Vision-guided picking
|
|
│ ├── RoboticsIntentManager.cs
|
|
│ ├── VisionGuidedRoboticsManager.cs
|
|
│ └── Tools/Robotics{Discovery,Monitoring,Control,Mission,Vision}Tools.cs
|
|
├── Opc.Ua.Mcp.Vision/ # Vision discovery, monitoring, seeing, inference, feedback, geometry
|
|
│ ├── VisionClientAccessor.cs
|
|
│ └── Tools/Vision{Discovery,Monitoring,Seeing,Inference,Feedback,Geometry}Tools.cs
|
|
└── Opc.Ua.Mcp/ # .NET 10 project, packaged as dotnet tool
|
|
├── Program.cs # Entry point, stdio + Streamable HTTP transport (/mcp)
|
|
├── McpHostBuilder.cs # Composes the six libraries
|
|
├── Opc.Ua.Mcp.Config.xml # OPC UA client application config
|
|
└── .mcp/server.json # MCP server manifest for NuGet discovery
|
|
```
|
|
|
|
### Packages
|
|
|
|
| Package | Tools | Depends on |
|
|
|---|---|---|
|
|
| `OPCFoundation.NetStandard.Opc.Ua.Mcp.Core` | Part 4 services, connection, configuration, PKI, NodeSet export | `Opc.Ua.Core`, `.Configuration`, `.Client` |
|
|
| `OPCFoundation.NetStandard.Opc.Ua.Mcp.PubSub` | PubSub runtime, actions, discovery | Core + `Opc.Ua.PubSub` |
|
|
| `OPCFoundation.NetStandard.Opc.Ua.Mcp.Diagnostics` | UA-TCP capture, decode, replay | Core + `Opc.Ua.Core.Diagnostics` |
|
|
| `OPCFoundation.NetStandard.Opc.Ua.Mcp.PubSub.Diagnostics` | PubSub capture, decode | Core + `Opc.Ua.PubSub.Diagnostics` |
|
|
| `OPCFoundation.NetStandard.Opc.Ua.Mcp.Robotics` | Robot Intent discovery, typed control/missions, paged monitoring, Vision-guided Pick | Core + `Opc.Ua.Robotics.Client` + `Opc.Ua.Vision.Client` |
|
|
| `OPCFoundation.NetStandard.Opc.Ua.Mcp.Vision` | Vision discovery, monitoring, seeing (`vision_get_frame` returns an MCP `ImageContentBlock`), inference, off-server feedback, §5.12 pose composition | Core + `Opc.Ua.Vision.Client` |
|
|
| `OPCFoundation.NetStandard.Opc.Ua.Mcp` | the ready-to-run `opcua-mcp` tool | all of the above |
|
|
|
|
The libraries multi-target `net8.0;net9.0;net10.0`; the executable targets
|
|
`net10.0`. `Mcp.Robotics` and `Mcp.Vision` are preview packages; the other
|
|
libraries and the `opcua-mcp` tool, which includes all of them, are stable.
|
|
|
|
### Embedding the tools in your own MCP server
|
|
|
|
An application that wants OPC UA tools *and* its own application-level tools
|
|
composes them rather than shelling out to `opcua-mcp`:
|
|
|
|
```csharp
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Opc.Ua.Mcp;
|
|
|
|
builder.Services.AddOpcUaMcpCore();
|
|
|
|
builder.Services.AddMcpServer()
|
|
.WithStdioServerTransport()
|
|
.WithOpcUaMcpFilters()
|
|
.WithOpcUaCoreTools(McpToolProfile.Services)
|
|
.WithTools<MyApplicationTools>();
|
|
```
|
|
|
|
Add any of the other packages the same way — each contributes a service
|
|
registration and a tool registration:
|
|
|
|
```csharp
|
|
builder.Services.AddOpcUaMcpPubSub();
|
|
builder.Services.AddOpcUaMcpDiagnostics();
|
|
builder.Services.AddOpcUaMcpPubSubDiagnostics();
|
|
builder.Services.AddOpcUaMcpRobotics();
|
|
builder.Services.AddOpcUaMcpVision();
|
|
|
|
mcp.WithOpcUaPubSubTools(profile)
|
|
.WithOpcUaDiagnosticsTools(profile, diagnosticsEnabled)
|
|
.WithOpcUaPubSubDiagnosticsTools(profile, diagnosticsEnabled)
|
|
.WithOpcUaRoboticsTools(profile)
|
|
.WithOpcUaVisionTools(profile);
|
|
```
|
|
|
|
`WithOpcUaMcpFilters` registers the request and schema filters that make tool
|
|
errors actionable and tool schemas explicit. Call it once per server, even when
|
|
several OPC UA tool packages are composed.
|
|
|
|
`McpToolProfile` is shared vocabulary that lives in Core, and each package maps
|
|
the profile to its own tools. A profile a package does not own contributes
|
|
nothing rather than failing, so the same profile value can be passed to every
|
|
package a host references — `Full` in a host that never referenced
|
|
`Opc.Ua.Mcp.Diagnostics` simply yields no capture tools.
|
|
|
|
Bounded profiles that own their own connection tools — `Vision` in the
|
|
example above — carry `ConnectionTools` themselves in the single-profile
|
|
overload of `WithOpcUa...Tools`. When two or more bounded profiles are
|
|
composed through the `McpToolProfileSet` overloads (for example the
|
|
[`vision,robotics` composition](Vision.md#mcp-tools) the BinPickingClient
|
|
sample runs), the corresponding `WithOpcUaCoreTools(McpToolProfileSet)`
|
|
overload owns and deduplicates `ConnectionTools` across every package.
|
|
Each Vision or Robotics package's `McpToolProfileSet` overload never
|
|
registers `ConnectionTools` directly, so the composed catalog contains
|
|
one Connection surface, not several.
|
|
|
|
The capture tool classes stay `internal` and are reachable only through their
|
|
registration extensions.
|
|
|
|
## Security Notes
|
|
|
|
- The `autoAcceptCerts` parameter is for **testing only**. In production, configure proper certificate trust using the OPC UA certificate stores under `%LocalApplicationData%/OPC Foundation/pki/`.
|
|
- The server supports simultaneous named OPC UA sessions. Use the intended session identifier for each operation and disconnect that session when finished; connecting to another server does not require closing unrelated sessions.
|
|
- Application certificates are automatically created on first use and stored in the local certificate store.
|
|
- Logs are written to `%LocalApplicationData%/OPC Foundation/Logs/McpServer.log.txt`.
|
|
|
|
## Agent-Usability Quality Gate
|
|
|
|
Contributors can run the same deterministic static and live-probe grading used in CI:
|
|
|
|
```powershell
|
|
./tools/Opc.Ua.Mcp/Test-McpGrade.ps1
|
|
```
|
|
|
|
The script builds the server, checks out `mcpgrade` at the reviewed commit pinned in the script,
|
|
grades the `core` and `full` Streamable HTTP catalogs, and probes the full stdio catalog. Reports
|
|
are written under `artifacts/mcpgrade` by default.
|
|
|
|
The repository `.mcpgraderc.json` disables N002 after descriptions have been disambiguated.
|
|
`RegisterServer`/`RegisterServer2` are OPC UA standard service names, while
|
|
`ReadValue`/`ReadValues` and `GetConfiguration`/`SetConfiguration` are compatibility-sensitive
|
|
singular/plural and get/set pairs. These names must not be changed solely to satisfy edit-distance
|
|
heuristics.
|
|
|
|
## Requirements
|
|
|
|
- .NET 10 SDK or later
|
|
- An OPC UA server to connect to
|