Skip to main content
Glama

list_available_nodes

Discover available diagram nodes by provider, category, or search term to ensure valid selections before creating infrastructure diagrams.

Instructions

Discover 500+ node types across providers.

⚠️ USE THIS FIRST before create_diagram to avoid invalid node errors.

Filters: provider, category, search_term

Examples: AWS compute: provider="aws", category="compute" → EC2, Lambda, ECS, EKS... Search DBs: search_term="db" → RDS, DynamoDB, SQL across providers

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
providerNoFilter by provider (aws, azure, gcp, etc.)
categoryNoFilter by category (compute, database, etc.)
search_termNoSearch term for node type names
limitNoMaximum results to return

Implementation Reference

  • MCP tool registration decorator defining the tool name, description, annotations, and input schema via subsequent parameter annotations.
    @mcp.tool( name="list_available_nodes", description="""Discover 500+ node types across providers. ⚠️ USE THIS FIRST before create_diagram to avoid invalid node errors. Filters: provider, category, search_term Examples: AWS compute: provider="aws", category="compute" → EC2, Lambda, ECS, EKS... Search DBs: search_term="db" → RDS, DynamoDB, SQL across providers""", annotations={ "readOnlyHint": True, "destructiveHint": False, "idempotentHint": True, }, )
  • The async handler function implementing the tool logic: validates inputs implicitly via types, calls search_nodes helper, formats output or error.
    async def list_available_nodes( provider: Annotated[ Optional[str], Field(description="Filter by provider (aws, azure, gcp, etc.)") ] = None, category: Annotated[ Optional[str], Field(description="Filter by category (compute, database, etc.)") ] = None, search_term: Annotated[ Optional[str], Field(description="Search term for node type names") ] = None, limit: Annotated[int, Field(description="Maximum results to return", ge=1, le=500)] = 100, ) -> str: """List available diagram node types.""" try: # Search nodes nodes = search_nodes( provider=provider, category=category, search_term=search_term, limit=limit, ) # Calculate total (for this implementation, returned = total due to limit) total_count = len(nodes) returned_count = len(nodes) return format_node_catalog(nodes, total_count, returned_count) except Exception as e: return format_error(f"Failed to list nodes: {str(e)}")
  • Primary helper function that performs the node discovery and filtering logic by introspecting the diagrams library modules.
    def search_nodes( provider: Optional[str] = None, category: Optional[str] = None, search_term: Optional[str] = None, limit: int = 100, ) -> List[Dict[str, str]]: """Search for nodes matching criteria using dynamic discovery. Args: provider: Optional provider filter category: Optional category filter search_term: Optional search term for node type limit: Maximum number of results to return Returns: List of matching nodes with their information """ # Get discovered nodes (cached after first call) all_nodes = _discover_all_nodes() results = [] # Determine which providers to search providers_to_search = [provider] if provider else all_nodes.keys() for prov in providers_to_search: if prov not in all_nodes: continue provider_nodes = all_nodes[prov] # Determine which categories to search categories_to_search = [category] if category else provider_nodes.keys() for cat in categories_to_search: if cat not in provider_nodes: continue # Get nodes in this category nodes = provider_nodes[cat] for node in nodes: # Apply search filter if provided if search_term and search_term.lower() not in node.lower(): continue node_info = get_node_info(prov, cat, node) results.append(node_info) if len(results) >= limit: return results return results
  • Cached helper that dynamically discovers all node classes by importing and introspecting diagrams library provider/category modules.
    @lru_cache(maxsize=1) def _discover_all_nodes() -> Dict[str, Dict[str, List[str]]]: """Dynamically discover all available nodes from diagrams library. Results are cached for performance. Returns: Dict mapping provider -> category -> list of node types """ import diagrams # noqa: F401 results = {} # Only introspect known providers for provider in PROVIDER_CATEGORIES.keys(): try: provider_module = __import__(f"diagrams.{provider}", fromlist=[""]) results[provider] = {} # Get all submodules (categories) provider_path = provider_module.__path__ for _importer, category, _ispkg in pkgutil.iter_modules(provider_path): # Skip private/internal modules if category.startswith("_"): continue try: cat_module = __import__( f"diagrams.{provider}.{category}", fromlist=[""], ) nodes = [] # Get all classes that don't start with underscore for name, obj in inspect.getmembers(cat_module): if ( inspect.isclass(obj) and not name.startswith("_") and hasattr(obj, "_icon") ): # Ensure it's a node class nodes.append(name) if nodes: results[provider][category] = sorted(nodes) except (ImportError, AttributeError): # Skip categories that can't be imported pass except ImportError: # Skip providers that aren't installed pass return results

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/apetta/diagrams-mcp'

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