Skip to content

Releases: yotsuda/PowerShell.MCP

PowerShell.MCP v1.7.2 - Sub-Agent ID Redesign & Dead Console Detection

09 Mar 15:17

Choose a tag to compare

Sub-Agent ID Redesign & Dead Console Detection

This release redesigns sub-agent identification to prevent infinite console creation loops, and surfaces dead console warnings in all MCP tool responses.

🔧 Improvements

Server-Issued Sub-Agent IDs

  • Replaced the generate_agent_id MCP tool with a simpler is_subagent parameter on start_powershell_console, invoke_expression, get_current_location, and wait_for_completion
  • When is_subagent=true is passed (without an agent_id), the server automatically allocates a unique ID (sa-xxxxxxxx) and returns it in the response with 🔑 Your agent_id is: ...
  • Any agent_id not previously allocated by the server is rejected with an error, preventing the infinite console creation loop that occurred when AI agents mistakenly passed console names as agent IDs
  • wait_for_completion with is_subagent=true but no agent_id returns an error (since there is no console to wait on)

Dead Console Detection in All Tools

  • invoke_expression and get_current_location now report closed console warnings (e.g., ⚠ Console PID 12345 was closed)
  • Previously, dead console detection was only surfaced in wait_for_completion
  • Agents are now immediately aware when a console has died, regardless of which tool they call

🐛 Bug Fixes

