Jeremiah Lowin commited on
Commit
4461926
·
1 Parent(s): 2d794e9

Rename server

Browse files
examples/desktop.py CHANGED
@@ -7,10 +7,10 @@ A simple example that exposes the desktop directory as a resource.
7
  import asyncio
8
  from pathlib import Path
9
 
10
- from fastmcp.server import FastMCPServer
11
 
12
  # Create server
13
- app = FastMCPServer("desktop")
14
 
15
  # Add desktop as a directory resource
16
  desktop = Path.home() / "Desktop"
@@ -24,7 +24,7 @@ app.add_dir_resource(
24
 
25
  def main123():
26
  # Run the server
27
- asyncio.run(FastMCPServer.run_stdio(app))
28
 
29
 
30
  if __name__ == "__main__":
 
7
  import asyncio
8
  from pathlib import Path
9
 
10
+ from fastmcp.server import FastMCP
11
 
12
  # Create server
13
+ app = FastMCP("desktop")
14
 
15
  # Add desktop as a directory resource
16
  desktop = Path.home() / "Desktop"
 
24
 
25
  def main123():
26
  # Run the server
27
+ asyncio.run(FastMCP.run_stdio(app))
28
 
29
 
30
  if __name__ == "__main__":
examples/weather.py CHANGED
@@ -5,7 +5,7 @@ FastMCP Weather Server Example
5
  import os
6
  import httpx
7
  from pydantic import BaseModel, Field
8
- from fastmcp.server import FastMCPServer
9
 
10
  # Load env vars
11
  API_KEY = os.getenv("OPENWEATHER_API_KEY")
@@ -32,7 +32,7 @@ class AlertParams(BaseModel):
32
 
33
 
34
  # Create server
35
- app = FastMCPServer("weather-service")
36
 
37
 
38
  # Tools using Pydantic models
@@ -126,7 +126,7 @@ def main():
126
  )
127
 
128
  # Run the server
129
- asyncio.run(FastMCPServer.run_stdio(app))
130
 
131
 
132
  if __name__ == "__main__":
 
5
  import os
6
  import httpx
7
  from pydantic import BaseModel, Field
8
+ from fastmcp.server import FastMCP
9
 
10
  # Load env vars
11
  API_KEY = os.getenv("OPENWEATHER_API_KEY")
 
32
 
33
 
34
  # Create server
35
+ app = FastMCP("weather-service")
36
 
37
 
38
  # Tools using Pydantic models
 
126
  )
127
 
128
  # Run the server
129
+ asyncio.run(FastMCP.run_stdio(app))
130
 
131
 
132
  if __name__ == "__main__":
src/fastmcp/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .server import FastMCP
src/fastmcp/server.py CHANGED
@@ -1,13 +1,16 @@
1
  """FastMCP - A more ergonomic interface for MCP servers."""
2
 
 
3
  import base64
4
  import functools
5
  import json
6
  import logging
 
7
  from typing import Any, Callable, Dict, Optional, Sequence, Union, Literal
8
 
9
  from mcp.server import Server as MCPServer
10
  from mcp.server.stdio import stdio_server
 
11
  from mcp.types import Resource as MCPResource
12
  from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
13
  from pydantic import BaseModel
@@ -16,9 +19,9 @@ from pydantic_settings import BaseSettings
16
  from .exceptions import ResourceError
17
  from .resources import Resource, FunctionResource, ResourceManager
18
  from .tools import ToolManager
 
19
 
20
-
21
- logger = logging.getLogger("fastmcp")
22
 
23
 
24
  class Settings(BaseSettings):
@@ -45,10 +48,10 @@ class Settings(BaseSettings):
45
  warn_on_duplicate_tools: bool = True
46
 
47
 
48
- class FastMCPServer:
49
  def __init__(self, name=None, **settings: Optional[Settings]):
50
  self.settings = Settings(**settings)
51
- self._mcp_server = MCPServer(name=name or "FastMCPServer")
52
  self._tool_manager = ToolManager(
53
  warn_on_duplicate_tools=self.settings.warn_on_duplicate_tools
54
  )
@@ -57,11 +60,7 @@ class FastMCPServer:
57
  )
58
 
59
  # Configure logging
60
- logging.basicConfig(
61
- level=getattr(logging, self.settings.log_level.upper()),
62
- format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
63
- )
64
- logger.setLevel(getattr(logging, self.settings.log_level.upper()))
65
 
66
  self._setup_handlers()
67
 
@@ -297,7 +296,7 @@ class FastMCPServer:
297
  await self._mcp_server.run(*args, **kwargs)
298
 
299
  @classmethod
300
- async def run_stdio(cls, app: "FastMCPServer") -> None:
301
  """Run the server using stdio transport."""
302
  async with stdio_server() as (read_stream, write_stream):
