@mcp-b/webmcp-ts-sdk 0.0.0-beta-20260216200013

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 mcp-b contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,246 @@
1
+ # @mcp-b/webmcp-ts-sdk
2
+
3
+ > Browser-adapted MCP TypeScript SDK - Dynamic tool registration for AI agents like Claude, ChatGPT, and Gemini
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@mcp-b/webmcp-ts-sdk?style=flat-square)](https://www.npmjs.com/package/@mcp-b/webmcp-ts-sdk)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@mcp-b/webmcp-ts-sdk?style=flat-square)](https://www.npmjs.com/package/@mcp-b/webmcp-ts-sdk)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue?style=flat-square)](https://www.typescriptlang.org/)
9
+ [![Minimal Code](https://img.shields.io/badge/Custom_Code-~50_lines-green?style=flat-square)](https://github.com/WebMCP-org/npm-packages)
10
+
11
+ **[Full Documentation](https://docs.mcp-b.ai/packages/webmcp-ts-sdk)** | **[Quick Start](https://docs.mcp-b.ai/quickstart)**
12
+
13
+ **@mcp-b/webmcp-ts-sdk** adapts the official MCP TypeScript SDK for browser environments, enabling dynamic tool registration required by the W3C Web Model Context API. This allows AI agents like Claude, ChatGPT, Gemini, Cursor, and Copilot to interact with browser-based applications.
14
+
15
+ ## Why Use @mcp-b/webmcp-ts-sdk?
16
+
17
+ | Feature | Benefit |
18
+ |---------|---------|
19
+ | **Dynamic Tool Registration** | Register tools after transport connection - required for browser apps |
20
+ | **Minimal Overhead** | Only ~50 lines of custom code on top of official SDK |
21
+ | **Full SDK Compatibility** | Re-exports all types, classes, and utilities from official SDK |
22
+ | **Type-Safe** | No prototype hacks - clean TypeScript extension |
23
+ | **Auto-Updates** | Types and protocol follow official SDK automatically |
24
+
25
+ ## Overview
26
+
27
+ This package adapts the official [@modelcontextprotocol/sdk](https://www.npmjs.com/package/@modelcontextprotocol/sdk) for browser environments with modifications to support dynamic tool registration required by the [W3C Web Model Context API](https://github.com/nicolo-ribaudo/model-context-protocol-api) (`window.navigator.modelContext`).
28
+
29
+ ## Why This Package Exists
30
+
31
+ The official MCP TypeScript SDK has a restriction that prevents registering server capabilities (like tools) after a transport connection is established. This is enforced by this check in the `Server` class:
32
+
33
+ ```typescript
34
+ public registerCapabilities(capabilities: ServerCapabilities): void {
35
+ if (this.transport) {
36
+ throw new Error('Cannot register capabilities after connecting to transport');
37
+ }
38
+ ...
39
+ }
40
+ ```
41
+
42
+ For the Web Model Context API, this restriction is incompatible because:
43
+
44
+ 1. **Tools arrive dynamically** - Web pages call `window.navigator.modelContext.provideContext({ tools: [...] })` at any time
45
+ 2. **Transport must be ready immediately** - The MCP server/transport needs to be connected when the page loads
46
+ 3. **Asynchronous registration** - Tools are registered as the page's JavaScript executes, potentially long after initialization
47
+
48
+ This package solves the problem by **pre-registering tool capabilities** before the transport connects, allowing dynamic tool registration to work seamlessly.
49
+
50
+ ## Modifications from Official SDK
51
+
52
+ ### BrowserMcpServer Class
53
+
54
+ The `BrowserMcpServer` extends `McpServer` with these changes:
55
+
56
+ ```typescript
57
+ export class BrowserMcpServer extends BaseMcpServer {
58
+ constructor(serverInfo, options?) {
59
+ // Pre-register tool capabilities in constructor
60
+ const enhancedOptions = {
61
+ ...options,
62
+ capabilities: mergeCapabilities(options?.capabilities || {}, {
63
+ tools: { listChanged: true }
64
+ })
65
+ };
66
+ super(serverInfo, enhancedOptions);
67
+ }
68
+
69
+ async connect(transport: Transport) {
70
+ // Ensure capabilities are set before connecting
71
+ // This bypasses the "cannot register after connect" restriction
72
+ return super.connect(transport);
73
+ }
74
+ }
75
+ ```
76
+
77
+ **Key Difference**: Capabilities are registered **before** connecting, allowing tools to be added dynamically afterward.
78
+
79
+ ## What's Re-Exported
80
+
81
+ This package re-exports almost everything from the official SDK:
82
+
83
+ ### Types
84
+ - All MCP protocol types (`Tool`, `Resource`, `Prompt`, etc.)
85
+ - Request/response schemas
86
+ - Client and server capabilities
87
+ - Error codes and constants
88
+
89
+ ### Classes
90
+ - `Server` - Base server class (unchanged)
91
+ - `McpServer` - Aliased to `BrowserMcpServer` with our modifications
92
+
93
+ ### Utilities
94
+ - `Transport` interface
95
+ - `mergeCapabilities` helper
96
+ - Protocol version constants
97
+
98
+ ## Installation
99
+
100
+ ```bash
101
+ npm install @mcp-b/webmcp-ts-sdk
102
+ # or
103
+ pnpm add @mcp-b/webmcp-ts-sdk
104
+ ```
105
+
106
+ ## Usage
107
+
108
+ Use it exactly like the official SDK:
109
+
110
+ ```typescript
111
+ import { McpServer } from '@mcp-b/webmcp-ts-sdk';
112
+ import { TabServerTransport } from '@mcp-b/transports';
113
+
114
+ const server = new McpServer({
115
+ name: 'my-web-app',
116
+ version: '1.0.0'
117
+ });
118
+
119
+ // Connect transport first
120
+ const transport = new TabServerTransport({ allowedOrigins: ['*'] });
121
+ await server.connect(transport);
122
+
123
+ // Now you can register tools dynamically (this would fail with official SDK)
124
+ server.registerTool('my-tool', {
125
+ description: 'A dynamically registered tool',
126
+ inputSchema: { message: z.string() },
127
+ // Output schemas enable structured, type-safe AI responses
128
+ outputSchema: { result: z.string() }
129
+ }, async ({ message }) => {
130
+ return {
131
+ content: [{ type: 'text', text: `Echo: ${message}` }],
132
+ // structuredContent must match the outputSchema
133
+ structuredContent: { result: `Echo: ${message}` }
134
+ };
135
+ });
136
+
137
+ // Example with complex output schema
138
+ server.registerTool('analyze-data', {
139
+ description: 'Analyze data and return structured results',
140
+ inputSchema: {
141
+ data: z.array(z.number()),
142
+ operation: z.enum(['sum', 'average', 'stats'])
143
+ },
144
+ outputSchema: {
145
+ result: z.number(),
146
+ operation: z.string(),
147
+ metadata: z.object({
148
+ count: z.number(),
149
+ min: z.number().optional(),
150
+ max: z.number().optional()
151
+ })
152
+ }
153
+ }, async ({ data, operation }) => {
154
+ const stats = calculateStats(data, operation);
155
+ return {
156
+ content: [{ type: 'text', text: `Result: ${stats.result}` }],
157
+ structuredContent: stats
158
+ };
159
+ });
160
+ ```
161
+
162
+ ## Architecture
163
+
164
+ ```
165
+ ┌─────────────────────────────────┐
166
+ │ @mcp-b/webmcp-ts-sdk │
167
+ │ │
168
+ │ ┌───────────────────────────┐ │
169
+ │ │ BrowserMcpServer │ │
170
+ │ │ (Modified behavior) │ │
171
+ │ └───────────┬───────────────┘ │
172
+ │ │ extends │
173
+ │ ▼ │
174
+ │ ┌───────────────────────────┐ │
175
+ │ │ @modelcontextprotocol/sdk │ │
176
+ │ │ (Official SDK) │ │
177
+ │ │ - Types │ │
178
+ │ │ - Protocol │ │
179
+ │ │ - Validation │ │
180
+ │ └───────────────────────────┘ │
181
+ └─────────────────────────────────┘
182
+ ```
183
+
184
+ ## Maintenance Strategy
185
+
186
+ This package is designed for **minimal maintenance**:
187
+
188
+ - **~50 lines** of custom code
189
+ - **Automatic updates** for types, protocol, validation via official SDK dependency
190
+ - **Single modification point** - only capability registration behavior
191
+ - **Type-safe** - no prototype hacks or unsafe casts
192
+
193
+ ### Syncing with Upstream
194
+
195
+ When the official SDK updates:
196
+
197
+ 1. Update the catalog version in `pnpm-workspace.yaml`
198
+ 2. Run `pnpm install` to get latest SDK
199
+ 3. Test that capability registration still works
200
+ 4. Update this README if SDK behavior changes
201
+
202
+ The modification is minimal and unlikely to conflict with upstream changes.
203
+
204
+ ## Frequently Asked Questions
205
+
206
+ ### Why can't I use the official SDK directly?
207
+
208
+ The official SDK throws an error if you try to register tools after connecting a transport. Browsers need dynamic registration because tools arrive asynchronously as the page loads.
209
+
210
+ ### Is this a fork of the official SDK?
211
+
212
+ No - it's a thin adapter (~50 lines) that extends the official SDK. All types, protocol handling, and validation come from the upstream package.
213
+
214
+ ### Will this break when the official SDK updates?
215
+
216
+ Unlikely. The modification is minimal and isolated. When upstream updates, just update your dependencies - the wrapper adapts automatically.
217
+
218
+ ### When should I use this vs `@mcp-b/global`?
219
+
220
+ Use `@mcp-b/global` for the standard `navigator.modelContext` API. Use this package directly only if you need low-level control over the MCP server.
221
+
222
+ ## Related Packages
223
+
224
+ - [`@mcp-b/global`](https://docs.mcp-b.ai/packages/global) - W3C Web Model Context API polyfill (uses this package internally)
225
+ - [`@mcp-b/transports`](https://docs.mcp-b.ai/packages/transports) - Browser-specific MCP transports
226
+ - [`@mcp-b/react-webmcp`](https://docs.mcp-b.ai/packages/react-webmcp) - React hooks for MCP
227
+ - [`@mcp-b/chrome-devtools-mcp`](https://docs.mcp-b.ai/packages/chrome-devtools-mcp) - Connect desktop AI agents to browser tools
228
+ - [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) - Official MCP SDK
229
+
230
+ ## Resources
231
+
232
+ - [WebMCP Documentation](https://docs.mcp-b.ai)
233
+ - [Web Model Context API Explainer](https://github.com/nicolo-ribaudo/model-context-protocol-api)
234
+ - [Model Context Protocol Spec](https://modelcontextprotocol.io/)
235
+ - [Official MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
236
+ - [MCP GitHub Repository](https://github.com/modelcontextprotocol)
237
+
238
+ ## License
239
+
240
+ MIT - see [LICENSE](../../LICENSE) for details
241
+
242
+ ## Support
243
+
244
+ - [GitHub Issues](https://github.com/WebMCP-org/npm-packages/issues)
245
+ - [Documentation](https://docs.mcp-b.ai)
246
+ - [Discord Community](https://discord.gg/a9fBR6Bw)
@@ -0,0 +1,202 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { Server, ServerOptions } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { RequestOptions, RequestOptions as RequestOptions$1, mergeCapabilities } from "@modelcontextprotocol/sdk/shared/protocol.js";
4
+ import { ReadBuffer, serializeMessage } from "@modelcontextprotocol/sdk/shared/stdio.js";
5
+ import { CallToolRequest, CallToolRequestSchema, CallToolResult, CallToolResultSchema, ClientCapabilities, ClientNotification, ClientRequest, ClientResult, CreateMessageRequest, CreateMessageRequest as CreateMessageRequest$1, CreateMessageRequestSchema, CreateMessageResult, CreateMessageResult as CreateMessageResult$1, CreateMessageResultSchema, ElicitRequest, ElicitRequest as ElicitRequest$1, ElicitRequestSchema, ElicitResult, ElicitResult as ElicitResult$1, ElicitResultSchema, ErrorCode, GetPromptRequest, GetPromptRequestSchema, GetPromptResult, GetPromptResultSchema, Implementation, Implementation as Implementation$1, InitializeRequest, InitializeRequestSchema, InitializeResult, InitializeResultSchema, JSONRPCMessage, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, ListPromptsRequest, ListPromptsRequestSchema, ListPromptsResult, ListPromptsResultSchema, ListResourcesRequest, ListResourcesRequestSchema, ListResourcesResult, ListResourcesResultSchema, ListToolsRequest, ListToolsRequestSchema, ListToolsResult, ListToolsResultSchema, LoggingLevel, LoggingLevelSchema, LoggingMessageNotification, McpError, Notification, Prompt, PromptMessage, PromptMessage as PromptMessage$1, ReadResourceRequest, ReadResourceRequestSchema, ReadResourceResult, ReadResourceResultSchema, Request, Resource, ResourceContents, ResourceListChangedNotificationSchema, ResourceTemplate, Result, SUPPORTED_PROTOCOL_VERSIONS, ServerCapabilities, ServerNotification, ServerRequest, ServerResult, Tool, ToolAnnotations, ToolListChangedNotificationSchema } from "@modelcontextprotocol/sdk/types.js";
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import { InputSchema, ModelContextCore, ModelContextOptions, ResourceContents as ResourceContents$1, ToolDescriptor, ToolListItem, ToolResponse } from "@mcp-b/webmcp-types";
8
+ import { Transport, Transport as Transport$1, TransportSendOptions } from "@modelcontextprotocol/sdk/shared/transport.js";
9
+
10
+ //#region src/browser-server.d.ts
11
+ interface BrowserMcpServerOptions extends ServerOptions {
12
+ native?: ModelContextCore;
13
+ }
14
+ /**
15
+ * Browser-optimized MCP Server that speaks WebMCP natively.
16
+ *
17
+ * This server IS navigator.modelContext — it implements the WebMCP standard API
18
+ * (provideContext, registerTool, unregisterTool, clearContext) while retaining
19
+ * full MCP protocol capabilities (resources, prompts, elicitation, sampling)
20
+ * via the inherited BaseMcpServer surface.
21
+ *
22
+ * When `native` is provided, all tool operations are mirrored to it so that
23
+ * navigator.modelContextTesting (polyfill testing shim) stays in sync.
24
+ */
25
+ declare class BrowserMcpServer extends McpServer {
26
+ private native;
27
+ constructor(serverInfo: Implementation$1, options?: BrowserMcpServerOptions);
28
+ private get _parentTools();
29
+ private get _parentResources();
30
+ private get _parentPrompts();
31
+ registerTool(tool: ToolDescriptor): {
32
+ unregister: () => void;
33
+ };
34
+ unregisterTool(name: string): void;
35
+ registerResource(descriptor: {
36
+ uri: string;
37
+ name: string;
38
+ description?: string;
39
+ mimeType?: string;
40
+ read: (uri: URL, params?: Record<string, string>) => Promise<{
41
+ contents: ResourceContents$1[];
42
+ }>;
43
+ }): {
44
+ unregister: () => void;
45
+ };
46
+ registerPrompt(descriptor: {
47
+ name: string;
48
+ description?: string;
49
+ argsSchema?: InputSchema;
50
+ get: (args: Record<string, unknown>) => Promise<{
51
+ messages: PromptMessage$1[];
52
+ }>;
53
+ }): {
54
+ unregister: () => void;
55
+ };
56
+ provideContext(options?: ModelContextOptions): void;
57
+ clearContext(): void;
58
+ listResources(): Array<{
59
+ uri: string;
60
+ name: string;
61
+ description?: string;
62
+ mimeType?: string;
63
+ }>;
64
+ readResource(uri: string): Promise<{
65
+ contents: ResourceContents$1[];
66
+ }>;
67
+ listPrompts(): Array<{
68
+ name: string;
69
+ description?: string;
70
+ arguments?: Array<{
71
+ name: string;
72
+ description?: string;
73
+ required?: boolean;
74
+ }>;
75
+ }>;
76
+ getPrompt(name: string, args?: Record<string, unknown>): Promise<{
77
+ messages: PromptMessage$1[];
78
+ }>;
79
+ listTools(): ToolListItem[];
80
+ callTool(params: {
81
+ name: string;
82
+ arguments?: Record<string, unknown>;
83
+ }): Promise<ToolResponse>;
84
+ executeTool(name: string, args?: Record<string, unknown>): Promise<ToolResponse>;
85
+ /**
86
+ * Override connect to initialize request handlers BEFORE the transport connection.
87
+ * This prevents "Cannot register capabilities after connecting to transport" errors
88
+ * when tools are registered dynamically after connection.
89
+ */
90
+ connect(transport: Transport$1): Promise<void>;
91
+ createMessage(params: CreateMessageRequest$1['params'], options?: RequestOptions$1): Promise<CreateMessageResult$1>;
92
+ elicitInput(params: ElicitRequest$1['params'], options?: RequestOptions$1): Promise<ElicitResult$1>;
93
+ }
94
+ interface ResourceDescriptor {
95
+ uri: string;
96
+ name: string;
97
+ description?: string;
98
+ mimeType?: string;
99
+ read: (uri: URL, params?: Record<string, string>) => Promise<{
100
+ contents: ResourceContents$1[];
101
+ }>;
102
+ }
103
+ interface PromptDescriptor {
104
+ name: string;
105
+ description?: string;
106
+ argsSchema?: InputSchema;
107
+ get: (args: Record<string, unknown>) => Promise<{
108
+ messages: PromptMessage$1[];
109
+ }>;
110
+ }
111
+ //#endregion
112
+ //#region src/no-op-validator.d.ts
113
+ /**
114
+ * No-op JSON Schema validator for browser environments.
115
+ *
116
+ * This validator bypasses the MCP SDK's internal ajv-based validation which causes
117
+ * "Error compiling schema" errors in browser extensions due to ajv's use of
118
+ * eval/Function constructor.
119
+ *
120
+ * Validation is handled externally by Zod in @mcp-b/global, making the SDK's
121
+ * internal validation redundant. This no-op validator allows the SDK to function
122
+ * without the ajv dependency issues.
123
+ */
124
+ /**
125
+ * Interface for JSON Schema validators.
126
+ * This matches the MCP SDK's jsonSchemaValidator interface.
127
+ */
128
+ interface JsonSchemaValidator$1 {
129
+ getValidator<T>(schema: unknown): (input: unknown) => JsonSchemaValidatorResult$1<T>;
130
+ }
131
+ /**
132
+ * Result type for JSON Schema validation
133
+ */
134
+ type JsonSchemaValidatorResult$1<T> = {
135
+ valid: true;
136
+ data: T;
137
+ errorMessage: undefined;
138
+ } | {
139
+ valid: false;
140
+ data: undefined;
141
+ errorMessage: string;
142
+ };
143
+ /**
144
+ * A no-op JSON Schema validator that always returns valid.
145
+ *
146
+ * Use this in browser environments where:
147
+ * - ajv causes "Error compiling schema" errors
148
+ * - Validation is already handled elsewhere (e.g., by Zod)
149
+ * - You need to avoid eval/Function constructor restrictions
150
+ *
151
+ * @example
152
+ * ```typescript
153
+ * import { BrowserMcpServer } from '@mcp-b/webmcp-ts-sdk';
154
+ * import { NoOpJsonSchemaValidator } from '@mcp-b/webmcp-ts-sdk/no-op-validator';
155
+ *
156
+ * const server = new BrowserMcpServer(
157
+ * { name: 'my-server', version: '1.0.0' },
158
+ * { jsonSchemaValidator: new NoOpJsonSchemaValidator() }
159
+ * );
160
+ * ```
161
+ */
162
+ declare class NoOpJsonSchemaValidator implements JsonSchemaValidator$1 {
163
+ /**
164
+ * Returns a validator function that always passes.
165
+ * The input data is passed through unchanged.
166
+ *
167
+ * @param _schema - The JSON Schema (ignored)
168
+ * @returns A validator function that always returns valid
169
+ */
170
+ getValidator<T>(_schema: unknown): (input: unknown) => JsonSchemaValidatorResult$1<T>;
171
+ }
172
+ //#endregion
173
+ //#region src/polyfill-validator.d.ts
174
+ interface JsonSchemaValidator {
175
+ getValidator<T>(schema: unknown): (input: unknown) => JsonSchemaValidatorResult<T>;
176
+ }
177
+ type JsonSchemaValidatorResult<T> = {
178
+ valid: true;
179
+ data: T;
180
+ errorMessage: undefined;
181
+ } | {
182
+ valid: false;
183
+ data: undefined;
184
+ errorMessage: string;
185
+ };
186
+ declare class PolyfillJsonSchemaValidator implements JsonSchemaValidator {
187
+ getValidator<T>(schema: unknown): (input: unknown) => JsonSchemaValidatorResult<T>;
188
+ }
189
+ //#endregion
190
+ //#region src/index.d.ts
191
+ type SamplingRequestParams = CreateMessageRequest$1['params'];
192
+ type SamplingResult = CreateMessageResult$1;
193
+ declare global {
194
+ interface Navigator {
195
+ modelContext: BrowserMcpServer;
196
+ }
197
+ }
198
+ //# sourceMappingURL=index.d.ts.map
199
+
200
+ //#endregion
201
+ export { BrowserMcpServer, BrowserMcpServer as McpServer, type BrowserMcpServerOptions, type CallToolRequest, CallToolRequestSchema, type CallToolResult, CallToolResultSchema, Client, type ClientCapabilities, type ClientNotification, type ClientRequest, type ClientResult, type CreateMessageRequest, CreateMessageRequestSchema, type CreateMessageResult, CreateMessageResultSchema, type ElicitRequest, ElicitRequestSchema, type ElicitResult, ElicitResultSchema, ErrorCode, type GetPromptRequest, GetPromptRequestSchema, type GetPromptResult, GetPromptResultSchema, type Implementation, type InitializeRequest, InitializeRequestSchema, type InitializeResult, InitializeResultSchema, type JSONRPCMessage, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, type ListPromptsRequest, ListPromptsRequestSchema, type ListPromptsResult, ListPromptsResultSchema, type ListResourcesRequest, ListResourcesRequestSchema, type ListResourcesResult, ListResourcesResultSchema, type ListToolsRequest, ListToolsRequestSchema, type ListToolsResult, ListToolsResultSchema, type LoggingLevel, LoggingLevelSchema, type LoggingMessageNotification, type McpError, NoOpJsonSchemaValidator, type Notification, PolyfillJsonSchemaValidator, type Prompt, type PromptDescriptor, type PromptMessage, ReadBuffer, type ReadResourceRequest, ReadResourceRequestSchema, type ReadResourceResult, ReadResourceResultSchema, type Request, type RequestOptions, type Resource, type ResourceContents, type ResourceDescriptor, ResourceListChangedNotificationSchema, type ResourceTemplate, type Result, SUPPORTED_PROTOCOL_VERSIONS, SamplingRequestParams, SamplingResult, Server, type ServerCapabilities, type ServerNotification, type ServerRequest, type ServerResult, type Tool, type ToolAnnotations, ToolListChangedNotificationSchema, type Transport, type TransportSendOptions, mergeCapabilities, serializeMessage };
202
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/browser-server.ts","../src/no-op-validator.ts","../src/polyfill-validator.ts","../src/index.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,226 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { mergeCapabilities, mergeCapabilities as mergeCapabilities$1 } from "@modelcontextprotocol/sdk/shared/protocol.js";
4
+ import { ReadBuffer, serializeMessage } from "@modelcontextprotocol/sdk/shared/stdio.js";
5
+ import { CallToolRequestSchema, CallToolResultSchema, CreateMessageRequestSchema, CreateMessageResultSchema, ElicitRequestSchema, ElicitResultSchema, ErrorCode, GetPromptRequestSchema, GetPromptResultSchema, InitializeRequestSchema, InitializeResultSchema, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, ListPromptsRequestSchema, ListPromptsResultSchema, ListResourcesRequestSchema, ListResourcesResultSchema, ListToolsRequestSchema, ListToolsResultSchema, LoggingLevelSchema, ReadResourceRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, SUPPORTED_PROTOCOL_VERSIONS, ToolListChangedNotificationSchema } from "@modelcontextprotocol/sdk/types.js";
6
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ import { isPlainObject, validateArgsWithSchema } from "@mcp-b/webmcp-polyfill";
8
+
9
+ //#region src/polyfill-validator.ts
10
+ var PolyfillJsonSchemaValidator = class {
11
+ getValidator(schema) {
12
+ return (input) => {
13
+ if (!isPlainObject(input)) return {
14
+ valid: false,
15
+ data: void 0,
16
+ errorMessage: "expected object arguments"
17
+ };
18
+ const issue = validateArgsWithSchema(input, schema);
19
+ if (issue) return {
20
+ valid: false,
21
+ data: void 0,
22
+ errorMessage: issue.message
23
+ };
24
+ return {
25
+ valid: true,
26
+ data: input,
27
+ errorMessage: void 0
28
+ };
29
+ };
30
+ }
31
+ };
32
+
33
+ //#endregion
34
+ //#region src/browser-server.ts
35
+ const DEFAULT_INPUT_SCHEMA = {
36
+ type: "object",
37
+ properties: {}
38
+ };
39
+ /**
40
+ * Browser-optimized MCP Server that speaks WebMCP natively.
41
+ *
42
+ * This server IS navigator.modelContext — it implements the WebMCP standard API
43
+ * (provideContext, registerTool, unregisterTool, clearContext) while retaining
44
+ * full MCP protocol capabilities (resources, prompts, elicitation, sampling)
45
+ * via the inherited BaseMcpServer surface.
46
+ *
47
+ * When `native` is provided, all tool operations are mirrored to it so that
48
+ * navigator.modelContextTesting (polyfill testing shim) stays in sync.
49
+ */
50
+ var BrowserMcpServer = class extends McpServer {
51
+ native;
52
+ constructor(serverInfo, options) {
53
+ const enhancedOptions = {
54
+ capabilities: mergeCapabilities$1(options?.capabilities || {}, {
55
+ tools: { listChanged: true },
56
+ resources: { listChanged: true },
57
+ prompts: { listChanged: true }
58
+ }),
59
+ jsonSchemaValidator: options?.jsonSchemaValidator ?? new PolyfillJsonSchemaValidator()
60
+ };
61
+ super(serverInfo, enhancedOptions);
62
+ this.native = options?.native;
63
+ }
64
+ get _parentTools() {
65
+ return this._registeredTools;
66
+ }
67
+ get _parentResources() {
68
+ return this._registeredResources;
69
+ }
70
+ get _parentPrompts() {
71
+ return this._registeredPrompts;
72
+ }
73
+ registerTool(tool) {
74
+ if (this.native) this.native.registerTool(tool);
75
+ const inputSchema = tool.inputSchema ?? DEFAULT_INPUT_SCHEMA;
76
+ try {
77
+ super.registerTool(tool.name, {
78
+ description: tool.description,
79
+ inputSchema,
80
+ ...tool.outputSchema ? { outputSchema: tool.outputSchema } : {},
81
+ ...tool.annotations ? { annotations: tool.annotations } : {}
82
+ }, async (args) => {
83
+ return tool.execute(args, { requestUserInteraction: async (cb) => cb() });
84
+ });
85
+ return { unregister: () => this.unregisterTool(tool.name) };
86
+ } catch (error) {
87
+ if (this.native) try {
88
+ this.native.unregisterTool(tool.name);
89
+ } catch {}
90
+ throw error;
91
+ }
92
+ }
93
+ unregisterTool(name) {
94
+ this._parentTools[name]?.remove();
95
+ if (this.native) this.native.unregisterTool(name);
96
+ }
97
+ registerResource(descriptor) {
98
+ const registered = super.registerResource(descriptor.name, descriptor.uri, {
99
+ ...descriptor.description !== void 0 && { description: descriptor.description },
100
+ ...descriptor.mimeType !== void 0 && { mimeType: descriptor.mimeType }
101
+ }, async (uri) => ({ contents: (await descriptor.read(uri)).contents }));
102
+ return { unregister: () => registered.remove() };
103
+ }
104
+ registerPrompt(descriptor) {
105
+ const registered = super.registerPrompt(descriptor.name, {
106
+ ...descriptor.description !== void 0 && { description: descriptor.description },
107
+ ...descriptor.argsSchema !== void 0 && { argsSchema: descriptor.argsSchema }
108
+ }, async (args) => ({ messages: (await descriptor.get(args)).messages }));
109
+ return { unregister: () => registered.remove() };
110
+ }
111
+ provideContext(options) {
112
+ for (const tool of Object.values(this._parentTools)) tool.remove();
113
+ if (this.native) this.native.clearContext();
114
+ for (const tool of options?.tools ?? []) this.registerTool(tool);
115
+ }
116
+ clearContext() {
117
+ for (const tool of Object.values(this._parentTools)) tool.remove();
118
+ if (this.native) this.native.clearContext();
119
+ }
120
+ listResources() {
121
+ return Object.entries(this._parentResources).filter(([, resource]) => resource.enabled).map(([uri, resource]) => ({
122
+ uri,
123
+ name: resource.name,
124
+ ...resource.metadata
125
+ }));
126
+ }
127
+ async readResource(uri) {
128
+ const resource = this._parentResources[uri];
129
+ if (!resource) throw new Error(`Resource not found: ${uri}`);
130
+ return resource.readCallback(new URL(uri), {});
131
+ }
132
+ listPrompts() {
133
+ return Object.entries(this._parentPrompts).filter(([, prompt]) => prompt.enabled).map(([name, prompt]) => ({
134
+ name,
135
+ ...prompt.description !== void 0 && { description: prompt.description },
136
+ ...prompt.argsSchema ? { arguments: Object.entries(prompt.argsSchema ?? {}).map(([argName]) => ({ name: argName })) } : {}
137
+ }));
138
+ }
139
+ async getPrompt(name, args = {}) {
140
+ const prompt = this._parentPrompts[name];
141
+ if (!prompt) throw new Error(`Prompt not found: ${name}`);
142
+ return prompt.callback(args, {});
143
+ }
144
+ listTools() {
145
+ return Object.entries(this._parentTools).filter(([, tool]) => tool.enabled).map(([name, tool]) => {
146
+ const item = {
147
+ name,
148
+ description: tool.description ?? "",
149
+ inputSchema: tool.inputSchema ?? DEFAULT_INPUT_SCHEMA
150
+ };
151
+ if (tool.outputSchema) item.outputSchema = tool.outputSchema;
152
+ if (tool.annotations) item.annotations = tool.annotations;
153
+ return item;
154
+ });
155
+ }
156
+ async callTool(params) {
157
+ const tool = this._parentTools[params.name];
158
+ if (!tool) throw new Error(`Tool not found: ${params.name}`);
159
+ return tool.handler(params.arguments ?? {}, {});
160
+ }
161
+ async executeTool(name, args = {}) {
162
+ return this.callTool({
163
+ name,
164
+ arguments: args
165
+ });
166
+ }
167
+ /**
168
+ * Override connect to initialize request handlers BEFORE the transport connection.
169
+ * This prevents "Cannot register capabilities after connecting to transport" errors
170
+ * when tools are registered dynamically after connection.
171
+ */
172
+ async connect(transport) {
173
+ this.setToolRequestHandlers();
174
+ this.setResourceRequestHandlers();
175
+ this.setPromptRequestHandlers();
176
+ return super.connect(transport);
177
+ }
178
+ async createMessage(params, options) {
179
+ return this.server.createMessage(params, options);
180
+ }
181
+ async elicitInput(params, options) {
182
+ return this.server.elicitInput(params, options);
183
+ }
184
+ };
185
+
186
+ //#endregion
187
+ //#region src/no-op-validator.ts
188
+ /**
189
+ * A no-op JSON Schema validator that always returns valid.
190
+ *
191
+ * Use this in browser environments where:
192
+ * - ajv causes "Error compiling schema" errors
193
+ * - Validation is already handled elsewhere (e.g., by Zod)
194
+ * - You need to avoid eval/Function constructor restrictions
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * import { BrowserMcpServer } from '@mcp-b/webmcp-ts-sdk';
199
+ * import { NoOpJsonSchemaValidator } from '@mcp-b/webmcp-ts-sdk/no-op-validator';
200
+ *
201
+ * const server = new BrowserMcpServer(
202
+ * { name: 'my-server', version: '1.0.0' },
203
+ * { jsonSchemaValidator: new NoOpJsonSchemaValidator() }
204
+ * );
205
+ * ```
206
+ */
207
+ var NoOpJsonSchemaValidator = class {
208
+ /**
209
+ * Returns a validator function that always passes.
210
+ * The input data is passed through unchanged.
211
+ *
212
+ * @param _schema - The JSON Schema (ignored)
213
+ * @returns A validator function that always returns valid
214
+ */
215
+ getValidator(_schema) {
216
+ return (input) => ({
217
+ valid: true,
218
+ data: input,
219
+ errorMessage: void 0
220
+ });
221
+ }
222
+ };
223
+
224
+ //#endregion
225
+ export { BrowserMcpServer, BrowserMcpServer as McpServer, CallToolRequestSchema, CallToolResultSchema, Client, CreateMessageRequestSchema, CreateMessageResultSchema, ElicitRequestSchema, ElicitResultSchema, ErrorCode, GetPromptRequestSchema, GetPromptResultSchema, InitializeRequestSchema, InitializeResultSchema, JSONRPCMessageSchema, LATEST_PROTOCOL_VERSION, ListPromptsRequestSchema, ListPromptsResultSchema, ListResourcesRequestSchema, ListResourcesResultSchema, ListToolsRequestSchema, ListToolsResultSchema, LoggingLevelSchema, NoOpJsonSchemaValidator, PolyfillJsonSchemaValidator, ReadBuffer, ReadResourceRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, SUPPORTED_PROTOCOL_VERSIONS, Server, ToolListChangedNotificationSchema, mergeCapabilities, serializeMessage };
226
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["DEFAULT_INPUT_SCHEMA: InputSchema","BaseMcpServer","enhancedOptions: ServerOptions","mergeCapabilities","item: ToolListItem"],"sources":["../src/polyfill-validator.ts","../src/browser-server.ts","../src/no-op-validator.ts"],"sourcesContent":["import { isPlainObject, validateArgsWithSchema } from '@mcp-b/webmcp-polyfill';\nimport type { InputSchema } from '@mcp-b/webmcp-types';\n\ninterface JsonSchemaValidator {\n getValidator<T>(schema: unknown): (input: unknown) => JsonSchemaValidatorResult<T>;\n}\n\ntype JsonSchemaValidatorResult<T> =\n | { valid: true; data: T; errorMessage: undefined }\n | { valid: false; data: undefined; errorMessage: string };\n\nexport class PolyfillJsonSchemaValidator implements JsonSchemaValidator {\n getValidator<T>(schema: unknown): (input: unknown) => JsonSchemaValidatorResult<T> {\n return (input: unknown): JsonSchemaValidatorResult<T> => {\n if (!isPlainObject(input)) {\n return { valid: false, data: undefined, errorMessage: 'expected object arguments' };\n }\n\n const issue = validateArgsWithSchema(input, schema as InputSchema);\n if (issue) {\n return { valid: false, data: undefined, errorMessage: issue.message };\n }\n\n return { valid: true, data: input as T, errorMessage: undefined };\n };\n }\n}\n","import type {\n CallToolResult,\n InputSchema,\n ModelContextClient,\n ModelContextCore,\n ModelContextOptions,\n ResourceContents,\n ToolDescriptor,\n ToolListItem,\n ToolResponse,\n} from '@mcp-b/webmcp-types';\nimport type { ServerOptions } from '@modelcontextprotocol/sdk/server/index.js';\nimport { McpServer as BaseMcpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport { mergeCapabilities } from '@modelcontextprotocol/sdk/shared/protocol.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport type {\n CreateMessageRequest,\n CreateMessageResult,\n ElicitRequest,\n ElicitResult,\n Implementation,\n PromptMessage,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { PolyfillJsonSchemaValidator } from './polyfill-validator.js';\n\nconst DEFAULT_INPUT_SCHEMA: InputSchema = { type: 'object', properties: {} };\n\ninterface ParentRegisteredTool {\n description?: string;\n inputSchema?: unknown;\n outputSchema?: unknown;\n annotations?: unknown;\n handler: (args: Record<string, unknown>, extra: unknown) => Promise<CallToolResult>;\n enabled: boolean;\n remove: () => void;\n}\n\ninterface ParentRegisteredResource {\n name: string;\n metadata?: { description?: string; mimeType?: string; title?: string };\n readCallback: (uri: URL, extra: unknown) => Promise<{ contents: ResourceContents[] }>;\n enabled: boolean;\n remove: () => void;\n}\n\ninterface ParentRegisteredPrompt {\n title?: string;\n description?: string;\n argsSchema?: unknown;\n callback: (\n args: Record<string, unknown>,\n extra: unknown\n ) => Promise<{ messages: PromptMessage[] }>;\n enabled: boolean;\n remove: () => void;\n}\n\nexport interface BrowserMcpServerOptions extends ServerOptions {\n native?: ModelContextCore;\n}\n\ntype ParentRegisterToolFn = (\n name: string,\n config: Record<string, unknown>,\n cb: (args: Record<string, unknown>, extra: unknown) => Promise<CallToolResult>\n) => void;\n\n/**\n * Browser-optimized MCP Server that speaks WebMCP natively.\n *\n * This server IS navigator.modelContext — it implements the WebMCP standard API\n * (provideContext, registerTool, unregisterTool, clearContext) while retaining\n * full MCP protocol capabilities (resources, prompts, elicitation, sampling)\n * via the inherited BaseMcpServer surface.\n *\n * When `native` is provided, all tool operations are mirrored to it so that\n * navigator.modelContextTesting (polyfill testing shim) stays in sync.\n */\nexport class BrowserMcpServer extends BaseMcpServer {\n private native: ModelContextCore | undefined;\n\n constructor(serverInfo: Implementation, options?: BrowserMcpServerOptions) {\n const enhancedOptions: ServerOptions = {\n capabilities: mergeCapabilities(options?.capabilities || {}, {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n }),\n jsonSchemaValidator: options?.jsonSchemaValidator ?? new PolyfillJsonSchemaValidator(),\n };\n\n super(serverInfo, enhancedOptions);\n this.native = options?.native;\n }\n\n private get _parentTools(): Record<string, ParentRegisteredTool> {\n return (this as unknown as { _registeredTools: Record<string, ParentRegisteredTool> })\n ._registeredTools;\n }\n\n private get _parentResources(): Record<string, ParentRegisteredResource> {\n return (this as unknown as { _registeredResources: Record<string, ParentRegisteredResource> })\n ._registeredResources;\n }\n\n private get _parentPrompts(): Record<string, ParentRegisteredPrompt> {\n return (this as unknown as { _registeredPrompts: Record<string, ParentRegisteredPrompt> })\n ._registeredPrompts;\n }\n\n // --- WebMCP standard API (primary surface) ---\n\n // @ts-expect-error -- WebMCP API: (ToolDescriptor) vs MCP SDK: (name, config, cb)\n override registerTool(tool: ToolDescriptor): { unregister: () => void } {\n // Mirror to native first — the polyfill validates the descriptor\n if (this.native) {\n (this.native.registerTool as (tool: ToolDescriptor) => void)(tool);\n }\n\n const inputSchema = tool.inputSchema ?? DEFAULT_INPUT_SCHEMA;\n\n try {\n // Cast needed: parent expects Zod-compatible schemas, we pass JSON Schema objects\n (super.registerTool as unknown as ParentRegisterToolFn)(\n tool.name,\n {\n description: tool.description,\n inputSchema,\n ...(tool.outputSchema ? { outputSchema: tool.outputSchema } : {}),\n ...(tool.annotations ? { annotations: tool.annotations } : {}),\n },\n async (args: Record<string, unknown>) => {\n const client: ModelContextClient = {\n requestUserInteraction: async (cb: () => Promise<unknown>) => cb(),\n };\n return tool.execute(args, client);\n }\n );\n return {\n unregister: () => this.unregisterTool(tool.name),\n }\n } catch (error) {\n // Rollback native registration on server failure\n if (this.native) {\n try {\n this.native.unregisterTool(tool.name);\n } catch {\n // best-effort rollback\n }\n }\n throw error;\n }\n }\n\n unregisterTool(name: string): void {\n this._parentTools[name]?.remove();\n\n if (this.native) {\n this.native.unregisterTool(name);\n }\n }\n\n // @ts-expect-error -- WebMCP API: (descriptor) vs MCP SDK: (name, uri, config, readCallback)\n override registerResource(descriptor: {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n read: (uri: URL, params?: Record<string, string>) => Promise<{ contents: ResourceContents[] }>;\n }): { unregister: () => void } {\n const registered = (super.registerResource as Function)(\n descriptor.name,\n descriptor.uri,\n {\n ...(descriptor.description !== undefined && { description: descriptor.description }),\n ...(descriptor.mimeType !== undefined && { mimeType: descriptor.mimeType }),\n },\n async (uri: URL) => ({\n contents: (await descriptor.read(uri)).contents,\n })\n );\n\n return {\n unregister: () => registered.remove(),\n };\n }\n\n // @ts-expect-error -- WebMCP API: (descriptor) vs MCP SDK: (name, config, cb)\n override registerPrompt(descriptor: {\n name: string;\n description?: string;\n argsSchema?: InputSchema;\n get: (args: Record<string, unknown>) => Promise<{ messages: PromptMessage[] }>;\n }): { unregister: () => void } {\n const registered = (super.registerPrompt as Function)(\n descriptor.name,\n {\n ...(descriptor.description !== undefined && { description: descriptor.description }),\n ...(descriptor.argsSchema !== undefined && { argsSchema: descriptor.argsSchema }),\n },\n async (args: Record<string, unknown>) => ({\n messages: (await descriptor.get(args)).messages,\n })\n );\n\n return {\n unregister: () => registered.remove(),\n };\n }\n\n provideContext(options?: ModelContextOptions): void {\n for (const tool of Object.values(this._parentTools)) {\n tool.remove();\n }\n\n if (this.native) {\n this.native.clearContext();\n }\n\n for (const tool of options?.tools ?? []) {\n this.registerTool(tool);\n }\n }\n\n clearContext(): void {\n for (const tool of Object.values(this._parentTools)) {\n tool.remove();\n }\n\n if (this.native) {\n this.native.clearContext();\n }\n }\n\n // --- Extension methods ---\n\n listResources(): Array<{\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n }> {\n return Object.entries(this._parentResources)\n .filter(([, resource]) => resource.enabled)\n .map(([uri, resource]) => ({\n uri,\n name: resource.name,\n ...resource.metadata,\n }));\n }\n\n async readResource(uri: string): Promise<{ contents: ResourceContents[] }> {\n const resource = this._parentResources[uri];\n if (!resource) {\n throw new Error(`Resource not found: ${uri}`);\n }\n\n return resource.readCallback(new URL(uri), {});\n }\n\n listPrompts(): Array<{\n name: string;\n description?: string;\n arguments?: Array<{ name: string; description?: string; required?: boolean }>;\n }> {\n return Object.entries(this._parentPrompts)\n .filter(([, prompt]) => prompt.enabled)\n .map(([name, prompt]) => ({\n name,\n ...(prompt.description !== undefined && { description: prompt.description }),\n ...(prompt.argsSchema\n ? {\n arguments: Object.entries((prompt.argsSchema as Record<string, unknown>) ?? {}).map(\n ([argName]) => ({ name: argName })\n ),\n }\n : {}),\n }));\n }\n\n async getPrompt(\n name: string,\n args: Record<string, unknown> = {}\n ): Promise<{ messages: PromptMessage[] }> {\n const prompt = this._parentPrompts[name];\n if (!prompt) {\n throw new Error(`Prompt not found: ${name}`);\n }\n\n return prompt.callback(args, {});\n }\n\n listTools(): ToolListItem[] {\n return Object.entries(this._parentTools)\n .filter(([, tool]) => tool.enabled)\n .map(([name, tool]) => {\n const item: ToolListItem = {\n name,\n description: tool.description ?? '',\n inputSchema: (tool.inputSchema as InputSchema) ?? DEFAULT_INPUT_SCHEMA,\n };\n if (tool.outputSchema) item.outputSchema = tool.outputSchema as InputSchema;\n if (tool.annotations)\n item.annotations = tool.annotations as NonNullable<ToolListItem['annotations']>;\n return item;\n });\n }\n\n async callTool(params: {\n name: string;\n arguments?: Record<string, unknown>;\n }): Promise<ToolResponse> {\n const tool = this._parentTools[params.name];\n if (!tool) {\n throw new Error(`Tool not found: ${params.name}`);\n }\n\n return tool.handler(params.arguments ?? {}, {});\n }\n\n async executeTool(name: string, args: Record<string, unknown> = {}): Promise<ToolResponse> {\n return this.callTool({ name, arguments: args });\n }\n\n /**\n * Override connect to initialize request handlers BEFORE the transport connection.\n * This prevents \"Cannot register capabilities after connecting to transport\" errors\n * when tools are registered dynamically after connection.\n */\n override async connect(transport: Transport): Promise<void> {\n (this as unknown as { setToolRequestHandlers: () => void }).setToolRequestHandlers();\n (this as unknown as { setResourceRequestHandlers: () => void }).setResourceRequestHandlers();\n (this as unknown as { setPromptRequestHandlers: () => void }).setPromptRequestHandlers();\n return super.connect(transport);\n }\n\n // --- Sampling & Elicitation (delegated to Server) ---\n\n async createMessage(\n params: CreateMessageRequest['params'],\n options?: RequestOptions\n ): Promise<CreateMessageResult> {\n return this.server.createMessage(params, options);\n }\n\n async elicitInput(\n params: ElicitRequest['params'],\n options?: RequestOptions\n ): Promise<ElicitResult> {\n return this.server.elicitInput(params, options);\n }\n}\n\n// --- Exported descriptor types for consumers ---\n\nexport interface ResourceDescriptor {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n read: (uri: URL, params?: Record<string, string>) => Promise<{ contents: ResourceContents[] }>;\n}\n\nexport interface PromptDescriptor {\n name: string;\n description?: string;\n argsSchema?: InputSchema;\n get: (args: Record<string, unknown>) => Promise<{ messages: PromptMessage[] }>;\n}\n","/**\n * No-op JSON Schema validator for browser environments.\n *\n * This validator bypasses the MCP SDK's internal ajv-based validation which causes\n * \"Error compiling schema\" errors in browser extensions due to ajv's use of\n * eval/Function constructor.\n *\n * Validation is handled externally by Zod in @mcp-b/global, making the SDK's\n * internal validation redundant. This no-op validator allows the SDK to function\n * without the ajv dependency issues.\n */\n\n/**\n * Interface for JSON Schema validators.\n * This matches the MCP SDK's jsonSchemaValidator interface.\n */\ninterface JsonSchemaValidator {\n getValidator<T>(schema: unknown): (input: unknown) => JsonSchemaValidatorResult<T>;\n}\n\n/**\n * Result type for JSON Schema validation\n */\ntype JsonSchemaValidatorResult<T> =\n | { valid: true; data: T; errorMessage: undefined }\n | { valid: false; data: undefined; errorMessage: string };\n\n/**\n * A no-op JSON Schema validator that always returns valid.\n *\n * Use this in browser environments where:\n * - ajv causes \"Error compiling schema\" errors\n * - Validation is already handled elsewhere (e.g., by Zod)\n * - You need to avoid eval/Function constructor restrictions\n *\n * @example\n * ```typescript\n * import { BrowserMcpServer } from '@mcp-b/webmcp-ts-sdk';\n * import { NoOpJsonSchemaValidator } from '@mcp-b/webmcp-ts-sdk/no-op-validator';\n *\n * const server = new BrowserMcpServer(\n * { name: 'my-server', version: '1.0.0' },\n * { jsonSchemaValidator: new NoOpJsonSchemaValidator() }\n * );\n * ```\n */\nexport class NoOpJsonSchemaValidator implements JsonSchemaValidator {\n /**\n * Returns a validator function that always passes.\n * The input data is passed through unchanged.\n *\n * @param _schema - The JSON Schema (ignored)\n * @returns A validator function that always returns valid\n */\n getValidator<T>(_schema: unknown): (input: unknown) => JsonSchemaValidatorResult<T> {\n return (input: unknown): JsonSchemaValidatorResult<T> => ({\n valid: true,\n data: input as T,\n errorMessage: undefined,\n });\n }\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "@mcp-b/webmcp-ts-sdk",
3
+ "version": "0.0.0-beta-20260216200013",
4
+ "description": "Browser-adapted MCP TypeScript SDK - Dynamic tool registration for W3C Web Model Context API and AI agent integration",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "browser",
9
+ "typescript",
10
+ "sdk",
11
+ "adapter",
12
+ "web-model-context",
13
+ "navigator-modelcontext",
14
+ "w3c",
15
+ "ai-agents",
16
+ "llm",
17
+ "claude",
18
+ "chatgpt",
19
+ "openai",
20
+ "anthropic",
21
+ "cursor",
22
+ "copilot",
23
+ "gemini",
24
+ "webmcp",
25
+ "dynamic-tools",
26
+ "mcp-server",
27
+ "mcp-client",
28
+ "tool-registration",
29
+ "ai-integration"
30
+ ],
31
+ "homepage": "https://docs.mcp-b.ai/packages/webmcp-ts-sdk",
32
+ "bugs": {
33
+ "url": "https://github.com/WebMCP-org/npm-packages/issues"
34
+ },
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/WebMCP-org/npm-packages.git",
38
+ "directory": "packages/webmcp-ts-sdk"
39
+ },
40
+ "license": "MIT",
41
+ "author": "Alex Nahas",
42
+ "type": "module",
43
+ "exports": {
44
+ ".": {
45
+ "types": "./dist/index.d.ts",
46
+ "import": "./dist/index.js"
47
+ }
48
+ },
49
+ "main": "./dist/index.js",
50
+ "module": "./dist/index.js",
51
+ "types": "./dist/index.d.ts",
52
+ "files": [
53
+ "dist"
54
+ ],
55
+ "dependencies": {
56
+ "@modelcontextprotocol/sdk": "1.25.2",
57
+ "@mcp-b/webmcp-polyfill": "0.0.0-beta-20260216200013",
58
+ "@mcp-b/webmcp-types": "0.0.0-beta-20260216200013"
59
+ },
60
+ "devDependencies": {
61
+ "@types/node": "22.17.2",
62
+ "tsdown": "^0.15.10",
63
+ "typescript": "^5.8.3"
64
+ },
65
+ "engines": {
66
+ "node": ">=18"
67
+ },
68
+ "publishConfig": {
69
+ "access": "public",
70
+ "registry": "https://registry.npmjs.org/"
71
+ },
72
+ "scripts": {
73
+ "build": "tsdown",
74
+ "check": "biome check --write .",
75
+ "clean": "rm -rf dist .turbo",
76
+ "format": "biome format --write .",
77
+ "lint": "biome lint --write .",
78
+ "publish:dry": "pnpm publish --access public --dry-run",
79
+ "publish:npm": "pnpm publish --access public",
80
+ "typecheck": "tsc --noEmit",
81
+ "version:major": "pnpm version major --no-git-tag-version",
82
+ "version:minor": "pnpm version minor --no-git-tag-version",
83
+ "version:patch": "pnpm version patch --no-git-tag-version"
84
+ }
85
+ }