@netpad/mcp-server-remote 1.0.1 → 1.2.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 CHANGED
@@ -6,7 +6,10 @@ Remote MCP server for NetPad, deployable to Vercel for use with Claude Custom Co
6
6
 
7
7
  This package provides a remote HTTP-based MCP server that can be used as a **Claude Custom Connector**. Unlike the stdio-based `@netpad/mcp-server` (for Claude Desktop), this server runs as a web service that Claude can connect to over the internet.
8
8
 
9
- **Authentication:** Uses your existing NetPad API keys (`np_live_xxx` or `np_test_xxx`).
9
+ **Features:**
10
+ - **All 80+ tools** from `@netpad/mcp-server` - forms, workflows, extensions, templates, data browser, and more
11
+ - **API key authentication** using your existing NetPad API keys (`np_live_xxx` or `np_test_xxx`)
12
+ - **Ready to deploy** to Vercel
10
13
 
11
14
  ## Quick Start
12
15
 
@@ -96,22 +99,69 @@ Manage your API keys at [netpad.io/settings](https://netpad.io/settings):
96
99
  - **Monitor** usage statistics
97
100
  - **Set expiration** dates for temporary access
98
101
 
99
- ## Available Tools
100
-
101
- The remote server includes a subset of the full NetPad MCP tools:
102
-
103
- ### Form Building
104
- - `generate_form` - Generate form configurations from natural language
105
- - `list_field_types` - List all 23+ supported field types
106
- - `list_form_templates` - Browse pre-built form templates
107
- - `create_form_from_template` - Create forms from templates
108
-
109
- ### Workflow Automation
110
- - `list_workflow_templates` - Browse workflow templates
111
- - `list_workflow_node_types` - List available workflow nodes
112
-
113
- ### Data
114
- - `generate_mongodb_query` - Generate MongoDB queries
102
+ ## Available Tools (80+)
103
+
104
+ The remote server includes **all tools from `@netpad/mcp-server`**:
105
+
106
+ ### 1. Form Building (6 tools)
107
+ - `generate_form` - Generate complete form configurations
108
+ - `generate_field` - Create individual field configurations
109
+ - `generate_conditional_logic` - Create show/hide logic
110
+ - `generate_computed_field` - Create formula-based fields
111
+ - `generate_multipage_config` - Multi-page wizard configurations
112
+ - `validate_form_config` - Validate form configurations
113
+
114
+ ### 2. Application Management (7 tools)
115
+ - `create_application` - Generate code to create applications
116
+ - `generate_application_contract` - Define API contracts
117
+ - `generate_application_release` - Create versioned releases
118
+ - And more...
119
+
120
+ ### 3. Marketplace & npm (8 tools)
121
+ - `publish_to_marketplace` - Publish applications
122
+ - `search_marketplace` - Search for applications
123
+ - `install_from_npm` - Install from npm registry
124
+ - And more...
125
+
126
+ ### 4. Workflow Automation (10 tools)
127
+ - `create_workflow` - Generate workflow configurations
128
+ - `add_workflow_node` - Add nodes to workflows
129
+ - `connect_workflow_nodes` - Connect nodes with edges
130
+ - `list_workflow_node_types` - Browse 25+ node types
131
+ - And more...
132
+
133
+ ### 5. Conversational & Search Forms (11 tools)
134
+ - `create_conversational_form` - AI-powered conversational forms
135
+ - `configure_rag_settings` - Enable RAG with document retrieval
136
+ - `create_search_form` - Build MongoDB search interfaces
137
+ - And more...
138
+
139
+ ### 6. Enhanced Templates (5 tools)
140
+ - `list_form_templates` - Browse 25+ form templates
141
+ - `get_form_template` - Get template details
142
+ - `create_form_from_template` - Create with customizations
143
+ - And more...
144
+
145
+ ### 7. Data Browser (12 tools)
146
+ - `generate_connection_config` - Configure MongoDB connections
147
+ - `generate_data_browser_query` - Generate find/aggregate queries
148
+ - `generate_aggregation_pipeline` - Build aggregation pipelines
149
+ - `generate_index_recommendations` - Get index suggestions
150
+ - And more...
151
+
152
+ ### 8. Extension Development (5 tools) - NEW
153
+ - `generate_extension` - Generate complete extension packages
154
+ - `list_node_categories` - List workflow node categories
155
+ - `list_config_field_types` - List configuration field types
156
+ - `list_workflow_icons` - List commonly used icons
157
+ - `list_workflow_colors` - List suggested colors
158
+
159
+ ### 9. Consolidated Reference Tools
160
+ - `get_reference` - Unified access to all reference documentation
161
+ - `browse_templates` - Browse all 40+ templates with filtering
162
+
163
+ ### 10. Legacy Reference & Helper (16 tools)
164
+ - Documentation, best practices, debugging tools
115
165
 
116
166
  ## Local Development
117
167
 
@@ -164,6 +214,10 @@ This server uses the MCP SDK's `StreamableHTTPServerTransport` which implements
164
214
  - Session management via `Mcp-Session-Id` header
165
215
  - Bearer token authentication via NetPad API
166
216
 
217
+ ### Code Sharing
218
+
219
+ The remote server imports `createNetPadMcpServer()` from `@netpad/mcp-server`, ensuring both servers have identical tool capabilities. Any updates to the main MCP server automatically apply to the remote server.
220
+
167
221
  ### Authentication Flow
168
222
 
169
223
  ```
@@ -204,6 +258,14 @@ This server uses the MCP SDK's `StreamableHTTPServerTransport` which implements
204
258
 
205
259
  - [@netpad/mcp-server](../mcp-server) - Local stdio MCP server for Claude Desktop (no auth required)
206
260
  - [NetPad Platform](https://netpad.io) - Full form builder platform
261
+ - [Documentation](https://docs.netpad.io/docs/developer/mcp-server) - MCP server documentation
262
+
263
+ ## Version History
264
+
265
+ | Version | Changes |
266
+ |---------|---------|
267
+ | **1.1.0** | Full parity with @netpad/mcp-server (80+ tools), imports shared server factory |
268
+ | **1.0.1** | Initial release with subset of tools |
207
269
 
208
270
  ## License
209
271
 
package/api/index.ts CHANGED
@@ -3,12 +3,32 @@ import type { VercelRequest, VercelResponse } from '@vercel/node';
3
3
  export default function handler(req: VercelRequest, res: VercelResponse) {
4
4
  res.status(200).json({
5
5
  name: '@netpad/mcp-server-remote',
6
- version: '1.0.0',
7
- description: 'NetPad MCP Server - Remote API for Claude Custom Connectors',
6
+ version: '1.1.0',
7
+ description: 'NetPad MCP Server - Remote API for Claude Custom Connectors. Includes all 80+ tools from @netpad/mcp-server.',
8
8
  endpoints: {
9
9
  mcp: '/mcp',
10
10
  health: '/health',
11
11
  },
12
- documentation: 'https://github.com/mrlynn/netpad-v3/tree/main/packages/mcp-server-remote',
12
+ features: {
13
+ tools: '80+ tools',
14
+ categories: [
15
+ 'Form Building (6 tools)',
16
+ 'Application Management (7 tools)',
17
+ 'Marketplace & npm (8 tools)',
18
+ 'Workflow Automation (10 tools)',
19
+ 'Conversational & Search Forms (11 tools)',
20
+ 'Enhanced Templates (5 tools)',
21
+ 'Data Browser (12 tools)',
22
+ 'Extension Development (5 tools)',
23
+ 'Consolidated Reference Tools',
24
+ 'Legacy Reference & Helper (16 tools)',
25
+ ],
26
+ },
27
+ authentication: {
28
+ type: 'Bearer token',
29
+ format: 'Authorization: Bearer np_live_xxx',
30
+ generateAt: 'https://netpad.io/settings',
31
+ },
32
+ documentation: 'https://docs.netpad.io/docs/developer/mcp-server',
13
33
  });
14
34
  }
package/api/mcp.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import type { VercelRequest, VercelResponse } from '@vercel/node';
2
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
2
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
4
3
  import { IncomingMessage, ServerResponse } from 'node:http';
5
- import { z } from 'zod';
4
+ import { createNetPadMcpServer } from '@netpad/mcp-server';
6
5
 
7
6
  // Store transports by session ID for reconnection
8
7
  const transports = new Map<string, StreamableHTTPServerTransport>();
@@ -131,542 +130,6 @@ async function validateApiKey(req: VercelRequest): Promise<{ status: number; err
131
130
  }
132
131
  }
133
132
 
134
- // Create and configure the MCP server with NetPad tools
135
- function createNetPadServer(): McpServer {
136
- const server = new McpServer({
137
- name: '@netpad/mcp-server-remote',
138
- version: '1.0.0',
139
- });
140
-
141
- // ============================================================================
142
- // RESOURCES - Documentation
143
- // ============================================================================
144
-
145
- server.resource(
146
- 'netpad-docs',
147
- 'netpad://docs/readme',
148
- async () => ({
149
- contents: [
150
- {
151
- uri: 'netpad://docs/readme',
152
- mimeType: 'text/markdown',
153
- text: `# NetPad MCP Server
154
-
155
- NetPad is a form builder and workflow automation platform.
156
-
157
- ## Quick Start
158
-
159
- Use the available tools to:
160
- - Generate forms from natural language descriptions
161
- - Create workflow automations
162
- - Browse and query MongoDB data
163
- - Search the marketplace for pre-built applications
164
-
165
- ## Available Tools
166
-
167
- - \`generate_form\` - Generate a complete form configuration
168
- - \`list_field_types\` - List all supported field types
169
- - \`list_form_templates\` - Browse pre-built form templates
170
- - \`create_form_from_template\` - Create a form from a template
171
- - \`list_workflow_templates\` - Browse workflow automation templates
172
-
173
- ## Extensions System
174
-
175
- NetPad supports extensions that add custom functionality:
176
-
177
- **Built-in Extensions:**
178
- - **@netpad/cloud-features**: Billing, Atlas provisioning, premium AI features (cloud only)
179
- - **@netpad/collaborate**: Community gallery and collaboration features
180
- - **@netpad/demo-node**: Example extension showing how to create custom workflow nodes (use as template)
181
-
182
- **Extension Capabilities:**
183
- - Custom API routes under /api/ext/{extension-name}/
184
- - Custom workflow node types (see @netpad/demo-node for example)
185
- - Shared services (billing, provisioning, analytics)
186
- - Request/response middleware
187
- - React UI components
188
- - Feature flags
189
-
190
- **Creating Custom Extensions:**
191
- Use @netpad/demo-node as a template:
192
- 1. Copy the demo-node package
193
- 2. Update package.json with your extension name
194
- 3. Modify the node definition and handler in src/index.ts
195
- 4. Export your extension as default
196
- 5. Install and enable via NETPAD_EXTENSIONS
197
-
198
- **Enabling Extensions:**
199
- Set NETPAD_EXTENSIONS environment variable:
200
- \`NETPAD_EXTENSIONS=@netpad/collaborate,@netpad/demo-node,@myorg/custom-extension\`
201
-
202
- **Example: Demo Node Extension**
203
- The @netpad/demo-node extension provides a "Log Message" workflow node that:
204
- - Logs messages with configurable levels (info/warn/error)
205
- - Supports {{variable}} syntax for dynamic values
206
- - Can pass through input data to downstream nodes
207
- - Demonstrates complete extension structure (metadata, node definition, handler, lifecycle hooks)
208
-
209
- For more information, visit https://netpad.io and https://docs.netpad.io/docs/extensions/overview
210
- `,
211
- },
212
- ],
213
- })
214
- );
215
-
216
- // ============================================================================
217
- // TOOLS - Form Building
218
- // ============================================================================
219
-
220
- server.tool(
221
- 'generate_form',
222
- 'Generate a complete NetPad form configuration from a natural language description',
223
- {
224
- description: z.string().describe('Description of the form to generate'),
225
- formName: z.string().describe('Name of the form'),
226
- includeMultiPage: z.boolean().optional().describe('Organize fields into multiple pages'),
227
- },
228
- async ({ description, formName, includeMultiPage }) => {
229
- const slug = formName.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
230
-
231
- // Parse description to generate appropriate fields
232
- const fields = parseDescriptionToFields(description);
233
-
234
- const config = {
235
- name: formName,
236
- slug,
237
- description,
238
- fieldConfigs: fields,
239
- multiPage: includeMultiPage ? {
240
- enabled: true,
241
- pages: [{ id: 'page-1', title: 'Form', fields: fields.map(f => f.path) }],
242
- } : undefined,
243
- };
244
-
245
- return {
246
- content: [
247
- {
248
- type: 'text',
249
- text: JSON.stringify(config, null, 2),
250
- },
251
- ],
252
- };
253
- }
254
- );
255
-
256
- server.tool(
257
- 'list_field_types',
258
- 'List all supported field types in NetPad forms',
259
- {},
260
- async () => {
261
- const fieldTypes = [
262
- { id: 'short_text', name: 'Short Text', description: 'Single line text input' },
263
- { id: 'long_text', name: 'Long Text', description: 'Multi-line textarea' },
264
- { id: 'email', name: 'Email', description: 'Email input with validation' },
265
- { id: 'phone', name: 'Phone', description: 'Phone number input' },
266
- { id: 'number', name: 'Number', description: 'Numeric input' },
267
- { id: 'date', name: 'Date', description: 'Date picker' },
268
- { id: 'time', name: 'Time', description: 'Time picker' },
269
- { id: 'datetime', name: 'Date & Time', description: 'Combined date and time picker' },
270
- { id: 'dropdown', name: 'Dropdown', description: 'Single select dropdown' },
271
- { id: 'multiple_choice', name: 'Multiple Choice', description: 'Radio button selection' },
272
- { id: 'checkboxes', name: 'Checkboxes', description: 'Multi-select checkboxes' },
273
- { id: 'yes_no', name: 'Yes/No', description: 'Boolean toggle' },
274
- { id: 'rating', name: 'Rating', description: 'Star rating input' },
275
- { id: 'slider', name: 'Slider', description: 'Range slider' },
276
- { id: 'file', name: 'File Upload', description: 'File attachment' },
277
- { id: 'image', name: 'Image Upload', description: 'Image upload with preview' },
278
- { id: 'signature', name: 'Signature', description: 'Signature capture' },
279
- { id: 'url', name: 'URL', description: 'URL input with validation' },
280
- { id: 'currency', name: 'Currency', description: 'Monetary value input' },
281
- { id: 'address', name: 'Address', description: 'Address autocomplete' },
282
- { id: 'section_header', name: 'Section Header', description: 'Section divider with title' },
283
- { id: 'paragraph', name: 'Paragraph', description: 'Static text/instructions' },
284
- { id: 'hidden', name: 'Hidden', description: 'Hidden field for data' },
285
- ];
286
-
287
- return {
288
- content: [
289
- {
290
- type: 'text',
291
- text: JSON.stringify(fieldTypes, null, 2),
292
- },
293
- ],
294
- };
295
- }
296
- );
297
-
298
- server.tool(
299
- 'list_form_templates',
300
- 'List available pre-built form templates',
301
- {
302
- category: z.string().optional().describe('Filter by category'),
303
- },
304
- async ({ category }) => {
305
- const templates = [
306
- { id: 'contact-form', name: 'Contact Form', category: 'Business', description: 'Basic contact form' },
307
- { id: 'lead-capture', name: 'Lead Capture', category: 'Business', description: 'Sales lead collection' },
308
- { id: 'newsletter', name: 'Newsletter Signup', category: 'Business', description: 'Email subscription' },
309
- { id: 'event-registration', name: 'Event Registration', category: 'Events', description: 'Event signup form' },
310
- { id: 'rsvp', name: 'RSVP', category: 'Events', description: 'Event RSVP form' },
311
- { id: 'customer-feedback', name: 'Customer Feedback', category: 'Feedback', description: 'Customer satisfaction survey' },
312
- { id: 'nps-survey', name: 'NPS Survey', category: 'Feedback', description: 'Net Promoter Score survey' },
313
- { id: 'support-ticket', name: 'Support Ticket', category: 'Support', description: 'Help desk ticket form' },
314
- { id: 'job-application', name: 'Job Application', category: 'HR', description: 'Employment application' },
315
- { id: 'patient-intake', name: 'Patient Intake', category: 'Healthcare', description: 'Medical intake form' },
316
- { id: 'order-form', name: 'Order Form', category: 'E-commerce', description: 'Product order form' },
317
- { id: 'expense-report', name: 'Expense Report', category: 'Finance', description: 'Expense submission form' },
318
- ];
319
-
320
- const filtered = category
321
- ? templates.filter(t => t.category.toLowerCase() === category.toLowerCase())
322
- : templates;
323
-
324
- return {
325
- content: [
326
- {
327
- type: 'text',
328
- text: JSON.stringify(filtered, null, 2),
329
- },
330
- ],
331
- };
332
- }
333
- );
334
-
335
- server.tool(
336
- 'create_form_from_template',
337
- 'Create a form configuration from a pre-built template',
338
- {
339
- templateId: z.string().describe('Template ID (e.g., "contact-form", "lead-capture")'),
340
- formName: z.string().describe('Name for the new form'),
341
- customizations: z.object({
342
- additionalFields: z.array(z.string()).optional(),
343
- removeFields: z.array(z.string()).optional(),
344
- }).optional().describe('Optional customizations'),
345
- },
346
- async ({ templateId, formName, customizations }) => {
347
- const templateConfigs: Record<string, { fields: Array<{ path: string; label: string; type: string; required?: boolean; options?: Array<{ label: string; value: string }> }> }> = {
348
- 'contact-form': {
349
- fields: [
350
- { path: 'name', label: 'Name', type: 'short_text', required: true },
351
- { path: 'email', label: 'Email', type: 'email', required: true },
352
- { path: 'phone', label: 'Phone', type: 'phone' },
353
- { path: 'message', label: 'Message', type: 'long_text', required: true },
354
- ],
355
- },
356
- 'lead-capture': {
357
- fields: [
358
- { path: 'firstName', label: 'First Name', type: 'short_text', required: true },
359
- { path: 'lastName', label: 'Last Name', type: 'short_text', required: true },
360
- { path: 'email', label: 'Work Email', type: 'email', required: true },
361
- { path: 'company', label: 'Company', type: 'short_text', required: true },
362
- { path: 'jobTitle', label: 'Job Title', type: 'short_text' },
363
- { path: 'phone', label: 'Phone', type: 'phone' },
364
- { path: 'interest', label: 'Interest', type: 'dropdown', options: [
365
- { label: 'Product Demo', value: 'demo' },
366
- { label: 'Pricing', value: 'pricing' },
367
- { label: 'Partnership', value: 'partnership' },
368
- { label: 'Other', value: 'other' },
369
- ]},
370
- ],
371
- },
372
- 'customer-feedback': {
373
- fields: [
374
- { path: 'satisfaction', label: 'Overall Satisfaction', type: 'rating', required: true },
375
- { path: 'recommend', label: 'How likely are you to recommend us?', type: 'slider' },
376
- { path: 'liked', label: 'What did you like?', type: 'checkboxes', options: [
377
- { label: 'Product Quality', value: 'quality' },
378
- { label: 'Customer Service', value: 'service' },
379
- { label: 'Pricing', value: 'pricing' },
380
- { label: 'Ease of Use', value: 'ease' },
381
- ]},
382
- { path: 'improvements', label: 'What could we improve?', type: 'long_text' },
383
- { path: 'email', label: 'Email (optional)', type: 'email' },
384
- ],
385
- },
386
- 'support-ticket': {
387
- fields: [
388
- { path: 'name', label: 'Name', type: 'short_text', required: true },
389
- { path: 'email', label: 'Email', type: 'email', required: true },
390
- { path: 'category', label: 'Category', type: 'dropdown', required: true, options: [
391
- { label: 'Technical Issue', value: 'technical' },
392
- { label: 'Billing', value: 'billing' },
393
- { label: 'Feature Request', value: 'feature' },
394
- { label: 'General Inquiry', value: 'general' },
395
- ]},
396
- { path: 'priority', label: 'Priority', type: 'multiple_choice', options: [
397
- { label: 'Low', value: 'low' },
398
- { label: 'Medium', value: 'medium' },
399
- { label: 'High', value: 'high' },
400
- { label: 'Critical', value: 'critical' },
401
- ]},
402
- { path: 'subject', label: 'Subject', type: 'short_text', required: true },
403
- { path: 'description', label: 'Description', type: 'long_text', required: true },
404
- { path: 'attachment', label: 'Attachment', type: 'file' },
405
- ],
406
- },
407
- };
408
-
409
- const template = templateConfigs[templateId];
410
- if (!template) {
411
- return {
412
- content: [
413
- {
414
- type: 'text',
415
- text: `Template "${templateId}" not found. Available templates: ${Object.keys(templateConfigs).join(', ')}`,
416
- },
417
- ],
418
- };
419
- }
420
-
421
- let fields = [...template.fields];
422
-
423
- if (customizations?.removeFields) {
424
- fields = fields.filter(f => !customizations.removeFields!.includes(f.path));
425
- }
426
-
427
- const slug = formName.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
428
-
429
- return {
430
- content: [
431
- {
432
- type: 'text',
433
- text: JSON.stringify({
434
- name: formName,
435
- slug,
436
- templateId,
437
- fieldConfigs: fields,
438
- }, null, 2),
439
- },
440
- ],
441
- };
442
- }
443
- );
444
-
445
- // ============================================================================
446
- // TOOLS - Workflow Templates
447
- // ============================================================================
448
-
449
- server.tool(
450
- 'list_workflow_templates',
451
- 'List available workflow automation templates',
452
- {},
453
- async () => {
454
- const templates = [
455
- {
456
- id: 'form-to-email',
457
- name: 'Form to Email',
458
- description: 'Send email notification on form submission',
459
- nodes: ['form-trigger', 'email-send'],
460
- },
461
- {
462
- id: 'form-to-database',
463
- name: 'Form to Database',
464
- description: 'Save form submissions to MongoDB',
465
- nodes: ['form-trigger', 'mongodb-insert'],
466
- },
467
- {
468
- id: 'lead-qualification',
469
- name: 'Lead Qualification',
470
- description: 'Score and route leads based on criteria',
471
- nodes: ['form-trigger', 'condition', 'email-send', 'slack-message'],
472
- },
473
- {
474
- id: 'scheduled-report',
475
- name: 'Scheduled Report',
476
- description: 'Generate and email periodic reports',
477
- nodes: ['schedule-trigger', 'mongodb-query', 'transform', 'email-send'],
478
- },
479
- {
480
- id: 'webhook-processor',
481
- name: 'Webhook Processor',
482
- description: 'Process incoming webhooks and store data',
483
- nodes: ['webhook-trigger', 'transform', 'mongodb-insert'],
484
- },
485
- ];
486
-
487
- return {
488
- content: [
489
- {
490
- type: 'text',
491
- text: JSON.stringify(templates, null, 2),
492
- },
493
- ],
494
- };
495
- }
496
- );
497
-
498
- server.tool(
499
- 'list_workflow_node_types',
500
- 'List available workflow node types for building automations',
501
- {
502
- category: z.string().optional().describe('Filter by category'),
503
- },
504
- async ({ category }) => {
505
- const nodeTypes = [
506
- // Triggers
507
- { id: 'form-trigger', name: 'Form Submission', category: 'Triggers', description: 'Trigger on form submission' },
508
- { id: 'webhook-trigger', name: 'Webhook', category: 'Triggers', description: 'Trigger on webhook call' },
509
- { id: 'schedule-trigger', name: 'Schedule', category: 'Triggers', description: 'Trigger on schedule (cron)' },
510
- { id: 'manual-trigger', name: 'Manual', category: 'Triggers', description: 'Trigger manually' },
511
-
512
- // Logic
513
- { id: 'condition', name: 'Condition', category: 'Logic', description: 'Branch based on conditions' },
514
- { id: 'switch', name: 'Switch', category: 'Logic', description: 'Multi-way branching' },
515
- { id: 'loop', name: 'Loop', category: 'Logic', description: 'Iterate over items' },
516
- { id: 'delay', name: 'Delay', category: 'Logic', description: 'Wait for duration' },
517
-
518
- // Data
519
- { id: 'transform', name: 'Transform', category: 'Data', description: 'Transform data with expressions' },
520
- { id: 'code', name: 'Code', category: 'Data', description: 'Run custom JavaScript' },
521
- { id: 'set-variable', name: 'Set Variable', category: 'Data', description: 'Set workflow variable' },
522
-
523
- // Database
524
- { id: 'mongodb-query', name: 'MongoDB Query', category: 'Database', description: 'Query MongoDB collection' },
525
- { id: 'mongodb-insert', name: 'MongoDB Insert', category: 'Database', description: 'Insert document' },
526
- { id: 'mongodb-update', name: 'MongoDB Update', category: 'Database', description: 'Update documents' },
527
- { id: 'mongodb-delete', name: 'MongoDB Delete', category: 'Database', description: 'Delete documents' },
528
-
529
- // Communication
530
- { id: 'email-send', name: 'Send Email', category: 'Communication', description: 'Send email via SMTP' },
531
- { id: 'slack-message', name: 'Slack Message', category: 'Communication', description: 'Send Slack message' },
532
- { id: 'http-request', name: 'HTTP Request', category: 'Communication', description: 'Make HTTP API call' },
533
-
534
- // AI
535
- { id: 'ai-generate', name: 'AI Generate', category: 'AI', description: 'Generate text with AI' },
536
- { id: 'ai-classify', name: 'AI Classify', category: 'AI', description: 'Classify with AI' },
537
- { id: 'ai-extract', name: 'AI Extract', category: 'AI', description: 'Extract structured data' },
538
- ];
539
-
540
- const filtered = category
541
- ? nodeTypes.filter(n => n.category.toLowerCase() === category.toLowerCase())
542
- : nodeTypes;
543
-
544
- return {
545
- content: [
546
- {
547
- type: 'text',
548
- text: JSON.stringify(filtered, null, 2),
549
- },
550
- ],
551
- };
552
- }
553
- );
554
-
555
- // ============================================================================
556
- // TOOLS - MongoDB Data Browser
557
- // ============================================================================
558
-
559
- server.tool(
560
- 'generate_mongodb_query',
561
- 'Generate a MongoDB query based on natural language description',
562
- {
563
- description: z.string().describe('Description of what to query'),
564
- collection: z.string().describe('Collection name'),
565
- operation: z.enum(['find', 'aggregate', 'count', 'distinct']).optional().describe('Query operation'),
566
- },
567
- async ({ description, collection, operation = 'find' }) => {
568
- // Simple query generation based on description
569
- const descLower = description.toLowerCase();
570
-
571
- let filter: Record<string, unknown> = {};
572
- let sort: Record<string, number> | undefined;
573
- let limit: number | undefined;
574
-
575
- if (descLower.includes('recent') || descLower.includes('latest')) {
576
- sort = { createdAt: -1 };
577
- limit = 10;
578
- }
579
-
580
- if (descLower.includes('active')) {
581
- filter['status'] = 'active';
582
- }
583
-
584
- if (descLower.includes('today')) {
585
- const today = new Date();
586
- today.setHours(0, 0, 0, 0);
587
- filter['createdAt'] = { $gte: today.toISOString() };
588
- }
589
-
590
- const query = {
591
- collection,
592
- operation,
593
- filter,
594
- sort,
595
- limit,
596
- code: operation === 'find'
597
- ? `db.collection('${collection}').find(${JSON.stringify(filter)})${sort ? `.sort(${JSON.stringify(sort)})` : ''}${limit ? `.limit(${limit})` : ''}.toArray()`
598
- : `db.collection('${collection}').${operation}(${JSON.stringify(filter)})`,
599
- };
600
-
601
- return {
602
- content: [
603
- {
604
- type: 'text',
605
- text: JSON.stringify(query, null, 2),
606
- },
607
- ],
608
- };
609
- }
610
- );
611
-
612
- return server;
613
- }
614
-
615
- // Helper function to parse natural language description into form fields
616
- function parseDescriptionToFields(description: string): Array<{
617
- path: string;
618
- label: string;
619
- type: string;
620
- required?: boolean;
621
- options?: Array<{ label: string; value: string }>;
622
- }> {
623
- const fields: Array<{
624
- path: string;
625
- label: string;
626
- type: string;
627
- required?: boolean;
628
- options?: Array<{ label: string; value: string }>;
629
- }> = [];
630
- const descLower = description.toLowerCase();
631
-
632
- // Common field patterns
633
- if (descLower.includes('name') || descLower.includes('contact')) {
634
- fields.push({ path: 'name', label: 'Name', type: 'short_text', required: true });
635
- }
636
- if (descLower.includes('email')) {
637
- fields.push({ path: 'email', label: 'Email', type: 'email', required: true });
638
- }
639
- if (descLower.includes('phone') || descLower.includes('contact')) {
640
- fields.push({ path: 'phone', label: 'Phone', type: 'phone' });
641
- }
642
- if (descLower.includes('message') || descLower.includes('comment') || descLower.includes('feedback')) {
643
- fields.push({ path: 'message', label: 'Message', type: 'long_text' });
644
- }
645
- if (descLower.includes('date') || descLower.includes('when')) {
646
- fields.push({ path: 'date', label: 'Date', type: 'date' });
647
- }
648
- if (descLower.includes('address') || descLower.includes('location')) {
649
- fields.push({ path: 'address', label: 'Address', type: 'address' });
650
- }
651
- if (descLower.includes('rating') || descLower.includes('score')) {
652
- fields.push({ path: 'rating', label: 'Rating', type: 'rating' });
653
- }
654
- if (descLower.includes('file') || descLower.includes('upload') || descLower.includes('attachment')) {
655
- fields.push({ path: 'file', label: 'File Upload', type: 'file' });
656
- }
657
-
658
- // If no fields detected, create basic contact fields
659
- if (fields.length === 0) {
660
- fields.push(
661
- { path: 'name', label: 'Name', type: 'short_text', required: true },
662
- { path: 'email', label: 'Email', type: 'email', required: true },
663
- { path: 'message', label: 'Message', type: 'long_text' }
664
- );
665
- }
666
-
667
- return fields;
668
- }
669
-
670
133
  // Main handler
