# Knowledge Base

> Hybrid-search knowledge base for teams — ingests docs, git logs, Slack, code, and PRs into one Postgres+pgvector table, served over MCP, CLI, and a web dashboard

- **Type:** MCP server
- **Install:** `agentstack add mcp-riemannulus-knowledge-base`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [riemannulus](https://agentstack.voostack.com/s/riemannulus)
- **Installs:** 0
- **Category:** [Databases](https://agentstack.voostack.com/c/databases)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [riemannulus](https://github.com/riemannulus)
- **Source:** https://github.com/riemannulus/knowledge-base

## Install

```sh
agentstack add mcp-riemannulus-knowledge-base
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# knowledge-base

여러 소스(문서, git 로그, Slack, …)의 팀 지식을 **하나의 Postgres 임베딩 테이블**로
수집하고, **하이브리드 검색**(전문검색 + 벡터 + RRF 융합)을 **MCP 도구**로 노출하는
지식 베이스 서버.

> Inspired by Cerebras’ ["How We Built Our Knowledge Base"](https://www.cerebras.ai/blog/how-we-built-our-knowledge-base).

핵심 원칙:

- **정보가 사는 곳에서 그대로 추출** — 커넥터가 소스별로 행을 정규화해 같은 테이블에 쓴다.
  테이블에 들어가면 즉시 같은 인터페이스로 검색된다.
- **하이브리드 검색** — 전문검색(정확 토큰: 에러 문자열·설정 키)과 벡터 검색(개념 질의)을
  RRF(k=60)로 융합. Slack 문서에는 나이 감쇠("옛 답변은 만료된다") 적용.
- **MCP에는 LLM-free 검색 프리미티브만** — 합성된 답이 아니라 원시 증거 행을 반환.
  오케스트레이션과 답변 생성은 Claude Code 같은 클라이언트 에이전트의 몫.
- **에이전트가 쓰는 지식 베이스** — 개발 중 내린 의사결정(`record_decision`)과
  삽질에서 얻은 교훈(`record_learning`)을 MCP로 직접 기록하면 즉시 팀 전체가 검색 가능.
  작업 전 `pitfalls`로 과거에 밟은 문제를 확인해 **같은 실수를 반복하지 않는다**
  → [팀 워크플로 가이드](docs/05-team-workflow.md).

```
 SOURCES        markdown · git log · Slack(export/실시간) · 코드 저장소 · GitHub PR · (커스텀)
    │ sync (커넥터가 SourceRow 방출)          ┌ 에이전트/사람이 MCP로 직접 기록
 PIPELINE       해시 dedup → [대화형: LLM 증류] → 청킹(헤딩 인지) → [문맥 생성] → 임베딩
    │ upsert                                  └ record_decision / learning / note
 POSTGRES       documents(원문+FTS) + chunks(임베딩+문맥) — 단일 임베딩 테이블
    │ query
 SEARCH         FTS(희귀토큰 OR/접두) + 벡터 + IDF + trigram + 문맥FTS → 가중 RRF(k=60)
    │           → 나이 감쇠 · boost/숨김 · supersede 감점 · 소스별 중복 상한
 INTERFACES     kb CLI · MCP 서버(stdio 로컬 / Streamable HTTP 원격 — 토큰 또는 OAuth 인증)
                읽기: search·get_document·list_sources·who_knows·recent_changes
                      ·search_code·subsystem_index·recent_prs
                쓰기: record_decision·learning·note·verify_note·search_feedback / 예방: pitfalls
                웹 대시보드(:8080) — 운영 헬스 · 모델/API 비용 · 쿼리 분석 · 질문(/ask)
                      · 노트 재검증/중복 큐 · 토큰/프로젝트 관리
```

---

## 1. 요구사항

| 항목 | 버전 | 비고 |
|---|---|---|
| Python | 3.11+ | tomllib 사용 |
| PostgreSQL | 14+ (16에서 테스트) | |
| pgvector | 0.5+ (0.6에서 테스트) | HNSW 인덱스 사용. **halfvec(2000차원 초과·메모리 절감)은 0.7+, 필터 검색 리콜 보정(iterative_scan)은 0.8+에서 자동 활성** |
| pg_trgm | 선택 권장 | 한국어 복합어 내부 매칭(trigram 신호). Postgres 기본 동봉 확장 |
| ripgrep (`rg`) | 선택 | `search_code` 도구용. 없으면 grep 폴백 |
| claude CLI **또는** `ANTHROPIC_API_KEY` **또는** AWS 자격증명 | 선택 | LLM 기능(증류/요약/재순위/문맥/질문)용. 컨테이너 환경은 `backend="anthropic"`(공식 SDK) 또는 `backend="bedrock"`(Bedrock의 Claude, API 키 불필요) — §7.3 |

## 2. 설치

```bash
git clone https://github.com/riemannulus/knowledge-base && cd knowledge-base
python3 -m venv .venv && source .venv/bin/activate
pip install -e .            # 개발용은 pip install -e ".[dev]"
```

선택 기능은 extras로: `[aws]`(Bedrock 임베딩) · `[slack]`(실시간 수집) ·
`[dashboard]`(웹 대시보드, §11) · `[anthropic]`(LLM 기능 API 백엔드, §7.3).
Docker 이미지는 네 개를 모두 포함한다.

Postgres에 pgvector가 없다면 (Debian/Ubuntu 예시):

```bash
sudo apt-get install postgresql-16-pgvector
createdb kb                 # 원하는 이름의 DB 생성
```

## 3. 빠른 시작 (5분)

> Postgres 설치 없이 바로 띄우려면 §4.1의 Docker Compose 경로를 쓰면 된다 —
> `cp .env.example .env && docker compose up -d --build` 한 번으로 DB·MCP 서버·sync가 다 뜬다.

```bash
# 1) 설정 파일 작성
cp kb.toml.example kb.toml
$EDITOR kb.toml             # dsn, 커넥터 경로 수정

# 2) 스키마 마이그레이션 (Alembic — 멱등, 여러 번 실행해도 안전)
kb migrate

# 3) 동기화 (커넥터 전체 실행, 증분)
kb sync
# {"connector": "markdown:kb-docs", "emitted": 4, "upserted": 4, ...}
# {"connector": "gitlog:kb-repo", "emitted": 12, "upserted": 12, ...}

# 4) 검색해 보기
kb search "배포 락 타임아웃"
kb search "ERR_MANIFEST_TIMEOUT" --source slack --limit 5
kb search "재색인 주기" --json
```

`kb sync`는 커서 기반 증분이다: 다시 실행하면 변경된 것만 처리하고,
내용이 같으면(`content_hash`) 재임베딩도 건너뛴다. 주기 실행은 cron에 걸면 된다:

```cron
*/10 * * * *  cd /path/to/kb && .venv/bin/kb sync >> /var/log/kb-sync.log 2>&1
```

## 4. Claude Code / Claude Desktop에 MCP로 연결

두 가지 모드가 있다:

- **로컬(stdio)** — 혼자 쓸 때. 아래처럼 명령으로 등록.
- **원격(Streamable HTTP)** — 팀 공유. §4.1의 Docker 배포 후 URL로 등록.

### Claude Code (로컬 stdio)

```bash
claude mcp add kb --env KB_CONFIG=/absolute/path/kb.toml -- /absolute/path/.venv/bin/kb mcp
```

또는 프로젝트의 `.mcp.json`:

```json
{
  "mcpServers": {
    "kb": {
      "command": "/absolute/path/.venv/bin/kb",
      "args": ["mcp"],
      "env": { "KB_CONFIG": "/absolute/path/kb.toml" }
    }
  }
}
```

### Claude Desktop (로컬 stdio)

`claude_desktop_config.json`의 `mcpServers`에 위와 동일한 블록을 추가한다.

### 4.1 팀 공유 원격 서버 (Docker Compose로 한 번에)

```bash
cp .env.example .env
$EDITOR .env                      # KB_AUTH_TOKEN만 채우면 됨 (openssl rand -hex 24)
docker compose up -d --build

# 확인: 401이 나오면 정상 (인증이 걸린 상태)
curl -s -o /dev/null -w "%{http_code}\n" -X POST http://localhost:8000/mcp -d '{}'
```

`db`(pgvector) + `migrate`(**Alembic 스키마 마이그레이션** — 1회 실행 후 종료) +
`mcp`(HTTP `:8000/mcp`, 헬스체크 포함) + `sync`(주기 동기화, `KB_SYNC_INTERVAL`
기본 300초) + `dashboard`(웹 UI `:8080`, §11) 서비스가 뜨고 재시작 정책이 걸려 있다.
앱 서비스들은 `migrate`가 성공해야 시작되므로 **스키마 업그레이드가 배포에 자동
포함**된다 (k8s도 동일 — mcp/dashboard의 initContainer, sync CronJob의 선행 단계).
**기본값 그대로면 이 저장소 자신(docs/ + git log)을 인덱싱하는 데모로 즉시 동작**하고,
실데이터는 `.env`의 `KB_DOCS_DIR`/`KB_REPO_DIR`와 `deploy/kb.docker.toml`을 수정한다.
커넥터 하나가 실패해도 나머지 sync는 계속된다(실패 격리). DB 데이터는
`kb-pgdata` 볼륨에 보존되므로 `docker compose down`(­`-v` 없이)으로는 유실되지 않는다.

수동 실행도 가능: `kb mcp --transport http --host 0.0.0.0 --port 8000`
(`KB_AUTH_TOKEN` 환경변수가 있으면 `Authorization: Bearer` 검사).

**팀원 등록 (Claude Code):**

```bash
claude mcp add --transport http kb https://kb.example.com/mcp \
  --header "Authorization: Bearer "
```

프로젝트 공유는 `.mcp.json`으로 (토큰은 각자 환경변수로 — 커밋 금지):

```json
{
  "mcpServers": {
    "kb": {
      "type": "http",
      "url": "https://kb.example.com/mcp",
      "headers": { "Authorization": "Bearer ${KB_AUTH_TOKEN}" }
    }
  }
}
```

**플러그인으로 한 번에 (권장)**: 수동 `mcp add` 대신 `kb-workflow` 플러그인을 설치하면
KB 연결(+워크플로 스킬 kb-brief/kb-log/kb-wrap + 기록 유실 방지 훅)이 함께 배선된다.
**설치 시 서버 URL/토큰을 물어본다** — 로컬(compose)은 기본값 엔터, 원격은 팀 서버
URL + `kbt_` 토큰 입력(마스킹·보안 저장소 저장). 이후 전환·재설정은 `/plugin` 메뉴의
플러그인 설정 또는 `/kb-workflow:setup` 참고. 프로젝트 `.mcp.json`에 동명 `kb` 서버를
정의하면 플러그인 정의를 덮는다(완전 오버라이드).
상세: [plugins/kb-workflow/README.md](plugins/kb-workflow/README.md).

```
/plugin marketplace add riemannulus/knowledge-base
/plugin install kb-workflow@knowledge-base
```

**claude.ai / Claude Desktop 커스텀 커넥터**: 설정 → 커넥터 → 커스텀 커넥터에
`https://kb.example.com/mcp` 등록. 웹 커넥터 UI는 커스텀 헤더를 붙일 수 없으므로
**OAuth로 붙인다 — §4.2**. 자동화/봇은 Anthropic API MCP connector의
`authorization_token`에 `kbt_` 토큰을 쓰면 된다.
상세 절차와 운영 팁: [docs/05-team-workflow.md](docs/05-team-workflow.md).

### 4.2 claude.ai 웹 커넥터 연결 (Google OAuth)

kb가 **스스로 OAuth 2.1 인가 서버(AS)**가 되고 "누구인가"만 Google에 위임한다.
claude.ai가 커넥터를 연결할 때 브라우저로 Google 로그인을 띄우고, 허용 도메인
계정이면 kb가 자기 액세스 토큰을 발급한다. 팀원은 토큰을 복사·붙여넣을 일이 없다.

```
claude.ai ──OAuth 2.1(PKCE + 동적 등록)──▶ kb(/mcp)
                                            └─OIDC─▶ Google (허용 도메인만 통과)
```

Google이 아니라 kb가 AS인 이유: Google은 임의 리소스 서버를 위한 RFC 9728 리소스
메타데이터도, MCP 클라이언트의 동적 등록(RFC 7591)도 제공하지 않는다. MCP 스펙이
명시한 3rd-party IdP 위임 패턴이 이 구조다.

**1) Google OAuth 클라이언트 만들기** (하나로 커넥터·대시보드 모두 커버)

Google Cloud Console → API 및 서비스 → 사용자 인증 정보 → OAuth 클라이언트 ID →
애플리케이션 유형 **웹 애플리케이션**. 승인된 리디렉션 URI에 둘을 등록한다
(외부에서 실제로 접속하는 주소여야 하고, 문자 하나까지 일치해야 한다):

```
https://kb.example.com/oauth/google/callback     # MCP 서버 (= KB_PUBLIC_URL + 고정 경로)
https://kb-dash.example.com/auth/callback        # 대시보드 (= KB_DASHBOARD_URL + 고정 경로)
```

**2) 서버 환경변수** (5개가 모두 있어야 켜진다 — 일부만 채우면 기동 시 예외로 알려준다)

