mcp2cli 2.7.0__tar.gz → 2.8.0__tar.gz
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.
- {mcp2cli-2.7.0 → mcp2cli-2.8.0}/PKG-INFO +1 -1
- {mcp2cli-2.7.0 → mcp2cli-2.8.0}/pyproject.toml +1 -1
- {mcp2cli-2.7.0 → mcp2cli-2.8.0}/src/mcp2cli/__init__.py +260 -19
- {mcp2cli-2.7.0 → mcp2cli-2.8.0}/README.md +0 -0
- {mcp2cli-2.7.0 → mcp2cli-2.8.0}/src/mcp2cli/__main__.py +0 -0
- {mcp2cli-2.7.0 → mcp2cli-2.8.0}/src/mcp2cli/py.typed +0 -0
|
@@ -26,6 +26,8 @@ from http.server import HTTPServer, BaseHTTPRequestHandler
|
|
|
26
26
|
from pathlib import Path
|
|
27
27
|
from urllib.parse import parse_qs, urlparse
|
|
28
28
|
|
|
29
|
+
from datetime import datetime, timezone
|
|
30
|
+
|
|
29
31
|
import anyio
|
|
30
32
|
import httpx
|
|
31
33
|
|
|
@@ -33,6 +35,7 @@ CACHE_DIR = Path(
|
|
|
33
35
|
os.environ.get("MCP2CLI_CACHE_DIR", Path.home() / ".cache" / "mcp2cli")
|
|
34
36
|
)
|
|
35
37
|
DEFAULT_CACHE_TTL = 3600
|
|
38
|
+
USAGE_FILE = CACHE_DIR / "usage.json"
|
|
36
39
|
CONFIG_DIR = Path(
|
|
37
40
|
os.environ.get("MCP2CLI_CONFIG_DIR", Path.home() / ".config" / "mcp2cli")
|
|
38
41
|
)
|
|
@@ -387,6 +390,94 @@ def save_cache(key: str, data: dict):
|
|
|
387
390
|
(CACHE_DIR / f"{key}.json").write_text(json.dumps(data))
|
|
388
391
|
|
|
389
392
|
|
|
393
|
+
# ---------------------------------------------------------------------------
|
|
394
|
+
# Usage tracking
|
|
395
|
+
# ---------------------------------------------------------------------------
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def _load_usage() -> dict:
|
|
399
|
+
"""Load the usage tracking file. Returns empty dict on any failure."""
|
|
400
|
+
if not USAGE_FILE.exists():
|
|
401
|
+
return {}
|
|
402
|
+
try:
|
|
403
|
+
return json.loads(USAGE_FILE.read_text())
|
|
404
|
+
except (json.JSONDecodeError, OSError):
|
|
405
|
+
return {}
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def _save_usage(data: dict) -> None:
|
|
409
|
+
"""Write usage data. Last-write-wins -- no file locking."""
|
|
410
|
+
CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
|
411
|
+
USAGE_FILE.write_text(json.dumps(data, indent=2))
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def record_usage(source_hash: str, tool_name: str) -> None:
|
|
415
|
+
"""Increment the call count and update last_used for a tool."""
|
|
416
|
+
usage = _load_usage()
|
|
417
|
+
bucket = usage.setdefault(source_hash, {})
|
|
418
|
+
entry = bucket.setdefault(tool_name, {"count": 0, "last_used": ""})
|
|
419
|
+
entry["count"] += 1
|
|
420
|
+
entry["last_used"] = datetime.now(timezone.utc).isoformat()
|
|
421
|
+
_save_usage(usage)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _source_hash_for(source: str) -> str:
|
|
425
|
+
"""Derive a stable hash key from a source URL/command string."""
|
|
426
|
+
return hashlib.sha256(source.encode()).hexdigest()[:16]
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
def sort_commands(
|
|
430
|
+
commands: list["CommandDef"],
|
|
431
|
+
sort_mode: str,
|
|
432
|
+
source_hash: str,
|
|
433
|
+
) -> list["CommandDef"]:
|
|
434
|
+
"""Sort commands by the given mode using usage data.
|
|
435
|
+
|
|
436
|
+
Modes:
|
|
437
|
+
usage -- most-called first (default when usage data exists)
|
|
438
|
+
recent -- most-recently-used first
|
|
439
|
+
alpha -- alphabetical by name
|
|
440
|
+
default -- original insertion order
|
|
441
|
+
"""
|
|
442
|
+
if sort_mode == "default":
|
|
443
|
+
return commands
|
|
444
|
+
if sort_mode == "alpha":
|
|
445
|
+
return sorted(commands, key=lambda c: c.name)
|
|
446
|
+
|
|
447
|
+
usage = _load_usage().get(source_hash, {})
|
|
448
|
+
if not usage:
|
|
449
|
+
return commands # no data, keep insertion order
|
|
450
|
+
|
|
451
|
+
def _usage_key(c: "CommandDef") -> str:
|
|
452
|
+
return c.tool_name or c.graphql_field_name or c.name
|
|
453
|
+
|
|
454
|
+
if sort_mode == "usage":
|
|
455
|
+
return sorted(
|
|
456
|
+
commands,
|
|
457
|
+
key=lambda c: usage.get(_usage_key(c), {}).get("count", 0),
|
|
458
|
+
reverse=True,
|
|
459
|
+
)
|
|
460
|
+
if sort_mode == "recent":
|
|
461
|
+
return sorted(
|
|
462
|
+
commands,
|
|
463
|
+
key=lambda c: usage.get(_usage_key(c), {}).get("last_used", ""),
|
|
464
|
+
reverse=True,
|
|
465
|
+
)
|
|
466
|
+
return commands
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
def _resolve_sort_mode(explicit_sort: str | None, source_hash: str) -> str:
|
|
470
|
+
"""Determine the effective sort mode.
|
|
471
|
+
|
|
472
|
+
If the user passed --sort explicitly, use that. Otherwise, default to
|
|
473
|
+
'usage' when usage data exists for this source, else 'default'.
|
|
474
|
+
"""
|
|
475
|
+
if explicit_sort is not None:
|
|
476
|
+
return explicit_sort
|
|
477
|
+
usage = _load_usage().get(source_hash, {})
|
|
478
|
+
return "usage" if usage else "default"
|
|
479
|
+
|
|
480
|
+
|
|
390
481
|
# ---------------------------------------------------------------------------
|
|
391
482
|
# OAuth support
|
|
392
483
|
# ---------------------------------------------------------------------------
|
|
@@ -1225,8 +1316,20 @@ def _wrap_description(description: str, indent: int, total_width: int = 110) ->
|
|
|
1225
1316
|
)
|
|
1226
1317
|
|
|
1227
1318
|
|
|
1228
|
-
def list_graphql_commands(
|
|
1319
|
+
def list_graphql_commands(
|
|
1320
|
+
commands: list[CommandDef],
|
|
1321
|
+
verbose: bool = False,
|
|
1322
|
+
compact: bool = False,
|
|
1323
|
+
source_hash: str = "",
|
|
1324
|
+
sort_mode: str | None = None,
|
|
1325
|
+
top: int | None = None,
|
|
1326
|
+
):
|
|
1229
1327
|
"""Group commands by operation type and print."""
|
|
1328
|
+
commands = _apply_list_options(commands, source_hash, sort_mode, top)
|
|
1329
|
+
|
|
1330
|
+
if compact:
|
|
1331
|
+
print(" ".join(cmd.name for cmd in commands))
|
|
1332
|
+
return
|
|
1230
1333
|
|
|
1231
1334
|
groups: dict[str, list[CommandDef]] = {}
|
|
1232
1335
|
for cmd in commands:
|
|
@@ -1364,19 +1467,30 @@ def handle_graphql(
|
|
|
1364
1467
|
jq_expr: str | None = None,
|
|
1365
1468
|
head: int | None = None,
|
|
1366
1469
|
verbose: bool = False,
|
|
1470
|
+
sort_mode: str | None = None,
|
|
1471
|
+
top: int | None = None,
|
|
1472
|
+
compact: bool = False,
|
|
1367
1473
|
):
|
|
1368
1474
|
"""Top-level handler for --graphql mode."""
|
|
1475
|
+
src_hash = _source_hash_for(url)
|
|
1369
1476
|
schema = load_graphql_schema(url, auth_headers, cache_key, ttl, refresh, oauth_provider=oauth_provider)
|
|
1370
1477
|
commands = extract_graphql_commands(schema)
|
|
1371
1478
|
|
|
1479
|
+
list_kwargs = dict(
|
|
1480
|
+
verbose=verbose, compact=compact,
|
|
1481
|
+
source_hash=src_hash, sort_mode=sort_mode, top=top,
|
|
1482
|
+
)
|
|
1483
|
+
|
|
1372
1484
|
if list_mode:
|
|
1373
|
-
list_graphql_commands(commands,
|
|
1485
|
+
list_graphql_commands(commands, **list_kwargs)
|
|
1374
1486
|
return
|
|
1375
1487
|
|
|
1376
1488
|
if not remaining:
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1489
|
+
if not compact:
|
|
1490
|
+
print("Available operations:")
|
|
1491
|
+
list_graphql_commands(commands, **list_kwargs)
|
|
1492
|
+
if not compact:
|
|
1493
|
+
print("\nUse --list for the same output, or provide a subcommand.")
|
|
1380
1494
|
return
|
|
1381
1495
|
|
|
1382
1496
|
pre_for_gql = argparse.ArgumentParser(add_help=False)
|
|
@@ -1394,6 +1508,9 @@ def handle_graphql(
|
|
|
1394
1508
|
jq_expr=jq_expr, head=head,
|
|
1395
1509
|
)
|
|
1396
1510
|
|
|
1511
|
+
# Record usage after successful execution
|
|
1512
|
+
record_usage(src_hash, cmd.graphql_field_name or cmd.name)
|
|
1513
|
+
|
|
1397
1514
|
|
|
1398
1515
|
# ---------------------------------------------------------------------------
|
|
1399
1516
|
# Command filtering (bake mode)
|
|
@@ -1820,7 +1937,34 @@ def build_argparse(
|
|
|
1820
1937
|
# ---------------------------------------------------------------------------
|
|
1821
1938
|
|
|
1822
1939
|
|
|
1823
|
-
def
|
|
1940
|
+
def _apply_list_options(
|
|
1941
|
+
commands: list[CommandDef],
|
|
1942
|
+
source_hash: str = "",
|
|
1943
|
+
sort_mode: str | None = None,
|
|
1944
|
+
top: int | None = None,
|
|
1945
|
+
) -> list[CommandDef]:
|
|
1946
|
+
"""Apply sort and top-N filtering to a command list."""
|
|
1947
|
+
effective_sort = _resolve_sort_mode(sort_mode, source_hash)
|
|
1948
|
+
commands = sort_commands(commands, effective_sort, source_hash)
|
|
1949
|
+
if top is not None:
|
|
1950
|
+
commands = commands[:top]
|
|
1951
|
+
return commands
|
|
1952
|
+
|
|
1953
|
+
|
|
1954
|
+
def list_openapi_commands(
|
|
1955
|
+
commands: list[CommandDef],
|
|
1956
|
+
verbose: bool = False,
|
|
1957
|
+
compact: bool = False,
|
|
1958
|
+
source_hash: str = "",
|
|
1959
|
+
sort_mode: str | None = None,
|
|
1960
|
+
top: int | None = None,
|
|
1961
|
+
):
|
|
1962
|
+
commands = _apply_list_options(commands, source_hash, sort_mode, top)
|
|
1963
|
+
|
|
1964
|
+
if compact:
|
|
1965
|
+
print(" ".join(cmd.name for cmd in commands))
|
|
1966
|
+
return
|
|
1967
|
+
|
|
1824
1968
|
groups: dict[str, list[CommandDef]] = {}
|
|
1825
1969
|
for cmd in commands:
|
|
1826
1970
|
prefix = cmd.name.split("-", 1)[0] if "-" in cmd.name else "other"
|
|
@@ -1840,7 +1984,20 @@ def list_openapi_commands(commands: list[CommandDef], verbose: bool = False):
|
|
|
1840
1984
|
print(line)
|
|
1841
1985
|
|
|
1842
1986
|
|
|
1843
|
-
def list_mcp_commands(
|
|
1987
|
+
def list_mcp_commands(
|
|
1988
|
+
commands: list[CommandDef],
|
|
1989
|
+
verbose: bool = False,
|
|
1990
|
+
compact: bool = False,
|
|
1991
|
+
source_hash: str = "",
|
|
1992
|
+
sort_mode: str | None = None,
|
|
1993
|
+
top: int | None = None,
|
|
1994
|
+
):
|
|
1995
|
+
commands = _apply_list_options(commands, source_hash, sort_mode, top)
|
|
1996
|
+
|
|
1997
|
+
if compact:
|
|
1998
|
+
print(" ".join(cmd.name for cmd in commands))
|
|
1999
|
+
return
|
|
2000
|
+
|
|
1844
2001
|
for cmd in commands:
|
|
1845
2002
|
if cmd.description:
|
|
1846
2003
|
if verbose:
|
|
@@ -2030,6 +2187,10 @@ def run_mcp_http(
|
|
|
2030
2187
|
jq_expr: str | None = None,
|
|
2031
2188
|
head: int | None = None,
|
|
2032
2189
|
verbose: bool = False,
|
|
2190
|
+
sort_mode: str | None = None,
|
|
2191
|
+
top: int | None = None,
|
|
2192
|
+
compact: bool = False,
|
|
2193
|
+
source_hash: str = "",
|
|
2033
2194
|
):
|
|
2034
2195
|
extra = dict(
|
|
2035
2196
|
resource_action=resource_action,
|
|
@@ -2041,6 +2202,10 @@ def run_mcp_http(
|
|
|
2041
2202
|
jq_expr=jq_expr,
|
|
2042
2203
|
head=head,
|
|
2043
2204
|
verbose=verbose,
|
|
2205
|
+
sort_mode=sort_mode,
|
|
2206
|
+
top=top,
|
|
2207
|
+
compact=compact,
|
|
2208
|
+
source_hash=source_hash,
|
|
2044
2209
|
)
|
|
2045
2210
|
|
|
2046
2211
|
async def _run():
|
|
@@ -2127,6 +2292,10 @@ def run_mcp_stdio(
|
|
|
2127
2292
|
jq_expr: str | None = None,
|
|
2128
2293
|
head: int | None = None,
|
|
2129
2294
|
verbose: bool = False,
|
|
2295
|
+
sort_mode: str | None = None,
|
|
2296
|
+
top: int | None = None,
|
|
2297
|
+
compact: bool = False,
|
|
2298
|
+
source_hash: str = "",
|
|
2130
2299
|
):
|
|
2131
2300
|
extra = dict(
|
|
2132
2301
|
resource_action=resource_action,
|
|
@@ -2138,6 +2307,10 @@ def run_mcp_stdio(
|
|
|
2138
2307
|
jq_expr=jq_expr,
|
|
2139
2308
|
head=head,
|
|
2140
2309
|
verbose=verbose,
|
|
2310
|
+
sort_mode=sort_mode,
|
|
2311
|
+
top=top,
|
|
2312
|
+
compact=compact,
|
|
2313
|
+
source_hash=source_hash,
|
|
2141
2314
|
)
|
|
2142
2315
|
|
|
2143
2316
|
import anyio
|
|
@@ -2190,6 +2363,10 @@ async def _mcp_session(
|
|
|
2190
2363
|
jq_expr: str | None = None,
|
|
2191
2364
|
head: int | None = None,
|
|
2192
2365
|
verbose: bool = False,
|
|
2366
|
+
sort_mode: str | None = None,
|
|
2367
|
+
top: int | None = None,
|
|
2368
|
+
compact: bool = False,
|
|
2369
|
+
source_hash: str = "",
|
|
2193
2370
|
):
|
|
2194
2371
|
# Handle resource operations
|
|
2195
2372
|
if resource_action:
|
|
@@ -2207,6 +2384,11 @@ async def _mcp_session(
|
|
|
2207
2384
|
)
|
|
2208
2385
|
return
|
|
2209
2386
|
|
|
2387
|
+
list_kwargs = dict(
|
|
2388
|
+
verbose=verbose, compact=compact,
|
|
2389
|
+
source_hash=source_hash, sort_mode=sort_mode, top=top,
|
|
2390
|
+
)
|
|
2391
|
+
|
|
2210
2392
|
if list_mode:
|
|
2211
2393
|
result = await session.list_tools()
|
|
2212
2394
|
tools = [
|
|
@@ -2223,10 +2405,12 @@ async def _mcp_session(
|
|
|
2223
2405
|
if not commands:
|
|
2224
2406
|
print(f"\nNo tools matching '{search_pattern}'.")
|
|
2225
2407
|
return
|
|
2226
|
-
|
|
2408
|
+
if not compact:
|
|
2409
|
+
print(f"\nTools matching '{search_pattern}':")
|
|
2227
2410
|
else:
|
|
2228
|
-
|
|
2229
|
-
|
|
2411
|
+
if not compact:
|
|
2412
|
+
print("\nAvailable tools:")
|
|
2413
|
+
list_mcp_commands(commands, **list_kwargs)
|
|
2230
2414
|
return
|
|
2231
2415
|
|
|
2232
2416
|
if tool_name is None:
|
|
@@ -2845,6 +3029,9 @@ def handle_mcp(
|
|
|
2845
3029
|
jq_expr: str | None = None,
|
|
2846
3030
|
head: int | None = None,
|
|
2847
3031
|
verbose: bool = False,
|
|
3032
|
+
sort_mode: str | None = None,
|
|
3033
|
+
top: int | None = None,
|
|
3034
|
+
compact: bool = False,
|
|
2848
3035
|
):
|
|
2849
3036
|
# Build a config dict for cache key generation (future-proof)
|
|
2850
3037
|
config_for_cache = {
|
|
@@ -2854,8 +3041,9 @@ def handle_mcp(
|
|
|
2854
3041
|
'env_vars': env_vars,
|
|
2855
3042
|
'is_stdio': is_stdio,
|
|
2856
3043
|
}
|
|
2857
|
-
|
|
3044
|
+
|
|
2858
3045
|
key = cache_key_override or cache_key_for(config_for_cache)
|
|
3046
|
+
src_hash = _source_hash_for(source)
|
|
2859
3047
|
|
|
2860
3048
|
# Resource/prompt operations skip the tool flow entirely
|
|
2861
3049
|
if resource_action or prompt_action:
|
|
@@ -2876,9 +3064,14 @@ def handle_mcp(
|
|
|
2876
3064
|
)
|
|
2877
3065
|
return
|
|
2878
3066
|
|
|
3067
|
+
list_kwargs = dict(
|
|
3068
|
+
verbose=verbose, compact=compact,
|
|
3069
|
+
source_hash=src_hash, sort_mode=sort_mode, top=top,
|
|
3070
|
+
)
|
|
3071
|
+
|
|
2879
3072
|
if list_mode:
|
|
2880
3073
|
if bake_config and (bake_config.include or bake_config.exclude or bake_config.methods):
|
|
2881
|
-
# Fetch tools, filter, then list
|
|
3074
|
+
# Fetch tools, filter, then list -- don't delegate to unfiltered path
|
|
2882
3075
|
tools = _fetch_or_cache_mcp_tools(
|
|
2883
3076
|
key, ttl, refresh, source, is_stdio, auth_headers, env_vars,
|
|
2884
3077
|
transport=transport, oauth_provider=oauth_provider,
|
|
@@ -2887,8 +3080,9 @@ def handle_mcp(
|
|
|
2887
3080
|
commands = filter_commands(
|
|
2888
3081
|
commands, bake_config.include, bake_config.exclude, bake_config.methods,
|
|
2889
3082
|
)
|
|
2890
|
-
|
|
2891
|
-
|
|
3083
|
+
if not compact:
|
|
3084
|
+
print("\nAvailable tools:")
|
|
3085
|
+
list_mcp_commands(commands, **list_kwargs)
|
|
2892
3086
|
return
|
|
2893
3087
|
_dispatch_mcp_call(
|
|
2894
3088
|
source, is_stdio, auth_headers, env_vars,
|
|
@@ -2897,6 +3091,8 @@ def handle_mcp(
|
|
|
2897
3091
|
search_pattern=search_pattern,
|
|
2898
3092
|
jq_expr=jq_expr, head=head,
|
|
2899
3093
|
verbose=verbose,
|
|
3094
|
+
sort_mode=sort_mode, top=top, compact=compact,
|
|
3095
|
+
source_hash=src_hash,
|
|
2900
3096
|
)
|
|
2901
3097
|
return
|
|
2902
3098
|
|
|
@@ -2913,9 +3109,11 @@ def handle_mcp(
|
|
|
2913
3109
|
)
|
|
2914
3110
|
|
|
2915
3111
|
if not remaining:
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
3112
|
+
if not compact:
|
|
3113
|
+
print("Available tools:")
|
|
3114
|
+
list_mcp_commands(commands, **list_kwargs)
|
|
3115
|
+
if not compact:
|
|
3116
|
+
print("\nUse --list for the same output, or provide a subcommand.")
|
|
2919
3117
|
return
|
|
2920
3118
|
|
|
2921
3119
|
pre = argparse.ArgumentParser(add_help=False)
|
|
@@ -2944,6 +3142,9 @@ def handle_mcp(
|
|
|
2944
3142
|
jq_expr=jq_expr, head=head,
|
|
2945
3143
|
)
|
|
2946
3144
|
|
|
3145
|
+
# Record usage after successful execution
|
|
3146
|
+
record_usage(src_hash, cmd.tool_name or cmd.name)
|
|
3147
|
+
|
|
2947
3148
|
|
|
2948
3149
|
def _fetch_mcp_tools(
|
|
2949
3150
|
source: str,
|
|
@@ -3130,6 +3331,30 @@ def _build_main_parser() -> argparse.ArgumentParser:
|
|
|
3130
3331
|
dest="verbose",
|
|
3131
3332
|
help="Show full tool descriptions in --list output, wrapped to terminal width (default: truncated with ...)",
|
|
3132
3333
|
)
|
|
3334
|
+
pre.add_argument(
|
|
3335
|
+
"--sort",
|
|
3336
|
+
choices=["usage", "recent", "alpha", "default"],
|
|
3337
|
+
default=None,
|
|
3338
|
+
dest="sort_mode",
|
|
3339
|
+
help=(
|
|
3340
|
+
"Sort order for --list output. 'usage' sorts by call frequency, "
|
|
3341
|
+
"'recent' by last-used time, 'alpha' alphabetically, 'default' keeps "
|
|
3342
|
+
"insertion order. When omitted, defaults to 'usage' if usage data "
|
|
3343
|
+
"exists, otherwise 'default'."
|
|
3344
|
+
),
|
|
3345
|
+
)
|
|
3346
|
+
pre.add_argument(
|
|
3347
|
+
"--top",
|
|
3348
|
+
type=int,
|
|
3349
|
+
default=None,
|
|
3350
|
+
metavar="N",
|
|
3351
|
+
help="Show only the top N tools in --list output (useful for LLM agents)",
|
|
3352
|
+
)
|
|
3353
|
+
pre.add_argument(
|
|
3354
|
+
"--compact",
|
|
3355
|
+
action="store_true",
|
|
3356
|
+
help="Space-separated tool names only, no descriptions (~2 tokens/tool)",
|
|
3357
|
+
)
|
|
3133
3358
|
pre.add_argument("--pretty", action="store_true", help="Pretty-print JSON output")
|
|
3134
3359
|
pre.add_argument("--raw", action="store_true", help="Print raw response body")
|
|
3135
3360
|
pre.add_argument(
|
|
@@ -3541,6 +3766,7 @@ def _handle_openapi_mode(
|
|
|
3541
3766
|
oauth_provider: "httpx.Auth | None" = None,
|
|
3542
3767
|
) -> None:
|
|
3543
3768
|
"""Execute OpenAPI mode: load spec, build parser, execute."""
|
|
3769
|
+
src_hash = _source_hash_for(pre_args.spec)
|
|
3544
3770
|
spec = load_openapi_spec(
|
|
3545
3771
|
pre_args.spec,
|
|
3546
3772
|
auth_headers,
|
|
@@ -3555,14 +3781,20 @@ def _handle_openapi_mode(
|
|
|
3555
3781
|
commands, bake_config.include, bake_config.exclude, bake_config.methods,
|
|
3556
3782
|
)
|
|
3557
3783
|
|
|
3784
|
+
list_kwargs = dict(
|
|
3785
|
+
verbose=pre_args.verbose, compact=pre_args.compact,
|
|
3786
|
+
source_hash=src_hash, sort_mode=pre_args.sort_mode, top=pre_args.top,
|
|
3787
|
+
)
|
|
3788
|
+
|
|
3558
3789
|
if pre_args.list_commands:
|
|
3559
3790
|
if search_pattern:
|
|
3560
3791
|
commands = _filter_commands(commands, search_pattern)
|
|
3561
3792
|
if not commands:
|
|
3562
3793
|
print(f"\nNo tools matching '{search_pattern}'.")
|
|
3563
3794
|
return
|
|
3564
|
-
|
|
3565
|
-
|
|
3795
|
+
if not pre_args.compact:
|
|
3796
|
+
print(f"\nTools matching '{search_pattern}':")
|
|
3797
|
+
list_openapi_commands(commands, **list_kwargs)
|
|
3566
3798
|
return
|
|
3567
3799
|
|
|
3568
3800
|
if not remaining:
|
|
@@ -3608,6 +3840,9 @@ def _handle_openapi_mode(
|
|
|
3608
3840
|
jq_expr=pre_args.jq, head=pre_args.head,
|
|
3609
3841
|
)
|
|
3610
3842
|
|
|
3843
|
+
# Record usage after successful execution
|
|
3844
|
+
record_usage(src_hash, cmd.tool_name or cmd.graphql_field_name or cmd.name)
|
|
3845
|
+
|
|
3611
3846
|
|
|
3612
3847
|
def _main_impl(argv: list[str], bake_config: BakeConfig | None = None):
|
|
3613
3848
|
pre = _build_main_parser()
|
|
@@ -3665,6 +3900,9 @@ def _main_impl(argv: list[str], bake_config: BakeConfig | None = None):
|
|
|
3665
3900
|
jq_expr=pre_args.jq,
|
|
3666
3901
|
head=pre_args.head,
|
|
3667
3902
|
verbose=pre_args.verbose,
|
|
3903
|
+
sort_mode=pre_args.sort_mode,
|
|
3904
|
+
top=pre_args.top,
|
|
3905
|
+
compact=pre_args.compact,
|
|
3668
3906
|
)
|
|
3669
3907
|
return
|
|
3670
3908
|
|
|
@@ -3697,6 +3935,9 @@ def _main_impl(argv: list[str], bake_config: BakeConfig | None = None):
|
|
|
3697
3935
|
jq_expr=pre_args.jq,
|
|
3698
3936
|
head=pre_args.head,
|
|
3699
3937
|
verbose=pre_args.verbose,
|
|
3938
|
+
sort_mode=pre_args.sort_mode,
|
|
3939
|
+
top=pre_args.top,
|
|
3940
|
+
compact=pre_args.compact,
|
|
3700
3941
|
)
|
|
3701
3942
|
return
|
|
3702
3943
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|