Skip to main content
Glama
wjswnsdnjs1

eGov Security MCP Server

by wjswnsdnjs1
README.md
# eGov Security MCP Server

전자정부프레임워크 보안 공지 수집, 첨부파일 다운로드, PDF 분석, 수정 diff 미리보기, 검증/알림을 제공하는 커스텀 MCP 서버입니다.

## 도구

- `fetch_latest_security_notice`: 보안 공지 페이지를 크롤링하고, 기본적으로 최신 보안 공지 1건의 첨부파일을 모두 다운로드합니다.
- `analyze_vulnerability_context`: 다운로드된 PDF를 읽고 취약점 요약, 조치 대상 후보 파일, 승인 전 확인용 diff 미리보기를 생성합니다.
- `verify_and_notify_result`: Maven/Gradle 검증을 실행하고 결과를 반환합니다.
- `generate_work_summary_report`: 수집, 분석, 검증 결과를 하나의 Markdown 파일로 정리합니다.

소스 수정은 MCP Tool이 직접 수행하지 않습니다. Codex/Claude가 `fix_previews`를 바탕으로 수정 계획을 보여주고, 사용자가 승인하면 일반 코드 편집 기능으로 프로젝트 파일을 수정하는 구조입니다.

## 설치

```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -e ".[dev]"
```

## 실행

```powershell
egov-security-mcp
```

또는:

```powershell
python -m egov_security_mcp.server
```

## Codex/Claude Desktop MCP 예시

```json
{
  "mcpServers": {
    "egov-security": {
      "command": "python",
      "args": ["-m", "egov_security_mcp.server"],
      "cwd": "D:\\workspace\\mcp_custom_prj"
    }
  }
}
```

## `fetch_latest_security_notice`

```json
{
  "download_dir": "data/notices",
  "notice_query": null,
  "max_downloads": null,
  "max_notices": 1
}
```

- `notice_query`를 지정하면 전자정부프레임워크 공지사항 게시판에서 제목 기준으로 검색합니다.
- 기본 실행은 최신 보안 공지 1건만 상세 조회합니다.
- `max_notices` 기본값은 `1`입니다. 다건 공지 수집이 필요할 때만 값을 늘리거나 `null`로 지정합니다.
- `max_downloads`를 생략하거나 `null`로 두면 선택된 공지의 첨부파일을 모두 다운로드합니다.
- 상세 URL에 `nttId`만 있으면 서버가 `menuNo=74`, `bbsId=6`을 자동 보완합니다.
- 다운로드 폴더는 `download_dir/nttId/공지 제목/` 형식으로 생성합니다.
- 이미 처리한 공지는 `nttId`를 기준으로 `download_dir/.crawl_state.json`에 저장된 상세 페이지 해시와 비교합니다. 변경이 없으면 다운로드를 건너뛰고 `skipped_notices`에 `already_processed_unchanged`로 기록합니다.
- 기존 공지가 수정되면 해시가 달라지므로 다시 첨부파일을 다운로드하고 상태 파일을 갱신합니다.
- 공지 상세 페이지에 첨부파일이 없으면 다운로드를 시도하지 않고 `notice_content_summaries`에 게시글 본문 요약을 담아 반환합니다.

다운로드 경로:

```text
data/notices/
└── 1949/
    └── 2026년도 표준프레임워크 템플릿 보안 패치 안내/
        ├── 공통컴포넌트 보안패치 내역.pdf
        ├── MSA-EDU 보안패치 내역.pdf
        └── 심플홈페이지-프론트-백엔드 보안패치 내역.pdf
```

특정 과거 공지 검색 예시:

```text
fetch_latest_security_notice를 실행해줘.
notice_query는 "2024년도 공통컴포넌트 보안 패치 안내",
download_dir는 data/notices,
max_downloads는 null로 해줘.
max_notices는 1로 해줘.
```

이미 처리된 공지를 다시 요청했을 때 변경이 없으면 결과는 대략 아래처럼 반환됩니다.

```json
{
  "already_processed_count": 1,
  "skipped_notices": [
    {
      "reason": "already_processed_unchanged",
      "message": "이미 처리된 공지이며 내용 변경이 없어 추가 작업을 건너뜁니다."
    }
  ],
  "downloaded": []
}
```

첨부파일이 없는 신규/수정 공지는 결과가 대략 아래처럼 반환됩니다.

