PoshMCP

Expose explicitly whitelisted PowerShell commandlets as a MCP Tool

PowerShell MCP Server

A Model Context Protocol (MCP) server that exposes PowerShell cmdlets as tools for AI assistants like Claude or Github Copilot. Built with security in mind through explicit whitelisting of allowed cmdlets.

Overview

This MCP server dynamically loads PowerShell cmdlets from modules and scripts, automatically generating tool schemas from cmdlet documentation. Unlike traditional PowerShell remoting, this server uses a whitelist approach - only explicitly configured cmdlets are exposed, making it safer for AI interactions.

Key Features

  • Declarative Configuration: Define available tools in a simple JSON config file
  • Automatic Schema Generation: Uses PowerShell reflection to generate MCP tool schemas from cmdlet help documentation
  • Security by Whitelisting: Only explicitly listed cmdlets are exposed as tools
  • Dynamic Loading: Supports both PowerShell modules (.psm1) and script files (.ps1)
  • Type Conversion: Automatically handles parameter type conversions (DateTime, switch parameters, etc.)

How It Works

  1. Configuration Loading: Reads mcp-config.json to determine which cmdlets to expose
  2. Module/Script Import: Loads specified PowerShell modules and dot-sources script files
  3. Schema Generation: Uses Get-Command and Get-Help to introspect each cmdlet:
    • Extracts cmdlet synopsis as tool description
    • Maps PowerShell parameter types to JSON schema types
    • Identifies mandatory parameters from [Parameter(Mandatory)] attributes
    • Generates camelCase parameter names for JSON (e.g., StartDatestartDate)
  4. Tool Invocation: When a tool is called, dynamically dispatches to the corresponding cmdlet with parameter mapping

Installation

From PowerShell Gallery (Recommended)

Install-Module -Name PoshMCP -Scope CurrentUser

From Source

  1. Clone or download this repository to your local machine
  2. Ensure PowerShell 7+ is installed (pwsh)

Configuration

MCP Server Configuration

Add the following to your VS Code MCP configuration file (typically %APPDATA%\Code\User\mcp.json on Windows):

{
    "servers": {
        "posh-mcp": {
            "type": "stdio",
            "command": "pwsh",
            "args": [
                "-NoProfile",
                "-NoLogo",
                "-Command",
                "Import-Module PoshMCP;",
                "Start-PoshMcp -ConfigPath C:\\path\\to\\your\\mcp-config.json"
            ]
        }
    }
}

Tool Configuration

Edit mcp-config.json to define which cmdlets to expose:

{
    "serverInfo": {
        "name": "posh-mcp",
        "version": "1.0.0"
    },
    "modules": [
        {
            "name": "ModuleName",
            "path": "./MyModule.psm1",
            "cmdlets": [
                "Get-MyData",
                "Set-MyConfig"
            ]
        }
    ],
    "scripts": [
        {
            "path": "./my-tools.ps1",
            "cmdlets": [
                "Get-CustomInfo",
                "Invoke-CustomTask"
            ]
        }
    ]
}

Configuration Structure:

  • serverInfo: Metadata about the MCP server

    • name: Server name displayed to MCP clients
    • version: Server version
  • modules: PowerShell modules to import

    • name: Module name (informational)
    • path: Relative or absolute path to the .psm1 file
    • cmdlets: Array of cmdlet names to expose as tools
  • scripts: PowerShell script files to dot-source

    • path: Relative or absolute path to the .ps1 file
    • cmdlets: Array of function names to expose as tools

Creating Custom Tools

Example: Creating a Custom Script

Create a script file (e.g., my-tools.ps1):

function Get-SystemUptime {
    <#
    .SYNOPSIS
        Returns the system uptime information.
    
    .DESCRIPTION
        Gets how long the system has been running since last boot.
    
    .EXAMPLE
        Get-SystemUptime
        Returns uptime information.
    
    .OUTPUTS
        Hashtable with uptime details.
    #>
    [CmdletBinding()]
    param()
    
    $os = Get-CimInstance Win32_OperatingSystem
    $uptime = (Get-Date) - $os.LastBootUpTime
    
    return @{
        LastBootTime = $os.LastBootUpTime.ToString("o")
        UptimeDays = $uptime.Days
        UptimeHours = $uptime.Hours
        UptimeMinutes = $uptime.Minutes
    }
}

Add to mcp-config.json:

{
    "scripts": [
        {
            "path": "./my-tools.ps1",
            "cmdlets": [
                "Get-SystemUptime"
            ]
        }
    ]
}

The tool will automatically be exposed as getSystemUptime (camelCase) with schema generated from the comment-based help.

Documentation Best Practices

For best results, include complete comment-based help in your cmdlets:

function Get-MyData {
    <#
    .SYNOPSIS
        Brief one-line description (becomes tool description)
    
    .PARAMETER Name
        Detailed parameter description (appears in tool schema)
    
    .PARAMETER StartDate
        Start date for filtering results
    
    .EXAMPLE
        Get-MyData -Name "Test" -StartDate "2025-01-01"
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Name,
        
        [Parameter(Mandatory = $false)]
        [DateTime]$StartDate = (Get-Date).AddDays(-7)
    )
    
    # Your implementation
}

Security Considerations

Why This Is Safer

  1. Whitelist-Only: Only cmdlets explicitly listed in mcp-config.json are accessible
  2. No Dynamic Execution: The server doesn't execute arbitrary PowerShell commands
  3. Parameter Validation: All parameters go through PowerShell's native validation
  4. Isolated Scope: Each cmdlet runs in a controlled context

Related Servers