671
134
  export default async function handler(req: VercelRequest, res: VercelResponse) {
672
135
  // Handle CORS preflight
@@ -698,7 +161,11 @@ export default async function handler(req: VercelRequest, res: VercelResponse) {
698
161
  sessionIdGenerator: () => crypto.randomUUID(),
699
162
  });
700
163
 
701
- const server = createNetPadServer();
164
+ // Create the full NetPad MCP server with all 80+ tools
165
+ const server = createNetPadMcpServer({
166
+ name: '@netpad/mcp-server-remote',
167
+ version: '1.1.0',
168
+ });
702
169
  await server.connect(transport);
703
170
 
704
171
  // Store transport for future requests
@@ -724,7 +191,11 @@ export default async function handler(req: VercelRequest, res: VercelResponse) {
724
191
  sessionIdGenerator: () => crypto.randomUUID(),
725
192
  });
726
193
 
727
- const server = createNetPadServer();
194
+ // Create the full NetPad MCP server with all 80+ tools
195
+ const server = createNetPadMcpServer({
196
+ name: '@netpad/mcp-server-remote',
197
+ version: '1.1.0',
198
+ });
728
199
  await server.connect(transport);
729
200
 
730
201
  if (transport.sessionId) {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@netpad/mcp-server-remote",
3
- "version": "1.0.1",
4
- "description": "Remote MCP server for NetPad - deployable to Vercel for Claude custom connectors",
5
- "author": "MongoDB",
3
+ "version": "1.2.0",
4
+ "description": "Remote MCP server for NetPad - deployable to Vercel for Claude custom connectors. Includes all 80+ tools from @netpad/mcp-server.",
5
+ "author": "Michael Lynn",
6
6
  "license": "Apache-2.0",
7
7
  "type": "module",
8
8
  "scripts": {
@@ -12,6 +12,7 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@modelcontextprotocol/sdk": "^1.0.0",
15
+ "@netpad/mcp-server": "file:../mcp-server",
15
16
  "zod": "^3.23.0"
16
17
  },
17
18
  "devDependencies": {