Skip to content

Commit 125012b

Browse files
committed
Add Named Pipe communication tests to GitHub Actions
1 parent 26af07e commit 125012b

1 file changed

Lines changed: 172 additions & 11 deletions

File tree

.github/workflows/cross-platform-test.yml

Lines changed: 172 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,185 @@ jobs:
137137
138138
Write-Host "`n=== All tests passed ===" -ForegroundColor Green
139139
140-
- name: Test Proxy startup
140+
- name: Test Proxy JSON-RPC communication
141141
shell: pwsh
142142
run: |
143143
$ErrorActionPreference = "Stop"
144144
145-
Write-Host "=== Testing Proxy ===" -ForegroundColor Cyan
145+
Write-Host "=== Testing Proxy JSON-RPC ===" -ForegroundColor Cyan
146146
$proxyPath = Get-MCPProxyPath
147147
148+
# Start Proxy process with redirected stdin/stdout
149+
$psi = [System.Diagnostics.ProcessStartInfo]::new()
150+
$psi.FileName = $proxyPath
151+
$psi.RedirectStandardInput = $true
152+
$psi.RedirectStandardOutput = $true
153+
$psi.RedirectStandardError = $true
154+
$psi.UseShellExecute = $false
155+
$psi.CreateNoWindow = $true
156+
157+
$process = [System.Diagnostics.Process]::Start($psi)
158+
159+
function Send-JsonRpc {
160+
param([string]$Json)
161+
$process.StandardInput.WriteLine($Json)
162+
$process.StandardInput.Flush()
163+
Start-Sleep -Milliseconds 500
164+
165+
# Read available output
166+
$output = ""
167+
while ($process.StandardOutput.Peek() -ge 0) {
168+
$output += [char]$process.StandardOutput.Read()
169+
}
170+
return $output
171+
}
172+
173+
try {
174+
# Test 1: Initialize
175+
Write-Host "`n=== Test 1: Initialize ===" -ForegroundColor Yellow
176+
$initRequest = '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
177+
$response = Send-JsonRpc $initRequest
178+
Write-Host "Response: $response"
179+
180+
if ($response -match '"protocolVersion"') {
181+
Write-Host "Initialize: PASSED" -ForegroundColor Green
182+
} else {
183+
throw "Initialize failed - no protocolVersion in response"
184+
}
185+
186+
# Send initialized notification
187+
$process.StandardInput.WriteLine('{"jsonrpc":"2.0","method":"notifications/initialized"}')
188+
$process.StandardInput.Flush()
189+
Start-Sleep -Milliseconds 200
190+
191+
# Test 2: List tools
192+
Write-Host "`n=== Test 2: List Tools ===" -ForegroundColor Yellow
193+
$listRequest = '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
194+
$response = Send-JsonRpc $listRequest
195+
Write-Host "Response: $response"
196+
197+
if ($response -match '"get_current_location"' -and $response -match '"invoke_expression"' -and $response -match '"start_powershell_console"') {
198+
Write-Host "List Tools: PASSED" -ForegroundColor Green
199+
} else {
200+
throw "List Tools failed - expected tools not found"
201+
}
202+
203+
Write-Host "`n=== All JSON-RPC tests passed ===" -ForegroundColor Green
204+
205+
} finally {
206+
if (-not $process.HasExited) {
207+
$process.Kill()
208+
}
209+
$process.Dispose()
210+
}
211+
212+
- name: Test Named Pipe communication
213+
shell: pwsh
214+
run: |
215+
$ErrorActionPreference = "Stop"
216+
217+
Write-Host "=== Testing Named Pipe Communication ===" -ForegroundColor Cyan
218+
219+
# Start a background pwsh process with PowerShell.MCP imported
220+
Write-Host "Starting background pwsh with PowerShell.MCP..."
221+
$bgPsi = [System.Diagnostics.ProcessStartInfo]::new()
222+
$bgPsi.FileName = "pwsh"
223+
$bgPsi.Arguments = "-NoProfile -NoExit -Command `"Import-Module PowerShell.MCP; while (`$true) { Start-Sleep -Seconds 1 }`""
224+
$bgPsi.UseShellExecute = $false
225+
$bgPsi.CreateNoWindow = $true
226+
$bgPsi.RedirectStandardInput = $true
227+
$bgPsi.RedirectStandardOutput = $true
228+
$bgPsi.RedirectStandardError = $true
229+
230+
$bgProcess = [System.Diagnostics.Process]::Start($bgPsi)
231+
Write-Host "Background pwsh PID: $($bgProcess.Id)"
232+
233+
# Wait for Named Pipe server to be ready
234+
Write-Host "Waiting for Named Pipe server..."
235+
$pipeName = "PowerShell.MCP.$($bgProcess.Id)"
236+
$pipeReady = $false
237+
for ($i = 0; $i -lt 30; $i++) {
238+
Start-Sleep -Milliseconds 500
239+
if ($IsWindows) {
240+
$pipeReady = Test-Path "\\.\pipe\$pipeName"
241+
} else {
242+
$pipeReady = Test-Path "/tmp/CoreFxPipe_$pipeName"
243+
}
244+
if ($pipeReady) {
245+
Write-Host "Named Pipe ready after $($i * 500)ms"
246+
break
247+
}
248+
}
249+
250+
if (-not $pipeReady) {
251+
$bgProcess.Kill()
252+
throw "Named Pipe server did not start within 15 seconds"
253+
}
254+
255+
# Start Proxy
148256
Write-Host "Starting Proxy..."
149-
$process = Start-Process -FilePath $proxyPath -PassThru
257+
$proxyPath = Get-MCPProxyPath
258+
$psi = [System.Diagnostics.ProcessStartInfo]::new()
259+
$psi.FileName = $proxyPath
260+
$psi.RedirectStandardInput = $true
261+
$psi.RedirectStandardOutput = $true
262+
$psi.RedirectStandardError = $true
263+
$psi.UseShellExecute = $false
264+
$psi.CreateNoWindow = $true
150265
151-
Start-Sleep -Seconds 2
266+
$process = [System.Diagnostics.Process]::Start($psi)
152267
153-
if ($process.HasExited) {
154-
Write-Host "Proxy exited with code: $($process.ExitCode)" -ForegroundColor Red
155-
throw "Proxy exited unexpectedly"
156-
} else {
157-
Write-Host "Proxy is running (PID: $($process.Id))" -ForegroundColor Green
158-
Stop-Process -Id $process.Id -Force
159-
Write-Host "Proxy stopped successfully" -ForegroundColor Green
268+
function Send-JsonRpc {
269+
param([string]$Json, [int]$WaitMs = 2000)
270+
$process.StandardInput.WriteLine($Json)
271+
$process.StandardInput.Flush()
272+
Start-Sleep -Milliseconds $WaitMs
273+
274+
$output = ""
275+
while ($process.StandardOutput.Peek() -ge 0) {
276+
$output += [char]$process.StandardOutput.Read()
277+
}
278+
return $output
279+
}
280+
281+
try {
282+
# Initialize
283+
$initRequest = '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
284+
$null = Send-JsonRpc $initRequest
285+
$process.StandardInput.WriteLine('{"jsonrpc":"2.0","method":"notifications/initialized"}')
286+
$process.StandardInput.Flush()
287+
Start-Sleep -Milliseconds 200
288+
289+
# Test: invoke_expression with Get-Date
290+
Write-Host "`n=== Test: invoke_expression (Get-Date) ===" -ForegroundColor Yellow
291+
$invokeRequest = '{"jsonrpc":"2.0","id":10,"method":"tools/call","params":{"name":"invoke_expression","arguments":{"pipeline":"Get-Date -Format yyyy-MM-dd"}}}'
292+
$response = Send-JsonRpc $invokeRequest 3000
293+
Write-Host "Response: $response"
294+
295+
$today = Get-Date -Format "yyyy-MM-dd"
296+
if ($response -match $today) {
297+
Write-Host "invoke_expression (Get-Date): PASSED - Got today's date" -ForegroundColor Green
298+
} else {
299+
throw "invoke_expression failed - expected date $today not found in response"
300+
}
301+
302+
# Test: get_current_location
303+
Write-Host "`n=== Test: get_current_location ===" -ForegroundColor Yellow
304+
$locRequest = '{"jsonrpc":"2.0","id":11,"method":"tools/call","params":{"name":"get_current_location","arguments":{}}}'
305+
$response = Send-JsonRpc $locRequest 3000
306+
Write-Host "Response: $response"
307+
308+
if ($response -match '"current_location"' -or $response -match '"system"') {
309+
Write-Host "get_current_location: PASSED" -ForegroundColor Green
310+
} else {
311+
throw "get_current_location failed - no location info in response"
312+
}
313+
314+
Write-Host "`n=== All Named Pipe tests passed ===" -ForegroundColor Green
315+
316+
} finally {
317+
if (-not $process.HasExited) { $process.Kill() }
318+
$process.Dispose()
319+
if (-not $bgProcess.HasExited) { $bgProcess.Kill() }
320+
$bgProcess.Dispose()
160321
}

0 commit comments

Comments
 (0)