| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- # -*- coding: utf-8 -*-
- """
- MCP 远程工具列表查询 —— 格式化输出所有可用的 MCP 工具及参数签名
- """
- import asyncio
- import shutil
- from fastmcp import Client
- # ── 终端宽度 ──
- WIDTH = min(shutil.get_terminal_size().columns, 120)
- # ── 工具分类定义(按名称前缀归类)──
- CATEGORY_MAP = {
- "vent": "🌬️ 通风监测",
- "device": "🔧 设备管理",
- "tunnel": "🛤️ 巷道信息",
- "mine": "⛏️ 煤矿基础",
- "needq": "📊 需风量计算",
- }
- def _category(name: str) -> str:
- for prefix, label in CATEGORY_MAP.items():
- if name.startswith(prefix):
- return label
- return "📦 其他"
- def parse_tool_params(schema: dict) -> list[dict]:
- """解析 inputSchema 为参数列表"""
- params = []
- required = schema.get("required", [])
- props = schema.get("properties", {})
- for name, info in props.items():
- params.append({
- "name": name,
- "type": info.get("type", "—"),
- "desc": (info.get("description", "") or "")[:120],
- "required": name in required,
- })
- return params
- # ── 主入口 ──
- MCP_URL = "http://39.97.59.228:8071/mcp"
- client = Client(MCP_URL)
- async def list_all_mcp_tools_tcp():
- """TCP 远程 MCP 客户端查询工具列表"""
- async with client:
- tools = await client.list_tools()
- # ══════════════════════════════════════════════
- # 头部
- # ══════════════════════════════════════════════
- print()
- print("╔" + "═" * (WIDTH - 2) + "╗")
- print("║" + f" 🔌 MCP 远程工具列表 | {MCP_URL} | 共 {len(tools)} 个工具".center(WIDTH - 2) + "║")
- print("╚" + "═" * (WIDTH - 2) + "╝")
- print()
- # 按类别分组
- groups: dict[str, list] = {}
- for t in tools:
- cat = _category(t.name)
- groups.setdefault(cat, []).append(t)
- order = ["🌬️ 通风监测", "🛤️ 巷道信息", "🔧 设备管理", "📊 需风量计算", "⛏️ 煤矿基础", "📦 其他"]
- index = 0
- for cat in order:
- if cat not in groups:
- continue
- group_tools = groups[cat]
- print(f" {cat}({len(group_tools)} 个)")
- print(f" {'─' * (WIDTH - 6)}")
- for t in group_tools:
- index += 1
- # ── 工具名 + 序号 ──
- print(f"\n ┌─ [{index:02d}] {t.name} {'─' * max(WIDTH - len(t.name) - 15, 0)}")
- # ── 描述 ──
- desc = (t.description or "").strip()
- if desc:
- # 自动换行
- for line in _wrap(desc, WIDTH - 8):
- print(f" │ 📝 {line}")
- # ── 参数表 ──
- params = parse_tool_params(t.inputSchema)
- if params:
- print(f" │ ┌ 参数{'─' * (WIDTH - 13)}")
- for p in params:
- flag = "🔴" if p["required"] else "🟢"
- print(f" │ │ {flag} {p['name']}: {p['type']}")
- if p["desc"]:
- for line in _wrap(p["desc"], WIDTH - 12):
- print(f" │ │ {line}")
- print(f" │ └{'─' * (WIDTH - 9)}")
- else:
- print(f" │ (无参数)")
- print(f" └{'─' * (WIDTH - 6)}")
- print()
- # ══════════════════════════════════════════════
- # 底部统计
- # ══════════════════════════════════════════════
- total_params = sum(
- len(parse_tool_params(t.inputSchema)) for t in tools
- )
- print("╔" + "═" * (WIDTH - 2) + "╗")
- print("║" + f" ✅ 总计 {len(tools)} 个工具,{total_params} 个参数,{len(groups)} 个分类".ljust(WIDTH - 2) + "║")
- print("╚" + "═" * (WIDTH - 2) + "╝")
- print()
- def _wrap(text: str, width: int) -> list[str]:
- """按宽度自动换行,尊重中文宽度"""
- lines = []
- while len(text) > width:
- # 尝试在空格处断行
- cut = text.rfind(" ", 0, width)
- if cut == -1:
- cut = width
- lines.append(text[:cut].strip())
- text = text[cut:].strip()
- if text:
- lines.append(text)
- return lines
- asyncio.run(list_all_mcp_tools_tcp())
|