Skip to main content

Squillify development is paused indefinitely. Read why, and discover what this experiment achieved. Read the story

MicroSkills Reference

MCP Tool Descriptor Check

schema.validate_mcp_tool_descriptor

ProductionBounded custom (Class B)Deterministicstrictinstantv1.0.0
No network

Overview

You send one MCP tool descriptor and name the revision it targets, and we answer two questions separately. Eleven completeness rules decide whether a client can reliably invoke it — a usable name, an object inputSchema that is itself a well-formed schema, required entries that name real properties, annotations inside the published set, no key from a revision later than the one you declared — and failing any of those makes valid false. Ten clarity rules decide whether an agent can choose it correctly — descriptions long enough to mean something, properties that say what to send, a name in namespace.verb shape, a mutating verb backed by a hint — and those come back as warnings, leaving valid true, so a build can gate on invocability without gating on prose.

A descriptor is the only thing standing between an agent and the wrong tool call, and the two ways it fails are different: one stops the call outright, the other quietly makes the tool the wrong choice. Mixing them in one severity column is how a build gate ends up switched off.

Reliability

The same descriptor, dialect and rule settings always produce the same findings in the same order, independent of your machine's locale, time zone and default character set. valid reflects the eleven completeness rules only; the ten clarity rules never change it. Whether an inputSchema is itself a schema is decided by the same engine schema.validate_json uses, so the two cannot disagree. A reference problem inside inputSchema or outputSchema is reported as MCPD-E-011; switch that rule off through rules.enabled and the call is refused with the matching MCPD_REF_ failure instead, because a reference graph we have no rule for is not one we will walk. Eleven refusals stop the call and an unchanged retry will not help. MCPD_DESCRIPTOR_INVALID means descriptor is absent or is not an object; MCPD_DESCRIPTOR_TOO_LARGE means it is over 65536 bytes, so trim it; MCPD_DIALECT_UNSUPPORTED means dialect is not one of the three published names; MCPD_RULE_UNKNOWN means rules.enabled names a code outside MCPD-E-001 to MCPD-E-011 and MCPD-W-001 to MCPD-W-010; MCPD_RULE_PARAMETER_INVALID means a threshold is outside its published range; MCPD_OPTION_UNSUPPORTED_FOR_DIALECT means requireOutputSchema was set on MCP_TOOL_2025_03_26, which has no such key, so declare the newer dialect instead; MCPD_NODE_LIMIT_EXCEEDED means the descriptor has over 20000 nodes, nests deeper than 64 levels, breaks a per-object cap, or its schemas would pass 100000 nodes once local references were expanded; MCPD_REF_REMOTE_REFUSED, MCPD_REF_CYCLE_DETECTED and MCPD_REF_DEPTH_EXCEEDED are the reference refusals above; and MCPD_WORK_REFUSED means the run was projected past the 2000000-unit budget before it started and reports both numbers.

Context footprint

Findings carry codes and pointers rather than descriptor text, so a report stays small; the two lists cap at 500 errors and 200 warnings with truncated set when either is exceeded. A 65536-byte descriptor under those caps cannot reach the platform's 2 MiB inline ceiling, so this skill publishes no output-size refusal. A successful call costs 1 execution credit.

When to use it

Before publishing or changing a tool descriptor, especially when clients on more than one MCP revision will read it.

When you want to validate a caller's arguments, or when the document is a plain JSON Schema rather than a tool descriptor.

Scope

Note
We judge one MCP tool descriptor against twenty-one published rules and return the invocability failures and the selectability advice in two separate lists.

Non-goals

  • We never call the tool, or check that it does what it says
  • We never validate a document against the descriptor's inputSchema
  • We never rewrite the descriptor or suggest replacement text
  • We never guess which revision a descriptor targets: you declare it

Properties

IdempotentRetry safeStreaming supportedFile input supportedRequires external service

Capabilities

analysisvalidation

Cost & billing

Flat rate per invocation

MetercallsBillable onsuccessCost per call1 credit

File handling

Accepts file_refProduces file_refMax input64 KB

How we handle your data

Sensitive input, safe output
What this means

This skill may receive sensitive content, but it does not target sensitive data and returns only a structured non-sensitive result.