| 환경변수 | 값 |
|---|---|
| `KB_GOOGLE_CLIENT_ID` / `KB_GOOGLE_CLIENT_SECRET` | 위에서 만든 클라이언트 |
| `KB_OAUTH_ALLOWED_DOMAINS` | 허용 Google Workspace 도메인 (예: `example.com`) |
| `KB_OAUTH_SECRET` | state·세션 쿠키 서명 키. `openssl rand -hex 32` (레플리카 전체 동일) |
| `KB_PUBLIC_URL` | MCP 서버 공개 주소 (예: `https://kb.example.com`) |

선택: `KB_OAUTH_ALLOWED_EMAILS`(도메인 밖 개별 허용), `KB_OAUTH_TOKEN_TTL`(기본 3600),
`KB_OAUTH_REFRESH_TTL`(기본 30일). 설치는 `pip install -e ".[oauth]"`
(Docker 이미지에는 포함, compose는 `.env`만 채우면 된다).

**3) 팀원 연결**: claude.ai 설정 → 커넥터 → 커스텀 커넥터에 `https://kb.example.com/mcp`
입력 → 연결 → Google 계정 선택. 끝. Claude Desktop·MCP Inspector·Claude Code
(`claude mcp add --transport http kb https://kb.example.com/mcp`)도 같은 흐름을 탄다.

