daita-agents 0.2.0__py3-none-any.whl
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.
- daita/__init__.py +216 -0
- daita/agents/__init__.py +33 -0
- daita/agents/base.py +743 -0
- daita/agents/substrate.py +1141 -0
- daita/cli/__init__.py +145 -0
- daita/cli/__main__.py +7 -0
- daita/cli/ascii_art.py +44 -0
- daita/cli/core/__init__.py +0 -0
- daita/cli/core/create.py +254 -0
- daita/cli/core/deploy.py +473 -0
- daita/cli/core/deployments.py +309 -0
- daita/cli/core/import_detector.py +219 -0
- daita/cli/core/init.py +481 -0
- daita/cli/core/logs.py +239 -0
- daita/cli/core/managed_deploy.py +709 -0
- daita/cli/core/run.py +648 -0
- daita/cli/core/status.py +421 -0
- daita/cli/core/test.py +239 -0
- daita/cli/core/webhooks.py +172 -0
- daita/cli/main.py +588 -0
- daita/cli/utils.py +541 -0
- daita/config/__init__.py +62 -0
- daita/config/base.py +159 -0
- daita/config/settings.py +184 -0
- daita/core/__init__.py +262 -0
- daita/core/decision_tracing.py +701 -0
- daita/core/exceptions.py +480 -0
- daita/core/focus.py +251 -0
- daita/core/interfaces.py +76 -0
- daita/core/plugin_tracing.py +550 -0
- daita/core/relay.py +779 -0
- daita/core/reliability.py +381 -0
- daita/core/scaling.py +459 -0
- daita/core/tools.py +554 -0
- daita/core/tracing.py +770 -0
- daita/core/workflow.py +1144 -0
- daita/display/__init__.py +1 -0
- daita/display/console.py +160 -0
- daita/execution/__init__.py +58 -0
- daita/execution/client.py +856 -0
- daita/execution/exceptions.py +92 -0
- daita/execution/models.py +317 -0
- daita/llm/__init__.py +60 -0
- daita/llm/anthropic.py +291 -0
- daita/llm/base.py +530 -0
- daita/llm/factory.py +101 -0
- daita/llm/gemini.py +355 -0
- daita/llm/grok.py +219 -0
- daita/llm/mock.py +172 -0
- daita/llm/openai.py +220 -0
- daita/plugins/__init__.py +141 -0
- daita/plugins/base.py +37 -0
- daita/plugins/base_db.py +167 -0
- daita/plugins/elasticsearch.py +849 -0
- daita/plugins/mcp.py +481 -0
- daita/plugins/mongodb.py +520 -0
- daita/plugins/mysql.py +362 -0
- daita/plugins/postgresql.py +342 -0
- daita/plugins/redis_messaging.py +500 -0
- daita/plugins/rest.py +537 -0
- daita/plugins/s3.py +770 -0
- daita/plugins/slack.py +729 -0
- daita/utils/__init__.py +18 -0
- daita_agents-0.2.0.dist-info/METADATA +409 -0
- daita_agents-0.2.0.dist-info/RECORD +69 -0
- daita_agents-0.2.0.dist-info/WHEEL +5 -0
- daita_agents-0.2.0.dist-info/entry_points.txt +2 -0
- daita_agents-0.2.0.dist-info/licenses/LICENSE +56 -0
- daita_agents-0.2.0.dist-info/top_level.txt +1 -0
daita/plugins/mcp.py
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MCP (Model Context Protocol) plugin for Daita Agents.
|
|
3
|
+
|
|
4
|
+
This plugin enables agents to connect to any MCP server and autonomously use
|
|
5
|
+
their tools via LLM function calling. Agents discover available tools and
|
|
6
|
+
decide which ones to use based on the task.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
```python
|
|
10
|
+
from daita import SubstrateAgent
|
|
11
|
+
from daita.plugins import mcp
|
|
12
|
+
|
|
13
|
+
# Agent with MCP tools
|
|
14
|
+
agent = SubstrateAgent(
|
|
15
|
+
name="file_analyzer",
|
|
16
|
+
mcp_servers=[
|
|
17
|
+
mcp.server(command="uvx", args=["mcp-server-filesystem", "/data"])
|
|
18
|
+
]
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Agent autonomously discovers and uses MCP tools
|
|
22
|
+
result = await agent.process("Read report.csv and calculate average revenue")
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
MCP Protocol:
|
|
26
|
+
The Model Context Protocol (MCP) is Anthropic's open standard for connecting
|
|
27
|
+
AI systems to external data sources and tools. This plugin provides native
|
|
28
|
+
MCP client support for Daita agents.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
import asyncio
|
|
32
|
+
import logging
|
|
33
|
+
import json
|
|
34
|
+
from typing import Any, Dict, List, Optional, Callable
|
|
35
|
+
from dataclasses import dataclass
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class MCPTool:
|
|
42
|
+
"""Represents a tool exposed by an MCP server"""
|
|
43
|
+
|
|
44
|
+
name: str
|
|
45
|
+
description: str
|
|
46
|
+
input_schema: Dict[str, Any]
|
|
47
|
+
|
|
48
|
+
def to_llm_function(self) -> Dict[str, Any]:
|
|
49
|
+
"""
|
|
50
|
+
Convert MCP tool schema to LLM function calling format.
|
|
51
|
+
|
|
52
|
+
Returns OpenAI/Anthropic compatible function definition.
|
|
53
|
+
"""
|
|
54
|
+
return {
|
|
55
|
+
"name": self.name,
|
|
56
|
+
"description": self.description,
|
|
57
|
+
"parameters": self.input_schema
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class MCPServer:
|
|
62
|
+
"""
|
|
63
|
+
MCP Server connection manager.
|
|
64
|
+
|
|
65
|
+
Manages connection to a single MCP server via stdio transport,
|
|
66
|
+
discovers available tools, and executes tool calls.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def __init__(
|
|
70
|
+
self,
|
|
71
|
+
command: str,
|
|
72
|
+
args: Optional[List[str]] = None,
|
|
73
|
+
env: Optional[Dict[str, str]] = None,
|
|
74
|
+
server_name: Optional[str] = None
|
|
75
|
+
):
|
|
76
|
+
"""
|
|
77
|
+
Initialize MCP server configuration.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
command: Command to run MCP server (e.g., "uvx", "python", "npx")
|
|
81
|
+
args: Arguments for the command (e.g., ["mcp-server-filesystem", "/data"])
|
|
82
|
+
env: Environment variables for the server process
|
|
83
|
+
server_name: Optional name for this server (for logging/debugging)
|
|
84
|
+
"""
|
|
85
|
+
self.command = command
|
|
86
|
+
self.args = args or []
|
|
87
|
+
self.env = env or {}
|
|
88
|
+
self.server_name = server_name or f"mcp_{command}"
|
|
89
|
+
|
|
90
|
+
# Connection state
|
|
91
|
+
self._session = None
|
|
92
|
+
self._read = None
|
|
93
|
+
self._write = None
|
|
94
|
+
self._tools: List[MCPTool] = []
|
|
95
|
+
self._connected = False
|
|
96
|
+
self._stdio_context_task = None # Background task keeping context alive
|
|
97
|
+
self._session_lock = asyncio.Lock() # Protects session access from concurrent calls
|
|
98
|
+
|
|
99
|
+
async def _maintain_connection(self, server_params):
|
|
100
|
+
"""
|
|
101
|
+
Background task that maintains the stdio connection context.
|
|
102
|
+
|
|
103
|
+
This keeps the MCP SDK's anyio task group alive for the duration
|
|
104
|
+
of the connection. We use an event to signal when to disconnect.
|
|
105
|
+
"""
|
|
106
|
+
from mcp import ClientSession
|
|
107
|
+
from mcp.client.stdio import stdio_client
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
async with stdio_client(server_params) as (read_stream, write_stream):
|
|
111
|
+
# Create session as context manager (required by MCP SDK)
|
|
112
|
+
async with ClientSession(read_stream, write_stream) as session:
|
|
113
|
+
self._session = session
|
|
114
|
+
|
|
115
|
+
# Initialize session
|
|
116
|
+
await session.initialize()
|
|
117
|
+
|
|
118
|
+
# Discover tools
|
|
119
|
+
await self._discover_tools()
|
|
120
|
+
|
|
121
|
+
# Mark as connected
|
|
122
|
+
self._connected = True
|
|
123
|
+
logger.info(f"Connected to MCP server {self.server_name}: {len(self._tools)} tools available")
|
|
124
|
+
|
|
125
|
+
# Keep connection alive until disconnect is called
|
|
126
|
+
while self._connected:
|
|
127
|
+
await asyncio.sleep(0.1)
|
|
128
|
+
|
|
129
|
+
except Exception as e:
|
|
130
|
+
self._connected = False
|
|
131
|
+
logger.error(f"MCP connection error for {self.server_name}: {str(e)}")
|
|
132
|
+
raise
|
|
133
|
+
finally:
|
|
134
|
+
# Cleanup
|
|
135
|
+
self._session = None
|
|
136
|
+
self._read = None
|
|
137
|
+
self._write = None
|
|
138
|
+
|
|
139
|
+
async def connect(self) -> None:
|
|
140
|
+
"""
|
|
141
|
+
Connect to the MCP server and discover available tools.
|
|
142
|
+
|
|
143
|
+
Raises:
|
|
144
|
+
ImportError: If MCP SDK is not installed
|
|
145
|
+
ConnectionError: If connection to server fails
|
|
146
|
+
"""
|
|
147
|
+
if self._connected:
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
# Import MCP SDK
|
|
152
|
+
from mcp import StdioServerParameters
|
|
153
|
+
|
|
154
|
+
# Create server parameters
|
|
155
|
+
server_params = StdioServerParameters(
|
|
156
|
+
command=self.command,
|
|
157
|
+
args=self.args,
|
|
158
|
+
env=self.env if self.env else None
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
logger.info(f"Connecting to MCP server: {self.server_name}")
|
|
162
|
+
|
|
163
|
+
# Start background task that maintains the connection
|
|
164
|
+
self._stdio_context_task = asyncio.create_task(
|
|
165
|
+
self._maintain_connection(server_params)
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
# Wait for connection to be established
|
|
169
|
+
max_wait = 5.0 # seconds
|
|
170
|
+
start_time = asyncio.get_event_loop().time()
|
|
171
|
+
while not self._connected:
|
|
172
|
+
if asyncio.get_event_loop().time() - start_time > max_wait:
|
|
173
|
+
raise ConnectionError(f"Connection timeout after {max_wait}s")
|
|
174
|
+
if self._stdio_context_task.done():
|
|
175
|
+
# Task failed
|
|
176
|
+
try:
|
|
177
|
+
self._stdio_context_task.result()
|
|
178
|
+
except Exception as e:
|
|
179
|
+
raise ConnectionError(f"Connection task failed: {str(e)}")
|
|
180
|
+
await asyncio.sleep(0.05)
|
|
181
|
+
|
|
182
|
+
except ImportError as e:
|
|
183
|
+
error_msg = (
|
|
184
|
+
"MCP SDK not installed. Install with: pip install mcp\n"
|
|
185
|
+
"Official SDK: https://github.com/modelcontextprotocol/python-sdk"
|
|
186
|
+
)
|
|
187
|
+
logger.error(error_msg)
|
|
188
|
+
raise ImportError(error_msg) from e
|
|
189
|
+
|
|
190
|
+
except Exception as e:
|
|
191
|
+
error_msg = f"Failed to connect to MCP server {self.server_name}: {str(e)}"
|
|
192
|
+
logger.error(error_msg)
|
|
193
|
+
raise ConnectionError(error_msg) from e
|
|
194
|
+
|
|
195
|
+
async def _discover_tools(self) -> None:
|
|
196
|
+
"""Discover available tools from the MCP server"""
|
|
197
|
+
try:
|
|
198
|
+
# List available tools from server
|
|
199
|
+
tools_response = await self._session.list_tools()
|
|
200
|
+
|
|
201
|
+
# Convert to MCPTool objects
|
|
202
|
+
self._tools = []
|
|
203
|
+
for tool in tools_response.tools:
|
|
204
|
+
mcp_tool = MCPTool(
|
|
205
|
+
name=tool.name,
|
|
206
|
+
description=tool.description or f"Tool: {tool.name}",
|
|
207
|
+
input_schema=tool.inputSchema if hasattr(tool, 'inputSchema') else {}
|
|
208
|
+
)
|
|
209
|
+
self._tools.append(mcp_tool)
|
|
210
|
+
pass
|
|
211
|
+
|
|
212
|
+
logger.info(f"Discovered {len(self._tools)} tools from {self.server_name}")
|
|
213
|
+
|
|
214
|
+
except Exception as e:
|
|
215
|
+
logger.error(f"Failed to discover tools from {self.server_name}: {str(e)}")
|
|
216
|
+
raise
|
|
217
|
+
|
|
218
|
+
async def disconnect(self) -> None:
|
|
219
|
+
"""Disconnect from the MCP server and clean up resources"""
|
|
220
|
+
# Thread-safe disconnect
|
|
221
|
+
async with self._session_lock:
|
|
222
|
+
if not self._connected:
|
|
223
|
+
return
|
|
224
|
+
|
|
225
|
+
try:
|
|
226
|
+
# Signal the connection task to stop
|
|
227
|
+
self._connected = False
|
|
228
|
+
|
|
229
|
+
# Wait for background task to finish (with timeout)
|
|
230
|
+
if self._stdio_context_task and not self._stdio_context_task.done():
|
|
231
|
+
try:
|
|
232
|
+
await asyncio.wait_for(self._stdio_context_task, timeout=2.0)
|
|
233
|
+
except asyncio.TimeoutError:
|
|
234
|
+
logger.warning(f"MCP disconnect timeout for {self.server_name}, cancelling task")
|
|
235
|
+
self._stdio_context_task.cancel()
|
|
236
|
+
try:
|
|
237
|
+
await self._stdio_context_task
|
|
238
|
+
except asyncio.CancelledError:
|
|
239
|
+
pass
|
|
240
|
+
|
|
241
|
+
self._stdio_context_task = None
|
|
242
|
+
logger.info(f"Disconnected from MCP server: {self.server_name}")
|
|
243
|
+
|
|
244
|
+
except Exception as e:
|
|
245
|
+
logger.warning(f"Error during MCP server disconnect: {str(e)}")
|
|
246
|
+
|
|
247
|
+
def list_tools(self) -> List[MCPTool]:
|
|
248
|
+
"""
|
|
249
|
+
Get list of available tools from this MCP server.
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
List of MCPTool objects
|
|
253
|
+
|
|
254
|
+
Raises:
|
|
255
|
+
RuntimeError: If not connected to server
|
|
256
|
+
"""
|
|
257
|
+
if not self._connected:
|
|
258
|
+
raise RuntimeError(f"MCP server {self.server_name} not connected. Call connect() first.")
|
|
259
|
+
|
|
260
|
+
return self._tools.copy()
|
|
261
|
+
|
|
262
|
+
async def call_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Any:
|
|
263
|
+
"""
|
|
264
|
+
Execute a tool on the MCP server with thread-safe session access.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
tool_name: Name of the tool to call
|
|
268
|
+
arguments: Arguments to pass to the tool
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
Tool execution result
|
|
272
|
+
|
|
273
|
+
Raises:
|
|
274
|
+
RuntimeError: If not connected or tool not found
|
|
275
|
+
Exception: If tool execution fails
|
|
276
|
+
"""
|
|
277
|
+
# Thread-safe session access
|
|
278
|
+
async with self._session_lock:
|
|
279
|
+
if not self._connected:
|
|
280
|
+
raise RuntimeError(f"MCP server {self.server_name} not connected")
|
|
281
|
+
|
|
282
|
+
# Verify tool exists
|
|
283
|
+
tool = next((t for t in self._tools if t.name == tool_name), None)
|
|
284
|
+
if not tool:
|
|
285
|
+
available_tools = [t.name for t in self._tools]
|
|
286
|
+
raise RuntimeError(
|
|
287
|
+
f"Tool '{tool_name}' not found on server {self.server_name}. "
|
|
288
|
+
f"Available tools: {', '.join(available_tools)}"
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
try:
|
|
292
|
+
# Call the tool via MCP session (protected by lock)
|
|
293
|
+
result = await self._session.call_tool(tool_name, arguments=arguments)
|
|
294
|
+
|
|
295
|
+
# Extract content from result
|
|
296
|
+
if hasattr(result, 'content'):
|
|
297
|
+
# MCP returns content as a list of content items
|
|
298
|
+
if isinstance(result.content, list) and len(result.content) > 0:
|
|
299
|
+
first_content = result.content[0]
|
|
300
|
+
# Text content
|
|
301
|
+
if hasattr(first_content, 'text'):
|
|
302
|
+
return first_content.text
|
|
303
|
+
# Other content types
|
|
304
|
+
return str(first_content)
|
|
305
|
+
return result.content
|
|
306
|
+
|
|
307
|
+
return result
|
|
308
|
+
|
|
309
|
+
except Exception as e:
|
|
310
|
+
error_msg = f"MCP tool call failed: {tool_name} on {self.server_name}: {str(e)}"
|
|
311
|
+
logger.error(error_msg)
|
|
312
|
+
raise Exception(error_msg) from e
|
|
313
|
+
|
|
314
|
+
@property
|
|
315
|
+
def is_connected(self) -> bool:
|
|
316
|
+
"""Check if server is connected"""
|
|
317
|
+
return self._connected
|
|
318
|
+
|
|
319
|
+
@property
|
|
320
|
+
def tool_names(self) -> List[str]:
|
|
321
|
+
"""Get list of tool names"""
|
|
322
|
+
return [t.name for t in self._tools]
|
|
323
|
+
|
|
324
|
+
def __repr__(self) -> str:
|
|
325
|
+
status = "connected" if self._connected else "disconnected"
|
|
326
|
+
tool_count = len(self._tools) if self._tools else 0
|
|
327
|
+
return f"MCPServer({self.server_name}, {status}, {tool_count} tools)"
|
|
328
|
+
|
|
329
|
+
async def __aenter__(self):
|
|
330
|
+
"""Async context manager entry - automatically connect"""
|
|
331
|
+
await self.connect()
|
|
332
|
+
return self
|
|
333
|
+
|
|
334
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
335
|
+
"""Async context manager exit - automatically disconnect"""
|
|
336
|
+
await self.disconnect()
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
class MCPToolRegistry:
|
|
340
|
+
"""
|
|
341
|
+
Registry for managing multiple MCP servers and their tools.
|
|
342
|
+
|
|
343
|
+
Used internally by SubstrateAgent to aggregate tools from multiple
|
|
344
|
+
MCP servers and route tool calls to the appropriate server.
|
|
345
|
+
"""
|
|
346
|
+
|
|
347
|
+
def __init__(self):
|
|
348
|
+
"""Initialize empty registry"""
|
|
349
|
+
self.servers: List[MCPServer] = []
|
|
350
|
+
self._tool_server_map: Dict[str, MCPServer] = {}
|
|
351
|
+
|
|
352
|
+
async def add_server(self, server: MCPServer) -> None:
|
|
353
|
+
"""
|
|
354
|
+
Add an MCP server to the registry.
|
|
355
|
+
|
|
356
|
+
Args:
|
|
357
|
+
server: MCPServer instance to add
|
|
358
|
+
"""
|
|
359
|
+
# Connect if not already connected
|
|
360
|
+
if not server.is_connected:
|
|
361
|
+
await server.connect()
|
|
362
|
+
|
|
363
|
+
# Add to registry
|
|
364
|
+
self.servers.append(server)
|
|
365
|
+
|
|
366
|
+
# Map tools to servers
|
|
367
|
+
for tool in server.list_tools():
|
|
368
|
+
if tool.name in self._tool_server_map:
|
|
369
|
+
logger.warning(
|
|
370
|
+
f"Tool name collision: {tool.name} exists in multiple servers. "
|
|
371
|
+
f"Using tool from {server.server_name}"
|
|
372
|
+
)
|
|
373
|
+
self._tool_server_map[tool.name] = server
|
|
374
|
+
|
|
375
|
+
logger.info(f"Added MCP server {server.server_name} to registry")
|
|
376
|
+
|
|
377
|
+
def get_all_tools(self) -> List[MCPTool]:
|
|
378
|
+
"""Get aggregated list of all tools from all servers"""
|
|
379
|
+
all_tools = []
|
|
380
|
+
for server in self.servers:
|
|
381
|
+
all_tools.extend(server.list_tools())
|
|
382
|
+
return all_tools
|
|
383
|
+
|
|
384
|
+
async def call_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Any:
|
|
385
|
+
"""
|
|
386
|
+
Call a tool by routing to the appropriate server.
|
|
387
|
+
|
|
388
|
+
Args:
|
|
389
|
+
tool_name: Name of the tool to call
|
|
390
|
+
arguments: Arguments for the tool
|
|
391
|
+
|
|
392
|
+
Returns:
|
|
393
|
+
Tool execution result
|
|
394
|
+
"""
|
|
395
|
+
server = self._tool_server_map.get(tool_name)
|
|
396
|
+
if not server:
|
|
397
|
+
available_tools = list(self._tool_server_map.keys())
|
|
398
|
+
raise RuntimeError(
|
|
399
|
+
f"Tool '{tool_name}' not found in any MCP server. "
|
|
400
|
+
f"Available tools: {', '.join(available_tools)}"
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
return await server.call_tool(tool_name, arguments)
|
|
404
|
+
|
|
405
|
+
async def disconnect_all(self) -> None:
|
|
406
|
+
"""Disconnect from all MCP servers"""
|
|
407
|
+
for server in self.servers:
|
|
408
|
+
try:
|
|
409
|
+
await server.disconnect()
|
|
410
|
+
except Exception as e:
|
|
411
|
+
logger.warning(f"Error disconnecting from {server.server_name}: {str(e)}")
|
|
412
|
+
|
|
413
|
+
self.servers.clear()
|
|
414
|
+
self._tool_server_map.clear()
|
|
415
|
+
|
|
416
|
+
@property
|
|
417
|
+
def tool_count(self) -> int:
|
|
418
|
+
"""Total number of tools across all servers"""
|
|
419
|
+
return len(self._tool_server_map)
|
|
420
|
+
|
|
421
|
+
@property
|
|
422
|
+
def server_count(self) -> int:
|
|
423
|
+
"""Number of connected servers"""
|
|
424
|
+
return len(self.servers)
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
# Factory function for clean server configuration
|
|
428
|
+
def server(
|
|
429
|
+
command: str,
|
|
430
|
+
args: Optional[List[str]] = None,
|
|
431
|
+
env: Optional[Dict[str, str]] = None,
|
|
432
|
+
name: Optional[str] = None
|
|
433
|
+
) -> Dict[str, Any]:
|
|
434
|
+
"""
|
|
435
|
+
Create MCP server configuration.
|
|
436
|
+
|
|
437
|
+
This factory function provides a clean API for configuring MCP servers
|
|
438
|
+
to be used with SubstrateAgent.
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
command: Command to run MCP server (e.g., "uvx", "python", "npx")
|
|
442
|
+
args: Arguments for the command
|
|
443
|
+
env: Environment variables for the server process
|
|
444
|
+
name: Optional name for the server
|
|
445
|
+
|
|
446
|
+
Returns:
|
|
447
|
+
Server configuration dict
|
|
448
|
+
|
|
449
|
+
Example:
|
|
450
|
+
```python
|
|
451
|
+
from daita.plugins import mcp
|
|
452
|
+
|
|
453
|
+
# Filesystem server
|
|
454
|
+
fs_server = mcp.server(
|
|
455
|
+
command="uvx",
|
|
456
|
+
args=["mcp-server-filesystem", "/data"]
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
# GitHub server with environment
|
|
460
|
+
gh_server = mcp.server(
|
|
461
|
+
command="npx",
|
|
462
|
+
args=["-y", "@modelcontextprotocol/server-github"],
|
|
463
|
+
env={"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN")}
|
|
464
|
+
)
|
|
465
|
+
```
|
|
466
|
+
"""
|
|
467
|
+
return {
|
|
468
|
+
"command": command,
|
|
469
|
+
"args": args or [],
|
|
470
|
+
"env": env or {},
|
|
471
|
+
"name": name
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
# Export public API
|
|
476
|
+
__all__ = [
|
|
477
|
+
"MCPServer",
|
|
478
|
+
"MCPTool",
|
|
479
|
+
"MCPToolRegistry",
|
|
480
|
+
"server"
|
|
481
|
+
]
|