fmea-api-mcp-server 1.1.3 → 1.1.5

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/dist/index.js CHANGED
@@ -7,55 +7,32 @@ import * as fsSync from "fs";
7
7
  import * as path from "path";
8
8
  import { fileURLToPath } from "url";
9
9
  import { getSynonyms } from "./synonyms.js";
10
+ // @ts-ignore
11
+ import { stemmer } from "stemmer";
10
12
  const __filename = fileURLToPath(import.meta.url);
11
13
  const __dirname = path.dirname(__filename);
14
+ // Domain terms that should NOT be stemmed
15
+ const DOMAIN_TERMS = new Set([
16
+ "fmea", "bom", "api", "uuid", "id", "url", "uri", "json", "xml", "html", "css", "js", "ts"
17
+ ]);
12
18
  /**
13
- * Normalize token to singular form for better matching.
14
- * Handles common English plural patterns.
19
+ * Intelligent Stemming Helper with Domain Protection
20
+ * 1. Checks if token is a protected domain term (returns as-is)
21
+ * 2. Checks length (skips short words <= 2 chars)
22
+ * 3. Applies Porter Stemmer
15
23
  */
16
- function normalizeToken(token) {
17
- const normalized = [token];
18
- // Simple pluralization rules (token -> singular or singular -> plural)
19
- const rules = [
20
- // Remove 's' for common plurals
21
- [/([a-z]+)s$/, '$1'],
22
- // Remove 'es' for words ending with s, x, z, ch, sh
23
- [/([a-z]+)es$/, '$1'],
24
- // Remove 'ies' and replace with 'y'
25
- [/([a-z]+)ies$/, '$1y'],
26
- // Remove 'ves' and replace with 'f' (leaf -> leaves)
27
- [/([a-z]+)ves$/, '$1f'],
28
- // Remove 'men' and replace with 'man' (woman -> women)
29
- [/([a-z]+)men$/, '$1man'],
30
- ];
31
- // Generate singular variants
32
- for (const [pattern, replacement] of rules) {
33
- if (pattern.test(token)) {
34
- const singular = token.replace(pattern, replacement);
35
- if (singular !== token && singular.length > 2) {
36
- normalized.push(singular);
37
- }
38
- break;
39
- }
24
+ function stemToken(token) {
25
+ const lower = token.toLowerCase();
26
+ // Rule 1: Protected Domain Terms
27
+ if (DOMAIN_TERMS.has(lower)) {
28
+ return lower;
40
29
  }
41
- // Add plural variant (append 's' if not ending with 's')
42
- if (!token.endsWith('s') && token.length > 2) {
43
- normalized.push(token + 's');
30
+ // Rule 2: Skip very short words
31
+ if (lower.length <= 2) {
32
+ return lower;
44
33
  }
45
- return normalized;
46
- }
47
- /**
48
- * Expand tokens to include singular/plural variants
49
- */
50
- function expandTokenVariants(tokens) {
51
- const variants = new Set(tokens);
52
- for (const token of tokens) {
53
- const normalized = normalizeToken(token);
54
- for (const variant of normalized) {
55
- variants.add(variant);
56
- }
57
- }
58
- return variants;
34
+ // Rule 3: Apply Stemmer
35
+ return stemmer(lower);
59
36
  }
60
37
  // Directory where endpoint definitions are stored.
61
38
  // Priority:
@@ -334,13 +311,14 @@ class ApiDocsServer {
334
311
  (endpoint.path || "").toLowerCase()
335
312
  ].join(" ");
336
313
  const tokens = searchableText.split(/\s+/).filter(t => t.length > 0);
337
- // Expand document tokens with singular/plural variants
338
- const expandedTokens = Array.from(expandTokenVariants(tokens));
314
+ // Stemming tokens for Indexing
315
+ const stemmedTokens = tokens.map(token => stemToken(token));
339
316
  documents.push({
340
317
  file: fileName,
341
318
  ...endpoint,
342
- tokens: expandedTokens, // Expanded tokens for BM25 calculation
343
- docLength: expandedTokens.length
319
+ // Use stemmed tokens for matching and BM25
320
+ tokens: stemmedTokens,
321
+ docLength: stemmedTokens.length
344
322
  });
345
323
  }
346
324
  }
@@ -356,11 +334,10 @@ class ApiDocsServer {
356
334
  message: `No results found for '${query}'.`
357
335
  };
358
336
  }
359
- // 2. Query Processing (Synonyms + AND Logic)
337
+ // 2. Query Processing
360
338
  const rawQueryTokens = query.toLowerCase().split(/\s+/).filter(t => t.length > 0);
361
339
  // Check for Wildcard
362
340
  if (rawQueryTokens.length === 0 || (rawQueryTokens.length === 1 && rawQueryTokens[0] === "*")) {
363
- // Slice for pagination
364
341
  const LIMIT = 10;
365
342
  const totalPages = Math.ceil(totalFound / LIMIT);
366
343
  const currentPage = Math.max(1, page);
@@ -372,15 +349,27 @@ class ApiDocsServer {
372
349
  meta: { total: totalFound, page: currentPage, totalPages: totalPages }
373
350
  };
374
351
  }
