{
  "name": "VASTlint",
  "title": "VASTlint",
  "display_name": "VASTlint",
  "subtitle": "IAB VAST tag validator",
  "short_description": "IAB VAST tag validator",
  "developer_name": "VASTlint",
  "category": "Developer Tools",
  "mcp_server_url": "https://vastlint.org/mcp",
  "mcp_url_type": "universal",
  "authentication": "none",
  "website_url": "https://vastlint.org/",
  "privacy_url": "https://vastlint.org/privacy/",
  "terms_url": "https://vastlint.org/terms/",
  "support_url": "https://github.com/aleksUIX/vastlint/issues",
  "company_url": "https://vastlint.org/",
  "logo_url": "https://vastlint.org/openai/logo-512.png",
  "composer_icon_url": "https://vastlint.org/openai/logo-512.png",
  "contact_email": "aleks@vastlint.org",
  "chatgpt_connector_description": "Validate VAST, VMAP, or DAAST tags. Call the tools. Do not send the user to a website.",
  "description": "Call validate_vast or validate_vast_url when the user wants to check a VAST, VMAP, or DAAST tag. Return rule IDs, severities, and fix guidance. Do not send the user to a website instead of calling the tool.",
  "long_description": "VASTlint checks VAST, VMAP, and DAAST XML against IAB Tech Lab specs (VAST 2.0 through 4.3, plus SIMID envelope checks). Paste XML to run validate_vast, or pass a live tag URL to validate_vast_url. inspect_vast follows wrapper chains hop by hop. list_rules and explain_rule return stable rule IDs. fix_vast returns repaired XML (HTTPS upgrades and deprecated-attribute cleanup); it does not write to the user's ad server.\n\nPublic tools require no login. AdCP content-standards tools on the same host are Bearer-protected and are not part of the ChatGPT listing. Tags sent to the hosted endpoint may be stored with identifiers stripped; see the privacy policy. For tags that must not leave the machine, use local vastlint-mcp over stdio.",
  "domain_verification": {
    "path": "/.well-known/openai-apps-challenge",
    "host": "https://vastlint.org",
    "notes": "Paste the token from the OpenAI plugin portal into apps/vastlint-web/public/.well-known/openai-apps-challenge as a single line with no extra whitespace, then ship. The response must be that token only, text/plain, no JSON."
  },
  "starter_prompts": [
    "Fetch https://vastlint.org/samples/vast-4.2-inline.xml and say if it is spec-valid.",
    "Validate an empty VAST 4.2 document and list every error with its rule ID.",
    "What does rule VAST-2.0-impression-missing mean and how do I fix it?"
  ],
  "capabilities": [
    "Validate pasted VAST, VMAP, and DAAST XML",
    "Fetch and validate a live VAST tag URL",
    "Inspect VAST wrapper chains hop by hop",
    "Explain a VAST rule ID and how to fix it"
  ],
  "test_prompts": [
    {
      "prompt": "Validate this VAST tag and list every error with its rule ID: <VAST version=\"4.2\"></VAST>",
      "expect_tool": "validate_vast"
    },
    {
      "prompt": "Fetch https://vastlint.org/samples/vast-4.2-inline.xml and tell me if it is spec-valid.",
      "expect_tool": "validate_vast_url"
    },
    {
      "prompt": "What does rule VAST-2.0-impression-missing mean and how do I fix it?",
      "expect_tool": "explain_rule"
    },
    {
      "prompt": "List VAST validation rules that mention duration.",
      "expect_tool": "list_rules"
    }
  ],
  "test_cases": [
    {
      "description": "Validate a live sample tag URL.",
      "user_prompt": "Fetch https://vastlint.org/samples/vast-4.2-inline.xml and tell me if it is spec-valid.",
      "tools_triggered": "validate_vast_url",
      "expected_output": "A validation result for the fetched XML, with valid true or false and any rule IDs."
    },
    {
      "description": "Validate an empty VAST 4.2 document.",
      "user_prompt": "Validate this VAST tag and list every error with its rule ID: <VAST version=\"4.2\"></VAST>",
      "tools_triggered": "validate_vast",
      "expected_output": "valid false, with rule IDs for a document that has no Ad and no Error."
    },
    {
      "description": "Explain a stable rule ID.",
      "user_prompt": "What does rule VAST-2.0-impression-missing mean and how do I fix it?",
      "tools_triggered": "explain_rule",
      "expected_output": "Description, spec reference, trigger, and fix guidance for VAST-2.0-impression-missing."
    },
    {
      "description": "List rules that mention duration.",
      "user_prompt": "List VAST validation rules that mention duration.",
      "tools_triggered": "list_rules",
      "expected_output": "A filtered rule catalog with IDs and short descriptions."
    },
    {
      "description": "Inspect a sample tag as a wrapper chain of one hop.",
      "user_prompt": "Inspect https://vastlint.org/samples/vast-4.2-inline.xml hop by hop.",
      "tools_triggered": "inspect_vast",
      "expected_output": "Hop metadata (AdSystem, AdTitle, Duration, media files) plus validation for that hop."
    }
  ],
  "negative_test_cases": [
    {
      "description": "Weather is outside the plugin.",
      "user_prompt": "What is the weather in Paris today?",
      "tools_triggered": null,
      "expected_output": "Answer without calling VASTlint tools."
    },
    {
      "description": "Travel booking is outside the plugin.",
      "user_prompt": "Book me a flight from SFO to JFK tomorrow.",
      "tools_triggered": null,
      "expected_output": "Refuse or answer without calling VASTlint tools."
    },
    {
      "description": "Destructive third-party file access is outside the plugin.",
      "user_prompt": "Delete every file in my Google Drive.",
      "tools_triggered": null,
      "expected_output": "Refuse. Do not call VASTlint tools."
    }
  ],
  "annotation_justifications": {
    "validate_vast": {
      "readOnlyHint": true,
      "openWorldHint": false,
      "destructiveHint": false,
      "read_only_justification": "Parses the supplied XML in memory and returns issues; it does not write to any ad server or datastore as part of the user's request.",
      "open_world_justification": "Operates only on XML in the tool arguments; it does not fetch URLs or change public internet state.",
      "destructive_justification": "Does not delete, overwrite, or revoke anything."
    },
    "validate_vast_url": {
      "readOnlyHint": true,
      "openWorldHint": true,
      "destructiveHint": false,
      "read_only_justification": "GETs the tag URL and validates the response body; it does not update the remote tag.",
      "open_world_justification": "Fetches an arbitrary HTTP URL supplied by the user, so it contacts hosts outside this server.",
      "destructive_justification": "The fetch is a read; it does not delete or overwrite remote resources."
    },
    "inspect_vast": {
      "readOnlyHint": true,
      "openWorldHint": true,
      "destructiveHint": false,
      "read_only_justification": "Follows wrapper hops with GET requests and reports metadata; it does not modify those tags.",
      "open_world_justification": "Fetches user-supplied and wrapper-chain URLs on the public internet.",
      "destructive_justification": "Does not delete or overwrite remote tags."
    },
    "list_rules": {
      "readOnlyHint": true,
      "openWorldHint": false,
      "destructiveHint": false,
      "read_only_justification": "Returns the static rule catalog.",
      "open_world_justification": "Does not contact third-party hosts.",
      "destructive_justification": "Does not delete or overwrite anything."
    },
    "explain_rule": {
      "readOnlyHint": true,
      "openWorldHint": false,
      "destructiveHint": false,
      "read_only_justification": "Looks up one rule ID and returns guidance.",
      "open_world_justification": "Does not contact third-party hosts.",
      "destructive_justification": "Does not delete or overwrite anything."
    },
    "fix_vast": {
      "readOnlyHint": false,
      "openWorldHint": false,
      "destructiveHint": false,
      "read_only_justification": "Returns a transformed XML string (HTTPS upgrades and deprecated-attribute cleanup), so it is a write against the document in the conversation.",
      "open_world_justification": "Does not publish the repaired tag to any ad server or public URL.",
      "destructive_justification": "Transformations are reversible by the user keeping the original XML; the tool does not delete remote resources."
    }
  },
  "claude_directory": {
    "server_name": "VASTlint",
    "slug": "vastlint",
    "tagline": "Validate VAST, VMAP, and DAAST tags against IAB specs",
    "auth": "none",
    "icon_url": "https://vastlint.org/openai/logo-512.png",
    "documentation_url": "https://vastlint.org/docs/mcp/",
    "categories": ["Developer tools"]
  },
  "public_tools": [
    "validate_vast",
    "validate_vast_url",
    "inspect_vast",
    "list_rules",
    "explain_rule",
    "fix_vast"
  ],
  "release_notes": "Initial public MCP plugin. Hosted endpoint https://vastlint.org/mcp. Authentication none. Public VAST tools only. No custom UI, so no screenshots.",
  "submission": {
    "portal": "https://developers.openai.com/plugins/deploy/submission",
    "mcp_docs": "https://developers.openai.com/plugins/build/mcp-server",
    "scan_tools": "Use MCP server URL https://vastlint.org/mcp, authentication none, then Scan Tools.",
    "notes": [
      "Choose Universal MCP server URL.",
      "Public VAST tools declare securitySchemes noauth.",
      "Do not configure OAuth. There is no authorization server on vastlint.org.",
      "If Scan Tools lists AdCP content-standards tools, leave them unused. They are Bearer-protected and not part of this listing.",
      "Display name and short description must stay at or under 30 characters.",
      "Submit exactly five positive test cases and three negative test cases from this file.",
      "Starter prompts: at most three, one line, at most 128 characters, no @mentions.",
      "No plugin UI: do not upload screenshots.",
      "Demo-recording URL is required by the portal. Record ChatGPT calling validate_vast_url on the sample tag, then paste an unlisted video URL.",
      "AdCP content-standards tools stay Bearer-protected and are not part of the ChatGPT listing."
    ]
  }
}
