fastmcp 0.3.3__py3-none-any.whl → 0.3.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fastmcp/cli/claude.py CHANGED
@@ -41,14 +41,31 @@ def update_claude_config(
41
41
  with_packages: Optional list of additional packages to install
42
42
  env_vars: Optional dictionary of environment variables. These are merged with
43
43
  any existing variables, with new values taking precedence.
44
+
45
+ Raises:
46
+ RuntimeError: If Claude Desktop's config directory is not found, indicating
47
+ Claude Desktop may not be installed or properly set up.
44
48
  """
45
49
  config_dir = get_claude_config_path()
46
50
  if not config_dir:
47
- return False
51
+ raise RuntimeError(
52
+ "Claude Desktop config directory not found. Please ensure Claude Desktop "
53
+ "is installed and has been run at least once to initialize its configuration."
54
+ )
48
55
 
49
56
  config_file = config_dir / "claude_desktop_config.json"
50
57
  if not config_file.exists():
51
- return False
58
+ try:
59
+ config_file.write_text("{}")
60
+ except Exception as e:
61
+ logger.error(
62
+ "Failed to create Claude config file",
63
+ extra={
64
+ "error": str(e),
65
+ "config_file": str(config_file),
66
+ },
67
+ )
68
+ return False
52
69
 
53
70
  try:
54
71
  config = json.loads(config_file.read_text())
fastmcp/resources/base.py CHANGED
@@ -1,34 +1,17 @@
1
1
  """Base classes and interfaces for FastMCP resources."""
2
2
 
3
3
  import abc
4
- from typing import Annotated, Union
4
+ from typing import Union
5
5
 
6
6
  from pydantic import (
7
7
  AnyUrl,
8
8
  BaseModel,
9
- BeforeValidator,
10
9
  ConfigDict,
11
10
  Field,
12
11
  FileUrl,
13
12
  ValidationInfo,
14
13
  field_validator,
15
14
  )
16
- from pydantic.networks import _BaseUrl # TODO: remove this once pydantic is updated
17
-
18
-
19
- def maybe_cast_str_to_any_url(x) -> AnyUrl:
20
- if isinstance(x, FileUrl):
21
- return x
22
- elif isinstance(x, AnyUrl):
23
- return x
24
- elif isinstance(x, str):
25
- if x.startswith("file://"):
26
- return FileUrl(x)
27
- return AnyUrl(x)
28
- raise ValueError(f"Expected str or AnyUrl, got {type(x)}")
29
-
30
-
31
- LaxAnyUrl = Annotated[_BaseUrl | str, BeforeValidator(maybe_cast_str_to_any_url)]
32
15
 
33
16
 
34
17
  class Resource(BaseModel, abc.ABC):
@@ -36,7 +19,8 @@ class Resource(BaseModel, abc.ABC):
36
19
 
37
20
  model_config = ConfigDict(validate_default=True)
38
21
 
39
- uri: LaxAnyUrl = Field(default=..., description="URI of the resource")
22
+ # uri: Annotated[AnyUrl, BeforeValidator(maybe_cast_str_to_any_url)] = Field(
23
+ uri: AnyUrl = Field(default=..., description="URI of the resource")
40
24
  name: str | None = Field(description="Name of the resource", default=None)
41
25
  description: str | None = Field(
42
26
  description="Description of the resource", default=None
@@ -47,6 +31,15 @@ class Resource(BaseModel, abc.ABC):
47
31
  pattern=r"^[a-zA-Z0-9]+/[a-zA-Z0-9\-+.]+$",
48
32
  )
49
33
 
34
+ @field_validator("uri", mode="before")
35
+ def validate_uri(cls, uri: AnyUrl | str) -> AnyUrl:
36
+ if isinstance(uri, str):
37
+ # AnyUrl doesn't support triple-slashes, but files do ("file:///absolute/path")
38
+ if uri.startswith("file://"):
39
+ return FileUrl(uri)
40
+ return AnyUrl(uri)
41
+ return uri
42
+
50
43
  @field_validator("name", mode="before")
51
44
  @classmethod
52
45
  def set_default_name(cls, name: str | None, info: ValidationInfo) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: fastmcp
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: A more ergonomic interface for MCP servers
5
5
  Author: Jeremiah Lowin
6
6
  License: Apache-2.0
@@ -122,6 +122,8 @@ pip install fastmcp
122
122
  Let's create a simple MCP server that exposes a calculator tool and some data:
123
123
 
124
124
  ```python
125
+ # server.py
126
+
125
127
  from fastmcp import FastMCP
126
128
 
127
129
 
@@ -143,14 +145,12 @@ def get_greeting(name: str) -> str:
143
145
  return f"Hello, {name}!"
144
146
  ```
145
147
 
146
- To use this server, you have two options:
147
-
148
- 1. Install it in [Claude Desktop](https://claude.ai/download):
148
+ You can install this server in [Claude Desktop](https://claude.ai/download) and interact with it right away by running:
149
149
  ```bash
150
150
  fastmcp install server.py
151
151
  ```
152
152
 
153
- 2. Test it with the MCP Inspector:
153
+ Alternatively, you can test it with the MCP Inspector:
154
154
  ```bash
155
155
  fastmcp dev server.py
156
156
  ```
@@ -181,9 +181,6 @@ from fastmcp import FastMCP
181
181
  # Create a named server
182
182
  mcp = FastMCP("My App")
183
183
 
184
- # Configure host/port for HTTP transport (optional)
185
- mcp = FastMCP("My App", host="localhost", port=8000)
186
-
187
184
  # Specify dependencies for deployment and development
188
185
  mcp = FastMCP("My App", dependencies=["pandas", "numpy"])
189
186
  ```
@@ -2,14 +2,14 @@ fastmcp/__init__.py,sha256=Y5dHGBwyQPgNP5gzOyNIItefvMZ3vJLdom1oV8A1u_k,248
2
2
  fastmcp/exceptions.py,sha256=K0rCgXsUVlws39hz98Tb4BBf_BzIql_zXFZgqbkNTiE,348
3
3
  fastmcp/server.py,sha256=V6BaciC5u9g_XzbvPkafjGO8OtEBPGy_KlV535Au0do,22234
4
4
  fastmcp/cli/__init__.py,sha256=7hrwtCHX9nMd9qcz7R_JFSoqbL71fC35cBLXBS430mg,88
5
- fastmcp/cli/claude.py,sha256=APgTMQm7qa68Fz4EObZYmrgY-8-wjn6vCJZD7Se6XlU,3765
5
+ fastmcp/cli/claude.py,sha256=5SoVEsA_PnOyOe2bcItvfcCwuhfX6W99TP1nXahLIJE,4442
6
6
  fastmcp/cli/cli.py,sha256=Ub2iNwnCVRO4TbC6Rr_1xOeTKnDN-9XE1z1O1yZatbg,11664
7
7
  fastmcp/prompts/__init__.py,sha256=4BsMxoYolpoxg74xkkkzCFL8vvdkLVJ5cIPNs1ND1Jo,99
8
8
  fastmcp/prompts/base.py,sha256=WaSsfyFSsUPUbcApkGy3Pm-Ne-Gk-5ZwU3efqRYn1mQ,4996
9
9
  fastmcp/prompts/manager.py,sha256=EkexOB_N4QNtC-UlZmIcWcau91ceO2O1K4_kD75pA_A,1485
10
10
  fastmcp/prompts/prompt_manager.py,sha256=5uR14gsi7l0YHwbxFH7N5b_ACHHRWyTtBAH3R0-G5rk,1129
11
11
  fastmcp/resources/__init__.py,sha256=9QShop6ckX3Khh3BQLZNkB6R2ZhwskAcnh7-sIuX-W8,464
12
- fastmcp/resources/base.py,sha256=glGLpHp8Eq-LKq7YLJx3LRDiCktLlLaTTmltNcdWzHg,1818
12
+ fastmcp/resources/base.py,sha256=inm2uhaE6KPQEsMd4SyDLbRIOjQrXahSn84RNT3Y6MY,1723
13
13
  fastmcp/resources/resource_manager.py,sha256=b0PKpG-pKi7x2Yx-qaeknjv0mqL17zixSIYOz2V5G6o,3271
14
14
  fastmcp/resources/templates.py,sha256=EmLlI-ddBBzSTAUiA6-knFnHCE3MPMW2ZoH9WswPKvI,2868
15
15
  fastmcp/resources/types.py,sha256=ofE6bfeQQfPSmaWrLGDf3qjCP0kGjKmvupsHDYkSrj0,5658
@@ -19,8 +19,8 @@ fastmcp/tools/tool_manager.py,sha256=PT6XHcQWzhdC6kfdsJaddRn7VLps4nAs5FMG8l1j8Zc
19
19
  fastmcp/utilities/__init__.py,sha256=-imJ8S-rXmbXMWeDamldP-dHDqAPg_wwmPVz-LNX14E,31
20
20
  fastmcp/utilities/logging.py,sha256=VLJdNc0tIYoQZmpobehLUnWrQz7NXnuwSqrDlFt2RF0,738
21
21
  fastmcp/utilities/types.py,sha256=jFlZMZsKrJg4NWc1vTBIILLoHpTVwSd-vxO7ycoRuig,1718
22
- fastmcp-0.3.3.dist-info/METADATA,sha256=pDlwjd5p0ErFBvpK2D6u9jAWb4rsGzL9f3l95IWJToc,15319
23
- fastmcp-0.3.3.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
24
- fastmcp-0.3.3.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
25
- fastmcp-0.3.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
26
- fastmcp-0.3.3.dist-info/RECORD,,
22
+ fastmcp-0.3.4.dist-info/METADATA,sha256=-DqzP1SZTCU0qgtFZ7K3ABSaswQz9Q5ShWU-UwN_mkM,15260
23
+ fastmcp-0.3.4.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
24
+ fastmcp-0.3.4.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
25
+ fastmcp-0.3.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
26
+ fastmcp-0.3.4.dist-info/RECORD,,