375
- // Filter Documents: AND Logic with Synonym Expansion + Plural/Singular Normalization
376
- // Every query token (or one of its synonyms/plurals) MUST be present in the document
352
+ // Filter Documents: AND Logic with Stemming + Synonyms
353
+ // Step: Query Token -> Stem -> Synonyms -> Stem Synonyms -> Match Document Stems
377
354
  const filteredDocs = documents.filter(doc => {
378
355
  return rawQueryTokens.every(qToken => {
379
- // Get synonyms first
380
- const synonyms = getSynonyms(qToken);
381
- // Expand with plural/singular variants
382
- const expandedQuery = Array.from(expandTokenVariants(synonyms));
383
- return expandedQuery.some((variant) => doc.tokens.includes(variant));
356
+ // 1. Stem the query token first (e.g. "parsing" -> "pars")
357
+ // But wait, synonyms often map "parse" -> "parsing".
358
+ // If we stem query first, we might miss synonym keys.
359
+ // BETTER STRATEGY: Get synonyms for RAW token, THEN stem everything.
360
+ const synonyms = getSynonyms(qToken); // e.g. "upload" -> ["post", "send"...]
361
+ // Stem the query token and all its synonyms
362
+ // e.g. "uploaded" -> stem("uploaded")="upload"
363
+ // synonyms("uploaded") might be empty if map uses root forms.
364
+ // So we should try:
365
+ // A. Synonyms of raw token
366
+ // B. Synonyms of stemmed token ? - Maybe overkill, let's stick to A for now.
367
+ const searchTerms = new Set();
368
+ synonyms.forEach(s => searchTerms.add(stemToken(s)));
369
+ // Also stem the query token itself regardless of synonyms
370
+ searchTerms.add(stemToken(qToken));
371
+ // Check if ANY of the stemmed search terms exist in the document's stemmed tokens
372
+ return Array.from(searchTerms).some(term => doc.tokens.includes(term));
384
373
  });
385
374
  });
386
375
  if (filteredDocs.length === 0) {
@@ -390,22 +379,15 @@ class ApiDocsServer {
390
379
  };
391
380
  }
392
381
  // 3. BM25 Calculation on Filtered Docs
393
- // Context: We calculate stats based on the *filtered* corpus or *full* corpus?
394
- // Standard BM25 usages often use full corpus stats for IDF. We will use full corpus stats.
395
382
  const k1 = 1.2;
396
383
  const b = 0.75;
397
384
  const avgdl = documents.reduce((acc, doc) => acc + doc.docLength, 0) / totalFound;
398
- // Calculate IDF (using full corpus) for *expanded* tokens (synonyms + plurals)
399
- // We expand query terms with both synonyms and plural/singular variants
385
+ // Calculate IDF (using full corpus) for stemmed terms
400
386
  const allQueryTerms = new Set();
401
387
  rawQueryTokens.forEach(t => {
402
388
  const synonyms = getSynonyms(t);
403
- synonyms.forEach((s) => {
404
- allQueryTerms.add(s);
405
- // Also add plural/singular variants
406
- const variants = normalizeToken(s);
407
- variants.forEach(v => allQueryTerms.add(v));
408
- });
389
+ synonyms.forEach(s => allQueryTerms.add(stemToken(s)));
390
+ allQueryTerms.add(stemToken(t));
409
391
  });
410
392
  const idf = {};
