{
  "serverInfo": {
    "name": "2s.io",
    "version": "1",
    "description": "Pay-per-call AI agent APIs — patents, papers, law, geo, weather, AI utilities. Settled in USDC on Base via x402 (EIP-3009 transferWithAuthorization). No accounts, no API keys.",
    "homepage": "https://2s.io",
    "documentation": "https://2s.io/api/openapi",
    "vendor": "2s.io"
  },
  "authentication": {
    "required": true,
    "schemes": [
      "x402"
    ],
    "x402": {
      "version": 2,
      "network": "base",
      "asset": "USDC",
      "facilitator": "https://api.cdp.coinbase.com/platform/v2/x402",
      "spec": "https://x402.org"
    }
  },
  "tools": [
    {
      "name": "ai.describe-image",
      "description": "Describe an image. POST { imageUrl, instruction? }. Returns { imageUrl, altText (5-15 word accessibility text), description (2-3 sentences), contentType (photograph|illustration|screenshot|diagram|document|mixed|other), text (verbatim OCR transcription, \"\" if none), mainObjects[], dominantColors[] (hex) }. Accepts JPEG, PNG, GIF, WebP. 1MB image size cap.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "imageUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "HTTPS URL of a JPEG, PNG, GIF, or WebP image (≤1MB)."
          },
          "instruction": {
            "type": "string",
            "maxLength": 1000,
            "description": "Optional caller-supplied focus hint, e.g. \"describe the chart axes\"."
          }
        },
        "required": [
          "imageUrl"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/ai/describe-image",
      "x-2s-price-usd": 0.018
    },
    {
      "name": "ai.extract",
      "description": "Extract structured data from a webpage. POST { url, schema, instruction? }. The schema is a JSON Schema object (top-level type:\"object\") describing the shape you want back; output is guaranteed to conform. Returns { url, finalUrl, extracted, meta:{ truncated } }.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "schema": {
            "type": "object",
            "additionalProperties": {}
          },
          "instruction": {
            "type": "string",
            "maxLength": 2000
          }
        },
        "required": [
          "url",
          "schema"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/ai/extract",
      "x-2s-price-usd": 0.03
    },
    {
      "name": "ai.screenshot",
      "description": "Render a URL as a screenshot. POST { url, width?, height?, fullPage?, format?, quality?, waitUntil?, timeoutMs?, deviceScaleFactor?, blockAds? }. Returns raw image bytes (no JSON envelope) with X-2s-Render-Ms and X-2s-Image-Bytes headers. Viewport clamped 320-3840 × 320-2160. Timeout clamped 1-15s. Defaults: 1280×720 PNG, networkidle2 wait, ad-blocking on. Use cases: visual verification, archival, change detection, OG-card generation, RSS thumbnails.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "HTTPS URL to render."
          },
          "width": {
            "type": "integer",
            "minimum": 320,
            "maximum": 3840,
            "description": "Viewport width (320-3840). Default 1280."
          },
          "height": {
            "type": "integer",
            "minimum": 320,
            "maximum": 2160,
            "description": "Viewport height (320-2160). Default 720."
          },
          "fullPage": {
            "type": "boolean",
            "description": "Capture the full scrollable page instead of the viewport."
          },
          "format": {
            "type": "string",
            "enum": [
              "png",
              "jpeg",
              "webp"
            ],
            "description": "Image format. Default png."
          },
          "quality": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "description": "JPEG/WebP quality 1-100. Ignored for PNG."
          },
          "waitUntil": {
            "type": "string",
            "enum": [
              "load",
              "domcontentloaded",
              "networkidle0",
              "networkidle2"
            ],
            "description": "Wait condition before snap. Default networkidle2."
          },
          "timeoutMs": {
            "type": "integer",
            "minimum": 1000,
            "maximum": 15000,
            "description": "Render timeout in milliseconds (1000-15000). Default 8000."
          },
          "deviceScaleFactor": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "description": "Pixel density multiplier 1-3. Default 1."
          },
          "blockAds": {
            "type": "boolean",
            "description": "Block ads + trackers. Default true."
          }
        },
        "required": [
          "url"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/ai/screenshot",
      "x-2s-price-usd": 0.0075
    },
    {
      "name": "ai.summarize",
      "description": "Summarize a webpage. POST { url, instruction? }. Returns { url, finalUrl, summary (1-3 sentences), keyPoints (3-7 bullets), title, audience, estimatedReadingMinutes, meta:{ truncated } }. Sibling to /api/ai/extract — use extract when you need a typed payload conforming to your own schema; use summarize when you want a ready-made digest.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "instruction": {
            "type": "string",
            "maxLength": 1000
          }
        },
        "required": [
          "url"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/ai/summarize",
      "x-2s-price-usd": 0.0225
    },
    {
      "name": "ai.translate",
      "description": "Translate text. POST { text, targetLanguage, sourceLanguage? } — language codes are BCP-47 (e.g. \"en\", \"es-MX\", \"zh-Hans\"). Source auto-detected when omitted. Returns { text, targetLanguage, detectedSourceLanguage, confidence (high|medium|low) }. Best for short-to-medium passages; chunk long documents on your side.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 6000,
            "description": "Source text to translate (1-6000 chars)."
          },
          "targetLanguage": {
            "type": "string",
            "minLength": 2,
            "maxLength": 20,
            "description": "Target language as BCP-47 (e.g. \"en\", \"es-MX\", \"zh-Hans\")."
          },
          "sourceLanguage": {
            "type": "string",
            "minLength": 2,
            "maxLength": 20,
            "description": "Source language as BCP-47. Auto-detected when omitted."
          }
        },
        "required": [
          "text",
          "targetLanguage"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/ai/translate",
      "x-2s-price-usd": 0.0075
    },
    {
      "name": "airport.lookup",
      "description": "Look up an airport by 3-letter IATA (e.g. SFO) or 4-letter ICAO (e.g. KSFO) code. Query: code (3-5 chars, alphanumeric). Returns { airport: { id, ident, type, name, latitude, longitude, elevationFt, continent, isoCountry, isoRegion, municipality, scheduledService, icaoCode, iataCode, gpsCode, localCode, wikipediaLink } } or 404 NOT_FOUND.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "minLength": 3,
            "maxLength": 5,
            "description": "3-letter IATA or 4-letter ICAO airport code (e.g. SFO, KSFO)."
          }
        },
        "required": [
          "code"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/airport/lookup",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "airport.near",
      "description": "Airports within a radius of a coordinate, sorted by distance. Query: lat (-90..90), lon (-180..180), radius_km (1-2000, default 200), limit (1-100, default 20), type (optional: large_airport|medium_airport|small_airport|heliport|seaplane_base|balloonport|closed), country (optional 2-letter ISO 3166-1), scheduled_service (optional bool, true = commercial-service airports only). Returns { query, count, airports: [{ id, ident, name, iataCode, icaoCode, type, latitude, longitude, distanceKm, ... }] }.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number",
            "minimum": -90,
            "maximum": 90,
            "description": "Latitude in decimal degrees (-90 to 90)."
          },
          "lon": {
            "type": "number",
            "minimum": -180,
            "maximum": 180,
            "description": "Longitude in decimal degrees (-180 to 180)."
          },
          "radius_km": {
            "type": "number",
            "minimum": 1,
            "maximum": 2000,
            "default": 200,
            "description": "Search radius in kilometers (1-2000). Default 200."
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 20,
            "description": "Max airports to return (1-100). Default 20."
          },
          "type": {
            "type": "string",
            "enum": [
              "large_airport",
              "medium_airport",
              "small_airport",
              "heliport",
              "seaplane_base",
              "balloonport",
              "closed"
            ],
            "description": "Filter by airport type."
          },
          "country": {
            "type": "string",
            "pattern": "^[A-Z]{2}$",
            "description": "Filter by ISO 3166-1 alpha-2 country code (e.g. US)."
          },
          "scheduled_service": {
            "type": "boolean",
            "description": "When true, only commercial-service airports."
          }
        },
        "required": [
          "lat",
          "lon"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/airport/near",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "barcode.generate",
      "description": "Generate QR / Aztec / Data Matrix / PDF417 codes from structured payloads (url, wifi, vcard, vevent, email, sms, tel, geo, bitcoin, json, text). QR supports rounded or dotted modules, solid colors or linear/radial gradients, transparent backgrounds, configurable error correction, and a centered logo image (URL or data URI).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "format": {
            "type": "string",
            "enum": [
              "qr",
              "aztec",
              "datamatrix",
              "pdf417"
            ],
            "default": "qr"
          },
          "data": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "text"
                    ]
                  },
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  }
                },
                "required": [
                  "type",
                  "text"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "url"
                    ]
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  }
                },
                "required": [
                  "type",
                  "url"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "email"
                    ]
                  },
                  "to": {
                    "type": "string",
                    "format": "email"
                  },
                  "subject": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "body": {
                    "type": "string",
                    "maxLength": 1000
                  }
                },
                "required": [
                  "type",
                  "to"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "sms"
                    ]
                  },
                  "to": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 50
                  },
                  "body": {
                    "type": "string",
                    "maxLength": 1000
                  }
                },
                "required": [
                  "type",
                  "to"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "phone"
                    ]
                  },
                  "number": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 50
                  }
                },
                "required": [
                  "type",
                  "number"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "wifi"
                    ]
                  },
                  "ssid": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "password": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "security": {
                    "type": "string",
                    "enum": [
                      "WPA",
                      "WEP",
                      "none"
                    ]
                  },
                  "hidden": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "type",
                  "ssid"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "vcard"
                    ]
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "firstName": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "lastName": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "phone": {
                    "type": "string",
                    "maxLength": 50
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "org": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "title": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [
                  "type",
                  "name"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "geo"
                    ]
                  },
                  "lat": {
                    "type": "number",
                    "minimum": -90,
                    "maximum": 90
                  },
                  "lon": {
                    "type": "number",
                    "minimum": -180,
                    "maximum": 180
                  },
                  "altitude": {
                    "type": "number"
                  }
                },
                "required": [
                  "type",
                  "lat",
                  "lon"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "bitcoin"
                    ]
                  },
                  "address": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "amount": {
                    "type": "number",
                    "exclusiveMinimum": true,
                    "minimum": 0
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "message": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [
                  "type",
                  "address"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "calendar"
                    ]
                  },
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "start": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "end": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "location": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 1000
                  }
                },
                "required": [
                  "type",
                  "title",
                  "start",
                  "end"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "json"
                    ]
                  },
                  "value": {}
                },
                "required": [
                  "type"
                ],
                "additionalProperties": false
              }
            ]
          },
          "output": {
            "type": "string",
            "enum": [
              "svg",
              "png",
              "dataurl"
            ],
            "default": "svg"
          },
          "size": {
            "type": "integer",
            "minimum": 64,
            "maximum": 4096,
            "default": 512
          },
          "margin": {
            "type": "integer",
            "minimum": 0,
            "maximum": 16,
            "default": 4
          },
          "errorCorrection": {
            "type": "string",
            "enum": [
              "L",
              "M",
              "Q",
              "H"
            ],
            "default": "M",
            "description": "L=~7%, M=~15%, Q=~25%, H=~30% recoverable damage (QR only)."
          },
          "style": {
            "type": "object",
            "properties": {
              "modules": {
                "type": "string",
                "enum": [
                  "square",
                  "rounded",
                  "dots"
                ]
              },
              "foreground": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "linear",
                          "radial"
                        ],
                        "description": "Gradient type."
                      },
                      "stops": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "offset": {
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "color": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "offset",
                            "color"
                          ],
                          "additionalProperties": false
                        },
                        "minItems": 2,
                        "maxItems": 10
                      },
                      "rotation": {
                        "type": "number",
                        "description": "Linear gradient rotation in degrees."
                      }
                    },
                    "required": [
                      "type",
                      "stops"
                    ],
                    "additionalProperties": false
                  }
                ]
              },
              "background": {
                "type": "string",
                "description": "CSS color or \"transparent\"."
              },
              "logo": {
                "type": "object",
                "properties": {
                  "source": {
                    "type": "string",
                    "description": "https:// URL or data: URI. QR only."
                  },
                  "sizePct": {
                    "type": "number",
                    "minimum": 0.05,
                    "maximum": 0.4
                  },
                  "padding": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 32
                  },
                  "background": {
                    "type": "string"
                  },
                  "cornerRadius": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 64
                  }
                },
                "required": [
                  "source"
                ],
                "additionalProperties": false
              }
            },
            "additionalProperties": false
          }
        },
        "required": [
          "data"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/barcode/generate",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "census.zipcode",
      "description": "US Census ACS 5-year demographics for a ZIP code (ZCTA). Returns population, median age, median household income, poverty rate, household composition, race + ethnicity breakdown, education attainment, workforce (with computed unemployment rate), and housing (with computed owner-occupancy rate and median rent/home value). Backed by ~33k ZCTAs pre-ingested from api.census.gov; refreshed annually. Public-domain US government data.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "zip": {
            "type": "string",
            "pattern": "^\\d{5}$"
          }
        },
        "required": [
          "zip"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/census/zipcode",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "climate.station-near",
      "description": "Find NOAA GHCN-Daily weather stations near a coordinate. Returns up to 100 stations within a configurable radius (default 500 km), sorted by distance. Each station includes id, name, lat/lon, elevation, country/state, and GSN/HCN/WMO flags. Backed by a ~132k-station registry refreshed monthly from ncei.noaa.gov.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "lon": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "radius_km": {
            "type": "number",
            "minimum": 1,
            "maximum": 5000
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          }
        },
        "required": [
          "lat",
          "lon"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/climate/station-near",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "countdown.gif",
      "description": "Animated countdown GIF from the current UTC time to endDate. Always uncached. Supports 5 templates (default, minimal, neon, retro, corporate) and full customization: colors, fonts, dimensions, padding, cell padding, labels, dividers. Animates for `seconds` frames at `fps`.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "endDate": {
            "type": "string",
            "format": "date-time"
          },
          "template": {
            "type": "string",
            "enum": [
              "default",
              "minimal",
              "neon",
              "retro",
              "corporate"
            ]
          },
          "seconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60
          },
          "fps": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10
          },
          "width": {
            "type": "integer",
            "minimum": 200,
            "maximum": 1600
          },
          "height": {
            "type": "integer",
            "minimum": 80,
            "maximum": 800
          },
          "padding": {
            "type": "integer",
            "minimum": 0,
            "maximum": 200
          },
          "cellPadding": {
            "type": "integer",
            "minimum": 0,
            "maximum": 200
          },
          "digitFontSize": {
            "type": "integer",
            "minimum": 20,
            "maximum": 300
          },
          "labelFontSize": {
            "type": "integer",
            "minimum": 6,
            "maximum": 80
          },
          "labelPaddingY": {
            "type": "integer",
            "minimum": 0,
            "maximum": 60
          },
          "digitPaddingY": {
            "type": "integer",
            "minimum": -60,
            "maximum": 60
          },
          "letterSpacing": {
            "type": "number",
            "minimum": 0,
            "maximum": 20
          },
          "bg": {
            "type": "string",
            "maxLength": 40
          },
          "fg": {
            "type": "string",
            "maxLength": 40
          },
          "labelColor": {
            "type": "string",
            "maxLength": 40
          },
          "dividerColor": {
            "type": "string",
            "maxLength": 40
          },
          "digitFont": {
            "type": "string",
            "enum": [
              "mono",
              "sans"
            ]
          },
          "labelFont": {
            "type": "string",
            "enum": [
              "mono",
              "sans"
            ]
          },
          "digitWeight": {
            "type": "string",
            "enum": [
              "regular",
              "bold"
            ]
          },
          "showLabels": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string",
                "enum": [
                  "true",
                  "false",
                  "0",
                  "1"
                ]
              }
            ]
          },
          "showDays": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string",
                "enum": [
                  "true",
                  "false",
                  "0",
                  "1"
                ]
              }
            ]
          },
          "dividerChar": {
            "type": "string",
            "minLength": 1,
            "maxLength": 3
          },
          "expiredText": {
            "type": "string",
            "minLength": 1,
            "maxLength": 30
          },
          "labelDays": {
            "type": "string",
            "minLength": 1,
            "maxLength": 12
          },
          "labelHours": {
            "type": "string",
            "minLength": 1,
            "maxLength": 12
          },
          "labelMinutes": {
            "type": "string",
            "minLength": 1,
            "maxLength": 12
          },
          "labelSeconds": {
            "type": "string",
            "minLength": 1,
            "maxLength": 12
          }
        },
        "required": [
          "endDate"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/countdown/gif",
      "x-2s-price-usd": 0.006
    },
    {
      "name": "crypto.address-validate",
      "description": "Validate a cryptocurrency address with full checksum verification (not just regex). Returns {chain, address, valid, canonical, format, reason}. Chains: btc (P2PKH, P2SH, Bech32 SegWit v0, Taproot Bech32m), eth (full EIP-55 checksum; non-checksummed flagged), sol (Ed25519 32-byte Base58), ltc (Base58Check L.../M.../3... + ltc1 Bech32), trx (T-prefix Base58Check 0x41), xrp (r-prefix custom Base58), bch (legacy Base58Check + bitcoincash:q... CashAddr). Catches typos via cryptographic checksum; canonical field returns the checksummed/lowercased form.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chain": {
            "type": "string",
            "enum": [
              "btc",
              "eth",
              "sol",
              "ltc",
              "trx",
              "xrp",
              "bch"
            ]
          },
          "address": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "chain",
          "address"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/crypto/address-validate",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "crypto.gas-oracle",
      "description": "Live EVM gas oracle. Returns latest block baseFeePerGas + slow/standard/fast tiers derived from priority-fee percentiles (p25/p50/p75) over the trailing 4 blocks, plus a 21,000-gas transfer cost estimate in the chain native unit. Chains: base, ethereum, polygon, arbitrum, optimism. Real-time post-training data, ~5s freshness.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "chain": {
            "type": "string",
            "enum": [
              "base",
              "ethereum",
              "polygon",
              "arbitrum",
              "optimism"
            ],
            "description": "EVM chain to query: base | ethereum | polygon | arbitrum | optimism."
          }
        },
        "required": [
          "chain"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/crypto/gas-oracle",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "dns.lookup",
      "description": "Resolve a hostname over public DNS and return parsed records. Query: host (required FQDN), types (comma-separated: A,AAAA,MX,TXT,NS,CAA,SRV,CNAME,PTR,SOA — default A,AAAA,MX,TXT,NS), resolver (cloudflare|google|quad9|opendns, optional). Returns one normalized JSON shape per record type with per-type error pass-through. Reserved/local TLDs (.local, .internal, .invalid, .test, localhost) are rejected. 4s per-query timeout.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "host": {
            "type": "string",
            "minLength": 1,
            "maxLength": 253
          },
          "types": {
            "type": "string",
            "pattern": "^(A|AAAA|MX|TXT|NS|CAA|SRV|CNAME|PTR|SOA)(,(A|AAAA|MX|TXT|NS|CAA|SRV|CNAME|PTR|SOA)){0,9}$"
          },
          "resolver": {
            "type": "string",
            "enum": [
              "cloudflare",
              "google",
              "quad9",
              "opendns"
            ]
          }
        },
        "required": [
          "host"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/dns/lookup",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "domain.whois",
      "description": "Modern WHOIS via RDAP. Query: domain (e.g. example.com). Returns { domain, ldhName, handle, registrar:{ name, ianaId, url, abuseEmail, abusePhone }, registeredAt, expiresAt, updatedAt, statuses (camelCase ICANN EPP codes), nameservers[], dnssecSigned, rdapUrl }. GDPR: registrant personal data is generally redacted upstream and not returned. Some TLDs without RDAP are not supported and return 404 TLD_NOT_SUPPORTED.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "domain": {
            "type": "string",
            "minLength": 3,
            "maxLength": 253
          }
        },
        "required": [
          "domain"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/domain/whois",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "earth.now",
      "description": "Situational awareness for a coordinate: recent earthquakes (USGS) and active wildfires (NIFC) within a configurable radius. Returns each with distance-from-query in km, sorted nearest-first. Multi-source synthesis from free US Government feeds. Real-time, post-training data.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "lon": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "radius_km": {
            "type": "number",
            "minimum": 1,
            "maximum": 1000,
            "default": 500
          },
          "hours": {
            "type": "number",
            "minimum": 1,
            "maximum": 168,
            "default": 24
          },
          "min_magnitude": {
            "type": "number",
            "minimum": 0,
            "maximum": 10,
            "default": 2
          }
        },
        "required": [
          "lat",
          "lon"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/earth/now",
      "x-2s-price-usd": 0.0012
    },
    {
      "name": "geo.ip",
      "description": "Geolocate an IPv4/IPv6 address to country, region, city, and coordinates.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "ip": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "ip"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/geo/ip",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "geocode.address",
      "description": "Forward geocoding — free-text address or place name → latitude/longitude plus structured address components (houseNumber, road, suburb, city, county, state, postcode, country, countryCode). Query: q (2-500 chars), limit (1-10, default 5), country (optional 2-letter ISO 3166-1 bias). Underlying data is OpenStreetMap (ODbL). Sister: /api/geocode/reverse.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "q": {
            "type": "string",
            "minLength": 2,
            "maxLength": 500
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 5
          },
          "country": {
            "type": "string",
            "pattern": "^[a-z]{2}$"
          }
        },
        "required": [
          "q"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/geocode/address",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "geocode.reverse",
      "description": "Reverse geocoding — latitude/longitude → nearest formatted address plus structured components (houseNumber, road, suburb, city, county, state, postcode, country, countryCode). Query: lat (-90..90), lon (-180..180). Underlying data is OpenStreetMap (ODbL). Sister: /api/geocode/address.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "lon": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          }
        },
        "required": [
          "lat",
          "lon"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/geocode/reverse",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "hash.compute",
      "description": "Compute one or more cryptographic digests (MD5, SHA-1, SHA-2 family, SHA-3 family, BLAKE2) of a string or hex/base64-encoded byte buffer. Returns hex or base64-encoded digests.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "input": {
            "type": "string",
            "maxLength": 524288
          },
          "algorithms": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "md5",
                "sha1",
                "sha224",
                "sha256",
                "sha384",
                "sha512",
                "sha3-224",
                "sha3-256",
                "sha3-384",
                "sha3-512",
                "blake2b512",
                "blake2s256"
              ]
            },
            "minItems": 1,
            "maxItems": 12
          },
          "algorithm": {
            "type": "string",
            "enum": [
              "md5",
              "sha1",
              "sha224",
              "sha256",
              "sha384",
              "sha512",
              "sha3-224",
              "sha3-256",
              "sha3-384",
              "sha3-512",
              "blake2b512",
              "blake2s256"
            ]
          },
          "inputEncoding": {
            "type": "string",
            "enum": [
              "utf8",
              "hex",
              "base64"
            ],
            "default": "utf8"
          },
          "outputEncoding": {
            "type": "string",
            "enum": [
              "hex",
              "base64"
            ],
            "default": "hex"
          }
        },
        "required": [
          "input"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/hash/compute",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "image.compress",
      "description": "Compress an image. POST exactly one of { url } or { imageBase64 }, plus optional { format?: auto|png|jpeg|webp|avif (default auto = keep input format), quality?: 1-100 (default 75), lossy?: bool (default true), effort?: 1-10 (default 6) }. Returns compressed image bytes directly with X-2s-* headers: Original-Bytes, Compressed-Bytes, Saved-Percent, Output-Format, Source-Format, Source-Width, Source-Height, Process-Ms. Limits: 5MB URL fetch, ~3MB inline body, 4096 × 4096 input pixels. Animated GIF input becomes animated WebP when format=webp or auto.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "imageBase64": {
            "type": "string",
            "maxLength": 4400000
          },
          "format": {
            "type": "string",
            "enum": [
              "auto",
              "png",
              "jpeg",
              "webp",
              "avif"
            ]
          },
          "quality": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          },
          "lossy": {
            "type": "boolean"
          },
          "effort": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10
          }
        },
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/image/compress",
      "x-2s-price-usd": 0.0024
    },
    {
      "name": "ipinfo.bulk",
      "description": "Geolocate up to 100 IPv4/IPv6 addresses in a single call. Returns per-IP results in input order; failed entries include an error object instead of geo fields.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "ips": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            },
            "minItems": 1,
            "maxItems": 100
          }
        },
        "required": [
          "ips"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/ipinfo/bulk",
      "x-2s-price-usd": 0.006
    },
    {
      "name": "law.case-search",
      "description": "Search US court opinions (SCOTUS, federal circuits, state appellate/supreme — ~9M opinions). Query by free-text (party names, keywords, docket #, citation). Filter by court slug (e.g., \"scotus\", \"ca9\", \"nysupct\"), filing date range, and order (relevance/dateFiled-desc/dateFiled-asc/citeCount-desc). Returns clusterId, caseName, court, year, docket, reporter citations, citationCount, snippet, canonical URL. Discovery-side complement to case-verify. Backed by CourtListener (Free Law Project); underlying opinions are public domain.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "q": {
            "type": "string",
            "minLength": 2,
            "maxLength": 500
          },
          "court": {
            "type": "string",
            "pattern": "^[a-z0-9-]{2,40}(,[a-z0-9-]{2,40}){0,9}$"
          },
          "filedAfter": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "filedBefore": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "order": {
            "type": "string",
            "enum": [
              "relevance",
              "dateFiled-desc",
              "dateFiled-asc",
              "citeCount-desc"
            ]
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 10
          }
        },
        "required": [
          "q"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/law/case-search",
      "x-2s-price-usd": 0.0036
    },
    {
      "name": "law.case-verify",
      "description": "Verify US legal case citations in a passage of text. POST { text } where text contains one or more citations (e.g. \"Marbury v. Madison, 5 U.S. 137 (1803)\"). Returns per-citation results with canonical case name, court, year, docket, citationCount, and a public CourtListener URL — or flags the citation as unverified. Anti-hallucination check for legal LLM output. Underlying opinions are public domain; CourtListener (Free Law Project) is the corpus.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 30000
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/law/case-verify",
      "x-2s-price-usd": 0.006
    },
    {
      "name": "law.federal-register",
      "description": "Search the US Federal Register — proposed rules, final rules, notices, and presidential documents. Filter by free-text term, document type (RULE/PRORULE/NOTICE/PRESDOCU), agency slug (e.g., epa, fda, sec), and publication date range. Returns document_number, type, title, abstract, FR citation, agencies, publication_date, effective_on, comments_close_on, htmlUrl, pdfUrl, rawTextUrl. Public-domain US government data. Real-time — published daily, past LLM training cutoff.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "q": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500
          },
          "type": {
            "type": "string",
            "enum": [
              "RULE",
              "PRORULE",
              "NOTICE",
              "PRESDOCU"
            ]
          },
          "agency": {
            "type": "string",
            "pattern": "^[a-z0-9-]{2,60}$"
          },
          "since": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "until": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 10
          }
        },
        "required": [
          "q"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/law/federal-register",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "law.opinion",
      "description": "Fetch the full text of a US court opinion by CourtListener opinion ID OR by citation. Returns plain text (preferred), HTML fallback, case metadata (case name, court, year, docket, citation), opinion type (lead/concurrence/dissent), author, and a list of alternate opinions in the same cluster. POST { opinionId?: number, citation?: string } — exactly one required. Anti-hallucination follow-up to case-verify: once you confirm the citation exists, fetch the text. Backed by CourtListener (public-domain underlying corpus).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "opinionId": {
            "type": "integer",
            "exclusiveMinimum": true,
            "minimum": 0
          },
          "citation": {
            "type": "string",
            "minLength": 2,
            "maxLength": 500
          }
        },
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/law/opinion",
      "x-2s-price-usd": 0.0048
    },
    {
      "name": "law.sanctions-check",
      "description": "Fuzzy-match a name (person, company, vessel, aircraft) against the US Treasury OFAC Specially Designated Nationals list. POST { query, threshold?, limit?, sourceList? }. Returns ranked matches with similarity scores, entity type, sanctions programs, aliases, and remarks. Threshold default 0.4; scores ≥ 0.85 flagged as hasHighConfidenceMatch. List refreshed daily from public US Treasury data.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "minLength": 2,
            "maxLength": 500
          },
          "threshold": {
            "type": "number",
            "minimum": 0.1,
            "maximum": 1
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          },
          "sourceList": {
            "type": "string",
            "maxLength": 64
          }
        },
        "required": [
          "query"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "POST",
      "x-2s-path": "/api/law/sanctions-check",
      "x-2s-price-usd": 0.0048
    },
    {
      "name": "papers.search",
      "description": "Unified scientific literature search across arXiv (preprints), PubMed (biomedical), and Semantic Scholar (cross-field, with citation counts). Returns a flat array of papers with stable schema: source, sourceId, doi, title, authors, abstract, year, publishedAt, citationCount, url, pdfUrl. Partial failures surface in the errors array rather than failing the whole call. Optional filters: since (YYYY-MM-DD), sources (subset), limit (max 20 per source).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "q": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 10
          },
          "since": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          },
          "sources": {
            "type": "string"
          }
        },
        "required": [
          "q"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/papers/search",
      "x-2s-price-usd": 0.0024
    },
    {
      "name": "patents.detail",
      "description": "Full US patent application file-wrapper detail by application number. Returns bibliographic data (title, inventors, applicants, dates, status, examiner, art unit, docket #, confirmation #) plus the file-wrapper event timeline (filing, IDS, Office Actions, allowance, abandonment, …), continuity chain (parent / continuation / divisional / national stage), recorded assignments (assignor → assignee with reel/frame + conveyance text), and foreign priority claims under 35 USC § 119. Application number is the 6-10 digit USPTO ID (e.g. 18566276).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "applicationNumber": {
            "type": "string",
            "pattern": "^[0-9]{6,10}$"
          }
        },
        "required": [
          "applicationNumber"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/patents/detail",
      "x-2s-price-usd": 0.0018
    },
    {
      "name": "patents.documents",
      "description": "List every document in the file wrapper for a US patent application. Returns each document with its USPTO code (e.g. CTNF non-final OA, CTFR final OA, IDS, WCLM claims worksheet, NOA notice of allowance), human-readable description, official date, direction (INTERNAL/INCOMING/OUTGOING), and available formats with page counts. Includes patentCenterUrl pointing at the public USPTO Patent Center documents page for direct PDF download. Application number is the 6-10 digit USPTO ID.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "applicationNumber": {
            "type": "string",
            "pattern": "^[0-9]{6,10}$"
          }
        },
        "required": [
          "applicationNumber"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/patents/documents",
      "x-2s-price-usd": 0.0018
    },
    {
      "name": "patents.search",
      "description": "Search US patent applications and grants via the USPTO Open Data Portal. Query: q (required, 2+ chars), yearFrom / yearTo (optional filing-year bounds), applicationType (optional: Utility|Design|Plant|Reissue), limit (1-100, default 10), offset (0-based, default 0). Returns { total, returned, offset, limit, hits[{ applicationNumber, title, applicationType, firstInventor, inventors[], applicants[], filingDate, effectiveFilingDate, status:{ code, description, updatedAt }, cpcSymbols[], uspcSymbol, url }] }. URLs link to USPTO Patent Center for the public file wrapper.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "q": {
            "type": "string",
            "minLength": 2,
            "maxLength": 500
          },
          "yearFrom": {
            "type": "integer",
            "minimum": 1790,
            "maximum": 2100
          },
          "yearTo": {
            "type": "integer",
            "minimum": 1790,
            "maximum": 2100
          },
          "applicationType": {
            "type": "string",
            "enum": [
              "Utility",
              "Design",
              "Plant",
              "Reissue"
            ]
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 10
          },
          "offset": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000,
            "default": 0
          }
        },
        "required": [
          "q"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/patents/search",
      "x-2s-price-usd": 0.0018
    },
    {
      "name": "poi.near",
      "description": "Find points of interest near a coordinate. Backed by OpenStreetMap via the Overpass API (free, public, ODbL). Returns name, OSM id (e.g. node/123 — deep-linkable to openstreetmap.org), latitude, longitude, distance in meters, composed street address (when present), phone, website, opening hours, brand, and cuisine tags. Results sorted nearest-first. Supported categories: restaurant, cafe, bar, fast_food, gas_station, ev_charging, parking, atm, bank, hospital, pharmacy, clinic, doctor, dentist, police, fire_station, post_office, library, toilets, school, university, supermarket, convenience, hotel, hostel, museum, attraction, park, playground. Query: lat (-90..90), lon (-180..180), category (one of the supported names), radius_m (1-10000, default 1000), limit (1-100, default 20).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "lon": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "category": {
            "type": "string",
            "enum": [
              "restaurant",
              "cafe",
              "bar",
              "fast_food",
              "gas_station",
              "ev_charging",
              "parking",
              "atm",
              "bank",
              "hospital",
              "pharmacy",
              "clinic",
              "doctor",
              "dentist",
              "police",
              "fire_station",
              "post_office",
              "library",
              "toilets",
              "school",
              "university",
              "supermarket",
              "convenience",
              "hotel",
              "hostel",
              "museum",
              "attraction",
              "park",
              "playground"
            ]
          },
          "radius_m": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000,
            "default": 1000
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "default": 20
          }
        },
        "required": [
          "lat",
          "lon",
          "category"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/poi/near",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "quakes.recent",
      "description": "Recent earthquakes near a coordinate. Returns each quake with magnitude, place name, time (ISO), latitude/longitude/depth, tsunami flag, USGS event URL, and distance-from-query in km — sorted by time descending. Real-time data, post-LLM-training-cutoff. Backed by USGS FDSN event API (public domain). Query: lat (-90..90), lon (-180..180), radius_km (1-1000, default 500), hours (1-720, default 24), min_magnitude (0-10, default 2.0).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "lon": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "radius_km": {
            "type": "number",
            "minimum": 1,
            "maximum": 1000,
            "default": 500
          },
          "hours": {
            "type": "number",
            "minimum": 1,
            "maximum": 720,
            "default": 24
          },
          "min_magnitude": {
            "type": "number",
            "minimum": 0,
            "maximum": 10,
            "default": 2
          }
        },
        "required": [
          "lat",
          "lon"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/quakes/recent",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "sunrise.compute",
      "description": "Compute sunrise, sunset, solar noon, and civil/nautical/astronomical twilight times for a coordinate + date. Query: lat (-90..90), lon (-180..180), date (YYYY-MM-DD). All times returned as ISO 8601 UTC. At high latitudes near solstices an event may not occur (polar day/night) — those fields return null and a note is included. dayLengthMinutes is the sunrise→sunset interval.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "lon": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "date": {
            "type": "string",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
          }
        },
        "required": [
          "lat",
          "lon",
          "date"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/sunrise/compute",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "tides.now",
      "description": "Next high/low tide predictions near a coordinate. Query: lat (-90..90), lon (-180..180), radius_km (1-500, default 100), hours (1-72, default 24). Returns { query, station:{ id, name, latitude, longitude, state, distanceKm }, predictions[{ time (station local), type: \"high\"|\"low\", heightMeters }], source }. Returns 404 NO_STATION if no NOAA tide station is within radius. Heights are referenced to MLLW (Mean Lower-Low Water).",
      "inputSchema": {
        "type": "object",
        "properties": {
          "lat": {
            "type": "number",
            "minimum": -90,
            "maximum": 90
          },
          "lon": {
            "type": "number",
            "minimum": -180,
            "maximum": 180
          },
          "radius_km": {
            "type": "number",
            "minimum": 1,
            "maximum": 500,
            "default": 100
          },
          "hours": {
            "type": "number",
            "minimum": 1,
            "maximum": 72,
            "default": 24
          }
        },
        "required": [
          "lat",
          "lon"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/tides/now",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "url.clean",
      "description": "Fetch any URL and return the article content as clean markdown (with optional plain-text version). Strips nav, footer, ads, sidebars, scripts, styles, comments. Heuristic article extraction picks <article> / <main> / role=main / densest content block. SSRF-guarded, 512KB body cap, 8s timeout, 5 redirects max. Returns { url, finalUrl, title, markdown, text, wordCount, sourceBytes }. Sister to /api/url/unfurl (which returns metadata + 500-char preview); use clean when you want the FULL article for LLM consumption.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          },
          "format": {
            "type": "string",
            "enum": [
              "markdown",
              "text",
              "both"
            ],
            "default": "markdown"
          }
        },
        "required": [
          "url"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/url/clean",
      "x-2s-price-usd": 0.00108
    },
    {
      "name": "url.unfurl",
      "description": "Fetch any URL and extract structured page metadata: title, description, og:image, canonical, favicon, site name, author, published time, language, and the first ~500 chars of body text. SSRF-guarded against private networks. 8s timeout, 512 KB max body. Returns the parsed metadata plus the raw og:/twitter:/itemprop meta dictionary for inspection.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048
          }
        },
        "required": [
          "url"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/url/unfurl",
      "x-2s-price-usd": 0.001
    },
    {
      "name": "weather.zip",
      "description": "Current weather conditions for a US ZIP code (temperature, wind, humidity, conditions). Backed by the US National Weather Service (api.weather.gov) — public domain, no rate-limit pressure on commercial use.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "zip": {
            "type": "string",
            "pattern": "^\\d{5}$"
          }
        },
        "required": [
          "zip"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/weather/zip",
      "x-2s-price-usd": 0.0012
    },
    {
      "name": "wikipedia.summary",
      "description": "Fetch a Wikipedia article summary in any of 30 supported languages. Returns title, displayTitle, lang, pageId, description, extract (plain text), extractHtml, lead image, canonical URLs, last-modified timestamp, word count, license, and an attribution string. Backed by https://<lang>.wikipedia.org/api/rest_v1/page/summary. Content is CC BY-SA 4.0 with attribution provided.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300
          },
          "lang": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "fr",
              "de",
              "it",
              "pt",
              "ru",
              "ja",
              "zh",
              "ko",
              "ar",
              "nl",
              "pl",
              "tr",
              "sv",
              "cs",
              "fi",
              "da",
              "no",
              "el",
              "he",
              "hi",
              "th",
              "vi",
              "uk",
              "id",
              "ms",
              "ro",
              "hu",
              "simple"
            ],
            "default": "en"
          }
        },
        "required": [
          "title"
        ],
        "additionalProperties": false
      },
      "x-2s-method": "GET",
      "x-2s-path": "/api/wikipedia/summary",
      "x-2s-price-usd": 0.001
    }
  ],
  "resources": [],
  "prompts": []
}