Jeremiah Lowin commited on
Commit
7ca2f08
·
1 Parent(s): 4461926

Update logging

Browse files
examples/weather.py CHANGED
@@ -6,6 +6,7 @@ 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")
@@ -117,13 +118,9 @@ app.add_dir_resource(
117
 
118
  def main():
119
  import asyncio
120
- import logging
121
 
122
  # Configure logging
123
- logging.basicConfig(
124
- level=logging.INFO,
125
- format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
126
- )
127
 
128
  # Run the server
129
  asyncio.run(FastMCP.run_stdio(app))
 
6
  import httpx
7
  from pydantic import BaseModel, Field
8
  from fastmcp.server import FastMCP
9
+ from fastmcp.utilities.logging import configure_logging
10
 
11
  # Load env vars
12
  API_KEY = os.getenv("OPENWEATHER_API_KEY")
 
118
 
119
  def main():
120
  import asyncio
 
121
 
122
  # Configure logging
123
+ configure_logging(level="INFO")
 
 
 
124
 
125
  # Run the server
126
  asyncio.run(FastMCP.run_stdio(app))
src/fastmcp/cli.py CHANGED
@@ -1,15 +1,15 @@
1
  """FastMCP CLI tools."""
2
 
3
  import importlib.metadata
4
- import logging
5
  import subprocess
6
  import sys
7
  from pathlib import Path
8
 
9
  import typer
10
 
11
- # Configure logging
12
- logger = logging.getLogger("mcp")
 
13
 
14
  app = typer.Typer(
15
  name="fastmcp",
 
1
  """FastMCP CLI tools."""
2
 
3
  import importlib.metadata
 
4
  import subprocess
5
  import sys
6
  from pathlib import Path
7
 
8
  import typer
9
 
10
+ from .utilities.logging import get_logger
11
+
12
+ logger = get_logger(__name__)
13
 
14
  app = typer.Typer(
15
  name="fastmcp",
src/fastmcp/resources.py CHANGED
@@ -3,7 +3,6 @@
3
  import abc
4
  import asyncio
5
  import json
6
- import logging
7
  from pathlib import Path
8
  from typing import Dict, Optional, Callable, Any
9
  from urllib.parse import parse_qs, urlparse
@@ -11,7 +10,9 @@ from urllib.parse import parse_qs, urlparse
11
  import httpx
12
  from pydantic import BaseModel, field_validator
13
 
14
- logger = logging.getLogger("mcp")
 
 
15
 
16
 
17
  class Resource(BaseModel):
 
3
  import abc
4
  import asyncio
5
  import json
 
6
  from pathlib import Path
7
  from typing import Dict, Optional, Callable, Any
8
  from urllib.parse import parse_qs, urlparse
 
10
  import httpx
11
  from pydantic import BaseModel, field_validator
12
 
13
+ from .utilities.logging import get_logger
14
+
15
+ logger = get_logger(__name__)
16
 
17
 
18
  class Resource(BaseModel):
src/fastmcp/server.py CHANGED
@@ -1,11 +1,8 @@
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
@@ -19,7 +16,7 @@ from pydantic_settings import BaseSettings
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
 
 
1
  """FastMCP - A more ergonomic interface for MCP servers."""
2
 
 
3
  import base64
4
  import functools
5
  import json
 
 
6
  from typing import Any, Callable, Dict, Optional, Sequence, Union, Literal
7
 
8
  from mcp.server import Server as MCPServer
 
16
  from .exceptions import ResourceError
17
  from .resources import Resource, FunctionResource, ResourceManager
18
  from .tools import ToolManager
19
+ from .utilities.logging import get_logger, configure_logging
20
 
21
  logger = get_logger(__name__)
22
 
src/fastmcp/tools.py CHANGED
@@ -6,9 +6,9 @@ from typing import Any, Callable, Dict, Optional
6
  from pydantic import BaseModel, Field, TypeAdapter
7
 
8
  from .exceptions import ToolError
9
- import logging
10
 
11
- logger = logging.getLogger("fastmcp")
12
 
13
 
14
  class Tool(BaseModel):
@@ -84,7 +84,7 @@ class ToolManager:
84
  existing = self._tools.get(tool.name)
85
  if existing:
86
  if self.warn_on_duplicate_tools:
87
- logging.warning(f"Tool already exists: {tool.name}")
88
  return existing
89
  self._tools[tool.name] = tool
90
  return tool
 
6
  from pydantic import BaseModel, Field, TypeAdapter
7
 
8
  from .exceptions import ToolError
9
+ from .utilities.logging import get_logger
10
 
11
+ logger = get_logger(__name__)
12
 
13
 
14
  class Tool(BaseModel):
 
84
  existing = self._tools.get(tool.name)
85
  if existing:
86
  if self.warn_on_duplicate_tools:
87
+ logger.warning(f"Tool already exists: {tool.name}")
88
  return existing
89
  self._tools[tool.name] = tool
90
  return tool
src/fastmcp/utilities/__init__.py CHANGED
@@ -1,4 +1 @@
1
- """Utility functions for FastMCP."""
2
- from .logging import get_logger, configure_logging
3
-
4
- __all__ = ["get_logger", "configure_logging"]
 
1
+ """FastMCP utility modules."""
 
 
 
src/fastmcp/utilities/logging.py CHANGED
@@ -1,33 +1,30 @@
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()))
 
1
  """Logging utilities for FastMCP."""
2
+
3
  import logging
4
+ from typing import Literal
5
+
6
 
7
+ def get_logger(name: str) -> logging.Logger:
8
+ """Get a logger nested under FastMCP namespace.
9
 
 
 
 
10
  Args:
11
+ name: The name of the logger, which will be prefixed with 'FastMCP.'
12
+
 
 
13
  Returns:
14
  A configured logger instance
15
  """
16
+ return logging.getLogger(f"FastMCP.{name}")
17
+
 
 
18
 
19
+ def configure_logging(
20
+ level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = "INFO",
21
+ ) -> None:
22
+ """Configure logging for FastMCP.
23
 
 
 
 
24
  Args:
25
+ level: The log level to use
26
  """
27
  logging.basicConfig(
28
+ level=level,
29
  format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
30
  )