nodestorm-mcp 0.1.1 → 0.1.2

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
@@ -61,6 +61,8 @@ Note: Access tokens require an active NodeStorm subscription.
61
61
 
62
62
  ## Available Tools
63
63
 
64
+ At connect the server sends short instructions (0.1.2): what NodeStorm is, which tool a nodestorm.ai link maps to (`/files/N`, `/flows/N`, `/flow-runs/N`, `/help/slug`), and to read a node's doc with `get_doc` before `execute_node`. MCP clients such as Claude Code show them to the model at session start.
65
+
64
66
  ### create_flow
65
67
  Create a new workflow from a natural language description.
66
68
 
@@ -109,14 +111,6 @@ Input: { query: "pricing", scope: "user", limit: 20 }
109
111
  Output: { flows: [...], total }
110
112
  ```
111
113
 
112
- ### describe_nodes
113
- Get node type definitions (no API call).
114
-
115
- ```
116
- Input: { types: ["prompt", "list"] } // optional filter
117
- Output: { nodes: [{ type, description, category, config_schema, handles }] }
118
- ```
119
-
120
114
  ### get_flow_run
121
115
  Get details of a specific flow run, including execution results and node outputs.
122
116
 
@@ -141,14 +135,44 @@ Input: { query: "how did I set up the scraper flow", limit: 10 }
141
135
  Output: { messages: [...] }
142
136
  ```
143
137
 
138
+ ### execute_node
139
+ Run one node directly, without a flow. `config` is the node's `data` as in a flow; read the node's doc with `get_doc` first. Each call counts as one node execution against the monthly quota and is capped at about 90 seconds. Nodes that send or write take effect at once.
140
+
141
+ ```
142
+ Input: { node_type: "file", config: { mode: "read", file_id: 123 } } // read a file (nodestorm.ai/files/123)
143
+ Input: { node_type: "folder", config: { folder_id: "top" } } // list the files in a folder ("top" = no folder)
144
+ Input: { node_type: "prompt", config: { input: "Summarize" }, input: "..." }
145
+ Output: { success, node_type, output }
146
+ ```
147
+
148
+ ### list_docs
149
+ List NodeStorm product documentation pages. Pass `category` to filter (e.g. `"node"` for the node catalog).
150
+
151
+ ```
152
+ Input: { category: "node" } // optional filter
153
+ Output: { pages: [{ slug, title, category, description }] }
154
+ ```
155
+
156
+ ### get_doc
157
+ Get a documentation page by slug, including its full markdown body. Node pages use kebab-case slugs like `node-prompt` and `node-http-request`.
158
+
159
+ ```
160
+ Input: { slug: "workflow-execution" }
161
+ Output: { page: { slug, title, category, description, body, updated_at } }
162
+ ```
163
+
164
+ ### search_docs
165
+ Semantic (meaning-based) search over the NodeStorm documentation.
166
+
167
+ ```
168
+ Input: { query: "how does iteration work" }
169
+ Output: { results: [{ slug, title, category, chunk_content, relevance }] }
170
+ ```
171
+
144
172
  ## Resources
145
173
 
146
174
  ### workflow-guide
147
- Complete guide for building NodeStorm workflows. Read this resource to understand:
148
- - Node types and their configurations
149
- - Edge connection rules
150
- - Iteration patterns
151
- - Validation requirements
175
+ Pointer to the live NodeStorm docs. The bundled guide was replaced by the docs tools above — start with `get_doc("workflow-execution")` and `list_docs({ category: "node" })`.
152
176
 
153
177
  ## Example Usage
154
178
 
