PrefectHQ/fastmcp · warning · FastMCPDeprecationWarning

Accessing `{cls_name}.{camel}` is deprecated; MCP SDK v2 ren

Error message

Accessing `{cls_name}.{camel}` is deprecated; MCP SDK v2 renamed this field to `{snake}`. Update your code to read `.{snake}` instead.

What it means

MCP SDK v2 renamed camelCase fields to snake_case. FastMCP keeps a compatibility shim (`__getattr__` getter) that, when `settings.mcp_camelcase_compat` is enabled, emits a `FastMCPDeprecationWarning` and returns the snake_case field value. With compat disabled, attribute access raises `AttributeError` instead.

Source

Thrown at fastmcp_slim/fastmcp/_compat.py:127

def _make_property(cls_name: str, camel: str, snake: str) -> property:
    """Build a warn-once property routing a camelCase read to a snake attr.

    The getter reads the live `mcp_camelcase_compat` setting on every access: if
    the bridge is disabled it raises `AttributeError` (matching the message
    Python raises for a genuinely missing attribute) so the shim is transparent;
    if enabled it warns once and returns the snake_case value.
    """
    warned = False

    def getter(self: object) -> object:
        nonlocal warned
        import fastmcp

        if not fastmcp.settings.mcp_camelcase_compat:
            raise AttributeError(f"{cls_name!r} object has no attribute {camel!r}")
        if not warned:
            warned = True
            warnings.warn(
                f"Accessing `{cls_name}.{camel}` is deprecated; MCP SDK v2 "
                f"renamed this field to `{snake}`. Update your code to read "
                f"`.{snake}` instead.",
                FastMCPDeprecationWarning,
                stacklevel=2,
            )
        return getattr(self, snake)

    return property(getter)


def install() -> None:
    """Install camelCase compatibility properties on SDK v2 model classes.

    Idempotent. Each bridged read warns once per (class, name) and returns the
    snake_case value. Skips any camelCase name a class already defines to avoid
    shadowing real upstream attributes.
    """

View on GitHub (pinned to 1f02114297)

Solutions

  1. Rename all attribute accesses to the snake_case name shown in the warning.
  2. Optionally keep the deprecated access temporarily by leaving `fastmcp.settings.mcp_camelcase_compat = True`, but plan the rename.
  3. Run a deprecation-warning sweep (`-W error::FastMCPDeprecationWarning` in tests) to catch remaining usages.
  4. Regenerate typed code (SDK models) against the v2 SDK so field names are current.

Example fix

// before
print(result.requestId)
// after
print(result.request_id)
Defensive patterns

Strategy: type-guard

Validate before calling

import fastmcp
assert fastmcp.settings.mcp_camelcase_compat, "camelCase access requires mcp_camelcase_compat=True; migrate to snake_case"

Type guard

def has_new_field(obj, snake: str) -> bool:
    return hasattr(obj, snake)

Try / catch

import warnings
from fastmcp.exceptions import FastMCPDeprecationWarning
with warnings.catch_warnings(record=True) as caught:
    warnings.simplefilter("always", FastMCPDeprecationWarning)
    value = getattr(obj, camel_name)
for w in caught:
    logging.warning("migrate field: %s", w.message)

Prevention

When it happens

Trigger: Reading a camelCase attribute (e.g. `request_id` -> `requestId` style names) on a v2 SDK type while `mcp_camelcase_compat=True`; with the setting off, the same access raises AttributeError.

Common situations: Code written against MCP SDK v1 (camelCase) running under the v2 SDK; gradual migration scripts; examples copied from older docs.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/211ea8c090b937bc. Report an issue: GitHub.