411
393
  for (const term of allQueryTerms) {
@@ -420,11 +402,11 @@ class ApiDocsServer {
420
402
  let scoredDocs = filteredDocs.map(doc => {
421
403
  let score = 0;
422
404
  for (const qToken of rawQueryTokens) {
423
- // Find which synonyms + plural variants of qToken are present in this doc
424
405
  const synonyms = getSynonyms(qToken);
425
- const expandedQuery = Array.from(expandTokenVariants(synonyms));
426
- const presentTerms = expandedQuery.filter((term) => doc.tokens.includes(term));
427
- // Sum up scores for all matching terms (synonyms + plurals)
406
+ const searchTerms = new Set();
407
+ synonyms.forEach(s => searchTerms.add(stemToken(s)));
408
+ searchTerms.add(stemToken(qToken));
409
+ const presentTerms = Array.from(searchTerms).filter(term => doc.tokens.includes(term));
428
410
  for (const term of presentTerms) {
429
411
  const f_q = doc.tokens.filter((t) => t === term).length;
430
412
  const numerator = idf[term] * f_q * (k1 + 1);
@@ -446,12 +428,8 @@ class ApiDocsServer {
446
428
  const slice = scoredDocs.slice(start, start + LIMIT);
447
429
  // Post-processing: Add warnings for V1 endpoints AND strip heavy fields
448
430
  const finalResults = await Promise.all(slice.map(async (item) => {
449
- // Deconstruct to remove heavy fields (parameters, requestBody, responses, tags) and internal scoring props
450
431
  const { score, tokens, docLength, parameters, requestBody, responses, tags, file, ...lightweightItem } = item;
451
432
  if (lightweightItem.path && lightweightItem.path.includes("/v1/")) {
452
- // Check for V1 Deprecation
453
- // Always generate a warning for v1 endpoints using the 3-step logic
454
- // We do this check after determining it is a v1 endpoint
455
433
  lightweightItem.warning = await this.generateDeprecationWarning(lightweightItem.path, lightweightItem.method);
456
434
  }
457
435
  return lightweightItem;
@@ -488,10 +466,6 @@ class ApiDocsServer {
488
466
  };
489
467
  // Check for V1 Deprecation
490
468
  if (apiPath.includes("/v1/")) {
491
- // Check for V1 Deprecation
492
- // Always generate a warning for v1 endpoints using the 3-step logic
493
- // We do this check regardless of whether a direct v2 exists or not,
494
- // because generateDeprecationWarning handles all cases.
495
469
  result.warning = await this.generateDeprecationWarning(apiPath, method);
496
470
  }
497
471
  return result;
package/dist/synonyms.js CHANGED
@@ -1,22 +1,49 @@
1
1
  export const SYNONYM_GROUPS = {
2
2
  // Read / Retrieve
3
- "get": ["fetch", "retrieve", "read", "load", "find", "search", "query", "list", "show"],
4
- "find": ["get", "search", "retrieve", "lookup", "show"],
5
- "search": ["find", "get", "query", "lookup", "show"],
6
- "show": ["get", "display", "view", "fetch", "find"],
7
- "list": ["get", "all", "collection", "show", "summary"],
8
- "summary": ["list", "all", "overview", "collection"],
3
+ "get": ["fetch", "retrieve", "read", "load", "find", "search", "query", "list", "show", "details"],
4
+ "find": ["get", "search", "retrieve", "lookup", "show", "detect", "locate"],
5
+ "search": ["find", "get", "query", "lookup", "show", "explore", "scan"],
6
+ "show": ["get", "display", "view", "fetch", "find", "present"],
7
+ "list": ["get", "all", "collection", "show", "summary", "index", "catalog"],
8
+ "summary": ["list", "all", "overview", "collection", "report", "stats"],
9
9
  // Create
10
- "create": ["add", "insert", "make", "new", "post", "generate"],
11
- "add": ["create", "insert", "append", "attach"],
12
- "post": ["create", "add", "submit"],
10
+ "create": ["add", "insert", "make", "new", "post", "generate", "build", "register", "init"],
11
+ "add": ["create", "insert", "append", "attach", "include", "push"],
12
+ "post": ["create", "add", "submit", "send", "upload"],
13
+ "generate": ["create", "make", "build", "produce", "render"],
13
14
  // Update
14
- "update": ["modify", "edit", "change", "save", "put", "patch", "set"],
15
- "modify": ["update", "edit", "change", "adjust"],
16
- "save": ["update", "store", "persist", "write"],
15
+ "update": ["modify", "edit", "change", "save", "put", "patch", "set", "refresh", "renew", "upgrade"],
16
+ "modify": ["update", "edit", "change", "adjust", "alter", "tweak"],
17
+ "save": ["update", "store", "persist", "write", "record", "commit"],
18
+ "set": ["update", "assign", "define", "configure", "specify"],
17
19
  // Delete
18
- "delete": ["remove", "destroy", "clear", "erase", "drop"],
19
- "remove": ["delete", "detach", "discard"]
20
+ "delete": ["remove", "destroy", "clear", "erase", "drop", "cancel", "archive", "unlink"],
21
+ "remove": ["delete", "detach", "discard", "exclude", "strip"],
22
+ // Processing / Execution (New)
23
+ "parse": ["parsing", "read", "decode", "interpret", "analyze", "extract", "scan"],
24
+ "parsing": ["parse", "reading", "decoding", "interpreting", "analyzing"],
25
+ "process": ["processing", "run", "execute", "handle", "compute", "perform", "analyzing"],
26
+ "processing": ["process", "running", "execution", "handling", "computing"],
27
+ "execute": ["run", "launch", "start", "trigger", "invoke", "call", "process"],
28
+ "run": ["execute", "start", "launch", "go", "process"],
29
+ // File / Data Handling (New)
30
+ "upload": ["post", "send", "import", "attach", "submit"],
31
+ "import": ["upload", "include", "load", "read", "ingest"],
32
+ "export": ["download", "save", "extract", "dump", "backup"],
33
+ "download": ["get", "fetch", "retrieve", "export", "pull"],
34
+ "copy": ["duplicate", "clone", "replicate", "mirror"],
35
+ "move": ["transfer", "relocate", "rename", "shift", "migrate"],
36
+ // Auth / Security (New)
37
+ "auth": ["authentication", "login", "signin", "verify", "check", "token", "credential"],
38
+ "login": ["signin", "auth", "authenticate", "connect", "access"],
39
+ "logout": ["signout", "disconnect", "exit", "leave"],
40
+ "verify": ["check", "validate", "confirm", "auth", "authorize", "test"],
41
+ "check": ["verify", "validate", "test", "inspect", "assess", "status"],
42
+ // General / Utilities (New)
43
+ "config": ["configuration", "settings", "setup", "options", "preferences", "profile"],
44
+ "settings": ["config", "preferences", "options", "profile", "properties"],
45
+ "connect": ["link", "join", "pair", "attach", "login", "bind"],
46
+ "disconnect": ["unlink", "detach", "logout", "close", "break"]
20
47
  };
21
48
  /**
22
49
  * Expands a single token into a list of synonyms including itself.
@@ -46,6 +46,9 @@ To prevent ambiguity, follow these classification principles:
46
46
  - `operationId`: String (Unique identifier)
47
47
  - `parameters`: Array (Optional parameters)
48
48
  - `responses`: Object (Response definitions)
49
+ - `x-dependency-warning`: String (Optional). **URGENT**: When an endpoint depends on a prior initiation step (like file upload), this field MUST be included. It should state "REQUIRES PRIOR {ACTION} via [{METHOD} {PATH}]".
50
+
51
+ ### Example
49
52
 
50
53
  ### Example
51
54
 
@@ -56,3 +59,42 @@ endpoints/v1/projects/
56
59
  ├── data.json
57
60
  └── recommendations.json
58
61
  ```
62
+
63
+ ## Advanced Patterns & Dependencies
64
+
65
+ To ensure AI agents correctly navigate complex workflows, strict patterns for dependency management are enforced.
66
+
67
+ ### 1. Documentation Standard: `x-dependency-warning`
68
+
69
+ When an endpoint depends on a prior initiation step (e.g., file upload, login), the definition MUST include the `x-dependency-warning` field.
70
+
71
+ - **Field**: `x-dependency-warning`
72
+ - **Value Format**: `"REQUIRES PRIOR {ACTION} via [{METHOD} {PATH}]. {CONTEXT}"`
73
+ - **Example**:
74
+ ```json
75
+ "x-dependency-warning": "REQUIRES PRIOR FILE UPLOAD via [POST /api/v2/files]. The {uuid} parameter is the file ID returned by the upload endpoint."
76
+ ```
77
+
78
+ ### 2. Workflow Pattern: File Upload & Processing
79
+
80
+ This is the canonical pattern for handling file-based operations in this API.
81
+
82
+ **The Workflow:**
83
+ 1. **Initiator**: Client uploads a file via `POST /api/v2/files` -> Returns `{uuid}`.
84
+ 2. **Consumer**: Client calls processing endpoints (e.g., `GET /api/v2/excel/{uuid}`) using that `{uuid}`.
85
+
86
+ **AI Operational Protocol:**
87
+ When this pattern is identified (via `x-dependency-warning` or path analysis), the AI MUST:
88
+
89
+ 1. **Stop & Check**: If the user requests a "Consumer" action, verify if a file `uuid` is available in context.
90
+ 2. **Propose Initiator**: If no `uuid` exists, explicitly propose the file upload step first.
91
+ 3. **Auto-Chain**: Once the upload is complete, capture the `uuid` and automatically apply it to subsequent steps without asking the user.
92
+
93
+ ### 3. Identification Criteria
94
+
95
+ Use these signals to identify dependency roles if `x-dependency-warning` is missing:
96
+
97
+ | Role | Signals |
98
+ | :--- | :--- |
99
+ | **Initiator** | Path ends in `/files`, `/upload`; Method is `POST`; Returns an ID. |
100
+ | **Consumer** | Path contains `{uuid}`; Logic involves parsing/extracting; Does *not* create `{uuid}` resource. |
@@ -6,6 +6,7 @@
6
6
  {
7
7
  "path": "/api/v1/projects/{projectId}/blockdiagrams/{blockId}/nodes/{nodeId}/failuremodes",
8
8
  "method": "GET",
9
+ "operationId": "findByNodeId",
9
10
  "summary": "Find Failure Modes",
10
11
  "description": "Retrieve failure modes for a specific node in a block diagram",
11
12
  "tags": [],
@@ -48,6 +49,7 @@
48
49
  {
49
50
  "path": "/api/v1/projects/{projectId}/blockdiagrams/{blockId}/nodes/{nodeId}/failuremodes",
50
51
  "method": "DELETE",
52
+ "operationId": "deleteByNodeId",
51
53
  "summary": "Delete Failure Modes",
52
54
  "description": "Delete failure modes for a specific node in a block diagram",
53
55
  "tags": [],
@@ -102,6 +104,7 @@
102
104
  {
103
105
  "path": "/api/v1/projects/{projectId}/blockdiagrams/{blockId}/failuremodes/import-from-project",
104
106
  "method": "POST",
107
+ "operationId": "importFromProject",
105
108
  "summary": "Import Failure Modes from Project",
106
109
  "description": "Import failure modes from another project",
107
110
  "tags": [],
@@ -144,6 +147,7 @@
144
147
  {
145
148
  "path": "/api/v1/projects/{projectId}/blockdiagrams/{blockId}/failuremodes",
146
149
  "method": "POST",
150
+ "operationId": "saveAll",
147
151
  "summary": "Save All Failure Modes",
148
152
  "description": "Save multiple failure modes for a block diagram",
149
153
  "tags": [],
@@ -190,6 +194,7 @@
190
194
  {
191
195
  "path": "/api/v1/projects/{projectId}/failuremods/{fmmId}/fmmdiagram",
192
196
  "method": "GET",
197
+ "operationId": "listFmmDiagram",
193
198
  "summary": "List FMM Diagram",
194
199
  "description": "Retrieve FMM diagram for a specific failure mode",
195
200
  "tags": [],
@@ -224,6 +229,7 @@
224
229
  {
225
230
  "path": "/api/v1/projects/{projectId}/failuremods/{topEventId}/fta",
226
231
  "method": "GET",
232
+ "operationId": "listFta",
227
233
  "summary": "List FTA",
228
234
  "description": "Retrieve Fault Tree Analysis for a failure mode",
229
235
  "tags": [],
@@ -258,6 +264,7 @@
258
264
  {
259
265
  "path": "/api/v1/projects/{projectId}/failuremods/{topEventId}/fta",
260
266
  "method": "POST",
267
+ "operationId": "saveFta",
261
268
  "summary": "Save FTA",
262
269
  "description": "Save Fault Tree Analysis for a failure mode",
263
270
  "tags": [],
@@ -185,6 +185,7 @@
185
185
  "path": "/api/v2/projects/{projectId}/block-diagrams-excel/{uuid}/data",
186
186
  "method": "GET",
187
187
  "operationId": "getData",
188
+ "x-dependency-warning": "REQUIRES PRIOR FILE UPLOAD via [POST /api/v2/files]. The {uuid} parameter is the file ID returned by the upload endpoint.",
188
189
  "summary": "Get block diagram Excel data",
189
190
  "description": "Get data from block diagram Excel file",
190
191
  "tags": [],
@@ -0,0 +1,73 @@
1
+ {
2
+ "category": "excel",
3
+ "version": "v2",
4
+ "description": "Excel parsing endpoints for analyzing uploaded Excel files",
5
+ "endpoints": [
6
+ {
7
+ "path": "/api/v2/excel/{uuid}",
8
+ "method": "GET",
9
+ "summary": "Parse all sheets in Excel file",
10
+ "description": "Parse and retrieve all sheets from an uploaded Excel file identified by its UUID",
11
+ "tags": ["excel"],
12
+ "operationId": "parseAll",
13
+ "x-dependency-warning": "REQUIRES PRIOR FILE UPLOAD via [POST /api/v2/files]. The {uuid} parameter is the file ID returned by the upload endpoint.",
14
+ "parameters": [
15
+ {
16
+ "name": "uuid",
17
+ "in": "path",
18
+ "required": true,
19
+ "schema": {
20
+ "type": "string"
21
+ },
22
+ "description": "UUID of the uploaded Excel file"
23
+ }
24
+ ],
25
+ "responses": {
26
+ "default": {
27
+ "description": "default response",
28
+ "content": {
29
+ "application/json": {}
30
+ }
31
+ }
32
+ }
33
+ },
34
+ {
35
+ "path": "/api/v2/excel/{uuid}/sheets/{sheetIndex}",
36
+ "method": "GET",
37
+ "summary": "Parse specific sheet in Excel file",
38
+ "description": "Parse and retrieve a specific sheet from an uploaded Excel file by its index",
39
+ "tags": ["excel"],
40
+ "operationId": "parseSheet",
41
+ "x-dependency-warning": "REQUIRES PRIOR FILE UPLOAD via [POST /api/v2/files]. The {uuid} parameter is the file ID returned by the upload endpoint.",
42
+ "parameters": [
43
+ {
44
+ "name": "uuid",
45
+ "in": "path",
46
+ "required": true,
47
+ "schema": {
48
+ "type": "string"
49
+ },
50
+ "description": "UUID of the uploaded Excel file"
51
+ },
52
+ {
53
+ "name": "sheetIndex",
54
+ "in": "path",
55
+ "required": true,
56
+ "schema": {
57
+ "type": "integer",
58
+ "format": "int32"
59
+ },
60
+ "description": "Zero-based index of the sheet to parse"
61
+ }
62
+ ],
63
+ "responses": {
64
+ "default": {
65
+ "description": "default response",
66
+ "content": {
67
+ "application/json": {}
68
+ }
69
+ }
70
+ }
71
+ }
72
+ ]
73
+ }
@@ -6,6 +6,7 @@
6
6
  {
7
7
  "path": "/api/v2/projects/{projectId}/block-diagrams/{blockDiagramId}/failure-modes/{failureModeId}",
8
8
  "method": "GET",
9
+ "operationId": "getFailureMode",
9
10
  "summary": "Get Failure Mode",
10
11
  "description": "Retrieve a specific failure mode from a block diagram",
11
12
  "tags": [],
@@ -48,6 +49,7 @@
48
49
  {
49
50
  "path": "/api/v2/projects/{projectId}/failure-modes/{failureModeId}/fmm-diagram",
50
51
  "method": "PUT",
52
+ "operationId": "updateFMMDiagram",
51
53
  "summary": "Update FMM diagram",
52
54
  "description": "Update FMM diagram for a specific failure mode",
53
55
  "tags": [
@@ -6,6 +6,7 @@
6
6
  {
7
7
  "path": "/api/v2/fourm",
8
8
  "method": "GET",
9
+ "operationId": "list",
9
10
  "summary": "List 4M analysis items",
10
11
  "description": "Retrieves a list of 4M (Man, Machine, Material, Environment) analysis items with optional filtering by project and tags",
11
12
  "tags": [],
@@ -48,6 +49,7 @@
48
49
  {
49
50
  "path": "/api/v2/fourm",
50
51
  "method": "POST",
52
+ "operationId": "create",
51
53
  "summary": "Create 4M analysis item",
52
54
  "description": "Creates a new 4M (Man, Machine, Material, Environment) analysis item",
53
55
  "tags": [],
@@ -73,6 +75,7 @@
73
75
  {
74
76
  "path": "/api/v2/fourm/{id}",
75
77
  "method": "GET",
78
+ "operationId": "get",
76
79
  "summary": "Get 4M analysis item by ID",
77
80
  "description": "Retrieves a specific 4M analysis item by its ID",
78
81
  "tags": [],
@@ -100,6 +103,7 @@
100
103
  {
101
104
  "path": "/api/v2/fourm/{id}",
102
105
  "method": "PUT",
106
+ "operationId": "update",
103
107
  "summary": "Update 4M analysis item",
104
108
  "description": "Updates an existing 4M analysis item",
105
109
  "tags": [],
@@ -135,6 +139,7 @@
135
139
  {
136
140
  "path": "/api/v2/fourm/{id}",
137
141
  "method": "DELETE",
142
+ "operationId": "delete",
138
143
  "summary": "Delete 4M analysis item",
139
144
  "description": "Deletes a 4M analysis item by its ID",
140
145
  "tags": [],
@@ -0,0 +1,188 @@
1
+ {
2
+ "category": "Worksheets",
3
+ "version": "v2",
4
+ "description": "Worksheet Core Operations",
5
+ "endpoints": [
6
+ {
7
+ "path": "/api/v2/projects/{projectId}/worksheets",
8
+ "method": "GET",
9
+ "summary": "Get worksheet summaries",
10
+ "description": "Retrieve all worksheet summaries for a specific project",
11
+ "tags": [],
12
+ "parameters": [
13
+ {
14
+ "name": "projectId",
15
+ "in": "path",
16
+ "required": true,
17
+ "schema": {
18
+ "type": "string"
19
+ }
20
+ }
21
+ ],
22
+ "operationId": "getSummaries",
23
+ "responses": {
24
+ "default": {
25
+ "description": "default response",
26
+ "content": {
27
+ "application/json": {}
28
+ }
29
+ }
30
+ }
31
+ },
32
+ {
33
+ "path": "/api/v2/projects/{projectId}/worksheets",
34
+ "method": "POST",
35
+ "summary": "Create worksheet",
36
+ "description": "Create a new worksheet for a specific project",
37
+ "tags": [],
38
+ "parameters": [
39
+ {
40
+ "name": "projectId",
41
+ "in": "path",
42
+ "required": true,
43
+ "schema": {
44
+ "type": "string"
45
+ }
46
+ }
47
+ ],
48
+ "requestBody": {
49
+ "content": {
50
+ "application/json": {
51
+ "schema": {
52
+ "$ref": "#/components/schemas/WorksheetCreationDTO"
53
+ }
54
+ }
55
+ }
56
+ },
57
+ "responses": {
58
+ "default": {
59
+ "description": "default response",
60
+ "content": {
61
+ "*/*": {}
62
+ }
63
+ }
64
+ },
65
+ "operationId": "create_4"
66
+ },
67
+ {
68
+ "path": "/api/v2/projects/{projectId}/worksheets/{reportNoSimple}",
69
+ "method": "GET",
70
+ "summary": "Get worksheet by report number",
71
+ "description": "Retrieve a specific worksheet by its report number",
72
+ "tags": [],
73
+ "parameters": [
74
+ {
75
+ "name": "projectId",
76
+ "in": "path",
77
+ "required": true,
78
+ "schema": {
79
+ "type": "string"
80
+ }
81
+ },
82
+ {
83
+ "name": "reportNoSimple",
84
+ "in": "path",
85
+ "required": true,
86
+ "schema": {
87
+ "$ref": "#/components/schemas/ReportNoSetDTO"
88
+ }
89
+ }
90
+ ],
91
+ "operationId": "get_5",
92
+ "responses": {
93
+ "default": {
94
+ "description": "default response",
95
+ "content": {
96
+ "application/json": {}
97
+ }
98
+ }
99
+ }
100
+ },
101
+ {
102
+ "path": "/api/v2/projects/{projectId}/worksheets/{reportNoSimple}",
103
+ "method": "PUT",
104
+ "summary": "Update worksheet",
105
+ "description": "Update an existing worksheet by its report number",
106
+ "tags": [],
107
+ "parameters": [
108
+ {
109
+ "name": "projectId",
110
+ "in": "path",
111
+ "required": true,
112
+ "schema": {
113
+ "type": "string"
114
+ }
115
+ },
116
+ {
117
+ "name": "reportNoSimple",
118
+ "in": "path",
119
+ "required": true,
120
+ "schema": {
121
+ "$ref": "#/components/schemas/ReportNoSetDTO"
122
+ }
123
+ }
124
+ ],
125
+ "requestBody": {
126
+ "content": {
127
+ "application/json": {
128
+ "schema": {
129
+ "$ref": "#/components/schemas/WorksheetSaveDTO"
130
+ }
131
+ }
132
+ }
133
+ },
134
+ "responses": {
135
+ "default": {
136
+ "description": "default response",
137
+ "content": {
138
+ "*/*": {}
139
+ }
140
+ }
141
+ },
142
+ "operationId": "save_7"
143
+ },
144
+ {
145
+ "path": "/api/v2/projects/{projectId}/worksheets/{reportNoSimple}",
146
+ "method": "DELETE",
147
+ "summary": "Delete worksheet",
148
+ "description": "Delete a worksheet by its report number",
149
+ "tags": [],
150
+ "parameters": [
151
+ {
152
+ "name": "projectId",
153
+ "in": "path",
154
+ "required": true,
155
+ "schema": {
156
+ "type": "string"
157
+ }
158
+ },
159
+ {
160
+ "name": "reportNoSimple",
161
+ "in": "path",
162
+ "required": true,
163
+ "schema": {
164
+ "$ref": "#/components/schemas/ReportNoSetDTO"
165
+ }
166
+ }
167
+ ],
168
+ "requestBody": {
169
+ "content": {
170
+ "application/json": {
171
+ "schema": {
172
+ "$ref": "#/components/schemas/WorksheetSaveDTO"
173
+ }
174
+ }
175
+ }
176
+ },
177
+ "responses": {
178
+ "default": {
179
+ "description": "default response",
180
+ "content": {
181
+ "*/*": {}
182
+ }
183
+ }
184
+ },
185
+ "operationId": "delete_4"
186
+ }
187
+ ]
188
+ }
@@ -44,7 +44,8 @@
44
44
  }
45
45
  }
46
46
  },
47
- "operationId": "update_4"
47
+ "operationId": "update_4",
48
+ "x-dependency-warning": "REQUIRES PRIOR FILE UPLOAD via [POST /api/v2/files]. The {uuid} parameter is the file ID returned by the upload endpoint."
48
49
  },
