From c646382e478f97529782819989a29f2bcd1891b4 Mon Sep 17 00:00:00 2001
From: rakib-liberatelabs <rakibhosen@liberate-labs.com>
Date: Tue, 1 Apr 2025 00:04:33 +0600
Subject: [PATCH 1/3] fix: Update context logging type hints to match MCP spec

---
 src/mcp/server/fastmcp/server.py    | 38 ++++++++++++++++++++++-------
 tests/server/fastmcp/test_server.py | 37 ++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py
index bf0ce880..a1bb7f79 100644
--- a/src/mcp/server/fastmcp/server.py
+++ b/src/mcp/server/fastmcp/server.py
@@ -660,7 +660,7 @@ async def read_resource(self, uri: str | AnyUrl) -> Iterable[ReadResourceContent
     async def log(
         self,
         level: Literal["debug", "info", "warning", "error"],
-        message: str,
+        message: Any,
         *,
         logger_name: str | None = None,
     ) -> None:
@@ -696,18 +696,38 @@ def session(self):
         return self.request_context.session
 
     # Convenience methods for common log levels
-    async def debug(self, message: str, **extra: Any) -> None:
-        """Send a debug log message."""
+    async def debug(self, message: Any, **extra: Any) -> None:
+        """Send a debug log message.
+        
+        Args:
+            message: The message to log. Can be any JSON-serializable type.
+            **extra: Additional structured data to include
+        """
         await self.log("debug", message, **extra)
 
-    async def info(self, message: str, **extra: Any) -> None:
-        """Send an info log message."""
+    async def info(self, message: Any, **extra: Any) -> None:
+        """Send an info log message.
+        
+        Args:
+            message: The message to log. Can be any JSON-serializable type.
+            **extra: Additional structured data to include
+        """
         await self.log("info", message, **extra)
 
-    async def warning(self, message: str, **extra: Any) -> None:
-        """Send a warning log message."""
+    async def warning(self, message: Any, **extra: Any) -> None:
+        """Send a warning log message.
+        
+        Args:
+            message: The message to log. Can be any JSON-serializable type.
+            **extra: Additional structured data to include
+        """
         await self.log("warning", message, **extra)
 
-    async def error(self, message: str, **extra: Any) -> None:
-        """Send an error log message."""
+    async def error(self, message: Any, **extra: Any) -> None:
+        """Send an error log message.
+        
+        Args:
+            message: The message to log. Can be any JSON-serializable type.
+            **extra: Additional structured data to include
+        """
         await self.log("error", message, **extra)
diff --git a/tests/server/fastmcp/test_server.py b/tests/server/fastmcp/test_server.py
index e76e59c5..21c698fa 100644
--- a/tests/server/fastmcp/test_server.py
+++ b/tests/server/fastmcp/test_server.py
@@ -554,6 +554,43 @@ async def logging_tool(msg: str, ctx: Context) -> str:
                     level="error", data="Error message", logger=None
                 )
 
+    @pytest.mark.anyio
+    async def test_context_logging_any_type(self):
+        """Test that context logging methods can handle different types of messages."""
+        from unittest.mock import patch
+
+        import mcp.server.session
+
+        mcp = FastMCP()
+
+        async def logging_tool(ctx: Context) -> str:
+            # Test with different data types
+            await ctx.debug(42)  # integer
+            await ctx.info(["list", "of", "items"])  # list
+            await ctx.warning({"key": "value"})  # dictionary
+            await ctx.error(3.14)  # float
+            return "Logged messages of different types"
+
+        mcp.add_tool(logging_tool)
+
+        with patch("mcp.server.session.ServerSession.send_log_message") as mock_log:
+            async with client_session(mcp._mcp_server) as client:
+                result = await client.call_tool("logging_tool", {})
+                assert len(result.content) == 1
+                content = result.content[0]
+                assert isinstance(content, TextContent)
+                assert "Logged messages of different types" in content.text
+
+                assert mock_log.call_count == 4
+                mock_log.assert_any_call(level="debug", data=42, logger=None)
+                mock_log.assert_any_call(
+                    level="info", data=["list", "of", "items"], logger=None
+                )
+                mock_log.assert_any_call(
+                    level="warning", data={"key": "value"}, logger=None
+                )
+                mock_log.assert_any_call(level="error", data=3.14, logger=None)
+
     @pytest.mark.anyio
     async def test_optional_context(self):
         """Test that context is optional."""

