키워드 기반으로 로컬 docs/ 폴더의 마크다운 문서를 검색해 LLM 에이전트(Claude Code / Codex / Cursor 등)에게 반환하는 로컬 MCP 서버 샘플.
- 에이전트가
get_design_docs,get_react_design_guide,get_api_docs,get_test_docs중 하나를 호출하면서topic키워드를 넘긴다. - 서버는
DOCS_PATH아래의 해당 도메인 폴더(design/,react-design/,api/,testing/)에서.md파일을 수집한다. - 키워드 + 동의어 + 우선순위 패턴으로 파일을 랭킹해 상위 8개(curated) 또는 매칭된 전체(full)를 본문과 함께 텍스트로 반환한다.
랭킹 점수 구성:
- priority pattern: 도메인별로 미리 정의한 핵심 파일 경로일수록 가산점
- filename match: 파일명에 키워드가 들어가면 큰 가산점
- path match: 폴더 경로에 키워드가 들어가면 중간 가산점
- content occurrences: 본문 키워드 등장 횟수 (최대 10회까지)
- exact phrase: topic 전체 문장이 본문에 그대로 등장하면 추가 가산점
tools/test-mcp/
├── package.json
├── tsconfig.json
├── install.sh / install.cmd # pnpm install + tsc build
├── register-codex.sh / register-codex.cmd # Codex CLI에 MCP 등록
├── src/
│ ├── index.ts # MCP 서버 진입점 (StdioServerTransport)
│ ├── search.ts # 마크다운 수집·랭킹·포맷팅
│ └── scripts/
│ └── query-regression.ts # 랭킹 회귀 테스트
└── README.md
cd tools/test-mcp
./install.sh # pnpm install + pnpm build
# Windows: install.cmd빌드 결과는 dist/에 생성된다.
DOCS_PATH=/absolute/path/to/docs node dist/index.jsstdio로 MCP 요청을 받는다. 단독 실행은 LLM 호스트가 stdin/stdout으로 JSON-RPC를 주고받을 때만 의미가 있다.
{
"mcpServers": {
"local-docs-guide": {
"command": "node",
"args": ["/absolute/path/to/tools/test-mcp/dist/index.js"],
"env": {
"DOCS_PATH": "/absolute/path/to/docs"
}
}
}
}./register-codex.sh
# 등록 확인
codex mcp get local-docs-guideDOCS_PATH 환경변수가 미리 설정돼 있지 않으면 <repo>/docs를 기본값으로 사용한다.
command = node, args = ["dist/index.js"], env.DOCS_PATH = ... 형태로 등록하면 동작한다.
docs/
├── design/
│ ├── foundation/invariants.md
│ ├── architecture/overview.md
│ ├── architecture/source-structure.md
│ └── architecture/state-management.md
├── react-design/
│ ├── foundation/invariants.md
│ ├── architecture/overview.md
│ ├── architecture/source-structure.md
│ ├── architecture/state-management.md
│ └── components/overview.md
├── api/
│ ├── foundation/invariants.md
│ ├── architecture/overview.md
│ ├── endpoints/overview.md
│ └── auth/overview.md
└── testing/
├── overview.md
├── unit-testing.md
├── integration-testing.md
└── e2e-testing.md
위 경로들은 src/search.ts의 createDomainConfigs()에서 도메인별 priorityPatterns / defaultEntryPaths로 정의돼 있다. 본인 프로젝트의 폴더 구조에 맞게 자유롭게 수정하면 된다.
-
src/search.ts의createDomainConfigs()에 새 키를 추가한다.get_runtime_docs: { folderPath: path.join(docsPath, 'runtime'), priorityPatterns: ['overview.md', 'lifecycle.md'], defaultEntryPaths: ['overview.md'] }
-
src/index.ts의tools배열에 동일한 이름으로 tool 정의를 추가한다 (name, description, inputSchema). -
pnpm build후 MCP 호스트를 재시작한다.
src/search.ts 상단:
QUERY_STOP_WORDS— 검색 시 무시할 흔한 단어TOKEN_SYNONYMS— 키워드 → 유사어 매핑 (예:hook↔subscription)
도메인 용어가 많은 프로젝트라면 여기 동의어를 추가하면 검색 정확도가 크게 올라간다.
DOCS_PATH=/absolute/path/to/docs pnpm test:queriessrc/scripts/query-regression.ts 의 cases 배열에 (tool, topic, expected[]) 쌍을 추가하면, 향후 동의어/우선순위를 바꿔도 기대 문서가 상위에 잡히는지 자동 검증할 수 있다.
이 샘플은 사내 프로젝트에서 사용 중이던 docs 검색 MCP 서버를 도메인 종속 명칭을 제거하고 공개용으로 정리한 것이다. 자유롭게 fork/수정하여 사용하면 된다.