package/dist/client.d.ts CHANGED
@@ -29,7 +29,7 @@ export interface FlowRun {
29
29
  flow_id: number;
30
30
  flow_title: string;
31
31
  user_id?: number;
32
- status: 'success' | 'error' | 'pending' | 'running';
32
+ status: 'success' | 'partial' | 'error' | 'pending' | 'running';
33
33
  node_count: number;
34
34
  duration_seconds: number | null;
35
35
  result?: {
@@ -50,7 +50,7 @@ export interface FlowRunListItem {
50
50
  id: number;
51
51
  flow_id: number;
52
52
  flow_title: string;
53
- status: 'success' | 'error' | 'pending' | 'running';
53
+ status: 'success' | 'partial' | 'error' | 'pending' | 'running';
54
54
  node_count: number;
55
55
  duration_seconds: number | null;
56
56
  created_at: string;
@@ -104,6 +104,10 @@ export declare class NodeStormClient {
104
104
  schedule_enabled?: boolean;
105
105
  schedule_cron?: string;
106
106
  schedule_timezone?: string;
107
+ settings?: {
108
+ on_step_failure?: 'continue' | 'stop';
109
+ notify_on_failure?: boolean;
110
+ };
107
111
  }): Promise<Flow>;
108
112
  /**
109
113
  * Apply atomic structural operations (edit/add/remove nodes and edges) to an existing flow.
@@ -136,10 +140,24 @@ export declare class NodeStormClient {
136
140
  */
137
141
  listFlowRuns(options?: {
138
142
  flowId?: number;
139
- status?: 'success' | 'error' | 'pending' | 'running';
143
+ status?: 'success' | 'partial' | 'error' | 'pending' | 'running';
140
144
  page?: number;
141
145
  perPage?: number;
142
146
  }): Promise<FlowRunListResponse>;
147
+ /**
148
+ * List documentation pages, optionally filtered by category
149
+ */
150
+ listDocs(options?: {
151
+ category?: string;
152
+ }): Promise<DocListResponse>;
153
+ /**
154
+ * Get a documentation page by slug, including its full markdown body
155
+ */
156
+ getDoc(slug: string): Promise<DocPageResponse>;
157
+ /**
158
+ * Search documentation using semantic search
159
+ */
160
+ searchDocs(query: string): Promise<DocSearchResponse>;
143
161
  /**
144
162
  * Search chat message history using semantic search
145
163
  */
@@ -151,6 +169,42 @@ export declare class NodeStormClient {
151
169
  from?: string;
152
170
  to?: string;
153
171
  }): Promise<ChatSearchResponse>;
172
+ /**
173
+ * Execute a single node directly, outside any flow. Capped at ~90s server-side;
174
+ * long-running work belongs in a real flow.
175
+ */
176
+ executeNode(params: {
177
+ node_type: string;
178
+ config?: object;
179
+ input?: unknown;
180
+ }): Promise<ExecuteNodeResponse>;
181
+ }
182
+ export interface DocListItem {
183
+ slug: string;
184
+ title: string;
185
+ category: string;
186
+ visibility: string;
187
+ description: string | null;
188
+ }
189
+ export interface DocListResponse {
190
+ pages: DocListItem[];
191
+ }
192
+ export interface DocPage extends DocListItem {
193
+ body: string;
194
+ updated_at: string;
195
+ }
196
+ export interface DocPageResponse {
197
+ page: DocPage;
198
+ }
199
+ export interface DocSearchResult {
200
+ slug: string;
201
+ title: string;
202
+ category: string;
203
+ chunk_content: string;
204
+ relevance: number;
205
+ }
206
+ export interface DocSearchResponse {
207
+ results: DocSearchResult[];
154
208
  }
