= [Dev] Mcp [Dev] 에이전트(Claude Code 등)가 위키를 찾고 읽고, 허용하면 쓰게 해 주는 MCP(Model Context Protocol) 서버입니다. `scripts/mcp.ahawiki.mjs` 한 파일이고, 위키의 [Api] 를 도구로 감쌀 뿐입니다 — 새 권한도 새 저장 경로도 없습니다. == 왜 만들었나 노션이 올해 외부 에이전트(Claude Code·Cursor·Codex 등)를 작업공간에 붙이는 길을 열었습니다. AhaWiki 는 이미 API Key 로 읽고 쓰는 `/api/v1` 이 있으니, 필요한 것은 에이전트가 그것을 «도구로» 알아보게 하는 얇은 층이었습니다. 에이전트에게 `curl` 예시를 주는 것([Api] 의 «AI 자동화 프롬프트 예시»)과 달리, 도구는 이름·설명·인자가 에이전트에게 구조로 보이고 사용자가 호출 하나하나를 승인할 수 있습니다. == 쓰는 법 [[[#!Vim bash AHAWIKI_BASE_URL=https://<위키 주소> AHAWIKI_API_KEY=<키> node scripts/mcp.ahawiki.mjs ]]] Claude Code 에서는 이 명령을 MCP 서버로 등록합니다(`claude mcp add`). 위키 주소는 환경변수로만 받습니다 — 이 저장소는 공개라서 주소를 적지 않습니다. 키는 본인의 API Key([Dev ApiKey])이고, 에이전트는 그 키 소유자가 볼 수 있는 것만 보고 쓸 수 있는 것만 씁니다. [[[#!Table tsv 1 도구 하는 일 쓰기 `ahawiki_search` 이름·본문 검색. 맞은 곳 앞뒤 글과 함께 아니오 `ahawiki_read_page` 페이지 원문과 현재 revision 아니오 `ahawiki_list_pages` 이름 접두사로 목록 아니오 `ahawiki_recent_changes` 최근 변경 아니오 `ahawiki_save_page` 페이지 전체를 바꿔 저장 예 — `AHAWIKI_MCP_WRITE=1` 일 때만 보입니다 ]]] == 정한 것과 그 이유 * '''기본은 읽기 전용입니다.''' 쓰기 도구는 `AHAWIKI_MCP_WRITE=1` 을 줘야 목록에 나타납니다. 키가 쓰기를 할 수 있어도 에이전트에게는 쓰는 길이 아예 없는 상태가 기본입니다. 도구를 숨기는 것이 «쓰지 마세요» 라고 부탁하는 것보다 확실합니다. * '''저장에는 revision 과 comment 가 필수입니다.''' revision 은 읽을 때 받은 것을 그대로 돌려줘야 하고(새 페이지는 0), 그사이 누가 고쳤으면 서버가 409 로 거절해 덮어쓰지 않습니다. 에이전트가 «읽지 않고 쓰는» 길이 없습니다. comment 는 [Api] 와 같은 이유로 비울 수 없습니다 — 페이지 이력에 남는 것이 그것입니다. 둘 다 위키에 닿기 전에 서버 쪽 도구에서 먼저 거절합니다. * '''저장은 기본이 minor edit 입니다.''' 에이전트의 수정이 최근 변경 목록을 채우지 않게. `viaApi` 와 키 이름은 서버가 알아서 기록하므로 «누가 했는지» 는 남습니다. * '''삭제·이름 바꾸기는 도구로 주지 않았습니다.''' 되돌릴 수 없는 일을 에이전트의 한 번의 호출에 맡기지 않습니다. 필요하면 사람이 합니다. * '''SDK 를 쓰지 않고 손으로 썼습니다.''' 이 저장소의 의존성은 번들러 하나뿐이고, 필요한 메서드는 `initialize`·`ping`·`tools/list`·`tools/call` 넷입니다. 프로토콜 처리(`scripts/lib/mcp.mjs`)와 위키 도구(`scripts/mcp.ahawiki.mjs`)를 나눴고, 앞의 것은 위키를 모릅니다. * '''도구가 던진 오류는 프로토콜 오류가 아니라 `isError` 결과입니다.''' 호출은 도구까지 닿았고, 무엇이 틀렸는지 모델이 읽고 다시 해 보게 해야 합니다(예: 409 를 받고 다시 읽어 합치기). 프로토콜 오류는 이 서버가 알아들을 수 없는 요청에만 씁니다. == 서버 쪽에 더한 것: `GET /api/v1/search` 에이전트가 «어느 페이지를 열지» 찾으려면 JSON 검색이 필요했는데, `/search` 는 HTML 만 줬습니다. [Api] 의 «검색» 에 쓴 대로, 검색 화면과 같은 질의·같은 읽기 권한 필터에 평문 발췌(`SearchSnippet`)를 얹었습니다. 상한을 100 으로 둔 것은 위키를 통째로 내려받는 용도가 아니어서입니다. == 확인한 것과 못 한 것 * `test/mcp.ahawiki.test.mjs` — 프로토콜(초기화·알림·없는 메서드), 쓰기 도구가 스위치 없이는 안 보이는 것, revision·comment 없는 저장이 서버에 닿기 전에 거절되는 것, 오류가 `isError` 로 돌아오는 것, 베어러 키와 상태 코드 오류를 가짜 위키로 확인합니다. * 실제 stdio 로 `initialize`·`tools/list` 를 주고받는 것과 환경변수가 없을 때 종료하는 것을 손으로 확인했습니다. * '''운영 위키에 대한 호출(검색 포함)은 배포 뒤에야 해 볼 수 있습니다.''' 서버 쪽 검색은 컴파일과 `SearchSnippetSpec` 으로만 확인했습니다. * '''실제 에이전트(Claude Code)에 등록해 써 본 것은 아직 없습니다.''' == 하지 않은 것 * HTTP 로 여는 원격 MCP 서버(OAuth 포함). 로컬 stdio 로 충분하고, 위키에 인증 경로를 하나 더 만들게 됩니다. * 속성(`#!Schema`)으로 거르는 도구. [InterpreterQuery] 같은 질의 뷰가 생기면 그 위에 얹는 것이 맞습니다.