mirror of
https://github.com/docling-project/docling-mcp.git
synced 2026-05-17 13:10:50 +00:00
chore: delete MCP client, delete empty sdg app, fix ACP client
Signed-off-by: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com>
This commit is contained in:
@@ -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.",
|
||||
)
|
||||
|
||||
@@ -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 <path_to_server_script>")
|
||||
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())
|
||||
@@ -1 +0,0 @@
|
||||
"""Tools for synthetically generate data from DoclingDocument objects."""
|
||||
@@ -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",
|
||||
|
||||
@@ -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" },
|
||||
|
||||
Reference in New Issue
Block a user