@graphmemory/server 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -579,8 +579,8 @@ Graph Memory maintains six separate but interconnected graphs:
579
579
 
580
580
  | Graph | What it indexes | Created from |
581
581
  |-------|----------------|--------------|
582
- | **DocGraph** | Markdown sections, headings, code blocks | Files matching \`graphs.docs.pattern\` |
583
- | **CodeGraph** | Functions, classes, methods, imports | Files matching \`graphs.code.pattern\` |
582
+ | **DocGraph** | Markdown sections, headings, code blocks | Files matching \`graphs.docs.include\` |
583
+ | **CodeGraph** | Functions, classes, methods, imports | Files matching \`graphs.code.include\` |
584
584
  | **FileIndexGraph** | All files and directories with metadata | Entire project directory |
585
585
  | **KnowledgeGraph** | User-created notes, facts, decisions | Manual creation via tools |
586
586
  | **TaskGraph** | Tasks with status, priority, dependencies | Manual creation via tools |
@@ -600,8 +600,7 @@ This means \`"how to authenticate users"\` will find documentation about auth ev
600
600
 
601
601
  ## Quick start workflow
602
602
 
603
- 1. **Configure** your project in \`graph-memory.yaml\` with \`graphs.docs.pattern\` and \`graphs.code.pattern\`
604
- 2. **Start** the server: \`graphmemory serve --config graph-memory.yaml\`
603
+ 1. **Start** the server: \`graphmemory serve\` (uses current directory as project, or \`--config graph-memory.yaml\` for custom config)
605
604
  3. **Browse** your indexed content in the UI
606
605
  4. **Search** across all graphs using natural language
607
606
  5. **Create notes** to capture knowledge and decisions
@@ -640,19 +639,19 @@ Each graph can use a different embedding model, configured in \`graph-memory.yam
640
639
  \`\`\`yaml
641
640
  projects:
642
641
  my-app:
643
- embedding:
644
- model: Xenova/bge-m3 # default for all graphs
642
+ model:
643
+ name: Xenova/bge-m3 # default for all graphs
645
644
  graphs:
646
645
  docs:
647
- embedding:
648
- model: Xenova/bge-m3 # override for docs (full config, no merge)
646
+ model:
647
+ name: Xenova/bge-m3 # override for docs (whole object, no merge)
649
648
  code:
650
- embedding:
651
- model: Xenova/bge-base-en-v1.5
652
- # knowledge, tasks, files, skills inherit project.embedding
649
+ model:
650
+ name: Xenova/bge-base-en-v1.5
651
+ # knowledge, tasks, files, skills inherit project.model
653
652
  \`\`\`
654
653
 
655
- Resolution: \`graph.embedding → project.embedding → server.embedding → defaults\`. Each level is a complete config block — no field-by-field merge.
654
+ Model resolution: \`graph.model → project.model → server.model → defaults\`. Each level is a complete config block — no field-by-field merge. Embedding config (\`batchSize\`, \`maxChars\`, etc.) is separate and merges field-by-field.
656
655
 
657
656
  ## Cosine similarity
658
657
 
@@ -873,54 +872,11 @@ This lets you create connections like:
873
872
  - Task "Update auth docs" → links to \`guide.md\` in DocGraph
874
873
  - Note "Config format" → links to \`src/config.ts\` in FileIndexGraph
875
874
  - Skill "Add REST endpoint" → links to \`auth.ts::AuthService\` in CodeGraph
876
- `},{id:`cross-graph`,title:`Cross-Graph Links`,summary:`How to link notes and tasks to code, docs, and files via proxy nodes.`,category:`concept`,relatedTools:[`create_relation`,`delete_relation`,`list_relations`,`create_task_link`,`delete_task_link`,`create_skill_link`,`delete_skill_link`,`find_linked_notes`,`find_linked_tasks`,`find_linked_skills`],content:'# Cross-Graph Links\n\nOne of Graph Memory\'s most powerful features is the ability to **link knowledge across different graphs**. A note can reference a code symbol, a task can link to documentation, and everything stays connected.\n\n## How it works\n\nWhen you create a cross-graph link (via `create_relation`, `create_task_link`, or `create_skill_link`), the system creates a **proxy node** — a lightweight placeholder in the source graph that represents a node from another graph.\n\nProxy node IDs follow the format `@{graph}::{nodeId}`:\n- `@docs::guide.md::Setup` — a doc section\n- `@code::auth.ts::AuthService` — a code symbol\n- `@files::src/config.ts` — a file\n- `@tasks::fix-auth-bug` — a task\n- `@knowledge::auth-architecture` — a note\n- `@skills::add-rest-endpoint` — a skill\n\n## Creating cross-graph links\n\n### From Knowledge (notes)\n\nUse `create_relation` with the `targetGraph` parameter:\n\n```\ncreate_relation({\n fromId: "auth-architecture",\n toId: "auth.ts::AuthService",\n kind: "documents",\n targetGraph: "code"\n})\n```\n\nSupported target graphs: `docs`, `code`, `files`, `tasks`, `skills`\n\n### From Tasks\n\nUse `create_task_link` with the `targetGraph` parameter:\n\n```\ncreate_task_link({\n taskId: "update-auth-docs",\n targetId: "guide.md::Authentication",\n kind: "relates_to",\n targetGraph: "docs"\n})\n```\n\nSupported target graphs: `docs`, `code`, `files`, `knowledge`, `skills`\n\n### From Skills\n\nUse `create_skill_link` with the `targetGraph` parameter:\n\n```\ncreate_skill_link({\n skillId: "add-rest-endpoint",\n targetId: "api-guide.md::REST",\n kind: "relates_to",\n targetGraph: "docs"\n})\n```\n\nSupported target graphs: `docs`, `code`, `files`, `knowledge`, `tasks`\n\n## Discovering cross-graph links\n\n- `find_linked_notes` — find all notes linked to a specific external node\n- `find_linked_tasks` — find all tasks linked to a specific external node\n- `find_linked_skills` — find all skills linked to a specific external node\n- `list_relations` — list all relations for a note (including cross-graph)\n- `get_task` — returns enriched task data including all cross-graph links\n- `get_skill` — returns enriched skill data including all cross-graph links\n\n## Proxy cleanup\n\nProxy nodes are automatically cleaned up when:\n- The source note, task, or skill is deleted (orphaned proxies removed)\n- The relation/link is explicitly deleted\n- During indexing, if the target file no longer exists\n\n## Use cases\n\n- **Architecture decisions**: Create notes documenting why code is structured a certain way, link to the actual code symbols\n- **Task context**: Link tasks to the files and docs they affect for quick navigation\n- **Knowledge mapping**: Build a web of connections between concepts, implementations, and documentation\n- **Reusable skills**: Link skills to the code, docs, and tasks they relate to so they can be recalled in context\n'},{id:`mcp-setup`,title:`Connecting MCP Clients`,summary:`How to connect Claude Desktop, Cursor, Windsurf, and other MCP clients via stdio or HTTP.`,category:`guide`,relatedTools:[`get_context`],content:`# Connecting MCP Clients
875
+ `},{id:`cross-graph`,title:`Cross-Graph Links`,summary:`How to link notes and tasks to code, docs, and files via proxy nodes.`,category:`concept`,relatedTools:[`create_relation`,`delete_relation`,`list_relations`,`create_task_link`,`delete_task_link`,`create_skill_link`,`delete_skill_link`,`find_linked_notes`,`find_linked_tasks`,`find_linked_skills`],content:'# Cross-Graph Links\n\nOne of Graph Memory\'s most powerful features is the ability to **link knowledge across different graphs**. A note can reference a code symbol, a task can link to documentation, and everything stays connected.\n\n## How it works\n\nWhen you create a cross-graph link (via `create_relation`, `create_task_link`, or `create_skill_link`), the system creates a **proxy node** — a lightweight placeholder in the source graph that represents a node from another graph.\n\nProxy node IDs follow the format `@{graph}::{nodeId}`:\n- `@docs::guide.md::Setup` — a doc section\n- `@code::auth.ts::AuthService` — a code symbol\n- `@files::src/config.ts` — a file\n- `@tasks::fix-auth-bug` — a task\n- `@knowledge::auth-architecture` — a note\n- `@skills::add-rest-endpoint` — a skill\n\n## Creating cross-graph links\n\n### From Knowledge (notes)\n\nUse `create_relation` with the `targetGraph` parameter:\n\n```\ncreate_relation({\n fromId: "auth-architecture",\n toId: "auth.ts::AuthService",\n kind: "documents",\n targetGraph: "code"\n})\n```\n\nSupported target graphs: `docs`, `code`, `files`, `tasks`, `skills`\n\n### From Tasks\n\nUse `create_task_link` with the `targetGraph` parameter:\n\n```\ncreate_task_link({\n taskId: "update-auth-docs",\n targetId: "guide.md::Authentication",\n kind: "relates_to",\n targetGraph: "docs"\n})\n```\n\nSupported target graphs: `docs`, `code`, `files`, `knowledge`, `skills`\n\n### From Skills\n\nUse `create_skill_link` with the `targetGraph` parameter:\n\n```\ncreate_skill_link({\n skillId: "add-rest-endpoint",\n targetId: "api-guide.md::REST",\n kind: "relates_to",\n targetGraph: "docs"\n})\n```\n\nSupported target graphs: `docs`, `code`, `files`, `knowledge`, `tasks`\n\n## Discovering cross-graph links\n\n- `find_linked_notes` — find all notes linked to a specific external node\n- `find_linked_tasks` — find all tasks linked to a specific external node\n- `find_linked_skills` — find all skills linked to a specific external node\n- `list_relations` — list all relations for a note (including cross-graph)\n- `get_task` — returns enriched task data including all cross-graph links\n- `get_skill` — returns enriched skill data including all cross-graph links\n\n## Proxy cleanup\n\nProxy nodes are automatically cleaned up when:\n- The source note, task, or skill is deleted (orphaned proxies removed)\n- The relation/link is explicitly deleted\n- During indexing, if the target file no longer exists\n\n## Use cases\n\n- **Architecture decisions**: Create notes documenting why code is structured a certain way, link to the actual code symbols\n- **Task context**: Link tasks to the files and docs they affect for quick navigation\n- **Knowledge mapping**: Build a web of connections between concepts, implementations, and documentation\n- **Reusable skills**: Link skills to the code, docs, and tasks they relate to so they can be recalled in context\n'},{id:`mcp-setup`,title:`Connecting MCP Clients`,summary:`How to connect Claude Desktop, Cursor, Windsurf, and other MCP clients via HTTP.`,category:`guide`,relatedTools:[`get_context`],content:`# Connecting MCP Clients
877
876
 
878
- Graph Memory supports two transport modes for MCP clients: **stdio** (single project) and **HTTP** (multi-project). Choose the right one for your setup.
877
+ Graph Memory uses HTTP transport for MCP clients. Start the server, then connect your client to the MCP endpoint.
879
878
 
880
- ## Stdio transport
881
-
882
- Best for: single-project setups, IDE integrations where each project gets its own MCP server process.
883
-
884
- The MCP client launches the server as a subprocess. Communication happens over stdin/stdout.
885
-
886
- After \`npm install -g @graphmemory/server\`:
887
-
888
- ### Claude Desktop (stdio)
889
-
890
- Add to your Claude Desktop config (\`claude_desktop_config.json\`):
891
-
892
- \`\`\`json
893
- {
894
- "mcpServers": {
895
- "graph-memory": {
896
- "command": "graphmemory",
897
- "args": ["mcp", "--config", "/path/to/graph-memory.yaml", "--project", "my-app"]
898
- }
899
- }
900
- }
901
- \`\`\`
902
-
903
- Replace \`my-app\` with the project ID from your \`graph-memory.yaml\`.
904
-
905
- ### Claude Code (stdio)
906
-
907
- Add to your project's \`.mcp.json\`:
908
-
909
- \`\`\`json
910
- {
911
- "mcpServers": {
912
- "graph-memory": {
913
- "type": "stdio",
914
- "command": "graphmemory",
915
- "args": ["mcp", "--config", "/path/to/graph-memory.yaml", "--project", "my-app"]
916
- }
917
- }
918
- }
919
- \`\`\`
920
-
921
- ## HTTP transport
922
-
923
- Best for: multi-project setups, shared team servers, or when multiple clients need to access the same graphs simultaneously.
879
+ ## Setup
924
880
 
925
881
  Start the server first:
926
882
 
@@ -930,7 +886,7 @@ graphmemory serve --config graph-memory.yaml
930
886
 
931
887
  Each project gets its own MCP endpoint at \`http://localhost:3000/mcp/{projectId}\`.
932
888
 
933
- ### Claude Desktop (HTTP)
889
+ ### Claude Desktop
934
890
 
935
891
  Add via **Settings > Connectors** in the Claude Desktop app, enter the URL:
936
892
 
@@ -938,7 +894,7 @@ Add via **Settings > Connectors** in the Claude Desktop app, enter the URL:
938
894
  http://localhost:3000/mcp/my-app
939
895
  \`\`\`
940
896
 
941
- ### Claude Code (HTTP)
897
+ ### Claude Code
942
898
 
943
899
  Run in your project directory:
944
900
 
@@ -969,8 +925,6 @@ http://localhost:3000/mcp/{projectId}
969
925
 
970
926
  ## Docker
971
927
 
972
- When running via Docker, the HTTP transport is the only option (stdio requires a local process).
973
-
974
928
  \`\`\`bash
975
929
  docker run -d \\
976
930
  --name graph-memory \\
@@ -997,18 +951,6 @@ docker run --rm \\
997
951
  docker compose run --rm graph-memory index --config /data/config/graph-memory.yaml
998
952
  \`\`\`
999
953
 
1000
- ## Which transport to choose?
1001
-
1002
- | | Stdio | HTTP |
1003
- |---|---|---|
1004
- | **Projects** | One per process | Multiple from one server |
1005
- | **Clients** | One client per server | Many clients share one server |
1006
- | **Web UI** | Not available | Available at \`http://localhost:3000\` |
1007
- | **REST API** | Not available | Available at \`/api/*\` |
1008
- | **WebSocket** | Not available | Real-time updates via \`/api/ws\` |
1009
- | **Setup** | Client manages process | You start the server separately |
1010
- | **Best for** | IDE integration | Teams, multi-project, Docker |
1011
-
1012
954
  ## Troubleshooting
1013
955
 
1014
956
  **Model loading is slow on first start**: The embedding model (\`Xenova/bge-m3\`, ~560MB) is downloaded on first use. Subsequent starts use the cached model from \`~/.graph-memory/models/\` (or the configured \`modelsDir\`).
@@ -1017,7 +959,7 @@ docker compose run --rm graph-memory index --config /data/config/graph-memory.ya
1017
959
 
1018
960
  **Tools not showing up**: Make sure \`graphs.docs.include\` and/or \`graphs.code.include\` are set in your config (defaults: \`**/*.md\` and \`**/*.{js,ts,jsx,tsx}\`). If a graph is \`enabled: false\`, its tools won't be registered.
1019
961
 
1020
- **Config changes not taking effect**: The \`serve\` command watches \`graph-memory.yaml\` for changes automatically. For \`mcp\` (stdio), you need to restart the process.
962
+ **Config changes not taking effect**: Restart the server process to apply changes to \`graph-memory.yaml\`.
1021
963
  `},{id:`configuration`,title:`Configuration Guide`,summary:`All graph-memory.yaml settings: server, projects, workspaces, embedding models, and patterns.`,category:`guide`,relatedTools:[],content:`# Configuration Guide
1022
964
 
1023
965
  All configuration is done via a single \`graph-memory.yaml\` file. This guide covers every setting and common patterns.
@@ -1095,8 +1037,8 @@ projects:
1095
1037
  enabled: true # Set false to disable this graph
1096
1038
  include: "**/*.md" # Default — indexes all markdown files
1097
1039
  exclude: "**/archive/**" # Glob to exclude
1098
- embedding: # Full embedding config (no merge with parent)
1099
- model: "Xenova/bge-m3"
1040
+ model: # Full model config (whole object, no merge with parent)
1041
+ name: "Xenova/bge-m3"
1100
1042
  pooling: "cls"
1101
1043
  normalize: true
1102
1044
  access: # Per-graph access control
@@ -1104,8 +1046,8 @@ projects:
1104
1046
  code:
1105
1047
  enabled: true
1106
1048
  include: "**/*.{js,ts,jsx,tsx}" # Default — indexes all JS/TS files
1107
- embedding:
1108
- model: "Xenova/bge-base-en-v1.5"
1049
+ model:
1050
+ name: "Xenova/bge-base-en-v1.5"
1109
1051
  knowledge:
1110
1052
  access:
1111
1053
  bob: rw # bob gets rw on knowledge
@@ -1154,7 +1096,7 @@ workspaces:
1154
1096
 
1155
1097
  ## Users & authentication
1156
1098
 
1157
- Define users for REST API and UI authentication. MCP stdio mode does not use authentication — identity comes from the \`author\` config.
1099
+ Define users for REST API and UI authentication.
1158
1100
 
1159
1101
  \`\`\`yaml
1160
1102
  users:
@@ -1296,8 +1238,9 @@ Instead of running the embedding model locally, delegate to a remote embedding A
1296
1238
 
1297
1239
  \`\`\`yaml
1298
1240
  server:
1241
+ model:
1242
+ name: "Xenova/bge-m3"
1299
1243
  embedding:
1300
- model: "Xenova/bge-m3"
1301
1244
  remote: "http://gpu-server:3000/api/embed"
1302
1245
  remoteApiKey: "emb-secret-key"
1303
1246
  \`\`\`
@@ -1372,16 +1315,16 @@ projects:
1372
1315
  projectDir: "/data/projects/my-app"
1373
1316
  \`\`\`
1374
1317
 
1375
- ## Hot reload
1318
+ ## Applying config changes
1376
1319
 
1377
- When using the \`serve\` command, the config file is watched for changes. You can add, remove, or update projects without restarting the server.
1320
+ Restart the server process to apply changes to \`graph-memory.yaml\`.
1378
1321
 
1379
1322
  ## Automatic re-indexing
1380
1323
 
1381
1324
  Each graph stores which embedding model was used. If you change the model in config, the graph is automatically discarded and re-indexed on next startup — no \`--reindex\` flag needed.
1382
1325
  `},{id:`docs-tools`,title:`Documentation Tools`,summary:`Search, browse, and navigate indexed markdown documentation.`,category:`guide`,relatedTools:[`list_topics`,`get_toc`,`search`,`get_node`,`search_topic_files`,`find_examples`,`search_snippets`,`list_snippets`,`explain_symbol`],content:`# Documentation Tools
1383
1326
 
1384
- The docs tools let you search, browse, and navigate your indexed markdown documentation. They're available when \`graphs.docs.pattern\` (or legacy \`docsPattern\`) is configured in your project.
1327
+ The docs tools let you search, browse, and navigate your indexed markdown documentation. They're available when \`graphs.docs.include\` is configured in your project (default: \`**/*.md\`).
1385
1328
 
1386
1329
  ## Tool overview
1387
1330
 
@@ -1574,7 +1517,7 @@ Find documentation that explains a symbol — returns both code example and surr
1574
1517
  - Lower \`minScore\` to 0.3 when exploring unfamiliar codebases
1575
1518
  - Set \`bfsDepth: 0\` in \`search\` for pure vector search without graph expansion
1576
1519
  - Set \`bfsDepth: 2\` to discover more loosely related content
1577
- `},{id:`code-tools`,title:`Code Tools`,summary:`Search and navigate TypeScript/JavaScript source code symbols.`,category:`guide`,relatedTools:[`list_files`,`get_file_symbols`,`search_code`,`get_symbol`,`search_files`],content:'# Code Tools\n\nThe code tools let you search and navigate your indexed TypeScript/JavaScript source code. They\'re available when `graphs.code.pattern` (or legacy `codePattern`) is configured in your project.\n\n## Tool overview\n\n| Tool | Purpose | When to use |\n|------|---------|-------------|\n| `list_files` | List all indexed source files | Get an overview of the codebase |\n| `get_file_symbols` | List symbols in a file | Explore a file\'s exports and structure |\n| `search_code` | Semantic search across code symbols | Find functions/classes by what they do |\n| `get_symbol` | Get full details of a symbol | Read signature, JSDoc, body, line numbers |\n| `search_files` | Search at file level | Find which files are relevant to a topic |\n\n## What gets indexed\n\nThe code parser uses tree-sitter to extract:\n- **Functions** — name, signature, JSDoc, line range, exported flag\n- **Classes** — name, methods, extends/implements relationships\n- **Interfaces** and **Types** — name, signature\n- **Enums** — name, members\n- **Variables** (exported) — name, type\n- **Methods** — as children of their parent class\n\nEdges capture structural relationships:\n- `contains` — file → symbol, class → method\n- `imports` — file → imported file (resolved by import resolver)\n- `extends` — class → base class\n- `implements` — class → interface\n\n## Node ID format\n\nCode graph node IDs follow a hierarchical pattern:\n- `"src/auth.ts"` — file node\n- `"src/auth.ts::createUser"` — top-level symbol in file\n- `"src/auth.ts::AuthService::login"` — method within a class\n\n## Typical workflow\n\n### 1. Find code by meaning\n\nUse `search_code` with a description of what you\'re looking for:\n- `"user authentication"` — finds auth-related functions and classes\n- `"parse markdown into sections"` — finds parsing logic\n\nUnlike grep, this finds code by **what it does**, not by exact text matches.\n\n### 2. Explore a symbol\n\nUse `get_symbol` with the symbol ID from search results. This returns the full picture: signature, JSDoc comment, body text, file location, line numbers, export status.\n\n### 3. Understand file structure\n\nUse `get_file_symbols` to see all symbols in a file — helpful for understanding module organization. The result includes `isExported` flag to distinguish public API from internal helpers.\n\n### 4. Discover relevant files\n\nUse `search_files` for a quick file-level search before diving into symbols. Lighter than `search_code` when you just need to identify which files to explore.\n\n### 5. Cross-reference with docs\n\nUse `cross_references` (requires both `docsPattern` and `codePattern`) to find everywhere a symbol appears — in both code definitions and documentation examples. See the dedicated guide for details.\n\n## Tool reference\n\n### list_files\n\nList indexed source files with optional filtering.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `filter` | string | No | — | Case-insensitive substring to match against file paths, e.g. `"graph"` or `"src/lib"` |\n| `limit` | number | No | 20 | Maximum number of results |\n\n**Returns:** `[{ fileId, symbolCount }]`\n\n### get_file_symbols\n\nReturn all symbols declared in a specific file.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `fileId` | string | Yes | File path, e.g. `"src/lib/graph.ts"` |\n\n**Returns:** `[{ id, kind, name, signature, startLine, endLine, isExported }]`\n\nSymbol kinds: `function`, `class`, `interface`, `type`, `enum`, `variable`, `method`, `property`.\n\n### search_code\n\nSemantic search over code symbols. Matches against signatures and doc comments using vector similarity, then expands through graph edges.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | — | Natural language or code search query |\n| `topK` | number | No | 5 | Number of seed nodes from vector search |\n| `bfsDepth` | number | No | 1 | Hops to follow graph edges (imports, contains, extends) from each seed. 0 = no expansion |\n| `maxResults` | number | No | 20 | Maximum results to return |\n| `minScore` | number | No | 0.5 | Minimum relevance score (0–1) |\n| `bfsDecay` | number | No | 0.8 | Score multiplier per graph hop |\n\n**Returns:** `[{ id, fileId, kind, name, signature, docComment, startLine, endLine, score }]`\n\n### get_symbol\n\nReturn full details of a specific code symbol.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `nodeId` | string | Yes | Symbol ID, e.g. `"src/lib/graph.ts::updateFile"` or `"src/auth.ts::AuthService::login"` |\n\n**Returns:** `{ id, fileId, kind, name, signature, docComment, body, startLine, endLine, isExported }`\n\nThe `body` field contains the full implementation text. `docComment` contains the JSDoc comment if present.\n\n### search_files\n\nSemantic search at file level using file path embeddings.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | — | Natural language or path search query |\n| `topK` | number | No | 10 | Maximum results |\n| `minScore` | number | No | 0.3 | Minimum relevance score (0–1) |\n\n**Returns:** `[{ fileId, symbolCount, score }]`\n\n## Tips\n\n- `search_code` works best with descriptive queries about **what the code does**, not exact symbol names\n- For exact name lookup, use `get_symbol` directly with the node ID\n- `get_file_symbols` shows `isExported` — useful for distinguishing public API from internals\n- `search_files` is useful as a first step when exploring unfamiliar codebases\n- The `cross_references` tool (see dedicated guide) is the most comprehensive way to understand a symbol\n- BFS expansion in `search_code` follows `imports`, `contains`, and `extends` edges — set `bfsDepth: 2` to discover related modules\n- Code graph edges track `imports` for relative imports only (`./ ../` paths); external packages are skipped\n'},{id:`knowledge-tools`,title:`Knowledge Tools`,summary:`Create and manage notes, facts, and decisions in a persistent knowledge graph.`,category:`guide`,relatedTools:[`create_note`,`update_note`,`delete_note`,`get_note`,`list_notes`,`search_notes`,`create_relation`,`delete_relation`,`list_relations`,`find_linked_notes`,`add_note_attachment`,`remove_note_attachment`],content:'# Knowledge Tools\n\nThe knowledge tools manage a persistent graph of **notes, facts, and decisions**. Unlike docs and code tools that index existing files, the knowledge graph is built manually — capturing information that lives in people\'s heads.\n\n## Why use a knowledge graph?\n\nCode and docs tell you **what** exists. The knowledge graph captures **why** — architectural decisions, domain knowledge, gotchas, context that doesn\'t belong in code comments.\n\nExamples:\n- "We use JWT instead of sessions because the mobile app needs stateless auth"\n- "The billing service has a 30-second timeout — don\'t chain more than 3 API calls"\n- "Users in the \'legacy\' tier have different rate limits, check `isLegacy` flag"\n\n## Tool overview\n\n| Tool | Purpose | Type |\n|------|---------|------|\n| `create_note` | Create a new note with title, content, tags | Mutation |\n| `update_note` | Update an existing note | Mutation |\n| `delete_note` | Remove a note and all its relations | Mutation |\n| `get_note` | Read a single note by ID | Read |\n| `list_notes` | List notes with optional filters | Read |\n| `search_notes` | Semantic search across notes | Read |\n| `create_relation` | Link a note to another note or external node | Mutation |\n| `delete_relation` | Remove a link | Mutation |\n| `list_relations` | List all relations for a note | Read |\n| `find_linked_notes` | Reverse lookup: find notes that link to an external node | Read |\n| `add_note_attachment` | Attach a file to a note | Mutation |\n| `remove_note_attachment` | Remove an attachment from a note | Mutation |\n\n> **Mutation tools** are serialized through a queue to prevent concurrent graph modifications.\n\n## Note ID generation\n\nNote IDs are slugified from the title:\n- "Auth Architecture" → `auth-architecture`\n- "JWT Token Format" → `jwt-token-format`\n\nDuplicate titles get a suffix: `auth-architecture::2`, `auth-architecture::3`.\n\n## Tool reference\n\n### create_note\n\nCreate a new note. Automatically embedded for semantic search.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `title` | string | Yes | Short title, e.g. `"Auth uses JWT tokens"` |\n| `content` | string | Yes | Full text content |\n| `tags` | string[] | No | Tags for filtering, e.g. `["architecture", "decision"]` |\n\n**Returns:** `{ noteId }` — the generated slug ID\n\n### update_note\n\nUpdate an existing note. Only provided fields change. Re-embeds automatically if title or content changes.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | ID of the note to update |\n| `title` | string | No | New title |\n| `content` | string | No | New content |\n| `tags` | string[] | No | New tags (replaces existing array entirely) |\n\n**Returns:** `{ noteId, updated: true }`\n\n### delete_note\n\nDelete a note and all its connected edges (relations, cross-graph links). Orphaned proxy nodes are cleaned up automatically.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | ID of the note to delete |\n\n**Returns:** `{ noteId, deleted: true }`\n\n### get_note\n\nReturn the full content of a note.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | Note ID, e.g. `"auth-uses-jwt-tokens"` |\n\n**Returns:** `{ id, title, content, tags, createdAt, updatedAt }`\n\n### list_notes\n\nList notes with optional filtering. Sorted by most recently updated.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `filter` | string | No | — | Case-insensitive substring match on title or ID |\n| `tag` | string | No | — | Filter by tag (exact match, case-insensitive) |\n| `limit` | number | No | 20 | Maximum results |\n\n**Returns:** `[{ id, title, tags, updatedAt }]`\n\n### search_notes\n\nSemantic search over the knowledge graph with BFS expansion through note relations.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | — | Natural language search query |\n| `topK` | number | No | 5 | Number of seed nodes from vector search |\n| `bfsDepth` | number | No | 1 | Hops to follow relations from each seed (0 = no expansion) |\n| `maxResults` | number | No | 20 | Maximum results |\n| `minScore` | number | No | 0.5 | Minimum relevance score (0–1) |\n| `bfsDecay` | number | No | 0.8 | Score multiplier per hop |\n\n**Returns:** `[{ id, title, content, tags, score }]`\n\n### create_relation\n\nCreate a directed edge from a note to another note or to an external graph node.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `fromId` | string | Yes | Source note ID |\n| `toId` | string | Yes | Target note ID, or target node ID in external graph |\n| `kind` | string | Yes | Relation type: `"relates_to"`, `"depends_on"`, `"contradicts"`, `"supports"`, `"part_of"`, `"references"`, etc. |\n| `targetGraph` | `"docs"` \\| `"code"` \\| `"files"` \\| `"tasks"` \\| `"skills"` | No | Set to create a cross-graph link instead of note-to-note |\n\n**Returns:** `{ fromId, toId, kind, targetGraph, created: true }`\n\n**Cross-graph examples:**\n```\ncreate_relation({ fromId: "auth-arch", toId: "auth.ts::AuthService", kind: "documents", targetGraph: "code" })\ncreate_relation({ fromId: "config-note", toId: "src/config.ts", kind: "references", targetGraph: "files" })\ncreate_relation({ fromId: "api-decision", toId: "api-guide.md::Endpoints", kind: "explains", targetGraph: "docs" })\ncreate_relation({ fromId: "my-note", toId: "fix-auth-bug", kind: "tracks", targetGraph: "tasks" })\n```\n\n### delete_relation\n\nRemove a directed edge.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `fromId` | string | Yes | Source note ID |\n| `toId` | string | Yes | Target note ID or external node ID |\n| `targetGraph` | `"docs"` \\| `"code"` \\| `"files"` \\| `"tasks"` \\| `"skills"` | No | Set when deleting a cross-graph link |\n\n**Returns:** `{ fromId, toId, targetGraph, deleted: true }`\n\n### list_relations\n\nList all relations (both incoming and outgoing) for a note. Cross-graph links include `targetGraph` field and resolve the real node ID (not the proxy ID).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | Note ID to list relations for |\n\n**Returns:** `[{ fromId, toId, kind, targetGraph? }]`\n\n### find_linked_notes\n\nReverse lookup: given a node in an external graph, find all notes that link to it.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `targetId` | string | Yes | Target node ID in the external graph, e.g. `"src/config.ts"`, `"auth.ts::login"`, `"api.md::Setup"` |\n| `targetGraph` | `"docs"` \\| `"code"` \\| `"files"` \\| `"tasks"` \\| `"skills"` | Yes | Which graph the target belongs to |\n| `kind` | string | No | Filter by relation kind. If omitted, returns all relations |\n\n**Returns:** `[{ noteId, title, kind, tags }]`\n\n**Use case:** When working on a code file, call `find_linked_notes({ targetId: "src/auth.ts", targetGraph: "code" })` to discover what knowledge notes reference that file.\n\n### add_note_attachment\n\nAttach a file to a note. The file is copied into the note\'s directory (`.notes/{noteId}/`).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | Note ID to attach the file to |\n| `filePath` | string | Yes | Absolute path to the file on disk |\n\n**Returns:** `{ noteId, attachment: { filename, mimeType, size } }`\n\n### remove_note_attachment\n\nRemove an attachment from a note. Deletes the file from disk.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | Note ID |\n| `filename` | string | Yes | Filename of the attachment to remove |\n\n**Returns:** `{ noteId, filename, deleted: true }`\n\n## Tips\n\n- Use tags consistently for easy filtering (e.g., `decision`, `gotcha`, `todo`, `architecture`)\n- Link notes to the code they describe — this creates a navigable knowledge web\n- `find_linked_notes` is useful to discover what knowledge exists about a specific code symbol or file\n- Notes persist across server restarts (saved as `knowledge.json`)\n- The `kind` field on relations is free-form — use whatever makes sense for your domain\n- `update_note` with `tags` replaces the entire array — include all tags you want to keep\n- `search_notes` with `bfsDepth: 2` will traverse through related notes to find loosely connected knowledge\n- Notes support file attachments — attach images, logs, or any file via `add_note_attachment`\n- Attachments are stored in `.notes/{noteId}/` alongside the note\'s markdown file\n'},{id:`task-tools`,title:`Task Tools`,summary:`Kanban task management with priorities, dependencies, and cross-graph links.`,category:`guide`,relatedTools:[`create_task`,`update_task`,`delete_task`,`get_task`,`list_tasks`,`search_tasks`,`move_task`,`link_task`,`create_task_link`,`delete_task_link`,`find_linked_tasks`,`add_task_attachment`,`remove_task_attachment`],content:'# Task Tools\n\nThe task tools provide a full **kanban-style task management** system within Graph Memory. Tasks have status, priority, due dates, estimates, and can link to any other graph.\n\n## Why tasks in Graph Memory?\n\nTasks here are tightly integrated with your project\'s knowledge graph:\n- Link a task to the code files it affects\n- Link a task to documentation that needs updating\n- Link a task to knowledge notes for context\n- Track dependencies between tasks (subtasks, blockers)\n\n## Tool overview\n\n| Tool | Purpose | Type |\n|------|---------|------|\n| `create_task` | Create a task | Mutation |\n| `update_task` | Modify task fields | Mutation |\n| `delete_task` | Remove a task and all its edges | Mutation |\n| `get_task` | Read a task with all relations | Read |\n| `list_tasks` | List tasks with filters | Read |\n| `search_tasks` | Semantic search across tasks | Read |\n| `move_task` | Change task status (kanban move) | Mutation |\n| `link_task` | Create task-to-task relation | Mutation |\n| `create_task_link` | Link task to external graph node | Mutation |\n| `delete_task_link` | Remove cross-graph link | Mutation |\n| `find_linked_tasks` | Reverse lookup: find tasks linked to an external node | Read |\n| `add_task_attachment` | Attach a file to a task | Mutation |\n| `remove_task_attachment` | Remove an attachment from a task | Mutation |\n\n> **Mutation tools** are serialized through a queue to prevent concurrent graph modifications.\n\n## Task properties\n\n| Property | Type | Values / Format | Notes |\n|----------|------|-----------------|-------|\n| `title` | string | Free text | Becomes slug ID |\n| `description` | string | Markdown | Full task description |\n| `status` | enum | `backlog`, `todo`, `in_progress`, `review`, `done`, `cancelled` | Use `move_task` to change |\n| `priority` | enum | `critical`, `high`, `medium`, `low` | Affects sort order |\n| `tags` | string[] | Free-form | For filtering |\n| `dueDate` | number | Unix timestamp in milliseconds | Optional deadline |\n| `estimate` | number | Hours | Optional effort estimate |\n| `assignee` | string \\| null | Team member ID | Optional assignee from `users:` config |\n| `completedAt` | number | Unix timestamp (auto-managed) | Set on done/cancelled, cleared on reopen |\n| `createdAt` | number | Unix timestamp (auto) | Set at creation |\n| `updatedAt` | number | Unix timestamp (auto) | Updated on every change |\n\n## Task ID generation\n\nLike notes, task IDs are slugified from the title:\n- "Fix auth redirect loop" → `fix-auth-redirect-loop`\n- Duplicates get suffixes: `fix-auth-redirect-loop::2`\n\n## Tool reference\n\n### create_task\n\nCreate a new task. Automatically embedded for semantic search.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `title` | string | Yes | — | Short title, e.g. `"Fix auth redirect loop"` |\n| `description` | string | Yes | — | Full description (markdown) |\n| `priority` | enum | Yes | — | `"critical"`, `"high"`, `"medium"`, `"low"` |\n| `status` | enum | No | `"backlog"` | `"backlog"`, `"todo"`, `"in_progress"`, `"review"`, `"done"`, `"cancelled"` |\n| `tags` | string[] | No | `[]` | Tags for filtering |\n| `dueDate` | number | No | — | Due date as Unix timestamp in milliseconds |\n| `estimate` | number | No | — | Estimated effort in hours |\n| `assignee` | string | No | — | Team member ID to assign the task to |\n\n**Returns:** `{ taskId }`\n\n### update_task\n\nUpdate an existing task. Only provided fields change. Re-embeds if title or description changes. Status changes auto-manage `completedAt`.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID to update |\n| `title` | string | No | New title |\n| `description` | string | No | New description |\n| `status` | enum | No | New status |\n| `priority` | enum | No | New priority |\n| `tags` | string[] | No | Replace tags array (include all you want to keep) |\n| `dueDate` | number \\| null | No | New due date (ms timestamp), or `null` to clear |\n| `estimate` | number \\| null | No | New estimate (hours), or `null` to clear |\n| `assignee` | string \\| null | No | Team member ID to assign, or `null` to unassign |\n\n**Returns:** `{ taskId, updated: true }`\n\n> Use `move_task` for a simpler status-only change — it\'s more explicit about `completedAt` management.\n\n### delete_task\n\nDelete a task and all its edges (relations + cross-graph links). Orphaned proxy nodes cleaned up automatically. **Irreversible.**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID to delete |\n\n**Returns:** `{ taskId, deleted: true }`\n\n### get_task\n\nReturn full task details including all relations. This is the most complete view of a task.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID to retrieve |\n\n**Returns:**\n```\n{\n id, title, description, status, priority, tags, assignee,\n dueDate, estimate, completedAt, createdAt, updatedAt,\n subtasks: [{ id, title, status }],\n blockedBy: [{ id, title, status }],\n blocks: [{ id, title, status }],\n related: [{ id, title, status }]\n}\n```\n\nThe `subtasks`, `blockedBy`, `blocks`, and `related` arrays are automatically populated from task-to-task edges.\n\n### list_tasks\n\nList tasks with optional filters. Sorted by priority (critical → low) then due date (earliest first, nulls last).\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `status` | enum | No | — | Filter by status |\n| `priority` | enum | No | — | Filter by priority |\n| `tag` | string | No | — | Filter by tag (exact match, case-insensitive) |\n| `filter` | string | No | — | Substring match on title or ID |\n| `assignee` | string | No | — | Filter by assignee (team member ID) |\n| `limit` | number | No | 50 | Maximum results |\n\n**Returns:** `[{ id, title, description, status, priority, tags, dueDate, estimate, assignee, completedAt, createdAt, updatedAt }]`\n\n### search_tasks\n\nSemantic search over the task graph with BFS expansion.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | — | Natural language search query |\n| `topK` | number | No | 5 | Seed nodes from vector search |\n| `bfsDepth` | number | No | 1 | Hops to follow relations (0 = no expansion) |\n| `maxResults` | number | No | 20 | Maximum results |\n| `minScore` | number | No | 0.5 | Minimum relevance score (0–1) |\n| `bfsDecay` | number | No | 0.8 | Score multiplier per hop |\n\n**Returns:** `[{ id, title, description, status, priority, tags, score }]`\n\n### move_task\n\nChange task status. The preferred way to move tasks through the kanban workflow.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID to move |\n| `status` | enum | Yes | New status: `"backlog"`, `"todo"`, `"in_progress"`, `"review"`, `"done"`, `"cancelled"` |\n\n**Returns:** `{ taskId, status, completedAt }`\n\n**Automatic behavior:**\n- Moving to `done` or `cancelled` → sets `completedAt` to current time\n- Moving from `done`/`cancelled` to any other status → clears `completedAt`\n\n### link_task\n\nCreate a directed relation between two tasks.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `fromId` | string | Yes | Source task ID |\n| `toId` | string | Yes | Target task ID |\n| `kind` | enum | Yes | `"subtask_of"`, `"blocks"`, `"related_to"` |\n\n**Returns:** `{ fromId, toId, kind, created: true }`\n\n**Semantics:**\n- `subtask_of` — `fromId` is a subtask of `toId` (child → parent)\n- `blocks` — `fromId` blocks `toId` (blocker → blocked task)\n- `related_to` — free association between tasks\n\n### create_task_link\n\nLink a task to a node in another graph (docs, code, files, or knowledge).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Source task ID |\n| `targetId` | string | Yes | Target node ID in the external graph |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"skills"` |\n| `kind` | string | Yes | Relation type: `"references"`, `"fixes"`, `"implements"`, `"documents"`, etc. |\n\n**Returns:** `{ taskId, targetId, targetGraph, kind, created: true }`\n\n**Examples:**\n```\ncreate_task_link({ taskId: "fix-auth", targetId: "src/auth.ts::login", targetGraph: "code", kind: "fixes" })\ncreate_task_link({ taskId: "update-docs", targetId: "guide.md::Authentication", targetGraph: "docs", kind: "updates" })\ncreate_task_link({ taskId: "review-config", targetId: "src/config.ts", targetGraph: "files", kind: "references" })\ncreate_task_link({ taskId: "implement-arch", targetId: "auth-architecture", targetGraph: "knowledge", kind: "implements" })\n```\n\n### delete_task_link\n\nRemove a cross-graph link from a task. Orphaned proxy nodes cleaned up automatically.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Source task ID |\n| `targetId` | string | Yes | Target node ID in the external graph |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"skills"` |\n\n**Returns:** `{ taskId, targetId, targetGraph, deleted: true }`\n\n### find_linked_tasks\n\nReverse lookup: given a node in an external graph, find all tasks that link to it.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `targetId` | string | Yes | Target node ID, e.g. `"src/auth.ts"`, `"guide.md::Setup"`, `"my-note"` |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"skills"` |\n| `kind` | string | No | Filter by relation kind. Omit for all relations |\n\n**Returns:** `[{ taskId, title, kind, status, priority, tags }]`\n\n**Use case:** When working on a file, call `find_linked_tasks({ targetId: "src/auth.ts", targetGraph: "code" })` to see all tasks related to that file.\n\n### add_task_attachment\n\nAttach a file to a task. The file is copied into the task\'s directory (`.tasks/{taskId}/`).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID to attach the file to |\n| `filePath` | string | Yes | Absolute path to the file on disk |\n\n**Returns:** `{ taskId, attachment: { filename, mimeType, size } }`\n\n### remove_task_attachment\n\nRemove an attachment from a task. Deletes the file from disk.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID |\n| `filename` | string | Yes | Filename of the attachment to remove |\n\n**Returns:** `{ taskId, filename, deleted: true }`\n\n## Kanban board UI\n\nThe Tasks page provides a visual kanban board with these features:\n\n- **Column visibility** — toggle which status columns are shown via the column icon in the top bar; saved in localStorage\n- **Drag-and-drop** — drag task cards between columns to change status; drop-zone highlights on hover\n- **Inline task creation** — click "+" in a column header to quickly create a task in that status\n- **Filter bar** — search tasks by text, filter by priority or tag\n- **Due date indicators** — overdue tasks show a red badge, approaching deadlines (≤3 days) show yellow\n- **Estimate badges** — tasks with estimates show hours on the card\n- **Quick actions** — hover a card to see edit and delete buttons\n- **Scrollable columns** — columns scroll independently when content overflows\n\n## Tips\n\n- Use `move_task` instead of `update_task` for status changes — it explicitly handles `completedAt`\n- `get_task` returns the richest data — includes subtasks, blockers, and related tasks\n- `list_tasks` is sorted by priority then due date — critical overdue tasks appear first\n- Link tasks to code files they affect — makes it easy to find related tasks when working on code\n- Use `search_tasks` to find tasks by meaning, not just title keywords\n- `update_task` with `dueDate: null` or `estimate: null` clears those fields\n- `update_task` with `tags` replaces the entire array — include all tags you want to keep\n- Task-to-task `kind` values are a fixed enum (`subtask_of`, `blocks`, `related_to`), unlike knowledge relations which are free-form\n- Tasks support file attachments — attach screenshots, logs, or any file via `add_task_attachment`\n- Attachments are stored in `.tasks/{taskId}/` alongside the task\'s markdown file\n'},{id:`skill-tools`,title:`Skill Tools`,summary:`Create and manage reusable skills, recipes, and procedures with triggers and usage tracking.`,category:`guide`,relatedTools:[`create_skill`,`update_skill`,`delete_skill`,`get_skill`,`list_skills`,`search_skills`,`link_skill`,`create_skill_link`,`delete_skill_link`,`find_linked_skills`,`add_skill_attachment`,`remove_skill_attachment`,`recall_skills`,`bump_skill_usage`],content:'# Skill Tools\n\nThe skill tools provide a **recipe/procedure management** system within Graph Memory. Skills capture reusable knowledge — step-by-step procedures, patterns, and best practices — with triggers, usage tracking, and cross-graph links.\n\n## Why skills in Graph Memory?\n\nSkills here are tightly integrated with your project\'s knowledge graph:\n- Link a skill to the code files it applies to\n- Link a skill to documentation that describes the pattern\n- Link a skill to knowledge notes for context\n- Link a skill to tasks that use the procedure\n- Track dependencies and variants between skills\n\n## Tool overview\n\n| Tool | Purpose | Type |\n|------|---------|------|\n| `create_skill` | Create a skill with steps, triggers, and metadata | Mutation |\n| `update_skill` | Modify skill fields (partial update) | Mutation |\n| `delete_skill` | Remove a skill and all its edges | Mutation |\n| `get_skill` | Read a skill with all relations | Read |\n| `list_skills` | List skills with filters | Read |\n| `search_skills` | Semantic search across skills | Read |\n| `link_skill` | Create skill-to-skill relation | Mutation |\n| `create_skill_link` | Link skill to external graph node | Mutation |\n| `delete_skill_link` | Remove cross-graph link | Mutation |\n| `find_linked_skills` | Reverse lookup: find skills linked to an external node | Read |\n| `add_skill_attachment` | Attach a file to a skill | Mutation |\n| `remove_skill_attachment` | Remove an attachment from a skill | Mutation |\n| `recall_skills` | Recall relevant skills for a task context | Read |\n| `bump_skill_usage` | Increment usage counter + set lastUsedAt | Mutation |\n\n> **Mutation tools** are serialized through a queue to prevent concurrent graph modifications.\n\n## Skill properties\n\n| Property | Type | Values / Format | Notes |\n|----------|------|-----------------|-------|\n| `title` | string | Free text | Becomes slug ID |\n| `description` | string | Markdown | Full skill description |\n| `steps` | string[] | Ordered list | Step-by-step procedure |\n| `triggers` | string[] | Free-form | When to apply this skill |\n| `source` | enum | `user`, `learned` | How the skill was created |\n| `tags` | string[] | Free-form | For filtering |\n| `usageCount` | number | Auto-managed | Incremented by `bump_skill_usage` |\n| `lastUsedAt` | number | Unix timestamp (auto) | Set by `bump_skill_usage` |\n| `createdAt` | number | Unix timestamp (auto) | Set at creation |\n| `updatedAt` | number | Unix timestamp (auto) | Updated on every change |\n\n## Skill ID generation\n\nLike notes and tasks, skill IDs are slugified from the title:\n- "Add REST Endpoint" -> `add-rest-endpoint`\n- Duplicates get suffixes: `add-rest-endpoint::2`\n\n## Tool reference\n\n### create_skill\n\nCreate a new skill. Automatically embedded for semantic search.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `title` | string | Yes | -- | Short title, e.g. `"Add REST Endpoint"` |\n| `description` | string | Yes | -- | Full description (markdown) |\n| `steps` | string[] | No | `[]` | Ordered steps of the procedure |\n| `triggers` | string[] | No | `[]` | When this skill should be applied |\n| `source` | enum | No | `"user"` | `"user"`, `"learned"` |\n| `tags` | string[] | No | `[]` | Tags for filtering |\n\n**Returns:** `{ skillId }`\n\n### update_skill\n\nUpdate an existing skill. Only provided fields change. Re-embeds if title, description, or triggers change.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID to update |\n| `title` | string | No | New title |\n| `description` | string | No | New description |\n| `steps` | string[] | No | Replace steps array |\n| `triggers` | string[] | No | Replace triggers array |\n| `source` | enum | No | New source |\n| `tags` | string[] | No | Replace tags array (include all you want to keep) |\n\n**Returns:** `{ skillId, updated: true }`\n\n### delete_skill\n\nDelete a skill and all its edges (relations + cross-graph links). Orphaned proxy nodes cleaned up automatically. **Irreversible.**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID to delete |\n\n**Returns:** `{ skillId, deleted: true }`\n\n### get_skill\n\nReturn full skill details including all relations. This is the most complete view of a skill.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID to retrieve |\n\n**Returns:**\n```\n{\n id, title, description, steps, triggers, source, tags,\n usageCount, lastUsedAt, createdAt, updatedAt,\n dependsOn: [{ id, title }],\n dependedBy: [{ id, title }],\n related: [{ id, title }],\n variants: [{ id, title }]\n}\n```\n\nThe `dependsOn`, `dependedBy`, `related`, and `variants` arrays are automatically populated from skill-to-skill edges.\n\n### list_skills\n\nList skills with optional filters. Sorted by usage count (most used first).\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `source` | enum | No | -- | Filter by source (`user`, `learned`) |\n| `tag` | string | No | -- | Filter by tag (exact match, case-insensitive) |\n| `filter` | string | No | -- | Substring match on title or ID |\n| `limit` | number | No | 50 | Maximum results |\n\n**Returns:** `[{ id, title, description, steps, triggers, source, tags, usageCount, lastUsedAt, createdAt, updatedAt }]`\n\n### search_skills\n\nSemantic search over the skill graph with BFS expansion.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | -- | Natural language search query |\n| `topK` | number | No | 5 | Seed nodes from vector search |\n| `bfsDepth` | number | No | 1 | Hops to follow relations (0 = no expansion) |\n| `maxResults` | number | No | 20 | Maximum results |\n| `minScore` | number | No | 0.5 | Minimum relevance score (0-1) |\n| `bfsDecay` | number | No | 0.8 | Score multiplier per hop |\n\n**Returns:** `[{ id, title, description, steps, triggers, source, tags, score }]`\n\n### recall_skills\n\nRecall relevant skills for a task context. Uses a lower default `minScore` (0.3) for higher recall.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | -- | Task context or description |\n| `topK` | number | No | 10 | Maximum results |\n| `minScore` | number | No | 0.3 | Minimum relevance score (0-1) |\n\n**Returns:** `[{ id, title, description, steps, triggers, source, tags, score, usageCount }]`\n\n### bump_skill_usage\n\nRecord that a skill was used. Increments `usageCount` and sets `lastUsedAt` to the current time.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID to bump |\n\n**Returns:** `{ skillId, usageCount, lastUsedAt }`\n\n### link_skill\n\nCreate a directed relation between two skills.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `fromId` | string | Yes | Source skill ID |\n| `toId` | string | Yes | Target skill ID |\n| `kind` | enum | Yes | `"depends_on"`, `"related_to"`, `"variant_of"` |\n\n**Returns:** `{ fromId, toId, kind, created: true }`\n\n**Semantics:**\n- `depends_on` -- `fromId` depends on `toId` (prerequisite)\n- `related_to` -- free association between skills\n- `variant_of` -- `fromId` is a variation of `toId`\n\n### create_skill_link\n\nLink a skill to a node in another graph (docs, code, files, knowledge, or tasks).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Source skill ID |\n| `targetId` | string | Yes | Target node ID in the external graph |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"tasks"` |\n| `kind` | string | Yes | Relation type: `"applies_to"`, `"documented_in"`, `"used_by"`, etc. |\n\n**Returns:** `{ skillId, targetId, targetGraph, kind, created: true }`\n\n**Examples:**\n```\ncreate_skill_link({ skillId: "add-rest-endpoint", targetId: "src/routes/index.ts", targetGraph: "code", kind: "applies_to" })\ncreate_skill_link({ skillId: "add-rest-endpoint", targetId: "guide.md::REST API", targetGraph: "docs", kind: "documented_in" })\ncreate_skill_link({ skillId: "add-rest-endpoint", targetId: "implement-api", targetGraph: "tasks", kind: "used_by" })\n```\n\n### delete_skill_link\n\nRemove a cross-graph link from a skill. Orphaned proxy nodes cleaned up automatically.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Source skill ID |\n| `targetId` | string | Yes | Target node ID in the external graph |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"tasks"` |\n\n**Returns:** `{ skillId, targetId, targetGraph, deleted: true }`\n\n### find_linked_skills\n\nReverse lookup: given a node in an external graph, find all skills that link to it.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `targetId` | string | Yes | Target node ID, e.g. `"src/auth.ts"`, `"guide.md::Setup"`, `"my-task"` |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"tasks"` |\n| `kind` | string | No | Filter by relation kind. Omit for all relations |\n\n**Returns:** `[{ skillId, title, kind, source, tags }]`\n\n**Use case:** When working on a file, call `find_linked_skills({ targetId: "src/routes/index.ts", targetGraph: "code" })` to see all skills related to that file.\n\n### add_skill_attachment\n\nAttach a file to a skill. The file is copied into the skill\'s directory (`.skills/{skillId}/`).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID to attach the file to |\n| `filePath` | string | Yes | Absolute path to the file on disk |\n\n**Returns:** `{ skillId, attachment: { filename, mimeType, size } }`\n\n### remove_skill_attachment\n\nRemove an attachment from a skill. Deletes the file from disk.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID |\n| `filename` | string | Yes | Filename of the attachment to remove |\n\n**Returns:** `{ skillId, filename, deleted: true }`\n\n## Tips\n\n- Use `recall_skills` when starting a task to find relevant procedures -- it uses a lower threshold for better recall\n- Call `bump_skill_usage` after applying a skill to track which skills are most useful\n- Skills with `source: "learned"` are typically created by AI agents that discover patterns\n- Skills with `source: "user"` are created by humans documenting their procedures\n- Link skills to code files they apply to -- makes it easy to find relevant skills when working on code\n- Use `search_skills` to find skills by meaning, not just title keywords\n- `update_skill` with `tags` replaces the entire array -- include all tags you want to keep\n- Skill-to-skill `kind` values are a fixed enum (`depends_on`, `related_to`, `variant_of`)\n- Skills support file attachments -- attach templates, examples, or reference files via `add_skill_attachment`\n- Attachments are stored in `.skills/{skillId}/` alongside the skill\'s markdown file\n'},{id:`files-tools`,title:`File Index Tools`,summary:`Browse and search metadata for every file and directory in your project.`,category:`guide`,relatedTools:[`list_all_files`,`search_all_files`,`get_file_info`],content:'# File Index Tools\n\nThe file index tools provide access to metadata about **every file and directory** in your project. Unlike docs and code tools which only index pattern-matched files, the file index covers the entire project tree.\n\n## Tool overview\n\n| Tool | Purpose | When to use |\n|------|---------|-------------|\n| `list_all_files` | List files/directories with filters | Browse project structure, filter by extension/language |\n| `search_all_files` | Semantic search by file path | Find files by what they might contain |\n| `get_file_info` | Get metadata for a specific path | Check size, language, modification date |\n\n## What gets indexed\n\nFor every file in the project directory:\n- **Path** (relative to project root)\n- **File name** and **extension**\n- **Size** in bytes\n- **Language** (detected from extension: `.ts` → TypeScript, `.md` → Markdown, `.json` → JSON, etc.)\n- **MIME type** (e.g., `application/json`, `text/markdown`, `image/png`)\n- **Modification time** (`mtime`)\n\nFor directories:\n- **Aggregate size** (sum of all contained files)\n- **File count** (total files in subtree)\n- Directory → child edges (`contains`)\n\n## Browsing vs searching\n\n### Directory browsing\n\n`list_all_files` with the `directory` parameter returns **immediate children** (files + subdirectories) of that directory. This is how you browse the project tree:\n\n```\nlist_all_files({ directory: "." }) → root contents\nlist_all_files({ directory: "src" }) → src/ contents\nlist_all_files({ directory: "src/api" }) → src/api/ contents\n```\n\nWithout `directory`, it returns all files matching filters (flat list, no directories).\n\n### File search\n\n`search_all_files` embeds file paths for semantic search. You can search by:\n- Partial paths: `"config"` finds configuration files\n- Concepts: `"authentication"` finds files in auth-related directories\n- File types: `"typescript source"` finds `.ts` files\n\nThe `minScore` default is **0.3** (lower than node search) because file path embeddings are less semantically rich than content embeddings.\n\n## Tool reference\n\n### list_all_files\n\nList project files and directories with optional filters.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `directory` | string | No | — | List immediate children of this directory (e.g. `"."`, `"src/lib"`). Without this, returns all files matching filters |\n| `extension` | string | No | — | Filter by extension (e.g. `".ts"`, `".md"`, `".png"`) |\n| `language` | string | No | — | Filter by detected language (e.g. `"typescript"`, `"markdown"`, `"json"`) |\n| `filter` | string | No | — | Substring match on file path (case-insensitive) |\n| `limit` | number | No | 50 | Maximum results |\n\n**Returns:** `[{ filePath, kind, fileName, extension, language, mimeType, size, fileCount }]`\n\n- `kind` is `"file"` or `"directory"`\n- `fileCount` is present for directories (number of files in subtree)\n- `language` and `mimeType` are present for files\n\n**Behavior differences:**\n- With `directory` set: returns both files and subdirectories (immediate children only)\n- Without `directory`: returns only files (no directories), across the entire project\n\n### search_all_files\n\nSemantic search over file nodes by path embedding. Searches files only (not directories).\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | — | Search query (natural language or path fragment) |\n| `topK` | number | No | 10 | Maximum results |\n| `minScore` | number | No | 0.3 | Minimum cosine similarity score (0–1) |\n\n**Returns:** `[{ filePath, fileName, extension, language, size, score }]`\n\n### get_file_info\n\nGet full metadata for a specific file or directory. Use `"."` for the project root.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `filePath` | string | Yes | Relative file or directory path (e.g. `"src/lib/config.ts"`, `"src/lib"`, `"."`) |\n\n**Returns for files:**\n```\n{ filePath, kind: "file", fileName, directory, extension, language, mimeType, size, mtime }\n```\n\n**Returns for directories:**\n```\n{ filePath, kind: "directory", fileName, directory, fileCount, size }\n```\n\n- `size` for directories is the total size of all direct children\n- `fileCount` for directories is the total number of files in the subtree\n- `mtime` is the last modification timestamp (files only)\n\n## Cross-graph links\n\nFiles can be linked from notes and tasks:\n\n```\n// From a knowledge note\ncreate_relation({ fromId: "config-format", toId: "src/config.ts", kind: "documents", targetGraph: "files" })\n\n// From a task\ncreate_task_link({ taskId: "refactor-config", targetId: "src/config.ts", targetGraph: "files", kind: "affects" })\n```\n\nUse `find_linked_notes` or `find_linked_tasks` with `targetGraph: "files"` to discover what knowledge or tasks reference a specific file:\n\n```\nfind_linked_notes({ targetId: "src/auth.ts", targetGraph: "files" })\nfind_linked_tasks({ targetId: "src/auth.ts", targetGraph: "files" })\n```\n\n## Tips\n\n- Use `list_all_files` with `directory` to browse top-down through the project tree\n- Use `list_all_files` with `extension: ".ts"` or `language: "typescript"` to find all files of a type\n- `get_file_info` on `"."` gives project-level stats (total size, file count)\n- `search_all_files` works better with path-like queries than abstract concepts\n- File index is always active — no `docsPattern` or `codePattern` configuration needed\n- The `language` filter in `list_all_files` uses detected language names like `"typescript"`, `"javascript"`, `"markdown"`, `"json"`, `"yaml"`, `"css"`, `"html"`, `"python"`, etc.\n'},{id:`cross-references`,title:`Cross References Tool`,summary:`Bridge code definitions and documentation examples for any symbol.`,category:`guide`,relatedTools:[`cross_references`],content:`# Cross References Tool
1520
+ `},{id:`code-tools`,title:`Code Tools`,summary:`Search and navigate TypeScript/JavaScript source code symbols.`,category:`guide`,relatedTools:[`list_files`,`get_file_symbols`,`search_code`,`get_symbol`,`search_files`],content:'# Code Tools\n\nThe code tools let you search and navigate your indexed TypeScript/JavaScript source code. They\'re available when `graphs.code.include` is configured in your project (default: `**/*.{js,ts,jsx,tsx}`).\n\n## Tool overview\n\n| Tool | Purpose | When to use |\n|------|---------|-------------|\n| `list_files` | List all indexed source files | Get an overview of the codebase |\n| `get_file_symbols` | List symbols in a file | Explore a file\'s exports and structure |\n| `search_code` | Semantic search across code symbols | Find functions/classes by what they do |\n| `get_symbol` | Get full details of a symbol | Read signature, JSDoc, body, line numbers |\n| `search_files` | Search at file level | Find which files are relevant to a topic |\n\n## What gets indexed\n\nThe code parser uses tree-sitter to extract:\n- **Functions** — name, signature, JSDoc, line range, exported flag\n- **Classes** — name, methods, extends/implements relationships\n- **Interfaces** and **Types** — name, signature\n- **Enums** — name, members\n- **Variables** (exported) — name, type\n- **Methods** — as children of their parent class\n\nEdges capture structural relationships:\n- `contains` — file → symbol, class → method\n- `imports` — file → imported file (resolved by import resolver)\n- `extends` — class → base class\n- `implements` — class → interface\n\n## Node ID format\n\nCode graph node IDs follow a hierarchical pattern:\n- `"src/auth.ts"` — file node\n- `"src/auth.ts::createUser"` — top-level symbol in file\n- `"src/auth.ts::AuthService::login"` — method within a class\n\n## Typical workflow\n\n### 1. Find code by meaning\n\nUse `search_code` with a description of what you\'re looking for:\n- `"user authentication"` — finds auth-related functions and classes\n- `"parse markdown into sections"` — finds parsing logic\n\nUnlike grep, this finds code by **what it does**, not by exact text matches.\n\n### 2. Explore a symbol\n\nUse `get_symbol` with the symbol ID from search results. This returns the full picture: signature, JSDoc comment, body text, file location, line numbers, export status.\n\n### 3. Understand file structure\n\nUse `get_file_symbols` to see all symbols in a file — helpful for understanding module organization. The result includes `isExported` flag to distinguish public API from internal helpers.\n\n### 4. Discover relevant files\n\nUse `search_files` for a quick file-level search before diving into symbols. Lighter than `search_code` when you just need to identify which files to explore.\n\n### 5. Cross-reference with docs\n\nUse `cross_references` (requires both `graphs.docs.include` and `graphs.code.include`) to find everywhere a symbol appears — in both code definitions and documentation examples. See the dedicated guide for details.\n\n## Tool reference\n\n### list_files\n\nList indexed source files with optional filtering.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `filter` | string | No | — | Case-insensitive substring to match against file paths, e.g. `"graph"` or `"src/lib"` |\n| `limit` | number | No | 20 | Maximum number of results |\n\n**Returns:** `[{ fileId, symbolCount }]`\n\n### get_file_symbols\n\nReturn all symbols declared in a specific file.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `fileId` | string | Yes | File path, e.g. `"src/lib/graph.ts"` |\n\n**Returns:** `[{ id, kind, name, signature, startLine, endLine, isExported }]`\n\nSymbol kinds: `function`, `class`, `interface`, `type`, `enum`, `variable`, `method`, `property`.\n\n### search_code\n\nSemantic search over code symbols. Matches against signatures and doc comments using vector similarity, then expands through graph edges.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | — | Natural language or code search query |\n| `topK` | number | No | 5 | Number of seed nodes from vector search |\n| `bfsDepth` | number | No | 1 | Hops to follow graph edges (imports, contains, extends) from each seed. 0 = no expansion |\n| `maxResults` | number | No | 20 | Maximum results to return |\n| `minScore` | number | No | 0.5 | Minimum relevance score (0–1) |\n| `bfsDecay` | number | No | 0.8 | Score multiplier per graph hop |\n\n**Returns:** `[{ id, fileId, kind, name, signature, docComment, startLine, endLine, score }]`\n\n### get_symbol\n\nReturn full details of a specific code symbol.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `nodeId` | string | Yes | Symbol ID, e.g. `"src/lib/graph.ts::updateFile"` or `"src/auth.ts::AuthService::login"` |\n\n**Returns:** `{ id, fileId, kind, name, signature, docComment, body, startLine, endLine, isExported }`\n\nThe `body` field contains the full implementation text. `docComment` contains the JSDoc comment if present.\n\n### search_files\n\nSemantic search at file level using file path embeddings.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | — | Natural language or path search query |\n| `topK` | number | No | 10 | Maximum results |\n| `minScore` | number | No | 0.3 | Minimum relevance score (0–1) |\n\n**Returns:** `[{ fileId, symbolCount, score }]`\n\n## Tips\n\n- `search_code` works best with descriptive queries about **what the code does**, not exact symbol names\n- For exact name lookup, use `get_symbol` directly with the node ID\n- `get_file_symbols` shows `isExported` — useful for distinguishing public API from internals\n- `search_files` is useful as a first step when exploring unfamiliar codebases\n- The `cross_references` tool (see dedicated guide) is the most comprehensive way to understand a symbol\n- BFS expansion in `search_code` follows `imports`, `contains`, and `extends` edges — set `bfsDepth: 2` to discover related modules\n- Code graph edges track `imports` for relative imports only (`./ ../` paths); external packages are skipped\n'},{id:`knowledge-tools`,title:`Knowledge Tools`,summary:`Create and manage notes, facts, and decisions in a persistent knowledge graph.`,category:`guide`,relatedTools:[`create_note`,`update_note`,`delete_note`,`get_note`,`list_notes`,`search_notes`,`create_relation`,`delete_relation`,`list_relations`,`find_linked_notes`,`add_note_attachment`,`remove_note_attachment`],content:'# Knowledge Tools\n\nThe knowledge tools manage a persistent graph of **notes, facts, and decisions**. Unlike docs and code tools that index existing files, the knowledge graph is built manually — capturing information that lives in people\'s heads.\n\n## Why use a knowledge graph?\n\nCode and docs tell you **what** exists. The knowledge graph captures **why** — architectural decisions, domain knowledge, gotchas, context that doesn\'t belong in code comments.\n\nExamples:\n- "We use JWT instead of sessions because the mobile app needs stateless auth"\n- "The billing service has a 30-second timeout — don\'t chain more than 3 API calls"\n- "Users in the \'legacy\' tier have different rate limits, check `isLegacy` flag"\n\n## Tool overview\n\n| Tool | Purpose | Type |\n|------|---------|------|\n| `create_note` | Create a new note with title, content, tags | Mutation |\n| `update_note` | Update an existing note | Mutation |\n| `delete_note` | Remove a note and all its relations | Mutation |\n| `get_note` | Read a single note by ID | Read |\n| `list_notes` | List notes with optional filters | Read |\n| `search_notes` | Semantic search across notes | Read |\n| `create_relation` | Link a note to another note or external node | Mutation |\n| `delete_relation` | Remove a link | Mutation |\n| `list_relations` | List all relations for a note | Read |\n| `find_linked_notes` | Reverse lookup: find notes that link to an external node | Read |\n| `add_note_attachment` | Attach a file to a note | Mutation |\n| `remove_note_attachment` | Remove an attachment from a note | Mutation |\n\n> **Mutation tools** are serialized through a queue to prevent concurrent graph modifications.\n\n## Note ID generation\n\nNote IDs are slugified from the title:\n- "Auth Architecture" → `auth-architecture`\n- "JWT Token Format" → `jwt-token-format`\n\nDuplicate titles get a suffix: `auth-architecture::2`, `auth-architecture::3`.\n\n## Tool reference\n\n### create_note\n\nCreate a new note. Automatically embedded for semantic search.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `title` | string | Yes | Short title, e.g. `"Auth uses JWT tokens"` |\n| `content` | string | Yes | Full text content |\n| `tags` | string[] | No | Tags for filtering, e.g. `["architecture", "decision"]` |\n\n**Returns:** `{ noteId }` — the generated slug ID\n\n### update_note\n\nUpdate an existing note. Only provided fields change. Re-embeds automatically if title or content changes.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | ID of the note to update |\n| `title` | string | No | New title |\n| `content` | string | No | New content |\n| `tags` | string[] | No | New tags (replaces existing array entirely) |\n\n**Returns:** `{ noteId, updated: true }`\n\n### delete_note\n\nDelete a note and all its connected edges (relations, cross-graph links). Orphaned proxy nodes are cleaned up automatically.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | ID of the note to delete |\n\n**Returns:** `{ noteId, deleted: true }`\n\n### get_note\n\nReturn the full content of a note.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | Note ID, e.g. `"auth-uses-jwt-tokens"` |\n\n**Returns:** `{ id, title, content, tags, createdAt, updatedAt }`\n\n### list_notes\n\nList notes with optional filtering. Sorted by most recently updated.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `filter` | string | No | — | Case-insensitive substring match on title or ID |\n| `tag` | string | No | — | Filter by tag (exact match, case-insensitive) |\n| `limit` | number | No | 20 | Maximum results |\n\n**Returns:** `[{ id, title, tags, updatedAt }]`\n\n### search_notes\n\nSemantic search over the knowledge graph with BFS expansion through note relations.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | — | Natural language search query |\n| `topK` | number | No | 5 | Number of seed nodes from vector search |\n| `bfsDepth` | number | No | 1 | Hops to follow relations from each seed (0 = no expansion) |\n| `maxResults` | number | No | 20 | Maximum results |\n| `minScore` | number | No | 0.5 | Minimum relevance score (0–1) |\n| `bfsDecay` | number | No | 0.8 | Score multiplier per hop |\n\n**Returns:** `[{ id, title, content, tags, score }]`\n\n### create_relation\n\nCreate a directed edge from a note to another note or to an external graph node.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `fromId` | string | Yes | Source note ID |\n| `toId` | string | Yes | Target note ID, or target node ID in external graph |\n| `kind` | string | Yes | Relation type: `"relates_to"`, `"depends_on"`, `"contradicts"`, `"supports"`, `"part_of"`, `"references"`, etc. |\n| `targetGraph` | `"docs"` \\| `"code"` \\| `"files"` \\| `"tasks"` \\| `"skills"` | No | Set to create a cross-graph link instead of note-to-note |\n\n**Returns:** `{ fromId, toId, kind, targetGraph, created: true }`\n\n**Cross-graph examples:**\n```\ncreate_relation({ fromId: "auth-arch", toId: "auth.ts::AuthService", kind: "documents", targetGraph: "code" })\ncreate_relation({ fromId: "config-note", toId: "src/config.ts", kind: "references", targetGraph: "files" })\ncreate_relation({ fromId: "api-decision", toId: "api-guide.md::Endpoints", kind: "explains", targetGraph: "docs" })\ncreate_relation({ fromId: "my-note", toId: "fix-auth-bug", kind: "tracks", targetGraph: "tasks" })\n```\n\n### delete_relation\n\nRemove a directed edge.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `fromId` | string | Yes | Source note ID |\n| `toId` | string | Yes | Target note ID or external node ID |\n| `targetGraph` | `"docs"` \\| `"code"` \\| `"files"` \\| `"tasks"` \\| `"skills"` | No | Set when deleting a cross-graph link |\n\n**Returns:** `{ fromId, toId, targetGraph, deleted: true }`\n\n### list_relations\n\nList all relations (both incoming and outgoing) for a note. Cross-graph links include `targetGraph` field and resolve the real node ID (not the proxy ID).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | Note ID to list relations for |\n\n**Returns:** `[{ fromId, toId, kind, targetGraph? }]`\n\n### find_linked_notes\n\nReverse lookup: given a node in an external graph, find all notes that link to it.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `targetId` | string | Yes | Target node ID in the external graph, e.g. `"src/config.ts"`, `"auth.ts::login"`, `"api.md::Setup"` |\n| `targetGraph` | `"docs"` \\| `"code"` \\| `"files"` \\| `"tasks"` \\| `"skills"` | Yes | Which graph the target belongs to |\n| `kind` | string | No | Filter by relation kind. If omitted, returns all relations |\n\n**Returns:** `[{ noteId, title, kind, tags }]`\n\n**Use case:** When working on a code file, call `find_linked_notes({ targetId: "src/auth.ts", targetGraph: "code" })` to discover what knowledge notes reference that file.\n\n### add_note_attachment\n\nAttach a file to a note. The file is copied into the note\'s directory (`.notes/{noteId}/`).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | Note ID to attach the file to |\n| `filePath` | string | Yes | Absolute path to the file on disk |\n\n**Returns:** `{ noteId, attachment: { filename, mimeType, size } }`\n\n### remove_note_attachment\n\nRemove an attachment from a note. Deletes the file from disk.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `noteId` | string | Yes | Note ID |\n| `filename` | string | Yes | Filename of the attachment to remove |\n\n**Returns:** `{ noteId, filename, deleted: true }`\n\n## Tips\n\n- Use tags consistently for easy filtering (e.g., `decision`, `gotcha`, `todo`, `architecture`)\n- Link notes to the code they describe — this creates a navigable knowledge web\n- `find_linked_notes` is useful to discover what knowledge exists about a specific code symbol or file\n- Notes persist across server restarts (saved as `knowledge.json`)\n- The `kind` field on relations is free-form — use whatever makes sense for your domain\n- `update_note` with `tags` replaces the entire array — include all tags you want to keep\n- `search_notes` with `bfsDepth: 2` will traverse through related notes to find loosely connected knowledge\n- Notes support file attachments — attach images, logs, or any file via `add_note_attachment`\n- Attachments are stored in `.notes/{noteId}/` alongside the note\'s markdown file\n'},{id:`task-tools`,title:`Task Tools`,summary:`Kanban task management with priorities, dependencies, and cross-graph links.`,category:`guide`,relatedTools:[`create_task`,`update_task`,`delete_task`,`get_task`,`list_tasks`,`search_tasks`,`move_task`,`link_task`,`create_task_link`,`delete_task_link`,`find_linked_tasks`,`add_task_attachment`,`remove_task_attachment`],content:'# Task Tools\n\nThe task tools provide a full **kanban-style task management** system within Graph Memory. Tasks have status, priority, due dates, estimates, and can link to any other graph.\n\n## Why tasks in Graph Memory?\n\nTasks here are tightly integrated with your project\'s knowledge graph:\n- Link a task to the code files it affects\n- Link a task to documentation that needs updating\n- Link a task to knowledge notes for context\n- Track dependencies between tasks (subtasks, blockers)\n\n## Tool overview\n\n| Tool | Purpose | Type |\n|------|---------|------|\n| `create_task` | Create a task | Mutation |\n| `update_task` | Modify task fields | Mutation |\n| `delete_task` | Remove a task and all its edges | Mutation |\n| `get_task` | Read a task with all relations | Read |\n| `list_tasks` | List tasks with filters | Read |\n| `search_tasks` | Semantic search across tasks | Read |\n| `move_task` | Change task status (kanban move) | Mutation |\n| `link_task` | Create task-to-task relation | Mutation |\n| `create_task_link` | Link task to external graph node | Mutation |\n| `delete_task_link` | Remove cross-graph link | Mutation |\n| `find_linked_tasks` | Reverse lookup: find tasks linked to an external node | Read |\n| `add_task_attachment` | Attach a file to a task | Mutation |\n| `remove_task_attachment` | Remove an attachment from a task | Mutation |\n\n> **Mutation tools** are serialized through a queue to prevent concurrent graph modifications.\n\n## Task properties\n\n| Property | Type | Values / Format | Notes |\n|----------|------|-----------------|-------|\n| `title` | string | Free text | Becomes slug ID |\n| `description` | string | Markdown | Full task description |\n| `status` | enum | `backlog`, `todo`, `in_progress`, `review`, `done`, `cancelled` | Use `move_task` to change |\n| `priority` | enum | `critical`, `high`, `medium`, `low` | Affects sort order |\n| `tags` | string[] | Free-form | For filtering |\n| `dueDate` | number | Unix timestamp in milliseconds | Optional deadline |\n| `estimate` | number | Hours | Optional effort estimate |\n| `assignee` | string \\| null | Team member ID | Optional assignee from `users:` config |\n| `completedAt` | number | Unix timestamp (auto-managed) | Set on done/cancelled, cleared on reopen |\n| `createdAt` | number | Unix timestamp (auto) | Set at creation |\n| `updatedAt` | number | Unix timestamp (auto) | Updated on every change |\n\n## Task ID generation\n\nLike notes, task IDs are slugified from the title:\n- "Fix auth redirect loop" → `fix-auth-redirect-loop`\n- Duplicates get suffixes: `fix-auth-redirect-loop::2`\n\n## Tool reference\n\n### create_task\n\nCreate a new task. Automatically embedded for semantic search.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `title` | string | Yes | — | Short title, e.g. `"Fix auth redirect loop"` |\n| `description` | string | Yes | — | Full description (markdown) |\n| `priority` | enum | Yes | — | `"critical"`, `"high"`, `"medium"`, `"low"` |\n| `status` | enum | No | `"backlog"` | `"backlog"`, `"todo"`, `"in_progress"`, `"review"`, `"done"`, `"cancelled"` |\n| `tags` | string[] | No | `[]` | Tags for filtering |\n| `dueDate` | number | No | — | Due date as Unix timestamp in milliseconds |\n| `estimate` | number | No | — | Estimated effort in hours |\n| `assignee` | string | No | — | Team member ID to assign the task to |\n\n**Returns:** `{ taskId }`\n\n### update_task\n\nUpdate an existing task. Only provided fields change. Re-embeds if title or description changes. Status changes auto-manage `completedAt`.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID to update |\n| `title` | string | No | New title |\n| `description` | string | No | New description |\n| `status` | enum | No | New status |\n| `priority` | enum | No | New priority |\n| `tags` | string[] | No | Replace tags array (include all you want to keep) |\n| `dueDate` | number \\| null | No | New due date (ms timestamp), or `null` to clear |\n| `estimate` | number \\| null | No | New estimate (hours), or `null` to clear |\n| `assignee` | string \\| null | No | Team member ID to assign, or `null` to unassign |\n\n**Returns:** `{ taskId, updated: true }`\n\n> Use `move_task` for a simpler status-only change — it\'s more explicit about `completedAt` management.\n\n### delete_task\n\nDelete a task and all its edges (relations + cross-graph links). Orphaned proxy nodes cleaned up automatically. **Irreversible.**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID to delete |\n\n**Returns:** `{ taskId, deleted: true }`\n\n### get_task\n\nReturn full task details including all relations. This is the most complete view of a task.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID to retrieve |\n\n**Returns:**\n```\n{\n id, title, description, status, priority, tags, assignee,\n dueDate, estimate, completedAt, createdAt, updatedAt,\n subtasks: [{ id, title, status }],\n blockedBy: [{ id, title, status }],\n blocks: [{ id, title, status }],\n related: [{ id, title, status }]\n}\n```\n\nThe `subtasks`, `blockedBy`, `blocks`, and `related` arrays are automatically populated from task-to-task edges.\n\n### list_tasks\n\nList tasks with optional filters. Sorted by priority (critical → low) then due date (earliest first, nulls last).\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `status` | enum | No | — | Filter by status |\n| `priority` | enum | No | — | Filter by priority |\n| `tag` | string | No | — | Filter by tag (exact match, case-insensitive) |\n| `filter` | string | No | — | Substring match on title or ID |\n| `assignee` | string | No | — | Filter by assignee (team member ID) |\n| `limit` | number | No | 50 | Maximum results |\n\n**Returns:** `[{ id, title, description, status, priority, tags, dueDate, estimate, assignee, completedAt, createdAt, updatedAt }]`\n\n### search_tasks\n\nSemantic search over the task graph with BFS expansion.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | — | Natural language search query |\n| `topK` | number | No | 5 | Seed nodes from vector search |\n| `bfsDepth` | number | No | 1 | Hops to follow relations (0 = no expansion) |\n| `maxResults` | number | No | 20 | Maximum results |\n| `minScore` | number | No | 0.5 | Minimum relevance score (0–1) |\n| `bfsDecay` | number | No | 0.8 | Score multiplier per hop |\n\n**Returns:** `[{ id, title, description, status, priority, tags, score }]`\n\n### move_task\n\nChange task status. The preferred way to move tasks through the kanban workflow.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID to move |\n| `status` | enum | Yes | New status: `"backlog"`, `"todo"`, `"in_progress"`, `"review"`, `"done"`, `"cancelled"` |\n\n**Returns:** `{ taskId, status, completedAt }`\n\n**Automatic behavior:**\n- Moving to `done` or `cancelled` → sets `completedAt` to current time\n- Moving from `done`/`cancelled` to any other status → clears `completedAt`\n\n### link_task\n\nCreate a directed relation between two tasks.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `fromId` | string | Yes | Source task ID |\n| `toId` | string | Yes | Target task ID |\n| `kind` | enum | Yes | `"subtask_of"`, `"blocks"`, `"related_to"` |\n\n**Returns:** `{ fromId, toId, kind, created: true }`\n\n**Semantics:**\n- `subtask_of` — `fromId` is a subtask of `toId` (child → parent)\n- `blocks` — `fromId` blocks `toId` (blocker → blocked task)\n- `related_to` — free association between tasks\n\n### create_task_link\n\nLink a task to a node in another graph (docs, code, files, or knowledge).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Source task ID |\n| `targetId` | string | Yes | Target node ID in the external graph |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"skills"` |\n| `kind` | string | Yes | Relation type: `"references"`, `"fixes"`, `"implements"`, `"documents"`, etc. |\n\n**Returns:** `{ taskId, targetId, targetGraph, kind, created: true }`\n\n**Examples:**\n```\ncreate_task_link({ taskId: "fix-auth", targetId: "src/auth.ts::login", targetGraph: "code", kind: "fixes" })\ncreate_task_link({ taskId: "update-docs", targetId: "guide.md::Authentication", targetGraph: "docs", kind: "updates" })\ncreate_task_link({ taskId: "review-config", targetId: "src/config.ts", targetGraph: "files", kind: "references" })\ncreate_task_link({ taskId: "implement-arch", targetId: "auth-architecture", targetGraph: "knowledge", kind: "implements" })\n```\n\n### delete_task_link\n\nRemove a cross-graph link from a task. Orphaned proxy nodes cleaned up automatically.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Source task ID |\n| `targetId` | string | Yes | Target node ID in the external graph |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"skills"` |\n\n**Returns:** `{ taskId, targetId, targetGraph, deleted: true }`\n\n### find_linked_tasks\n\nReverse lookup: given a node in an external graph, find all tasks that link to it.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `targetId` | string | Yes | Target node ID, e.g. `"src/auth.ts"`, `"guide.md::Setup"`, `"my-note"` |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"skills"` |\n| `kind` | string | No | Filter by relation kind. Omit for all relations |\n\n**Returns:** `[{ taskId, title, kind, status, priority, tags }]`\n\n**Use case:** When working on a file, call `find_linked_tasks({ targetId: "src/auth.ts", targetGraph: "code" })` to see all tasks related to that file.\n\n### add_task_attachment\n\nAttach a file to a task. The file is copied into the task\'s directory (`.tasks/{taskId}/`).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID to attach the file to |\n| `filePath` | string | Yes | Absolute path to the file on disk |\n\n**Returns:** `{ taskId, attachment: { filename, mimeType, size } }`\n\n### remove_task_attachment\n\nRemove an attachment from a task. Deletes the file from disk.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `taskId` | string | Yes | Task ID |\n| `filename` | string | Yes | Filename of the attachment to remove |\n\n**Returns:** `{ taskId, filename, deleted: true }`\n\n## Kanban board UI\n\nThe Tasks page provides a visual kanban board with these features:\n\n- **Column visibility** — toggle which status columns are shown via the column icon in the top bar; saved in localStorage\n- **Drag-and-drop** — drag task cards between columns to change status; drop-zone highlights on hover\n- **Inline task creation** — click "+" in a column header to quickly create a task in that status\n- **Filter bar** — search tasks by text, filter by priority or tag\n- **Due date indicators** — overdue tasks show a red badge, approaching deadlines (≤3 days) show yellow\n- **Estimate badges** — tasks with estimates show hours on the card\n- **Quick actions** — hover a card to see edit and delete buttons\n- **Scrollable columns** — columns scroll independently when content overflows\n\n## Tips\n\n- Use `move_task` instead of `update_task` for status changes — it explicitly handles `completedAt`\n- `get_task` returns the richest data — includes subtasks, blockers, and related tasks\n- `list_tasks` is sorted by priority then due date — critical overdue tasks appear first\n- Link tasks to code files they affect — makes it easy to find related tasks when working on code\n- Use `search_tasks` to find tasks by meaning, not just title keywords\n- `update_task` with `dueDate: null` or `estimate: null` clears those fields\n- `update_task` with `tags` replaces the entire array — include all tags you want to keep\n- Task-to-task `kind` values are a fixed enum (`subtask_of`, `blocks`, `related_to`), unlike knowledge relations which are free-form\n- Tasks support file attachments — attach screenshots, logs, or any file via `add_task_attachment`\n- Attachments are stored in `.tasks/{taskId}/` alongside the task\'s markdown file\n'},{id:`skill-tools`,title:`Skill Tools`,summary:`Create and manage reusable skills, recipes, and procedures with triggers and usage tracking.`,category:`guide`,relatedTools:[`create_skill`,`update_skill`,`delete_skill`,`get_skill`,`list_skills`,`search_skills`,`link_skill`,`create_skill_link`,`delete_skill_link`,`find_linked_skills`,`add_skill_attachment`,`remove_skill_attachment`,`recall_skills`,`bump_skill_usage`],content:'# Skill Tools\n\nThe skill tools provide a **recipe/procedure management** system within Graph Memory. Skills capture reusable knowledge — step-by-step procedures, patterns, and best practices — with triggers, usage tracking, and cross-graph links.\n\n## Why skills in Graph Memory?\n\nSkills here are tightly integrated with your project\'s knowledge graph:\n- Link a skill to the code files it applies to\n- Link a skill to documentation that describes the pattern\n- Link a skill to knowledge notes for context\n- Link a skill to tasks that use the procedure\n- Track dependencies and variants between skills\n\n## Tool overview\n\n| Tool | Purpose | Type |\n|------|---------|------|\n| `create_skill` | Create a skill with steps, triggers, and metadata | Mutation |\n| `update_skill` | Modify skill fields (partial update) | Mutation |\n| `delete_skill` | Remove a skill and all its edges | Mutation |\n| `get_skill` | Read a skill with all relations | Read |\n| `list_skills` | List skills with filters | Read |\n| `search_skills` | Semantic search across skills | Read |\n| `link_skill` | Create skill-to-skill relation | Mutation |\n| `create_skill_link` | Link skill to external graph node | Mutation |\n| `delete_skill_link` | Remove cross-graph link | Mutation |\n| `find_linked_skills` | Reverse lookup: find skills linked to an external node | Read |\n| `add_skill_attachment` | Attach a file to a skill | Mutation |\n| `remove_skill_attachment` | Remove an attachment from a skill | Mutation |\n| `recall_skills` | Recall relevant skills for a task context | Read |\n| `bump_skill_usage` | Increment usage counter + set lastUsedAt | Mutation |\n\n> **Mutation tools** are serialized through a queue to prevent concurrent graph modifications.\n\n## Skill properties\n\n| Property | Type | Values / Format | Notes |\n|----------|------|-----------------|-------|\n| `title` | string | Free text | Becomes slug ID |\n| `description` | string | Markdown | Full skill description |\n| `steps` | string[] | Ordered list | Step-by-step procedure |\n| `triggers` | string[] | Free-form | When to apply this skill |\n| `source` | enum | `user`, `learned` | How the skill was created |\n| `tags` | string[] | Free-form | For filtering |\n| `usageCount` | number | Auto-managed | Incremented by `bump_skill_usage` |\n| `lastUsedAt` | number | Unix timestamp (auto) | Set by `bump_skill_usage` |\n| `createdAt` | number | Unix timestamp (auto) | Set at creation |\n| `updatedAt` | number | Unix timestamp (auto) | Updated on every change |\n\n## Skill ID generation\n\nLike notes and tasks, skill IDs are slugified from the title:\n- "Add REST Endpoint" -> `add-rest-endpoint`\n- Duplicates get suffixes: `add-rest-endpoint::2`\n\n## Tool reference\n\n### create_skill\n\nCreate a new skill. Automatically embedded for semantic search.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `title` | string | Yes | -- | Short title, e.g. `"Add REST Endpoint"` |\n| `description` | string | Yes | -- | Full description (markdown) |\n| `steps` | string[] | No | `[]` | Ordered steps of the procedure |\n| `triggers` | string[] | No | `[]` | When this skill should be applied |\n| `source` | enum | No | `"user"` | `"user"`, `"learned"` |\n| `tags` | string[] | No | `[]` | Tags for filtering |\n\n**Returns:** `{ skillId }`\n\n### update_skill\n\nUpdate an existing skill. Only provided fields change. Re-embeds if title, description, or triggers change.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID to update |\n| `title` | string | No | New title |\n| `description` | string | No | New description |\n| `steps` | string[] | No | Replace steps array |\n| `triggers` | string[] | No | Replace triggers array |\n| `source` | enum | No | New source |\n| `tags` | string[] | No | Replace tags array (include all you want to keep) |\n\n**Returns:** `{ skillId, updated: true }`\n\n### delete_skill\n\nDelete a skill and all its edges (relations + cross-graph links). Orphaned proxy nodes cleaned up automatically. **Irreversible.**\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID to delete |\n\n**Returns:** `{ skillId, deleted: true }`\n\n### get_skill\n\nReturn full skill details including all relations. This is the most complete view of a skill.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID to retrieve |\n\n**Returns:**\n```\n{\n id, title, description, steps, triggers, source, tags,\n usageCount, lastUsedAt, createdAt, updatedAt,\n dependsOn: [{ id, title }],\n dependedBy: [{ id, title }],\n related: [{ id, title }],\n variants: [{ id, title }]\n}\n```\n\nThe `dependsOn`, `dependedBy`, `related`, and `variants` arrays are automatically populated from skill-to-skill edges.\n\n### list_skills\n\nList skills with optional filters. Sorted by usage count (most used first).\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `source` | enum | No | -- | Filter by source (`user`, `learned`) |\n| `tag` | string | No | -- | Filter by tag (exact match, case-insensitive) |\n| `filter` | string | No | -- | Substring match on title or ID |\n| `limit` | number | No | 50 | Maximum results |\n\n**Returns:** `[{ id, title, description, steps, triggers, source, tags, usageCount, lastUsedAt, createdAt, updatedAt }]`\n\n### search_skills\n\nSemantic search over the skill graph with BFS expansion.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | -- | Natural language search query |\n| `topK` | number | No | 5 | Seed nodes from vector search |\n| `bfsDepth` | number | No | 1 | Hops to follow relations (0 = no expansion) |\n| `maxResults` | number | No | 20 | Maximum results |\n| `minScore` | number | No | 0.5 | Minimum relevance score (0-1) |\n| `bfsDecay` | number | No | 0.8 | Score multiplier per hop |\n\n**Returns:** `[{ id, title, description, steps, triggers, source, tags, score }]`\n\n### recall_skills\n\nRecall relevant skills for a task context. Uses a lower default `minScore` (0.3) for higher recall.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | -- | Task context or description |\n| `topK` | number | No | 10 | Maximum results |\n| `minScore` | number | No | 0.3 | Minimum relevance score (0-1) |\n\n**Returns:** `[{ id, title, description, steps, triggers, source, tags, score, usageCount }]`\n\n### bump_skill_usage\n\nRecord that a skill was used. Increments `usageCount` and sets `lastUsedAt` to the current time.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID to bump |\n\n**Returns:** `{ skillId, usageCount, lastUsedAt }`\n\n### link_skill\n\nCreate a directed relation between two skills.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `fromId` | string | Yes | Source skill ID |\n| `toId` | string | Yes | Target skill ID |\n| `kind` | enum | Yes | `"depends_on"`, `"related_to"`, `"variant_of"` |\n\n**Returns:** `{ fromId, toId, kind, created: true }`\n\n**Semantics:**\n- `depends_on` -- `fromId` depends on `toId` (prerequisite)\n- `related_to` -- free association between skills\n- `variant_of` -- `fromId` is a variation of `toId`\n\n### create_skill_link\n\nLink a skill to a node in another graph (docs, code, files, knowledge, or tasks).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Source skill ID |\n| `targetId` | string | Yes | Target node ID in the external graph |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"tasks"` |\n| `kind` | string | Yes | Relation type: `"applies_to"`, `"documented_in"`, `"used_by"`, etc. |\n\n**Returns:** `{ skillId, targetId, targetGraph, kind, created: true }`\n\n**Examples:**\n```\ncreate_skill_link({ skillId: "add-rest-endpoint", targetId: "src/routes/index.ts", targetGraph: "code", kind: "applies_to" })\ncreate_skill_link({ skillId: "add-rest-endpoint", targetId: "guide.md::REST API", targetGraph: "docs", kind: "documented_in" })\ncreate_skill_link({ skillId: "add-rest-endpoint", targetId: "implement-api", targetGraph: "tasks", kind: "used_by" })\n```\n\n### delete_skill_link\n\nRemove a cross-graph link from a skill. Orphaned proxy nodes cleaned up automatically.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Source skill ID |\n| `targetId` | string | Yes | Target node ID in the external graph |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"tasks"` |\n\n**Returns:** `{ skillId, targetId, targetGraph, deleted: true }`\n\n### find_linked_skills\n\nReverse lookup: given a node in an external graph, find all skills that link to it.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `targetId` | string | Yes | Target node ID, e.g. `"src/auth.ts"`, `"guide.md::Setup"`, `"my-task"` |\n| `targetGraph` | enum | Yes | `"docs"`, `"code"`, `"files"`, `"knowledge"`, `"tasks"` |\n| `kind` | string | No | Filter by relation kind. Omit for all relations |\n\n**Returns:** `[{ skillId, title, kind, source, tags }]`\n\n**Use case:** When working on a file, call `find_linked_skills({ targetId: "src/routes/index.ts", targetGraph: "code" })` to see all skills related to that file.\n\n### add_skill_attachment\n\nAttach a file to a skill. The file is copied into the skill\'s directory (`.skills/{skillId}/`).\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID to attach the file to |\n| `filePath` | string | Yes | Absolute path to the file on disk |\n\n**Returns:** `{ skillId, attachment: { filename, mimeType, size } }`\n\n### remove_skill_attachment\n\nRemove an attachment from a skill. Deletes the file from disk.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `skillId` | string | Yes | Skill ID |\n| `filename` | string | Yes | Filename of the attachment to remove |\n\n**Returns:** `{ skillId, filename, deleted: true }`\n\n## Tips\n\n- Use `recall_skills` when starting a task to find relevant procedures -- it uses a lower threshold for better recall\n- Call `bump_skill_usage` after applying a skill to track which skills are most useful\n- Skills with `source: "learned"` are typically created by AI agents that discover patterns\n- Skills with `source: "user"` are created by humans documenting their procedures\n- Link skills to code files they apply to -- makes it easy to find relevant skills when working on code\n- Use `search_skills` to find skills by meaning, not just title keywords\n- `update_skill` with `tags` replaces the entire array -- include all tags you want to keep\n- Skill-to-skill `kind` values are a fixed enum (`depends_on`, `related_to`, `variant_of`)\n- Skills support file attachments -- attach templates, examples, or reference files via `add_skill_attachment`\n- Attachments are stored in `.skills/{skillId}/` alongside the skill\'s markdown file\n'},{id:`files-tools`,title:`File Index Tools`,summary:`Browse and search metadata for every file and directory in your project.`,category:`guide`,relatedTools:[`list_all_files`,`search_all_files`,`get_file_info`],content:'# File Index Tools\n\nThe file index tools provide access to metadata about **every file and directory** in your project. Unlike docs and code tools which only index pattern-matched files, the file index covers the entire project tree.\n\n## Tool overview\n\n| Tool | Purpose | When to use |\n|------|---------|-------------|\n| `list_all_files` | List files/directories with filters | Browse project structure, filter by extension/language |\n| `search_all_files` | Semantic search by file path | Find files by what they might contain |\n| `get_file_info` | Get metadata for a specific path | Check size, language, modification date |\n\n## What gets indexed\n\nFor every file in the project directory:\n- **Path** (relative to project root)\n- **File name** and **extension**\n- **Size** in bytes\n- **Language** (detected from extension: `.ts` → TypeScript, `.md` → Markdown, `.json` → JSON, etc.)\n- **MIME type** (e.g., `application/json`, `text/markdown`, `image/png`)\n- **Modification time** (`mtime`)\n\nFor directories:\n- **Aggregate size** (sum of all contained files)\n- **File count** (total files in subtree)\n- Directory → child edges (`contains`)\n\n## Browsing vs searching\n\n### Directory browsing\n\n`list_all_files` with the `directory` parameter returns **immediate children** (files + subdirectories) of that directory. This is how you browse the project tree:\n\n```\nlist_all_files({ directory: "." }) → root contents\nlist_all_files({ directory: "src" }) → src/ contents\nlist_all_files({ directory: "src/api" }) → src/api/ contents\n```\n\nWithout `directory`, it returns all files matching filters (flat list, no directories).\n\n### File search\n\n`search_all_files` embeds file paths for semantic search. You can search by:\n- Partial paths: `"config"` finds configuration files\n- Concepts: `"authentication"` finds files in auth-related directories\n- File types: `"typescript source"` finds `.ts` files\n\nThe `minScore` default is **0.3** (lower than node search) because file path embeddings are less semantically rich than content embeddings.\n\n## Tool reference\n\n### list_all_files\n\nList project files and directories with optional filters.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `directory` | string | No | — | List immediate children of this directory (e.g. `"."`, `"src/lib"`). Without this, returns all files matching filters |\n| `extension` | string | No | — | Filter by extension (e.g. `".ts"`, `".md"`, `".png"`) |\n| `language` | string | No | — | Filter by detected language (e.g. `"typescript"`, `"markdown"`, `"json"`) |\n| `filter` | string | No | — | Substring match on file path (case-insensitive) |\n| `limit` | number | No | 50 | Maximum results |\n\n**Returns:** `[{ filePath, kind, fileName, extension, language, mimeType, size, fileCount }]`\n\n- `kind` is `"file"` or `"directory"`\n- `fileCount` is present for directories (number of files in subtree)\n- `language` and `mimeType` are present for files\n\n**Behavior differences:**\n- With `directory` set: returns both files and subdirectories (immediate children only)\n- Without `directory`: returns only files (no directories), across the entire project\n\n### search_all_files\n\nSemantic search over file nodes by path embedding. Searches files only (not directories).\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| `query` | string | Yes | — | Search query (natural language or path fragment) |\n| `topK` | number | No | 10 | Maximum results |\n| `minScore` | number | No | 0.3 | Minimum cosine similarity score (0–1) |\n\n**Returns:** `[{ filePath, fileName, extension, language, size, score }]`\n\n### get_file_info\n\nGet full metadata for a specific file or directory. Use `"."` for the project root.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `filePath` | string | Yes | Relative file or directory path (e.g. `"src/lib/config.ts"`, `"src/lib"`, `"."`) |\n\n**Returns for files:**\n```\n{ filePath, kind: "file", fileName, directory, extension, language, mimeType, size, mtime }\n```\n\n**Returns for directories:**\n```\n{ filePath, kind: "directory", fileName, directory, fileCount, size }\n```\n\n- `size` for directories is the total size of all direct children\n- `fileCount` for directories is the total number of files in the subtree\n- `mtime` is the last modification timestamp (files only)\n\n## Cross-graph links\n\nFiles can be linked from notes and tasks:\n\n```\n// From a knowledge note\ncreate_relation({ fromId: "config-format", toId: "src/config.ts", kind: "documents", targetGraph: "files" })\n\n// From a task\ncreate_task_link({ taskId: "refactor-config", targetId: "src/config.ts", targetGraph: "files", kind: "affects" })\n```\n\nUse `find_linked_notes` or `find_linked_tasks` with `targetGraph: "files"` to discover what knowledge or tasks reference a specific file:\n\n```\nfind_linked_notes({ targetId: "src/auth.ts", targetGraph: "files" })\nfind_linked_tasks({ targetId: "src/auth.ts", targetGraph: "files" })\n```\n\n## Tips\n\n- Use `list_all_files` with `directory` to browse top-down through the project tree\n- Use `list_all_files` with `extension: ".ts"` or `language: "typescript"` to find all files of a type\n- `get_file_info` on `"."` gives project-level stats (total size, file count)\n- `search_all_files` works better with path-like queries than abstract concepts\n- File index is always active — no `graphs.docs.include` or `graphs.code.include` configuration needed\n- The `language` filter in `list_all_files` uses detected language names like `"typescript"`, `"javascript"`, `"markdown"`, `"json"`, `"yaml"`, `"css"`, `"html"`, `"python"`, etc.\n'},{id:`cross-references`,title:`Cross References Tool`,summary:`Bridge code definitions and documentation examples for any symbol.`,category:`guide`,relatedTools:[`cross_references`],content:`# Cross References Tool
1578
1521
 
1579
1522
  \`cross_references\` is the only tool that works across **both** the CodeGraph and DocGraph simultaneously. It's the most comprehensive way to understand a symbol — combining source code definitions, documentation context, and usage examples.
1580
1523
 
@@ -1587,7 +1530,7 @@ Use \`cross_references\` when you want to fully understand a symbol:
1587
1530
 
1588
1531
  ## Requirements
1589
1532
 
1590
- This tool is **only available** when both \`docsPattern\` and \`codePattern\` are configured in the project. It needs both graphs to bridge definitions and documentation.
1533
+ This tool is **only available** when both \`graphs.docs.include\` and \`graphs.code.include\` are configured in the project. It needs both graphs to bridge definitions and documentation.
1591
1534
 
1592
1535
  ## Tool reference
1593
1536
 
@@ -1696,7 +1639,7 @@ Calling \`cross_references({ symbol: "createUser" })\` returns:
1696
1639
  ## Tips
1697
1640
 
1698
1641
  - Use exact symbol names (case-sensitive match)
1699
- - If you get no results, check that both \`docsPattern\` and \`codePattern\` are configured
1642
+ - If you get no results, check that both \`graphs.docs.include\` and \`graphs.code.include\` are configured
1700
1643
  - Empty \`definitions\` + non-empty \`examples\` means the symbol is documented but not in your indexed code
1701
1644
  - Empty \`examples\` + non-empty \`definitions\` means the symbol exists in code but isn't documented with examples
1702
1645
  - Combine with \`get_symbol\` to read the full implementation body (which \`cross_references\` doesn't include)
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>ui</title>
8
- <script type="module" crossorigin src="/assets/index-D6oxrVF7.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-0hRezICt.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-kKd4mVrh.css">
10
10
  </head>
11
11
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphmemory/server",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "MCP server for semantic graph memory from markdown files",
5
5
  "main": "dist/cli/index.js",
6
6
  "bin": {