Tool / Function-Schema Builder

Build an LLM tool or function definition visually and export it as an OpenAI function, an Anthropic tool, and an MCP tool. One JSON Schema, three formats.

Advertisement

Build one tool schema, export it for OpenAI, Anthropic and MCP

Defining a tool for a model is mostly clerical work with an unforgiving format. You need a name, a description written for a model rather than a human, and a JSON Schema describing the arguments — and then you need to wrap that schema in whichever envelope your provider expects. Get a brace wrong and the request is rejected. Get the description wrong and the model calls the tool at the wrong moment, which is harder to notice and much harder to debug.

This builder handles the clerical half. You fill in a function name, a description and a list of parameters; it produces valid JSON Schema and shows it in three envelopes at once. Switch tabs to copy whichever you need. It runs entirely in the browser with no request to any model API and no key required — the schema is assembled from form state and rendered directly, so nothing you type is transmitted.

The same schema, three envelopes

The central point, and the reason a single builder can serve all three targets, is that the schema itself is identical. Only the wrapper differs.

TargetEnvelope shapeWhere the schema goes
OpenAI{ "type": "function", "function": { … } }function.parameters
Anthropic{ "name": …, "description": …, … }input_schema
MCP tool{ "name": …, "description": …, … }inputSchema (camelCase)

OpenAI nests the whole definition one level deeper under a function key with a sibling type: "function". Anthropic and MCP are structurally the same as each other — name, description, schema, at the top level — and differ only in the casing of the schema key: input_schema with an underscore for Anthropic, inputSchema in camelCase for MCP. That one-character-class difference is a genuinely common source of a rejected tool definition when porting a server between the two.

In all three, the description key is omitted entirely if you leave the description box empty, rather than emitted as an empty string. If the function name box is empty, the name falls back to unnamed_function so the output stays syntactically valid.

Parameter types the builder supports

Seven type options are available per parameter, and each maps to a specific JSON Schema property.

TypeEmitted property
string{ "type": "string" }
number{ "type": "number" }
integer{ "type": "integer" }
boolean{ "type": "boolean" }
array{ "type": "array", "items": { "type": "string" } }
object{ "type": "object" }
enum{ "type": "string", "enum": [ … ] }

Two of these deserve a caveat. Array always gets an item schema of { "type": "string" }. That is a deliberate default — a bare {"type": "array"} is under-specified and some validators reject it — but if your array holds numbers or objects you must edit items after copying. Object is emitted with no properties at all, which means a nested object is effectively unconstrained; the builder is one level deep by design. For a nested structure, generate the outer shape here and hand-write the inner one.

Enum is a convenience rather than a distinct JSON Schema type: it emits a string with an enum array built by splitting your comma-separated input, trimming each value and dropping blanks. Typing celsius, fahrenheit produces ["celsius","fahrenheit"]. If you select enum and leave the values box empty, no enum key is added and you are left with a plain string.

Each parameter also carries an optional description, emitted as a description key inside its property object and omitted when blank, and a Required checkbox, which controls membership of the schema's required array. The required array is omitted entirely when nothing is required.

A worked example

The builder opens on a weather function: name get_weather, description "Get the current weather for a given location", and two parameters. location is a required string described as "City and state, e.g. San Francisco, CA". unit is an optional enum with the values celsius and fahrenheit.

The shared schema that produces is an object with a properties map containing location as a described string and unit as a string with a two-value enum, plus a required array holding only location. The OpenAI tab wraps that under function.parameters with type: "function" alongside. The Anthropic tab puts it in input_schema. The MCP tab puts the identical object in inputSchema. Three outputs, one schema, and the only edits between them are structural.

Two live warnings

The builder checks two things about parameter names and reports them below the parameter list.

  • Name characters. Names are expected to match ^[a-zA-Z0-9_-]+$. A name with a space, a dot or a slash is listed as a warning. It is not blocked — JSON Schema itself permits arbitrary property names — but provider validators are stricter than the schema standard, and a name outside that set is a likely rejection.
  • Duplicate names. Two parameters with the same name are flagged, because the output silently merges them: the later one's property definition overwrites the earlier one. If both are marked required, the name is pushed into the required array twice, so you get a literal duplicate entry there. Rename one.

