# Description _Describe the changes here to communicate to the maintainers why they should accept this pull request. By default - this will become the Commit message after merging and thus define history._ Add provider-backed MachineTool, bundled WMTP, GMS and CranesHoists companions using the existing Machinery/MachineVision fluent, DI and typed-client approach. **The PR is open/non-draft by user choice. Current head `ecc4a7d6ca3e8004cf28ab54da605da302d026bf` is mergeable and has 108 successful checks, six intentionally skipped checks, zero failures and zero pending checks. All five primary workflows completed successfully at that exact head.** | Family | Released specification/model | Packaging | | --- | --- | --- | | MachineTool | OPC 40501-1, 1.02.0 | Model, Server, Client and MCP; normal root versions | | WMTP | OPC 40505, 1.0.0 | Bundled in MachineTool; distinct CLR/wire namespace and independent WMTP-only hosting | | GMS | OPC 40210 reference 1.0.1, normative model 1.0.0 | Model, Server, Client and MCP; normal root versions | | CranesHoists | OPC 40020-1, 1.00 | Model, Server, Client and MCP; all four plus Debug variants forced preview | There are **12 new packable projects**. No separate WMTP package/profile/guide, root version bump, tag, release or package publication is included. Mandatory instance structure is the default; selected optional features require explicit providers. The implementation reuses Machinery results/jobs/files/ProcessValues and Robotics topology, including retained MachineTool Production, defined GMS jobs/parts, modern ISA95/Machinery jobs, shared-owner hosting and isolated instances alongside MachineVision. Runtime and integration fixes preserve raw quality/timestamps, coherent acquisition, namespace ownership, accepted-configuration state, borrowed-resource lifetime, session/node/file cleanup, terminal-value publication, event propagation and endpoint-aware capability publication. Firmware/licence transfer means provider acceptance, not installation/activation. Cancellation does not silently abort another caller's operation. The later upstream MCP expansion is integrated without losing either family set or its default-off privileged/live execution policy. ### Conformance and scope Canonical model inputs are pinned to UA-Nodeset revision `96a08945425d0295edb3607d2a38f6841ef44046`. **GMS upstream exception:** [Annex A.1](https://reference.opcfoundation.org/specs/OPC-40210/annex-a) makes the released NodeSet normative, but §12.3.2.7 requires undefined `GMS_ProductionStatisticsType`. Inherited statistics and defined jobs/parts are implemented without inventing a standard type/NodeId; the complete GMS Production facet is withheld. The requirement ledger records **102 positively evidenced CU rows, 96 directly negative-tested rows and six explicit negative-evidence limitations**. All 648 test-class/name/TRX links were independently resolved to passing cases. The six limitations concern Stacklight, retained legacy PowerOnDuration, Machinery PowerOnDuration, WorkingUnit, Obligation and MaintenanceMode. They are not claims that every invalid-input or hardware-control behavior was tested. The undefined GMS requirement is outside the 102 defined CUs. No external certification claim is made. Retained baseline complete-assembly line coverage, with generated code retained and no source exclusions: | Family | Model | Server | Client | | --- | ---: | ---: | ---: | | MachineTool/WMTP | 83.80% | 91.98% | 84.74% | | GMS | 95.51% | 90.63% | 88.38% | | CranesHoists | 92.76% | 94.45% | 92.24% | These nine measurements predate the later focused review fixes and merges; they are not relabelled as new `ecc4a7d6c` percentages. The current head's separate CI code-coverage check succeeded. No new exclusions or threshold relaxations were introduced. ## Related Issues - Fixes [#4764](https://github.com/OPCFoundation/UA-.NETStandard/issues/4764), the implementation/design and acceptance tracker. ## 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. - [x] 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. - [ ] 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. - [x] I have addressed **all** PR feedback received.
6.0 KiB
OPC UA GMS MCP tools
Six bounded workflows for OPC 40210 Geometric Measurement Systems, using
GmsClient, GmsResultClient, generated proxies and the shared session,
subscription and result-file services. This package has no server dependency.
It follows the normal repository version policy, including .Debug packages.
The reference edition is 1.0.1; the released namespace model is 1.0.0.
Embedding
services.AddOpcUaMcpCore();
services.AddOpcUaMcpGms();
services.AddMcpServer()
.WithStdioServerTransport()
.WithOpcUaMcpFilters()
.WithOpcUaGmsTools(McpToolProfile.Gms);
Use WithOpcUaGmsTools(McpToolProfileSet.Parse("core,gms")) for composition.
Both overloads include GMS for Full and exclude it for other selections.
Repeated registration deduplicates both GMS and shared connection tools.
Existing named sessions are borrowed from OpcUaSessionManager; disposing a
call's facade never closes the host's session or unrelated subscriptions.
Configure GmsClientOptions and TimeProvider through DI when tighter native
read bounds or an injected observation clock are needed.
Catalog
| Tool | Workflow |
|---|---|
gms_list_systems |
Actual GMSType/vendor-subtype inventory, not namespace-only detection. |
gms_read_system |
System, Equipment, Calibration, Production, or per-instance Capabilities. |
gms_read_results |
Latest, ById, bounded Query, raw Published slots/UsedTools, or Corrections. |
gms_download_result |
Bounded inline base64 via standard temporary-file transfer; no host paths. |
gms_observe |
Data, Events, initial retained Conditions, or IntermediateResults. |
gms_acknowledge_results |
Standard result acknowledgement with explicit confirmAcknowledgement=true. |
Every tool accepts sessionName; omission is valid only when exactly one
session is connected. Selectors are exact and case-sensitive. Descriptions and
schemas specify hard limits: 1–100 inventory/results/notifications, 1–60
seconds, 1–524288 download bytes, and 1024–1048576 complete UTF-8 reply bytes
(default 128 KiB). Host native-read limits may be tighter. A response that
exceeds its count or byte budget fails, rather than silently truncating.
Query asks the server for one extra identifier to detect count overflow.
Its native query object groups filterField, filterValue, and orderBy.
Use a ResultId or JobId string equality filter, or an IsPartial Boolean.
Omitting query (or using {}) means no filter and ascending ResultId order;
orderBy: "None" preserves the server's order. Nondefault query selections
require operation: "Query". Unknown or duplicate object properties, invalid
selector names, and incorrectly typed values are rejected before session use.
The filter remains a standard Machinery ContentFilter, not another protocol.
gms_read_results has seven top-level parameters: systemNodeId, operation,
resultId, maximumResults, query, maximumResponseBytes, and sessionName.
Move the former top-level filterField, filterValue, and orderBy arguments
inside query; they are no longer top-level parameters.
Example MCP arguments:
{
"systemNodeId": "ns=12;s=InspectionCell",
"operation": "Query",
"query": {
"filterField": "JobId",
"filterValue": "J-1",
"orderBy": "ResultId"
},
"maximumResults": 20,
"sessionName": "metrology"
}
For intermediate results, explicitly select instance-qualified characteristic placeholders; their namespace need not be the GMS namespace:
{
"systemNodeId": "ns=12;s=InspectionCell",
"kind": "IntermediateResults",
"characteristics": [{"name": "Bore", "namespaceIndex": 12}],
"durationSeconds": 5,
"maximumNotifications": 10
}
Native values use the stack's JSON encoder, preserving wire numeric types,
structures, status and source/server timestamps. A missing optional variable,
folder or property is distinguished from a present bad/uncertain sample.
Method and event values have no invented per-field acquisition quality.
Published samples retain their original DataValue; correction measurements
retain their independent engineering-unit samples. Native catalogs preserve
Number scalar/array representation, and qualification retains its actual
remaining-hours countdown, including negative values after expiry.
Side effects and lifetime
Passive reads never acknowledge results/conditions, confirm alarms, start jobs or measurements, fetch calibration-certificate URIs, change equipment, or apply corrections. There are no invented GMS start/acquire/actuation verbs. Acknowledgement is a separate, explicitly authorized standard result operation; per-result domain errors remain distinct from UA service failures, and no automatic retry is performed.
Retained conditions use standard ConditionRefresh and report
refreshCompleted; an incomplete or lossy refresh is an MCP error.
Intermediate observation awaits real monitored-item creation and its status:
setup failure is not an empty successful window. Every observation releases
only its own subscription/items on completion, error or cancellation.
Metadata and temporary-file handle ownership stays with the existing clients.
MCP 2.2's local client cancellation token does not necessarily send a protocol
cancel notification. The adapter honors its server-side cancellation token;
clients should send the standard MCP notifications/cancelled notification
when immediate server cancellation is needed. The bounded window still
terminates naturally. Cleanup may continue briefly under the typed client's
independent cleanup token after the user-facing window expires.
Conformance boundary
Capabilities describe actual selected surfaces, not authorization or external
certification. Native job/part monitoring and inherited statistics are exposed,
but the complete GMS Production facet is not claimed: the released specification
requires GMS_ProductionStatisticsType without defining its type or NodeId.
This package does not invent that missing definition.