```json
{
  "notices_without_attachments_count": 1,
  "notice_content_summaries": [
    {
      "reason": "no_attachment_found",
      "message": "첨부파일이 없는 공지라서 다운로드 없이 게시글 본문 요약을 제공합니다.",
      "notice_id": "2000",
      "notice_title": "2026년 1분기 모바일 디바이스 API (Server) 보안 패치 안내",
      "summary": {
        "text_excerpt": "게시글 본문 일부...",
        "important_lines": ["보안 패치 적용 안내입니다."]
      }
    }
  ],
  "downloaded": []
}
```

## `analyze_vulnerability_context`

다운로드된 PDF를 분석하고, PDF가 없으면 `fetch_latest_security_notice`가 저장한 게시글 본문 요약을 분석합니다.

분석 결과에는 아래 정보가 포함됩니다.

- `input_source`: `pdf` 또는 `notice_page`
- `summary`: PDF 또는 게시글 본문 핵심 요약, 버전/CVE/KVE/중요 문장 후보
- `target_file_candidates`: 프로젝트 내 조치 대상 후보 파일
- `fix_previews`: 승인 전 확인용 수정 계획과 unified diff 미리보기
- `diff_preview_report`: `fix_previews`를 사람이 읽기 쉬운 Markdown diff 보고서로 합친 값

PDF가 있는 경우:

```text
방금 다운로드한 보안패치 PDF를 analyze_vulnerability_context로 분석해줘.
취약점 요약, 조치 대상 후보 파일, 그리고 diff_preview_report 원문을 보여줘.
project_dir는 D:\workspace\my-project로 해줘.
```

PDF가 없는 공지인 경우:

```text
방금 크롤링한 공지에는 PDF 첨부가 없으니 analyze_vulnerability_context로 게시글 본문을 분석해줘.
notice_id는 2000,
download_dir는 data/notices,
project_dir는 D:\workspace\my-project로 해줘.
```

이 경우 `data/notices/.crawl_state.json`의 `page_summary` 또는 `fetch_latest_security_notice` 결과의 `notice_content_summaries`를 사용합니다. 먼저 `fetch_latest_security_notice`를 실행해야 게시글 본문 요약이 저장됩니다.

현재 diff 미리보기는 확정적으로 판단 가능한 룰부터 제공합니다. 예를 들어 PDF에서 세션/쿠키 보안 설정이 언급되고 프로젝트에 `web.xml`이 있으면, 아래처럼 `<cookie-config>`에 `http-only`와 `secure`를 추가하거나 보정하는 diff를 반환합니다.

```diff
--- src/main/webapp/WEB-INF/web.xml:before
+++ src/main/webapp/WEB-INF/web.xml:after
@@
 <web-app>
+    <session-config>
+        <cookie-config>
+            <http-only>true</http-only>
+            <secure>true</secure>
+        </cookie-config>
+    </session-config>
 </web-app>
```

확신이 낮은 파일은 `manual_review_required`로 표시됩니다. 이 경우 Codex/Claude가 PDF 요약과 파일 내용을 함께 보고 별도 수정 계획을 제안해야 합니다.

EgovFileTool 경로 취약점처럼 `tempFolderPath` 또는 `Globals.fileWebrootPath` 사용이 발견되면, `Globals.fileStorePath`로 바꾸는 중간 신뢰도 diff preview를 생성합니다. 이 preview는 실제 수정이 아니라 승인 전 검토용입니다.

## 승인 후 수정 흐름

```text
분석 결과와 diff 미리보기 확인했어.
제안한 수정 계획대로 프로젝트 파일을 수정해줘.
수정 후 변경 파일과 diff 요약을 알려줘.
```

이 단계의 파일 수정은 MCP 서버가 아니라 Codex/Claude의 일반 코드 편집 기능으로 수행됩니다.

## `verify_and_notify_result`

```text
verify_and_notify_result를 실행해서 Maven/Gradle 테스트를 돌리고 결과를 알려줘.
project_dir는 D:\workspace\my-project로 해줘.
```

Windows에서 MCP 클라이언트가 Maven PATH를 물고 있지 않으면 `mvn` 대신 `mvn.cmd` 절대경로를 넘기면 됩니다.

```text
verify_and_notify_result를 실행해줘.
project_dir는 D:\workspace\my-project로 하고,
verify_command는 ["D:\\env\\maven\\apache-maven-3.9.16\\bin\\mvn.cmd", "compile", "-q"]로 해줘.
```

프로젝트 루트에 `mvnw.cmd`가 있으면 `verify_command`를 생략해도 자동으로 Maven Wrapper를 우선 사용합니다.

## `generate_work_summary_report`

