acp-sdk 0.0.1__tar.gz → 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/PKG-INFO +2 -2
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/clients/simple-chatbot/mcp_simple_chatbot/main.py +2 -3
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/agents.py +4 -4
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/pyproject.toml +11 -21
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/agents/base.py +1 -3
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/agents/templates.py +1 -3
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/context.py +3 -3
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/server.py +6 -6
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/lowlevel/server.py +36 -25
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/shared/memory.py +3 -3
- acp_sdk-0.0.3/tasks.toml +67 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/issues/test_100_tool_listing.py +3 -3
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/issues/test_152_resource_mime_type.py +30 -30
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/issues/test_176_progress_token.py +3 -3
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/test_server.py +0 -1
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/shared/test_session.py +1 -0
- acp_sdk-0.0.1/examples/servers/simple-tool/.python-version +0 -1
- acp_sdk-0.0.1/uv.lock +0 -786
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/.github/workflows/check-lock.yml +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/.github/workflows/main-checks.yml +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/.github/workflows/publish-pypi.yml +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/.github/workflows/pull-request-checks.yml +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/.github/workflows/shared.yml +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/.gitignore +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/.pre-commit-config.yaml +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/CLAUDE.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/CODE_OF_CONDUCT.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/CONTRIBUTING.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/LICENSE +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/README.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/RELEASE.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/SECURITY.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/README.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3/examples/clients/simple-chatbot}/.python-version +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/clients/simple-chatbot/README.MD +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/clients/simple-chatbot/mcp_simple_chatbot/.env.example +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/clients/simple-chatbot/mcp_simple_chatbot/requirements.txt +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/clients/simple-chatbot/mcp_simple_chatbot/servers_config.json +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/clients/simple-chatbot/mcp_simple_chatbot/test.db +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/clients/simple-chatbot/pyproject.toml +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/clients/simple-chatbot/uv.lock +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/complex_inputs.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/desktop.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/echo.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/memory.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/parameter_descriptions.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/readme-quickstart.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/screenshot.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/simple_echo.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/text_me.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/highlevel/unicode_example.py +0 -0
- {acp_sdk-0.0.1/examples/clients/simple-chatbot → acp_sdk-0.0.3/examples/servers/simple-prompt}/.python-version +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-prompt/README.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-prompt/mcp_simple_prompt/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-prompt/mcp_simple_prompt/__main__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-prompt/mcp_simple_prompt/server.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-prompt/pyproject.toml +0 -0
- {acp_sdk-0.0.1/examples/servers/simple-prompt → acp_sdk-0.0.3/examples/servers/simple-resource}/.python-version +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-resource/README.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-resource/mcp_simple_resource/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-resource/mcp_simple_resource/__main__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-resource/mcp_simple_resource/server.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-resource/pyproject.toml +0 -0
- {acp_sdk-0.0.1/examples/servers/simple-resource → acp_sdk-0.0.3/examples/servers/simple-tool}/.python-version +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-tool/README.md +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-tool/mcp_simple_tool/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-tool/mcp_simple_tool/__main__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-tool/mcp_simple_tool/server.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/examples/servers/simple-tool/pyproject.toml +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/cli/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/cli/claude.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/cli/cli.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/client/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/client/__main__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/client/session.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/client/sse.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/client/stdio.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/py.typed +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/__main__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/agents/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/agents/agent_manager.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/exceptions.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/prompts/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/prompts/base.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/prompts/manager.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/prompts/prompt_manager.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/resources/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/resources/base.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/resources/resource_manager.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/resources/templates.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/resources/types.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/tools/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/tools/base.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/tools/tool_manager.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/utilities/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/utilities/func_metadata.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/utilities/logging.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/highlevel/utilities/types.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/lowlevel/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/lowlevel/helper_types.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/models.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/session.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/sse.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/stdio.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/server/websocket.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/shared/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/shared/context.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/shared/exceptions.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/shared/progress.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/shared/session.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/shared/version.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/src/acp/types.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/client/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/client/test_config.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/client/test_session.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/client/test_stdio.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/conftest.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/issues/test_129_resource_templates.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/issues/test_141_resource_templates.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/issues/test_88_random_error.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/prompts/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/prompts/test_base.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/prompts/test_manager.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/resources/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/resources/test_file_resources.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/resources/test_function_resources.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/resources/test_resource_manager.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/resources/test_resource_template.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/resources/test_resources.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/servers/__init__.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/servers/test_file_server.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/test_func_metadata.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/test_parameter_descriptions.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/fastmcp/test_tool_manager.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/test_read_resource.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/test_session.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/server/test_stdio.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/shared/test_memory.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/shared/test_sse.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/test_examples.py +0 -0
- {acp_sdk-0.0.1 → acp_sdk-0.0.3}/tests/test_types.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: acp-sdk
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.3
|
4
4
|
Summary: Agent Communication Protocol SDK
|
5
5
|
Project-URL: Homepage, https://github.com/i-am-bee/beeai
|
6
6
|
Project-URL: Repository, https://github.com/i-am-bee/beeai
|
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
20
|
-
Requires-Python:
|
20
|
+
Requires-Python: <4.0,>=3.10
|
21
21
|
Requires-Dist: anyio>=4.5
|
22
22
|
Requires-Dist: httpx-sse>=0.4
|
23
23
|
Requires-Dist: httpx>=0.27
|
@@ -7,9 +7,9 @@ from contextlib import AsyncExitStack
|
|
7
7
|
from typing import Any
|
8
8
|
|
9
9
|
import httpx
|
10
|
+
from acp import ClientSession, StdioServerParameters
|
10
11
|
from acp.client.stdio import stdio_client
|
11
12
|
from dotenv import load_dotenv
|
12
|
-
from mcp import ClientSession, StdioServerParameters
|
13
13
|
|
14
14
|
# Configure logging
|
15
15
|
logging.basicConfig(
|
@@ -322,8 +322,7 @@ class ChatSession:
|
|
322
322
|
total = result["total"]
|
323
323
|
percentage = (progress / total) * 100
|
324
324
|
logging.info(
|
325
|
-
f"Progress: {progress}/{total} "
|
326
|
-
f"({percentage:.1f}%)"
|
325
|
+
f"Progress: {progress}/{total} ({percentage:.1f}%)"
|
327
326
|
)
|
328
327
|
|
329
328
|
return f"Tool execution result: {result}"
|
@@ -6,16 +6,16 @@ from acp.server.highlevel import Context, Server
|
|
6
6
|
class Input(BaseModel):
|
7
7
|
prompt: str
|
8
8
|
|
9
|
+
|
9
10
|
class Output(BaseModel):
|
10
11
|
text: str
|
11
12
|
|
13
|
+
|
12
14
|
acp_server = Server()
|
13
15
|
|
16
|
+
|
14
17
|
@acp_server.agent(
|
15
|
-
name="Echoagent",
|
16
|
-
description="Echoing agent",
|
17
|
-
input=Input,
|
18
|
-
output=Output
|
18
|
+
name="Echoagent", description="Echoing agent", input=Input, output=Output
|
19
19
|
)
|
20
20
|
async def run_agent(input: Input, ctx: Context) -> Output:
|
21
21
|
agent = "Echoagent"
|
@@ -1,9 +1,9 @@
|
|
1
1
|
[project]
|
2
2
|
name = "acp-sdk"
|
3
|
-
version = "0.0.
|
3
|
+
version = "0.0.3"
|
4
4
|
description = "Agent Communication Protocol SDK"
|
5
5
|
readme = "README.md"
|
6
|
-
requires-python = ">=3.10"
|
6
|
+
requires-python = ">=3.10,<4.0"
|
7
7
|
authors = [{ name = "IBM Corp." }, { name = "Anthropic, PBC" }]
|
8
8
|
maintainers = []
|
9
9
|
keywords = ["git", "acp", "llm"]
|
@@ -31,16 +31,8 @@ dependencies = [
|
|
31
31
|
"setuptools==75.8.0",
|
32
32
|
]
|
33
33
|
|
34
|
-
[
|
35
|
-
|
36
|
-
cli = ["typer>=0.12.4", "python-dotenv>=1.0.0"]
|
37
|
-
|
38
|
-
[project.scripts]
|
39
|
-
acp = "acp.cli:app [cli]"
|
40
|
-
|
41
|
-
[tool.uv]
|
42
|
-
resolution = "lowest-direct"
|
43
|
-
dev-dependencies = [
|
34
|
+
[dependency-groups]
|
35
|
+
dev = [
|
44
36
|
"pyright>=1.1.391",
|
45
37
|
"pytest>=8.3.4",
|
46
38
|
"ruff>=0.8.5",
|
@@ -49,6 +41,13 @@ dev-dependencies = [
|
|
49
41
|
"pytest-xdist>=3.6.1",
|
50
42
|
]
|
51
43
|
|
44
|
+
[project.optional-dependencies]
|
45
|
+
rich = ["rich>=13.9.4"]
|
46
|
+
cli = ["typer>=0.12.4", "python-dotenv>=1.0.0"]
|
47
|
+
|
48
|
+
[project.scripts]
|
49
|
+
acp = "acp.cli:app [cli]"
|
50
|
+
|
52
51
|
[build-system]
|
53
52
|
requires = ["hatchling"]
|
54
53
|
build-backend = "hatchling.build"
|
@@ -63,8 +62,6 @@ packages = ["src/acp"]
|
|
63
62
|
|
64
63
|
[tool.pyright]
|
65
64
|
include = ["src/acp"]
|
66
|
-
venvPath = "."
|
67
|
-
venv = ".venv"
|
68
65
|
|
69
66
|
[tool.ruff.lint]
|
70
67
|
select = ["E", "F", "I"]
|
@@ -77,10 +74,3 @@ target-version = "py310"
|
|
77
74
|
[tool.ruff.lint.per-file-ignores]
|
78
75
|
"__init__.py" = ["F401"]
|
79
76
|
"tests/server/fastmcp/test_func_metadata.py" = ["E501"]
|
80
|
-
|
81
|
-
|
82
|
-
[tool.uv.workspace]
|
83
|
-
members = ["examples/servers/*"]
|
84
|
-
|
85
|
-
[tool.uv.sources]
|
86
|
-
acp = { workspace = true }
|
@@ -14,9 +14,7 @@ class Agent(BaseModel):
|
|
14
14
|
input: Type[BaseModel] = Field(description="Model for input")
|
15
15
|
output: Type[BaseModel] = Field(description="Model for output")
|
16
16
|
|
17
|
-
run_fn: Callable[[BaseModel, "Context"], Awaitable[BaseModel]] = Field(
|
18
|
-
exclude=True
|
19
|
-
)
|
17
|
+
run_fn: Callable[[BaseModel, "Context"], Awaitable[BaseModel]] = Field(exclude=True)
|
20
18
|
destroy_fn: Callable[["Context"], Awaitable[None]] | None = Field(exclude=True)
|
21
19
|
|
22
20
|
model_config = ConfigDict(extra="allow")
|
@@ -16,8 +16,6 @@ class AgentTemplate(BaseModel):
|
|
16
16
|
input: Type[BaseModel] = Field(description="Model for run input")
|
17
17
|
output: Type[BaseModel] = Field(description="Model for run output")
|
18
18
|
|
19
|
-
create_fn: Callable[[BaseModel, "Context"], Awaitable[Agent]] = Field(
|
20
|
-
exclude=True
|
21
|
-
)
|
19
|
+
create_fn: Callable[[BaseModel, "Context"], Awaitable[Agent]] = Field(exclude=True)
|
22
20
|
|
23
21
|
model_config = ConfigDict(extra="allow")
|
@@ -124,9 +124,9 @@ class Context(BaseModel):
|
|
124
124
|
Returns:
|
125
125
|
The resource content as either text or bytes
|
126
126
|
"""
|
127
|
-
assert (
|
128
|
-
|
129
|
-
)
|
127
|
+
assert self._fastmcp is not None, (
|
128
|
+
"Context is not available outside of a request"
|
129
|
+
)
|
130
130
|
return await self._fastmcp.read_resource(uri)
|
131
131
|
|
132
132
|
async def log(
|
@@ -467,7 +467,7 @@ class Server:
|
|
467
467
|
config: Type[BaseModel],
|
468
468
|
input: Type[BaseModel],
|
469
469
|
output: Type[BaseModel],
|
470
|
-
**kwargs
|
470
|
+
**kwargs,
|
471
471
|
) -> Callable:
|
472
472
|
"""Decorator to register an agent template.
|
473
473
|
|
@@ -494,7 +494,7 @@ class Server:
|
|
494
494
|
input=input,
|
495
495
|
output=output,
|
496
496
|
create_fn=func,
|
497
|
-
**kwargs
|
497
|
+
**kwargs,
|
498
498
|
)
|
499
499
|
self.add_agent_template(template)
|
500
500
|
return func
|
@@ -513,7 +513,7 @@ class Server:
|
|
513
513
|
configSchema=template.config.model_json_schema(),
|
514
514
|
inputSchema=template.input.model_json_schema(),
|
515
515
|
outputSchema=template.output.model_json_schema(),
|
516
|
-
**(template.model_extra if template.model_extra else {})
|
516
|
+
**(template.model_extra if template.model_extra else {}),
|
517
517
|
)
|
518
518
|
for template in templates
|
519
519
|
]
|
@@ -529,7 +529,7 @@ class Server:
|
|
529
529
|
description: str,
|
530
530
|
input: Type[BaseModel],
|
531
531
|
output: Type[BaseModel],
|
532
|
-
**kwargs
|
532
|
+
**kwargs,
|
533
533
|
) -> Callable:
|
534
534
|
"""Decorator to register an agent.
|
535
535
|
|
@@ -554,7 +554,7 @@ class Server:
|
|
554
554
|
output=output,
|
555
555
|
run_fn=func,
|
556
556
|
destroy_fn=None,
|
557
|
-
**kwargs
|
557
|
+
**kwargs,
|
558
558
|
)
|
559
559
|
self.add_agent(agent=agent)
|
560
560
|
return func
|
@@ -570,7 +570,7 @@ class Server:
|
|
570
570
|
description=agent.description,
|
571
571
|
inputSchema=agent.input.model_json_schema(),
|
572
572
|
outputSchema=agent.output.model_json_schema(),
|
573
|
-
**(agent.model_extra if agent.model_extra else {})
|
573
|
+
**(agent.model_extra if agent.model_extra else {}),
|
574
574
|
)
|
575
575
|
for agent in agents
|
576
576
|
]
|
@@ -68,8 +68,10 @@ import contextvars
|
|
68
68
|
import logging
|
69
69
|
import warnings
|
70
70
|
from collections.abc import Awaitable, Callable
|
71
|
+
from contextlib import AsyncExitStack
|
71
72
|
from typing import Any, Sequence
|
72
73
|
|
74
|
+
import anyio
|
73
75
|
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
|
74
76
|
from pydantic import AnyUrl
|
75
77
|
|
@@ -182,7 +184,7 @@ class Server:
|
|
182
184
|
if types.ListAgentsRequest in self.request_handlers:
|
183
185
|
agents_capability = types.AgentsCapability(
|
184
186
|
templates=types.ListAgentTemplatesRequest in self.request_handlers,
|
185
|
-
listChanged=notification_options.agents_changed
|
187
|
+
listChanged=notification_options.agents_changed,
|
186
188
|
)
|
187
189
|
|
188
190
|
# Set logging capabilities if handler exists
|
@@ -538,30 +540,41 @@ class Server:
|
|
538
540
|
# in-process servers.
|
539
541
|
raise_exceptions: bool = False,
|
540
542
|
):
|
541
|
-
with
|
542
|
-
|
543
|
-
read_stream, write_stream, initialization_options
|
544
|
-
)
|
543
|
+
async with AsyncExitStack() as stack:
|
544
|
+
session = await stack.enter_async_context(
|
545
|
+
ServerSession(read_stream, write_stream, initialization_options)
|
546
|
+
)
|
547
|
+
|
548
|
+
async with anyio.create_task_group() as tg:
|
545
549
|
async for message in session.incoming_messages:
|
546
550
|
logger.debug(f"Received message: {message}")
|
547
551
|
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
552
|
+
tg.start_soon(
|
553
|
+
self._handle_message, message, session, raise_exceptions
|
554
|
+
)
|
555
|
+
|
556
|
+
async def _handle_message(
|
557
|
+
self,
|
558
|
+
message: RequestResponder[types.ClientRequest, types.ServerResult]
|
559
|
+
| types.ClientNotification
|
560
|
+
| Exception,
|
561
|
+
session: ServerSession,
|
562
|
+
raise_exceptions: bool = False,
|
563
|
+
):
|
564
|
+
with warnings.catch_warnings(record=True) as w:
|
565
|
+
match message:
|
566
|
+
case (
|
567
|
+
RequestResponder(request=types.ClientRequest(root=req)) as responder
|
568
|
+
):
|
569
|
+
with responder:
|
570
|
+
await self._handle_request(
|
571
|
+
message, req, session, raise_exceptions
|
564
572
|
)
|
573
|
+
case types.ClientNotification(root=notify):
|
574
|
+
await self._handle_notification(notify)
|
575
|
+
|
576
|
+
for warning in w:
|
577
|
+
logger.info(f"Warning: {warning.category.__name__}: {warning.message}")
|
565
578
|
|
566
579
|
async def _handle_request(
|
567
580
|
self,
|
@@ -614,14 +627,12 @@ class Server:
|
|
614
627
|
assert type(notify) in self.notification_handlers
|
615
628
|
|
616
629
|
handler = self.notification_handlers[type(notify)]
|
617
|
-
logger.debug(
|
618
|
-
f"Dispatching notification of type " f"{type(notify).__name__}"
|
619
|
-
)
|
630
|
+
logger.debug(f"Dispatching notification of type {type(notify).__name__}")
|
620
631
|
|
621
632
|
try:
|
622
633
|
await handler(notify)
|
623
634
|
except Exception as err:
|
624
|
-
logger.error(f"Uncaught exception in notification handler:
|
635
|
+
logger.error(f"Uncaught exception in notification handler: {err}")
|
625
636
|
|
626
637
|
|
627
638
|
async def _ping_handler(request: types.PingRequest) -> types.ServerResult:
|
@@ -20,9 +20,9 @@ MessageStream = tuple[
|
|
20
20
|
|
21
21
|
|
22
22
|
@asynccontextmanager
|
23
|
-
async def create_client_server_memory_streams() ->
|
24
|
-
|
25
|
-
|
23
|
+
async def create_client_server_memory_streams() -> AsyncGenerator[
|
24
|
+
tuple[MessageStream, MessageStream], None
|
25
|
+
]:
|
26
26
|
"""
|
27
27
|
Creates a pair of bidirectional memory streams for client-server communication.
|
28
28
|
|
acp_sdk-0.0.3/tasks.toml
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# check
|
2
|
+
|
3
|
+
["acp-python-sdk:check"]
|
4
|
+
depends = ["acp-python-sdk:check:*"]
|
5
|
+
|
6
|
+
["acp-python-sdk:check:ruff-check"]
|
7
|
+
depends = ["setup:uv"]
|
8
|
+
dir = "{{config_root}}/packages/acp-python-sdk"
|
9
|
+
run = "uv run ruff check --quiet"
|
10
|
+
sources = ["src/**/*.py"]
|
11
|
+
outputs = { auto = true }
|
12
|
+
|
13
|
+
["acp-python-sdk:check:ruff-format"]
|
14
|
+
depends = ["setup:uv"]
|
15
|
+
dir = "{{config_root}}/packages/acp-python-sdk"
|
16
|
+
run = "uv run ruff format --quiet --check"
|
17
|
+
sources = ["src/**/*.py"]
|
18
|
+
outputs = { auto = true }
|
19
|
+
|
20
|
+
["acp-python-sdk:check:pyright"]
|
21
|
+
depends = ["setup:uv"]
|
22
|
+
dir = "{{config_root}}/packages/acp-python-sdk"
|
23
|
+
run = "uv run pyright"
|
24
|
+
sources = ["src/**/*.py"]
|
25
|
+
outputs = { auto = true }
|
26
|
+
|
27
|
+
# fix
|
28
|
+
|
29
|
+
["acp-python-sdk:fix"]
|
30
|
+
depends = ["acp-python-sdk:fix:*"]
|
31
|
+
|
32
|
+
["acp-python-sdk:fix:ruff-check"]
|
33
|
+
depends = ["setup:uv"]
|
34
|
+
dir = "{{config_root}}/packages/acp-python-sdk"
|
35
|
+
run = "uv run ruff check --quiet --fix"
|
36
|
+
sources = ["src/**/*.py"]
|
37
|
+
outputs = { auto = true }
|
38
|
+
|
39
|
+
["acp-python-sdk:fix:ruff-format"]
|
40
|
+
depends = ["setup:uv"]
|
41
|
+
dir = "{{config_root}}/packages/acp-python-sdk"
|
42
|
+
run = "uv run ruff format --quiet"
|
43
|
+
sources = ["src/**/*.py"]
|
44
|
+
outputs = { auto = true }
|
45
|
+
|
46
|
+
# test
|
47
|
+
|
48
|
+
["acp-python-sdk:test"]
|
49
|
+
depends = ["setup:uv"]
|
50
|
+
dir = "{{config_root}}/packages/acp-python-sdk"
|
51
|
+
run = "uv run pytest"
|
52
|
+
sources = ["src/**/*.py"]
|
53
|
+
outputs = { auto = true }
|
54
|
+
|
55
|
+
# build
|
56
|
+
|
57
|
+
["acp-python-sdk:build"]
|
58
|
+
dir = "{{config_root}}/packages/acp-python-sdk"
|
59
|
+
run = "uv build --out-dir dist"
|
60
|
+
sources = ["src/**/*.py"]
|
61
|
+
outputs = ["dist/**/*"]
|
62
|
+
|
63
|
+
# clean
|
64
|
+
|
65
|
+
["acp-python-sdk:clean"]
|
66
|
+
dir = "{{config_root}}/packages/acp-python-sdk"
|
67
|
+
run = "rm -rf dist"
|
@@ -30,6 +30,6 @@ async def test_list_tools_returns_all_tools():
|
|
30
30
|
# Verify each tool is unique and has the correct name
|
31
31
|
tool_names = [tool.name for tool in tools]
|
32
32
|
expected_names = [f"tool_{i}" for i in range(num_tools)]
|
33
|
-
assert sorted(tool_names) == sorted(
|
34
|
-
|
35
|
-
)
|
33
|
+
assert sorted(tool_names) == sorted(expected_names), (
|
34
|
+
"Tool names don't match expected names"
|
35
|
+
)
|
@@ -45,31 +45,31 @@ async def test_fastmcp_resource_mime_type():
|
|
45
45
|
bytes_resource = mapping["test://image_bytes"]
|
46
46
|
|
47
47
|
# Verify mime types
|
48
|
-
assert (
|
49
|
-
|
50
|
-
)
|
51
|
-
assert (
|
52
|
-
|
53
|
-
)
|
48
|
+
assert string_resource.mimeType == "image/png", (
|
49
|
+
"String resource mime type not respected"
|
50
|
+
)
|
51
|
+
assert bytes_resource.mimeType == "image/png", (
|
52
|
+
"Bytes resource mime type not respected"
|
53
|
+
)
|
54
54
|
|
55
55
|
# Also verify the content can be read correctly
|
56
56
|
string_result = await client.read_resource(AnyUrl("test://image"))
|
57
57
|
assert len(string_result.contents) == 1
|
58
|
-
assert (
|
59
|
-
|
60
|
-
)
|
61
|
-
assert (
|
62
|
-
|
63
|
-
)
|
58
|
+
assert getattr(string_result.contents[0], "text") == base64_string, (
|
59
|
+
"Base64 string mismatch"
|
60
|
+
)
|
61
|
+
assert string_result.contents[0].mimeType == "image/png", (
|
62
|
+
"String content mime type not preserved"
|
63
|
+
)
|
64
64
|
|
65
65
|
bytes_result = await client.read_resource(AnyUrl("test://image_bytes"))
|
66
66
|
assert len(bytes_result.contents) == 1
|
67
67
|
assert (
|
68
68
|
base64.b64decode(getattr(bytes_result.contents[0], "blob")) == image_bytes
|
69
69
|
), "Bytes mismatch"
|
70
|
-
assert (
|
71
|
-
|
72
|
-
)
|
70
|
+
assert bytes_result.contents[0].mimeType == "image/png", (
|
71
|
+
"Bytes content mime type not preserved"
|
72
|
+
)
|
73
73
|
|
74
74
|
|
75
75
|
async def test_lowlevel_resource_mime_type():
|
@@ -119,28 +119,28 @@ async def test_lowlevel_resource_mime_type():
|
|
119
119
|
bytes_resource = mapping["test://image_bytes"]
|
120
120
|
|
121
121
|
# Verify mime types
|
122
|
-
assert (
|
123
|
-
|
124
|
-
)
|
125
|
-
assert (
|
126
|
-
|
127
|
-
)
|
122
|
+
assert string_resource.mimeType == "image/png", (
|
123
|
+
"String resource mime type not respected"
|
124
|
+
)
|
125
|
+
assert bytes_resource.mimeType == "image/png", (
|
126
|
+
"Bytes resource mime type not respected"
|
127
|
+
)
|
128
128
|
|
129
129
|
# Also verify the content can be read correctly
|
130
130
|
string_result = await client.read_resource(AnyUrl("test://image"))
|
131
131
|
assert len(string_result.contents) == 1
|
132
|
-
assert (
|
133
|
-
|
134
|
-
)
|
135
|
-
assert (
|
136
|
-
|
137
|
-
)
|
132
|
+
assert getattr(string_result.contents[0], "text") == base64_string, (
|
133
|
+
"Base64 string mismatch"
|
134
|
+
)
|
135
|
+
assert string_result.contents[0].mimeType == "image/png", (
|
136
|
+
"String content mime type not preserved"
|
137
|
+
)
|
138
138
|
|
139
139
|
bytes_result = await client.read_resource(AnyUrl("test://image_bytes"))
|
140
140
|
assert len(bytes_result.contents) == 1
|
141
141
|
assert (
|
142
142
|
base64.b64decode(getattr(bytes_result.contents[0], "blob")) == image_bytes
|
143
143
|
), "Bytes mismatch"
|
144
|
-
assert (
|
145
|
-
|
146
|
-
)
|
144
|
+
assert bytes_result.contents[0].mimeType == "image/png", (
|
145
|
+
"Bytes content mime type not preserved"
|
146
|
+
)
|
@@ -32,9 +32,9 @@ async def test_progress_token_zero_first_call():
|
|
32
32
|
await ctx.report_progress(10, 10) # Complete
|
33
33
|
|
34
34
|
# Verify progress notifications
|
35
|
-
assert (
|
36
|
-
|
37
|
-
)
|
35
|
+
assert mock_session.send_progress_notification.call_count == 3, (
|
36
|
+
"All progress notifications should be sent"
|
37
|
+
)
|
38
38
|
mock_session.send_progress_notification.assert_any_call(
|
39
39
|
progress_token=0, progress=0.0, total=10.0
|
40
40
|
)
|
@@ -44,6 +44,7 @@ async def test_in_flight_requests_cleared_after_completion(
|
|
44
44
|
|
45
45
|
|
46
46
|
@pytest.mark.anyio
|
47
|
+
@pytest.mark.skip("broken on Python 3.11+, needs investigation")
|
47
48
|
async def test_request_cancellation():
|
48
49
|
"""Test that requests can be cancelled while in-flight."""
|
49
50
|
# The tool is already registered in the fixture
|
@@ -1 +0,0 @@
|
|
1
|
-
3.10
|