155
209
  export interface ChatSearchResult {
156
210
  content: string;
@@ -162,6 +216,12 @@ export interface ChatSearchResult {
162
216
  export interface ChatSearchResponse {
163
217
  results: ChatSearchResult[];
164
218
  }
219
+ export interface ExecuteNodeResponse {
220
+ success: boolean;
221
+ node_type: string;
222
+ /** The worker's result (NodeResult shape: { data, data_type, success, error?, metadata? }) */
223
+ output: unknown;
224
+ }
165
225
  export declare class NodeStormApiError extends Error {
166
226
  code: string;
167
227
  statusCode: number;
package/dist/client.js CHANGED
@@ -110,6 +110,31 @@ export class NodeStormClient {
110
110
  const path = queryString ? `/flow-runs?${queryString}` : '/flow-runs';
111
111
  return this.request(path);
112
112
  }
113
+ /**
114
+ * List documentation pages, optionally filtered by category
115
+ */
116
+ async listDocs(options = {}) {
117
+ const params = new URLSearchParams();
118
+ if (options.category)
119
+ params.append('category', options.category);
120
+ const queryString = params.toString();
121
+ const path = queryString ? `/docs?${queryString}` : '/docs';
122
+ return this.request(path);
123
+ }
124
+ /**
125
+ * Get a documentation page by slug, including its full markdown body
126
+ */
127
+ async getDoc(slug) {
128
+ return this.request(`/docs/${encodeURIComponent(slug)}`);
129
+ }
130
+ /**
131
+ * Search documentation using semantic search
132
+ */
133
+ async searchDocs(query) {
134
+ const params = new URLSearchParams();
135
+ params.append('q', query);
136
+ return this.request(`/docs/search?${params.toString()}`);
137
+ }
113
138
  /**
114
139
  * Search chat message history using semantic search
115
140
  */
@@ -128,6 +153,16 @@ export class NodeStormClient {
128
153
  params.append('to', options.to);
129
154
  return this.request(`/chat/search?${params.toString()}`);
130
155
  }
156
+ /**
157
+ * Execute a single node directly, outside any flow. Capped at ~90s server-side;
158
+ * long-running work belongs in a real flow.
159
+ */
160
+ async executeNode(params) {
161
+ return this.request('/nodes/execute', {
162
+ method: 'POST',
163
+ body: JSON.stringify(params),
164
+ });
165
+ }
131
166
  }
132
167
  export class NodeStormApiError extends Error {
133
168
  code;
package/dist/index.js CHANGED
@@ -8,17 +8,15 @@
8
8
  * - NODESTORM_API_KEY (required): API key for authentication
9
9
  * - NODESTORM_API_URL (optional): API base URL (default: https://nodestorm.ai)
10
10
  */
11
+ import { createRequire } from 'node:module';
11
12
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
12
13
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
13
14
  import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
14
15
  import { NodeStormClient, NodeStormApiError } from './client.js';
15
- import { getNodeDefinitions } from './tools/describe.js';
16
- import { readFileSync } from 'fs';
17
- import { fileURLToPath } from 'url';
18
- import { dirname, join } from 'path';
19
- // Get the directory of this file
20
- const __filename = fileURLToPath(import.meta.url);
21
- const __dirname = dirname(__filename);
16
+ import { DOCS_TOOL_DEFINITIONS } from './tools/docs.js';
17
+ import { EXECUTE_NODE_DESCRIPTION, SERVER_INSTRUCTIONS } from './instructions.js';
18
+ // One version string: package.json's. Before 0.1.2 this was hard-coded and drifted.
19
+ const { version: VERSION } = createRequire(import.meta.url)('../package.json');
22
20
  // Read environment variables
23
21
  const apiKey = process.env.NODESTORM_API_KEY;
24
22
  const apiUrl = process.env.NODESTORM_API_URL || 'https://nodestorm.ai';
@@ -28,25 +26,29 @@ if (!apiKey) {
28
26
  }
29
27
  // Initialize client
30
28
  const client = new NodeStormClient(apiKey, apiUrl);
31
- // Load workflow guide (bundled with package)
32
- function loadWorkflowGuide() {
33
- try {
34
- const guidePath = join(__dirname, 'workflow-guide.md');
35
- return readFileSync(guidePath, 'utf-8');
36
- }
37
- catch {
38
- return '# Workflow Guide\n\nGuide file not found. Please reinstall the package.';
39
- }
40
- }
29
+ // The bundled workflow guide was retired in favor of the live docs (see the docs tools).
30
+ // This pointer keeps the resource URI working for existing clients.
31
+ const WORKFLOW_GUIDE_POINTER = [
32
+ '# Workflow Guide',
33
+ '',
34
+ 'The workflow guide moved into the live NodeStorm docs.',
35
+ 'Use the `list_docs` / `get_doc` / `search_docs` tools instead of this resource.',
36
+ '',
37
+ "Start with `get_doc('workflow-execution')` for the execution model, and",
38
+ "`list_docs({ category: 'node' })` for the node catalog (slugs are kebab-case,",
39
+ 'e.g. `node-prompt`, `node-http-request`).',
40
+ ].join('\n');
41
41
  // Create MCP server
42
42
  const server = new Server({
43
43
  name: 'nodestorm-mcp',
44
- version: '0.1.0',
44
+ version: VERSION,
45
45
  }, {
46
46
  capabilities: {
47
47
  tools: {},
48
48
  resources: {},
49
49
  },
50
+ // 099.9: shown to the model at session start (URL → tool map, read docs first).
51
+ instructions: SERVER_INSTRUCTIONS,
50
52
  });
51
53
  // Tool definitions
52
54
  server.setRequestHandler(ListToolsRequestSchema, async () => {
@@ -97,8 +99,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
97
99
  },
98
100
  {
99
101
  name: 'update_flow',
100
- description: 'Update flow METADATA: name, description, schedule_*. Does NOT modify nodes or edges. ' +
101
- 'For any structural change use update_flow_structure.',
102
+ description: 'Update flow METADATA: name, description, schedule_*, and the flow settings ' +
103
+ '(settings.on_step_failure: "continue" | "stop"; settings.notify_on_failure: boolean). ' +
104
+ 'Does NOT modify nodes or edges. For any structural change use update_flow_structure.',
102
105
  inputSchema: {
103
106
  type: 'object',
104
107
  properties: {
@@ -114,7 +117,15 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
114
117
  description: { type: 'string' },
115
118
  schedule_enabled: { type: 'boolean' },
116
119
  schedule_cron: { type: 'string' },
117
- schedule_timezone: { type: 'string' },
120
+ schedule_timezone: { type: 'string', description: 'IANA name, e.g. America/New_York' },
121
+ settings: {
122
+ type: 'object',
123
+ description: 'Flow settings; keys sent are merged into the stored ones',
124
+ properties: {
125
+ on_step_failure: { type: 'string', enum: ['continue', 'stop'] },
126
+ notify_on_failure: { type: 'boolean' },
127
+ },
128
+ },
118
129
  },
119
130
  },
120
131
  },
@@ -177,7 +188,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
177
188
  description: 'Node payload. Server generates id if not provided.',
178
189
  properties: {
179
190
  id: { type: 'string' },
180
- type: { type: 'string', description: 'Node type — see describe_nodes for the catalog' },
191
+ type: {
192
+ type: 'string',
193
+ description: "Node type — see list_docs({category: 'node'}) for the catalog and get_doc for each node's schema",
194
+ },
181
195
  data: { type: 'object' },
182
196
  position: {
183
197
  type: 'object',
@@ -265,20 +279,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
265
279
  },
266
280
  },
267
281
  },
268
- {
269
- name: 'describe_nodes',
270
- description: 'Get node type definitions for building flows',
271
- inputSchema: {
272
- type: 'object',
273
- properties: {
274
- types: {
275
- type: 'array',
276
- items: { type: 'string' },
277
- description: "Filter to specific node types (e.g., ['prompt', 'list'])",
278
- },
279
- },
280
- },
281
- },
282
282
  {
283
283
  name: 'get_flow_run',
284
284
  description: 'Get details of a specific flow run by ID, including execution results and node outputs',
@@ -341,7 +341,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
341
341
  },
342
342
  status: {
343
343
  type: 'string',
344
- enum: ['success', 'error', 'pending', 'running'],
344
+ enum: ['success', 'partial', 'error', 'pending', 'running'],
345
345
  description: 'Filter by status',
346
346
  },
347
347
  page: {
@@ -355,6 +355,28 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
355
355
  },
356
356
  },
357
357
  },
358
+ {
359
+ name: 'execute_node',
360
+ description: EXECUTE_NODE_DESCRIPTION,
361
+ inputSchema: {
362
+ type: 'object',
363
+ properties: {
364
+ node_type: {
365
+ type: 'string',
366
+ description: "Node type to run — see list_docs({category: 'node'}) for the catalog",
367
+ },
368
+ config: {
369
+ type: 'object',
370
+ description: "Node configuration, same shape as the node's `data` in a flow",
371
+ },
372
+ input: {
373
+ description: 'Optional input passed as the parent node result (any JSON value)',
374
+ },
375
+ },
376
+ required: ['node_type'],
377
+ },
378
+ },
379
+ ...DOCS_TOOL_DEFINITIONS,
358
380
  ],
359
381
  };
