@bimatrix-aud-platform/aud_mcp_server 1.1.80 → 1.1.82

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.
@@ -78,6 +78,7 @@ export interface BoxStyleSaveResult {
78
78
  export declare function callBoxStyleSaveService(boxStyle: Record<string, any> | Record<string, any>[]): Promise<BoxStyleSaveResult>;
79
79
  /**
80
80
  * i-AUD 서버에 보고서를 저장(Publish)합니다.
81
+ * 저장 전 서버 파일 변경 충돌 검사를 수행합니다.
81
82
  * VS Code Extension의 submitSaveReportPost와 동일한 역할입니다.
82
83
  */
83
84
  export declare function callSaveReportService(saveModel: Record<string, any>): Promise<any>;
@@ -198,6 +198,49 @@ export function isAudConfigured() {
198
198
  const config = getAudConfig();
199
199
  return !!(config.serviceUrl && config.apiKey && config.userName);
200
200
  }
201
+ /**
202
+ * config 검증 + DataSet.maf URL을 반환합니다.
203
+ */
204
+ function ensureConfig() {
205
+ const config = getAudConfig();
206
+ if (!config.serviceUrl || !config.apiKey) {
207
+ throw new Error("i-AUD 서버 접속 정보를 찾을 수 없습니다.\n"
208
+ + "다음 중 하나를 설정해 주세요:\n"
209
+ + " 1) .vscode/settings.json의 aud.config (ServiceURL, ApiKey, UserName)\n"
210
+ + " 2) 환경변수: AUD_SERVICE_URL, AUD_API_KEY, AUD_USER_NAME");
211
+ }
212
+ const url = config.serviceUrl
213
+ + (config.serviceUrl.endsWith("/") ? "servlet/DataSet.maf" : "/servlet/DataSet.maf");
214
+ return { config, url };
215
+ }
216
+ /**
217
+ * i-AUD 서버에 PACKET을 POST로 전송하고 응답을 반환합니다.
218
+ * 서버 레벨 오류(retCode/retMsg)가 있으면 throw 합니다.
219
+ */
220
+ async function postServiceRequest(config, url, packetStr, hashcodeSuffix) {
221
+ const formBody = new URLSearchParams();
222
+ formBody.append("ENC", "false");
223
+ formBody.append("OUT", "1");
224
+ formBody.append("hashcode", "aud.mcp." + config.userName + (hashcodeSuffix || ""));
225
+ formBody.append("ver", "400");
226
+ formBody.append("PACKET", packetStr);
227
+ const response = await fetch(url, {
228
+ method: "POST",
229
+ headers: {
230
+ "Content-Type": "application/x-www-form-urlencoded",
231
+ "Authorization": "Bearer " + config.apiKey,
232
+ },
233
+ body: formBody.toString(),
234
+ });
235
+ if (!response.ok) {
236
+ throw new Error(`i-AUD 서버 요청 실패: HTTP ${response.status} ${response.statusText}`);
237
+ }
238
+ const data = await response.json();
239
+ if (data.retCode && data.retMsg) {
240
+ throw new Error(`i-AUD 서버 오류: [${data.retCode}] ${data.retMsg}`);
241
+ }
242
+ return data;
243
+ }
201
244
  /**
202
245
  * PACKET JSON을 구성합니다. (VS Code Extension의 getPacketText와 동일한 구조)
203
246
  */
@@ -231,44 +274,13 @@ function buildPacket(config, scriptCode, script, params) {
231
274
  * i-AUD 서버의 @SCHEMA_SERVICE 서버 스크립트를 호출합니다.
232
275
  */
233
276
  export async function callSchemaService(schemaType, params) {
234
- const config = getAudConfig();
235
- if (!config.serviceUrl || !config.apiKey) {
236
- throw new Error("i-AUD 서버 접속 정보를 찾을 수 없습니다.\n"
237
- + "다음 중 하나를 설정해 주세요:\n"
238
- + " 1) .vscode/settings.json의 aud.config (ServiceURL, ApiKey, UserName)\n"
239
- + " 2) 환경변수: AUD_SERVICE_URL, AUD_API_KEY, AUD_USER_NAME");
240
- }
277
+ const { config, url } = ensureConfig();
241
278
  const allParams = [
242
279
  { Key: "#SCHEMA_TYPE#", Value: [schemaType] },
243
280
  ...params,
244
281
  ];
245
- const url = config.serviceUrl
246
- + (config.serviceUrl.endsWith("/") ? "servlet/DataSet.maf" : "/servlet/DataSet.maf");
247
282
  const packetStr = buildPacket(config, "@AUD_SAVE_SERVICE@SCHEMA_SERVICE", SERVICE_SOURCE_LIST.SCHEMA_SERVICE, allParams);
248
- // multipart/form-data 형식으로 전송 (VS Code Extension과 동일)
249
- const formBody = new URLSearchParams();
250
- formBody.append("ENC", "false");
251
- formBody.append("OUT", "1");
252
- formBody.append("hashcode", "aud.mcp." + config.userName + generateId("."));
253
- formBody.append("ver", "400");
254
- formBody.append("PACKET", packetStr);
255
- const response = await fetch(url, {
256
- method: "POST",
257
- headers: {
258
- "Content-Type": "application/x-www-form-urlencoded",
259
- "Authorization": "Bearer " + config.apiKey,
260
- },
261
- body: formBody.toString(),
262
- });
263
- if (!response.ok) {
264
- throw new Error(`i-AUD 서버 요청 실패: HTTP ${response.status} ${response.statusText}`);
265
- }
266
- const data = await response.json();
267
- // 서버 레벨 오류 체크
268
- if (data.retCode && data.retMsg) {
269
- throw new Error(`i-AUD 서버 오류: [${data.retCode}] ${data.retMsg}`);
270
- }
271
- return data;
283
+ return await postServiceRequest(config, url, packetStr, generateId("."));
272
284
  }
273
285
  /**
274
286
  * i-AUD 서버의 @MODULE_SERVICE 서버 스크립트를 호출합니다.
@@ -277,241 +289,99 @@ export async function callSchemaService(schemaType, params) {
277
289
  * @param params 추가 파라미터
278
290
  */
279
291
  export async function callModuleService(schemaType, params) {
280
- const config = getAudConfig();
281
- if (!config.serviceUrl || !config.apiKey) {
282
- throw new Error("i-AUD 서버 접속 정보를 찾을 수 없습니다.\n"
283
- + "다음 중 하나를 설정해 주세요:\n"
284
- + " 1) .vscode/settings.json의 aud.config (ServiceURL, ApiKey, UserName)\n"
285
- + " 2) 환경변수: AUD_SERVICE_URL, AUD_API_KEY, AUD_USER_NAME");
286
- }
292
+ const { config, url } = ensureConfig();
287
293
  const allParams = [
288
294
  { Key: "#SCHEMA_TYPE#", Value: [schemaType] },
289
295
  ...params,
290
296
  ];
291
- const url = config.serviceUrl
292
- + (config.serviceUrl.endsWith("/") ? "servlet/DataSet.maf" : "/servlet/DataSet.maf");
293
297
  const packetStr = buildPacket(config, "@AUD_SAVE_SERVICE@MODULE_SERVICE", SERVICE_SOURCE_LIST.MODULE_SERVICE, allParams);
294
- // multipart/form-data 형식으로 전송 (VS Code Extension과 동일)
295
- const formBody = new URLSearchParams();
296
- formBody.append("ENC", "false");
297
- formBody.append("OUT", "1");
298
- formBody.append("hashcode", "aud.mcp." + config.userName);
299
- formBody.append("ver", "400");
300
- formBody.append("PACKET", packetStr);
301
- const response = await fetch(url, {
302
- method: "POST",
303
- headers: {
304
- "Content-Type": "application/x-www-form-urlencoded",
305
- "Authorization": "Bearer " + config.apiKey,
306
- },
307
- body: formBody.toString(),
308
- });
309
- if (!response.ok) {
310
- throw new Error(`i-AUD 서버 요청 실패: HTTP ${response.status} ${response.statusText}`);
311
- }
312
- const data = await response.json();
313
- // 서버 레벨 오류 체크
314
- if (data.retCode && data.retMsg) {
315
- throw new Error(`i-AUD 서버 오류: [${data.retCode}] ${data.retMsg}`);
316
- }
317
- return data;
298
+ return await postServiceRequest(config, url, packetStr);
318
299
  }
319
300
  /**
320
301
  * i-AUD 서버의 @DBMS_LIST 서버 스크립트를 호출하여
321
302
  * 현재 사용자에게 권한이 있는 DB 연결 목록을 가져옵니다.
322
303
  */
323
304
  export async function callDbmsList() {
324
- const config = getAudConfig();
325
- if (!config.serviceUrl || !config.apiKey) {
326
- throw new Error("i-AUD 서버 접속 정보를 찾을 수 없습니다.\n"
327
- + "다음 중 하나를 설정해 주세요:\n"
328
- + " 1) .vscode/settings.json의 aud.config (ServiceURL, ApiKey, UserName)\n"
329
- + " 2) 환경변수: AUD_SERVICE_URL, AUD_API_KEY, AUD_USER_NAME");
330
- }
331
- const url = config.serviceUrl
332
- + (config.serviceUrl.endsWith("/") ? "servlet/DataSet.maf" : "/servlet/DataSet.maf");
305
+ const { config, url } = ensureConfig();
333
306
  const packetStr = buildPacket(config, "@AUD_SAVE_SERVICE@DBMS_LIST", SERVICE_SOURCE_LIST.DBMS_LIST, []);
334
- const formBody = new URLSearchParams();
335
- formBody.append("ENC", "false");
336
- formBody.append("OUT", "1");
337
- formBody.append("hashcode", "aud.mcp." + config.userName);
338
- formBody.append("ver", "400");
339
- formBody.append("PACKET", packetStr);
340
- const response = await fetch(url, {
341
- method: "POST",
342
- headers: {
343
- "Content-Type": "application/x-www-form-urlencoded",
344
- "Authorization": "Bearer " + config.apiKey,
345
- },
346
- body: formBody.toString(),
347
- });
348
- if (!response.ok) {
349
- throw new Error(`i-AUD 서버 요청 실패: HTTP ${response.status} ${response.statusText}`);
350
- }
351
- const data = await response.json();
352
- if (data.retCode && data.retMsg) {
353
- throw new Error(`i-AUD 서버 오류: [${data.retCode}] ${data.retMsg}`);
354
- }
355
- return data;
307
+ return await postServiceRequest(config, url, packetStr);
356
308
  }
357
309
  /**
358
310
  * i-AUD 서버의 @BOXSTYLE_LIST 서버 스크립트를 호출하여
359
311
  * BoxStyle 목록을 가져옵니다.
360
312
  */
361
313
  export async function callBoxStyleService() {
362
- const config = getAudConfig();
363
- if (!config.serviceUrl || !config.apiKey) {
364
- throw new Error("i-AUD 서버 접속 정보를 찾을 수 없습니다.\n"
365
- + "다음 중 하나를 설정해 주세요:\n"
366
- + " 1) .vscode/settings.json의 aud.config (ServiceURL, ApiKey, UserName)\n"
367
- + " 2) 환경변수: AUD_SERVICE_URL, AUD_API_KEY, AUD_USER_NAME");
368
- }
369
- const url = config.serviceUrl
370
- + (config.serviceUrl.endsWith("/") ? "servlet/DataSet.maf" : "/servlet/DataSet.maf");
314
+ const { config, url } = ensureConfig();
371
315
  const packetStr = buildPacket(config, "@AUD_SAVE_SERVICE@BOXSTYLE_LIST", SERVICE_SOURCE_LIST.BOXSTYLE_LIST, []);
372
- const formBody = new URLSearchParams();
373
- formBody.append("ENC", "false");
374
- formBody.append("OUT", "1");
375
- formBody.append("hashcode", "aud.mcp." + config.userName);
376
- formBody.append("ver", "400");
377
- formBody.append("PACKET", packetStr);
378
- const response = await fetch(url, {
379
- method: "POST",
380
- headers: {
381
- "Content-Type": "application/x-www-form-urlencoded",
382
- "Authorization": "Bearer " + config.apiKey,
383
- },
384
- body: formBody.toString(),
385
- });
386
- if (!response.ok) {
387
- throw new Error(`i-AUD 서버 요청 실패: HTTP ${response.status} ${response.statusText}`);
388
- }
389
- const data = await response.json();
390
- if (data.retCode && data.retMsg) {
391
- throw new Error(`i-AUD 서버 오류: [${data.retCode}] ${data.retMsg}`);
392
- }
393
- return data;
316
+ return await postServiceRequest(config, url, packetStr);
394
317
  }
395
318
  /**
396
319
  * i-AUD 서버에 BoxStyle을 저장(생성/수정)합니다.
397
320
  * 단일 객체 또는 배열을 전달할 수 있습니다.
398
321
  */
399
322
  export async function callBoxStyleSaveService(boxStyle) {
400
- const config = getAudConfig();
401
- if (!config.serviceUrl || !config.apiKey) {
402
- throw new Error("i-AUD 서버 접속 정보를 찾을 수 없습니다.\n"
403
- + "다음 중 하나를 설정해 주세요:\n"
404
- + " 1) .vscode/settings.json의 aud.config (ServiceURL, ApiKey, UserName)\n"
405
- + " 2) 환경변수: AUD_SERVICE_URL, AUD_API_KEY, AUD_USER_NAME");
406
- }
407
- const url = config.serviceUrl
408
- + (config.serviceUrl.endsWith("/") ? "servlet/DataSet.maf" : "/servlet/DataSet.maf");
323
+ const { config, url } = ensureConfig();
409
324
  const packetStr = buildPacket(config, "@AUD_SAVE_SERVICE@BOXSTYLE_SAVE", SERVICE_SOURCE_LIST.BOXSTYLE_SAVE, [
410
325
  { Key: "#BOXSTYLE_DATA#", Value: [JSON.stringify(boxStyle)] },
411
326
  ]);
412
- const formBody = new URLSearchParams();
413
- formBody.append("ENC", "false");
414
- formBody.append("OUT", "1");
415
- formBody.append("hashcode", "aud.mcp." + config.userName);
416
- formBody.append("ver", "400");
417
- formBody.append("PACKET", packetStr);
418
- const response = await fetch(url, {
419
- method: "POST",
420
- headers: {
421
- "Content-Type": "application/x-www-form-urlencoded",
422
- "Authorization": "Bearer " + config.apiKey,
423
- },
424
- body: formBody.toString(),
425
- });
426
- if (!response.ok) {
427
- throw new Error(`i-AUD 서버 요청 실패: HTTP ${response.status} ${response.statusText}`);
327
+ return await postServiceRequest(config, url, packetStr);
328
+ }
329
+ /**
330
+ * 저장 전 서버의 보고서 수정일자를 확인하여 충돌 여부를 검사합니다.
331
+ * 서버 파일이 로컬보다 최근에 수정되었으면 에러를 throw 합니다.
332
+ */
333
+ async function callCheckSaveService(config, url, reportCode, clientEditDate) {
334
+ const packetStr = buildPacket(config, "@AUD_SAVE_SERVICE@CHECK_SAVE", SERVICE_SOURCE_LIST.CHECK_SAVE || "", [
335
+ { Key: "VS_REPORT_CODE", Value: [reportCode] },
336
+ { Key: "VS_EDIT_DATE", Value: [clientEditDate] },
337
+ ]);
338
+ try {
339
+ const data = await postServiceRequest(config, url, packetStr);
340
+ let result = data;
341
+ if (typeof data === "string") {
342
+ result = JSON.parse(data);
343
+ }
344
+ if (result.Success === false) {
345
+ throw new Error(result.Message);
346
+ }
428
347
  }
429
- const data = await response.json();
430
- if (data.retCode && data.retMsg) {
431
- throw new Error(`i-AUD 서버 오류: [${data.retCode}] ${data.retMsg}`);
348
+ catch (e) {
349
+ // postServiceRequest의 서버 오류(retCode/retMsg) 에러 메시지만 출력하고 저장 진행
350
+ if (e.message?.includes("i-AUD 서버 오류")) {
351
+ process.stderr.write(`[aud_mcp_server] checkSaveConflict server error: ${e.message}\n`);
352
+ return;
353
+ }
354
+ throw e;
432
355
  }
433
- return data;
434
356
  }
435
357
  /**
436
358
  * i-AUD 서버에 보고서를 저장(Publish)합니다.
359
+ * 저장 전 서버 파일 변경 충돌 검사를 수행합니다.
437
360
  * VS Code Extension의 submitSaveReportPost와 동일한 역할입니다.
438
361
  */
439
362
  export async function callSaveReportService(saveModel) {
440
- const config = getAudConfig();
441
- if (!config.serviceUrl || !config.apiKey) {
442
- throw new Error("i-AUD 서버 접속 정보를 찾을 수 없습니다.\n"
443
- + "다음 하나를 설정해 주세요:\n"
444
- + " 1) .vscode/settings.json의 aud.config (ServiceURL, ApiKey, UserName)\n"
445
- + " 2) 환경변수: AUD_SERVICE_URL, AUD_API_KEY, AUD_USER_NAME");
446
- }
447
- const url = config.serviceUrl
448
- + (config.serviceUrl.endsWith("/") ? "servlet/DataSet.maf" : "/servlet/DataSet.maf");
363
+ const { config, url } = ensureConfig();
364
+ // 1. 저장 충돌 검사
365
+ const reportCode = saveModel.REPORT_CODE || "";
366
+ const clientEditDate = saveModel.ReportModel?.ReportInfo?.EditDate || "";
367
+ await callCheckSaveService(config, url, reportCode, clientEditDate);
368
+ // 2. 서버 전송
449
369
  const packetStr = buildPacket(config, "@AUD_SAVE_SERVICE@SAVE_REPORT", SERVICE_SOURCE_LIST.SAVE_REPORT, [
450
370
  { Key: "VS_REPORT_INFO", Value: [JSON.stringify(saveModel)] },
451
371
  ]);
452
- const formBody = new URLSearchParams();
453
- formBody.append("ENC", "false");
454
- formBody.append("OUT", "1");
455
- formBody.append("hashcode", "aud.mcp." + config.userName);
456
- formBody.append("ver", "400");
457
- formBody.append("PACKET", packetStr);
458
- const response = await fetch(url, {
459
- method: "POST",
460
- headers: {
461
- "Content-Type": "application/x-www-form-urlencoded",
462
- "Authorization": "Bearer " + config.apiKey,
463
- },
464
- body: formBody.toString(),
465
- });
466
- if (!response.ok) {
467
- throw new Error(`i-AUD 서버 요청 실패: HTTP ${response.status} ${response.statusText}`);
468
- }
469
- const data = await response.json();
470
- if (data.retCode && data.retMsg) {
471
- throw new Error(`i-AUD 서버 오류: [${data.retCode}] ${data.retMsg}`);
472
- }
473
- return data;
372
+ return await postServiceRequest(config, url, packetStr);
474
373
  }
475
374
  /**
476
375
  * i-AUD 서버에서 보고서를 읽어옵니다 (Pull).
477
376
  * VS Code Extension의 submitReadReportPost와 동일한 역할입니다.
478
377
  */
479
378
  export async function callReadReportService(reportCode) {
480
- const config = getAudConfig();
481
- if (!config.serviceUrl || !config.apiKey) {
482
- throw new Error("i-AUD 서버 접속 정보를 찾을 수 없습니다.\n"
483
- + "다음 중 하나를 설정해 주세요:\n"
484
- + " 1) .vscode/settings.json의 aud.config (ServiceURL, ApiKey, UserName)\n"
485
- + " 2) 환경변수: AUD_SERVICE_URL, AUD_API_KEY, AUD_USER_NAME");
486
- }
487
- const url = config.serviceUrl
488
- + (config.serviceUrl.endsWith("/") ? "servlet/DataSet.maf" : "/servlet/DataSet.maf");
379
+ const { config, url } = ensureConfig();
489
380
  const packetStr = buildPacket(config, "@AUD_SAVE_SERVICE@READ_REPORT", SERVICE_SOURCE_LIST.READ_REPORT, [
490
381
  { Key: "VS_REPORT_CODE", Value: [reportCode] },
491
382
  { Key: "VS_REPORT_NAME", Value: [""] },
492
383
  ]);
493
- const formBody = new URLSearchParams();
494
- formBody.append("ENC", "false");
495
- formBody.append("OUT", "1");
496
- formBody.append("hashcode", "aud.mcp." + config.userName);
497
- formBody.append("ver", "400");
498
- formBody.append("PACKET", packetStr);
499
- const response = await fetch(url, {
500
- method: "POST",
501
- headers: {
502
- "Content-Type": "application/x-www-form-urlencoded",
503
- "Authorization": "Bearer " + config.apiKey,
504
- },
505
- body: formBody.toString(),
506
- });
507
- if (!response.ok) {
508
- throw new Error(`i-AUD 서버 요청 실패: HTTP ${response.status} ${response.statusText}`);
509
- }
510
- const data = await response.json();
511
- if (data.retCode && data.retMsg) {
512
- throw new Error(`i-AUD 서버 오류: [${data.retCode}] ${data.retMsg}`);
513
- }
514
- return data;
384
+ return await postServiceRequest(config, url, packetStr);
515
385
  }
516
386
  /**
517
387
  * MX_GRID 리소스 파일을 서버에서 다운로드하고 압축을 풀어 로컬에 저장합니다.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bimatrix-aud-platform/aud_mcp_server",
3
- "version": "1.1.80",
3
+ "version": "1.1.82",
4
4
  "description": "MCP Server for i-AUD MTSD document validation, generation, schema querying, control info extraction, and database operations",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",