@mcp-b/webmcp-types 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/README.md +127 -202
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,34 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
Strict TypeScript type definitions for the WebMCP core API (`navigator.modelContext`).
|
|
4
4
|
|
|
5
|
-
Zero
|
|
5
|
+
Zero runtime. Zero side effects. Just `.d.ts` types.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Type Safety First
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
9
|
+
This package is the type-safety source of truth for WebMCP.
|
|
10
|
+
|
|
11
|
+
- Infer tool input args from literal `inputSchema`
|
|
12
|
+
- Infer `structuredContent` from literal `outputSchema`
|
|
13
|
+
- Keep safe fallbacks (`Record<string, unknown>`) when schemas are widened/runtime-defined
|
|
14
|
+
- Provide name-aware typed registries with `TypedModelContext`
|
|
15
|
+
|
|
16
|
+
## Why This Package
|
|
17
|
+
|
|
18
|
+
- Global `Navigator` augmentation for `navigator.modelContext`
|
|
19
|
+
- Strongly typed tool descriptors and tool responses
|
|
20
|
+
- Literal JSON Schema inference for tool args and `structuredContent`
|
|
21
|
+
- Name-aware helper types for typed tool registries
|
|
22
|
+
- Runtime-agnostic: works with native implementations, polyfills, or adapters
|
|
23
|
+
|
|
24
|
+
## Package Selection
|
|
25
|
+
|
|
26
|
+
| Package | Use When |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `@mcp-b/webmcp-types` | You only need compile-time types |
|
|
29
|
+
| `@mcp-b/webmcp-polyfill` | You need strict WebMCP core runtime behavior |
|
|
30
|
+
| `@mcp-b/global` | You want core + MCPB bridge extensions (`callTool`, prompts, resources, etc.) |
|
|
16
31
|
|
|
17
32
|
## Install
|
|
18
33
|
|
|
19
34
|
```bash
|
|
20
|
-
npm install --save-dev @mcp-b/webmcp-types
|
|
21
|
-
# or
|
|
22
35
|
pnpm add -D @mcp-b/webmcp-types
|
|
36
|
+
# or
|
|
37
|
+
npm install --save-dev @mcp-b/webmcp-types
|
|
23
38
|
```
|
|
24
39
|
|
|
25
|
-
If your published library exposes
|
|
26
|
-
|
|
27
|
-
## Usage
|
|
40
|
+
If your published library exposes these types in its public declarations, install as a production dependency instead of a dev dependency.
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
## Activate Global Types
|
|
30
43
|
|
|
31
|
-
TypeScript
|
|
32
|
-
Use one of the following activation methods:
|
|
44
|
+
TypeScript may not automatically include global declarations from npm packages. Use one of these:
|
|
33
45
|
|
|
34
46
|
1. Add to `tsconfig.json`:
|
|
35
47
|
|
|
@@ -43,145 +55,19 @@ Use one of the following activation methods:
|
|
|
43
55
|
|
|
44
56
|
2. Add a triple-slash reference in a global `.d.ts` file:
|
|
45
57
|
|
|
46
|
-
```
|
|
58
|
+
```ts
|
|
47
59
|
/// <reference types="@mcp-b/webmcp-types" />
|
|
48
60
|
```
|
|
49
61
|
|
|
50
|
-
3. Add a type-only import
|
|
62
|
+
3. Add a type-only import:
|
|
51
63
|
|
|
52
|
-
```
|
|
64
|
+
```ts
|
|
53
65
|
import type {} from '@mcp-b/webmcp-types';
|
|
54
66
|
```
|
|
55
67
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
After activating the types, `navigator.modelContext` is available on `Navigator`:
|
|
59
|
-
|
|
60
|
-
```typescript
|
|
61
|
-
// No import needed - types are globally augmented
|
|
62
|
-
navigator.modelContext.registerTool({
|
|
63
|
-
name: 'search',
|
|
64
|
-
description: 'Search the web',
|
|
65
|
-
inputSchema: {
|
|
66
|
-
type: 'object',
|
|
67
|
-
properties: { query: { type: 'string' } },
|
|
68
|
-
required: ['query'],
|
|
69
|
-
},
|
|
70
|
-
execute: async ({ query }) => ({
|
|
71
|
-
content: [{ type: 'text', text: `Results for: ${query}` }],
|
|
72
|
-
}),
|
|
73
|
-
});
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Individual imports
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
import type {
|
|
80
|
-
ElicitationParams,
|
|
81
|
-
ElicitationResult,
|
|
82
|
-
InferArgsFromInputSchema,
|
|
83
|
-
JsonSchemaForInference,
|
|
84
|
-
LooseContentBlock,
|
|
85
|
-
MaybePromise,
|
|
86
|
-
ModelContext,
|
|
87
|
-
ModelContextClient,
|
|
88
|
-
ModelContextExtensions,
|
|
89
|
-
ToolExecutionContext,
|
|
90
|
-
ToolDescriptor,
|
|
91
|
-
ToolDescriptorFromSchema,
|
|
92
|
-
ToolResultFromOutputSchema,
|
|
93
|
-
TypedModelContext,
|
|
94
|
-
CallToolResult,
|
|
95
|
-
} from '@mcp-b/webmcp-types';
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### Sync or async execute handlers
|
|
99
|
-
|
|
100
|
-
`execute` can return a plain result or a `Promise`.
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
import type { CallToolResult, ToolDescriptor } from '@mcp-b/webmcp-types';
|
|
104
|
-
|
|
105
|
-
const syncTool: ToolDescriptor<{ message: string }, CallToolResult, 'sync_echo'> = {
|
|
106
|
-
name: 'sync_echo',
|
|
107
|
-
description: 'Synchronous echo',
|
|
108
|
-
inputSchema: {
|
|
109
|
-
type: 'object',
|
|
110
|
-
properties: { message: { type: 'string' } },
|
|
111
|
-
required: ['message'],
|
|
112
|
-
},
|
|
113
|
-
execute(args) {
|
|
114
|
-
return {
|
|
115
|
-
content: [{ type: 'text', text: args.message }],
|
|
116
|
-
};
|
|
117
|
-
},
|
|
118
|
-
};
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
### Strict and loose content blocks
|
|
122
|
-
|
|
123
|
-
`CallToolResult.content` accepts strict MCP content blocks and pragmatic loose objects.
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
import type { CallToolResult } from '@mcp-b/webmcp-types';
|
|
127
|
-
|
|
128
|
-
const result: CallToolResult = {
|
|
129
|
-
content: [
|
|
130
|
-
{ type: 'text', text: 'strict block' },
|
|
131
|
-
{ text: 'loose block', data: 'opaque payload' },
|
|
132
|
-
],
|
|
133
|
-
};
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Typed tool descriptors
|
|
137
|
-
|
|
138
|
-
```typescript
|
|
139
|
-
import type { ToolDescriptor } from '@mcp-b/webmcp-types';
|
|
140
|
-
|
|
141
|
-
type SearchArgs = {
|
|
142
|
-
query: string;
|
|
143
|
-
limit?: number;
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
const searchTool: ToolDescriptor<SearchArgs> = {
|
|
147
|
-
name: 'search',
|
|
148
|
-
description: 'Search indexed docs',
|
|
149
|
-
inputSchema: {
|
|
150
|
-
type: 'object',
|
|
151
|
-
properties: {
|
|
152
|
-
query: { type: 'string' },
|
|
153
|
-
limit: { type: 'number' },
|
|
154
|
-
},
|
|
155
|
-
required: ['query'],
|
|
156
|
-
},
|
|
157
|
-
execute: async ({ query, limit }, context) => {
|
|
158
|
-
const approval = await context.requestUserInteraction(async () => ({
|
|
159
|
-
confirmed: true,
|
|
160
|
-
}));
|
|
161
|
-
|
|
162
|
-
if (
|
|
163
|
-
typeof approval !== 'object' ||
|
|
164
|
-
!approval ||
|
|
165
|
-
!('confirmed' in approval) ||
|
|
166
|
-
!approval.confirmed
|
|
167
|
-
) {
|
|
168
|
-
return {
|
|
169
|
-
content: [{ type: 'text', text: 'Search cancelled by user.' }],
|
|
170
|
-
};
|
|
171
|
-
}
|
|
68
|
+
## Quick Start
|
|
172
69
|
|
|
173
|
-
|
|
174
|
-
content: [{ type: 'text', text: `Searching for "${query}" (limit: ${limit ?? 10})` }],
|
|
175
|
-
};
|
|
176
|
-
},
|
|
177
|
-
};
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Pure JSON Schema inference (input + output)
|
|
181
|
-
|
|
182
|
-
Inference focuses on core keywords (`type`, `properties`, `required`, `items`, `enum`, `const`) and tolerates additional schema metadata.
|
|
183
|
-
|
|
184
|
-
```typescript
|
|
70
|
+
```ts
|
|
185
71
|
import type { JsonSchemaForInference } from '@mcp-b/webmcp-types';
|
|
186
72
|
|
|
187
73
|
const inputSchema = {
|
|
@@ -198,10 +84,7 @@ const outputSchema = {
|
|
|
198
84
|
type: 'object',
|
|
199
85
|
properties: {
|
|
200
86
|
total: { type: 'integer' },
|
|
201
|
-
items: {
|
|
202
|
-
type: 'array',
|
|
203
|
-
items: { type: 'string' },
|
|
204
|
-
},
|
|
87
|
+
items: { type: 'array', items: { type: 'string' } },
|
|
205
88
|
},
|
|
206
89
|
required: ['total'],
|
|
207
90
|
additionalProperties: false,
|
|
@@ -213,13 +96,11 @@ navigator.modelContext.registerTool({
|
|
|
213
96
|
inputSchema,
|
|
214
97
|
outputSchema,
|
|
215
98
|
async execute(args) {
|
|
216
|
-
// args is inferred as:
|
|
217
|
-
// { query: string; limit?: number }
|
|
99
|
+
// args is inferred as: { query: string; limit?: number }
|
|
218
100
|
return {
|
|
219
101
|
content: [{ type: 'text', text: `Searching for ${args.query}` }],
|
|
220
|
-
// structuredContent is inferred from outputSchema as:
|
|
221
|
-
// { total: number; items?: string[] }
|
|
222
102
|
structuredContent: {
|
|
103
|
+
// inferred from outputSchema
|
|
223
104
|
total: 1,
|
|
224
105
|
items: [args.query],
|
|
225
106
|
},
|
|
@@ -228,79 +109,123 @@ navigator.modelContext.registerTool({
|
|
|
228
109
|
});
|
|
229
110
|
```
|
|
230
111
|
|
|
231
|
-
|
|
112
|
+
## Strict Type Inference Deep Dive
|
|
232
113
|
|
|
233
|
-
###
|
|
114
|
+
### 1. Inference works best with literal schemas
|
|
234
115
|
|
|
235
|
-
|
|
236
|
-
import type { ModelContextExtensions } from '@mcp-b/webmcp-types';
|
|
237
|
-
|
|
238
|
-
const modelContext = navigator.modelContext as Navigator['modelContext'] & ModelContextExtensions;
|
|
116
|
+
Use `as const satisfies JsonSchemaForInference` so TypeScript preserves literal schema information.
|
|
239
117
|
|
|
240
|
-
|
|
241
|
-
name: 'deploy',
|
|
242
|
-
description: 'Deploy current build',
|
|
243
|
-
inputSchema: {
|
|
244
|
-
type: 'object',
|
|
245
|
-
properties: {
|
|
246
|
-
environment: { type: 'string' },
|
|
247
|
-
},
|
|
248
|
-
required: ['environment'],
|
|
249
|
-
},
|
|
250
|
-
async execute({ environment }, context) {
|
|
251
|
-
const confirmation = await context.requestUserInteraction(async () => ({
|
|
252
|
-
action: 'accept',
|
|
253
|
-
content: { confirm: true },
|
|
254
|
-
}));
|
|
255
|
-
|
|
256
|
-
if (confirmation.action !== 'accept' || !confirmation.content?.confirm) {
|
|
257
|
-
return {
|
|
258
|
-
content: [{ type: 'text', text: 'Deployment cancelled.' }],
|
|
259
|
-
};
|
|
260
|
-
}
|
|
118
|
+
If schema types are widened (for example `InputSchema` loaded at runtime), inference intentionally falls back to:
|
|
261
119
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
};
|
|
265
|
-
},
|
|
266
|
-
};
|
|
120
|
+
```ts
|
|
121
|
+
Record<string, unknown>
|
|
267
122
|
```
|
|
268
123
|
|
|
269
|
-
###
|
|
124
|
+
### 2. Input inference rules
|
|
125
|
+
|
|
126
|
+
`InferArgsFromInputSchema<T>` and schema-driven `registerTool(...)` inference use a focused subset:
|
|
127
|
+
|
|
128
|
+
- `type`
|
|
129
|
+
- `properties`
|
|
130
|
+
- `required`
|
|
131
|
+
- `items`
|
|
132
|
+
- `enum`
|
|
133
|
+
- `const`
|
|
134
|
+
- `nullable`
|
|
135
|
+
- `additionalProperties`
|
|
136
|
+
|
|
137
|
+
Other schema keywords are accepted as metadata but do not add new inferred structure.
|
|
138
|
+
|
|
139
|
+
### 3. `additionalProperties` behavior
|
|
140
|
+
|
|
141
|
+
| Schema shape | Inferred extras |
|
|
142
|
+
| --- | --- |
|
|
143
|
+
| `additionalProperties: false` | No extra keys |
|
|
144
|
+
| `additionalProperties` omitted/`true` | Extra keys allowed as `unknown` |
|
|
145
|
+
| `additionalProperties: { ... }` with no named `properties` | Map-like `Record<string, ...>` |
|
|
146
|
+
| `additionalProperties: { ... }` with named `properties` | Named properties inferred, extras remain `unknown` |
|
|
147
|
+
|
|
148
|
+
### 4. Required keys depend on literal `required`
|
|
270
149
|
|
|
271
|
-
|
|
150
|
+
If `required` is widened (for example a runtime `string[]`), fields are treated as optional by design.
|
|
151
|
+
|
|
152
|
+
### 5. Output inference from `outputSchema`
|
|
153
|
+
|
|
154
|
+
When `outputSchema` is a literal object schema, `structuredContent` is inferred automatically via `ToolResultFromOutputSchema`.
|
|
155
|
+
|
|
156
|
+
This catches enum/type mismatches at compile time.
|
|
157
|
+
|
|
158
|
+
### 6. Explicit typing is still available
|
|
159
|
+
|
|
160
|
+
You can always provide explicit generic args/results with `ToolDescriptor<TArgs, TResult, TName>` when schema inference is not enough for your use case.
|
|
161
|
+
|
|
162
|
+
## Name-Aware Typed Context (Advanced)
|
|
163
|
+
|
|
164
|
+
`TypedModelContext<TTools>` gives literal-name-aware `callTool(...)` typing for known registries.
|
|
165
|
+
|
|
166
|
+
```ts
|
|
272
167
|
import type { CallToolResult, ToolDescriptor, TypedModelContext } from '@mcp-b/webmcp-types';
|
|
273
168
|
|
|
274
169
|
type SearchTool = ToolDescriptor<
|
|
275
|
-
{ query: string },
|
|
170
|
+
{ query: string; limit?: number },
|
|
276
171
|
CallToolResult & { structuredContent: { total: number } },
|
|
277
172
|
'search'
|
|
278
173
|
>;
|
|
279
174
|
|
|
280
175
|
type PingTool = ToolDescriptor<Record<string, never>, CallToolResult, 'ping'>;
|
|
281
|
-
|
|
282
176
|
type AppModelContext = TypedModelContext<readonly [SearchTool, PingTool]>;
|
|
177
|
+
|
|
283
178
|
declare const modelContext: AppModelContext;
|
|
284
179
|
|
|
285
|
-
|
|
180
|
+
await modelContext.callTool({
|
|
286
181
|
name: 'search',
|
|
287
182
|
arguments: { query: 'webmcp' },
|
|
288
183
|
});
|
|
289
|
-
// searchResult is inferred from the 'search' tool result type.
|
|
290
184
|
|
|
291
185
|
await modelContext.callTool({ name: 'ping' });
|
|
292
|
-
//
|
|
186
|
+
// arguments are optional for Record<string, never> tools
|
|
293
187
|
```
|
|
294
188
|
|
|
295
|
-
##
|
|
189
|
+
## Core and Extension Surfaces
|
|
296
190
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
191
|
+
`Navigator['modelContext']` is typed as strict core WebMCP methods only.
|
|
192
|
+
|
|
193
|
+
Extension methods are available via `ModelContextExtensions` and `ModelContextWithExtensions`:
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import type { ModelContextExtensions } from '@mcp-b/webmcp-types';
|
|
197
|
+
|
|
198
|
+
const modelContext = navigator.modelContext as Navigator['modelContext'] & ModelContextExtensions;
|
|
199
|
+
const tools = modelContext.listTools();
|
|
200
|
+
const result = await modelContext.callTool({
|
|
201
|
+
name: 'search',
|
|
202
|
+
arguments: { query: 'docs' },
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
void tools;
|
|
206
|
+
void result;
|
|
207
|
+
```
|
|
302
208
|
|
|
303
|
-
|
|
209
|
+
## Commonly Used Exports
|
|
210
|
+
|
|
211
|
+
| Export | Purpose |
|
|
212
|
+
| --- | --- |
|
|
213
|
+
| `ModelContext` | Strict core `navigator.modelContext` type |
|
|
214
|
+
| `ToolDescriptor` | Explicitly typed tool descriptor |
|
|
215
|
+
| `ToolDescriptorFromSchema` | Schema-driven descriptor with inferred args/result |
|
|
216
|
+
| `JsonSchemaForInference` | Supported JSON Schema subset for inference |
|
|
217
|
+
| `InferArgsFromInputSchema` | Derive args shape from a schema type |
|
|
218
|
+
| `ToolResultFromOutputSchema` | Derive `structuredContent` type from output schema |
|
|
219
|
+
| `TypedModelContext` | Name-aware typed `callTool`/`listTools` for known registries |
|
|
220
|
+
| `CallToolResult` | Tool response type |
|
|
221
|
+
| `ContentBlock` / `LooseContentBlock` | Strict and pragmatic content block typing |
|
|
222
|
+
| `ModelContextClient` | Tool execution client (`requestUserInteraction`) |
|
|
223
|
+
|
|
224
|
+
## Important Notes
|
|
225
|
+
|
|
226
|
+
- This package does not install any runtime behavior.
|
|
227
|
+
- Runtime validation/execution behavior depends on your WebMCP runtime package.
|
|
228
|
+
- `navigator.modelContextTesting` is typed as optional for compatibility with Chromium preview/testing surfaces.
|
|
304
229
|
|
|
305
230
|
## License
|
|
306
231
|
|