360
382
  });
@@ -435,18 +457,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
435
457
  ],
436
458
  };
437
459
  }
438
- case 'describe_nodes': {
439
- const { types } = args;
440
- const nodes = getNodeDefinitions(types);
441
- return {
442
- content: [
443
- {
444
- type: 'text',
445
- text: JSON.stringify({ nodes }, null, 2),
446
- },
447
- ],
448
- };
449
- }
450
460
  case 'get_flow_run': {
451
461
  const { id } = args;
452
462
  const result = await client.getFlowRun(id);
@@ -488,6 +498,54 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
488
498
  ],
489
499
  };
490
500
  }
501
+ case 'execute_node': {
502
+ const { node_type, config, input } = args;
503
+ const result = await client.executeNode({ node_type, config, input });
504
+ return {
505
+ content: [
506
+ {
507
+ type: 'text',
508
+ text: JSON.stringify(result, null, 2),
509
+ },
510
+ ],
511
+ };
512
+ }
513
+ case 'list_docs': {
514
+ const { category } = args;
515
+ const result = await client.listDocs({ category });
516
+ return {
517
+ content: [
518
+ {
519
+ type: 'text',
520
+ text: JSON.stringify(result, null, 2),
521
+ },
522
+ ],
523
+ };
524
+ }
525
+ case 'get_doc': {
526
+ const { slug } = args;
527
+ const result = await client.getDoc(slug);
528
+ return {
529
+ content: [
530
+ {
531
+ type: 'text',
532
+ text: JSON.stringify(result, null, 2),
533
+ },
534
+ ],
535
+ };
536
+ }
537
+ case 'search_docs': {
538
+ const { query } = args;
539
+ const result = await client.searchDocs(query);
540
+ return {
541
+ content: [
542
+ {
543
+ type: 'text',
544
+ text: JSON.stringify(result, null, 2),
545
+ },
546
+ ],
547
+ };
548
+ }
491
549
  default:
