Jeremiah Lowin commited on
Commit
c7184ac
·
1 Parent(s): ad3a4c4

Move components to own file; add resource

Browse files
docs/getting-started/installation.mdx CHANGED
@@ -72,7 +72,7 @@ For users concerned about stability in production environments, we recommend pin
72
 
73
  Whenever possible, FastMCP will issue deprecation warnings when users attempt to use APIs that are either deprecated or destined for future removal. These warnings will be maintained for at least 1 minor version release, and may be maintained longer.
74
 
75
- Note that the "public API" includes the core functionality of the `FastMCP` server and its methods. It does not include private methods or objects that are stored as private attributes, as we do not expect users to rely on those implementation details.
76
 
77
  ## Installing for Development
78
 
 
72
 
73
  Whenever possible, FastMCP will issue deprecation warnings when users attempt to use APIs that are either deprecated or destined for future removal. These warnings will be maintained for at least 1 minor version release, and may be maintained longer.
74
 
75
+ Note that the "public API" includes the public functionality of the `FastMCP` server, core FastMCP components like `Tool`, `Prompt`, `Resource`, and `ResourceTemplate`, and their respective public methods. It does not include private methods, utilities, or objects that are stored as private attributes, as we do not expect users to rely on those implementation details.
76
 
77
  ## Installing for Development
78
 
src/fastmcp/prompts/prompt.py CHANGED
@@ -15,11 +15,11 @@ from pydantic import Field, TypeAdapter, validate_call
15
 
16
  from fastmcp.exceptions import PromptError
17
  from fastmcp.server.dependencies import get_context
 
18
  from fastmcp.utilities.json_schema import compress_schema
19
  from fastmcp.utilities.logging import get_logger
20
  from fastmcp.utilities.types import (
21
  FastMCPBaseModel,
22
- FastMCPComponent,
23
  find_kwarg_by_type,
24
  get_cached_typeadapter,
25
  )
 
15
 
16
  from fastmcp.exceptions import PromptError
17
  from fastmcp.server.dependencies import get_context
18
+ from fastmcp.utilities.components import FastMCPComponent
19
  from fastmcp.utilities.json_schema import compress_schema
20
  from fastmcp.utilities.logging import get_logger
21
  from fastmcp.utilities.types import (
22
  FastMCPBaseModel,
 
23
  find_kwarg_by_type,
24
  get_cached_typeadapter,
25
  )
src/fastmcp/resources/resource.py CHANGED
@@ -11,7 +11,6 @@ import pydantic_core
11
  from mcp.types import Resource as MCPResource
12
  from pydantic import (
13
  AnyUrl,
14
- BeforeValidator,
15
  ConfigDict,
16
  Field,
17
  UrlConstraints,
@@ -20,9 +19,8 @@ from pydantic import (
20
  )
21
 
22
  from fastmcp.server.dependencies import get_context
 
23
  from fastmcp.utilities.types import (
24
- FastMCPBaseModel,
25
- _convert_set_default_none,
26
  find_kwarg_by_type,
27
  )
28
 
@@ -30,7 +28,7 @@ if TYPE_CHECKING:
30
  pass
31
 
32
 
33
- class Resource(FastMCPBaseModel, abc.ABC):
34
  """Base class for all resources."""
35
 
36
  model_config = ConfigDict(validate_default=True)
@@ -38,13 +36,6 @@ class Resource(FastMCPBaseModel, abc.ABC):
38
  uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] = Field(
39
  default=..., description="URI of the resource"
40
  )
