TLDR: Claude in a sandbox can reach your API at http://host.docker.internal:3333. Network access to a port does not give access to env vars. Three options: exposed ports (zero setup), shared Docker network (hides DB from Claude), MCP proxy (full audit trail).
An isolated agent that cannot test anything is useless. Claude needs to hit endpoints and see error responses. The key insight: network access to a container’s port does NOT give access to that container’s environment variables.
Option 1: Exposed ports (recommended)
Your docker-compose.dev.yml already exposes ports. Claude uses host.docker.internal:
# Inside Claude's sandboxcurl http://host.docker.internal:3333/api/healthZero setup. Works with Docker Desktop out of the box.
Option 2: Shared network (more controlled)
Only the API is visible to Claude. Database and Redis stay hidden:
services: api: networks: [dev-net, claude-shared] postgres: networks: [dev-net] # Claude cannot reach this
networks: claude-shared: name: claude-shared external: truedocker network create claude-sharedOption 3: MCP proxy (most secure)
A lightweight MCP server that mediates all requests with logging:
server.tool( "api_request", "Send request to dev API", { method: { type: "string", enum: ["GET", "POST", "PUT", "DELETE"] }, path: { type: "string" }, }, async ({ method, path }) => { console.error(`[MCP] ${method} ${path}`); const res = await fetch(`http://api:3333${path}`, { method }); return { content: [ { type: "text", text: `HTTP ${res.status}\n${await res.text()}` }, ], }; },);Add to CLAUDE.md
## Local Development
API: http://host.docker.internal:3333Frontend: http://host.docker.internal:3000Check .env.example for required variables.Never read .env files or access container env vars.MCP server credentials
MCP config files (claude_desktop_config.json, .mcp.json) often contain API keys inline. This is a secret on disk that AI agents read automatically.
Fix: Use environment variable references:
{ "mcpServers": { "github": { "command": "mcp-server-github", "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" } } }}Set the variable before launching Claude:
export GITHUB_TOKEN=$(infisical secrets get GITHUB_TOKEN --env=dev --plain --silent)Add MCP configs to .claudeignore:
claude_desktop_config.json.mcp.json**/mcp.jsonWhich option
Solo dev: Option 1. Want to hide DB: Option 2. Real money involved: Option 3.