동작 확인:

```bash
# 무인증 요청은 401 + AS 위치를 알려주는 헤더를 돌려준다 (클라이언트가 이걸로 발견)
curl -si -X POST https://kb.example.com/mcp -d '{}' | grep -i www-authenticate
# WWW-Authenticate: Bearer error="invalid_token",
#   resource_metadata="https://kb.example.com/.well-known/oauth-protected-resource/mcp"

curl -s https://kb.example.com/.well-known/oauth-authorization-server | jq .issuer
```

노출되는 엔드포인트: `/.well-known/oauth-authorization-server`(RFC 8414),
`/.well-known/oauth-protected-resource/mcp`(RFC 9728), `/register`(RFC 7591 동적 등록),
`/authorize`, `/token`, `/revoke`(RFC 7009), `/oauth/google/callback`.

**권한 모델**: 허용 도메인 계정 = 팀 전체 접근(프로젝트 스코프 없음), 쓰기는
`kb.write` 스코프에 달려 있다(기본 발급에 포함 — 읽기 전용 클라이언트는 `kb.read`만
요청하면 된다). 신원 이름은 이메일이라 `record_*`의 author와 query_log에 그대로 남는다.
세부 스코프가 필요하면 `kbt_` 토큰(§8.1)을 계속 쓰면 된다 — 두 경로는 공존한다.

