diff --git a/docling_mcp/clients/acp_client.py b/docling_mcp/clients/acp_client.py index 96231ba..1683b23 100644 --- a/docling_mcp/clients/acp_client.py +++ b/docling_mcp/clients/acp_client.py @@ -8,8 +8,8 @@ from colorama import Fore async def run_conversion_workflow() -> None: """Run the document conversion workflow by calling the docling_agent.""" - async with Client(base_url="http://localhost:4242") as hospital: - run1 = await hospital.run_sync( + async with Client(base_url="http://localhost:4242") as acp_client: + run1 = await acp_client.run_sync( agent="docling_agent", input="Please convert the document at https://arxiv.org/pdf/2408.09869 to markdown and summarize its content.", ) diff --git a/docling_mcp/clients/mcp_client.py b/docling_mcp/clients/mcp_client.py deleted file mode 100644 index b237d29..0000000 --- a/docling_mcp/clients/mcp_client.py +++ /dev/null @@ -1,156 +0,0 @@ -"""Clients for MCP servers.""" - -import asyncio -from contextlib import AsyncExitStack -from typing import Optional - -from anthropic import Anthropic -from anthropic.types import Message, MessageParam, ToolParam -from dotenv import load_dotenv -from mcp import ClientSession, StdioServerParameters -from mcp.client.stdio import stdio_client - -load_dotenv() # load environment variables from .env - - -class MCPClient: - """A simple client to prompt an MCP server.""" - - def __init__(self) -> None: - # Initialize session and client objects - self.session: Optional[ClientSession] = None - self.exit_stack = AsyncExitStack() - self.anthropic = Anthropic() - - async def connect_to_server(self, server_script_path: str) -> None: - """Connect to an MCP server. - - Args: - server_script_path: Path to the server script (.py or .js). - """ - is_python = server_script_path.endswith(".py") - is_js = server_script_path.endswith(".js") - if not (is_python or is_js): - raise ValueError("Server script must be a .py or .js file") - - command = "python" if is_python else "node" - server_params = StdioServerParameters( - command=command, args=[server_script_path], env=None - ) - - stdio_transport = await self.exit_stack.enter_async_context( - stdio_client(server_params) - ) - self.stdio, self.write = stdio_transport - self.session = await self.exit_stack.enter_async_context( - ClientSession(self.stdio, self.write) - ) - - await self.session.initialize() - - # List available tools - response = await self.session.list_tools() - tools = response.tools - print("\nConnected to server with tools:", [tool.name for tool in tools]) - - async def process_query(self, query: str) -> str: - """Process a query using Claude and available tools.""" - messages: list[MessageParam] = [MessageParam(role="user", content=query)] - - if self.session is None: - return "" - response = await self.session.list_tools() - available_tools: list[ToolParam] = [ - ToolParam( - name=tool.name, - description=(tool.description or ""), - input_schema=tool.inputSchema, - ) - for tool in response.tools - ] - - # Initial Claude API call - msg: Message = self.anthropic.messages.create( - model="claude-3-5-sonnet-20241022", - max_tokens=1000, - messages=messages, - tools=available_tools, - ) - - # Process response and handle tool calls - final_text = [] - - for content in msg.content: - if content.type == "text": - final_text.append(content.text) - elif content.type == "tool_use": - tool_name = content.name - tool_args = content.input - - # Execute tool call - result = await self.session.call_tool( - tool_name, - tool_args, # type: ignore[arg-type] - ) - final_text.append(f"[Calling tool {tool_name} with args {tool_args}]") - - # Continue conversation with tool results - if hasattr(content, "text") and content.text: - messages.append( - MessageParam(role="assistant", content=content.text) - ) - messages.append(MessageParam(role="user", content=result.content)) # type: ignore[typeddict-item] - - # Get next response from Claude - msg = self.anthropic.messages.create( - model="claude-3-5-sonnet-20241022", - max_tokens=1000, - messages=messages, - ) - - final_text.append(msg.content[0].text) # type: ignore[union-attr] - - return "\n".join(final_text) - - async def chat_loop(self) -> None: - """Run an interactive chat loop.""" - print("\nMCP Client Started!") - print("Type your queries or 'quit' to exit.") - - while True: - try: - query = input("\nQuery: ").strip() - - if query.lower() == "quit": - break - - response = await self.process_query(query) - print("\n" + response) - - except Exception as e: - print(f"\nError: {e!s}") - - async def cleanup(self) -> None: - """Clean up resources.""" - await self.exit_stack.aclose() - - -async def main() -> None: - """Run a simple MCP client from the command prompt.""" - if len(sys.argv) < 2: - print("Usage: python client.py ") - sys.exit(1) - - client = MCPClient() - try: - await client.connect_to_server(sys.argv[1]) - await client.chat_loop() - finally: - await client.cleanup() - - -if __name__ == "__main__": - """Run the MCP client.""" - import sys - - asyncio.run(main()) diff --git a/docling_mcp/tools/sdg.py b/docling_mcp/tools/sdg.py deleted file mode 100644 index 23500a0..0000000 --- a/docling_mcp/tools/sdg.py +++ /dev/null @@ -1 +0,0 @@ -"""Tools for synthetically generate data from DoclingDocument objects.""" diff --git a/pyproject.toml b/pyproject.toml index 7387c69..17423d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,6 @@ classifiers = [ requires-python = ">=3.10" dependencies = [ "acp-sdk>=0.0.6", - "anthropic>=0.51.0", "docling~=2.25", "httpx>=0.28.1", "llama-index>=0.12.33", diff --git a/uv.lock b/uv.lock index c6e7ef4..c8d7b5a 100644 --- a/uv.lock +++ b/uv.lock @@ -207,24 +207,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] -[[package]] -name = "anthropic" -version = "0.51.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "distro" }, - { name = "httpx" }, - { name = "jiter" }, - { name = "pydantic" }, - { name = "sniffio" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/63/4a/96f99a61ae299f9e5aa3e765d7342d95ab2e2ba5b69a3ffedb00ef779651/anthropic-0.51.0.tar.gz", hash = "sha256:6f824451277992af079554430d5b2c8ff5bc059cc2c968cdc3f06824437da201", size = 219063, upload-time = "2025-05-07T15:39:22.348Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8c/6e/9637122c5f007103bd5a259f4250bd8f1533dd2473227670fd10a1457b62/anthropic-0.51.0-py3-none-any.whl", hash = "sha256:b8b47d482c9aa1f81b923555cebb687c2730309a20d01be554730c8302e0f62a", size = 263957, upload-time = "2025-05-07T15:39:20.82Z" }, -] - [[package]] name = "anyio" version = "4.9.0" @@ -748,7 +730,6 @@ source = { editable = "." } dependencies = [ { name = "acp-sdk", version = "0.0.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "acp-sdk", version = "0.9.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, - { name = "anthropic" }, { name = "docling" }, { name = "httpx" }, { name = "llama-index" }, @@ -791,7 +772,6 @@ dev = [ [package.metadata] requires-dist = [ { name = "acp-sdk", specifier = ">=0.0.6" }, - { name = "anthropic", specifier = ">=0.51.0" }, { name = "docling", specifier = "~=2.25" }, { name = "httpx", specifier = ">=0.28.1" }, { name = "llama-index", specifier = ">=0.12.33" }, @@ -3853,16 +3833,16 @@ name = "rapidocr-onnxruntime" version = "1.4.4" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "1.26.4", source = { registry = "https://pypi.org/simple" }, marker = "platform_machine == 'x86_64' and sys_platform == 'darwin'" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "platform_machine != 'x86_64' or sys_platform != 'darwin'" }, - { name = "onnxruntime" }, - { name = "opencv-python" }, - { name = "pillow" }, - { name = "pyclipper" }, - { name = "pyyaml" }, - { name = "shapely" }, - { name = "six" }, - { name = "tqdm" }, + { name = "numpy", version = "1.26.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13' and platform_machine == 'x86_64' and sys_platform == 'darwin'" }, + { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.13' and platform_machine != 'x86_64') or (python_full_version < '3.13' and sys_platform != 'darwin')" }, + { name = "onnxruntime", marker = "python_full_version < '3.13'" }, + { name = "opencv-python", marker = "python_full_version < '3.13'" }, + { name = "pillow", marker = "python_full_version < '3.13'" }, + { name = "pyclipper", marker = "python_full_version < '3.13'" }, + { name = "pyyaml", marker = "python_full_version < '3.13'" }, + { name = "shapely", marker = "python_full_version < '3.13'" }, + { name = "six", marker = "python_full_version < '3.13'" }, + { name = "tqdm", marker = "python_full_version < '3.13'" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/ba/12/1e5497183bdbe782dbb91bad1d0d2297dba4d2831b2652657f7517bfc6df/rapidocr_onnxruntime-1.4.4-py3-none-any.whl", hash = "sha256:971d7d5f223a7a808662229df1ef69893809d8457d834e6373d3854bc1782cbf", size = 14915192, upload-time = "2025-01-17T01:48:25.104Z" },