Revert Progress Bar Remnant Clearing

  • Reverted the \e[0K (Erase in Line) escape sequences added in v1.7.1 to clear progress bar remnants after prompt display
  • While the escape sequences did clear remnants, they caused incorrect caret positioning that broke the console display
  • Progress bar remnants may occasionally appear but are less disruptive than the caret position issues

🗑 Removed

generate_agent_id MCP Tool

  • Removed in favor of the is_subagent parameter approach, which is simpler and less error-prone

📊 What's Changed Since v1.7.1

  • 🔧 is_subagent parameter replaces generate_agent_id tool — server issues validated sa-xxxxxxxx IDs
  • 🔧 Invalid agent_id values are now rejected, preventing infinite console creation loops
  • 🔧 Dead console warnings surfaced in invoke_expression and get_current_location
  • 🐛 Reverted progress bar remnant clearing (\e[0K) that caused caret position issues
  • 🗑 Removed generate_agent_id MCP tool

🔄 Installation & Upgrade

Windows

# New installation
Install-PSResource PowerShell.MCP

# Upgrade existing
Update-PSResource PowerShell.MCP

Linux / macOS

# Install
Install-PSResource PowerShell.MCP

# Set execute permission
chmod +x (Get-MCPProxyPath)

Update MCP Configuration

For Claude Code:

claude mcp add PowerShell -s user -- "$(Get-MCPProxyPath)"

For Claude Desktop — Update claude_desktop_config.json:

Get-MCPProxyPath -Escape  # Returns JSON-escaped path
{
  "mcpServers": {
    "PowerShell": {
      "command": "C:\\Users\\YourName\\Documents\\PowerShell\\Modules\\PowerShell.MCP\\1.7.2\\bin\\win-x64\\PowerShell.MCP.Proxy.exe"
    }
  }
}

Restart your MCP client after updating.


📖 Full Documentation: https://github.com/yotsuda/PowerShell.MCP

💬 Questions? GitHub Discussions | 🐞 Report Issues: GitHub Issues

PowerShell.MCP v1.7.1 - Cross-Platform Fixes, Cmdlet Display Improvements & Skills Removal

05 Mar 11:59

Choose a tag to compare

Cross-Platform Fixes, Cmdlet Display Improvements & Skills Removal

This release fixes critical issues on macOS/Linux, improves file editing cmdlet output, and removes the now-redundant skills infrastructure.

🐛 Bug Fixes

macOS/Linux: Commands No Longer Require Manual Enter (#38)

  • On macOS/Linux, after Remove-Module PSReadLine, the built-in PSConsoleHostReadLine called Console.ReadLine() which blocked the main runspace, preventing MCP timer events from firing
  • Replaced with a custom PSConsoleHostReadLine that polls Console.KeyAvailable + Start-Sleep -Milliseconds 50, allowing the MCP timer action block to run between input polls
  • This fixes the issue where commands sent via invoke_expression appeared in Terminal.app but required pressing Enter to execute

Linux: Terminal Launch Shell Quoting (#39)

  • On Linux, launching pwsh via terminal emulators (konsole, gnome-terminal, etc.) failed due to nested shell quoting issues with the -Command argument
  • Replaced with -EncodedCommand (Base64 UTF-16LE), which completely bypasses shell quote interpretation
  • Verified on Ubuntu + konsole (same terminal emulator as the reporter)

macOS: Named Pipe Path Too Long

  • On macOS, UNIX domain socket paths are limited to 104 characters (sun_path)
  • The previous pipe name CoreFxPipe_PowerShell.MCP.Communication.{proxyPid}.{agentId}.{pwshPid} exceeded this limit under /var/folders/.../T/
  • Shortened the base pipe name from PowerShell.MCP.Communication to PSMCP
  • ⚠️ Note: Due to the pipe name change, mixing v1.7.0 Proxy with v1.7.1 Module (or vice versa) will fail silently instead of showing the usual version mismatch error. After upgrading, make sure to update your MCP client configuration so the Proxy path points to the new version

🔧 Improvements

File Edit Cmdlet Display

  • With the var1var4 parameters added to invoke_expression in v1.7.0, file content is passed via variables instead of inline strings. The actual content being written is no longer visible in the console command line, so the cmdlet output now shows the full detail of what was changed.
  • Add-LinesToFile: Now displays added content in green when creating new or empty files
  • Remove-LinesFromFile: Shows actual deleted line content in red instead of position markers ( :)
  • Update-LinesInFile: Replaced deferred context buffer with real-time single-pass display (pre-context → deleted lines in red → inserted lines in green → post-context)

Get-Content / Set-Content Usage Warning

  • When Get-Content (or aliases: gc, cat, type) or Set-Content is used via invoke_expression, a warning is now appended to the response suggesting the optimized PowerShell.MCP cmdlets instead:
    • Show-TextFiles instead of Get-Content
    • Update-MatchInFile, Update-LinesInFile, Add-LinesToFile, Remove-LinesFromFile instead of Set-Content
  • Warning is shown once per command invocation (not noisy)

Multi-Line Command History Warning Removed

  • Removed the warning that discouraged 3+ line commands due to console history limitations
  • This warning caused AI to write less readable single-line pipelines; history recall is not a primary use case for MCP-driven sessions

Cmdlet Help Streamlined

  • Removed boilerplate -WhatIf, -Confirm, -ProgressAction parameter sections from all cmdlet help (covered by CommonParameters)
  • Added var1/var2 usage hints to NOTES section for cmdlets that accept text content
  • Help now provides all essential information with or without -Full / -Examples flags

🗑 Removed

Install-ClaudeSkill Cmdlet & Skills Infrastructure

  • Removed Install-ClaudeSkill cmdlet and the skills/ folder
  • Claude Code now supports MCP prompts as slash commands natively, making the separate skills installation mechanism unnecessary
  • MCP prompts (served by PowerShell.MCP.Proxy) continue to work as before
  • If you previously ran Install-ClaudeSkill, you can safely remove the installed files:
    rm -rf ~/.claude/skills/ps-*

🧪 Testing

macOS Terminal E2E Test

  • Added GitHub Actions workflow (macos-terminal-test.yml) that launches Terminal.app on macOS, starts pwsh with the MCP module, and verifies command execution via Named Pipe
  • Tests: quick command, 5-second delayed command (#38 scenario), long-running command, and post-long-running command

📊 What's Changed Since v1.7.0

  • 🐛 macOS/Linux: custom PSConsoleHostReadLine polling loop fixes blocked MCP commands (#38)
  • 🐛 Linux: -EncodedCommand fixes terminal launch shell quoting (#39)
  • 🐛 macOS: shortened pipe name (PSMCP) fixes 104-char UNIX socket path limit
  • ⚠️ Pipe name changed — update MCP client configuration after upgrading
  • 🔧 File edit cmdlets: real-time display with colored deleted/inserted lines
  • 🔧 Get-Content/Set-Content usage warning guides AI to optimized cmdlets
  • 🔧 Removed noisy multi-line command history warning
  • 🔧 Streamlined cmdlet help with var1/var2 hints
  • 🗑 Removed Install-ClaudeSkill and skills infrastructure (replaced by MCP prompts)
  • 🧪 Added macOS Terminal E2E test in GitHub Actions

🙏 Acknowledgements

  • @davidbordenwi — Detailed analysis of the macOS blocking issue (#38), including the PSConsoleHostReadLine polling approach that became the fix
  • @Fabelwesen — Root cause analysis and -EncodedCommand solution for the Linux terminal launch failure (#39), plus the caseFix empty path guard

📖 Full Documentation: https://github.com/yotsuda/PowerShell.MCP

💬 Questions? GitHub Discussions | 🐞 Report Issues: GitHub Issues

PowerShell.MCP v1.7.0 - Reliability, Thread Safety & Security Hardening

20 Feb 13:55

Choose a tag to compare

Reliability, Thread Safety & Security Hardening

This release focuses on internal reliability and security improvements. Thread safety issues in the command execution pipeline have been resolved, named pipe communication has been hardened, and several resource management and code quality fixes have been applied.

🔒 Security Hardening

Named Pipe Access Control

  • Unix/macOS: Named pipe socket permissions are now set to 0600 (owner-only), preventing other local users from connecting
  • All platforms: Added 10 MB upper bound on message length to prevent out-of-memory from malformed length headers

Stop-AllPwsh Confirmation

  • Stop-AllPwsh now requires explicit confirmation (SupportsShouldProcess with ConfirmImpact=High) before killing all pwsh processes

SHA256 for File Comparison

  • Replaced MD5 with SHA256 for file comparison in module loader

🐛 Bug Fixes

Thread Safety in Command Execution

  • ExecutionState: Replaced _cacheLock with a unified _lock protecting all shared state (_isBusy, _currentPipeline, _shouldCacheOutput, heartbeat fields) to eliminate race conditions between status reads and state mutations
  • McpServerHost: Replaced volatile fields with lock-protected private fields and atomic ConsumeCommand/ConsumeSilentCommand methods to prevent partial reads across command+variables fields
  • PowerShellCommunication: Replaced ManualResetEvent with Monitor.Wait/PulseAll and a submitted/completed generation counter pair to prevent lost wakeups from late-completing timed-out commands

One-Shot Timer for Polling Engine

  • Redesigned from AutoReset = $true to one-shot mode (AutoReset = $false with try/finally restart), preventing event queue buildup while the main runspace is busy

Atomic File Replacement

  • FileOperationHelper: Now uses File.Replace for truly atomic file replacement instead of 3-step move sequence
  • Added millisecond precision to backup timestamps to prevent collisions

Resource Leaks

  • ConsoleSessionManager: Dispose Process object from GetProcessById to prevent handle leaks
  • PowerShellProcessManager: Dispose fire-and-forget Process from terminal emulator launch
  • Module loader: Added try/finally for StreamReader/Stream dispose

🔧 Code Quality

  • EncodingHelper: Consolidated duplicated encoding alias switch expressions into single GetEncodingByName method
  • MCPPollingEngine.ps1: Fixed $null comparison order to prevent collection filtering gotcha ($null -ne ... instead of ... -ne $null)
  • PipelineHelper: Marked static display-state booleans as volatile
  • MCPModuleInitializer: Added _serverLock to protect _namedPipeServer and _tokenSource from concurrent access; escaped single quotes in error messages

📊 What's Changed Since v1.6.8

  • 🔒 Named pipe socket restricted to owner-only on Unix/macOS
  • 🔒 Message length validation (10 MB cap) on pipe communication
  • 🔒 Stop-AllPwsh now requires confirmation
  • 🐛 Thread safety: unified locking in ExecutionState, atomic command consumption, lost-wakeup prevention
  • 🐛 Polling engine: one-shot timer to prevent event accumulation
  • 🐛 Atomic file replacement in FileOperationHelper
  • 🐛 Resource leak fixes (Process handles, StreamReader)
  • 🔧 SHA256 for file comparison, encoding helper consolidation, null comparison fix

📖 Full Documentation: https://github.com/yotsuda/PowerShell.MCP

💬 Questions? GitHub Discussions | 🐞 Report Issues: GitHub Issues

PowerShell.MCP v1.6.8 - Output Truncation & AX Improvements

17 Feb 12:19

Choose a tag to compare

Output Truncation & AX Improvements

AX (Agent Experience) — just as UX focuses on human users, AX focuses on the experience of AI agents interacting with tools and APIs. Term coined by Matt Biilmann (Netlify CEO).

This release introduces automatic output truncation to protect the AI context window from large command results, and improves AX across the board — smarter scope warnings, enhanced tool descriptions, and clearer console behavior for AI agents.

✨ New Features

Output Truncation for Large Results (#34)

Commands that produce large output (>15,000 characters) are now automatically truncated to preserve the AI's context window budget:

  • Head preview (~1,000 chars) + tail preview (~2,000 chars) with newline-aligned boundaries
  • Full output is saved to a temp file and retrievable via Show-TextFiles
  • Old output files are automatically cleaned up after 120 minutes
Output too large (47066 characters). Full output saved to: C:\Users\...\pwsh_output_20260217_205404.txt
Use invoke_expression('Show-TextFiles "..." -Contains "search term"') to search the output.

--- Preview (first ~1000 chars) ---
...
--- truncated (44106 chars omitted) ---
--- Preview (last ~2000 chars) ---
...

⚡ Improvements

Smarter Scope Warnings

Optimized variable scope warnings to reduce AI token consumption:

  • First occurrence shows a detailed warning; subsequent ones show a compact one-liner
  • for loop initializer variables (e.g., $i) are now excluded from warnings
  • Warnings are now displayed after command output for better readability

Enhanced Tool Descriptions

  • invoke_expression: Clarified primary use cases (git, build, file operations, etc.) and added string interpolation guidance
  • start_powershell_console: Added capability overview and PowerShell Gallery module installation hints

Other

  • Console reuse message is now always displayed for clearer behavior

📊 What's Changed Since v1.6.7

AI-Facing Changes

  • invoke_expression: Automatic output truncation for large results (>15,000 chars)
  • ⚡ Scope warning: Compact one-liner after first detailed warning
  • ⚡ Scope warning: for loop initializer variables excluded from warnings
  • ⚡ Scope warning moved after command output for better readability
  • 📝 invoke_expression: Clarified primary use cases and added string interpolation guidance
  • 📝 start_powershell_console: Added capability overview and module installation hints
  • 📝 start_powershell_console: Console reuse message always displayed

🙏 Contributors

  • @doraemonkeys — Design and implementation of the output truncation feature (#34)

Thank you @doraemonkeys for the output truncation implementation that keeps the AI context window safe!


📖 Full Documentation: https://github.com/yotsuda/PowerShell.MCP

💬 Questions? GitHub Discussions | 🐞 Report Issues: GitHub Issues

PowerShell.MCP v1.6.7 - Smart Console Reuse & Tool Description Refinements

14 Feb 09:19

Choose a tag to compare

Smart Console Reuse & Tool Description Refinements

This release redesigns start_powershell_console with smart console reuse via the new reason parameter, introduces a fast-path optimization in pipe discovery, and refines tool descriptions for clearer AI agent guidance.

✨ New Features

Smart Console Reuse (reason parameter)

start_powershell_console now intelligently reuses existing standby consoles instead of always launching a new one:

  • No reason: Checks for an existing standby console and reuses it if available. Banner is displayed silently on the existing console.
  • With reason: Always launches a new console regardless of existing ones. The reason is displayed in dark yellow at startup.
# Reuse existing console (default behavior)
start_powershell_console(banner: "Hello!")

# Force a new console with reason
start_powershell_console(reason: "Need a separate console for background task", banner: "Worker console")

This reduces unnecessary console proliferation while preserving the ability to create dedicated consoles when needed.


⚡ Performance

Faster Tool Response When Console Is Ready

When the active console is already in a ready state, tool calls now skip the full console discovery process and connect immediately. This reduces latency for the most common case — consecutive commands on a single console.


📊 What's Changed Since v1.6.6

User-Facing Changes

  • start_powershell_console: Smart console reuse with reason parameter
  • ⚡ Faster tool response when active console is already ready
  • 📝 invoke_expression: Console visibility hint and stronger text editing guidance
  • 📝 invoke_expression: Multi-line history warning shown once per session
  • 📝 Tool parameter descriptions unified and simplified

📖 Full Documentation: https://github.com/yotsuda/PowerShell.MCP

💬 Questions? GitHub Discussions | 🐞 Report Issues: GitHub Issues

PowerShell.MCP v1.6.6 - Elevation Consent, Pipe Security, Literal Variables & Guardrails

12 Feb 14:58

Choose a tag to compare

Elevation Consent, Pipe Security, Literal Variables & Guardrails

This release introduces an elevation consent prompt for RunAs/sudo commands, Named Pipe access control restricting connections to the current user, var1-var4 literal string parameters for safe content injection bypassing the PowerShell parser, and server-side guardrails that enforce correct variable usage for text editing cmdlets.

✨ New Features

Elevation Consent Prompt

When a pipeline contains elevation patterns (-Verb RunAs, runas, gsudo, sudo), PowerShell.MCP now displays the command in the console and requires explicit user confirmation via Read-Host before execution. This provides a user consent mechanism independent of OS UAC, which may auto-approve elevation without displaying a prompt on certain configurations (e.g., Entra ID joined devices with Windows Hello).

⚠ ELEVATION REQUEST DETECTED
Start-Process pwsh -Verb RunAs -ArgumentList '-Command', 'Get-Process'

Allow? (Y/N):
  • Only the physical user at the console can approve (AI agents communicate via Named Pipe and cannot interact with console stdin)
  • Denial throws "Elevation denied by user" and the pipeline is not executed

var1-var4 Literal String Parameters

invoke_expression now accepts var1, var2, var3, and var4 parameters that inject literal string values into the pipeline via Set-Variable, completely bypassing the PowerShell parser. This prevents unintended expansion of $, backtick, and double-quote characters when editing source code files.

invoke_expression(
  pipeline: "Update-MatchInFile file.cs -OldText $var1 -Replacement $var2",
  var1: "$oldVariable = `Get-Value`",
  var2: "$newVariable = \"Get-Value\""
)

Key behaviors:

  • Values are injected as PowerShell variables ($var1-$var4) before pipeline execution
  • No escaping required — content is passed as-is, never parsed by PowerShell
  • Ideal for -Content, -OldText, -Replacement, -Value, -Pattern, -Contains parameters
  • var1/var2 cover most use cases; var3/var4 provide headroom for complex pipelines

Variable Enforcement Guardrails

The proxy now validates that text editing cmdlets are called with the required variable parameters. If a cmdlet is detected in the pipeline without the required variable, an error is returned before the pipeline reaches the PowerShell console. The validation is aware of context: Get-Help/Get-Command pipelines are skipped, and cmdlet names appearing in file paths (e.g., Show-TextFiles "C:\...\Add-LinesToFile.md") are not falsely matched.

Cmdlet Required
Add-LinesToFile var1 (for -Content)
Update-LinesInFile var1 (for -Content)
Update-MatchInFile var1 (for -OldText) + var2 (for -Replacement)
Remove-LinesFromFile var1 when -Pattern or -Contains is used
Set-Content var1 (for -Value)
Add-Content var1 (for -Value)

🔒 Security

Named Pipe Access Control (Windows)

Named Pipes now use PipeSecurity to explicitly restrict access to the current user's SID only. Without explicit PipeSecurity, Windows assigns a default ACL that may grant access to other principals (SYSTEM, Administrators, or broader groups depending on the environment). The new ACL ensures only the user who started the console can connect.

On Linux/macOS, Named Pipes (Unix domain sockets) already default to owner-only permissions — no change needed.


📝 Improvements

Full Output for Add-LinesToFile and Update-LinesInFile

Previously, inserting or replacing 6+ lines showed only the first 2 + ellipsis + last 2 lines. Now all changed lines are displayed, giving AI agents full visibility of editing results without a separate Show-TextFiles call.

PSReadLine History: 1-2 Line Commands Only

Single-line and 2-line commands are now added to PSReadLine console history for user learning. Multi-line commands (3+ lines) are skipped to avoid cluttering history with large code blocks. A warning is returned when a multi-line command is not added to history.

Improved Tool Description

The invoke_expression tool description now includes guidance on var1-var4 usage and references to bundled text editing cmdlets (Show-TextFiles, Add-LinesToFile, etc.).

Show-TextFiles Help Improvement

Updated Show-TextFiles help to clarify its file search capability (recursive search with -Pattern/-Contains). SYNOPSIS now reads "Display file contents with line numbers, or search across files with regex or literal patterns". Also worked around a PlatyPS rendering issue where * wildcards were stripped from help output.


📊 What's Changed Since v1.6.5

User-Facing Changes

  • invoke_expression: Elevation consent prompt for RunAs/sudo commands
  • invoke_expression: var1-var4 literal string parameters for safe content injection
  • invoke_expression: Server-side guardrails enforcing variable usage for text editing cmdlets
  • 🔒 Named Pipe access restricted to current user SID via PipeSecurity (Windows)
  • 📝 Add-LinesToFile / Update-LinesInFile: Full output display (no more 6+ line abbreviation)
  • 📝 invoke_expression: PSReadLine history limited to 1-2 line commands
  • 📝 invoke_expression: Improved tool description with variables guidance
  • 📝 Show-TextFiles: Help updated to clarify search/grep capability; PlatyPS wildcard fix

📖 Full Documentation: https://github.com/yotsuda/PowerShell.MCP

💬 Questions? GitHub Discussions | 🐞 Report Issues: GitHub Issues

PowerShell.MCP v1.6.5 - Multiline Text Editing, Wildcard Recurse & Quality Improvements

11 Feb 11:02

Choose a tag to compare

Multiline Text Editing, Wildcard Recurse & Quality Improvements

This release renames Show-TextFile to Show-TextFiles for AI clarity, adds multiline literal text support to Show-TextFiles and Remove-LinesFromFile, wildcard -Path with -Recurse for extension filtering, and fixes a critical AddToHistory bug that could leave consoles permanently busy.

✨ New Features

Rename Show-TextFileShow-TextFiles

Cmdlet renamed to Show-TextFiles to clearly communicate that it handles multiple files (wildcards, arrays, -Recurse). This helps AI agents understand the cmdlet's capabilities from the name alone, similar to how Update-LinesInFile signals multi-line editing.

Wildcard -Path with -Recurse

-Path now accepts wildcard patterns (e.g., *.cs, Show*.ps1) when combined with -Recurse, enabling file extension filtering across all subdirectories.

# Search only .cs files recursively for TODO comments
Show-TextFiles *.cs -Recurse -Pattern "TODO"

# Search only partial-match filenames
Show-TextFiles Show*.cs -Recurse -Contains "EnumerateFiles"

Multiline -Contains for Show-TextFiles and Remove-LinesFromFile

-Contains now accepts multi-line strings. When the search text contains newlines, the cmdlet switches to whole-file mode, reading the entire file to find cross-line literal matches.

# Search for a multi-line code pattern
Show-TextFiles script.ps1 -Contains "if (`$condition) {`n    Write-Host 'hello'"

# Remove a multi-line block
Remove-LinesFromFile config.txt -Contains "# BEGIN SECTION`r`n# END SECTION"

Key behaviors:

  • Single-line Contains (no newlines): efficient 1-pass streaming — unchanged
  • Multi-line Contains (newlines present): whole-file mode with newline normalization
  • Newlines in -Contains are auto-normalized to match the file's newline style (CRLF/LF)
  • -Contains + -Pattern OR combination is supported (single-line mode only)
  • Multi-line -Contains + -Pattern → error (not supported)
  • Multi-line -Contains + -Recurse → error (not supported)
  • -Pattern with newlines → error (regex multiline not supported)

-Contains + -Pattern OR Combination for Remove-LinesFromFile

Remove-LinesFromFile now supports combining -Contains and -Pattern as an OR condition, matching Show-TextFiles's existing behavior. Previously, these were mutually exclusive.

# Remove lines containing "DEBUG" OR matching regex pattern
Remove-LinesFromFile log.txt -Contains "DEBUG" -Pattern "^\[TRACE\]"

Multiline -OldText for Update-MatchInFile

Update-MatchInFile now supports multi-line literal replacement via -OldText, with automatic newline normalization.

Update-MatchInFile file.txt -OldText "old line 1`nold line 2" -Replacement "new content"

Parameter Aliases for Update-MatchInFile

  • -Replacement now has alias -NewText (symmetry with -OldText)

Stop-AllPwsh Function

A utility for PowerShell module developers. Stops all pwsh processes to release DLL locks before dotnet build.

# Stop all pwsh processes including this console to release DLL locks
Stop-AllPwsh

# Stop all and start a new session from a specific pwsh binary
Stop-AllPwsh -PwshPath (Get-PSOutput)

🐛 Bug Fixes

AddToHistory NullReferenceException Causing Permanent Busy State

Fixed: PSConsoleReadLine::AddToHistory could throw NullReferenceException in the timer event handler. Because this call was outside the try/catch/finally block, NotifyResultReady was never called, leaving _isBusy = true permanently. This caused wait_for_completion to never return.

Fix: Moved AddToHistory inside the try block with an inner try {} catch {} wrapper for defense in depth.

Race Condition in Command Execution

Fixed: start_powershell_console and invoke_expression could run concurrently on the same PowerShell runspace, causing intermittent failures.

Fix: Added proper synchronization to prevent concurrent execution on the same console session.

Update-LinesInFile Position Attribute

Fixed: -LineRange was incorrectly assigned Position = 1, preventing positional use of -Content.

Fix: Moved Position = 1 from -LineRange to -Content, so Update-LinesInFile file.txt -LineRange 1,5 "new content" works as expected.


📝 Improvements

PlatyPS Help Documentation

  • Rewrote all cmdlet help markdown with accurate descriptions, examples, and notes
  • Added help documentation for Get-MCPOwner and Install-ClaudeSkill
  • Standardized example format across all cmdlets

Console Name Categories

  • Revised console window naming for better quality and consistency

Performance Optimizations

  • Remove-LinesFromFile: StringBuilder forward-copy for multiline removal — O(M) instead of O(N×M)
  • Show-TextFiles / Remove-LinesFromFile: Binary search (GetLineNumberFromOffset) for character-offset-to-line-number mapping

📊 What's Changed Since v1.6.3

User-Facing Changes

  • Show-TextFiles: Rename Show-TextFileShow-TextFiles for AI clarity
  • Show-TextFiles: Wildcard -Path with -Recurse for file extension filtering
  • Show-TextFiles / Remove-LinesFromFile: Multiline -Contains support
  • Remove-LinesFromFile: -Contains + -Pattern OR combination
  • Update-MatchInFile: Multiline -OldText support
  • Update-MatchInFile: -Replacement alias -NewText
  • 🐛 invoke_expression: AddToHistory crash causing permanent busy state and wait_for_completion hang
  • 🐛 start_powershell_console / invoke_expression: Race condition fix
  • 🐛 Update-LinesInFile: Positional -Content parameter fix
  • Stop-AllPwsh: New function for releasing DLL locks before PS module rebuild
  • 📝 All cmdlets: Complete PlatyPS help rewrite

📖 Full Documentation: https://github.com/yotsuda/PowerShell.MCP

💬 Questions? GitHub Discussions | 🐞 Report Issues: GitHub Issues

PowerShell.MCP v1.6.3 - Headless / CI Support

09 Feb 03:59

Choose a tag to compare

Headless / CI Support

This release adds headless/CI support, enabling PowerShell.MCP to run in non-interactive environments such as GitHub Actions and other CI/CD pipelines.

✨ New Feature

Headless / CI Mode

PowerShell.MCP can now operate without a terminal window. When no desktop environment is available (e.g., Linux CI runners), the Proxy automatically launches pwsh in headless mode and communicates via Named Pipes.

This enables AI coding agents to execute PowerShell commands in CI environments:

  • GitHub Copilot coding agent — with MCP configuration and copilot-setup-steps.yml
  • Claude Code Action — via GitHub Actions workflows with claude-code-action

⚙️ GitHub Actions Setup

Copilot coding agent — Add an Install step to .github/workflows/copilot-setup-steps.yml:

      - name: Install PowerShell.MCP
        shell: pwsh
        run: |
          Install-PSResource -Name 'PowerShell.MCP' -Scope CurrentUser -TrustRepository
          $proxy = Get-ChildItem ($env:PSModulePath -split ':') -Filter 'PowerShell.MCP.Proxy' -Recurse -EA SilentlyContinue |
            Where-Object { $_.FullName -match 'linux-x64' } | Select-Object -First 1 -ExpandProperty FullName
          chmod +x $proxy
          New-Item -ItemType SymbolicLink -Path '/usr/local/bin/PowerShell.MCP.Proxy' -Target $proxy -Force

Note: If your repository requires additional bootstrapping (e.g., dotnet SDK, build module imports), add those steps before the Install step.

Then add MCP config in Settings > Copilot > Coding agent > MCP configuration:

{
  "mcpServers": {
    "PowerShell": {
      "type": "stdio",
      "command": "/usr/local/bin/PowerShell.MCP.Proxy",
      "args": []
    }
  }
}

Claude Code Action — Add the install step to your workflow and pass the Proxy path via claude_args --mcp-config:

      - name: Install PowerShell.MCP
        shell: pwsh
        run: |
          Install-PSResource -Name 'PowerShell.MCP' -Scope CurrentUser -TrustRepository
          $proxy = Get-ChildItem ($env:PSModulePath -split ':') -Filter 'PowerShell.MCP.Proxy' -Recurse -EA SilentlyContinue |
            Where-Object { $_.FullName -match 'linux-x64' } | Select-Object -First 1 -ExpandProperty FullName
          chmod +x $proxy
          New-Item -ItemType SymbolicLink -Path '/usr/local/bin/PowerShell.MCP.Proxy' -Target $proxy -Force

      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          github_token: ${{ secrets.GITHUB_TOKEN }}
          settings: |
            {
              "permissions": {
                "allow": [
                  "mcp__PowerShell__invoke_expression",
                  "mcp__PowerShell__get_current_location",
                  "mcp__PowerShell__wait_for_completion",
                  "mcp__PowerShell__start_powershell_console",
                  "mcp__PowerShell__generate_agent_id"
                ]
              }
            }
          claude_args: |
            --mcp-config '{"mcpServers":{"PowerShell":{"type":"stdio","command":"/usr/local/bin/PowerShell.MCP.Proxy","args":[]}}}'

📊 Verified with AI Coding Agents

Headless/CI mode has been verified on a PowerShell repository fork (Ubuntu 24.04, GitHub Actions):

Copilot coding agent — Used invoke_expression to build, test, and verify fixes:

  • PR #20 (bug fix): 14 invoke_expression calls — Start-PSBuild × 3, Start-PSPester × 2 (Passed: 52, Failed: 0), verification scripts × 3
  • PR #22 (feature): 16 invoke_expression calls — Start-PSBuild × 6 (compile errors resolved in-session), verification scripts × 4

Claude Code Action — Workflow configured with invoke_expression MCP tool via claude-code-action@v1.

The Copilot agent leveraged the persistent PowerShell session: modules imported via invoke_expression remained loaded across all subsequent calls, enabling rapid iteration without re-importing.


🐛 Bug Fixes

Version Mismatch Hang

Fixed: When the PowerShell.MCP module version and Proxy executable version were mismatched, invoke_expression would hang indefinitely instead of reporting an error.

Root cause: The DLL returned a plain text error message for version mismatches, but the Proxy only processed JSON responses. The plain text was silently ignored, causing the tool call to hang with no response.

Fix:

  • DLL (NamedPipeServer.cs): Version mismatch error is now returned as a JSON response with status: "error" and error: "version_mismatch"
  • Proxy (PowerShellTools.cs): Added case "error" handling to the response switch, returning the error message to the user
  • Proxy (JsonRpcModels.cs): Added Error and Message properties to GetStatusResponse

Linux Case Sensitivity

Fixed: Import-Module PowerShell.MCP failed on Linux after installing via Install-PSResource from PS Gallery.

Root cause: Install-PSResource creates a lowercase directory powershell.mcp, but Import-Module PowerShell.MCP requires an exact case match on case-sensitive Linux filesystems.

Fix: Added a case-correction script before Import-Module in both the headless launcher (LaunchPwshDirectly) and the Linux terminal launcher (TryLaunchTerminal). The script renames powershell.mcp to PowerShell.MCP if needed. Windows and macOS are unaffected (case-insensitive filesystems).

Headless stdout/stderr Redirect

Fixed: The headless pwsh process could deadlock due to unbuffered stdout/stderr streams.

Fix: Added RedirectStandardInput/Output/Error and asynchronous drain handlers (BeginOutputReadLine/BeginErrorReadLine) in LaunchPwshDirectly to prevent buffer deadlocks.


📊 What's Changed Since v1.6.2

User-Facing Changes

  • New: Headless/CI mode — PowerShell.MCP works in non-interactive environments (GitHub Actions)
  • 🐛 Fix: Version mismatch now shows a clear error message instead of hanging
  • 🐛 Fix: Module installs and loads correctly on case-sensitive Linux filesystems
  • 🐛 Fix: Headless mode no longer deadlocks on stdout/stderr

Internal Changes

  • NamedPipeServer.cs: Version error response changed from plain text to JSON format
  • JsonRpcModels.cs: Added Error and Message properties to GetStatusResponse
  • PowerShellTools.cs: Added case "error" to response status switch
  • PowerShellProcessManager.cs: Added case-fix script to Linux launchers, added stdout/stderr redirect in headless mode

📖 Full Documentation: https://github.com/yotsuda/PowerShell.MCP

💬 Questions? GitHub Discussions | 🐞 Report Issues: GitHub Issues

PowerShell.MCP v1.6.2 - Bug Fix: $PROFILE Import Conflict

08 Feb 22:55

Choose a tag to compare

Bug Fix: $PROFILE Import Conflict

This release fixes a critical bug where PowerShell.MCP fails to work when Import-Module PowerShell.MCP is in your $PROFILE.

🐛 Bug Fix

$PROFILE Import Conflict

Fixed: PowerShell.MCP failed to establish a Named Pipe connection when Import-Module PowerShell.MCP was present in $PROFILE.

Root cause: When the module was loaded by $PROFILE before the Proxy set the global variables ($global:PowerShellMCPProxyPid, $global:PowerShellMCPAgentId), the Named Pipe server started with null values. The subsequent Import-Module by the Proxy was silently ignored since the module was already loaded.

Fix:

  • Added -Force to all Import-Module PowerShell.MCP calls across Windows, macOS, and Linux launchers, ensuring the module re-initializes with correct Proxy PID and Agent ID
  • Added cleanup logic in MCPModuleInitializer.OnImport() to properly dispose of the existing Named Pipe server before creating a new one

📊 What's Changed Since v1.6.1

User-Facing Changes

  • Fix: Module now works correctly when imported from $PROFILE

Internal Changes

  • Added -Force flag to Import-Module PowerShell.MCP in all platform launchers
  • Added existing Named Pipe server cleanup in MCPModuleInitializer.OnImport()
  • Split Import-Module PowerShell.MCP,PSReadLine into Import-Module PowerShell.MCP -Force; Import-Module PSReadLine (to apply -Force only to PowerShell.MCP)

🔄 Installation & Upgrade

Windows

# New installation
Install-Module PowerShell.MCP -Force

# Upgrade existing
Update-Module PowerShell.MCP

Linux / macOS

# Install
pwsh -Command "Install-Module PowerShell.MCP -Scope CurrentUser -Force"

# Set execute permission
chmod +x $(pwsh -Command "Import-Module PowerShell.MCP; Get-MCPProxyPath")

Update MCP Configuration

For Claude Code:

claude mcp add PowerShell -s user -- "$(Get-MCPProxyPath)"

For Claude Desktop — Update claude_desktop_config.json:

Get-MCPProxyPath -Escape  # Returns JSON-escaped path
{
  "mcpServers": {
    "PowerShell": {
      "command": "C:\\Users\\YourName\\Documents\\PowerShell\\Modules\\PowerShell.MCP\\1.6.2\\bin\\win-x64\\PowerShell.MCP.Proxy.exe"
    }
  }
}

Restart your MCP client after updating.

📖 Full Guide: https://github.com/yotsuda/PowerShell.MCP#quick-start


Full Documentation: https://github.com/yotsuda/PowerShell.MCP

Questions? GitHub Discussions | Report Issues: GitHub Issues

PowerShell.MCP v1.6.1 - Cross-Platform Stability & Performance Improvements

08 Feb 13:52

Choose a tag to compare

Cross-Platform Stability & Performance Improvements

This release improves cross-platform reliability, console performance, and broader PowerShell compatibility, making PowerShell.MCP more stable on Linux/macOS and preventing performance degradation from heavy usage.

🎉 What's New

Cross-Platform Console Title

Console window title now works correctly on Linux and macOS. Previously, Console.Title threw exceptions on non-Windows platforms, causing the title to fall back to PID only. Now uses $Host.UI.RawUI.WindowTitle via the PowerShell Host API on Unix systems.

Multi-line Command History Handling

Multi-line commands are now intentionally excluded from PSReadLine history with a clear warning message.

Why this matters: Multi-line commands significantly contribute to history file growth, leading to severe performance degradation. By excluding them from PSReadLine history, you avoid console slowdowns while still being able to execute multi-line commands normally.

Automatic History File Trimming

Critical performance fix: PSReadLine history file is now automatically trimmed to 4,096 lines when it exceeds 1 MB.

Why this matters: Large history files cause severe console performance degradation — command input becomes sluggish with noticeable delays of several seconds when typing. This issue became more prevalent in v1.6.0 with multi-instance support, as multiple Claude Code instances writing to history can rapidly grow the file.

PowerShell 7.4 Support

Minimum PowerShell version lowered from 7.5 to 7.4 for broader compatibility. The module DLL targets net8.0 (forward-compatible with net9.0). The Proxy is self-contained and requires no .NET installation.


📊 What's Changed Since v1.6.0

User-Facing Changes

  • Cross-platform console title: Uses Host API on Unix instead of Console.Title
  • Multi-line history handling: Clear warnings when commands cannot be added to history
  • Performance fix: Automatic history file trimming prevents console slowdown
  • Compatibility: PowerShell 7.4 support (down from 7.5)

Internal Improvements

  • Replace string literals with PipeStatus constants for pipe status checks
  • Inject PipeDiscoveryService via DI instead of creating new instances per call
  • Reuse NamedPipeClient instance in WaitForPipeReadyAsync loop
  • Remove unused StartPowerShellConsoleParams class
  • Remove duplicate Get-Process call in Get-MCPOwner fallback
  • 500+ lines of new unit tests for PowerShellTools
  • CI workflow now runs tests on Windows, Ubuntu, and macOS

Full Documentation: https://github.com/yotsuda/PowerShell.MCP

Questions? GitHub Discussions | Report Issues: GitHub Issues