**운영**: 등록된 커넥터와 활성 세션은 대시보드 토큰 페이지에서 보고 폐기한다
(`kb oauth clients|sessions|revoke-client|revoke-user`도 같은 일을 한다).
퇴사자 처리는 Google 계정 정지 + `kb oauth revoke-user `.
액세스 토큰은 만료가 짧고(기본 1시간), 리프레시는 회전할 때 옛 쌍이 함께 폐기된다.

⚠ **OAuth를 켜면 "등록 토큰 0개 = 무인증 admin" 완화가 꺼진다** (§8.1) — 토큰 없는
요청은 항상 401이다. HTTPS는 여전히 reverse proxy/터널 몫이다: OAuth 토큰은 베어러라
평문 HTTP로 노출하면 그대로 유출된다.

연결 후 이렇게 물어보면 된다:

> "kb에서 검색해줘: staging 배포가 락 때문에 멈추는 문제 예전에 어떻게 해결했지?"

에이전트가 `search` → `get_document`를 호출해 근거 문서(document_id, URL)를 인용하며 답한다.

### MCP 도구 레퍼런스

| 도구 | 파라미터 | 설명 |
|---|---|---|
| `search` | `query, source?, project?, limit=10, rerank=false, expand=0` | 하이브리드 검색. `expand=1~2`면 매치 청크의 이웃을 context로 복원. 노트 결과의 `project`는 기록 시 명시한 소속 프로젝트(null=팀 공용) — 스코프 검색에서 타 프로젝트 노트는 하향 + `other-project` 표시. 반환: document_id/score/title/url/snippet/matched/context/project |
| `get_document` | `document_id, context=0` | 원문 전체 + (Slack이면) 증류 결과. `context=1`이면 헤딩 청크 목록 포함. 열람은 감사 로그에 남는다 |
| `list_sources` | — | 소스/구획별 문서 수·최근 갱신·**설명("무엇을 잘 답하나")**, 프로젝트 목록. 도구 선택 전 상황 파악용 |
| `subsystem_index` | `query, limit=10` | 파일별 요약 인덱스 — "어느 파일에 구현돼 있나" 류 질문 (file_summary/file_head 대상) |
| `recent_prs` | `query?, days=14, limit=10` | 최근 PR 목록/검색 (`github_prs` 커넥터 필요) |
| `who_knows` | `topic, limit=5` | 주제 관련 스레드 참여자·커밋 작성자 집계 → 실증 전문가 |
| `recent_changes` | `source?, days=7, limit=20` | 최근 갱신 문서 (커밋/스레드/문서) |
| `search_code` | `pattern, repo?, regex=false, limit=30` | `[code_repos]` 위 ripgrep 정확 매칭 |
| `search_feedback` | `document_id, useful, query?` | 검색 결과 품질 피드백 — 골든셋/큐레이션 재료 |
| `record_decision` | `title, decision, context?, alternatives?, tags?, author?, project?, code_refs?, supersedes?` | **쓰기**: 의사결정 기록. `supersedes`로 옛 결정 대체(번복 추적), `code_refs`의 파일이 바뀌면 재검증 대상 표시. 프로젝트 한정 결정이면 `project` 명시(미지정 = 팀 공용) |
| `record_learning` | `title, problem, root_cause?, solution?, prevention?, tags?, author?, project?, code_refs?, supersedes?` | **쓰기**: 삽질/버그 교훈 기록. prevention이 핵심. 특정 프로젝트에서만 성립하는 교훈이면 `project` 명시 |
| `record_note` | `title, content, tags?, author?, project?` | **쓰기**: 일반 지식 메모 |
| `stale_notes` | `days=90, limit=20, reason?` | **재검증 큐** (대시보드와 동일): 참조 코드 변경(`code`) 우선, 90일+ 미검증(`age`) 다음. `counts`로 전체 규모 동봉 — 일일 재검증 루틴의 입력 |
| `verify_note` | `document_id` | **쓰기**: 노트 재검증 표시 (stale 플래그 해제) |
| `pitfalls` | `topic, limit=5, project?` | **작업 전 사전 점검**: 주제 관련 과거 교훈·결정 조회. 대체된 노트 제외, `stale=true`는 참조 코드가 변경됨 표시. 결과의 `project`는 소속 프로젝트(null=팀 공용), 스코프와 다른 프로젝트의 노트는 하향 + `other_project=true` |