303
  await app.run(
@@ -309,7 +308,7 @@ class FastMCPServer:
309
  @classmethod
310
  async def run_sse(
311
  cls,
312
- app: "FastMCPServer",
313
  ) -> None:
314
  """Run the server using SSE transport."""
315
  from mcp.server.sse import SseServerTransport
 
1
  """FastMCP - A more ergonomic interface for MCP servers."""
2
 
3
+ import asyncio
4
  import base64
5
  import functools
6
  import json
7
  import logging
8
+ from dataclasses import dataclass
9
  from typing import Any, Callable, Dict, Optional, Sequence, Union, Literal
10
 
11
  from mcp.server import Server as MCPServer
12
  from mcp.server.stdio import stdio_server
13
+ from mcp.server.sse import SseServerTransport
14
  from mcp.types import Resource as MCPResource
15
  from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
16
  from pydantic import BaseModel
 
19
  from .exceptions import ResourceError
20
  from .resources import Resource, FunctionResource, ResourceManager
21
  from .tools import ToolManager
22
+ from .utilities import get_logger, configure_logging
23
 
24
+ logger = get_logger(__name__)
 
25
 
26
 
27
  class Settings(BaseSettings):
 
48
  warn_on_duplicate_tools: bool = True
49
 
50
 
51
+ class FastMCP:
52
  def __init__(self, name=None, **settings: Optional[Settings]):
53
  self.settings = Settings(**settings)
54
+ self._mcp_server = MCPServer(name=name or "FastMCP")
55
  self._tool_manager = ToolManager(
56
  warn_on_duplicate_tools=self.settings.warn_on_duplicate_tools
57
  )
 
60
  )
61
 
62
  # Configure logging
63
+ configure_logging(self.settings.log_level)
 
 
 
 
64
 
65
  self._setup_handlers()
66
 
 
296
  await self._mcp_server.run(*args, **kwargs)
297
 
298
  @classmethod
299
+ async def run_stdio(cls, app: "FastMCP") -> None:
300
  """Run the server using stdio transport."""
301
  async with stdio_server() as (read_stream, write_stream):
302
  await app.run(
 
308
  @classmethod
309
  async def run_sse(
310
  cls,
311
+ app: "FastMCP",
312
  ) -> None:
313
  """Run the server using SSE transport."""
314
  from mcp.server.sse import SseServerTransport
src/fastmcp/utilities/__init__.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ """Utility functions for FastMCP."""
2
+ from .logging import get_logger, configure_logging
3
+
4
+ __all__ = ["get_logger", "configure_logging"]
src/fastmcp/utilities/logging.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Logging utilities for FastMCP."""
2
+ import logging
3
+ from typing import Optional
4
+
5
+
6
+ def get_logger(name: Optional[str] = None) -> logging.Logger:
7
+ """Get a logger instance nested under the FastMCP namespace.
8
+
9
+ Args:
10
+ name: Optional name to append to the FastMCP namespace.
11
+ If provided, the logger will be named 'FastMCP.[name]'.
12
+ If not provided, returns the root FastMCP logger.
13
+
14
+ Returns:
15
+ A configured logger instance
16
+ """
17
+ logger_name = "FastMCP"
18
+ if name:
19
+ logger_name = f"{logger_name}.{name}"
20
+ return logging.getLogger(logger_name)
21
+
22
+
23
+ def configure_logging(level: str = "INFO") -> None:
24
+ """Configure the root FastMCP logger.
25
+
26
+ Args:
27
+ level: The log level to use. Defaults to INFO.
28
+ """
29
+ logging.basicConfig(
30
+ level=getattr(logging, level.upper()),
31
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
32
+ )
33
+ get_logger().setLevel(getattr(logging, level.upper()))
tests/test_server.py CHANGED
@@ -1,13 +1,13 @@
1
  from mcp.shared.memory import (
2
  create_connected_server_and_client_session as client_session,
3
  )
4
- from fastmcp.server import FastMCPServer
5
 
6
 
7
  class TestServer:
8
  async def test_create_server(self):
9
- server = FastMCPServer()
10
- assert server.name == "FastMCPServer"
11
 
12
 
13
  def tool_fn(x: int, y: int) -> int:
@@ -16,20 +16,20 @@ def tool_fn(x: int, y: int) -> int:
16
 
17
  class TestServerTools:
18
  async def test_add_tool(self):
19
- server = FastMCPServer()
20
  server.add_tool(tool_fn)
21
  server.add_tool(tool_fn)
22
  assert len(server._tool_manager.list_tools()) == 1
23
 
24
  async def test_list_tools(self):
25
- server = FastMCPServer()
26
  server.add_tool(tool_fn)
27
  async with client_session(server._mcp_server) as client:
28
  tools = await client.list_tools()
29
  assert len(tools.tools) == 1
30
 
31
  async def test_call_tool(self):
32
- server = FastMCPServer()
33
  server.add_tool(tool_fn)
34
  async with client_session(server._mcp_server) as client:
35
  result = await client.call_tool("my_tool", {"arg1": "value"})
 
1
  from mcp.shared.memory import (
2
  create_connected_server_and_client_session as client_session,
3
  )
4
+ from fastmcp.server import FastMCP
5
 
6
 
7
  class TestServer:
8
  async def test_create_server(self):
9
+ server = FastMCP()
10
+ assert server.name == "FastMCP"
11
 
12
 
13
  def tool_fn(x: int, y: int) -> int:
 
16
 
17
  class TestServerTools:
18
  async def test_add_tool(self):
19
+ server = FastMCP()
20
  server.add_tool(tool_fn)
21
  server.add_tool(tool_fn)
22
  assert len(server._tool_manager.list_tools()) == 1
23
 
24
  async def test_list_tools(self):
25
+ server = FastMCP()
26
  server.add_tool(tool_fn)
27
  async with client_session(server._mcp_server) as client:
28
  tools = await client.list_tools()
29
  assert len(tools.tools) == 1
30
 
31
  async def test_call_tool(self):
32
+ server = FastMCP()
33
  server.add_tool(tool_fn)
34
  async with client_session(server._mcp_server) as client:
35
  result = await client.call_tool("my_tool", {"arg1": "value"})