diff --git a/.github/workflows/martian-triage-issue.yml b/.github/workflows/martian-triage-issue.yml index f5f4e9ebd..2789bd7be 100644 --- a/.github/workflows/martian-triage-issue.yml +++ b/.github/workflows/martian-triage-issue.yml @@ -125,7 +125,7 @@ jobs: Every claim in your response must be grounded in evidence you can cite: - - **Code references**: Always include file path and line number (e.g., `src/fastmcp/client/client.py:142`). Never say "the client code does X" without pointing to where. + - **Code references**: Always include file path and line number (e.g., `fastmcp_slim/fastmcp/client/client.py:142`). Never say "the client code does X" without pointing to where. - **Bug confirmation**: If you say a bug is real, show the specific code path that produces it. If you ran a test, include the command and output. - **Related items**: When citing a related issue or PR, explain specifically why it's related — not just that it exists. - **Confidence**: If you're uncertain about a finding, say so. "I don't know" or "I couldn't confirm this" is better than a speculative diagnosis. Only report findings you would confidently defend. diff --git a/.github/workflows/marvin-label-triage.yml b/.github/workflows/marvin-label-triage.yml index fed226e7c..bed6f82e2 100644 --- a/.github/workflows/marvin-label-triage.yml +++ b/.github/workflows/marvin-label-triage.yml @@ -116,7 +116,7 @@ jobs: - auth: Authentication is the main concern (Bearer, JWT, OAuth, WorkOS) - openapi: OpenAPI integration/parsing is the primary topic - http: HTTP transport or networking is the main issue - - contrib: Specifically about community contributions in src/contrib/ + - contrib: Specifically about community contributions in fastmcp_slim/fastmcp/contrib/ - tests: Issues primarily about testing infrastructure, CI/CD workflows, or test coverage - security: Apply ONLY when the issue/PR addresses an exploitable vulnerability or hardens against one. Examples: SSRF, LFI, path traversal, injection, auth bypass allowing unauthorized access, scope escalation, open redirects. Do NOT apply for ordinary auth bugs (wrong scopes returned, token refresh logic, OAuth flow correctness) unless an attacker could exploit the bug to bypass access controls or escalate privileges. The key question: "Could a malicious actor exploit this?" If the answer is just "it breaks for legitimate users," that's a bug, not a security issue. diff --git a/.github/workflows/publish-fastmcp-slim.yml b/.github/workflows/publish-fastmcp-slim.yml new file mode 100644 index 000000000..58fcc5625 --- /dev/null +++ b/.github/workflows/publish-fastmcp-slim.yml @@ -0,0 +1,30 @@ +name: Publish fastmcp-slim to PyPI + +on: + release: + types: [published] + workflow_dispatch: + +permissions: + contents: read + id-token: write + +jobs: + pypi-publish: + name: Upload fastmcp-slim to PyPI + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Install uv + uses: astral-sh/setup-uv@v7 + + - name: Build fastmcp-slim + run: uv build --package fastmcp-slim + + - name: Publish fastmcp-slim to PyPI + run: uv publish -v dist/fastmcp_slim-*.tar.gz dist/fastmcp_slim-*.whl diff --git a/.github/workflows/publish-fastmcp.yml b/.github/workflows/publish-fastmcp.yml new file mode 100644 index 000000000..ec35db97c --- /dev/null +++ b/.github/workflows/publish-fastmcp.yml @@ -0,0 +1,87 @@ +name: Publish fastmcp to PyPI + +on: + workflow_run: + workflows: ["Publish fastmcp-slim to PyPI"] + types: [completed] + workflow_dispatch: + +permissions: + contents: read + id-token: write + +jobs: + pypi-publish: + name: Upload fastmcp to PyPI + runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'release') + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + ref: ${{ github.event.workflow_run.head_sha || github.sha }} + + - name: Install uv + uses: astral-sh/setup-uv@v7 + + - name: Build fastmcp + run: uv build --package fastmcp + + - name: Verify matching fastmcp-slim is published + run: | + SLIM_VERSION=$(python - <<'PY' + import email.parser + import re + import zipfile + from pathlib import Path + + wheel = next(Path("dist").glob("fastmcp-*.whl")) + metadata_name = next( + name for name in zipfile.ZipFile(wheel).namelist() + if name.endswith(".dist-info/METADATA") + ) + metadata = email.parser.Parser().parsestr( + zipfile.ZipFile(wheel).read(metadata_name).decode() + ) + for value in metadata.get_all("Requires-Dist", []): + requirement, _, marker = value.partition(";") + if marker.strip(): + continue + match = re.fullmatch( + r"fastmcp-slim(?:\[[^\]]+\])?==([^;\s]+)", + requirement.strip(), + ) + if match: + print(match.group(1)) + break + else: + raise RuntimeError("Could not find the base fastmcp-slim dependency") + PY + ) + + for attempt in {1..12}; do + if python - "$SLIM_VERSION" <<'PY' + import json + import sys + import urllib.request + + version = sys.argv[1] + url = f"https://pypi.org/pypi/fastmcp-slim/{version}/json" + with urllib.request.urlopen(url, timeout=30) as response: + json.load(response) + PY + then + exit 0 + fi + + echo "fastmcp-slim ${SLIM_VERSION} is not available on PyPI yet; retrying (${attempt}/12)." + sleep 10 + done + + echo "fastmcp-slim ${SLIM_VERSION} is not available on PyPI; refusing to publish fastmcp." >&2 + exit 1 + + - name: Publish fastmcp to PyPI + run: uv publish -v dist/fastmcp-*.tar.gz dist/fastmcp-*.whl diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 5f2fe8d53..000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Publish FastMCP to PyPI -on: - release: - types: [published] - workflow_dispatch: - -jobs: - pypi-publish: - name: Upload to PyPI - runs-on: ubuntu-latest - permissions: - id-token: write # For PyPI's trusted publishing - steps: - - name: Checkout - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: "Install uv" - uses: astral-sh/setup-uv@v7 - - - name: Build - run: uv build - - - name: Publish to PyPi - run: uv publish -v dist/* diff --git a/.github/workflows/run-schema-crash-test.yml b/.github/workflows/run-schema-crash-test.yml index a57a46b69..2adb9ff83 100644 --- a/.github/workflows/run-schema-crash-test.yml +++ b/.github/workflows/run-schema-crash-test.yml @@ -4,21 +4,21 @@ on: push: branches: ["main"] paths: - - "src/fastmcp/utilities/json_schema_type.py" - - "src/fastmcp/utilities/json_schema.py" - - "src/fastmcp/utilities/openapi/**" - - "src/fastmcp/server/providers/openapi/**" - - "src/fastmcp/client/mixins/tools.py" + - "fastmcp_slim/fastmcp/utilities/json_schema_type.py" + - "fastmcp_slim/fastmcp/utilities/json_schema.py" + - "fastmcp_slim/fastmcp/utilities/openapi/**" + - "fastmcp_slim/fastmcp/server/providers/openapi/**" + - "fastmcp_slim/fastmcp/client/mixins/tools.py" - "tests/utilities/json_schema_type/test_real_world_schemas.py" - ".github/workflows/run-schema-crash-test.yml" pull_request: paths: - - "src/fastmcp/utilities/json_schema_type.py" - - "src/fastmcp/utilities/json_schema.py" - - "src/fastmcp/utilities/openapi/**" - - "src/fastmcp/server/providers/openapi/**" - - "src/fastmcp/client/mixins/tools.py" + - "fastmcp_slim/fastmcp/utilities/json_schema_type.py" + - "fastmcp_slim/fastmcp/utilities/json_schema.py" + - "fastmcp_slim/fastmcp/utilities/openapi/**" + - "fastmcp_slim/fastmcp/server/providers/openapi/**" + - "fastmcp_slim/fastmcp/client/mixins/tools.py" - "tests/utilities/json_schema_type/test_real_world_schemas.py" - ".github/workflows/run-schema-crash-test.yml" diff --git a/.github/workflows/run-static.yml b/.github/workflows/run-static.yml index 01976291a..e6cd8a2c2 100644 --- a/.github/workflows/run-static.yml +++ b/.github/workflows/run-static.yml @@ -7,10 +7,10 @@ on: push: branches: ["main"] paths: - - "src/**" + - "fastmcp_slim/**" - "tests/**" - - "uv.lock" - "pyproject.toml" + - "uv.lock" - ".github/workflows/**" # run on all pull requests because these checks are required and will block merges otherwise diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index dbac1d9c2..c2f77cc18 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -7,10 +7,10 @@ on: push: branches: ["main"] paths: - - "src/**" + - "fastmcp_slim/**" - "tests/**" - - "uv.lock" - "pyproject.toml" + - "uv.lock" - ".github/workflows/**" # run on all pull requests because these checks are required and will block merges otherwise @@ -117,3 +117,102 @@ jobs: FASTMCP_GITHUB_TOKEN: ${{ secrets.FASTMCP_GITHUB_TOKEN }} FASTMCP_TEST_AUTH_GITHUB_CLIENT_ID: ${{ secrets.FASTMCP_TEST_AUTH_GITHUB_CLIENT_ID }} FASTMCP_TEST_AUTH_GITHUB_CLIENT_SECRET: ${{ secrets.FASTMCP_TEST_AUTH_GITHUB_CLIENT_SECRET }} + + package_install_smoke: + name: "Package install smoke" + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v6 + + - name: Setup uv + uses: ./.github/actions/setup-uv + with: + resolution: locked + + - name: Build package wheels + run: uv build --all-packages --wheel --out-dir /tmp/fastmcp-dist + + - name: Install bare slim wheel + run: | + uv venv /tmp/fastmcp-slim-bare-smoke + SLIM_WHEEL=$(ls /tmp/fastmcp-dist/fastmcp_slim-*.whl) + uv pip install --python /tmp/fastmcp-slim-bare-smoke/bin/python "$SLIM_WHEEL" + /tmp/fastmcp-slim-bare-smoke/bin/python - <<'PY' + from importlib.metadata import entry_points + + import fastmcp + import fastmcp.settings + + assert not any(ep.name == "fastmcp" for ep in entry_points(group="console_scripts")) + + try: + fastmcp.FastMCP + except ImportError as exc: + assert "fastmcp-slim[server]" in str(exc) + else: + raise AssertionError("bare fastmcp-slim unexpectedly imported FastMCP") + PY + + - name: Install client slim wheel + run: | + uv venv /tmp/fastmcp-slim-client-smoke + SLIM_WHEEL=$(ls /tmp/fastmcp-dist/fastmcp_slim-*.whl) + uv pip install --python /tmp/fastmcp-slim-client-smoke/bin/python "${SLIM_WHEEL}[client]" + /tmp/fastmcp-slim-client-smoke/bin/python - <<'PY' + from importlib.metadata import entry_points + + from fastmcp import Client + from fastmcp.client.transports import StdioTransport, StreamableHttpTransport + from fastmcp.mcp_config import MCPConfig + + assert not any(ep.name == "fastmcp" for ep in entry_points(group="console_scripts")) + + assert Client("https://example.com/mcp") + assert StreamableHttpTransport("https://example.com/mcp") + assert StdioTransport(command="uvx", args=["demo"]) + assert MCPConfig.from_dict({"mcpServers": {"demo": {"url": "https://example.com/mcp"}}}) + + try: + from fastmcp import FastMCP + except ImportError as exc: + assert "fastmcp-slim[server]" in str(exc) + else: + raise AssertionError(f"client-only slim unexpectedly imported {FastMCP!r}") + PY + + - name: Install server slim wheel + run: | + uv venv /tmp/fastmcp-slim-server-smoke + SLIM_WHEEL=$(ls /tmp/fastmcp-dist/fastmcp_slim-*.whl) + uv pip install --python /tmp/fastmcp-slim-server-smoke/bin/python "${SLIM_WHEEL}[server]" + /tmp/fastmcp-slim-server-smoke/bin/python - <<'PY' + from fastmcp import FastMCP + + mcp = FastMCP("smoke") + assert mcp.name == "smoke" + PY + + - name: Install full package from matching local wheels + run: | + uv venv /tmp/fastmcp-full-smoke + FULL_WHEEL=$(ls /tmp/fastmcp-dist/fastmcp-*.whl) + uv pip install --python /tmp/fastmcp-full-smoke/bin/python --find-links /tmp/fastmcp-dist "$FULL_WHEEL" + /tmp/fastmcp-full-smoke/bin/python - <<'PY' + from importlib.metadata import entry_points + + from fastmcp import Client, FastMCP + from fastmcp.client.client import CallToolResult + from fastmcp.exceptions import ToolError + + assert any( + ep.name == "fastmcp" and ep.value == "fastmcp.cli:app" + for ep in entry_points(group="console_scripts") + ) + + assert Client("https://example.com/mcp") + assert FastMCP("smoke").name == "smoke" + assert CallToolResult is not None + assert ToolError is not None + PY diff --git a/.github/workflows/run-upgrade-checks.yml b/.github/workflows/run-upgrade-checks.yml index c94720ba7..582be2b6f 100644 --- a/.github/workflows/run-upgrade-checks.yml +++ b/.github/workflows/run-upgrade-checks.yml @@ -7,10 +7,10 @@ on: push: branches: ["main"] paths: - - "src/**" + - "fastmcp_slim/**" - "tests/**" - - "uv.lock" - "pyproject.toml" + - "uv.lock" - ".github/workflows/**" schedule: diff --git a/.github/workflows/update-config-schema.yml b/.github/workflows/update-config-schema.yml index 128f660d1..78898be3f 100644 --- a/.github/workflows/update-config-schema.yml +++ b/.github/workflows/update-config-schema.yml @@ -7,8 +7,8 @@ on: push: branches: ["main"] paths: - - "src/fastmcp/utilities/mcp_server_config/**" - - "!src/fastmcp/utilities/mcp_server_config/v1/schema.json" + - "fastmcp_slim/fastmcp/utilities/mcp_server_config/**" + - "!fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/schema.json" workflow_dispatch: permissions: @@ -47,7 +47,7 @@ jobs: from fastmcp.utilities.mcp_server_config import generate_schema generate_schema('docs/public/schemas/fastmcp.json/latest.json') generate_schema('docs/public/schemas/fastmcp.json/v1.json') - generate_schema('src/fastmcp/utilities/mcp_server_config/v1/schema.json') + generate_schema('fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/schema.json') " - name: Create Pull Request @@ -59,7 +59,7 @@ jobs: body: | This PR updates the fastmcp.json schema files to match the current source code. - The schema is automatically generated from `src/fastmcp/utilities/mcp_server_config/` to ensure consistency. + The schema is automatically generated from `fastmcp_slim/fastmcp/utilities/mcp_server_config/` to ensure consistency. **Note:** This PR is fully automated and will update itself with any subsequent changes to the schema, or close automatically if the schema becomes up-to-date through other means. diff --git a/.github/workflows/update-sdk-docs.yml b/.github/workflows/update-sdk-docs.yml index c8fd96287..373c7dc24 100644 --- a/.github/workflows/update-sdk-docs.yml +++ b/.github/workflows/update-sdk-docs.yml @@ -7,7 +7,7 @@ on: push: branches: ["main"] paths: - - "src/**" + - "fastmcp_slim/**" - "pyproject.toml" workflow_dispatch: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dd3574432..2209f8d6e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,7 @@ repos: entry: uv run --isolated ty check language: system types: [python] - files: ^src/|^tests/ + files: ^fastmcp_slim/|^tests/ pass_filenames: false require_serial: true diff --git a/CLAUDE.md b/CLAUDE.md index db34995f5..58f33c5c2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,7 +27,7 @@ uv run prek run --all-files # Ruff + Prettier + ty | Path | Purpose | | ----------------- | -------------------------------------- | -| `src/fastmcp/` | Library source code | +| `fastmcp_slim/fastmcp/` | Library source code | | `├─server/` | Server implementation | | `│ ├─auth/` | Authentication providers | | `│ └─middleware/` | Error handling, logging, rate limiting | @@ -50,7 +50,7 @@ When modifying MCP functionality, changes typically need to be applied across al - **Resource Templates** (`src/resources/`) - **Prompts** (`src/prompts/`) -**Before writing cross-component logic (dedupe, grouping, lookups, identity checks), read `FastMCPComponent` in `src/fastmcp/utilities/components.py`.** The base class defines the shared surface — `name`, `version`, `tags`, `meta`, and critically the `key` property which is the canonical MCP identity (encodes type, identifier, and version). Prefer `item.key` over ad-hoc `name or uri or uri_template` fallbacks; overrides in `Resource` and `ResourceTemplate` already handle URI-based identity, and `.key` includes the version suffix so variants of the same component don't falsely collide. +**Before writing cross-component logic (dedupe, grouping, lookups, identity checks), read `FastMCPComponent` in `fastmcp_slim/fastmcp/utilities/components.py`.** The base class defines the shared surface — `name`, `version`, `tags`, `meta`, and critically the `key` property which is the canonical MCP identity (encodes type, identifier, and version). Prefer `item.key` over ad-hoc `name or uri or uri_template` fallbacks; overrides in `Resource` and `ResourceTemplate` already handle URI-based identity, and `.key` includes the version suffix so variants of the same component don't falsely collide. ## Development Rules @@ -147,9 +147,9 @@ gh api -X POST repos/PrefectHQ/fastmcp/releases/generate-notes \ - Uses Mintlify framework - Files must be in docs.json to be included - Do not manually modify `docs/python-sdk/**` — these files are auto-generated from source code by a bot and maintained via a long-lived PR. Do not include changes to these files in contributor PRs. -- Do not manually modify `docs/public/schemas/**` or `src/fastmcp/utilities/mcp_server_config/v1/schema.json` — these are auto-generated and maintained via a long-lived PR. +- Do not manually modify `docs/public/schemas/**` or `fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/schema.json` — these are auto-generated and maintained via a long-lived PR. - **Core Principle:** A feature doesn't exist unless it is documented! -- When adding or modifying settings in `src/fastmcp/settings.py`, update `docs/more/settings.mdx` to match. +- When adding or modifying settings in `fastmcp_slim/fastmcp/settings.py`, update `docs/more/settings.mdx` to match. ### Documentation Guidelines diff --git a/docs/clients/client-only-package.mdx b/docs/clients/client-only-package.mdx new file mode 100644 index 000000000..fd0ca5010 --- /dev/null +++ b/docs/clients/client-only-package.mdx @@ -0,0 +1,89 @@ +--- +title: Client-Only Package +description: Use FastMCP's client without installing the full server framework. +icon: package +--- + +import { VersionBadge } from '/snippets/version-badge.mdx' + + + +FastMCP's full `fastmcp` package includes everything needed to build and run MCP servers, apps, proxies, and clients. If you are only embedding an MCP client in another framework, building your own LLM host, or testing MCP servers, you can install the smaller client-only package instead. + +```bash +pip install "fastmcp-slim[client]" +``` + +The client-only package uses the `fastmcp` import namespace: + +```python +from fastmcp import Client + +client = Client("https://example.com/mcp") +``` + +Use `fastmcp-slim[client]` when your code connects to MCP servers but does not define or run FastMCP servers itself. For example, framework authors can depend on `fastmcp-slim[client]` to provide MCP connectivity without requiring users to install the full FastMCP server stack. + +## Supported Usage + +Client-only installs support remote and subprocess transports: + +```python +from fastmcp import Client + +# Remote MCP server +http_client = Client("https://example.com/mcp") + +# Local MCP server over stdio +stdio_client = Client("my_server.py") +``` + +Single-server MCP configuration works as well: + +```python +from fastmcp import Client + +config = { + "mcpServers": { + "weather": { + "url": "https://weather.example.com/mcp" + } + } +} + +client = Client(config) +``` + +Optional sampling handlers are available through the same extras as the full package: + +```bash +pip install "fastmcp-slim[client,openai]" +pip install "fastmcp-slim[client,anthropic]" +pip install "fastmcp-slim[client,gemini]" +``` + +## When to Use the Full Package + +Install `fastmcp` when you need server-side FastMCP features: + +```bash +pip install fastmcp +``` + +The full package remains the default for most users and continues to support the existing import style: + +```python +from fastmcp import Client, FastMCP + +server = FastMCP("Example") +client = Client(server) +``` + +Use the full package for: + +- defining or running FastMCP servers +- in-memory clients connected directly to `FastMCP` server objects +- multi-server MCP configurations +- FastMCP apps, proxies, server auth, middleware, and other server-side features + +The `fastmcp-slim` package is intentionally narrower: it is for client-only consumers who want FastMCP's MCP client behavior without depending on the full framework. diff --git a/docs/clients/sampling.mdx b/docs/clients/sampling.mdx index 1c7f37d1d..6b845c3bb 100644 --- a/docs/clients/sampling.mdx +++ b/docs/clients/sampling.mdx @@ -186,5 +186,5 @@ client = Client( Tool execution happens on the server side. The client's role is to pass tools to the LLM and return the LLM's response (which may include tool use requests). The server then executes the tools and may send follow-up sampling requests with tool results. -To implement a custom sampling handler, see the [handler source code](https://github.com/PrefectHQ/fastmcp/tree/main/src/fastmcp/client/sampling/handlers) as a reference. +To implement a custom sampling handler, see the [handler source code](https://github.com/PrefectHQ/fastmcp/tree/main/fastmcp_slim/fastmcp/client/sampling/handlers) as a reference. diff --git a/docs/development/tests.mdx b/docs/development/tests.mdx index 6a9973fe8..4653368be 100644 --- a/docs/development/tests.mdx +++ b/docs/development/tests.mdx @@ -33,7 +33,7 @@ Tests should complete in under 1 second unless marked as integration tests. This ### Test Organization -Our test organization mirrors the `src/` directory structure, creating a predictable mapping between code and tests. When you're working on `src/fastmcp/server/auth.py`, you'll find its tests in `tests/server/test_auth.py`. In rare cases tests are split further - for example, the OpenAPI tests are so comprehensive they're split across multiple files. +Our test organization mirrors the source package structure, creating a predictable mapping between code and tests. When you're working on `fastmcp_slim/fastmcp/server/auth.py`, you'll find its tests in `tests/server/test_auth.py`. In rare cases tests are split further - for example, the OpenAPI tests are so comprehensive they're split across multiple files. ### Test Markers @@ -393,4 +393,4 @@ just docs mintlify dev ``` -The local server watches for changes and automatically refreshes. This preview catches formatting issues and helps you see documentation as users will experience it. \ No newline at end of file +The local server watches for changes and automatically refreshes. This preview catches formatting issues and helps you see documentation as users will experience it. diff --git a/docs/development/v3-notes/v3-features.mdx b/docs/development/v3-notes/v3-features.mdx index 476349a01..3d656248a 100644 --- a/docs/development/v3-notes/v3-features.mdx +++ b/docs/development/v3-notes/v3-features.mdx @@ -444,7 +444,7 @@ async def dashboard(ctx: Context) -> dict: **Future phases** will add a component DSL for building UIs declaratively, an in-repo renderer, and a `FastMCPApp` class. -Implementation: `src/fastmcp/server/apps.py` (models and constants), with integration points in `server.py` (decorator parameters), `low_level.py` (extension advertisement), and `context.py` (`client_supports_extension` method). +Implementation: `fastmcp_slim/fastmcp/server/apps.py` (models and constants), with integration points in `server.py` (decorator parameters), `low_level.py` (extension advertisement), and `context.py` (`client_supports_extension` method). --- @@ -454,7 +454,7 @@ Implementation: `src/fastmcp/server/apps.py` (models and constants), with integr v3.0 introduces a provider-based component system that replaces v2's static-only registration ([#2622](https://github.com/PrefectHQ/fastmcp/pull/2622)). Providers dynamically source tools, resources, templates, and prompts at runtime. -**Core abstraction** (`src/fastmcp/server/providers/base.py`): +**Core abstraction** (`fastmcp_slim/fastmcp/server/providers/base.py`): ```python class Provider: async def list_tools(self) -> Sequence[Tool]: ... @@ -474,7 +474,7 @@ Providers support: ### LocalProvider -`LocalProvider` (`src/fastmcp/server/providers/local_provider.py`) manages components registered via decorators. Can be used standalone and attached to multiple servers: +`LocalProvider` (`fastmcp_slim/fastmcp/server/providers/local_provider.py`) manages components registered via decorators. Can be used standalone and attached to multiple servers: ```python from fastmcp.server.providers import LocalProvider @@ -492,7 +492,7 @@ server2 = FastMCP("Server2", providers=[provider]) ### ProxyProvider -`ProxyProvider` (`src/fastmcp/server/providers/proxy.py`) proxies components from remote MCP servers via a client factory. Used by `create_proxy()` and `FastMCP.mount()` for remote server integration. +`ProxyProvider` (`fastmcp_slim/fastmcp/server/providers/proxy.py`) proxies components from remote MCP servers via a client factory. Used by `create_proxy()` and `FastMCP.mount()` for remote server integration. ```python from fastmcp.server import create_proxy @@ -503,7 +503,7 @@ server = create_proxy("http://remote-server/mcp") ### OpenAPIProvider -`OpenAPIProvider` (`src/fastmcp/server/providers/openapi/provider.py`) creates MCP components from OpenAPI specifications. Routes map HTTP operations to tools, resources, or templates based on configurable rules. +`OpenAPIProvider` (`fastmcp_slim/fastmcp/server/providers/openapi/provider.py`) creates MCP components from OpenAPI specifications. Routes map HTTP operations to tools, resources, or templates based on configurable rules. ```python from fastmcp.server.providers.openapi import OpenAPIProvider @@ -523,7 +523,7 @@ Features: ### FastMCPProvider -`FastMCPProvider` (`src/fastmcp/server/providers/fastmcp_provider.py`) wraps a FastMCP server to enable mounting one server onto another. Components delegate execution through the wrapped server's middleware chain. +`FastMCPProvider` (`fastmcp_slim/fastmcp/server/providers/fastmcp_provider.py`) wraps a FastMCP server to enable mounting one server onto another. Components delegate execution through the wrapped server's middleware chain. ```python from fastmcp import FastMCP @@ -548,7 +548,7 @@ main.add_provider(provider) Transforms modify components (tools, resources, prompts) as they flow from providers to clients ([#2836](https://github.com/PrefectHQ/fastmcp/pull/2836)). They use a middleware pattern where each transform receives a `call_next` callable to continue the chain. -**Built-in transforms** (`src/fastmcp/server/transforms/`): +**Built-in transforms** (`fastmcp_slim/fastmcp/server/transforms/`): - `Namespace` - adds prefixes to names (`tool` → `api_tool`) and path segments to URIs (`data://x` → `data://api/x`) - `ToolTransform` - modifies tool schemas (rename, description, tags, argument transforms) @@ -873,7 +873,7 @@ v3.0 introduces type-safe result classes that provide explicit control over comp #### ToolResult -`ToolResult` (`src/fastmcp/tools/tool.py:79`) provides structured tool responses: +`ToolResult` (`fastmcp_slim/fastmcp/tools/tool.py:79`) provides structured tool responses: ```python from fastmcp.tools import ToolResult @@ -894,7 +894,7 @@ Fields: #### ResourceResult -`ResourceResult` (`src/fastmcp/resources/resource.py:117`) provides structured resource responses: +`ResourceResult` (`fastmcp_slim/fastmcp/resources/resource.py:117`) provides structured resource responses: ```python from fastmcp.resources import ResourceResult, ResourceContent @@ -914,7 +914,7 @@ Accepts strings, bytes, or `list[ResourceContent]` for flexible content handling #### PromptResult -`PromptResult` (`src/fastmcp/prompts/prompt.py:109`) provides structured prompt responses: +`PromptResult` (`fastmcp_slim/fastmcp/prompts/prompt.py:109`) provides structured prompt responses: ```python from fastmcp.prompts import PromptResult, Message @@ -936,7 +936,7 @@ def conversation() -> PromptResult: v3.0 implements MCP SEP-1686 for background task execution via Docket integration. -**Configuration** (`src/fastmcp/server/tasks/config.py`): +**Configuration** (`fastmcp_slim/fastmcp/server/tasks/config.py`): ```python from fastmcp.server.tasks import TaskConfig @@ -1012,7 +1012,7 @@ fastmcp run server.py --reload --reload-dir ./src --reload-dir ./lib fastmcp run server.py --reload --transport http --port 8080 ``` -Implementation (`src/fastmcp/cli/run.py`): +Implementation (`fastmcp_slim/fastmcp/cli/run.py`): - Uses `watchfiles` for efficient file monitoring - Runs server as subprocess for clean restarts - Stateless mode for seamless reconnection after restart diff --git a/docs/docs.json b/docs/docs.json index 924d0d6f6..d4a131679 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -235,6 +235,7 @@ "group": "Clients", "pages": [ "clients/client", + "clients/client-only-package", "clients/transports", { "collapsed": true, diff --git a/docs/patterns/contrib.mdx b/docs/patterns/contrib.mdx index da757662e..04ef45aff 100644 --- a/docs/patterns/contrib.mdx +++ b/docs/patterns/contrib.mdx @@ -12,7 +12,7 @@ FastMCP includes a `contrib` package that holds community-contributed modules. T Contrib modules provide additional features, integrations, or patterns that complement the core FastMCP library. They offer a way for the community to share useful extensions while keeping the core library focused and maintainable. -The available modules can be viewed in the [contrib directory](https://github.com/PrefectHQ/fastmcp/tree/main/src/fastmcp/contrib). +The available modules can be viewed in the [contrib directory](https://github.com/PrefectHQ/fastmcp/tree/main/fastmcp_slim/fastmcp/contrib). ## Usage @@ -32,7 +32,7 @@ from fastmcp.contrib import my_module We welcome contributions to the `contrib` package! If you have a module that extends FastMCP in a useful way, consider contributing it: -1. Create a new directory in `src/fastmcp/contrib/` for your module +1. Create a new directory in `fastmcp_slim/fastmcp/contrib/` for your module 3. Add proper tests for your module in `tests/contrib/` 2. Include comprehensive documentation in a README.md file, including usage and examples, as well as any additional dependencies or installation instructions 5. Submit a pull request diff --git a/docs/v2/clients/sampling.mdx b/docs/v2/clients/sampling.mdx index 1bfea5b18..a709b1761 100644 --- a/docs/v2/clients/sampling.mdx +++ b/docs/v2/clients/sampling.mdx @@ -254,5 +254,5 @@ Install the Anthropic handler with `pip install fastmcp[anthropic]`. Tool execution happens on the server side. The client's role is to pass tools to the LLM and return the LLM's response (which may include tool use requests). The server then executes the tools and may send follow-up sampling requests with tool results. -To implement a custom sampling handler, see the [handler source code](https://github.com/PrefectHQ/fastmcp/tree/main/src/fastmcp/client/sampling/handlers) as a reference. +To implement a custom sampling handler, see the [handler source code](https://github.com/PrefectHQ/fastmcp/tree/main/fastmcp_slim/fastmcp/client/sampling/handlers) as a reference. \ No newline at end of file diff --git a/docs/v2/development/tests.mdx b/docs/v2/development/tests.mdx index 6a9973fe8..4653368be 100644 --- a/docs/v2/development/tests.mdx +++ b/docs/v2/development/tests.mdx @@ -33,7 +33,7 @@ Tests should complete in under 1 second unless marked as integration tests. This ### Test Organization -Our test organization mirrors the `src/` directory structure, creating a predictable mapping between code and tests. When you're working on `src/fastmcp/server/auth.py`, you'll find its tests in `tests/server/test_auth.py`. In rare cases tests are split further - for example, the OpenAPI tests are so comprehensive they're split across multiple files. +Our test organization mirrors the source package structure, creating a predictable mapping between code and tests. When you're working on `fastmcp_slim/fastmcp/server/auth.py`, you'll find its tests in `tests/server/test_auth.py`. In rare cases tests are split further - for example, the OpenAPI tests are so comprehensive they're split across multiple files. ### Test Markers @@ -393,4 +393,4 @@ just docs mintlify dev ``` -The local server watches for changes and automatically refreshes. This preview catches formatting issues and helps you see documentation as users will experience it. \ No newline at end of file +The local server watches for changes and automatically refreshes. This preview catches formatting issues and helps you see documentation as users will experience it. diff --git a/docs/v2/patterns/contrib.mdx b/docs/v2/patterns/contrib.mdx index da757662e..04ef45aff 100644 --- a/docs/v2/patterns/contrib.mdx +++ b/docs/v2/patterns/contrib.mdx @@ -12,7 +12,7 @@ FastMCP includes a `contrib` package that holds community-contributed modules. T Contrib modules provide additional features, integrations, or patterns that complement the core FastMCP library. They offer a way for the community to share useful extensions while keeping the core library focused and maintainable. -The available modules can be viewed in the [contrib directory](https://github.com/PrefectHQ/fastmcp/tree/main/src/fastmcp/contrib). +The available modules can be viewed in the [contrib directory](https://github.com/PrefectHQ/fastmcp/tree/main/fastmcp_slim/fastmcp/contrib). ## Usage @@ -32,7 +32,7 @@ from fastmcp.contrib import my_module We welcome contributions to the `contrib` package! If you have a module that extends FastMCP in a useful way, consider contributing it: -1. Create a new directory in `src/fastmcp/contrib/` for your module +1. Create a new directory in `fastmcp_slim/fastmcp/contrib/` for your module 3. Add proper tests for your module in `tests/contrib/` 2. Include comprehensive documentation in a README.md file, including usage and examples, as well as any additional dependencies or installation instructions 5. Submit a pull request diff --git a/fastmcp_slim/README.md b/fastmcp_slim/README.md new file mode 100644 index 000000000..9afc7f4f7 --- /dev/null +++ b/fastmcp_slim/README.md @@ -0,0 +1,120 @@ +
+ + + + + + + FastMCP Logo + + +# FastMCP 🚀 + +Move fast and make things. + +*Made with 💙 by [Prefect](https://www.prefect.io/)* + +[![Docs](https://img.shields.io/badge/docs-gofastmcp.com-blue)](https://gofastmcp.com) +[![Discord](https://img.shields.io/badge/community-discord-5865F2?logo=discord&logoColor=white)](https://discord.gg/uu8dJCgttd) +[![PyPI - Version](https://img.shields.io/pypi/v/fastmcp.svg)](https://pypi.org/project/fastmcp) +[![Tests](https://github.com/PrefectHQ/fastmcp/actions/workflows/run-tests.yml/badge.svg)](https://github.com/PrefectHQ/fastmcp/actions/workflows/run-tests.yml) +[![License](https://img.shields.io/github/license/PrefectHQ/fastmcp.svg)](https://github.com/PrefectHQ/fastmcp/blob/main/LICENSE) + +prefecthq%2Ffastmcp | Trendshift +
+ +--- + +The [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) connects LLMs to tools and data. FastMCP gives you everything you need to go from prototype to production: + +```python +from fastmcp import FastMCP + +mcp = FastMCP("Demo 🚀") + +@mcp.tool +def add(a: int, b: int) -> int: + """Add two numbers""" + return a + b + +if __name__ == "__main__": + mcp.run() +``` + +## Why FastMCP + +Building an effective MCP application is harder than it looks. FastMCP handles all of it. Declare a tool with a Python function, and the schema, validation, and documentation are generated automatically. Connect to a server with a URL, and transport negotiation, authentication, and protocol lifecycle are managed for you. You focus on your logic, and the MCP part just works: **with FastMCP, best practices are built in.** + +**That's why FastMCP is the standard framework for working with MCP.** FastMCP 1.0 was incorporated into the official MCP Python SDK in 2024. Today, the actively maintained standalone project is downloaded a million times a day, and some version of FastMCP powers 70% of MCP servers across all languages. + +FastMCP has three pillars: + + + + + + + +
+ +Servers +
Servers +
+
Expose tools, resources, and prompts to LLMs. +
+ +Apps +
Apps +
+
Give your tools interactive UIs rendered directly in the conversation. +
+ +Clients +
Clients +
+
Connect to any MCP server — local or remote, programmatic or CLI. +
+ +**[Servers](https://gofastmcp.com/servers/server)** wrap your Python functions into MCP-compliant tools, resources, and prompts. **[Clients](https://gofastmcp.com/clients/client)** connect to any server with full protocol support. And **[Apps](https://gofastmcp.com/apps/overview)** give your tools interactive UIs rendered directly in the conversation. + +Ready to build? Start with the [installation guide](https://gofastmcp.com/getting-started/installation) or jump straight to the [quickstart](https://gofastmcp.com/getting-started/quickstart). + +## Run FastMCP in production with Horizon + +FastMCP is the standard way to build MCP servers. **[Prefect Horizon](https://www.prefect.io/horizon?utm_source=github&utm_medium=readme&utm_campaign=readme_horizon&utm_content=readme_body)** is the enterprise MCP gateway for running them safely. + +Built by the FastMCP team, Horizon packages the best practices we've learned shipping the world's most popular MCP framework. + +Deploy FastMCP servers from GitHub with branch previews and instant rollback. Create a private registry of every MCP your company uses. Secure access with SSO and tool-level RBAC. Get audit logs, observability, and governance across your MCP stack. Remix approved tools into purpose-built endpoints for teams and agents. + +Start with FastMCP. [Scale with Horizon →](https://www.prefect.io/horizon?utm_source=github&utm_medium=readme&utm_campaign=readme_horizon&utm_content=readme_cta) + +## Installation + +We recommend installing FastMCP with [uv](https://docs.astral.sh/uv/): + +```bash +uv pip install fastmcp +``` + +For full installation instructions, including verification and upgrading, see the [**Installation Guide**](https://gofastmcp.com/getting-started/installation). + +**Upgrading?** We have guides for: +- [Upgrading from FastMCP v2](https://gofastmcp.com/getting-started/upgrading/from-fastmcp-2) +- [Upgrading from the MCP Python SDK](https://gofastmcp.com/getting-started/upgrading/from-mcp-sdk) +- [Upgrading from the low-level SDK](https://gofastmcp.com/getting-started/upgrading/from-low-level-sdk) + +## 📚 Documentation + +FastMCP's complete documentation is available at **[gofastmcp.com](https://gofastmcp.com)**, including detailed guides, API references, and advanced patterns. + +Documentation is also available in [llms.txt format](https://llmstxt.org/), which is a simple markdown standard that LLMs can consume easily: + +- [`llms.txt`](https://gofastmcp.com/llms.txt) is essentially a sitemap, listing all the pages in the documentation. +- [`llms-full.txt`](https://gofastmcp.com/llms-full.txt) contains the entire documentation. Note this may exceed the context window of your LLM. + +**Community:** Join our [Discord server](https://discord.gg/uu8dJCgttd) to connect with other FastMCP developers and share what you're building. + +## Contributing + +We welcome contributions! See the [Contributing Guide](https://gofastmcp.com/development/contributing) for setup instructions, testing requirements, and PR guidelines. diff --git a/fastmcp_slim/fastmcp/__init__.py b/fastmcp_slim/fastmcp/__init__.py new file mode 100644 index 000000000..592d5066e --- /dev/null +++ b/fastmcp_slim/fastmcp/__init__.py @@ -0,0 +1,117 @@ +"""FastMCP - An ergonomic MCP interface.""" + +import importlib +import warnings +from importlib.metadata import PackageNotFoundError, version as _version +from typing import TYPE_CHECKING + +from fastmcp.settings import Settings +from fastmcp.utilities.logging import configure_logging as _configure_logging + +if TYPE_CHECKING: + from fastmcp.client import Client as Client + from fastmcp.apps.app import FastMCPApp as FastMCPApp + from fastmcp.exceptions import ( + FastMCPDeprecationWarning as FastMCPDeprecationWarning, + ) + from fastmcp.server.context import Context as Context + from fastmcp.server.server import FastMCP as FastMCP + +settings = Settings() +if settings.log_enabled: + _configure_logging( + level=settings.log_level, + enable_rich_tracebacks=settings.enable_rich_tracebacks, + ) + +try: + __version__ = _version("fastmcp-slim") +except PackageNotFoundError: + __version__ = _version("fastmcp") + +if settings.deprecation_warnings: + try: + from fastmcp.exceptions import FastMCPDeprecationWarning + except ImportError: + pass + else: + warnings.simplefilter("default", FastMCPDeprecationWarning) + + +# --- Lazy imports for performance (see #3292) --- +# Client and the client submodule are deferred so that server-only users +# don't pay for the client import chain. Do not convert back to top-level. + + +def __getattr__(name: str) -> object: + if name == "Client": + try: + from fastmcp.client import Client + except ImportError as exc: + raise ImportError( + "FastMCP client support is not installed. Install " + "`fastmcp-slim[client]` or `fastmcp`." + ) from exc + + return Client + if name == "Context": + try: + from fastmcp.server.context import Context + except ImportError as exc: + raise ImportError( + "FastMCP server support is not installed. Install " + "`fastmcp-slim[server]` or `fastmcp`." + ) from exc + + return Context + if name == "FastMCP": + try: + from fastmcp.server.server import FastMCP + except ImportError as exc: + raise ImportError( + "FastMCP server support is not installed. Install " + "`fastmcp-slim[server]` or `fastmcp`." + ) from exc + + return FastMCP + if name == "FastMCPApp": + try: + from fastmcp.apps.app import FastMCPApp + except ImportError as exc: + raise ImportError( + "FastMCP app support is not installed. Install " + "`fastmcp-slim[server,apps]` or `fastmcp[apps]`." + ) from exc + + return FastMCPApp + if name == "FastMCPDeprecationWarning": + from fastmcp.exceptions import FastMCPDeprecationWarning + + return FastMCPDeprecationWarning + if name == "client": + try: + return importlib.import_module("fastmcp.client") + except ImportError as exc: + raise ImportError( + "FastMCP client support is not installed. Install " + "`fastmcp-slim[client]` or `fastmcp`." + ) from exc + if name == "server": + try: + return importlib.import_module("fastmcp.server") + except ImportError as exc: + raise ImportError( + "FastMCP server support is not installed. Install " + "`fastmcp-slim[server]` or `fastmcp`." + ) from exc + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + + +__all__ = [ + "Client", + "Context", + "FastMCP", + "FastMCPApp", + "FastMCPDeprecationWarning", + "settings", +] diff --git a/src/fastmcp/apps/__init__.py b/fastmcp_slim/fastmcp/apps/__init__.py similarity index 100% rename from src/fastmcp/apps/__init__.py rename to fastmcp_slim/fastmcp/apps/__init__.py diff --git a/src/fastmcp/apps/app.py b/fastmcp_slim/fastmcp/apps/app.py similarity index 100% rename from src/fastmcp/apps/app.py rename to fastmcp_slim/fastmcp/apps/app.py diff --git a/src/fastmcp/apps/approval.py b/fastmcp_slim/fastmcp/apps/approval.py similarity index 100% rename from src/fastmcp/apps/approval.py rename to fastmcp_slim/fastmcp/apps/approval.py diff --git a/src/fastmcp/apps/choice.py b/fastmcp_slim/fastmcp/apps/choice.py similarity index 100% rename from src/fastmcp/apps/choice.py rename to fastmcp_slim/fastmcp/apps/choice.py diff --git a/src/fastmcp/apps/config.py b/fastmcp_slim/fastmcp/apps/config.py similarity index 100% rename from src/fastmcp/apps/config.py rename to fastmcp_slim/fastmcp/apps/config.py diff --git a/src/fastmcp/apps/file_upload.py b/fastmcp_slim/fastmcp/apps/file_upload.py similarity index 100% rename from src/fastmcp/apps/file_upload.py rename to fastmcp_slim/fastmcp/apps/file_upload.py diff --git a/src/fastmcp/apps/form.py b/fastmcp_slim/fastmcp/apps/form.py similarity index 100% rename from src/fastmcp/apps/form.py rename to fastmcp_slim/fastmcp/apps/form.py diff --git a/src/fastmcp/apps/generative.py b/fastmcp_slim/fastmcp/apps/generative.py similarity index 100% rename from src/fastmcp/apps/generative.py rename to fastmcp_slim/fastmcp/apps/generative.py diff --git a/src/fastmcp/cli/__init__.py b/fastmcp_slim/fastmcp/cli/__init__.py similarity index 100% rename from src/fastmcp/cli/__init__.py rename to fastmcp_slim/fastmcp/cli/__init__.py diff --git a/src/fastmcp/cli/__main__.py b/fastmcp_slim/fastmcp/cli/__main__.py similarity index 100% rename from src/fastmcp/cli/__main__.py rename to fastmcp_slim/fastmcp/cli/__main__.py diff --git a/src/fastmcp/cli/apps_dev.py b/fastmcp_slim/fastmcp/cli/apps_dev.py similarity index 100% rename from src/fastmcp/cli/apps_dev.py rename to fastmcp_slim/fastmcp/cli/apps_dev.py diff --git a/src/fastmcp/cli/auth.py b/fastmcp_slim/fastmcp/cli/auth.py similarity index 100% rename from src/fastmcp/cli/auth.py rename to fastmcp_slim/fastmcp/cli/auth.py diff --git a/src/fastmcp/cli/cimd.py b/fastmcp_slim/fastmcp/cli/cimd.py similarity index 100% rename from src/fastmcp/cli/cimd.py rename to fastmcp_slim/fastmcp/cli/cimd.py diff --git a/src/fastmcp/cli/cli.py b/fastmcp_slim/fastmcp/cli/cli.py similarity index 100% rename from src/fastmcp/cli/cli.py rename to fastmcp_slim/fastmcp/cli/cli.py diff --git a/src/fastmcp/cli/client.py b/fastmcp_slim/fastmcp/cli/client.py similarity index 100% rename from src/fastmcp/cli/client.py rename to fastmcp_slim/fastmcp/cli/client.py diff --git a/src/fastmcp/cli/discovery.py b/fastmcp_slim/fastmcp/cli/discovery.py similarity index 100% rename from src/fastmcp/cli/discovery.py rename to fastmcp_slim/fastmcp/cli/discovery.py diff --git a/src/fastmcp/cli/generate.py b/fastmcp_slim/fastmcp/cli/generate.py similarity index 100% rename from src/fastmcp/cli/generate.py rename to fastmcp_slim/fastmcp/cli/generate.py diff --git a/src/fastmcp/cli/install/__init__.py b/fastmcp_slim/fastmcp/cli/install/__init__.py similarity index 100% rename from src/fastmcp/cli/install/__init__.py rename to fastmcp_slim/fastmcp/cli/install/__init__.py diff --git a/src/fastmcp/cli/install/claude_code.py b/fastmcp_slim/fastmcp/cli/install/claude_code.py similarity index 100% rename from src/fastmcp/cli/install/claude_code.py rename to fastmcp_slim/fastmcp/cli/install/claude_code.py diff --git a/src/fastmcp/cli/install/claude_desktop.py b/fastmcp_slim/fastmcp/cli/install/claude_desktop.py similarity index 100% rename from src/fastmcp/cli/install/claude_desktop.py rename to fastmcp_slim/fastmcp/cli/install/claude_desktop.py diff --git a/src/fastmcp/cli/install/cursor.py b/fastmcp_slim/fastmcp/cli/install/cursor.py similarity index 100% rename from src/fastmcp/cli/install/cursor.py rename to fastmcp_slim/fastmcp/cli/install/cursor.py diff --git a/src/fastmcp/cli/install/gemini_cli.py b/fastmcp_slim/fastmcp/cli/install/gemini_cli.py similarity index 100% rename from src/fastmcp/cli/install/gemini_cli.py rename to fastmcp_slim/fastmcp/cli/install/gemini_cli.py diff --git a/src/fastmcp/cli/install/goose.py b/fastmcp_slim/fastmcp/cli/install/goose.py similarity index 100% rename from src/fastmcp/cli/install/goose.py rename to fastmcp_slim/fastmcp/cli/install/goose.py diff --git a/src/fastmcp/cli/install/mcp_json.py b/fastmcp_slim/fastmcp/cli/install/mcp_json.py similarity index 100% rename from src/fastmcp/cli/install/mcp_json.py rename to fastmcp_slim/fastmcp/cli/install/mcp_json.py diff --git a/src/fastmcp/cli/install/shared.py b/fastmcp_slim/fastmcp/cli/install/shared.py similarity index 100% rename from src/fastmcp/cli/install/shared.py rename to fastmcp_slim/fastmcp/cli/install/shared.py diff --git a/src/fastmcp/cli/install/stdio.py b/fastmcp_slim/fastmcp/cli/install/stdio.py similarity index 100% rename from src/fastmcp/cli/install/stdio.py rename to fastmcp_slim/fastmcp/cli/install/stdio.py diff --git a/src/fastmcp/cli/run.py b/fastmcp_slim/fastmcp/cli/run.py similarity index 100% rename from src/fastmcp/cli/run.py rename to fastmcp_slim/fastmcp/cli/run.py diff --git a/src/fastmcp/cli/tasks.py b/fastmcp_slim/fastmcp/cli/tasks.py similarity index 100% rename from src/fastmcp/cli/tasks.py rename to fastmcp_slim/fastmcp/cli/tasks.py diff --git a/fastmcp_slim/fastmcp/client/__init__.py b/fastmcp_slim/fastmcp/client/__init__.py new file mode 100644 index 000000000..02e0c1079 --- /dev/null +++ b/fastmcp_slim/fastmcp/client/__init__.py @@ -0,0 +1,36 @@ +try: + from .auth import OAuth, BearerAuth + from .client import Client + from .transports import ( + ClientTransport, + FastMCPTransport, + NodeStdioTransport, + NpxStdioTransport, + PythonStdioTransport, + SSETransport, + StdioTransport, + StreamableHttpTransport, + UvStdioTransport, + UvxStdioTransport, + ) +except ImportError as exc: + raise ImportError( + "FastMCP client support is not installed. Install " + "`fastmcp-slim[client]` or `fastmcp`." + ) from exc + +__all__ = [ + "BearerAuth", + "Client", + "ClientTransport", + "FastMCPTransport", + "NodeStdioTransport", + "NpxStdioTransport", + "OAuth", + "PythonStdioTransport", + "SSETransport", + "StdioTransport", + "StreamableHttpTransport", + "UvStdioTransport", + "UvxStdioTransport", +] diff --git a/src/fastmcp/client/auth/__init__.py b/fastmcp_slim/fastmcp/client/auth/__init__.py similarity index 100% rename from src/fastmcp/client/auth/__init__.py rename to fastmcp_slim/fastmcp/client/auth/__init__.py diff --git a/src/fastmcp/client/auth/bearer.py b/fastmcp_slim/fastmcp/client/auth/bearer.py similarity index 100% rename from src/fastmcp/client/auth/bearer.py rename to fastmcp_slim/fastmcp/client/auth/bearer.py diff --git a/src/fastmcp/client/auth/oauth.py b/fastmcp_slim/fastmcp/client/auth/oauth.py similarity index 100% rename from src/fastmcp/client/auth/oauth.py rename to fastmcp_slim/fastmcp/client/auth/oauth.py diff --git a/src/fastmcp/client/client.py b/fastmcp_slim/fastmcp/client/client.py similarity index 99% rename from src/fastmcp/client/client.py rename to fastmcp_slim/fastmcp/client/client.py index 80c9bfbeb..f2a70924d 100644 --- a/src/fastmcp/client/client.py +++ b/fastmcp_slim/fastmcp/client/client.py @@ -10,7 +10,7 @@ from collections.abc import Coroutine from contextlib import AsyncExitStack, asynccontextmanager, suppress from dataclasses import dataclass, field from pathlib import Path -from typing import Any, Generic, Literal, TypeVar, cast, overload +from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar, cast, overload import anyio import httpx @@ -20,9 +20,12 @@ from mcp import ClientSession, McpError from mcp.types import GetTaskResult, TaskStatusNotification from pydantic import AnyUrl -import fastmcp +import fastmcp as fastmcp from fastmcp.client.auth.oauth import OAuth -from fastmcp.client.elicitation import ElicitationHandler, create_elicitation_callback +from fastmcp.client.elicitation import ( + ElicitationHandler, + create_elicitation_callback, +) from fastmcp.client.logging import ( LogHandler, create_log_callback, @@ -52,7 +55,6 @@ from fastmcp.client.tasks import ( ToolTask, ) from fastmcp.mcp_config import MCPConfig -from fastmcp.server import FastMCP from fastmcp.utilities.exceptions import get_catch_handlers from fastmcp.utilities.logging import get_logger from fastmcp.utilities.timeout import ( @@ -60,6 +62,11 @@ from fastmcp.utilities.timeout import ( normalize_timeout_to_timedelta, ) +if TYPE_CHECKING: + from fastmcp.server import FastMCP +else: + FastMCP = Any + from .transports import ( ClientTransport, ClientTransportT, diff --git a/fastmcp_slim/fastmcp/client/dependencies.py b/fastmcp_slim/fastmcp/client/dependencies.py new file mode 100644 index 000000000..54faaefe3 --- /dev/null +++ b/fastmcp_slim/fastmcp/client/dependencies.py @@ -0,0 +1,20 @@ +"""Client-side dependency helpers.""" + + +def get_http_headers( + include_all: bool = False, + include: set[str] | None = None, +) -> dict[str, str]: + """Return HTTP headers from an ambient server request, when available. + + The standalone client package has no server request context. When the full + FastMCP package is installed, delegate to its request-aware implementation. + """ + try: + from fastmcp.server.dependencies import ( + get_http_headers as get_server_http_headers, + ) + except ImportError: + return {} + + return get_server_http_headers(include_all=include_all, include=include) diff --git a/src/fastmcp/client/elicitation.py b/fastmcp_slim/fastmcp/client/elicitation.py similarity index 100% rename from src/fastmcp/client/elicitation.py rename to fastmcp_slim/fastmcp/client/elicitation.py diff --git a/src/fastmcp/client/logging.py b/fastmcp_slim/fastmcp/client/logging.py similarity index 100% rename from src/fastmcp/client/logging.py rename to fastmcp_slim/fastmcp/client/logging.py diff --git a/src/fastmcp/client/messages.py b/fastmcp_slim/fastmcp/client/messages.py similarity index 100% rename from src/fastmcp/client/messages.py rename to fastmcp_slim/fastmcp/client/messages.py diff --git a/src/fastmcp/client/mixins/__init__.py b/fastmcp_slim/fastmcp/client/mixins/__init__.py similarity index 100% rename from src/fastmcp/client/mixins/__init__.py rename to fastmcp_slim/fastmcp/client/mixins/__init__.py diff --git a/src/fastmcp/client/mixins/prompts.py b/fastmcp_slim/fastmcp/client/mixins/prompts.py similarity index 100% rename from src/fastmcp/client/mixins/prompts.py rename to fastmcp_slim/fastmcp/client/mixins/prompts.py diff --git a/src/fastmcp/client/mixins/resources.py b/fastmcp_slim/fastmcp/client/mixins/resources.py similarity index 100% rename from src/fastmcp/client/mixins/resources.py rename to fastmcp_slim/fastmcp/client/mixins/resources.py diff --git a/src/fastmcp/client/mixins/task_management.py b/fastmcp_slim/fastmcp/client/mixins/task_management.py similarity index 100% rename from src/fastmcp/client/mixins/task_management.py rename to fastmcp_slim/fastmcp/client/mixins/task_management.py diff --git a/src/fastmcp/client/mixins/tools.py b/fastmcp_slim/fastmcp/client/mixins/tools.py similarity index 100% rename from src/fastmcp/client/mixins/tools.py rename to fastmcp_slim/fastmcp/client/mixins/tools.py diff --git a/src/fastmcp/client/oauth_callback.py b/fastmcp_slim/fastmcp/client/oauth_callback.py similarity index 100% rename from src/fastmcp/client/oauth_callback.py rename to fastmcp_slim/fastmcp/client/oauth_callback.py diff --git a/src/fastmcp/client/progress.py b/fastmcp_slim/fastmcp/client/progress.py similarity index 100% rename from src/fastmcp/client/progress.py rename to fastmcp_slim/fastmcp/client/progress.py diff --git a/src/fastmcp/client/roots.py b/fastmcp_slim/fastmcp/client/roots.py similarity index 100% rename from src/fastmcp/client/roots.py rename to fastmcp_slim/fastmcp/client/roots.py diff --git a/src/fastmcp/client/sampling/__init__.py b/fastmcp_slim/fastmcp/client/sampling/__init__.py similarity index 98% rename from src/fastmcp/client/sampling/__init__.py rename to fastmcp_slim/fastmcp/client/sampling/__init__.py index 2987e9259..40f2f7d10 100644 --- a/src/fastmcp/client/sampling/__init__.py +++ b/fastmcp_slim/fastmcp/client/sampling/__init__.py @@ -58,7 +58,7 @@ def create_sampling_callback( if isinstance(result, str): result = CreateMessageResult( role="assistant", - model="fastmcp-client", + model="fastmcp-slim", content=mcp.types.TextContent(type="text", text=result), ) return result diff --git a/src/fastmcp/client/sampling/handlers/__init__.py b/fastmcp_slim/fastmcp/client/sampling/handlers/__init__.py similarity index 100% rename from src/fastmcp/client/sampling/handlers/__init__.py rename to fastmcp_slim/fastmcp/client/sampling/handlers/__init__.py diff --git a/src/fastmcp/client/sampling/handlers/anthropic.py b/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py similarity index 99% rename from src/fastmcp/client/sampling/handlers/anthropic.py rename to fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py index 945da5e2f..b7559ea89 100644 --- a/src/fastmcp/client/sampling/handlers/anthropic.py +++ b/fastmcp_slim/fastmcp/client/sampling/handlers/anthropic.py @@ -41,7 +41,7 @@ try: except ImportError as e: raise ImportError( "The `anthropic` package is not installed. " - "Install it with `pip install fastmcp[anthropic]` or add `anthropic` to your dependencies." + "Install it with `pip install fastmcp-slim[anthropic]` or add `anthropic` to your dependencies." ) from e __all__ = ["AnthropicSamplingHandler"] diff --git a/src/fastmcp/client/sampling/handlers/google_genai.py b/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py similarity index 99% rename from src/fastmcp/client/sampling/handlers/google_genai.py rename to fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py index 7404fb1eb..28301a1b1 100644 --- a/src/fastmcp/client/sampling/handlers/google_genai.py +++ b/fastmcp_slim/fastmcp/client/sampling/handlers/google_genai.py @@ -27,7 +27,7 @@ try: except ImportError as e: raise ImportError( "The `google-genai` package is not installed. " - "Install it with `pip install fastmcp[gemini]` or add `google-genai` " + "Install it with `pip install fastmcp-slim[gemini]` or add `google-genai` " "to your dependencies." ) from e diff --git a/src/fastmcp/client/sampling/handlers/openai.py b/fastmcp_slim/fastmcp/client/sampling/handlers/openai.py similarity index 99% rename from src/fastmcp/client/sampling/handlers/openai.py rename to fastmcp_slim/fastmcp/client/sampling/handlers/openai.py index 455babab9..3ed34a337 100644 --- a/src/fastmcp/client/sampling/handlers/openai.py +++ b/fastmcp_slim/fastmcp/client/sampling/handlers/openai.py @@ -44,7 +44,7 @@ try: except ImportError as e: raise ImportError( "The `openai` package is not installed. " - "Please install `fastmcp[openai]` or add `openai` to your dependencies manually." + "Please install `fastmcp-slim[openai]` or add `openai` to your dependencies manually." ) from e # OpenAI only supports wav and mp3 for input audio diff --git a/src/fastmcp/client/tasks.py b/fastmcp_slim/fastmcp/client/tasks.py similarity index 100% rename from src/fastmcp/client/tasks.py rename to fastmcp_slim/fastmcp/client/tasks.py diff --git a/src/fastmcp/client/telemetry.py b/fastmcp_slim/fastmcp/client/telemetry.py similarity index 100% rename from src/fastmcp/client/telemetry.py rename to fastmcp_slim/fastmcp/client/telemetry.py diff --git a/src/fastmcp/client/transports/__init__.py b/fastmcp_slim/fastmcp/client/transports/__init__.py similarity index 91% rename from src/fastmcp/client/transports/__init__.py rename to fastmcp_slim/fastmcp/client/transports/__init__.py index 010a7cb7c..5e37c55b2 100644 --- a/src/fastmcp/client/transports/__init__.py +++ b/fastmcp_slim/fastmcp/client/transports/__init__.py @@ -1,4 +1,3 @@ -# Re-export all public APIs for backward compatibility from mcp.server.fastmcp import FastMCP as FastMCP1Server from fastmcp.client.transports.base import ( @@ -20,7 +19,6 @@ from fastmcp.client.transports.stdio import ( UvStdioTransport, UvxStdioTransport, ) -from fastmcp.server.server import FastMCP __all__ = [ "ClientTransport", diff --git a/src/fastmcp/client/transports/base.py b/fastmcp_slim/fastmcp/client/transports/base.py similarity index 100% rename from src/fastmcp/client/transports/base.py rename to fastmcp_slim/fastmcp/client/transports/base.py diff --git a/src/fastmcp/client/transports/config.py b/fastmcp_slim/fastmcp/client/transports/config.py similarity index 92% rename from src/fastmcp/client/transports/config.py rename to fastmcp_slim/fastmcp/client/transports/config.py index cd1d59cfa..97208174b 100644 --- a/src/fastmcp/client/transports/config.py +++ b/fastmcp_slim/fastmcp/client/transports/config.py @@ -1,7 +1,7 @@ import contextlib import datetime from collections.abc import AsyncIterator -from typing import Any +from typing import TYPE_CHECKING, Any from mcp import ClientSession from typing_extensions import Unpack @@ -15,10 +15,13 @@ from fastmcp.mcp_config import ( StdioMCPServer, TransformingRemoteMCPServer, TransformingStdioMCPServer, + _coerce_tool_transform_configs, ) -from fastmcp.server.server import FastMCP, create_proxy from fastmcp.utilities.logging import get_logger +if TYPE_CHECKING: + from fastmcp.server.server import FastMCP + logger = get_logger(__name__) @@ -98,6 +101,14 @@ class MCPConfigTransport(ClientTransport): # each ProxyClient so its underlying transport session stays alive for # the duration of this context (fixes session persistence for # streamable-http backends — see #2790). + try: + from fastmcp.server.server import FastMCP + except ImportError as exc: + raise ImportError( + "MCP configs with multiple servers require the full `fastmcp` " + "package for now. Install it with `pip install fastmcp`." + ) from exc + timeout = session_kwargs.get("read_timeout_seconds") composite = FastMCP[Any](name="MCPRouter") @@ -138,7 +149,7 @@ class MCPConfigTransport(ClientTransport): config: MCPServerTypes, timeout: datetime.timedelta | None, stack: contextlib.AsyncExitStack, - ) -> tuple[ClientTransport, Any, FastMCP[Any]]: + ) -> tuple[ClientTransport, Any, "FastMCP[Any]"]: """Create underlying transport, proxy client, and proxy server for a single backend. The ProxyClient is connected via the AsyncExitStack *before* being @@ -149,6 +160,7 @@ class MCPConfigTransport(ClientTransport): """ # Import here to avoid circular dependency from fastmcp.server.providers.proxy import StatefulProxyClient + from fastmcp.server.server import create_proxy tool_transforms = None include_tags = None @@ -194,7 +206,9 @@ class MCPConfigTransport(ClientTransport): if tool_transforms: from fastmcp.server.transforms import ToolTransform - proxy.add_transform(ToolTransform(tool_transforms)) + proxy.add_transform( + ToolTransform(_coerce_tool_transform_configs(tool_transforms)) + ) # Then add enabled filters - they filter based on tags if include_tags: proxy.enable(tags=set(include_tags), only=True) diff --git a/src/fastmcp/client/transports/http.py b/fastmcp_slim/fastmcp/client/transports/http.py similarity index 99% rename from src/fastmcp/client/transports/http.py rename to fastmcp_slim/fastmcp/client/transports/http.py index bfed0fa00..280a93d4a 100644 --- a/src/fastmcp/client/transports/http.py +++ b/fastmcp_slim/fastmcp/client/transports/http.py @@ -15,12 +15,12 @@ from mcp.shared._httpx_utils import McpHttpClientFactory, create_mcp_http_client from pydantic import AnyUrl from typing_extensions import Unpack -import fastmcp +import fastmcp as fastmcp from fastmcp.client.auth.bearer import BearerAuth from fastmcp.client.auth.oauth import OAuth +from fastmcp.client.dependencies import get_http_headers from fastmcp.client.transports.base import ClientTransport, SessionKwargs from fastmcp.exceptions import FastMCPDeprecationWarning -from fastmcp.server.dependencies import get_http_headers from fastmcp.utilities.timeout import normalize_timeout_to_timedelta diff --git a/src/fastmcp/client/transports/inference.py b/fastmcp_slim/fastmcp/client/transports/inference.py similarity index 90% rename from src/fastmcp/client/transports/inference.py rename to fastmcp_slim/fastmcp/client/transports/inference.py index 438995c23..a0bd6bc51 100644 --- a/src/fastmcp/client/transports/inference.py +++ b/fastmcp_slim/fastmcp/client/transports/inference.py @@ -9,13 +9,17 @@ from fastmcp.client.transports.config import MCPConfigTransport from fastmcp.client.transports.http import StreamableHttpTransport from fastmcp.client.transports.memory import FastMCPTransport from fastmcp.client.transports.sse import SSETransport -from fastmcp.client.transports.stdio import NodeStdioTransport, PythonStdioTransport +from fastmcp.client.transports.stdio import ( + NodeStdioTransport, + PythonStdioTransport, +) from fastmcp.mcp_config import MCPConfig, infer_transport_type_from_url -from fastmcp.server.server import FastMCP from fastmcp.utilities.logging import get_logger if TYPE_CHECKING: - pass + from fastmcp.server.server import FastMCP +else: + FastMCP = Any logger = get_logger(__name__) @@ -114,9 +118,9 @@ def infer_transport( return transport # the transport is a FastMCP server (2.x or 1.0) - elif isinstance(transport, FastMCP | FastMCP1Server): + elif _is_fastmcp_server(transport): inferred_transport = FastMCPTransport( - mcp=cast(FastMCP[Any] | FastMCP1Server, transport) + mcp=cast("FastMCP[Any] | FastMCP1Server", transport) ) # the transport is a path to a script @@ -152,3 +156,15 @@ def infer_transport( logger.debug(f"Inferred transport: {inferred_transport}") return inferred_transport + + +def _is_fastmcp_server(transport: object) -> bool: + if isinstance(transport, FastMCP1Server): + return True + + try: + from fastmcp.server.server import FastMCP as FastMCP2Server + except ImportError: + return False + + return isinstance(transport, FastMCP2Server) diff --git a/src/fastmcp/client/transports/memory.py b/fastmcp_slim/fastmcp/client/transports/memory.py similarity index 84% rename from src/fastmcp/client/transports/memory.py rename to fastmcp_slim/fastmcp/client/transports/memory.py index 7b2cbc8e4..d74708029 100644 --- a/src/fastmcp/client/transports/memory.py +++ b/fastmcp_slim/fastmcp/client/transports/memory.py @@ -1,5 +1,7 @@ import contextlib +import importlib from collections.abc import AsyncIterator +from typing import TYPE_CHECKING, Any import anyio from mcp import ClientSession @@ -8,7 +10,9 @@ from mcp.shared.memory import create_client_server_memory_streams from typing_extensions import Unpack from fastmcp.client.transports.base import ClientTransport, SessionKwargs -from fastmcp.server.server import FastMCP + +if TYPE_CHECKING: + from fastmcp.server.server import FastMCP class FastMCPTransport(ClientTransport): @@ -20,7 +24,9 @@ class FastMCPTransport(ClientTransport): tests or scenarios where client and server run in the same runtime. """ - def __init__(self, mcp: FastMCP | FastMCP1Server, raise_exceptions: bool = False): + def __init__( + self, mcp: "FastMCP[Any] | FastMCP1Server", raise_exceptions: bool = False + ): """Initialize a FastMCPTransport from a FastMCP server instance.""" # Accept both FastMCP 2.x and FastMCP 1.0 servers. Both expose a @@ -87,10 +93,22 @@ class FastMCPTransport(ClientTransport): @contextlib.asynccontextmanager async def _enter_server_lifespan( - server: FastMCP | FastMCP1Server, + server: "FastMCP[Any] | FastMCP1Server", ) -> AsyncIterator[None]: """Enters the server's lifespan context for FastMCP servers and does nothing for FastMCP 1 servers.""" - if isinstance(server, FastMCP): + FastMCP2: type[Any] | None + try: + FastMCP2 = importlib.import_module("fastmcp.server.server").FastMCP + except ImportError: + FastMCP2 = None + + if FastMCP2 is None and not isinstance(server, FastMCP1Server): + raise ImportError( + "In-memory FastMCP transports require the full `fastmcp` package. " + "Install it with `pip install fastmcp`." + ) + + if FastMCP2 is not None and isinstance(server, FastMCP2): async with server._lifespan_manager(): yield else: diff --git a/src/fastmcp/client/transports/sse.py b/fastmcp_slim/fastmcp/client/transports/sse.py similarity index 99% rename from src/fastmcp/client/transports/sse.py rename to fastmcp_slim/fastmcp/client/transports/sse.py index 43bdb7c96..8c2d7c167 100644 --- a/src/fastmcp/client/transports/sse.py +++ b/fastmcp_slim/fastmcp/client/transports/sse.py @@ -17,8 +17,8 @@ from typing_extensions import Unpack from fastmcp.client.auth.bearer import BearerAuth from fastmcp.client.auth.oauth import OAuth +from fastmcp.client.dependencies import get_http_headers from fastmcp.client.transports.base import ClientTransport, SessionKwargs -from fastmcp.server.dependencies import get_http_headers from fastmcp.utilities.timeout import normalize_timeout_to_timedelta diff --git a/src/fastmcp/client/transports/stdio.py b/fastmcp_slim/fastmcp/client/transports/stdio.py similarity index 97% rename from src/fastmcp/client/transports/stdio.py rename to fastmcp_slim/fastmcp/client/transports/stdio.py index d772c3a88..9b3bd8dff 100644 --- a/src/fastmcp/client/transports/stdio.py +++ b/fastmcp_slim/fastmcp/client/transports/stdio.py @@ -14,7 +14,6 @@ from typing_extensions import Unpack from fastmcp.client.transports.base import ClientTransport, SessionKwargs from fastmcp.utilities.logging import get_logger -from fastmcp.utilities.mcp_server_config.v1.environments.uv import UVEnvironment logger = get_logger(__name__) @@ -385,20 +384,18 @@ class UvStdioTransport(StdioTransport): f"Project directory not found: {project_directory}" ) - # Create Environment from provided parameters (internal use) - env_config = UVEnvironment( - python=python_version, - dependencies=with_packages, - requirements=with_requirements, - project=project_directory, - editable=None, # Not exposed in this transport - ) - # Build uv arguments using the config uv_args: list[str] = [] # Check if we need any environment setup - if env_config._must_run_with_uv(): + if any( + [ + python_version, + with_packages, + with_requirements, + project_directory, + ] + ): # Use the config to build args, but we need to handle the command differently # since transport has specific needs uv_args = ["run"] diff --git a/src/fastmcp/contrib/README.md b/fastmcp_slim/fastmcp/contrib/README.md similarity index 100% rename from src/fastmcp/contrib/README.md rename to fastmcp_slim/fastmcp/contrib/README.md diff --git a/src/fastmcp/contrib/bulk_tool_caller/README.md b/fastmcp_slim/fastmcp/contrib/bulk_tool_caller/README.md similarity index 100% rename from src/fastmcp/contrib/bulk_tool_caller/README.md rename to fastmcp_slim/fastmcp/contrib/bulk_tool_caller/README.md diff --git a/src/fastmcp/contrib/bulk_tool_caller/__init__.py b/fastmcp_slim/fastmcp/contrib/bulk_tool_caller/__init__.py similarity index 100% rename from src/fastmcp/contrib/bulk_tool_caller/__init__.py rename to fastmcp_slim/fastmcp/contrib/bulk_tool_caller/__init__.py diff --git a/src/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py b/fastmcp_slim/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py similarity index 100% rename from src/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py rename to fastmcp_slim/fastmcp/contrib/bulk_tool_caller/bulk_tool_caller.py diff --git a/src/fastmcp/contrib/bulk_tool_caller/example.py b/fastmcp_slim/fastmcp/contrib/bulk_tool_caller/example.py similarity index 100% rename from src/fastmcp/contrib/bulk_tool_caller/example.py rename to fastmcp_slim/fastmcp/contrib/bulk_tool_caller/example.py diff --git a/src/fastmcp/contrib/component_manager/README.md b/fastmcp_slim/fastmcp/contrib/component_manager/README.md similarity index 100% rename from src/fastmcp/contrib/component_manager/README.md rename to fastmcp_slim/fastmcp/contrib/component_manager/README.md diff --git a/src/fastmcp/contrib/component_manager/__init__.py b/fastmcp_slim/fastmcp/contrib/component_manager/__init__.py similarity index 100% rename from src/fastmcp/contrib/component_manager/__init__.py rename to fastmcp_slim/fastmcp/contrib/component_manager/__init__.py diff --git a/src/fastmcp/contrib/component_manager/component_manager.py b/fastmcp_slim/fastmcp/contrib/component_manager/component_manager.py similarity index 100% rename from src/fastmcp/contrib/component_manager/component_manager.py rename to fastmcp_slim/fastmcp/contrib/component_manager/component_manager.py diff --git a/src/fastmcp/contrib/component_manager/example.py b/fastmcp_slim/fastmcp/contrib/component_manager/example.py similarity index 100% rename from src/fastmcp/contrib/component_manager/example.py rename to fastmcp_slim/fastmcp/contrib/component_manager/example.py diff --git a/src/fastmcp/contrib/mcp_mixin/README.md b/fastmcp_slim/fastmcp/contrib/mcp_mixin/README.md similarity index 100% rename from src/fastmcp/contrib/mcp_mixin/README.md rename to fastmcp_slim/fastmcp/contrib/mcp_mixin/README.md diff --git a/src/fastmcp/contrib/mcp_mixin/__init__.py b/fastmcp_slim/fastmcp/contrib/mcp_mixin/__init__.py similarity index 100% rename from src/fastmcp/contrib/mcp_mixin/__init__.py rename to fastmcp_slim/fastmcp/contrib/mcp_mixin/__init__.py diff --git a/src/fastmcp/contrib/mcp_mixin/example.py b/fastmcp_slim/fastmcp/contrib/mcp_mixin/example.py similarity index 100% rename from src/fastmcp/contrib/mcp_mixin/example.py rename to fastmcp_slim/fastmcp/contrib/mcp_mixin/example.py diff --git a/src/fastmcp/contrib/mcp_mixin/mcp_mixin.py b/fastmcp_slim/fastmcp/contrib/mcp_mixin/mcp_mixin.py similarity index 100% rename from src/fastmcp/contrib/mcp_mixin/mcp_mixin.py rename to fastmcp_slim/fastmcp/contrib/mcp_mixin/mcp_mixin.py diff --git a/src/fastmcp/decorators.py b/fastmcp_slim/fastmcp/decorators.py similarity index 100% rename from src/fastmcp/decorators.py rename to fastmcp_slim/fastmcp/decorators.py diff --git a/src/fastmcp/dependencies.py b/fastmcp_slim/fastmcp/dependencies.py similarity index 100% rename from src/fastmcp/dependencies.py rename to fastmcp_slim/fastmcp/dependencies.py diff --git a/src/fastmcp/exceptions.py b/fastmcp_slim/fastmcp/exceptions.py similarity index 87% rename from src/fastmcp/exceptions.py rename to fastmcp_slim/fastmcp/exceptions.py index e14d5a15b..947d9be13 100644 --- a/src/fastmcp/exceptions.py +++ b/fastmcp_slim/fastmcp/exceptions.py @@ -2,7 +2,12 @@ import logging -from mcp import McpError # noqa: F401 +try: + from mcp import McpError +except ImportError: + + class McpError(Exception): # type: ignore[no-redef] + """Fallback used when MCP dependencies are not installed.""" class FastMCPDeprecationWarning(DeprecationWarning): diff --git a/src/fastmcp/experimental/__init__.py b/fastmcp_slim/fastmcp/experimental/__init__.py similarity index 100% rename from src/fastmcp/experimental/__init__.py rename to fastmcp_slim/fastmcp/experimental/__init__.py diff --git a/src/fastmcp/experimental/sampling/__init__.py b/fastmcp_slim/fastmcp/experimental/sampling/__init__.py similarity index 100% rename from src/fastmcp/experimental/sampling/__init__.py rename to fastmcp_slim/fastmcp/experimental/sampling/__init__.py diff --git a/src/fastmcp/experimental/sampling/handlers/__init__.py b/fastmcp_slim/fastmcp/experimental/sampling/handlers/__init__.py similarity index 100% rename from src/fastmcp/experimental/sampling/handlers/__init__.py rename to fastmcp_slim/fastmcp/experimental/sampling/handlers/__init__.py diff --git a/src/fastmcp/experimental/sampling/handlers/openai.py b/fastmcp_slim/fastmcp/experimental/sampling/handlers/openai.py similarity index 100% rename from src/fastmcp/experimental/sampling/handlers/openai.py rename to fastmcp_slim/fastmcp/experimental/sampling/handlers/openai.py diff --git a/src/fastmcp/experimental/server/openapi/__init__.py b/fastmcp_slim/fastmcp/experimental/server/openapi/__init__.py similarity index 100% rename from src/fastmcp/experimental/server/openapi/__init__.py rename to fastmcp_slim/fastmcp/experimental/server/openapi/__init__.py diff --git a/src/fastmcp/experimental/transforms/__init__.py b/fastmcp_slim/fastmcp/experimental/transforms/__init__.py similarity index 100% rename from src/fastmcp/experimental/transforms/__init__.py rename to fastmcp_slim/fastmcp/experimental/transforms/__init__.py diff --git a/src/fastmcp/experimental/transforms/code_mode.py b/fastmcp_slim/fastmcp/experimental/transforms/code_mode.py similarity index 100% rename from src/fastmcp/experimental/transforms/code_mode.py rename to fastmcp_slim/fastmcp/experimental/transforms/code_mode.py diff --git a/src/fastmcp/experimental/utilities/openapi/__init__.py b/fastmcp_slim/fastmcp/experimental/utilities/openapi/__init__.py similarity index 100% rename from src/fastmcp/experimental/utilities/openapi/__init__.py rename to fastmcp_slim/fastmcp/experimental/utilities/openapi/__init__.py diff --git a/src/fastmcp/mcp_config.py b/fastmcp_slim/fastmcp/mcp_config.py similarity index 87% rename from src/fastmcp/mcp_config.py rename to fastmcp_slim/fastmcp/mcp_config.py index 8f9f836fc..13c1abd6a 100644 --- a/src/fastmcp/mcp_config.py +++ b/fastmcp_slim/fastmcp/mcp_config.py @@ -40,9 +40,6 @@ from pydantic import ( ) from typing_extensions import Self, override -from fastmcp.tools.tool_transform import ToolTransformConfig -from fastmcp.utilities.types import FastMCPBaseModel - if TYPE_CHECKING: from fastmcp.client.transports import ( ClientTransport, @@ -50,7 +47,6 @@ if TYPE_CHECKING: StdioTransport, StreamableHttpTransport, ) - from fastmcp.server.server import FastMCP def infer_transport_type_from_url( @@ -73,10 +69,21 @@ def infer_transport_type_from_url( return "http" -class _TransformingMCPServerMixin(FastMCPBaseModel): +def _coerce_tool_transform_configs(tools: dict[str, Any]) -> dict[str, Any]: + from fastmcp.tools.tool_transform import ToolTransformConfig + + return { + name: config + if isinstance(config, ToolTransformConfig) + else ToolTransformConfig.model_validate(config) + for name, config in tools.items() + } + + +class _TransformingMCPServerMixin(BaseModel): """A mixin that enables wrapping an MCP Server with tool transforms.""" - tools: dict[str, ToolTransformConfig] = Field(default_factory=dict) + tools: dict[str, Any] = Field(default_factory=dict) """The multi-tool transform to apply to the tools.""" include_tags: set[str] | None = Field( @@ -114,40 +121,42 @@ class _TransformingMCPServerMixin(FastMCPBaseModel): self, server_name: str | None = None, client_name: str | None = None, - ) -> tuple[FastMCP[Any], ClientTransport]: - """Turn the Transforming MCPServer into a FastMCP Server and also return the underlying transport.""" - from fastmcp.client import Client - from fastmcp.client.transports import ( - ClientTransport, # pyright: ignore[reportUnusedImport] - ) - from fastmcp.server import create_proxy + ) -> tuple[Any, ClientTransport]: + """Turn the transforming server into a FastMCP proxy and return its transport.""" + try: + from fastmcp import Client + from fastmcp.server import create_proxy + from fastmcp.server.transforms import ToolTransform + except ImportError as exc: + raise ImportError( + "MCP configs that use FastMCP-specific tool transforms or tag filters " + "require the full `fastmcp` package. Install it with `pip install fastmcp`." + ) from exc - transport: ClientTransport = super().to_transport() # pyright: ignore[reportUnknownMemberType, reportAttributeAccessIssue, reportUnknownVariableType] # ty: ignore[unresolved-attribute] - transport = cast(ClientTransport, transport) - - client: Client[ClientTransport] = Client(transport=transport, name=client_name) - - wrapped_mcp_server = create_proxy( - client, - name=server_name, - ) + transport = cast("ClientTransport", super().to_transport()) # ty: ignore[unresolved-attribute] + client = Client(transport=transport, name=client_name) + wrapped_mcp_server = create_proxy(client, name=server_name) if self.include_tags is not None: wrapped_mcp_server.enable(tags=self.include_tags, only=True) if self.exclude_tags is not None: wrapped_mcp_server.disable(tags=self.exclude_tags) - - # Apply tool transforms if configured if self.tools: - from fastmcp.server.transforms import ToolTransform - - wrapped_mcp_server.add_transform(ToolTransform(self.tools)) + wrapped_mcp_server.add_transform( + ToolTransform(_coerce_tool_transform_configs(self.tools)) + ) return wrapped_mcp_server, transport def to_transport(self) -> ClientTransport: """Get the transport for the transforming MCP server.""" - from fastmcp.client.transports import FastMCPTransport + try: + from fastmcp.client.transports import FastMCPTransport + except ImportError as exc: + raise ImportError( + "MCP configs that use FastMCP-specific tool transforms or tag filters " + "require the full `fastmcp` package. Install it with `pip install fastmcp`." + ) from exc return FastMCPTransport(mcp=self._to_server_and_underlying_transport()[0]) @@ -238,7 +247,10 @@ class RemoteMCPServer(BaseModel): ) # Preserve unknown fields def to_transport(self) -> StreamableHttpTransport | SSETransport: - from fastmcp.client.transports import SSETransport, StreamableHttpTransport + from fastmcp.client.transports import ( + SSETransport, + StreamableHttpTransport, + ) if self.transport is None: transport = infer_transport_type_from_url(self.url) diff --git a/src/fastmcp/prompts/__init__.py b/fastmcp_slim/fastmcp/prompts/__init__.py similarity index 100% rename from src/fastmcp/prompts/__init__.py rename to fastmcp_slim/fastmcp/prompts/__init__.py diff --git a/src/fastmcp/prompts/base.py b/fastmcp_slim/fastmcp/prompts/base.py similarity index 100% rename from src/fastmcp/prompts/base.py rename to fastmcp_slim/fastmcp/prompts/base.py diff --git a/src/fastmcp/prompts/function_prompt.py b/fastmcp_slim/fastmcp/prompts/function_prompt.py similarity index 100% rename from src/fastmcp/prompts/function_prompt.py rename to fastmcp_slim/fastmcp/prompts/function_prompt.py diff --git a/src/fastmcp/py.typed b/fastmcp_slim/fastmcp/py.typed similarity index 100% rename from src/fastmcp/py.typed rename to fastmcp_slim/fastmcp/py.typed diff --git a/src/fastmcp/resources/__init__.py b/fastmcp_slim/fastmcp/resources/__init__.py similarity index 100% rename from src/fastmcp/resources/__init__.py rename to fastmcp_slim/fastmcp/resources/__init__.py diff --git a/src/fastmcp/resources/base.py b/fastmcp_slim/fastmcp/resources/base.py similarity index 100% rename from src/fastmcp/resources/base.py rename to fastmcp_slim/fastmcp/resources/base.py diff --git a/src/fastmcp/resources/function_resource.py b/fastmcp_slim/fastmcp/resources/function_resource.py similarity index 100% rename from src/fastmcp/resources/function_resource.py rename to fastmcp_slim/fastmcp/resources/function_resource.py diff --git a/src/fastmcp/resources/template.py b/fastmcp_slim/fastmcp/resources/template.py similarity index 100% rename from src/fastmcp/resources/template.py rename to fastmcp_slim/fastmcp/resources/template.py diff --git a/src/fastmcp/resources/types.py b/fastmcp_slim/fastmcp/resources/types.py similarity index 100% rename from src/fastmcp/resources/types.py rename to fastmcp_slim/fastmcp/resources/types.py diff --git a/src/fastmcp/server/__init__.py b/fastmcp_slim/fastmcp/server/__init__.py similarity index 52% rename from src/fastmcp/server/__init__.py rename to fastmcp_slim/fastmcp/server/__init__.py index 3f64a0f39..08ac85c34 100644 --- a/src/fastmcp/server/__init__.py +++ b/fastmcp_slim/fastmcp/server/__init__.py @@ -1,7 +1,13 @@ import importlib -from .context import Context -from .server import FastMCP, create_proxy +try: + from .context import Context + from .server import FastMCP, create_proxy +except ImportError as exc: + raise ImportError( + "FastMCP server support is not installed. Install " + "`fastmcp-slim[server]` or `fastmcp`." + ) from exc def __getattr__(name: str) -> object: diff --git a/src/fastmcp/server/app.py b/fastmcp_slim/fastmcp/server/app.py similarity index 100% rename from src/fastmcp/server/app.py rename to fastmcp_slim/fastmcp/server/app.py diff --git a/src/fastmcp/server/apps.py b/fastmcp_slim/fastmcp/server/apps.py similarity index 100% rename from src/fastmcp/server/apps.py rename to fastmcp_slim/fastmcp/server/apps.py diff --git a/src/fastmcp/server/auth/__init__.py b/fastmcp_slim/fastmcp/server/auth/__init__.py similarity index 100% rename from src/fastmcp/server/auth/__init__.py rename to fastmcp_slim/fastmcp/server/auth/__init__.py diff --git a/src/fastmcp/server/auth/auth.py b/fastmcp_slim/fastmcp/server/auth/auth.py similarity index 100% rename from src/fastmcp/server/auth/auth.py rename to fastmcp_slim/fastmcp/server/auth/auth.py diff --git a/src/fastmcp/server/auth/authorization.py b/fastmcp_slim/fastmcp/server/auth/authorization.py similarity index 100% rename from src/fastmcp/server/auth/authorization.py rename to fastmcp_slim/fastmcp/server/auth/authorization.py diff --git a/src/fastmcp/server/auth/cimd.py b/fastmcp_slim/fastmcp/server/auth/cimd.py similarity index 100% rename from src/fastmcp/server/auth/cimd.py rename to fastmcp_slim/fastmcp/server/auth/cimd.py diff --git a/src/fastmcp/server/auth/handlers/__init__.py b/fastmcp_slim/fastmcp/server/auth/handlers/__init__.py similarity index 100% rename from src/fastmcp/server/auth/handlers/__init__.py rename to fastmcp_slim/fastmcp/server/auth/handlers/__init__.py diff --git a/src/fastmcp/server/auth/handlers/authorize.py b/fastmcp_slim/fastmcp/server/auth/handlers/authorize.py similarity index 100% rename from src/fastmcp/server/auth/handlers/authorize.py rename to fastmcp_slim/fastmcp/server/auth/handlers/authorize.py diff --git a/src/fastmcp/server/auth/jwt_issuer.py b/fastmcp_slim/fastmcp/server/auth/jwt_issuer.py similarity index 100% rename from src/fastmcp/server/auth/jwt_issuer.py rename to fastmcp_slim/fastmcp/server/auth/jwt_issuer.py diff --git a/src/fastmcp/server/auth/middleware.py b/fastmcp_slim/fastmcp/server/auth/middleware.py similarity index 100% rename from src/fastmcp/server/auth/middleware.py rename to fastmcp_slim/fastmcp/server/auth/middleware.py diff --git a/src/fastmcp/server/auth/oauth_proxy/__init__.py b/fastmcp_slim/fastmcp/server/auth/oauth_proxy/__init__.py similarity index 100% rename from src/fastmcp/server/auth/oauth_proxy/__init__.py rename to fastmcp_slim/fastmcp/server/auth/oauth_proxy/__init__.py diff --git a/src/fastmcp/server/auth/oauth_proxy/consent.py b/fastmcp_slim/fastmcp/server/auth/oauth_proxy/consent.py similarity index 100% rename from src/fastmcp/server/auth/oauth_proxy/consent.py rename to fastmcp_slim/fastmcp/server/auth/oauth_proxy/consent.py diff --git a/src/fastmcp/server/auth/oauth_proxy/models.py b/fastmcp_slim/fastmcp/server/auth/oauth_proxy/models.py similarity index 100% rename from src/fastmcp/server/auth/oauth_proxy/models.py rename to fastmcp_slim/fastmcp/server/auth/oauth_proxy/models.py diff --git a/src/fastmcp/server/auth/oauth_proxy/proxy.py b/fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py similarity index 100% rename from src/fastmcp/server/auth/oauth_proxy/proxy.py rename to fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py diff --git a/src/fastmcp/server/auth/oauth_proxy/ui.py b/fastmcp_slim/fastmcp/server/auth/oauth_proxy/ui.py similarity index 100% rename from src/fastmcp/server/auth/oauth_proxy/ui.py rename to fastmcp_slim/fastmcp/server/auth/oauth_proxy/ui.py diff --git a/src/fastmcp/server/auth/oidc_proxy.py b/fastmcp_slim/fastmcp/server/auth/oidc_proxy.py similarity index 100% rename from src/fastmcp/server/auth/oidc_proxy.py rename to fastmcp_slim/fastmcp/server/auth/oidc_proxy.py diff --git a/src/fastmcp/server/auth/providers/__init__.py b/fastmcp_slim/fastmcp/server/auth/providers/__init__.py similarity index 100% rename from src/fastmcp/server/auth/providers/__init__.py rename to fastmcp_slim/fastmcp/server/auth/providers/__init__.py diff --git a/src/fastmcp/server/auth/providers/auth0.py b/fastmcp_slim/fastmcp/server/auth/providers/auth0.py similarity index 100% rename from src/fastmcp/server/auth/providers/auth0.py rename to fastmcp_slim/fastmcp/server/auth/providers/auth0.py diff --git a/src/fastmcp/server/auth/providers/aws.py b/fastmcp_slim/fastmcp/server/auth/providers/aws.py similarity index 100% rename from src/fastmcp/server/auth/providers/aws.py rename to fastmcp_slim/fastmcp/server/auth/providers/aws.py diff --git a/src/fastmcp/server/auth/providers/azure.py b/fastmcp_slim/fastmcp/server/auth/providers/azure.py similarity index 100% rename from src/fastmcp/server/auth/providers/azure.py rename to fastmcp_slim/fastmcp/server/auth/providers/azure.py diff --git a/src/fastmcp/server/auth/providers/clerk.py b/fastmcp_slim/fastmcp/server/auth/providers/clerk.py similarity index 100% rename from src/fastmcp/server/auth/providers/clerk.py rename to fastmcp_slim/fastmcp/server/auth/providers/clerk.py diff --git a/src/fastmcp/server/auth/providers/debug.py b/fastmcp_slim/fastmcp/server/auth/providers/debug.py similarity index 100% rename from src/fastmcp/server/auth/providers/debug.py rename to fastmcp_slim/fastmcp/server/auth/providers/debug.py diff --git a/src/fastmcp/server/auth/providers/descope.py b/fastmcp_slim/fastmcp/server/auth/providers/descope.py similarity index 100% rename from src/fastmcp/server/auth/providers/descope.py rename to fastmcp_slim/fastmcp/server/auth/providers/descope.py diff --git a/src/fastmcp/server/auth/providers/discord.py b/fastmcp_slim/fastmcp/server/auth/providers/discord.py similarity index 100% rename from src/fastmcp/server/auth/providers/discord.py rename to fastmcp_slim/fastmcp/server/auth/providers/discord.py diff --git a/src/fastmcp/server/auth/providers/github.py b/fastmcp_slim/fastmcp/server/auth/providers/github.py similarity index 100% rename from src/fastmcp/server/auth/providers/github.py rename to fastmcp_slim/fastmcp/server/auth/providers/github.py diff --git a/src/fastmcp/server/auth/providers/google.py b/fastmcp_slim/fastmcp/server/auth/providers/google.py similarity index 100% rename from src/fastmcp/server/auth/providers/google.py rename to fastmcp_slim/fastmcp/server/auth/providers/google.py diff --git a/src/fastmcp/server/auth/providers/in_memory.py b/fastmcp_slim/fastmcp/server/auth/providers/in_memory.py similarity index 100% rename from src/fastmcp/server/auth/providers/in_memory.py rename to fastmcp_slim/fastmcp/server/auth/providers/in_memory.py diff --git a/src/fastmcp/server/auth/providers/introspection.py b/fastmcp_slim/fastmcp/server/auth/providers/introspection.py similarity index 100% rename from src/fastmcp/server/auth/providers/introspection.py rename to fastmcp_slim/fastmcp/server/auth/providers/introspection.py diff --git a/src/fastmcp/server/auth/providers/jwt.py b/fastmcp_slim/fastmcp/server/auth/providers/jwt.py similarity index 100% rename from src/fastmcp/server/auth/providers/jwt.py rename to fastmcp_slim/fastmcp/server/auth/providers/jwt.py diff --git a/src/fastmcp/server/auth/providers/keycloak.py b/fastmcp_slim/fastmcp/server/auth/providers/keycloak.py similarity index 100% rename from src/fastmcp/server/auth/providers/keycloak.py rename to fastmcp_slim/fastmcp/server/auth/providers/keycloak.py diff --git a/src/fastmcp/server/auth/providers/oci.py b/fastmcp_slim/fastmcp/server/auth/providers/oci.py similarity index 100% rename from src/fastmcp/server/auth/providers/oci.py rename to fastmcp_slim/fastmcp/server/auth/providers/oci.py diff --git a/src/fastmcp/server/auth/providers/propelauth.py b/fastmcp_slim/fastmcp/server/auth/providers/propelauth.py similarity index 100% rename from src/fastmcp/server/auth/providers/propelauth.py rename to fastmcp_slim/fastmcp/server/auth/providers/propelauth.py diff --git a/src/fastmcp/server/auth/providers/scalekit.py b/fastmcp_slim/fastmcp/server/auth/providers/scalekit.py similarity index 100% rename from src/fastmcp/server/auth/providers/scalekit.py rename to fastmcp_slim/fastmcp/server/auth/providers/scalekit.py diff --git a/src/fastmcp/server/auth/providers/supabase.py b/fastmcp_slim/fastmcp/server/auth/providers/supabase.py similarity index 100% rename from src/fastmcp/server/auth/providers/supabase.py rename to fastmcp_slim/fastmcp/server/auth/providers/supabase.py diff --git a/src/fastmcp/server/auth/providers/workos.py b/fastmcp_slim/fastmcp/server/auth/providers/workos.py similarity index 100% rename from src/fastmcp/server/auth/providers/workos.py rename to fastmcp_slim/fastmcp/server/auth/providers/workos.py diff --git a/src/fastmcp/server/auth/redirect_validation.py b/fastmcp_slim/fastmcp/server/auth/redirect_validation.py similarity index 100% rename from src/fastmcp/server/auth/redirect_validation.py rename to fastmcp_slim/fastmcp/server/auth/redirect_validation.py diff --git a/src/fastmcp/server/auth/ssrf.py b/fastmcp_slim/fastmcp/server/auth/ssrf.py similarity index 100% rename from src/fastmcp/server/auth/ssrf.py rename to fastmcp_slim/fastmcp/server/auth/ssrf.py diff --git a/src/fastmcp/server/context.py b/fastmcp_slim/fastmcp/server/context.py similarity index 100% rename from src/fastmcp/server/context.py rename to fastmcp_slim/fastmcp/server/context.py diff --git a/src/fastmcp/server/dependencies.py b/fastmcp_slim/fastmcp/server/dependencies.py similarity index 100% rename from src/fastmcp/server/dependencies.py rename to fastmcp_slim/fastmcp/server/dependencies.py diff --git a/src/fastmcp/server/elicitation.py b/fastmcp_slim/fastmcp/server/elicitation.py similarity index 100% rename from src/fastmcp/server/elicitation.py rename to fastmcp_slim/fastmcp/server/elicitation.py diff --git a/src/fastmcp/server/event_store.py b/fastmcp_slim/fastmcp/server/event_store.py similarity index 100% rename from src/fastmcp/server/event_store.py rename to fastmcp_slim/fastmcp/server/event_store.py diff --git a/src/fastmcp/server/http.py b/fastmcp_slim/fastmcp/server/http.py similarity index 100% rename from src/fastmcp/server/http.py rename to fastmcp_slim/fastmcp/server/http.py diff --git a/src/fastmcp/server/lifespan.py b/fastmcp_slim/fastmcp/server/lifespan.py similarity index 100% rename from src/fastmcp/server/lifespan.py rename to fastmcp_slim/fastmcp/server/lifespan.py diff --git a/src/fastmcp/server/low_level.py b/fastmcp_slim/fastmcp/server/low_level.py similarity index 100% rename from src/fastmcp/server/low_level.py rename to fastmcp_slim/fastmcp/server/low_level.py diff --git a/src/fastmcp/server/middleware/__init__.py b/fastmcp_slim/fastmcp/server/middleware/__init__.py similarity index 100% rename from src/fastmcp/server/middleware/__init__.py rename to fastmcp_slim/fastmcp/server/middleware/__init__.py diff --git a/src/fastmcp/server/middleware/authorization.py b/fastmcp_slim/fastmcp/server/middleware/authorization.py similarity index 100% rename from src/fastmcp/server/middleware/authorization.py rename to fastmcp_slim/fastmcp/server/middleware/authorization.py diff --git a/src/fastmcp/server/middleware/caching.py b/fastmcp_slim/fastmcp/server/middleware/caching.py similarity index 100% rename from src/fastmcp/server/middleware/caching.py rename to fastmcp_slim/fastmcp/server/middleware/caching.py diff --git a/src/fastmcp/server/middleware/dereference.py b/fastmcp_slim/fastmcp/server/middleware/dereference.py similarity index 100% rename from src/fastmcp/server/middleware/dereference.py rename to fastmcp_slim/fastmcp/server/middleware/dereference.py diff --git a/src/fastmcp/server/middleware/error_handling.py b/fastmcp_slim/fastmcp/server/middleware/error_handling.py similarity index 100% rename from src/fastmcp/server/middleware/error_handling.py rename to fastmcp_slim/fastmcp/server/middleware/error_handling.py diff --git a/src/fastmcp/server/middleware/logging.py b/fastmcp_slim/fastmcp/server/middleware/logging.py similarity index 100% rename from src/fastmcp/server/middleware/logging.py rename to fastmcp_slim/fastmcp/server/middleware/logging.py diff --git a/src/fastmcp/server/middleware/middleware.py b/fastmcp_slim/fastmcp/server/middleware/middleware.py similarity index 100% rename from src/fastmcp/server/middleware/middleware.py rename to fastmcp_slim/fastmcp/server/middleware/middleware.py diff --git a/src/fastmcp/server/middleware/ping.py b/fastmcp_slim/fastmcp/server/middleware/ping.py similarity index 100% rename from src/fastmcp/server/middleware/ping.py rename to fastmcp_slim/fastmcp/server/middleware/ping.py diff --git a/src/fastmcp/server/middleware/rate_limiting.py b/fastmcp_slim/fastmcp/server/middleware/rate_limiting.py similarity index 100% rename from src/fastmcp/server/middleware/rate_limiting.py rename to fastmcp_slim/fastmcp/server/middleware/rate_limiting.py diff --git a/src/fastmcp/server/middleware/response_limiting.py b/fastmcp_slim/fastmcp/server/middleware/response_limiting.py similarity index 100% rename from src/fastmcp/server/middleware/response_limiting.py rename to fastmcp_slim/fastmcp/server/middleware/response_limiting.py diff --git a/src/fastmcp/server/middleware/timing.py b/fastmcp_slim/fastmcp/server/middleware/timing.py similarity index 100% rename from src/fastmcp/server/middleware/timing.py rename to fastmcp_slim/fastmcp/server/middleware/timing.py diff --git a/src/fastmcp/server/middleware/tool_injection.py b/fastmcp_slim/fastmcp/server/middleware/tool_injection.py similarity index 100% rename from src/fastmcp/server/middleware/tool_injection.py rename to fastmcp_slim/fastmcp/server/middleware/tool_injection.py diff --git a/src/fastmcp/server/mixins/__init__.py b/fastmcp_slim/fastmcp/server/mixins/__init__.py similarity index 100% rename from src/fastmcp/server/mixins/__init__.py rename to fastmcp_slim/fastmcp/server/mixins/__init__.py diff --git a/src/fastmcp/server/mixins/lifespan.py b/fastmcp_slim/fastmcp/server/mixins/lifespan.py similarity index 100% rename from src/fastmcp/server/mixins/lifespan.py rename to fastmcp_slim/fastmcp/server/mixins/lifespan.py diff --git a/src/fastmcp/server/mixins/mcp_operations.py b/fastmcp_slim/fastmcp/server/mixins/mcp_operations.py similarity index 100% rename from src/fastmcp/server/mixins/mcp_operations.py rename to fastmcp_slim/fastmcp/server/mixins/mcp_operations.py diff --git a/src/fastmcp/server/mixins/transport.py b/fastmcp_slim/fastmcp/server/mixins/transport.py similarity index 100% rename from src/fastmcp/server/mixins/transport.py rename to fastmcp_slim/fastmcp/server/mixins/transport.py diff --git a/src/fastmcp/server/openapi/__init__.py b/fastmcp_slim/fastmcp/server/openapi/__init__.py similarity index 100% rename from src/fastmcp/server/openapi/__init__.py rename to fastmcp_slim/fastmcp/server/openapi/__init__.py diff --git a/src/fastmcp/server/openapi/components.py b/fastmcp_slim/fastmcp/server/openapi/components.py similarity index 100% rename from src/fastmcp/server/openapi/components.py rename to fastmcp_slim/fastmcp/server/openapi/components.py diff --git a/src/fastmcp/server/openapi/routing.py b/fastmcp_slim/fastmcp/server/openapi/routing.py similarity index 100% rename from src/fastmcp/server/openapi/routing.py rename to fastmcp_slim/fastmcp/server/openapi/routing.py diff --git a/src/fastmcp/server/openapi/server.py b/fastmcp_slim/fastmcp/server/openapi/server.py similarity index 100% rename from src/fastmcp/server/openapi/server.py rename to fastmcp_slim/fastmcp/server/openapi/server.py diff --git a/src/fastmcp/server/providers/__init__.py b/fastmcp_slim/fastmcp/server/providers/__init__.py similarity index 100% rename from src/fastmcp/server/providers/__init__.py rename to fastmcp_slim/fastmcp/server/providers/__init__.py diff --git a/src/fastmcp/server/providers/addressing.py b/fastmcp_slim/fastmcp/server/providers/addressing.py similarity index 100% rename from src/fastmcp/server/providers/addressing.py rename to fastmcp_slim/fastmcp/server/providers/addressing.py diff --git a/src/fastmcp/server/providers/aggregate.py b/fastmcp_slim/fastmcp/server/providers/aggregate.py similarity index 100% rename from src/fastmcp/server/providers/aggregate.py rename to fastmcp_slim/fastmcp/server/providers/aggregate.py diff --git a/src/fastmcp/server/providers/base.py b/fastmcp_slim/fastmcp/server/providers/base.py similarity index 100% rename from src/fastmcp/server/providers/base.py rename to fastmcp_slim/fastmcp/server/providers/base.py diff --git a/src/fastmcp/server/providers/fastmcp_provider.py b/fastmcp_slim/fastmcp/server/providers/fastmcp_provider.py similarity index 100% rename from src/fastmcp/server/providers/fastmcp_provider.py rename to fastmcp_slim/fastmcp/server/providers/fastmcp_provider.py diff --git a/src/fastmcp/server/providers/filesystem.py b/fastmcp_slim/fastmcp/server/providers/filesystem.py similarity index 100% rename from src/fastmcp/server/providers/filesystem.py rename to fastmcp_slim/fastmcp/server/providers/filesystem.py diff --git a/src/fastmcp/server/providers/filesystem_discovery.py b/fastmcp_slim/fastmcp/server/providers/filesystem_discovery.py similarity index 100% rename from src/fastmcp/server/providers/filesystem_discovery.py rename to fastmcp_slim/fastmcp/server/providers/filesystem_discovery.py diff --git a/src/fastmcp/server/providers/local_provider/__init__.py b/fastmcp_slim/fastmcp/server/providers/local_provider/__init__.py similarity index 100% rename from src/fastmcp/server/providers/local_provider/__init__.py rename to fastmcp_slim/fastmcp/server/providers/local_provider/__init__.py diff --git a/src/fastmcp/server/providers/local_provider/decorators/__init__.py b/fastmcp_slim/fastmcp/server/providers/local_provider/decorators/__init__.py similarity index 100% rename from src/fastmcp/server/providers/local_provider/decorators/__init__.py rename to fastmcp_slim/fastmcp/server/providers/local_provider/decorators/__init__.py diff --git a/src/fastmcp/server/providers/local_provider/decorators/prompts.py b/fastmcp_slim/fastmcp/server/providers/local_provider/decorators/prompts.py similarity index 100% rename from src/fastmcp/server/providers/local_provider/decorators/prompts.py rename to fastmcp_slim/fastmcp/server/providers/local_provider/decorators/prompts.py diff --git a/src/fastmcp/server/providers/local_provider/decorators/resources.py b/fastmcp_slim/fastmcp/server/providers/local_provider/decorators/resources.py similarity index 100% rename from src/fastmcp/server/providers/local_provider/decorators/resources.py rename to fastmcp_slim/fastmcp/server/providers/local_provider/decorators/resources.py diff --git a/src/fastmcp/server/providers/local_provider/decorators/tools.py b/fastmcp_slim/fastmcp/server/providers/local_provider/decorators/tools.py similarity index 100% rename from src/fastmcp/server/providers/local_provider/decorators/tools.py rename to fastmcp_slim/fastmcp/server/providers/local_provider/decorators/tools.py diff --git a/src/fastmcp/server/providers/local_provider/local_provider.py b/fastmcp_slim/fastmcp/server/providers/local_provider/local_provider.py similarity index 100% rename from src/fastmcp/server/providers/local_provider/local_provider.py rename to fastmcp_slim/fastmcp/server/providers/local_provider/local_provider.py diff --git a/src/fastmcp/server/providers/openapi/README.md b/fastmcp_slim/fastmcp/server/providers/openapi/README.md similarity index 100% rename from src/fastmcp/server/providers/openapi/README.md rename to fastmcp_slim/fastmcp/server/providers/openapi/README.md diff --git a/src/fastmcp/server/providers/openapi/__init__.py b/fastmcp_slim/fastmcp/server/providers/openapi/__init__.py similarity index 100% rename from src/fastmcp/server/providers/openapi/__init__.py rename to fastmcp_slim/fastmcp/server/providers/openapi/__init__.py diff --git a/src/fastmcp/server/providers/openapi/components.py b/fastmcp_slim/fastmcp/server/providers/openapi/components.py similarity index 100% rename from src/fastmcp/server/providers/openapi/components.py rename to fastmcp_slim/fastmcp/server/providers/openapi/components.py diff --git a/src/fastmcp/server/providers/openapi/provider.py b/fastmcp_slim/fastmcp/server/providers/openapi/provider.py similarity index 100% rename from src/fastmcp/server/providers/openapi/provider.py rename to fastmcp_slim/fastmcp/server/providers/openapi/provider.py diff --git a/src/fastmcp/server/providers/openapi/routing.py b/fastmcp_slim/fastmcp/server/providers/openapi/routing.py similarity index 100% rename from src/fastmcp/server/providers/openapi/routing.py rename to fastmcp_slim/fastmcp/server/providers/openapi/routing.py diff --git a/src/fastmcp/server/providers/prefab_synthesis.py b/fastmcp_slim/fastmcp/server/providers/prefab_synthesis.py similarity index 100% rename from src/fastmcp/server/providers/prefab_synthesis.py rename to fastmcp_slim/fastmcp/server/providers/prefab_synthesis.py diff --git a/src/fastmcp/server/providers/proxy.py b/fastmcp_slim/fastmcp/server/providers/proxy.py similarity index 100% rename from src/fastmcp/server/providers/proxy.py rename to fastmcp_slim/fastmcp/server/providers/proxy.py diff --git a/src/fastmcp/server/providers/skills/__init__.py b/fastmcp_slim/fastmcp/server/providers/skills/__init__.py similarity index 100% rename from src/fastmcp/server/providers/skills/__init__.py rename to fastmcp_slim/fastmcp/server/providers/skills/__init__.py diff --git a/src/fastmcp/server/providers/skills/_common.py b/fastmcp_slim/fastmcp/server/providers/skills/_common.py similarity index 100% rename from src/fastmcp/server/providers/skills/_common.py rename to fastmcp_slim/fastmcp/server/providers/skills/_common.py diff --git a/src/fastmcp/server/providers/skills/claude_provider.py b/fastmcp_slim/fastmcp/server/providers/skills/claude_provider.py similarity index 100% rename from src/fastmcp/server/providers/skills/claude_provider.py rename to fastmcp_slim/fastmcp/server/providers/skills/claude_provider.py diff --git a/src/fastmcp/server/providers/skills/directory_provider.py b/fastmcp_slim/fastmcp/server/providers/skills/directory_provider.py similarity index 100% rename from src/fastmcp/server/providers/skills/directory_provider.py rename to fastmcp_slim/fastmcp/server/providers/skills/directory_provider.py diff --git a/src/fastmcp/server/providers/skills/skill_provider.py b/fastmcp_slim/fastmcp/server/providers/skills/skill_provider.py similarity index 100% rename from src/fastmcp/server/providers/skills/skill_provider.py rename to fastmcp_slim/fastmcp/server/providers/skills/skill_provider.py diff --git a/src/fastmcp/server/providers/skills/vendor_providers.py b/fastmcp_slim/fastmcp/server/providers/skills/vendor_providers.py similarity index 100% rename from src/fastmcp/server/providers/skills/vendor_providers.py rename to fastmcp_slim/fastmcp/server/providers/skills/vendor_providers.py diff --git a/src/fastmcp/server/providers/wrapped_provider.py b/fastmcp_slim/fastmcp/server/providers/wrapped_provider.py similarity index 100% rename from src/fastmcp/server/providers/wrapped_provider.py rename to fastmcp_slim/fastmcp/server/providers/wrapped_provider.py diff --git a/src/fastmcp/server/proxy.py b/fastmcp_slim/fastmcp/server/proxy.py similarity index 100% rename from src/fastmcp/server/proxy.py rename to fastmcp_slim/fastmcp/server/proxy.py diff --git a/src/fastmcp/server/sampling/__init__.py b/fastmcp_slim/fastmcp/server/sampling/__init__.py similarity index 100% rename from src/fastmcp/server/sampling/__init__.py rename to fastmcp_slim/fastmcp/server/sampling/__init__.py diff --git a/src/fastmcp/server/sampling/run.py b/fastmcp_slim/fastmcp/server/sampling/run.py similarity index 100% rename from src/fastmcp/server/sampling/run.py rename to fastmcp_slim/fastmcp/server/sampling/run.py diff --git a/src/fastmcp/server/sampling/sampling_tool.py b/fastmcp_slim/fastmcp/server/sampling/sampling_tool.py similarity index 100% rename from src/fastmcp/server/sampling/sampling_tool.py rename to fastmcp_slim/fastmcp/server/sampling/sampling_tool.py diff --git a/src/fastmcp/server/server.py b/fastmcp_slim/fastmcp/server/server.py similarity index 100% rename from src/fastmcp/server/server.py rename to fastmcp_slim/fastmcp/server/server.py diff --git a/src/fastmcp/server/tasks/__init__.py b/fastmcp_slim/fastmcp/server/tasks/__init__.py similarity index 100% rename from src/fastmcp/server/tasks/__init__.py rename to fastmcp_slim/fastmcp/server/tasks/__init__.py diff --git a/src/fastmcp/server/tasks/capabilities.py b/fastmcp_slim/fastmcp/server/tasks/capabilities.py similarity index 100% rename from src/fastmcp/server/tasks/capabilities.py rename to fastmcp_slim/fastmcp/server/tasks/capabilities.py diff --git a/src/fastmcp/server/tasks/config.py b/fastmcp_slim/fastmcp/server/tasks/config.py similarity index 100% rename from src/fastmcp/server/tasks/config.py rename to fastmcp_slim/fastmcp/server/tasks/config.py diff --git a/src/fastmcp/server/tasks/context.py b/fastmcp_slim/fastmcp/server/tasks/context.py similarity index 100% rename from src/fastmcp/server/tasks/context.py rename to fastmcp_slim/fastmcp/server/tasks/context.py diff --git a/src/fastmcp/server/tasks/elicitation.py b/fastmcp_slim/fastmcp/server/tasks/elicitation.py similarity index 100% rename from src/fastmcp/server/tasks/elicitation.py rename to fastmcp_slim/fastmcp/server/tasks/elicitation.py diff --git a/src/fastmcp/server/tasks/handlers.py b/fastmcp_slim/fastmcp/server/tasks/handlers.py similarity index 100% rename from src/fastmcp/server/tasks/handlers.py rename to fastmcp_slim/fastmcp/server/tasks/handlers.py diff --git a/src/fastmcp/server/tasks/keys.py b/fastmcp_slim/fastmcp/server/tasks/keys.py similarity index 100% rename from src/fastmcp/server/tasks/keys.py rename to fastmcp_slim/fastmcp/server/tasks/keys.py diff --git a/src/fastmcp/server/tasks/notifications.py b/fastmcp_slim/fastmcp/server/tasks/notifications.py similarity index 100% rename from src/fastmcp/server/tasks/notifications.py rename to fastmcp_slim/fastmcp/server/tasks/notifications.py diff --git a/src/fastmcp/server/tasks/requests.py b/fastmcp_slim/fastmcp/server/tasks/requests.py similarity index 100% rename from src/fastmcp/server/tasks/requests.py rename to fastmcp_slim/fastmcp/server/tasks/requests.py diff --git a/src/fastmcp/server/tasks/routing.py b/fastmcp_slim/fastmcp/server/tasks/routing.py similarity index 100% rename from src/fastmcp/server/tasks/routing.py rename to fastmcp_slim/fastmcp/server/tasks/routing.py diff --git a/src/fastmcp/server/tasks/subscriptions.py b/fastmcp_slim/fastmcp/server/tasks/subscriptions.py similarity index 100% rename from src/fastmcp/server/tasks/subscriptions.py rename to fastmcp_slim/fastmcp/server/tasks/subscriptions.py diff --git a/src/fastmcp/server/telemetry.py b/fastmcp_slim/fastmcp/server/telemetry.py similarity index 100% rename from src/fastmcp/server/telemetry.py rename to fastmcp_slim/fastmcp/server/telemetry.py diff --git a/src/fastmcp/server/transforms/__init__.py b/fastmcp_slim/fastmcp/server/transforms/__init__.py similarity index 100% rename from src/fastmcp/server/transforms/__init__.py rename to fastmcp_slim/fastmcp/server/transforms/__init__.py diff --git a/src/fastmcp/server/transforms/catalog.py b/fastmcp_slim/fastmcp/server/transforms/catalog.py similarity index 100% rename from src/fastmcp/server/transforms/catalog.py rename to fastmcp_slim/fastmcp/server/transforms/catalog.py diff --git a/src/fastmcp/server/transforms/namespace.py b/fastmcp_slim/fastmcp/server/transforms/namespace.py similarity index 100% rename from src/fastmcp/server/transforms/namespace.py rename to fastmcp_slim/fastmcp/server/transforms/namespace.py diff --git a/src/fastmcp/server/transforms/prompts_as_tools.py b/fastmcp_slim/fastmcp/server/transforms/prompts_as_tools.py similarity index 100% rename from src/fastmcp/server/transforms/prompts_as_tools.py rename to fastmcp_slim/fastmcp/server/transforms/prompts_as_tools.py diff --git a/src/fastmcp/server/transforms/resources_as_tools.py b/fastmcp_slim/fastmcp/server/transforms/resources_as_tools.py similarity index 100% rename from src/fastmcp/server/transforms/resources_as_tools.py rename to fastmcp_slim/fastmcp/server/transforms/resources_as_tools.py diff --git a/src/fastmcp/server/transforms/search/__init__.py b/fastmcp_slim/fastmcp/server/transforms/search/__init__.py similarity index 100% rename from src/fastmcp/server/transforms/search/__init__.py rename to fastmcp_slim/fastmcp/server/transforms/search/__init__.py diff --git a/src/fastmcp/server/transforms/search/base.py b/fastmcp_slim/fastmcp/server/transforms/search/base.py similarity index 100% rename from src/fastmcp/server/transforms/search/base.py rename to fastmcp_slim/fastmcp/server/transforms/search/base.py diff --git a/src/fastmcp/server/transforms/search/bm25.py b/fastmcp_slim/fastmcp/server/transforms/search/bm25.py similarity index 100% rename from src/fastmcp/server/transforms/search/bm25.py rename to fastmcp_slim/fastmcp/server/transforms/search/bm25.py diff --git a/src/fastmcp/server/transforms/search/regex.py b/fastmcp_slim/fastmcp/server/transforms/search/regex.py similarity index 100% rename from src/fastmcp/server/transforms/search/regex.py rename to fastmcp_slim/fastmcp/server/transforms/search/regex.py diff --git a/src/fastmcp/server/transforms/tool_transform.py b/fastmcp_slim/fastmcp/server/transforms/tool_transform.py similarity index 100% rename from src/fastmcp/server/transforms/tool_transform.py rename to fastmcp_slim/fastmcp/server/transforms/tool_transform.py diff --git a/src/fastmcp/server/transforms/version_filter.py b/fastmcp_slim/fastmcp/server/transforms/version_filter.py similarity index 100% rename from src/fastmcp/server/transforms/version_filter.py rename to fastmcp_slim/fastmcp/server/transforms/version_filter.py diff --git a/src/fastmcp/server/transforms/visibility.py b/fastmcp_slim/fastmcp/server/transforms/visibility.py similarity index 100% rename from src/fastmcp/server/transforms/visibility.py rename to fastmcp_slim/fastmcp/server/transforms/visibility.py diff --git a/src/fastmcp/settings.py b/fastmcp_slim/fastmcp/settings.py similarity index 100% rename from src/fastmcp/settings.py rename to fastmcp_slim/fastmcp/settings.py diff --git a/src/fastmcp/telemetry.py b/fastmcp_slim/fastmcp/telemetry.py similarity index 100% rename from src/fastmcp/telemetry.py rename to fastmcp_slim/fastmcp/telemetry.py diff --git a/src/fastmcp/tools/__init__.py b/fastmcp_slim/fastmcp/tools/__init__.py similarity index 100% rename from src/fastmcp/tools/__init__.py rename to fastmcp_slim/fastmcp/tools/__init__.py diff --git a/src/fastmcp/tools/base.py b/fastmcp_slim/fastmcp/tools/base.py similarity index 100% rename from src/fastmcp/tools/base.py rename to fastmcp_slim/fastmcp/tools/base.py diff --git a/src/fastmcp/tools/function_parsing.py b/fastmcp_slim/fastmcp/tools/function_parsing.py similarity index 100% rename from src/fastmcp/tools/function_parsing.py rename to fastmcp_slim/fastmcp/tools/function_parsing.py diff --git a/src/fastmcp/tools/function_tool.py b/fastmcp_slim/fastmcp/tools/function_tool.py similarity index 100% rename from src/fastmcp/tools/function_tool.py rename to fastmcp_slim/fastmcp/tools/function_tool.py diff --git a/src/fastmcp/tools/tool_transform.py b/fastmcp_slim/fastmcp/tools/tool_transform.py similarity index 100% rename from src/fastmcp/tools/tool_transform.py rename to fastmcp_slim/fastmcp/tools/tool_transform.py diff --git a/src/fastmcp/types.py b/fastmcp_slim/fastmcp/types.py similarity index 100% rename from src/fastmcp/types.py rename to fastmcp_slim/fastmcp/types.py diff --git a/src/fastmcp/utilities/__init__.py b/fastmcp_slim/fastmcp/utilities/__init__.py similarity index 100% rename from src/fastmcp/utilities/__init__.py rename to fastmcp_slim/fastmcp/utilities/__init__.py diff --git a/src/fastmcp/utilities/async_utils.py b/fastmcp_slim/fastmcp/utilities/async_utils.py similarity index 100% rename from src/fastmcp/utilities/async_utils.py rename to fastmcp_slim/fastmcp/utilities/async_utils.py diff --git a/src/fastmcp/utilities/auth.py b/fastmcp_slim/fastmcp/utilities/auth.py similarity index 100% rename from src/fastmcp/utilities/auth.py rename to fastmcp_slim/fastmcp/utilities/auth.py diff --git a/src/fastmcp/utilities/cli.py b/fastmcp_slim/fastmcp/utilities/cli.py similarity index 100% rename from src/fastmcp/utilities/cli.py rename to fastmcp_slim/fastmcp/utilities/cli.py diff --git a/src/fastmcp/utilities/components.py b/fastmcp_slim/fastmcp/utilities/components.py similarity index 100% rename from src/fastmcp/utilities/components.py rename to fastmcp_slim/fastmcp/utilities/components.py diff --git a/src/fastmcp/utilities/docstring_parsing.py b/fastmcp_slim/fastmcp/utilities/docstring_parsing.py similarity index 100% rename from src/fastmcp/utilities/docstring_parsing.py rename to fastmcp_slim/fastmcp/utilities/docstring_parsing.py diff --git a/src/fastmcp/utilities/exceptions.py b/fastmcp_slim/fastmcp/utilities/exceptions.py similarity index 100% rename from src/fastmcp/utilities/exceptions.py rename to fastmcp_slim/fastmcp/utilities/exceptions.py diff --git a/src/fastmcp/utilities/http.py b/fastmcp_slim/fastmcp/utilities/http.py similarity index 100% rename from src/fastmcp/utilities/http.py rename to fastmcp_slim/fastmcp/utilities/http.py diff --git a/src/fastmcp/utilities/inspect.py b/fastmcp_slim/fastmcp/utilities/inspect.py similarity index 100% rename from src/fastmcp/utilities/inspect.py rename to fastmcp_slim/fastmcp/utilities/inspect.py diff --git a/src/fastmcp/utilities/json_schema.py b/fastmcp_slim/fastmcp/utilities/json_schema.py similarity index 100% rename from src/fastmcp/utilities/json_schema.py rename to fastmcp_slim/fastmcp/utilities/json_schema.py diff --git a/src/fastmcp/utilities/json_schema_type.py b/fastmcp_slim/fastmcp/utilities/json_schema_type.py similarity index 100% rename from src/fastmcp/utilities/json_schema_type.py rename to fastmcp_slim/fastmcp/utilities/json_schema_type.py diff --git a/src/fastmcp/utilities/lifespan.py b/fastmcp_slim/fastmcp/utilities/lifespan.py similarity index 100% rename from src/fastmcp/utilities/lifespan.py rename to fastmcp_slim/fastmcp/utilities/lifespan.py diff --git a/src/fastmcp/utilities/logging.py b/fastmcp_slim/fastmcp/utilities/logging.py similarity index 97% rename from src/fastmcp/utilities/logging.py rename to fastmcp_slim/fastmcp/utilities/logging.py index 1cd0470d7..d39d6ef4a 100644 --- a/src/fastmcp/utilities/logging.py +++ b/fastmcp_slim/fastmcp/utilities/logging.py @@ -83,9 +83,15 @@ def configure_logging( # no path or level name to maximize width available for the traceback # suppress framework frames and limit the number of frames to 3 - import mcp import pydantic + try: + import mcp + except ImportError: + tracebacks_suppress = [fastmcp, pydantic] + else: + tracebacks_suppress = [fastmcp, mcp, pydantic] + # Build traceback kwargs with defaults that can be overridden traceback_kwargs = { "console": Console(stderr=True), @@ -93,7 +99,7 @@ def configure_logging( "show_level": False, "rich_tracebacks": enable_rich_tracebacks, "tracebacks_max_frames": 3, - "tracebacks_suppress": [fastmcp, mcp, pydantic], + "tracebacks_suppress": tracebacks_suppress, } # Override defaults with user-provided values traceback_kwargs.update(rich_kwargs) diff --git a/src/fastmcp/utilities/mcp_server_config/__init__.py b/fastmcp_slim/fastmcp/utilities/mcp_server_config/__init__.py similarity index 100% rename from src/fastmcp/utilities/mcp_server_config/__init__.py rename to fastmcp_slim/fastmcp/utilities/mcp_server_config/__init__.py diff --git a/src/fastmcp/utilities/mcp_server_config/v1/__init__.py b/fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/__init__.py similarity index 100% rename from src/fastmcp/utilities/mcp_server_config/v1/__init__.py rename to fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/__init__.py diff --git a/src/fastmcp/utilities/mcp_server_config/v1/environments/__init__.py b/fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/environments/__init__.py similarity index 100% rename from src/fastmcp/utilities/mcp_server_config/v1/environments/__init__.py rename to fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/environments/__init__.py diff --git a/src/fastmcp/utilities/mcp_server_config/v1/environments/base.py b/fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/environments/base.py similarity index 100% rename from src/fastmcp/utilities/mcp_server_config/v1/environments/base.py rename to fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/environments/base.py diff --git a/src/fastmcp/utilities/mcp_server_config/v1/environments/uv.py b/fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/environments/uv.py similarity index 100% rename from src/fastmcp/utilities/mcp_server_config/v1/environments/uv.py rename to fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/environments/uv.py diff --git a/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py b/fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py similarity index 100% rename from src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py rename to fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py diff --git a/src/fastmcp/utilities/mcp_server_config/v1/schema.json b/fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/schema.json similarity index 100% rename from src/fastmcp/utilities/mcp_server_config/v1/schema.json rename to fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/schema.json diff --git a/src/fastmcp/utilities/mcp_server_config/v1/sources/__init__.py b/fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/sources/__init__.py similarity index 100% rename from src/fastmcp/utilities/mcp_server_config/v1/sources/__init__.py rename to fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/sources/__init__.py diff --git a/src/fastmcp/utilities/mcp_server_config/v1/sources/base.py b/fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/sources/base.py similarity index 100% rename from src/fastmcp/utilities/mcp_server_config/v1/sources/base.py rename to fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/sources/base.py diff --git a/src/fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py b/fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py similarity index 100% rename from src/fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py rename to fastmcp_slim/fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py diff --git a/src/fastmcp/utilities/mime.py b/fastmcp_slim/fastmcp/utilities/mime.py similarity index 100% rename from src/fastmcp/utilities/mime.py rename to fastmcp_slim/fastmcp/utilities/mime.py diff --git a/src/fastmcp/utilities/openapi/README.md b/fastmcp_slim/fastmcp/utilities/openapi/README.md similarity index 100% rename from src/fastmcp/utilities/openapi/README.md rename to fastmcp_slim/fastmcp/utilities/openapi/README.md diff --git a/src/fastmcp/utilities/openapi/__init__.py b/fastmcp_slim/fastmcp/utilities/openapi/__init__.py similarity index 100% rename from src/fastmcp/utilities/openapi/__init__.py rename to fastmcp_slim/fastmcp/utilities/openapi/__init__.py diff --git a/src/fastmcp/utilities/openapi/director.py b/fastmcp_slim/fastmcp/utilities/openapi/director.py similarity index 100% rename from src/fastmcp/utilities/openapi/director.py rename to fastmcp_slim/fastmcp/utilities/openapi/director.py diff --git a/src/fastmcp/utilities/openapi/formatters.py b/fastmcp_slim/fastmcp/utilities/openapi/formatters.py similarity index 100% rename from src/fastmcp/utilities/openapi/formatters.py rename to fastmcp_slim/fastmcp/utilities/openapi/formatters.py diff --git a/src/fastmcp/utilities/openapi/json_schema_converter.py b/fastmcp_slim/fastmcp/utilities/openapi/json_schema_converter.py similarity index 100% rename from src/fastmcp/utilities/openapi/json_schema_converter.py rename to fastmcp_slim/fastmcp/utilities/openapi/json_schema_converter.py diff --git a/src/fastmcp/utilities/openapi/models.py b/fastmcp_slim/fastmcp/utilities/openapi/models.py similarity index 100% rename from src/fastmcp/utilities/openapi/models.py rename to fastmcp_slim/fastmcp/utilities/openapi/models.py diff --git a/src/fastmcp/utilities/openapi/parser.py b/fastmcp_slim/fastmcp/utilities/openapi/parser.py similarity index 100% rename from src/fastmcp/utilities/openapi/parser.py rename to fastmcp_slim/fastmcp/utilities/openapi/parser.py diff --git a/src/fastmcp/utilities/openapi/schemas.py b/fastmcp_slim/fastmcp/utilities/openapi/schemas.py similarity index 100% rename from src/fastmcp/utilities/openapi/schemas.py rename to fastmcp_slim/fastmcp/utilities/openapi/schemas.py diff --git a/src/fastmcp/utilities/pagination.py b/fastmcp_slim/fastmcp/utilities/pagination.py similarity index 100% rename from src/fastmcp/utilities/pagination.py rename to fastmcp_slim/fastmcp/utilities/pagination.py diff --git a/src/fastmcp/utilities/skills.py b/fastmcp_slim/fastmcp/utilities/skills.py similarity index 100% rename from src/fastmcp/utilities/skills.py rename to fastmcp_slim/fastmcp/utilities/skills.py diff --git a/src/fastmcp/utilities/tests.py b/fastmcp_slim/fastmcp/utilities/tests.py similarity index 100% rename from src/fastmcp/utilities/tests.py rename to fastmcp_slim/fastmcp/utilities/tests.py diff --git a/src/fastmcp/utilities/timeout.py b/fastmcp_slim/fastmcp/utilities/timeout.py similarity index 100% rename from src/fastmcp/utilities/timeout.py rename to fastmcp_slim/fastmcp/utilities/timeout.py diff --git a/src/fastmcp/utilities/token_cache.py b/fastmcp_slim/fastmcp/utilities/token_cache.py similarity index 100% rename from src/fastmcp/utilities/token_cache.py rename to fastmcp_slim/fastmcp/utilities/token_cache.py diff --git a/src/fastmcp/utilities/types.py b/fastmcp_slim/fastmcp/utilities/types.py similarity index 100% rename from src/fastmcp/utilities/types.py rename to fastmcp_slim/fastmcp/utilities/types.py diff --git a/src/fastmcp/utilities/ui.py b/fastmcp_slim/fastmcp/utilities/ui.py similarity index 100% rename from src/fastmcp/utilities/ui.py rename to fastmcp_slim/fastmcp/utilities/ui.py diff --git a/src/fastmcp/utilities/version_check.py b/fastmcp_slim/fastmcp/utilities/version_check.py similarity index 100% rename from src/fastmcp/utilities/version_check.py rename to fastmcp_slim/fastmcp/utilities/version_check.py diff --git a/src/fastmcp/utilities/versions.py b/fastmcp_slim/fastmcp/utilities/versions.py similarity index 100% rename from src/fastmcp/utilities/versions.py rename to fastmcp_slim/fastmcp/utilities/versions.py diff --git a/fastmcp_slim/pyproject.toml b/fastmcp_slim/pyproject.toml new file mode 100644 index 000000000..0f69170f7 --- /dev/null +++ b/fastmcp_slim/pyproject.toml @@ -0,0 +1,117 @@ +[project] +name = "fastmcp-slim" +dynamic = ["version"] +description = "The dependency-slim FastMCP package." +authors = [{ name = "Jeremiah Lowin" }] +dependencies = [ + "platformdirs>=4.0.0", + "pydantic[email]>=2.11.7", + "pydantic-settings>=2.0.0", + "python-dotenv>=1.1.0", + "rich>=13.9.4", + "typing-extensions>=4.0.0", +] + +requires-python = ">=3.10" +readme = "README.md" +license = "Apache-2.0" + +keywords = [ + "mcp", + "mcp server", + "mcp client", + "model context protocol", + "fastmcp", + "llm", + "agent", +] +classifiers = [ + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Typing :: Typed", +] + +[project.optional-dependencies] +anthropic = ["anthropic>=0.48.0"] +apps = ["prefab-ui>=0.18.0"] +# PyJWT floor: transitive via msal; CVE-2026-32597 affects <= 2.11.0 +azure = ["azure-identity>=1.16.0", "PyJWT>=2.12.0"] +client = [ + "authlib>=1.6.11", + "exceptiongroup>=1.2.2", + "httpx>=0.28.1,<1.0", + "mcp>=1.24.0,<2.0", + "opentelemetry-api>=1.20.0", + "py-key-value-aio[filetree,keyring,memory]>=0.4.4,<0.5.0", +] +code-mode = ["pydantic-monty==0.0.16"] +gemini = ["google-genai>=1.18.0", "jsonref>=1.1.0"] +full = [ + "authlib>=1.6.11", + "cyclopts>=4.0.0", + "exceptiongroup>=1.2.2", + "griffelib>=2.0.0", + "httpx>=0.28.1,<1.0", + "jsonref>=1.1.0", + "jsonschema-path>=0.3.4", + "mcp>=1.24.0,<2.0", + "openapi-pydantic>=0.5.1", + "opentelemetry-api>=1.20.0", + "packaging>=24.0", + "py-key-value-aio[filetree,keyring,memory]>=0.4.4,<0.5.0", + "pyperclip>=1.9.0", + "python-multipart>=0.0.26", + "pyyaml>=6.0,<7.0", + "uncalled-for>=0.2.0", + "uvicorn>=0.35", + "watchfiles>=1.0.0", + "websockets>=15.0.1", +] +openai = ["openai>=1.102.0"] +server = [ + "authlib>=1.6.11", + "exceptiongroup>=1.2.2", + "griffelib>=2.0.0", + "httpx>=0.28.1,<1.0", + "jsonref>=1.1.0", + "jsonschema-path>=0.3.4", + "mcp>=1.24.0,<2.0", + "openapi-pydantic>=0.5.1", + "opentelemetry-api>=1.20.0", + "packaging>=24.0", + "py-key-value-aio[filetree,keyring,memory]>=0.4.4,<0.5.0", + "python-multipart>=0.0.26", + "pyyaml>=6.0,<7.0", + "uncalled-for>=0.2.0", + "uvicorn>=0.35", + "watchfiles>=1.0.0", + "websockets>=15.0.1", +] +tasks = ["pydocket>=0.20.0"] + +[project.urls] +Homepage = "https://gofastmcp.com" +Repository = "https://github.com/PrefectHQ/fastmcp" +Documentation = "https://gofastmcp.com" + +[build-system] +requires = ["hatchling", "uv-dynamic-versioning>=0.7.0"] +build-backend = "hatchling.build" + +[tool.hatch.version] +source = "uv-dynamic-versioning" + +[tool.hatch.build.targets.wheel] +packages = ["fastmcp"] + + +[tool.uv-dynamic-versioning] +vcs = "git" +style = "pep440" +bump = true +fallback-version = "0.0.0" diff --git a/justfile b/justfile index 8c601a16c..2876e6f33 100644 --- a/justfile +++ b/justfile @@ -1,3 +1,5 @@ +api_ref_package := "fastmcp-slim[anthropic,apps,azure,code-mode,full,gemini,openai,tasks] @ file://" + justfile_directory() + "/fastmcp_slim" + # Build the project build: uv sync @@ -20,14 +22,14 @@ docs-broken-links: # Generate API reference documentation for all modules api-ref-all: - uvx --with-editable . --refresh-package mdxify mdxify@latest --all --root-module fastmcp --nav-output docs/python-sdk-pages.json --exclude fastmcp.contrib + uvx --with-editable "{{api_ref_package}}" --refresh-package mdxify mdxify@latest --all --root-module fastmcp --nav-output docs/python-sdk-pages.json --exclude fastmcp.contrib # Generate API reference for specific modules (e.g., just api-ref prefect.flows prefect.tasks) api-ref *MODULES: - uvx --with-editable . --refresh-package mdxify mdxify@latest {{MODULES}} --root-module fastmcp --nav-output docs/python-sdk-pages.json + uvx --with-editable "{{api_ref_package}}" --refresh-package mdxify mdxify@latest {{MODULES}} --root-module fastmcp --nav-output docs/python-sdk-pages.json # Clean up API reference documentation api-ref-clean: rm -rf docs/python-sdk copy-context: - uvx --with-editable . --refresh-package copychat copychat@latest src/ docs/ -x changelog.mdx -x python-sdk/ -v \ No newline at end of file + uvx --with-editable fastmcp_slim --refresh-package copychat copychat@latest fastmcp_slim/fastmcp docs/ -x changelog.mdx -x python-sdk/ -v diff --git a/loq.toml b/loq.toml index f1ac457ab..18f31e50f 100644 --- a/loq.toml +++ b/loq.toml @@ -11,35 +11,35 @@ path = "tests/**" max_lines = 1000 [[rules]] -path = "src/fastmcp/server/context.py" +path = "fastmcp_slim/fastmcp/server/context.py" max_lines = 1404 [[rules]] -path = "src/fastmcp/server/server.py" +path = "fastmcp_slim/fastmcp/server/server.py" max_lines = 2410 [[rules]] -path = "src/fastmcp/server/auth/oauth_proxy/proxy.py" +path = "fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py" max_lines = 2098 [[rules]] -path = "src/fastmcp/cli/apps_dev.py" +path = "fastmcp_slim/fastmcp/cli/apps_dev.py" max_lines = 1814 [[rules]] -path = "src/fastmcp/cli/cli.py" +path = "fastmcp_slim/fastmcp/cli/cli.py" max_lines = 1116 [[rules]] -path = "src/fastmcp/server/dependencies.py" +path = "fastmcp_slim/fastmcp/server/dependencies.py" max_lines = 1686 [[rules]] -path = "src/fastmcp/server/providers/proxy.py" +path = "fastmcp_slim/fastmcp/server/providers/proxy.py" max_lines = 1096 [[rules]] -path = "src/fastmcp/tools/tool_transform.py" +path = "fastmcp_slim/fastmcp/tools/tool_transform.py" max_lines = 1004 [[rules]] diff --git a/pyproject.toml b/pyproject.toml index c24f08e02..5e1cee944 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,38 +1,11 @@ [project] name = "fastmcp" -dynamic = ["version"] +dynamic = ["version", "dependencies", "optional-dependencies"] description = "The fast, Pythonic way to build MCP servers and clients." authors = [{ name = "Jeremiah Lowin" }] -dependencies = [ - "python-dotenv>=1.1.0", - "exceptiongroup>=1.2.2", - "httpx>=0.28.1,<1.0", - "mcp>=1.24.0,<2.0", - "openapi-pydantic>=0.5.1", - "opentelemetry-api>=1.20.0", - "packaging>=24.0", - "platformdirs>=4.0.0", - "rich>=13.9.4", - "cyclopts>=4.0.0", - "authlib>=1.6.11", - "pydantic[email]>=2.11.7", - "pyyaml>=6.0,<7.0", - "pyperclip>=1.9.0", - "py-key-value-aio[filetree,keyring,memory]>=0.4.4,<0.5.0", - "python-multipart>=0.0.26", - "uvicorn>=0.35", - "websockets>=15.0.1", - "jsonschema-path>=0.3.4", - "jsonref>=1.1.0", - "uncalled-for>=0.2.0", - "watchfiles>=1.0.0", - "griffelib>=2.0.0", -] - requires-python = ">=3.10" readme = "README.md" license = "Apache-2.0" - keywords = [ "mcp", "mcp server", @@ -53,21 +26,55 @@ classifiers = [ "Typing :: Typed", ] -[project.optional-dependencies] -anthropic = ["anthropic>=0.48.0"] -apps = ["prefab-ui>=0.18.0"] -# PyJWT floor: transitive via msal; CVE-2026-32597 affects <= 2.11.0 -azure = ["azure-identity>=1.16.0", "PyJWT>=2.12.0"] -code-mode = ["pydantic-monty==0.0.16"] -gemini = ["google-genai>=1.18.0"] -openai = ["openai>=1.102.0"] -tasks = ["pydocket>=0.20.0"] +[project.urls] +Homepage = "https://gofastmcp.com" +Repository = "https://github.com/PrefectHQ/fastmcp" +Documentation = "https://gofastmcp.com" + +[project.scripts] +fastmcp = "fastmcp.cli:app" + +[build-system] +requires = ["hatchling", "uv-dynamic-versioning>=0.7.0"] +build-backend = "hatchling.build" + +[tool.hatch.version] +source = "uv-dynamic-versioning" + +[tool.hatch.build.targets.wheel] +bypass-selection = true + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.metadata.hooks.uv-dynamic-versioning] +dependencies = ["fastmcp-slim[full]=={{ version }}"] + +[tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies] +anthropic = ["fastmcp-slim[full,anthropic]=={{ version }}"] +apps = ["fastmcp-slim[full,apps]=={{ version }}"] +azure = ["fastmcp-slim[full,azure]=={{ version }}"] +code-mode = ["fastmcp-slim[full,code-mode]=={{ version }}"] +gemini = ["fastmcp-slim[full,gemini]=={{ version }}"] +openai = ["fastmcp-slim[full,openai]=={{ version }}"] +tasks = ["fastmcp-slim[full,tasks]=={{ version }}"] + +[tool.uv-dynamic-versioning] +vcs = "git" +style = "pep440" +bump = true +fallback-version = "0.0.0" + +[tool.uv.workspace] +members = ["fastmcp_slim"] + +[tool.uv] +default-groups = ["dev"] [dependency-groups] dev = [ "dirty-equals>=0.9.0", "fastmcp[anthropic,apps,azure,code-mode,gemini,openai,tasks]", - # add optional dependencies for fastmcp dev "fastapi>=0.115.12", "opentelemetry-sdk>=1.20.0", "inline-snapshot[dirty-equals]>=0.27.2", @@ -94,40 +101,15 @@ dev = [ "pytest-examples>=0.0.18", ] -[project.scripts] -fastmcp = "fastmcp.cli:app" - -[project.urls] -Homepage = "https://gofastmcp.com" -Repository = "https://github.com/PrefectHQ/fastmcp" -Documentation = "https://gofastmcp.com" - -[build-system] -requires = ["hatchling", "uv-dynamic-versioning>=0.7.0"] -build-backend = "hatchling.build" - -[tool.hatch.version] -source = "uv-dynamic-versioning" - -[tool.hatch.metadata] -allow-direct-references = true - - -[tool.uv-dynamic-versioning] -vcs = "git" -style = "pep440" -bump = true -fallback-version = "0.0.0" +[tool.uv.sources] +fastmcp = { workspace = true } +fastmcp-slim = { workspace = true } [tool.pytest.ini_options] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" -# filterwarnings = ["error::DeprecationWarning"] filterwarnings = [ - # Suppress OAuth in-memory token storage warnings in tests - # Tests intentionally use ephemeral storage; this warning is for end users "ignore:Using in-memory token storage:UserWarning", - # Treat unawaited coroutine warnings as errors - these are almost always bugs "error:coroutine .* was never awaited:RuntimeWarning", "error:Exception ignored in.*coroutine:pytest.PytestUnraisableExceptionWarning", ] @@ -136,15 +118,13 @@ env = [ "FASTMCP_TEST_MODE=1", 'D:FASTMCP_LOG_LEVEL=DEBUG', 'D:FASTMCP_ENABLE_RICH_TRACEBACKS=0', - ] markers = [ "integration: marks tests as integration tests (deselect with '-m \"not integration\"')", "client_process: marks tests that spawn client processes via stdio transport. These can create issues when run in the same CI environment as other subprocess-based tests.", "conformance: marks MCP conformance tests (require Node.js/npx)", ] -# Automatically mark all tests in integration_tests folder -pythonpath = ["."] +pythonpath = ["fastmcp_slim"] testpaths = ["tests"] python_files = ["test_*.py", "*_test.py"] python_classes = ["Test*"] @@ -152,19 +132,13 @@ python_functions = ["test_*"] addopts = ["--inline-snapshot=disable"] [tool.ty.src] -include = ["src", "tests"] +include = ["fastmcp_slim", "tests"] exclude = ["**/node_modules", "**/__pycache__", ".venv", ".git", "dist"] [tool.ty.environment] python-version = "3.10" [tool.ty.rules] -# NOTE: ty currently doesn't support type narrowing with isinstance() on unions -# See: https://github.com/astral-sh/ty/issues/122 and https://github.com/astral-sh/ty/issues/1113 -# Some code uses `# ty: ignore[invalid-argument-type]` for this limitation. -# TODO: Remove these ignores once ty supports union narrowing - -# Promote rules from default-ignore to warn (becomes error via error-on-warning) division-by-zero = "warn" possibly-missing-attribute = "warn" possibly-missing-import = "warn" @@ -180,31 +154,31 @@ error-on-warning = true fixable = ["ALL"] ignore = [ "COM812", - "PERF203", # try-except in loop — all existing hits are intentional (retry loops, error skipping) - "PLR0913", # Too many arguments, MCP Servers have a lot of arguments, OKAY?! - "SIM102", # Dont require combining if statements + "PERF203", + "PLR0913", + "SIM102", ] extend-select = [ - "B", # flake8-bugbear: Catches actual bugs like mutable default arguments - "C4", # flake8-comprehensions: More efficient/readable comprehensions - "DTZ", # flake8-datetimez: Enforce timezone-aware datetime usage - "ERA", # eradicate: Detect commented-out code - "FA", # flake8-future-annotations: Enforce from __future__ import annotations - "FLY", # flynt: Static string joins that should be f-strings - "I", # isort: Import sorting - "INP", # flake8-no-pep420: Require __init__.py in namespace packages - "ISC", # flake8-implicit-str-concat: Prevent accidental string concatenation - "LOG", # flake8-logging: Catches logging module misuse - "PERF", # perflint: Performance anti-patterns (unnecessary copies, allocations) - "PIE", # flake8-pie: More idiomatic Python code - "PLE", # pylint-error: Catches actual errors (invalid operations, syntax issues) - "RSE", # flake8-raise: Unnecessary parentheses on raise - "RUF", # Ruff-specific: Modern best practices unique to Ruff - "SIM", # flake8-simplify: Simplifies verbose code patterns - "SLOT", # flake8-slots: Enforce __slots__ where applicable - "T20", # flake8-print: Catch accidental print() in library code - "TID", # flake8-tidy-imports: Banned imports and relative import enforcement - "UP", # pyupgrade: Modernize syntax for newer Python versions + "B", + "C4", + "DTZ", + "ERA", + "FA", + "FLY", + "I", + "INP", + "ISC", + "LOG", + "PERF", + "PIE", + "PLE", + "RSE", + "RUF", + "SIM", + "SLOT", + "T20", + "TID", + "UP", ] [tool.ruff.lint.isort] @@ -212,33 +186,30 @@ known-first-party = ["fastmcp"] [tool.ruff.lint.per-file-ignores] "__init__.py" = ["F401", "I001", "RUF013"] -# allow imports not at the top of the file -"src/fastmcp/__init__.py" = ["E402"] -# CLI and example code legitimately uses print() for user-facing output -"src/fastmcp/cli/**.py" = ["T20"] -"src/fastmcp/client/oauth_callback.py" = ["T20"] -"src/fastmcp/contrib/**/example.py" = ["T20"] -"!src/**.py" = [ # Only enforce extended ruff rules for code in src/ - "B", # flake8-bugbear - "C4", # flake8-comprehensions - "DTZ", # flake8-datetimez - "ERA", # eradicate - "FA", # flake8-future-annotations - "FLY", # flynt - "INP", # flake8-no-pep420 - "ISC", # flake8-implicit-str-concat - "LOG", # flake8-logging - "PERF", # perflint - "PIE", # flake8-pie - "PLE", # pylint-error - "RSE", # flake8-raise - "RUF", # Ruff-specific - "SIM", # flake8-simplify - "SLOT", # flake8-slots - "T20", # flake8-print - "TID", # flake8-tidy-imports +"fastmcp_slim/fastmcp/__init__.py" = ["E402"] +"fastmcp_slim/fastmcp/cli/**.py" = ["T20"] +"fastmcp_slim/fastmcp/client/oauth_callback.py" = ["T20"] +"fastmcp_slim/fastmcp/contrib/**/example.py" = ["T20"] +"!fastmcp_slim/fastmcp/**.py" = [ + "B", + "C4", + "DTZ", + "ERA", + "FA", + "FLY", + "INP", + "ISC", + "LOG", + "PERF", + "PIE", + "PLE", + "RSE", + "RUF", + "SIM", + "SLOT", + "T20", + "TID", ] - [tool.codespell] ignore-words-list = "asend,shttp,te" diff --git a/src/fastmcp/__init__.py b/src/fastmcp/__init__.py deleted file mode 100644 index 3208b064a..000000000 --- a/src/fastmcp/__init__.py +++ /dev/null @@ -1,59 +0,0 @@ -"""FastMCP - An ergonomic MCP interface.""" - -import importlib -import warnings -from importlib.metadata import version as _version -from typing import TYPE_CHECKING - -from fastmcp.settings import Settings -from fastmcp.utilities.logging import configure_logging as _configure_logging - -if TYPE_CHECKING: - from fastmcp.client import Client as Client - from fastmcp.apps.app import FastMCPApp as FastMCPApp - -settings = Settings() -if settings.log_enabled: - _configure_logging( - level=settings.log_level, - enable_rich_tracebacks=settings.enable_rich_tracebacks, - ) - -from fastmcp.exceptions import FastMCPDeprecationWarning -from fastmcp.server.server import FastMCP -from fastmcp.server.context import Context -import fastmcp.server - -__version__ = _version("fastmcp") - -if settings.deprecation_warnings: - warnings.simplefilter("default", FastMCPDeprecationWarning) - - -# --- Lazy imports for performance (see #3292) --- -# Client and the client submodule are deferred so that server-only users -# don't pay for the client import chain. Do not convert back to top-level. - - -def __getattr__(name: str) -> object: - if name == "Client": - from fastmcp.client import Client - - return Client - if name == "FastMCPApp": - from fastmcp.apps.app import FastMCPApp - - return FastMCPApp - if name == "client": - return importlib.import_module("fastmcp.client") - raise AttributeError(f"module {__name__!r} has no attribute {name!r}") - - -__all__ = [ - "Client", - "Context", - "FastMCP", - "FastMCPApp", - "FastMCPDeprecationWarning", - "settings", -] diff --git a/src/fastmcp/client/__init__.py b/src/fastmcp/client/__init__.py deleted file mode 100644 index e7e638176..000000000 --- a/src/fastmcp/client/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -from .auth import OAuth, BearerAuth -from .client import Client -from .transports import ( - ClientTransport, - FastMCPTransport, - NodeStdioTransport, - NpxStdioTransport, - PythonStdioTransport, - SSETransport, - StdioTransport, - StreamableHttpTransport, - UvStdioTransport, - UvxStdioTransport, -) - -__all__ = [ - "BearerAuth", - "Client", - "ClientTransport", - "FastMCPTransport", - "NodeStdioTransport", - "NpxStdioTransport", - "OAuth", - "PythonStdioTransport", - "SSETransport", - "StdioTransport", - "StreamableHttpTransport", - "UvStdioTransport", - "UvxStdioTransport", -] diff --git a/tests/client/test_slim_package_boundaries.py b/tests/client/test_slim_package_boundaries.py new file mode 100644 index 000000000..5c6a4b073 --- /dev/null +++ b/tests/client/test_slim_package_boundaries.py @@ -0,0 +1,61 @@ +from __future__ import annotations + +import builtins +import contextlib +import types +from collections.abc import Mapping, Sequence +from typing import Any, cast + +import pytest + + +@contextlib.contextmanager +def block_server_imports(): + original_import = builtins.__import__ + + def blocked_import( + name: str, + globals: Mapping[str, object] | None = None, + locals: Mapping[str, object] | None = None, + fromlist: Sequence[str] | None = (), + level: int = 0, + ) -> types.ModuleType: + if level == 0 and ( + name == "fastmcp.server" or name.startswith("fastmcp.server.") + ): + raise ImportError(f"blocked server import: {name}") + return original_import(name, globals, locals, fromlist, level) + + cast(Any, builtins).__import__ = blocked_import + try: + yield + finally: + cast(Any, builtins).__import__ = original_import + + +def test_client_http_headers_do_not_require_server() -> None: + from fastmcp.client.dependencies import get_http_headers + + with block_server_imports(): + assert get_http_headers(include_all=True) == {} + + +@pytest.mark.asyncio +async def test_multiserver_config_requires_server_for_now() -> None: + from fastmcp.client.transports import MCPConfigTransport + + with block_server_imports(): + transport = MCPConfigTransport( + { + "mcpServers": { + "one": {"command": "uvx", "args": ["one"]}, + "two": {"command": "uvx", "args": ["two"]}, + } + } + ) + + with pytest.raises( + ImportError, match="multiple servers require the full `fastmcp`" + ): + async with transport.connect_session(): + pass diff --git a/tests/client/transports/test_uv_transport.py b/tests/client/transports/test_uv_transport.py index 8c2a500fd..8b27babe0 100644 --- a/tests/client/transports/test_uv_transport.py +++ b/tests/client/transports/test_uv_transport.py @@ -94,7 +94,7 @@ async def test_uv_transport_module(): "--directory", tmpdir, "--with-editable", - str(_fastmcp_src_dir), + f"{_fastmcp_src_dir}[server]", "--module", "my_module", ], diff --git a/tests/utilities/json_schema_type/cluster_failures.py b/tests/utilities/json_schema_type/cluster_failures.py index bb9cbc3cd..5c6b44005 100644 --- a/tests/utilities/json_schema_type/cluster_failures.py +++ b/tests/utilities/json_schema_type/cluster_failures.py @@ -34,7 +34,7 @@ Workflow for fixing a cluster 2. Grab the example schema from the cluster output. 3. Reproduce in a unit test: add a test to test_json_schema_type.py that calls json_schema_to_type() with that schema and asserts the correct type is returned. -4. Fix the root cause in src/fastmcp/utilities/json_schema_type.py. +4. Fix the root cause in fastmcp_slim/fastmcp/utilities/json_schema_type.py. 5. Re-run the crash test — confirm the cluster count drops. 6. Ratchet the baseline in tests/utilities/json_schema_type/conftest.py: - Lower MAX_TYPE_ERRORS / MAX_SCHEMA_ERRORS to the new actual count. diff --git a/uv.lock b/uv.lock index 1f560aa5c..5246f4cc7 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.14'", @@ -9,6 +9,12 @@ resolution-markers = [ "python_full_version < '3.11'", ] +[manifest] +members = [ + "fastmcp", + "fastmcp-slim", +] + [[package]] name = "aiofile" version = "3.9.0" @@ -824,53 +830,30 @@ wheels = [ name = "fastmcp" source = { editable = "." } dependencies = [ - { name = "authlib" }, - { name = "cyclopts" }, - { name = "exceptiongroup" }, - { name = "griffelib" }, - { name = "httpx" }, - { name = "jsonref" }, - { name = "jsonschema-path" }, - { name = "mcp" }, - { name = "openapi-pydantic" }, - { name = "opentelemetry-api" }, - { name = "packaging" }, - { name = "platformdirs" }, - { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, - { name = "pydantic", extra = ["email"] }, - { name = "pyperclip" }, - { name = "python-dotenv" }, - { name = "python-multipart" }, - { name = "pyyaml" }, - { name = "rich" }, - { name = "uncalled-for" }, - { name = "uvicorn" }, - { name = "watchfiles" }, - { name = "websockets" }, + { name = "fastmcp-slim", extra = ["full"] }, ] [package.optional-dependencies] anthropic = [ - { name = "anthropic" }, + { name = "fastmcp-slim", extra = ["anthropic", "full"] }, ] apps = [ - { name = "prefab-ui" }, + { name = "fastmcp-slim", extra = ["apps", "full"] }, ] azure = [ - { name = "azure-identity" }, - { name = "pyjwt" }, + { name = "fastmcp-slim", extra = ["azure", "full"] }, ] code-mode = [ - { name = "pydantic-monty" }, + { name = "fastmcp-slim", extra = ["code-mode", "full"] }, ] gemini = [ - { name = "google-genai" }, + { name = "fastmcp-slim", extra = ["full", "gemini"] }, ] openai = [ - { name = "openai" }, + { name = "fastmcp-slim", extra = ["full", "openai"] }, ] tasks = [ - { name = "pydocket" }, + { name = "fastmcp-slim", extra = ["full", "tasks"] }, ] [package.dev-dependencies] @@ -907,37 +890,14 @@ dev = [ [package.metadata] requires-dist = [ - { name = "anthropic", marker = "extra == 'anthropic'", specifier = ">=0.48.0" }, - { name = "authlib", specifier = ">=1.6.11" }, - { name = "azure-identity", marker = "extra == 'azure'", specifier = ">=1.16.0" }, - { name = "cyclopts", specifier = ">=4.0.0" }, - { name = "exceptiongroup", specifier = ">=1.2.2" }, - { name = "google-genai", marker = "extra == 'gemini'", specifier = ">=1.18.0" }, - { name = "griffelib", specifier = ">=2.0.0" }, - { name = "httpx", specifier = ">=0.28.1,<1.0" }, - { name = "jsonref", specifier = ">=1.1.0" }, - { name = "jsonschema-path", specifier = ">=0.3.4" }, - { name = "mcp", specifier = ">=1.24.0,<2.0" }, - { name = "openai", marker = "extra == 'openai'", specifier = ">=1.102.0" }, - { name = "openapi-pydantic", specifier = ">=0.5.1" }, - { name = "opentelemetry-api", specifier = ">=1.20.0" }, - { name = "packaging", specifier = ">=24.0" }, - { name = "platformdirs", specifier = ">=4.0.0" }, - { name = "prefab-ui", marker = "extra == 'apps'", specifier = ">=0.18.0" }, - { name = "py-key-value-aio", extras = ["filetree", "keyring", "memory"], specifier = ">=0.4.4,<0.5.0" }, - { name = "pydantic", extras = ["email"], specifier = ">=2.11.7" }, - { name = "pydantic-monty", marker = "extra == 'code-mode'", specifier = "==0.0.16" }, - { name = "pydocket", marker = "extra == 'tasks'", specifier = ">=0.20.0" }, - { name = "pyjwt", marker = "extra == 'azure'", specifier = ">=2.12.0" }, - { name = "pyperclip", specifier = ">=1.9.0" }, - { name = "python-dotenv", specifier = ">=1.1.0" }, - { name = "python-multipart", specifier = ">=0.0.26" }, - { name = "pyyaml", specifier = ">=6.0,<7.0" }, - { name = "rich", specifier = ">=13.9.4" }, - { name = "uncalled-for", specifier = ">=0.2.0" }, - { name = "uvicorn", specifier = ">=0.35" }, - { name = "watchfiles", specifier = ">=1.0.0" }, - { name = "websockets", specifier = ">=15.0.1" }, + { name = "fastmcp-slim", extras = ["anthropic", "full"], marker = "extra == 'anthropic'", editable = "fastmcp_slim" }, + { name = "fastmcp-slim", extras = ["apps", "full"], marker = "extra == 'apps'", editable = "fastmcp_slim" }, + { name = "fastmcp-slim", extras = ["azure", "full"], marker = "extra == 'azure'", editable = "fastmcp_slim" }, + { name = "fastmcp-slim", extras = ["code-mode", "full"], marker = "extra == 'code-mode'", editable = "fastmcp_slim" }, + { name = "fastmcp-slim", extras = ["full"], editable = "fastmcp_slim" }, + { name = "fastmcp-slim", extras = ["full", "gemini"], marker = "extra == 'gemini'", editable = "fastmcp_slim" }, + { name = "fastmcp-slim", extras = ["full", "openai"], marker = "extra == 'openai'", editable = "fastmcp_slim" }, + { name = "fastmcp-slim", extras = ["full", "tasks"], marker = "extra == 'tasks'", editable = "fastmcp_slim" }, ] provides-extras = ["anthropic", "apps", "azure", "code-mode", "gemini", "openai", "tasks"] @@ -945,7 +905,7 @@ provides-extras = ["anthropic", "apps", "azure", "code-mode", "gemini", "openai" dev = [ { name = "dirty-equals", specifier = ">=0.9.0" }, { name = "fastapi", specifier = ">=0.115.12" }, - { name = "fastmcp", extras = ["anthropic", "apps", "azure", "code-mode", "gemini", "openai", "tasks"] }, + { name = "fastmcp", extras = ["anthropic", "apps", "azure", "code-mode", "gemini", "openai", "tasks"], editable = "." }, { name = "inline-snapshot", extras = ["dirty-equals"], specifier = ">=0.27.2" }, { name = "ipython", specifier = ">=8.12.3" }, { name = "loq", specifier = ">=0.1.0a3" }, @@ -971,6 +931,153 @@ dev = [ { name = "ty", specifier = ">=0.0.29" }, ] +[[package]] +name = "fastmcp-slim" +source = { editable = "fastmcp_slim" } +dependencies = [ + { name = "platformdirs" }, + { name = "pydantic", extra = ["email"] }, + { name = "pydantic-settings" }, + { name = "python-dotenv" }, + { name = "rich" }, + { name = "typing-extensions" }, +] + +[package.optional-dependencies] +anthropic = [ + { name = "anthropic" }, +] +apps = [ + { name = "prefab-ui" }, +] +azure = [ + { name = "azure-identity" }, + { name = "pyjwt" }, +] +client = [ + { name = "authlib" }, + { name = "exceptiongroup" }, + { name = "httpx" }, + { name = "mcp" }, + { name = "opentelemetry-api" }, + { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, +] +code-mode = [ + { name = "pydantic-monty" }, +] +full = [ + { name = "authlib" }, + { name = "cyclopts" }, + { name = "exceptiongroup" }, + { name = "griffelib" }, + { name = "httpx" }, + { name = "jsonref" }, + { name = "jsonschema-path" }, + { name = "mcp" }, + { name = "openapi-pydantic" }, + { name = "opentelemetry-api" }, + { name = "packaging" }, + { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, + { name = "pyperclip" }, + { name = "python-multipart" }, + { name = "pyyaml" }, + { name = "uncalled-for" }, + { name = "uvicorn" }, + { name = "watchfiles" }, + { name = "websockets" }, +] +gemini = [ + { name = "google-genai" }, + { name = "jsonref" }, +] +openai = [ + { name = "openai" }, +] +server = [ + { name = "authlib" }, + { name = "exceptiongroup" }, + { name = "griffelib" }, + { name = "httpx" }, + { name = "jsonref" }, + { name = "jsonschema-path" }, + { name = "mcp" }, + { name = "openapi-pydantic" }, + { name = "opentelemetry-api" }, + { name = "packaging" }, + { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, + { name = "python-multipart" }, + { name = "pyyaml" }, + { name = "uncalled-for" }, + { name = "uvicorn" }, + { name = "watchfiles" }, + { name = "websockets" }, +] +tasks = [ + { name = "pydocket" }, +] + +[package.metadata] +requires-dist = [ + { name = "anthropic", marker = "extra == 'anthropic'", specifier = ">=0.48.0" }, + { name = "authlib", marker = "extra == 'client'", specifier = ">=1.6.11" }, + { name = "authlib", marker = "extra == 'full'", specifier = ">=1.6.11" }, + { name = "authlib", marker = "extra == 'server'", specifier = ">=1.6.11" }, + { name = "azure-identity", marker = "extra == 'azure'", specifier = ">=1.16.0" }, + { name = "cyclopts", marker = "extra == 'full'", specifier = ">=4.0.0" }, + { name = "exceptiongroup", marker = "extra == 'client'", specifier = ">=1.2.2" }, + { name = "exceptiongroup", marker = "extra == 'full'", specifier = ">=1.2.2" }, + { name = "exceptiongroup", marker = "extra == 'server'", specifier = ">=1.2.2" }, + { name = "google-genai", marker = "extra == 'gemini'", specifier = ">=1.18.0" }, + { name = "griffelib", marker = "extra == 'full'", specifier = ">=2.0.0" }, + { name = "griffelib", marker = "extra == 'server'", specifier = ">=2.0.0" }, + { name = "httpx", marker = "extra == 'client'", specifier = ">=0.28.1,<1.0" }, + { name = "httpx", marker = "extra == 'full'", specifier = ">=0.28.1,<1.0" }, + { name = "httpx", marker = "extra == 'server'", specifier = ">=0.28.1,<1.0" }, + { name = "jsonref", marker = "extra == 'full'", specifier = ">=1.1.0" }, + { name = "jsonref", marker = "extra == 'gemini'", specifier = ">=1.1.0" }, + { name = "jsonref", marker = "extra == 'server'", specifier = ">=1.1.0" }, + { name = "jsonschema-path", marker = "extra == 'full'", specifier = ">=0.3.4" }, + { name = "jsonschema-path", marker = "extra == 'server'", specifier = ">=0.3.4" }, + { name = "mcp", marker = "extra == 'client'", specifier = ">=1.24.0,<2.0" }, + { name = "mcp", marker = "extra == 'full'", specifier = ">=1.24.0,<2.0" }, + { name = "mcp", marker = "extra == 'server'", specifier = ">=1.24.0,<2.0" }, + { name = "openai", marker = "extra == 'openai'", specifier = ">=1.102.0" }, + { name = "openapi-pydantic", marker = "extra == 'full'", specifier = ">=0.5.1" }, + { name = "openapi-pydantic", marker = "extra == 'server'", specifier = ">=0.5.1" }, + { name = "opentelemetry-api", marker = "extra == 'client'", specifier = ">=1.20.0" }, + { name = "opentelemetry-api", marker = "extra == 'full'", specifier = ">=1.20.0" }, + { name = "opentelemetry-api", marker = "extra == 'server'", specifier = ">=1.20.0" }, + { name = "packaging", marker = "extra == 'full'", specifier = ">=24.0" }, + { name = "packaging", marker = "extra == 'server'", specifier = ">=24.0" }, + { name = "platformdirs", specifier = ">=4.0.0" }, + { name = "prefab-ui", marker = "extra == 'apps'", specifier = ">=0.18.0" }, + { name = "py-key-value-aio", extras = ["filetree", "keyring", "memory"], marker = "extra == 'client'", specifier = ">=0.4.4,<0.5.0" }, + { name = "py-key-value-aio", extras = ["filetree", "keyring", "memory"], marker = "extra == 'full'", specifier = ">=0.4.4,<0.5.0" }, + { name = "py-key-value-aio", extras = ["filetree", "keyring", "memory"], marker = "extra == 'server'", specifier = ">=0.4.4,<0.5.0" }, + { name = "pydantic", extras = ["email"], specifier = ">=2.11.7" }, + { name = "pydantic-monty", marker = "extra == 'code-mode'", specifier = "==0.0.16" }, + { name = "pydantic-settings", specifier = ">=2.0.0" }, + { name = "pydocket", marker = "extra == 'tasks'", specifier = ">=0.20.0" }, + { name = "pyjwt", marker = "extra == 'azure'", specifier = ">=2.12.0" }, + { name = "pyperclip", marker = "extra == 'full'", specifier = ">=1.9.0" }, + { name = "python-dotenv", specifier = ">=1.1.0" }, + { name = "python-multipart", marker = "extra == 'full'", specifier = ">=0.0.26" }, + { name = "python-multipart", marker = "extra == 'server'", specifier = ">=0.0.26" }, + { name = "pyyaml", marker = "extra == 'full'", specifier = ">=6.0,<7.0" }, + { name = "pyyaml", marker = "extra == 'server'", specifier = ">=6.0,<7.0" }, + { name = "rich", specifier = ">=13.9.4" }, + { name = "typing-extensions", specifier = ">=4.0.0" }, + { name = "uncalled-for", marker = "extra == 'full'", specifier = ">=0.2.0" }, + { name = "uncalled-for", marker = "extra == 'server'", specifier = ">=0.2.0" }, + { name = "uvicorn", marker = "extra == 'full'", specifier = ">=0.35" }, + { name = "uvicorn", marker = "extra == 'server'", specifier = ">=0.35" }, + { name = "watchfiles", marker = "extra == 'full'", specifier = ">=1.0.0" }, + { name = "watchfiles", marker = "extra == 'server'", specifier = ">=1.0.0" }, + { name = "websockets", marker = "extra == 'full'", specifier = ">=15.0.1" }, + { name = "websockets", marker = "extra == 'server'", specifier = ">=15.0.1" }, +] +provides-extras = ["anthropic", "apps", "azure", "client", "code-mode", "full", "gemini", "openai", "server", "tasks"] + [[package]] name = "google-auth" version = "2.49.1"