The Modal MCP server lets you manage Modal cloud resources and deploy/run Modal apps directly from MCP clients using your local Modal CLI configuration.
Deploy & Run
Deploy apps: Deploy Modal apps persistently; returns live web endpoint URLs
Run apps: Execute a Modal function once and stream output; supports detach mode for long-running jobs
App Management
List deployed/running apps, fetch or stream logs, stop apps, roll back to previous versions, and view deployment history
Container Management
List running containers, fetch/stream container logs, execute commands inside containers, and stop containers
Log Search
Search app or container logs with grep, supporting regex, case control, context lines, and time filtering
Volume File Operations
List volumes, browse contents, copy/move/remove files, upload local files to a volume, and download files from a volume
Volume Lifecycle
Create, delete (irreversibly), and rename named persistent volumes
Secrets Management
List secret names (values never exposed), create secrets from inline key-values,
.envfiles, or JSON files, and delete secrets
Account & Discovery
Show the active Modal profile and all configured profiles; list available environments (e.g. "dev", "production") in the workspace
Provides tools for managing Modal apps, containers, volumes, and secrets, enabling deployment and execution of Modal apps directly from MCP clients.
MCP Modal Server
An MCP server for managing Modal — apps, containers, volumes, and secrets — and for deploying & running Modal apps directly from Claude Code and other MCP clients.
Every tool shells out to your local modal CLI, so it operates against whatever Modal profile and credentials are configured on your machine. There are no extra tokens to manage.
Installation
The server is published on PyPI as mcp-modal. No manual install is needed — the recommended way to run it is with uvx, which fetches and launches it on demand. Just point your MCP client at the command below (see Configuration).
Related MCP server: MCP Server Modal
Logging in to Modal
This server uses your local Modal credentials. If you haven't authenticated yet, run:
modal setupThis opens a browser to log in and stores a token in ~/.modal.toml. Already logged in elsewhere? Check with modal profile current.
Configuration
Add the server to Claude Code with the claude mcp CLI:
claude mcp add mcp-modal -- uvx mcp-modalOr add it to a .mcp.json file in your project root:
{
"mcpServers": {
"mcp-modal": {
"command": "uvx",
"args": ["mcp-modal"]
}
}
}To pin a specific release, use uvx mcp-modal@0.2.0.
Requirements
Python 3.11 or higher
uv(providesuvx)Modal CLI 1.x configured with valid credentials (
modal setup)For Modal deploy and run support:
The project being deployed/run must use
uvfor dependency managementmodalmust be installed in that project's virtual environment
Security
This server shells out to your local modal CLI using whatever credentials are in
~/.modal.toml. A few tools are powerful by design — if the MCP client driving the server
is ever prompt-injected (for example by malicious text inside logs it fetched), these are
the escalation paths and should stay behind your client's tool-approval prompts rather
than being auto-approved:
deploy_modal_app/run_modal_app— execute arbitrary local Python on the host (modal deployimports the app file;uv runresolves and installs the target project's dependencies).put_modal_volume_file— can read any local file (e.g.~/.ssh/id_rsa,~/.modal.toml) and upload it to a cloud volume (a data-exfiltration primitive).get_modal_volume_filewithforce=True— can overwrite any local path (e.g.~/.zshrcor a shell profile, a persistence primitive).exec_modal_container— runs arbitrary commands inside a container, by design.
Optional local-path allowlist
To contain the two filesystem-touching volume tools, set the
MCP_MODAL_ALLOWED_LOCAL_PATHS environment variable to an
os.pathsep-separated list of
directories (: on macOS/Linux). When it is set, put_modal_volume_file (its local_path)
and get_modal_volume_file (its local_destination) are refused unless the resolved path —
after expanding ~ and collapsing ../symlinks — falls inside one of those roots. The
download target "-" (stream to stdout) is exempt because nothing is written to disk.
When the variable is unset (the default) there is no restriction, so existing setups are unaffected. Configure it in your MCP client, e.g.:
{
"mcpServers": {
"mcp-modal": {
"command": "uvx",
"args": ["mcp-modal"],
"env": { "MCP_MODAL_ALLOWED_LOCAL_PATHS": "/Users/me/modal-workspace:/tmp/modal" }
}
}
}All tools also pass user-supplied names/paths after a -- end-of-options separator, so a
value beginning with - is always treated as data, never as a modal CLI flag. Secret
values handed to create_modal_secret are redacted from the echoed command, logs, and any
error output.
Supported Tools
26 tools, grouped by area. Account-scoped tools accept an optional env argument to
target a specific Modal environment; if
omitted, they use the profile's default (or MODAL_ENVIRONMENT).
Deploy & Run
Deploy Modal App (
deploy_modal_app)Deploys a Modal app (
modal deploy). Deployed web endpoints persist, so any links in the output are live and shareable (returned inurls).Parameters:
absolute_path_to_app(required),env,name,tag,strategy(rolling/recreate),stream_logsThe app's directory must use
uvwithmodalinstalled in its virtualenv.
Run Modal App (
run_modal_app)Runs a function or local entrypoint once and streams its output (
modal run).Parameters:
absolute_path_to_app(required),function_name,env,detach,timeout_seconds(default 120)Returns a snapshot with
truncated: trueif the run is still going at the timeout. Passdetach=Trueto keep long jobs alive on Modal past the timeout.
Why no
modal servetool?modal serveonly keeps its endpoints alive while the blocking process runs — an MCP tool that returns would tear them down immediately, handing back a dead URL. Usedeploy_modal_appfor a persistent, shareable endpoint.
Apps
List Modal Apps (
list_modal_apps)Lists apps currently deployed/running or recently stopped. Use this to find the app name/ID for the other app tools.
Parameters:
env
Get Modal App Logs (
get_modal_app_logs)Fetches or streams logs for an app by name or ID (
modal app logs).Parameters:
app_identifier(required),timeout_seconds(default 30),env,since,until,tail,search,source(stdout/stderr/system),timestamps(prefix each line with its wall-clock time),followWith
follow=True, logs stream until the app stops ortimeout_secondsis reached, returning a snapshot withtruncated: true.Only covers the stdout/stderr/system streams; some failures (e.g. a crash reported as "... exited with ...") are Modal dashboard events, not log lines, and won't appear here.
Stop Modal App (
stop_modal_app)Permanently stops an app and terminates its containers (
modal app stop).Parameters:
app_identifier(required),env
Roll Back Modal App (
rollback_modal_app)Redeploys a previous version of an app (
modal app rollback).Parameters:
app_identifier(required),version(optional — defaults to the previous version),env
Get Modal App History (
get_modal_app_history)Returns an app's deployment history (
modal app history). Use it to find aversionfor rollback.Parameters:
app_identifier(required),env
Containers
List Modal Containers (
list_modal_containers)Lists currently running containers (
modal container list).Parameters:
app_id(optional filter),env
Get Modal Container Logs (
get_modal_container_logs)Fetches or streams logs for a container ID (
modal container logs).Parameters:
container_id(required),timeout_seconds(default 30),since,until,tail,search,source,timestamps,followSame stdout/stderr/system-only caveat as the app-logs tool above.
Exec in Modal Container (
exec_modal_container)Runs a command inside a running container (
modal container exec --no-pty).Parameters:
container_id(required),command(list of args, e.g.["python", "-c", "print('hi')"]),timeout_seconds(default 60)
Stop Modal Container (
stop_modal_container)Terminates a running container (
modal container stop).Parameters:
container_id(required)
Log Search
Search Modal Logs (
search_modal_logs)Greps an app's or container's logs for a pattern and returns each hit with the surrounding lines — built for "where did it go wrong?" debugging. Logs are fetched once and searched locally, so (unlike the
searchargument on the log tools) you get context, regex, case control, and match counts, not just the bare matching line.Parameters:
identifier(required — app name/ID or container ID),pattern(required),target(app/container, defaultapp),regex,case_sensitive,context_lines(default 3),max_matches(default 50),since,tail(defaults to the last 1000 entries),source(stdout/stderr/system),exclude(drop noise lines before searching, e.g."queue put failed"),timestamps(defaulttrue— carry each line's wall-clock time into the result),timeout_seconds,envReturns
match_countandmatches: timestamped, line-numbered context blocks where matched lines are prefixed with>, e.g.> 8: 2026-06-04T... ValueError: bad input. Reportsexcluded_lineswhenexcludeis used.Only searches the stdout/stderr/system streams; failures emitted as Modal dashboard events (e.g. "... exited with ...") return 0 matches even when the failure is real.
Volumes — Files
List Modal Volumes (
list_modal_volumes) — lists all volumes. Parameters: none.List Volume Contents (
list_modal_volume_contents) —volume_name,path(default/). Setsempty: truewith a message when the listing genuinely returns nothing, so an empty directory is distinguishable from an error or a wrong path.Copy Files (
copy_modal_volume_files) —volume_name,paths(last is destination).Remove File (
remove_modal_volume_file) —volume_name,remote_path,recursive.Upload File (
put_modal_volume_file) —volume_name,local_path,remote_path,force.Download File (
get_modal_volume_file) —volume_name,remote_path,local_destination,force. Use-as the destination to stream contents to stdout.
Volumes — Lifecycle
Create Volume (
create_modal_volume) — creates a named persistent volume. Parameters:volume_name,env.Delete Volume (
delete_modal_volume) — deletes a volume and all its data (irreversible). Parameters:volume_name,env.Rename Volume (
rename_modal_volume) — Parameters:old_name,new_name,env.
Secrets
List Secrets (
list_modal_secrets)Lists published secrets (names and timestamps only — values are never exposed).
Parameters:
env
Create Secret (
create_modal_secret)Creates a secret from inline key/values or a local file (
modal secret create). Secret values are redacted from the returnedcommand.Parameters:
secret_name(required),key_values(dict),from_dotenv(path),from_json(path),force,env. Provide at least one ofkey_values,from_dotenv, orfrom_json.
Delete Secret (
delete_modal_secret) — Parameters:secret_name,env.
Discovery
Get Modal Profile (
get_modal_profile)Shows the active profile and all configured profiles. Use it to confirm which workspace/account the server is authenticated as. Parameters: none.
List Modal Environments (
list_modal_environments)Lists the environments in the current workspace; the names are valid
envarguments for the other tools. Parameters: none.
Response Format
All tools return responses in a standardized format, with slight variations depending on the operation type:
# JSON / list operations (apps, containers, volumes, secrets, history, ...):
{
"success": True,
"apps": [...] # or "containers", "volumes", "secrets", "history", "environments"
}
# Action operations (deploy, stop, create, delete, rename, copy, put, get, rm):
{
"success": True,
"message": "Operation successful message",
"command": "executed command string",
"stdout": "command output", # if any
"stderr": "error output" # if any
}
# Log / run / exec operations (snapshot-based):
{
"success": True,
"logs": "...", # or "output" for run/exec
"truncated": False, # True when cut off at timeout_seconds
"command": "executed command string"
}
# Error case (all operations):
{
"success": False,
"error": "Error message describing what went wrong",
"command": "executed command string",
"stdout": "command output", # if available
"stderr": "error output" # if available
}License
This project is licensed under the MIT License - see the LICENSE file for details.
Maintenance
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/george-bobby/mcp-modal'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