수집/분석/검증 결과를 하나의 Markdown 파일로 생성합니다. 이전 Tool 결과를 그대로 넘기면 가장 자세한 보고서가 만들어지고, 결과 객체를 넘기지 않아도 `download_dir/.crawl_state.json`과 다운로드된 PDF/첨부파일 목록을 기준으로 보고서 내용을 자동 보강합니다.

```text
generate_work_summary_report를 실행해줘.
fetch_latest_security_notice 결과, analyze_vulnerability_context 결과, verify_and_notify_result 결과를 포함해서 정리해줘.
```

사용자 지정 제목을 적용해서 생성할 때는 아래 값만 넘깁니다. 별도 Markdown 파일을 재가공할 필요가 없으면 `source_report_path`는 사용하지 않습니다.

```json
{
  "title": "2026년 1분기 모바일 디바이스 API (Server) 보안 패치 작업 결과",
  "output_dir": "data/report",
  "use_custom_output": true,
  "use_custom_title": true,
  "notice_id": "1939"
}
```

`analysis_result`를 넘기지 않아도 `notice_id` 기준으로 `data/notices/{notice_id}` 아래 PDF를 찾아 취약점 요약, 공식 패치 방법 후보, 첨부파일 목록을 자동으로 채웁니다. 프로젝트 조치 대상 파일까지 함께 채우려면 `project_dir`를 같이 넘깁니다.

```json
{
  "title": "2026년 1분기 모바일 디바이스 API (Server) 보안 패치 작업 결과",
  "output_dir": "data/report",
  "use_custom_output": true,
  "use_custom_title": true,
  "notice_id": "1939",
  "project_dir": "D:\\mVoting\\workspace"
}
```

이미 정리된 Markdown 보고서를 재가공해야 할 때만 `source_report_path`를 넘깁니다. 이 경우 상단 제목/생성일/공지사항 번호/제목은 표준 형식으로 다시 만들고, 기존 Markdown 본문은 그대로 이어 붙입니다.

`source_report_path`를 사용할 때 보고서 유형 우선순위는 아래와 같습니다.

1. `20260715_security_patch_report.md`처럼 `## 1.`부터 `## 10.`까지 번호 섹션이 있는 상세 보안 패치 보고서 형식
2. 1번 형식에 맞지 않으면 `egov-security-work-summary_*.md`처럼 기존 본문을 보존하는 work-summary fallback 형식

```text
generate_work_summary_report를 실행해줘.
source_report_path는 data/report/20260715/security_patch_report_2025_Q2.md,
```

기본 보고서 제목은 `전자정부 표준프레임워크 보안 패치 결과`입니다. 보고서 상단에는 생성일, 공지사항 번호, 제목이 명시됩니다.

일반적인 사용에서는 `title`, `output_dir`, `output_filename`, `download_dir`를 넘기지 않습니다. `download_dir`를 생략하면 내부적으로 `data/notices`를 사용합니다.

클라이언트가 자연어를 해석하면서 `title`, `output_dir`, `output_filename`을 임의로 채워 넣어도 기본값이 우선 적용됩니다. 사용자 지정 제목을 실제로 적용하려면 `use_custom_title`을 `true`로 함께 넘기고, 사용자 지정 저장 경로/파일명을 실제로 적용하려면 `use_custom_output`을 `true`로 함께 넘깁니다.

저장 경로는 기본적으로 아래 형식입니다.

```text
data/report/
└── 공지사항번호/
    └── egov-security-work-summary_YYYYMMDDHHMMSS.md
```

예를 들어 공지사항 번호가 `1900`이면 아래에 생성됩니다.

```text
data/report/1900/egov-security-work-summary_20260715134100.md
```

`output_filename`을 생략하거나 빈 값으로 넘기면 기본 파일명 `egov-security-work-summary.md`를 사용하고, 실제 저장 시 타임스탬프가 붙습니다.

생성되는 보고서에는 보통 아래 섹션이 포함됩니다.

- 분석 입력 자료
- 1. 취약점 요약
- 2. 공식 패치 방법
- 3. 패치된 코드
- 4. 프로젝트 조치 대상 파일
- 5. 변경된 파일 요약
- 6. Diff 요약
- 7. 문제 원인 및 해결
- 8. 보안 효과
- 9. Maven 컴파일 검증 결과
- 10. 주의사항

반환값 예시:

```json
{
  "report_path": "D:\\workspace\\mcp_custom_prj\\data\\report\\1900\\egov-security-work-summary_20260715134100.md",
  "format": "markdown",
  "notice_id": "1900",
  "notice_title": "2024년도 공통컴포넌트 보안 패치 안내",
  "bytes": 12345
}
```