react-webmcp 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import React from 'react';
2
+ import React$1 from 'react';
3
3
 
4
4
  /**
5
5
  * WebMCP type definitions for the W3C navigator.modelContext API.
@@ -36,7 +36,13 @@ interface JSONSchema {
36
36
  items?: JSONSchemaProperty;
37
37
  }
38
38
  interface ToolAnnotations {
39
- /** Indicates the tool only reads data and does not modify state (browser-native). */
39
+ /**
40
+ * Indicates the tool only reads data and does not modify state.
41
+ *
42
+ * Per the spec's formalized `registerTool()` algorithm, this value is
43
+ * extracted from annotations and stored as a top-level field on the
44
+ * internal tool definition struct (`read-only hint`, initially false).
45
+ */
40
46
  readOnlyHint?: boolean;
41
47
  /**
42
48
  * Indicates the tool performs a destructive/irreversible operation.
@@ -138,6 +144,7 @@ interface ModelContextTesting {
138
144
  name: string;
139
145
  description: string;
140
146
  inputSchema: string;
147
+ readOnlyHint?: boolean;
141
148
  }>;
142
149
  /**
143
150
  * Execute a tool by name.
@@ -270,7 +277,7 @@ declare function useWebMCPContext(config: {
270
277
  */
271
278
  declare function useToolEvent(event: "toolactivated" | "toolcancel", callback: (toolName: string) => void, toolNameFilter?: string): void;
272
279
 
