배경
이슈만으로 표현하기 어려운 비즈니스 정책 / 데이터 모델 등의 디테일은 wiki
문서로 기록 (사용자 지시). M3 의 wiki 구현은 GitHub Wiki, 대상 repo 는
vonkernel/guestbook.
본 이슈는 #36 (IssueTracker MCP) 와 같은 패턴 적용 — mcp/CLAUDE.md §0 (thin
bridge) + §2.2 (API-client) + ISP + composition.
호출자 (proposal §6.1단계)
P 가 PRD 작성 후:
- Doc Store(
wiki_pages collection) 에 영속 (Librarian 통해)
- GitHub Wiki MCP 호출해 GitHub Wiki 에 동기화
본 PR 의 스코프는 위 2번의 MCP 도구 노출 + SDK 까지. P 의 graph 가 SDK 호출
하는 wiring 은 별 이슈 (M3 의 P 그래프 확장 #39 등).
모듈 구조 (#36 미러)
mcp/wiki/ (서버, §2.2 API-client 패턴, ISP)
src/wiki_mcp/
├── adapters/
│ ├── base.py # PageOps ABC + Wiki (composition) ABC
│ └── github/ # 패키지 (도메인별 모듈 분할)
│ ├── adapter.py # GitHubWikiAdapter (composition)
│ ├── page.py # GitHubPageOps (6 op)
│ ├── _ctx.py # 공유 _Ctx
│ └── _git.py # subprocess git wrapper (clone/commit/push)
├── factory.py # WIKI_TYPE → 어댑터 (OCP)
├── tools/page.py # 6 도구 (delegate to tracker.pages.X)
├── mcp_instance.py
└── server.py
scripts/
├── verify_sandbox.sh
└── verify_sandbox.py # 자동 검증
shared/src/dev_team_shared/wiki/ (consumer SDK, doc-store/issue_tracker 미러)
├── schemas/page.py # PageCreate / PageUpdate / PageRead / PageRef
├── tool_names.py # PageTools
├── _ops_client.py # PageClient
└── client.py # WikiClient (composition: 1 property `pages`)
추상화 — Wiki ABC (ISP)
class PageOps(ABC):
async def create(doc: PageCreate) -> PageRead
async def update(slug: str, patch: PageUpdate) -> PageRead | None
async def get(slug: str) -> PageRead | None
async def list() -> list[PageRef] # slug + title 만 (가벼움)
async def delete(slug: str) -> bool
async def count() -> int
class Wiki(ABC): # 컴포지트
@property @abstractmethod
def pages(self) -> PageOps
transition / close 같은 lifecycle 없음 — wiki page 는 just data.
GitHub Wiki 어댑터 — subprocess git
GitHub Wiki = 별 git repo (<owner>/<repo>.wiki.git). GraphQL / REST 미지원
(GitHub API 에 wiki 페이지 CRUD endpoint 없음 — git access 만 공식).
구현: subprocess git 호출 (외부 라이브러리 dulwich 등 미사용 — 표준 git
binary 가 일관성 / 디버그 / standard 우위).
| op |
동작 |
| create / update |
clone → write <slug>.md (front matter + content) → commit → push |
| get |
clone → read <slug>.md → front matter parse |
| list |
clone → ls *.md (front matter title 추출) |
| delete |
clone → rm <slug>.md → commit → push |
| count |
clone → ls 카운트 |
인증: HTTPS URL 에 token 임베드 (https://x-access-token:{token}@github.com/...).
workdir 은 매 호출마다 임시 디렉터리 + 작업 후 cleanup → token leak 방지.
Dockerfile: apt install -y --no-install-recommends git 추가 (~30MB).
front matter (page metadata 인코딩)
YAML front matter — 표준 필드 + 도메인 필드 분리:
---
title: GuestBook PRD
created_at: 2026-05-04T17:39:00Z
updated_at: 2026-05-04T17:39:00Z
page_type: prd
structured:
milestones:
- {name: M1}
in_scope: ["..."]
---
# GuestBook — PRD
...
GitHub Wiki UI 가 front matter 를 hide 하지 않고 그대로 렌더 (사람이 보기 약간
noisy 하지만 round-trip 가능). doc-store 의 wiki_pages.page_type / structured
와 키 일치.
식별자 — slug
GitHub Wiki 의 페이지 파일명 = <slug>.md. URL 도 slug 기반:
github.com/<owner>/<repo>/wiki/<slug>.
slug 컨벤션 — kebab-case (doc-store wiki_pages.slug 와 일치).
도구 면 (6 op)
| 도구 |
args |
return |
page.create |
doc: PageCreate{slug, title, content_md, page_type, structured?} |
PageRead |
page.update |
slug: str, patch: PageUpdate{title?, content_md?, structured?} |
PageRead | None |
page.get |
slug: str |
PageRead | None |
page.list |
(없음) |
list[PageRef{slug, title}] |
page.delete |
slug: str |
bool |
page.count |
(없음) |
int |
환경변수
#36 과 재활용:
GITHUB_TOKEN (PAT, repo scope 가 wiki 권한 포함)
GITHUB_TARGET_OWNER
GITHUB_TARGET_REPO
신규: WIKI_TYPE (default github, factory 가 사용).
포트
mcp/CLAUDE.md §3 표 — 9102 (이미 예약).
비-스코프
검증 (sandbox: vonkernel/guestbook)
scripts/verify_sandbox.sh 자동:
배경
이슈만으로 표현하기 어려운 비즈니스 정책 / 데이터 모델 등의 디테일은 wiki
문서로 기록 (사용자 지시). M3 의 wiki 구현은 GitHub Wiki, 대상 repo 는
vonkernel/guestbook.본 이슈는 #36 (IssueTracker MCP) 와 같은 패턴 적용 —
mcp/CLAUDE.md §0(thinbridge) +
§2.2(API-client) + ISP + composition.호출자 (proposal §6.1단계)
P 가 PRD 작성 후:
wiki_pagescollection) 에 영속 (Librarian 통해)본 PR 의 스코프는 위 2번의 MCP 도구 노출 + SDK 까지. P 의 graph 가 SDK 호출
하는 wiring 은 별 이슈 (M3 의 P 그래프 확장 #39 등).
모듈 구조 (#36 미러)
mcp/wiki/(서버, §2.2 API-client 패턴, ISP)shared/src/dev_team_shared/wiki/(consumer SDK, doc-store/issue_tracker 미러)추상화 —
WikiABC (ISP)transition/close같은 lifecycle 없음 — wiki page 는 just data.GitHub Wiki 어댑터 — subprocess git
GitHub Wiki = 별 git repo (
<owner>/<repo>.wiki.git). GraphQL / REST 미지원(GitHub API 에 wiki 페이지 CRUD endpoint 없음 — git access 만 공식).
구현: subprocess
git호출 (외부 라이브러리 dulwich 등 미사용 — 표준 gitbinary 가 일관성 / 디버그 / standard 우위).
<slug>.md(front matter + content) → commit → push<slug>.md→ front matter parse*.md(front matter title 추출)<slug>.md→ commit → push인증: HTTPS URL 에 token 임베드 (
https://x-access-token:{token}@github.com/...).workdir 은 매 호출마다 임시 디렉터리 + 작업 후 cleanup → token leak 방지.
Dockerfile:
apt install -y --no-install-recommends git추가 (~30MB).front matter (page metadata 인코딩)
YAML front matter — 표준 필드 + 도메인 필드 분리:
GitHub Wiki UI 가 front matter 를 hide 하지 않고 그대로 렌더 (사람이 보기 약간
noisy 하지만 round-trip 가능). doc-store 의
wiki_pages.page_type / structured와 키 일치.
식별자 — slug
GitHub Wiki 의 페이지 파일명 =
<slug>.md. URL 도 slug 기반:github.com/<owner>/<repo>/wiki/<slug>.slug 컨벤션 — kebab-case (doc-store
wiki_pages.slug와 일치).도구 면 (6 op)
page.createdoc: PageCreate{slug, title, content_md, page_type, structured?}PageReadpage.updateslug: str, patch: PageUpdate{title?, content_md?, structured?}PageRead | Nonepage.getslug: strPageRead | Nonepage.listlist[PageRef{slug, title}]page.deleteslug: strboolpage.countint환경변수
#36과 재활용:GITHUB_TOKEN(PAT,reposcope 가 wiki 권한 포함)GITHUB_TARGET_OWNERGITHUB_TARGET_REPO신규:
WIKI_TYPE(defaultgithub, factory 가 사용).포트
mcp/CLAUDE.md §3표 — 9102 (이미 예약).비-스코프
검증 (sandbox: vonkernel/guestbook)
scripts/verify_sandbox.sh자동:page.create("[verify]-sandbox", title, content)→ wiki 에 실 생성page.get라운드트립 (front matter parse 확인)page.list가 만든 페이지 포함page.updatecontent 변경 반영page.delete후page.get→ None