Running One Shared Service¶
STDIO makes each MCP client launch its own server process. Streamable HTTP lets every local agent session connect to one long-lived process instead.
The server is stateless at the MCP transport layer. It does not require session affinity, and all connected clients share one process-wide PageSpeed request limit.
Endpoints¶
| Endpoint | Purpose |
|---|---|
http://127.0.0.1:8080/mcp |
Streamable HTTP MCP |
http://127.0.0.1:8080/health |
Supervisor health and version metadata |
http://127.0.0.1:8080/shutdown |
Manager-authenticated graceful shutdown |
The listener defaults to 127.0.0.1. Use --listen-address only when network
access is intentional. The included service manager is deliberately
loopback-only; network deployments should use a platform service supervisor.
Prepare credentials¶
The shared process must receive the Google API key itself. Client-side HTTP MCP configuration does not launch the server and therefore cannot supply its environment.
Set GOOGLE_PSI_API_KEY in the service environment or place it in a .env
file beside the binary. Do not put the key into the HTTP client configuration.
Manage the process¶
The repository and GitHub release include a reusable PowerShell service manager:
$manager = ".\scripts\manage-mcp-service.ps1"
$binary = "C:\path\to\psi-mcp-go.exe"
& $manager Start -BinaryPath $binary
& $manager Status -BinaryPath $binary
& $manager Restart -BinaryPath $binary
& $manager Stop -BinaryPath $binary
Windows PowerShell is sufficient on Windows. Linux and macOS require
PowerShell 7 (pwsh) and nohup.
Start is idempotent: it checks /health and reuses the existing process.
Concurrent start attempts are serialized so multiple agent sessions do not
launch duplicate servers.
Runtime state and logs are stored under the current user's local application data directory:
The state file records the PID, process creation time, executable path, and a
per-run shutdown credential. Stop verifies the process identity, requests a
graceful shutdown, and only falls back to terminating that verified process.
This prevents a stale PID from targeting an unrelated application. On Unix,
the state directory and file are restricted before the shutdown credential is
persisted.
To replace a stopped or running binary:
& $manager Update `
-BinaryPath "C:\path\to\psi-mcp-go.exe" `
-ReplacementBinaryPath "C:\downloads\psi-mcp-go-windows-amd64.exe"
The manager works with either the Go or C# binary because both accept the same transport, address, and port arguments.
Configure Copilot CLI¶
Replace the STDIO entry with an HTTP entry:
{
"mcpServers": {
"pagespeed-insights": {
"type": "http",
"url": "http://127.0.0.1:8080/mcp",
"tools": ["*"]
}
}
}
The command, args, and env properties are removed because Copilot no
longer launches the server. Restart existing Copilot sessions after changing
the configuration.
STDIO remains available for clients that cannot use Streamable HTTP.
Start automatically¶
Run the manager's Start action from a user-level startup mechanism such as:
- a Copilot
sessionStarthook - Windows Task Scheduler
- a systemd user service
- a launchd user agent
Repeated calls are inexpensive health checks and will not create another server while the existing instance is healthy.
Concurrency and quotas¶
The limit of four concurrent PageSpeed requests is process-wide. Calls from different MCP clients queue behind the same limiter rather than multiplying the upstream load by the number of agent sessions.
Each analyze_pages call still accepts at most ten URLs and preserves input
order in its response.
Network deployment¶
Loopback hosting is intended for a single user's trusted local processes. For any non-loopback listener:
- Terminate TLS at the service or a trusted reverse proxy.
- Authenticate and authorize every MCP request.
- Validate
Originat the ingress and preserve the effective scheme and host when forwarding accepted requests. - Apply request, connection, and rate limits at the ingress.
- Trust forwarded headers only from a proxy that replaces untrusted values.
The built-in HTTP host does not implement OAuth and should not be exposed directly to the internet.