Start
Self-hosting
Deploy your own authenticated MCP and REST API with Vercel and Upstash Redis.
This guide covers running your own dm-dot API. Deploy the Go MCP and REST endpoints as Vercel Functions, backed by Upstash Redis to persist your dot’s webhook subscription. You’ll get two authenticated routes, /mcp and /v1/messages, on your own Vercel hostname or custom domain.
Prerequisites
- A Vercel account with access to the source repository.
- An Upstash Redis database with its HTTPS REST endpoint and REST token. Prefer a dedicated database because it stores a webhook signing secret.
- A long, random API key stored in your password manager or secret store.
- Go 1.26+ for local development and testing; the Vercel Go builder installs its own toolchain.
The baseline architecture does not require Docker, a VPS, an OAuth identity provider, or an OpenAI Platform API key.
1. Provision Redis
Create an Upstash Redis database through the Upstash console (or its official API). For a small personal deployment, select a supported free tier if available. Prefer TLS enabled, eviction disabled, and a region near your Vercel function.
Find the database’s REST URL and token. Do not put the REST token in a tracked .env file or documentation. Pricing, limits, and free-tier availability are determined by Upstash, not this repository.
dm-dot uses the Upstash REST API and does not need a Redis TCP connection string. The application owns one key:
dm-dot:subscription:v1
This key holds the subscription callback URL, HMAC signing secret, ID, and expiration. Its Redis TTL follows the granted subscription duration. It does not store message bodies.
2. Create your Vercel project
Import the GitHub repository in Vercel, or use the CLI from the repository root:
vercel project create my-dm-dot-api
vercel link --yes --project my-dm-dot-api
Configure:
| Setting | Value |
|---|---|
| Root directory | . (repository root) |
| Framework preset | Other |
| Source branch | main |
| Function entry point | api/mcp.go |
| Public MCP route | /mcp (rewritten to /api/mcp) |
| Max function duration | 60 seconds (configured in vercel.json) |
When linking a private repository, grant the Vercel GitHub integration access to this repository, not unnecessarily to every private repository.
The repository-root vercel.json disables automatic Git deployments, so deploy manually with the Vercel CLI or configure your own CI. If you want automated deployments, the example API GitHub Actions workflow requires your own Vercel project ID, organization ID, and project-scoped token. None of the maintainer’s credentials or deployment settings are needed to self-host the API.
3. Set Production secrets
| Variable | Required | Description |
|---|---|---|
MCP_API_KEY |
Yes | Shared bearer-equivalent secret passed in ?key= on the MCP URL |
DM_DOT_REST_API_KEY |
Yes, for REST | Separate bearer token authorizing POST /v1/messages |
UPSTASH_REDIS_REST_URL |
Yes | HTTPS endpoint for the dedicated Redis REST API |
UPSTASH_REDIS_REST_TOKEN |
Yes | REST token to read/write the subscription key |
Generate a random MCP_API_KEY of at least 32 bytes using a secure generator, and save it in a trusted secret manager. Configure each value as a sensitive Production secret in Vercel. For example, the Vercel CLI prompts for each value:
vercel env add MCP_API_KEY --environment production --sensitive
vercel env add DM_DOT_REST_API_KEY --environment production --sensitive
vercel env add UPSTASH_REDIS_REST_URL --environment production --sensitive
vercel env add UPSTASH_REDIS_REST_TOKEN --environment production --sensitive
The CLI also supports piping values through standard input for automation. Avoid passing tokens in command-line arguments, where they may end up in shell history or process listings.
Important: The API key is needed again to connect an MCP client. Keep a recoverable copy in your password manager or OS keychain. Do not rely on retrieving a sensitive Vercel environment variable later.
4. Deploy and verify
go test ./...
go vet ./...
vercel deploy --prod --yes
The public route follows this pattern:
https://YOUR-API-HOST/mcp?key=YOUR-MCP-API-KEY
Expected outcomes:
- Without
?key=, the MCP endpoint responds with HTTP 401 (whenMCP_API_KEYis configured). - If
MCP_API_KEYis missing, it responds with HTTP 503 and refuses requests. - With a valid key, MCP
initializeandserver/discoveradvertiseevents,tools/listexposessend_to_dot, andevents/listexposesmessage.created. - Before a dot subscribes, calling
send_to_dotreturns a tool error saying there is no active subscription. That is expected; it also confirms the application can query Redis. POST /v1/messagesrequiresAuthorization: Bearer <DM_DOT_REST_API_KEY>; with no subscription it returns409, and after delivery succeeds it returns202.
Use Getting started to connect ChatGPT and subscribe the dot. Follow Troubleshooting if the platform’s event source list lags behind the plugin UI.
Updating or recovering
- Changing secrets: Update the Vercel Production secret(s) and redeploy. Redeploying is required for the running function to receive new values.
- Rotating
MCP_API_KEY: Every connected MCP client must update its authenticated URL. Because the subscription ID incorporates this key, reconnect/re-subscribe the dot after rotation. - Replacing Redis: Recreate the variables and have the dot subscribe again. Existing subscriptions are not automatically migrated.
- Refreshing a subscription: The client calls
events/subscribeagain beforerefreshBefore. No background cron refresh is provided bydm-dot. - Separating environments: Use independent Redis databases and different MCP API keys for production and staging. Never point both environments at the same single-subscription key.
Deployment protection
Vercel project-wide authentication, an upstream access gateway, or private network protection can prevent ChatGPT from reaching /mcp. The application-level ?key= check does not bypass those layers. Verify that external MCP clients can actually access the endpoint while the application still enforces its own secret. Do not disable account or workspace security controls without evaluating the consequences.
Next: Security · Troubleshooting.