모든 읽기 도구는 LLM을 호출하지 않아 빠르고 싸다. 쓰기 도구의 기록은 즉시
청킹·임베딩되어 바로 검색된다.
record_* 응답의 `similar_existing`은 비슷한 기존 기록이 이미 있다는 신호다 — 같은
문제라면 새 제목 대신 기존 제목으로 갱신하거나 `supersedes`를 쓰라. 단 후보의
`project`가 다르면 같은 증상이라도 원인이 다를 수 있다 — 힌트에 경고가 붙으니
같은 근본 원인임을 확인한 경우에만 갱신하고, 아니면 별도 기록을 유지하라.

record_*의 `project`는 **등록된 프로젝트 이름 기준으로 해석**된다: 등록명은 그대로,
저장소 이름(모노레포 하위 저장소 등 `project_sources`의 source_key)은 소유
프로젝트로 자동 교정, 등록되지 않았거나 여러 프로젝트에 걸려 모호한 이름은
라벨을 버리고 팀 공용으로 기록한다 — 잘못된 라벨은 자기 프로젝트 스코프 검색에서
억울한 감점을 만들기 때문. 결과는 응답의 `project`(최종 저장값)와
`project_hint`(교정/폐기 사유)로 알 수 있고, 같은 제목으로 다시 기록하면
갱신되므로 즉시 교정 가능하다.
에이전트가 이 루프(작업 전 pitfalls → 작업 후 record)를 스스로 돌게 만드는
CLAUDE.md 스니펫은 [docs/05-team-workflow.md](docs/05-team-workflow.md) §3에 있다.

