@blueberrybytes/webmcp 0.1.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 ADDED
@@ -0,0 +1,196 @@
1
+ # WebMCP TypeScript Library
2
+
3
+ A TypeScript implementation of the Web Model Context Protocol (WebMCP) for creating MCP servers and tools.
4
+
5
+ ## Overview
6
+
7
+ WebMCP (Web Model Context Protocol) is a JavaScript API that allows web developers to expose their web application functionality as "tools" - JavaScript functions with natural language descriptions and structured schemas that can be invoked by AI agents, browser assistants, and assistive technologies.
8
+
9
+ This TypeScript library provides a complete implementation of the WebMCP specification, allowing you to:
10
+
11
+ - Create and manage WebMCP tools
12
+ - Implement an MCP server that can communicate with AI agents
13
+ - Handle client connections and communication
14
+ - Validate tool schemas and inputs
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @webmcp/core
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ### Creating a Simple Tool
25
+
26
+ ```typescript
27
+ import { ModelContext, ToolManager } from "@webmcp/core";
28
+
29
+ // Create a model context
30
+ const modelContext = new ModelContext();
31
+
32
+ // Create a tool manager
33
+ const toolManager = new ToolManager(modelContext);
34
+
35
+ // Create a simple tool
36
+ const helloTool = toolManager.createTool(
37
+ "hello",
38
+ "Say hello to someone",
39
+ async (input: { name: string }) => {
40
+ return `Hello, ${input.name}!`;
41
+ },
42
+ {
43
+ inputSchema: {
44
+ type: "object",
45
+ properties: {
46
+ name: {
47
+ type: "string",
48
+ description: "The name of the person to greet",
49
+ },
50
+ },
51
+ required: ["name"],
52
+ },
53
+ },
54
+ );
55
+
56
+ // Register the tool
57
+ toolManager.registerTool(helloTool);
58
+
59
+ // Execute the tool
60
+ const result = await modelContext.executeTool("hello", { name: "World" });
61
+ console.log(result); // "Hello, World!"
62
+ ```
63
+
64
+ ### Creating an MCP Server
65
+
66
+ ```typescript
67
+ import { MCPServer, ToolManager } from "@webmcp/core";
68
+
69
+ // Create an MCP server
70
+ const server = new MCPServer();
71
+
72
+ // Create and register tools
73
+ const toolManager = new ToolManager(server.getModelContext());
74
+
75
+ const calculatorTool = toolManager.createTool(
76
+ "add",
77
+ "Add two numbers together",
78
+ async (input: { a: number; b: number }) => {
79
+ return { result: input.a + input.b };
80
+ },
81
+ {
82
+ inputSchema: {
83
+ type: "object",
84
+ properties: {
85
+ a: { type: "number", description: "First number" },
86
+ b: { type: "number", description: "Second number" },
87
+ },
88
+ required: ["a", "b"],
89
+ },
90
+ },
91
+ );
92
+
93
+ toolManager.registerTool(calculatorTool);
94
+
95
+ // Handle incoming requests (example)
96
+ const request = {
97
+ jsonrpc: "2.0",
98
+ id: 1,
99
+ method: "tools/call",
100
+ params: {
101
+ name: "add",
102
+ arguments: { a: 5, b: 3 },
103
+ },
104
+ };
105
+
106
+ const response = await server.receive(request);
107
+ console.log(response); // { jsonrpc: '2.0', id: 1, result: { result: 8 } }
108
+ ```
109
+
110
+ ### Creating Categorized Tools
111
+
112
+ ```typescript
113
+ import { ToolManager } from "@webmcp/core";
114
+
115
+ const toolManager = new ToolManager(modelContext);
116
+
117
+ // Create a categorized tool
118
+ const searchTool = toolManager.createCategorizedTool(
119
+ "search-docs",
120
+ "Search documentation for specific terms",
121
+ "search",
122
+ async (input: { query: string }) => {
123
+ // Implementation here
124
+ return { results: [`Result for: ${input.query}`] };
125
+ },
126
+ {
127
+ inputSchema: {
128
+ type: "object",
129
+ properties: {
130
+ query: { type: "string", description: "Search query" },
131
+ },
132
+ required: ["query"],
133
+ },
134
+ tags: ["documentation", "search"],
135
+ },
136
+ );
137
+
138
+ toolManager.registerTool(searchTool);
139
+ ```
140
+
141
+ ## API Reference
142
+
143
+ ### ModelContext
144
+
145
+ The core class for managing WebMCP tools.
146
+
147
+ #### Methods
148
+
149
+ - `provideContext(options: ModelContextOptions)`: Registers tools with the browser
150
+ - `clearContext()`: Unregisters all tools
151
+ - `registerTool(tool: ModelContextTool)`: Registers a single tool
152
+ - `unregisterTool(name: string)`: Removes a tool
153
+ - `getTool(name: string)`: Gets a tool by name
154
+ - `getAllTools()`: Gets all registered tools
155
+ - `executeTool(name: string, input: Record<string, any>, client: ModelContextClient)`: Executes a tool
156
+
157
+ ### ToolManager
158
+
159
+ Utility class for creating and managing tools.
160
+
161
+ #### Methods
162
+
163
+ - `createTool(...)`: Creates a new tool
164
+ - `createCategorizedTool(...)`: Creates a tool with category annotation
165
+ - `createAuthenticatedTool(...)`: Creates a tool with authentication requirements
166
+ - `createReadOnlyTool(...)`: Creates a read-only tool
167
+ - `registerTool(tool: ModelContextTool)`: Registers a tool
168
+ - `registerTools(tools: ModelContextTool[])`: Batch registers tools
169
+
170
+ ### MCPServer
171
+
172
+ MCP server implementation that handles JSON-RPC communication.
173
+
174
+ #### Methods
175
+
176
+ - `receive(request: JSONRPCRequest, clientId?: string)`: Handles incoming requests
177
+ - `addTool(tool: ModelContextTool)`: Adds a tool
178
+ - `removeTool(name: string)`: Removes a tool
179
+ - `getTools()`: Gets all registered tools
180
+
181
+ ## Tool Categories
182
+
183
+ The library supports categorizing tools for better organization and discovery:
184
+
185
+ - `search`: Find/query information
186
+ - `read`: Retrieve specific data
187
+ - `create`: Create new resources
188
+ - `update`: Modify existing resources
189
+ - `delete`: Remove resources
190
+ - `analysis`: Process/analyze data
191
+ - `navigation`: Page/UI navigation
192
+ - `media`: Images, audio, video
193
+
194
+ ## License
195
+
196
+ MIT
@@ -0,0 +1,121 @@
1
+ /**
2
+ * ClientHandler - Handles client connections for WebMCP MCP server
3
+ */
4
+ import { JSONRPCRequest, JSONRPCResponse } from 'json-rpc-2.0';
5
+ import { MCPServer } from './mcp-server';
6
+ /**
7
+ * ClientHandler manages client connections and communication for the MCP server
8
+ */
9
+ export declare class ClientHandler {
10
+ private server;
11
+ private clients;
12
+ constructor(server: MCPServer);
13
+ /**
14
+ * Adds a new client connection
15
+ * @param clientId - Unique identifier for the client
16
+ * @param clientInfo - Information about the client
17
+ * @returns The connected client
18
+ */
19
+ addClient(clientId: string, clientInfo: ClientInfo): ConnectedClient;
20
+ /**
21
+ * Removes a client connection
22
+ * @param clientId - The client ID to remove
23
+ */
24
+ removeClient(clientId: string): void;
25
+ /**
26
+ * Gets a client by ID
27
+ * @param clientId - The client ID
28
+ * @returns The connected client or undefined if not found
29
+ */
30
+ getClient(clientId: string): ConnectedClient | undefined;
31
+ /**
32
+ * Gets all connected clients
33
+ * @returns Array of all connected clients
34
+ */
35
+ getClients(): ConnectedClient[];
36
+ /**
37
+ * Handles an incoming JSON-RPC request from a client
38
+ * @param clientId - The client ID
39
+ * @param request - The JSON-RPC request
40
+ * @returns Promise that resolves with the JSON-RPC response
41
+ */
42
+ handleRequest(clientId: string, request: JSONRPCRequest): Promise<JSONRPCResponse | null>;
43
+ /**
44
+ * Sends a notification to a client
45
+ * @param clientId - The client ID
46
+ * @param method - The method to call
47
+ * @param params - The parameters to pass
48
+ */
49
+ sendNotification(clientId: string, method: string, params: any): void;
50
+ /**
51
+ * Sends a request to a client
52
+ * @param clientId - The client ID
53
+ * @param method - The method to call
54
+ * @param params - The parameters to pass
55
+ * @returns Promise that resolves with the response
56
+ */
57
+ sendRequest(clientId: string, method: string, params: any): Promise<any>;
58
+ /**
59
+ * Gets the number of connected clients
60
+ * @returns The number of connected clients
61
+ */
62
+ getClientCount(): number;
63
+ /**
64
+ * Gets inactive clients older than the specified time
65
+ * @param minutes - The number of minutes to consider a client inactive
66
+ * @returns Array of inactive clients
67
+ */
68
+ getInactiveClients(minutes: number): ConnectedClient[];
69
+ /**
70
+ * Disconnects inactive clients
71
+ * @param minutes - The number of minutes to consider a client inactive
72
+ * @returns The number of clients disconnected
73
+ */
74
+ disconnectInactiveClients(minutes: number): number;
75
+ }
76
+ /**
77
+ * Information about a connected client
78
+ */
79
+ export interface ClientInfo {
80
+ /**
81
+ * Client name or identifier
82
+ */
83
+ name: string;
84
+ /**
85
+ * Client version
86
+ */
87
+ version?: string;
88
+ /**
89
+ * Client type (e.g., 'browser', 'desktop', 'mobile')
90
+ */
91
+ type?: string;
92
+ /**
93
+ * Client capabilities
94
+ */
95
+ capabilities?: string[];
96
+ /**
97
+ * Additional metadata
98
+ */
99
+ metadata?: Record<string, any>;
100
+ }
101
+ /**
102
+ * Represents a connected client
103
+ */
104
+ export interface ConnectedClient {
105
+ /**
106
+ * Client ID
107
+ */
108
+ id: string;
109
+ /**
110
+ * Client information
111
+ */
112
+ info: ClientInfo;
113
+ /**
114
+ * Connection timestamp
115
+ */
116
+ connectedAt: Date;
117
+ /**
118
+ * Last activity timestamp
119
+ */
120
+ lastActivity: Date;
121
+ }
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ /**
3
+ * ClientHandler - Handles client connections for WebMCP MCP server
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ClientHandler = void 0;
7
+ /**
8
+ * ClientHandler manages client connections and communication for the MCP server
9
+ */
10
+ class ClientHandler {
11
+ constructor(server) {
12
+ this.clients = new Map();
13
+ this.server = server;
14
+ }
15
+ /**
16
+ * Adds a new client connection
17
+ * @param clientId - Unique identifier for the client
18
+ * @param clientInfo - Information about the client
19
+ * @returns The connected client
20
+ */
21
+ addClient(clientId, clientInfo) {
22
+ const client = {
23
+ id: clientId,
24
+ info: clientInfo,
25
+ connectedAt: new Date(),
26
+ lastActivity: new Date()
27
+ };
28
+ this.clients.set(clientId, client);
29
+ return client;
30
+ }
31
+ /**
32
+ * Removes a client connection
33
+ * @param clientId - The client ID to remove
34
+ */
35
+ removeClient(clientId) {
36
+ this.clients.delete(clientId);
37
+ }
38
+ /**
39
+ * Gets a client by ID
40
+ * @param clientId - The client ID
41
+ * @returns The connected client or undefined if not found
42
+ */
43
+ getClient(clientId) {
44
+ return this.clients.get(clientId);
45
+ }
46
+ /**
47
+ * Gets all connected clients
48
+ * @returns Array of all connected clients
49
+ */
50
+ getClients() {
51
+ return Array.from(this.clients.values());
52
+ }
53
+ /**
54
+ * Handles an incoming JSON-RPC request from a client
55
+ * @param clientId - The client ID
56
+ * @param request - The JSON-RPC request
57
+ * @returns Promise that resolves with the JSON-RPC response
58
+ */
59
+ async handleRequest(clientId, request) {
60
+ // Update client activity
61
+ const client = this.getClient(clientId);
62
+ if (client) {
63
+ client.lastActivity = new Date();
64
+ }
65
+ // Process the request through the MCP server
66
+ return await this.server.receive(request, clientId);
67
+ }
68
+ /**
69
+ * Sends a notification to a client
70
+ * @param clientId - The client ID
71
+ * @param method - The method to call
72
+ * @param params - The parameters to pass
73
+ */
74
+ sendNotification(clientId, method, params) {
75
+ const client = this.getClient(clientId);
76
+ if (!client) {
77
+ throw new Error(`Client '${clientId}' not found`);
78
+ }
79
+ // In a real implementation, this would send the notification to the client
80
+ // For now, we'll just log it
81
+ console.log(`Sending notification to client ${clientId}: ${method}`, params);
82
+ }
83
+ /**
84
+ * Sends a request to a client
85
+ * @param clientId - The client ID
86
+ * @param method - The method to call
87
+ * @param params - The parameters to pass
88
+ * @returns Promise that resolves with the response
89
+ */
90
+ async sendRequest(clientId, method, params) {
91
+ const client = this.getClient(clientId);
92
+ if (!client) {
93
+ throw new Error(`Client '${clientId}' not found`);
94
+ }
95
+ // In a real implementation, this would send the request to the client
96
+ // For now, we'll just log it and return a mock response
97
+ console.log(`Sending request to client ${clientId}: ${method}`, params);
98
+ // Mock response for demonstration
99
+ return {
100
+ result: `Mock response for ${method}`,
101
+ client: clientId
102
+ };
103
+ }
104
+ /**
105
+ * Gets the number of connected clients
106
+ * @returns The number of connected clients
107
+ */
108
+ getClientCount() {
109
+ return this.clients.size;
110
+ }
111
+ /**
112
+ * Gets inactive clients older than the specified time
113
+ * @param minutes - The number of minutes to consider a client inactive
114
+ * @returns Array of inactive clients
115
+ */
116
+ getInactiveClients(minutes) {
117
+ const now = new Date();
118
+ const inactiveClients = [];
119
+ for (const client of this.clients.values()) {
120
+ const minutesSinceLastActivity = (now.getTime() - client.lastActivity.getTime()) / (1000 * 60);
121
+ if (minutesSinceLastActivity > minutes) {
122
+ inactiveClients.push(client);
123
+ }
124
+ }
125
+ return inactiveClients;
126
+ }
127
+ /**
128
+ * Disconnects inactive clients
129
+ * @param minutes - The number of minutes to consider a client inactive
130
+ * @returns The number of clients disconnected
131
+ */
132
+ disconnectInactiveClients(minutes) {
133
+ const inactiveClients = this.getInactiveClients(minutes);
134
+ const count = inactiveClients.length;
135
+ for (const client of inactiveClients) {
136
+ this.removeClient(client.id);
137
+ }
138
+ return count;
139
+ }
140
+ }
141
+ exports.ClientHandler = ClientHandler;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * WebMCP - Web Model Context Protocol
3
+ *
4
+ * A TypeScript library for implementing WebMCP servers and tools
5
+ */
6
+ export { ModelContext } from './model-context';
7
+ export { MCPServer, MCPClient } from './mcp-server';
8
+ export { ToolManager } from './tool-manager';
9
+ export { ClientHandler, ClientInfo, ConnectedClient } from './client-handler';
10
+ export * from './types';
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /**
3
+ * WebMCP - Web Model Context Protocol
4
+ *
5
+ * A TypeScript library for implementing WebMCP servers and tools
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.ClientHandler = exports.ToolManager = exports.MCPServer = exports.ModelContext = void 0;
23
+ var model_context_1 = require("./model-context");
24
+ Object.defineProperty(exports, "ModelContext", { enumerable: true, get: function () { return model_context_1.ModelContext; } });
25
+ var mcp_server_1 = require("./mcp-server");
26
+ Object.defineProperty(exports, "MCPServer", { enumerable: true, get: function () { return mcp_server_1.MCPServer; } });
27
+ var tool_manager_1 = require("./tool-manager");
28
+ Object.defineProperty(exports, "ToolManager", { enumerable: true, get: function () { return tool_manager_1.ToolManager; } });
29
+ var client_handler_1 = require("./client-handler");
30
+ Object.defineProperty(exports, "ClientHandler", { enumerable: true, get: function () { return client_handler_1.ClientHandler; } });
31
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,100 @@
1
+ /**
2
+ * MCP Server - Implementation of MCP protocol for WebMCP
3
+ */
4
+ import { JSONRPCRequest, JSONRPCResponse } from 'json-rpc-2.0';
5
+ import { ModelContext } from './model-context';
6
+ import { ModelContextTool } from './types';
7
+ /**
8
+ * MCP Server that handles JSON-RPC communication for WebMCP tools
9
+ */
10
+ export declare class MCPServer {
11
+ private server;
12
+ private modelContext;
13
+ private clients;
14
+ constructor(modelContext?: ModelContext);
15
+ /**
16
+ * Sets up the JSON-RPC methods for the MCP server
17
+ */
18
+ private setupMethods;
19
+ /**
20
+ * Handles incoming JSON-RPC requests
21
+ * @param request - The JSON-RPC request
22
+ * @param clientId - Optional client ID
23
+ * @returns Promise that resolves with the JSON-RPC response
24
+ */
25
+ receive(request: JSONRPCRequest, clientId?: string): Promise<JSONRPCResponse | null>;
26
+ /**
27
+ * Adds a tool to the model context
28
+ * @param tool - The tool to add
29
+ */
30
+ addTool(tool: ModelContextTool): void;
31
+ /**
32
+ * Removes a tool from the model context
33
+ * @param name - The name of the tool to remove
34
+ */
35
+ removeTool(name: string): void;
36
+ /**
37
+ * Gets all registered tools
38
+ * @returns Array of all registered tools
39
+ */
40
+ getTools(): ModelContextTool[];
41
+ /**
42
+ * Gets the model context
43
+ * @returns The model context
44
+ */
45
+ getModelContext(): ModelContext;
46
+ /**
47
+ * Adds a client to the server
48
+ * @param clientId - The client ID
49
+ * @param client - The client to add
50
+ */
51
+ addClient(clientId: string, client: MCPClient): void;
52
+ /**
53
+ * Removes a client from the server
54
+ * @param clientId - The client ID to remove
55
+ */
56
+ removeClient(clientId: string): void;
57
+ /**
58
+ * Gets a client by ID
59
+ * @param clientId - The client ID
60
+ * @returns The client or undefined if not found
61
+ */
62
+ getClient(clientId: string): MCPClient | undefined;
63
+ /**
64
+ * Gets the default client
65
+ * @returns The default client
66
+ */
67
+ private getDefaultClient;
68
+ /**
69
+ * Formats a tool result for MCP protocol
70
+ * @param result - The tool result
71
+ * @returns Formatted result
72
+ */
73
+ private formatToolResult;
74
+ }
75
+ /**
76
+ * Represents an MCP client
77
+ */
78
+ export interface MCPClient {
79
+ /**
80
+ * Client ID
81
+ */
82
+ id: string;
83
+ /**
84
+ * Client name
85
+ */
86
+ name: string;
87
+ /**
88
+ * Send a notification to the client
89
+ * @param method - The method to call
90
+ * @param params - The parameters to pass
91
+ */
92
+ sendNotification(method: string, params: any): void;
93
+ /**
94
+ * Send a request to the client
95
+ * @param method - The method to call
96
+ * @param params - The parameters to pass
97
+ * @returns Promise that resolves with the response
98
+ */
99
+ sendRequest(method: string, params: any): Promise<any>;
100
+ }