# /// script
# requires-python = ">=3.10"
# dependencies = ["mcp==1.30.0", "httpx>=0.28,<1"]
# ///
"""Local stdio MCP adapter. Run with uv run validatedmails_mcp.py."""
import os
from typing import Annotated, Any

import httpx
from mcp.server.fastmcp import FastMCP
from pydantic import Field

API_ORIGIN = "https://api.validatedmails.com"
mcp = FastMCP(
    "ValidatedMails",
    instructions=(
        "Verify credentials first with check_api_key (free). Validation uses prepaid credits: "
        "one per conclusive result; unknown results are not charged. "
        "Use status (valid, risky, invalid, unknown), not reason, for decisions. "
        "Unknown does not mean invalid. Do not automatically retry paid requests."
    ),
)


async def api_request(method: str, path: str, payload: dict | None = None) -> dict[str, Any]:
    key = os.environ.get("VALIDATEDMAILS_API_KEY", "").strip()
    if not key:
        raise ValueError("Set VALIDATEDMAILS_API_KEY in the MCP server environment.")
    try:
        async with httpx.AsyncClient(timeout=120, follow_redirects=False) as client:
            response = await client.request(
                method, API_ORIGIN + path,
                headers={"Authorization": f"Bearer {key}"}, json=payload,
            )
    except httpx.RequestError:
        raise ValueError(
            "The API could not be reached or timed out. The request may have completed; "
            "do not automatically retry a paid validation."
        ) from None
    if not response.is_success:
        messages = {
            401: "API key rejected. Check or replace VALIDATEDMAILS_API_KEY.",
            402: "Insufficient credits. Add credits in the console.",
            429: "Rate limited or capacity unavailable. Wait before trying again.",
        }
        request_id = response.headers.get("X-Request-Id", "unavailable")[:128]
        raise ValueError(
            f"{messages.get(response.status_code, 'API request failed.')} "
            f"HTTP {response.status_code}; request ID: {request_id}"
        )
    try:
        data = response.json()
    except ValueError:
        raise ValueError("API returned an unreadable response. Do not automatically retry paid requests.") from None
    if not isinstance(data, dict):
        raise ValueError("API returned an unexpected response shape.")
    return data


@mcp.tool(annotations={"readOnlyHint": True, "openWorldHint": True})
async def check_api_key() -> dict[str, Any]:
    """Verify the configured API key and return its account identity. Costs no credits."""
    return await api_request("GET", "/api-keys/me")


Email = Annotated[str, Field(min_length=3, max_length=320, description="Email address to verify")]


@mcp.tool(annotations={"readOnlyHint": False, "destructiveHint": False, "idempotentHint": False, "openWorldHint": True})
async def validate_email(email: Email) -> dict[str, Any]:
    """Verify one email. Costs one credit for valid/risky/invalid; unknown is free."""
    return await api_request("POST", "/validate", {"email": email})


@mcp.tool(annotations={"readOnlyHint": False, "destructiveHint": False, "idempotentHint": False, "openWorldHint": True})
async def validate_batch(emails: Annotated[list[Email], Field(min_length=1, max_length=100)]) -> dict[str, Any]:
    """Verify 1–100 emails in input order. Each conclusive result costs one credit.

    Inspect both per-item errors and status; a successful HTTP response may contain
    partial failures. Unknown results are free. Do not automatically retry a batch.
    """
    return await api_request("POST", "/validate/batch", {"emails": emails})


if __name__ == "__main__":
    mcp.run(transport="stdio")
