diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b671f00a3..9de98ee25 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv tool install poethepoet - - run: uv sync --all-extras + - run: uv sync - run: poe bridge-lint if: ${{ matrix.clippyLinter }} - run: poe build-develop @@ -73,14 +73,6 @@ jobs: timeout-minutes: 10 env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - - name: "Upload junit-xml artifacts" - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 - if: always() - with: - name: junit-xml--${{github.run_id}}--${{github.run_attempt}}--${{ matrix.python }}--${{ matrix.os }} - path: junit-xml - retention-days: 14 - # Do docs stuff (only on one host) - name: Build API docs if: ${{ matrix.docsTarget }} @@ -100,6 +92,31 @@ jobs: npx doctoc README.md [[ -z $(git status --porcelain README.md) ]] || (git diff README.md; echo "README changed"; exit 1) + # Poe syncs these MCP v1 integrations into their own environment, leaving + # the default MCP v2 environment intact. + - name: Type-check MCP v1 integrations + if: ${{ matrix.docsTarget }} + run: poe lint-types-mcp-v1 + - name: Test MCP v1 integrations + if: ${{ matrix.docsTarget }} + run: >- + poe test-mcp-v1 -s tests/contrib/google_adk_agents + tests/contrib/google_genai tests/contrib/strands + --junit-xml=junit-xml/mcp-v1-integrations.xml + - name: Test deprecated OpenAI MCP APIs with MCP v1 + if: ${{ matrix.docsTarget }} + run: >- + poe test-mcp-v1 -s tests/contrib/openai_agents/test_openai.py + -m mcp_v1 --junit-xml=junit-xml/openai-mcp-v1.xml + + - name: "Upload junit-xml artifacts" + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + if: always() + with: + name: junit-xml--${{github.run_id}}--${{github.run_attempt}}--${{ matrix.python }}--${{ matrix.os }} + path: junit-xml + retention-days: 14 + # Verify the optional FIPS build: the Rust core must link aws-lc-fips-sys # (aws-lc-rs FIPS mode) and must NOT link `ring` (the cargo-tree guard, ported # from sdk-ruby PR #466's `fips_tree` guard); then run the test suite against the @@ -160,7 +177,7 @@ jobs: repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv tool install poethepoet - - run: uv sync --all-extras + - run: uv sync # Develop build so the FIPS extension is importable, then run the suite # against it to confirm the aws-lc-rs stack works end to end (not just links). - run: poe build-develop-fips @@ -202,7 +219,7 @@ jobs: with: python-version: "3.14" - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - - run: uv sync --all-extras + - run: uv sync - name: Build Alpine wheel run: uv run cibuildwheel --output-dir dist env: @@ -235,9 +252,9 @@ jobs: - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv tool install poethepoet - run: uv remove google-adk --optional google-adk - - run: uv add --dev --python 3.10 "googleapis-common-protos==1.70.0" + - run: uv add --group dev-common --python 3.10 "googleapis-common-protos==1.70.0" - run: uv add --python 3.10 "protobuf<4" - - run: uv sync --all-extras + - run: uv sync - run: cargo install --locked nexgen --version 0.2.2 --features advanced --force - run: poe build-develop - run: poe gen-protos @@ -274,7 +291,7 @@ jobs: - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv tool install poethepoet - run: uv lock --upgrade - - run: uv sync --all-extras + - run: uv sync - run: poe build-develop - run: poe lint - run: mkdir junit-xml @@ -312,7 +329,7 @@ jobs: repo-token: ${{ secrets.GITHUB_TOKEN }} - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - run: uv tool install poethepoet - - run: uv sync --all-extras + - run: uv sync - run: poe build-develop - name: Generate Cloud test certificates run: | diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 6a97c7bc5..1031e9c79 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -67,7 +67,7 @@ jobs: workspaces: temporalio/bridge -> target key: ${{ env.pythonLocation }} - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 - - run: uv sync --all-extras + - run: uv sync # Add the source dist only for Linux x64 for now - if: ${{ matrix.package-suffix == 'linux-amd64' }} diff --git a/.github/workflows/run-bench.yml b/.github/workflows/run-bench.yml index 26e0b4759..bd94e78f9 100644 --- a/.github/workflows/run-bench.yml +++ b/.github/workflows/run-bench.yml @@ -52,7 +52,7 @@ jobs: - uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8 # Build - run: uv tool install poethepoet - - run: uv sync --all-extras + - run: uv sync - run: poe build-develop-with-release # Run a bunch of bench tests. We run multiple times since results vary. diff --git a/.gitignore b/.gitignore index 8cd439e05..ddb5d1346 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .venv +.venv-* __pycache__ /build /dist diff --git a/AGENTS.md b/AGENTS.md index 7ecbb40d5..116510f0e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -52,7 +52,7 @@ document as a quick reference when submitting pull requests. The common local commands are: ```bash -uv sync --all-extras +uv sync poe build-develop poe lint poe test @@ -63,6 +63,7 @@ For focused iteration, prefer: ```bash poe test -s -k +poe test-mcp-v1 -s uv run pytest tests/path/test_file.py::test_name ``` diff --git a/CHANGELOG.md b/CHANGELOG.md index be3444177..5c13b426a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,14 +20,49 @@ to include examples, links to docs, or any other relevant information. ### Added +- Added an `mcp` extra pinning MCP Python SDK v2, for use alongside the + `openai-agents` extra. +- Added experimental `temporalio.contrib.mcp.MCPPlugin` and + `TemporalMCPClient` for using stdio, streamable HTTP, in-process, and custom + MCP Python SDK v2 clients from native workflow code. Tools, prompts, and + resources run durably through Activities, with fully paginated list results + and replay-safe tool discovery caching. + ### Changed +- `OpenAIAgentsPlugin` now accepts named OpenAI `MCPServer` factories through + `mcp_servers`, and `workflow.temporal_mcp_server()` proxies them durably from + workflow code. Each MCP operation runs as an Activity, list operations are + fully paginated, and tool discovery is cached by default. The servers keep + their OpenAI-specific configuration. Parameterless modern connections are + reused for up to five idle minutes by default. + ### Deprecated +- Deprecated the OpenAI Agents integration's legacy + `StatelessMCPServerProvider`, `StatefulMCPServerProvider`, + `workflow.stateless_mcp_server()`, `workflow.stateful_mcp_server()`, and + `mcp_server_providers` plugin option. They remain available for source and + workflow-history compatibility; use `mcp_servers` with + `workflow.temporal_mcp_server()` for new integrations. + ### :boom: Breaking Changes +- The OpenAI Agents integration now requires `openai-agents>=0.20,<0.21`. Its + deprecated provider APIs continue to work with MCP v1, while the new + `mcp_servers` API requires MCP v2. Existing Activity history contracts remain + supported. +- MCP v1 and MCP v2 cannot coexist in one environment, so the `mcp` extra cannot + be installed alongside the extras that require MCP v1. Resolution fails for + `uv add "temporalio[mcp,google-adk]"` and for + `uv add "temporalio[mcp,strands-agents]"`; install those integrations in + separate environments. + ### Fixed +- The `Worker` async context manager now waits for plugin run-context cleanup + after worker shutdown instead of cancelling it. + ### Security ## [1.32.0] - 2026-08-24 diff --git a/README.md b/README.md index 7a1caedd9..cb5a3fe11 100644 --- a/README.md +++ b/README.md @@ -2044,7 +2044,7 @@ cd sdk-python Install the dependencies: ```bash -uv sync --all-extras +uv sync ``` #### Build @@ -2167,7 +2167,7 @@ installing dependencies: ```bash git clone --recursive https://github.com/temporalio/sdk-python.git cd sdk-python -uv sync --all-extras +uv sync ``` Now compile the Rust extension in develop mode which is quicker than release mode: @@ -2200,6 +2200,17 @@ To execute a single test: poe test -s --log-cli-level=DEBUG -k test_sync_activity_thread_cancel_caught ``` +The default development environment uses MCP v2. Google ADK and Strands tests use +MCP v1 in a separate `.venv-mcp-v1` environment, which Poe creates and updates +automatically: + +```bash +poe test-mcp-v1 -s tests/contrib/google_adk_agents tests/contrib/strands +``` + +Run `poe sync-mcp-v1` separately when an editor or another tool needs the MCP v1 +environment without running tests. + **Temporal Server** - Tests that use the workflow test environment run against the [Temporal CLI dev server](https://docs.temporal.io/cli#start-dev-server). @@ -2218,9 +2229,9 @@ poe gen-protos-docker ``` Alternatively: to generate protobuf code, you must be on Python <= 3.10, and then run `uv add -"protobuf<4"` + `uv sync --all-extras`. Then the protobuf files can be generated via `poe +"protobuf<4"` + `uv sync`. Then the protobuf files can be generated via `poe gen-protos` followed by `poe format`. Do not commit `uv.lock` or `pyproject.toml` changes. To go -back from this downgrade, restore both of those files and run `uv sync --all-extras`. Tests can be +back from this downgrade, restore both of those files and run `uv sync`. Tests can be run for protobuf version 3 by setting the `TEMPORAL_TEST_PROTO3` env var to `1` prior to running tests. diff --git a/pyproject.toml b/pyproject.toml index d05d2f8c6..5cbc338c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,8 @@ classifiers = [ grpc = ["grpcio>=1.48.2,<2"] opentelemetry = ["opentelemetry-api>=1.26,<2", "opentelemetry-sdk>=1.26,<2"] pydantic = ["pydantic>=2.0.0,<3"] -openai-agents = ["openai-agents>=0.19.2,<0.20", "mcp>=1.9.4, <2"] +openai-agents = ["openai-agents>=0.20,<0.21", "mcp>=1.24,<3"] +mcp = ["mcp>=2,<3"] google-adk = ["google-adk>=2.2.0,<3", "mcp>=1.24,<2"] langgraph = ["langgraph>=1.1.0"] langsmith = ["langsmith>=0.7.34,<0.9"] @@ -55,7 +56,7 @@ Documentation = "https://docs.temporal.io/docs/python" "Bug Tracker" = "https://github.com/temporalio/sdk-python/issues" [dependency-groups] -dev = [ +dev-common = [ "basedpyright==1.34.0", "cibuildwheel>=2.22.0,<3", "cryptography>=46", @@ -73,18 +74,21 @@ dev = [ "toml>=0.10.2,<0.11", "twine>=4.0.1,<5", "maturin>=1.8.2", - "openinference-instrumentation-openai-agents>=0.1.0", "pytest-cov>=6.1.1", "httpx>=0.28.1", "pytest-pretty>=1.3.0", - "openai-agents>=0.19.2,<0.20; python_version >= '3.14'", - "openai-agents[litellm]>=0.19.2,<0.20; python_version < '3.14'", "litellm>=1.83.0", - "openinference-instrumentation-google-adk>=0.1.11", "googleapis-common-protos>=1.75.0,<2", "pytest-rerunfailures>=16.1", "pytest-xdist>=3.6,<4", "moto[s3,server]>=5", + "grpcio>=1.48.2,<2", + "opentelemetry-api>=1.26,<2", + "opentelemetry-sdk>=1.26,<2", + "pydantic>=2.0.0,<3", + "aioboto3>=10.4.0", + "types-aioboto3[s3]>=10.4.0", + "google-genai>=2.10.0,<3.0.0", "langgraph>=1.1.0", "langsmith>=0.7.34,<0.9", "deepagents>=0.6.12,<0.7; python_version >= '3.11'", @@ -97,9 +101,26 @@ dev = [ "opentelemetry-sdk-extension-aws>=2.0.0,<3", "pytest-flakefinder>=1.1.0", "async-timeout>=4.0,<6; python_version < '3.11'", +] +# MCP v1 cannot share an environment with MCP v2, so the v1 profile includes all +# dependencies it needs and its Poe tasks target a separate virtual environment. +dev = [ + { include-group = "dev-common" }, + "openinference-instrumentation-openai-agents>=0.1.0", + "openai-agents>=0.20,<0.21; python_version >= '3.14'", + "openai-agents[litellm]>=0.20,<0.21; python_version < '3.14'", + "mcp>=2,<3", +] +dev-mcp-v1 = [ + { include-group = "dev-common" }, + "openinference-instrumentation-openai-agents>=0.1.0", + "openinference-instrumentation-google-adk>=0.1.11", + "openai-agents>=0.20,<0.21; python_version >= '3.14'", + "openai-agents[litellm]>=0.20,<0.21; python_version < '3.14'", + "google-adk>=2.2.0,<3", "strands-agents>=1.39.0", "strands-agents-tools>=0.5.2", - "mcp>=1.9.4,<2", + "mcp>=1.24,<2", ] [tool.poe.tasks] @@ -145,7 +166,34 @@ lint-types = [ { cmd = "uv run basedpyright" }, ] run-bench = "uv run python scripts/run_bench.py" -test = "uv run pytest -n auto --dist=worksteal" +test = "uv run pytest -n auto --dist=worksteal --ignore=tests/contrib/google_adk_agents --ignore=tests/contrib/google_genai/test_gemini_mcp.py --ignore=tests/contrib/strands" +sync-mcp-v1 = { cmd = "uv sync --no-default-groups --group dev-mcp-v1", env = { UV_PROJECT_ENVIRONMENT = ".venv-mcp-v1" }, executor = { type = "simple" } } +test-mcp-v1 = { cmd = "uv run --no-default-groups --group dev-mcp-v1 pytest -n auto --dist=worksteal", env = { UV_PROJECT_ENVIRONMENT = ".venv-mcp-v1" }, executor = { type = "simple" } } + +[tool.poe.tasks.lint-types-mcp-v1] +shell = """ +set -e +MCP_V1_TYPECHECK_PATHS=" + temporalio/contrib/google_adk_agents/*.py + temporalio/contrib/google_genai/*.py + temporalio/contrib/strands/*.py + temporalio/contrib/openai_agents/_mcp.py + tests/contrib/google_adk_agents/*.py + tests/contrib/google_genai/*.py + tests/contrib/strands/*.py + tests/contrib/openai_agents/test_openai.py +" +uv run --no-default-groups --group dev-mcp-v1 pyright \ + $MCP_V1_TYPECHECK_PATHS +uv run --no-default-groups --group dev-mcp-v1 mypy \ + --cache-dir .mypy_cache/mcp-v1 --follow-imports=skip \ + --namespace-packages --check-untyped-defs \ + $MCP_V1_TYPECHECK_PATHS +uv run --no-default-groups --group dev-mcp-v1 basedpyright \ + $MCP_V1_TYPECHECK_PATHS +""" +env = { UV_PROJECT_ENVIRONMENT = ".venv-mcp-v1" } +executor = { type = "simple" } [tool.pytest.ini_options] @@ -155,6 +203,12 @@ asyncio_mode = "auto" log_level = "DEBUG" log_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" testpaths = ["tests"] +markers = [ + # Tests that must also be verified against MCP Python SDK v1, which cannot + # coexist with v2 in one environment. CI runs them with `poe test-mcp-v1 -m + # mcp_v1`; they also run in the default v2 job. + "mcp_v1: must also run under MCP Python SDK v1", +] timeout = 60 timeout_func_only = true filterwarnings = [ @@ -187,7 +241,22 @@ exclude = [ # Ignore generated code 'temporalio/api', 'temporalio/bridge/proto', + # These integrations require MCP v1 and are checked in the dev-mcp-v1 CI profile. + 'temporalio/contrib/google_adk_agents', + 'temporalio/contrib/google_genai', + 'temporalio/contrib/strands', + 'tests/contrib/google_adk_agents', + 'tests/contrib/google_genai/echo_mcp_server.py', + 'tests/contrib/strands', +] + +[[tool.mypy.overrides]] +module = [ + "temporalio.contrib.google_adk_agents.*", + "temporalio.contrib.google_genai._temporal_mcp", + "temporalio.contrib.strands.*", ] +follow_imports = "skip" [tool.pydocstyle] convention = "google" @@ -259,6 +328,13 @@ exclude = [ "temporalio/bridge/proto", "temporalio/bridge/_visitor.py", "tests/worker/workflow_sandbox/testmodules/proto", + # These integrations require MCP v1 and are checked in the dev-mcp-v1 CI profile. + "temporalio/contrib/google_adk_agents", + "temporalio/contrib/google_genai/_temporal_mcp.py", + "temporalio/contrib/strands", + "tests/contrib/google_adk_agents", + "tests/contrib/google_genai/echo_mcp_server.py", + "tests/contrib/strands", ] [tool.ruff] @@ -276,6 +352,32 @@ include = ["LICENSE"] exclude = ["temporalio/bridge/target/**/*", "temporalio/bridge/sdk-core/.git"] [tool.uv] +conflicts = [ + [ + { group = "dev" }, + { group = "dev-mcp-v1" }, + ], + [ + { group = "dev" }, + { extra = "google-adk" }, + ], + [ + { group = "dev" }, + { extra = "strands-agents" }, + ], + [ + { group = "dev-mcp-v1" }, + { extra = "mcp" }, + ], + [ + { extra = "mcp" }, + { extra = "google-adk" }, + ], + [ + { extra = "mcp" }, + { extra = "strands-agents" }, + ], +] # Prevent uv commands from building the package by default package = false exclude-newer = "2 weeks" diff --git a/scripts/_proto/Dockerfile b/scripts/_proto/Dockerfile index 0bbe18bb3..ab9f2c598 100644 --- a/scripts/_proto/Dockerfile +++ b/scripts/_proto/Dockerfile @@ -9,9 +9,9 @@ COPY ./ ./ RUN mkdir -p ./temporalio/api RUN uv remove google-adk --optional google-adk -RUN uv add --dev "googleapis-common-protos==1.70.0" +RUN uv add --group dev-common "googleapis-common-protos==1.70.0" RUN uv add "protobuf<4" -RUN uv sync --all-extras +RUN uv sync RUN uv run scripts/gen_protos.py CMD ["sh", "-c", "cp -r ./temporalio/api/* /api_new && cp -r ./temporalio/bridge/proto/* /bridge_new"] diff --git a/scripts/_proto/Dockerfile.dockerignore b/scripts/_proto/Dockerfile.dockerignore index 00714526a..6f61ba057 100644 --- a/scripts/_proto/Dockerfile.dockerignore +++ b/scripts/_proto/Dockerfile.dockerignore @@ -4,6 +4,7 @@ .pytest_cache/ .ruff_cache/ .venv/ +.venv-*/ build/ dist/ temporalio/api/ diff --git a/temporalio/contrib/langgraph/README.md b/temporalio/contrib/langgraph/README.md index d5b7d4e0f..0649fdeec 100644 --- a/temporalio/contrib/langgraph/README.md +++ b/temporalio/contrib/langgraph/README.md @@ -299,7 +299,7 @@ Use Workflow state for per-run memory, or an external database (Postgres/Redis/e Install dependencies: ```sh -uv sync --all-extras +uv sync ``` Run the test suite: diff --git a/temporalio/contrib/mcp/README.md b/temporalio/contrib/mcp/README.md new file mode 100644 index 000000000..6a591267d --- /dev/null +++ b/temporalio/contrib/mcp/README.md @@ -0,0 +1,145 @@ +# Temporal MCP integration + +> This package is experimental and may change in future versions. + +`temporalio.contrib.mcp` lets native Temporal workflow code use MCP Python SDK +v2 clients. The workflow sees a durable proxy, while MCP transports, processes, +network connections, and credentials remain in worker-side Activities. + +Install the integration with: + +```bash +uv add "temporalio[mcp]" +``` + +## Usage + +Create the workflow-side client with a durable name and call the regular MCP +request/response operations: + +```python +from mcp.types import TextContent +from temporalio import workflow +from temporalio.contrib.mcp import TemporalMCPClient + + +@workflow.defn +class WeatherWorkflow: + @workflow.run + async def run(self, city: str) -> str: + mcp = TemporalMCPClient("weather") + tools = await mcp.list_tools() + assert any(tool.name == "get_weather" for tool in tools.tools) + + result = await mcp.call_tool("get_weather", {"city": city}) + content = result.content[0] + assert isinstance(content, TextContent) + return content.text +``` + +Register a worker-side factory under the same name. Streamable HTTP is the +simplest network transport: + +```python +from mcp import Client +from temporalio.contrib.mcp import MCPPlugin +from temporalio.worker import Worker + +plugin = MCPPlugin( + { + "weather": lambda: Client("https://example.com/mcp"), + } +) + +worker = Worker( + temporal_client, + task_queue="weather", + workflows=[WeatherWorkflow], + plugins=[plugin], +) +``` + +For a stdio server, return a fresh `Client` and transport from the factory: + +```python +from mcp import Client, StdioServerParameters, stdio_client +from temporalio.contrib.mcp import MCPPlugin + +parameters = StdioServerParameters( + command="python", + args=["weather_mcp_server.py"], +) +plugin = MCPPlugin( + { + "weather": lambda: Client(stdio_client(parameters)), + } +) +``` + +`MCPPlugin` also accepts in-process MCP servers and custom MCP v2 transports +through the same `mcp.Client` API. + +## Operations and durability + +The proxy exposes these MCP operations, each backed by a named Activity: + +| Workflow method | Activity suffix | Result | +| --- | --- | --- | +| `list_tools()` | `list-tools` | `ListToolsResult` | +| `call_tool()` | `call-tool` | `CallToolResult` | +| `list_prompts()` | `list-prompts` | `ListPromptsResult` | +| `get_prompt()` | `get-prompt` | `GetPromptResult` | +| `list_resources()` | `list-resources` | `ListResourcesResult` | +| `list_resource_templates()` | `list-resource-templates` | `ListResourceTemplatesResult` | +| `read_resource()` | `read-resource` | `ReadResourceResult` | + +List operations follow every server pagination cursor within one Activity and +return a complete result with `next_cursor=None`. `list_tools()` is cached in +replay-safe workflow state by default. Set `cache_tools_list=False` to schedule +an Activity for every call. + +All operations default to a one-minute start-to-close timeout. Override this +with an `ActivityConfig`: + +```python +from datetime import timedelta +from temporalio.contrib.mcp import TemporalMCPClient + +mcp = TemporalMCPClient( + "weather", + activity_config={"start_to_close_timeout": timedelta(seconds=20)}, +) +``` + +Activities have at-least-once execution semantics. An MCP tool can therefore +run more than once when a worker loses its completion response. Tools with side +effects should be idempotent, usually by accepting a stable idempotency key. + +## Connections and configuration + +Parameterless factories reuse modern, sessionless MCP connections until they +have been idle for five minutes. Set `connection_idle_timeout=None` to retain +them until plugin shutdown, or `timedelta(0)` to close them whenever they become +idle. Connections using a legacy MCP handshake are not shared between +Activities. + +A factory may instead declare one positional parameter. The matching workflow +client passes `factory_argument` to it: + +```python +plugin = MCPPlugin( + { + "weather": lambda tenant: Client(endpoint_for(tenant)), + } +) + +mcp = TemporalMCPClient("weather", factory_argument="acme") +``` + +A non-`None` argument creates a fresh client for every Activity. It is recorded +in workflow history, so use only a stable, non-secret identifier. Resolve URLs, +tokens, and other secrets inside the worker-side factory. + +Connection reuse is an optimization, not durable session storage. A process +restart creates a new connection, while completed MCP results remain in +workflow history and replay without reconnecting. diff --git a/temporalio/contrib/mcp/__init__.py b/temporalio/contrib/mcp/__init__.py new file mode 100644 index 000000000..eb1d6a297 --- /dev/null +++ b/temporalio/contrib/mcp/__init__.py @@ -0,0 +1,36 @@ +"""Run MCP Python SDK v2 clients durably from Temporal workflows. + +Register named worker-side clients with :class:`MCPPlugin`, then construct a +:class:`TemporalMCPClient` with the same name inside workflow code. MCP +operations execute as Activities; transports and credentials remain on the +worker. + +This package is experimental and may change in future versions. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from temporalio.contrib.mcp._plugin import MCPClientFactory, MCPPlugin + from temporalio.contrib.mcp._workflow import TemporalMCPClient + +__all__ = ["MCPClientFactory", "MCPPlugin", "TemporalMCPClient"] + + +def __getattr__(name: str) -> Any: + """Load the MCP v2 public API only when a symbol is requested. + + The shared package also backs deprecated integration APIs that still import + under MCP v1, so importing the package itself cannot require MCP v2. + """ + if name in ("MCPClientFactory", "MCPPlugin"): + from temporalio.contrib.mcp import _plugin + + return getattr(_plugin, name) + if name == "TemporalMCPClient": + from temporalio.contrib.mcp._workflow import TemporalMCPClient + + return TemporalMCPClient + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/temporalio/contrib/mcp/_activities.py b/temporalio/contrib/mcp/_activities.py new file mode 100644 index 000000000..19abc9e80 --- /dev/null +++ b/temporalio/contrib/mcp/_activities.py @@ -0,0 +1,221 @@ +# pyright: reportUnusedClass=false + +from __future__ import annotations + +import asyncio +import logging +from collections.abc import AsyncIterator, Awaitable, Callable, Sequence +from contextlib import asynccontextmanager +from datetime import timedelta +from typing import Any, TypeVar + +from mcp.types import ( + ListPromptsResult, + ListResourcesResult, + ListResourceTemplatesResult, + ListToolsResult, +) +from pydantic import BaseModel + +from temporalio import activity +from temporalio.contrib.mcp._activity import ( + _activity_name, + _CallToolRequest, + _GetPromptRequest, + _MCPRequest, + _ReadResourceRequest, +) +from temporalio.contrib.mcp._backend import _MCPBackend, _MCPBackendFactory +from temporalio.contrib.mcp._pool import _MCPConnectionPool + +_Result = TypeVar("_Result") + +logger = logging.getLogger(__name__) + +# Upper bound on how long worker shutdown waits for MCP transports to close. +_CLOSE_TIMEOUT_SECONDS = 10.0 + + +def _dump(model: BaseModel) -> dict[str, Any]: + return model.model_dump(mode="json") + + +class _MCPActivities: + """Build framework-neutral MCP operation Activities for named backends.""" + + def __init__( + self, + factories: dict[str, _MCPBackendFactory], + idle_timeout: timedelta | None = timedelta(minutes=5), + ) -> None: + self._factories = dict(factories) + self._pool = _MCPConnectionPool(self._factories, idle_timeout) + self._abandoned_closes: set[asyncio.Task[None]] = set() + self.activities = self._build_activities() + + async def _run( + self, + server: str, + request: _MCPRequest, + operation: Callable[[_MCPBackend], Awaitable[_Result]], + ) -> _Result: + async with self._pool.backend( + server, + factory_argument=request.factory_argument, + ) as backend: + return await operation(backend) + + def _build_activities(self) -> Sequence[Callable[..., Any]]: + activities: list[Callable[..., Any]] = [] + for server in self._factories: + + @activity.defn(name=_activity_name(server, "list-tools")) + async def list_tools( + request: dict[str, Any], server: str = server + ) -> dict[str, Any]: + parsed = _MCPRequest(**request) + return _dump( + ListToolsResult( + tools=await self._run( + server, + parsed, + lambda backend: backend.list_tools(), + ) + ) + ) + + @activity.defn(name=_activity_name(server, "call-tool")) + async def call_tool( + request: dict[str, Any], server: str = server + ) -> dict[str, Any]: + parsed = _CallToolRequest(**request) + result = await self._run( + server, + parsed, + lambda backend: backend.call_tool( + parsed.name, + parsed.arguments, + parsed.meta, + ), + ) + return _dump(result) + + @activity.defn(name=_activity_name(server, "list-prompts")) + async def list_prompts( + request: dict[str, Any], server: str = server + ) -> dict[str, Any]: + parsed = _MCPRequest(**request) + return _dump( + ListPromptsResult( + prompts=await self._run( + server, + parsed, + lambda backend: backend.list_prompts(), + ) + ) + ) + + @activity.defn(name=_activity_name(server, "get-prompt")) + async def get_prompt( + request: dict[str, Any], server: str = server + ) -> dict[str, Any]: + parsed = _GetPromptRequest(**request) + result = await self._run( + server, + parsed, + lambda backend: backend.get_prompt( + parsed.name, + parsed.arguments, + ), + ) + return _dump(result) + + @activity.defn(name=_activity_name(server, "list-resources")) + async def list_resources( + request: dict[str, Any], server: str = server + ) -> dict[str, Any]: + parsed = _MCPRequest(**request) + return _dump( + ListResourcesResult( + resources=await self._run( + server, + parsed, + lambda backend: backend.list_resources(), + ) + ) + ) + + @activity.defn(name=_activity_name(server, "list-resource-templates")) + async def list_resource_templates( + request: dict[str, Any], server: str = server + ) -> dict[str, Any]: + parsed = _MCPRequest(**request) + return _dump( + ListResourceTemplatesResult( + resource_templates=await self._run( + server, + parsed, + lambda backend: backend.list_resource_templates(), + ) + ) + ) + + @activity.defn(name=_activity_name(server, "read-resource")) + async def read_resource( + request: dict[str, Any], server: str = server + ) -> dict[str, Any]: + parsed = _ReadResourceRequest(**request) + result = await self._run( + server, + parsed, + lambda backend: backend.read_resource(parsed.uri), + ) + return _dump(result) + + activities.extend( + ( + list_tools, + call_tool, + list_prompts, + get_prompt, + list_resources, + list_resource_templates, + read_resource, + ) + ) + return activities + + @asynccontextmanager + async def run_context(self) -> AsyncIterator[None]: + body_completed = False + try: + yield + body_completed = True + finally: + close_task = asyncio.create_task(self._pool.close()) + try: + await asyncio.shield(close_task) + except asyncio.CancelledError: + # Worker context exit cancels its wrapper after the inner run + # completes. Finish MCP cleanup without swallowing cancellation + # received while the worker was still running. + if not body_completed: + raise + await self._finish_close(close_task) + + async def _finish_close(self, close_task: asyncio.Task[None]) -> None: + """Wait a bounded time for a close whose cancellation was swallowed.""" + try: + await asyncio.wait_for(asyncio.shield(close_task), _CLOSE_TIMEOUT_SECONDS) + except asyncio.TimeoutError: + # An unresponsive MCP server must not hang worker shutdown + # indefinitely, especially now that there is no cancellation left to + # break out with. Leave the close running, but strongly referenced + # so it is not garbage collected part way through. + self._abandoned_closes.add(close_task) + close_task.add_done_callback(self._abandoned_closes.discard) + logger.warning( + "Timed out after %s seconds closing MCP connections; " + "an MCP server may not have shut down cleanly.", + _CLOSE_TIMEOUT_SECONDS, + ) diff --git a/temporalio/contrib/mcp/_activity.py b/temporalio/contrib/mcp/_activity.py new file mode 100644 index 000000000..55c086361 --- /dev/null +++ b/temporalio/contrib/mcp/_activity.py @@ -0,0 +1,37 @@ +# pyright: reportUnusedClass=false, reportUnusedFunction=false + +from __future__ import annotations + +import dataclasses +from typing import Any + +from mcp.types import RequestParamsMeta + + +@dataclasses.dataclass +class _MCPRequest: + factory_argument: Any = None + + +@dataclasses.dataclass +class _CallToolRequest(_MCPRequest): + name: str = "" + arguments: dict[str, Any] | None = None + # Only call_tool has a caller that supplies request metadata: the OpenAI + # Agents base MCPServer resolves it per tool call. + meta: RequestParamsMeta | None = None + + +@dataclasses.dataclass +class _GetPromptRequest(_MCPRequest): + name: str = "" + arguments: dict[str, str] | None = None + + +@dataclasses.dataclass +class _ReadResourceRequest(_MCPRequest): + uri: str = "" + + +def _activity_name(server: str, operation: str) -> str: + return f"temporalio.contrib.mcp.{server}.{operation}" diff --git a/temporalio/contrib/mcp/_backend.py b/temporalio/contrib/mcp/_backend.py new file mode 100644 index 000000000..3d1cc1f19 --- /dev/null +++ b/temporalio/contrib/mcp/_backend.py @@ -0,0 +1,132 @@ +# pyright: reportUnusedClass=false + +from __future__ import annotations + +import inspect +from collections.abc import Callable +from types import TracebackType +from typing import Any, Protocol + +from mcp.types import ( + CallToolResult, + GetPromptResult, + Prompt, + ReadResourceResult, + RequestParamsMeta, + Resource, + ResourceTemplate, + Tool, +) + +from temporalio.exceptions import ApplicationError + + +class _MCPBackend(Protocol): + """Normalized worker-side MCP operations used by the Activity layer.""" + + async def __aenter__(self) -> "_MCPBackend": ... + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: ... + + @property + def cacheable(self) -> bool: ... + + async def list_tools(self) -> list[Tool]: ... + + async def call_tool( + self, + name: str, + arguments: dict[str, Any] | None, + meta: RequestParamsMeta | None, + ) -> CallToolResult: ... + + async def list_prompts(self) -> list[Prompt]: ... + + async def get_prompt( + self, name: str, arguments: dict[str, str] | None + ) -> GetPromptResult: ... + + async def list_resources(self) -> list[Resource]: ... + + async def list_resource_templates(self) -> list[ResourceTemplate]: ... + + async def read_resource(self, uri: str) -> ReadResourceResult: ... + + +_MCPBackendFactory = Callable[[], _MCPBackend] | Callable[[Any], _MCPBackend] + + +class _NotSupplied: + pass + + +_NOT_SUPPLIED = _NotSupplied() + + +def _factory_accepts_argument(name: str, factory: Callable[..., Any]) -> bool: + """Resolve whether an MCP backend factory receives the ``factory_argument``. + + A factory declaring a positional parameter always receives the argument, as + ``None`` when the workflow supplied none; a parameterless factory is always + called with no arguments. A signature that could satisfy neither form raises + here, so the mismatch surfaces where the factory is registered rather than as + an Activity failure that retries forever. + """ + try: + parameters = list(inspect.signature(factory).parameters.values()) + except (TypeError, ValueError): + # Some callables (C builtins, for instance) expose no signature. Assume + # the parameterless form and let the call report any real mismatch. + return False + kinds = inspect.Parameter + positional = [ + param + for param in parameters + if param.kind + in (kinds.POSITIONAL_ONLY, kinds.POSITIONAL_OR_KEYWORD, kinds.VAR_POSITIONAL) + ] + required = [ + param + for param in parameters + if param.default is kinds.empty + and param.kind not in (kinds.VAR_POSITIONAL, kinds.VAR_KEYWORD) + ] + if len(required) > 1: + raise TypeError( + f"MCP server factory {name!r} requires {len(required)} parameters; it " + "may declare at most one, which receives the factory_argument" + ) + if required and required[0].kind is kinds.KEYWORD_ONLY: + raise TypeError( + f"MCP server factory {name!r} requires keyword-only parameter " + f"{required[0].name!r}, which cannot receive the factory_argument; " + "make it positional or give it a default" + ) + return bool(positional) + + +class _FactoryInvoker: + """Call an MCP backend factory with the arity its signature declares.""" + + def __init__(self, name: str, factory: Callable[..., Any]) -> None: + self._name = name + self._factory = factory + self._accepts_argument = _factory_accepts_argument(name, factory) + + def __call__(self, argument: Any = _NOT_SUPPLIED) -> Any: + supplied = None if isinstance(argument, _NotSupplied) else argument + if self._accepts_argument: + return self._factory(supplied) + if supplied is not None: + raise ApplicationError( + f"MCP server factory {self._name!r} declares no parameters, so it " + "cannot receive a factory_argument; give the factory a single " + "positional parameter to accept one", + non_retryable=True, + ) + return self._factory() diff --git a/temporalio/contrib/mcp/_client.py b/temporalio/contrib/mcp/_client.py new file mode 100644 index 000000000..cc708cbb9 --- /dev/null +++ b/temporalio/contrib/mcp/_client.py @@ -0,0 +1,110 @@ +# pyright: reportUnusedClass=false, reportUnusedFunction=false + +from __future__ import annotations + +from collections.abc import Callable +from types import TracebackType +from typing import Any, cast + +from mcp import Client +from mcp.types import ( + CallToolResult, + GetPromptResult, + Prompt, + ReadResourceResult, + RequestParamsMeta, + Resource, + ResourceTemplate, + Tool, +) +from mcp_types.version import MODERN_PROTOCOL_VERSIONS + +from temporalio.contrib.mcp._backend import ( + _NOT_SUPPLIED, + _FactoryInvoker, + _MCPBackendFactory, +) + + +class _MCPClientBackend: + """Adapt an MCP Python SDK v2 client to the shared Activity backend.""" + + def __init__(self, client: Client) -> None: + self._client = client + + async def __aenter__(self) -> "_MCPClientBackend": + await self._client.__aenter__() + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + await self._client.__aexit__(exc_type, exc_val, exc_tb) + + @property + def cacheable(self) -> bool: + return self._client.protocol_version in MODERN_PROTOCOL_VERSIONS + + async def _list_all(self, method: str, field: str) -> list[Any]: + values: list[Any] = [] + cursor: str | None = None + seen_cursors: set[str | None] = set() + while True: + options: dict[str, Any] = {"cursor": cursor} + if method == "list_tools": + options["cache_mode"] = "bypass" + result = await getattr(self._client, method)(**options) + values.extend(getattr(result, field)) + seen_cursors.add(cursor) + next_cursor = result.next_cursor + if next_cursor is None: + return values + if next_cursor in seen_cursors: + raise ValueError("MCP server returned a repeated pagination cursor") + cursor = next_cursor + + async def list_tools(self) -> list[Tool]: + return await self._list_all("list_tools", "tools") + + async def call_tool( + self, + name: str, + arguments: dict[str, Any] | None, + meta: RequestParamsMeta | None, + ) -> CallToolResult: + return await self._client.call_tool(name, arguments, meta=meta) + + async def list_prompts(self) -> list[Prompt]: + return await self._list_all("list_prompts", "prompts") + + async def get_prompt( + self, name: str, arguments: dict[str, str] | None + ) -> GetPromptResult: + return await self._client.get_prompt(name, arguments) + + async def list_resources(self) -> list[Resource]: + return await self._list_all("list_resources", "resources") + + async def list_resource_templates(self) -> list[ResourceTemplate]: + return await self._list_all("list_resource_templates", "resource_templates") + + async def read_resource(self, uri: str) -> ReadResourceResult: + return await self._client.read_resource(uri) + + +_MCPClientFactory = Callable[[], Client] | Callable[[Any], Client] + + +def _mcp_client_backend_factory( + name: str, factory: _MCPClientFactory +) -> _MCPBackendFactory: + """Adapt a public MCP client factory to the shared Activity backend.""" + invoke = _FactoryInvoker(name, factory) + + def create(argument: Any = _NOT_SUPPLIED) -> _MCPClientBackend: + return _MCPClientBackend(cast(Client, invoke(argument))) + + return create diff --git a/temporalio/contrib/mcp/_plugin.py b/temporalio/contrib/mcp/_plugin.py new file mode 100644 index 000000000..48e8bac97 --- /dev/null +++ b/temporalio/contrib/mcp/_plugin.py @@ -0,0 +1,76 @@ +"""Worker plugin for durable MCP clients.""" + +from __future__ import annotations + +import dataclasses +from collections.abc import Callable, Mapping +from datetime import timedelta +from typing import Any, TypeAlias + +from mcp import Client + +from temporalio.contrib.mcp._activities import _MCPActivities +from temporalio.contrib.mcp._client import _mcp_client_backend_factory +from temporalio.plugin import SimplePlugin +from temporalio.worker import WorkflowRunner +from temporalio.worker.workflow_sandbox import SandboxedWorkflowRunner + +MCPClientFactory: TypeAlias = Callable[[], Client] | Callable[[Any], Client] +"""Factory for an MCP client, optionally parameterized by workflow input.""" + + +class MCPPlugin(SimplePlugin): + """Register worker-side MCP clients for use from Temporal workflows. + + This class is experimental and may change in future versions. + + The mapping keys are durable server names used by + :class:`temporalio.contrib.mcp.TemporalMCPClient`. Factories and transports + remain on the worker, so credentials are not captured in workflow history. + + A factory may declare one positional parameter. It receives the workflow + client's ``factory_argument`` (``None`` when no argument was supplied). + Parameterless modern connections are reused until they have been idle for + ``connection_idle_timeout``. A non-None factory argument selects a fresh + connection for each Activity. + """ + + def __init__( + self, + clients: Mapping[str, MCPClientFactory], + *, + connection_idle_timeout: timedelta | None = timedelta(minutes=5), + ) -> None: + """Create an MCP plugin for the named client factories. + + Args: + clients: Mapping of durable names to worker-side MCP client + factories. + connection_idle_timeout: How long an idle modern MCP connection is + reused. ``None`` disables idle eviction; zero disables reuse. + """ + mcp_activities = _MCPActivities( + { + name: _mcp_client_backend_factory(name, factory) + for name, factory in clients.items() + }, + idle_timeout=connection_idle_timeout, + ) + self._mcp_activities = mcp_activities + + def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: + if runner is None: + raise ValueError("No WorkflowRunner provided to the MCP plugin") + if isinstance(runner, SandboxedWorkflowRunner): + return dataclasses.replace( + runner, + restrictions=runner.restrictions.with_passthrough_modules("mcp"), + ) + return runner + + super().__init__( + name="MCPPlugin", + activities=mcp_activities.activities, + workflow_runner=workflow_runner, + run_context=mcp_activities.run_context, + ) diff --git a/temporalio/contrib/mcp/_pool.py b/temporalio/contrib/mcp/_pool.py new file mode 100644 index 000000000..c113de245 --- /dev/null +++ b/temporalio/contrib/mcp/_pool.py @@ -0,0 +1,263 @@ +# pyright: reportUnusedClass=false + +from __future__ import annotations + +import asyncio +from collections.abc import AsyncIterator, Callable +from contextlib import asynccontextmanager +from datetime import timedelta +from typing import Any, cast + +from temporalio.contrib.mcp._backend import _MCPBackend, _MCPBackendFactory + + +class _ConnectionRecord: + """Own an MCP backend context in one task for its complete lifetime.""" + + def __init__(self, factory: Callable[[], _MCPBackend]) -> None: + loop = asyncio.get_running_loop() + self._ready: asyncio.Future[_MCPBackend] = loop.create_future() + self._stop = asyncio.Event() + self._owner = asyncio.create_task(self._run(factory)) + self._inflight = 0 + self._idle_handle: asyncio.TimerHandle | None = None + self._close_task: asyncio.Task[None] | None = None + self._failure: BaseException | None = None + self._retired = False + + async def _run(self, factory: Callable[[], _MCPBackend]) -> None: + try: + backend = factory() + async with backend: + self._ready.set_result(backend) + await self._stop.wait() + except BaseException as err: + if not self._ready.done(): + self._ready.set_exception(err) + else: + self._failure = err + + async def backend(self) -> _MCPBackend: + backend = await asyncio.shield(self._ready) + if self._failure is not None: + raise self._failure + return backend + + @property + def idle(self) -> bool: + return self._inflight == 0 + + @property + def retired(self) -> bool: + return self._retired + + def retire(self) -> None: + self._retired = True + + def acquire(self) -> None: + self._inflight += 1 + self.cancel_idle() + + def cancel_idle(self) -> None: + if self._idle_handle is not None: + self._idle_handle.cancel() + self._idle_handle = None + + def release( + self, idle_timeout: timedelta | None, on_idle: Callable[[], None] + ) -> bool: + self._inflight -= 1 + if self._inflight != 0: + return False + if idle_timeout is None: + return True + seconds = idle_timeout.total_seconds() + if seconds == 0: + on_idle() + else: + self._idle_handle = asyncio.get_running_loop().call_later(seconds, on_idle) + return True + + async def close(self) -> None: + if self._close_task is None: + self._close_task = asyncio.create_task(self._close()) + await asyncio.shield(self._close_task) + + async def _close(self) -> None: + self.cancel_idle() + self._stop.set() + if not self._ready.done(): + self._owner.cancel() + try: + await self._owner + except BaseException: + pass + if self._ready.done() and not self._ready.cancelled(): + self._ready.exception() + + +class _MCPConnectionPool: + """Cache parameterless modern MCP connections within each worker event loop.""" + + def __init__( + self, + factories: dict[str, _MCPBackendFactory], + idle_timeout: timedelta | None, + ) -> None: + if idle_timeout is not None and idle_timeout.total_seconds() < 0: + raise ValueError("mcp_connection_idle_timeout cannot be negative") + self._factories = factories + self._idle_timeout = idle_timeout + self._records: dict[ + tuple[asyncio.AbstractEventLoop, str], _ConnectionRecord + ] = {} + self._locks: dict[tuple[asyncio.AbstractEventLoop, str], asyncio.Lock] = {} + self._evictions: set[asyncio.Task[None]] = set() + + def _key(self, server: str) -> tuple[asyncio.AbstractEventLoop, str]: + return asyncio.get_running_loop(), server + + async def _new_record(self, server: str) -> _ConnectionRecord: + factory = cast(Callable[[], _MCPBackend], self._factories[server]) + record = _ConnectionRecord(factory) + try: + await record.backend() + except BaseException: + await record.close() + raise + return record + + @asynccontextmanager + async def backend( + self, + server: str, + *, + factory_argument: Any, + ) -> AsyncIterator[_MCPBackend]: + if factory_argument is not None: + factory = cast(Callable[[Any], _MCPBackend], self._factories[server]) + async with factory(factory_argument) as backend: + yield backend + return + + key = self._key(server) + lock = self._locks.setdefault(key, asyncio.Lock()) + cached = False + async with lock: + record = self._records.get(key) + if record is None: + record = await self._new_record(server) + record_backend = await record.backend() + if record_backend.cacheable: + self._records[key] = record + cached = True + else: + cached = True + record.acquire() + + failed = False + try: + yield await record.backend() + except asyncio.CancelledError: + # Cancelling an operation leaves the transport healthy: the MCP + # client cancels the in-flight request on the wire. Retiring the + # connection here would make one cancelled Activity force every + # other workflow sharing it to reconnect. + raise + except BaseException: + failed = True + raise + finally: + if failed: + # Retire the connection so no later operation reuses it, but + # leave the transport open for operations still in flight on + # it. The last operation to release the record closes it. + record.retire() + await self._unmap(key, record) + if record.retired: + if record.release(timedelta(0), lambda: None): + await record.close() + elif cached: + if self._idle_timeout is None: + record.release(None, lambda: None) + elif self._idle_timeout.total_seconds() == 0: + if record.release(self._idle_timeout, lambda: None): + await self._evict(key, record) + else: + record.release( + self._idle_timeout, + lambda: self._schedule_evict(key, record), + ) + else: + record.release(timedelta(0), lambda: None) + await record.close() + + def _schedule_evict( + self, + key: tuple[asyncio.AbstractEventLoop, str], + record: _ConnectionRecord, + ) -> None: + task = asyncio.create_task(self._evict(key, record, only_if_idle=True)) + # The event loop holds only a weak reference to a task, so an unretained + # eviction can be garbage collected part way through and leave the + # connection open until the pool closes. Holding it here also lets + # close() await evictions rather than orphan them on a closing loop. + self._evictions.add(task) + task.add_done_callback(self._evictions.discard) + + async def _unmap( + self, + key: tuple[asyncio.AbstractEventLoop, str], + record: _ConnectionRecord, + *, + only_if_idle: bool = False, + ) -> bool: + """Drop the cached record, returning whether it may now be closed.""" + lock = self._locks.setdefault(key, asyncio.Lock()) + async with lock: + # The idle check applies even when the record is no longer mapped: + # a failing operation unmaps the record while others are still in + # flight on it, and a pending eviction must not close it early. + if only_if_idle and not record.idle: + return False + if self._records.get(key) is record: + self._records.pop(key, None) + return True + + async def _evict( + self, + key: tuple[asyncio.AbstractEventLoop, str], + record: _ConnectionRecord, + *, + only_if_idle: bool = False, + ) -> None: + if await self._unmap(key, record, only_if_idle=only_if_idle): + await record.close() + + async def close(self) -> None: + loop = asyncio.get_running_loop() + records = [ + record + for (record_loop, _), record in list(self._records.items()) + if record_loop is loop + ] + # Disarm timers before yielding so none can create a new eviction after + # the snapshot below. + for record in records: + record.cancel_idle() + evictions = [task for task in self._evictions if task.get_loop() is loop] + # An eviction may already have unmapped its record, so let it finish + # closing that record rather than cancelling it part way through. + if evictions: + await asyncio.gather(*evictions, return_exceptions=True) + self._evictions.difference_update(evictions) + if records: + await asyncio.gather(*(record.close() for record in records)) + # Drop the locks along with the records only after eviction tasks have + # settled; _unmap() creates a lock when an eviction runs. + for key in list(self._records): + if key[0] is loop: + self._records.pop(key, None) + for key in list(self._locks): + if key[0] is loop: + self._locks.pop(key, None) diff --git a/temporalio/contrib/mcp/_workflow.py b/temporalio/contrib/mcp/_workflow.py new file mode 100644 index 000000000..6dea772a0 --- /dev/null +++ b/temporalio/contrib/mcp/_workflow.py @@ -0,0 +1,163 @@ +"""Workflow-side durable MCP client.""" + +# pyright: reportUnusedClass=false + +from __future__ import annotations + +import dataclasses +from datetime import timedelta +from typing import Any + +from mcp.types import ( + CallToolResult, + GetPromptResult, + ListPromptsResult, + ListResourcesResult, + ListResourceTemplatesResult, + ListToolsResult, + ReadResourceResult, + RequestParamsMeta, +) + +from temporalio import workflow +from temporalio.contrib.mcp._activity import ( + _activity_name, + _CallToolRequest, + _GetPromptRequest, + _MCPRequest, + _ReadResourceRequest, +) +from temporalio.workflow import ActivityConfig + + +class TemporalMCPClient: + """A durable workflow proxy for an MCP Python SDK v2 client. + + This class is experimental and may change in future versions. + + Each operation executes as an Activity. Tool discovery is cached for the + lifetime of this object by default. A non-None ``factory_argument`` selects + a fresh worker-side client for every Activity. The argument is recorded in + workflow history and must not contain secrets. + + This class intentionally does not inherit from ``mcp.Client`` or + ``mcp.ClientSession``. It exposes the request/response operations that can + cross a durable Activity boundary, while the real transport lifecycle stays + on the worker. + """ + + def __init__( + self, + name: str, + *, + activity_config: ActivityConfig | None = None, + cache_tools_list: bool = True, + factory_argument: Any = None, + ) -> None: + """Configure the registered name and MCP operation Activities.""" + self._name = name + self._activity_config: ActivityConfig = activity_config or { + "start_to_close_timeout": timedelta(minutes=1) + } + self._cache_tools_list = cache_tools_list + self._tools: ListToolsResult | None = None + self._factory_argument = factory_argument + + @property + def name(self) -> str: + """Return the registered worker-side client name.""" + return self._name + + @property + def cached_tools(self) -> ListToolsResult | None: + """Return the cached tool result, or ``None`` when none is cached.""" + return self._tools + + def _request(self) -> _MCPRequest: + return _MCPRequest(factory_argument=self._factory_argument) + + async def _execute( + self, operation: str, request: _MCPRequest, result_type: Any + ) -> Any: + return await workflow.execute_activity( + _activity_name(self._name, operation), + dataclasses.asdict(request), + result_type=result_type, + **self._activity_config, + ) + + async def list_tools(self) -> ListToolsResult: + """List all tools in one Activity, following every pagination cursor.""" + if self._cache_tools_list and self._tools is not None: + return self._tools + value = await self._execute("list-tools", self._request(), dict[str, Any]) + tools = ListToolsResult.model_validate(value) + if self._cache_tools_list: + self._tools = tools + return tools + + async def call_tool( + self, + name: str, + arguments: dict[str, Any] | None = None, + *, + meta: RequestParamsMeta | None = None, + ) -> CallToolResult: + """Call a tool. + + ``meta`` is the only request metadata carried by this client, because + ``call_tool`` is the only operation with a caller that supplies it. + """ + request = _CallToolRequest( + factory_argument=self._factory_argument, + meta=meta, + name=name, + arguments=arguments, + ) + value = await self._execute("call-tool", request, dict[str, Any]) + return CallToolResult.model_validate(value) + + async def list_prompts(self) -> ListPromptsResult: + """List all prompts in one Activity, following every pagination cursor.""" + value = await self._execute("list-prompts", self._request(), dict[str, Any]) + return ListPromptsResult.model_validate(value) + + async def get_prompt( + self, name: str, arguments: dict[str, str] | None = None + ) -> GetPromptResult: + """Get a prompt.""" + request = _GetPromptRequest( + factory_argument=self._factory_argument, + name=name, + arguments=arguments, + ) + value = await self._execute("get-prompt", request, dict[str, Any]) + return GetPromptResult.model_validate(value) + + async def list_resources(self) -> ListResourcesResult: + """List all resources in one Activity, following every pagination cursor.""" + value = await self._execute("list-resources", self._request(), dict[str, Any]) + return ListResourcesResult.model_validate(value) + + async def list_resource_templates(self) -> ListResourceTemplatesResult: + """List all resource templates, following every pagination cursor.""" + value = await self._execute( + "list-resource-templates", + self._request(), + dict[str, Any], + ) + return ListResourceTemplatesResult.model_validate(value) + + async def read_resource(self, uri: str) -> ReadResourceResult: + """Read a resource.""" + request = _ReadResourceRequest( + factory_argument=self._factory_argument, + uri=uri, + ) + value = await self._execute("read-resource", request, dict[str, Any]) + return ReadResourceResult.model_validate(value) + + +# Kept as an internal alias while contrib integrations migrate to the public +# name. It is not exported from ``temporalio.contrib.mcp``. +_MCPClient = TemporalMCPClient diff --git a/temporalio/contrib/openai_agents/README.md b/temporalio/contrib/openai_agents/README.md index 2266e38a7..5a7ff2d27 100644 --- a/temporalio/contrib/openai_agents/README.md +++ b/temporalio/contrib/openai_agents/README.md @@ -374,114 +374,101 @@ Tools that run in the workflow can also update OpenAI Agents context, which is r ## MCP Support -This integration provides support for Model Context Protocol (MCP) servers through two wrapper approaches designed to handle different implications of failures. - -While Temporal provides durable execution for your workflows, this durability does not extend to MCP servers, which operate independently of the workflow and must provide their own durability. The integration handles this by offering stateless and stateful wrappers that you can choose based on your MCP server's design. - -### Stateless vs Stateful MCP Servers - -You need to understand your MCP server's behavior to choose the correct wrapper: - -**Stateless MCP servers** treat each operation independently. For example, a weather server with a `get_weather(location)` tool is stateless because each call is self-contained and includes all necessary information. These servers can be safely restarted or reconnected to without changing their behavior. - -**Stateful MCP servers** maintain session state between calls. For example, a weather server that requires calling `set_location(location)` followed by `get_weather()` is stateful because it remembers the configured location and uses it for subsequent calls. If the session or the server is restarted, state crucial for operation is lost. Temporal identifies such failures and raises an `ApplicationError` to signal the need for application-level failure handling. - -### Usage Example (Stateless MCP) - -The code below gives an example of using a stateless MCP server. - -#### Worker Configuration +This integration uses MCP Python SDK v2. Register named OpenAI MCP server +factories on the worker, then reference the same name from workflow code: ```python -import asyncio -from datetime import timedelta -from agents.mcp import MCPServerStdio -from temporalio.client import Client -from temporalio.contrib.openai_agents import ( - ModelActivityParameters, - OpenAIAgentsPlugin, - StatelessMCPServerProvider, -) -from temporalio.worker import Worker - - -async def main(): - # Create the MCP server provider - filesystem_server = StatelessMCPServerProvider( - lambda: MCPServerStdio( - name="FileSystemServer", - params={ - "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/files"], - }, - ) - ) - - # Register the MCP server with the OpenAI Agents plugin - client = await Client.connect( - "localhost:7233", - plugins=[ - OpenAIAgentsPlugin( - model_params=ModelActivityParameters( - start_to_close_timeout=timedelta(seconds=60) - ), - mcp_server_providers=[filesystem_server], - ), - ], - ) - - worker = Worker( - client, - task_queue="my-task-queue", - workflows=[FileSystemWorkflow], - ) - await worker.run() +from agents.mcp import MCPServerStreamableHttp +from temporalio.contrib.openai_agents import OpenAIAgentsPlugin -if __name__ == "__main__": - asyncio.run(main()) +plugin = OpenAIAgentsPlugin( + mcp_servers={ + "weather": lambda: MCPServerStreamableHttp( + name="weather", + params={"url": "https://example.com/mcp"}, + ), + }, +) ``` -#### Workflow Implementation - ```python -from temporalio import workflow -from temporalio.contrib import openai_agents -from agents import Agent, Runner +from agents import Agent +from temporalio.contrib.openai_agents.workflow import temporal_mcp_server -@workflow.defn -class FileSystemWorkflow: - @workflow.run - async def run(self, query: str) -> str: - # Reference the MCP server by name (matches name in worker configuration) - server = openai_agents.workflow.stateless_mcp_server("FileSystemServer") +server = temporal_mcp_server("weather") +agent = Agent(name="weather", mcp_servers=[server]) +``` - agent = Agent( - name="File Assistant", - instructions="Use the filesystem tools to read files and answer questions.", - mcp_servers=[server], - ) +Configure transport, connection, retry, and message-handling behavior on the +worker-side OpenAI `MCPServer`. Configure workflow-facing behavior such as +`tool_filter`, `require_approval`, `failure_error_function`, and metadata +resolvers on `temporal_mcp_server(...)`, where the OpenAI agent can use it. +Custom `MCPServer` method implementations still execute worker-side. A callable +`tool_filter` on the worker-side server is rejected, because the run context and +agent it receives exist only in the workflow. + +Every MCP operation is a Temporal Activity. The workflow-side tool list is +cached by default; pass `cache_tools_list=False` to refresh it on every Agents +SDK listing. A parameterless factory's connection is also reused for up to five +idle minutes when it negotiates the modern, sessionless protocol. Set +`mcp_connection_idle_timeout=None` to keep cached modern connections until +plugin shutdown, or `timedelta(0)` to close them as soon as they become idle. +Connections that negotiate a legacy handshake are closed after the current +Activity and are never shared across workflows. + +An optional `factory_argument` can select worker-side configuration such as a +tenant endpoint: - result = await Runner.run(agent, input=query) - return result.final_output +```python +server = temporal_mcp_server( + "weather", + factory_argument={"tenant": "acme"}, +) ``` -The `StatelessMCPServerProvider` takes a factory function that creates new MCP server instances. The server name used in `stateless_mcp_server()` must match the name configured in the MCP server instance. In this example, the name is `FileSystemServer`. +A non-`None` argument creates a fresh client for each Activity. Omitting the +argument or passing `None` uses the zero-argument factory and permits connection +caching. Caching by only the registered name could otherwise +reuse one tenant's endpoint or authorization for another tenant; caching by the +argument itself is unsafe because arguments may be unhashable, high-cardinality, +or refer to configuration that changes worker-side. The argument is recorded in +workflow history, so it must be a non-secret stable identifier. Resolve secrets +inside the factory. -### Stateful MCP Servers +MCP v2 uses `httpx2`, not legacy `httpx`. OpenAI Agents owns the custom HTTP +client lifecycle supplied through its MCP server parameters: -For implementation details and examples, see the [samples repository](https://github.com/temporalio/samples-python/tree/main/openai_agents/mcp). +```python +import httpx2 +from agents.mcp import MCPServerStreamableHttp -When using stateful servers, the dedicated worker maintaining the connection may fail due to network issues or server problems. When this happens, Temporal raises an `ApplicationError` and cannot automatically recover because it cannot restore the lost server state. -To recover from such failures, you need to implement your own application-level retry logic. -### Factory Arguments +def http_client_factory(headers=None, timeout=None, auth=None): + return httpx2.AsyncClient( + headers={**(headers or {}), "X-Client": "temporal"}, + timeout=timeout, + auth=auth, + ) -Both `stateless_mcp_server()` and `stateful_mcp_server()` accept an optional `factory_argument`, which is passed to the registered server factory when the MCP server is created. -A stateless factory that declares no parameters — like the `lambda: MCPServerStdio(...)` example above — ignores the value, but it is still recorded in history. +def weather_server() -> MCPServerStreamableHttp: + return MCPServerStreamableHttp( + name="weather", + params={ + "url": "https://example.com/mcp", + "httpx_client_factory": http_client_factory, + }, + ) +``` -**Do not pass secrets, credentials, or API keys through `factory_argument`.** It is an activity argument, so it is recorded in workflow history and, without a payload codec, visible in the web UI. Resolve credentials worker-side inside the server factory instead. +`StatelessMCPServerProvider`, `StatefulMCPServerProvider`, the plugin's +`mcp_server_providers` option, `stateless_mcp_server()`, and +`stateful_mcp_server()` are deprecated. They remain supported for source and +workflow-history compatibility and can still run with MCP Python SDK v1. New +integrations should use `mcp_servers` and `temporal_mcp_server()`, which require +MCP Python SDK v2. The legacy stateful path retains its dedicated per-workflow +worker and persistent-session behavior. ### Hosted MCP Tool @@ -811,17 +798,19 @@ As described in [Tool Calling](#tool-calling), context propagation is read-only ### MCP -The MCP protocol is stateful, but many MCP servers are stateless. -We let you choose between two MCP wrappers, one designed for stateless MCP servers and one for stateful MCP servers. -These wrappers work with all transport varieties. +The integration supports MCP Python SDK v2 clients. Modern MCP protocol +connections are sessionless; transport connections may still be reused as an +optimization. The OpenAI MCP server factory can use stdio, streamable HTTP, an +in-process server, or a custom v2 transport. Note that when using network-accessible MCP servers, you also can also use the tool `HostedMCPTool`, which is part of the OpenAI Responses API and uses an MCP client hosted by OpenAI. -| MCP Class | Supported | +| MCP v2 client transport | Supported | | :---------------------- | :-------: | -| MCPServerStdio | Yes | -| MCPServerSse | Yes | -| MCPServerStreamableHttp | Yes | +| Stdio | Yes | +| Streamable HTTP | Yes | +| In-process server | Yes | +| Custom transport | Yes | ### Guardrails diff --git a/temporalio/contrib/openai_agents/_mcp.py b/temporalio/contrib/openai_agents/_mcp.py index 8f5294c42..00fdaf668 100644 --- a/temporalio/contrib/openai_agents/_mcp.py +++ b/temporalio/contrib/openai_agents/_mcp.py @@ -2,6 +2,7 @@ import dataclasses import functools import inspect +import warnings from collections.abc import Callable, Sequence from contextlib import AbstractAsyncContextManager from datetime import timedelta @@ -134,6 +135,10 @@ async def get_prompt( class StatelessMCPServerProvider: """A stateless MCP server implementation for Temporal workflows. + .. deprecated:: 1.32 + Use ``OpenAIAgentsPlugin(mcp_servers=...)`` and + ``workflow.temporal_mcp_server()`` instead. + This class wraps a function to create MCP servers to make them stateless by executing each MCP operation as a separate Temporal activity. Each operation (list_tools, call_tool, etc.) will connect to the underlying server, execute the operation, and then clean up the connection. @@ -155,6 +160,13 @@ def __init__( so that state is not shared between workflow runs. It may accept a single positional parameter, which receives a ``factory_argument`` from the workflow. """ + warnings.warn( + "StatelessMCPServerProvider is deprecated; use " + "OpenAIAgentsPlugin(mcp_servers=...) and " + "workflow.temporal_mcp_server() instead", + DeprecationWarning, + stacklevel=2, + ) self._server_factory = server_factory # Cache whether the server factory needs to be provided with arguments @@ -415,6 +427,10 @@ async def get_prompt( class StatefulMCPServerProvider: """A stateful MCP server implementation for Temporal workflows. + .. deprecated:: 1.32 + Use ``OpenAIAgentsPlugin(mcp_servers=...)`` and + ``workflow.temporal_mcp_server()`` instead. + This class wraps a function to create MCP servers to maintain a persistent connection throughout the workflow execution. It creates a dedicated worker that stays connected to the MCP server and processes operations on a dedicated task queue. @@ -441,6 +457,13 @@ def __init__( so that state is not shared between workflow runs. It receives an optional ``factory_argument`` from the workflow. """ + warnings.warn( + "StatefulMCPServerProvider is deprecated; use " + "OpenAIAgentsPlugin(mcp_servers=...) and " + "workflow.temporal_mcp_server() instead", + DeprecationWarning, + stacklevel=2, + ) self._server_factory = server_factory self._name = name + "-stateful" self._connect_handle: ActivityHandle | None = None diff --git a/temporalio/contrib/openai_agents/_mcp_backend.py b/temporalio/contrib/openai_agents/_mcp_backend.py new file mode 100644 index 000000000..8921d30af --- /dev/null +++ b/temporalio/contrib/openai_agents/_mcp_backend.py @@ -0,0 +1,129 @@ +# pyright: reportUnusedClass=false, reportUnusedFunction=false + +from __future__ import annotations + +from collections.abc import Callable +from types import TracebackType +from typing import Any, cast + +from agents.mcp import MCPServer +from mcp.types import ( + CallToolResult, + GetPromptResult, + Prompt, + ReadResourceResult, + RequestParamsMeta, + Resource, + ResourceTemplate, + Tool, +) +from mcp_types.version import MODERN_PROTOCOL_VERSIONS + +from temporalio.contrib.mcp._backend import ( + _NOT_SUPPLIED, + _FactoryInvoker, + _MCPBackendFactory, +) +from temporalio.exceptions import ApplicationError + +_MCPServerFactory = Callable[[], MCPServer] | Callable[[Any], MCPServer] + + +class _OpenAIMCPServerBackend: + """Adapt an OpenAI Agents MCPServer to durable MCP Activities.""" + + def __init__(self, server: MCPServer) -> None: + self._server = server + + async def __aenter__(self) -> "_OpenAIMCPServerBackend": + await self._server.connect() + return self + + async def __aexit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, + ) -> None: + await self._server.cleanup() + + @property + def cacheable(self) -> bool: + session = getattr(self._server, "session", None) + return getattr(session, "protocol_version", None) in MODERN_PROTOCOL_VERSIONS + + async def list_tools(self) -> list[Tool]: + return await self._server.list_tools() + + async def call_tool( + self, + name: str, + arguments: dict[str, Any] | None, + meta: RequestParamsMeta | None, + ) -> CallToolResult: + return await self._server.call_tool( + name, arguments, cast(dict[str, Any] | None, meta) + ) + + async def list_prompts(self) -> list[Prompt]: + return (await self._server.list_prompts()).prompts + + async def get_prompt( + self, name: str, arguments: dict[str, str] | None + ) -> GetPromptResult: + return await self._server.get_prompt(name, arguments) + + async def list_resources(self) -> list[Resource]: + return await self._list_all("list_resources", "resources") + + async def list_resource_templates(self) -> list[ResourceTemplate]: + return await self._list_all("list_resource_templates", "resource_templates") + + async def _list_all(self, method: str, field: str) -> list[Any]: + values: list[Any] = [] + cursor: str | None = None + seen_cursors: set[str | None] = set() + while True: + result = await getattr(self._server, method)(cursor) + values.extend(getattr(result, field)) + seen_cursors.add(cursor) + next_cursor = result.next_cursor + if next_cursor is None: + return values + if next_cursor in seen_cursors: + raise ValueError("MCP server returned a repeated pagination cursor") + cursor = next_cursor + + async def read_resource(self, uri: str) -> ReadResourceResult: + return await self._server.read_resource(uri) + + +def _reject_dynamic_tool_filter(name: str, server: MCPServer) -> None: + """Fail fast on a worker-side filter that can never be applied. + + A callable ``tool_filter`` needs the run context and agent, which exist only + in the workflow, so the Agents SDK rejects one on the worker side and the + list-tools Activity would otherwise retry forever. A static filter needs + neither and is applied here as usual. + """ + if callable(getattr(server, "tool_filter", None)): + raise ApplicationError( + f"MCP server {name!r} sets a callable tool_filter on its worker-side " + "MCPServer, which cannot be applied there because the run context " + "and agent it receives exist only in the workflow; pass the filter " + "to temporal_mcp_server() instead", + non_retryable=True, + ) + + +def _mcp_server_backend_factory( + name: str, factory: _MCPServerFactory +) -> _MCPBackendFactory: + invoke = _FactoryInvoker(name, factory) + + def create(argument: Any = _NOT_SUPPLIED) -> _OpenAIMCPServerBackend: + server = cast(MCPServer, invoke(argument)) + _reject_dynamic_tool_filter(name, server) + return _OpenAIMCPServerBackend(server) + + return create diff --git a/temporalio/contrib/openai_agents/_openai_runner.py b/temporalio/contrib/openai_agents/_openai_runner.py index 369b1d345..6ca806d76 100644 --- a/temporalio/contrib/openai_agents/_openai_runner.py +++ b/temporalio/contrib/openai_agents/_openai_runner.py @@ -155,16 +155,25 @@ def _prepare_workflow_run( ) for s in starting_agent.mcp_servers: - if not isinstance( + if isinstance( s, ( _StatelessMCPServerReference, _StatefulMCPServerReference, ), ): - raise ValueError( - f"Unknown mcp_server type {type(s)} may not work durably." - ) + continue + # Avoid importing the MCP v2-only proxy while validating a + # workflow that uses the legacy MCP v1 provider path. + if ( + type(s).__module__ + == "temporalio.contrib.openai_agents._temporal_mcp_server" + and type(s).__name__ == "_TemporalMCPServer" + ): + continue + raise ValueError( + f"Unknown mcp_server type {type(s)} may not work durably." + ) if isinstance(kwargs.get("session"), SQLiteSession): raise ValueError("Temporal workflows don't support SQLite sessions.") diff --git a/temporalio/contrib/openai_agents/_temporal_mcp_server.py b/temporalio/contrib/openai_agents/_temporal_mcp_server.py new file mode 100644 index 000000000..26b513bab --- /dev/null +++ b/temporalio/contrib/openai_agents/_temporal_mcp_server.py @@ -0,0 +1,126 @@ +"""Adapter exposing durable MCP v2 clients as OpenAI Agents MCP servers.""" + +# pyright: reportUnusedClass=false + +from __future__ import annotations + +import inspect +from typing import Any, cast + +from agents import AgentBase, RunContextWrapper +from agents.mcp import MCPServer +from agents.mcp.util import ToolFilter, ToolFilterContext +from mcp.types import ( + CallToolResult, + GetPromptResult, + ListPromptsResult, + ListResourcesResult, + ListResourceTemplatesResult, + ReadResourceResult, + RequestParamsMeta, + Tool, +) + +from temporalio.contrib.mcp._workflow import TemporalMCPClient + + +class _TemporalMCPServer(MCPServer): + def __init__( + self, + client: TemporalMCPClient, + *, + tool_filter: ToolFilter = None, + **kwargs: Any, + ) -> None: + self._client = client + self._tool_filter = tool_filter + super().__init__(**kwargs) + + @property + def name(self) -> str: + return self._client.name + + async def connect(self) -> None: + pass + + async def cleanup(self) -> None: + pass + + async def list_tools( + self, + run_context: RunContextWrapper[Any] | None = None, + agent: AgentBase | None = None, + ) -> list[Tool]: + tools = (await self._client.list_tools()).tools + if self._tool_filter is None: + return tools + if isinstance(self._tool_filter, dict): + if "allowed_tool_names" in self._tool_filter: + allowed = self._tool_filter["allowed_tool_names"] + tools = [tool for tool in tools if tool.name in allowed] + if "blocked_tool_names" in self._tool_filter: + blocked = self._tool_filter["blocked_tool_names"] + tools = [tool for tool in tools if tool.name not in blocked] + return tools + if run_context is None or agent is None: + raise ValueError( + "run_context and agent are required for dynamic MCP tool filtering" + ) + context = ToolFilterContext( + run_context=run_context, agent=agent, server_name=self.name + ) + filtered: list[Tool] = [] + for tool in tools: + included = self._tool_filter(context, tool) + if inspect.isawaitable(included): + included = await included + if included: + filtered.append(tool) + return filtered + + @property + def cached_tools(self) -> list[Tool] | None: + result = self._client.cached_tools + return result.tools if result is not None else None + + async def call_tool( + self, + tool_name: str, + arguments: dict[str, Any] | None, + meta: dict[str, Any] | None = None, + ) -> CallToolResult: + return await self._client.call_tool( + tool_name, arguments, meta=cast(RequestParamsMeta | None, meta) + ) + + async def list_prompts(self) -> ListPromptsResult: + return await self._client.list_prompts() + + async def get_prompt( + self, name: str, arguments: dict[str, Any] | None = None + ) -> GetPromptResult: + string_arguments = ( + None + if arguments is None + else {key: str(value) for key, value in arguments.items()} + ) + return await self._client.get_prompt(name, string_arguments) + + async def list_resources(self, cursor: str | None = None) -> ListResourcesResult: + if cursor is not None: + raise ValueError( + "Temporal MCP servers return fully paginated resource lists" + ) + return await self._client.list_resources() + + async def list_resource_templates( + self, cursor: str | None = None + ) -> ListResourceTemplatesResult: + if cursor is not None: + raise ValueError( + "Temporal MCP servers return fully paginated resource template lists" + ) + return await self._client.list_resource_templates() + + async def read_resource(self, uri: str) -> ReadResourceResult: + return await self._client.read_resource(uri) diff --git a/temporalio/contrib/openai_agents/_temporal_openai_agents.py b/temporalio/contrib/openai_agents/_temporal_openai_agents.py index 6023ad090..75fdcec0d 100644 --- a/temporalio/contrib/openai_agents/_temporal_openai_agents.py +++ b/temporalio/contrib/openai_agents/_temporal_openai_agents.py @@ -4,12 +4,21 @@ import json import threading import typing -from collections.abc import AsyncIterator, Callable, Collection, Iterator, Sequence +import warnings +from collections.abc import ( + AsyncIterator, + Callable, + Collection, + Iterator, + Mapping, + Sequence, +) from contextlib import asynccontextmanager, contextmanager from datetime import timedelta import pydantic from agents import ModelProvider, Trace, set_trace_provider +from agents.mcp import MCPServer from agents.run import get_default_agent_runner, set_default_agent_runner from agents.tracing import get_trace_provider from agents.tracing.provider import DefaultTraceProvider @@ -254,8 +263,8 @@ class OpenAIAgentsPlugin(SimplePlugin): Example: >>> from temporalio.client import Client >>> from temporalio.worker import Worker - >>> from temporalio.contrib.openai_agents import OpenAIAgentsPlugin, ModelActivityParameters, StatelessMCPServerProvider - >>> from agents.mcp import MCPServerStdio + >>> from agents.mcp import MCPServerStreamableHttp + >>> from temporalio.contrib.openai_agents import OpenAIAgentsPlugin, ModelActivityParameters >>> from datetime import timedelta >>> >>> # Configure model parameters @@ -264,16 +273,11 @@ class OpenAIAgentsPlugin(SimplePlugin): ... retry_policy=RetryPolicy(maximum_attempts=3) ... ) >>> - >>> # Create MCP servers - >>> filesystem_server = StatelessMCPServerProvider(MCPServerStdio( - ... name="Filesystem Server", - ... params={"command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "."]} - ... )) - >>> - >>> # Create plugin with MCP servers >>> plugin = OpenAIAgentsPlugin( ... model_params=model_params, - ... mcp_server_providers=[filesystem_server] + ... mcp_servers={"filesystem": lambda: MCPServerStreamableHttp( + ... name="filesystem", params={"url": "https://example.com/mcp"} + ... )} ... ) >>> >>> # Use with client and worker @@ -300,6 +304,9 @@ def __init__( add_temporal_spans: bool = True, use_otel_instrumentation: bool = False, resolvable_worker_env_vars: Collection[str] | AllowAllWorkerEnvVars = (), + *, + mcp_servers: Mapping[str, Callable[..., MCPServer]] | None = None, + mcp_connection_idle_timeout: timedelta | None = timedelta(minutes=5), ) -> None: """Initialize the OpenAI agents plugin. @@ -308,10 +315,19 @@ def __init__( of model calls. If None, default parameters will be used. model_provider: Optional model provider for custom model implementations. Useful for testing or custom model integrations. - mcp_server_providers: Sequence of MCP servers to automatically register with the worker. - Each server will be wrapped in a TemporalMCPServer if not already wrapped, - and their activities will be automatically registered with the worker. - The plugin manages the connection lifecycle of these servers. + mcp_server_providers: Legacy MCP server providers to register with the + worker. Deprecated; use ``mcp_servers`` for new MCP v2 + integrations. + mcp_servers: Named OpenAI MCP server factories to register on the worker. + Each factory may declare at most one positional parameter, which + receives the workflow's ``factory_argument`` (``None`` when the + workflow supplied none); a factory declaring more raises here. A + parameterless factory's modern connection is cached between + Activities. A factory called with a workflow ``factory_argument`` + always creates a fresh server for that Activity. + mcp_connection_idle_timeout: How long an idle modern MCP connection + remains cached. Defaults to five minutes. None disables idle + eviction, and zero disables reuse. sandbox_clients: Sequence of named sandbox client providers to register on the worker. Each provider pairs a unique name with a real ``BaseSandboxClient`` (e.g. ``DaytonaSandboxClient``, @@ -353,6 +369,36 @@ def __init__( ) self._use_otel_instrumentation = use_otel_instrumentation + if mcp_server_providers: + warnings.warn( + "mcp_server_providers is deprecated; use mcp_servers with " + "workflow.temporal_mcp_server() instead", + DeprecationWarning, + stacklevel=2, + ) + + mcp_activities = None + if mcp_servers: + # The shared Activity layer requires MCP v2, but the legacy OpenAI + # provider path remains importable with MCP v1. + try: + from temporalio.contrib.mcp._activities import _MCPActivities + from temporalio.contrib.openai_agents._mcp_backend import ( + _mcp_server_backend_factory, + ) + except ImportError as err: + raise RuntimeError( + "mcp_servers requires MCP Python SDK v2; use the deprecated " + "mcp_server_providers API when running with MCP v1" + ) from err + + mcp_activities = _MCPActivities( + { + name: _mcp_server_backend_factory(name, factory) + for name, factory in mcp_servers.items() + }, + idle_timeout=mcp_connection_idle_timeout, + ) resolvable_env_vars = _snapshot_resolvable_env_vars(resolvable_worker_env_vars) @@ -371,12 +417,14 @@ def add_activities( model_activity.invoke_model_activity_streaming, ] + if mcp_activities: + new_activities.extend(mcp_activities.activities) + server_names = [server.name for server in mcp_server_providers] if len(server_names) != len(set(server_names)): raise ValueError( "More than one mcp server registered with the same name. Please provide unique names." ) - for mcp_server in mcp_server_providers: new_activities.extend(mcp_server._get_activities()) @@ -431,12 +479,21 @@ def workflow_runner(runner: WorkflowRunner | None) -> WorkflowRunner: @asynccontextmanager async def run_context() -> AsyncIterator[None]: - with self.tracing_context(): - with _set_open_ai_agent_temporal_overrides( - model_params, - start_spans_in_replay=use_otel_instrumentation, - ): - yield + if mcp_activities: + async with mcp_activities.run_context(): + with self.tracing_context(): + with _set_open_ai_agent_temporal_overrides( + model_params, + start_spans_in_replay=use_otel_instrumentation, + ): + yield + else: + with self.tracing_context(): + with _set_open_ai_agent_temporal_overrides( + model_params, + start_spans_in_replay=use_otel_instrumentation, + ): + yield super().__init__( name="OpenAIAgentsPlugin", diff --git a/temporalio/contrib/openai_agents/testing.py b/temporalio/contrib/openai_agents/testing.py index 0c6b149c3..8bfeac4fd 100644 --- a/temporalio/contrib/openai_agents/testing.py +++ b/temporalio/contrib/openai_agents/testing.py @@ -1,6 +1,8 @@ """Testing utilities for OpenAI agents.""" -from collections.abc import AsyncIterator, Callable, Collection, Sequence +import hashlib +from collections.abc import AsyncIterator, Callable, Collection, Mapping, Sequence +from datetime import timedelta from typing import Any from agents import ( @@ -16,6 +18,7 @@ Usage, ) from agents.items import TResponseOutputItem, TResponseStreamEvent +from agents.mcp import MCPServer from openai.types.responses import ( ResponseFunctionToolCall, ResponseOutputMessage, @@ -72,15 +75,22 @@ def response_output_message(text: str) -> ResponseOutputMessage: ) @staticmethod - def tool_call(arguments: str, name: str) -> ModelResponse: + def tool_call( + arguments: str, + name: str, + *, + call_id: str | None = None, + item_id: str | None = None, + ) -> ModelResponse: """Create a ModelResponse with a function tool call.""" + identity = hashlib.sha256(f"{name}\0{arguments}".encode()).hexdigest()[:16] return ResponseBuilders.model_response( ResponseFunctionToolCall( arguments=arguments, - call_id="call", + call_id=call_id or f"call-{identity}", name=name, type="function_call", - id="id", + id=item_id or f"item-{identity}", status="completed", ) ) @@ -186,6 +196,9 @@ def __init__( add_temporal_spans: bool = True, use_otel_instrumentation: bool = False, resolvable_worker_env_vars: Collection[str] | AllowAllWorkerEnvVars = (), + *, + mcp_servers: Mapping[str, Callable[..., MCPServer]] | None = None, + mcp_connection_idle_timeout: timedelta | None = timedelta(minutes=5), ) -> None: """Initialize the AgentEnvironment. @@ -200,7 +213,12 @@ def __init__( Equivalent to model_provider=TestModelProvider(model). Only one of model_provider or model should be provided. If both are provided, model_provider will be used. - mcp_server_providers: Sequence of MCP servers to automatically register with the worker. + mcp_server_providers: Legacy MCP server providers to register with the + worker. Deprecated; use ``mcp_servers`` for new MCP v2 + integrations. + mcp_servers: Named OpenAI MCP server factories to register with the worker. + mcp_connection_idle_timeout: How long idle modern connections are reused. + None disables idle eviction, and zero disables reuse. register_activities: Whether to register activities during worker execution. add_temporal_spans: Whether to add temporal spans to traces use_otel_instrumentation: If set to true, enable open telemetry instrumentation. @@ -220,6 +238,8 @@ def __init__( elif model is not None: self._model_provider = TestModelProvider(model) self._mcp_server_providers = mcp_server_providers + self._mcp_servers = mcp_servers + self._mcp_connection_idle_timeout = mcp_connection_idle_timeout self._register_activities = register_activities self._plugin: OpenAIAgentsPlugin | None = None self._add_temporal_spans = add_temporal_spans @@ -235,6 +255,8 @@ async def __aenter__(self) -> "AgentEnvironment": model_params=self._model_params, model_provider=self._model_provider, mcp_server_providers=self._mcp_server_providers, + mcp_servers=self._mcp_servers, + mcp_connection_idle_timeout=self._mcp_connection_idle_timeout, register_activities=self._register_activities, add_temporal_spans=self._add_temporal_spans, use_otel_instrumentation=self._use_otel_instrumentation, diff --git a/temporalio/contrib/openai_agents/workflow.py b/temporalio/contrib/openai_agents/workflow.py index 70f54629f..74b3cf3e7 100644 --- a/temporalio/contrib/openai_agents/workflow.py +++ b/temporalio/contrib/openai_agents/workflow.py @@ -287,6 +287,9 @@ def stateless_mcp_server( ) -> "MCPServer": """A stateless MCP server implementation for Temporal workflows. + .. deprecated:: 1.32 + Use :py:func:`temporal_mcp_server` instead. + This uses a TemporalMCPServer of the same name registered with the OpenAIAgents plugin to implement durable MCP operations statelessly. @@ -308,6 +311,13 @@ def stateless_mcp_server( factory_argument: Optional argument to be provided to the factory when producing an MCPServer. Must not contain secrets. """ + import warnings + + warnings.warn( + "stateless_mcp_server() is deprecated; use temporal_mcp_server() instead", + DeprecationWarning, + stacklevel=2, + ) from temporalio.contrib.openai_agents._mcp import ( _StatelessMCPServerReference, ) @@ -325,6 +335,9 @@ def stateful_mcp_server( ) -> AbstractAsyncContextManager["MCPServer"]: """A stateful MCP server implementation for Temporal workflows. + .. deprecated:: 1.32 + Use :py:func:`temporal_mcp_server` instead. + This wraps an MCP server to maintain a persistent connection throughout the workflow execution. It creates a dedicated worker that stays connected to the MCP server and processes operations on a dedicated task queue. @@ -351,6 +364,13 @@ def stateful_mcp_server( factory_argument: Optional argument to be provided to the factory when producing an MCPServer. Must not contain secrets. """ + import warnings + + warnings.warn( + "stateful_mcp_server() is deprecated; use temporal_mcp_server() instead", + DeprecationWarning, + stacklevel=2, + ) from temporalio.contrib.openai_agents._mcp import ( _StatefulMCPServerReference, ) @@ -360,6 +380,59 @@ def stateful_mcp_server( ) +def temporal_mcp_server( + name: str, + activity_config: ActivityConfig | None = None, + cache_tools_list: bool = True, + factory_argument: Any = None, + **server_options: Any, +) -> "MCPServer": + """Create a durable MCP v2 server proxy for an OpenAI agent in a workflow. + + MCP operations execute as Activities using the server factory registered as + ``OpenAIAgentsPlugin(mcp_servers={name: factory})``. The tool list is cached + in workflow state by default. Set ``cache_tools_list=False`` to list tools on + every OpenAI Agents turn. + + .. warning:: + Do not pass secrets, credentials, or API keys through ``factory_argument``. It is an + activity argument, so it is recorded in workflow history and, without a payload codec, + visible in the web UI. Resolve credentials worker-side inside the server factory + instead. + + Args: + name: Name matching a server factory registered on the plugin. + activity_config: Activity options for MCP operations. Defaults to a + one-minute start-to-close timeout. + cache_tools_list: Whether to cache the tool list for this object. + factory_argument: Non-secret value passed to the worker-side factory. + A non-None value creates a fresh server for every Activity instead + of using the worker connection cache. + server_options: OpenAI Agents ``MCPServer`` options such as + ``require_approval`` and ``failure_error_function``. + """ + try: + from temporalio.contrib.mcp._workflow import TemporalMCPClient + from temporalio.contrib.openai_agents._temporal_mcp_server import ( + _TemporalMCPServer, + ) + except ImportError as err: + raise RuntimeError( + "temporal_mcp_server() requires MCP Python SDK v2; use the deprecated " + "stateless_mcp_server() or stateful_mcp_server() API with MCP v1" + ) from err + + return _TemporalMCPServer( + TemporalMCPClient( + name, + activity_config=activity_config, + cache_tools_list=cache_tools_list, + factory_argument=factory_argument, + ), + **server_options, + ) + + class ToolSerializationError(TemporalError): """Error that occurs when a tool output could not be serialized. diff --git a/tests/contrib/google_genai/test_gemini.py b/tests/contrib/google_genai/test_gemini.py index 0881f63b3..880f996f9 100644 --- a/tests/contrib/google_genai/test_gemini.py +++ b/tests/contrib/google_genai/test_gemini.py @@ -292,8 +292,8 @@ async def gemini_file_search_stores_upload( self, req: _GeminiUploadToFileSearchStoreRequest ) -> types.UploadToFileSearchStoreOperation: self.file_search_store_upload_requests.append(req) - return types.UploadToFileSearchStoreOperation.model_construct( - name="operations/test-op", + return types.UploadToFileSearchStoreOperation.model_validate( + {"name": "operations/test-op"} ) @activity.defn @@ -1387,8 +1387,8 @@ async def _gen(): ) gemini.aio.files.download = AsyncMock(return_value=b"mock download content") # type: ignore[method-assign] gemini.aio.file_search_stores.upload_to_file_search_store = AsyncMock( # type: ignore[method-assign] - return_value=types.UploadToFileSearchStoreOperation.model_construct( - name="operations/mock-op" + return_value=types.UploadToFileSearchStoreOperation.model_validate( + {"name": "operations/mock-op"} ) ) diff --git a/tests/contrib/mcp/__init__.py b/tests/contrib/mcp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/contrib/mcp/echo_mcp_server.py b/tests/contrib/mcp/echo_mcp_server.py new file mode 100644 index 000000000..638369f8c --- /dev/null +++ b/tests/contrib/mcp/echo_mcp_server.py @@ -0,0 +1,15 @@ +"""MCP v2 echo server used by transport integration tests.""" + +from mcp.server.mcpserver import MCPServer + +server = MCPServer("echo") + + +@server.tool() +def echo(value: str) -> str: + """Return the input unchanged.""" + return value + + +if __name__ == "__main__": + server.run() diff --git a/tests/contrib/mcp/test_activities.py b/tests/contrib/mcp/test_activities.py new file mode 100644 index 000000000..f377886e6 --- /dev/null +++ b/tests/contrib/mcp/test_activities.py @@ -0,0 +1,139 @@ +from datetime import timedelta +from typing import Any, cast + +from mcp.types import ( + CallToolResult, + GetPromptResult, + ListPromptsResult, + ListResourcesResult, + ListResourceTemplatesResult, + ListToolsResult, + Prompt, + PromptMessage, + ReadResourceResult, + Resource, + ResourceTemplate, + TextContent, + TextResourceContents, + Tool, +) + +from temporalio import activity +from temporalio.contrib.mcp._activities import _MCPActivities +from temporalio.contrib.mcp._client import _MCPClientBackend + + +class FakeClient: + protocol_version = "2026-07-28" + + def __init__(self) -> None: + self.metas: list[dict[str, Any] | None] = [] + + async def __aenter__(self) -> "FakeClient": + return self + + async def __aexit__(self, *args: Any) -> None: + pass + + def _page(self, cursor: str | None) -> tuple[str, str | None]: + return ("one", "next") if cursor is None else ("two", None) + + async def list_tools( + self, *, cursor: str | None, cache_mode: str + ) -> ListToolsResult: + assert cache_mode == "bypass" + name, next_cursor = self._page(cursor) + return ListToolsResult( + tools=[Tool(name=name, input_schema={"type": "object"})], + next_cursor=next_cursor, + ) + + async def list_prompts(self, *, cursor: str | None) -> ListPromptsResult: + name, next_cursor = self._page(cursor) + return ListPromptsResult(prompts=[Prompt(name=name)], next_cursor=next_cursor) + + async def list_resources(self, *, cursor: str | None) -> ListResourcesResult: + name, next_cursor = self._page(cursor) + return ListResourcesResult( + resources=[Resource(name=name, uri=f"test://{name}")], + next_cursor=next_cursor, + ) + + async def list_resource_templates( + self, *, cursor: str | None + ) -> ListResourceTemplatesResult: + name, next_cursor = self._page(cursor) + return ListResourceTemplatesResult( + resource_templates=[ + ResourceTemplate(name=name, uri_template=f"test://{name}/{{id}}") + ], + next_cursor=next_cursor, + ) + + async def call_tool( + self, + name: str, + _arguments: dict[str, Any] | None, + *, + meta: dict[str, Any] | None, + ) -> CallToolResult: + self.metas.append(meta) + return CallToolResult(content=[TextContent(text=name)]) + + async def get_prompt( + self, name: str, _arguments: dict[str, str] | None + ) -> GetPromptResult: + return GetPromptResult( + messages=[PromptMessage(role="user", content=TextContent(text=name))] + ) + + async def read_resource(self, uri: str) -> ReadResourceResult: + return ReadResourceResult( + contents=[TextResourceContents(uri=uri, text="contents")] + ) + + +async def test_operations_are_plain_json_and_lists_are_fully_paginated() -> None: + client = FakeClient() + support = _MCPActivities( + {"test": lambda: _MCPClientBackend(cast(Any, client))}, + idle_timeout=timedelta(minutes=5), + ) + functions: dict[str, Any] = {} + for fn in support.activities: + definition = activity._Definition.from_callable(fn) + assert definition is not None and definition.name is not None + functions[definition.name] = fn + request: dict[str, Any] = {"factory_argument": None} + try: + for operation, result_key in ( + ("list-tools", "tools"), + ("list-prompts", "prompts"), + ("list-resources", "resources"), + ("list-resource-templates", "resource_templates"), + ): + result = await functions[f"temporalio.contrib.mcp.test.{operation}"]( + request + ) + assert [item["name"] for item in result[result_key]] == ["one", "two"] + assert result["next_cursor"] is None + + tool_result = await functions["temporalio.contrib.mcp.test.call-tool"]( + {**request, "name": "echo", "arguments": {}, "meta": {"trace": "value"}} + ) + assert tool_result["content"][0]["text"] == "echo" + + prompt_result = await functions["temporalio.contrib.mcp.test.get-prompt"]( + {**request, "name": "prompt", "arguments": {}} + ) + assert prompt_result["messages"][0]["content"]["text"] == "prompt" + + resource_result = await functions["temporalio.contrib.mcp.test.read-resource"]( + {**request, "uri": "test://resource"} + ) + assert resource_result["contents"][0]["text"] == "contents" + + # call_tool is the only operation that carries request metadata. + assert client.metas == [{"trace": "value"}] + finally: + await support._pool.close() diff --git a/tests/contrib/mcp/test_backend.py b/tests/contrib/mcp/test_backend.py new file mode 100644 index 000000000..0928206d2 --- /dev/null +++ b/tests/contrib/mcp/test_backend.py @@ -0,0 +1,63 @@ +from typing import Any + +import pytest + +from temporalio.contrib.mcp._backend import _factory_accepts_argument, _FactoryInvoker +from temporalio.exceptions import ApplicationError + + +def test_parameterless_factory_is_called_with_no_arguments() -> None: + invoke = _FactoryInvoker("echo", lambda: "made") + assert _factory_accepts_argument("echo", lambda: None) is False + assert invoke() == "made" + + +def test_single_parameter_factory_receives_none_when_unsupplied() -> None: + def factory(argument: Any | None) -> Any: + return argument + + invoke = _FactoryInvoker("echo", factory) + assert invoke() is None + assert invoke({"tenant": "acme"}) == {"tenant": "acme"} + + +def test_defaulted_parameter_factory_receives_the_argument() -> None: + def factory(argument: Any = "default") -> Any: + return argument + + invoke = _FactoryInvoker("echo", factory) + assert invoke() is None + assert invoke("supplied") == "supplied" + + +def test_var_positional_factory_receives_the_argument() -> None: + invoke = _FactoryInvoker("echo", lambda *args: args) + assert invoke("supplied") == ("supplied",) + + +def test_var_keyword_only_factory_is_called_with_no_arguments() -> None: + invoke = _FactoryInvoker("echo", lambda **kwargs: kwargs) + assert invoke() == {} + + +def test_argument_for_parameterless_factory_fails_without_retry() -> None: + invoke = _FactoryInvoker("echo", lambda: "made") + with pytest.raises(ApplicationError, match="declares no parameters") as err: + invoke({"tenant": "acme"}) + assert err.value.non_retryable is True + + +def test_multi_parameter_factory_rejected_at_registration() -> None: + def factory(first: Any, second: Any) -> Any: + return first, second + + with pytest.raises(TypeError, match="requires 2 parameters"): + _FactoryInvoker("echo", factory) + + +def test_keyword_only_parameter_factory_rejected_at_registration() -> None: + def factory(*, argument: Any) -> Any: + return argument + + with pytest.raises(TypeError, match="keyword-only parameter 'argument'"): + _FactoryInvoker("echo", factory) diff --git a/tests/contrib/mcp/test_pool.py b/tests/contrib/mcp/test_pool.py new file mode 100644 index 000000000..f9dd9425b --- /dev/null +++ b/tests/contrib/mcp/test_pool.py @@ -0,0 +1,323 @@ +import asyncio +from datetime import timedelta +from typing import Any, cast + +import pytest +from mcp import Client +from mcp.server.mcpserver import MCPServer + +from temporalio.contrib.mcp._client import _MCPClientBackend +from temporalio.contrib.mcp._pool import _MCPConnectionPool + + +def echo_server() -> MCPServer[Any]: + server = MCPServer("echo") + + @server.tool() + def echo(value: str) -> str: # type: ignore[reportUnusedFunction] + return value + + return server + + +async def test_modern_connection_is_reused() -> None: + server = echo_server() + created = 0 + + def factory() -> _MCPClientBackend: + nonlocal created + created += 1 + return _MCPClientBackend(Client(server)) + + pool = _MCPConnectionPool({"echo": factory}, timedelta(minutes=5)) + try: + for _ in range(2): + async with pool.backend( + "echo", + factory_argument=None, + ) as client: + result = await client.call_tool("echo", {"value": "hi"}, None) + assert result.is_error is False + assert created == 1 + finally: + await pool.close() + + +async def test_non_none_factory_argument_always_uses_fresh_connection() -> None: + server = echo_server() + arguments: list[Any] = [] + + def factory(argument: Any) -> _MCPClientBackend: + arguments.append(argument) + return _MCPClientBackend(Client(server)) + + pool = _MCPConnectionPool({"echo": cast(Any, factory)}, timedelta(minutes=5)) + try: + for _ in range(2): + async with pool.backend( + "echo", + factory_argument={"tenant": "acme"}, + ): + pass + assert arguments == [{"tenant": "acme"}, {"tenant": "acme"}] + finally: + await pool.close() + + +async def test_legacy_fallback_is_not_reused() -> None: + server = echo_server() + created = 0 + + def factory() -> _MCPClientBackend: + nonlocal created + created += 1 + return _MCPClientBackend(Client(server, mode="legacy")) + + pool = _MCPConnectionPool({"echo": factory}, timedelta(minutes=5)) + try: + for _ in range(2): + async with pool.backend( + "echo", + factory_argument=None, + ): + pass + assert created == 2 + finally: + await pool.close() + + +@pytest.mark.parametrize("idle_timeout", [None, timedelta(minutes=5)]) +async def test_connection_reused_without_idle_eviction( + idle_timeout: timedelta | None, +) -> None: + server = echo_server() + created = 0 + + def factory() -> _MCPClientBackend: + nonlocal created + created += 1 + return _MCPClientBackend(Client(server)) + + pool = _MCPConnectionPool({"echo": factory}, idle_timeout) + try: + for _ in range(2): + async with pool.backend( + "echo", + factory_argument=None, + ): + pass + assert created == 1 + finally: + await pool.close() + + +async def test_zero_idle_timeout_disables_reuse() -> None: + server = echo_server() + created = 0 + + def factory() -> _MCPClientBackend: + nonlocal created + created += 1 + return _MCPClientBackend(Client(server)) + + pool = _MCPConnectionPool({"echo": factory}, timedelta(0)) + try: + for _ in range(2): + async with pool.backend( + "echo", + factory_argument=None, + ): + pass + assert created == 2 + finally: + await pool.close() + + +async def test_operation_failure_evicts_connection() -> None: + server = echo_server() + created = 0 + + def factory() -> _MCPClientBackend: + nonlocal created + created += 1 + return _MCPClientBackend(Client(server)) + + pool = _MCPConnectionPool({"echo": factory}, timedelta(minutes=5)) + try: + with pytest.raises(RuntimeError, match="connection failed"): + async with pool.backend( + "echo", + factory_argument=None, + ): + raise RuntimeError("connection failed") + async with pool.backend( + "echo", + factory_argument=None, + ): + pass + assert created == 2 + finally: + await pool.close() + + +async def test_failure_does_not_close_a_concurrently_used_connection() -> None: + server = echo_server() + created = 0 + + def factory() -> _MCPClientBackend: + nonlocal created + created += 1 + return _MCPClientBackend(Client(server)) + + pool = _MCPConnectionPool({"echo": factory}, timedelta(minutes=5)) + try: + entered = asyncio.Event() + release = asyncio.Event() + + async def survivor() -> Any: + async with pool.backend("echo", factory_argument=None) as client: + entered.set() + await release.wait() + return await client.call_tool("echo", {"value": "hi"}, None) + + task = asyncio.create_task(survivor()) + await entered.wait() + + # A peer operation failing must not tear the shared connection out from + # under the operation still in flight on it. + with pytest.raises(RuntimeError, match="connection failed"): + async with pool.backend("echo", factory_argument=None): + raise RuntimeError("connection failed") + + release.set() + result = await task + assert result.is_error is False + assert created == 1 + + # The retired connection is still not handed to later operations. + async with pool.backend("echo", factory_argument=None): + pass + assert created == 2 + finally: + await pool.close() + + +def test_negative_idle_timeout_rejected() -> None: + with pytest.raises(ValueError, match="cannot be negative"): + _MCPConnectionPool({}, timedelta(seconds=-1)) + + +async def test_pending_eviction_does_not_close_an_in_use_connection() -> None: + server = echo_server() + created = 0 + + def factory() -> _MCPClientBackend: + nonlocal created + created += 1 + return _MCPClientBackend(Client(server)) + + pool = _MCPConnectionPool({"echo": factory}, timedelta(minutes=5)) + try: + async with pool.backend("echo", factory_argument=None): + pass + key = next(iter(pool._records)) + record = pool._records[key] + + entered = asyncio.Event() + release = asyncio.Event() + + async def survivor() -> Any: + async with pool.backend("echo", factory_argument=None) as client: + entered.set() + await release.wait() + return await client.call_tool("echo", {"value": "hi"}, None) + + task = asyncio.create_task(survivor()) + await entered.wait() + + # A peer failure retires and unmaps the record while the survivor is + # still in flight on it. + with pytest.raises(RuntimeError, match="connection failed"): + async with pool.backend("echo", factory_argument=None): + raise RuntimeError("connection failed") + + # An idle-eviction task armed before either operation acquired the + # record now runs. It cannot be cancelled once created, so it must + # notice the record is still in use rather than closing the transport. + await pool._evict(key, record, only_if_idle=True) + + release.set() + result = await task + assert result.is_error is False + assert created == 1 + finally: + await pool.close() + + +async def test_idle_timeout_evicts_the_connection() -> None: + server = echo_server() + created = 0 + + def factory() -> _MCPClientBackend: + nonlocal created + created += 1 + return _MCPClientBackend(Client(server)) + + pool = _MCPConnectionPool({"echo": factory}, timedelta(milliseconds=10)) + try: + async with pool.backend("echo", factory_argument=None): + pass + assert created == 1 + + # The eviction runs in a task the pool must keep a strong reference to; + # an unretained one can be collected before it closes the connection. + for _ in range(100): + if not pool._records: + break + await asyncio.sleep(0.01) + assert not pool._records + + async with pool.backend("echo", factory_argument=None): + pass + assert created == 2 + finally: + await pool.close() + + +async def test_close_leaves_no_state_for_the_loop( + monkeypatch: pytest.MonkeyPatch, +) -> None: + server = echo_server() + + def factory() -> _MCPClientBackend: + return _MCPClientBackend(Client(server)) + + pool = _MCPConnectionPool({"echo": factory}, timedelta(milliseconds=50)) + async with pool.backend("echo", factory_argument=None): + pass + assert pool._locks + + record = next(iter(pool._records.values())) + original_close = record.close + close_started = asyncio.Event() + allow_close = asyncio.Event() + + async def delayed_close() -> None: + close_started.set() + await allow_close.wait() + await original_close() + + # Keep close in progress until the idle timer would have fired. This makes + # the teardown race deterministic on event loops where it is otherwise rare. + monkeypatch.setattr(record, "close", delayed_close) + close_task = asyncio.create_task(pool.close()) + await close_started.wait() + await asyncio.sleep(0.1) + allow_close.set() + await close_task + + # Locks are keyed by event loop alongside the records, so leaving them + # behind keeps every loop the pool has served alive. + assert not pool._records + assert not pool._locks + assert not pool._evictions diff --git a/tests/contrib/mcp/test_workflow.py b/tests/contrib/mcp/test_workflow.py new file mode 100644 index 000000000..7af22a830 --- /dev/null +++ b/tests/contrib/mcp/test_workflow.py @@ -0,0 +1,194 @@ +import asyncio +import sys +from collections.abc import AsyncIterator, Callable +from contextlib import asynccontextmanager +from pathlib import Path +from typing import Any, cast +from uuid import uuid4 + +from temporalio import workflow +from temporalio.contrib.mcp import TemporalMCPClient + +with workflow.unsafe.imports_passed_through(): + import uvicorn + from mcp import Client, StdioServerParameters, stdio_client + from mcp.server.mcpserver import MCPServer + from mcp.types import TextContent, TextResourceContents + + from temporalio.client import Client as TemporalClient + from temporalio.contrib.mcp import MCPPlugin + from temporalio.worker import Replayer + from tests.helpers import find_free_port, new_worker + + +def rich_server() -> MCPServer[Any]: + server = MCPServer("rich") + + @server.tool() + def echo(value: str) -> str: # type: ignore[reportUnusedFunction] + return value + + @server.prompt() + def greeting(name: str) -> str: # type: ignore[reportUnusedFunction] + return f"Hello {name}" + + @server.resource("test://static", name="static") + def static_resource() -> str: # type: ignore[reportUnusedFunction] + return "resource contents" + + @server.resource("test://items/{item}", name="item") + def item_resource(item: str) -> str: # type: ignore[reportUnusedFunction] + return item + + return server + + +@workflow.defn +class NativeMCPWorkflow: + @workflow.run + async def run(self) -> tuple[str, str, str, str, str, str, str]: + client = TemporalMCPClient("rich") + tools = await client.list_tools() + # The second call is served from replay-safe workflow state. + assert await client.list_tools() is tools + tool_result = await client.call_tool("echo", {"value": "hello"}) + prompts = await client.list_prompts() + prompt = await client.get_prompt("greeting", {"name": "Temporal"}) + resources = await client.list_resources() + templates = await client.list_resource_templates() + resource = await client.read_resource("test://static") + return ( + tools.tools[0].name, + cast(TextContent, tool_result.content[0]).text, + prompts.prompts[0].name, + cast(TextContent, prompt.messages[0].content).text, + resources.resources[0].name, + templates.resource_templates[0].name, + cast(TextResourceContents, resource.contents[0]).text, + ) + + +@workflow.defn +class TransportMCPWorkflow: + @workflow.run + async def run(self, server: str) -> str: + client = TemporalMCPClient(server) + tools = await client.list_tools() + assert [tool.name for tool in tools.tools] == ["echo"] + result = await client.call_tool("echo", {"value": "transport"}) + return cast(TextContent, result.content[0]).text + + +async def activity_names(handle: Any) -> list[str]: + names: list[str] = [] + async for event in handle.fetch_history_events(): + if event.HasField("activity_task_scheduled_event_attributes"): + names.append( + event.activity_task_scheduled_event_attributes.activity_type.name + ) + return names + + +async def test_native_workflow_operations_and_replay(client: TemporalClient) -> None: + server = rich_server() + plugin = MCPPlugin({"rich": lambda: Client(server)}) + async with new_worker(client, NativeMCPWorkflow, plugins=[plugin]) as worker: + handle = await client.start_workflow( + NativeMCPWorkflow.run, + id=f"native-mcp-{uuid4()}", + task_queue=worker.task_queue, + ) + assert await handle.result() == ( + "echo", + "hello", + "greeting", + "Hello Temporal", + "static", + "item", + "resource contents", + ) + names = await activity_names(handle) + history = await handle.fetch_history() + + assert names == [ + "temporalio.contrib.mcp.rich.list-tools", + "temporalio.contrib.mcp.rich.call-tool", + "temporalio.contrib.mcp.rich.list-prompts", + "temporalio.contrib.mcp.rich.get-prompt", + "temporalio.contrib.mcp.rich.list-resources", + "temporalio.contrib.mcp.rich.list-resource-templates", + "temporalio.contrib.mcp.rich.read-resource", + ] + await Replayer(workflows=[NativeMCPWorkflow], plugins=[plugin]).replay_workflow( + history + ) + + +async def run_transport_workflow( + client: TemporalClient, + name: str, + factory: Callable[[], Client], +) -> None: + async with new_worker( + client, + TransportMCPWorkflow, + plugins=[MCPPlugin({name: factory}, connection_idle_timeout=None)], + ) as worker: + result = await client.execute_workflow( + TransportMCPWorkflow.run, + name, + id=f"mcp-{name}-{uuid4()}", + task_queue=worker.task_queue, + ) + assert result == "transport" + + +async def test_stdio_transport(client: TemporalClient) -> None: + server_path = Path(__file__).parent / "echo_mcp_server.py" + parameters = StdioServerParameters( + command=sys.executable, + args=[str(server_path)], + ) + await run_transport_workflow( + client, + "stdio", + lambda: Client(stdio_client(parameters)), + ) + + +@asynccontextmanager +async def streamable_http_server() -> AsyncIterator[str]: + server = MCPServer("http-echo") + + @server.tool() + def echo(value: str) -> str: # type: ignore[reportUnusedFunction] + return value + + port = find_free_port() + app = server.streamable_http_app( + streamable_http_path="/mcp", + stateless_http=True, + host="127.0.0.1", + ) + uvicorn_server = uvicorn.Server( + uvicorn.Config(app, host="127.0.0.1", port=port, log_level="warning") + ) + task = asyncio.create_task(uvicorn_server.serve()) + try: + for _ in range(500): + if uvicorn_server.started: + break + if task.done(): + await task + await asyncio.sleep(0.01) + else: + raise RuntimeError("Streamable HTTP MCP server did not start") + yield f"http://127.0.0.1:{port}/mcp" + finally: + uvicorn_server.should_exit = True + await asyncio.gather(task, return_exceptions=True) + + +async def test_streamable_http_transport(client: TemporalClient) -> None: + async with streamable_http_server() as url: + await run_transport_workflow(client, "http", lambda: Client(url)) diff --git a/tests/contrib/openai_agents/test_mcp_v2.py b/tests/contrib/openai_agents/test_mcp_v2.py new file mode 100644 index 000000000..8fc5a7d4e --- /dev/null +++ b/tests/contrib/openai_agents/test_mcp_v2.py @@ -0,0 +1,218 @@ +from collections.abc import Callable +from datetime import timedelta +from typing import Any, cast +from uuid import uuid4 + +import pytest +from agents import Agent, AgentBase, RunContextWrapper, Runner +from agents.mcp import MCPServer as AgentsMCPServer +from mcp import Client as MCPClient +from mcp.server.mcpserver import MCPServer as SDKMCPServer +from mcp.types import CallToolResult, GetPromptResult, ListPromptsResult, Tool + +from temporalio import workflow +from temporalio.client import Client +from temporalio.contrib import openai_agents +from temporalio.contrib.openai_agents import ModelActivityParameters +from temporalio.contrib.openai_agents._mcp_backend import ( + _mcp_server_backend_factory, +) +from temporalio.contrib.openai_agents.testing import ( + AgentEnvironment, + ResponseBuilders, + TestModel, +) +from temporalio.exceptions import ApplicationError +from tests.helpers import new_worker + + +@workflow.defn +class MCPWorkflow: + @workflow.run + async def run(self, cache_tools_list: bool) -> str: + server = openai_agents.workflow.temporal_mcp_server( + "hello", cache_tools_list=cache_tools_list + ) + agent = Agent[str]( + name="MCP workflow", + instructions="Use the tools.", + mcp_servers=[server], + ) + result = await Runner.run(agent, "Say hello to Tom and Tim.") + return result.final_output + + +@workflow.defn +class MCPFactoryArgumentWorkflow: + @workflow.run + async def run(self) -> str: + server = openai_agents.workflow.temporal_mcp_server( + "hello", factory_argument={"tenant": "acme"} + ) + agent = Agent[str]( + name="MCP workflow", + instructions="Use the tools.", + mcp_servers=[server], + ) + result = await Runner.run(agent, "Say hello to Tom and Tim.") + return result.final_output + + +def model() -> TestModel: + return TestModel.returning_responses( + [ + ResponseBuilders.tool_call( + '{"name":"Tom"}', "say_hello", call_id="call-1", item_id="item-1" + ), + ResponseBuilders.tool_call( + '{"name":"Tim"}', "say_hello", call_id="call-2", item_id="item-2" + ), + ResponseBuilders.output_message("Hi Tom and Tim!"), + ] + ) + + +def server() -> SDKMCPServer[Any]: + value = SDKMCPServer("hello") + + @value.tool() + def say_hello(name: str) -> str: # type: ignore[reportUnusedFunction] + return f"Hello {name}" + + return value + + +class InProcessMCPServer(AgentsMCPServer): + def __init__(self, server: SDKMCPServer[Any]) -> None: + super().__init__() + self._client = MCPClient(server) + self.session: MCPClient | None = None + + @property + def name(self) -> str: + return "hello" + + async def connect(self) -> None: + await self._client.__aenter__() + self.session = self._client + + async def cleanup(self) -> None: + await self._client.__aexit__(None, None, None) + + async def list_tools( + self, + run_context: RunContextWrapper[Any] | None = None, + agent: AgentBase | None = None, + ) -> list[Tool]: + return (await self._client.list_tools()).tools + + async def call_tool( + self, + tool_name: str, + arguments: dict[str, Any] | None, + meta: dict[str, Any] | None = None, + ) -> CallToolResult: + return await self._client.call_tool(tool_name, arguments, meta=cast(Any, meta)) + + async def list_prompts(self) -> ListPromptsResult: + return await self._client.list_prompts() + + async def get_prompt( + self, name: str, arguments: dict[str, Any] | None = None + ) -> GetPromptResult: + return await self._client.get_prompt(name, arguments) + + +@pytest.mark.parametrize( + ("cache_tools_list", "expected_list_activities"), ((True, 1), (False, 3)) +) +async def test_openai_agents_uses_mcp_v2_and_caches_connection( + client: Client, cache_tools_list: bool, expected_list_activities: int +) -> None: + created = 0 + mcp_server = server() + + def factory() -> AgentsMCPServer: + nonlocal created + created += 1 + return InProcessMCPServer(mcp_server) + + async with AgentEnvironment( + model=model(), + model_params=ModelActivityParameters( + start_to_close_timeout=timedelta(seconds=30) + ), + mcp_servers={"hello": factory}, + ) as environment: + plugged_client = environment.applied_on_client(client) + async with new_worker(plugged_client, MCPWorkflow) as worker: + handle = await plugged_client.start_workflow( + MCPWorkflow.run, + cache_tools_list, + id=f"mcp-v2-{uuid4()}", + task_queue=worker.task_queue, + ) + result = await handle.result() + history = await handle.fetch_history() + + assert result == "Hi Tom and Tim!" + assert created == 1 + assert ( + sum( + event.activity_task_scheduled_event_attributes.activity_type.name + == "temporalio.contrib.mcp.hello.list-tools" + for event in history.events + if event.HasField("activity_task_scheduled_event_attributes") + ) + == expected_list_activities + ) + + +async def test_factory_argument_uses_fresh_client_per_activity( + client: Client, +) -> None: + arguments: list[Any] = [] + mcp_server = server() + + def factory(argument: Any) -> AgentsMCPServer: + arguments.append(argument) + return InProcessMCPServer(mcp_server) + + async with AgentEnvironment( + model=model(), + model_params=ModelActivityParameters( + start_to_close_timeout=timedelta(seconds=30) + ), + mcp_servers={"hello": factory}, + ) as environment: + plugged_client = environment.applied_on_client(client) + async with new_worker(plugged_client, MCPFactoryArgumentWorkflow) as worker: + result = await plugged_client.execute_workflow( + MCPFactoryArgumentWorkflow.run, + id=f"mcp-v2-argument-{uuid4()}", + task_queue=worker.task_queue, + ) + + assert result == "Hi Tom and Tim!" + assert arguments == [{"tenant": "acme"}] * 3 + + +def test_callable_worker_side_tool_filter_is_rejected() -> None: + def factory() -> AgentsMCPServer: + value = InProcessMCPServer(server()) + value.tool_filter = lambda context, tool: True # type: ignore[attr-defined] + return value + + with pytest.raises(ApplicationError) as err: + cast(Callable[[], Any], _mcp_server_backend_factory("hello", factory))() + assert err.value.non_retryable + assert "temporal_mcp_server()" in str(err.value) + + +def test_static_worker_side_tool_filter_is_allowed() -> None: + def factory() -> AgentsMCPServer: + value = InProcessMCPServer(server()) + value.tool_filter = {"blocked_tool_names": ["say_hello"]} # type: ignore[attr-defined] + return value + + cast(Callable[[], Any], _mcp_server_backend_factory("hello", factory))() diff --git a/tests/contrib/openai_agents/test_openai.py b/tests/contrib/openai_agents/test_openai.py index 79f7f9dcd..cd2e2ebca 100644 --- a/tests/contrib/openai_agents/test_openai.py +++ b/tests/contrib/openai_agents/test_openai.py @@ -6,10 +6,7 @@ from collections.abc import AsyncIterator, Callable, Sequence from dataclasses import dataclass from datetime import timedelta -from typing import ( - Any, - cast, -) +from typing import Any, cast import nexusrpc import pydantic @@ -1920,11 +1917,11 @@ def hosted_mcp_mock_model(): ModelResponse( output=[ McpApprovalRequest( - arguments="", - name="", + arguments="{}", + name="search", server_label="gitmcp", type="mcp_approval_request", - id="id", + id="approval-1", ) ], usage=Usage(), @@ -1933,11 +1930,11 @@ def hosted_mcp_mock_model(): ModelResponse( output=[ McpCall( - arguments="", - name="", - server_label="", + arguments="{}", + name="search", + server_label="gitmcp", type="mcp_call", - id="id", + id="call-1", output="Mcp output", ), ResponseBuilders.response_output_message("Some language"), @@ -2426,16 +2423,18 @@ async def list_tools( ) -> list[MCPTool]: self.calls.append("list_tools") return [ - MCPTool( - name="Say-Hello", - inputSchema={ - "type": "object", - "properties": { - "name": {"type": "string"}, + MCPTool.model_validate( + { + "name": "Say-Hello", + "inputSchema": { + "type": "object", + "properties": { + "name": {"type": "string"}, + }, + "required": ["name"], + "$schema": "http://json-schema.org/draft-07/schema#", }, - "required": ["name"], - "$schema": "http://json-schema.org/draft-07/schema#", - }, + } ) ] @@ -2462,9 +2461,44 @@ async def get_prompt( return TrackingMCPServer(name) +@pytest.mark.mcp_v1 +def test_legacy_mcp_apis_are_deprecated(): + with pytest.warns(DeprecationWarning, match="StatelessMCPServerProvider"): + stateless_provider = StatelessMCPServerProvider( + "deprecated-stateless", + lambda: cast(MCPServer, cast(object, None)), + ) + with pytest.warns(DeprecationWarning, match="StatefulMCPServerProvider"): + StatefulMCPServerProvider( + "deprecated-stateful", + lambda _argument: cast(MCPServer, cast(object, None)), + ) + with pytest.warns(DeprecationWarning, match="stateless_mcp_server"): + openai_agents.workflow.stateless_mcp_server("deprecated-stateless") + with pytest.warns(DeprecationWarning, match="stateful_mcp_server"): + openai_agents.workflow.stateful_mcp_server("deprecated-stateful") + with pytest.warns(DeprecationWarning, match="mcp_server_providers"): + openai_agents.OpenAIAgentsPlugin(mcp_server_providers=[stateless_provider]) + + +@pytest.mark.mcp_v1 +def test_mcp_servers_requires_v2(): + from importlib.metadata import version + + def factory() -> MCPServer: + return cast(MCPServer, cast(object, None)) + + if int(version("mcp").split(".", 1)[0]) < 2: + with pytest.raises(RuntimeError, match="requires MCP Python SDK v2"): + openai_agents.OpenAIAgentsPlugin(mcp_servers={"test": factory}) + else: + openai_agents.OpenAIAgentsPlugin(mcp_servers={"test": factory}) + + @pytest.mark.parametrize("use_local_model", [True, False]) @pytest.mark.parametrize("stateful", [True, False]) @pytest.mark.parametrize("caching", [True, False]) +@pytest.mark.mcp_v1 async def test_mcp_server( client: Client, use_local_model: bool, stateful: bool, caching: bool ): @@ -2566,6 +2600,7 @@ async def test_mcp_server( @pytest.mark.parametrize("stateful", [True, False]) +@pytest.mark.mcp_v1 async def test_mcp_server_factory_argument(client: Client, stateful: bool): def factory(args: Any | None) -> MCPServer: print("Invoking factory: ", args) @@ -2612,6 +2647,7 @@ def factory(args: Any | None) -> MCPServer: ) +@pytest.mark.mcp_v1 async def test_stateful_mcp_server_no_worker(client: Client): server = StatefulMCPServerProvider( "Filesystem-Server", diff --git a/tests/nexus/test_temporal_system_nexus.py b/tests/nexus/test_temporal_system_nexus.py index 6a9bc9959..dc49f0302 100644 --- a/tests/nexus/test_temporal_system_nexus.py +++ b/tests/nexus/test_temporal_system_nexus.py @@ -566,13 +566,10 @@ def _proto_scalar_sample(field: FieldDescriptor, *, path: str) -> Any: def _field_is_repeated(field: FieldDescriptor) -> bool: - return bool( - getattr( - field, - "is_repeated", - getattr(field, "label") == FieldDescriptor.LABEL_REPEATED, - ) - ) + is_repeated = getattr(field, "is_repeated", None) + if is_repeated is not None: + return bool(is_repeated) + return getattr(field, "label") == FieldDescriptor.LABEL_REPEATED @pytest.mark.parametrize( diff --git a/uv.lock b/uv.lock index 6e6ccc4f4..5655bcb03 100644 --- a/uv.lock +++ b/uv.lock @@ -2,14 +2,73 @@ version = 1 revision = 3 requires-python = ">=3.10" resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version == '3.13.*'", - "python_full_version >= '3.11' and python_full_version < '3.13'", - "python_full_version < '3.11'", -] + "python_full_version >= '3.14' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1') or (python_full_version == '3.11.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1')", + "python_full_version < '3.11' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1') or (python_full_version == '3.11.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1')", + "python_full_version < '3.11' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", +] +conflicts = [[ + { package = "temporalio", group = "dev" }, + { package = "temporalio", group = "dev-mcp-v1" }, +], [ + { package = "temporalio", extra = "google-adk" }, + { package = "temporalio", group = "dev" }, +], [ + { package = "temporalio", extra = "strands-agents" }, + { package = "temporalio", group = "dev" }, +], [ + { package = "temporalio", extra = "mcp" }, + { package = "temporalio", group = "dev-mcp-v1" }, +], [ + { package = "temporalio", extra = "google-adk" }, + { package = "temporalio", extra = "mcp" }, +], [ + { package = "temporalio", extra = "mcp" }, + { package = "temporalio", extra = "strands-agents" }, +]] [options] -exclude-newer = "2026-08-10T18:40:15.391197Z" +exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P2W" [[package]] @@ -73,12 +132,12 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, { name = "aiosignal" }, - { name = "async-timeout", marker = "python_full_version < '3.11'" }, + { name = "async-timeout", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "attrs" }, { name = "frozenlist" }, { name = "multidict" }, { name = "propcache" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "yarl" }, ] sdist = { url = "https://files.pythonhosted.org/packages/82/78/8ea7308cac6934de8c74a14f3d5f65d1c89287426688be79538d0e5c013d/aiohttp-3.14.1.tar.gz", hash = "sha256:307f2cff90a764d329e77040603fa032db89c5c24fdad50c4c15334cba744035", size = 7955794, upload-time = "2026-06-07T21:09:35.529Z" } @@ -218,7 +277,7 @@ version = "1.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "frozenlist" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } wheels = [ @@ -257,14 +316,14 @@ name = "anthropic" version = "0.117.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.11'" }, - { name = "distro", marker = "python_full_version >= '3.11'" }, - { name = "docstring-parser", marker = "python_full_version >= '3.11'" }, - { name = "httpx", marker = "python_full_version >= '3.11'" }, - { name = "jiter", marker = "python_full_version >= '3.11'" }, - { name = "pydantic", marker = "python_full_version >= '3.11'" }, - { name = "sniffio", marker = "python_full_version >= '3.11'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.11'" }, + { name = "anyio", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "distro", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "docstring-parser", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "httpx", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "jiter", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "pydantic", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "sniffio", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "typing-extensions", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/41/0d/8f71d535edb0d438f023bd825fb65f67c14fa88a2bd6b75f292a58a63de4/anthropic-0.117.0.tar.gz", hash = "sha256:98107f2b76439641e0ae2a1754087534b8f178dbab99d6eb1bc4b7bc8c744496", size = 989933, upload-time = "2026-07-16T19:36:13.07Z" } wheels = [ @@ -285,9 +344,9 @@ name = "anyio" version = "4.14.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "idna" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" } wheels = [ @@ -507,7 +566,7 @@ name = "cffi" version = "2.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pycparser", marker = "implementation_name != 'PyPy'" }, + { name = "pycparser", marker = "implementation_name != 'PyPy' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" } wheels = [ @@ -619,8 +678,8 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aws-sam-translator" }, { name = "jsonpatch" }, - { name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "networkx", version = "3.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "networkx", version = "3.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "networkx", version = "3.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "pyyaml" }, { name = "regex" }, { name = "sympy" }, @@ -730,8 +789,8 @@ dependencies = [ { name = "filelock" }, { name = "packaging" }, { name = "platformdirs" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/6c/1934be8118ea842c3ee7542e6e2a0ff9299f632db531f61368b412bb75a7/cibuildwheel-2.23.4.tar.gz", hash = "sha256:5a3e4a3d9c18e77838c37c483642e4f071da06ec05c05336826cc46c97abb708", size = 294641, upload-time = "2026-03-16T19:33:13.649Z" } wheels = [ @@ -743,7 +802,7 @@ name = "click" version = "8.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" } wheels = [ @@ -877,7 +936,7 @@ wheels = [ [package.optional-dependencies] toml = [ - { name = "tomli", marker = "python_full_version <= '3.11'" }, + { name = "tomli", marker = "python_full_version <= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] [[package]] @@ -885,8 +944,8 @@ name = "cryptography" version = "49.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "cffi", marker = "platform_python_implementation != 'PyPy' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1f/99/d1c90d6041656cc6ee229dc99cd67fd0cd5aec3c5f7d72fffc27cc750054/cryptography-49.0.0.tar.gz", hash = "sha256:f89660a348f4f78a92366240a61404e337586ef7f5909a2fef59ca88ef505493", size = 854345, upload-time = "2026-06-12T20:02:30.512Z" } wheels = [ @@ -942,12 +1001,12 @@ name = "deepagents" version = "0.6.12" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "langchain", marker = "python_full_version >= '3.11'" }, - { name = "langchain-anthropic", marker = "python_full_version >= '3.11'" }, - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, - { name = "langchain-google-genai", marker = "python_full_version >= '3.11'" }, - { name = "langsmith", marker = "python_full_version >= '3.11'" }, - { name = "wcmatch", marker = "python_full_version >= '3.11'" }, + { name = "langchain", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langchain-anthropic", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langchain-core", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langchain-google-genai", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langsmith", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "wcmatch", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e0/db/a6acdc72a9e90c3f07ed10de35c951734a02d4facb693bb59684ad368801/deepagents-0.6.12.tar.gz", hash = "sha256:1f281c0bc5a63132f62e2ee345c1dc593b23188da6e23016401f6879fbe54b5f", size = 211364, upload-time = "2026-06-25T17:26:52.775Z" } wheels = [ @@ -960,7 +1019,7 @@ version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/62/55/f054de99871e7beb81935dea8a10b90cd5ce42122b1c3081d5282fdb3621/dependency_groups-1.3.1.tar.gz", hash = "sha256:78078301090517fd938c19f64a53ce98c32834dfe0dee6b88004a569a6adfefd", size = 10093, upload-time = "2025-05-02T00:34:29.452Z" } wheels = [ @@ -990,7 +1049,7 @@ name = "docker" version = "7.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pywin32", marker = "sys_platform == 'win32'" }, + { name = "pywin32", marker = "sys_platform == 'win32' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "requests" }, { name = "urllib3" }, ] @@ -1022,7 +1081,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1158,7 +1217,7 @@ version = "6.0.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "flask" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "werkzeug" }, ] sdist = { url = "https://files.pythonhosted.org/packages/47/03/4e464a50860f9adf08b5c1d3479cb8ea1f12af2aa69535c7042c6e628135/flask_cors-6.0.5.tar.gz", hash = "sha256:30c5031552cd59f620ac0c8211dac45b345d3b2df310e7721879e4f46ef9c601", size = 101386, upload-time = "2026-06-08T20:20:17.765Z" } @@ -1305,7 +1364,7 @@ dependencies = [ { name = "authlib" }, { name = "click" }, { name = "fastapi" }, - { name = "google-auth", extra = ["pyopenssl"] }, + { name = "google-auth", extra = ["pyopenssl"], marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'group-10-temporalio-dev-mcp-v1' or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev')" }, { name = "google-genai" }, { name = "graphviz" }, { name = "httpx" }, @@ -1590,6 +1649,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, ] +[[package]] +name = "httpcore2" +version = "2.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "h11", marker = "(python_full_version != '3.12.*' and extra == 'extra-10-temporalio-mcp') or (python_full_version != '3.12.*' and extra == 'group-10-temporalio-dev') or (python_full_version != '3.12.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (sys_platform != 'emscripten' and extra == 'extra-10-temporalio-mcp') or (sys_platform != 'emscripten' and extra == 'group-10-temporalio-dev') or (sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "truststore", marker = "(python_full_version != '3.12.*' and extra == 'extra-10-temporalio-mcp') or (python_full_version != '3.12.*' and extra == 'group-10-temporalio-dev') or (python_full_version != '3.12.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (sys_platform != 'emscripten' and extra == 'extra-10-temporalio-mcp') or (sys_platform != 'emscripten' and extra == 'group-10-temporalio-dev') or (sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a9/83/a896fc59940fc5a6e2aff3a4be1d92fa890112936803b331cae75a993c34/httpcore2-2.10.0.tar.gz", hash = "sha256:13c0cc3d1919d4f28457f60cd2c2abe04113a8af184ccf1142811beba936f9dc", size = 67427, upload-time = "2026-08-09T09:11:32.123Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/4f/d149104195a35e2853a2fc203a8e3477747e58c80e17dda686dace174383/httpcore2-2.10.0-py3-none-any.whl", hash = "sha256:7df06cfb34070cae4f7c89be69dc1095eca138e9704ceffb98d25c1912ab6f01", size = 83000, upload-time = "2026-08-09T09:11:29.555Z" }, +] + [[package]] name = "httpx" version = "0.28.1" @@ -1614,6 +1686,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, ] +[[package]] +name = "httpx2" +version = "2.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio", marker = "(sys_platform != 'emscripten' and extra == 'extra-10-temporalio-mcp') or (sys_platform != 'emscripten' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "httpcore2", marker = "(sys_platform != 'emscripten' and extra == 'extra-10-temporalio-mcp') or (sys_platform != 'emscripten' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "httpx2-jsfetch", marker = "(python_full_version >= '3.12' and sys_platform == 'emscripten' and extra == 'extra-10-temporalio-mcp') or (python_full_version >= '3.12' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (python_full_version >= '3.12' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (python_full_version < '3.12' and extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (python_full_version < '3.12' and extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (python_full_version < '3.12' and extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (python_full_version < '3.12' and extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1') or (sys_platform != 'emscripten' and extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (sys_platform != 'emscripten' and extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (sys_platform != 'emscripten' and extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (sys_platform != 'emscripten' and extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev')" }, + { name = "idna", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "truststore", marker = "(sys_platform != 'emscripten' and extra == 'extra-10-temporalio-mcp') or (sys_platform != 'emscripten' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "typing-extensions", marker = "(python_full_version < '3.13' and extra == 'extra-10-temporalio-mcp') or (python_full_version < '3.13' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/3d/f9a8c07a3884f3e5b26205e8436a18b3af61c5d53192c3bea235574dbbec/httpx2-2.10.0.tar.gz", hash = "sha256:8741d7329fe2c7885fc9ceb61c8217acfb87a85f75723714b89ebf7ad7196338", size = 98749, upload-time = "2026-08-09T09:11:33.24Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/6d/a637d52449d98a6892d9a4dc0262587afdb6a66f201871842dce5a97b1c1/httpx2-2.10.0-py3-none-any.whl", hash = "sha256:5e3194a432701e1cc6f69a8b1b2fa199ef907013fede8d9a09a2c5b7b8141a18", size = 94355, upload-time = "2026-08-09T09:11:30.882Z" }, +] + +[[package]] +name = "httpx2-jsfetch" +version = "1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/c4/0e5636363151a2a1795e0a77617168b9ca438e1748ec05fc9b5687f93d64/httpx2_jsfetch-1.0.tar.gz", hash = "sha256:70a0e3eabfef7cce5ad9c629f7d01ca05e418f586646f4ddf14782e4c1454c60", size = 6872, upload-time = "2026-08-07T00:13:07.492Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/43/832f631d32e4f1211caa2ba368317739fe71f0b8530e4c9d15dc454bac2a/httpx2_jsfetch-1.0-py3-none-any.whl", hash = "sha256:cb916b707601e69a07721aabc8f3f6659be3a6893bc1ff5c6f9e02241df2da32", size = 6382, upload-time = "2026-08-07T00:13:06.567Z" }, +] + [[package]] name = "huggingface-hub" version = "1.23.0" @@ -1622,7 +1720,7 @@ dependencies = [ { name = "click" }, { name = "filelock" }, { name = "fsspec" }, - { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'" }, + { name = "hf-xet", marker = "platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "httpx" }, { name = "packaging" }, { name = "pyyaml" }, @@ -1673,7 +1771,7 @@ version = "24.11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ef/3c/82e84109e02c492f382c711c58a3dd91badda6d746def81a1465f74dc9f5/incremental-24.11.0.tar.gz", hash = "sha256:87d3480dbb083c1d736222511a8cf380012a8176c2456d01ef483242abbbcf8c", size = 24000, upload-time = "2025-11-28T02:30:17.861Z" } wheels = [ @@ -1715,7 +1813,7 @@ name = "jaraco-context" version = "6.1.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "backports-tarfile", marker = "python_full_version < '3.12'" }, + { name = "backports-tarfile", marker = "python_full_version < '3.12' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/af/50/4763cd07e722bb6285316d390a164bc7e479db9d90daa769f22578f698b4/jaraco_context-6.1.2.tar.gz", hash = "sha256:f1a6c9d391e661cc5b8d39861ff077a7dc24dc23833ccee564b234b81c82dfe3", size = 16801, upload-time = "2026-03-20T22:13:33.922Z" } wheels = [ @@ -1913,8 +2011,8 @@ dependencies = [ { name = "attrs" }, { name = "jsonschema-specifications" }, { name = "referencing" }, - { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "rpds-py", version = "2026.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "rpds-py", version = "2026.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } wheels = [ @@ -1953,13 +2051,13 @@ name = "keyring" version = "25.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, + { name = "importlib-metadata", marker = "python_full_version < '3.12' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "jaraco-classes" }, { name = "jaraco-context" }, { name = "jaraco-functools" }, - { name = "jeepney", marker = "sys_platform == 'linux'" }, - { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, - { name = "secretstorage", marker = "sys_platform == 'linux'" }, + { name = "jeepney", marker = "sys_platform == 'linux' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "pywin32-ctypes", marker = "sys_platform == 'win32' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "secretstorage", marker = "sys_platform == 'linux' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } wheels = [ @@ -1971,9 +2069,9 @@ name = "langchain" version = "1.3.14" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, - { name = "langgraph", marker = "python_full_version >= '3.11'" }, - { name = "pydantic", marker = "python_full_version >= '3.11'" }, + { name = "langchain-core", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langgraph", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "pydantic", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/29/68/a6dbad9c22df4087a0f9e79ddd46226c442b30128bfeee538d5889492a73/langchain-1.3.14.tar.gz", hash = "sha256:1b6696c72ba3bbbce54d745e0180742c9f6ece8bbc59ed5a46c3e20b9a435929", size = 645181, upload-time = "2026-07-16T13:28:18.29Z" } wheels = [ @@ -1985,9 +2083,9 @@ name = "langchain-anthropic" version = "1.4.8" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anthropic", marker = "python_full_version >= '3.11'" }, - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, - { name = "pydantic", marker = "python_full_version >= '3.11'" }, + { name = "anthropic", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langchain-core", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "pydantic", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/98/22/40ab129b08329ca295b391aa1d48267692b42594757084c6918e22b655ac/langchain_anthropic-1.4.8.tar.gz", hash = "sha256:c76891b2044d56105ff13c106ed12650637b53bd598a4bdf15b4796eefa2a4ec", size = 708524, upload-time = "2026-06-26T21:28:46.916Z" } wheels = [ @@ -2019,10 +2117,10 @@ name = "langchain-google-genai" version = "4.2.7" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "filetype", marker = "python_full_version >= '3.11'" }, - { name = "google-genai", marker = "python_full_version >= '3.11'" }, - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, - { name = "pydantic", marker = "python_full_version >= '3.11'" }, + { name = "filetype", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "google-genai", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langchain-core", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "pydantic", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1d/0c/bc60dabc362ca7c6ffe8c4bcc2f724c7e566b43eb230cee51419f88f784c/langchain_google_genai-4.2.7.tar.gz", hash = "sha256:03b1463ffe4d42435f43c7870467f2215f684bb46400d2543435d10157c80ac7", size = 281605, upload-time = "2026-07-06T13:51:58.724Z" } wheels = [ @@ -2106,7 +2204,7 @@ version = "0.8.18" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, - { name = "orjson", marker = "platform_python_implementation != 'PyPy'" }, + { name = "orjson", marker = "platform_python_implementation != 'PyPy' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "packaging" }, { name = "pydantic" }, { name = "requests" }, @@ -2313,7 +2411,7 @@ name = "maturin" version = "1.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e7/b3/addd877f871fb1860d46d3a4f206ecb10b946c85846805e6367631926fd3/maturin-1.14.1.tar.gz", hash = "sha256:9d6577a62cd08e0ceba7a0db06fb098e0c9b1b3429bad747a4f3a18215a1b3df", size = 369637, upload-time = "2026-06-19T05:19:49.774Z" } wheels = [ @@ -2336,27 +2434,108 @@ wheels = [ name = "mcp" version = "1.28.1" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "httpx" }, - { name = "httpx-sse" }, - { name = "jsonschema" }, - { name = "pydantic" }, - { name = "pydantic-settings" }, - { name = "pyjwt", extra = ["crypto"] }, - { name = "python-multipart" }, - { name = "pywin32", marker = "sys_platform == 'win32'" }, - { name = "sse-starlette" }, - { name = "starlette" }, - { name = "typing-extensions" }, - { name = "typing-inspection" }, - { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, +resolution-markers = [ + "python_full_version >= '3.14' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version < '3.11' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", +] +dependencies = [ + { name = "anyio", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "httpx", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "httpx-sse", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "jsonschema", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "pydantic", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "pydantic-settings", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "pyjwt", extra = ["crypto"], marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "python-multipart", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "pywin32", marker = "(sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk') or (sys_platform == 'win32' and extra == 'extra-10-temporalio-strands-agents') or (sys_platform == 'win32' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "sse-starlette", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "starlette", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "typing-extensions", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "typing-inspection", marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "uvicorn", marker = "(sys_platform != 'emscripten' and extra == 'extra-10-temporalio-google-adk') or (sys_platform != 'emscripten' and extra == 'extra-10-temporalio-strands-agents') or (sys_platform != 'emscripten' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/6e/77/9450b8f251a13affb6281997d0523c4615f8a8b35d0b21ff30db3a5aac9d/mcp-1.28.1.tar.gz", hash = "sha256:d51e36a5f5644faea4f85ea649bfffa6bc6c26770d42798ad6a3de3d2ba69683", size = 638501, upload-time = "2026-06-26T12:57:29.093Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e2/5e/d118fce19f87a2e7d8101c35c8ae0ec289098a4df0ff244cec23e415aca0/mcp-1.28.1-py3-none-any.whl", hash = "sha256:2726bca5e7193f61c5dde8b12500a6de2d9acf6d1a1c0be9e8c2e706437991df", size = 222620, upload-time = "2026-06-26T12:57:27.218Z" }, ] +[[package]] +name = "mcp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.13.*'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten') or (python_full_version == '3.11.*' and sys_platform == 'emscripten')", + "python_full_version < '3.11'", +] +dependencies = [ + { name = "anyio", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "httpx2", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "jsonschema", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "mcp-types", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "opentelemetry-api", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "pydantic", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "pyjwt", extra = ["crypto"], marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "python-multipart", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "pywin32", marker = "(sys_platform == 'win32' and extra == 'extra-10-temporalio-mcp') or (sys_platform == 'win32' and extra == 'group-10-temporalio-dev') or (sys_platform == 'win32' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev')" }, + { name = "sse-starlette", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "starlette", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "typing-extensions", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "typing-inspection", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "uvicorn", marker = "(sys_platform != 'emscripten' and extra == 'extra-10-temporalio-mcp') or (sys_platform != 'emscripten' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/33/32d4dff2c95bb5d897c3ef4c83649a08996b17b58f0a326d2495d4c81179/mcp-2.0.0.tar.gz", hash = "sha256:0f440e735c13ece8bb19bc62cf0b86f4313448432fbb77d35e14034f4e050728", size = 1662284, upload-time = "2026-07-28T13:45:32.346Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/72/7d7897418912c1d12e87556630dfb7bf0eac71160e9bef8b447960804ee3/mcp-2.0.0-py3-none-any.whl", hash = "sha256:1cb4c75d2d2c7b8c1d756355e5d82a39f2822cc7f13e22a2051d7ca3592349d6", size = 349980, upload-time = "2026-07-28T13:45:28.853Z" }, +] + +[[package]] +name = "mcp-types" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, + { name = "typing-extensions", marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bb/56/9b8e1c152f61f6c6b07c4b5896c88c7d0ae90bac6ee6306f852fcc5c1eb0/mcp_types-2.0.0.tar.gz", hash = "sha256:d7d939b9285c9961ae8866ba75ef85da34d12bafe276efbf4eb6a131786d8379", size = 66632, upload-time = "2026-07-28T13:45:33.804Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f5/4c/c78d78c3d52b0ac594ad7cc8ef5972adfe070e3597a8a4c6ce0cd39196ea/mcp_types-2.0.0-py3-none-any.whl", hash = "sha256:6b2de797ca2797f568b79529e1b25948e34de511bcc0bd82fef1039a6d1b8eb0", size = 69649, upload-time = "2026-07-28T13:45:30.713Z" }, +] + [[package]] name = "mdurl" version = "0.1.2" @@ -2502,7 +2681,7 @@ name = "multidict" version = "6.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1a/c2/c2d94cbe6ac1753f3fc980da97b3d930efe1da3af3c9f5125354436c073d/multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d", size = 102010, upload-time = "2026-01-26T02:46:45.979Z" } wheels = [ @@ -2642,7 +2821,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, { name = "pathspec" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c0/77/8f0d0001ffad290cef2f7f216f96c814866248a0b92a722365ed54648e7e/mypy-1.18.2.tar.gz", hash = "sha256:06a398102a5f203d7477b2923dda3634c36727fa5c237d8f859ef90c42a9924b", size = 3448846, upload-time = "2025-09-19T00:11:10.519Z" } @@ -2719,9 +2898,41 @@ name = "networkx" version = "3.6.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version == '3.13.*'", - "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version >= '3.14' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1') or (python_full_version == '3.11.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1')", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1') or (python_full_version == '3.11.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1')", ] sdist = { url = "https://files.pythonhosted.org/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" } wheels = [ @@ -2820,20 +3031,21 @@ wheels = [ [[package]] name = "openai-agents" -version = "0.19.4" +version = "0.20.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, - { name = "mcp" }, + { name = "mcp", version = "1.28.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "mcp", version = "2.0.0", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, { name = "openai" }, { name = "pydantic" }, { name = "requests" }, { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ff/ea/a8cae2dadf798f369be5f9cb544a169f5f6aecc096a80f1a209dddc4c00f/openai_agents-0.19.4.tar.gz", hash = "sha256:fe21778ee1e8216c9cdb775fa86d11b08be68c0184e14023993088d3f812c0be", size = 5784063, upload-time = "2026-08-05T02:59:12.939Z" } +sdist = { url = "https://files.pythonhosted.org/packages/57/18/1204bde976436ad85498b759d5297843ebd2e0a214f729eb2dc4423cdfc7/openai_agents-0.20.0.tar.gz", hash = "sha256:a6b37954877868ac233876a27dab1e2a461c53ecbd5fcf6e19e2d276d3e848cd", size = 6146452, upload-time = "2026-08-11T03:12:49.556Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/90/d8/98925e1e4888e58d7694ba71af2ba93b94540f481c45ee8b7f7be7e30fcd/openai_agents-0.19.4-py3-none-any.whl", hash = "sha256:12e0372fae9698fe6f78e05aaeb4ccdb229602f7ef99b8195a7d68dc82869f51", size = 968498, upload-time = "2026-08-05T02:59:11.191Z" }, + { url = "https://files.pythonhosted.org/packages/9f/8b/18528f00cb1a5d0b8e00f457f7dc88e7b17439bc520861aae2b638b88710/openai_agents-0.20.0-py3-none-any.whl", hash = "sha256:aaff662b802fa90762ad539e131b9ea387e12e3664b87bc75157ad1b3fc88850", size = 1064338, upload-time = "2026-08-11T03:12:47.615Z" }, ] [package.optional-dependencies] @@ -3719,7 +3931,7 @@ dependencies = [ { name = "lunr" }, { name = "platformdirs" }, { name = "requests" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "twisted" }, { name = "urllib3" }, ] @@ -3742,7 +3954,7 @@ name = "pyjwt" version = "2.13.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" } wheels = [ @@ -3781,13 +3993,13 @@ name = "pytest" version = "9.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, { name = "pygments" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "tomli", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ @@ -4031,9 +4243,9 @@ version = "0.37.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, - { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "rpds-py", version = "2026.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "rpds-py", version = "0.30.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "rpds-py", version = "2026.6.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } wheels = [ @@ -4366,9 +4578,41 @@ name = "rpds-py" version = "2026.6.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version == '3.13.*'", - "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version >= '3.14' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1') or (python_full_version == '3.11.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1')", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'win32' and extra == 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.11' and python_full_version < '3.13' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version >= '3.14' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.13.*' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1') or (python_full_version == '3.11.*' and sys_platform == 'emscripten' and extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev' and extra != 'group-10-temporalio-dev-mcp-v1')", ] sdist = { url = "https://files.pythonhosted.org/packages/aa/2a/9618a122aeb2a169a28b03889a2995fe297588964333d4a7d67bdf46e147/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", size = 64051, upload-time = "2026-06-30T07:17:53.009Z" } wheels = [ @@ -4531,8 +4775,8 @@ name = "secretstorage" version = "3.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cryptography" }, - { name = "jeepney" }, + { name = "cryptography", marker = "(python_full_version != '3.12.*' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32') or (sys_platform == 'emscripten' and extra == 'extra-10-temporalio-google-adk') or (sys_platform == 'emscripten' and extra == 'extra-10-temporalio-strands-agents') or (sys_platform == 'emscripten' and extra == 'group-10-temporalio-dev-mcp-v1') or (sys_platform == 'win32' and extra != 'extra-10-temporalio-google-adk') or (sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "jeepney", marker = "(python_full_version != '3.12.*' and sys_platform == 'emscripten') or (python_full_version < '3.11' and sys_platform == 'win32') or (sys_platform != 'emscripten' and sys_platform != 'win32') or (sys_platform == 'emscripten' and extra == 'extra-10-temporalio-google-adk') or (sys_platform == 'emscripten' and extra == 'extra-10-temporalio-strands-agents') or (sys_platform == 'emscripten' and extra == 'group-10-temporalio-dev-mcp-v1') or (sys_platform == 'win32' and extra != 'extra-10-temporalio-google-adk') or (sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (sys_platform == 'win32' and extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } wheels = [ @@ -4624,7 +4868,7 @@ version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/7c1dc7381d9f8ab7d854328ebfa884e62cb3f3d8549ddfd37c7814f42afa/starlette-1.3.1.tar.gz", hash = "sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0", size = 2703240, upload-time = "2026-06-12T09:23:11.602Z" } wheels = [ @@ -4640,7 +4884,7 @@ dependencies = [ { name = "botocore" }, { name = "docstring-parser" }, { name = "jsonschema" }, - { name = "mcp" }, + { name = "mcp", version = "1.28.1", source = { registry = "https://pypi.org/simple" } }, { name = "opentelemetry-api" }, { name = "opentelemetry-instrumentation-threading" }, { name = "opentelemetry-sdk" }, @@ -4701,7 +4945,7 @@ source = { virtual = "." } dependencies = [ { name = "nexus-rpc" }, { name = "protobuf" }, - { name = "python-dateutil", marker = "python_full_version < '3.11'" }, + { name = "python-dateutil", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "types-protobuf" }, { name = "typing-extensions" }, ] @@ -4712,13 +4956,13 @@ aioboto3 = [ { name = "types-aioboto3", extra = ["s3"] }, ] deepagents = [ - { name = "deepagents", marker = "python_full_version >= '3.11'" }, - { name = "langchain", marker = "python_full_version >= '3.11'" }, - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, + { name = "deepagents", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langchain", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langchain-core", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] google-adk = [ { name = "google-adk" }, - { name = "mcp" }, + { name = "mcp", version = "1.28.1", source = { registry = "https://pypi.org/simple" } }, ] google-genai = [ { name = "google-genai" }, @@ -4739,8 +4983,12 @@ langgraph = [ langsmith = [ { name = "langsmith" }, ] +mcp = [ + { name = "mcp", version = "2.0.0", source = { registry = "https://pypi.org/simple" } }, +] openai-agents = [ - { name = "mcp" }, + { name = "mcp", version = "1.28.1", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-10-temporalio-google-adk' or extra == 'extra-10-temporalio-strands-agents' or extra == 'group-10-temporalio-dev-mcp-v1'" }, + { name = "mcp", version = "2.0.0", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'extra-10-temporalio-mcp' or extra == 'group-10-temporalio-dev' or (extra != 'extra-10-temporalio-google-adk' and extra != 'extra-10-temporalio-strands-agents' and extra != 'group-10-temporalio-dev-mcp-v1')" }, { name = "openai-agents" }, ] opentelemetry = [ @@ -4756,12 +5004,15 @@ strands-agents = [ [package.dev-dependencies] dev = [ + { name = "aioboto3" }, { name = "async-timeout", marker = "python_full_version < '3.11'" }, { name = "basedpyright" }, { name = "cibuildwheel" }, { name = "cryptography" }, { name = "deepagents", marker = "python_full_version >= '3.11'" }, + { name = "google-genai" }, { name = "googleapis-common-protos" }, + { name = "grpcio" }, { name = "grpcio-tools" }, { name = "httpx" }, { name = "langchain", marker = "python_full_version >= '3.11'" }, @@ -4771,18 +5022,118 @@ dev = [ { name = "langsmith" }, { name = "litellm" }, { name = "maturin" }, - { name = "mcp" }, + { name = "mcp", version = "2.0.0", source = { registry = "https://pypi.org/simple" } }, + { name = "moto", extra = ["s3", "server"], marker = "(extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra != 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "mypy" }, + { name = "mypy-protobuf" }, + { name = "openai-agents", marker = "(extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra != 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "openai-agents", extra = ["litellm"], marker = "(python_full_version < '3.14' and extra == 'group-10-temporalio-dev') or (python_full_version >= '3.14' and extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra != 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "openinference-instrumentation-openai-agents" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-grpc" }, + { name = "opentelemetry-sdk" }, + { name = "opentelemetry-sdk-extension-aws" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "psutil" }, + { name = "pydantic" }, + { name = "pydocstyle" }, + { name = "pydoctor" }, + { name = "pyright" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, + { name = "pytest-flakefinder" }, + { name = "pytest-pretty" }, + { name = "pytest-rerunfailures" }, + { name = "pytest-timeout" }, + { name = "pytest-xdist" }, + { name = "ruff" }, + { name = "setuptools" }, + { name = "toml" }, + { name = "twine" }, + { name = "types-aioboto3", extra = ["s3"], marker = "(extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra != 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra != 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra != 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, +] +dev-common = [ + { name = "aioboto3" }, + { name = "async-timeout", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "basedpyright" }, + { name = "cibuildwheel" }, + { name = "cryptography" }, + { name = "deepagents", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "google-genai" }, + { name = "googleapis-common-protos" }, + { name = "grpcio" }, + { name = "grpcio-tools" }, + { name = "httpx" }, + { name = "langchain", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langchain-anthropic", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langchain-core", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, + { name = "langgraph" }, + { name = "langsmith" }, + { name = "litellm" }, + { name = "maturin" }, { name = "moto", extra = ["s3", "server"] }, { name = "mypy" }, { name = "mypy-protobuf" }, - { name = "openai-agents" }, - { name = "openai-agents", extra = ["litellm"], marker = "python_full_version < '3.14'" }, + { name = "opentelemetry-api" }, + { name = "opentelemetry-exporter-otlp-proto-grpc" }, + { name = "opentelemetry-sdk" }, + { name = "opentelemetry-sdk-extension-aws" }, + { name = "opentelemetry-semantic-conventions" }, + { name = "psutil" }, + { name = "pydantic" }, + { name = "pydocstyle" }, + { name = "pydoctor" }, + { name = "pyright" }, + { name = "pytest" }, + { name = "pytest-asyncio" }, + { name = "pytest-cov" }, + { name = "pytest-flakefinder" }, + { name = "pytest-pretty" }, + { name = "pytest-rerunfailures" }, + { name = "pytest-timeout" }, + { name = "pytest-xdist" }, + { name = "ruff" }, + { name = "setuptools" }, + { name = "toml" }, + { name = "twine" }, + { name = "types-aioboto3", extra = ["s3"] }, +] +dev-mcp-v1 = [ + { name = "aioboto3" }, + { name = "async-timeout", marker = "python_full_version < '3.11'" }, + { name = "basedpyright" }, + { name = "cibuildwheel" }, + { name = "cryptography" }, + { name = "deepagents", marker = "python_full_version >= '3.11'" }, + { name = "google-adk" }, + { name = "google-genai" }, + { name = "googleapis-common-protos" }, + { name = "grpcio" }, + { name = "grpcio-tools" }, + { name = "httpx" }, + { name = "langchain", marker = "python_full_version >= '3.11'" }, + { name = "langchain-anthropic", marker = "python_full_version >= '3.11'" }, + { name = "langchain-core", marker = "python_full_version >= '3.11'" }, + { name = "langgraph" }, + { name = "langsmith" }, + { name = "litellm" }, + { name = "maturin" }, + { name = "mcp", version = "1.28.1", source = { registry = "https://pypi.org/simple" } }, + { name = "moto", extra = ["s3", "server"], marker = "extra == 'group-10-temporalio-dev-mcp-v1' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev')" }, + { name = "mypy" }, + { name = "mypy-protobuf" }, + { name = "openai-agents", marker = "extra == 'group-10-temporalio-dev-mcp-v1' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev')" }, + { name = "openai-agents", extra = ["litellm"], marker = "(python_full_version < '3.14' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, { name = "openinference-instrumentation-google-adk" }, { name = "openinference-instrumentation-openai-agents" }, + { name = "opentelemetry-api" }, { name = "opentelemetry-exporter-otlp-proto-grpc" }, + { name = "opentelemetry-sdk" }, { name = "opentelemetry-sdk-extension-aws" }, { name = "opentelemetry-semantic-conventions" }, { name = "psutil" }, + { name = "pydantic" }, { name = "pydocstyle" }, { name = "pydoctor" }, { name = "pyright" }, @@ -4800,6 +5151,7 @@ dev = [ { name = "strands-agents-tools" }, { name = "toml" }, { name = "twine" }, + { name = "types-aioboto3", extra = ["s3"], marker = "extra == 'group-10-temporalio-dev-mcp-v1' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev')" }, ] [package.metadata] @@ -4814,9 +5166,10 @@ requires-dist = [ { name = "langgraph", marker = "extra == 'langgraph'", specifier = ">=1.1.0" }, { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.34,<0.9" }, { name = "mcp", marker = "extra == 'google-adk'", specifier = ">=1.24,<2" }, - { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, + { name = "mcp", marker = "extra == 'mcp'", specifier = ">=2,<3" }, + { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.24,<3" }, { name = "nexus-rpc", specifier = "==1.4.0" }, - { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.19.2,<0.20" }, + { name = "openai-agents", marker = "extra == 'openai-agents'", specifier = ">=0.20,<0.21" }, { name = "opentelemetry-api", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.26,<2" }, { name = "opentelemetry-api", marker = "extra == 'opentelemetry'", specifier = ">=1.26,<2" }, { name = "opentelemetry-exporter-otlp-proto-grpc", marker = "extra == 'lambda-worker-otel'", specifier = ">=1.11.1,<2" }, @@ -4832,16 +5185,69 @@ requires-dist = [ { name = "types-protobuf", specifier = ">=3.20,<8.0.0" }, { name = "typing-extensions", specifier = ">=4.2.0,<5" }, ] -provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "google-adk", "langgraph", "langsmith", "deepagents", "lambda-worker-otel", "aioboto3", "google-genai", "strands-agents"] +provides-extras = ["grpc", "opentelemetry", "pydantic", "openai-agents", "mcp", "google-adk", "langgraph", "langsmith", "deepagents", "lambda-worker-otel", "aioboto3", "google-genai", "strands-agents"] [package.metadata.requires-dev] dev = [ + { name = "aioboto3", specifier = ">=10.4.0" }, + { name = "async-timeout", marker = "python_full_version < '3.11'", specifier = ">=4.0,<6" }, + { name = "basedpyright", specifier = "==1.34.0" }, + { name = "cibuildwheel", specifier = ">=2.22.0,<3" }, + { name = "cryptography", specifier = ">=46" }, + { name = "deepagents", marker = "python_full_version >= '3.11'", specifier = ">=0.6.12,<0.7" }, + { name = "google-genai", specifier = ">=2.10.0,<3.0.0" }, + { name = "googleapis-common-protos", specifier = ">=1.75.0,<2" }, + { name = "grpcio", specifier = ">=1.48.2,<2" }, + { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, + { name = "httpx", specifier = ">=0.28.1" }, + { name = "langchain", marker = "python_full_version >= '3.11'", specifier = ">=1.3.11,<2" }, + { name = "langchain-anthropic", marker = "python_full_version >= '3.11'", specifier = ">=1.4.7" }, + { name = "langchain-core", marker = "python_full_version >= '3.11'", specifier = ">=1.4.8,<2" }, + { name = "langgraph", specifier = ">=1.1.0" }, + { name = "langsmith", specifier = ">=0.7.34,<0.9" }, + { name = "litellm", specifier = ">=1.83.0" }, + { name = "maturin", specifier = ">=1.8.2" }, + { name = "mcp", specifier = ">=2,<3" }, + { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, + { name = "mypy", specifier = "==1.18.2" }, + { name = "mypy-protobuf", specifier = ">=3.3.0,<4" }, + { name = "openai-agents", marker = "python_full_version >= '3.14'", specifier = ">=0.20,<0.21" }, + { name = "openai-agents", extras = ["litellm"], marker = "python_full_version < '3.14'", specifier = ">=0.20,<0.21" }, + { name = "openinference-instrumentation-openai-agents", specifier = ">=0.1.0" }, + { name = "opentelemetry-api", specifier = ">=1.26,<2" }, + { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.11.1,<2" }, + { name = "opentelemetry-sdk", specifier = ">=1.26,<2" }, + { name = "opentelemetry-sdk-extension-aws", specifier = ">=2.0.0,<3" }, + { name = "opentelemetry-semantic-conventions", specifier = ">=0.40b0,<1" }, + { name = "psutil", specifier = ">=5.9.3,<6" }, + { name = "pydantic", specifier = ">=2.0.0,<3" }, + { name = "pydocstyle", specifier = ">=6.3.0,<7" }, + { name = "pydoctor", specifier = ">=25.10.1,<26" }, + { name = "pyright", specifier = "==1.1.403" }, + { name = "pytest", specifier = "~=9.0" }, + { name = "pytest-asyncio", specifier = ">=0.21,<0.22" }, + { name = "pytest-cov", specifier = ">=6.1.1" }, + { name = "pytest-flakefinder", specifier = ">=1.1.0" }, + { name = "pytest-pretty", specifier = ">=1.3.0" }, + { name = "pytest-rerunfailures", specifier = ">=16.1" }, + { name = "pytest-timeout", specifier = "~=2.2" }, + { name = "pytest-xdist", specifier = ">=3.6,<4" }, + { name = "ruff", specifier = ">=0.15.12,<0.16" }, + { name = "setuptools", specifier = "<82" }, + { name = "toml", specifier = ">=0.10.2,<0.11" }, + { name = "twine", specifier = ">=4.0.1,<5" }, + { name = "types-aioboto3", extras = ["s3"], specifier = ">=10.4.0" }, +] +dev-common = [ + { name = "aioboto3", specifier = ">=10.4.0" }, { name = "async-timeout", marker = "python_full_version < '3.11'", specifier = ">=4.0,<6" }, { name = "basedpyright", specifier = "==1.34.0" }, { name = "cibuildwheel", specifier = ">=2.22.0,<3" }, { name = "cryptography", specifier = ">=46" }, { name = "deepagents", marker = "python_full_version >= '3.11'", specifier = ">=0.6.12,<0.7" }, + { name = "google-genai", specifier = ">=2.10.0,<3.0.0" }, { name = "googleapis-common-protos", specifier = ">=1.75.0,<2" }, + { name = "grpcio", specifier = ">=1.48.2,<2" }, { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "langchain", marker = "python_full_version >= '3.11'", specifier = ">=1.3.11,<2" }, @@ -4851,18 +5257,68 @@ dev = [ { name = "langsmith", specifier = ">=0.7.34,<0.9" }, { name = "litellm", specifier = ">=1.83.0" }, { name = "maturin", specifier = ">=1.8.2" }, - { name = "mcp", specifier = ">=1.9.4,<2" }, { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, { name = "mypy", specifier = "==1.18.2" }, { name = "mypy-protobuf", specifier = ">=3.3.0,<4" }, - { name = "openai-agents", marker = "python_full_version >= '3.14'", specifier = ">=0.19.2,<0.20" }, - { name = "openai-agents", extras = ["litellm"], marker = "python_full_version < '3.14'", specifier = ">=0.19.2,<0.20" }, + { name = "opentelemetry-api", specifier = ">=1.26,<2" }, + { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.11.1,<2" }, + { name = "opentelemetry-sdk", specifier = ">=1.26,<2" }, + { name = "opentelemetry-sdk-extension-aws", specifier = ">=2.0.0,<3" }, + { name = "opentelemetry-semantic-conventions", specifier = ">=0.40b0,<1" }, + { name = "psutil", specifier = ">=5.9.3,<6" }, + { name = "pydantic", specifier = ">=2.0.0,<3" }, + { name = "pydocstyle", specifier = ">=6.3.0,<7" }, + { name = "pydoctor", specifier = ">=25.10.1,<26" }, + { name = "pyright", specifier = "==1.1.403" }, + { name = "pytest", specifier = "~=9.0" }, + { name = "pytest-asyncio", specifier = ">=0.21,<0.22" }, + { name = "pytest-cov", specifier = ">=6.1.1" }, + { name = "pytest-flakefinder", specifier = ">=1.1.0" }, + { name = "pytest-pretty", specifier = ">=1.3.0" }, + { name = "pytest-rerunfailures", specifier = ">=16.1" }, + { name = "pytest-timeout", specifier = "~=2.2" }, + { name = "pytest-xdist", specifier = ">=3.6,<4" }, + { name = "ruff", specifier = ">=0.15.12,<0.16" }, + { name = "setuptools", specifier = "<82" }, + { name = "toml", specifier = ">=0.10.2,<0.11" }, + { name = "twine", specifier = ">=4.0.1,<5" }, + { name = "types-aioboto3", extras = ["s3"], specifier = ">=10.4.0" }, +] +dev-mcp-v1 = [ + { name = "aioboto3", specifier = ">=10.4.0" }, + { name = "async-timeout", marker = "python_full_version < '3.11'", specifier = ">=4.0,<6" }, + { name = "basedpyright", specifier = "==1.34.0" }, + { name = "cibuildwheel", specifier = ">=2.22.0,<3" }, + { name = "cryptography", specifier = ">=46" }, + { name = "deepagents", marker = "python_full_version >= '3.11'", specifier = ">=0.6.12,<0.7" }, + { name = "google-adk", specifier = ">=2.2.0,<3" }, + { name = "google-genai", specifier = ">=2.10.0,<3.0.0" }, + { name = "googleapis-common-protos", specifier = ">=1.75.0,<2" }, + { name = "grpcio", specifier = ">=1.48.2,<2" }, + { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, + { name = "httpx", specifier = ">=0.28.1" }, + { name = "langchain", marker = "python_full_version >= '3.11'", specifier = ">=1.3.11,<2" }, + { name = "langchain-anthropic", marker = "python_full_version >= '3.11'", specifier = ">=1.4.7" }, + { name = "langchain-core", marker = "python_full_version >= '3.11'", specifier = ">=1.4.8,<2" }, + { name = "langgraph", specifier = ">=1.1.0" }, + { name = "langsmith", specifier = ">=0.7.34,<0.9" }, + { name = "litellm", specifier = ">=1.83.0" }, + { name = "maturin", specifier = ">=1.8.2" }, + { name = "mcp", specifier = ">=1.24,<2" }, + { name = "moto", extras = ["s3", "server"], specifier = ">=5" }, + { name = "mypy", specifier = "==1.18.2" }, + { name = "mypy-protobuf", specifier = ">=3.3.0,<4" }, + { name = "openai-agents", marker = "python_full_version >= '3.14'", specifier = ">=0.20,<0.21" }, + { name = "openai-agents", extras = ["litellm"], marker = "python_full_version < '3.14'", specifier = ">=0.20,<0.21" }, { name = "openinference-instrumentation-google-adk", specifier = ">=0.1.11" }, { name = "openinference-instrumentation-openai-agents", specifier = ">=0.1.0" }, + { name = "opentelemetry-api", specifier = ">=1.26,<2" }, { name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.11.1,<2" }, + { name = "opentelemetry-sdk", specifier = ">=1.26,<2" }, { name = "opentelemetry-sdk-extension-aws", specifier = ">=2.0.0,<3" }, { name = "opentelemetry-semantic-conventions", specifier = ">=0.40b0,<1" }, { name = "psutil", specifier = ">=5.9.3,<6" }, + { name = "pydantic", specifier = ">=2.0.0,<3" }, { name = "pydocstyle", specifier = ">=6.3.0,<7" }, { name = "pydoctor", specifier = ">=25.10.1,<26" }, { name = "pyright", specifier = "==1.1.403" }, @@ -4880,6 +5336,7 @@ dev = [ { name = "strands-agents-tools", specifier = ">=0.5.2" }, { name = "toml", specifier = ">=0.10.2,<0.11" }, { name = "twine", specifier = ">=4.0.1,<5" }, + { name = "types-aioboto3", extras = ["s3"], specifier = ">=10.4.0" }, ] [[package]] @@ -5047,13 +5504,22 @@ name = "tqdm" version = "4.68.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ae/5f/57ff8b434839e70dab45601284ea413e947a63799891b7553e5960a793a8/tqdm-4.68.4.tar.gz", hash = "sha256:19829c9673638f2a0b8617da4cdcb927e831cd88bcfcb6e78d42a4d1af131520", size = 792418, upload-time = "2026-07-07T09:58:18.369Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/22/2a/5e5e750890ada51017d18d0d4c30da696e5b5bd3180947729927628fc3cb/tqdm-4.68.4-py3-none-any.whl", hash = "sha256:5168118b2368f48c561afda8020fd79195b1bdb0bdf8086b88442c267a315dc2", size = 676612, upload-time = "2026-07-07T09:58:16.256Z" }, ] +[[package]] +name = "truststore" +version = "0.10.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/a3/1585216310e344e8102c22482f6060c7a6ea0322b63e026372e6dcefcfd6/truststore-0.10.4.tar.gz", hash = "sha256:9d91bd436463ad5e4ee4aba766628dd6cd7010cf3e2461756b3303710eebc301", size = 26169, upload-time = "2025-08-12T18:49:02.73Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/97/56608b2249fe206a67cd573bc93cd9896e1efb9e98bce9c163bcdc704b88/truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981", size = 18660, upload-time = "2025-08-12T18:49:01.46Z" }, +] + [[package]] name = "twine" version = "4.0.2" @@ -5100,7 +5566,7 @@ dependencies = [ { name = "botocore-stubs" }, { name = "types-aiobotocore" }, { name = "types-s3transfer" }, - { name = "typing-extensions", marker = "python_full_version < '3.12'" }, + { name = "typing-extensions", marker = "python_full_version < '3.12' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/56/76/e162ea2ef8d414d4f36f28a6e0b6078ccef3f2f9d5f957859f303995c528/types_aioboto3-15.5.0.tar.gz", hash = "sha256:5769a1c3df7ca1abedf3656ddf0b970c9b0436d0f88cf4686040b55cd2a02925", size = 81059, upload-time = "2025-10-31T01:11:54.445Z" } wheels = [ @@ -5118,7 +5584,7 @@ version = "3.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore-stubs" }, - { name = "typing-extensions", marker = "python_full_version < '3.12'" }, + { name = "typing-extensions", marker = "python_full_version < '3.12' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/76/e8/ef1fcb876937dbdddc0f01b5df4ed53f33b166a6367d80a9014d5e5f091d/types_aiobotocore-3.7.0.tar.gz", hash = "sha256:fe35de52c12e5fdb89ca60b3989766e7fe827e3d2e95fcf4583e91581945205c", size = 87992, upload-time = "2026-05-10T03:19:32.353Z" } wheels = [ @@ -5130,7 +5596,7 @@ name = "types-aiobotocore-s3" version = "2.25.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.12'" }, + { name = "typing-extensions", marker = "python_full_version < '3.12' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a7/c6/9bb91a44eed1114690edb15d8251f32392e355dfa0a5b8e1c190b4cf89a4/types_aiobotocore_s3-2.25.2.tar.gz", hash = "sha256:678aa425491af19bd6d011d59ecdbbb7ae7e95800efddcf4fd559ab72c94e194", size = 75955, upload-time = "2025-11-12T01:52:06.536Z" } wheels = [ @@ -5323,7 +5789,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a2/65/b7c6c443ccc58678c91e1e973bbe2a878591538655d6e1d47f24ba1c51f3/uvicorn-0.51.0.tar.gz", hash = "sha256:f6f4b69b657c312f516dd2d268ab9ae6f254b11e4bac504f37b2ab58b24dd0b0", size = 94412, upload-time = "2026-07-08T10:59:05.962Z" } wheels = [ @@ -5367,7 +5833,7 @@ name = "wcmatch" version = "11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "bracex", marker = "python_full_version >= '3.11'" }, + { name = "bracex", marker = "python_full_version >= '3.11' or (extra == 'extra-10-temporalio-google-adk' and extra == 'extra-10-temporalio-mcp') or (extra == 'extra-10-temporalio-google-adk' and extra == 'group-10-temporalio-dev') or (extra == 'extra-10-temporalio-mcp' and extra == 'extra-10-temporalio-strands-agents') or (extra == 'extra-10-temporalio-mcp' and extra == 'group-10-temporalio-dev-mcp-v1') or (extra == 'extra-10-temporalio-strands-agents' and extra == 'group-10-temporalio-dev') or (extra == 'group-10-temporalio-dev' and extra == 'group-10-temporalio-dev-mcp-v1')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/16/25/1da725838132221e33568973da484ff43813662ccc06ebf7f6e3abddfcd5/wcmatch-11.0.tar.gz", hash = "sha256:55d95c2447789712774b198ceec72939e88b5618f1f8f0a9b605bf7740b63b96", size = 141360, upload-time = "2026-07-10T05:50:24.183Z" } wheels = [