Skip to content

Commit dc21769

Browse files
committed
Cleanup pr
Signed-off-by: Mihai Criveti <[email protected]>
1 parent 308dc1b commit dc21769

File tree

14 files changed

+125
-147
lines changed

14 files changed

+125
-147
lines changed

agent_runtimes/langchain_agent/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ etc. are provided.
2121
- **Health Monitoring**: `/health`, `/ready`, `/list_tools` endpoints
2222

2323
## User Stories Implemented
24-
[x] **Dynamic Tool Discovery** - Auto-discovers from gateway or uses allowlist
25-
[x] **Dual Endpoint Exposure** - OpenAI + A2A JSON-RPC endpoints
26-
[x] **Parameterised Tool Allow-List** - `TOOLS=` environment variable
24+
[x] **Dynamic Tool Discovery** - Auto-discovers from gateway or uses allowlist
25+
[x] **Dual Endpoint Exposure** - OpenAI + A2A JSON-RPC endpoints
26+
[x] **Parameterised Tool Allow-List** - `TOOLS=` environment variable
2727
[x] **Tool Schema Introspection** - JSON schema parsing and validation
2828

2929
Structure:
@@ -77,7 +77,7 @@ Basic Health Checks
7777
# Health check
7878
curl http://localhost:8000/health
7979

80-
# Readiness check
80+
# Readiness check
8181
curl http://localhost:8000/ready
8282

