mcp-use 1.3.8__py3-none-any.whl → 1.3.10__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.
Potentially problematic release.
This version of mcp-use might be problematic. Click here for more details.
- mcp_use/__init__.py +6 -3
- mcp_use/adapters/base.py +3 -3
- mcp_use/adapters/langchain_adapter.py +5 -4
- mcp_use/agents/mcpagent.py +101 -17
- mcp_use/agents/remote.py +102 -14
- mcp_use/cli.py +581 -0
- mcp_use/client.py +15 -1
- mcp_use/config.py +10 -8
- mcp_use/connectors/base.py +100 -15
- mcp_use/connectors/http.py +13 -2
- mcp_use/connectors/sandbox.py +12 -6
- mcp_use/connectors/stdio.py +11 -2
- mcp_use/errors/__init__.py +1 -0
- mcp_use/errors/error_formatting.py +29 -0
- mcp_use/logging.py +27 -12
- mcp_use/managers/base.py +36 -0
- mcp_use/managers/server_manager.py +3 -8
- mcp_use/managers/tools/connect_server.py +2 -1
- mcp_use/managers/tools/disconnect_server.py +2 -1
- mcp_use/managers/tools/list_servers_tool.py +2 -0
- mcp_use/observability/__init__.py +2 -1
- mcp_use/observability/callbacks_manager.py +162 -0
- mcp_use/observability/laminar.py +24 -3
- mcp_use/observability/langfuse.py +27 -3
- mcp_use/session.py +70 -0
- mcp_use/telemetry/telemetry.py +1 -4
- {mcp_use-1.3.8.dist-info → mcp_use-1.3.10.dist-info}/METADATA +73 -48
- mcp_use-1.3.10.dist-info/RECORD +55 -0
- mcp_use-1.3.10.dist-info/entry_points.txt +2 -0
- mcp_use-1.3.8.dist-info/RECORD +0 -49
- {mcp_use-1.3.8.dist-info → mcp_use-1.3.10.dist-info}/WHEEL +0 -0
- {mcp_use-1.3.8.dist-info → mcp_use-1.3.10.dist-info}/licenses/LICENSE +0 -0
mcp_use/cli.py
ADDED
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
MCP-Use CLI Tool - All-in-one CLI for creating and deploying MCP projects.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import sys
|
|
8
|
+
import threading
|
|
9
|
+
import time
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from mcp_use import __version__
|
|
13
|
+
|
|
14
|
+
# ============= SPINNER CLASS =============
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Spinner:
|
|
18
|
+
"""Simple loading spinner similar to UV's style."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, message: str = "Loading"):
|
|
21
|
+
self.message = message
|
|
22
|
+
self.running = False
|
|
23
|
+
self.thread = None
|
|
24
|
+
self.frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
|
|
25
|
+
self.current = 0
|
|
26
|
+
|
|
27
|
+
def start(self):
|
|
28
|
+
"""Start the spinner."""
|
|
29
|
+
self.running = True
|
|
30
|
+
self.thread = threading.Thread(target=self._spin)
|
|
31
|
+
self.thread.daemon = True
|
|
32
|
+
self.thread.start()
|
|
33
|
+
|
|
34
|
+
def _spin(self):
|
|
35
|
+
"""Spin animation loop."""
|
|
36
|
+
while self.running:
|
|
37
|
+
frame = self.frames[self.current % len(self.frames)]
|
|
38
|
+
print(f"\r{frame} {self.message}...", end="", flush=True)
|
|
39
|
+
self.current += 1
|
|
40
|
+
time.sleep(0.1)
|
|
41
|
+
|
|
42
|
+
def stop(self, success_message=None):
|
|
43
|
+
"""Stop the spinner and optionally print success message."""
|
|
44
|
+
self.running = False
|
|
45
|
+
if self.thread:
|
|
46
|
+
self.thread.join()
|
|
47
|
+
if success_message:
|
|
48
|
+
print(f"\r✓ {success_message} ")
|
|
49
|
+
else:
|
|
50
|
+
print("\r" + " " * (len(self.message) + 10), end="\r")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# ============= PROJECT CREATION FUNCTIONS =============
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def print_header():
|
|
57
|
+
"""Print the CLI header."""
|
|
58
|
+
print("\n mcp-use create")
|
|
59
|
+
print("━" * 50)
|
|
60
|
+
print()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_project_name() -> str:
|
|
64
|
+
"""Get project name from user."""
|
|
65
|
+
while True:
|
|
66
|
+
name = input("📝 Project name: ").strip().replace("-", "_")
|
|
67
|
+
if not name:
|
|
68
|
+
print(" ⚠️ Project name cannot be empty")
|
|
69
|
+
continue
|
|
70
|
+
if " " in name:
|
|
71
|
+
print(" ⚠️ Project name cannot contain spaces")
|
|
72
|
+
continue
|
|
73
|
+
if Path(name).exists():
|
|
74
|
+
print(f" ⚠️ Directory '{name}' already exists")
|
|
75
|
+
continue
|
|
76
|
+
return name
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def get_project_type() -> str:
|
|
80
|
+
"""Get project type from user."""
|
|
81
|
+
print("\n📦 What would you like to create?")
|
|
82
|
+
print(" 1) Server + Agent")
|
|
83
|
+
print(" 2) Server only")
|
|
84
|
+
print(" 3) Agent only")
|
|
85
|
+
|
|
86
|
+
while True:
|
|
87
|
+
choice = input("\n Choice (1-3): ").strip()
|
|
88
|
+
if choice == "1":
|
|
89
|
+
return "server_agent"
|
|
90
|
+
elif choice == "2":
|
|
91
|
+
return "server"
|
|
92
|
+
elif choice == "3":
|
|
93
|
+
return "agent"
|
|
94
|
+
else:
|
|
95
|
+
print(" ⚠️ Please enter 1, 2, or 3")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def create_server_structure(project_dir: Path, project_name: str):
|
|
99
|
+
"""Create server file in nested project folder."""
|
|
100
|
+
# Create nested project folder
|
|
101
|
+
nested_dir = project_dir / project_name
|
|
102
|
+
nested_dir.mkdir(parents=True)
|
|
103
|
+
|
|
104
|
+
# Create server.py
|
|
105
|
+
server_content = f'''"""
|
|
106
|
+
MCP Server for {project_name}
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
from mcp.server import FastMCP
|
|
110
|
+
|
|
111
|
+
# Create server instance
|
|
112
|
+
server = FastMCP("{project_name}-server")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# ============= TOOLS =============
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@server.tool()
|
|
119
|
+
async def add_numbers(a: float, b: float) -> str:
|
|
120
|
+
"""Add two numbers together."""
|
|
121
|
+
result = a + b
|
|
122
|
+
return f"{{result}}"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
# ============= RESOURCES =============
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@server.resource("config://app")
|
|
129
|
+
async def get_app_config() -> str:
|
|
130
|
+
"""Get the application configuration."""
|
|
131
|
+
return "App: {project_name}, Version: 0.1.0, Status: Active"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# ============= PROMPTS =============
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@server.prompt()
|
|
138
|
+
async def assistant_prompt() -> str:
|
|
139
|
+
"""Generate a helpful assistant prompt."""
|
|
140
|
+
return "You are a helpful assistant for {project_name}. Be concise and friendly."
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
# ============= MAIN =============
|
|
144
|
+
|
|
145
|
+
if __name__ == "__main__":
|
|
146
|
+
server.run("stdio")
|
|
147
|
+
'''
|
|
148
|
+
(nested_dir / "server.py").write_text(server_content)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def create_agent_structure(project_dir: Path, project_name: str, project_type: str):
|
|
152
|
+
"""Create agent file in nested project folder."""
|
|
153
|
+
# Create nested project folder if it doesn't exist
|
|
154
|
+
nested_dir = project_dir / project_name
|
|
155
|
+
if not nested_dir.exists():
|
|
156
|
+
nested_dir.mkdir(parents=True)
|
|
157
|
+
|
|
158
|
+
if project_type == "server_agent":
|
|
159
|
+
# For server_agent mode, embed config directly in agent.py
|
|
160
|
+
agent_content = f'''"""
|
|
161
|
+
MCP Agent implementation for {project_name}
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
from langchain_openai import ChatOpenAI
|
|
165
|
+
|
|
166
|
+
from mcp_use import MCPAgent, MCPClient
|
|
167
|
+
|
|
168
|
+
config = {{
|
|
169
|
+
"mcpServers": {{
|
|
170
|
+
"{project_name}": {{
|
|
171
|
+
"command": "python",
|
|
172
|
+
"args": ["{project_name}/server.py"],
|
|
173
|
+
}}
|
|
174
|
+
}}
|
|
175
|
+
}}
|
|
176
|
+
|
|
177
|
+
client = MCPClient(config=config)
|
|
178
|
+
agent = MCPAgent(llm=ChatOpenAI(model="gpt-4o"), client=client, max_steps=10, memory_enabled=True)
|
|
179
|
+
'''
|
|
180
|
+
else:
|
|
181
|
+
# For agent-only mode, use external JSON config file
|
|
182
|
+
agent_content = f'''"""
|
|
183
|
+
MCP Agent implementation for {project_name}
|
|
184
|
+
"""
|
|
185
|
+
|
|
186
|
+
from langchain_openai import ChatOpenAI
|
|
187
|
+
|
|
188
|
+
from mcp_use import MCPAgent, MCPClient
|
|
189
|
+
|
|
190
|
+
client = MCPClient.from_config_file("{project_name}/mcp_servers.json")
|
|
191
|
+
agent = MCPAgent(llm=ChatOpenAI(model="gpt-4o"), client=client, max_steps=10, memory_enabled=True)
|
|
192
|
+
'''
|
|
193
|
+
# Create mcp_servers.json for agent-only mode
|
|
194
|
+
mcp_servers_json = (
|
|
195
|
+
'''{
|
|
196
|
+
"mcpServers": {
|
|
197
|
+
"'''
|
|
198
|
+
+ project_name
|
|
199
|
+
+ """": {
|
|
200
|
+
"command": "npx",
|
|
201
|
+
"args": ["-y", "@modelcontextprotocol/server-everything"]
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}"""
|
|
205
|
+
)
|
|
206
|
+
(nested_dir / "mcp_servers.json").write_text(mcp_servers_json)
|
|
207
|
+
|
|
208
|
+
(nested_dir / "agent.py").write_text(agent_content)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def create_common_files(project_dir: Path, project_name: str, project_type: str):
|
|
212
|
+
"""Create common project files."""
|
|
213
|
+
|
|
214
|
+
# pyproject.toml
|
|
215
|
+
pyproject = f"""[project]
|
|
216
|
+
name = "{project_name}"
|
|
217
|
+
version = "0.1.0"
|
|
218
|
+
description = "An MCP project"
|
|
219
|
+
requires-python = ">=3.10"
|
|
220
|
+
dependencies = [
|
|
221
|
+
"mcp>=1.0.0",
|
|
222
|
+
"mcp-use>=0.1.0",
|
|
223
|
+
"langchain-openai>=0.1.0",
|
|
224
|
+
"python-dotenv>=1.0.0",
|
|
225
|
+
]
|
|
226
|
+
"""
|
|
227
|
+
(project_dir / "pyproject.toml").write_text(pyproject)
|
|
228
|
+
|
|
229
|
+
# requirements.txt
|
|
230
|
+
requirements = """mcp>=1.0.0
|
|
231
|
+
mcp-use>=0.1.0
|
|
232
|
+
langchain-openai>=0.1.0
|
|
233
|
+
python-dotenv>=1.0.0
|
|
234
|
+
"""
|
|
235
|
+
(project_dir / "requirements.txt").write_text(requirements)
|
|
236
|
+
|
|
237
|
+
# .gitignore
|
|
238
|
+
gitignore = """__pycache__/
|
|
239
|
+
*.py[cod]
|
|
240
|
+
.env
|
|
241
|
+
venv/
|
|
242
|
+
.venv/
|
|
243
|
+
*.egg-info/
|
|
244
|
+
dist/
|
|
245
|
+
build/
|
|
246
|
+
.pytest_cache/
|
|
247
|
+
.coverage
|
|
248
|
+
"""
|
|
249
|
+
(project_dir / ".gitignore").write_text(gitignore)
|
|
250
|
+
|
|
251
|
+
# README.md
|
|
252
|
+
readme = f"""# {project_name}
|
|
253
|
+
|
|
254
|
+
An MCP project created with mcp-use.
|
|
255
|
+
|
|
256
|
+
## Project Structure
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
{project_name}/
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
if project_type in ["server_agent", "server"]:
|
|
263
|
+
readme += f"""├── {project_name}/
|
|
264
|
+
│ ├── server.py # MCP server with all components
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
if project_type in ["server_agent", "agent"]:
|
|
268
|
+
if project_type == "agent":
|
|
269
|
+
readme += f"""├── {project_name}/
|
|
270
|
+
│ ├── agent.py # MCP agent implementation
|
|
271
|
+
│ └── mcp_servers.json # Server configuration
|
|
272
|
+
"""
|
|
273
|
+
else:
|
|
274
|
+
readme += """│ └── agent.py # MCP agent implementation
|
|
275
|
+
"""
|
|
276
|
+
|
|
277
|
+
if project_type in ["server_agent", "agent"]:
|
|
278
|
+
readme += """├── run.py # Simple example
|
|
279
|
+
├── chat.py # Interactive chat
|
|
280
|
+
"""
|
|
281
|
+
|
|
282
|
+
readme += """├── pyproject.toml
|
|
283
|
+
├── requirements.txt
|
|
284
|
+
├── .gitignore
|
|
285
|
+
└── README.md
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Setup
|
|
289
|
+
|
|
290
|
+
1. Install dependencies:
|
|
291
|
+
```bash
|
|
292
|
+
pip install -r requirements.txt
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
2. Configure environment:
|
|
296
|
+
```bash
|
|
297
|
+
export OPENAI_API_KEY=your-api-key-here
|
|
298
|
+
```
|
|
299
|
+
"""
|
|
300
|
+
|
|
301
|
+
if project_type in ["server_agent", "server"]:
|
|
302
|
+
readme += f"""
|
|
303
|
+
## Running the Server
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
python {project_name}/server.py
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
The server uses FastMCP and includes:
|
|
310
|
+
- **Tools**: Simple tool functions (e.g., add_numbers)
|
|
311
|
+
- **Resources**: Data resources (e.g., config)
|
|
312
|
+
- **Prompts**: Prompt templates for the LLM
|
|
313
|
+
"""
|
|
314
|
+
|
|
315
|
+
if project_type in ["server_agent", "agent"]:
|
|
316
|
+
readme += f"""
|
|
317
|
+
## Using the Agent
|
|
318
|
+
|
|
319
|
+
```python
|
|
320
|
+
from {project_name}.agent import agent
|
|
321
|
+
|
|
322
|
+
result = await agent.run("Your prompt")
|
|
323
|
+
```
|
|
324
|
+
"""
|
|
325
|
+
|
|
326
|
+
(project_dir / "README.md").write_text(readme)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def create_example_files(project_dir: Path, project_name: str):
|
|
330
|
+
"""Create example files."""
|
|
331
|
+
|
|
332
|
+
# run.py
|
|
333
|
+
run_content = f'''"""
|
|
334
|
+
Example usage of {project_name}.
|
|
335
|
+
"""
|
|
336
|
+
|
|
337
|
+
import asyncio
|
|
338
|
+
import os
|
|
339
|
+
|
|
340
|
+
from dotenv import load_dotenv
|
|
341
|
+
|
|
342
|
+
from {project_name}.agent import agent
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
async def main():
|
|
346
|
+
load_dotenv()
|
|
347
|
+
|
|
348
|
+
if not os.getenv("OPENAI_API_KEY"):
|
|
349
|
+
print("Error: OPENAI_API_KEY not found")
|
|
350
|
+
return
|
|
351
|
+
|
|
352
|
+
result = await agent.run("What tools are available?")
|
|
353
|
+
print(f"Result: {{result}}")
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
if __name__ == "__main__":
|
|
357
|
+
asyncio.run(main())
|
|
358
|
+
'''
|
|
359
|
+
(project_dir / "run.py").write_text(run_content)
|
|
360
|
+
|
|
361
|
+
# chat.py
|
|
362
|
+
chat_content = f'''"""
|
|
363
|
+
Interactive chat for {project_name}.
|
|
364
|
+
"""
|
|
365
|
+
|
|
366
|
+
import asyncio
|
|
367
|
+
import os
|
|
368
|
+
|
|
369
|
+
from dotenv import load_dotenv
|
|
370
|
+
|
|
371
|
+
from {project_name}.agent import agent
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
async def chat():
|
|
375
|
+
load_dotenv()
|
|
376
|
+
|
|
377
|
+
if not os.getenv("OPENAI_API_KEY"):
|
|
378
|
+
print("Error: OPENAI_API_KEY not found")
|
|
379
|
+
return
|
|
380
|
+
|
|
381
|
+
print("Chat started (type 'exit' to quit)")
|
|
382
|
+
|
|
383
|
+
while True:
|
|
384
|
+
user_input = input("\\nYou: ")
|
|
385
|
+
if user_input.lower() == "exit":
|
|
386
|
+
break
|
|
387
|
+
|
|
388
|
+
print("Assistant: ", end="", flush=True)
|
|
389
|
+
response = await agent.run(user_input)
|
|
390
|
+
print(response)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
if __name__ == "__main__":
|
|
394
|
+
asyncio.run(chat())
|
|
395
|
+
'''
|
|
396
|
+
(project_dir / "chat.py").write_text(chat_content)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def create_project(project_name: str, project_type: str) -> bool:
|
|
400
|
+
"""Create the project structure."""
|
|
401
|
+
project_dir = Path.cwd() / project_name
|
|
402
|
+
|
|
403
|
+
try:
|
|
404
|
+
# Create main directory
|
|
405
|
+
spinner = Spinner("Creating project directory")
|
|
406
|
+
spinner.start()
|
|
407
|
+
time.sleep(0.5) # Simulate work
|
|
408
|
+
project_dir.mkdir(parents=True)
|
|
409
|
+
spinner.stop("Created project directory")
|
|
410
|
+
|
|
411
|
+
# Create server if needed
|
|
412
|
+
if project_type in ["server_agent", "server"]:
|
|
413
|
+
spinner = Spinner("Creating server")
|
|
414
|
+
spinner.start()
|
|
415
|
+
time.sleep(0.3)
|
|
416
|
+
create_server_structure(project_dir, project_name)
|
|
417
|
+
spinner.stop("Created server structure")
|
|
418
|
+
|
|
419
|
+
# Create agent if needed
|
|
420
|
+
if project_type in ["server_agent", "agent"]:
|
|
421
|
+
spinner = Spinner("Creating agent")
|
|
422
|
+
spinner.start()
|
|
423
|
+
time.sleep(0.3)
|
|
424
|
+
create_agent_structure(project_dir, project_name, project_type)
|
|
425
|
+
spinner.stop("Created agent structure")
|
|
426
|
+
|
|
427
|
+
# Create common files
|
|
428
|
+
spinner = Spinner("Creating configuration files")
|
|
429
|
+
spinner.start()
|
|
430
|
+
time.sleep(0.3)
|
|
431
|
+
create_common_files(project_dir, project_name, project_type)
|
|
432
|
+
spinner.stop("Created configuration files")
|
|
433
|
+
|
|
434
|
+
# Create examples for server_agent and agent
|
|
435
|
+
if project_type in ["server_agent", "agent"]:
|
|
436
|
+
spinner = Spinner("Creating example files")
|
|
437
|
+
spinner.start()
|
|
438
|
+
time.sleep(0.3)
|
|
439
|
+
create_example_files(project_dir, project_name)
|
|
440
|
+
spinner.stop("Created example files")
|
|
441
|
+
|
|
442
|
+
return True
|
|
443
|
+
|
|
444
|
+
except Exception as e:
|
|
445
|
+
print(f"\n❌ Error: {str(e)}")
|
|
446
|
+
return False
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
# ============= MAIN CLI FUNCTIONS =============
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def show_help():
|
|
453
|
+
"""Show the main help message."""
|
|
454
|
+
help_text = """
|
|
455
|
+
╔══════════════════════════════════════════════════════════════════╗
|
|
456
|
+
║ MCP-Use CLI Tool ║
|
|
457
|
+
║ ║
|
|
458
|
+
║ Create and deploy MCP servers and agents with ease ║
|
|
459
|
+
╚══════════════════════════════════════════════════════════════════╝
|
|
460
|
+
|
|
461
|
+
Usage: uvx mcp-use <command> [options]
|
|
462
|
+
|
|
463
|
+
Available Commands:
|
|
464
|
+
create 🚀 Create a new MCP project (server, agent, or both)
|
|
465
|
+
Interactive wizard to scaffold your MCP project
|
|
466
|
+
|
|
467
|
+
deploy ☁️ Deploy your MCP project to the cloud
|
|
468
|
+
(Coming soon - Cloud deployment from CLI)
|
|
469
|
+
|
|
470
|
+
Examples:
|
|
471
|
+
uvx mcp-use create # Start interactive project creation
|
|
472
|
+
uvx mcp-use deploy # Deploy to cloud (coming soon)
|
|
473
|
+
uvx mcp-use --help # Show this help message
|
|
474
|
+
uvx mcp-use --version # Show version information
|
|
475
|
+
|
|
476
|
+
For more information, visit: https://mcp-use.com
|
|
477
|
+
"""
|
|
478
|
+
print(help_text)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def handle_create():
|
|
482
|
+
"""Handle the create command."""
|
|
483
|
+
print_header()
|
|
484
|
+
|
|
485
|
+
# Get project configuration
|
|
486
|
+
project_name = get_project_name()
|
|
487
|
+
project_type = get_project_type()
|
|
488
|
+
|
|
489
|
+
print(f"\n⚙️ Creating {project_type.replace('_', ' + ')} project: {project_name}")
|
|
490
|
+
print()
|
|
491
|
+
|
|
492
|
+
# Create the project
|
|
493
|
+
if create_project(project_name, project_type):
|
|
494
|
+
print(f"\n✨ Successfully created '{project_name}'!")
|
|
495
|
+
print("\n📋 Next steps:")
|
|
496
|
+
print(f" cd {project_name}")
|
|
497
|
+
print(" pip install -r requirements.txt")
|
|
498
|
+
print(" export OPENAI_API_KEY=your-api-key-here")
|
|
499
|
+
|
|
500
|
+
if project_type in ["server_agent", "server"]:
|
|
501
|
+
print("\n # Test the server:")
|
|
502
|
+
print(f" python {project_name}/server.py")
|
|
503
|
+
|
|
504
|
+
if project_type in ["server_agent", "agent"]:
|
|
505
|
+
print("\n # Run examples:")
|
|
506
|
+
print(" python run.py # Simple example")
|
|
507
|
+
print(" python chat.py # Interactive chat")
|
|
508
|
+
|
|
509
|
+
print()
|
|
510
|
+
else:
|
|
511
|
+
sys.exit(1)
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
def handle_deploy():
|
|
515
|
+
"""Handle the deploy command (placeholder for future implementation)."""
|
|
516
|
+
print("\n" + "=" * 60)
|
|
517
|
+
print("🚀 MCP Cloud Deployment")
|
|
518
|
+
print("=" * 60)
|
|
519
|
+
|
|
520
|
+
print("\n📝 Please login to MCP Cloud to continue...")
|
|
521
|
+
print(" Visit: https://cloud.mcp-use.com/login")
|
|
522
|
+
print()
|
|
523
|
+
|
|
524
|
+
# Simulate login prompt
|
|
525
|
+
print("Enter your MCP Cloud credentials:")
|
|
526
|
+
email = input("Email: ")
|
|
527
|
+
|
|
528
|
+
if email:
|
|
529
|
+
print(f"\n✨ Welcome {email}!")
|
|
530
|
+
print()
|
|
531
|
+
print("ℹ️ Deployment from CLI is coming soon!")
|
|
532
|
+
print(" For now, please use the web interface at:")
|
|
533
|
+
print(" https://cloud.mcp-use.com/deploy")
|
|
534
|
+
print()
|
|
535
|
+
print("Stay tuned for updates! 🎉")
|
|
536
|
+
else:
|
|
537
|
+
print("\n❌ Login cancelled")
|
|
538
|
+
|
|
539
|
+
print("=" * 60)
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def main(args=None):
|
|
543
|
+
"""Main entry point for the CLI."""
|
|
544
|
+
parser = argparse.ArgumentParser(
|
|
545
|
+
prog="mcp-use",
|
|
546
|
+
description="MCP-Use CLI Tool - Create and deploy MCP projects",
|
|
547
|
+
add_help=False, # We'll handle help ourselves
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
# Add version argument
|
|
551
|
+
parser.add_argument(
|
|
552
|
+
"--version", "-v", action="version", version=f"mcp-use {__version__}", help="Show version information"
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
# Add help argument
|
|
556
|
+
parser.add_argument("--help", "-h", action="store_true", help="Show help message")
|
|
557
|
+
|
|
558
|
+
# Add subcommand as positional argument
|
|
559
|
+
parser.add_argument("command", nargs="?", choices=["create", "deploy"], help="Command to execute")
|
|
560
|
+
|
|
561
|
+
# Parse arguments
|
|
562
|
+
parsed_args = parser.parse_args(args)
|
|
563
|
+
|
|
564
|
+
# Handle help flag or no command
|
|
565
|
+
if parsed_args.help or not parsed_args.command:
|
|
566
|
+
show_help()
|
|
567
|
+
sys.exit(0)
|
|
568
|
+
|
|
569
|
+
# Handle commands
|
|
570
|
+
if parsed_args.command == "create":
|
|
571
|
+
handle_create()
|
|
572
|
+
elif parsed_args.command == "deploy":
|
|
573
|
+
handle_deploy()
|
|
574
|
+
else:
|
|
575
|
+
print(f"Unknown command: {parsed_args.command}")
|
|
576
|
+
show_help()
|
|
577
|
+
sys.exit(1)
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
if __name__ == "__main__":
|
|
581
|
+
main()
|
mcp_use/client.py
CHANGED
|
@@ -9,7 +9,7 @@ import json
|
|
|
9
9
|
import warnings
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
-
from mcp.client.session import ElicitationFnT, SamplingFnT
|
|
12
|
+
from mcp.client.session import ElicitationFnT, LoggingFnT, MessageHandlerFnT, SamplingFnT
|
|
13
13
|
|
|
14
14
|
from mcp_use.types.sandbox import SandboxOptions
|
|
15
15
|
|
|
@@ -33,6 +33,8 @@ class MCPClient:
|
|
|
33
33
|
sandbox_options: SandboxOptions | None = None,
|
|
34
34
|
sampling_callback: SamplingFnT | None = None,
|
|
35
35
|
elicitation_callback: ElicitationFnT | None = None,
|
|
36
|
+
message_handler: MessageHandlerFnT | None = None,
|
|
37
|
+
logging_callback: LoggingFnT | None = None,
|
|
36
38
|
) -> None:
|
|
37
39
|
"""Initialize a new MCP client.
|
|
38
40
|
|
|
@@ -51,6 +53,8 @@ class MCPClient:
|
|
|
51
53
|
self.active_sessions: list[str] = []
|
|
52
54
|
self.sampling_callback = sampling_callback
|
|
53
55
|
self.elicitation_callback = elicitation_callback
|
|
56
|
+
self.message_handler = message_handler
|
|
57
|
+
self.logging_callback = logging_callback
|
|
54
58
|
# Load configuration if provided
|
|
55
59
|
if config is not None:
|
|
56
60
|
if isinstance(config, str):
|
|
@@ -66,6 +70,8 @@ class MCPClient:
|
|
|
66
70
|
sandbox_options: SandboxOptions | None = None,
|
|
67
71
|
sampling_callback: SamplingFnT | None = None,
|
|
68
72
|
elicitation_callback: ElicitationFnT | None = None,
|
|
73
|
+
message_handler: MessageHandlerFnT | None = None,
|
|
74
|
+
logging_callback: LoggingFnT | None = None,
|
|
69
75
|
) -> "MCPClient":
|
|
70
76
|
"""Create a MCPClient from a dictionary.
|
|
71
77
|
|
|
@@ -82,6 +88,8 @@ class MCPClient:
|
|
|
82
88
|
sandbox_options=sandbox_options,
|
|
83
89
|
sampling_callback=sampling_callback,
|
|
84
90
|
elicitation_callback=elicitation_callback,
|
|
91
|
+
message_handler=message_handler,
|
|
92
|
+
logging_callback=logging_callback,
|
|
85
93
|
)
|
|
86
94
|
|
|
87
95
|
@classmethod
|
|
@@ -92,6 +100,8 @@ class MCPClient:
|
|
|
92
100
|
sandbox_options: SandboxOptions | None = None,
|
|
93
101
|
sampling_callback: SamplingFnT | None = None,
|
|
94
102
|
elicitation_callback: ElicitationFnT | None = None,
|
|
103
|
+
message_handler: MessageHandlerFnT | None = None,
|
|
104
|
+
logging_callback: LoggingFnT | None = None,
|
|
95
105
|
) -> "MCPClient":
|
|
96
106
|
"""Create a MCPClient from a configuration file.
|
|
97
107
|
|
|
@@ -108,6 +118,8 @@ class MCPClient:
|
|
|
108
118
|
sandbox_options=sandbox_options,
|
|
109
119
|
sampling_callback=sampling_callback,
|
|
110
120
|
elicitation_callback=elicitation_callback,
|
|
121
|
+
message_handler=message_handler,
|
|
122
|
+
logging_callback=logging_callback,
|
|
111
123
|
)
|
|
112
124
|
|
|
113
125
|
def add_server(
|
|
@@ -187,6 +199,8 @@ class MCPClient:
|
|
|
187
199
|
sandbox_options=self.sandbox_options,
|
|
188
200
|
sampling_callback=self.sampling_callback,
|
|
189
201
|
elicitation_callback=self.elicitation_callback,
|
|
202
|
+
message_handler=self.message_handler,
|
|
203
|
+
logging_callback=self.logging_callback,
|
|
190
204
|
)
|
|
191
205
|
|
|
192
206
|
# Create the session
|
mcp_use/config.py
CHANGED
|
@@ -7,17 +7,11 @@ This module provides functionality to load MCP configuration from JSON files.
|
|
|
7
7
|
import json
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
|
-
from mcp.client.session import ElicitationFnT, SamplingFnT
|
|
10
|
+
from mcp.client.session import ElicitationFnT, LoggingFnT, MessageHandlerFnT, SamplingFnT
|
|
11
11
|
|
|
12
12
|
from mcp_use.types.sandbox import SandboxOptions
|
|
13
13
|
|
|
14
|
-
from .connectors import
|
|
15
|
-
BaseConnector,
|
|
16
|
-
HttpConnector,
|
|
17
|
-
SandboxConnector,
|
|
18
|
-
StdioConnector,
|
|
19
|
-
WebSocketConnector,
|
|
20
|
-
)
|
|
14
|
+
from .connectors import BaseConnector, HttpConnector, SandboxConnector, StdioConnector, WebSocketConnector
|
|
21
15
|
from .connectors.utils import is_stdio_server
|
|
22
16
|
|
|
23
17
|
|
|
@@ -40,6 +34,8 @@ def create_connector_from_config(
|
|
|
40
34
|
sandbox_options: SandboxOptions | None = None,
|
|
41
35
|
sampling_callback: SamplingFnT | None = None,
|
|
42
36
|
elicitation_callback: ElicitationFnT | None = None,
|
|
37
|
+
message_handler: MessageHandlerFnT | None = None,
|
|
38
|
+
logging_callback: LoggingFnT | None = None,
|
|
43
39
|
) -> BaseConnector:
|
|
44
40
|
"""Create a connector based on server configuration.
|
|
45
41
|
This function can be called with just the server_config parameter:
|
|
@@ -61,6 +57,8 @@ def create_connector_from_config(
|
|
|
61
57
|
env=server_config.get("env", None),
|
|
62
58
|
sampling_callback=sampling_callback,
|
|
63
59
|
elicitation_callback=elicitation_callback,
|
|
60
|
+
message_handler=message_handler,
|
|
61
|
+
logging_callback=logging_callback,
|
|
64
62
|
)
|
|
65
63
|
|
|
66
64
|
# Sandboxed connector
|
|
@@ -72,6 +70,8 @@ def create_connector_from_config(
|
|
|
72
70
|
e2b_options=sandbox_options,
|
|
73
71
|
sampling_callback=sampling_callback,
|
|
74
72
|
elicitation_callback=elicitation_callback,
|
|
73
|
+
message_handler=message_handler,
|
|
74
|
+
logging_callback=logging_callback,
|
|
75
75
|
)
|
|
76
76
|
|
|
77
77
|
# HTTP connector
|
|
@@ -84,6 +84,8 @@ def create_connector_from_config(
|
|
|
84
84
|
sse_read_timeout=server_config.get("sse_read_timeout", 60 * 5),
|
|
85
85
|
sampling_callback=sampling_callback,
|
|
86
86
|
elicitation_callback=elicitation_callback,
|
|
87
|
+
message_handler=message_handler,
|
|
88
|
+
logging_callback=logging_callback,
|
|
87
89
|
)
|
|
88
90
|
|
|
89
91
|
# WebSocket connector
|