README.md
Instead of manually setting each variable, use the Heroku CLI to pull the correct values.
export APP_NAME=<your-heroku-app-name>
heroku create $APP_NAME
heroku buildpacks:add --index 1 heroku/ruby
heroku buildpacks:add --index 2 heroku/python
# set a private API key that you create, for example:
heroku config:set API_KEY=$(openssl rand -hex 32) -a $APP_NAME
heroku config:set STDIO_MODE_ONLY=<true/false> -a $APP_NAME
# set the remote server type (module) that your web process will use (only relevant for web deployments)
heroku config:set REMOTE_SERVER_TRANSPORT_MODULE=<streamable_http_server/sse_server>
Note: we recommend setting STDIO_MODE_ONLY
to true
for security and code execution isolation security in non-dev environments.
If you only want local & deployed STDIO
capabilities (no SSE server
), run:
heroku ps:scale web=0 -a $APP_NAME
If you do want a deployed SSE
server, run:
heroku ps:scale web=1 -a $APP_NAME
heroku config:set WEB_CONCURRENCY=1 -a $APP_NAME
Optionally, put these config variables into a local .env file for local development:
heroku config -a $APP_NAME --shell | tee .env > /dev/null
Next, connect your app to your git repo:
heroku git:remote -a $APP_NAME
And deploy!
git push heroku main
View logs with:
heroku logs --tail -a $APP_NAME
One-time packages installation:
virtualenv venv
source venv/bin/activate
pip install -r requirements.txt
If you're testing (stateless) Streamable HTTP OR SSE, in one terminal pane you'll need to start the server:
source venv/bin/activate
export API_KEY=$(heroku config:get API_KEY -a $APP_NAME)
# Either run src.streamable_http_server or src.sse_server, here:
uvicorn src.streamable_http_server:app --reload
Running with --reload
is optional, but great for local development
Next, in a new pane, you can try running some queries against your server:
First run:
export API_KEY=$(heroku config:get API_KEY -a $APP_NAME)
In the following commands, use either example_clients/streamable_http_client.py
if you ran the streamable HTTP server above, or example_clients/sse_client.py
if you're running the SSE server.
List tools:
python example_clients/streamable_http_client.py mcp list_tools | jq
Example tool call request:
NOTE: this will intentionally NOT work if you have set STDIO_MODE_ONLY
to true
.
python example_clients/streamable_http_client.py mcp call_tool --args '{
"name": "code_exec_ruby",
"arguments": {
"code": "puts Array.new(100) { rand(1..100) }.join(\\", \\\")",
"packages": [""]
}
}' | jq
There are two ways to easily test out your MCP server in STDIO mode:
List tools:
python example_clients/stdio_client.py mcp list_tools | jq
Example tool call request:
python example_clients/stdio_client.py mcp call_tool --args '{
"name": "code_exec_ruby",
"arguments": {
"code": "require \\"colorize\\"; puts \\"Success!\\".colorize(:green)",
"packages": ["colorize"],
"use_temp_dir": false
}
}' | jq -r '.content[0].text' | jq -r .stdout
Example tool call request:
cat <<EOF | python -m src.stdio_server
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"0.1.0","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}
{"jsonrpc":"2.0","method"...