Squillify guarantees
  • Runs inside Squillify
  • This skill runs inside Squillify.
  • Payloads are not sent to an external service by this skill.
  • Squillify does not permanently store submitted payloads.
  • Telemetry records metadata only, not submitted content.
  • Submitted payloads are not used for training.
  • Submitted payloads are not reviewed by humans.
  • This skill does not target sensitive data.
  • The response does not contain submitted content.
Your responsibility

Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.

Read the Microskill Data Handling Policy

Input schema

FieldTypeRequiredDescription
descriptorobjectYesOne MCP tool descriptor as a JSON object, 2 through 65536 bytes; extra keys are descriptor fields. — unconstrained RFC 8259 JSON items.
dialectstringNoRevision the descriptor targets; omit it for MCP_TOOL_2025_06_18.
rulesobjectNoClosed published thresholds and an optional enabled-code list; omit the object to run all 21 rules with documented defaults.

Output schema

FieldTypeRequiredDescription
validbooleanYesTrue when the errors list is empty; warnings never change it.
errorsarrayYesCompleteness findings that make valid false, 0 through 500 closed objects with code, pointer, optional keyword and message.
warningsarrayYesClarity findings that never change valid, 0 through 200 closed objects with code, pointer, optional keyword and message.
dialectAppliedstringYesRevision the rules actually ran under.
ruleProfilestringYesRule-profile version such as mcp-descriptor-rules-1.
summaryobjectYesClosed unfiltered counts with errorCount, warningCount, propertyCount, rulesEvaluated and truncated.

API contract

POST /v1/execute
curl
curl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"schema.validate_mcp_tool_descriptor","input":{"descriptor":{"name":"weather.get_forecast","description":"Returns a forecast for one city.","inputSchema":{"type":"object"}}}}'
Integrations
TypeScript SDK
import { Squillify } from "@squillify/sdk";

const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });

const { output } = await sq.execute("schema.validate_mcp_tool_descriptor", {"descriptor":{"name":"weather.get_forecast","description":"Weather.","inputSchema":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}});

Errors

CodeHTTPRetryableDescription
VALIDATION_ERROR400NoThe request payload failed schema validation.
UNAUTHORIZED401NoMissing or invalid API key.
SKILL_NOT_ACCESSIBLE403NoThe API key is not granted access to this skill.
SKILL_NOT_AVAILABLE_FOR_PLAN403NoThis skill is not included in your current plan.
PLAN_ELIGIBILITY_UNAVAILABLE503YesPlan eligibility could not be decided. Retry after backoff.
SKILL_NOT_FOUND404NoThe requested skill or version does not exist.
TENANT_RATE_LIMITED429YesRequest rate limit exceeded. Retry after backoff.
QUOTA_EXCEEDED429YesPlan quota exhausted. Retryable once the quota period resets.
EXECUTION_TIMEOUT504YesExecution exceeded the allowed time budget.
MCPD_DESCRIPTOR_INVALID400NoThe request payload failed this skill's input validation.
MCPD_DESCRIPTOR_TOO_LARGE429NoA size, quota, rate, or time limit was exceeded.
MCPD_DIALECT_UNSUPPORTED400NoThe skill does not support the requested variant.
MCPD_RULE_UNKNOWN400NoThe request payload failed this skill's input validation.
MCPD_RULE_PARAMETER_INVALID400NoThe request payload failed this skill's input validation.
MCPD_OPTION_UNSUPPORTED_FOR_DIALECT400NoThe skill does not support the requested variant.
MCPD_NODE_LIMIT_EXCEEDED429NoA size, quota, rate, or time limit was exceeded.
MCPD_REF_REMOTE_REFUSED400NoThe request payload failed this skill's input validation.
MCPD_REF_CYCLE_DETECTED400NoThe request payload failed this skill's input validation.
MCPD_REF_DEPTH_EXCEEDED429NoA size, quota, rate, or time limit was exceeded.
MCPD_WORK_REFUSED429NoA size, quota, rate, or time limit was exceeded.

Other limits

LimitValue
Recommended inline bytes32 KiB