41
- name: str | None = Field(default=None, description="Name of the resource")
42
- description: str | None = Field(
43
- default=None, description="Description of the resource"
44
- )
45
- tags: Annotated[set[str], BeforeValidator(_convert_set_default_none)] = Field(
46
- default_factory=set, description="Tags for the resource"
47
- )
48
  mime_type: str = Field(
49
  default="text/plain",
50
  description="MIME type of the resource content",
 
11
  from mcp.types import Resource as MCPResource
12
  from pydantic import (
13
  AnyUrl,
 
14
  ConfigDict,
15
  Field,
16
  UrlConstraints,
 
19
  )
20
 
21
  from fastmcp.server.dependencies import get_context
22
+ from fastmcp.utilities.components import FastMCPComponent
23
  from fastmcp.utilities.types import (
 
 
24
  find_kwarg_by_type,
25
  )
26
 
 
28
  pass
29
 
30
 
31
+ class Resource(FastMCPComponent, abc.ABC):
32
  """Base class for all resources."""
33
 
34
  model_config = ConfigDict(validate_default=True)
 
36
  uri: Annotated[AnyUrl, UrlConstraints(host_required=False)] = Field(
37
  default=..., description="URI of the resource"
38
  )
 
 
 
 
 
 
 
39
  mime_type: str = Field(
40
  default="text/plain",
41
  description="MIME type of the resource content",
src/fastmcp/resources/template.py CHANGED
@@ -17,9 +17,9 @@ from pydantic import (
17
 
18
  from fastmcp.resources.types import Resource
19
  from fastmcp.server.dependencies import get_context
 
20
  from fastmcp.utilities.json_schema import compress_schema
21
  from fastmcp.utilities.types import (
22
- FastMCPComponent,
23
  find_kwarg_by_type,
24
  get_cached_typeadapter,
25
  )
 
17
 
18
  from fastmcp.resources.types import Resource
19
  from fastmcp.server.dependencies import get_context
20
+ from fastmcp.utilities.components import FastMCPComponent
21
  from fastmcp.utilities.json_schema import compress_schema
22
  from fastmcp.utilities.types import (
 
23
  find_kwarg_by_type,
24
  get_cached_typeadapter,
25
  )
src/fastmcp/tools/tool.py CHANGED
@@ -14,10 +14,10 @@ from pydantic import Field
14
 
15
  import fastmcp
16
  from fastmcp.server.dependencies import get_context
 
17
  from fastmcp.utilities.json_schema import compress_schema
18
  from fastmcp.utilities.logging import get_logger
19
  from fastmcp.utilities.types import (
20
- FastMCPComponent,
21
  Image,
22
  find_kwarg_by_type,
23
  get_cached_typeadapter,
 
14
 
15
  import fastmcp
16
  from fastmcp.server.dependencies import get_context
17
+ from fastmcp.utilities.components import FastMCPComponent
18
  from fastmcp.utilities.json_schema import compress_schema
19
  from fastmcp.utilities.logging import get_logger
20
  from fastmcp.utilities.types import (
 
21
  Image,
22
  find_kwarg_by_type,
23
  get_cached_typeadapter,
src/fastmcp/utilities/components.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections.abc import Sequence
2
+ from typing import Annotated, TypeVar
3
+
4
+ from pydantic import BeforeValidator, Field
5
+
6
+ from fastmcp.utilities.types import FastMCPBaseModel
7
+
8
+ T = TypeVar("T")
9
+
10
+
11
+ def _convert_set_default_none(maybe_set: set[T] | Sequence[T] | None) -> set[T]:
12
+ """Convert a sequence to a set, defaulting to an empty set if None."""
13
+ if maybe_set is None:
14
+ return set()
15
+ if isinstance(maybe_set, set):
16
+ return maybe_set
17
+ return set(maybe_set)
18
+
19
+
20
+ class FastMCPComponent(FastMCPBaseModel):
21
+ """Base class for FastMCP tools, prompts, resources, and resource templates."""
22
+
23
+ name: str = Field(
24
+ description="The name of the component.",
25
+ )
26
+ description: str | None = Field(
27
+ default=None,
28
+ description="The description of the component.",
29
+ )
30
+ tags: Annotated[set[str], BeforeValidator(_convert_set_default_none)] = Field(
31
+ default_factory=set,
32
+ description="Tags for the component.",
33
+ )
34
+
35
+ def __eq__(self, other: object) -> bool:
36
+ if type(self) is not type(other):
37
+ return False
38
+ assert isinstance(other, type(self))
39
+ return self.model_dump() == other.model_dump()
src/fastmcp/utilities/types.py CHANGED
@@ -2,55 +2,24 @@
2
 
3
  import base64
4
  import inspect
5
- from collections.abc import Callable, Sequence
6
  from functools import lru_cache
7
  from pathlib import Path
8
  from types import UnionType
9
  from typing import Annotated, TypeVar, Union, get_args, get_origin
10
 
11
  from mcp.types import ImageContent
12
- from pydantic import BaseModel, BeforeValidator, ConfigDict, Field, TypeAdapter
13
 
14
  T = TypeVar("T")
15
 
16
 
17
- def _convert_set_default_none(maybe_set: set[T] | Sequence[T] | None) -> set[T]:
18
- """Convert a sequence to a set, defaulting to an empty set if None."""
19
- if maybe_set is None:
20
- return set()
21
- if isinstance(maybe_set, set):
22
- return maybe_set
23
- return set(maybe_set)
24
-
25
-
26
  class FastMCPBaseModel(BaseModel):
27
  """Base model for FastMCP models."""
28
 
29
  model_config = ConfigDict(extra="forbid")
30
 
31
 
32
- class FastMCPComponent(FastMCPBaseModel):
33
- """Base class for FastMCP tools, prompts, resources, and resource templates."""
34
-
35
- name: str = Field(
36
- description="The name of the component.",
37
- )
38
- description: str | None = Field(
39
- default=None,
40
- description="The description of the component.",
41
- )
42
- tags: Annotated[set[str], BeforeValidator(_convert_set_default_none)] = Field(
43
- default_factory=set,
44
- description="Tags for the component.",
45
- )
46
-
47
- def __eq__(self, other: object) -> bool:
48
- if type(self) is not type(other):
49
- return False
50
- assert isinstance(other, type(self))
51
- return self.model_dump() == other.model_dump()
52
-
53
-
54
  @lru_cache(maxsize=5000)
55
  def get_cached_typeadapter(cls: T) -> TypeAdapter[T]:
56
  """
 
2
 
3
  import base64
4
  import inspect
5
+ from collections.abc import Callable
6
  from functools import lru_cache
7
  from pathlib import Path
8
  from types import UnionType
9
  from typing import Annotated, TypeVar, Union, get_args, get_origin
10
 
11
  from mcp.types import ImageContent
12
+ from pydantic import BaseModel, ConfigDict, TypeAdapter
13
 
14
  T = TypeVar("T")
15
 
16
 
 
 
 
 
 
 
 
 
 
17
  class FastMCPBaseModel(BaseModel):
18
  """Base model for FastMCP models."""
19
 
20
  model_config = ConfigDict(extra="forbid")
21
 
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  @lru_cache(maxsize=5000)
24
  def get_cached_typeadapter(cls: T) -> TypeAdapter[T]:
25
  """