Deployment Guide
Deployment model
This server is usually deployed as a local Windows companion process next to the target WPF application.
When an AI agent assists the install, follow Agent-Assisted Install so discovery, confirmation, provenance verification, and client registration stay separated.
Canonical script sources
Installer and packaging behavior are defined in scripts/, not in the documentation site:
scripts/online-installer.ps1scripts/tools/packaging/Publish-Release.ps1scripts/installer/Installer.Actions.ps1
Recommended install modes
Public HTTPS installer after release assets exist
Use the public installer after the matching GitHub Release assets exist:
irm https://installer.wpf-mcptools.evanlau1798.com | iex
The HTTPS alias resolves the reviewed scripts/online-installer.ps1 entrypoint. The promotion gate is the release asset set for the selected version: release_<version>_win-<arch>.zip, SHA256SUMS.txt, release-assets.json, release-sbom.spdx.json, and release-evidence.json.
GitHub pre-release E2E install
For pre-release E2E before a public release is promoted, download the reviewed online installer from the public installer alias and install the latest GitHub pre-release without cloning the repository:
$e2eRoot = Join-Path ([System.IO.Path]::GetTempPath()) 'wpf-devtools-mcp-e2e'
New-Item -ItemType Directory -Force -Path $e2eRoot | Out-Null
$installerPath = Join-Path $e2eRoot 'online-installer.ps1'
$installerDownload = @{
Uri = 'https://installer.wpf-mcptools.evanlau1798.com/'
OutFile = $installerPath
}
if ((Get-Command Invoke-WebRequest).Parameters.ContainsKey('UseBasicParsing')) {
$installerDownload.UseBasicParsing = $true
}
Invoke-WebRequest @installerDownload
$installRoot = Join-Path $e2eRoot 'installed-wpf-devtools'
$workingRoot = Join-Path $e2eRoot 'installer-work'
powershell -ExecutionPolicy Bypass -File $installerPath -Version latest -Prerelease -Architecture x64 -Client other -InstallRoot $installRoot -WorkingRoot $workingRoot -NonInteractive -Force -OutputJson
Pre-release E2E requires the GitHub pre-release to contain the matching package archive and sidecars, including release-assets.json, SHA256SUMS.txt, release-sbom.spdx.json, and release-evidence.json. Signed Release packaging still requires WPFDEVTOOLS_RELEASE_SIGNER_THUMBPRINT. Use -Client other for validation-only E2E so the installer writes registration artifacts without updating a real MCP client.
For a real local connect() E2E, install the archive and launch <InstallRoot>\<arch>\current\bin\wpf-devtools-<arch>.exe. A source-tree server launch is useful for tools/list and resource discovery, but it does not validate the packaged bin\inspectors and bin\bootstrapper sidecar layout required for raw injection. Exhaustive 64-tool validation should either pace calls below the default rate limit or set WPFDEVTOOLS_RATE_LIMIT_RPM=10000 only for that local test session.
Reviewed local package install
Review scripts/online-installer.ps1 as the maintainer source first. The reviewed installer can install a local package archive, validates archive integrity before extraction, and then installs the extracted packaged payload through the reviewed installer/helper flow.
Recommended local package example:
powershell -ExecutionPolicy Bypass -File .\scripts\online-installer.ps1 -PackageArchivePath .\release\release_<version>_win-<arch>.zip -TrustedReleaseMetadataDirectory .\release -NonInteractive -Force -OutputJson
The default interactive flow asks for the release version, uses the current machine architecture (x64, x86, or arm64) as the default architecture, and then asks which MCP client registration to generate. When you omit -Architecture, the installer detects the system architecture; pass -Architecture only when you intentionally need to install a different package.
Client-specific automation example:
powershell -ExecutionPolicy Bypass -File .\scripts\online-installer.ps1 -PackageArchivePath .\release\release_<version>_win-<arch>.zip -TrustedReleaseMetadataDirectory .\release -Client claude-code -NonInteractive -Force -OutputJson
Public release package fallback
- Use a locally generated package, or after the GitHub Release assets exist, download the architecture-matched
release_<version>_win-<arch>.zipfrom Releases together withSHA256SUMS.txt,release-assets.json,release-sbom.spdx.json, andrelease-evidence.json. - Verify the archive with
SHA256SUMS.txt,release-assets.json, andrelease-sbom.spdx.jsonbefore extraction. Retainrelease-sbom.spdx.jsonas the published release asset SBOM. It is an asset-level SPDX inventory for the release archives, not a full package/dependency SBOM. - Extract the package.
- Run
run.bat.
Before trusting the extracted package, keep the verified release sidecars beside the archive: SHA256SUMS.txt for the checksum, release-assets.json for the canonical release metadata and sidecar hashes, and release-sbom.spdx.json for the release asset SBOM. The current SBOM sidecar is a release archive inventory, not a full package/dependency SBOM. Production payload signature verification still requires an independent WPFDEVTOOLS_RELEASE_SIGNER_THUMBPRINT; adjacent sidecars prove archive provenance but do not replace signer trust. WPFDEVTOOLS_RELEASE_SIGNER_SUBJECT is only an additional constraint after the thumbprint is pinned.
run.bat requests elevation when the current shell is not already elevated and then launches the packaged bin/install.ps1. Set WPFDEVTOOLS_SKIP_ELEVATION=1 when you need to keep the install in the current unelevated shell.
Remote script execution is optional
Any package-local bootstrap flow is optional. Review the repository source first and treat the script in scripts/ as the authoritative implementation.
Release layout matters
The bootstrapper and inspector sidecars are discovered relative to the server, so the documented release layout must stay stable across installs and upgrades.
See Release Layout for the exact folder contract.
Server Native AOT and trimming boundary
The current packaged server is a framework-dependent, non-AOT Windows process. It is not published as a Native AOT, trimmed, or single-file server distribution.
This is intentional for the current release line because src/WpfDevTools.Mcp.Server/Program.cs registers MCP tools, prompts, and resources through assembly-based discovery:
WithToolsFromAssemblyWithPromptsFromAssemblyWithResourcesFromAssembly
The MCP C# SDK marks the non-generic assembly discovery APIs with RequiresUnreferencedCode because they use dynamic lookup of method metadata and may not work in Native AOT or aggressively trimmed deployments. If Native AOT, trimming, or single-file server distribution becomes a product goal, first replace these registrations with AOT-safe explicit/generic registrations, then add publish-time tests that prove tools/list, prompts, resources, and response schemas survive trimming.
Installed executable contract
The MCP client should launch the resolved installed wpf-devtools-<arch>.exe under the chosen install root, for example:
<InstallRoot>\<arch>\current\bin\wpf-devtools-<arch>.exe
If you do not pass -InstallRoot, the installer first reuses the last live install root when possible. Only when no reusable install root exists does it fall back to %APPDATA%\WpfDevToolsMcp\<arch>\current\bin\wpf-devtools-<arch>.exe.
When -InstallRoot is provided, payloads and generated client registration artifacts are written under that explicit root. The installer state file still lives at %APPDATA%\WpfDevToolsMcp\installer-state.json; it is current-user state used to remember live install evidence across installer runs, not a payload directory override.
Signed payload provenance checklist
- Keep the verified
SHA256SUMS.txt,release-assets.json, andrelease-sbom.spdx.jsonbeside the downloaded archive until after installation evidence is captured. - Verify the signed release payloads, including
bin/wpf-devtools-<arch>.exe,bin/inspectors, andbin/bootstrapper, against the independent pinned release signer fromWPFDEVTOOLS_RELEASE_SIGNER_THUMBPRINT. - Run a package-local smoke check from the extracted package with
run.bat, then verifyget_processes,connect, andget_ui_summarybefore registering that install with user tools. - Repeat the smoke check from the final installed path by launching
<InstallRoot>\<arch>\current\bin\wpf-devtools-<arch>.exe.
Dependency audit cadence
Run dotnet restore --locked-mode and dotnet list package --vulnerable before promoting a release candidate. The NuGet audit result should be captured with release evidence, and package lock validation must remain enabled in CI. Review ModelContextProtocol, System.Text.Json, PowerShell packaging dependencies, and GitHub Actions versions against verified advisories. Avoid dependency churn for speculative CVE claims; update when a verified advisory, compatibility requirement, or pinned GitHub Actions runner/action change applies.
Production checklist
- Use the architecture that matches the target process.
- Keep the published
bin/inspectorsandbin/bootstrapperfolders next to the installed server layout. - Sign Release inspector binaries.
- Configure authentication and TLS settings for hardened environments.
- Validate
get_processes,connect, and a scene-level call such asget_ui_summaryfrom the installed path outside the repository.