## 5. kb.toml 레퍼런스

```toml
[database]
dsn = "host=127.0.0.1 port=5432 user=kb dbname=kb"  # $KB_DSN이 있으면 그것이 우선

[embedding]
backend = "hashing"   # 'hashing' | 'openai' | 'bedrock'
dim = 1024
model = ""            # openai: 기본 text-embedding-3-small / bedrock: 기본 amazon.titan-embed-text-v2:0
region = ""           # bedrock 전용 AWS 리전 (비우면 $AWS_REGION)

[distill]
backend = "none"      # 'none' | 'claude-cli'
model = "claude-haiku-4-5-20251001"

[[connector]]         # 소스 하나당 하나. type: markdown | gitlog | slack_export
type = "markdown"
root = "docs"         # 상대 경로는 kb.toml 위치 기준
source_key = "kb-docs"
url_prefix = "https://github.com/org/repo/blob/main/docs"   # 선택: 결과 URL 생성

[[connector]]
type = "gitlog"
repo = "."
source_key = "kb-repo"
url_prefix = "https://github.com/org/repo/commit"

[[connector]]
type = "slack_export"
root = "/data/slack-export"      # 워크스페이스 export(zip 해제) 디렉터리
channels = ["deploy", "infra"]   # 생략 시 전체 채널
workspace_url = "https://your.slack.com"   # 선택: 스레드 딥링크 생성

[[connector]]
type = "github_prs"   # PR 본문+코멘트를 대화형 문서로 수집 (증류 경로 적용)
repo = "org/repo"     # $GITHUB_TOKEN 권장
source_key = "prs"

[code_repos]          # search_code(ripgrep) 대상
platform = "/srv/repos/platform"
```

이 밖에 `[context]`(청크 문맥 생성 — Contextual Retrieval), `[ask]`(대시보드 질문
페이지), `[rerank] pool`, `[chunking] max_chars`, `[search]`(RRF 가중치·다양성 캡),
`[pricing]`(단가 오버라이드), 커넥터 `description`(소스 카탈로그) 옵션이 있다 —
전체 주석은 [kb.toml.example](kb.toml.example) 참고. LLM 백엔드는 공통으로
`'none' | 'claude-cli' | 'anthropic' | 'bedrock'`이며, API 백엔드는 컨테이너/k8s에서도
동작한다 (`pip install '.[anthropic]'`, bedrock은 `[anthropic,aws]`).

`[context]`는 프롬프트 캐싱으로 동작한다: 문서 본문을 캐시 프리픽스로 한 번
기록(1.25×)한 뒤 나머지 청크가 캐시 적중(0.1×)으로 돌아, 청크마다 문서를
풀프라이스로 재전송하는 것 대비 첫 백필 비용이 **~85% 절감**된다. 캐시 프라이밍
후 청크 호출은 4-way 병렬이라 백필 속도도 그만큼 빨라진다 (API 백엔드 한정 —
claude-cli는 캐싱 제어가 없어 프리픽스를 이어붙여 실행).

