Deployment
Deploy ContextMCP to production
ContextMCP runs on Cloudflare Workers for low-latency edge deployment.
Cloudflare Workers
Prerequisites
- Cloudflare account (free tier works)
- Wrangler CLI installed:
npm install -g wrangler - Indexed documentation (run
npm run reindexfirst)
Configure
Edit cloudflare-worker/wrangler.jsonc:
{
"name": "contextmcp",
"compatibility_date": "2024-01-01",
"vars": {
"SERVER_NAME": "my-company-docs",
"SERVER_DESCRIPTION": "Documentation search for My Company",
},
}Set Secrets
cd cloudflare-worker
wrangler secret put OPENAI_API_KEY
wrangler secret put PINECONE_API_KEY
wrangler secret put API_KEY # Optional: for authenticated accessDeploy
npm run deployYour server is live at: https://contextmcp.your-subdomain.workers.dev
Verify
# Health check
curl https://your-worker.workers.dev/health
# Test search
curl "https://your-worker.workers.dev/search?query=authentication&limit=3"Custom Domain
Add a custom domain in wrangler.jsonc:
{
"routes": [{ "pattern": "mcp.yourdomain.com", "custom_domain": true }],
}Local Development
For testing locally without deploying:
cd cloudflare-worker
npm run devServer runs at http://localhost:8787.
Auto-Reindex with GitHub Actions
Keep your index fresh by reindexing on every push to main:
# .github/workflows/reindex.yml
name: Reindex Documentation
on:
push:
branches: [main]
paths:
- 'docs/**'
- 'content/**'
jobs:
reindex:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Reindex
run: npm run reindex
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
PINECONE_API_KEY: ${{ secrets.PINECONE_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}Incremental Reindex
Full reindexing re-embeds every chunk on every run, which is slow and costly
for large docs. Use --incremental to embed and upload only the chunks that
changed since the last run:
npm run reindex -- --incrementalHow it works:
- After each run, a manifest (
data/reindex-manifest.json) records a content hash for every chunk. - On the next incremental run, ContextMCP diffs the freshly parsed chunks against the manifest: new/changed chunks are embedded and upserted, removed chunks are deleted from the vector store, and unchanged chunks are skipped.
- The manifest is written after every non-dry run, so a normal full reindex also seeds it.
To make incremental runs work in CI, persist data/reindex-manifest.json
between runs (commit it, or use an actions cache).
Important:
actions/cacheonly writes a new entry on a cache miss. With a constantkey, the manifest is saved once and never updated again, so every incremental run would diff against that first, now-stale manifest forever. Use a rotating key (unique per run) plusrestore-keysso each run restores the latest manifest and saves a fresh one:
- name: Restore reindex manifest
uses: actions/cache@v4
with:
path: data/reindex-manifest.json
# Unique per run -> always a miss -> the updated manifest is always saved.
key: reindex-manifest-${{ github.run_id }}
# Falls back to the most recent previous manifest on restore.
restore-keys: |
reindex-manifest-
- name: Reindex (incremental)
run: npm run reindex -- --incremental
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
PINECONE_API_KEY: ${{ secrets.PINECONE_API_KEY }}Alternatively, commit data/reindex-manifest.json to the repo after each run —
simpler and fully deterministic, at the cost of a commit per reindex.
--incrementalcovers all sources, so it can't be combined with--source.
Scheduled Reindex
For sources that change externally, add a cron schedule:
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM UTC
workflow_dispatch: # Manual triggerEnvironment Variables
| Variable | Required | Description |
|---|---|---|
OPENAI_API_KEY | Yes | For generating embeddings |
PINECONE_API_KEY | Yes | For vector storage |
GITHUB_TOKEN | For private repos | GitHub access token |
Troubleshooting
"Worker failed to deploy"
Check that all required secrets are set:
wrangler secret list"No results from search"
- Verify reindex completed: check for errors in
npm run reindex - Confirm vectors exist in Pinecone dashboard
- Try a broader query
"Timeout errors"
Cloudflare Workers have a 30s CPU limit. If indexing large docs, ensure chunking produces reasonable sizes.