492
550
  return {
493
551
  content: [
@@ -537,7 +595,7 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
537
595
  {
538
596
  uri: 'nodestorm://workflow-guide',
539
597
  name: 'Workflow Builder Guide',
540
- description: 'Complete guide for building NodeStorm flows: node types, edge rules, iteration semantics, validation, patterns, and examples',
598
+ description: 'Pointer to the live NodeStorm docs — use the list_docs / get_doc / search_docs tools instead',
541
599
  mimeType: 'text/markdown',
542
600
  },
543
601
  ],
@@ -547,13 +605,12 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
547
605
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
548
606
  const { uri } = request.params;
549
607
  if (uri === 'nodestorm://workflow-guide') {
550
- const guide = loadWorkflowGuide();
551
608
  return {
552
609
  contents: [
553
610
  {
554
611
  uri,
555
612
  mimeType: 'text/markdown',
556
- text: guide,
613
+ text: WORKFLOW_GUIDE_POINTER,
557
614
  },
558
615
  ],
559
616
  };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * What the server tells a client at connect (099.9). Shown to the model at
3
+ * session start, so it reaches the right tool first try instead of trying
4
+ * curl or a hosting dashboard on a nodestorm.ai link. Kept here, outside
5
+ * index.ts, so tests can import it without starting the server.
6
+ */
7
+ export declare const SERVER_INSTRUCTIONS = "NodeStorm runs recurring reports and tasks as flows of nodes (LLM prompts, search, scraping, files, tables, email, integrations). You act on one user's account through their access token.\n\nLinks from nodestorm.ai map to tools:\n- /files/N: execute_node {node_type: \"file\", config: {mode: \"read\", file_id: N}} returns the file's text.\n- /flows/N: get_flow {id: N}. /flows/N/runs: list_flow_runs {flow_id: N}. /flow-runs/N: get_flow_run {id: N}.\n- /help/SLUG: get_doc {slug: SLUG}.\nThere is no HTTP download for files or flows; do not fetch nodestorm.ai URLs directly.\n\nBefore execute_node or update_flow_structure, read the node's doc with get_doc (list_docs {category: \"node\"} lists them): the config keys come from there. Each execute_node call counts as one node execution against the user's monthly quota and is capped at about 90 seconds. Nodes that send or write (email, integrations, file create or update) take effect at once; confirm with the user first.";
8
+ export declare const EXECUTE_NODE_DESCRIPTION: string;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * What the server tells a client at connect (099.9). Shown to the model at
3
+ * session start, so it reaches the right tool first try instead of trying
4
+ * curl or a hosting dashboard on a nodestorm.ai link. Kept here, outside
5
+ * index.ts, so tests can import it without starting the server.
6
+ */
7
+ export const SERVER_INSTRUCTIONS = `NodeStorm runs recurring reports and tasks as flows of nodes (LLM prompts, search, scraping, files, tables, email, integrations). You act on one user's account through their access token.
8
+
9
+ Links from nodestorm.ai map to tools:
10
+ - /files/N: execute_node {node_type: "file", config: {mode: "read", file_id: N}} returns the file's text.
11
+ - /flows/N: get_flow {id: N}. /flows/N/runs: list_flow_runs {flow_id: N}. /flow-runs/N: get_flow_run {id: N}.
12
+ - /help/SLUG: get_doc {slug: SLUG}.
13
+ There is no HTTP download for files or flows; do not fetch nodestorm.ai URLs directly.
14
+
15
+ Before execute_node or update_flow_structure, read the node's doc with get_doc (list_docs {category: "node"} lists them): the config keys come from there. Each execute_node call counts as one node execution against the user's monthly quota and is capped at about 90 seconds. Nodes that send or write (email, integrations, file create or update) take effect at once; confirm with the user first.`;
16
+ export const EXECUTE_NODE_DESCRIPTION = 'Run a single NodeStorm node directly, without creating a flow — any node type. ' +
17
+ "config is identical to the node's `data` in a flow (see the node's doc via get_doc); " +
18
+ 'optional `input` is passed to the node as its parent result. ' +
19
+ 'Recipes: read a file (a nodestorm.ai/files/N link): {node_type: "file", config: {mode: "read", file_id: N}}. ' +
20
+ 'List the files in a folder: {node_type: "folder", config: {folder_id: ID}}, with folder_id "top" for files in no folder. ' +
21
+ 'Each call counts as one node execution against the monthly quota. ' +
22
+ 'Runs that send or write take effect immediately; confirm with your user first. ' +
23
+ 'Capped at ~90 seconds — long-running work belongs in a real flow instead.';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Docs tool definitions for the docs endpoints
3
+ * NodeStorm product documentation — node behavior, workflow mechanics, guides.
4
+ * These wrap the backend's v1 docs endpoints via NodeStormClient.
5
+ */
6
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
7
+ export declare const DOCS_TOOL_DEFINITIONS: Tool[];
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Docs tool definitions for the docs endpoints
3
+ * NodeStorm product documentation — node behavior, workflow mechanics, guides.
4
+ * These wrap the backend's v1 docs endpoints via NodeStormClient.
5
+ */
6
+ export const DOCS_TOOL_DEFINITIONS = [
7
+ {
8
+ name: 'list_docs',
9
+ description: 'List NodeStorm product documentation pages — node behavior, workflow mechanics, guides. ' +
10
+ 'Returns slug, title, category, and description for each page. Pass `category` to filter.',
11
+ inputSchema: {
12
+ type: 'object',
13
+ properties: {
14
+ category: {
15
+ type: 'string',
16
+ description: "Filter to a single category (e.g., 'node', 'guide', 'help')",
17
+ },
18
+ },
19
+ },
20
+ },
21
+ {
22
+ name: 'get_doc',
23
+ description: 'Get a NodeStorm documentation page by slug, including its full markdown body. ' +
24
+ 'Use list_docs or search_docs to find slugs.',
25
+ inputSchema: {
26
+ type: 'object',
27
+ properties: {
28
+ slug: {
29
+ type: 'string',
30
+ description: 'Page slug (from list_docs or search_docs results)',
31
+ },
32
+ },
33
+ required: ['slug'],
34
+ },
35
+ },
36
+ {
37
+ name: 'search_docs',
38
+ description: 'Search NodeStorm product documentation using semantic (meaning-based) search. ' +
39
+ 'Returns matching content chunks ranked by relevance to the query.',
40
+ inputSchema: {
41
+ type: 'object',
42
+ properties: {
43
+ query: {
44
+ type: 'string',
45
+ description: 'Natural language search query',
46
+ },
47
+ },
48
+ required: ['query'],
49
+ },
50
+ },
51
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodestorm-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "MCP server for NodeStorm workflow automation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,7 +12,7 @@
12
12
  "dist"
13
13
  ],
14
14
  "scripts": {
15
- "build": "tsc && cp src/workflow-guide.md dist/",
15
+ "build": "tsc",
16
16
  "dev": "tsc --watch",
17
17
  "start": "node dist/index.js",
18
18
  "test": "vitest run",
@@ -1,18 +0,0 @@
1
- /**
2
- * Node definitions for the describe_nodes tool
3
- * These are bundled statically to avoid API calls
4
- */
5
- export interface NodeDefinition {
6
- type: string;
7
- description: string;
8
- category: string;
9
- config_schema: Record<string, any>;
10
- handles: {
11
- inputs: string[];
12
- outputs: string[];
13
- };
14
- }
15
- /**
16
- * Get node definitions, optionally filtered by type
17
- */
18
- export declare function getNodeDefinitions(types?: string[]): NodeDefinition[];