diff --git a/README.md b/README.md index 5dbc4bd9d..76985aec4 100644 --- a/README.md +++ b/README.md @@ -888,9 +888,13 @@ Tools can send logs and notifications through the context: ```python from mcp.server.fastmcp import Context, FastMCP +from mcp.server.lowlevel.server import NotificationOptions from mcp.server.session import ServerSession -mcp = FastMCP(name="Notifications Example") +# Setup Server Capabilities +notification_options = NotificationOptions(prompts_changed=False, resources_changed=True, tools_changed=False) + +mcp = FastMCP(name="Notifications Example", notification_options=notification_options) @mcp.tool() diff --git a/examples/snippets/servers/notifications.py b/examples/snippets/servers/notifications.py index 833bc8905..15a28ba88 100644 --- a/examples/snippets/servers/notifications.py +++ b/examples/snippets/servers/notifications.py @@ -1,7 +1,11 @@ from mcp.server.fastmcp import Context, FastMCP +from mcp.server.lowlevel.server import NotificationOptions from mcp.server.session import ServerSession -mcp = FastMCP(name="Notifications Example") +# Setup Server Capabilities +notification_options = NotificationOptions(prompts_changed=False, resources_changed=True, tools_changed=False) + +mcp = FastMCP(name="Notifications Example", notification_options=notification_options) @mcp.tool() diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index 719595916..9e7c8bc28 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -51,7 +51,7 @@ from mcp.server.fastmcp.utilities.context_injection import find_context_parameter from mcp.server.fastmcp.utilities.logging import configure_logging, get_logger from mcp.server.lowlevel.helper_types import ReadResourceContents -from mcp.server.lowlevel.server import LifespanResultT +from mcp.server.lowlevel.server import LifespanResultT, NotificationOptions from mcp.server.lowlevel.server import Server as MCPServer from mcp.server.lowlevel.server import lifespan as default_lifespan from mcp.server.session import ServerSession, ServerSessionT @@ -168,6 +168,7 @@ def __init__( # noqa: PLR0913 lifespan: (Callable[[FastMCP[LifespanResultT]], AbstractAsyncContextManager[LifespanResultT]] | None) = None, auth: AuthSettings | None = None, transport_security: TransportSecuritySettings | None = None, + notification_options: NotificationOptions | None = None, ): self.settings = Settings( debug=debug, @@ -197,6 +198,7 @@ def __init__( # noqa: PLR0913 # TODO(Marcelo): It seems there's a type mismatch between the lifespan type from an FastMCP and Server. # We need to create a Lifespan type that is a generic on the server type, like Starlette does. lifespan=(lifespan_wrapper(self, self.settings.lifespan) if self.settings.lifespan else default_lifespan), # type: ignore + notification_options=notification_options, ) self._tool_manager = ToolManager(tools=tools, warn_on_duplicate_tools=self.settings.warn_on_duplicate_tools) self._resource_manager = ResourceManager(warn_on_duplicate_resources=self.settings.warn_on_duplicate_resources) diff --git a/src/mcp/server/lowlevel/server.py b/src/mcp/server/lowlevel/server.py index 9cec31bab..b07d4ab29 100644 --- a/src/mcp/server/lowlevel/server.py +++ b/src/mcp/server/lowlevel/server.py @@ -142,10 +142,12 @@ def __init__( [Server[LifespanResultT, RequestT]], AbstractAsyncContextManager[LifespanResultT], ] = lifespan, + notification_options: NotificationOptions | None = None, ): self.name = name self.version = version self.instructions = instructions + self.notification_options = notification_options or NotificationOptions() self.website_url = website_url self.icons = icons self.lifespan = lifespan @@ -177,7 +179,7 @@ def pkg_version(package: str) -> str: server_name=self.name, server_version=self.version if self.version else pkg_version("mcp"), capabilities=self.get_capabilities( - notification_options or NotificationOptions(), + notification_options or self.notification_options, experimental_capabilities or {}, ), instructions=self.instructions,