From c2ca8e03e046908935d089a2ceed4e80b0c29a24 Mon Sep 17 00:00:00 2001
From: anupsajjan <anup.sajjan@monetize360.com>
Date: Wed, 2 Apr 2025 19:21:50 +0530
Subject: [PATCH 2/3] Docs : Enhance README to suggest commands for creating a
 new UV project before adding mcp dependency. (#408)

---
 README.md | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 68969d0e..05d60725 100644
--- a/README.md
+++ b/README.md
@@ -73,11 +73,20 @@ The Model Context Protocol allows applications to provide context for LLMs in a
 
 ### Adding MCP to your python project
 
-We recommend using [uv](https://docs.astral.sh/uv/) to manage your Python projects. In a uv managed python project, add mcp to dependencies by:
+We recommend using [uv](https://docs.astral.sh/uv/) to manage your Python projects. 
 
-```bash
-uv add "mcp[cli]"
-```
+If you haven't created a uv-managed project yet, create one:
+
+   ```bash
+   uv init mcp-server-demo
+   cd mcp-server-demo
+   ```
+
+   Then add MCP to your project dependencies:
+
+   ```bash
+   uv add "mcp[cli]"
+   ```
 
 Alternatively, for projects using pip for dependencies:
 ```bash

From d97f15b3d5722e59c0e5aaa189c6b16de64b9a2e Mon Sep 17 00:00:00 2001
From: rakib-liberatelabs <rakibhosen@liberate-labs.com>
Date: Tue, 1 Apr 2025 00:04:33 +0600
Subject: [PATCH 3/3] fix: Update context logging type hints to match MCP spec

---
 src/mcp/server/fastmcp/server.py    | 38 ++++++++++++++++++++++-------
 tests/server/fastmcp/test_server.py | 37 ++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py
index bf0ce880..a1bb7f79 100644
--- a/src/mcp/server/fastmcp/server.py
+++ b/src/mcp/server/fastmcp/server.py
@@ -660,7 +660,7 @@ async def read_resource(self, uri: str | AnyUrl) -> Iterable[ReadResourceContent
     async def log(
         self,
         level: Literal["debug", "info", "warning", "error"],
-        message: str,
+        message: Any,
         *,
         logger_name: str | None = None,
     ) -> None:
@@ -696,18 +696,38 @@ def session(self):
         return self.request_context.session
 
     # Convenience methods for common log levels
-    async def debug(self, message: str, **extra: Any) -> None:
-        """Send a debug log message."""
+    async def debug(self, message: Any, **extra: Any) -> None:
+        """Send a debug log message.
+        
+        Args:
+            message: The message to log. Can be any JSON-serializable type.
+            **extra: Additional structured data to include
+        """
         await self.log("debug", message, **extra)
 
-    async def info(self, message: str, **extra: Any) -> None:
-        """Send an info log message."""
+    async def info(self, message: Any, **extra: Any) -> None:
+        """Send an info log message.
+        
+        Args:
+            message: The message to log. Can be any JSON-serializable type.
+            **extra: Additional structured data to include
+        """
         await self.log("info", message, **extra)
 
-    async def warning(self, message: str, **extra: Any) -> None:
-        """Send a warning log message."""
+    async def warning(self, message: Any, **extra: Any) -> None:
+        """Send a warning log message.
+        
+        Args:
+            message: The message to log. Can be any JSON-serializable type.
+            **extra: Additional structured data to include
+        """
         await self.log("warning", message, **extra)
 
-    async def error(self, message: str, **extra: Any) -> None:
-        """Send an error log message."""
+    async def error(self, message: Any, **extra: Any) -> None:
+        """Send an error log message.
+        
+        Args:
+            message: The message to log. Can be any JSON-serializable type.
+            **extra: Additional structured data to include
+        """
         await self.log("error", message, **extra)
diff --git a/tests/server/fastmcp/test_server.py b/tests/server/fastmcp/test_server.py
index e76e59c5..21c698fa 100644
--- a/tests/server/fastmcp/test_server.py
+++ b/tests/server/fastmcp/test_server.py
@@ -554,6 +554,43 @@ async def logging_tool(msg: str, ctx: Context) -> str:
                     level="error", data="Error message", logger=None
                 )
 
+    @pytest.mark.anyio
+    async def test_context_logging_any_type(self):
+        """Test that context logging methods can handle different types of messages."""
+        from unittest.mock import patch
+
+        import mcp.server.session
+
+        mcp = FastMCP()
+
+        async def logging_tool(ctx: Context) -> str:
+            # Test with different data types
+            await ctx.debug(42)  # integer
+            await ctx.info(["list", "of", "items"])  # list
+            await ctx.warning({"key": "value"})  # dictionary
+            await ctx.error(3.14)  # float
+            return "Logged messages of different types"
+
+        mcp.add_tool(logging_tool)
+
+        with patch("mcp.server.session.ServerSession.send_log_message") as mock_log:
+            async with client_session(mcp._mcp_server) as client:
+                result = await client.call_tool("logging_tool", {})
+                assert len(result.content) == 1
+                content = result.content[0]
+                assert isinstance(content, TextContent)
+                assert "Logged messages of different types" in content.text
+
+                assert mock_log.call_count == 4
+                mock_log.assert_any_call(level="debug", data=42, logger=None)
+                mock_log.assert_any_call(
+                    level="info", data=["list", "of", "items"], logger=None
+                )
+                mock_log.assert_any_call(
+                    level="warning", data={"key": "value"}, logger=None
+                )
+                mock_log.assert_any_call(level="error", data=3.14, logger=None)
+
     @pytest.mark.anyio
     async def test_optional_context(self):
         """Test that context is optional."""