Skip to content
WebMCP Agents
Esc
↑↓navigate↵open⌘Jpreview
On this page

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:

  1. default, then const.
  2. Objects: an object of each property’s default. Arrays: [].
  3. integer / number: minimum, else 1. boolean: true.
  4. Otherwise the first non-empty enum option, 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, .hint and so on) live in the devtools’ shadow root. Outside it the form is unstyled.

See also

Was this page helpful?