@saulwade/swl-ses 1.6.3 → 1.6.5
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.
- package/CLAUDE.md +3 -3
- package/README.md +2 -2
- package/agentes/gh-fix-ci-swl.md +275 -0
- package/agentes/nemesis-auditor-swl.md +90 -1
- package/comandos/swl/exportar-vault.md +106 -14
- package/comandos/swl/nemesis.md +70 -3
- package/comandos/swl/release.md +62 -2
- package/comandos/swl/salud.md +32 -0
- package/comandos/swl/verificar.md +116 -2
- package/habilidades/agent-browser/SKILL.md +111 -4
- package/habilidades/agent-deep-links/SKILL.md +148 -0
- package/habilidades/backend-async-postgres-testing/SKILL.md +215 -0
- package/habilidades/backend-error-design/SKILL.md +221 -0
- package/habilidades/browser-interaction-patterns/SKILL.md +514 -0
- package/habilidades/browser-research-domains/SKILL.md +635 -0
- package/habilidades/changelog-generator/SKILL.md +172 -0
- package/habilidades/changelog-generator/scripts/parse-commits.js +354 -0
- package/habilidades/devsecops-pipeline-security/SKILL.md +3 -0
- package/habilidades/fastapi-experto/SKILL.md +49 -4
- package/habilidades/harness-claude-code/SKILL.md +4 -1
- package/habilidades/postgresql-experto/SKILL.md +80 -4
- package/habilidades/proceso-discovery-machote/SKILL.md +157 -0
- package/habilidades/proceso-modular-split/SKILL.md +256 -0
- package/habilidades/tdd-workflow/SKILL.md +12 -5
- package/hooks/extraccion-aprendizajes.js +8 -0
- package/hooks/lib/deep-links.js +185 -0
- package/hooks/lib/evolution-tracker.js +115 -18
- package/hooks/lib/gateway-notify.js +70 -7
- package/manifiestos/modulos.json +13 -3
- package/manifiestos/skills-lock.json +1247 -1191
- package/package.json +3 -3
- package/plugin.json +11 -2
- package/reglas/arquitectura.md +38 -0
- package/reglas/arreglar-al-detectar.md +93 -0
- package/reglas/auditorias-documentales-estructurales.md +38 -0
- package/reglas/registro-componentes-nuevos.md +14 -0
- package/reglas/tests-cleanup.md +220 -0
- package/scripts/lib/mcp_config.py +29 -14
- package/scripts/mcp-orchestrator.py +153 -131
- package/scripts/mcp-pool-manager.py +132 -107
- package/scripts/mcp-telemetry.py +139 -120
- package/scripts/verificar-release.js +199 -1
|
@@ -32,8 +32,8 @@ from pathlib import Path
|
|
|
32
32
|
from typing import Any
|
|
33
33
|
|
|
34
34
|
# Importar helper compartido sin convertir scripts/ en paquete.
|
|
35
|
-
sys.path.insert(0, str(Path(__file__).resolve().parent /
|
|
36
|
-
from mcp_config import cargar_config_mcp # noqa: E402
|
|
35
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent / "lib"))
|
|
36
|
+
from mcp_config import build_stdio_env, cargar_config_mcp # noqa: E402
|
|
37
37
|
|
|
38
38
|
# ---------------------------------------------------------------------------
|
|
39
39
|
# Dependencias — raw mcp SDK (disponible en entornos con Claude Code)
|
|
@@ -42,6 +42,7 @@ try:
|
|
|
42
42
|
from mcp import ClientSession
|
|
43
43
|
from mcp.client.stdio import stdio_client, StdioServerParameters
|
|
44
44
|
from mcp.client.sse import sse_client
|
|
45
|
+
|
|
45
46
|
HAS_MCP = True
|
|
46
47
|
except ImportError:
|
|
47
48
|
HAS_MCP = False
|
|
@@ -50,8 +51,8 @@ except ImportError:
|
|
|
50
51
|
# Constantes
|
|
51
52
|
# ---------------------------------------------------------------------------
|
|
52
53
|
|
|
53
|
-
TIMEOUT_CONNECT_S = 10
|
|
54
|
-
TIMEOUT_CALL_S
|
|
54
|
+
TIMEOUT_CONNECT_S = 10 # segundos maximo para conectar a un servidor
|
|
55
|
+
TIMEOUT_CALL_S = 30 # segundos maximo para llamar una herramienta
|
|
55
56
|
|
|
56
57
|
# ---------------------------------------------------------------------------
|
|
57
58
|
# Carga de configuracion — delega a scripts/lib/mcp_config.py
|
|
@@ -66,34 +67,33 @@ def _cargar_config(cwd: Path, config_path: str | None = None) -> dict:
|
|
|
66
67
|
def _get_server(servers: dict, nombre: str) -> dict:
|
|
67
68
|
"""Retorna la config de un servidor o termina con error."""
|
|
68
69
|
if nombre not in servers:
|
|
69
|
-
sys.stderr.write(f
|
|
70
|
-
sys.stderr.write(
|
|
70
|
+
sys.stderr.write(f"[mcp-pool] Servidor no encontrado: {nombre}\n")
|
|
71
|
+
sys.stderr.write(
|
|
72
|
+
f'[mcp-pool] Servidores disponibles: {", ".join(servers.keys())}\n'
|
|
73
|
+
)
|
|
71
74
|
sys.exit(1)
|
|
72
75
|
return servers[nombre]
|
|
73
76
|
|
|
77
|
+
|
|
74
78
|
# ---------------------------------------------------------------------------
|
|
75
79
|
# Fabrica de transporte
|
|
76
80
|
# ---------------------------------------------------------------------------
|
|
77
81
|
|
|
78
82
|
|
|
79
|
-
def _build_env(cfg: dict) -> dict
|
|
83
|
+
def _build_env(cfg: dict) -> dict:
|
|
80
84
|
"""Combina el entorno del proceso con las variables de entorno del servidor."""
|
|
81
|
-
|
|
82
|
-
if not extra:
|
|
83
|
-
return None
|
|
84
|
-
merged = dict(os.environ)
|
|
85
|
-
merged.update(extra)
|
|
86
|
-
return merged
|
|
85
|
+
return build_stdio_env(cfg)
|
|
87
86
|
|
|
88
87
|
|
|
89
88
|
def _make_stdio_params(cfg: dict) -> StdioServerParameters:
|
|
90
89
|
return StdioServerParameters(
|
|
91
|
-
command=cfg[
|
|
92
|
-
args=cfg.get(
|
|
90
|
+
command=cfg["command"],
|
|
91
|
+
args=cfg.get("args", []),
|
|
93
92
|
env=_build_env(cfg),
|
|
94
|
-
cwd=cfg.get(
|
|
93
|
+
cwd=cfg.get("cwd"),
|
|
95
94
|
)
|
|
96
95
|
|
|
96
|
+
|
|
97
97
|
# ---------------------------------------------------------------------------
|
|
98
98
|
# Operaciones MCP (async helpers)
|
|
99
99
|
# ---------------------------------------------------------------------------
|
|
@@ -101,43 +101,51 @@ def _make_stdio_params(cfg: dict) -> StdioServerParameters:
|
|
|
101
101
|
|
|
102
102
|
async def _list_tools_server(nombre: str, cfg: dict) -> dict:
|
|
103
103
|
"""Conecta a un servidor MCP y lista sus herramientas. Tolera errores."""
|
|
104
|
-
resultado: dict = {
|
|
104
|
+
resultado: dict = {"server": nombre, "tools": [], "error": None, "duration_ms": 0}
|
|
105
105
|
t0 = time.time()
|
|
106
106
|
try:
|
|
107
|
-
if
|
|
108
|
-
transport = sse_client(cfg[
|
|
107
|
+
if "url" in cfg:
|
|
108
|
+
transport = sse_client(cfg["url"])
|
|
109
109
|
else:
|
|
110
110
|
transport = stdio_client(_make_stdio_params(cfg))
|
|
111
111
|
|
|
112
112
|
async with transport as (read, write):
|
|
113
113
|
async with ClientSession(read, write) as session:
|
|
114
114
|
await asyncio.wait_for(session.initialize(), timeout=TIMEOUT_CONNECT_S)
|
|
115
|
-
resp = await asyncio.wait_for(
|
|
116
|
-
|
|
115
|
+
resp = await asyncio.wait_for(
|
|
116
|
+
session.list_tools(), timeout=TIMEOUT_CONNECT_S
|
|
117
|
+
)
|
|
118
|
+
resultado["tools"] = [
|
|
117
119
|
{
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
"name": t.name,
|
|
121
|
+
"description": t.description or "",
|
|
122
|
+
"schema": t.inputSchema or {},
|
|
121
123
|
}
|
|
122
124
|
for t in (resp.tools or [])
|
|
123
125
|
]
|
|
124
126
|
except asyncio.TimeoutError:
|
|
125
|
-
resultado[
|
|
127
|
+
resultado["error"] = f"Timeout al conectar ({TIMEOUT_CONNECT_S}s)"
|
|
126
128
|
except Exception as exc:
|
|
127
|
-
resultado[
|
|
129
|
+
resultado["error"] = str(exc)
|
|
128
130
|
finally:
|
|
129
|
-
resultado[
|
|
131
|
+
resultado["duration_ms"] = int((time.time() - t0) * 1000)
|
|
130
132
|
return resultado
|
|
131
133
|
|
|
132
134
|
|
|
133
135
|
async def _call_tool_server(nombre: str, cfg: dict, tool: str, args: dict) -> dict:
|
|
134
136
|
"""Llama una herramienta en un servidor MCP."""
|
|
135
|
-
resultado: dict = {
|
|
136
|
-
|
|
137
|
+
resultado: dict = {
|
|
138
|
+
"server": nombre,
|
|
139
|
+
"tool": tool,
|
|
140
|
+
"result": None,
|
|
141
|
+
"is_error": False,
|
|
142
|
+
"error": None,
|
|
143
|
+
"duration_ms": 0,
|
|
144
|
+
}
|
|
137
145
|
t0 = time.time()
|
|
138
146
|
try:
|
|
139
|
-
if
|
|
140
|
-
transport = sse_client(cfg[
|
|
147
|
+
if "url" in cfg:
|
|
148
|
+
transport = sse_client(cfg["url"])
|
|
141
149
|
else:
|
|
142
150
|
transport = stdio_client(_make_stdio_params(cfg))
|
|
143
151
|
|
|
@@ -147,19 +155,20 @@ async def _call_tool_server(nombre: str, cfg: dict, tool: str, args: dict) -> di
|
|
|
147
155
|
resp = await asyncio.wait_for(
|
|
148
156
|
session.call_tool(tool, args), timeout=TIMEOUT_CALL_S
|
|
149
157
|
)
|
|
150
|
-
resultado[
|
|
151
|
-
resultado[
|
|
152
|
-
c.text if hasattr(c,
|
|
158
|
+
resultado["is_error"] = bool(getattr(resp, "isError", False))
|
|
159
|
+
resultado["result"] = [
|
|
160
|
+
c.text if hasattr(c, "text") else str(c)
|
|
153
161
|
for c in (resp.content or [])
|
|
154
162
|
]
|
|
155
163
|
except asyncio.TimeoutError:
|
|
156
|
-
resultado[
|
|
164
|
+
resultado["error"] = f"Timeout al llamar herramienta ({TIMEOUT_CALL_S}s)"
|
|
157
165
|
except Exception as exc:
|
|
158
|
-
resultado[
|
|
166
|
+
resultado["error"] = str(exc)
|
|
159
167
|
finally:
|
|
160
|
-
resultado[
|
|
168
|
+
resultado["duration_ms"] = int((time.time() - t0) * 1000)
|
|
161
169
|
return resultado
|
|
162
170
|
|
|
171
|
+
|
|
163
172
|
# ---------------------------------------------------------------------------
|
|
164
173
|
# Subcomandos
|
|
165
174
|
# ---------------------------------------------------------------------------
|
|
@@ -169,94 +178,104 @@ async def cmd_list_servers(servers: dict, as_json: bool) -> None:
|
|
|
169
178
|
out = sys.stdout.write
|
|
170
179
|
if as_json:
|
|
171
180
|
payload = [
|
|
172
|
-
{
|
|
173
|
-
|
|
181
|
+
{
|
|
182
|
+
"name": n,
|
|
183
|
+
"transport": "http" if "url" in c else "stdio",
|
|
184
|
+
"command": c.get("url")
|
|
185
|
+
or f"{c.get('command', '?')} {' '.join(c.get('args', []))}",
|
|
186
|
+
}
|
|
174
187
|
for n, c in servers.items()
|
|
175
188
|
]
|
|
176
|
-
out(json.dumps(payload, ensure_ascii=False, indent=2) +
|
|
189
|
+
out(json.dumps(payload, ensure_ascii=False, indent=2) + "\n")
|
|
177
190
|
return
|
|
178
|
-
out(f
|
|
179
|
-
out(
|
|
191
|
+
out(f"Servidores MCP configurados ({len(servers)}):\n")
|
|
192
|
+
out("-" * 60 + "\n")
|
|
180
193
|
for nombre, cfg in servers.items():
|
|
181
|
-
if
|
|
194
|
+
if "url" in cfg:
|
|
182
195
|
detalle = f"HTTP {cfg['url']}"
|
|
183
196
|
else:
|
|
184
197
|
detalle = f"stdio {cfg.get('command', '?')} {' '.join(cfg.get('args', []))}"
|
|
185
|
-
out(f
|
|
198
|
+
out(f" {nombre:<28} {detalle}\n")
|
|
186
199
|
|
|
187
200
|
|
|
188
|
-
async def cmd_list_tools(
|
|
201
|
+
async def cmd_list_tools(
|
|
202
|
+
servers: dict, server_filter: str | None, as_json: bool
|
|
203
|
+
) -> None:
|
|
189
204
|
out = sys.stdout.write
|
|
190
205
|
targets = {server_filter: servers[server_filter]} if server_filter else servers
|
|
191
|
-
tareas
|
|
206
|
+
tareas = [_list_tools_server(n, c) for n, c in targets.items()]
|
|
192
207
|
resultados = await asyncio.gather(*tareas)
|
|
193
208
|
|
|
194
209
|
if as_json:
|
|
195
|
-
out(json.dumps(resultados, ensure_ascii=False, indent=2) +
|
|
210
|
+
out(json.dumps(resultados, ensure_ascii=False, indent=2) + "\n")
|
|
196
211
|
return
|
|
197
212
|
|
|
198
213
|
for r in resultados:
|
|
199
|
-
if r[
|
|
214
|
+
if r["error"]:
|
|
200
215
|
out(f'\n[{r["server"]}] ERROR: {r["error"]}\n')
|
|
201
216
|
continue
|
|
202
|
-
out(
|
|
203
|
-
|
|
204
|
-
|
|
217
|
+
out(
|
|
218
|
+
f'\n[{r["server"]}] {len(r["tools"])} herramientas ({r["duration_ms"]}ms):\n'
|
|
219
|
+
)
|
|
220
|
+
for t in r["tools"]:
|
|
221
|
+
desc = t["description"]
|
|
205
222
|
if len(desc) > 80:
|
|
206
|
-
desc = desc[:77] +
|
|
223
|
+
desc = desc[:77] + "..."
|
|
207
224
|
out(f' - {t["name"]:<32} {desc}\n')
|
|
208
225
|
|
|
209
226
|
|
|
210
227
|
async def cmd_ping(servers: dict, server_filter: str | None, as_json: bool) -> None:
|
|
211
228
|
out = sys.stdout.write
|
|
212
|
-
targets
|
|
213
|
-
tareas
|
|
229
|
+
targets = {server_filter: servers[server_filter]} if server_filter else servers
|
|
230
|
+
tareas = [_list_tools_server(n, c) for n, c in targets.items()]
|
|
214
231
|
resultados = await asyncio.gather(*tareas)
|
|
215
232
|
|
|
216
233
|
pings = [
|
|
217
234
|
{
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
235
|
+
"server": r["server"],
|
|
236
|
+
"estado": "OK" if not r["error"] else "ERROR",
|
|
237
|
+
"herramientas": len(r["tools"]),
|
|
238
|
+
"duration_ms": r["duration_ms"],
|
|
239
|
+
"error": r["error"],
|
|
223
240
|
}
|
|
224
241
|
for r in resultados
|
|
225
242
|
]
|
|
226
243
|
|
|
227
244
|
if as_json:
|
|
228
|
-
out(json.dumps(pings, ensure_ascii=False, indent=2) +
|
|
245
|
+
out(json.dumps(pings, ensure_ascii=False, indent=2) + "\n")
|
|
229
246
|
return
|
|
230
247
|
|
|
231
|
-
out(
|
|
232
|
-
out(
|
|
248
|
+
out("\nPing a servidores MCP:\n")
|
|
249
|
+
out("-" * 64 + "\n")
|
|
233
250
|
for p in pings:
|
|
234
|
-
estado = p[
|
|
235
|
-
ms
|
|
236
|
-
tools
|
|
237
|
-
sufijo = f' ({p["error"]})' if p[
|
|
251
|
+
estado = p["estado"]
|
|
252
|
+
ms = p["duration_ms"]
|
|
253
|
+
tools = p["herramientas"]
|
|
254
|
+
sufijo = f' ({p["error"]})' if p["error"] else ""
|
|
238
255
|
out(f' {p["server"]:<28} {estado:<6} {tools:>3} tools {ms:>5}ms{sufijo}\n')
|
|
239
256
|
|
|
240
257
|
|
|
241
|
-
async def cmd_call_tool(
|
|
242
|
-
|
|
258
|
+
async def cmd_call_tool(
|
|
259
|
+
servers: dict, server_name: str, tool: str, tool_args: dict, as_json: bool
|
|
260
|
+
) -> None:
|
|
243
261
|
out = sys.stdout.write
|
|
244
262
|
cfg = _get_server(servers, server_name)
|
|
245
|
-
r
|
|
263
|
+
r = await _call_tool_server(server_name, cfg, tool, tool_args)
|
|
246
264
|
|
|
247
265
|
if as_json:
|
|
248
|
-
out(json.dumps(r, ensure_ascii=False, indent=2) +
|
|
266
|
+
out(json.dumps(r, ensure_ascii=False, indent=2) + "\n")
|
|
249
267
|
return
|
|
250
268
|
|
|
251
|
-
if r[
|
|
269
|
+
if r["error"]:
|
|
252
270
|
out(f'ERROR ({r["duration_ms"]}ms): {r["error"]}\n')
|
|
253
271
|
return
|
|
254
|
-
if r[
|
|
272
|
+
if r["is_error"]:
|
|
255
273
|
out(f'Tool error ({r["duration_ms"]}ms):\n')
|
|
256
274
|
else:
|
|
257
275
|
out(f'Resultado ({r["duration_ms"]}ms):\n')
|
|
258
|
-
for linea in
|
|
259
|
-
out(f
|
|
276
|
+
for linea in r["result"] or []:
|
|
277
|
+
out(f"{linea}\n")
|
|
278
|
+
|
|
260
279
|
|
|
261
280
|
# ---------------------------------------------------------------------------
|
|
262
281
|
# CLI
|
|
@@ -264,78 +283,84 @@ async def cmd_call_tool(servers: dict, server_name: str, tool: str,
|
|
|
264
283
|
|
|
265
284
|
|
|
266
285
|
def main() -> None:
|
|
267
|
-
if hasattr(sys.stdout,
|
|
268
|
-
sys.stdout.reconfigure(encoding=
|
|
286
|
+
if hasattr(sys.stdout, "reconfigure"):
|
|
287
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
269
288
|
|
|
270
289
|
if not HAS_MCP:
|
|
271
290
|
sys.stderr.write(
|
|
272
|
-
|
|
273
|
-
|
|
291
|
+
"[mcp-pool] ERROR: la libreria mcp no esta instalada.\n"
|
|
292
|
+
"[mcp-pool] Ejecuta: pip install mcp\n"
|
|
274
293
|
)
|
|
275
294
|
sys.exit(1)
|
|
276
295
|
|
|
277
296
|
parser = argparse.ArgumentParser(
|
|
278
|
-
description=
|
|
297
|
+
description="Gestor de conexiones MCP para swl-ses"
|
|
279
298
|
)
|
|
280
|
-
parser.add_argument(
|
|
281
|
-
parser.add_argument(
|
|
282
|
-
parser.add_argument(
|
|
299
|
+
parser.add_argument("--json", action="store_true", help="Salida en formato JSON")
|
|
300
|
+
parser.add_argument("--config", default=None, help="Ruta al archivo de config MCP")
|
|
301
|
+
parser.add_argument("--cwd", default=".", help="Directorio raiz del proyecto")
|
|
283
302
|
|
|
284
|
-
sub = parser.add_subparsers(dest=
|
|
303
|
+
sub = parser.add_subparsers(dest="cmd")
|
|
285
304
|
|
|
286
|
-
sub.add_parser(
|
|
305
|
+
sub.add_parser("list-servers", help="Lista servidores MCP configurados")
|
|
287
306
|
|
|
288
|
-
p_tools = sub.add_parser(
|
|
289
|
-
p_tools.add_argument(
|
|
307
|
+
p_tools = sub.add_parser("list-tools", help="Lista herramientas de servidor(es)")
|
|
308
|
+
p_tools.add_argument("servidor", nargs="?", help="Nombre del servidor (opcional)")
|
|
290
309
|
|
|
291
|
-
p_ping = sub.add_parser(
|
|
292
|
-
p_ping.add_argument(
|
|
310
|
+
p_ping = sub.add_parser("ping", help="Verifica conectividad de servidor(es)")
|
|
311
|
+
p_ping.add_argument("servidor", nargs="?", help="Nombre del servidor (opcional)")
|
|
293
312
|
|
|
294
|
-
p_call = sub.add_parser(
|
|
295
|
-
p_call.add_argument(
|
|
296
|
-
p_call.add_argument(
|
|
297
|
-
p_call.add_argument(
|
|
298
|
-
|
|
313
|
+
p_call = sub.add_parser("call-tool", help="Llama una herramienta MCP")
|
|
314
|
+
p_call.add_argument("servidor", help="Nombre del servidor")
|
|
315
|
+
p_call.add_argument("herramienta", help="Nombre de la herramienta")
|
|
316
|
+
p_call.add_argument(
|
|
317
|
+
"args",
|
|
318
|
+
nargs="?",
|
|
319
|
+
default="{}",
|
|
320
|
+
help="Argumentos JSON de la herramienta (default: {})",
|
|
321
|
+
)
|
|
299
322
|
|
|
300
|
-
args
|
|
301
|
-
cwd
|
|
323
|
+
args = parser.parse_args()
|
|
324
|
+
cwd = Path(args.cwd).resolve()
|
|
302
325
|
servers = _cargar_config(cwd, args.config)
|
|
303
326
|
|
|
304
327
|
if not servers:
|
|
305
328
|
sys.stderr.write(
|
|
306
|
-
|
|
329
|
+
"[mcp-pool] No se encontraron servidores MCP configurados.\n"
|
|
307
330
|
'[mcp-pool] Verifica la clave "mcpServers" en .claude/settings.json\n'
|
|
308
331
|
)
|
|
309
332
|
sys.exit(1)
|
|
310
333
|
|
|
311
|
-
as_json = bool(getattr(args,
|
|
334
|
+
as_json = bool(getattr(args, "json", False))
|
|
312
335
|
|
|
313
|
-
if args.cmd ==
|
|
336
|
+
if args.cmd == "list-servers":
|
|
314
337
|
asyncio.run(cmd_list_servers(servers, as_json))
|
|
315
338
|
|
|
316
|
-
elif args.cmd ==
|
|
317
|
-
servidor = getattr(args,
|
|
339
|
+
elif args.cmd == "list-tools":
|
|
340
|
+
servidor = getattr(args, "servidor", None)
|
|
318
341
|
if servidor:
|
|
319
|
-
_get_server(servers, servidor)
|
|
342
|
+
_get_server(servers, servidor) # valida que exista
|
|
320
343
|
asyncio.run(cmd_list_tools(servers, servidor, as_json))
|
|
321
344
|
|
|
322
|
-
elif args.cmd ==
|
|
323
|
-
servidor = getattr(args,
|
|
345
|
+
elif args.cmd == "ping":
|
|
346
|
+
servidor = getattr(args, "servidor", None)
|
|
324
347
|
if servidor:
|
|
325
348
|
_get_server(servers, servidor)
|
|
326
349
|
asyncio.run(cmd_ping(servers, servidor, as_json))
|
|
327
350
|
|
|
328
|
-
elif args.cmd ==
|
|
351
|
+
elif args.cmd == "call-tool":
|
|
329
352
|
try:
|
|
330
353
|
tool_args = json.loads(args.args)
|
|
331
354
|
except json.JSONDecodeError:
|
|
332
|
-
sys.stderr.write(f
|
|
355
|
+
sys.stderr.write(f"[mcp-pool] Argumentos JSON invalidos: {args.args}\n")
|
|
333
356
|
sys.exit(1)
|
|
334
|
-
asyncio.run(
|
|
357
|
+
asyncio.run(
|
|
358
|
+
cmd_call_tool(servers, args.servidor, args.herramienta, tool_args, as_json)
|
|
359
|
+
)
|
|
335
360
|
|
|
336
361
|
else:
|
|
337
362
|
parser.print_help()
|
|
338
363
|
|
|
339
364
|
|
|
340
|
-
if __name__ ==
|
|
365
|
+
if __name__ == "__main__":
|
|
341
366
|
main()
|