Skip to main content
Glama
rog0x
by rog0x

api_health

Monitor API endpoint health by checking status codes, response times, SSL certificates, and validating response content for multiple URLs.

Instructions

Check the health of multiple API endpoints. Returns status, response time, SSL certificate validity, and optional response body validation for each endpoint.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
endpointsYesArray of endpoints to check (max 20)

Implementation Reference

  • The main handler function for the `api_health` tool which checks the health of provided endpoints.
    export async function apiHealth(
      endpoints: HealthEndpoint[]
    ): Promise<{ results: EndpointHealth[]; summary: { total: number; healthy: number; unhealthy: number; errors: number } }> {
      if (!endpoints || endpoints.length === 0) {
        throw new Error("Provide at least one endpoint to check");
      }
    
      const capped = endpoints.slice(0, 20);
      const results = await Promise.all(capped.map(checkEndpoint));
    
      const healthy = results.filter((r) => r.status === "healthy").length;
      const unhealthy = results.filter((r) => r.status === "unhealthy").length;
      const errors = results.filter((r) => r.status === "error").length;
    
      return {
        results,
        summary: {
          total: results.length,
          healthy,
          unhealthy,
          errors,
        },
      };
    }
  • Input and output interface definitions for the `api_health` tool.
    export interface HealthEndpoint {
      url: string;
      expected_status?: number;
      expected_body_contains?: string;
    }
    
    export interface EndpointHealth {
      url: string;
      status: "healthy" | "unhealthy" | "error";
      http_status: number | null;
      response_time_ms: number;
      ssl: SslInfo | null;
      body_valid: boolean | null;
      error: string | null;
    }
  • Helper functions used by `apiHealth` to check individual endpoints and SSL status.
    function checkSsl(hostname: string, port: number): Promise<SslInfo | null> {
      return new Promise((resolve) => {
        const timeout = setTimeout(() => {
          socket.destroy();
          resolve(null);
        }, 5000);
    
        const socket = tls.connect({ host: hostname, port, servername: hostname }, () => {
          clearTimeout(timeout);
          const cert = socket.getPeerCertificate();
          if (!cert || !cert.valid_to) {
            socket.destroy();
            resolve(null);
            return;
          }
    
          const expiresDate = new Date(cert.valid_to);
          const now = new Date();
          const daysRemaining = Math.floor(
            (expiresDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)
          );
    
          const flatten = (val: string | string[] | undefined): string => {
            if (!val) return "Unknown";
            return Array.isArray(val) ? val[0] : val;
          };
    
          resolve({
            valid: socket.authorized,
            issuer:
              typeof cert.issuer === "object"
                ? flatten(cert.issuer.O) !== "Unknown"
                  ? flatten(cert.issuer.O)
                  : flatten(cert.issuer.CN)
                : "Unknown",
            subject:
              typeof cert.subject === "object"
                ? flatten(cert.subject.CN)
                : "Unknown",
            expires: cert.valid_to,
            days_remaining: daysRemaining,
          });
    
          socket.destroy();
        });
    
        socket.on("error", () => {
          clearTimeout(timeout);
          resolve(null);
        });
      });
    }
    
    async function checkEndpoint(endpoint: HealthEndpoint): Promise<EndpointHealth> {
      const { url, expected_status = 200, expected_body_contains } = endpoint;
    
      let parsedUrl: URL;
      try {
        parsedUrl = new URL(url);
      } catch {
        return {
          url,
          status: "error",
          http_status: null,
          response_time_ms: 0,
          ssl: null,
          body_valid: null,
          error: "Invalid URL",
        };
      }
    
      const isHttps = parsedUrl.protocol === "https:";
      const sslPromise = isHttps
        ? checkSsl(parsedUrl.hostname, Number(parsedUrl.port) || 443)
        : Promise.resolve(null);
    
      const controller = new AbortController();
      const timer = setTimeout(() => controller.abort(), 15000);
      const start = Date.now();
    
      try {
        const response = await fetch(url, {
          method: "GET",
          signal: controller.signal,
          redirect: "follow",
        });
    
        const body = await response.text();
        const elapsed = Date.now() - start;
    
        let bodyValid: boolean | null = null;
        if (expected_body_contains) {
          bodyValid = body.includes(expected_body_contains);
        }
    
        const isHealthy =
          response.status === expected_status &&
          (bodyValid === null || bodyValid === true);
    
        const ssl = await sslPromise;
    
        return {
          url,
          status: isHealthy ? "healthy" : "unhealthy",
          http_status: response.status,
          response_time_ms: elapsed,
          ssl,
          body_valid: bodyValid,
          error: null,
        };
      } catch (err: unknown) {
        const elapsed = Date.now() - start;
        const ssl = await sslPromise;
        const message = err instanceof Error ? err.message : String(err);
        return {
          url,
          status: "error",
          http_status: null,
          response_time_ms: elapsed,
          ssl,
          body_valid: null,
          error: message,
        };
      } finally {
        clearTimeout(timer);
      }
    }

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/rog0x/mcp-api-tools'

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