Skip to main content
Glama
elad12390
by elad12390

check_service_status

Verify if an API service or platform is currently experiencing operational issues or downtime.

Instructions

Check if an API service or platform is experiencing issues.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
serviceYes
reasoningYes

Implementation Reference

  • The @mcp.tool()-decorated async function that serves as the MCP tool handler for 'check_service_status'. It invokes ServiceHealthChecker.check_service(service), formats the result as JSON, handles errors, and tracks usage.
    async def check_service_status( service: Annotated[str, "Service name (e.g., stripe, aws, github, openai)"], reasoning: Annotated[str, "Why you're checking service status"], ) -> str: """Check if an API service or platform is experiencing issues.""" import json start_time = time.time() success = False error_msg = None result = "" try: # Check service health status = await service_health_checker.check_service(service) result = json.dumps(status, indent=2, ensure_ascii=False) result = clamp_text(result, MAX_RESPONSE_CHARS) success = "error" not in status if not success: error_msg = status.get("error") except Exception as exc: error_msg = str(exc) result = f"Service health check failed for {service}: {exc}" finally: response_time = (time.time() - start_time) * 1000 tracker.track_usage( tool_name="check_service_status", reasoning=reasoning, parameters={"service": service}, response_time_ms=response_time, success=success, error_message=error_msg, response_size=len(result.encode("utf-8")), ) return result
  • The core implementation logic in ServiceHealthChecker.check_service() method, which finds the service's status page URL, attempts API fetch/parse, falls back to HTML parsing or accessibility check, and formats the ServiceStatus response.
    async def check_service(self, service: str) -> dict: """Check service health status.""" # Find status page status_url = self.detector.find_status_page(service) if not status_url: return { "service": service, "status": "unknown", "status_emoji": "❓", "error": "Could not find status page for this service", "suggestion": f"Try checking {service}.com/status or searching for '{service} status page'", } # Strategy 1: Try Statuspage.io API (many services use this - it's more reliable) api_data = await self._fetch_statuspage_api(status_url) if api_data: status = self._parse_statuspage_api_response(api_data, service) status.status_page_url = status_url status.checked_at = datetime.utcnow().isoformat() + "Z" return self._format_status_response(status) # Strategy 2: Try crawling the page try: html = await self.crawler.fetch_raw(status_url, max_chars=200000) if html and len(html.strip()) > 100: # Parse status from HTML status = self.parser.parse_status_page(html, service) status.status_page_url = status_url status.checked_at = datetime.utcnow().isoformat() + "Z" return self._format_status_response(status) except Exception: pass # Fall through to HTTP check # Strategy 3: Fallback - just check if URL is accessible accessible, http_code = await self._check_url_accessible(status_url) if accessible: # Page is up but we couldn't parse it (likely JS-rendered) return { "service": service, "status": "unknown", "status_emoji": "❓", "status_page_url": status_url, "checked_at": datetime.utcnow().isoformat() + "Z", "message": "Status page is accessible but requires JavaScript to render. Please check manually.", "note": f"Visit {status_url} to see current status", } else: return { "service": service, "status": "unknown", "status_emoji": "❓", "status_page_url": status_url, "error": f"Status page returned HTTP {http_code}" if http_code else "Status page unreachable", } def _format_status_response(self, status: ServiceStatus) -> dict: """Format status object as response dict.""" response = { "service": status.service, "status": status.status, "status_emoji": self.parser.get_status_emoji(status.status), "status_page_url": status.status_page_url, "checked_at": status.checked_at, } if status.current_incidents: response["current_incidents"] = status.current_incidents else: response["current_incidents"] = [] response["message"] = "No active incidents reported" if status.components: response["components"] = [ {"name": comp.name, "status": comp.status} for comp in status.components[:10] ] return response
  • ServiceStatus dataclass defining the structured output format returned by the health check, including status, incidents, components, etc.
    class ServiceStatus: """Overall service health status.""" service: str status: str status_page_url: str | None = None checked_at: str | None = None current_incidents: list[str] = field(default_factory=list) components: list[ServiceComponent] = field(default_factory=list)
  • StatusPageDetector class that resolves service names to status page URLs using predefined mappings (KNOWN_STATUS_PAGES), aliases, and fallback patterns.
    class StatusPageDetector: """Detect and find status pages for services.""" # Known service → status page mappings KNOWN_STATUS_PAGES = { # Payment & Finance "stripe": "https://status.stripe.com", "paypal": "https://www.paypal-status.com", "plaid": "https://status.plaid.com", # Code & DevOps "github": "https://www.githubstatus.com", "gitlab": "https://status.gitlab.com", "bitbucket": "https://bitbucket.status.atlassian.com", "vercel": "https://www.vercel-status.com", "netlify": "https://www.netlifystatus.com", "heroku": "https://status.heroku.com", "docker": "https://status.docker.com", "dockerhub": "https://status.docker.com", "npm": "https://status.npmjs.org", "pypi": "https://status.python.org", "circleci": "https://status.circleci.com", # AI & ML Services "openai": "https://status.openai.com", "anthropic": "https://status.anthropic.com", "claude": "https://status.anthropic.com", "claudeapi": "https://status.anthropic.com", "anthropicclaudeapi": "https://status.anthropic.com", "gemini": "https://status.cloud.google.com", "googlegemini": "https://status.cloud.google.com", "googlegeminiapi": "https://status.cloud.google.com", "vertexai": "https://status.cloud.google.com", "googlecloudvertexai": "https://status.cloud.google.com", "googlecloud": "https://status.cloud.google.com", "replicate": "https://replicate.statuspage.io", "huggingface": "https://status.huggingface.co", "hf": "https://status.huggingface.co", "cohere": "https://status.cohere.com", "mistral": "https://status.mistral.ai", "mistralai": "https://status.mistral.ai", "together": "https://status.together.ai", "togetherai": "https://status.together.ai", "groq": "https://status.groq.com", "perplexity": "https://status.perplexity.ai", "perplexityai": "https://status.perplexity.ai", # Image/Video AI "fal": "https://fal.statuspage.io", "falai": "https://fal.statuspage.io", "midjourney": "https://status.midjourney.com", "stability": "https://status.stability.ai", "stabilityai": "https://status.stability.ai", "runway": "https://status.runwayml.com", "runwayml": "https://status.runwayml.com", "leonardo": "https://status.leonardo.ai", "leonardoai": "https://status.leonardo.ai", "ideogram": "https://status.ideogram.ai", "flux": "https://status.bfl.ml", "bfl": "https://status.bfl.ml", "blackforestlabs": "https://status.bfl.ml", "blackforestlabsbflfluxapi": "https://status.bfl.ml", "bflblackforestlabsfluxapi": "https://status.bfl.ml", # Voice/Audio AI "elevenlabs": "https://status.elevenlabs.io", "11labs": "https://status.elevenlabs.io", "resemble": "https://status.resemble.ai", "assemblyai": "https://status.assemblyai.com", "deepgram": "https://status.deepgram.com", # Video AI "heygen": "https://status.heygen.com", "descript": "https://status.descript.com", "luma": "https://status.lumalabs.ai", "lumalabs": "https://status.lumalabs.ai", "pika": "https://status.pika.art", "sync": "https://status.sync.so", "syncso": "https://status.sync.so", "synclabs": "https://status.sync.so", # Cloud Providers "aws": "https://health.aws.amazon.com/health/status", "amazon": "https://health.aws.amazon.com/health/status", "gcp": "https://status.cloud.google.com", "googlecloudplatform": "https://status.cloud.google.com", "azure": "https://status.azure.com", "microsoft": "https://status.azure.com", "digitalocean": "https://status.digitalocean.com", "linode": "https://status.linode.com", "vultr": "https://status.vultr.com", "render": "https://status.render.com", "railway": "https://railway.instatus.com", "fly": "https://status.fly.io", "flyio": "https://status.fly.io", # Databases "mongodb": "https://status.mongodb.com", "supabase": "https://status.supabase.com", "planetscale": "https://www.planetscalestatus.com", "neon": "https://neonstatus.com", "fauna": "https://status.fauna.com", "redis": "https://status.redis.com", "upstash": "https://status.upstash.com", "cockroachdb": "https://status.cockroachlabs.cloud", # Communication "twilio": "https://status.twilio.com", "sendgrid": "https://status.sendgrid.com", "mailgun": "https://status.mailgun.com", "postmark": "https://status.postmarkapp.com", "slack": "https://status.slack.com", "discord": "https://discordstatus.com", "zoom": "https://status.zoom.us", "intercom": "https://www.intercomstatus.com", # CDN & DNS "cloudflare": "https://www.cloudflarestatus.com", "fastly": "https://status.fastly.com", "akamai": "https://cloudharmony.com/status-for-akamai", # Auth & Identity "auth0": "https://status.auth0.com", "okta": "https://status.okta.com", "clerk": "https://status.clerk.com", # Analytics & Monitoring "datadog": "https://status.datadoghq.com", "newrelic": "https://status.newrelic.com", "sentry": "https://status.sentry.io", "mixpanel": "https://status.mixpanel.com", "amplitude": "https://status.amplitude.com", "segment": "https://status.segment.com", "posthog": "https://status.posthog.com", # Other "notion": "https://status.notion.so", "airtable": "https://status.airtable.com", "figma": "https://status.figma.com", "linear": "https://linearstatus.com", "jira": "https://jira-software.status.atlassian.com", "confluence": "https://confluence.status.atlassian.com", "atlassian": "https://status.atlassian.com", "shopify": "https://www.shopifystatus.com", "algolia": "https://status.algolia.com", "pinecone": "https://status.pinecone.io", "weaviate": "https://status.weaviate.io", "qdrant": "https://status.qdrant.io", "milvus": "https://status.milvus.io", } # Service name aliases - map variations to canonical names SERVICE_ALIASES = { # Anthropic/Claude variations "anthropic claude": "anthropic", "anthropic claude api": "anthropic", "claude api": "anthropic", "claude": "anthropic", # Google variations "google cloud": "gcp", "google cloud platform": "gcp", "google cloud vertex ai": "vertexai", "vertex ai": "vertexai", "google gemini": "gemini", "google gemini api": "gemini", "gemini api": "gemini", # Fal variations "fal.ai": "fal", "fal ai": "fal", "fal.ai api": "fal", # BFL/Flux variations "black forest labs": "bfl", "black forest labs flux": "bfl", "bfl flux": "bfl", "flux api": "bfl", "black forest labs bfl flux api": "bfl", "bfl black forest labs flux api": "bfl", # Sync variations "sync.so": "sync", "sync labs": "sync", # Other common variations "eleven labs": "elevenlabs", "stability ai": "stability", "runway ml": "runway", "leonardo ai": "leonardo", "hugging face": "huggingface", "together ai": "together", "mistral ai": "mistral", "perplexity ai": "perplexity", "luma labs": "luma", "fly.io": "fly", } # Common patterns to try STATUS_PAGE_PATTERNS = [ "https://status.{service}.com", "https://status.{service}.io", "https://status.{service}.ai", "https://{service}.statuspage.io", "https://{service}.instatus.com", "https://{service}status.com", "https://www.{service}status.com", "https://{service}.com/status", ] def normalize_service_name(self, service: str) -> str: """Normalize service name using aliases.""" # Clean up the input service_lower = service.lower().strip() # Check aliases first if service_lower in self.SERVICE_ALIASES: return self.SERVICE_ALIASES[service_lower] # Try partial matching for aliases for alias, canonical in self.SERVICE_ALIASES.items(): if alias in service_lower or service_lower in alias: return canonical # Remove common suffixes and clean up cleaned = service_lower for suffix in [" api", " status", " service"]: if cleaned.endswith(suffix): cleaned = cleaned[: -len(suffix)].strip() # Remove spaces, dots, dashes for lookup cleaned = cleaned.replace(" ", "").replace(".", "").replace("-", "") return cleaned def find_status_page(self, service: str) -> str | None: """Find status page URL for a service.""" # Normalize the service name normalized = self.normalize_service_name(service) # Check known mappings first if normalized in self.KNOWN_STATUS_PAGES: return self.KNOWN_STATUS_PAGES[normalized] # Also try the raw cleaned name (no alias resolution) raw_cleaned = service.lower().replace(" ", "").replace(".", "").replace("-", "") if raw_cleaned in self.KNOWN_STATUS_PAGES: return self.KNOWN_STATUS_PAGES[raw_cleaned] # Try common patterns with normalized name for pattern in self.STATUS_PAGE_PATTERNS: url = pattern.format(service=normalized) return url # Return first pattern to try return None
  • Instantiation of ServiceHealthChecker with crawler_client, imported from .service_health, used by the tool handler.
    service_health_checker = ServiceHealthChecker(crawler_client)

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/elad12390/web-research-assistant'

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