Advanced Configuration
Advanced topics for power users and enterprise deployments.
Custom Startup Scripts
Define PowerShell functions and utilities available to all sessions:
# startup.ps1
function Get-HealthCheck {
$critical = @('wuauserv', 'spooler', 'w32time')
$critical | ForEach-Object {
$service = Get-Service -Name $_
[PSCustomObject]@{
Service = $service.Name
Status = $service.Status
StartType = $service.StartType
}
}
}
Write-Host "✓ Custom utilities loaded" -ForegroundColor Green
Multi-Module Configuration
Expose tools from multiple modules with module-specific settings:
poshmcp update-config --add-include-pattern "Get-AzVM"
poshmcp update-config --add-include-pattern "Get-AzResource"
poshmcp update-config --add-include-pattern "Get-Service"
poshmcp update-config --add-exclude-pattern "Remove-*"
poshmcp update-config --add-exclude-pattern "Invoke-*"
poshmcp update-config --add-module Az.Accounts
poshmcp update-config --add-module Az.Compute
Azure Scaffold Workflow
For Azure-first deployments, use the scaffold workflow documented in Azure Integration to generate infra/azure assets with poshmcp scaffold and then run deploy.ps1 from the generated folder.
Performance Tuning
Enable Result Caching
Cache command output for repeated queries:
poshmcp update-config --enable-result-caching true
Use Default Display Properties
Leverage PowerShell's default formatting for faster output:
# In appsettings.json
{
"PowerShellConfiguration": {
"Performance": {
"UseDefaultDisplayProperties": true
}
}
}
Pre-install Modules in Docker
docker build \
--build-arg MODULES="Az.Accounts Az.Resources Az.Storage" \
-t poshmcp:optimized .
Out-of-Process PowerShell
Run PowerShell in a separate pwsh subprocess so that heavy or conflicting modules (Az, Microsoft.Graph) cannot crash or destabilize the MCP server. Requires PowerShell 7.x on PATH.
Enable Out-of-Process Mode
Set RuntimeMode in appsettings.json:
{
"PowerShellConfiguration": {
"RuntimeMode": "OutOfProcess"
}
}
Or via environment variable:
export POSHMCP_RUNTIME_MODE=OutOfProcess
poshmcp serve --transport http
The environment variable takes precedence over the config file value. Valid values: InProcess, OutOfProcess (kebab-case in-process / out-of-process is also accepted by the env var and CLI). Unrecognized values cause the server to fail startup with InvalidOperationException (Unsupported runtime mode '<value>'. Supported runtime modes: in-process, out-of-process.).
Subprocess Host Modes
When RuntimeMode is OutOfProcess, SubprocessHostMode selects the subprocess topology:
SubprocessHostMode |
Topology | When to use |
|---|---|---|
Pool (default) |
One subprocess, runspace pool inside it | Default since 2026-05-06. Best concurrent warm-invoke throughput; recommended for typical MCP workloads. |
ProcessPool |
N independent single-runspace subprocess hosts, leased per request | Trust-boundary or tail-latency-sensitive workloads. Crashes are reconciled per slot without disturbing other hosts. |
Single |
One subprocess, one runspace, serialized requests | Backward-compatible legacy mode. Useful for bisecting regressions or when only cold-start latency matters. |
The default flip from Single to Pool was driven by benchmark study — Pool posted ~4.86× warm-invoke throughput at concurrency 10 versus Single. See specs/004-out-of-process-execution/benchmark-findings.md for full data.
Pool Sizing
{
"PowerShellConfiguration": {
"RuntimeMode": "OutOfProcess",
"SubprocessHostMode": "Pool",
"SubprocessRunspacePoolSize": 0
}
}
SubprocessRunspacePoolSize(Pool mode): runspaces in the pool.0(default) auto-sizes tomin(ProcessorCount, 8). Ignored inSingleandProcessPoolmodes.SubprocessPoolSize(ProcessPool mode): independent subprocess hosts to launch. Default4.SubprocessMinHealthyForStartup(ProcessPool mode): minimum healthy hosts required for the pool to start. Clamped to[1, SubprocessPoolSize]. Default1.
ProcessPool example for tenant isolation:
{
"PowerShellConfiguration": {
"RuntimeMode": "OutOfProcess",
"SubprocessHostMode": "ProcessPool",
"SubprocessPoolSize": 4,
"SubprocessMinHealthyForStartup": 2
}
}
Cancellation
The MCP request CancellationToken propagates into the subprocess channel for all three host modes via a cancel control frame sent by OutOfProcessHost.SendRequestAsync. The host attempts a cooperative BeginStop on the in-flight pipeline; the .NET awaiter completes with OperationCanceledException immediately without waiting for the host to acknowledge. Per-mode behavior:
Pool:PoolDispatcherlooks up the active[powershell]instance by request id and callsBeginStopon it. The runspace is returned to the pool when the pipeline unwinds, so pool capacity recovers without restart. Pool capacity under stuck-but-cancelled invokes isN - in_flight_uncancelled.ProcessPool: each leased host runs the Single-mode script and inherits the same soft-cancel via the inheritedOutOfProcessHostcancel frame. If the host honorsBeginStop, the slot stays healthy and is returned to the pool; other hosts are unaffected. The existing per-request kill-on-timeout path inOutOfProcessSubprocessPoolremains as a backstop for wedged hosts (e.g., a cmdlet stuck in unmanaged code) that do not honorBeginStopwithin the per-request timeout.Single:SingleDispatcherruns the invoke on a background dispatcher thread and callsBeginStopon the matching[powershell]instance when the cancel frame arrives. The host stays healthy for follow-up requests; the per-request timeout serves as the backstop and recycles the host only ifBeginStopdoes not unwind the pipeline in time.
Diagnostics
poshmcp doctor reports the resolved host mode, effective pool sizes, host-script path, and any clamp warnings under Runtime Settings.
Dynamic Tool Reloading
Automatically reload tool definitions when configuration changes (experimental):
# In appsettings.json
{
"PowerShellConfiguration": {
"EnableDynamicReloadTools": true
}
}
Note: This can be slow; use sparingly.
See also: Configuration Guide | Security