Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

MCP Modal Server

PYPI · MCP-MODAL · SCANNED SEP 21

MCP server for managing Modal apps, containers, volumes, and secrets.

Available components

+18 this week 73 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security100
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • Runs hatchling.build at install time, a recognised native-build step with no shell scripting around it. View diagnostics → Pass
  • 4 of 54 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency32
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
  • License check failed: no license is declared. See how to fix → Fail
  • Actively maintained (last published 11 days ago).Pass
  • Security-disclosure policy not yet verified: we couldn't inspect the source repository.Unverified
Schema Quality & AI Usability70
  • 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
  • AI-judged instruction clarity (good).Pass
  • Context-footprint check failed: tool/resource definitions use about 3814 tokens (~317/item across 12 items; 12 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management60
  • Stability observed for 18 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage71
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 0% of tool parameters carry a description.Fail
  • Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • All 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
  • An AI judge read all 12 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

How do I install the MCP Modal Server server?

MCP Modal Server runs locally as a PyPI package, launched with uvx mcp-modal. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

pypi · mcp-modal

# add to Claude Code
claude mcp add george-bobby-mcp-modal -- uvx mcp-modal
// .cursor/mcp.json
{
  "mcpServers": {
    "george-bobby-mcp-modal": {
      "command": "uvx",
      "args": [
        "mcp-modal"
      ]
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "george-bobby-mcp-modal": {
      "command": "uvx",
      "args": [
        "mcp-modal"
      ]
    }
  }
}
# add to Codex CLI
codex mcp add george-bobby-mcp-modal -- uvx mcp-modal
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "george-bobby-mcp-modal": {
      "type": "local",
      "command": [
        "uvx",
        "mcp-modal"
      ],
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add george-bobby-mcp-modal --command uvx --arg mcp-modal
# ~/.hermes/config.yaml
mcp_servers:
  george-bobby-mcp-modal:
    command: "uvx"
    args: ["mcp-modal"]
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "george-bobby-mcp-modal": {
      "Transport": "stdio",
      "Command": "uvx",
      "Arguments": [
        "mcp-modal"
      ]
    }
  }
}
# add to Vellum
assistant mcp add george-bobby-mcp-modal -t stdio -c uvx -a mcp-modal
// mcp.json
{
  "mcpServers": {
    "george-bobby-mcp-modal": {
      "command": "uvx",
      "args": [
        "mcp-modal"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 21 Sept 26 +15
    • Malware scan: unverified → pass security
    • Security disclosure: fail → unverified functional
  • 20 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 53 to 57. That category is still filling its 30-day observation window: 16 days of observed history at the previous scan, 17 at this one. The score rises as the window fills, whether or not the server changes.

  • 18 Sept 26 −14
    • Malware scan: pass → unverified security
  • 17 Sept 26 +15
    • Malware scan: unverified → pass security
  • 16 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 40 to 43. That category is still filling its 30-day observation window: 12 days of observed history at the previous scan, 13 at this one. The score rises as the window fills, whether or not the server changes.

  • 14 Sept 26 −14
    • Malware scan: pass → unverified security
  • 12 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 27 to 30. That category is still filling its 30-day observation window: 8 days of observed history at the previous scan, 9 at this one. The score rises as the window fills, whether or not the server changes.

  • 10 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 20 to 23. That category is still filling its 30-day observation window: 6 days of observed history at the previous scan, 7 at this one. The score rises as the window fills, whether or not the server changes.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 21 Sept 2026 · Analysed pypi/mcp-modal@0.5.0

Provenance No attestation

The registry publishes no build provenance for this version, so there is nothing to verify.

Result No attestation
Ecosystem pypi

Background: How many MCP packages publish verified provenance →

Install scripts 1 script
Hook Tier Command
build_backend allowlisted hatchling.build

Background: Why install scripts are a supply-chain risk →

Dependencies 54 packages
Packages resolved 54
Stale 3
No linked repository 1
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 12 exposed · ~3,814 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
analyze_modal_costs ~602

Break down what the workspace is spending (`modal billing`). Costs are fetched once and aggregated locally, so you get ranked totals and period-over-period changes rather than hundreds of raw rows. Answering common questions: "what is my costliest app?" -> view="by_app", period="this month" "why was Monday expensive?" -> view="timeline", period="last week" (the `explanation` field diffs the peak day against the day before and ranks which apps grew) "what did that day cost hourly?" -> view="timeline", start="2026-08-31", end="2026-09-01", resolution="h" "where does the money go?" -> view="by_resource" (CPU / GPU / memory / ...) "what is the bill this cycle?" -> view="summary" Billing is workspace-wide, so this reports across every environment; use `environment` to narrow it after the fact. Args: view: "by_app" (default), "timeline" (per interval, with an explanation of the peak), "by_environment", "by_resource", "summary" (billed vs metered for a month cycle), or "rates" (current unit prices). period: Convenience range — "today", "yesterday", "this week", "last week", "this month", "last month". For "summary" also accepts "YYYY-MM". start / end: Explicit range instead of `period` — ISO dates ("2026-08-31") or relative ("3 days ago"). Start is inclusive, end exclusive; end defaults to now. resolution: "d" (daily, default) or "h" (hourly). Hourly is what you want when drilling into a single day. timezone: Timezone for interpreting dates — "local", an offset ("+05:30"), or an IANA name. Requires resolution="h". app: Only include apps whose name or ID contains this string (case-insensitive). environment: Only include rows from this Modal environment. top_n: How many groups/movers to return. Default 10. tag_names: Comma-separated cost-attribution tag…

NameTypeReqDescription
app
end
environment
period
resolutionstring
start
tag_names
timezone
top_ninteger
viewstring
NameTypeReqDescription
resultobjectyes

No examples provided.

deploy_modal_app ~182

Deploy a Modal app (`modal deploy`). Deployed endpoints persist after this returns, so any URLs in the result are live, shareable links. Args: absolute_path_to_app: Absolute path to the app file. Its directory must use `uv` and have `modal` installed in its virtualenv. env: Modal environment to deploy into. name: Deployment name (`--name`). tag: Version tag (`--tag`). strategy: Rollout strategy — "rolling" or "recreate". stream_logs: Stream the app's logs after deploying. Returns: {message, urls (live endpoints), stdout, stderr}.

NameTypeReqDescription
absolute_path_to_appstringyes
env
name
strategy
stream_logsboolean
tag
NameTypeReqDescription
resultobjectyes

No examples provided.

get_modal_logs ~385

Fetch logs for an app or container (`modal app logs` / `modal container logs`). To find where something went wrong, prefer search_modal_logs — it returns matches with surrounding context instead of a raw tail. Covers the stdout/stderr/system streams ONLY. Crash events shown on the Modal dashboard (e.g. "... exited with ...") are not log lines and never appear here. Args: identifier: App name/ID ("my-app", "ap-...") or container ID ("ta-..."). target: "auto" (default — "ta-..." is a container), "app", or "container". timeout_seconds: Max seconds to collect. Default 30. env: Modal environment. Apps only — container logs take no environment. since / until: Time range, ISO 8601 or relative ("2h", "30m", "1d"). Max 35 days. `since` without `tail` fetches EVERY entry in the range — pass `until` too (or a `tail`) to bound the volume on a busy app. tail: Only the last N entries (max 20000). source: "stdout", "stderr", or "system". timestamps: Prefix each line with its wall-clock timestamp. follow: Live-stream until the app/container stops or the timeout hits. Returns: {logs, truncated (still streaming at the timeout), output_capped (text trimmed to fit context — narrow with tail/since/source)}.

NameTypeReqDescription
env
followboolean
identifierstringyes
since
source
tail
targetstring
timeout_secondsinteger
timestampsboolean
until
NameTypeReqDescription
resultobjectyes

No examples provided.

inspect_modal_secret ~442

List the KEY NAMES inside a Modal secret — never the values. Modal exposes no API for this: neither the CLI, the SDK, nor the gRPC layer can read a secret's contents, by design. The only way to see which keys a secret defines is to mount it in a container and look at the environment variable names. So this tool starts a short-lived container (`modal shell --secret ...`), prints the variable NAMES only, and subtracts the ones the image and the Modal runtime would have set anyway. That means, unlike every other read in this server, a call here **starts remote compute and costs a few cents** (and takes tens of seconds — longer on the first run for a given image, which has to be built). It is not a free lookup: use list_modal_resources(resource="secrets") to see which secrets exist, and reach for this only when you need to know what is inside one. Values never leave the container: the probe is `compgen -e`, a bash builtin that prints exported variable NAMES only, so no value is ever printed or read. Args: secret_name: Name of the secret, from list_modal_resources(resource="secrets"). env: Modal environment the secret lives in. image: Optional container image. Omit it to use Modal's default image, which is built to match this server's Python — that is the most reliable choice. Pass one (e.g. "python:3.12-slim") if the workspace's image builder rejects that Python. timeout_seconds: Max seconds to wait, including image build. Default 300. Returns: {keys: [...names...], all_env_names: [...], filtered_out: n}. `all_env_names` is the unfiltered list, so a key that looks like a runtime variable (e.g. one literally named "PATH") is still visible rather than silently dropped.

NameTypeReqDescription
env
image
secret_namestringyes
timeout_secondsinteger
NameTypeReqDescription
resultobjectyes

No examples provided.

list_modal_resources ~313

Read-only lookup of everything in the Modal account. Start here to find the app name, container ID or volume name that the other tools take. Args: resource: One of: "apps" — deployed/running/recently-stopped apps. "app_history" — one app's deployment versions (`name` = app name/ID); use it to pick a version for manage_modal_app(action="rollback"). "containers" — running containers ("ta-..."); `name` = app ID to filter. "volumes" — named volumes. "volume_files" — files in a volume (`name` = volume, plus `path`). "secrets" — secret names only; values are never returned. "environments" — valid values for every `env` argument. "profile" — active profile + all profiles (which account am I?). name: App name/ID, app ID filter, or volume name — see `resource`. path: Path inside the volume for "volume_files". Default "/". env: Modal environment. Ignored for "environments"/"profile". Returns: {<resource key>: [...]} — e.g. "apps", "containers", "contents". Listings over 200 entries are capped, with `omitted_items` giving the count dropped.

NameTypeReqDescription
env
name
pathstring
resourcestringyes
NameTypeReqDescription
resultobjectyes

No examples provided.

manage_modal_app ~157

Change a deployed app's state. Both actions affect live traffic. Args: action: "stop" — shut the app down, ending web endpoints (`modal app stop`). "rollback" — restore a previous deployment (`modal app rollback`). app_identifier: App name ("my-app") or ID ("ap-..."). version: Rollback target; omit for the immediately preceding version. List valid versions with list_modal_resources(resource="app_history", name=...). env: Modal environment to target. Returns: {message, stdout, stderr} or {error}.

NameTypeReqDescription
actionstringyes
app_identifierstringyes
env
version
NameTypeReqDescription
resultobjectyes

No examples provided.

manage_modal_container ~228

Act on one running container. Find IDs with list_modal_resources(resource="containers"). Args: action: "exec" — run a command inside the container (`modal container exec`). This is arbitrary remote code execution: treat it like SSH, not a lookup. "stop" — terminate it (`modal container stop`); in-flight inputs are cancelled and rescheduled elsewhere. container_id: Container ID ("ta-..."). Unique across environments, so no `env` argument is needed (the CLI accepts none for these subcommands). command: For "exec": argv list, e.g. ["python", "-c", "print('hi')"] or ["ls", "-la", "/"]. timeout_seconds: For "exec": max seconds to wait. Default 60. Returns: exec → {output, returncode, truncated, output_capped}; stop → {message}.

NameTypeReqDescription
actionstringyes
command
container_idstringyes
timeout_secondsinteger
NameTypeReqDescription
resultobjectyes

No examples provided.

manage_modal_secret ~207

Create or delete a secret. To list secret names use list_modal_resources(resource="secrets") — values are never readable. Values are redacted from every field returned (command, stdout, stderr, error), so they cannot leak back into the transcript on failure. Args: action: "create" or "delete". secret_name: Secret name. key_values: For "create": {"API_KEY": "abc", ...}. from_dotenv / from_json: For "create": load key/values from a local file instead. force: For "create": overwrite an existing secret. env: Modal environment to target. Returns: {message, stdout, stderr} or {error}, with values redacted.

NameTypeReqDescription
actionstringyes
env
forceboolean
from_dotenv
from_json
key_values
secret_namestringyes
NameTypeReqDescription
resultobjectyes

No examples provided.

manage_modal_volume ~157

Volume lifecycle. For the files inside a volume use modal_volume_files (writes) or list_modal_resources(resource="volume_files") (reads). Args: action: "create", "delete" (removes the volume and ALL its data — irreversible), or "rename". volume_name: Volume name (the current name, for "rename"). new_name: Required for "rename". env: Modal environment. Volumes are environment-scoped, so this must match the environment the volume lives in. Returns: {message, stdout, stderr} or {error}.

NameTypeReqDescription
actionstringyes
env
new_name
volume_namestringyes
NameTypeReqDescription
resultobjectyes

No examples provided.

modal_volume_files ~303

Write operations on a volume's files. To LIST a volume's contents use list_modal_resources(resource="volume_files"). Args: action: "put" (upload local_path → remote_path), "get" (download remote_path → local_path; "-" returns the contents instead of writing a file), "cp" (copy inside the volume, using `paths`), "rm" (delete remote_path). volume_name: Volume name. local_path: Local source ("put") or destination ("get", default "."). remote_path: In-volume destination ("put", default "/", trailing "/" keeps the filename), source ("get"), or target ("rm"). paths: For "cp": sources followed by the destination, e.g. ["a.txt", "dest/"]. recursive: Needed to "rm" or "cp" a directory. force: Overwrite existing files ("put"/"get"). env: Modal environment the volume lives in. Returns: {message, stdout, stderr} or {error}. When MCP_MODAL_ALLOWED_LOCAL_PATHS is set, "put"/"get" are refused for local paths outside the allowlist.

NameTypeReqDescription
actionstringyes
env
forceboolean
local_path
paths
recursiveboolean
remote_path
volume_namestringyes
NameTypeReqDescription
resultobjectyes

No examples provided.

run_modal_app ~203

Run a Modal function or local entrypoint once and collect its output (`modal run`). Use this to test on Modal compute; use deploy_modal_app to publish. Args: absolute_path_to_app: Absolute path to the app file. Its directory must use `uv` and have `modal` installed in its virtualenv. function_name: Function/entrypoint name, e.g. "main". Omit if the module has exactly one. env: Modal environment to target. detach: Keep the run alive on Modal past this call (`--detach`) — for long jobs. timeout_seconds: Max seconds to collect output. Default 120. Returns: {output, urls, truncated (still running at the timeout), output_capped}.

NameTypeReqDescription
absolute_path_to_appstringyes
detachboolean
env
function_name
timeout_secondsinteger
NameTypeReqDescription
resultobjectyes

No examples provided.

search_modal_logs ~635

Search an app's or container's logs and return each hit WITH surrounding context — the fastest way to find a traceback, an error or a request ID. Logs are fetched once and grepped locally, so you get the lines around each match, not just the match. Covers the stdout/stderr/system streams ONLY. Crash events shown on the Modal dashboard (e.g. "... exited with ...") are not log lines, so a search for them returns 0 matches even though the failure is real — check the dashboard instead. Args: identifier: App name/ID ("my-app", "ap-...") or container ID ("ta-..."). pattern: Text to find, or a Python regex when regex=True. target: "auto" (default — "ta-..." is a container), "app", or "container". regex / case_sensitive: Match mode. Both default False. context_lines: Lines of context each side of a match. Default 3. max_matches: Cap on match blocks returned. Default 50. since / until: Time range, ISO 8601 or relative ("2h", "30m", "1d"). PREFER a bounded range (both ends) when you know roughly when something happened — `since` alone fetches every entry from then until now, which on a busy app is megabytes and gets cut off at the timeout. Range must be <= 35 days. tail: Search only the last N entries (max 20000) instead of a whole range. With no since/until/tail, defaults to the last 1000 entries. source: Search only "stdout", "stderr", or "system". exclude: Drop lines matching this BEFORE searching, to strip repeated noise. prefilter: Push `pattern` down to Modal as a server-side substring filter, so non-matching lines are never fetched. The big lever for huge logs, but it requires regex=False and leaves `context_lines` showing only other matching lines — use it to find *where* something is, then re-query that window. timestamps: Prefix lines with their timestamp. Default True. timeout_seconds: Max seconds spent fetching logs. Default 30. env: Modal environmen…

NameTypeReqDescription
case_sensitiveboolean
context_linesinteger
env
exclude
identifierstringyes
max_matchesinteger
patternstringyes
prefilterboolean
regexboolean
since
source
tail
targetstring
timeout_secondsinteger
timestampsboolean
until
NameTypeReqDescription
resultobjectyes

No examples provided.

Common questions

What is the MCP Modal Server server?

MCP Modal Server is listed in the public MCP registry as io.github.george-bobby/mcp-modal. MCP server for managing Modal apps, containers, volumes, and secrets. This page covers its PyPI package (mcp-modal).

Is the MCP Modal Server server safe to use?

MCP Modal Server scores 73 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 21 September 2026. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the MCP Modal Server server expose?

MCP Modal Server exposes 12 tools: manage_modal_app, manage_modal_container, analyze_modal_costs, deploy_modal_app, run_modal_app, and 7 more. Their descriptions and schemas cost roughly 3,814 tokens of context every time the server is loaded.

Is the MCP Modal Server server still maintained?

MCP Modal Server is still listed as active in the MCP registry. We last reached this channel on 21 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.