Spellbook
MCP for memorize document & cast document
Ask AI about Spellbook
Powered by Claude ยท Grounded in docs
I know everything about Spellbook. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
Spellbook v1.0 ๐ฎ
VectorDB ๊ธฐ๋ฐ AI Agent ๋ฉ๋ชจ๋ฆฌ MCP ์๋ฒ
๊ฐ์
AI ์์ด์ ํธ ๊ฐ์ธํ ๊ณผ์ ์์ ์ถ์ ๋๋ ์ ๋ณด๋ค์ VectorDB์ ์ ์ฅํ๊ณ ์๋ฏธ ๊ธฐ๋ฐ์ผ๋ก ๊ฒ์ํฉ๋๋ค.
Canon (๋ฉ์ธ ์ ์ฅ์):
- Scribe: Canon์ ์ ๋ณด ์ ์ฅ (REST ๋ชจ๋์์๋ง)
- Memorize: Canon ์๋ฏธ ๊ธฐ๋ฐ ๊ฒ์
- Find: Canon ํค์๋ ๊ธฐ๋ฐ ๊ฒ์
Lore (์๋ธ ์ ์ฅ์):
- Chronicle: Lore์ ์ ๋ณด ์ ์ฅ (REST ๋ชจ๋์์๋ง, Lore ์ด๋ฆ ์ง์ )
- Recall: Lore ์๋ฏธ ๊ธฐ๋ฐ ๊ฒ์
- Recall Find: Lore ํค์๋ ๊ธฐ๋ฐ ๊ฒ์
Canon๊ณผ Lore์ API๋ ์์ ํ ๋ถ๋ฆฌ๋์ด ์์ต๋๋ค. Canon API๋ก Lore ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์๊ณ , ๊ทธ ๋ฐ๋๋ ๋ง์ฐฌ๊ฐ์ง์ ๋๋ค.
Spellbook์ ๋จ์ํ ์ ์ฅ์์ ๋๋ค. ๋ฌด์์ ์ ์ฅํ๊ณ ์ธ์ ๊ฒ์ํ ์ง๋ ์ฌ์ฉ์๊ฐ ๊ฒฐ์ ํฉ๋๋ค.
ํต์ฌ ํน์ง
- โ Canon + Lore: ๋ฉ์ธ ์ ์ฅ์์ ์ฉ๋๋ณ ์๋ธ ์ ์ฅ์ ๋ถ๋ฆฌ
- โ REST ์ํ ๊ด๋ฆฌ: ์ฒญํน ์ผ๊ด์ฑ ๋ณด์ฅ (scribe/chronicle ๊ณต์ฉ)
- โ ์ด์ค ๊ฒ์: ์๋ฏธ ๊ธฐ๋ฐ + ํค์๋ ๊ธฐ๋ฐ (Canon/Lore ๊ฐ๊ฐ)
- โ nomic-embed-text: 768์ฐจ์, ํ๊ธ/์์ด ์ฐ์
- โ HTTP/SSE MCP: Docker๋ก ๊ฐํธ ๋ฐฐํฌ
- โ Bun ๋ฐํ์: ๋น ๋ฅธ ์์, TypeScript ๋ค์ดํฐ๋ธ ์คํ
๋น ๋ฅธ ์์
๐ ์์ธ ์ค์น ๊ฐ์ด๋:
- ๐ค ์ฌ๋: INSTALL.md - ๋ํํ ์ค์น ์คํฌ๋ฆฝํธ ์ฌ์ฉ
- ๐ค AI Agent: INSTALL_AI.md - ํ๊ฒฝ ๋ณ์ ์ค์ ๊ฐ์ด๋
๋ฐฉ๋ฒ 1: Docker Compose (๊ถ์ฅ) โญ
์ฌ์ ์๊ตฌ์ฌํญ: Docker, Ollama
git clone https://github.com/zilhak/spellbook.git
cd spellbook
./scripts/setup.sh # ํ๊ฒฝ ํ์ธ + ๋ชจ๋ธ ๋ค์ด๋ก๋ + ์ด๋ฏธ์ง ๋น๋
docker compose up -d
setup.sh๊ฐ Docker, Ollama ํ์ธ ๋ฐ ์๋ฒ ๋ฉ ๋ชจ๋ธ ๋ค์ด๋ก๋, ์ด๋ฏธ์ง ๋น๋๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์ฒซ ์คํ ์ ์์คํ ๊ฐ์ด๋ seed๊ฐ ์๋์ผ๋ก ์ํ๋ฉ๋๋ค.
์ค์ ์ปค์คํฐ๋ง์ด์ง (์ ํ):
cp .env.example .env
nano .env
| ํ๊ฒฝ ๋ณ์ | ๊ธฐ๋ณธ๊ฐ | ์ค๋ช |
|---|---|---|
PORT | 17950 | Spellbook ์๋ฒ ํฌํธ |
QDRANT_PORT | 17951 | Qdrant ์ธ๋ถ ํฌํธ |
QDRANT_DATA_PATH | ./data/qdrant | ๋ฐ์ดํฐ ์ ์ฅ ๊ฒฝ๋ก |
OLLAMA_HOST | http://host.docker.internal:11434 | Ollama ์ฃผ์ |
๋ฐฉ๋ฒ 2: Bun ์ง์ ์คํ (๊ฐ๋ฐ์ฉ)
git clone https://github.com/zilhak/spellbook.git
cd spellbook
bun install
# Qdrant + Ollama ์ค๋น
docker run -d -p 17951:6333 qdrant/qdrant
ollama pull nomic-embed-text
# ๊ฐ๋ฐ ๋ชจ๋ (hot reload)
bun run dev
ํ์ ์กฐ๊ฑด: Bun (curl -fsSL https://bun.sh/install | bash)
Claude Code ์ค์
๋ฐฉ๋ฒ 1: CLI ๋ช ๋ น์ด (๊ถ์ฅ)
claude mcp add --transport http spellbook http://localhost:17950/mcp
๋ฐฉ๋ฒ 2: ์๋ ์ค์
~/.claude/mcp.json:
{
"mcpServers": {
"spellbook": {
"url": "http://localhost:17950/mcp"
}
}
}
AI Agent ์์คํ ํ๋กฌํํธ ์ค์ (๊ถ์ฅ)
Spellbook์ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํ๋ ค๋ฉด, AI Agent์ ์์คํ ํ๋กฌํํธ(CLAUDE.md ๋ฑ)์ ๋ค์๊ณผ ๊ฐ์ ์ง์นจ์ ์ถ๊ฐํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค:
## Spellbook ํ์ฉ ๊ท์น
- ๋ชจ๋ฅด๋ ๊ฐ๋
, ํ๋ก์ ํธ ์ปจ๋ฒค์
, ๊ณผ๊ฑฐ ๊ฒฐ์ ์ฌํญ์ด ๋์ค๋ฉด ๋จผ์ Spellbook์์ ๊ฒ์ํ๋ผ
- ์ธ์
์์ ์ get_index()๋ก ์ด๋ค ์ ๋ณด๊ฐ ์ ์ฅ๋์ด ์๋์ง ํ์ธํ๋ผ
- Canon ๊ฒ์ (๋ฒ์ฉ ์ง์):
- ๋งฅ๋ฝ/๊ฐ๋
์ด ๊ถ๊ธํ ๋: memorize(query)
- ์ ํํ ์ฉ์ด๋ฅผ ์ ๋: find(keywords)
- Lore ๊ฒ์ (ํ๋ก์ ํธ๋ณ ์ ๋ณด):
- ๋งฅ๋ฝ/๊ฐ๋
์ด ๊ถ๊ธํ ๋: recall(lore, query)
- ์ ํํ ์ฉ์ด๋ฅผ ์ ๋: recall_find(lore, keywords)
- ์ค์ํ ๊ฒฐ์ , ์๋ก์ด ํจํด, ์ฌ์ฉ์ ์ ํธ๋๊ฐ ํ์ธ๋๋ฉด REST ๋ชจ๋๋ก ์ ์ฅํ๋ผ
- ๋ฒ์ฉ ์ง์ โ scribe (Canon)
- ํ๋ก์ ํธ ํ์ ์ ๋ณด โ chronicle (Lore)
์ด๋ฅผ ํตํด Agent๊ฐ ์ด์ ์ธ์ ์์ ์ถ์ ํ ์ง์์ ์์ฐ์ค๋ฝ๊ฒ ํ์ฉํ๊ฒ ๋ฉ๋๋ค.
์ฌ์ฉ๋ฒ
Canon ์ํฌํ๋ก์ฐ (๋ฉ์ธ ์ ์ฅ์)
// 1. REST ๋ชจ๋ ์ง์
const session = await rest();
// 2. Canon์ ์ฒญํฌ ์ ์ฅ
await scribe({
chunk: {
text: "Docker Compose๋...",
metadata: {
topic_id: "์ธํ๋ผ",
category: "technology",
keywords: ["Docker", "Compose"],
questions: ["Docker Compose ์ค์ ๋ฐฉ๋ฒ์?"],
entities: [{name: "Docker", type: "technology"}],
importance: "high"
}
},
session_id: session.session_id
});
// 3. REST ์ข
๋ฃ
await rest_end(session.session_id);
// Canon ๊ฒ์
await memorize({query: "Docker ์ปจํ
์ด๋ ์ค์ "});
await find({keywords: ["Docker", "Qdrant"]});
Lore ์ํฌํ๋ก์ฐ (์๋ธ ์ ์ฅ์)
// 1. REST ๋ชจ๋ ์ง์
const session = await rest();
// 2. Lore์ ์ฒญํฌ ์ ์ฅ (Lore๊ฐ ์์ผ๋ฉด ์๋ ์์ฑ)
await chronicle({
lore: "my-project",
lore_description: "My Project ๊ธฐ์ ๊ฒฐ์ ์ฌํญ",
chunk: {
text: "์ธ์ฆ์ JWT ๊ธฐ๋ฐ์ผ๋ก...",
metadata: {
topic_id: "auth",
category: "architecture",
keywords: ["JWT", "์ธ์ฆ"],
questions: ["ํ๋ก์ ํธ ์ธ์ฆ ๋ฐฉ์์?"],
entities: [{name: "JWT", type: "technology"}],
importance: "high"
}
},
session_id: session.session_id
});
// 3. REST ์ข
๋ฃ
await rest_end(session.session_id);
// Lore ๊ฒ์
await recall({lore: "my-project", query: "์ธ์ฆ ๋ฐฉ์"});
await recall_find({lore: "my-project", keywords: ["JWT"]});
// Lore ๊ด๋ฆฌ
await list_lores(); // ๋ชจ๋ Lore ๋ชฉ๋ก + ์ค๋ช
await lore_stats("my-project"); // ํน์ Lore ํต๊ณ
๋ฐ์ดํฐ ๊ด๋ฆฌ
์์์ฑ (Persistence)
Docker Compose ์ฌ์ฉ ์:
- ํธ์คํธ ๊ฒฝ๋ก ์ง์ ์ฌ์ฉ (
.env์QDRANT_DATA_PATH) - ์ปจํ ์ด๋ ์ฌ์์/์ฌ์์ฑ ์์๋ ๋ฐ์ดํฐ ์๋ ์ ์ง
# .env ํ์ผ์์ ์ค์
QDRANT_DATA_PATH=/your/data/path
# ๋ฐ์ดํฐ ํ์ธ
ls -la /your/data/path
โ ์์ ํ ์ข ๋ฃ (๋ฐ์ดํฐ ์ ์ง):
docker-compose down # ์ปจํ
์ด๋๋ง ์ญ์ , ๋ฐ์ดํฐ ์ ์ง
docker-compose restart # ๋ฐ์ดํฐ ๊ทธ๋๋ก ๋ณต๊ตฌ
๋ฐฑ์ /๋ณต์ (export/import)
export ๋๊ตฌ (๋ฐฑ์ )
# MCP ์ธ์
์ด๊ธฐํ ํ export ํธ์ถ
curl -X POST http://localhost:17950/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"clientInfo":{"name":"test"},"protocolVersion":"2024-11-05"},"id":1}'
# ์ธ์
ID๋ก export
curl -X POST http://localhost:17950/mcp \
-H "Content-Type: application/json" \
-H "mcp-session-id: YOUR_SESSION_ID" \
-d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"export","arguments":{}},"id":2}'
import ๋๊ตฌ (๋ณต์)
curl -X POST http://localhost:17950/mcp \
-H "Content-Type: application/json" \
-H "mcp-session-id: YOUR_SESSION_ID" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "import",
"arguments": {
"data": {
"chunks": [
{"text": "๋ณต์ํ ๋ด์ฉ", "category": "knowledge"}
]
}
}
},
"id": 1
}'
ํน์ง:
- REST ์ธ์ ์์ด ์ง์ ๋ณต์ ๊ฐ๋ฅ
- ๊ฐ ์ฒญํฌ์ ๋ํด ์๋ฒ ๋ฉ ์๋ ์ฌ์์ฑ
- ์ฑ๊ณต/์คํจ ๊ฐ์ ๋ฐํ
๊ฐ๋ฐ
๋ก์ปฌ ์คํ
# ์์กด์ฑ ์ค์น
bun install
# Qdrant๋ง Docker๋ก
docker-compose up -d qdrant
# ๊ฐ๋ฐ ๋ชจ๋ (hot reload)
bun run dev
# ํ์
์ฒดํฌ
bun run typecheck
์์คํ ๊ฐ์ด๋ seed
# ์ต์ด 1ํ
bun run seed
MCP ๋๊ตฌ
๊ณต์ฉ
| ๋๊ตฌ | ์ค๋ช | ์ ์ฝ |
|---|---|---|
rest | REST ๋ชจ๋ ์์ | - |
rest_end | REST ๋ชจ๋ ์ข ๋ฃ | - |
get_index | ๋ฉํ ๋ชฉ์ฐจ | - |
stats | Canon ํต๊ณ | - |
filter_guide | ํํฐ ์ฌ์ฉ๋ฒ ๊ฐ์ด๋ | - |
export | Canon JSON ๋ฐฑ์ | - |
import | Canon JSON ๋ณต์ | - |
Canon (๋ฉ์ธ ์ ์ฅ์)
| ๋๊ตฌ | ์ค๋ช | ์ ์ฝ |
|---|---|---|
scribe | Canon์ ์ฒญํฌ ์ ์ฅ | REST ๋ชจ๋ ํ์ |
memorize | Canon ์๋ฏธ ๊ฒ์ | - |
find | Canon ํค์๋ ๊ฒ์ | - |
get_topic | ํ ํฝ ์กฐํ | - |
erase | Canon ์ฒญํฌ ์ญ์ | - |
revise | Canon ์ฒญํฌ ์์ | - |
Lore (์๋ธ ์ ์ฅ์)
| ๋๊ตฌ | ์ค๋ช | ์ ์ฝ |
|---|---|---|
chronicle | Lore์ ์ฒญํฌ ์ ์ฅ | REST ๋ชจ๋ ํ์ |
recall | Lore ์๋ฏธ ๊ฒ์ | - |
recall_find | Lore ํค์๋ ๊ฒ์ | - |
erase_lore | Lore ์ฒญํฌ ์ญ์ | - |
revise_lore | Lore ์ฒญํฌ ์์ | - |
list_lores | ๋ชจ๋ Lore ๋ชฉ๋ก | - |
delete_lore | Lore ์ญ์ (๋ณต๊ตฌ ๋ถ๊ฐ) | - |
lore_stats | Lore ํต๊ณ | - |
update_lore | Lore ์ค๋ช ์์ | - |
์ํคํ ์ฒ
Claude Code
โ HTTP/SSE (MCP Protocol)
โผ
Spellbook (Bun + MCP SDK)
โ
โโ REST ์ธ์
๊ด๋ฆฌ (scribe/chronicle ๊ณต์ฉ)
โโ Canon ๋๊ตฌ (scribe, memorize, find)
โโ Lore ๋๊ตฌ (chronicle, recall, recall_find)
โโ Lore ๊ด๋ฆฌ (list_lores, delete_lore, lore_stats, update_lore)
โโ ์๋ฒ ๋ฉ (Ollama + nomic-embed-text)
โโ VectorDB (Qdrant)
โโ Canon: chunks + chunks_metadata
โโ Lore: lore_{name} + lore_{name}_metadata (๊ฐ๊ฐ)
๊ธฐ์ ์คํ
| ๊ตฌ์ฑ์์ | ์ ํ |
|---|---|
| ๋ฐํ์ | Bun |
| ์ธ์ด | TypeScript (๋ค์ดํฐ๋ธ ์คํ) |
| MCP | @modelcontextprotocol/sdk |
| VectorDB | Qdrant |
| ์๋ฒ ๋ฉ | Ollama + nomic-embed-text |
| HTTP | Express |
์์ธ ๋ฌธ์
- CLAUDE.md - ํ๋ก์ ํธ ์ ์ฒด ์ค๊ณ ๋ฌธ์
- src/data/system-guides.ts - ์ฒญํน ๊ฐ์ด๋
๋ผ์ด์ ์ค
MIT
