Skip to main content
Glama
0ozzzii

DSW Control MCP

by 0ozzzii
README.md
# DSW Control MCP

A private, stateless Remote MCP gateway on Cloudflare Workers for controlling one allowlisted ModelScope DSW machine through an existing HTTPS command Relay.

## Architecture

ChatGPT / MCP client → Cloudflare Worker (Streamable HTTP MCP) → fixed Relay → ModelScope DSW

## Current production-compatible endpoint

The existing connector remains valid after this upgrade:

`https://dswmcp.servers0o.kdns.fr/mcp/<MCP_PATH_KEY>`

`MCP_PATH_KEY` and `RELAY_EXEC_URL` are Cloudflare **runtime secrets**. Never commit their values.

## Tools

| Tool | Purpose | Safety metadata |
| --- | --- | --- |
| `list_targets` | List server-side allowlisted targets | read-only, closed-world |
| `status` | Harmless `echo MCP_STATUS_OK` health probe | read-only, open-world |
| `exec` | Execute one arbitrary shell command | write/destructive, non-idempotent, open-world |

All tools expose explicit input and output schemas. Tool results return both MCP `structuredContent` and concise `content` text. `exec` is intentionally marked destructive; do not change its annotations merely to suppress host safety warnings.

## Security boundaries

- No user-supplied URLs: only the `dsw` allowlist target exists.
- Relay redirects are blocked and arbitrary shell commands are never auto-retried.
- Command length, timeout and response size are bounded.
- Secrets, command text and output bodies are excluded from Worker logs.
- Known Relay/MCP credentials are redacted from returned errors/output.
- The legacy Relay URL is stored only as a Cloudflare secret.
- A preferred split Relay configuration (`RELAY_BASE_URL` + `RELAY_TOKEN`) is supported for later migration.

## Runtime secrets (current mode)

- `RELAY_EXEC_URL` — complete private Relay URL for `/r/dsw`.
- `MCP_PATH_KEY` — 32–128 character URL-safe random key.

The code also supports a preferred Relay split mode. If `RELAY_BASE_URL` and `RELAY_TOKEN` are configured, they take precedence over `RELAY_EXEC_URL`.

## OAuth 2.1 readiness

A standards-based OAuth endpoint is implemented at `/mcp`, but it stays disabled until both are configured:

1. Cloudflare KV binding named `OAUTH_KV`.
2. Runtime secret `MCP_OWNER_KEY` (distinct random secret, at least 32 characters).

The canonical public origin is `https://dswmcp.servers0o.kdns.fr`. OAuth uses PKCE S256, Client ID Metadata Documents (CIMD), DCR compatibility, exact resource binding, short access tokens, rotating refresh tokens from the Cloudflare OAuth provider, and only accepts ChatGPT OAuth redirect URIs.

Once OAuth is enabled, create a new ChatGPT connector using:

`https://dswmcp.servers0o.kdns.fr/mcp`

and select OAuth. Keep the legacy secret-path connector until the OAuth connector has been verified, then rotate/remove the exposed legacy path key.

## Development

```text
npm ci
npm run typecheck
npm test
npm run dry-run
```

Cloudflare deployment is `npx wrangler deploy` (the existing Git integration already uses this).

## Health

`GET /health` returns a non-sensitive JSON health document. It reports whether OAuth prerequisites are present, but never returns secret values.