273
- interface WebMCPFormProps extends Omit<React.FormHTMLAttributes<HTMLFormElement>, "onSubmit"> {
280
+ interface WebMCPFormProps extends Omit<React$1.FormHTMLAttributes<HTMLFormElement>, "onSubmit"> {
274
281
  /** The tool name exposed to AI agents. Maps to the `toolname` HTML attribute. */
275
282
  toolName: string;
276
283
  /** Description of what this tool does. Maps to `tooldescription`. */
@@ -286,7 +293,7 @@ interface WebMCPFormProps extends Omit<React.FormHTMLAttributes<HTMLFormElement>
286
293
  onToolActivated?: (toolName: string) => void;
287
294
  /** Called when a tool cancel event fires for this form's tool. */
288
295
  onToolCancel?: (toolName: string) => void;
289
- children: React.ReactNode;
296
+ children: React$1.ReactNode;
290
297
  }
291
298
  /**
292
299
  * A React wrapper for the WebMCP declarative API.
@@ -314,7 +321,7 @@ interface WebMCPFormProps extends Omit<React.FormHTMLAttributes<HTMLFormElement>
314
321
  */
315
322
  declare function WebMCPForm({ toolName, toolDescription, toolAutoSubmit, onSubmit, onToolActivated, onToolCancel, children, ...rest }: WebMCPFormProps): react_jsx_runtime.JSX.Element;
316
323
 
317
- interface WebMCPInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
324
+ interface WebMCPInputProps extends React$1.InputHTMLAttributes<HTMLInputElement> {
318
325
  /** Maps to the `toolparamtitle` attribute (overrides the JSON Schema property key). */
319
326
  toolParamTitle?: string;
320
327
  /** Maps to the `toolparamdescription` attribute (describes this parameter to agents). */
@@ -337,14 +344,14 @@ interface WebMCPInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
337
344
  * />
338
345
  * ```
339
346
  */
340
- declare const WebMCPInput: React.ForwardRefExoticComponent<WebMCPInputProps & React.RefAttributes<HTMLInputElement>>;
347
+ declare const WebMCPInput: React$1.ForwardRefExoticComponent<WebMCPInputProps & React$1.RefAttributes<HTMLInputElement>>;
341
348
 
342
- interface WebMCPSelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
349
+ interface WebMCPSelectProps extends React$1.SelectHTMLAttributes<HTMLSelectElement> {
343
350
  /** Maps to the `toolparamtitle` attribute (overrides the JSON Schema property key). */
344
351
  toolParamTitle?: string;
345
352
  /** Maps to the `toolparamdescription` attribute (describes this parameter to agents). */
346
353
  toolParamDescription?: string;
347
- children: React.ReactNode;
354
+ children: React$1.ReactNode;
348
355
  }
349
356
  /**
350
357
  * A `<select>` element enhanced with WebMCP declarative attributes.
@@ -364,9 +371,9 @@ interface WebMCPSelectProps extends React.SelectHTMLAttributes<HTMLSelectElement
364
371
  * </WebMCPSelect>
365
372
  * ```
366
373
  */
367
- declare const WebMCPSelect: React.ForwardRefExoticComponent<WebMCPSelectProps & React.RefAttributes<HTMLSelectElement>>;
374
+ declare const WebMCPSelect: React$1.ForwardRefExoticComponent<WebMCPSelectProps & React$1.RefAttributes<HTMLSelectElement>>;
368
375
 
369
- interface WebMCPTextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
376
+ interface WebMCPTextareaProps extends React$1.TextareaHTMLAttributes<HTMLTextAreaElement> {
370
377
  /** Maps to the `toolparamtitle` attribute (overrides the JSON Schema property key). */
371
378
  toolParamTitle?: string;
372
379
  /** Maps to the `toolparamdescription` attribute (describes this parameter to agents). */
@@ -386,7 +393,7 @@ interface WebMCPTextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaE
386
393
  * />
387
394
  * ```
388
395
  */
389
- declare const WebMCPTextarea: React.ForwardRefExoticComponent<WebMCPTextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
396
+ declare const WebMCPTextarea: React$1.ForwardRefExoticComponent<WebMCPTextareaProps & React$1.RefAttributes<HTMLTextAreaElement>>;
390
397
 
391
398
  interface WebMCPContextValue {
392
399
  /** Whether navigator.modelContext is available in this browser. */
@@ -412,7 +419,7 @@ interface WebMCPContextValue {
412
419
  * ```
413
420
  */
414
421
  declare function WebMCPProvider({ children }: {
415
- children: React.ReactNode;
422
+ children: React$1.ReactNode;
416
423
  }): react_jsx_runtime.JSX.Element;
417
424
  /**
418
425
  * Returns the current WebMCP availability status.
@@ -445,4 +452,284 @@ declare function isWebMCPAvailable(): boolean;
445
452
  */
446
453
  declare function isWebMCPTestingAvailable(): boolean;
447
454
 
448
- export { type JSONSchema, type JSONSchemaProperty, type ModelContext, type ModelContextTesting, type ToolActivatedEvent, type ToolAnnotations, type ToolCancelEvent, type ToolContent, type ToolContentJSON, type ToolContentText, type UseWebMCPToolConfig, type WebMCPContextConfig, WebMCPForm, type WebMCPFormProps, type WebMCPFormSubmitEvent, WebMCPInput, type WebMCPInputProps, WebMCPProvider, WebMCPSelect, type WebMCPSelectProps, WebMCPTextarea, type WebMCPTextareaProps, type WebMCPToolDefinition, getModelContext, isWebMCPAvailable, isWebMCPTestingAvailable, useToolEvent, useWebMCPContext, useWebMCPStatus, useWebMCPTool };
455
+ /**
456
+ * Type definitions for the WebMCP adapter layer.
457
+ *
458
+ * These types support the runtime schema collector engine that enables
459
+ * third-party UI component libraries (e.g. Material UI) to work with
460
+ * the WebMCP tool registration API.
461
+ */
462
+ /**
463
+ * Describes a single field (tool parameter) collected from React children,
464
+ * the `fields` prop, or via `useRegisterField`.
465
+ *
466
+ * @example
467
+ * ```ts
468
+ * const field: FieldDefinition = {
469
+ * name: "email",
470
+ * type: "email",
471
+ * required: true,
472
+ * description: "Recipient's email address",
473
+ * };
474
+ * ```
475
+ */
476
+ interface FieldDefinition {
477
+ /** Field name — must be unique within a tool. */
478
+ name: string;
479
+ /** HTML input type (e.g. "text", "email", "number"). Defaults to "string". */
480
+ type?: string;
481
+ /** Whether the field is required. */
482
+ required?: boolean;
483
+ /** Human-readable title for agents. */
484
+ title?: string;
485
+ /** Human-readable description for agents. */
486
+ description?: string;
487
+ /** Minimum numeric value (maps to JSON Schema `minimum`). */
488
+ min?: number;
489
+ /** Maximum numeric value (maps to JSON Schema `maximum`). */
490
+ max?: number;
491
+ /** Minimum string length (maps to JSON Schema `minLength`). */
492
+ minLength?: number;
493
+ /** Maximum string length (maps to JSON Schema `maxLength`). */
494
+ maxLength?: number;
495
+ /** Regex pattern for string validation (maps to JSON Schema `pattern`). */
496
+ pattern?: string;
497
+ /** Allowed values — mapped to JSON Schema `enum`. */
498
+ enumValues?: (string | number | boolean)[];
499
+ /** Labelled options — mapped to JSON Schema `oneOf`. */
500
+ oneOf?: {
501
+ value: string | number | boolean;
502
+ label: string;
503
+ }[];
504
+ }
505
+
506
+ /**
507
+ * Props for the `WebMCP.Tool` component.
508
+ */
509
+ interface WebMCPToolProps {
510
+ /** Unique tool name exposed to AI agents. */
511
+ name: string;
512
+ /** Human-readable description of what this tool does. */
513
+ description: string;
514
+ /** Handler called when an AI agent invokes this tool. */
515
+ onExecute: (input: Record<string, unknown>) => unknown | Promise<unknown>;
516
+ /** Optional field overrides / enrichment keyed by field name. */
517
+ fields?: Record<string, Partial<FieldDefinition>>;
518
+ /** When true, schema validation issues throw instead of warn. */
519
+ strict?: boolean;
520
+ /** If true, the tool auto-submits when filled by an agent. */
521
+ autoSubmit?: boolean;
522
+ /** Optional metadata hints for agents. */
523
+ annotations?: ToolAnnotations;
524
+ /** Called when a `toolactivated` event fires for this tool. */
525
+ onToolActivated?: (toolName: string) => void;
526
+ /** Called when a `toolcancel` event fires for this tool. */
527
+ onToolCancel?: (toolName: string) => void;
528
+ children: React$1.ReactNode;
529
+ }
530
+ /**
531
+ * Framework-agnostic tool wrapper that collects a JSON Schema from its
532
+ * React children and registers it as a WebMCP tool.
533
+ *
534
+ * Fields are auto-detected from child components (e.g. `<Input name="email" />`),
535
+ * enriched via the `fields` prop, and can be overridden by descendant
536
+ * components using `useRegisterField`.
537
+ *
538
+ * @example
539
+ * ```tsx
540
+ * <WebMCPTool
541
+ * name="send_email"
542
+ * description="Send an email to a user"
543
+ * onExecute={async ({ email, priority }) => {
544
+ * await sendEmail(email, priority);
545
+ * return { content: [{ type: "text", text: "Sent!" }] };
546
+ * }}
547
+ * fields={{ email: { description: "Recipient's email" } }}
548
+ * >
549
+ * <FormControl>
550
+ * <Input name="email" type="email" required />
551
+ * </FormControl>
552
+ * </WebMCPTool>
553
+ * ```
554
+ */
555
+ declare function WebMCPTool({ name, description, onExecute, fields: fieldsProp, strict, autoSubmit, annotations, onToolActivated, onToolCancel, children, }: WebMCPToolProps): react_jsx_runtime.JSX.Element;
556
+ declare namespace WebMCPTool {
557
+ var displayName: string;
558
+ }
559
+
560
+ /**
561
+ * Props for the `WebMCP.Field` component.
562
+ */
563
+ interface WebMCPFieldProps extends Omit<FieldDefinition, "name"> {
564
+ /** Field name — must be unique within the parent `WebMCP.Tool`. */
565
+ name: string;
566
+ children: React$1.ReactNode;
567
+ }
568
+ /**
569
+ * Zero-UI wrapper that registers a field with the nearest `WebMCP.Tool`.
570
+ *
571
+ * Use this as an escape hatch for custom components that cannot be
572
+ * auto-detected by the children traversal engine. Enum values are
573
+ * automatically detected from children that have a `value` prop
574
+ * (e.g. `<MenuItem value="low">Low</MenuItem>`).
575
+ *
576
+ * Renders a React Fragment — no extra DOM elements are introduced.
577
+ *
578
+ * @example
579
+ * ```tsx
580
+ * <WebMCP.Field name="priority" description="Email priority">
581
+ * <Select>
582
+ * <MenuItem value="low">Low</MenuItem>
583
+ * <MenuItem value="high">High</MenuItem>
584
+ * </Select>
585
+ * </WebMCP.Field>
586
+ * ```
587
+ */
588
+ declare function WebMCPField({ children, name, ...rest }: WebMCPFieldProps): react_jsx_runtime.JSX.Element;
589
+ declare namespace WebMCPField {
590
+ var displayName: string;
591
+ }
592
+
593
+ /**
594
+ * Register a field definition with the nearest `WebMCP.Tool` ancestor.
595
+ *
596
+ * Uses `useEffect` (SSR-safe) so registration only happens on the client.
597
+ * The field is automatically unregistered on unmount. Re-registration
598
+ * only occurs when the field definition changes (compared by fingerprint).
599
+ *
600
+ * If no `WebMCP.Tool` ancestor exists, a dev-mode warning is logged.
601
+ *
602
+ * @example
603
+ * ```tsx
604
+ * function MyField() {
605
+ * useRegisterField({ name: "email", type: "email", required: true });
606
+ * return <input name="email" type="email" required />;
607
+ * }
608
+ * ```
609
+ */
610
+ declare function useRegisterField(field: FieldDefinition): void;
611
+
612
+ interface UseSchemaCollectorOptions {
613
+ /** React children to traverse for auto-detected fields. */
614
+ children: React.ReactNode;
615
+ /** Optional field overrides keyed by field name. */
616
+ fields?: Record<string, Partial<FieldDefinition>>;
617
+ /** When true, validation issues throw instead of warn. */
618
+ strict?: boolean;
619
+ }
620
+ /**
621
+ * Core engine hook that collects field definitions from three sources,
622
+ * merges them, validates in dev, and builds a deterministic JSON Schema.
623
+ *
624
+ * **Sources** (lowest to highest priority):
625
+ * 1. Children traversal (auto-detected from React tree)
626
+ * 2. `fields` prop (enrichment / override)
627
+ * 3. Context-registered fields (via `useRegisterField`)
628
+ *
629
+ * @example
630
+ * ```tsx
631
+ * const { schema, registerField, unregisterField } = useSchemaCollector({
632
+ * children,
633
+ * fields: { email: { description: "Recipient" } },
634
+ * });
635
+ * ```
636
+ */
637
+ declare function useSchemaCollector({ children, fields: fieldsProp, strict, }: UseSchemaCollectorOptions): {
638
+ schema: JSONSchema;
639
+ registerField: (field: FieldDefinition) => void;
640
+ unregisterField: (name: string) => void;
641
+ };
642
+
643
+ /**
644
+ * Recursively extract option values from React children.
645
+ *
646
+ * Detects elements that have a `value` prop (e.g. `<MenuItem value="low">Low</MenuItem>`)
647
+ * and collects `{ value, label }` pairs. The label is derived from string children
648
+ * or falls back to `String(value)`.
649
+ *
650
+ * @example
651
+ * ```tsx
652
+ * const options = extractOptions(
653
+ * <>
654
+ * <MenuItem value="low">Low</MenuItem>
655
+ * <MenuItem value="high">High</MenuItem>
656
+ * </>
657
+ * );
658
+ * // [{ value: "low", label: "Low" }, { value: "high", label: "High" }]
659
+ * ```
660
+ */
661
+ declare function extractOptions(children: React$1.ReactNode): {
662
+ value: string | number | boolean;
663
+ label: string;
664
+ }[];
665
+ /**
666
+ * Recursively extract field definitions from a React children tree.
667
+ *
668
+ * Walks the tree using `React.Children.toArray` (safe, pure traversal).
669
+ * Detects field names from `props.name`, `props.inputProps.name`, or
670
+ * `props.slotProps.input.name`. When a named element is found, it builds
671
+ * a `FieldDefinition` from its props and auto-detects enum values from
672
+ * its children. Elements without a name are recursed into.
673
+ *
674
+ * @example
675
+ * ```tsx
676
+ * const fields = extractFields(
677
+ * <>
678
+ * <Input name="email" type="email" required />
679
+ * <Select name="priority">
680
+ * <MenuItem value="low">Low</MenuItem>
681
+ * <MenuItem value="high">High</MenuItem>
682
+ * </Select>
683
+ * </>
684
+ * );
685
+ * ```
686
+ */
687
+ declare function extractFields(children: React$1.ReactNode): FieldDefinition[];
688
+
689
+ /**
690
+ * Build a deterministic JSON Schema from an array of field definitions.
691
+ *
692
+ * Property names are sorted alphabetically and the `required` array is
693
+ * also sorted, ensuring identical output regardless of field insertion
694
+ * order.
695
+ *
696
+ * @example
697
+ * ```ts
698
+ * const schema = buildInputSchema([
699
+ * { name: "email", type: "email", required: true },
700
+ * { name: "age", type: "number", min: 0, max: 120 },
701
+ * ]);
702
+ * ```
703
+ */
704
+ declare function buildInputSchema(fields: FieldDefinition[]): JSONSchema;
705
+
706
+ /**
707
+ * Validate an array of field definitions for common schema issues.
708
+ *
709
+ * In production this is a no-op. In development it checks for:
710
+ * - Duplicate field names
711
+ * - `pattern` used on non-string types
712
+ * - `min`/`max` used on non-number types
713
+ * - `minLength`/`maxLength` used on non-string types
714
+ * - Enum values whose types don't match the declared field type
715
+ *
716
+ * By default warnings are logged via `console.warn` with the
717
+ * `[react-webmcp]` prefix. When `strict` is `true`, an `Error` is
718
+ * thrown instead.
719
+ *
720
+ * @example
721
+ * ```ts
722
+ * validateSchema(fields); // warns in dev
723
+ * validateSchema(fields, { strict: true }); // throws in dev
724
+ * ```
725
+ */
726
+ declare function validateSchema(fields: FieldDefinition[], options?: {
727
+ strict?: boolean;
728
+ }): void;
729
+
730
+ declare const WebMCP: {
731
+ readonly Tool: typeof WebMCPTool;
732
+ readonly Field: typeof WebMCPField;
733
+ };
734
+
735
+ export { type FieldDefinition, type JSONSchema, type JSONSchemaProperty, type ModelContext, type ModelContextTesting, type ToolActivatedEvent, type ToolAnnotations, type ToolCancelEvent, type ToolContent, type ToolContentJSON, type ToolContentText, type UseWebMCPToolConfig, WebMCP, type WebMCPContextConfig, WebMCPField, type WebMCPFieldProps, WebMCPForm, type WebMCPFormProps, type WebMCPFormSubmitEvent, WebMCPInput, type WebMCPInputProps, WebMCPProvider, WebMCPSelect, type WebMCPSelectProps, WebMCPTextarea, type WebMCPTextareaProps, WebMCPTool, type WebMCPToolDefinition, type WebMCPToolProps, buildInputSchema, extractFields, extractOptions, getModelContext, isWebMCPAvailable, isWebMCPTestingAvailable, useRegisterField, useSchemaCollector, useToolEvent, useWebMCPContext, useWebMCPStatus, useWebMCPTool, validateSchema };