meshagent-cli 0.6.1__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 meshagent-cli might be problematic. Click here for more details.
- meshagent/cli/__init__.py +3 -0
- meshagent/cli/agent.py +263 -0
- meshagent/cli/api_keys.py +102 -0
- meshagent/cli/async_typer.py +31 -0
- meshagent/cli/auth.py +30 -0
- meshagent/cli/auth_async.py +295 -0
- meshagent/cli/call.py +224 -0
- meshagent/cli/chatbot.py +311 -0
- meshagent/cli/cli.py +184 -0
- meshagent/cli/cli_mcp.py +344 -0
- meshagent/cli/cli_secrets.py +414 -0
- meshagent/cli/common_options.py +23 -0
- meshagent/cli/containers.py +577 -0
- meshagent/cli/developer.py +70 -0
- meshagent/cli/exec.py +381 -0
- meshagent/cli/helper.py +147 -0
- meshagent/cli/helpers.py +131 -0
- meshagent/cli/mailbot.py +260 -0
- meshagent/cli/meeting_transcriber.py +124 -0
- meshagent/cli/messaging.py +160 -0
- meshagent/cli/oauth2.py +189 -0
- meshagent/cli/participant_token.py +61 -0
- meshagent/cli/projects.py +105 -0
- meshagent/cli/queue.py +91 -0
- meshagent/cli/services.py +490 -0
- meshagent/cli/sessions.py +26 -0
- meshagent/cli/storage.py +813 -0
- meshagent/cli/version.py +1 -0
- meshagent/cli/voicebot.py +178 -0
- meshagent/cli/webhook.py +100 -0
- meshagent_cli-0.6.1.dist-info/METADATA +47 -0
- meshagent_cli-0.6.1.dist-info/RECORD +35 -0
- meshagent_cli-0.6.1.dist-info/WHEEL +5 -0
- meshagent_cli-0.6.1.dist-info/entry_points.txt +2 -0
- meshagent_cli-0.6.1.dist-info/top_level.txt +1 -0
meshagent/cli/cli_mcp.py
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from rich import print
|
|
3
|
+
from typing import Annotated, Optional, List
|
|
4
|
+
from meshagent.cli.common_options import ProjectIdOption, RoomOption
|
|
5
|
+
|
|
6
|
+
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
7
|
+
from meshagent.api import RoomClient, WebSocketClientProtocol, RoomException
|
|
8
|
+
from meshagent.cli import async_typer
|
|
9
|
+
from meshagent.cli.helper import (
|
|
10
|
+
get_client,
|
|
11
|
+
resolve_project_id,
|
|
12
|
+
resolve_room,
|
|
13
|
+
resolve_key,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
from meshagent.tools.hosting import RemoteToolkit
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
from meshagent.api.services import ServiceHost
|
|
20
|
+
import os
|
|
21
|
+
|
|
22
|
+
import shlex
|
|
23
|
+
|
|
24
|
+
from meshagent.api import ParticipantToken, ApiScope
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _kv_to_dict(pairs: List[str]) -> dict[str, str]:
|
|
28
|
+
"""Convert ["A=1","B=2"] → {"A":"1","B":"2"}."""
|
|
29
|
+
out: dict[str, str] = {}
|
|
30
|
+
for p in pairs:
|
|
31
|
+
if "=" not in p:
|
|
32
|
+
raise typer.BadParameter(f"'{p}' must be KEY=VALUE")
|
|
33
|
+
k, v = p.split("=", 1)
|
|
34
|
+
out[k] = v
|
|
35
|
+
return out
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
app = async_typer.AsyncTyper()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@app.async_command("sse")
|
|
42
|
+
async def sse(
|
|
43
|
+
*,
|
|
44
|
+
project_id: ProjectIdOption = None,
|
|
45
|
+
room: RoomOption,
|
|
46
|
+
name: Annotated[str, typer.Option(..., help="Participant name")] = "cli",
|
|
47
|
+
role: str = "tool",
|
|
48
|
+
url: Annotated[str, typer.Option()],
|
|
49
|
+
toolkit_name: Annotated[Optional[str], typer.Option()] = None,
|
|
50
|
+
key: Annotated[
|
|
51
|
+
str,
|
|
52
|
+
typer.Option("--key", help="an api key to sign the token with"),
|
|
53
|
+
] = None,
|
|
54
|
+
):
|
|
55
|
+
from mcp.client.session import ClientSession
|
|
56
|
+
from mcp.client.sse import sse_client
|
|
57
|
+
|
|
58
|
+
from meshagent.mcp import MCPToolkit
|
|
59
|
+
|
|
60
|
+
key = await resolve_key(project_id=project_id, key=key)
|
|
61
|
+
|
|
62
|
+
if toolkit_name is None:
|
|
63
|
+
toolkit_name = "mcp"
|
|
64
|
+
|
|
65
|
+
account_client = await get_client()
|
|
66
|
+
try:
|
|
67
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
68
|
+
room = resolve_room(room)
|
|
69
|
+
|
|
70
|
+
token = ParticipantToken(
|
|
71
|
+
name=name,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
token.add_api_grant(ApiScope.agent_default())
|
|
75
|
+
|
|
76
|
+
token.add_role_grant(role=role)
|
|
77
|
+
token.add_room_grant(room)
|
|
78
|
+
|
|
79
|
+
jwt = token.to_jwt(api_key=key)
|
|
80
|
+
|
|
81
|
+
print("[bold green]Connecting to room...[/bold green]")
|
|
82
|
+
async with RoomClient(
|
|
83
|
+
protocol=WebSocketClientProtocol(
|
|
84
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
85
|
+
token=jwt,
|
|
86
|
+
)
|
|
87
|
+
) as client:
|
|
88
|
+
async with sse_client(url) as (read_stream, write_stream):
|
|
89
|
+
async with ClientSession(
|
|
90
|
+
read_stream=read_stream, write_stream=write_stream
|
|
91
|
+
) as session:
|
|
92
|
+
mcp_tools_response = await session.list_tools()
|
|
93
|
+
|
|
94
|
+
toolkit = MCPToolkit(
|
|
95
|
+
name=toolkit_name,
|
|
96
|
+
session=session,
|
|
97
|
+
tools=mcp_tools_response.tools,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
remote_toolkit = RemoteToolkit(
|
|
101
|
+
name=toolkit.name,
|
|
102
|
+
tools=toolkit.tools,
|
|
103
|
+
title=toolkit.title,
|
|
104
|
+
description=toolkit.description,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
await remote_toolkit.start(room=client)
|
|
108
|
+
try:
|
|
109
|
+
await client.protocol.wait_for_close()
|
|
110
|
+
except KeyboardInterrupt:
|
|
111
|
+
await remote_toolkit.stop()
|
|
112
|
+
|
|
113
|
+
except RoomException as e:
|
|
114
|
+
print(f"[red]{e}[/red]")
|
|
115
|
+
finally:
|
|
116
|
+
await account_client.close()
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@app.async_command("stdio")
|
|
120
|
+
async def stdio(
|
|
121
|
+
*,
|
|
122
|
+
project_id: ProjectIdOption = None,
|
|
123
|
+
room: RoomOption,
|
|
124
|
+
name: Annotated[str, typer.Option(..., help="Participant name")] = "cli",
|
|
125
|
+
role: str = "tool",
|
|
126
|
+
command: Annotated[str, typer.Option()],
|
|
127
|
+
toolkit_name: Annotated[Optional[str], typer.Option()] = None,
|
|
128
|
+
env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = [],
|
|
129
|
+
key: Annotated[
|
|
130
|
+
str,
|
|
131
|
+
typer.Option("--key", help="an api key to sign the token with"),
|
|
132
|
+
] = None,
|
|
133
|
+
):
|
|
134
|
+
from mcp.client.session import ClientSession
|
|
135
|
+
from mcp.client.stdio import stdio_client, StdioServerParameters
|
|
136
|
+
|
|
137
|
+
from meshagent.mcp import MCPToolkit
|
|
138
|
+
|
|
139
|
+
key = await resolve_key(project_id=project_id, key=key)
|
|
140
|
+
|
|
141
|
+
if toolkit_name is None:
|
|
142
|
+
toolkit_name = "mcp"
|
|
143
|
+
|
|
144
|
+
account_client = await get_client()
|
|
145
|
+
try:
|
|
146
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
147
|
+
room = resolve_room(room)
|
|
148
|
+
|
|
149
|
+
token = ParticipantToken(
|
|
150
|
+
name=name,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
token.add_api_grant(ApiScope.agent_default())
|
|
154
|
+
|
|
155
|
+
token.add_role_grant(role=role)
|
|
156
|
+
token.add_room_grant(room)
|
|
157
|
+
|
|
158
|
+
jwt = token.to_jwt(api_key=key)
|
|
159
|
+
|
|
160
|
+
print("[bold green]Connecting to room...[/bold green]")
|
|
161
|
+
async with RoomClient(
|
|
162
|
+
protocol=WebSocketClientProtocol(
|
|
163
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
164
|
+
token=jwt,
|
|
165
|
+
)
|
|
166
|
+
) as client:
|
|
167
|
+
parsed_command = shlex.split(command)
|
|
168
|
+
|
|
169
|
+
async with (
|
|
170
|
+
stdio_client(
|
|
171
|
+
StdioServerParameters(
|
|
172
|
+
command=parsed_command[0], # Executable
|
|
173
|
+
args=parsed_command[1:], # Optional command line arguments
|
|
174
|
+
env=_kv_to_dict(env), # Optional environment variables
|
|
175
|
+
)
|
|
176
|
+
) as (read_stream, write_stream)
|
|
177
|
+
):
|
|
178
|
+
async with ClientSession(
|
|
179
|
+
read_stream=read_stream, write_stream=write_stream
|
|
180
|
+
) as session:
|
|
181
|
+
mcp_tools_response = await session.list_tools()
|
|
182
|
+
|
|
183
|
+
toolkit = MCPToolkit(
|
|
184
|
+
name=toolkit_name,
|
|
185
|
+
session=session,
|
|
186
|
+
tools=mcp_tools_response.tools,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
remote_toolkit = RemoteToolkit(
|
|
190
|
+
name=toolkit.name,
|
|
191
|
+
tools=toolkit.tools,
|
|
192
|
+
title=toolkit.title,
|
|
193
|
+
description=toolkit.description,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
await remote_toolkit.start(room=client)
|
|
197
|
+
try:
|
|
198
|
+
await client.protocol.wait_for_close()
|
|
199
|
+
except KeyboardInterrupt:
|
|
200
|
+
await remote_toolkit.stop()
|
|
201
|
+
|
|
202
|
+
except RoomException as e:
|
|
203
|
+
print(f"[red]{e}[/red]")
|
|
204
|
+
finally:
|
|
205
|
+
await account_client.close()
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@app.async_command("http-proxy")
|
|
209
|
+
async def stdio_host(
|
|
210
|
+
*,
|
|
211
|
+
command: Annotated[str, typer.Option()],
|
|
212
|
+
host: Annotated[Optional[str], typer.Option()] = None,
|
|
213
|
+
port: Annotated[Optional[int], typer.Option()] = None,
|
|
214
|
+
path: Annotated[Optional[str], typer.Option()] = None,
|
|
215
|
+
name: Annotated[Optional[str], typer.Option()] = None,
|
|
216
|
+
env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = [],
|
|
217
|
+
):
|
|
218
|
+
from fastmcp import FastMCP, Client
|
|
219
|
+
from fastmcp.client.transports import StdioTransport
|
|
220
|
+
|
|
221
|
+
parsed_command = shlex.split(command)
|
|
222
|
+
|
|
223
|
+
# Create a client that connects to the original server
|
|
224
|
+
proxy_client = Client(
|
|
225
|
+
transport=StdioTransport(
|
|
226
|
+
parsed_command[0], parsed_command[1:], _kv_to_dict(env)
|
|
227
|
+
),
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
if name is None:
|
|
231
|
+
name = "Stdio-to-Streamable Http Proxy"
|
|
232
|
+
|
|
233
|
+
# Create a proxy server that connects to the client and exposes its capabilities
|
|
234
|
+
proxy = FastMCP.as_proxy(proxy_client, name=name)
|
|
235
|
+
if path is None:
|
|
236
|
+
path = "/mcp"
|
|
237
|
+
|
|
238
|
+
await proxy.run_async(transport="streamable-http", host=host, port=port, path=path)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
@app.async_command("sse-proxy")
|
|
242
|
+
async def sse_proxy(
|
|
243
|
+
*,
|
|
244
|
+
command: Annotated[str, typer.Option()],
|
|
245
|
+
host: Annotated[Optional[str], typer.Option()] = None,
|
|
246
|
+
port: Annotated[Optional[int], typer.Option()] = None,
|
|
247
|
+
path: Annotated[Optional[str], typer.Option()] = None,
|
|
248
|
+
name: Annotated[Optional[str], typer.Option()] = None,
|
|
249
|
+
env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = [],
|
|
250
|
+
):
|
|
251
|
+
from fastmcp import FastMCP, Client
|
|
252
|
+
from fastmcp.client.transports import StdioTransport
|
|
253
|
+
|
|
254
|
+
parsed_command = shlex.split(command)
|
|
255
|
+
|
|
256
|
+
# Create a client that connects to the original server
|
|
257
|
+
proxy_client = Client(
|
|
258
|
+
transport=StdioTransport(
|
|
259
|
+
parsed_command[0], parsed_command[1:], _kv_to_dict(env)
|
|
260
|
+
),
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
if name is None:
|
|
264
|
+
name = "Stdio-to-SSE Proxy"
|
|
265
|
+
|
|
266
|
+
# Create a proxy server that connects to the client and exposes its capabilities
|
|
267
|
+
proxy = FastMCP.as_proxy(proxy_client, name=name)
|
|
268
|
+
if path is None:
|
|
269
|
+
path = "/sse"
|
|
270
|
+
|
|
271
|
+
await proxy.run_async(transport="sse", host=host, port=port, path=path)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
@app.async_command("stdio-service")
|
|
275
|
+
async def stdio_service(
|
|
276
|
+
*,
|
|
277
|
+
command: Annotated[str, typer.Option()],
|
|
278
|
+
host: Annotated[Optional[str], typer.Option()] = None,
|
|
279
|
+
port: Annotated[Optional[int], typer.Option()] = None,
|
|
280
|
+
webhook_secret: Annotated[Optional[str], typer.Option()] = None,
|
|
281
|
+
path: Annotated[Optional[str], typer.Option()] = None,
|
|
282
|
+
toolkit_name: Annotated[Optional[str], typer.Option()] = None,
|
|
283
|
+
env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = [],
|
|
284
|
+
):
|
|
285
|
+
from mcp.client.session import ClientSession
|
|
286
|
+
from mcp.client.stdio import stdio_client, StdioServerParameters
|
|
287
|
+
|
|
288
|
+
from meshagent.mcp import MCPToolkit
|
|
289
|
+
|
|
290
|
+
try:
|
|
291
|
+
parsed_command = shlex.split(command)
|
|
292
|
+
|
|
293
|
+
async with (
|
|
294
|
+
stdio_client(
|
|
295
|
+
StdioServerParameters(
|
|
296
|
+
command=parsed_command[0], # Executable
|
|
297
|
+
args=parsed_command[1:], # Optional command line arguments
|
|
298
|
+
env=_kv_to_dict(env), # Optional environment variables
|
|
299
|
+
)
|
|
300
|
+
) as (read_stream, write_stream)
|
|
301
|
+
):
|
|
302
|
+
async with ClientSession(
|
|
303
|
+
read_stream=read_stream, write_stream=write_stream
|
|
304
|
+
) as session:
|
|
305
|
+
mcp_tools_response = await session.list_tools()
|
|
306
|
+
|
|
307
|
+
if toolkit_name is None:
|
|
308
|
+
toolkit_name = "mcp"
|
|
309
|
+
|
|
310
|
+
toolkit = MCPToolkit(
|
|
311
|
+
name=toolkit_name, session=session, tools=mcp_tools_response.tools
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
if port is None:
|
|
315
|
+
port = int(os.getenv("MESHAGENT_PORT", "8080"))
|
|
316
|
+
|
|
317
|
+
if host is None:
|
|
318
|
+
host = "0.0.0.0"
|
|
319
|
+
|
|
320
|
+
service_host = ServiceHost(
|
|
321
|
+
host=host, port=port, webhook_secret=webhook_secret
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
if path is None:
|
|
325
|
+
path = "/service"
|
|
326
|
+
|
|
327
|
+
print(
|
|
328
|
+
f"[bold green]Starting service host on {host}:{port}{path}...[/bold green]"
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
@service_host.path(path=path)
|
|
332
|
+
class CustomToolkit(RemoteToolkit):
|
|
333
|
+
def __init__(self):
|
|
334
|
+
super().__init__(
|
|
335
|
+
name=toolkit.name,
|
|
336
|
+
tools=toolkit.tools,
|
|
337
|
+
title=toolkit.title,
|
|
338
|
+
description=toolkit.description,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
await service_host.run()
|
|
342
|
+
|
|
343
|
+
except RoomException as e:
|
|
344
|
+
print(f"[red]{e}[/red]")
|