8383
# List available tools
@@ -134,7 +134,7 @@ curl -X POST http://localhost:8000/a2a \
134134
curl -X POST http://localhost:8000/a2a \
135135
-H "Content-Type: application/json" \
136136
-d '{
137-
"jsonrpc": "2.0",
137+
"jsonrpc": "2.0",
138138
"id": "1",
139139
"method": "invoke",
140140
"params": {
@@ -162,4 +162,4 @@ Expected Success Response:
162162
}
163163
}
164164
```
165-
![alt text](image.png)
165+
![alt text](image.png)

agent_runtimes/langchain_agent/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
"""
23
MCP Langchain Agent Package
34
@@ -9,4 +10,4 @@
910
from .mcp_client import MCPClient
1011
from .config import get_settings
1112

12-
__all__ = []
13+
__all__ = []

agent_runtimes/langchain_agent/agent_langchain.py

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
import asyncio
23
import json
34
import logging
@@ -18,15 +19,15 @@
1819

1920
class MCPTool(BaseTool):
2021
"""Langchain tool wrapper for MCP tools"""
21-
22+
2223
name: str = Field(..., description="Tool name")
2324
description: str = Field(..., description="Tool description")
2425
mcp_client: MCPClient = Field(..., description="MCP client instance")
2526
tool_id: str = Field(..., description="MCP tool ID")
26-
27+
2728
class Config:
2829
arbitrary_types_allowed = True
29-
30+
3031
def _run(self, **kwargs) -> str:
3132
"""Synchronous tool execution"""
3233
try:
@@ -35,7 +36,7 @@ def _run(self, **kwargs) -> str:
3536
except Exception as e:
3637
logger.error(f"Tool {self.tool_id} execution failed: {e}")
3738
return f"Error executing tool: {str(e)}"
38-
39+
3940
async def _arun(self, **kwargs) -> str:
4041
"""Asynchronous tool execution"""
4142
# Run in thread pool since MCP client might not be async
@@ -44,27 +45,27 @@ async def _arun(self, **kwargs) -> str:
4445

4546
class LangchainMCPAgent:
4647
"""Langchain agent that integrates with MCP Gateway"""
47-
48+
4849
def __init__(self, config: AgentConfig):
4950
self.config = config
5051
self.mcp_client = MCPClient.from_env(config.mcp_gateway_url)
5152
self.mcp_client.debug = config.debug_mode
52-
53+
5354
self.llm = ChatOpenAI(
5455
model=config.default_model,
5556
temperature=config.temperature,
5657
streaming=config.streaming_enabled
5758
)
58-
59+
5960
self.tools: List[MCPTool] = []
6061
self.agent_executor: Optional[AgentExecutor] = None
6162
self._initialized = False
62-
63+
6364
@classmethod
6465
def from_config(cls, config: AgentConfig) -> "LangchainMCPAgent":
6566
"""Create agent from configuration"""
6667
return cls(config)
67-
68+
6869
async def initialize(self):
6970
"""Initialize the agent and load tools"""
7071
try:
@@ -77,24 +78,24 @@ async def initialize(self):
7778
# Auto-discover from gateway
7879
logger.info("Auto-discovering tools from MCP Gateway")
7980
await self._load_mcp_tools()
80-
81+
8182
# Create the agent
8283
await self._create_agent()
83-
84+
8485
self._initialized = True
8586
logger.info(f"Agent initialized with {len(self.tools)} tools")
86-
87+
8788
except Exception as e:
8889
logger.error(f"Failed to initialize agent: {e}")
8990
raise
90-
91+
9192
async def _load_allowlisted_tools(self):
9293
"""Load only tools specified in the allowlist (no autodiscovery)"""
9394
try:
9495
# Clean the allowlist
9596
allowlist = [tool.strip() for tool in self.config.tools_allowlist if tool.strip()]
9697
logger.info(f"Loading allowlisted tools: {allowlist}")
97-
98+
9899
self.tools = []
99100
for tool_id in allowlist:
100101
# Create a basic tool definition for allowlisted tools
@@ -107,27 +108,27 @@ async def _load_allowlisted_tools(self):
107108
)
108109
self.tools.append(mcp_tool)
109110
logger.info(f"Added allowlisted tool: {tool_id}")
110-
111+
111112
except Exception as e:
112113
logger.error(f"Failed to load allowlisted tools: {e}")
113114
raise
114-
115+
115116
async def _load_mcp_tools(self):
116117
"""Load tools from MCP Gateway"""
117118
try:
118119
# Add debug info about the connection
119120
logger.info(f"Connecting to MCP Gateway at: {self.mcp_client.base_url}")
120121
logger.info(f"Using token: {'Yes' if self.mcp_client.token else 'No'}")
121-
122+
122123
tool_defs = self.mcp_client.list_tools()
123124
logger.info(f"Found {len(tool_defs)} tools from MCP Gateway")
124-
125+
125126
if len(tool_defs) == 0:
126127
logger.warning("No tools found from MCP Gateway. Check if:")
127128
logger.warning(" 1. Gateway is running on the expected URL")
128129
logger.warning(" 2. Authentication token is valid")
129130
logger.warning(" 3. Gateway has tools configured")
130-
131+
131132
self.tools = []
132133
for tool_def in tool_defs:
133134
mcp_tool = MCPTool(
@@ -138,17 +139,17 @@ async def _load_mcp_tools(self):
138139
)
139140
self.tools.append(mcp_tool)
140141
logger.info(f"Loaded tool: {tool_def.id} ({tool_def.name})")
141-
142+
142143
except Exception as e:
143144
logger.error(f"Failed to load MCP tools: {e}")
144145
raise
145-
146+
146147
async def _create_agent(self):
147148
"""Create the Langchain agent executor"""
148149
try:
149150
# Define the system prompt
150151
system_prompt = """You are a helpful AI assistant with access to various tools through the MCP (Model Context Protocol) Gateway.
151-
152+
152153
Use the available tools to help answer questions and complete tasks. When using tools:
153154
1. Read tool descriptions carefully to understand their purpose
154155
2. Provide the correct arguments as specified in the tool schema
@@ -158,22 +159,22 @@ async def _create_agent(self):
158159
Available tools: {tool_names}
159160
160161
Always strive to be helpful, accurate, and honest in your responses."""
161-
162+
162163
# Create prompt template
163164
prompt = ChatPromptTemplate.from_messages([
164165
("system", system_prompt),
165166
MessagesPlaceholder(variable_name="chat_history"),
166167
("human", "{input}"),
167168
MessagesPlaceholder(variable_name="agent_scratchpad"),
168169
])
169-
170+
170171
# Create the agent
171172
agent = create_openai_functions_agent(
172173
llm=self.llm,
173174
tools=self.tools,
174175
prompt=prompt
175176
)
176-
177+
177178
# Create agent executor
178179
self.agent_executor = AgentExecutor(
179180
agent=agent,
@@ -182,29 +183,29 @@ async def _create_agent(self):
182183
verbose=self.config.debug_mode,
183184
return_intermediate_steps=True
184185
)
185-
186+
186187
logger.info("Langchain agent created successfully")
187-
188+
188189
except Exception as e:
189190
logger.error(f"Failed to create agent: {e}")
190191
raise
191-
192+
192193
def is_initialized(self) -> bool:
193194
"""Check if agent is initialized"""
194195
return self._initialized
195-
196+
196197
async def check_readiness(self) -> bool:
197198
"""Check if agent is ready to handle requests"""
198199
try:
199200
return (
200-
self._initialized and
201-
self.agent_executor is not None and
201+
self._initialized and
202+
self.agent_executor is not None and
202203
len(self.tools) >= 0 and # Allow 0 tools for testing
203204
await self.test_gateway_connection()
204205
)
205206
except Exception:
206207
return False
207-
208+
208209
async def test_gateway_connection(self) -> bool:
209210
"""Test connection to MCP Gateway"""
210211
try:
@@ -214,17 +215,17 @@ async def test_gateway_connection(self) -> bool:
214215
except Exception as e:
215216
logger.error(f"Gateway connection test failed: {e}")
216217
return False
217-
218+
218219
def get_available_tools(self) -> List[ToolDef]:
219220
"""Get list of available tools"""
220221
try:
221222
return self.mcp_client.list_tools()
222223
except Exception:
223224
return []
224-
225+
225226
async def run_async(
226-
self,
227-
messages: List[Dict[str, str]],
227+
self,
228+
messages: List[Dict[str, str]],
228229
model: Optional[str] = None,
229230
max_tokens: Optional[int] = None,
230231
temperature: Optional[float] = None,
@@ -233,15 +234,15 @@ async def run_async(
233234
"""Run the agent asynchronously"""
234235
if not self._initialized:
235236
raise RuntimeError("Agent not initialized. Call initialize() first.")
236-
237+
237238
try:
238239
# Convert messages to input format
239240
if messages:
240241
latest_message = messages[-1]
241242
input_text = latest_message.get("content", "")
242243
else:
243244
input_text = ""
244-
245+
245246
# Prepare chat history (all messages except the last one)
246247
chat_history = []
247248
for msg in messages[:-1]:
@@ -251,20 +252,20 @@ async def run_async(
251252
chat_history.append(AIMessage(content=msg["content"]))
252253
elif msg["role"] == "system":
253254
chat_history.append(SystemMessage(content=msg["content"]))
254-
255+
255256
# Run the agent
256257
result = await self.agent_executor.ainvoke({
257258
"input": input_text,
258259
"chat_history": chat_history,
259260
"tool_names": [tool.name for tool in self.tools]
260261
})
261-
262+
262263
return result["output"]
263-
264+
264265
except Exception as e:
265266
logger.error(f"Agent execution failed: {e}")
266267
return f"I encountered an error while processing your request: {str(e)}"
267-
268+
268269
async def stream_async(
269270
self,
270271
messages: List[Dict[str, str]],

0 commit comments

Comments
 (0)