49
50
  {
50
51
  "path": "/api/v2/projects/{projectId}/worksheet-excel/{uuid}",
@@ -87,7 +88,8 @@
87
88
  }
88
89
  }
89
90
  },
90
- "operationId": "add"
91
+ "operationId": "add",
92
+ "x-dependency-warning": "REQUIRES PRIOR FILE UPLOAD via [POST /api/v2/files]. The {uuid} parameter is the file ID returned by the upload endpoint."
91
93
  },
92
94
  {
93
95
  "path": "/api/v2/projects/{projectId}/worksheet-excel/{reportNoSimple}",
@@ -148,6 +150,7 @@
148
150
  }
149
151
  ],
150
152
  "operationId": "getMetadata",
153
+ "x-dependency-warning": "REQUIRES PRIOR FILE UPLOAD via [POST /api/v2/files]. The {uuid} parameter is the file ID returned by the upload endpoint.",
151
154
  "responses": {
152
155
  "default": {
153
156
  "description": "default response",
@@ -3,67 +3,6 @@
3
3
  "version": "v2",
4
4
  "description": "Worksheet Management Operations",
5
5
  "endpoints": [
6
- {
7
- "path": "/api/v2/projects/{projectId}/worksheets",
8
- "method": "GET",
9
- "summary": "Get worksheet summaries",
10
- "description": "Retrieve all worksheet summaries for a specific project",
11
- "tags": [],
12
- "parameters": [
13
- {
14
- "name": "projectId",
15
- "in": "path",
16
- "required": true,
17
- "schema": {
18
- "type": "string"
19
- }
20
- }
21
- ],
22
- "operationId": "getSummaries",
23
- "responses": {
24
- "default": {
25
- "description": "default response",
26
- "content": {
27
- "application/json": {}
28
- }
29
- }
30
- }
31
- },
32
- {
33
- "path": "/api/v2/projects/{projectId}/worksheets",
34
- "method": "POST",
35
- "summary": "Create worksheet",
36
- "description": "Create a new worksheet for a specific project",
37
- "tags": [],
38
- "parameters": [
39
- {
40
- "name": "projectId",
41
- "in": "path",
42
- "required": true,
43
- "schema": {
44
- "type": "string"
45
- }
46
- }
47
- ],
48
- "requestBody": {
49
- "content": {
50
- "application/json": {
51
- "schema": {
52
- "$ref": "#/components/schemas/WorksheetCreationDTO"
53
- }
54
- }
55
- }
56
- },
57
- "responses": {
58
- "default": {
59
- "description": "default response",
60
- "content": {
61
- "*/*": {}
62
- }
63
- }
64
- },
65
- "operationId": "create_4"
66
- },
67
6
  {
68
7
  "path": "/api/v2/projects/{projectId}/worksheets/failuremode/{failureModeId}",
69
8
  "method": "GET",
@@ -140,126 +79,6 @@
140
79
  }
141
80
  }
142
81
  },
143
- {
144
- "path": "/api/v2/projects/{projectId}/worksheets/{reportNoSimple}",
145
- "method": "GET",
146
- "summary": "Get worksheet by report number",
147
- "description": "Retrieve a specific worksheet by its report number",
148
- "tags": [],
149
- "parameters": [
150
- {
151
- "name": "projectId",
152
- "in": "path",
153
- "required": true,
154
- "schema": {
155
- "type": "string"
156
- }
157
- },
158
- {
159
- "name": "reportNoSimple",
160
- "in": "path",
161
- "required": true,
162
- "schema": {
163
- "$ref": "#/components/schemas/ReportNoSetDTO"
164
- }
165
- }
166
- ],
167
- "operationId": "get_5",
168
- "responses": {
169
- "default": {
170
- "description": "default response",
171
- "content": {
172
- "application/json": {}
173
- }
174
- }
175
- }
176
- },
177
- {
178
- "path": "/api/v2/projects/{projectId}/worksheets/{reportNoSimple}",
179
- "method": "PUT",
180
- "summary": "Update worksheet",
181
- "description": "Update an existing worksheet by its report number",
182
- "tags": [],
183
- "parameters": [
184
- {
185
- "name": "projectId",
186
- "in": "path",
187
- "required": true,
188
- "schema": {
189
- "type": "string"
190
- }
191
- },
192
- {
193
- "name": "reportNoSimple",
194
- "in": "path",
195
- "required": true,
196
- "schema": {
197
- "$ref": "#/components/schemas/ReportNoSetDTO"
198
- }
199
- }
200
- ],
201
- "requestBody": {
202
- "content": {
203
- "application/json": {
204
- "schema": {
205
- "$ref": "#/components/schemas/WorksheetSaveDTO"
206
- }
207
- }
208
- }
209
- },
210
- "responses": {
211
- "default": {
212
- "description": "default response",
213
- "content": {
214
- "*/*": {}
215
- }
216
- }
217
- },
218
- "operationId": "save_7"
219
- },
220
- {
221
- "path": "/api/v2/projects/{projectId}/worksheets/{reportNoSimple}",
222
- "method": "DELETE",
223
- "summary": "Delete worksheet",
224
- "description": "Delete a worksheet by its report number",
225
- "tags": [],
226
- "parameters": [
227
- {
228
- "name": "projectId",
229
- "in": "path",
230
- "required": true,
231
- "schema": {
232
- "type": "string"
233
- }
234
- },
235
- {
236
- "name": "reportNoSimple",
237
- "in": "path",
238
- "required": true,
239
- "schema": {
240
- "$ref": "#/components/schemas/ReportNoSetDTO"
241
- }
242
- }
243
- ],
244
- "requestBody": {
245
- "content": {
246
- "application/json": {
247
- "schema": {
248
- "$ref": "#/components/schemas/WorksheetSaveDTO"
249
- }
250
- }
251
- }
252
- },
253
- "responses": {
254
- "default": {
255
- "description": "default response",
256
- "content": {
257
- "*/*": {}
258
- }
259
- }
260
- },
261
- "operationId": "delete_4"
262
- },
263
82
  {
264
83
  "path": "/api/v2/projects/{projectId}/worksheets/{reportNo}/headers",
265
84
  "method": "GET",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fmea-api-mcp-server",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "MCP server for serving API documentation from endpoints directory",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -15,6 +15,7 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@modelcontextprotocol/sdk": "^1.25.2",
18
+ "stemmer": "^2.0.1",
18
19
  "zod": "^3.22.4"
19
20
  },
20
21
  "devDependencies": {