MCPSafe.io
RegistryThreatsMethodologyDocsPricingScanSign in
MCPSafe.io

Security checks for MCP servers — public packages and private repos, fast or deep.

Legal

Privacy PolicyCookie PolicyTerms of ServiceSecurity disclosure

Resources

State of MCP SecuritySupportSystem statusMade in Germany 🇩🇪

© 2026 MCPSafe. All rights reserved.

GDPR — Privacy Policy
← Threat Catalog

Configuration & Environment

Denial-of-wallet (unbounded LLM costs)

HIGHAIVSS 7.1CWE: CWE-400OWASP: LLM10Agentic: T04Rule: MCP-084

A tool itself calls a paid LLM API (OpenAI, Anthropic, Cohere, …) and passes through user-controlled input with no input cap and no `max_tokens` — a single adversarial call can cost tens of dollars. Paid-LLM variant of the unbounded-cost family; compute/memory is MCP-110, MCP sampling is MCP-211, oversized tool descriptions are MCP-252.

What it is

Denial-of-wallet is a DoS variant whose cost shows up on a credit-card statement instead of a pager. MCP servers that wrap an LLM — summarisers, translators, embedders — proxy paid API calls on the user's behalf. Without a cap on prompt length or output length, a single `summarise('A' * 500_000)` produces a six-figure token bill. Over a day, a loop driven by indirect prompt injection can drain a budget without triggering traditional rate-limits.

Why it matters for MCP

MCP encourages composition: a tool that calls an LLM is often called by another LLM. The outer model has no notion of cost; it will happily retry, expand, or loop. A missing `max_tokens` on the inner call is the difference between a healthy tool and a wallet-emptying proxy.

Vulnerable example

example.py
1
from openai import OpenAI
2
client = OpenAI()
3
4
@server.tool()
5
def summarize(text: str) -> str:
6
    # No max_tokens, no input length check
7
    resp = client.chat.completions.create(
8
        model="gpt-4o",
9
        messages=[{"role": "user", "content": f"Summarize: {text}"}],
10
    )
11
    return resp.choices[0].message.content

Secure example

example.py
1
from openai import OpenAI
2
client = OpenAI()
3
4
_MAX_INPUT = 20_000  # characters
5
6
@server.tool()
7
def summarize(text: str) -> str:
8
    if len(text) > _MAX_INPUT:
9
        raise ValueError("input too long")
10
    resp = client.chat.completions.create(
11
        model="gpt-4o",
12
        messages=[{"role": "user", "content": f"Summarize: {text}"}],
13
        max_tokens=400,
14
    )
15
    return resp.choices[0].message.content

How MCPSafe detects this

We flag LLM SDK calls (`openai.*.create`, `anthropic.messages.create`, `cohere.chat`, `genai.*.generate_content`, Bedrock `converse`) inside `@server.tool` / `server.tool(...)` handlers when `max_tokens` / `max_output_tokens` is absent AND the prompt is built from a handler parameter with no obvious length check.

See the full threat catalog for every documented detection.

Framework alignment

OWASP LLM Top-10 (2025)
LLM10 — Unbounded Consumption
OWASP Agentic AI Top-10
T04 — Resource Overload
AIVSS v0.5
7.1 (HIGH)AIVSS:1.0/S:HIGH/AV:N/AU:H/BR:H/CD:I

Further reading

  • CWE-400: Uncontrolled Resource Consumption
  • OWASP LLM10: Unbounded Consumption

Scan an MCP server for this issue

MCPSafe runs this check — and every other rule in the catalog — on any MCP server you paste in.

Scan now