fmea-api-mcp-server 1.1.48 → 1.1.50

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
@@ -28,7 +28,7 @@ class ApiDocsServer {
28
28
  constructor() {
29
29
  this.server = new Server({
30
30
  name: "api-docs-mcp",
31
- version: "1.1.48",
31
+ version: "1.1.50",
32
32
  }, {
33
33
  capabilities: {
34
34
  resources: {},
@@ -190,6 +190,24 @@ class ApiDocsServer {
190
190
  required: ["path"],
191
191
  },
192
192
  },
193
+ {
194
+ name: "get_changes",
195
+ description: "Get API endpoint changelog. Shows what endpoints/parameters were added, removed, or modified across versions.",
196
+ inputSchema: {
197
+ type: "object",
198
+ properties: {
199
+ since_version: {
200
+ type: "string",
201
+ description: "Return all changes from this version onwards (e.g. '1.1.40'). Omit to get the latest version only.",
202
+ },
203
+ version: {
204
+ type: "string",
205
+ description: "Return changes for this exact version only (e.g. '1.1.49').",
206
+ },
207
+ },
208
+ required: [],
209
+ },
210
+ },
193
211
  ],
194
212
  };
195
213
  });
@@ -296,6 +314,46 @@ class ApiDocsServer {
296
314
  ],
297
315
  };
298
316
  }
317
+ if (request.params.name === "get_changes") {
318
+ const changelogPath = path.join(DATA_DIR, "changelog.json");
319
+ try {
320
+ const raw = await fs.readFile(changelogPath, "utf-8");
321
+ const changelog = JSON.parse(raw);
322
+ const sinceVersion = request.params.arguments?.since_version
323
+ ? String(request.params.arguments.since_version) : undefined;
324
+ const exactVersion = request.params.arguments?.version
325
+ ? String(request.params.arguments.version) : undefined;
326
+ const parseVer = (v) => v.split(".").map(Number);
327
+ const cmpVer = (a, b) => {
328
+ for (let i = 0; i < 3; i++) {
329
+ if ((a[i] || 0) !== (b[i] || 0))
330
+ return (a[i] || 0) - (b[i] || 0);
331
+ }
332
+ return 0;
333
+ };
334
+ let result;
335
+ if (exactVersion) {
336
+ result = changelog[exactVersion] ? { [exactVersion]: changelog[exactVersion] } : {};
337
+ }
338
+ else if (sinceVersion) {
339
+ const sinceArr = parseVer(sinceVersion);
340
+ result = Object.fromEntries(Object.entries(changelog).filter(([v]) => cmpVer(parseVer(v), sinceArr) >= 0));
341
+ }
342
+ else {
343
+ // Latest version only
344
+ const versions = Object.keys(changelog).sort((a, b) => cmpVer(parseVer(b), parseVer(a)));
345
+ result = versions.length > 0 ? { [versions[0]]: changelog[versions[0]] } : {};
346
+ }
347
+ return {
348
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
349
+ };
350
+ }
351
+ catch (_error) {
352
+ return {
353
+ content: [{ type: "text", text: JSON.stringify({ message: "No changelog available yet." }) }],
354
+ };
355
+ }
356
+ }
299
357
  throw new McpError(ErrorCode.MethodNotFound, "Tool not found");
300
358
  });
301
359
  }
