Skip to content

Commit 67de515

Browse files
committed
merge
1 parent 633c34f commit 67de515

File tree

10 files changed

+136
-743
lines changed

10 files changed

+136
-743
lines changed

Diff for: .github/workflows/publish.yml

+12-18
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,22 @@ on:
55
workflow_dispatch:
66

77
jobs:
8-
publish-pypi-release:
8+
pypi-publish:
9+
name: Upload to PyPI
910
runs-on: ubuntu-latest
10-
environment: release
1111
permissions:
12-
contents: write
13-
id-token: write
12+
id-token: write # For PyPI's trusted publishing
1413
steps:
1514
- name: Checkout
1615
uses: actions/checkout@v4
17-
- name: Set up Python
18-
uses: actions/setup-python@v5
1916
with:
20-
python-version: "3.11"
21-
cache: pip
22-
cache-dependency-path: "**/pyproject.toml"
23-
- name: Install dependencies
24-
run: |
25-
pip install setuptools wheel build
17+
fetch-depth: 0
18+
19+
- name: "Install uv"
20+
uses: astral-sh/setup-uv@v3
21+
2622
- name: Build
27-
run: |
28-
python -m build
29-
- name: Publish
30-
uses: pypa/gh-action-pypi-publish@release/v1
31-
with:
32-
verbose: true
23+
run: uv build
24+
25+
- name: Publish to PyPi
26+
run: uv publish -v dist/*

Diff for: .gitignore

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,8 @@ wheels/
1111
.DS_Store
1212

1313

14-
src/fastmcp/_version.py
14+
src/fastmcp/_version.py
15+
16+
# editors
17+
.cursorrules
18+
.vscode/

Diff for: .pre-commit-config.yaml

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
fail_fast: true
2+
3+
repos:
4+
- repo: https://github.com/abravalheri/validate-pyproject
5+
rev: v0.23
6+
hooks:
7+
- id: validate-pyproject
8+
9+
- repo: https://github.com/pre-commit/mirrors-prettier
10+
rev: v3.1.0
11+
hooks:
12+
- id: prettier
13+
types_or: [yaml, json5]
14+
15+
- repo: https://github.com/astral-sh/ruff-pre-commit
16+
rev: v0.8.0
17+
hooks:
18+
- id: ruff-format
19+
- id: ruff
20+
args: [--fix, --exit-non-zero-on-fix]

Diff for: examples/echo.py

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from fastmcp import FastMCP
66

7-
87
# Create server
98
mcp = FastMCP("Echo Server")
109

Diff for: pyproject.toml

+2
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ dev = [
2929
"copychat>=0.5.2",
3030
"ipython>=8.12.3",
3131
"pdbpp>=0.10.3",
32+
"pre-commit>=3.10.1",
3233
"pytest-xdist>=3.6.1",
3334
"pytest>=8.3.3",
3435
"pytest-asyncio>=0.23.5",
3536
]
3637

3738
[tool.pytest.ini_options]
3839
asyncio_mode = "auto"
40+
asyncio_default_fixture_loop_scope = "session"

Diff for: src/fastmcp/resources/base.py

+9-11
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@
33
import abc
44
from typing import Union
55

6-
from pydantic import BaseModel, Field, field_validator
7-
from pydantic.networks import _BaseUrl
6+
from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, field_validator
7+
8+
from fastmcp.types import LaxAnyUrl
89

910

1011
class Resource(BaseModel, abc.ABC):
1112
"""Base class for all resources."""
1213

13-
uri: _BaseUrl = Field(description="URI of the resource")
14-
name: str = Field(description="Name of the resource", default=None)
14+
model_config = ConfigDict(validate_default=True)
15+
16+
uri: LaxAnyUrl = Field(description="URI of the resource")
17+
name: str | None = Field(description="Name of the resource", default=None)
1518
description: str | None = Field(
1619
description="Description of the resource", default=None
1720
)
@@ -23,13 +26,12 @@ class Resource(BaseModel, abc.ABC):
2326

2427
@field_validator("name", mode="before")
2528
@classmethod
26-
def set_default_name(cls, name: str | None, info) -> str:
29+
def set_default_name(cls, name: str | None, info: ValidationInfo) -> str:
2730
"""Set default name from URI if not provided."""
2831
if name:
2932
return name
3033
# Extract everything after the protocol (e.g., "desktop" from "resource://desktop")
31-
uri = info.data.get("uri")
32-
if uri:
34+
if uri := info.data.get("uri"):
3335
uri_str = str(uri)
3436
if "://" in uri_str:
3537
name = uri_str.split("://", 1)[1]
@@ -41,7 +43,3 @@ def set_default_name(cls, name: str | None, info) -> str:
4143
async def read(self) -> Union[str, bytes]:
4244
"""Read the resource content."""
4345
pass
44-
45-
model_config = {
46-
"validate_default": True,
47-
}

Diff for: src/fastmcp/resources/resource_manager.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from typing import Callable, Dict, Optional, Union
44

5-
from pydantic.networks import _BaseUrl
5+
from pydantic import AnyUrl
66

77
from fastmcp.resources.base import Resource
88
from fastmcp.resources.templates import ResourceTemplate
@@ -64,7 +64,7 @@ def add_template(
6464
self._templates[template.uri_template] = template
6565
return template
6666

67-
async def get_resource(self, uri: Union[_BaseUrl, str]) -> Optional[Resource]:
67+
async def get_resource(self, uri: Union[AnyUrl, str]) -> Optional[Resource]:
6868
"""Get resource by URI, checking concrete resources first, then templates."""
6969
uri_str = str(uri)
7070
logger.debug("Getting resource", extra={"uri": uri_str})

0 commit comments

Comments
 (0)