Limitations

  • We never call the tool, or check that it does what it says
  • We never validate a document against the descriptor's inputSchema
  • We never rewrite the descriptor or suggest replacement text
  • We never guess which revision a descriptor targets: you declare it
  • Validating arguments a caller sent against the descriptor's inputSchema
  • Judging a plain JSON Schema that is not a tool descriptor

How to call

POST /v1/execute (requires authentication)

Request bodyjson
{
  "skillKey": "schema.validate_mcp_tool_descriptor",
  "input": {
    "descriptor": {
      "name": "weather.get_forecast",
      "description": "Weather.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "city": {
            "type": "string"
          }
        },
        "required": [
          "city"
        ]
      }
    }
  }
}

Examples

A descriptor a client can invoke but an agent will struggle to choose

Inputjson
{
  "descriptor": {
    "name": "weather.get_forecast",
    "description": "Weather.",
    "inputSchema": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string"
        }
      },
      "required": [
        "city"
      ]
    }
  }
}
Expected outputjson
{
  "dialectApplied": "MCP_TOOL_2025_06_18",
  "summary": {
    "errorCount": 0,
    "warningCount": 3,
    "propertyCount": 1,
    "rulesEvaluated": [
      "MCPD-E-001",
      "MCPD-E-002",
      "MCPD-E-003",
      "MCPD-E-004",
      "MCPD-E-005",
      "MCPD-E-006",
      "MCPD-E-007",
      "MCPD-E-008",
      "MCPD-E-009",
      "MCPD-E-010",
      "MCPD-E-011",
      "MCPD-W-001",
      "MCPD-W-002",
      "MCPD-W-003",
      "MCPD-W-004",
      "MCPD-W-005",
      "MCPD-W-006",
      "MCPD-W-007",
      "MCPD-W-008",
      "MCPD-W-009",
      "MCPD-W-010"
    ],
    "truncated": false
  },
  "errors": [],
  "valid": true,
  "ruleProfile": "mcp-descriptor-rules-1",
  "warnings": [
    {
      "code": "MCPD-W-001",
      "pointer": "/description",
      "keyword": "description",
      "message": "The description is absent or shorter than the declared minimum of 24 characters."
    },
    {
      "code": "MCPD-W-002",
      "pointer": "/inputSchema/properties/city/description",
      "keyword": "description",
      "message": "This property has no description, or one shorter than the declared minimum of 8 characters."
    },
    {
      "code": "MCPD-W-007",
      "pointer": "/outputSchema",
      "keyword": "outputSchema",
      "message": "The declared dialect supports an outputSchema and none is declared, so a caller cannot tell what comes back."
    }
  ]
}

A required argument the inputSchema never declares, which stops the call outright

Inputjson
{
  "descriptor": {
    "name": "weather.get_forecast",
    "description": "Returns a five-day forecast for one city.",
    "inputSchema": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "description": "City name."
        }
      },
      "required": [
        "city",
        "units"
      ]
    }
  },
  "rules": {
    "enabled": [
      "MCPD-E-005"
    ]
  }
}
Expected outputjson
{
  "dialectApplied": "MCP_TOOL_2025_06_18",
  "summary": {
    "errorCount": 1,
    "warningCount": 0,
    "propertyCount": 1,
    "rulesEvaluated": [
      "MCPD-E-005"
    ],
    "truncated": false
  },
  "errors": [
    {
      "code": "MCPD-E-005",
      "pointer": "/inputSchema/required/1",
      "keyword": "required",
      "message": "A required entry names a property that the inputSchema does not declare."
    }
  ],
  "valid": false,
  "ruleProfile": "mcp-descriptor-rules-1",
  "warnings": []
}
  • Gate a build on whether a tool descriptor can actually be invoked
  • Review a descriptor's selectability before publishing it to agents
  • Check a descriptor against an older MCP revision before shipping to a client on it

Avoid for

  • Validating arguments a caller sent against the descriptor's inputSchema
  • Judging a plain JSON Schema that is not a tool descriptor

Composable with

Safety & privacy

  • Runs without calling any external service.
  • Your payloads are never stored permanently.
  • Telemetry captures metadata only — never your payload contents.
  • We never train models on your payloads.
  • No human reviews your payloads.

Tags

metadatajsonschemavalidation