When to Use This Approach
Choose Docker containers when you:- Want to use any programming language (not just TypeScript/JavaScript)
- Need full control over your environment, dependencies, or runtime configuration
Prerequisites
- Docker installed locally
- Server that implements MCP Streamable HTTP transport with
/mcp
endpoint and CORS configuration - Server that listens on a configurable
PORT
environment variable (Smithery will set this to 8081 when launching your container) - (Optional) Server that can handle session configuration passed by Smithery (API keys, settings, etc.) - see our cookbook for a complete example
New to custom containers? See our Python FastMCP Server cookbook for a complete working example that demonstrates all the requirements above.
Requirements
Your deployment needs:- Dockerfile - Container configuration file
- smithery.yaml - Project and session configuration
Setup
1. Create smithery.yaml
Thesmithery.yaml
file tells Smithery how to build and run your container, and optionally defines what session configuration your server accepts from users.
Create a smithery.yaml
file in your repository root:
Need more details? See Project Configuration for complete smithery.yaml options and Session Configuration for handling user settings.
2. Create Dockerfile
The Dockerfile defines how to build your container image with all dependencies and runtime configuration. Test it builds locally withdocker build .
before deploying.
Your Dockerfile should:
- Install dependencies and build your application
- Handle the
/mcp
endpoint - Start your server process
Monorepo Considerations
If you’re working with a monorepo (using tools like Turbo, Lerna, or Nx), you’ll need to adjust your configuration:smithery.yaml for Monorepo
For monorepos, you may need to specify a custom Docker build path that includes the entire repository context:Dockerfile Patterns
The monorepo Dockerfile example above shows the key patterns:- Copy the entire monorepo structure: Include
packages/
,apps/
, and root configuration files - Use Turbo build arguments: Pass
TURBO_TEAM
andTURBO_TOKEN
if using Turbo Cloud - Build with dependency awareness: Use
npx turbo build --filter=your-app
to build only your app and its dependencies - Maintain module resolution: Start the application from the root directory to preserve workspace module resolution
Common Monorepo Issues
- Build context: Ensure your
dockerBuildPath
includes all necessary workspace dependencies - File copying: Copy shared packages and configuration files before building
- Module resolution: Start your application from the correct working directory to maintain import paths
Deploy
- Push your code (including
smithery.yaml
andDockerfile
) to GitHub - Connect your GitHub to Smithery (or claim your server if already listed)
- Navigate to the Deployments tab on your server page
- Click Deploy to build and host your container
What Happens Under the Hood
When you deploy, Smithery will:- Clone your repository
- Parse your
smithery.yaml
to understand how to build and configure your server (Dockerfile path, build context, etc.) - Build your Docker container using the specified Dockerfile
- Deploy the container to our hosting infrastructure
- Send MCP
initialize
andlist_tools
messages with a dummy configuration to discover your server’s capabilities - Make it available at
https://server.smithery.ai/your-server/mcp
- Handle load balancing, scaling, and monitoring
Troubleshooting
Why does my deployment fail?
Common deployment failures and solutions:- Docker build fails: Check your Dockerfile syntax and ensure all files are copied correctly
- Dependencies not found: Make sure your package files are copied before installing dependencies
- Monorepo build issues: Ensure your
dockerBuildPath
includes the entire repository context and all workspace dependencies are copied correctly
Why don’t my server’s capabilities get listed?
If your server’s capabilities aren’t showing up in Smithery:- Port binding issues: Ensure your server listens on the
PORT
environment variable (Smithery sets this to 8081) - CORS errors: Configure CORS headers properly for the
/mcp
endpoint - MCP protocol issues: Ensure your server properly responds to
initialize
andlist_tools
messages - Endpoint not found: Verify your server exposes the
/mcp
endpoint correctly - Server crashes: Review your server logs for runtime errors during tool discovery
How do I implement session configuration handling in my server?
To handle user configuration (API keys, settings, etc.):- Parse the config parameters: Read and parse JSON dot-notation query parameters (e.g.,
apiKey=...
,model.name=...
) - Validate configuration: Check that required fields match your
configSchema
insmithery.yaml
- Handle missing config: Gracefully handle cases where no configuration is provided
- See our cookbook for a complete implementation example
How do I set up CORS handling?
To properly configure CORS for your MCP server:- Allow all origins: Set
Access-Control-Allow-Origin: *
for the/mcp
endpoint - Allow credentials: Set
Access-Control-Allow-Credentials: true
- Allow required methods: Include
GET, POST, OPTIONS
inAccess-Control-Allow-Methods
- Allow required headers: Include
Content-Type, Authorization
and all headers with*
inAccess-Control-Allow-Headers
- Expose MCP headers: Include
mcp-session-id, mcp-protocol-version
inAccess-Control-Expose-Headers
- Handle preflight requests: Respond to
OPTIONS
requests with appropriate CORS headers - Example: See our cookbook for complete CORS implementation
Migration Guides
- Migrating from STDIO to HTTP
- TypeScript Custom Container Migration
- Python Custom Container Migration
Examples
- Python FastMCP Server with Docker - Complete working example with configuration handling