usewebmcp 4.1.0-beta.20260702224704 → 5.0.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/README.md +54 -225
- package/dist/index.d.ts +23 -347
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +11 -5
- package/dist/index.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,56 +1,21 @@
|
|
|
1
1
|
# usewebmcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React hook for registering strict-core WebMCP tools with `document.modelContext`.
|
|
4
4
|
|
|
5
|
-
`usewebmcp`
|
|
6
|
-
|
|
7
|
-
- Use `usewebmcp` for strict core WebMCP workflows.
|
|
8
|
-
- Use `@mcp-b/react-webmcp` for full MCP-B runtime features (resources, prompts, client/provider flows, etc.).
|
|
9
|
-
|
|
10
|
-
## Type Safety First
|
|
11
|
-
|
|
12
|
-
`usewebmcp` is built for schema-driven types:
|
|
13
|
-
|
|
14
|
-
- `config.execute`/`config.handler` input is inferred from `inputSchema`
|
|
15
|
-
- Tool result type is inferred from `outputSchema`
|
|
16
|
-
- `state.lastResult` and returned `execute(input)` are typed from that same inferred output
|
|
17
|
-
|
|
18
|
-
## Package Selection
|
|
19
|
-
|
|
20
|
-
| Package | Use When |
|
|
21
|
-
| ------------------------ | --------------------------------------------------------- |
|
|
22
|
-
| `usewebmcp` | React hooks for strict core `document.modelContext` tools |
|
|
23
|
-
| `@mcp-b/react-webmcp` | React hooks for full MCP-B runtime surface |
|
|
24
|
-
| `@mcp-b/webmcp-polyfill` | You need a strict core runtime polyfill |
|
|
25
|
-
| `@mcp-b/global` | You need full MCP-B runtime (core + extensions) |
|
|
5
|
+
Use `usewebmcp` when an app only needs standard tool registration. Use
|
|
6
|
+
`@mcp-b/react-webmcp` for prompts, resources, or MCP client/provider flows.
|
|
26
7
|
|
|
27
8
|
## Install
|
|
28
9
|
|
|
29
10
|
```bash
|
|
30
11
|
pnpm add usewebmcp react
|
|
31
|
-
# or
|
|
32
|
-
npm install usewebmcp react
|
|
33
12
|
```
|
|
34
13
|
|
|
35
|
-
|
|
14
|
+
The hook expects `document.modelContext` to exist before the component mounts. Provide it through
|
|
15
|
+
native browser support, `@mcp-b/webmcp-polyfill`, or `@mcp-b/global`. Older
|
|
16
|
+
`navigator.modelContext` runtimes remain a fallback.
|
|
36
17
|
|
|
37
|
-
|
|
38
|
-
pnpm add zod
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Runtime Prerequisite
|
|
42
|
-
|
|
43
|
-
`usewebmcp` expects `window.document.modelContext` to exist.
|
|
44
|
-
|
|
45
|
-
You can provide it via:
|
|
46
|
-
|
|
47
|
-
- Browser-native WebMCP implementation, or
|
|
48
|
-
- `@mcp-b/webmcp-polyfill`, or
|
|
49
|
-
- `@mcp-b/global`
|
|
50
|
-
|
|
51
|
-
If `document.modelContext` is missing, the hook falls back to older preview `navigator.modelContext` runtimes. If both are missing, the hook logs a warning and skips registration.
|
|
52
|
-
|
|
53
|
-
## Quick Start
|
|
18
|
+
## Quick start
|
|
54
19
|
|
|
55
20
|
```tsx
|
|
56
21
|
import { initializeWebMCPPolyfill } from '@mcp-b/webmcp-polyfill';
|
|
@@ -58,221 +23,85 @@ import { useWebMCP } from 'usewebmcp';
|
|
|
58
23
|
|
|
59
24
|
initializeWebMCPPolyfill();
|
|
60
25
|
|
|
61
|
-
const COUNTER_INPUT_SCHEMA = {
|
|
62
|
-
type: 'object',
|
|
63
|
-
properties: {},
|
|
64
|
-
} as const;
|
|
65
|
-
|
|
66
|
-
const COUNTER_OUTPUT_SCHEMA = {
|
|
67
|
-
type: 'object',
|
|
68
|
-
properties: {
|
|
69
|
-
count: { type: 'integer' },
|
|
70
|
-
},
|
|
71
|
-
required: ['count'],
|
|
72
|
-
additionalProperties: false,
|
|
73
|
-
} as const;
|
|
74
|
-
|
|
75
|
-
export function CounterTool() {
|
|
76
|
-
const counterTool = useWebMCP({
|
|
77
|
-
name: 'counter_get',
|
|
78
|
-
description: 'Get current count',
|
|
79
|
-
inputSchema: COUNTER_INPUT_SCHEMA,
|
|
80
|
-
outputSchema: COUNTER_OUTPUT_SCHEMA,
|
|
81
|
-
execute: async () => ({ count: 42 }),
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
<div>
|
|
86
|
-
<p>Executions: {counterTool.state.executionCount}</p>
|
|
87
|
-
<p>Last count: {counterTool.state.lastResult?.count ?? 'none'}</p>
|
|
88
|
-
{counterTool.state.error && <p>Error: {counterTool.state.error.message}</p>}
|
|
89
|
-
<button
|
|
90
|
-
onClick={async () => {
|
|
91
|
-
await counterTool.execute({});
|
|
92
|
-
}}
|
|
93
|
-
>
|
|
94
|
-
Run Tool Locally
|
|
95
|
-
</button>
|
|
96
|
-
</div>
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## How `useWebMCP` Works
|
|
102
|
-
|
|
103
|
-
- Registers a tool on mount with `document.modelContext.registerTool(tool, { signal })` and aborts the controller on unmount.
|
|
104
|
-
- Older Chrome preview builds may not remove tools when the controller aborts. Install `@mcp-b/global` or `@mcp-b/webmcp-polyfill` when you need consistent cleanup across preview versions.
|
|
105
|
-
- Exposes local execution state:
|
|
106
|
-
- `state.isExecuting`
|
|
107
|
-
- `state.lastResult`
|
|
108
|
-
- `state.error`
|
|
109
|
-
- `state.executionCount`
|
|
110
|
-
- Returns `execute(input)` for manual in-app invocation and `reset()` for state reset.
|
|
111
|
-
|
|
112
|
-
Your tool implementation (`config.execute` or `config.handler`) can be synchronous or asynchronous.
|
|
113
|
-
|
|
114
|
-
## `config.execute` vs returned `execute(...)`
|
|
115
|
-
|
|
116
|
-
- `config.execute`: preferred config field for tool logic.
|
|
117
|
-
- `config.handler`: backward-compatible alias for `config.execute`.
|
|
118
|
-
- returned `execute(input)`: hook return function for local manual invocation from your UI/tests.
|
|
119
|
-
|
|
120
|
-
If both `config.execute` and `config.handler` are provided, `config.execute` is used.
|
|
121
|
-
|
|
122
|
-
Both paths run the same underlying tool logic and update the hook state.
|
|
123
|
-
|
|
124
|
-
## Type Inference
|
|
125
|
-
|
|
126
|
-
### Input inference
|
|
127
|
-
|
|
128
|
-
`inputSchema` supports:
|
|
129
|
-
|
|
130
|
-
- JSON Schema literals (`as const`) via `InferArgsFromInputSchema`
|
|
131
|
-
- Standard Schema v1 input typing (for example Zod v4 / Valibot / ArkType) via `~standard.types.input`
|
|
132
|
-
|
|
133
|
-
```tsx
|
|
134
26
|
const INPUT_SCHEMA = {
|
|
135
27
|
type: 'object',
|
|
136
|
-
properties: {
|
|
137
|
-
query: { type: 'string' },
|
|
138
|
-
limit: { type: 'integer' },
|
|
139
|
-
},
|
|
28
|
+
properties: { query: { type: 'string' } },
|
|
140
29
|
required: ['query'],
|
|
141
|
-
additionalProperties: false,
|
|
142
30
|
} as const;
|
|
143
31
|
|
|
144
|
-
useWebMCP({
|
|
145
|
-
name: 'search',
|
|
146
|
-
description: 'Search docs',
|
|
147
|
-
inputSchema: INPUT_SCHEMA,
|
|
148
|
-
execute(input) {
|
|
149
|
-
// input is inferred as { query: string; limit?: number }
|
|
150
|
-
return { total: 1 };
|
|
151
|
-
},
|
|
152
|
-
});
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### Output inference
|
|
156
|
-
|
|
157
|
-
When `outputSchema` is provided as a literal JSON Schema:
|
|
158
|
-
|
|
159
|
-
- implementation return type is inferred from `outputSchema`
|
|
160
|
-
- `state.lastResult` is inferred to the same type
|
|
161
|
-
- MCP response includes `structuredContent`
|
|
162
|
-
|
|
163
|
-
```tsx
|
|
164
32
|
const OUTPUT_SCHEMA = {
|
|
165
33
|
type: 'object',
|
|
166
|
-
properties: {
|
|
167
|
-
total: { type: 'integer' },
|
|
168
|
-
},
|
|
34
|
+
properties: { total: { type: 'integer' } },
|
|
169
35
|
required: ['total'],
|
|
170
|
-
additionalProperties: false,
|
|
171
36
|
} as const;
|
|
172
37
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
// tool.state.lastResult is inferred as { total: number } | null
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
## Manual `execute(...)` Calls
|
|
184
|
-
|
|
185
|
-
You can call the returned `execute(...)` function directly from your component.
|
|
186
|
-
|
|
187
|
-
```tsx
|
|
188
|
-
function SearchToolPanel() {
|
|
189
|
-
const searchTool = useWebMCP({
|
|
190
|
-
name: 'search_local',
|
|
191
|
-
description: 'Run local search',
|
|
192
|
-
inputSchema: {
|
|
193
|
-
type: 'object',
|
|
194
|
-
properties: { query: { type: 'string' } },
|
|
195
|
-
required: ['query'],
|
|
196
|
-
additionalProperties: false,
|
|
197
|
-
} as const,
|
|
198
|
-
execute: async ({ query }) => ({ query, total: query.length }),
|
|
38
|
+
export function SearchTool() {
|
|
39
|
+
const search = useWebMCP({
|
|
40
|
+
name: 'search',
|
|
41
|
+
description: 'Search indexed documents',
|
|
42
|
+
inputSchema: INPUT_SCHEMA,
|
|
43
|
+
outputSchema: OUTPUT_SCHEMA,
|
|
44
|
+
execute: async ({ query }) => ({ total: await countMatches(query) }),
|
|
199
45
|
});
|
|
200
46
|
|
|
201
47
|
return (
|
|
202
|
-
<button
|
|
203
|
-
|
|
204
|
-
await searchTool.execute({ query: 'webmcp' });
|
|
205
|
-
}}
|
|
206
|
-
>
|
|
207
|
-
Run Search
|
|
48
|
+
<button disabled={search.state.isExecuting} onClick={() => search.execute({ query: 'webmcp' })}>
|
|
49
|
+
Run search ({search.state.executionCount})
|
|
208
50
|
</button>
|
|
209
51
|
);
|
|
210
52
|
}
|
|
211
53
|
```
|
|
212
54
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
If `outputSchema` is defined, your tool implementation must return a JSON-serializable value that matches that schema for MCP-B helpers that consume it. Object, array, string, number, boolean, and null schemas are supported for type inference and hook result shaping.
|
|
55
|
+
JSON Schema literals infer the `execute` input, output, returned `execute(input)`, and
|
|
56
|
+
`state.lastResult` types. Standard JSON Schema v1 inputs such as Zod 4.2+ are also supported.
|
|
216
57
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
## Re-Registration and Performance
|
|
220
|
-
|
|
221
|
-
The tool re-registers when any of these change:
|
|
222
|
-
|
|
223
|
-
- `name`
|
|
224
|
-
- `description`
|
|
225
|
-
- `inputSchema` reference
|
|
226
|
-
- `outputSchema` reference
|
|
227
|
-
- `annotations` reference
|
|
228
|
-
- values in `deps`
|
|
229
|
-
|
|
230
|
-
The hook avoids re-registration when only callback references change:
|
|
58
|
+
## API
|
|
231
59
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
- `onError`
|
|
236
|
-
- `formatOutput`
|
|
60
|
+
```ts
|
|
61
|
+
const { state, execute, reset } = useWebMCP(config, deps?);
|
|
62
|
+
```
|
|
237
63
|
|
|
238
|
-
|
|
64
|
+
`config` contains:
|
|
239
65
|
|
|
240
|
-
|
|
66
|
+
- `name` and `description`
|
|
67
|
+
- optional `inputSchema`, `outputSchema`, and `annotations`
|
|
68
|
+
- `execute(input)`, which may return synchronously or asynchronously
|
|
241
69
|
|
|
242
|
-
|
|
243
|
-
|
|
70
|
+
`state` contains `isExecuting`, `lastResult`, `error`, and `executionCount`. The returned
|
|
71
|
+
`execute(input)` invokes the same implementation locally. `reset()` clears observed state; it does
|
|
72
|
+
not cancel work already running.
|
|
244
73
|
|
|
245
|
-
##
|
|
74
|
+
## Tool responses
|
|
246
75
|
|
|
247
|
-
|
|
76
|
+
Raw return values use the same normalization as the MCP-B runtime:
|
|
248
77
|
|
|
249
|
-
`
|
|
78
|
+
- Existing MCP responses with a `content` array pass through unchanged.
|
|
79
|
+
- Strings become text content.
|
|
80
|
+
- JSON values become text content plus `structuredContent`.
|
|
81
|
+
- Other values receive a safe text representation.
|
|
250
82
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
- `outputSchema?`
|
|
255
|
-
- `annotations?`
|
|
256
|
-
- `execute(input)` (preferred)
|
|
257
|
-
- `handler(input)` (backward-compatible alias)
|
|
258
|
-
- `formatOutput?(output)` (deprecated)
|
|
259
|
-
- `onSuccess?(result, input)`
|
|
260
|
-
- `onError?(error, input)`
|
|
83
|
+
When `outputSchema` is present, a non-JSON-serializable result rejects local execution and becomes
|
|
84
|
+
an MCP error response. Native Chrome WebMCP does not advertise `outputSchema`; it is MCP-B metadata
|
|
85
|
+
for output inference and compatible runtimes.
|
|
261
86
|
|
|
262
|
-
|
|
87
|
+
## Re-registration
|
|
263
88
|
|
|
264
|
-
- `
|
|
265
|
-
-
|
|
266
|
-
|
|
89
|
+
The tool re-registers when `name`, `description`, or a value in `deps` changes. Implementations,
|
|
90
|
+
schemas, and annotations use their latest committed values without reference-driven churn. Include
|
|
91
|
+
a primitive schema or annotation revision in `deps` when registered metadata must change.
|
|
267
92
|
|
|
268
|
-
|
|
269
|
-
|
|
93
|
+
Registration is aborted on unmount. If the runtime is missing at mount, the hook warns and skips
|
|
94
|
+
registration; initialize the runtime first rather than polling once per hook.
|
|
270
95
|
|
|
271
|
-
##
|
|
96
|
+
## Exports
|
|
272
97
|
|
|
273
|
-
-
|
|
274
|
-
- `
|
|
275
|
-
-
|
|
98
|
+
- `useWebMCP`
|
|
99
|
+
- `WebMCPConfig`
|
|
100
|
+
- `WebMCPReturn`
|
|
101
|
+
- `ToolExecutionState`
|
|
102
|
+
- `ToolExecuteFunction`
|
|
103
|
+
- `InferToolInput`
|
|
104
|
+
- `InferOutput`
|
|
276
105
|
|
|
277
106
|
## License
|
|
278
107
|
|
package/dist/index.d.ts
CHANGED
|
@@ -3,377 +3,53 @@ import { DependencyList } from "react";
|
|
|
3
3
|
import { InferArgsFromInputSchema, InferJsonSchema, InputSchema, JsonSchemaForInference, ToolAnnotations } from "@mcp-b/webmcp-types";
|
|
4
4
|
|
|
5
5
|
//#region src/types.d.ts
|
|
6
|
-
/**
|
|
7
|
-
* Infers tool input type from either a Standard Schema or JSON Schema.
|
|
8
|
-
*
|
|
9
|
-
* - **Standard Schema** (Zod v4, Valibot, ArkType): extracts `~standard.types.input`
|
|
10
|
-
* - **JSON Schema** (`as const`): uses `InferArgsFromInputSchema` for structural inference
|
|
11
|
-
* - **Fallback**: `Record<string, unknown>`
|
|
12
|
-
*
|
|
13
|
-
* @template T - The input schema type
|
|
14
|
-
* @internal
|
|
15
|
-
*/
|
|
6
|
+
/** Infers tool input from a JSON Schema literal or Standard JSON Schema. */
|
|
16
7
|
type InferToolInput<T> = T extends {
|
|
17
8
|
readonly '~standard': {
|
|
18
9
|
readonly types?: infer Types;
|
|
19
10
|
};
|
|
20
|
-
} ? Types extends {
|
|
21
|
-
readonly input: infer
|
|
22
|
-
} ?
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
* When `TOutputSchema` is a literal inferable JSON schema, this resolves to
|
|
27
|
-
* `InferJsonSchema<TOutputSchema>`. When it's `undefined`,
|
|
28
|
-
* it falls back to the provided `TFallback` type.
|
|
29
|
-
*
|
|
30
|
-
* @template TOutputSchema - JSON Schema for output inference
|
|
31
|
-
* @template TFallback - Fallback type when no schema is provided
|
|
32
|
-
* @internal
|
|
33
|
-
*/
|
|
34
|
-
type InferOutput<TOutputSchema extends JsonSchemaForInference | undefined = undefined, TFallback = unknown> = TOutputSchema extends undefined ? TFallback : TOutputSchema extends JsonSchemaForInference ? InferJsonSchema<TOutputSchema> : TFallback;
|
|
35
|
-
/**
|
|
36
|
-
* Represents the current execution state of a tool, including loading status,
|
|
37
|
-
* results, errors, and execution history.
|
|
38
|
-
*
|
|
39
|
-
* @template TOutput - The type of data returned by the tool implementation
|
|
40
|
-
* @public
|
|
41
|
-
*/
|
|
11
|
+
} ? NonNullable<Types> extends {
|
|
12
|
+
readonly input: infer Input;
|
|
13
|
+
} ? Input : Record<string, unknown> : T extends InputSchema ? InferArgsFromInputSchema<T> : Record<string, unknown>;
|
|
14
|
+
/** Infers tool output from a JSON Schema literal. */
|
|
15
|
+
type InferOutput<TOutputSchema extends JsonSchemaForInference | undefined = undefined> = TOutputSchema extends undefined ? unknown : TOutputSchema extends JsonSchemaForInference ? InferJsonSchema<TOutputSchema> : unknown;
|
|
16
|
+
/** Current state for local and MCP-triggered tool executions. */
|
|
42
17
|
interface ToolExecutionState<TOutput = unknown> {
|
|
43
|
-
/**
|
|
44
|
-
* Indicates whether the tool is currently executing.
|
|
45
|
-
* Use this to show loading states in your UI.
|
|
46
|
-
*/
|
|
18
|
+
/** Whether at least one execution is pending. */
|
|
47
19
|
isExecuting: boolean;
|
|
48
|
-
/**
|
|
49
|
-
* The result from the most recent successful execution.
|
|
50
|
-
* Will be `null` if the tool hasn't been executed or last execution failed.
|
|
51
|
-
*/
|
|
20
|
+
/** Most recent successful result, or `null` before one exists. */
|
|
52
21
|
lastResult: TOutput | null;
|
|
53
|
-
/**
|
|
54
|
-
* The error from the most recent failed execution.
|
|
55
|
-
* Will be `null` if the tool hasn't been executed or last execution succeeded.
|
|
56
|
-
*/
|
|
22
|
+
/** Most recent execution error. */
|
|
57
23
|
error: Error | null;
|
|
58
|
-
/**
|
|
59
|
-
* Total number of times this tool has been executed.
|
|
60
|
-
* Increments on successful executions only.
|
|
61
|
-
*/
|
|
24
|
+
/** Number of successful executions since the last reset. */
|
|
62
25
|
executionCount: number;
|
|
63
26
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Tool implementation function used by `useWebMCP`.
|
|
66
|
-
*
|
|
67
|
-
* Supports sync or async implementations.
|
|
68
|
-
*
|
|
69
|
-
* @template TInputSchema - Schema defining input parameters
|
|
70
|
-
* @template TOutputSchema - Optional JSON Schema defining output structure
|
|
71
|
-
*
|
|
72
|
-
* @public
|
|
73
|
-
*/
|
|
27
|
+
/** Synchronous or asynchronous tool implementation. */
|
|
74
28
|
type ToolExecuteFunction<TInputSchema extends ToolInputSchema = InputSchema, TOutputSchema extends JsonSchemaForInference | undefined = undefined> = (input: InferToolInput<TInputSchema>) => Promise<InferOutput<TOutputSchema>> | InferOutput<TOutputSchema>;
|
|
75
|
-
/**
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
* Defines a tool's metadata, schema, and lifecycle callbacks.
|
|
79
|
-
* Uses JSON Schema for type inference via `as const`.
|
|
80
|
-
*
|
|
81
|
-
* @template TInputSchema - JSON Schema defining input parameters
|
|
82
|
-
* @template TOutputSchema - JSON Schema defining output structure
|
|
83
|
-
*
|
|
84
|
-
* @public
|
|
85
|
-
*
|
|
86
|
-
* @example Basic tool without output schema:
|
|
87
|
-
* ```typescript
|
|
88
|
-
* const config: WebMCPConfig = {
|
|
89
|
-
* name: 'posts_like',
|
|
90
|
-
* description: 'Like a post by its ID',
|
|
91
|
-
* inputSchema: {
|
|
92
|
-
* type: 'object',
|
|
93
|
-
* properties: { postId: { type: 'string' } },
|
|
94
|
-
* required: ['postId'],
|
|
95
|
-
* } as const,
|
|
96
|
-
* execute: async ({ postId }) => {
|
|
97
|
-
* await api.likePost(postId);
|
|
98
|
-
* return { success: true };
|
|
99
|
-
* },
|
|
100
|
-
* };
|
|
101
|
-
* ```
|
|
102
|
-
*
|
|
103
|
-
* @example Tool with output schema (enables MCP structuredContent):
|
|
104
|
-
* ```typescript
|
|
105
|
-
* useWebMCP({
|
|
106
|
-
* name: 'posts_like',
|
|
107
|
-
* description: 'Like a post and return updated like count',
|
|
108
|
-
* inputSchema: {
|
|
109
|
-
* type: 'object',
|
|
110
|
-
* properties: { postId: { type: 'string' } },
|
|
111
|
-
* required: ['postId'],
|
|
112
|
-
* } as const,
|
|
113
|
-
* outputSchema: {
|
|
114
|
-
* type: 'object',
|
|
115
|
-
* properties: {
|
|
116
|
-
* likes: { type: 'number', description: 'Updated like count' },
|
|
117
|
-
* likedAt: { type: 'string', description: 'ISO timestamp of the like' },
|
|
118
|
-
* },
|
|
119
|
-
* } as const,
|
|
120
|
-
* execute: async ({ postId }) => {
|
|
121
|
-
* const result = await api.likePost(postId);
|
|
122
|
-
* return { likes: result.likes, likedAt: new Date().toISOString() };
|
|
123
|
-
* },
|
|
124
|
-
* });
|
|
125
|
-
* ```
|
|
126
|
-
*/
|
|
127
|
-
interface WebMCPConfigBase<TInputSchema extends ToolInputSchema = InputSchema, TOutputSchema extends JsonSchemaForInference | undefined = undefined> {
|
|
128
|
-
/**
|
|
129
|
-
* Unique identifier for the tool (e.g., 'posts_like', 'graph_navigate').
|
|
130
|
-
* Must follow naming conventions: lowercase with underscores.
|
|
131
|
-
*/
|
|
29
|
+
/** Configuration for a tool registered by `useWebMCP`. */
|
|
30
|
+
interface WebMCPConfig<TInputSchema extends ToolInputSchema = InputSchema, TOutputSchema extends JsonSchemaForInference | undefined = undefined> {
|
|
31
|
+
/** Unique WebMCP tool name. */
|
|
132
32
|
name: string;
|
|
133
|
-
/**
|
|
134
|
-
* Human-readable description explaining what the tool does.
|
|
135
|
-
* This description is used by AI assistants to understand when to use the tool.
|
|
136
|
-
*/
|
|
33
|
+
/** Description shown to MCP clients. */
|
|
137
34
|
description: string;
|
|
138
|
-
/**
|
|
139
|
-
* Schema defining the input parameters for the tool.
|
|
140
|
-
* Accepts JSON Schema (with `as const`) or any Standard Schema v1
|
|
141
|
-
* library (Zod v4, Valibot, ArkType, etc.).
|
|
142
|
-
*
|
|
143
|
-
* @example JSON Schema
|
|
144
|
-
* ```typescript
|
|
145
|
-
* inputSchema: {
|
|
146
|
-
* type: 'object',
|
|
147
|
-
* properties: {
|
|
148
|
-
* postId: { type: 'string', description: 'The ID of the post to like' },
|
|
149
|
-
* },
|
|
150
|
-
* required: ['postId'],
|
|
151
|
-
* } as const
|
|
152
|
-
* ```
|
|
153
|
-
*
|
|
154
|
-
* @example Standard Schema (Zod v4)
|
|
155
|
-
* ```typescript
|
|
156
|
-
* inputSchema: z.object({ postId: z.string() })
|
|
157
|
-
* ```
|
|
158
|
-
*/
|
|
35
|
+
/** JSON Schema literal or Standard JSON Schema for the tool input. */
|
|
159
36
|
inputSchema?: TInputSchema;
|
|
160
|
-
/**
|
|
161
|
-
* **Recommended:** JSON Schema defining the expected output structure.
|
|
162
|
-
*
|
|
163
|
-
* When provided, this enables three key features:
|
|
164
|
-
* 1. **Type Safety**: The implementation return type is inferred from this schema
|
|
165
|
-
* 2. **MCP structuredContent**: The MCP response includes `structuredContent`
|
|
166
|
-
* containing the typed output per the MCP specification
|
|
167
|
-
* 3. **AI Understanding**: AI models can better understand and use the tool's output
|
|
168
|
-
*
|
|
169
|
-
* @see {@link https://spec.modelcontextprotocol.io/specification/server/tools/#output-schemas}
|
|
170
|
-
*
|
|
171
|
-
* @example
|
|
172
|
-
* ```typescript
|
|
173
|
-
* outputSchema: {
|
|
174
|
-
* type: 'object',
|
|
175
|
-
* properties: {
|
|
176
|
-
* counter: { type: 'number', description: 'The current counter value' },
|
|
177
|
-
* timestamp: { type: 'string', description: 'ISO timestamp' },
|
|
178
|
-
* },
|
|
179
|
-
* } as const
|
|
180
|
-
* ```
|
|
181
|
-
*/
|
|
37
|
+
/** JSON Schema used for output inference and structured content. */
|
|
182
38
|
outputSchema?: TOutputSchema;
|
|
183
|
-
/**
|
|
184
|
-
* Optional metadata annotations providing hints about tool behavior.
|
|
185
|
-
* See {@link ToolAnnotations} for available options.
|
|
186
|
-
*/
|
|
39
|
+
/** Optional WebMCP behavior hints. */
|
|
187
40
|
annotations?: ToolAnnotations;
|
|
188
|
-
/**
|
|
189
|
-
* Custom formatter for the MCP text response.
|
|
190
|
-
*
|
|
191
|
-
* @deprecated Use `outputSchema` instead. The `outputSchema` provides type-safe
|
|
192
|
-
* structured output via MCP's `structuredContent`, which is the recommended
|
|
193
|
-
* approach for tool outputs. This property will be removed in a future version.
|
|
194
|
-
*
|
|
195
|
-
* @param output - The raw output from the tool implementation
|
|
196
|
-
* @returns Formatted string for the MCP response content
|
|
197
|
-
*/
|
|
198
|
-
formatOutput?: (output: InferOutput<TOutputSchema>) => string;
|
|
199
|
-
/**
|
|
200
|
-
* Optional callback invoked when the tool execution succeeds.
|
|
201
|
-
* Useful for triggering side effects like navigation or analytics.
|
|
202
|
-
*
|
|
203
|
-
* @param result - The successful result from the tool implementation
|
|
204
|
-
* @param input - The input that was passed to the tool implementation
|
|
205
|
-
*/
|
|
206
|
-
onSuccess?: (result: InferOutput<TOutputSchema>, input: unknown) => void;
|
|
207
|
-
/**
|
|
208
|
-
* Optional callback invoked when the tool execution fails.
|
|
209
|
-
* Useful for error handling, logging, or showing user notifications.
|
|
210
|
-
*
|
|
211
|
-
* @param error - The error that occurred during execution
|
|
212
|
-
* @param input - The input that was passed to the tool implementation
|
|
213
|
-
*/
|
|
214
|
-
onError?: (error: Error, input: unknown) => void;
|
|
215
|
-
}
|
|
216
|
-
type WebMCPConfigImplementation<TInputSchema extends ToolInputSchema = InputSchema, TOutputSchema extends JsonSchemaForInference | undefined = undefined> = {
|
|
217
|
-
/**
|
|
218
|
-
* Preferred tool implementation function.
|
|
219
|
-
*/
|
|
41
|
+
/** Tool implementation. */
|
|
220
42
|
execute: ToolExecuteFunction<TInputSchema, TOutputSchema>;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
*/
|
|
224
|
-
handler?: ToolExecuteFunction<TInputSchema, TOutputSchema>;
|
|
225
|
-
} | {
|
|
226
|
-
/**
|
|
227
|
-
* Backward-compatible alias for `execute`.
|
|
228
|
-
*/
|
|
229
|
-
handler: ToolExecuteFunction<TInputSchema, TOutputSchema>;
|
|
230
|
-
/**
|
|
231
|
-
* Preferred tool implementation function.
|
|
232
|
-
*/
|
|
233
|
-
execute?: ToolExecuteFunction<TInputSchema, TOutputSchema>;
|
|
234
|
-
};
|
|
235
|
-
/**
|
|
236
|
-
* Configuration options for the `useWebMCP` hook.
|
|
237
|
-
*
|
|
238
|
-
* You can provide tool logic with either:
|
|
239
|
-
* - `execute` (preferred), or
|
|
240
|
-
* - `handler` (backward-compatible alias).
|
|
241
|
-
*
|
|
242
|
-
* If both are provided, `execute` is used.
|
|
243
|
-
*
|
|
244
|
-
* @template TInputSchema - JSON Schema defining input parameters
|
|
245
|
-
* @template TOutputSchema - JSON Schema defining output structure
|
|
246
|
-
*
|
|
247
|
-
* @public
|
|
248
|
-
*/
|
|
249
|
-
type WebMCPConfig<TInputSchema extends ToolInputSchema = InputSchema, TOutputSchema extends JsonSchemaForInference | undefined = undefined> = WebMCPConfigBase<TInputSchema, TOutputSchema> & WebMCPConfigImplementation<TInputSchema, TOutputSchema>;
|
|
250
|
-
/**
|
|
251
|
-
* Return value from the `useWebMCP` hook.
|
|
252
|
-
* Provides access to execution state and methods for manual tool control.
|
|
253
|
-
*
|
|
254
|
-
* @template TOutputSchema - JSON Schema defining output structure
|
|
255
|
-
* @public
|
|
256
|
-
*/
|
|
43
|
+
}
|
|
44
|
+
/** State and controls returned by `useWebMCP`. */
|
|
257
45
|
interface WebMCPReturn<TOutputSchema extends JsonSchemaForInference | undefined = undefined, TInputSchema extends ToolInputSchema = InputSchema> {
|
|
258
|
-
/**
|
|
259
|
-
* Current execution state including loading status, results, and errors.
|
|
260
|
-
* See {@link ToolExecutionState} for details.
|
|
261
|
-
*/
|
|
262
46
|
state: ToolExecutionState<InferOutput<TOutputSchema>>;
|
|
263
|
-
/**
|
|
264
|
-
* Manually execute the tool with the provided input.
|
|
265
|
-
* Useful for testing, debugging, or triggering execution from your UI.
|
|
266
|
-
*
|
|
267
|
-
* @param input - The input parameters to pass to the tool
|
|
268
|
-
* @returns Promise resolving to the tool's output
|
|
269
|
-
* @throws Error if validation fails or tool implementation throws
|
|
270
|
-
*/
|
|
271
47
|
execute: (input: InferToolInput<TInputSchema>) => Promise<InferOutput<TOutputSchema>>;
|
|
272
|
-
/**
|
|
273
|
-
* Reset the execution state to its initial values.
|
|
274
|
-
* Clears results, errors, and resets the execution count.
|
|
275
|
-
*/
|
|
276
48
|
reset: () => void;
|
|
277
49
|
}
|
|
278
50
|
//#endregion
|
|
279
51
|
//#region src/useWebMCP.d.ts
|
|
280
|
-
/**
|
|
281
|
-
* React hook for registering and managing Model Context Protocol (MCP) tools.
|
|
282
|
-
*
|
|
283
|
-
* This hook handles the complete lifecycle of an MCP tool:
|
|
284
|
-
* - Registers the tool with `window.document.modelContext`
|
|
285
|
-
* - Manages execution state (loading, results, errors)
|
|
286
|
-
* - Handles tool execution and lifecycle callbacks
|
|
287
|
-
* - Automatically unregisters on component unmount
|
|
288
|
-
* - Returns `structuredContent` when `outputSchema` is defined
|
|
289
|
-
*
|
|
290
|
-
* ## Output Schema (Recommended)
|
|
291
|
-
*
|
|
292
|
-
* Always define an `outputSchema` for your tools. This provides:
|
|
293
|
-
* - **Type Safety**: Handler return type is inferred from the schema
|
|
294
|
-
* - **MCP structuredContent**: AI models receive structured, typed data
|
|
295
|
-
* - **Better AI Understanding**: Models can reason about your tool's output format
|
|
296
|
-
*
|
|
297
|
-
* ```tsx
|
|
298
|
-
* useWebMCP({
|
|
299
|
-
* name: 'get_user',
|
|
300
|
-
* description: 'Get user by ID',
|
|
301
|
-
* inputSchema: {
|
|
302
|
-
* type: 'object',
|
|
303
|
-
* properties: { userId: { type: 'string' } },
|
|
304
|
-
* required: ['userId'],
|
|
305
|
-
* } as const,
|
|
306
|
-
* outputSchema: {
|
|
307
|
-
* type: 'object',
|
|
308
|
-
* properties: {
|
|
309
|
-
* id: { type: 'string' },
|
|
310
|
-
* name: { type: 'string' },
|
|
311
|
-
* email: { type: 'string' },
|
|
312
|
-
* },
|
|
313
|
-
* } as const,
|
|
314
|
-
* execute: async ({ userId }) => {
|
|
315
|
-
* const user = await fetchUser(userId);
|
|
316
|
-
* return { id: user.id, name: user.name, email: user.email };
|
|
317
|
-
* },
|
|
318
|
-
* });
|
|
319
|
-
* ```
|
|
320
|
-
*
|
|
321
|
-
* ## Re-render Optimization
|
|
322
|
-
*
|
|
323
|
-
* This hook is optimized to minimize unnecessary tool re-registrations:
|
|
324
|
-
*
|
|
325
|
-
* - **Ref-based static descriptors and callbacks**: `inputSchema`, `outputSchema`,
|
|
326
|
-
* `annotations`, `execute`/`handler`, `onSuccess`, `onError`, and `formatOutput`
|
|
327
|
-
* are stored in refs, so recreating them during render won't trigger re-registration.
|
|
328
|
-
*
|
|
329
|
-
* If a schema or annotation actually changes and the registered descriptor should change,
|
|
330
|
-
* include the relevant primitive value in the `deps` array.
|
|
331
|
-
*
|
|
332
|
-
* ```tsx
|
|
333
|
-
* useWebMCP({
|
|
334
|
-
* outputSchema: { type: 'object', properties: { count: { type: 'number' } } } as const,
|
|
335
|
-
* });
|
|
336
|
-
* ```
|
|
337
|
-
*
|
|
338
|
-
* @template TInputSchema - JSON Schema defining input parameter types (use `as const` for inference)
|
|
339
|
-
* @template TOutputSchema - JSON Schema defining output structure
|
|
340
|
-
*
|
|
341
|
-
* @param config - Configuration object for the tool
|
|
342
|
-
* @param deps - Optional dependency array that triggers tool re-registration when values change.
|
|
343
|
-
*
|
|
344
|
-
* @returns Object containing execution state and control methods
|
|
345
|
-
*
|
|
346
|
-
* @public
|
|
347
|
-
*
|
|
348
|
-
* @example
|
|
349
|
-
* Basic tool with outputSchema (recommended):
|
|
350
|
-
* ```tsx
|
|
351
|
-
* function PostActions() {
|
|
352
|
-
* const likeTool = useWebMCP({
|
|
353
|
-
* name: 'posts_like',
|
|
354
|
-
* description: 'Like a post by ID',
|
|
355
|
-
* inputSchema: {
|
|
356
|
-
* type: 'object',
|
|
357
|
-
* properties: { postId: { type: 'string', description: 'The post ID' } },
|
|
358
|
-
* required: ['postId'],
|
|
359
|
-
* } as const,
|
|
360
|
-
* outputSchema: {
|
|
361
|
-
* type: 'object',
|
|
362
|
-
* properties: {
|
|
363
|
-
* success: { type: 'boolean' },
|
|
364
|
-
* likeCount: { type: 'number' },
|
|
365
|
-
* },
|
|
366
|
-
* } as const,
|
|
367
|
-
* execute: async ({ postId }) => {
|
|
368
|
-
* const result = await api.posts.like(postId);
|
|
369
|
-
* return { success: true, likeCount: result.likes };
|
|
370
|
-
* },
|
|
371
|
-
* });
|
|
372
|
-
*
|
|
373
|
-
* return <div>Likes: {likeTool.state.lastResult?.likeCount ?? 0}</div>;
|
|
374
|
-
* }
|
|
375
|
-
* ```
|
|
376
|
-
*/
|
|
52
|
+
/** Registers a React-owned tool with the current WebMCP model context. */
|
|
377
53
|
declare function useWebMCP<TInputSchema extends ToolInputSchema = InputSchema, TOutputSchema extends JsonSchemaForInference | undefined = undefined>(config: WebMCPConfig<TInputSchema, TOutputSchema>, deps?: DependencyList): WebMCPReturn<TOutputSchema, TInputSchema>;
|
|
378
54
|
//#endregion
|
|
379
55
|
export { type InferOutput, type InferToolInput, type ToolExecuteFunction, type ToolExecutionState, type WebMCPConfig, type WebMCPReturn, useWebMCP };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{normalizeInputSchema as e,
|
|
1
|
+
"use client";import{normalizeInputSchema as e,normalizeToolResponse as t}from"@mcp-b/webmcp-polyfill/schema";import{useCallback as n,useEffect as r,useLayoutEffect as i,useRef as a,useState as o}from"react";const s={isExecuting:!1,lastResult:null,error:null,executionCount:0},c=typeof window>`u`?r:i;function l(i,l){let{name:u,description:d}=i,[f,p]=o(s),m=a(i),h=a(0);c(()=>{m.current=i});let g=n(async e=>{h.current+=1,p(e=>({...e,isExecuting:!0,error:null}));let n,r=m.current;try{if(n=await r.execute(e),r.outputSchema&&t(n).structuredContent===void 0)throw Error(`Tool "${r.name}" outputSchema requires execute to return a JSON-serializable result`)}catch(e){--h.current;let t=e instanceof Error?e:Error(String(e));throw p(e=>({...e,isExecuting:h.current>0,error:t})),t}return--h.current,p(e=>({isExecuting:h.current>0,lastResult:n,error:null,executionCount:e.executionCount+1})),n},[]),_=n(()=>p({...s,isExecuting:h.current>0}),[]);return r(()=>{let n=typeof document>`u`?void 0:document.modelContext??(typeof navigator>`u`?void 0:navigator.modelContext);if(!n){console.warn(`[useWebMCP] document.modelContext is not available. Tool "${u}" will not be registered.`);return}let r=m.current,i=r.outputSchema,a=new AbortController,o={name:u,description:d,inputSchema:e(r.inputSchema).inputSchema,...i&&{outputSchema:i},...r.annotations&&{annotations:r.annotations},execute:async e=>{try{let n=t(await g(e));if(i&&n.structuredContent===void 0)throw Error(`Tool "${u}" outputSchema requires the tool implementation to return a JSON-serializable result`);return n}catch(e){return{content:[{type:`text`,text:`Error: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}}};try{let e=n.registerTool(o,{signal:a.signal});Promise.resolve(e).catch(e=>{a.signal.aborted||(a.abort(),console.warn(`[useWebMCP] registerTool("${u}") rejected:`,e))})}catch(e){a.abort(),console.warn(`[useWebMCP] registerTool("${u}") rejected:`,e);return}return()=>a.abort()},[u,d,...l??[]]),{state:f,execute:g,reset:_}}export{l as useWebMCP};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/model-context.ts","../src/useWebMCP.ts"],"sourcesContent":["import type { ModelContext } from '@mcp-b/webmcp-types';\n\nexport type ModelContextSurface = ModelContext;\ntype ModelContextHost = { modelContext?: ModelContext };\n\nexport function getModelContext(): ModelContextSurface | undefined {\n if (typeof window === 'undefined') {\n return undefined;\n }\n\n const documentContext = (window.document as Document & ModelContextHost).modelContext;\n const navigatorContext = (window.navigator as Navigator & ModelContextHost).modelContext;\n return documentContext ?? navigatorContext;\n}\n","import {\n normalizeInputSchema,\n toJsonValue,\n type ToolInputSchema,\n} from '@mcp-b/webmcp-polyfill/schema';\nimport type {\n CallToolResult,\n InputSchema,\n JsonSchemaForInference,\n ToolDescriptor,\n} from '@mcp-b/webmcp-types';\nimport type { DependencyList } from 'react';\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport type {\n InferOutput,\n InferToolInput,\n ToolExecutionState,\n WebMCPConfig,\n WebMCPReturn,\n} from './types.js';\nimport { getModelContext } from './model-context.js';\n\n/**\n * Default output formatter that converts values to formatted JSON strings.\n *\n * String values are returned as-is; all other types are serialized to\n * indented JSON for readability.\n *\n * @internal\n */\nfunction defaultFormatOutput(output: unknown): string {\n if (typeof output === 'string') {\n return output;\n }\n return JSON.stringify(output, null, 2);\n}\n\nconst TOOL_OWNER_BY_NAME = new Map<string, symbol>();\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\nfunction isDev(): boolean {\n const env = typeof process !== 'undefined' ? process.env?.NODE_ENV : undefined;\n return env !== undefined ? env !== 'production' : false;\n}\n\n/**\n * React hook for registering and managing Model Context Protocol (MCP) tools.\n *\n * This hook handles the complete lifecycle of an MCP tool:\n * - Registers the tool with `window.document.modelContext`\n * - Manages execution state (loading, results, errors)\n * - Handles tool execution and lifecycle callbacks\n * - Automatically unregisters on component unmount\n * - Returns `structuredContent` when `outputSchema` is defined\n *\n * ## Output Schema (Recommended)\n *\n * Always define an `outputSchema` for your tools. This provides:\n * - **Type Safety**: Handler return type is inferred from the schema\n * - **MCP structuredContent**: AI models receive structured, typed data\n * - **Better AI Understanding**: Models can reason about your tool's output format\n *\n * ```tsx\n * useWebMCP({\n * name: 'get_user',\n * description: 'Get user by ID',\n * inputSchema: {\n * type: 'object',\n * properties: { userId: { type: 'string' } },\n * required: ['userId'],\n * } as const,\n * outputSchema: {\n * type: 'object',\n * properties: {\n * id: { type: 'string' },\n * name: { type: 'string' },\n * email: { type: 'string' },\n * },\n * } as const,\n * execute: async ({ userId }) => {\n * const user = await fetchUser(userId);\n * return { id: user.id, name: user.name, email: user.email };\n * },\n * });\n * ```\n *\n * ## Re-render Optimization\n *\n * This hook is optimized to minimize unnecessary tool re-registrations:\n *\n * - **Ref-based static descriptors and callbacks**: `inputSchema`, `outputSchema`,\n * `annotations`, `execute`/`handler`, `onSuccess`, `onError`, and `formatOutput`\n * are stored in refs, so recreating them during render won't trigger re-registration.\n *\n * If a schema or annotation actually changes and the registered descriptor should change,\n * include the relevant primitive value in the `deps` array.\n *\n * ```tsx\n * useWebMCP({\n * outputSchema: { type: 'object', properties: { count: { type: 'number' } } } as const,\n * });\n * ```\n *\n * @template TInputSchema - JSON Schema defining input parameter types (use `as const` for inference)\n * @template TOutputSchema - JSON Schema defining output structure\n *\n * @param config - Configuration object for the tool\n * @param deps - Optional dependency array that triggers tool re-registration when values change.\n *\n * @returns Object containing execution state and control methods\n *\n * @public\n *\n * @example\n * Basic tool with outputSchema (recommended):\n * ```tsx\n * function PostActions() {\n * const likeTool = useWebMCP({\n * name: 'posts_like',\n * description: 'Like a post by ID',\n * inputSchema: {\n * type: 'object',\n * properties: { postId: { type: 'string', description: 'The post ID' } },\n * required: ['postId'],\n * } as const,\n * outputSchema: {\n * type: 'object',\n * properties: {\n * success: { type: 'boolean' },\n * likeCount: { type: 'number' },\n * },\n * } as const,\n * execute: async ({ postId }) => {\n * const result = await api.posts.like(postId);\n * return { success: true, likeCount: result.likes };\n * },\n * });\n *\n * return <div>Likes: {likeTool.state.lastResult?.likeCount ?? 0}</div>;\n * }\n * ```\n */\nexport function useWebMCP<\n TInputSchema extends ToolInputSchema = InputSchema,\n TOutputSchema extends JsonSchemaForInference | undefined = undefined,\n>(\n config: WebMCPConfig<TInputSchema, TOutputSchema>,\n deps?: DependencyList\n): WebMCPReturn<TOutputSchema, TInputSchema> {\n type TOutput = InferOutput<TOutputSchema>;\n type TInput = InferToolInput<TInputSchema>;\n const {\n name,\n description,\n inputSchema,\n outputSchema,\n annotations,\n execute: configExecute,\n handler: legacyHandler,\n formatOutput = defaultFormatOutput,\n onSuccess,\n onError,\n } = config;\n const toolExecute = configExecute ?? legacyHandler;\n\n if (!toolExecute) {\n throw new TypeError(\n `[useWebMCP] Tool \"${name}\" must provide an implementation via config.execute or config.handler`\n );\n }\n\n const [state, setState] = useState<ToolExecutionState<TOutput>>({\n isExecuting: false,\n lastResult: null,\n error: null,\n executionCount: 0,\n });\n\n const toolExecuteRef = useRef(toolExecute);\n const onSuccessRef = useRef(onSuccess);\n const onErrorRef = useRef(onError);\n const formatOutputRef = useRef(formatOutput);\n const inputSchemaRef = useRef(inputSchema);\n const outputSchemaRef = useRef(outputSchema);\n const annotationsRef = useRef(annotations);\n const isMountedRef = useRef(true);\n const warnedRef = useRef(new Set<string>());\n const prevConfigRef = useRef({\n description,\n deps,\n });\n // Update refs when callbacks or static descriptors are recreated during render.\n useIsomorphicLayoutEffect(() => {\n toolExecuteRef.current = toolExecute;\n onSuccessRef.current = onSuccess;\n onErrorRef.current = onError;\n formatOutputRef.current = formatOutput;\n inputSchemaRef.current = inputSchema;\n outputSchemaRef.current = outputSchema;\n annotationsRef.current = annotations;\n }, [annotations, inputSchema, onSuccess, onError, outputSchema, toolExecute, formatOutput]);\n\n // Cleanup: mark component as unmounted\n useEffect(() => {\n isMountedRef.current = true;\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n\n useEffect(() => {\n if (!isDev()) {\n prevConfigRef.current = { description, deps };\n return;\n }\n\n const warnOnce = (key: string, message: string) => {\n if (warnedRef.current.has(key)) {\n return;\n }\n console.warn(`[useWebMCP] ${message}`);\n warnedRef.current.add(key);\n };\n\n const prev = prevConfigRef.current;\n\n if (description !== prev.description) {\n warnOnce(\n 'description',\n `Tool \"${name}\" description changed; this re-registers the tool. Memoize the description if it does not need to update.`\n );\n }\n\n if (\n deps?.some(\n (value) => (typeof value === 'object' && value !== null) || typeof value === 'function'\n )\n ) {\n warnOnce(\n 'deps',\n `Tool \"${name}\" deps contains non-primitive values; prefer primitives or memoize objects/functions to reduce re-registration.`\n );\n }\n\n prevConfigRef.current = { description, deps };\n }, [deps, description, name]);\n\n /**\n * Executes the configured tool implementation with input validation and state management.\n *\n * @param input - The input parameters to validate and pass to the tool implementation\n * @returns Promise resolving to the tool output\n * @throws Error if validation fails or the tool implementation throws\n */\n const execute = useCallback(async (input: TInput): Promise<TOutput> => {\n setState((prev) => ({\n ...prev,\n isExecuting: true,\n error: null,\n }));\n\n try {\n const result = await toolExecuteRef.current(input);\n\n // Only update state if component is still mounted\n if (isMountedRef.current) {\n setState((prev) => ({\n isExecuting: false,\n lastResult: result,\n error: null,\n executionCount: prev.executionCount + 1,\n }));\n }\n\n if (onSuccessRef.current) {\n onSuccessRef.current(result, input);\n }\n\n return result;\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n\n // Only update state if component is still mounted\n if (isMountedRef.current) {\n setState((prev) => ({\n ...prev,\n isExecuting: false,\n error: err,\n }));\n }\n\n if (onErrorRef.current) {\n onErrorRef.current(err, input);\n }\n\n throw err;\n }\n }, []);\n const executeRef = useRef(execute);\n\n useEffect(() => {\n executeRef.current = execute;\n }, [execute]);\n\n const stableExecute = useCallback(\n (input: TInput): Promise<TOutput> => executeRef.current(input),\n []\n );\n\n /**\n * Resets the execution state to initial values.\n */\n const reset = useCallback(() => {\n setState({\n isExecuting: false,\n lastResult: null,\n error: null,\n executionCount: 0,\n });\n }, []);\n\n useEffect(() => {\n const modelContext = getModelContext();\n if (!modelContext) {\n console.warn(\n `[useWebMCP] window.document.modelContext is not available. Tool \"${name}\" will not be registered.`\n );\n return;\n }\n\n /**\n * Handles MCP tool execution by running the tool implementation and formatting the response.\n *\n * @param input - The input parameters from the MCP client\n * @returns CallToolResult with text content and optional structuredContent\n */\n const mcpHandler = async (input: unknown): Promise<CallToolResult> => {\n try {\n const result = await Reflect.apply(executeRef.current, undefined, [input]);\n const formattedOutput = formatOutputRef.current(result);\n\n const response: CallToolResult = {\n content: [\n {\n type: 'text',\n text: formattedOutput,\n },\n ],\n };\n\n if (outputSchemaRef.current) {\n const structuredContent = toJsonValue(result);\n if (structuredContent === undefined) {\n throw new Error(\n `Tool \"${name}\" outputSchema requires the tool implementation to return a JSON-serializable result`\n );\n }\n response.structuredContent = structuredContent;\n }\n\n return response;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n return {\n content: [\n {\n type: 'text',\n text: `Error: ${errorMessage}`,\n },\n ],\n isError: true,\n };\n }\n };\n\n const ownerToken = Symbol(name);\n const resolvedInputSchema = normalizeInputSchema(inputSchemaRef.current).inputSchema;\n const resolvedOutputSchema = outputSchemaRef.current;\n const resolvedAnnotations = annotationsRef.current;\n const toolDescriptor: ToolDescriptor & { inputSchema: InputSchema } = {\n name,\n description,\n inputSchema: resolvedInputSchema,\n ...(resolvedOutputSchema && { outputSchema: resolvedOutputSchema }),\n ...(resolvedAnnotations && { annotations: resolvedAnnotations }),\n execute: mcpHandler,\n };\n\n const controller = new AbortController();\n let registered = false;\n let disposed = false;\n\n try {\n const registerResult = modelContext.registerTool(toolDescriptor, {\n signal: controller.signal,\n });\n\n void Promise.resolve(registerResult).then(\n () => {\n if (!disposed && !controller.signal.aborted) {\n registered = true;\n TOOL_OWNER_BY_NAME.set(name, ownerToken);\n }\n },\n (error: unknown) => {\n if (!controller.signal.aborted) {\n controller.abort();\n console.warn(`[useWebMCP] registerTool(\"${name}\") rejected:`, error);\n }\n }\n );\n } catch (error) {\n controller.abort();\n console.warn(`[useWebMCP] registerTool(\"${name}\") rejected:`, error);\n return;\n }\n\n return () => {\n disposed = true;\n\n if (registered && TOOL_OWNER_BY_NAME.get(name) === ownerToken) {\n TOOL_OWNER_BY_NAME.delete(name);\n controller.abort();\n return;\n }\n\n if (!registered) {\n controller.abort();\n }\n };\n // Spread operator in dependencies: Allows users to provide additional dependencies\n // via the `deps` parameter. While unconventional, this pattern is intentional to support\n // dynamic dependency injection. The spread is safe because deps is validated and warned\n // about non-primitive values earlier in this hook.\n }, [name, description, ...(deps ?? [])]);\n\n return {\n state,\n execute: stableExecute,\n reset,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/useWebMCP.ts"],"sourcesContent":["import {\n normalizeInputSchema,\n normalizeToolResponse,\n type ToolInputSchema,\n} from '@mcp-b/webmcp-polyfill/schema';\nimport type { InputSchema, JsonSchemaForInference } from '@mcp-b/webmcp-types';\nimport type { DependencyList } from 'react';\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport type {\n InferOutput,\n InferToolInput,\n ToolExecutionState,\n WebMCPConfig,\n WebMCPReturn,\n} from './types.js';\n\nconst INITIAL_STATE = {\n isExecuting: false,\n lastResult: null,\n error: null,\n executionCount: 0,\n};\n\nconst useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;\n\n/** Registers a React-owned tool with the current WebMCP model context. */\nexport function useWebMCP<\n TInputSchema extends ToolInputSchema = InputSchema,\n TOutputSchema extends JsonSchemaForInference | undefined = undefined,\n>(\n config: WebMCPConfig<TInputSchema, TOutputSchema>,\n deps?: DependencyList\n): WebMCPReturn<TOutputSchema, TInputSchema> {\n type TOutput = InferOutput<TOutputSchema>;\n type TInput = InferToolInput<TInputSchema>;\n const { name, description } = config;\n const [state, setState] = useState<ToolExecutionState<TOutput>>(INITIAL_STATE);\n const committedConfigRef = useRef(config);\n const pendingExecutionsRef = useRef(0);\n\n // MCP calls can arrive after commit but before passive effects. A layout effect\n // publishes only committed renders; the server fallback avoids the SSR warning.\n useIsomorphicLayoutEffect(() => {\n committedConfigRef.current = config;\n });\n\n const run = useCallback(async (input: TInput): Promise<TOutput> => {\n pendingExecutionsRef.current += 1;\n setState((previous) => ({ ...previous, isExecuting: true, error: null }));\n\n let result: TOutput;\n const executionConfig = committedConfigRef.current;\n try {\n result = await executionConfig.execute(input);\n if (\n executionConfig.outputSchema &&\n normalizeToolResponse(result).structuredContent === undefined\n ) {\n throw new Error(\n `Tool \"${executionConfig.name}\" outputSchema requires execute to return a JSON-serializable result`\n );\n }\n } catch (error) {\n pendingExecutionsRef.current -= 1;\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n setState((previous) => ({\n ...previous,\n isExecuting: pendingExecutionsRef.current > 0,\n error: normalizedError,\n }));\n throw normalizedError;\n }\n\n pendingExecutionsRef.current -= 1;\n setState((previous) => ({\n isExecuting: pendingExecutionsRef.current > 0,\n lastResult: result,\n error: null,\n executionCount: previous.executionCount + 1,\n }));\n return result;\n }, []);\n\n const reset = useCallback(\n () => setState({ ...INITIAL_STATE, isExecuting: pendingExecutionsRef.current > 0 }),\n []\n );\n\n useEffect(() => {\n const modelContext =\n typeof document === 'undefined'\n ? undefined\n : (document.modelContext ??\n (typeof navigator === 'undefined' ? undefined : navigator.modelContext));\n if (!modelContext) {\n console.warn(\n `[useWebMCP] document.modelContext is not available. Tool \"${name}\" will not be registered.`\n );\n return;\n }\n\n const registeredConfig = committedConfigRef.current;\n const registeredOutputSchema = registeredConfig.outputSchema;\n const controller = new AbortController();\n const tool = {\n name,\n description,\n inputSchema: normalizeInputSchema(registeredConfig.inputSchema).inputSchema,\n ...(registeredOutputSchema && { outputSchema: registeredOutputSchema }),\n ...(registeredConfig.annotations && { annotations: registeredConfig.annotations }),\n execute: async (input: TInput) => {\n try {\n const response = normalizeToolResponse(await run(input));\n if (registeredOutputSchema && response.structuredContent === undefined) {\n throw new Error(\n `Tool \"${name}\" outputSchema requires the tool implementation to return a JSON-serializable result`\n );\n }\n return response;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [{ type: 'text' as const, text: `Error: ${message}` }],\n isError: true,\n };\n }\n },\n };\n\n try {\n const registration = modelContext.registerTool(tool, { signal: controller.signal });\n void Promise.resolve(registration).catch((error: unknown) => {\n if (!controller.signal.aborted) {\n controller.abort();\n console.warn(`[useWebMCP] registerTool(\"${name}\") rejected:`, error);\n }\n });\n } catch (error) {\n controller.abort();\n console.warn(`[useWebMCP] registerTool(\"${name}\") rejected:`, error);\n return;\n }\n\n return () => controller.abort();\n // `deps` lets callers explicitly opt descriptor values into re-registration.\n // oxlint-disable-next-line react-doctor/exhaustive-deps -- Public API deliberately forwards caller deps.\n }, [name, description, ...(deps ?? [])]);\n\n return { state, execute: run, reset };\n}\n"],"mappings":"+MAgBA,MAAM,EAAgB,CACpB,YAAa,GACb,WAAY,KACZ,MAAO,KACP,eAAgB,EACjB,CAEK,EAA4B,OAAO,OAAW,IAAc,EAAY,EAG9E,SAAgB,EAId,EACA,EAC2C,CAG3C,GAAM,CAAE,OAAM,eAAgB,EACxB,CAAC,EAAO,GAAY,EAAsC,EAAc,CACxE,EAAqB,EAAO,EAAO,CACnC,EAAuB,EAAO,EAAE,CAItC,MAAgC,CAC9B,EAAmB,QAAU,GAC7B,CAEF,IAAM,EAAM,EAAY,KAAO,IAAoC,CACjE,EAAqB,SAAW,EAChC,EAAU,IAAc,CAAE,GAAG,EAAU,YAAa,GAAM,MAAO,KAAM,EAAE,CAEzE,IAAI,EACE,EAAkB,EAAmB,QAC3C,GAAI,CAEF,GADA,EAAS,MAAM,EAAgB,QAAQ,EAAM,CAE3C,EAAgB,cAChB,EAAsB,EAAO,CAAC,oBAAsB,IAAA,GAEpD,MAAU,MACR,SAAS,EAAgB,KAAK,sEAC/B,OAEI,EAAO,CACd,IAAqB,QACrB,IAAM,EAAkB,aAAiB,MAAQ,EAAY,MAAM,OAAO,EAAM,CAAC,CAMjF,MALA,EAAU,IAAc,CACtB,GAAG,EACH,YAAa,EAAqB,QAAU,EAC5C,MAAO,EACR,EAAE,CACG,EAUR,MAPA,IAAqB,QACrB,EAAU,IAAc,CACtB,YAAa,EAAqB,QAAU,EAC5C,WAAY,EACZ,MAAO,KACP,eAAgB,EAAS,eAAiB,EAC3C,EAAE,CACI,GACN,EAAE,CAAC,CAEA,EAAQ,MACN,EAAS,CAAE,GAAG,EAAe,YAAa,EAAqB,QAAU,EAAG,CAAC,CACnF,EAAE,CACH,CA8DD,OA5DA,MAAgB,CACd,IAAM,EACJ,OAAO,SAAa,IAChB,IAAA,GACC,SAAS,eACT,OAAO,UAAc,IAAc,IAAA,GAAY,UAAU,cAChE,GAAI,CAAC,EAAc,CACjB,QAAQ,KACN,6DAA6D,EAAK,2BACnE,CACD,OAGF,IAAM,EAAmB,EAAmB,QACtC,EAAyB,EAAiB,aAC1C,EAAa,IAAI,gBACjB,EAAO,CACX,OACA,cACA,YAAa,EAAqB,EAAiB,YAAY,CAAC,YAChE,GAAI,GAA0B,CAAE,aAAc,EAAwB,CACtE,GAAI,EAAiB,aAAe,CAAE,YAAa,EAAiB,YAAa,CACjF,QAAS,KAAO,IAAkB,CAChC,GAAI,CACF,IAAM,EAAW,EAAsB,MAAM,EAAI,EAAM,CAAC,CACxD,GAAI,GAA0B,EAAS,oBAAsB,IAAA,GAC3D,MAAU,MACR,SAAS,EAAK,sFACf,CAEH,OAAO,QACA,EAAO,CAEd,MAAO,CACL,QAAS,CAAC,CAAE,KAAM,OAAiB,KAAM,UAF3B,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAEN,CAAC,CAC/D,QAAS,GACV,GAGN,CAED,GAAI,CACF,IAAM,EAAe,EAAa,aAAa,EAAM,CAAE,OAAQ,EAAW,OAAQ,CAAC,CACnF,QAAa,QAAQ,EAAa,CAAC,MAAO,GAAmB,CACtD,EAAW,OAAO,UACrB,EAAW,OAAO,CAClB,QAAQ,KAAK,6BAA6B,EAAK,cAAe,EAAM,GAEtE,OACK,EAAO,CACd,EAAW,OAAO,CAClB,QAAQ,KAAK,6BAA6B,EAAK,cAAe,EAAM,CACpE,OAGF,UAAa,EAAW,OAAO,EAG9B,CAAC,EAAM,EAAa,GAAI,GAAQ,EAAE,CAAE,CAAC,CAEjC,CAAE,QAAO,QAAS,EAAK,QAAO"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usewebmcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Standalone React hooks for strict core WebMCP tool registration with document.modelContext",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"type": "module",
|
|
32
|
+
"sideEffects": false,
|
|
32
33
|
"main": "./dist/index.js",
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
33
35
|
"exports": {
|
|
34
36
|
".": {
|
|
35
37
|
"types": "./dist/index.d.ts",
|
|
@@ -41,8 +43,8 @@
|
|
|
41
43
|
"registry": "https://registry.npmjs.org/"
|
|
42
44
|
},
|
|
43
45
|
"dependencies": {
|
|
44
|
-
"@mcp-b/webmcp-polyfill": "
|
|
45
|
-
"@mcp-b/webmcp-types": "
|
|
46
|
+
"@mcp-b/webmcp-polyfill": "5.0.0",
|
|
47
|
+
"@mcp-b/webmcp-types": "5.0.0"
|
|
46
48
|
},
|
|
47
49
|
"devDependencies": {
|
|
48
50
|
"@types/node": "22.17.2",
|
|
@@ -55,10 +57,14 @@
|
|
|
55
57
|
"vite-plus": "^0.1.22",
|
|
56
58
|
"vitest": "npm:@voidzero-dev/vite-plus-test@latest",
|
|
57
59
|
"vitest-browser-react": "^2.0.4",
|
|
58
|
-
"
|
|
60
|
+
"zod": "4.4.3",
|
|
61
|
+
"@mcp-b/global": "5.0.0"
|
|
59
62
|
},
|
|
60
63
|
"peerDependencies": {
|
|
61
|
-
"react": "^
|
|
64
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
65
|
+
},
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": ">=20"
|
|
62
68
|
},
|
|
63
69
|
"scripts": {
|
|
64
70
|
"build": "vp pack",
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/useWebMCP.ts"],"mappings":";;;;;;;;AAmBA;;;;;;;KAAY,cAAA,MAAoB,CAAA;EAAA,SAAqB,WAAA;IAAA,SAAwB,KAAA;EAAA;AAAA,IACzE,KAAA;EAAA,SAAyB,KAAA;AAAA,IACvB,CAAA,GACA,MAAA,oBACF,CAAA,SAAU,WAAA,GACR,wBAAA,CAAyB,CAAA,IACzB,MAAA;;;;;;;;;;;;KAaM,WAAA,uBACY,sBAAA,iDAEpB,aAAA,qBACA,SAAA,GACA,aAAA,SAAsB,sBAAA,GACpB,eAAA,CAAgB,aAAA,IAChB,SAAA;;;;AAPN;;;;UAgBiB,kBAAA;EAZb;;;;EAiBF,WAAA;EAdI;;;;EAoBJ,UAAA,EAAY,OAAA;EAzBZ;;;;EA+BA,KAAA,EAAO,KAAA;EA3BH;;;;EAiCJ,cAAA;AAAA;;;;;;;;;;;KAaU,mBAAA,sBACW,eAAA,GAAkB,WAAA,wBACjB,sBAAA,6BAEtB,KAAA,EAAO,cAAA,CAAe,YAAA,MACnB,OAAA,CAAQ,WAAA,CAAY,aAAA,KAAkB,WAAA,CAAY,aAAA;;AALvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKsE;;;;;;;;;;;;;;;;;;;;;UAsD5D,gBAAA,sBACa,eAAA,GAAkB,WAAA,wBACjB,sBAAA;EAYtB;;;;EANA,IAAA;EA2DA;;;;EArDA,WAAA;EAiEgB;;;;;;;;;;;;AAkBuB;;;;;;;;;EA5DvC,WAAA,GAAc,YAAA;EA2EkC;;;;;;;;;;;;;;;;;;;;;;EAnDhD,YAAA,GAAe,aAAA;EAyDX;;;;EAnDJ,WAAA,GAAc,eAAA;EAuDA;;;;;AAiBhB;;;;;EA5DE,YAAA,IAAgB,MAAA,EAAQ,WAAA,CAAY,aAAA;EA+DjB;;;;;;;EAtDnB,SAAA,IAAa,MAAA,EAAQ,WAAA,CAAY,aAAA,GAAgB,KAAA;EAoDjD;;;;;;;EA3CA,OAAA,IAAW,KAAA,EAAO,KAAA,EAAO,KAAA;AAAA;AAAA,KAGtB,0BAAA,sBACkB,eAAA,GAAkB,WAAA,wBACjB,sBAAA;EAyCmB;;;EAnCrC,OAAA,EAAS,mBAAA,CAAoB,YAAA,EAAc,aAAA;EA4CpB;;;EAxCvB,OAAA,GAAU,mBAAA,CAAoB,YAAA,EAAc,aAAA;AAAA;EAgDV;;;EA1ClC,OAAA,EAAS,mBAAA,CAAoB,YAAA,EAAc,aAAA;EAoD9B;;;EAhDb,OAAA,GAAU,mBAAA,CAAoB,YAAA,EAAc,aAAA;AAAA;;;;;;;;;;;;;;;KAiBtC,YAAA,sBACW,eAAA,GAAkB,WAAA,wBACjB,sBAAA,4BACpB,gBAAA,CAAiB,YAAA,EAAc,aAAA,IACjC,0BAAA,CAA2B,YAAA,EAAc,aAAA;;;;;;;;UAS1B,YAAA,uBACO,sBAAA,+CACD,eAAA,GAAkB,WAAA;EChKzB;;;;EDsKd,KAAA,EAAO,kBAAA,CAAmB,WAAA,CAAY,aAAA;ECpKhB;;;;;;;;ED8KtB,OAAA,GAAU,KAAA,EAAO,cAAA,CAAe,YAAA,MAAkB,OAAA,CAAQ,WAAA,CAAY,aAAA;EC1KzD;;;;EDgLb,KAAA;AAAA;;;;AAlTF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmBA;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA;;;;;;;;;;;;;AAoCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCqDgB,SAAA,sBACO,eAAA,GAAkB,WAAA,wBACjB,sBAAA,yBAAA,CAEtB,MAAA,EAAQ,YAAA,CAAa,YAAA,EAAc,aAAA,GACnC,IAAA,GAAO,cAAA,GACN,YAAA,CAAa,aAAA,EAAe,YAAA"}
|