egovframe-scaffold-mcp 0.25.2 → 0.25.3

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.
Files changed (3) hide show
  1. package/README.md +11 -4
  2. package/dist/index.js +21 -1
  3. package/package.json +4 -3
package/README.md CHANGED
@@ -11,18 +11,19 @@
11
11
  Claude, VS Code(Copilot), Cursor 등 MCP를 지원하는 AI 도구에서 **대화 중 즉시** 표준프레임워크
12
12
  프로젝트를 만들고 공통컴포넌트·AI 계층을 조립할 수 있습니다. 기존 프로젝트 진단, 리포트, 안전한 upstream 재동기화도 지원합니다.
13
13
 
14
- 현재 v0.25.2는 **도구 21종, 공식 템플릿 10종, 공통컴포넌트 카탈로그 190항목(리프 176종+그룹 14종)**을 제공합니다.
14
+ 현재 v0.25.3은 **도구 21종, 공식 템플릿 10종, 공통컴포넌트 카탈로그 190항목(리프 176종+그룹 14종)**을 제공합니다.
15
15
 
16
16
  ## 진행 현황 (2026-09-13)
17
17
 
18
- - **소스 기준**: v0.25.2(`package.json`), 도구 21종·공식 템플릿 10종·카탈로그 190항목.
18
+ - **소스 기준**: v0.25.3(`package.json`), 도구 21종·공식 템플릿 10종·카탈로그 190항목.
19
19
  - **안전성 기준선 완료**: [PR #7](https://github.com/EricSeokgon/egovframe-scaffold-mcp/pull/7)~[#16](https://github.com/EricSeokgon/egovframe-scaffold-mcp/pull/16)을 반영해 provenance·strict assertion·safe remove와 프로젝트 생성/레시피/직접 조립/AI 조립/업그레이드 transaction을 갖췄습니다.
20
20
  - **v0.22.0 추가**: `EGOVFRAME_ALLOWED_ROOTS`를 19개 도구 진입점에 적용해 `..`·symlink/junction 이탈을 차단하고, 실패 시 rollback 결과를 구조화해 반환합니다. [PR #16](https://github.com/EricSeokgon/egovframe-scaffold-mcp/pull/16)은 7파일(+340/−31), 로컬 16종 스위트 전체 통과 후 병합됐습니다.
21
21
  - **v0.23.0 추가**: `build_egovframe_project` — 생성한 프로젝트를 실제로 빌드(maven/gradle·mvnw/gradlew 자동 감지)하고 컴파일·테스트 오류를 파일/라인 단위로 구조화해 생성→검증 루프를 완성합니다. 타임아웃·로그 상한·허용 root·dryRun 포함. [PR #18](https://github.com/EricSeokgon/egovframe-scaffold-mcp/pull/18)은 4파일(+458/−3), 오프라인 40단언과 실제 spawn 경로를 검증했습니다.
22
22
  - **v0.24.0 추가**: 공식 템플릿 커버리지 7 → 10종(`msa-common-components`·`mobile-device-api`·`ai-rag`, 모두 멀티 프로젝트). [PR #19](https://github.com/EricSeokgon/egovframe-scaffold-mcp/pull/19).
23
23
  - **v0.25.0 추가**: `test_egovframe_project` — 테스트를 실행하고 빌드도구가 남기는 JUnit XML 리포트(surefire·gradle)를 읽어 스위트·케이스 단위로 결과를 구조화합니다. 실패 케이스의 메시지·예외 타입·테스트 파일/라인, `testFilter`(클래스/메서드 패턴), 이전 실행 리포트 제외, 종료 코드가 0이어도 리포트에 실패가 있으면 실패로 판정. 오프라인 54단언(`npm run test:test`).
24
24
  - **v0.25.2 추가**: 보안·안정성 보강 — `generate_egovframe_ci`의 `jdk` 입력 검증(생성 YAML 주입 차단), 빌드·테스트 타임아웃 시 프로세스 트리 종료(래퍼가 띄운 JVM 때문에 타임아웃이 걸려도 호출이 끝나지 않던 문제 해결), MCP handshake 서버 버전을 `package.json`과 일치, 의존성 갱신으로 `npm audit` 0건.
25
- - **배포 상태**: npm 배포본은 **v0.25.1**(2026-09-13 실측), 저장소 소스는 v0.25.2 입니다. v0.25.2는 게시 전입니다.
25
+ - **v0.25.3 추가**: Linux·macOS에서 `npx egovframe-scaffold-mcp`(bin symlink 경유) 실행 시 서버가 기동하지 않고 종료되던 문제 수정, CI를 ubuntu·windows × Node 18·20·22 매트릭스로 확장.
26
+ - **배포 상태**: npm 최신 배포 버전은 상단 npm 배지와 [npm 패키지 페이지](https://www.npmjs.com/package/egovframe-scaffold-mcp)를 단일 출처로 확인합니다. 이 문서의 버전 표기는 저장소 소스(`package.json`) 기준이며, git 태그 `vX.Y.Z`가 해당 배포본의 커밋을 가리킵니다.
26
27
 
27
28
  ## 제공 도구
28
29
 
@@ -190,7 +191,8 @@ Claude Desktop / Claude Code 설정 예 (`mcpServers`):
190
191
  - 동기화 레벨: 공식 v5.0.6 태그→commit, SHA-256·크기·파일 수, `sec.security`, 미매핑 경로 0건 검증 (`npm run test:catalog-sync-live`, 네트워크 필요)
191
192
  - 조립 레벨: 실제 공통컴포넌트 저장소로 bbs+login+sec.security(+cmm) 843파일 조립, message·IDGN·웹 자산·공용 fragment·Maven 좌표·선별 DB 스크립트·충돌 전체 거부·파일/SQL/매니페스트 fault-injection rollback·상위 symlink 경계 검증 (`npm run test:components`)
192
193
  - 수명주기 레벨: 설치 매니페스트 기록, 중복 설치 거부, 의존 컴포넌트 제거 보호, 제거·검증 동작 (`npm run test:components`)
193
- - 프로토콜 레벨: MCP initialize / tools/list 핸드셰이크 및 `ref`·`dryRun` 파라미터 노출 확인
194
+ - 프로토콜 레벨: 빌드된 서버를 실제 프로세스로 띄워 MCP initialize / tools/list 핸드셰이크, `serverInfo.version`↔`package.json` 일치, 핵심 도구 노출, `jdk` 패턴 제약 노출 확인 (`npm run test:handshake`, 네트워크 불필요)
195
+ - 플랫폼 레벨: CI가 릴리스 게이트를 ubuntu·windows × Node 18·20·22 매트릭스로 실행하고, 공식 저장소를 내려받는 통합 테스트는 ubuntu/Node 20에서 실행합니다. 타임아웃 시 프로세스 트리 종료는 POSIX·Windows 모두 실제 프로세스로 검증합니다 (`npm run test:build`).
194
196
  - 레시피 레벨: `catalog/recipes.json`의 컴포넌트 id·의존성·템플릿 제공 컴포넌트 정합 검증 (`npm run test:recipes`, 네트워크 불필요). 공식 `simple-backend`의 기존 `cmm`을 보존하고 board-login의 bbs 88파일·login 41파일·SQL 4건(총 133파일)을 조립한 뒤 검증하며, 컴포넌트 이후 fault injection의 전체 staging rollback도 확인 (`npm run test:recipe-transaction`)
195
197
  - 진단 레벨: 픽스처(pom·DbType·컴포넌트 패키지)로 `diagnose_egovframe_project`의 빌드·버전·DbType·컴포넌트 지문·의존성 검출 검증 (`npm run test:diagnose`, 네트워크 불필요)
196
198
  - 문서 검색 레벨: `search_egovframe_docs`의 키워드 매칭·점수 정렬·컴포넌트 매핑·빈질의/미존재어 처리 검증 (`npm run test:docs`, 네트워크 불필요)
@@ -239,6 +241,11 @@ v0.25.0까지 프로젝트·CRUD 생성, 검증된 공통컴포넌트 실행 자
239
241
 
240
242
  ## 변경 이력
241
243
 
244
+ - **0.25.3** — 기동 버그 수정 + CI 확장(도구 인터페이스 하위 호환).
245
+ - **npx 기동 실패 수정(Linux·macOS)**: 진입점 판정이 `process.argv[1]`의 파일명 끝을 `import.meta.url`과 비교하는 방식이어서, npm이 POSIX에서 bin을 symlink(`node_modules/.bin/egovframe-scaffold-mcp → dist/index.js`)로 설치하면 진입점이 아니라고 판단해 서버를 띄우지 않고 오류 없이 종료했습니다. README가 안내하는 `npx -y egovframe-scaffold-mcp` 설정이 Linux·macOS에서 동작하지 않던 원인입니다(Windows는 `.cmd` shim이 `dist/index.js`를 직접 실행해 영향 없음, `node dist/index.js` 직접 실행도 영향 없음). 양쪽 경로를 realpath로 풀어 비교하도록 바꾸고, symlink 경유 기동을 회귀 테스트로 고정했습니다(`npm run test:handshake`).
246
+ - **CI**: 릴리스 게이트를 ubuntu·windows × Node 18·20·22 매트릭스로 실행하고, 공식 저장소를 내려받는 통합 테스트는 별도 job(ubuntu/Node 20)으로 분리했습니다. bash 파이프라인이던 핸드셰이크 확인을 플랫폼 중립 테스트(`test:handshake`)로 대체해 `prepublishOnly`에 포함했고, 런타임 의존성 `npm audit`(high 이상) 단계를 추가했습니다.
247
+ - **테스트**: 타임아웃 시 프로세스 트리 종료 회귀 테스트를 node 손자 프로세스 기반으로 바꿔 Windows(`taskkill /T /F` 경로)에서도 실행합니다.
248
+ - **문서**: 게시 시점에 따라 틀어지던 "배포 상태" 문구를 npm 배지 단일 출처 방식으로 정리했습니다.
242
249
  - **0.25.2** — 보안·안정성 보강(도구 인터페이스 하위 호환).
243
250
  - `generate_egovframe_ci`: `jdk` 값이 생성 워크플로 YAML에 검증 없이 삽입되어 따옴표·줄바꿈으로 임의 step을 끼워 넣을 수 있던 문제를 수정했습니다. 숫자·점 형식(`17`, `21`, `1.8`, `17.0.9`)만 허용하며 도구 스키마와 함수 양쪽에서 거부합니다. 위반 시 파일을 만들지 않습니다.
244
251
  - `build_egovframe_project`·`test_egovframe_project`: 타임아웃 시 직접 자식 프로세스만 종료해, `mvnw`/`gradlew`가 띄운 JVM이 출력 파이프를 붙잡은 채 살아남으면 타임아웃이 지나도 호출이 끝나지 않던 문제를 수정했습니다(재현: `timeoutMs` 1초 설정에 30초 후 반환). POSIX는 프로세스 그룹 단위 SIGKILL, Windows는 `taskkill /T /F`로 트리를 종료하고, 그래도 파이프가 닫히지 않으면 2초 유예 후 결과를 반환합니다. 실제 프로세스를 띄우는 회귀 테스트를 추가했습니다(`npm run test:build`).
package/dist/index.js CHANGED
@@ -17,6 +17,7 @@ import AdmZip from "adm-zip";
17
17
  import * as fs from "node:fs";
18
18
  import * as path from "node:path";
19
19
  import * as os from "node:os";
20
+ import { fileURLToPath } from "node:url";
20
21
  import { createHash, randomUUID } from "node:crypto";
21
22
  import { CRUD_JAVA_TYPES, CRUD_PROFILES, generateCrud } from "./crud.js";
22
23
  import { withDirectoryTransaction, withFileTransaction } from "./file-transaction.js";
@@ -2617,7 +2618,26 @@ export function buildServer() {
2617
2618
  });
2618
2619
  return server;
2619
2620
  }
2620
- const isMain = process.argv[1] && import.meta.url.endsWith(path.basename(process.argv[1]));
2621
+ /**
2622
+ * 이 파일이 실행 진입점인지 판정한다.
2623
+ *
2624
+ * POSIX 에서 npm 은 bin 을 `node_modules/.bin/egovframe-scaffold-mcp → dist/index.js` symlink 로 만들기 때문에
2625
+ * `process.argv[1]` 은 symlink 경로(확장자·파일명이 다름)다. 파일명 끝을 비교하면 `npx egovframe-scaffold-mcp`
2626
+ * 실행 시 진입점이 아니라고 판단해 서버를 띄우지 않고 조용히 종료하므로, 양쪽 모두 realpath 로 풀어 비교한다.
2627
+ */
2628
+ export function isMainModule(argv1 = process.argv[1], moduleUrl = import.meta.url) {
2629
+ if (!argv1)
2630
+ return false;
2631
+ try {
2632
+ const entry = fs.realpathSync(argv1);
2633
+ const self = fs.realpathSync(fileURLToPath(moduleUrl));
2634
+ return process.platform === "win32" ? entry.toLowerCase() === self.toLowerCase() : entry === self;
2635
+ }
2636
+ catch {
2637
+ return false;
2638
+ }
2639
+ }
2640
+ const isMain = isMainModule();
2621
2641
  if (isMain) {
2622
2642
  const server = buildServer();
2623
2643
  const transport = new StdioServerTransport();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "egovframe-scaffold-mcp",
3
- "version": "0.25.2",
3
+ "version": "0.25.3",
4
4
  "description": "전자정부 표준프레임워크(eGovFrame) 프로젝트·CRUD 스캐폴딩과 검증된 공통컴포넌트 완전 조립 MCP 서버",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -15,7 +15,7 @@
15
15
  "test:catalog": "node test/catalog.mjs",
16
16
  "test:components": "node test/components.mjs",
17
17
  "generate:catalog": "node scripts/generate-catalog.mjs",
18
- "prepublishOnly": "npm run build && npm run test:catalog && npm run test:catalog-sync && npm run test:ai && npm run test:recipes && npm run test:diagnose && npm run test:docs && npm run test:report && npm run test:upgrade && npm run test:remove && npm run test:transaction && npm run test:allowed-roots && npm run test:explain && npm run test:ci && npm run test:build && npm run test:test && npm run test:pom && npm run test:crud",
18
+ "prepublishOnly": "npm run build && npm run test:catalog && npm run test:catalog-sync && npm run test:ai && npm run test:recipes && npm run test:diagnose && npm run test:docs && npm run test:report && npm run test:upgrade && npm run test:remove && npm run test:transaction && npm run test:allowed-roots && npm run test:explain && npm run test:ci && npm run test:build && npm run test:test && npm run test:pom && npm run test:crud && npm run test:handshake",
19
19
  "test:ai": "node test/ai.mjs",
20
20
  "generate:ai-catalog": "node scripts/generate-ai-catalog.mjs",
21
21
  "test:ai-assembly": "node test/ai-assembly.mjs",
@@ -37,7 +37,8 @@
37
37
  "test:pom": "node test/pom.mjs",
38
38
  "test:catalog-sync": "node test/catalog-sync.mjs",
39
39
  "test:catalog-sync-live": "node test/catalog-sync-live.mjs",
40
- "test:allowed-roots": "node test/allowed-roots.mjs"
40
+ "test:allowed-roots": "node test/allowed-roots.mjs",
41
+ "test:handshake": "node test/handshake.mjs"
41
42
  },
42
43
  "engines": {
43
44
  "node": ">=18"