Skip to main content
Glama
yxxrn

ChatGPT Windows MCP

by yxxrn
README.md
# ChatGPT Windows MCP

Loopback-only Node.js MCP server for Windows 10/11 and Windows Server. The server exposes safe workspace tools by default and requires an explicit Administrator-mode opt-in for PowerShell and persistent jobs.

## Safety model

The process binds only to `127.0.0.1`. Public access, when desired, is an outbound Cloudflare Tunnel mapping a hostname to the loopback port; no inbound firewall rule or port forwarding is needed. Safe mode never exposes arbitrary PowerShell. Administrator tools are open-world and potentially destructive, and are enabled only with `ENABLE_ADMINISTRATOR_TOOLS=true` plus an explicit installer flag.

## Local verification

Requirements: Node.js 22+, PowerShell 5.1 or 7, and (optionally) Pester for installer tests.

```powershell
npm ci
npm test
pwsh -NoProfile -File .\scripts\Test-Local.ps1
Invoke-Pester .\test\installer.Tests.ps1
```

`Test-Local.ps1` uses a temporary state directory and random high loopback port, restores environment variables, stops its child process, and removes the temporary directory. It does not create accounts, tasks, services, firewall rules, DNS records, tunnels, or public exposure.

## Installation

Review `Install.ps1 -WhatIf` first. A real installation is an explicit administrative action:

```powershell
.\scripts\Install.ps1 -Hostname mcp.example.com -TunnelToken $token
.\scripts\Install.ps1 -Hostname mcp.example.com -TunnelToken $token -EnableAdministratorTools
```

The installer preflights Node.js, npm, PowerShell, Task Scheduler, the safe-mode account capability, the loopback port, and an already verified `cloudflared.exe` before mutation. It copies the app, runs `npm ci`, persists OAuth secrets, creates the exact `ChatGPTMcpSvc` local identity for safe mode, grants it the required `SeBatchLogonRight`, read-only runtime/config access, and Modify access only to workspace/jobs, and registers an S4U/least-privilege task without storing the generated password in the task. Administrator mode instead uses SYSTEM/highest privileges and should be reserved for a dedicated host. The local test workflow never executes these mutations. The named tunnel service is installed only by the real installer action with the supplied token; verify Cloudflare's Authenticode signature and SHA-256 first.

## Connecting ChatGPT

Expose only the loopback service through a named Cloudflare Tunnel. Configure the public HTTPS hostname as the OAuth issuer and MCP URL. In ChatGPT's connector setup use the authorization-server discovery URL `https://HOST/.well-known/oauth-authorization-server`; dynamic client registration returns a public client ID and loopback/HTTPS redirect URI. Authorization uses the owner password, authorization code, and PKCE S256. Never paste tunnel tokens, owner passwords, refresh tokens, or credential files into chat.

## Operations and rollback

Health is `GET /health`; MCP JSON-RPC is `POST /mcp`. Background jobs and persisted OAuth client registrations (`oauth-clients.json`) live under the configured jobs directory, survive the originating request, expose bounded tail logs, and retain records for seven days by default. Keep the app, state, and tunnel credentials backed up separately. Run `Uninstall.ps1 -WhatIf` before removal. State, credentials, and the dedicated service identity are preserved by default; `-RemoveState`, `-RemoveCredentials`, and `-RemoveServiceAccount` are explicit flags. The identity is removed only when `config.json` proves this installation created it. Remove the `cloudflared` service only with `-RemoveCloudflaredWhenExclusive` after confirming ownership.

## Configuration

See `.env.example`. `MCP_HOST` is loopback-only, ports are 1024–65535, and non-test issuers must be HTTPS. Do not commit `.env`, OAuth state, job output, tunnel credentials, generated passwords, certificates, or local config.

## Resource limits

Foreground PowerShell calls are capped at 300 seconds and 1 MiB per output stream. OAuth request bodies are capped at 16 KiB; MCP request bodies at 64 KiB. Job logs can be tailed up to 1 MiB. The server does not log command output or Authorization headers.

## Threat model

Model output is untrusted input. OAuth authenticates the connector but does not make Administrator commands safe. Workspace resolution rejects absolute paths, traversal, symbolic links, junctions, and other reparse points. The tunnel is the only supported public ingress. Use a dedicated Windows identity, least privilege, restrictive ACLs, patched Node/PowerShell, and a narrowly scoped workspace.