5 Commits

Author SHA1 Message Date
Marc Schier 5530a12d4a McpServerOptions: DI-driven NodeSetExportRoot + PcapBaseFolder
Replaces the static-only ExportRoot / env-var-only configuration in NodeSetExportTools with an instance-aware ResolveExportRoot(IServiceProvider) that consults McpServerOptions from DI first. Same pattern applied to PacketDecodeTools.GetDecodeAllowedRoot for symmetric naming.

Precedence (both options): services.GetService<McpServerOptions>().Property > OPCUA_MCP_EXPORT_ROOT env var (NodeSet) or PcapOptions.BaseFolder (Decode) > per-tool default. Backward-compat: ExportRoot static property + OPCUA_MCP_EXPORT_ROOT env var both still work.

Program.cs now seeds McpServerOptions from OPCUA_MCP_NODESET_EXPORT_ROOT and OPCUA_MCP_PCAP_BASE_FOLDER environment variables so hosts can override without code changes.

Tests: 7 NUnit tests in McpServerOptionsTests covering DI > env var > default precedence for both options. Reflection-based to reach internal/private helpers — same pattern as the existing PacketDecodePathValidationTests.

Build: 0 warnings / 0 errors on Applications/McpServer for net10.0. Pcap.Tests build blocked locally by the unrelated SDK 10 workload manifest issue (see prior commit for details).
2026-06-11 15:01:53 +02:00
Marc Schier 38d4a29070 [security] McpServer NodeSetExportTools: constrain MCP-tool file paths to an export root
ExportNodeSetAsync.filePath and ExportNodeSetPerNamespaceAsync.
outputDirectory are LLM-supplied MCP tool arguments. The old code
passed them directly to Directory.CreateDirectory and to
new FileStream(path, FileMode.Create) with no canonicalization or
allowlist. A prompt-injected LLM call could overwrite arbitrary files
the MCP-server process can write to.

Add a ResolveExportPath helper that:
  - rejects null/whitespace
  - resolves the request via Path.GetFullPath (so .. segments cannot
    escape after canonicalization)
  - rejects any candidate that would resolve outside the export root
    (relative or already-absolute paths must both end up inside)
  - returns the canonicalized absolute path

ExportRoot:
  - defaults to {Path.GetTempPath}/Opc.Ua.Mcp/exports
  - overridable via the OPCUA_MCP_EXPORT_ROOT environment variable
    set before the MCP server starts
  - cached via Lazy<string> with ExecutionAndPublication semantics
  - exposed publicly as NodeSetExportTools.ExportRoot for callers
    and tests

Both ExportNodeSetAsync and ExportNodeSetPerNamespaceAsync now call
ResolveExportPath first; if the LLM supplied an out-of-root path,
the call throws ArgumentException before any filesystem write
occurs.

Activity-level success records continue to include the (resolved)
filePath so the MCP caller still sees where the file landed.

Verified Applications/McpServer/Opc.Ua.Mcp.csproj builds clean
(net10.0): 0 W, 0 E.
2026-06-11 10:48:42 +02:00
Marc Schier 3e5f129c6f Enable nullable in Stack, Libraries (9), and Applications projects (#3732) 2026-05-17 12:55:24 +02:00
Marc Schier 70b4498db8 Certificate manager and ref counted certificate type (#3688)
* New certificate and secrete abstraction with certificate infrastructure and certificate/secret stores. 
* leak testing for certificate resources to validate new ref counting in every test assembly
* Migration guide updated and documentation added for all
* Remove IDisposable from Nodestate and UserIdentity.
* UserCertificateTokenHandler now just points into certificate registry/stores, no dispose required
* Fix CA2000 warnings and cleanup of other diagnostics, increase warning levels in .editorconfig
2026-05-12 07:56:38 +02:00
Marc Schier 94653f1aee Add a MCP server that enables LLM/Copilot to be a OPC UA client (#3701)
* Opc ua client Mcp Server
* fix for #3699
2026-04-24 19:03:45 +02:00