Skip to content

Support the stateless flag for STDIO transport #912

Open
@efj-amzn

Description

@efj-amzn

Is your feature request related to a problem? Please describe.

For many other MCP implementations, especially those that predate the initialize and notifications/initialized handshake, it's convenient to be able to test or execute new tools with a shell, like this:

echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | uv run main.py

And similar commands. This isn't possible anymore - one has to include the initialization messages as well.

This also greatly raises the bar for writing toy clients for educational purposes, which is my main goal. When learning about the MCP protocol, the initialization parts aren't as interesting as tools/list and tools/call to folks that are learning about how LLMs consume tools.

Describe the solution you'd like

Streamable HTTP Transport supports a settings flag stateless which initializes the Session state to be Initialized:

https://github.com/modelcontextprotocol/python-sdk/blob/main/src/mcp/server/session.py#L95

        self._initialization_state = (
            InitializationState.Initialized
            if stateless
            else InitializationState.NotInitialized
        )

A similar flag for STDIO would be awesome. It's easily patched like this:

from mcp.server.stdio import stdio_server

class MyFastMCP(FastMCP):
    async def run_stdio_async(self) -> None:
        """Run the server using stdio transport."""
        async with stdio_server() as (read_stream, write_stream):
            await self._mcp_server.run(
                read_stream,
                write_stream,
                self._mcp_server.create_initialization_options(),
                stateless=True
            )

# Initialize FastMCP server                                                                                                              
mcp = MyFastMCP("mymcp")

which is sufficient for testing the flag itself. It would be nice if I could pass this flag somehow. For HTTP it's done with a Setting: https://github.com/modelcontextprotocol/python-sdk/blob/main/src/mcp/server/fastmcp/server.py#L100

And that would be fine here as well, but it's not plumbed through.

Describe alternatives you've considered

None.

Additional context

I think the diff here is pretty straightforward. I'm filing this because CONTRIBUTING.md says:

Choose the correct branch for your changes:
    For bug fixes to a released version: use the latest release branch (e.g. v1.1.x for 1.1.3)
    For new features: use the main branch (which will become the next minor/major version)
    If unsure, ask in an issue first

I'm unsure, so I'm asking here first.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions