Skip navigation

PublicSeries

Self-hosting Cloud Harness MCP for ChatGPT (1/3): Overview and prerequisites

Part 1 of 3: what Cloud Harness MCP is, why it needs a VPS, Cloudflare Access and your own domain, the prerequisites, and the end-to-end order.

10 min read · v1.0.0 · Updated 16/09/2026

VI · Tự host Cloud Harness MCP cho ChatGPT (1/3): Tổng quan và điều kiện cần · Read in Vietnamese

Quick summary: you need a VPS to run Docker, a domain in Cloudflare to act as the OAuth sign-in gate, and a ChatGPT plan that supports MCP (Model Context Protocol). The order is: deploy to the VPS, put the hostname behind Cloudflare Access, enable Managed OAuth, switch the origin to cloudflare-access mode, then create the connector in ChatGPT. You only need a GitHub App when cloning private repos.

Disclosure: I maintain AgentKit and have an affiliate relationship with it: the AgentKit link in this post is an affiliate link; buying through it gets you 30% off. Cloud Harness MCP is written by Duy Nguyen (@mrgoonie). The source lives in the bestagentkits/cloud-harness-mcp repo under the AgentKit organization on GitHub, and the docs at docs.harness.agentkit.best. I am not the author of Cloud Harness; this series is how I set it up myself from that repo.

The images are real screenshots from a running instance. Screenshots and menu paths reflect the ChatGPT, Cloudflare, and GitHub interfaces as of September 16, 2026; these change often, so if a button is not where the guide says, search by the section name. Every identifying value is blurred: hostname, root domain, VPS IP, email, AUD, team domain, user name, GitHub App name and ID, repo name. Each blurred region maps to a placeholder in the table at the end of section 2. On October 29, 2026 I rechecked the steps against the repo at v0.79.1; the repo changes almost daily, so where they disagree, the repo's docs/ wins.

This is part 1 of a three-part series. It covers what Cloud Harness MCP is, the prerequisites and the end-to-end order. Part 2 walks the deploy and ChatGPT connector steps, and Part 3 gives a prompt for handing the VPS work to an AI agent. Part 1 is free to read; Parts 2 and 3 are for Subscribers.


1. Introduction

What Cloud Harness MCP is, why it needs exactly this VPS + Cloudflare pairing, and what you can do once it is set up.

What Cloud Harness MCP is

Cloud Harness MCP is a private, single-owner coding harness that runs on your own server and is exposed over authenticated MCP using Streamable HTTP (HyperText Transfer Protocol). Instead of letting an agent run commands on your machine, it opens a temporary workspace on the VPS: clones the repo into a sandbox, runs commands in a non-root Docker executor, cleans up on a TTL, then returns results to the AI client.

The agent runs on a separate Linux machine that Harness provisions, not on yours. The repo and Docker both live inside a container on that machine; when the TTL expires, Harness removes the container and workspace files, while the VPS itself stays.

Architecture

The architecture separates authentication authority from Docker authority. Everything in the later sections follows from this diagram.

A request goes from the AI client through a credential-free ingress and a stateless MCP API to the trusted runner, the only holder of Docker authority, state and credentials, then to an isolated non-root executor
Only the trusted runner holds Docker authority, state and credentials.
ComponentWhy it cannot be substituted
VPSDocker authority, the runner and the state all live here. Cloudflare and ChatGPT do not run containers
Cloudflare AccessChatGPT has nowhere to attach Authorization: Bearer, so an OAuth/JWT layer at the edge is mandatory
GitHub AppThe executor never sees a GitHub token; the broker passes credentials over stdin. Private repos require the App
Your own domainManaged OAuth needs a hostname inside a Cloudflare zone you control

This model is designed for one trusted operator, not as a multi-tenant sandbox hardened against attackers.

Two connection lanes

Two flows: Managed OAuth through Cloudflare Access for ChatGPT and Claude Desktop, a fixed API key for Cursor, Claude Code, Codex and the command line
ChatGPT only supports OAuth, so this guide takes the Managed OAuth flow.
LaneEndpointAuthUsed by
Managed OAuth<MCP_HOST>/mcpSSO (Single Sign-On) via Cloudflare AccessChatGPT, Claude Desktop
Static API (Application Programming Interface) keyapi.<ROOT_DOMAIN>/mcpAuthorization: Bearer <dashboard-api-key>Cursor, Claude Code, Codex, CLI

This guide takes the Managed OAuth lane, because ChatGPT only supports OAuth. Add the API key lane later if you need it.

What you can do once it is set up

On ChatGPT Web you only do three things:

  1. Open a new 1-on-1 chat. Not a Custom GPT, Project chat, Canvas or the mobile app.
  2. Pick the CloudHarness connector from the tools menu, or type @CloudHarness.
  3. Describe the work along with the repo URL, for example: "clone https://github.com/<OWNER>/<REPO>.git, run npm test, then commit the fix".

As you chat, the agent walks the four steps below and calls the matching tools:

Step in the sessionTool the agent calls
Open a workspace and clone the repoworkspace_open
Read and edit codefiles_list, files_read, grep_search, files_write
Run commands and testsexec_run
Commit, then close the workspacegit_status, git_commit, git_push, workspace_close

When you are done, tell the agent to close the workspace. Forgetting is fine. The workspace self-destructs when the idle TTL or the wall TTL runs out. The defaults are 5 minutes and 15 minutes (still true at v0.79.1). You can change them in the dashboard's Settings, which applies to workspaces opened afterwards, or through WORKSPACE_IDLE_TTL_SECONDS and WORKSPACE_WALL_TTL_SECONDS on the environment variables page.

Full tool set: Tools Reference.

If you do not have your own domain

This guide assumes you have a hostname inside a Cloudflare zone you manage. Without one you can only get halfway:

LaneResultWhy
owner-bearer, for Cursor, Claude Code, Codex, CLIWorksThe repo defaults to cloud-harness-mcp.<ip>.sslip.io; Let's Encrypt can issue a cert because sslip.io resolves to the IP embedded in the name. The trade-off: the dashboard is disabled in this mode
cloudflare-access, for ChatGPT WebDoes not workAn Access self-hosted app must attach to a hostname in your Cloudflare zone, and needs a Zero Trust org matching that zone. docs/deployment.md is explicit: "requires a hostname in an owner-controlled Cloudflare-managed zone… the current sslip.io hostname may not satisfy that prerequisite"

If ChatGPT is the target, you need a hostname in a zone you manage; it does not have to be a pretty domain. A cheap domain added to Cloudflare's free plan is enough. You can also keep the domain at another registrar and point its nameservers, or delegate a subdomain, to Cloudflare. The Zero Trust free plan covers a single user, so the main cost is the domain.

Unverified: whether *.workers.dev, *.pages.dev or *.cfargotunnel.com can serve as an Access self-hosted application. The current understanding is no, because those are not zones you control, but this has not been tested, so do not treat it as settled.


2. Prerequisites

Eight prerequisites before you start. The first three are infrastructure, the next four are accounts and permissions, the last is usage.

#PrerequisiteWhy
1Linux VPS (the repo recommends Ubuntu 24.04 LTS or Debian 12; at least 4 GB of RAM, 8 GB recommended; a 40 GB or larger SSD) + Docker Engine 26 or newer with Compose v2, nginx, Certbot (nginx plugin), Git, curl, OpenSSL, systemd; ports 80/443 open to nginxThis is where the repo is cloned and the executor runs. Each workspace can use up to 1 GiB of RAM and one CPU. Cloudflare and ChatGPT cannot run Docker for you
2A hostname you control, inside a Cloudflare zone, pointing at the VPSdocs/deployment.md requires a "hostname in an owner-controlled Cloudflare-managed zone". An sslip.io hostname does not qualify. Only required for the ChatGPT lane
3A Cloudflare Zero Trust organization matching that zoneTo create the Access application, the Allow policy and the Identity Provider
4AUTH_MODE=cloudflare-access + issuer/audience/JWKS on the originThe origin only trusts JWTs issued by Access
5A ChatGPT plan with full MCP supportCheck OpenAI's help page for your plan. Some plans can enable Developer mode and draft connectors but still hit FORBIDDEN: This conversation does not support developer MCPs at run time
6Managed OAuth + Allowed redirect URIs on the Access appChatGPT has nowhere to attach an Authorization: Bearer header
7An Access service token for the deploy canaryIn Access mode the deploy command checks the new release through the public HTTPS edge with a service token. Without one the canary fails and the deploy rolls itself back
8A 1-on-1 chat on the webIt does not run in a Custom GPT, Project chat (unless enabled), Canvas, temporary chat or mobile

Only needed for specific cases: a GitHub App (only when cloning private repos) and an API-key gateway at api.<ROOT_DOMAIN> (a separate lane for IDE/CLI). The API key lane does not require Cloudflare Access, and per the table in section 1, owner-bearer mode still works with an sslip.io hostname.

One side alone is not enough. Cloudflare without a VPS leaves nowhere to run workspaces and Docker. A VPS without Cloudflare Access means ChatGPT Web cannot follow the documented OAuth flow.

