modelcontextprotocol / modelcontextprotocol/python-sdk

FastMCP server with SSE transport fails to shut down on a signal

Ouverte
#514 12 commentaires 6 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

bug P3 ready for work
Langage dominant
Python
Étoiles
24.3k
Forks
4k
Merge moyen
1 j 1 h
PR mergées (30 j)
31

Description

A very simple server fails to shut down on a signal if it processed at least one request:

❯ python test-server.py --port=8085
INFO:     Started server process [216035]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8085 (Press CTRL+C to quit)
INFO:     127.0.0.1:55188 - "GET /sse HTTP/1.1" 200 OK
INFO:     127.0.0.1:55192 - "POST /messages/?session_id=e690de9733914d09aebf2b0e8c78191c HTTP/1.1" 202 Accepted
INFO:     127.0.0.1:55192 - "POST /messages/?session_id=e690de9733914d09aebf2b0e8c78191c HTTP/1.1" 202 Accepted
INFO:     127.0.0.1:55192 - "POST /messages/?session_id=e690de9733914d09aebf2b0e8c78191c HTTP/1.1" 202 Accepted
Processing request of type CallToolRequest
^CINFO:     Shutting down
INFO:     Waiting for background tasks to complete. (CTRL+C to force quit)

The expected behaviour would be:

❯ python test-server.py --port=8085
INFO:     Started server process [216006]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8085 (Press CTRL+C to quit)
^CINFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [216006]

Here is the code for both the server and the client.

What do I miss?

the server

import click
import sys
from pydantic import Field
from mcp.server.fastmcp import FastMCP

@click.command()
@click.option("--port", default=8085, help="Port to listen", type=int)
def main(port: int):
    mcp = FastMCP(
        "mcp-echo-tool",
        debug=True,
        log_level="INFO",
        port=port,
    )

    @mcp.tool(name="echo")
    async def echo_tool(string: str = Field(description="A string to echo back")) -> str:
        """Echoes back the input string"""
        return string

    mcp.run(transport='sse')
    return 0

if __name__ == "__main__":
    sys.exit(main())

and the client

import asyncio
import click
import sys
from mcp.client.session import ClientSession
from mcp.client.sse import sse_client

async def client(url, string):
    async with sse_client(url) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            result = await session.call_tool("echo", {"string": string})
            print(result.content)

@click.command()
@click.option('--url', default='http://localhost:8085', help='MCP Server URL', type=str)
@click.argument('string', type=str)
def main(url: str, string: str):
    asyncio.run(client(url, string))

if __name__ == "__main__":
    sys.exit(main())

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Reproduisez le comportement d’arrêt avec le serveur et le client FastMCP SSE fournis, en confirmant d’abord qu’une requête a été traitée avant d’envoyer le signal. Suivez ensuite le cycle de vie du serveur FastMCP SSE et son chemin d’arrêt Uvicorn ; le travail est terminé lorsque le processus atteint l’arrêt de l’application et se termine sans nécessiter un second signal.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
api, backend
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Active
Clarté
Plutôt claire
Accessibilité débutants
48/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.