Files
Marc Schier 8772f37275 Fix recycling scenario defaults and MCP interoperability (#4808)
# Description

Fix five failures reproduced while exercising the recycling sample
through a locally built OPC UA MCP server:

- Support Certificate authentication through named, host-approved X.509
identity selectors and the existing certificate/identity providers. Tool
arguments cannot supply private keys or arbitrary certificate-store
paths.
- Register custom enumeration dependencies from the validated, bounded
type snapshot before loading requested structure roots.
- Preserve structured fields and opaque encoded bodies in generic
read/call results using the selected session's UA codecs.
- Add bounded, explicitly typed UA JSON method arguments while retaining
the existing string argument behavior and C# overloads.
- Preserve omitted defaults in sparse recycling scenario JSON; explicit
invalid values and unknown members still fail validation. All six
shipped scenario files are covered by regressions.

Update the MCP and recycling documentation. This PR contains one fix
commit on a feature branch in **OPCFoundation/UA-.NETStandard**, based
directly on upstream `master` at `95850b7e5`. No local registration,
certificates, scenario journals or live-test artifacts are included.

### Validation

**Final commit `d199feba0`: 216 affected MCP tests and 16 recycling
CLI/scenario tests passed on .NET 10**, with no failures, fixture
setup/teardown errors or build/analyzer warnings. The repository's TRX
verdict helper accepted both reports.

**Draft: the full-solution gate is not green.** The .NET 10 solution run
encountered an `Opc.Ua.OneFuzz.Validator.Tests` fixture-publication
failure outside the files changed by this PR: `MSB3030`, missing
`Opc.Ua.OneFuzz.TestDependency.runtimeconfig.json`. It affected 210
tests; the run was stopped rather than expanding this PR into unrelated
OneFuzz work. The full .NET Framework 4.8 solution suite was not run.

Before the final rebase, the complete managed recycling suite passed
**117**, and the CLI/scenario tests passed **16 each on .NET 8 and .NET
9**, with no failures or fixture teardown errors. The five explicit
NativeAOT smoke cases were not selected.

Actual live qualification used one coordinator and all ten independent
process servers with strict certificate trust. Healthy, combined-fault
and zero-utility runs each produced 24 complete packages with exact
component conservation. Also exercised native companion discovery,
subscriptions, authorization, pause/step/enable/disable, durable request
replay, quality holds, reset and coordinator crash recovery. NativeAOT
executables, container deployment and parity against a complete external
producer contract were not qualified.

<details>
<summary>Exact validation commands and results</summary>

Commands ran from the repository root with an isolated .NET SDK
10.0.401. `$root` denotes the private validation-artifact directory; no
machine-specific path or key material is included here.

Affected MCP matrix, final commit — **passed: 216; failed: 0; skipped:
0**:

```powershell
dotnet test tests\Opc.Ua.Tools.Tests\Opc.Ua.Tools.Tests.csproj -c Release -f net10.0 -p:CustomTestTarget=net10.0 -p:CustomTargetFrameworks=net10.0 -p:UseSharedCompilation=false -m:1 -nr:false --no-restore --nologo -v:quiet --filter 'FullyQualifiedName~SchemaRemoteTests|FullyQualifiedName~OpcUaJsonHelperTests|FullyQualifiedName~MethodServiceToolsTests|FullyQualifiedName~ConvenienceToolsTests|FullyQualifiedName~AttributeServiceToolsTests|FullyQualifiedName~ViewServiceToolsTests|FullyQualifiedName~OpcUaSessionManagerTests|FullyQualifiedName~ConnectionToolsTests|FullyQualifiedName~McpHostBuilderTests|FullyQualifiedName~ConfigurationToolsTests' --logger 'trx;LogFileName=mcp-pr.trx' --results-directory "$root\pr-validation\focused"
```

.NET 10 CLI/scenario regressions, final commit — **passed: 16; failed:
0; skipped: 0**:

```powershell
dotnet test tests\Opc.Ua.Recycling.Samples.Tests\Opc.Ua.Recycling.Samples.Tests.csproj -c Release -f net10.0 -p:CustomTestTarget=net10.0 -p:CustomTargetFrameworks=net10.0 -p:UseSharedCompilation=false -m:1 -nr:false --no-restore --nologo -v:quiet --filter 'FullyQualifiedName~RecyclingCommandLineTests' --logger 'trx;LogFileName=recycling-cli-pr.trx' --results-directory "$root\pr-validation\focused"
```

Complete managed recycling suite, before rebase — **passed: 117; failed:
0; skipped: 0** (five explicit NativeAOT cases not selected):

```powershell
dotnet test tests\Opc.Ua.Recycling.Samples.Tests\Opc.Ua.Recycling.Samples.Tests.csproj -c Release -f net10.0 -p:CustomTestTarget=net10.0 -p:CustomTargetFrameworks=net10.0 -p:UseSharedCompilation=false -m:1 -nr:false --no-restore --nologo -v:quiet --logger 'trx;LogFileName=recycling-final.trx' --results-directory (Join-Path $root 'results')
```

.NET 8 CLI/scenario regressions, before rebase — **passed: 16; failed:
0; skipped: 0**:

```powershell
dotnet test tests\Opc.Ua.Recycling.Samples.Tests\Opc.Ua.Recycling.Samples.Tests.csproj -c Release -f net8.0 -p:CustomTestTarget=net8.0 -p:CustomTargetFrameworks=net8.0 -p:UseSharedCompilation=false -m:1 -nr:false --nologo -v:quiet --filter 'FullyQualifiedName~RecyclingCommandLineTests' --logger 'trx;LogFileName=recycling-cli-net8.trx' --results-directory "$root\results"
```

.NET 9 CLI/scenario regressions, before rebase — **passed: 16; failed:
0; skipped: 0**:

```powershell
dotnet test tests\Opc.Ua.Recycling.Samples.Tests\Opc.Ua.Recycling.Samples.Tests.csproj -c Release -f net9.0 -p:CustomTestTarget=net9.0 -p:CustomTargetFrameworks=net9.0 -p:UseSharedCompilation=false -m:1 -nr:false --nologo -v:quiet --filter 'FullyQualifiedName~RecyclingCommandLineTests' --logger 'trx;LogFileName=recycling-cli-net9.trx' --results-directory "$root\results"
```

Full .NET 10 solution — **not passed**: stopped after the OneFuzz
fixture failure above; incomplete solution run, not a clean validation
result:

```powershell
dotnet test UA.slnx -c Release -p:CustomTestTarget=net10.0 -p:CustomTargetFrameworks=net10.0 -p:UseSharedCompilation=false -m:1 -nr:false --nologo -v:quiet --logger trx --results-directory "$root\pr-validation\net10"
```

</details>

## Related Issues

Follow-up to
[#4772](https://github.com/OPCFoundation/UA-.NETStandard/pull/4772),
which introduced the recycling sample. No separate tracking issue is
currently linked. These fixes preserve the existing architecture and
address failures reproduced during live qualification.

## Checklist

_Put an `x` in the boxes that apply. You can complete these step by step
after opening the PR._

- [ ] 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.

Regression tests were added and passed as recorded above; aggregate
coverage was not collected, so the combined coverage checklist item
remains unchecked.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
2026-10-16 11:41:51 +02:00

9.5 KiB

OPC UA MCP Server

A Model Context Protocol (MCP) server that exposes OPC UA Part 4 service calls as MCP tools, enabling AI assistants (Claude, GitHub Copilot, VS Code, etc.) to interact with OPC UA servers.

Run without installing (.NET 10 SDK)

dotnet tool exec OPCFoundation.NetStandard.Opc.Ua.Mcp

# Short form
dnx OPCFoundation.NetStandard.Opc.Ua.Mcp

Install globally

dotnet tool install --global OPCFoundation.NetStandard.Opc.Ua.Mcp

The tool includes Robotics, Vision and the AMB, Machinery, Scales, Pumps, Device Integration, ISA-95, Positioning, MachineTool (with bundled WMTP), GMS, CranesHoists, WoT and xRegistry profiles. Profiles compose, for example --profile machinery,isa95, --profile machinetool,gms,craneshoists, or --profile core,wot,xregistry,wot-documents. wot-documents needs no UA connection. Additional profiles expose GDS/credential issuance, roles/users, files, alarms, history, schemas, PubSub configuration/bridges/SKS and live WoT execution.

Usage

The examples below assume a global installation. For run-on-demand use, replace opcua-mcp with dnx OPCFoundation.NetStandard.Opc.Ua.Mcp --.

# stdio transport (default) — for Claude Desktop, VS Code, Copilot
opcua-mcp

# Streamable HTTP transport (exposed only at /mcp) — for remote clients
opcua-mcp --transport http --port 5100

# --transport sse is a deprecated alias for --transport http

Client configuration

For on-demand execution, clients supporting command/argument arrays can use:

{
  "mcpServers": {
    "opcua": {
      "command": "dotnet",
      "args": ["tool", "exec", "OPCFoundation.NetStandard.Opc.Ua.Mcp", "--", "--profile", "core"]
    }
  }
}

After global installation, Claude Desktop and Cursor can use:

{
  "mcpServers": {
    "opcua": { "command": "opcua-mcp" }
  }
}

Claude's file is typically %APPDATA%\Claude\claude_desktop_config.json on Windows or ~/Library/Application Support/Claude/claude_desktop_config.json on macOS. Use the corresponding MCP settings in Cursor.

VS Code / GitHub Copilot uses .vscode/mcp.json:

{
  "servers": {
    "opcua": { "command": "opcua-mcp" }
  }
}

Host authority and shared transfer configuration are documented in the Core package reference; document dependency configuration is in the WoT package reference.

Tools

The server exposes tools through a tool profile — a bounded, named catalog selected with --profile <name>. Run opcua-mcp --help for the current profile names. Profiles can be composed, for example --profile vision,robotics. full is the default; the other profiles expose smaller focused subsets. See the full documentation for the profile-to-tool mapping.

Host-disabled privileged/live tools stay hidden even under full. Explicit host capabilities and exact caller/session/network grants are required to enable them; a profile is never an execution grant.

Tools in the full profile cover all OPC UA Part 4 service sets:

  • Connection: Connect, ConnectCertificate, Disconnect, GetConnectionStatus
  • Attribute: Read, Write, HistoryRead, HistoryUpdate
  • View: Browse, BrowseNext, TranslateBrowsePaths, RegisterNodes, UnregisterNodes, QueryFirst, QueryNext
  • Node Management: AddNodes, AddReferences, DeleteNodes, DeleteReferences
  • Method: Call
  • Subscription: CreateSubscription, ModifySubscription, SetPublishingMode, Publish, Republish, DeleteSubscriptions, TransferSubscriptions
  • MonitoredItem: CreateMonitoredItems, ModifyMonitoredItems, SetMonitoringMode, SetTriggering, DeleteMonitoredItems
  • Discovery: FindServers, FindServersOnNetwork, GetEndpoints, RegisterServer, RegisterServer2
  • Convenience: ReadValue, ReadValues, WriteValue, BrowseAll, CallMethod, ReadNode, Cancel
  • Robotics: typed Robot Intent control and missions, paged monitoring, bounded operation/mission waits, and same-session robotics_vision_pick
  • Vision: image capture, structured one-shot inference, result monitoring, feedback and frame-graph composition
  • MachineTool/WMTP: native monitoring, tools/life, production/jobs, remote files, independent peripheral measurements, records and explicit configuration
  • GMS: native equipment/qualification/calibration and result workflows, bounded observations and consented result acknowledgment
  • CranesHoists: observed topology and raw measurements with authorized standard speed-limit requests, never physical motion commands
  • Industrial companions: asset management, machinery, weighing, pumps, device integration, ISA-95 jobs and relative/global positioning. See the companion guide.
  • WoT and xRegistry: explicit asset/registry/version/label operations, bounded events and content transfers, document validation, binding planning and bidirectional WoT/NodeSet conversion. Remote dependencies require both request opt-in and the host's exact HTTPS origin allowlist; bindings are not executed by these document/management profiles.
  • GDS and credentials: directory, pull/push certificate lifecycle, KeyCredential/token issuance and refresh, and Part 21 onboarding. Inputs and outputs use authorized secret-store references, never private material.
  • General workflows: role/user administration, bounded regular/temporary files, alarms/conditions, historical reads/mutations and schema artifacts.
  • PubSub and live WoT: named runtimes with caller ownership, quotas, idle/absolute expiry and network/operation allowlists. WoT execution supports HTTP(S), MQTT, Modbus TCP and OPC UA. Live Kafka remains disabled until its backend can enforce policy on every broker-discovered connection; Kafka configuration and schema tools remain available.

Companion calls preserve server failures, use bounded lists and observations, and never acquire locks or retry commands implicitly. Package upload and result download require OPCUA_MCP_TRANSFER_ROOT; the default streaming byte limit is 64 MiB (OPCUA_MCP_MAX_TRANSFER_BYTES). Paths cannot escape the configured root.

Embedding

The tools also ship as libraries, so an application can offer OPC UA tools to an LLM alongside its own without forking this server:

builder.Services.AddOpcUaMcpCore();

builder.Services.AddMcpServer()
    .WithStdioServerTransport()
    .WithOpcUaMcpFilters()
    .WithOpcUaCoreTools(McpToolProfile.Services)
    .WithTools<MyApplicationTools>();
Package Tools
OPCFoundation.NetStandard.Opc.Ua.Mcp.Core Part 4 services, connection, configuration, PKI, NodeSet export
OPCFoundation.NetStandard.Opc.Ua.Mcp.PubSub PubSub transports, configuration, bridges, SKS, actions, discovery
OPCFoundation.NetStandard.Opc.Ua.Mcp.Diagnostics UA-TCP capture, decode, replay
OPCFoundation.NetStandard.Opc.Ua.Mcp.PubSub.Diagnostics PubSub capture, decode
OPCFoundation.NetStandard.Opc.Ua.Mcp.Robotics Robot Intent control, missions, waits and Vision-guided Pick
OPCFoundation.NetStandard.Opc.Ua.Mcp.Vision Vision discovery, seeing, inference, feedback and geometry
OPCFoundation.NetStandard.Opc.Ua.Mcp.MachineTool MachineTool and bundled wireless-peripheral workflows
OPCFoundation.NetStandard.Opc.Ua.Mcp.GMS GMS systems, results, downloads and observations
OPCFoundation.NetStandard.Opc.Ua.Mcp.CranesHoists Crane monitoring and authorized limit requests
OPCFoundation.NetStandard.Opc.Ua.Mcp.AMB Asset management
OPCFoundation.NetStandard.Opc.Ua.Mcp.Machinery Machine monitoring, process values, energy and results
OPCFoundation.NetStandard.Opc.Ua.Mcp.Scales Weighing, products and recipes
OPCFoundation.NetStandard.Opc.Ua.Mcp.Pumps Pump values, supervision and maintenance
OPCFoundation.NetStandard.Opc.Ua.Mcp.Di Device integration, locking and updates
OPCFoundation.NetStandard.Opc.Ua.Mcp.ISA95 Common objects and V1/V2 job control
OPCFoundation.NetStandard.Opc.Ua.Mcp.Positioning Spatial frames and coordinate conversion
OPCFoundation.NetStandard.Opc.Ua.Mcp.WotCon WoT management/documents and separately registered, policy-controlled live bindings
OPCFoundation.NetStandard.Opc.Ua.Mcp.XRegistry Generic registry/version/label/content operations
OPCFoundation.NetStandard.Opc.Ua.Mcp.Gds GDS, certificates, credential/token references, onboarding
OPCFoundation.NetStandard.Opc.Ua.Mcp.Workflows Roles/users, files, alarms and historical access
OPCFoundation.NetStandard.Opc.Ua.Mcp.Schema Bounded types and XSD/BSD/JSON, PubSub and OpenAPI artifacts

Robotics and CranesHoists libraries remain preview-only, including Debug variants. The other MCP libraries, including Vision, MachineTool and GMS, follow the root release channel and are stable when the root release is stable. WMTP has no separate package/profile. A development root version can still be prerelease. Conformance depends on actual endpoints/providers; GMS's documented undefined Production-statistics CU does not justify advertising that full facet.

Documentation

See the full documentation.