Skip to content

Tool Discovery System

Automatic detection and normalization of MCP server capabilities with support for multiple discovery strategies and protocols.

Overview

The MCP Platform tool discovery system provides comprehensive, automated detection of tools (capabilities) from MCP servers using multiple discovery strategies. It supports both the official MCP JSON-RPC over stdio protocol and fallback HTTP endpoints for broader compatibility.

Key Features

  • โœ… MCP Protocol Compliant: Full support for MCP 2025-06-18 specification with JSON-RPC over stdio
  • ๐Ÿณ Docker Integration: Direct discovery from Docker images with proper container lifecycle management
  • ๐Ÿ” Multi-Strategy Discovery: Static, dynamic, template-based, and Docker probe strategies
  • ๐Ÿ“Š Rich CLI Interface: Beautiful, formatted output with comprehensive tool information
  • โšก Caching Support: Optional caching for improved performance
  • ๐Ÿ”„ Fallback Support: HTTP endpoint fallback for non-standard implementations

Discovery Strategies

1. MCP Protocol Discovery (Primary)

Uses the official MCP JSON-RPC protocol over stdio transport:

  • Initialize: Establishes MCP session with proper handshake
  • Tools/List: Retrieves comprehensive tool definitions with schemas
  • Normalization: Converts MCP tool definitions to unified format

2. Static Discovery

Reads tool definitions from tools.json files in template directories:

{
  "tools": [
    {
      "name": "example_tool",
      "description": "Example tool description",
      "category": "general",
      "parameters": {
        "type": "object",
        "properties": {
          "input": {"type": "string"}
        }
      }
    }
  ]
}

3. Dynamic Discovery (Fallback)

Probes HTTP endpoints for tool information: - /tools, /api/tools, /v1/tools, /mcp/tools - Supports various response formats

4. Template Fallback

Extracts capabilities from existing template.json definitions for compatibility.

CLI Usage

List Tools for Templates

# Basic tool discovery for deployed template
mcp-template tools demo

# Force refresh cached results
mcp-template tools demo --refresh

# Ignore cache entirely
mcp-template tools demo --no-cache

Template-Based Tool Discovery

The CLI now supports discovering tools directly from templates, with automatic Docker fallback for templates configured with tool_discovery: "dynamic":

# Discover tools from a template directory
mcp-template tools my-template

# With configuration values for Docker fallback
mcp-template tools my-template --config "PORT=8080,HOST=localhost"

# Force refresh template tool discovery
mcp-template tools my-template --refresh --config "DEBUG=true"

When a template has tool_discovery: "dynamic" in its configuration and standard discovery methods fail, the system automatically:

  1. Checks for Docker image: Looks for docker_image and docker_tag in template config
  2. Spins up container: Creates temporary container with provided config values as environment variables
  3. Discovers tools: Uses MCP protocol or HTTP endpoints to discover available tools
  4. Cleans up: Automatically removes the temporary container

Example template configuration supporting dynamic discovery:

{
  "name": "My MCP Server",
  "tool_discovery": "dynamic",
  "docker_image": "myregistry/mcp-server",
  "docker_tag": "latest",
  "config_schema": {
    "PORT": {"type": "integer", "default": 8080},
    "DEBUG": {"type": "boolean", "default": false}
  }
}

Discover Tools from Docker Images

# Discover from MCP filesystem server
mcp-template tools --image mcp/filesystem /tmp

# Discover from custom server with arguments
mcp-template tools --image myregistry/mcp-server:latest config.json --port 8080

# Example output for filesystem server
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“
โ”ƒ                    ๐Ÿณ Docker Tool Discovery            โ”ƒ
โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›
โœ… Discovered 11 tools via docker_mcp_stdio

โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ณโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“
โ”ƒ Tool Name            โ”ƒ Description                           โ”ƒ
โ”กโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ•‡โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ฉ
โ”‚ read_file            โ”‚ Read complete file contents...       โ”‚
โ”‚ write_file           โ”‚ Create or overwrite files...         โ”‚
โ”‚ list_directory       โ”‚ List directory contents...           โ”‚
โ”‚ create_directory     โ”‚ Create directories...                โ”‚
โ”‚ ...                  โ”‚ ...                                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Template Configuration

Configure tool discovery behavior in template.json:

{
  "name": "My MCP Server",
  "description": "An example MCP server template",
  "version": "1.0.0",
  "tool_discovery": {
    "method": "mcp_protocol",
    "fallback_methods": ["http", "static"],
    "cache_ttl": 300,
    "timeout": 30
  },
  "transport": {
    "default": "stdio",
    "supported": ["stdio", "http"]
  },
  "mcp_protocol": {
    "version": "2025-06-18",
    "capabilities": {
      "tools": {}
    }
  }
}

Configuration Fields

  • tool_discovery: Discovery method ("static", "dynamic", or "none")
  • "static": Uses pre-defined tools from tools.json file
  • "dynamic": Probes running server endpoints, with Docker fallback for templates
  • "none": Disables tool discovery
  • tool_endpoint: Custom endpoint for dynamic discovery (default: "/tools")
  • has_image: Whether the template has a Docker image for probing
  • docker_image: Docker image name for dynamic discovery fallback
  • docker_tag: Docker image tag (default: "latest")
  • config_schema: Schema for configuration values passed to Docker containers
  • origin: Template origin ("internal" or "external")

Static Tool Discovery

For static discovery, create a tools.json file in your template directory:

{
  "tools": [
    {
      "name": "hello_world",
      "description": "Generate a greeting message",
      "category": "greeting",
      "parameters": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name to greet"
          }
        }
      }
    }
  ],
  "metadata": {
    "discovery_method": "static",
    "last_updated": "2024-07-29T00:00:00Z"
  }
}

Dynamic Tool Discovery

For dynamic discovery, the system will probe these endpoints in order:

  1. Custom endpoint (if specified in tool_endpoint)
  2. /tools
  3. /get_tools
  4. /capabilities
  5. /metadata
  6. /openapi.json

The system expects responses in these formats:

Standard Tools Format

{
  "tools": [
    {
      "name": "tool_name",
      "description": "Tool description",
      "parameters": {...}
    }
  ]
}

Capabilities Format

{
  "capabilities": [
    {
      "name": "capability_name",
      "description": "Capability description"
    }
  ]
}

OpenAPI Format

{
  "paths": {
    "/api/endpoint": {
      "get": {
        "summary": "Endpoint description",
        "parameters": [...]
      }
    }
  }
}

Caching

Tool discovery results are automatically cached in ~/.mcp/cache/ for 6 hours by default.

Cache Management

from mcp_template.tools import CacheManager

cache = CacheManager()

# Get cache info
info = cache.get_cache_info()
print(f"Total files: {info['total_files']}")

# Clear expired entries
removed = cache.clear_expired()
print(f"Removed {removed} expired entries")

# Clear all cache
cache.clear_all()

Programmatic Usage

Tool Discovery

from mcp_template.tools import ToolDiscovery
from pathlib import Path

discovery = ToolDiscovery()

# Discover tools for a template
result = discovery.discover_tools(
    template_name="my-template",
    template_dir=Path("templates/my-template"),
    template_config={
        "tool_discovery": "static",
        "tool_endpoint": "/api/tools"
    },
    use_cache=True,
    force_refresh=False
)

print(f"Found {len(result['tools'])} tools")
for tool in result['tools']:
    print(f"- {tool['name']}: {tool['description']}")

Docker Probe

from mcp_template.tools import DockerProbe

probe = DockerProbe()

# Discover tools from Docker image
result = probe.discover_tools_from_image("myregistry/mcp-server:latest")

if result:
    print(f"Discovered {len(result['tools'])} tools from image")
else:
    print("Failed to discover tools")

Best Practices

Template Authors

  1. Choose appropriate discovery method:
  2. Use "static" for stable, well-defined tools
  3. Use "dynamic" for servers with runtime tool generation
  4. Use "none" only if tools cannot be discovered

  5. Provide tools.json for static discovery:

  6. Include comprehensive tool descriptions
  7. Use consistent parameter schemas
  8. Keep metadata up to date

  9. Implement standard endpoints for dynamic discovery:

  10. Prefer /tools endpoint with standard format
  11. Include proper error handling and timeouts
  12. Support JSON content negotiation

Platform Users

  1. Use caching effectively:
  2. Let cache work automatically for better performance
  3. Use --refresh when you know tools have changed
  4. Use --no-cache only for debugging

  5. Monitor discovery results:

  6. Check discovery method in tool listings
  7. Verify tool counts and descriptions
  8. Report issues with external templates

Error Handling

The system gracefully handles various error conditions:

  • Missing tools.json: Falls back to template.json or dynamic discovery
  • Network timeouts: Logs debug messages and continues with fallback
  • Invalid JSON: Logs warnings and skips malformed responses
  • Container failures: Automatically cleans up failed Docker containers

Extension Points

The system is designed for extensibility:

Custom Discovery Methods

class CustomToolDiscovery(ToolDiscovery):
    def _discover_custom_tools(self, template_name, config):
        # Implement custom discovery logic
        return {
            "tools": [...],
            "discovery_method": "custom",
            "timestamp": time.time()
        }

Custom Tool Formats

def normalize_custom_format(self, raw_data):
    # Convert custom format to standard tool format
    return [
        {
            "name": item["function_id"],
            "description": item["help_text"],
            "parameters": item["input_schema"]
        }
        for item in raw_data["functions"]
    ]

Troubleshooting

Common Issues

  1. No tools discovered:
  2. Check template configuration
  3. Verify tools.json exists for static discovery
  4. Test endpoints manually for dynamic discovery

  5. Cache not working:

  6. Check permissions on ~/.mcp/cache/
  7. Verify cache timestamps
  8. Use --no-cache to bypass temporarily

  9. Docker probe failures:

  10. Ensure Docker is running
  11. Check image exists and is accessible
  12. Verify container exposes HTTP endpoints

  13. Timeout errors:

  14. Check network connectivity
  15. Verify server is responding
  16. Consider increasing timeout values

Debug Mode

Enable debug logging to see detailed discovery process:

import logging
logging.basicConfig(level=logging.DEBUG)

Or set environment variable:

export LOG_LEVEL=DEBUG
mcp-template tools my-template