환경변수: `KB_CONFIG`(설정 파일 경로), `KB_DSN`(DSN 오버라이드),
`OPENAI_API_KEY`/`OPENAI_BASE_URL`(openai 임베딩), `ANTHROPIC_API_KEY`(anthropic LLM
백엔드), `GITHUB_TOKEN`(github_prs 커넥터).

## 6. CLI 레퍼런스

| 명령 | 설명 |
|---|---|
| `kb migrate` (별칭 `init-db`) | 스키마를 최신 Alembic 리비전으로 (멱등). 구 init-db 스키마는 자동으로 baseline stamp 후 편입. compose/k8s 배포는 자동 실행 |
| `kb sync [--connector 이름]` | 전체(또는 특정) 커넥터 증분 동기화. 이름은 `markdown:kb-docs` 형식 |
| `kb search "질의" [--source S] [--project P] [--limit N] [--rerank] [--expand N] [--json]` | 하이브리드 검색. `--expand`는 매치 청크 이웃 복원, `--rerank`는 LLM 재채점 |
| `kb eval golden.jsonl [--k 10]` | **골든셋 검색 품질 평가** (Recall@k/MRR/nDCG). 모든 검색 튜닝의 판정 기준 |
| `kb eval --bootstrap out.jsonl [--days 30]` | query_log에서 골든셋 스켈레톤 생성 (expect는 사람이 라벨링) |
| `kb notes stale [--days 90]` | 재검증 필요 노트 (참조 코드 변경 또는 장기 미검증) |
| `kb notes dedup [--threshold 0.85]` | 유사 노트 쌍(병합 후보) — 자동 병합 안 함 |
| `kb notes verify ` / `kb notes supersede  ` | 노트 재검증 / 대체 표시 |
| `kb token create/list/revoke [--default-project P]` | 사용자별 접근 토큰 관리 (§8.1). default-project는 soft 기본 스코프 |
| `kb oauth clients\|sessions\|revoke-client\|revoke-user\|prune` | OAuth 커넥터 등록·사용자 세션 조회/폐기 (§4.2). 대시보드 토큰 페이지와 같은 조작의 헤드리스 경로 |
| `kb stats [--days N]` | 쿼리 로그 분석 — 무응답 질의(커넥터/골든세트 백로그 후보), 상위 질의, 클라이언트별 사용량 |
| `kb reindex` | 전 문서 재청킹·재임베딩 — **임베딩 백엔드/차원 변경 후 필수** |
| `kb gc [--connector 이름] [--dry-run]` | 소스에서 사라진 문서(유령) 수거. sync에도 포함되므로 평소엔 불필요 — 미리보기/수동용 |
| `kb slack-listen` | Slack Socket Mode 실시간 수집 (`SLACK_BOT_TOKEN`, `SLACK_APP_TOKEN` 필요, §7.2) |
| `kb mcp [--transport stdio\|http] [--host H] [--port P]` | MCP 서버 실행. http면 `/mcp` 경로, `KB_AUTH_TOKEN` 설정 시 베어러 인증 |
| `kb dashboard [--host H] [--port P]` | 웹 대시보드 (기본 :8080) — 운영 헬스/모델·비용/검색/관리 (§11) |

공통 옵션: `--config /path/kb.toml`.

### 6.1 원본이 바뀌거나 사라지면 (드리프트 처리)

| 원본 변화 | 동작 |
|---|---|
| 내용 수정 | 커서에 걸려 재방출 → `content_hash` 비교 후 변경분만 재청킹·재임베딩 (같으면 스킵) |
| 파일 삭제 | sync 말미의 **reconcile**이 소스의 현재 목록(`current_ids`)과 대조해 유령 행 삭제 |
| 파일 이름변경/이동 | 새 경로로 재인덱싱 + 옛 경로 유령 삭제 (파일별 mtime 커서라 rename도 감지) |
| Slack 메시지 수정 (답글 없이) | `edited.ts`가 커서에 반영되어 스레드 전체 재수집 |
| git 히스토리 리라이트 (force

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [riemannulus](https://github.com/riemannulus)
- **Source:** [riemannulus/knowledge-base](https://github.com/riemannulus/knowledge-base)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-riemannulus-knowledge-base
- Seller: https://agentstack.voostack.com/s/riemannulus
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
