@mcp-fe/mcp-worker 0.0.17 → 0.1.1

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/docs/guide.md ADDED
@@ -0,0 +1,454 @@
1
+ # Dynamic Tool Registration Guide
2
+
3
+ Learn how to register custom MCP tools that run in your browser with full access to all APIs.
4
+
5
+ ## How It Works
6
+
7
+ **Handlers run in the main thread**, not in the worker. This means you have full access to:
8
+
9
+ - ✅ React context, hooks, state
10
+ - ✅ DOM API, localStorage, fetch
11
+ - ✅ All your imports and dependencies
12
+ - ✅ Closures and external variables
13
+
14
+ The worker acts as a **proxy**, forwarding calls between the MCP protocol and your handler.
15
+
16
+ ```
17
+ MCP Client → Worker (proxy) → Your Handler (main thread) → Result
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```typescript
23
+ import { workerClient } from '@mcp-fe/mcp-worker';
24
+
25
+ // Initialize
26
+ await workerClient.init({
27
+ backendWsUrl: 'ws://localhost:3001'
28
+ });
29
+
30
+ // Register a tool
31
+ await workerClient.registerTool(
32
+ 'get_time',
33
+ 'Get current time',
34
+ { type: 'object', properties: {} },
35
+ async () => ({
36
+ content: [{
37
+ type: 'text',
38
+ text: new Date().toISOString()
39
+ }]
40
+ })
41
+ );
42
+ ```
43
+
44
+ ## API
45
+
46
+ ### `workerClient.registerTool(name, description, inputSchema, handler)`
47
+
48
+ Register a new MCP tool.
49
+
50
+ **Parameters:**
51
+ - `name` (string) - Tool name (use snake_case)
52
+ - `description` (string) - What the tool does (AI uses this)
53
+ - `inputSchema` (object) - JSON Schema for input validation
54
+ - `handler` (function) - Async function that handles the tool execution
55
+
56
+ **Returns:** `Promise<void>`
57
+
58
+ **Example:**
59
+ ```typescript
60
+ await workerClient.registerTool(
61
+ 'calculate',
62
+ 'Perform arithmetic operations',
63
+ {
64
+ type: 'object',
65
+ properties: {
66
+ operation: {
67
+ type: 'string',
68
+ enum: ['add', 'subtract', 'multiply', 'divide']
69
+ },
70
+ a: { type: 'number' },
71
+ b: { type: 'number' }
72
+ },
73
+ required: ['operation', 'a', 'b']
74
+ },
75
+ async (args: any) => {
76
+ const { operation, a, b } = args;
77
+ let result: number;
78
+
79
+ switch (operation) {
80
+ case 'add': result = a + b; break;
81
+ case 'subtract': result = a - b; break;
82
+ case 'multiply': result = a * b; break;
83
+ case 'divide':
84
+ if (b === 0) {
85
+ throw new Error('Division by zero');
86
+ }
87
+ result = a / b;
88
+ break;
89
+ }
90
+
91
+ return {
92
+ content: [{
93
+ type: 'text',
94
+ text: JSON.stringify({ operation, a, b, result })
95
+ }]
96
+ };
97
+ }
98
+ );
99
+ ```
100
+
101
+ ### `workerClient.unregisterTool(name)`
102
+
103
+ Unregister a previously registered tool.
104
+
105
+ **Parameters:**
106
+ - `name` (string) - Tool name to unregister
107
+
108
+ **Returns:** `Promise<boolean>` - True if tool was found and removed
109
+
110
+ **Example:**
111
+ ```typescript
112
+ const success = await workerClient.unregisterTool('calculate');
113
+ if (success) {
114
+ console.log('Tool unregistered');
115
+ }
116
+ ```
117
+
118
+ ## Handler Function
119
+
120
+ The handler receives the tool arguments and must return a result in MCP format.
121
+
122
+ **Signature:**
123
+ ```typescript
124
+ async (args: unknown) => Promise<{
125
+ content: Array<{
126
+ type: 'text' | 'image' | 'resource';
127
+ text?: string;
128
+ data?: string;
129
+ mimeType?: string;
130
+ }>;
131
+ }>
132
+ ```
133
+
134
+ **Example with validation:**
135
+ ```typescript
136
+ import { z } from 'zod';
137
+
138
+ const handler = async (args: unknown) => {
139
+ // Validate input
140
+ const schema = z.object({
141
+ username: z.string().min(3),
142
+ email: z.string().email()
143
+ });
144
+
145
+ try {
146
+ const validated = schema.parse(args);
147
+
148
+ // Your logic here
149
+ const result = await createUser(validated);
150
+
151
+ return {
152
+ content: [{
153
+ type: 'text',
154
+ text: JSON.stringify(result)
155
+ }]
156
+ };
157
+ } catch (error) {
158
+ return {
159
+ content: [{
160
+ type: 'text',
161
+ text: JSON.stringify({
162
+ error: error.message
163
+ })
164
+ }]
165
+ };
166
+ }
167
+ };
168
+ ```
169
+
170
+ ## Common Patterns
171
+
172
+ ### Accessing React State
173
+
174
+ ```typescript
175
+ function MyComponent() {
176
+ const [todos, setTodos] = useState([]);
177
+
178
+ useEffect(() => {
179
+ workerClient.registerTool(
180
+ 'get_todos',
181
+ 'Get all todos',
182
+ { type: 'object', properties: {} },
183
+ async () => ({
184
+ content: [{
185
+ type: 'text',
186
+ text: JSON.stringify(todos)
187
+ }]
188
+ })
189
+ );
190
+ }, [todos]);
191
+ }
192
+ ```
193
+
194
+ ### Using External APIs
195
+
196
+ ```typescript
197
+ await workerClient.registerTool(
198
+ 'fetch_weather',
199
+ 'Get weather for a city',
200
+ {
201
+ type: 'object',
202
+ properties: {
203
+ city: { type: 'string' }
204
+ }
205
+ },
206
+ async (args: any) => {
207
+ const response = await fetch(
208
+ `https://api.weather.com/data?city=${args.city}`
209
+ );
210
+ const data = await response.json();
211
+
212
+ return {
213
+ content: [{
214
+ type: 'text',
215
+ text: JSON.stringify(data)
216
+ }]
217
+ };
218
+ }
219
+ );
220
+ ```
221
+
222
+ ### Accessing localStorage
223
+
224
+ ```typescript
225
+ await workerClient.registerTool(
226
+ 'get_settings',
227
+ 'Get user settings',
228
+ { type: 'object', properties: {} },
229
+ async () => {
230
+ const theme = localStorage.getItem('theme') || 'light';
231
+ const language = localStorage.getItem('lang') || 'en';
232
+
233
+ return {
234
+ content: [{
235
+ type: 'text',
236
+ text: JSON.stringify({ theme, language })
237
+ }]
238
+ };
239
+ }
240
+ );
241
+ ```
242
+
243
+ ### Accessing DOM
244
+
245
+ ```typescript
246
+ await workerClient.registerTool(
247
+ 'get_page_info',
248
+ 'Get current page information',
249
+ { type: 'object', properties: {} },
250
+ async () => ({
251
+ content: [{
252
+ type: 'text',
253
+ text: JSON.stringify({
254
+ title: document.title,
255
+ url: window.location.href,
256
+ headings: document.querySelectorAll('h1, h2').length
257
+ })
258
+ }]
259
+ })
260
+ );
261
+ ```
262
+
263
+ ## Best Practices
264
+
265
+ ### 1. Tool Naming
266
+
267
+ Use **snake_case** for tool names:
268
+
269
+ ```typescript
270
+ // ✅ Good
271
+ 'get_user_profile'
272
+ 'create_todo'
273
+ 'fetch_data'
274
+
275
+ // ❌ Bad
276
+ 'getUserProfile'
277
+ 'CreateTodo'
278
+ 'fetch-data'
279
+ ```
280
+
281
+ ### 2. Descriptions
282
+
283
+ Write clear, specific descriptions. The AI uses these to decide when to call your tool:
284
+
285
+ ```typescript
286
+ // ✅ Good
287
+ 'Get the current user profile including username, email, and avatar'
288
+
289
+ // ❌ Bad
290
+ 'Get user'
291
+ ```
292
+
293
+ ### 3. Input Validation
294
+
295
+ Always validate inputs:
296
+
297
+ ```typescript
298
+ // ✅ Good - with validation
299
+ const handler = async (args: unknown) => {
300
+ const schema = z.object({
301
+ email: z.string().email()
302
+ });
303
+ const validated = schema.parse(args);
304
+ // ...
305
+ };
306
+
307
+ // ❌ Bad - no validation
308
+ const handler = async (args: any) => {
309
+ const email = args.email; // Could be anything!
310
+ // ...
311
+ };
312
+ ```
313
+
314
+ ### 4. Error Handling
315
+
316
+ Return helpful error messages:
317
+
318
+ ```typescript
319
+ try {
320
+ const result = await doSomething();
321
+ return {
322
+ content: [{
323
+ type: 'text',
324
+ text: JSON.stringify(result)
325
+ }]
326
+ };
327
+ } catch (error) {
328
+ return {
329
+ content: [{
330
+ type: 'text',
331
+ text: JSON.stringify({
332
+ error: error.message,
333
+ // Include context to help debug
334
+ input: args
335
+ })
336
+ }]
337
+ };
338
+ }
339
+ ```
340
+
341
+ ### 5. TypeScript
342
+
343
+ Use proper types for better developer experience:
344
+
345
+ ```typescript
346
+ interface CalculateArgs {
347
+ operation: 'add' | 'subtract' | 'multiply' | 'divide';
348
+ a: number;
349
+ b: number;
350
+ }
351
+
352
+ const handler = async (args: unknown) => {
353
+ const { operation, a, b } = args as CalculateArgs;
354
+ // TypeScript knows the types now
355
+ };
356
+ ```
357
+
358
+ ## Testing
359
+
360
+ Handlers are normal async functions - easy to test:
361
+
362
+ ```typescript
363
+ // Define handler
364
+ const myHandler = async (args: unknown) => {
365
+ return {
366
+ content: [{
367
+ type: 'text',
368
+ text: JSON.stringify({ result: 'ok' })
369
+ }]
370
+ };
371
+ };
372
+
373
+ // Test it
374
+ test('myHandler returns ok', async () => {
375
+ const result = await myHandler({});
376
+ expect(result.content[0].text).toContain('ok');
377
+ });
378
+
379
+ // Then register
380
+ await workerClient.registerTool('my_tool', '...', {}, myHandler);
381
+ ```
382
+
383
+ ## Examples
384
+
385
+ See [examples/](../examples/) for complete, runnable examples:
386
+
387
+ - [quick-start.ts](../examples/quick-start.ts) - Simple examples
388
+ - [dynamic-tools.ts](../examples/dynamic-tools.ts) - Advanced patterns
389
+
390
+ ## React Integration
391
+
392
+ For React applications, use the `useMCPTool` hook for automatic lifecycle management:
393
+
394
+ ```typescript
395
+ import { useMCPTool } from '@mcp-fe/react-event-tracker';
396
+
397
+ function MyComponent() {
398
+ useMCPTool({
399
+ name: 'my_tool',
400
+ description: 'My tool',
401
+ inputSchema: { type: 'object', properties: {} },
402
+ handler: async () => ({
403
+ content: [{ type: 'text', text: 'Hello!' }]
404
+ })
405
+ });
406
+ // Automatically registered on mount, unregistered on unmount
407
+ }
408
+ ```
409
+
410
+ See [React Hooks Guide](../../react-event-tracker/REACT_MCP_TOOLS.md) for details.
411
+
412
+ ## Troubleshooting
413
+
414
+ ### Tool doesn't register
415
+
416
+ Check that the worker is initialized:
417
+
418
+ ```typescript
419
+ await workerClient.init();
420
+ console.log(workerClient.initialized); // should be true
421
+ ```
422
+
423
+ ### Handler not called
424
+
425
+ Verify the tool name matches exactly:
426
+
427
+ ```typescript
428
+ // Registration
429
+ await workerClient.registerTool('get_user', ...);
430
+
431
+ // MCP call must use: 'get_user' (exact match)
432
+ ```
433
+
434
+ ### Arguments not received
435
+
436
+ Check your input schema matches what the AI sends:
437
+
438
+ ```typescript
439
+ // Schema says: { email: string }
440
+ inputSchema: {
441
+ type: 'object',
442
+ properties: {
443
+ email: { type: 'string' }
444
+ }
445
+ }
446
+
447
+ // Handler receives: { email: 'test@example.com' }
448
+ ```
449
+
450
+ ## Next Steps
451
+
452
+ - [Architecture](./architecture.md) - How the proxy pattern works
453
+ - [Initialization](./initialization.md) - Init queue handling
454
+ - [Examples](../examples/) - Runnable code examples
package/docs/index.md ADDED
@@ -0,0 +1,109 @@
1
+ # Documentation Index
2
+
3
+ Complete guide to all documentation and examples in the MCP Worker library.
4
+
5
+ ## 🎯 Quick Navigation
6
+
7
+ | I want to... | Go to... |
8
+ |--------------|----------|
9
+ | **Get started quickly** | [examples/quick-start.ts](../examples/quick-start.ts) |
10
+ | **See advanced patterns** | [examples/dynamic-tools.ts](../examples/dynamic-tools.ts) |
11
+ | **Learn step-by-step** | [Guide](./guide.md) |
12
+ | **Complete API reference** | [API Reference](./api.md) |
13
+ | **Worker implementation** | [Worker Details](./worker-details.md) |
14
+ | **Use with React** | [React Hooks Guide](../../react-event-tracker/REACT_MCP_TOOLS.md) |
15
+ | **Understand architecture** | [Architecture](./architecture.md) |
16
+ | **Handle initialization** | [Initialization](./initialization.md) |
17
+
18
+ ## 📁 Documentation Structure
19
+
20
+ ```
21
+ libs/mcp-worker/
22
+ ├── README.md ← Start here!
23
+
24
+ ├── docs/ ← Documentation
25
+ │ ├── index.md ← This file
26
+ │ ├── guide.md ← Complete guide
27
+ │ ├── api.md ← API reference
28
+ │ ├── worker-details.md ← Worker implementation
29
+ │ ├── architecture.md ← Technical architecture
30
+ │ └── initialization.md ← Init handling
31
+
32
+ ├── examples/ ← Code examples
33
+ │ ├── README.md ← Examples guide
34
+ │ ├── quick-start.ts ← Simple examples
35
+ │ └── dynamic-tools.ts ← Advanced patterns
36
+
37
+ └── src/ ← Source code
38
+ └── lib/
39
+ └── worker-client.ts
40
+
41
+ libs/react-event-tracker/
42
+ ├── REACT_MCP_TOOLS.md ← React hooks docs
43
+ └── src/examples/
44
+ └── ReactMCPToolsExamples.tsx ← React examples
45
+ ```
46
+
47
+ ## 📖 Documentation by Purpose
48
+
49
+ ### For Beginners
50
+
51
+ 1. [README.md](../README.md) - Overview and quick start
52
+ 2. [examples/quick-start.ts](../examples/quick-start.ts) - Simple examples
53
+ 3. [examples/README.md](../examples/README.md) - How to use examples
54
+
55
+ ### For Developers
56
+
57
+ 1. [Guide](./guide.md) - Step-by-step guide
58
+ 2. [API Reference](./api.md) - Complete API documentation
59
+ 3. [examples/dynamic-tools.ts](../examples/dynamic-tools.ts) - Advanced patterns
60
+ 4. [Worker Details](./worker-details.md) - Implementation details
61
+ 5. [Architecture](./architecture.md) - How it works
62
+
63
+ ### For React Users
64
+
65
+ 1. [React Hooks Guide](../../react-event-tracker/REACT_MCP_TOOLS.md) - React integration
66
+ 2. [React Examples](../../react-event-tracker/src/examples/ReactMCPToolsExamples.tsx) - Component examples
67
+
68
+ ## 🔍 Finding What You Need
69
+
70
+ ### "How do I register a tool?"
71
+ → [examples/quick-start.ts](../examples/quick-start.ts) (Example 1)
72
+
73
+ ### "How do I validate inputs?"
74
+ → [examples/dynamic-tools.ts](../examples/dynamic-tools.ts) (Calculator example)
75
+
76
+ ### "How do I use this with React?"
77
+ → [React Hooks Guide](../../react-event-tracker/REACT_MCP_TOOLS.md)
78
+
79
+ ### "How does the proxy pattern work?"
80
+ → [Architecture](./architecture.md)
81
+
82
+ ### "How do I handle initialization?"
83
+ → [Initialization](./initialization.md)
84
+
85
+ ## 📦 What's in the npm Package
86
+
87
+ When you install `@mcp-fe/mcp-worker`, you get:
88
+
89
+ ```
90
+ node_modules/@mcp-fe/mcp-worker/
91
+ ├── index.js # Main entry point
92
+ ├── index.d.ts # TypeScript definitions
93
+ ├── mcp-shared-worker.js # SharedWorker bundle
94
+ ├── mcp-service-worker.js # ServiceWorker bundle
95
+ ├── lib/ # Compiled library code
96
+ └── README.md # Basic documentation
97
+
98
+ # NOT included (development only):
99
+ # - examples/
100
+ # - docs/
101
+ # - src/
102
+ # - test files
103
+ ```
104
+
105
+ **Note:** Examples and full documentation are in the [GitHub repository](https://github.com/mcp-fe/mcp-fe) but not in the npm package.
106
+
107
+
108
+
109
+ **Last updated:** 2026-02-02