Enable Developer mode in ChatGPT

Path: https://chatgpt.com/ → avatar → Settings → Security and login → Developer mode (#settings/Security?section=developer-mode). Turn on the toggle and read the ELEVATED RISK warning. If your menu differs, the Cloud Harness docs give the path Settings → Apps → Advanced settings → Developer mode.

ChatGPT Developer mode

Cloudflare zone Active

What about the one-command installer

The repo now ships scripts/install.sh, a one-command install with Caddy or Cloudflare Tunnel. That installer writes AUTH_MODE=owner-bearer, which is the API-key route for IDEs and the command line. The Cloudflare Access rollout in docs/deployment.md is written for the nginx route, so this series follows nginx.

Placeholders and sample values

From here on, the guide uses placeholders instead of real values. In the screenshots, these are the blurred regions.

PlaceholderMeaningSample value, or what the blur hides
<MCP_HOST>Public hostname of the MCPe.g. mcp.example.com
<ROOT_DOMAIN>Cloudflare zonee.g. example.com
<MCP_SUBDOMAIN>A record subdomainmcp (not blurred)
<VPS_PUBLIC_IP>VPS IPv4e.g. 203.0.113.10 (the A record content)
<CF_TEAM>Zero Trust team nameteam name + team domain
<ACCESS_AUD>Application Audience (AUD) Tagthe hex string in the AUD tag tab
<GITHUB_APP_SLUG>GitHub App slugapp name on GitHub + breadcrumb
<GITHUB_APP_ID>Numeric App IDthe App ID: line
<GITHUB_INSTALLATION_ID>Numeric Installation IDthe INSTALLATION ID: line on the dashboard
<OWNER>/<REPO>Credential-free HTTPS repothe repo name in the list
<OPERATOR_EMAIL>Email in the Allow policythe email chip in the policy

Configuration and secrets live in /etc/cloud-harness-mcp on the VPS (owned by root, mode 700). The runner sees that directory read-only at /run/cloud-harness-secrets. Commands you run on the VPS use the first path; environment variables that point at a secret file, such as GITHUB_APP_PRIVATE_KEY_FILE, use the second.

Endpoints after substitution:

PurposeEndpoint
MCP (ChatGPT OAuth)https://<MCP_HOST>/mcp
Dashboardhttps://<MCP_HOST>/dashboard
Bind GitHubhttps://<MCP_HOST>/dashboard/github
MCP gateway (same Access application as /mcp)https://<MCP_HOST>/mcp-gateway
Local healthhttp://127.0.0.1:3100/readyz
API key lanehttps://api.<ROOT_DOMAIN>/mcp

A. End-to-end order

  1. Prepare the VPS + CF domain + Zero Trust + ChatGPT plan (section 2).
  2. DNS Proxied and pick the SSL/TLS mode (Part 2, section 3).
  3. Bootstrap the VPS, get TLS, deploy twice in owner-bearer mode, local /readyz returns 200 (section 4).
  4. Access app + hostname + policy + IdP (section 5).
  5. Managed OAuth + redirect URIs + AUD and team domain (section 6).
  6. Create the canary service token, cut over to cloudflare-access with a separate deploy, and verify the 401 (section 7).
  7. ChatGPT connector (section 8).
  8. GitHub App and dashboard bind, for private repos only (section 9).

To hand the VPS work to an AI agent, see Part 3.


D. References

Official docs: <https://docs.harness.agentkit.best/>

Use this piece in your agent

Get an API key

Copy the text below and paste it into Claude Code, Codex or whichever agent you use. The agent reads the piece and checks it against the repo you have open.

Paste into your agent
Read "Self-hosting Cloud Harness MCP for ChatGPT (1/3): Overview and prerequisites" on modernEngineer and apply it to this repo.
1. Call the content_get tool of the modernengineer MCP server with locale "en", slug "cloud-harness-mcp-chatgpt-setup". If MCP is not connected or access is refused, read the page https://modernengineer.dev/en/library/cloud-harness-mcp-chatgpt-setup instead.
2. Summarize the main steps of the piece and point out which apply to this repo.
3. Propose concrete changes and ask me before editing any file.
Connect MCP in Claude Code (once)
terminal
claude mcp add --transport http modernengineer \
  https://api.modernengineer.dev/mcp \
  --header "Authorization: Bearer <API key>"
How to connect Codex, Cursor and other clients

This piece is open to everyone: without MCP, the agent can still read it straight from the link.

Version
v1.0.0
Updated
16/09/2026
Licence
All rights reserved
Slug
cloud-harness-mcp-chatgpt-setup