Skip to content

Tool with argumemnt annotated as Enum string requires input to be explicitly quoted? #1373

@everdark

Description

@everdark

Question

It seems that if a tool has an argument annotated by a string Enum, the input value needs to be quoted. This results in problems when using client such as Claude Desktop, which will never quote the input and immediately crash the client.

Consider the following example:

from enum import Enum
from typing import Literal

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("test")


class A(str, Enum):
    ONE = "one"
    TWO = "two"


def test_tool_1(a: A):
    return f"a is {a}"

def test_tool_2(a: str):
    return f"a is {a}"

def test_tool_3(a: Literal["one", "two"]):
    return f"a is {a}"


mcp.add_tool(test_tool_1)
mcp.add_tool(test_tool_2)
mcp.add_tool(test_tool_3)

Then I run the MCP Inspector to test them. For test_tool_1 I need to input "one" to be successful. For test_tool_2 and test_tool_3 they both do not require the input to be quoted. Indeed, if we input "one" in test_tool_3, the validation will fail because apparently "one" != one, which is expected.

I'm wondering if the quoted string for enum argument is a feature by design? Because it could actually make a client unusable. I tried Claude Desktop connected to this MCP server locally, and Claude Desktop will never be able to successfully quote the input, no matter I type the quoted or unquoted version.

I'm quite new to MCP. Is there anything obvious that I'm missing here?

macOS 15.6.1
python==3.11.9
mcp==1.14.0
Claude Desktop version: Claude 0.13.11 (cc3b19) 2025-09-12T17:06:57.000Z

Additional Context

The different between Enum and Literal in the resulting input json schema is whether to use reference anchor or not.
For test_tool_1, the resulting schema is

{
    "$defs": {
        "A": {
            "enum": [
                "one",
                "two"
            ],
            "title": "A",
            "type": "string"
        }
    },
    "properties": {
        "a": {
            "$ref": "#/$defs/A"
        }
    },
    "required": [
        "a"
    ],
    "title": "test_tool_1Arguments",
    "type": "object"
}

while for test_tool_3 it is:

{
    "properties": {
        "a": {
            "enum": [
                "one",
                "two"
            ],
            "title": "A",
            "type": "string"
        }
    },
    "required": [
        "a"
    ],
    "title": "test_tool_3Arguments",
    "type": "object"
}

Maybe there is a bug leading to the different treatment of these two schema?

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude desktopneeds confirmationNeeds confirmation that the PR is actually required or needed.questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions