ChatGPT VPS MCP
by yxxrn
README.md
# ChatGPT VPS MCP
A self-hosted, no-Docker MCP server that lets ChatGPT inspect and administer a Linux VPS through Streamable HTTP. It includes HTTPS deployment, OAuth discovery, Dynamic Client Registration (DCR), authorization code + PKCE, refresh tokens, and an explicitly opt-in root command mode.
> [!CAUTION]
> Root mode gives an AI model the practical equivalent of an unrestricted root shell. Prompt injection, a stolen OAuth password, or an incorrect command can expose or destroy the entire VPS. Use a dedicated VPS, keep backups, and enable root mode only when you fully accept that risk.
## Features
- Streamable HTTP MCP endpoint at `https://your-domain.example/mcp`
- OAuth-compatible discovery for ChatGPT custom plugins/connectors
- Dynamic Client Registration and PKCE
- One-hour access tokens and 30-day refresh tokens
- Root mode disabled by default
- Optional `run_command` and `run_command_batch` root tools
- Contained workspace file tools
- VPS health/status tool, resources, and prompt
- systemd service, Nginx reverse proxy, Certbot, and automatic renewal
- No Docker
## Requirements
- Ubuntu or Debian VPS
- Root/sudo access
- A domain or subdomain whose `A` record points to the VPS
- Public inbound TCP ports 80 and 443
- Node.js 22 or newer (the installer uses the distribution package)
- ChatGPT access to custom plugins/connectors and Developer mode
Typical runtime usage is roughly 120–150 MB RAM for Node.js plus Nginx. CPU usage is near zero while idle.
## Quick installation
Create a DNS record first:
```text
Type: A
Name: mcp
Value: YOUR_VPS_IPV4
Proxy: DNS only during initial certificate issuance
```
Clone and install in the safer contained mode:
```bash
git clone https://github.com/yxxrn/chatgpt-vps-mcp.git
cd chatgpt-vps-mcp
sudo bash scripts/install.sh \
--domain mcp.example.com \
--email admin@example.com
```
To deliberately enable unrestricted root commands:
```bash
sudo bash scripts/install.sh \
--domain mcp.example.com \
--email admin@example.com \
--enable-root
```
The installer:
1. Installs Node.js, Nginx, Certbot, and the Nginx Certbot plugin.
2. Creates an unprivileged `chatgpt-mcp` service account.
3. Generates an OAuth signing secret and a random owner password.
4. Installs and starts the MCP systemd service on `127.0.0.1:3000`.
5. Publishes only Nginx on ports 80/443.
6. Obtains a Let's Encrypt certificate and enables renewal.
7. Verifies the health endpoint and the unauthenticated `401` challenge.
Retrieve the generated owner password only through SSH:
```bash
sudo cat /root/chatgpt-vps-mcp-credentials.txt
```
Do not paste this password into chats, issues, logs, or source files. Enter it only on your MCP authorization page.
## Connect from ChatGPT
The exact labels can vary by ChatGPT plan and UI release:
1. Open **Settings → Plugins/Connectors → Developer mode**.
2. Create a custom plugin/connector.
3. Enter `https://mcp.example.com/mcp` as the server URL.
4. Select **OAuth**.
5. Keep **Dynamic Client Registration (DCR)** selected.
6. Keep the default scope `mcp`; leave base scopes empty.
7. Create the connector and enter the generated owner password on the authorization page.
The server advertises these endpoints automatically:
```text
/.well-known/oauth-authorization-server
/.well-known/oauth-protected-resource/mcp
/register
/authorize
/token
/mcp
```
## Available tools
Always available:
- `ping`
- `system_status`
- `list_workspace`
- `read_text_file`
- `write_text_file`
- `make_directory`
- `delete_file`
Only with `--enable-root`:
- `run_command`
- `run_command_batch`
Root tools are intentionally annotated as destructive and open-world. The MCP server itself does not add a confirmation dialog, but ChatGPT may still enforce platform-level approvals.
## Long-running work
Each command is limited to five minutes. Start longer work as a persistent background unit and poll it in later tool calls:
```bash
systemd-run --unit=my-long-job --collect /usr/local/bin/my-task
systemctl status my-long-job
journalctl -u my-long-job --no-pager -n 200
```
This keeps VPS work running even if a ChatGPT turn reaches its duration limit.
## Operations
```bash
sudo systemctl status chatgpt-vps-mcp nginx
sudo journalctl -u chatgpt-vps-mcp -n 100 --no-pager
curl https://mcp.example.com/health
sudo nginx -t
sudo certbot renew --dry-run
```
An unauthenticated MCP request should return `401`:
```bash
curl -i -X POST \
-H 'Content-Type: application/json' \
--data '{}' \
https://mcp.example.com/mcp
```
## Updating
The installer preserves existing OAuth secrets and the owner password file:
```bash
cd chatgpt-vps-mcp
git pull --ff-only
sudo bash scripts/install.sh --domain mcp.example.com --email admin@example.com --enable-root
```
Omit `--enable-root` only if you intend to disable and remove root command access.
## Security model
- The Node process binds only to loopback.
- HTTPS terminates at Nginx.
- MCP requires a valid Bearer access token.
- OAuth authorization requires the generated owner password, stored as an scrypt hash in the service environment.
- Authorization codes expire after five minutes and require PKCE S256.
- Access tokens expire after one hour; refresh tokens expire after 30 days.
- Redirect URIs must be HTTPS, except HTTP loopback callbacks.
- Authorization attempts and client registrations have in-memory rate limits.
- Workspace paths reject absolute paths, traversal, and symbolic-link segments.
- Root mode uses a narrowly named service account and an explicit sudoers file. It is still unrestricted root access by design.
This project intentionally does not pretend that model prompts are a security boundary. OAuth protects who can connect; it cannot make arbitrary root command execution intrinsically safe.
## Development
```bash
npm ci
npm run check
npm audit --omit=dev
```
Read [AGENTS.md](AGENTS.md) before agent-assisted changes.
## License
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues