#!/bin/bash # # test_mcp_tools.sh - Test MCP tools via HTTPS/JSON-RPC with dynamic tool discovery # # Usage: # ./test_mcp_tools.sh [options] # # Options: # -v, --verbose Show verbose output # -q, --quiet Suppress progress messages # --endpoint NAME Test only specific endpoint (config, query, admin, cache, observe) # --tool NAME Test only specific tool # --skip-tool NAME Skip specific tool # --list-only Only list discovered tools without testing # -h, --help Show help # set -e # Configuration MCP_HOST="${MCP_HOST:-127.0.0.1}" MCP_PORT="${MCP_PORT:-6071}" # Endpoints (will be used for discovery) ENDPOINTS=("config" "query" "admin" "cache" "observe") # Test options VERBOSE=false QUIET=false TEST_ENDPOINT="" TEST_TOOL="" SKIP_TOOLS=() LIST_ONLY=false # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # Statistics TOTAL_TESTS=0 PASSED_TESTS=0 FAILED_TESTS=0 SKIPPED_TESTS=0 # Temp file for discovered tools DISCOVERED_TOOLS_FILE=$(mktemp) # Cleanup on exit trap "rm -f ${DISCOVERED_TOOLS_FILE}" EXIT log_info() { if [ "${QUIET}" = "false" ]; then echo -e "${GREEN}[INFO]${NC} $1" fi } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_verbose() { if [ "${VERBOSE}" = "true" ]; then echo -e "${BLUE}[DEBUG]${NC} $1" fi } log_test() { if [ "${QUIET}" = "false" ]; then echo -e "${BLUE}[TEST]${NC} $1" fi } # Get endpoint URL get_endpoint_url() { local endpoint="$1" echo "https://${MCP_HOST}:${MCP_PORT}/mcp/${endpoint}" } # Execute MCP request mcp_request() { local endpoint="$1" local payload="$2" local response response=$(curl -k -s -w "\n%{http_code}" -X POST "${endpoint}" \ -H "Content-Type: application/json" \ -d "${payload}" 2>/dev/null) local body body=$(echo "$response" | head -n -1) local code code=$(echo "$response" | tail -n 1) if [ "${VERBOSE}" = "true" ]; then echo "Request: ${payload}" >&2 echo "Response (${code}): ${body}" >&2 fi echo "${body}" return 0 } # Check if MCP server is accessible check_mcp_server() { log_test "Checking MCP server accessibility..." local config_url config_url=$(get_endpoint_url "config") local response response=$(mcp_request "${config_url}" '{"jsonrpc":"2.0","method":"ping","id":1}') if echo "${response}" | grep -q "result"; then log_info "MCP server is accessible" return 0 else log_error "MCP server is not accessible" log_error "Response: ${response}" return 1 fi } # Discover tools from an endpoint discover_tools() { local endpoint="$1" local url url=$(get_endpoint_url "${endpoint}") log_verbose "Discovering tools from endpoint: ${endpoint}" local payload='{"jsonrpc":"2.0","method":"tools/list","id":1}' local response response=$(mcp_request "${url}" "${payload}") # Extract tool names from response local tools_json="" if command -v jq >/dev/null 2>&1; then # Use jq for reliable JSON parsing tools_json=$(echo "${response}" | jq -r '.result.tools[].name' 2>/dev/null || echo "") else # Fallback to grep/sed tools_json=$(echo "${response}" | grep -o '"name"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*: "\(.*\)"/\1/') fi # Store discovered tools in temp file # Format: endpoint:tool_name while IFS= read -r tool_name; do if [ -n "${tool_name}" ]; then echo "${endpoint}:${tool_name}" >> "${DISCOVERED_TOOLS_FILE}" fi done <<< "${tools_json}" log_verbose "Discovered tools from ${endpoint}: ${tools_json}" } # Check if a tool is discovered on an endpoint is_tool_discovered() { local endpoint="$1" local tool="$2" local key="${endpoint}:${tool}" if grep -q "^${key}$" "${DISCOVERED_TOOLS_FILE}" 2>/dev/null; then return 0 fi return 1 } # Get discovered tools for an endpoint get_discovered_tools() { local endpoint="$1" grep "^${endpoint}:" "${DISCOVERED_TOOLS_FILE}" 2>/dev/null | sed "s/^${endpoint}://" || true } # Count discovered tools for an endpoint count_discovered_tools() { local endpoint="$1" get_discovered_tools "${endpoint}" | wc -l } # Assert that JSON contains expected value assert_json_contains() { local response="$1" local field="$2" local expected="$3" if echo "${response}" | grep -q "\"${field}\"[[:space:]]*:[[:space:]]*${expected}"; then return 0 fi # Try with jq if available if command -v jq >/dev/null 2>&1; then local actual actual=$(echo "${response}" | jq -r "${field}" 2>/dev/null) if [ "${actual}" = "${expected}" ]; then return 0 fi fi return 1 } # Test a tool test_tool() { local endpoint="$1" local tool_name="$2" local arguments="$3" local expected_field="$4" local expected_value="$5" TOTAL_TESTS=$((TOTAL_TESTS + 1)) log_test "Testing tool: ${tool_name} (endpoint: ${endpoint})" local url url=$(get_endpoint_url "${endpoint}") local payload payload=$(cat </dev/null || echo "0") echo "" echo "Total tools discovered: ${total}" echo "" } # Parse command line arguments parse_args() { while [[ $# -gt 0 ]]; do case $1 in -v|--verbose) VERBOSE=true shift ;; -q|--quiet) QUIET=true shift ;; --endpoint) TEST_ENDPOINT="$2" shift 2 ;; --tool) TEST_TOOL="$2" shift 2 ;; --skip-tool) SKIP_TOOLS+=("$2") shift 2 ;; --list-only) LIST_ONLY=true shift ;; -h|--help) cat < "${DISCOVERED_TOOLS_FILE}" # Clear the file if [ -n "${TEST_ENDPOINT}" ]; then discover_tools "${TEST_ENDPOINT}" else for endpoint in "${ENDPOINTS[@]}"; do discover_tools "${endpoint}" done fi } # Run all tests run_all_tests() { echo "======================================" echo "MCP Tools Test Suite (Dynamic Discovery)" echo "======================================" echo "" echo "MCP Host: ${MCP_HOST}" echo "MCP Port: ${MCP_PORT}" echo "" # Print environment variables if set if [ -n "${MCP_HOST}" ] || [ -n "${MCP_PORT}" ]; then log_info "Environment Variables:" [ -n "${MCP_HOST}" ] && echo " MCP_HOST=${MCP_HOST}" [ -n "${MCP_PORT}" ] && echo " MCP_PORT=${MCP_PORT}" echo "" fi # Check MCP server if ! check_mcp_server; then log_error "MCP server is not accessible. Please run:" echo " ./configure_mcp.sh --enable" exit 1 fi # Discover all tools discover_all_tools # Print discovery report print_discovery_report # Exit if list-only mode if [ "${LIST_ONLY}" = "true" ]; then exit 0 fi echo "======================================" echo "Running Tests" echo "======================================" echo "" # Run tests local num_tests=${#TEST_ENDPOINTS[@]} for ((i=0; i