@@ -481,6 +481,25 @@ export class OramaSearchService {
481
481
  if (!action && resource) {
482
482
  action = 'list';
483
483
  }
484
+ // [R39] Approval resource: override action for better sub-routing
485
+ if (resource === 'approval') {
486
+ const hasDecision = lower.includes('decision') || lower.includes('refuse') || lower.includes('reject') || lower.includes('batch');
487
+ const hasRequest = lower.includes('request') || lower.includes('submit') || lower.includes('reviewer') || lower.includes('send');
488
+ if (action === 'update' || hasDecision || hasRequest) {
489
+ action = 'create'; // POST /approvals/decisions or /approvals/requests
490
+ }
491
+ }
492
+ // [R39] Board resource: better differentiation between list/read/create
493
+ if (resource === 'board') {
494
+ const hasRepliesNoun = lower.includes('with replies') || lower.includes('replies') || lower.includes('thread');
495
+ const hasReplyVerb = lower.startsWith('reply') || lower.includes(' reply to') || lower.includes('reply to');
496
+ if (hasReplyVerb) {
497
+ action = 'create'; // POST /board/{boardId}/replies
498
+ }
499
+ else if (hasRepliesNoun && action !== 'create') {
500
+ action = 'read'; // GET /board/{boardId}
501
+ }
502
+ }
484
503
  // [R16] [R22] Heuristic for 'save work' — save block nodes or fmm-diagram
485
504
  if (!resource && lower.includes('save work')) {
486
505
  action = 'update';
package/dist/synonyms.js CHANGED
@@ -59,6 +59,8 @@ export const RESOURCE_ALIASES = {
59
59
  'scoring-criteria': ['scoring criteria', 'scoring', 'score criteria', 'completeness scoring', 'scoring tree'], // [R30] Scoring criteria tree management
60
60
  'process-symbol': ['process symbol', 'process symbols', 'flow chart symbol', 'flowchart symbol', 'process flow'], // [R30] Process flow chart symbols
61
61
  'additional-info': ['additional info', 'additional information', 'extra info', 'supplementary info', 'custom field', 'custom attribute', 'form field'], // [R31] Additional info template management
62
+ 'approval': ['approval board', 'approval request', 'approval decisions', 'approval progress', 'approve or refuse', 'request approval', 'review workflow', 'submit approval', 'approve'], // [R39] Approval workflow
63
+ 'board': ['board comment', 'board discussion', 'discussion board', 'comment thread', 'review comment', 'discussion', 'comment board'], // [R39] Board comments/discussion
62
64
  'notice': ['notice', 'notices', 'announcement', 'bulletin', 'notification'], // [R32] Notice CRUD and visibility
63
65
  'tree-search': ['tree search', 'tree query', 'structure search', 'pattern search', 'subtree match', 'anchor pattern', 'context completion', 'reference node', 'rebuild index', 'reindex'], // [R35] Tree search query and index rebuild
64
66
  };
@@ -169,6 +171,16 @@ export const SYNONYM_GROUPS = {
169
171
  // [R30] FM Checkpoint & Scoring Domain
170
172
  "checkpoint": ["checklist", "check item", "verification", "audit item"],
171
173
  "breadcrumb": ["path", "navigation", "ancestor", "경로", "trail"], // [R31] Removed "hierarchy path" to avoid boosting /tree endpoints
174
+ // [R39] Approval & Board Domain
175
+ "approval": ["approve", "authorization", "sign-off", "decision", "review request"],
176
+ "approve": ["authorize", "accept", "confirm", "approval", "sign off"],
177
+ "refuse": ["reject", "deny", "decline", "disapprove", "refusal"],
178
+ "decision": ["approve", "refuse", "verdict", "choice"],
179
+ "board": ["comment", "discussion", "thread", "forum"],
180
+ "comment": ["board", "remark", "note", "opinion"],
181
+ "discussion": ["comment", "thread", "board", "conversation"],
182
+ "reply": ["response", "comment", "feedback", "answer"],
183
+ "thread": ["discussion", "comments", "replies", "chain"],
172
184
  // [R31] Korean Term Mappings
173
185
  "조회": ["get", "list", "view", "fetch", "search", "retrieve", "read", "show"],
174
186
  "경로": ["breadcrumb", "path", "navigation", "route", "trail"],
@@ -18,7 +18,9 @@ export class ScoreCalculator {
18
18
  'fault-tree': ['failure-mode'],
19
19
  'failure-mode': ['fault-tree', 'fmm-diagram'], // FTA contains failure modes, FMM is a diagram view
20
20
  'fmm-diagram': ['failure-mode', 'tree-search'], // [R19] [R35]
21
- 'project': ['document', 'file', 'member', 'join-request', 'worksheet', 'block-diagram'], // Project contains everything
21
+ 'project': ['document', 'file', 'member', 'join-request', 'worksheet', 'block-diagram', 'approval', 'board'], // Project contains everything [R39]
22
+ 'approval': ['project', 'board'], // [R39] Approval is related to projects and boards
23
+ 'board': ['approval', 'project'], // [R39] Board comments are part of approval workflow
22
24
  'knowledge': ['category'],
23
25
  'category': ['knowledge'],
24
26
  'oauth': ['auth'],
@@ -0,0 +1,340 @@
1
+ {
2
+ "category": "Approvals",
3
+ "version": "v2",
4
+ "description": "",
5
+ "endpoints": [
6
+ {
7
+ "path": "/api/v2/approvals/board",
8
+ "method": "GET",
9
+ "operationId": "getBoard",
10
+ "summary": "Get approval board",
11
+ "description": "Returns approval progress and board items for a project. Includes progress status, step participants, and opinion list. Optional step filter narrows opinions by type (e.g., REVIEW_OPINION, APPROVAL_OPINION).",
12
+ "tags": [
13
+ "Approval"
14
+ ],
15
+ "parameters": [
16
+ {
17
+ "name": "projectId",
18
+ "in": "query",
19
+ "description": "Project ID (required)",
20
+ "schema": {
21
+ "type": "string"
22
+ }
23
+ },
24
+ {
25
+ "name": "step",
26
+ "in": "query",
27
+ "description": "Step filter (optional): REVIEW_OPINION|APPROVAL_OPINION|APPROVAL_DECISION|REVIEW_REFUSAL|SCORE_PASS|SCORE_FAIL|SCORE_REFUSAL",
28
+ "schema": {
29
+ "type": "string"
30
+ }
31
+ }
32
+ ],
33
+ "requestBody": null,
34
+ "responses": {
35
+ "default": {
36
+ "description": "default response",
37
+ "content": {
38
+ "application/json": {
39
+ "schema": {
40
+ "type": "object",
41
+ "properties": {
42
+ "progress": {
43
+ "type": "object",
44
+ "properties": {
45
+ "isModifyRequest": {
46
+ "type": "boolean"
47
+ },
48
+ "useScore": {
49
+ "type": "boolean"
50
+ },
51
+ "doApproval": {
52
+ "type": "boolean"
53
+ },
54
+ "approvalRound": {
55
+ "type": "integer"
56
+ },
57
+ "refusedStep": {
58
+ "type": "string"
59
+ },
60
+ "steps": {
61
+ "type": "array",
62
+ "items": {
63
+ "type": "object",
64
+ "properties": {
65
+ "step": {
66
+ "type": "string",
67
+ "enum": [
68
+ "WRITE",
69
+ "REVIEW",
70
+ "APPROVE",
71
+ "SCORE"
72
+ ]
73
+ },
74
+ "status": {
75
+ "type": "string",
76
+ "enum": [
77
+ "PENDING",
78
+ "ACTIVE",
79
+ "COMPLETED",
80
+ "REFUSED"
81
+ ]
82
+ },
83
+ "participants": {
84
+ "type": "array",
85
+ "items": {
86
+ "type": "object",
87
+ "properties": {
88
+ "userId": {
89
+ "type": "string"
90
+ },
91
+ "name": {
92
+ "type": "string"
93
+ },
94
+ "isAuthorizer": {
95
+ "type": "boolean"
96
+ },
97
+ "boardStatus": {
98
+ "type": "string",
99
+ "enum": [
100
+ "REVIEW",
101
+ "ASK_MODIFY",
102
+ "REVIEWED",
103
+ "APPROVE",
104
+ "ASK_MODIFY_REVIEWED",
105
+ "APPROVED",
106
+ "SCORE",
107
+ "ASK_MODIFY_APPROVED",
108
+ "REFUSED",
109
+ "SCORE_PASS",
110
+ "SCORE_FAIL",
111
+ "COMPLETED",
112
+ "CONFIRM_VALIDITY",
113
+ "DATE_EXPIRED"
114
+ ]
115
+ },
116
+ "isAdditionalReviewer": {
117
+ "type": "boolean"
118
+ },
119
+ "isModifyReviewer": {
120
+ "type": "boolean"
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ },
130
+ "items": {
131
+ "type": "array",
132
+ "items": {
133
+ "type": "object",
134
+ "properties": {
135
+ "id": {
136
+ "type": "integer",
137
+ "format": "int64"
138
+ },
139
+ "stepLabel": {
140
+ "type": "string"
141
+ },
142
+ "stepItem": {
143
+ "type": "string"
144
+ },
145
+ "title": {
146
+ "type": "string"
147
+ },
148
+ "content": {
149
+ "type": "string"
150
+ },
151
+ "userId": {
152
+ "type": "string"
153
+ },
154
+ "writerName": {
155
+ "type": "string"
156
+ },
157
+ "createdAt": {
158
+ "type": "string",
159
+ "format": "date-time"
160
+ },
161
+ "score": {
162
+ "type": "integer"
163
+ },
164
+ "status": {
165
+ "type": "string",
166
+ "enum": [
167
+ "REVIEW",
168
+ "ASK_MODIFY",
169
+ "REVIEWED",
170
+ "APPROVE",
171
+ "ASK_MODIFY_REVIEWED",
172
+ "APPROVED",
173
+ "SCORE",
174
+ "ASK_MODIFY_APPROVED",
175
+ "REFUSED",
176
+ "SCORE_PASS",
177
+ "SCORE_FAIL",
178
+ "COMPLETED",
179
+ "CONFIRM_VALIDITY",
180
+ "DATE_EXPIRED"
181
+ ]
182
+ },
183
+ "statusDisplay": {
184
+ "type": "string"
185
+ },
186
+ "department": {
187
+ "type": "string"
188
+ },
189
+ "fileUrl": {
190
+ "type": "string"
191
+ },
192
+ "parentId": {
193
+ "type": "integer",
194
+ "format": "int64"
195
+ },
196
+ "indentLevel": {
197
+ "type": "integer"
198
+ },
199
+ "replies": {
200
+ "type": "array",
201
+ "items": {
202
+ "type": "object",
203
+ "description": "(circular: ApprovalBoardDTO)"
204
+ }
205
+ }
206
+ }
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+ },
216
+ {
217
+ "path": "/api/v2/approvals/decisions",
218
+ "method": "POST",
219
+ "operationId": "postDecisions",
220
+ "summary": "Process approval decisions",
221
+ "description": "Processes a batch of approval decisions (approve/refuse/accept/reject). Each decision is processed independently. Returns per-item success/failure results. Partial success is supported - failed items don't affect successful ones.",
222
+ "tags": [
223
+ "Approval"
224
+ ],
225
+ "parameters": [],
226
+ "requestBody": {
227
+ "content": {
228
+ "application/json": {
229
+ "schema": {
230
+ "type": "object",
231
+ "properties": {
232
+ "decisions": {
233
+ "type": "array",
234
+ "items": {
235
+ "type": "object",
236
+ "properties": {
237
+ "projectId": {
238
+ "type": "string"
239
+ },
240
+ "action": {
241
+ "type": "string",
242
+ "enum": [
243
+ "APPROVE",
244
+ "REFUSE",
245
+ "ACCEPT",
246
+ "REJECT"
247
+ ]
248
+ },
249
+ "comment": {
250
+ "type": "string"
251
+ },
252
+ "score": {
253
+ "type": "integer",
254
+ "format": "int32"
255
+ }
256
+ }
257
+ }
258
+ }
259
+ }
260
+ }
261
+ }
262
+ }
263
+ },
264
+ "responses": {
265
+ "default": {
266
+ "description": "default response",
267
+ "content": {
268
+ "application/json": {
269
+ "schema": {
270
+ "type": "array",
271
+ "items": {
272
+ "type": "object",
273
+ "properties": {
274
+ "projectId": {
275
+ "type": "string"
276
+ },
277
+ "success": {
278
+ "type": "boolean"
279
+ },
280
+ "message": {
281
+ "type": "string"
282
+ }
283
+ }
284
+ }
285
+ }
286
+ }
287
+ }
288
+ }
289
+ }
290
+ },
291
+ {
292
+ "path": "/api/v2/approvals/requests",
293
+ "method": "POST",
294
+ "operationId": "postRequests",
295
+ "summary": "Request approval",
296
+ "description": "Submits a project for approval review. Project must be in In-Progress or CanModify status. Sets reviewers, approver, and transitions to Review status.",
297
+ "tags": [
298
+ "Approval"
299
+ ],
300
+ "parameters": [],
301
+ "requestBody": {
302
+ "content": {
303
+ "application/json": {
304
+ "schema": {
305
+ "type": "object",
306
+ "properties": {
307
+ "projectId": {
308
+ "type": "string"
309
+ },
310
+ "reviewerIds": {
311
+ "type": "array",
312
+ "items": {
313
+ "type": "string"
314
+ }
315
+ },
316
+ "approverId": {
317
+ "type": "string"
318
+ },
319
+ "targetDate": {
320
+ "type": "string"
321
+ },
322
+ "requestType": {
323
+ "type": "string"
324
+ }
325
+ }
326
+ }
327
+ }
328
+ }
329
+ },
330
+ "responses": {
331
+ "default": {
332
+ "description": "default response",
333
+ "content": {
334
+ "application/json": {}
335
+ }
336
+ }
337
+ }
338
+ }
339
+ ]
340
+ }
@@ -0,0 +1,181 @@
1
+ {
2
+ "category": "Board",
3
+ "version": "v2",
4
+ "description": "",
5
+ "endpoints": [
6
+ {
7
+ "path": "/api/v2/board",
8
+ "method": "GET",
9
+ "operationId": "listBoards",
10
+ "summary": "List board comments",
11
+ "description": "Returns board comments for a project and category. Supports optional step filter for comment type. Category determines the domain: approval, BlockDiagram, FmmDiagram, Worksheet, FTA, controlplan, info.",
12
+ "tags": [
13
+ "Board"
14
+ ],
15
+ "parameters": [
16
+ {
17
+ "name": "projectId",
18
+ "in": "query",
19
+ "description": "Project ID (required)",
20
+ "schema": {
21
+ "type": "string"
22
+ }
23
+ },
24
+ {
25
+ "name": "category",
26
+ "in": "query",
27
+ "description": "Board category filter",
28
+ "schema": {
29
+ "type": "string"
30
+ }
31
+ },
32
+ {
33
+ "name": "step",
34
+ "in": "query",
35
+ "description": "Step label filter for comment type (optional)",
36
+ "schema": {
37
+ "type": "string"
38
+ }
39
+ }
40
+ ],
41
+ "requestBody": null,
42
+ "responses": {
43
+ "default": {
44
+ "description": "default response",
45
+ "content": {
46
+ "application/json": {}
47
+ }
48
+ }
49
+ }
50
+ },
51
+ {
52
+ "path": "/api/v2/board/{boardId}",
53
+ "method": "GET",
54
+ "operationId": "getBoard_1",
55
+ "summary": "Get board comment detail",
56
+ "description": "Returns a single board comment with its replies. Replies are nested in the replies field, sorted by depth.",
57
+ "tags": [
58
+ "Board"
59
+ ],
60
+ "parameters": [
61
+ {
62
+ "name": "boardId",
63
+ "in": "path",
64
+ "description": "Board comment ID",
65
+ "required": true,
66
+ "schema": {
67
+ "type": "integer",
68
+ "format": "int64"
69
+ }
70
+ }
71
+ ],
72
+ "requestBody": null,
73
+ "responses": {
74
+ "default": {
75
+ "description": "default response",
76
+ "content": {
77
+ "application/json": {}
78
+ }
79
+ }
80
+ }
81
+ },
82
+ {
83
+ "path": "/api/v2/board",
84
+ "method": "POST",
85
+ "operationId": "createBoard",
86
+ "summary": "Create board comment",
87
+ "description": "Creates a new board comment. Sets author from authentication context. projectId, category, title, and content are required.",
88
+ "tags": [
89
+ "Board"
90
+ ],
91
+ "parameters": [],
92
+ "requestBody": {
93
+ "content": {
94
+ "application/json": {
95
+ "schema": {
96
+ "type": "object",
97
+ "properties": {
98
+ "projectId": {
99
+ "type": "string"
100
+ },
101
+ "category": {
102
+ "type": "string",
103
+ "enum": [
104
+ "APPROVAL",
105
+ "BLOCK_DIAGRAM",
106
+ "FMM_DIAGRAM",
107
+ "WORKSHEET",
108
+ "FTA",
109
+ "CONTROL_PLAN",
110
+ "INFO"
111
+ ]
112
+ },
113
+ "stepLabel": {
114
+ "type": "string"
115
+ },
116
+ "title": {
117
+ "type": "string"
118
+ },
119
+ "content": {
120
+ "type": "string"
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ },
127
+ "responses": {
128
+ "default": {
129
+ "description": "default response",
130
+ "content": {
131
+ "application/json": {}
132
+ }
133
+ }
134
+ }
135
+ },
136
+ {
137
+ "path": "/api/v2/board/{boardId}/replies",
138
+ "method": "POST",
139
+ "operationId": "createReply",
140
+ "summary": "Create reply to board comment",
141
+ "description": "Creates a reply to an existing board comment. Inherits category, projectId, stepLabel, and approvalRound from parent. Title is prefixed with 'Re: '.",
142
+ "tags": [
143
+ "Board"
144
+ ],
145
+ "parameters": [
146
+ {
147
+ "name": "boardId",
148
+ "in": "path",
149
+ "description": "Parent board comment ID",
150
+ "required": true,
151
+ "schema": {
152
+ "type": "integer",
153
+ "format": "int64"
154
+ }
155
+ }
156
+ ],
157
+ "requestBody": {
158
+ "content": {
159
+ "application/json": {
160
+ "schema": {
161
+ "type": "object",
162
+ "properties": {
163
+ "content": {
164
+ "type": "string"
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+ },
171
+ "responses": {
172
+ "default": {
173
+ "description": "default response",
174
+ "content": {
175
+ "application/json": {}
176
+ }
177
+ }
178
+ }
179
+ }
180
+ ]
181
+ }