kailash 0.1.1__py3-none-any.whl → 0.1.3__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.
- kailash/api/__init__.py +7 -0
- kailash/api/workflow_api.py +383 -0
- kailash/nodes/__init__.py +2 -1
- kailash/nodes/ai/__init__.py +26 -0
- kailash/nodes/ai/ai_providers.py +1272 -0
- kailash/nodes/ai/embedding_generator.py +853 -0
- kailash/nodes/ai/llm_agent.py +1166 -0
- kailash/nodes/api/auth.py +3 -3
- kailash/nodes/api/graphql.py +2 -2
- kailash/nodes/api/http.py +391 -48
- kailash/nodes/api/rate_limiting.py +2 -2
- kailash/nodes/api/rest.py +465 -57
- kailash/nodes/base.py +71 -12
- kailash/nodes/code/python.py +2 -1
- kailash/nodes/data/__init__.py +7 -0
- kailash/nodes/data/readers.py +28 -26
- kailash/nodes/data/retrieval.py +178 -0
- kailash/nodes/data/sharepoint_graph.py +7 -7
- kailash/nodes/data/sources.py +65 -0
- kailash/nodes/data/sql.py +7 -5
- kailash/nodes/data/vector_db.py +2 -2
- kailash/nodes/data/writers.py +6 -3
- kailash/nodes/logic/__init__.py +2 -1
- kailash/nodes/logic/operations.py +2 -1
- kailash/nodes/logic/workflow.py +439 -0
- kailash/nodes/mcp/__init__.py +11 -0
- kailash/nodes/mcp/client.py +558 -0
- kailash/nodes/mcp/resource.py +682 -0
- kailash/nodes/mcp/server.py +577 -0
- kailash/nodes/transform/__init__.py +16 -1
- kailash/nodes/transform/chunkers.py +78 -0
- kailash/nodes/transform/formatters.py +96 -0
- kailash/nodes/transform/processors.py +5 -3
- kailash/runtime/docker.py +8 -6
- kailash/sdk_exceptions.py +24 -10
- kailash/tracking/metrics_collector.py +2 -1
- kailash/tracking/models.py +0 -20
- kailash/tracking/storage/database.py +4 -4
- kailash/tracking/storage/filesystem.py +0 -1
- kailash/utils/templates.py +6 -6
- kailash/visualization/performance.py +7 -7
- kailash/visualization/reports.py +1 -1
- kailash/workflow/graph.py +4 -4
- kailash/workflow/mock_registry.py +1 -1
- {kailash-0.1.1.dist-info → kailash-0.1.3.dist-info}/METADATA +441 -47
- kailash-0.1.3.dist-info/RECORD +83 -0
- kailash-0.1.1.dist-info/RECORD +0 -69
- {kailash-0.1.1.dist-info → kailash-0.1.3.dist-info}/WHEEL +0 -0
- {kailash-0.1.1.dist-info → kailash-0.1.3.dist-info}/entry_points.txt +0 -0
- {kailash-0.1.1.dist-info → kailash-0.1.3.dist-info}/licenses/LICENSE +0 -0
- {kailash-0.1.1.dist-info → kailash-0.1.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,558 @@
|
|
1
|
+
"""MCP Client node for connecting to Model Context Protocol servers."""
|
2
|
+
|
3
|
+
import json
|
4
|
+
from typing import Any, Dict, List, Optional
|
5
|
+
|
6
|
+
from kailash.nodes.base import Node, NodeParameter, register_node
|
7
|
+
|
8
|
+
|
9
|
+
@register_node()
|
10
|
+
class MCPClient(Node):
|
11
|
+
"""
|
12
|
+
Client node for connecting to Model Context Protocol (MCP) servers.
|
13
|
+
|
14
|
+
Design Purpose and Philosophy:
|
15
|
+
The MCPClient node provides a standardized way to connect to MCP servers and access
|
16
|
+
their resources, tools, and prompts. It abstracts the complexity of the MCP protocol
|
17
|
+
while providing a simple interface for workflow integration.
|
18
|
+
|
19
|
+
Upstream Dependencies:
|
20
|
+
- Configuration data specifying server details
|
21
|
+
- Authentication credentials for secure connections
|
22
|
+
- Input parameters for resource requests and tool calls
|
23
|
+
|
24
|
+
Downstream Consumers:
|
25
|
+
- LLMAgent nodes that need context from MCP servers
|
26
|
+
- Workflow nodes that orchestrate multi-step MCP interactions
|
27
|
+
- Data processing nodes that consume MCP resources
|
28
|
+
|
29
|
+
Usage Patterns:
|
30
|
+
1. Connect to MCP servers using stdio, SSE, or HTTP transports
|
31
|
+
2. List available resources, tools, and prompts from servers
|
32
|
+
3. Fetch specific resources to provide context to AI models
|
33
|
+
4. Execute tools on MCP servers with proper error handling
|
34
|
+
5. Use prompts from servers for standardized interactions
|
35
|
+
|
36
|
+
Implementation Details:
|
37
|
+
- Uses the official MCP Python SDK for protocol compliance
|
38
|
+
- Supports all standard MCP transports (stdio, SSE, HTTP)
|
39
|
+
- Implements proper connection lifecycle management
|
40
|
+
- Provides caching for frequently accessed resources
|
41
|
+
- Handles authentication and rate limiting transparently
|
42
|
+
|
43
|
+
Error Handling:
|
44
|
+
- ConnectionError: When unable to connect to MCP server
|
45
|
+
- TimeoutError: When server operations exceed timeout limits
|
46
|
+
- AuthenticationError: When credentials are invalid or expired
|
47
|
+
- ProtocolError: When MCP protocol violations occur
|
48
|
+
- ResourceNotFoundError: When requested resources don't exist
|
49
|
+
|
50
|
+
Side Effects:
|
51
|
+
- Establishes network connections to external MCP servers
|
52
|
+
- May cache resource data locally for performance
|
53
|
+
- Logs connection events and errors for debugging
|
54
|
+
|
55
|
+
Examples:
|
56
|
+
|
57
|
+
Connect to an MCP server and list resources::
|
58
|
+
|
59
|
+
client = MCPClient()
|
60
|
+
result = client.run(
|
61
|
+
server_config={
|
62
|
+
"name": "filesystem-server",
|
63
|
+
"command": "python",
|
64
|
+
"args": ["-m", "mcp_filesystem"]
|
65
|
+
},
|
66
|
+
operation="list_resources"
|
67
|
+
)
|
68
|
+
|
69
|
+
Fetch a specific resource:
|
70
|
+
|
71
|
+
resource = client.run(
|
72
|
+
server_config=server_config,
|
73
|
+
operation="read_resource",
|
74
|
+
resource_uri="file:///path/to/document.txt"
|
75
|
+
)
|
76
|
+
|
77
|
+
Call a tool on the server:
|
78
|
+
|
79
|
+
tool_result = client.run(
|
80
|
+
server_config=server_config,
|
81
|
+
operation="call_tool",
|
82
|
+
tool_name="create_file",
|
83
|
+
tool_arguments={
|
84
|
+
"path": "/path/to/new_file.txt",
|
85
|
+
"content": "Hello, World!"
|
86
|
+
}
|
87
|
+
)
|
88
|
+
"""
|
89
|
+
|
90
|
+
def get_parameters(self) -> Dict[str, NodeParameter]:
|
91
|
+
return {
|
92
|
+
"server_config": NodeParameter(
|
93
|
+
name="server_config",
|
94
|
+
type=dict,
|
95
|
+
required=False,
|
96
|
+
default={},
|
97
|
+
description="MCP server configuration (name, command, args, transport)",
|
98
|
+
),
|
99
|
+
"operation": NodeParameter(
|
100
|
+
name="operation",
|
101
|
+
type=str,
|
102
|
+
required=False,
|
103
|
+
default="list_resources",
|
104
|
+
description="Operation to perform: list_resources, read_resource, list_tools, call_tool, list_prompts, get_prompt",
|
105
|
+
),
|
106
|
+
"resource_uri": NodeParameter(
|
107
|
+
name="resource_uri",
|
108
|
+
type=str,
|
109
|
+
required=False,
|
110
|
+
description="URI of the resource to read (for read_resource operation)",
|
111
|
+
),
|
112
|
+
"tool_name": NodeParameter(
|
113
|
+
name="tool_name",
|
114
|
+
type=str,
|
115
|
+
required=False,
|
116
|
+
description="Name of the tool to call (for call_tool operation)",
|
117
|
+
),
|
118
|
+
"tool_arguments": NodeParameter(
|
119
|
+
name="tool_arguments",
|
120
|
+
type=dict,
|
121
|
+
required=False,
|
122
|
+
default={},
|
123
|
+
description="Arguments to pass to the tool (for call_tool operation)",
|
124
|
+
),
|
125
|
+
"prompt_name": NodeParameter(
|
126
|
+
name="prompt_name",
|
127
|
+
type=str,
|
128
|
+
required=False,
|
129
|
+
description="Name of the prompt to get (for get_prompt operation)",
|
130
|
+
),
|
131
|
+
"prompt_arguments": NodeParameter(
|
132
|
+
name="prompt_arguments",
|
133
|
+
type=dict,
|
134
|
+
required=False,
|
135
|
+
default={},
|
136
|
+
description="Arguments to pass to the prompt (for get_prompt operation)",
|
137
|
+
),
|
138
|
+
"timeout": NodeParameter(
|
139
|
+
name="timeout",
|
140
|
+
type=int,
|
141
|
+
required=False,
|
142
|
+
default=30,
|
143
|
+
description="Timeout in seconds for MCP operations",
|
144
|
+
),
|
145
|
+
"max_retries": NodeParameter(
|
146
|
+
name="max_retries",
|
147
|
+
type=int,
|
148
|
+
required=False,
|
149
|
+
default=3,
|
150
|
+
description="Maximum number of retry attempts",
|
151
|
+
),
|
152
|
+
}
|
153
|
+
|
154
|
+
def run(self, **kwargs) -> Dict[str, Any]:
|
155
|
+
server_config = kwargs["server_config"]
|
156
|
+
operation = kwargs["operation"]
|
157
|
+
resource_uri = kwargs.get("resource_uri")
|
158
|
+
tool_name = kwargs.get("tool_name")
|
159
|
+
tool_arguments = kwargs.get("tool_arguments", {})
|
160
|
+
prompt_name = kwargs.get("prompt_name")
|
161
|
+
prompt_arguments = kwargs.get("prompt_arguments", {})
|
162
|
+
# timeout = kwargs.get("timeout", 30) # unused for now
|
163
|
+
# max_retries = kwargs.get("max_retries", 3) # unused for now
|
164
|
+
|
165
|
+
try:
|
166
|
+
# Import MCP SDK (graceful fallback if not installed)
|
167
|
+
try:
|
168
|
+
import mcp.client.session # noqa: F401
|
169
|
+
|
170
|
+
mcp_available = True
|
171
|
+
except ImportError:
|
172
|
+
mcp_available = False
|
173
|
+
|
174
|
+
if not mcp_available:
|
175
|
+
# Provide mock functionality when MCP SDK is not available
|
176
|
+
return self._mock_mcp_operation(
|
177
|
+
operation,
|
178
|
+
server_config,
|
179
|
+
resource_uri,
|
180
|
+
tool_name,
|
181
|
+
tool_arguments,
|
182
|
+
prompt_name,
|
183
|
+
prompt_arguments,
|
184
|
+
)
|
185
|
+
|
186
|
+
# Extract server configuration
|
187
|
+
server_name = server_config.get("name", "unknown-server")
|
188
|
+
transport_type = server_config.get("transport", "stdio")
|
189
|
+
|
190
|
+
if transport_type == "stdio":
|
191
|
+
command = server_config.get("command")
|
192
|
+
args = server_config.get("args", [])
|
193
|
+
|
194
|
+
if not command:
|
195
|
+
raise ValueError(
|
196
|
+
"stdio transport requires 'command' in server_config"
|
197
|
+
)
|
198
|
+
|
199
|
+
# For now, provide mock implementation as we need the actual MCP server running
|
200
|
+
return self._mock_stdio_operation(
|
201
|
+
operation,
|
202
|
+
server_name,
|
203
|
+
command,
|
204
|
+
args,
|
205
|
+
resource_uri,
|
206
|
+
tool_name,
|
207
|
+
tool_arguments,
|
208
|
+
prompt_name,
|
209
|
+
prompt_arguments,
|
210
|
+
)
|
211
|
+
|
212
|
+
elif transport_type in ["sse", "http"]:
|
213
|
+
# HTTP/SSE transport implementation
|
214
|
+
url = server_config.get("url")
|
215
|
+
headers = server_config.get("headers", {})
|
216
|
+
|
217
|
+
if not url:
|
218
|
+
raise ValueError(
|
219
|
+
f"{transport_type} transport requires 'url' in server_config"
|
220
|
+
)
|
221
|
+
|
222
|
+
return self._mock_http_operation(
|
223
|
+
operation,
|
224
|
+
server_name,
|
225
|
+
url,
|
226
|
+
headers,
|
227
|
+
resource_uri,
|
228
|
+
tool_name,
|
229
|
+
tool_arguments,
|
230
|
+
prompt_name,
|
231
|
+
prompt_arguments,
|
232
|
+
)
|
233
|
+
|
234
|
+
else:
|
235
|
+
raise ValueError(f"Unsupported transport type: {transport_type}")
|
236
|
+
|
237
|
+
except Exception as e:
|
238
|
+
return {
|
239
|
+
"success": False,
|
240
|
+
"error": str(e),
|
241
|
+
"error_type": type(e).__name__,
|
242
|
+
"operation": operation,
|
243
|
+
"server": server_config.get("name", "unknown"),
|
244
|
+
}
|
245
|
+
|
246
|
+
def _mock_mcp_operation(
|
247
|
+
self,
|
248
|
+
operation: str,
|
249
|
+
server_config: dict,
|
250
|
+
resource_uri: Optional[str],
|
251
|
+
tool_name: Optional[str],
|
252
|
+
tool_arguments: dict,
|
253
|
+
prompt_name: Optional[str],
|
254
|
+
prompt_arguments: dict,
|
255
|
+
) -> Dict[str, Any]:
|
256
|
+
"""Mock MCP operations when SDK is not available."""
|
257
|
+
server_name = server_config.get("name", "mock-server")
|
258
|
+
|
259
|
+
if operation == "list_resources":
|
260
|
+
return {
|
261
|
+
"success": True,
|
262
|
+
"operation": operation,
|
263
|
+
"server": server_name,
|
264
|
+
"resources": [
|
265
|
+
{
|
266
|
+
"uri": "file:///example/document.txt",
|
267
|
+
"name": "Example Document",
|
268
|
+
"description": "A sample text document",
|
269
|
+
"mimeType": "text/plain",
|
270
|
+
},
|
271
|
+
{
|
272
|
+
"uri": "data://config/settings.json",
|
273
|
+
"name": "Configuration Settings",
|
274
|
+
"description": "Application configuration",
|
275
|
+
"mimeType": "application/json",
|
276
|
+
},
|
277
|
+
],
|
278
|
+
"resource_count": 2,
|
279
|
+
"mock": True,
|
280
|
+
}
|
281
|
+
|
282
|
+
elif operation == "read_resource":
|
283
|
+
if not resource_uri:
|
284
|
+
return {
|
285
|
+
"success": False,
|
286
|
+
"error": "resource_uri is required for read_resource operation",
|
287
|
+
"operation": operation,
|
288
|
+
"server": server_name,
|
289
|
+
}
|
290
|
+
|
291
|
+
# Mock resource content based on URI
|
292
|
+
if "document.txt" in resource_uri:
|
293
|
+
content = "This is the content of the example document.\nIt contains sample text for testing MCP functionality."
|
294
|
+
elif "settings.json" in resource_uri:
|
295
|
+
content = json.dumps(
|
296
|
+
{
|
297
|
+
"app_name": "MCP Demo",
|
298
|
+
"version": "1.0.0",
|
299
|
+
"features": ["resource_access", "tool_calling", "prompts"],
|
300
|
+
},
|
301
|
+
indent=2,
|
302
|
+
)
|
303
|
+
else:
|
304
|
+
content = f"Mock content for resource: {resource_uri}"
|
305
|
+
|
306
|
+
return {
|
307
|
+
"success": True,
|
308
|
+
"operation": operation,
|
309
|
+
"server": server_name,
|
310
|
+
"resource": {
|
311
|
+
"uri": resource_uri,
|
312
|
+
"content": content,
|
313
|
+
"mimeType": (
|
314
|
+
"text/plain"
|
315
|
+
if resource_uri.endswith(".txt")
|
316
|
+
else "application/json"
|
317
|
+
),
|
318
|
+
},
|
319
|
+
"mock": True,
|
320
|
+
}
|
321
|
+
|
322
|
+
elif operation == "list_tools":
|
323
|
+
return {
|
324
|
+
"success": True,
|
325
|
+
"operation": operation,
|
326
|
+
"server": server_name,
|
327
|
+
"tools": [
|
328
|
+
{
|
329
|
+
"name": "create_file",
|
330
|
+
"description": "Create a new file with specified content",
|
331
|
+
"inputSchema": {
|
332
|
+
"type": "object",
|
333
|
+
"properties": {
|
334
|
+
"path": {"type": "string", "description": "File path"},
|
335
|
+
"content": {
|
336
|
+
"type": "string",
|
337
|
+
"description": "File content",
|
338
|
+
},
|
339
|
+
},
|
340
|
+
"required": ["path", "content"],
|
341
|
+
},
|
342
|
+
},
|
343
|
+
{
|
344
|
+
"name": "search_files",
|
345
|
+
"description": "Search for files matching a pattern",
|
346
|
+
"inputSchema": {
|
347
|
+
"type": "object",
|
348
|
+
"properties": {
|
349
|
+
"pattern": {
|
350
|
+
"type": "string",
|
351
|
+
"description": "Search pattern",
|
352
|
+
},
|
353
|
+
"directory": {
|
354
|
+
"type": "string",
|
355
|
+
"description": "Directory to search",
|
356
|
+
},
|
357
|
+
},
|
358
|
+
"required": ["pattern"],
|
359
|
+
},
|
360
|
+
},
|
361
|
+
],
|
362
|
+
"tool_count": 2,
|
363
|
+
"mock": True,
|
364
|
+
}
|
365
|
+
|
366
|
+
elif operation == "call_tool":
|
367
|
+
if not tool_name:
|
368
|
+
return {
|
369
|
+
"success": False,
|
370
|
+
"error": "tool_name is required for call_tool operation",
|
371
|
+
"operation": operation,
|
372
|
+
"server": server_name,
|
373
|
+
}
|
374
|
+
|
375
|
+
# Mock tool execution results
|
376
|
+
if tool_name == "create_file":
|
377
|
+
path = tool_arguments.get("path", "/unknown/path")
|
378
|
+
content = tool_arguments.get("content", "")
|
379
|
+
result = {
|
380
|
+
"success": True,
|
381
|
+
"message": f"File created successfully at {path}",
|
382
|
+
"file_size": len(content),
|
383
|
+
"created_at": "2025-06-01T12:00:00Z",
|
384
|
+
}
|
385
|
+
elif tool_name == "search_files":
|
386
|
+
pattern = tool_arguments.get("pattern", "*")
|
387
|
+
directory = tool_arguments.get("directory", "/")
|
388
|
+
result = {
|
389
|
+
"matches": [
|
390
|
+
f"{directory}/example1.txt",
|
391
|
+
f"{directory}/example2.txt",
|
392
|
+
],
|
393
|
+
"pattern": pattern,
|
394
|
+
"total_matches": 2,
|
395
|
+
}
|
396
|
+
else:
|
397
|
+
result = {
|
398
|
+
"message": f"Mock execution of tool '{tool_name}'",
|
399
|
+
"arguments": tool_arguments,
|
400
|
+
}
|
401
|
+
|
402
|
+
return {
|
403
|
+
"success": True,
|
404
|
+
"operation": operation,
|
405
|
+
"server": server_name,
|
406
|
+
"tool_name": tool_name,
|
407
|
+
"tool_arguments": tool_arguments,
|
408
|
+
"result": result,
|
409
|
+
"mock": True,
|
410
|
+
}
|
411
|
+
|
412
|
+
elif operation == "list_prompts":
|
413
|
+
return {
|
414
|
+
"success": True,
|
415
|
+
"operation": operation,
|
416
|
+
"server": server_name,
|
417
|
+
"prompts": [
|
418
|
+
{
|
419
|
+
"name": "summarize_document",
|
420
|
+
"description": "Summarize a document with specified length",
|
421
|
+
"arguments": [
|
422
|
+
{
|
423
|
+
"name": "document",
|
424
|
+
"description": "Document to summarize",
|
425
|
+
"required": True,
|
426
|
+
},
|
427
|
+
{
|
428
|
+
"name": "max_length",
|
429
|
+
"description": "Maximum summary length",
|
430
|
+
"required": False,
|
431
|
+
},
|
432
|
+
],
|
433
|
+
},
|
434
|
+
{
|
435
|
+
"name": "analyze_code",
|
436
|
+
"description": "Analyze code for issues and improvements",
|
437
|
+
"arguments": [
|
438
|
+
{
|
439
|
+
"name": "code",
|
440
|
+
"description": "Code to analyze",
|
441
|
+
"required": True,
|
442
|
+
},
|
443
|
+
{
|
444
|
+
"name": "language",
|
445
|
+
"description": "Programming language",
|
446
|
+
"required": False,
|
447
|
+
},
|
448
|
+
],
|
449
|
+
},
|
450
|
+
],
|
451
|
+
"prompt_count": 2,
|
452
|
+
"mock": True,
|
453
|
+
}
|
454
|
+
|
455
|
+
elif operation == "get_prompt":
|
456
|
+
if not prompt_name:
|
457
|
+
return {
|
458
|
+
"success": False,
|
459
|
+
"error": "prompt_name is required for get_prompt operation",
|
460
|
+
"operation": operation,
|
461
|
+
"server": server_name,
|
462
|
+
}
|
463
|
+
|
464
|
+
# Mock prompt content
|
465
|
+
if prompt_name == "summarize_document":
|
466
|
+
document = prompt_arguments.get("document", "[DOCUMENT CONTENT]")
|
467
|
+
max_length = prompt_arguments.get("max_length", 200)
|
468
|
+
prompt_content = f"Please summarize the following document in no more than {max_length} words:\n\n{document}"
|
469
|
+
elif prompt_name == "analyze_code":
|
470
|
+
code = prompt_arguments.get("code", "[CODE CONTENT]")
|
471
|
+
language = prompt_arguments.get("language", "python")
|
472
|
+
prompt_content = f"Please analyze the following {language} code and provide feedback on potential issues and improvements:\n\n```{language}\n{code}\n```"
|
473
|
+
else:
|
474
|
+
prompt_content = f"Mock prompt content for '{prompt_name}' with arguments: {prompt_arguments}"
|
475
|
+
|
476
|
+
return {
|
477
|
+
"success": True,
|
478
|
+
"operation": operation,
|
479
|
+
"server": server_name,
|
480
|
+
"prompt_name": prompt_name,
|
481
|
+
"prompt_arguments": prompt_arguments,
|
482
|
+
"prompt": {
|
483
|
+
"name": prompt_name,
|
484
|
+
"content": prompt_content,
|
485
|
+
"arguments": prompt_arguments,
|
486
|
+
},
|
487
|
+
"mock": True,
|
488
|
+
}
|
489
|
+
|
490
|
+
else:
|
491
|
+
return {
|
492
|
+
"success": False,
|
493
|
+
"error": f"Unsupported operation: {operation}",
|
494
|
+
"operation": operation,
|
495
|
+
"server": server_name,
|
496
|
+
"supported_operations": [
|
497
|
+
"list_resources",
|
498
|
+
"read_resource",
|
499
|
+
"list_tools",
|
500
|
+
"call_tool",
|
501
|
+
"list_prompts",
|
502
|
+
"get_prompt",
|
503
|
+
],
|
504
|
+
}
|
505
|
+
|
506
|
+
def _mock_stdio_operation(
|
507
|
+
self,
|
508
|
+
operation: str,
|
509
|
+
server_name: str,
|
510
|
+
command: str,
|
511
|
+
args: List[str],
|
512
|
+
resource_uri: Optional[str],
|
513
|
+
tool_name: Optional[str],
|
514
|
+
tool_arguments: dict,
|
515
|
+
prompt_name: Optional[str],
|
516
|
+
prompt_arguments: dict,
|
517
|
+
) -> Dict[str, Any]:
|
518
|
+
"""Mock stdio transport operations."""
|
519
|
+
result = self._mock_mcp_operation(
|
520
|
+
operation,
|
521
|
+
{"name": server_name},
|
522
|
+
resource_uri,
|
523
|
+
tool_name,
|
524
|
+
tool_arguments,
|
525
|
+
prompt_name,
|
526
|
+
prompt_arguments,
|
527
|
+
)
|
528
|
+
result.update(
|
529
|
+
{"transport": "stdio", "command": command, "args": args, "mock": True}
|
530
|
+
)
|
531
|
+
return result
|
532
|
+
|
533
|
+
def _mock_http_operation(
|
534
|
+
self,
|
535
|
+
operation: str,
|
536
|
+
server_name: str,
|
537
|
+
url: str,
|
538
|
+
headers: dict,
|
539
|
+
resource_uri: Optional[str],
|
540
|
+
tool_name: Optional[str],
|
541
|
+
tool_arguments: dict,
|
542
|
+
prompt_name: Optional[str],
|
543
|
+
prompt_arguments: dict,
|
544
|
+
) -> Dict[str, Any]:
|
545
|
+
"""Mock HTTP/SSE transport operations."""
|
546
|
+
result = self._mock_mcp_operation(
|
547
|
+
operation,
|
548
|
+
{"name": server_name},
|
549
|
+
resource_uri,
|
550
|
+
tool_name,
|
551
|
+
tool_arguments,
|
552
|
+
prompt_name,
|
553
|
+
prompt_arguments,
|
554
|
+
)
|
555
|
+
result.update(
|
556
|
+
{"transport": "http", "url": url, "headers": headers, "mock": True}
|
557
|
+
)
|
558
|
+
return result
|