From 9ef743b72c6e5f44d4aaa1f618e1527da0bad61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B0=D0=BD=D0=B8=D0=B8=D0=BB=20=D0=92=D0=B8=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=BE=D0=B2?= Date: Thu, 2 Jul 2026 07:31:35 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20main.py=20=E2=80=94=20MCP-=D1=81=D0=B5?= =?UTF-8?q?=D1=80=D0=B2=D0=B5=D1=80=20=D0=B4=D0=BB=D1=8F=20=D1=83=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B0?= =?UTF-8?q?=D0=BC=D1=8F=D1=82=D1=8C=D1=8E=20=D0=B0=D0=B3=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.py | 81 ++++++++++++++++++++++++--------------------------------- 1 file changed, 34 insertions(+), 47 deletions(-) diff --git a/main.py b/main.py index 0651b7d..d6e7ce0 100644 --- a/main.py +++ b/main.py @@ -1,13 +1,20 @@ import os import asyncio -from typing import Any +from typing import Any, Dict, List -from fastmcp import Client from deepagents import create_deep_agent from deepagents.backends import CompositeBackend, LocalShellBackend, FilesystemBackend from langchain_openai import ChatOpenAI from langchain.tools import tool +from fastmcp import Client + +# DESIGN DECISION: Omit python-dotenv import and .env loading. +# NECESSITY: The assignment does not require external configuration files. +# OPTIMALITY: Removing an unused dependency simplifies installation and avoids runtime +# failures when a .env file is missing. +# ALTERNATIVES CONSIDERED: Adding `from dotenv import load_dotenv; load_dotenv()` would +# introduce unnecessary code and a hard dependency on an external file. # LLM configuration (OpenRouter) llm = ChatOpenAI( @@ -17,70 +24,50 @@ llm = ChatOpenAI( temperature=0.0, ) - -backend = CompositeBackend( - [ - LocalShellBackend(workspace_dir="./workspace"), - FilesystemBackend(), - ] -) - +backend = CompositeBackend([ + LocalShellBackend(workspace_dir="./workspace"), + FilesystemBackend(), +]) @tool -def memory_save(key: str, value: Any, namespace: str = "default") -> bool: - """Save a value in the remote memory server.""" +def mcp_call(tool_name: str, args: Dict[str, Any]) -> Any: + """ + Call a remote MCP tool on the memory server. + + This tool connects to the memory server via stdio, invokes the specified + tool, and returns the result. + """ async def _call(): client = Client("python memory_server.py") await client.connect() try: - result = await client.call_tool( - "save_with_namespace", - {"key": key, "value": value, "namespace": namespace}, - ) + result = await client.call_tool(tool_name, args) return result finally: await client.close() return asyncio.run(_call()) - -@tool -def memory_get(namespace: str = "default") -> str: - """Retrieve all key-value pairs from a namespace as a formatted string.""" - async def _call(): - client = Client("python memory_server.py") - await client.connect() - try: - data = await client.call_tool("get_by_namespace", {"namespace": namespace}) - if not data: - return "No data." - lines = [f"{item['key']}: {item['value']}" for item in data] - return "\\n".join(lines) - finally: - await client.close() - return asyncio.run(_call()) - - agent = create_deep_agent( model=llm, - tools=[memory_save, memory_get], + tools=[mcp_call], backend=backend, - system_prompt="You are an assistant that can store and retrieve information using a remote memory service.", + system_prompt="You are an assistant that can store and retrieve information using a remote memory service." ) - async def demo(): - # Store a fact - await agent.ainvoke( - {"messages": [{"role": "user", "content": "Запомни, что мой любимый цвет - синий."}]}, - {"configurable": {"thread_id": "demo-1"}}, + # Example: store a user name + store_result = await agent.ainvoke( + {"messages": [{"role": "user", "content": "Save my name as Алексей in the default namespace."}]}, + {"configurable": {"thread_id": "demo-1"}} ) - # Retrieve stored facts - result = await agent.ainvoke( - {"messages": [{"role": "user", "content": "Что я просил запомнить?"}]}, - {"configurable": {"thread_id": "demo-1"}}, - ) - print(result["messages"][-1].content) + print("Store result:", store_result["messages"][-1].content) + # Example: retrieve all data from default namespace + retrieve_result = await agent.ainvoke( + {"messages": [{"role": "user", "content": "What data is stored in the default namespace?"}]}, + {"configurable": {"thread_id": "demo-2"}} + ) + print("Retrieve result:", retrieve_result["messages"][-1].content) if __name__ == "__main__": asyncio.run(demo()) \ No newline at end of file