Skip to main content
Glama

list_services

List available agent services with a lightweight summary to identify accessible options in the OpenAaaS network.

Instructions

获取可用的 Agent 服务列表(轻量摘要)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
serverNodefault

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The MCP tool handler for 'list_services'. Registered via @mcp.tool() decorator inside register_tools(). Calls GET /api/v1/client/services and formats a summary of available agent services.
    @mcp.tool()
    def list_services(server: str = "default") -> str:
        """获取可用的 Agent 服务列表(轻量摘要)"""
        try:
            sc = get_server_config(server)
            api_key = require_api_key(server)
        except RuntimeError as e:
            return f"❌ {e}"
    
        server_url = strip_trailing_slash(sc.get("server_url", ""))
        url = f"{server_url}/api/v1/client/services"
    
        try:
            result = safe_request(
                "GET", url, headers={"Authorization": f"Bearer {api_key}"}
            )
        except OpenAaaSError as e:
            return f"❌ 请求失败: {e}"
    
        services = result if isinstance(result, list) else result.get("services", [])
        if not services:
            return "暂无可用的 Agent 服务"
    
        status_icon = {"online": "🟢", "offline": "🔴", "unknown": "⚪"}
        lines = [f"找到 {len(services)} 个可用服务:"]
    
        for i, svc in enumerate(services):
            if not isinstance(svc, dict):
                continue
            svc_id = svc.get("id", "unknown")
            svc_name = svc.get("name", "未命名")
            description = svc.get("description", "无描述")
            agent_status = svc.get("agent_status", "unknown")
            access_type = svc.get("access_type", "unknown")
            has_permission = svc.get("has_permission") is True
            reg_status = svc.get("registration_status")
    
            icon = status_icon.get(agent_status, "⚪")
            perm = "✅ 有权限" if has_permission else "❌ 无权限"
    
            lines.append(f"{i + 1}. {svc_name}")
            lines.append(f"   ID: {svc_id}")
            lines.append(f"   状态: {icon} {agent_status}")
            lines.append(f"   访问类型: {access_type}")
            lines.append(f"   权限: {perm}")
            lines.append(f"   描述: {description}")
            if reg_status:
                lines.append(f"   注册状态: {reg_status}")
            if i < len(services) - 1:
                lines.append("")
    
        return "\n".join(lines)
  • The register_tools() function that defines and registers all MCP tools (including list_services) via the @mcp.tool() decorator on the FastMCP instance.
    def register_tools(mcp: FastMCP) -> None:
        """注册所有 OpenAaaS MCP Tools"""
  • Standalone list_services helper function used by the Kimi plugin, calling GET /api/v1/client/services and returning formatted JSON.
    def list_services(server_url, api_key):
        """
        调用服务列表接口
        
        Args:
            server_url: 服务端基础地址
            api_key: API 密钥
        """
        if not api_key:
            return {"error": "缺少 API Key,请先运行 register 进行注册"}
        
        server_url = server_url.rstrip("/")
        url = f"{server_url}/api/v1/client/services"
        
        try:
            headers = {
                "Authorization": f"Bearer {api_key}"
            }
            req = urllib.request.Request(url, headers=headers, method="GET")
            
            with urllib.request.urlopen(req, timeout=30) as response:
                result = json.loads(response.read().decode("utf-8"))
                
                # 处理返回结果(可能是列表或对象)
                services = result if isinstance(result, list) else result.get("services", [])
                
                # 格式化服务列表
                formatted_services = []
                for svc in services:
                    formatted_services.append({
                        "id": svc.get("id"),
                        "name": svc.get("name"),
                        "description": svc.get("description"),
                        "usage": svc.get("usage", ""),
                        "agent_status": svc.get("agent_status", "unknown"),
                        "access_type": svc.get("access_type", "unknown"),
                        "has_permission": svc.get("has_permission", False),
                        "registration_status": svc.get("registration_status", "unknown")
                    })
                
                return {
                    "content": f"找到 {len(formatted_services)} 个可用服务",
                    "data": {
                        "total": len(formatted_services),
                        "services": formatted_services
                    }
                }
                
        except urllib.error.HTTPError as e:
            error_body = e.read().decode("utf-8")
            try:
                error_data = json.loads(error_body)
                error_msg = error_data.get("error") or error_data.get("message") or error_body
            except:
                error_msg = error_body or e.reason
            
            if e.code == 401:
                return {"error": f"认证失败 (401): API Key 无效,请检查 config.json 中的 api_key 是否正确"}
            elif e.code == 403:
                return {"error": f"权限不足 (403): 无权访问服务列表"}
            return {"error": f"请求失败 (HTTP {e.code}): {error_msg}"}
        except urllib.error.URLError as e:
            return {"error": f"连接失败: {e.reason},请检查服务端地址是否正确"}
        except json.JSONDecodeError as e:
            return {"error": f"JSON 解析错误: {str(e)}"}
        except Exception as e:
            return {"error": f"请求失败: {str(e)}"}
  • Admin dashboard client method list_services() that calls GET /api/v1/services (admin endpoint) to list all services.
    def list_services(self) -> list[dict]:
        """List all services (admin perspective)."""
        try:
            data = self._get("/api/v1/services")
            if isinstance(data, list):
                return data
            return data.get("services", [])
        except requests.RequestException as e:
            print(f"[ERROR] Network error in list_services: {e}")
            return []
  • Mock client method list_services() returning mock services data for dashboard testing.
    def list_services(self) -> list[dict]:
        """List mock services."""
        return [dict(s) for s in self._services]
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, and description only states '轻量摘要' (lightweight summary), which hints at limited data but does not disclose traits like read-only nature, rate limits, or what 'lightweight' means in practice. Insufficient for a tool with no annotation support.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely concise (one phrase), but clearly conveys the tool's purpose. For a simple list operation, this is efficient; however, it could be more sentence-like for readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the existence of an output schema, the description does not need to detail return values. However, it lacks explanation of the 'server' parameter and what 'lightweight summary' entails, leaving some gaps for a tool with one parameter and no annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% with an optional 'server' parameter having no description. The description omits any explanation of the parameter's purpose, default value, or valid options, leaving the agent uninformed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it retrieves a list of available Agent services, with '轻量摘要' indicating a lightweight summary. This distinguishes it from sibling tools like list_servers (likely server instances) and list_files (files).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool vs alternatives like list_servers or get_service_usage. No context on prerequisites or exclusions provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Wolido/OpenAaaS'

If you have feedback or need assistance with the MCP directory API, please join our Discord server