Parameters with an empty name are skipped entirely rather than emitted as "", so a half-finished row will not corrupt the output while you are still typing it.

Writing descriptions the model can act on

The schema is the easy part. The descriptions are what determine whether the model calls your tool correctly, and they are the part a generator cannot do for you.

  • The function description answers "when should I call this?" not "what does this do internally". The model is reading it to make a routing decision. "Get the current weather for a given location" is a better prompt than "weather API wrapper".
  • State units, formats and examples in the parameter description. "City and state, e.g. San Francisco, CA" removes a whole class of malformed calls. A date parameter should say the expected format outright.
  • Prefer an enum to a described string whenever the set of values is closed. An enum is enforced; a description saying "must be celsius or fahrenheit" is only a suggestion, and models do occasionally ignore it.
  • Mark as required only what you truly need. Every required parameter is one more thing the model must guess when the user did not supply it, and a guessed value is worse than an absent one your code can default.
  • Prefer flat parameter lists. Beyond being what this builder emits, flat arguments are measurably easier for models to fill correctly than deeply nested objects.
  • Say what the tool does not do. One clause in the description — "current conditions only, not forecasts" — prevents a category of wrong calls that no schema constraint can.

What the output does not include

The generated schema is intentionally minimal: type, properties, and required when non-empty. It does not emit a $schema declaration, an additionalProperties setting, OpenAI's strict-mode flag, per-property constraints such as minimum, maxLength, pattern, format or default, or any nested object properties. If your provider configuration requires strict structured outputs, or you need value-range validation, add those keys to the copied JSON by hand.

Nothing here is validated against a live API either. The output is well-formed JSON and well-formed JSON Schema; whether a particular model version accepts a particular name or nesting depth is something only that API can tell you.

Common failures when a tool definition is rejected

SymptomLikely cause
Anthropic rejects the toolSchema left under inputSchema. Anthropic wants input_schema.
MCP client shows no toolSchema under input_schema. MCP wants camelCase inputSchema.
OpenAI rejects the toolThe function wrapper and its sibling type: "function" were dropped when pasting.
Model omits an argument you needNot marked required, or the description does not make it clear it is mandatory.
Model invents values for a closed setParameter is a plain string. Make it an enum.
Array argument arrives with wrong element typesThe default items: {"type": "string"} was left in place for a non-string array.
One parameter silently vanishedTwo parameters shared a name and were merged. Check the duplicate warning.
Tool called at the wrong timeA schema problem this is not. Rewrite the function description to say when it applies.

Where this fits

If you are writing tools for a single application and a single vendor, the provider's native format is all you need and this builder is a formatting shortcut. If you are exposing the same tools through an MCP server so several clients can use them, the MCP tab is the definition your server advertises — and getting it right is a prerequisite for the client actually listing the tool.

Testing a tool definition before you trust it

A schema that validates is not a schema that works. The failure mode that costs the most time is a tool that is called at the wrong moment or with a plausible but wrong argument, and neither the JSON nor the API will tell you about it. A short manual pass catches most of it.

  • Read the description as the model will. Strip away everything you know about your own system and ask whether the text alone says when to use this tool and when not to. If two of your tools could both plausibly answer the same request, one of the descriptions needs a boundary clause.
  • Try the ambiguous request. Ask for something that is close to but not exactly what the tool does. A well-described tool declines; a vaguely described one gets called and returns something misleading.
  • Try the request that omits a required argument. Watch whether the model asks the user or invents a value. If it invents, the parameter description is not telling it the value cannot be guessed.
  • Check an enum actually constrains. Ask for a value outside the set and confirm the call is rejected rather than coerced.
  • Count your tools. Selection accuracy degrades as the tool list grows, and two tools with overlapping descriptions hurt more than one tool with a longer one. Merging near-duplicates is usually a better fix than rewording them.

None of this is schema work, which is precisely the point: once the builder has taken the formatting off your plate, the description quality is the only variable left, and it is the one that determines whether the tool is actually used correctly.

This tool is provided for informational and educational purposes only. All processing happens in your browser — no data is sent to or stored on our servers. While we strive for accuracy, we make no warranties about the completeness or reliability of results.