Hosts one or more MCP servers behind a single ngrok tunnel, protected by OAuth 2.1.
ngrok (static domain)
└─► nginx :80 (path-based routing)
├─► hydra :4444/:4445 (OAuth 2.1, DCR, JWKS, tokens)
└─► oauth-proxy :8080 (login/consent UI + JWT validation)
└─► <server>-mcp:<port> (supergateway, streamableHttp)
└─► MCP server process (stdio)
supergateway bridges each stdio MCP server to HTTP. nginx routes OAuth protocol endpoints to Ory Hydra and MCP traffic through oauth-proxy, so all servers share one ngrok domain while MCP endpoints require valid Bearer tokens.
Hydra provides OAuth 2.1 authorization, PKCE, dynamic client registration (DCR), JWKS, and JWT access tokens. oauth-proxy provides the simple login/consent UI, reads users from oauth/hydra/users.yml, and validates JWTs before forwarding MCP requests.
MyFitnessPal MCP is available at:
https://<your-domain>/mfp/mcp
- Docker and Docker Compose
- A MyFitnessPal account
- A free ngrok account with an authtoken and a static domain
- Sign up at ngrok.com (free)
- Copy your authtoken from the ngrok dashboard
- Claim a free static domain at Cloud Edge → Domains → New Domain
cp .env.example .envEdit .env:
| Variable | Description |
|---|---|
MFP_USERNAME |
MyFitnessPal email address |
MFP_PASSWORD |
MyFitnessPal password |
NGROK_AUTHTOKEN |
Token from the ngrok dashboard |
NGROK_DOMAIN |
Your static domain, e.g. your-name.ngrok-free.app |
HYDRA_DSN |
Hydra database DSN, normally sqlite:///data/hydra.db?mode=rwc&_fk=true |
HYDRA_SYSTEM_SECRET |
32+ character Hydra system secret |
Users are configured in oauth/hydra/users.yml. The example username is user; change it there if needed. Passwords can be plaintext or bcrypt hashes; bcrypt is preferred.
cp oauth/hydra/users.example.yml oauth/hydra/users.yml
python3 -c "import bcrypt; print(bcrypt.hashpw(b'YOUR_PASSWORD', bcrypt.gensalt()).decode())"Put the generated hash in the user's password field.
docker compose build
docker compose up -dCheck logs:
docker compose logs -fThe MFP server is reachable once ngrok connects. Do not put credentials in the URL; OAuth handles authentication.
Use the MCP endpoint URL:
https://<your-domain>/mfp/mcp
Clients that support remote MCP OAuth, such as ChatGPT connectors and Claude.ai integrations, should discover OAuth metadata automatically, register via DCR, then redirect to the login UI. Use the username and password configured in oauth/hydra/users.yml.
Hydra remembers successful browser logins for 24 hours, so adding a second client in the same browser may not prompt for the password again.
Claude Code's HTTP MCP support may not perform the same OAuth connector flow as Claude.ai. If using Claude Code, add the unauthenticated URL only if your client supports OAuth for remote MCP:
claude mcp add myfitnesspal --transport http https://your-domain.ngrok-free.app/mfp/mcpdocker compose down