Public/New-MCP.ps1

Class TemplateNames : System.Management.Automation.IValidateSetValuesGenerator {
    [String[]] GetValidValues() {
        $templates = foreach ($template in Get-ChildItem $PSScriptRoot\..\template) {
            $template.BaseName -replace '.template', ''
        }
        
        return $templates
    }
}

function New-MCP {
    [CmdletBinding(SupportsShouldProcess = $true)]
    [OutputType([System.IO.DirectoryInfo])]
    param(
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [string]
        $Path, # Removed default value

        [Parameter()]
        [string]
        $ServerName = "MCPServer",

        [ValidateSet([TemplateNames])]
        [string]$template,

        [Parameter()]
        [switch]
        $Force
    )

    begin {
        # Determine the target directory
        $TargetDirectoryPath = $null
        if ([string]::IsNullOrEmpty($Path)) {
            # If Path is not specified, use the current directory
            $TargetDirectoryPath = (Get-Location).Path
            Write-Verbose "No -Path specified, using current directory: $TargetDirectoryPath"
        }
        else {
            # If Path is specified, check if it's an absolute path or a special path like TestDrive:
            if ([System.IO.Path]::IsPathRooted($Path) -or $Path -like "TestDrive:*") {
                $TargetDirectoryPath = $Path
            }
            else {
                # If not absolute, resolve it relative to the current directory
                $TargetDirectoryPath = Join-Path -Path (Get-Location).Path -ChildPath $Path
            }
        }

        # Resolve the final target directory path
        $TargetDirectory = Resolve-Path -Path $TargetDirectoryPath -ErrorAction SilentlyContinue
        if (-not $TargetDirectory) {
            # If path doesn't exist after resolving, treat it as a new directory to be created
            $TargetDirectory = $TargetDirectoryPath
            Write-Verbose "Target directory '$TargetDirectory' does not exist. It will be created."
        }
        elseif (Test-Path -Path $TargetDirectory -PathType Leaf) {
            throw "The specified path '$TargetDirectory' exists but is a file, not a directory."
        }

        # Construct paths for files and directories directly within the target directory
        $VscodeFolderPath = Join-Path -Path $TargetDirectory -ChildPath ".vscode"
        $McpJsonPath = Join-Path -Path $VscodeFolderPath -ChildPath "mcp.json"
        $ServerScriptPath = Join-Path -Path $TargetDirectory -ChildPath "$($ServerName).ps1"

        # Determine the script's directory
        $ScriptDirectory = Split-Path -Path $PSCommandPath -Parent

        # Determine the module root (one level up from Public)
        $ModuleRoot = Split-Path -Path $ScriptDirectory -Parent

        # Construct the template path

        if (-not $template) {
            $template = "server"
        }
        
        $templatePath = "template\$($template).template.ps1"

        # $TemplatePath = Join-Path -Path $ModuleRoot -ChildPath "template\server.template.ps1"
        $TemplatePath = Join-Path -Path $ModuleRoot -ChildPath $templatePath

        if (-not (Test-Path -Path $TemplatePath -PathType Leaf)) {
            throw "Server template file not found at '$TemplatePath'."
        }
    }

    process {
        $directoryExisted = Test-Path -Path $TargetDirectory -PathType Container
        $containsMcpFiles = $false
        $isEmpty = $false

        if ($directoryExisted) {
            Write-Verbose "Directory '$TargetDirectory' already exists."
            # Check for specific MCP files
            $containsMcpFiles = (Test-Path -Path $McpJsonPath -PathType Leaf) -or (Test-Path -Path $ServerScriptPath -PathType Leaf)
            # Check if the directory is empty (ignoring hidden/system items potentially)
            $isEmpty = (Get-ChildItem -Path $TargetDirectory -Force -ErrorAction SilentlyContinue | Measure-Object).Count -eq 0

            if ($containsMcpFiles -and -not $Force) {
                # It exists AND looks like an MCP project AND -Force is not used
                Write-Error "Directory '$TargetDirectory' already contains MCP configuration files (mcp.json or $($ServerName).ps1). Use -Force to overwrite."
                return # Stop execution
            }
            # If it exists but is empty, or doesn't contain MCP files, or -Force is used, we proceed.
            # Informational message will be printed after directory is confirmed/created.
        }
        else {
            # Directory does not exist, create it
            if ($PSCmdlet.ShouldProcess($TargetDirectory, "Create directory")) {
                New-Item -Path $TargetDirectory -ItemType Directory -Force:$Force | Out-Null
            }
            else {
                Write-Warning "Directory creation skipped by user."
                return
            }
        }

        # --- Point where directory is guaranteed to exist ---

        # Print informational message *before* creating/overwriting files
        if ($directoryExisted) {
            # Use $isEmpty here
            if ($isEmpty -or !$containsMcpFiles) {
                Write-Host "Initialized MCP project in existing directory '$TargetDirectory'."
            } 
            # If it contained MCP files and -Force was used, the file-level warnings/overwrites will occur.
            # A specific message here might be redundant or slightly confusing depending on which files get overwritten.
        }
        else {
            Write-Host "Initialized MCP project in new directory '$TargetDirectory'."
        }

        # 2. Create .vscode directory
        if (-not (Test-Path -Path $VscodeFolderPath -PathType Container)) {
            if ($PSCmdlet.ShouldProcess($VscodeFolderPath, "Create directory '.vscode'")) {
                New-Item -Path $VscodeFolderPath -ItemType Directory | Out-Null
            }
        }
        else {
            Write-Verbose "Directory '$VscodeFolderPath' already exists."
        }

        # 3. Create mcp.json
        $mcpJsonContent = @'
{
    "servers": {
        "mcp-powershell-{servername}": {
            "type": "stdio",
            "command": "pwsh",
            "args": [
                "-NoProfile",
                "-Command",
                "${workspaceFolder}\\{scriptname}.ps1"
            ]
        }
    }
}
'@
 -replace '\{servername\}', $ServerName -replace '\{scriptname\}', $ServerName

        if (Test-Path -Path $McpJsonPath -PathType Leaf) {
            Write-Verbose "File '$McpJsonPath' already exists."
            if (-not $Force) {
                Write-Warning "File '$McpJsonPath' already exists. Use -Force to overwrite."
            }
            elseif ($PSCmdlet.ShouldProcess($McpJsonPath, "Overwrite file 'mcp.json'")) {
                Set-Content -Path $McpJsonPath -Value $mcpJsonContent -Force
            }
        }
        else {
            if ($PSCmdlet.ShouldProcess($McpJsonPath, "Create file 'mcp.json'")) {
                # Ensure parent directory exists before writing file
                if (-not (Test-Path -Path $VscodeFolderPath -PathType Container)) {
                    New-Item -Path $VscodeFolderPath -ItemType Directory | Out-Null
                }
                Set-Content -Path $McpJsonPath -Value $mcpJsonContent
            }
        }

        # 4. Create $ServerName.ps1 from template
        $templateContent = Get-Content -Path $TemplatePath -Raw
        # Potentially add replacements to the template content here if needed in the future

        if (Test-Path -Path $ServerScriptPath -PathType Leaf) {
            Write-Verbose "File '$ServerScriptPath' already exists."
            if (-not $Force) {
                Write-Warning "File '$ServerScriptPath' already exists. Use -Force to overwrite."
            }
            elseif ($PSCmdlet.ShouldProcess($ServerScriptPath, "Overwrite file '$($ServerName).ps1'")) {
                Set-Content -Path $ServerScriptPath -Value $templateContent -Force
            }
        }
        else {
            if ($PSCmdlet.ShouldProcess($ServerScriptPath, "Create file '$($ServerName).ps1'")) {
                Set-Content -Path $ServerScriptPath -Value $templateContent
            }
        }
    }
}