SchemaForm
A controlled React form for a tool's JSON Schema, the one the devtools runner uses.
A controlled React form for a tool’s JSON Schema, the one the devtools runner uses. Pair it with defaultValueFor, which gives ready-to-run starting values so “Run” works on the first click for most tools.
Import
import { defaultValueFor, SchemaForm } from "@webmcp-agents/devtools";
import type { SchemaFormProps } from "@webmcp-agents/devtools";
Example
A runner for one tool: a form from its schema and a Run button that calls it like an agent.
import type { ModelContextToolInfo } from "@webmcp-agents/core";
import {
defaultValueFor,
parseSchema,
SchemaForm,
} from "@webmcp-agents/devtools";
import { useState } from "react";
import { Button } from "@/components/ui/button";
// A runner for one tool: a form from its schema, a Run button.
export function Runner({ tool }: { tool: ModelContextToolInfo }) {
const schema = parseSchema(tool.inputSchema);
const [args, setArgs] = useState(() => defaultValueFor(schema));
return (
<form
onSubmit={(event) => {
event.preventDefault();
void window.agent?.invoke(
tool.name,
args as Record<string, unknown>,
);
}}
>
<SchemaForm
schema={schema}
value={args}
onChange={setArgs}
idPrefix={`run-${tool.name}`}
/>
<Button type="submit">Run</Button>
</form>
);
}
Props
| Name | Type | Default | Description |
|---|---|---|---|
schema |
SchemaNode |
required | The tool’s input schema, parsed (see parseSchema). |
value |
unknown |
required | The current arguments. The form is controlled: it shows exactly this. |
onChange |
(value: unknown) => void |
required | Called with the whole new value on every edit. |
idPrefix |
string |
required | Prefix for element ids. Must be unique per form on the page. |
Field types
| Schema | Control |
|---|---|
string |
text input; format: "date" gives a date input; a textarea when maxLength > 120 or the description says “multiline” |
enum |
select with a “(not set)” first option |
number, integer |
number input with min / max; integer uses step 1 |
boolean |
checkbox |
object |
fieldset of its properties; required ones are marked |
array |
list of items fields with Add item and Remove |
oneOf, anyOf, allOf, $ref, not, or no type |
raw JSON textarea for that subtree |
defaultValueFor(schema)
Returns the starting value for a schema, in this order:
default, thenconst.- Objects: an object of each property’s default. Arrays:
[]. integer/number:minimum, else1.boolean:true.- Otherwise the first non-empty
enumoption, a sample from the description ("e.g. 123"gives"123"), a placeholder for a known format (email:you@example.com,date: today,uri:https://example.com), or"".
Returns
SchemaForm renders the fields. A top-level object renders its fields directly, without a fieldset. An object with no properties renders “This tool takes no arguments.”
Notes
- No validation: the tool validates, and its error comes back in the result.
- An empty text or number field removes the key from the value, so a missing required field is reported by the tool, not by the form.
- Numbers are coerced from the input text. Text that does not parse as a number is sent as the string.
- The JSON field keeps the last valid value while the text does not parse, and shows “Not valid JSON”.
- Styles (
.field,.input,.hintand so on) live in the devtools’ shadow root. Outside it the form is unstyled.
See also
parseSchema:parseSchema,SchemaNodecreateDevtoolsStore: the runner’s storetoAgentInvokeCode