@gmickel/gno 0.25.0 → 0.26.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.
- package/README.md +5 -3
- package/assets/skill/SKILL.md +75 -1
- package/assets/skill/cli-reference.md +8 -6
- package/package.json +1 -1
- package/src/cli/commands/skill/install.ts +2 -2
- package/src/cli/commands/skill/paths.ts +26 -4
- package/src/cli/commands/skill/uninstall.ts +2 -2
- package/src/cli/program.ts +18 -12
- package/src/mcp/tools/index.ts +434 -110
package/README.md
CHANGED
|
@@ -194,9 +194,11 @@ Check status: `gno mcp status`
|
|
|
194
194
|
Skills integrate via CLI with no MCP overhead:
|
|
195
195
|
|
|
196
196
|
```bash
|
|
197
|
-
gno skill install --scope user
|
|
198
|
-
gno skill install --target codex
|
|
199
|
-
gno skill install --target
|
|
197
|
+
gno skill install --scope user # User-wide
|
|
198
|
+
gno skill install --target codex # Codex
|
|
199
|
+
gno skill install --target opencode # OpenCode
|
|
200
|
+
gno skill install --target openclaw # OpenClaw
|
|
201
|
+
gno skill install --target all # All targets
|
|
200
202
|
```
|
|
201
203
|
|
|
202
204
|
> **Full setup guide**: [MCP Integration](https://gno.sh/docs/MCP/) · [CLI Reference](https://gno.sh/docs/CLI/)
|
package/assets/skill/SKILL.md
CHANGED
|
@@ -61,18 +61,92 @@ gno search "your query" # BM25 keyword search
|
|
|
61
61
|
|
|
62
62
|
**Retry strategy**: Use default first. If no results: rephrase query, then try `--thorough`.
|
|
63
63
|
|
|
64
|
-
## Common Flags
|
|
64
|
+
## Common Flags (search/vsearch/query/ask)
|
|
65
65
|
|
|
66
66
|
```
|
|
67
67
|
-n <num> Max results (default: 5)
|
|
68
68
|
-c, --collection Filter to collection
|
|
69
69
|
--tags-any <t1,t2> Has ANY of these tags
|
|
70
70
|
--tags-all <t1,t2> Has ALL of these tags
|
|
71
|
+
--since <date> Modified after date (ISO: 2026-03-01)
|
|
72
|
+
--until <date> Modified before date (ISO: 2026-03-31)
|
|
73
|
+
--exclude <terms> Exclude docs containing any term (comma-separated)
|
|
74
|
+
--intent <text> Disambiguate ambiguous queries (e.g. "python" = language not snake)
|
|
71
75
|
--json JSON output
|
|
72
76
|
--files URI list output
|
|
73
77
|
--line-numbers Include line numbers
|
|
74
78
|
```
|
|
75
79
|
|
|
80
|
+
## Advanced: Structured Query Modes (query/ask only)
|
|
81
|
+
|
|
82
|
+
Use `--query-mode` to combine multiple retrieval strategies in one query (repeatable):
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Combine keyword + hypothetical document
|
|
86
|
+
gno query "API rate limiting" \
|
|
87
|
+
--query-mode "term:rate limit" \
|
|
88
|
+
--query-mode "hyde:how to implement request throttling"
|
|
89
|
+
|
|
90
|
+
# Add intent steering
|
|
91
|
+
gno query "python" \
|
|
92
|
+
--query-mode "term:python" \
|
|
93
|
+
--query-mode "intent:programming language"
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Modes: `term:<text>` (keyword), `intent:<text>` (disambiguation), `hyde:<text>` (hypothetical doc for semantic matching). Max one hyde per query.
|
|
97
|
+
|
|
98
|
+
## Document Retrieval
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Full document by URI
|
|
102
|
+
gno get gno://work/readme.md
|
|
103
|
+
|
|
104
|
+
# By document ID
|
|
105
|
+
gno get "#a1b2c3d4"
|
|
106
|
+
|
|
107
|
+
# Specific line range: --from <start> -l <count>
|
|
108
|
+
gno get gno://work/report.md --from 100 -l 20
|
|
109
|
+
|
|
110
|
+
# With line numbers
|
|
111
|
+
gno get gno://work/report.md --line-numbers
|
|
112
|
+
|
|
113
|
+
# Multiple documents
|
|
114
|
+
gno multi-get gno://work/doc1.md gno://work/doc2.md
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Search Then Get (common pipeline)
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Search, get full content of top result
|
|
121
|
+
gno query "auth" --json | jq -r '.results[0].uri' | xargs gno get
|
|
122
|
+
|
|
123
|
+
# Get all results
|
|
124
|
+
gno search "error handling" --json | jq -r '.results[].uri' | xargs gno multi-get
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Document Links & Similarity
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# Outgoing links from a document
|
|
131
|
+
gno links gno://notes/readme.md
|
|
132
|
+
|
|
133
|
+
# Find documents linking TO a document (backlinks)
|
|
134
|
+
gno backlinks gno://notes/api-design.md
|
|
135
|
+
|
|
136
|
+
# Find semantically similar documents
|
|
137
|
+
gno similar gno://notes/auth.md
|
|
138
|
+
|
|
139
|
+
# Similar across all collections (not just same collection)
|
|
140
|
+
gno similar gno://notes/auth.md --cross-collection
|
|
141
|
+
|
|
142
|
+
# Stricter threshold (default: 0.7)
|
|
143
|
+
gno similar gno://notes/auth.md --threshold 0.85
|
|
144
|
+
|
|
145
|
+
# Knowledge graph
|
|
146
|
+
gno graph --json
|
|
147
|
+
gno graph -c notes --similar # Include similarity edges
|
|
148
|
+
```
|
|
149
|
+
|
|
76
150
|
## Global Flags
|
|
77
151
|
|
|
78
152
|
```
|
|
@@ -488,18 +488,20 @@ Install GNO skill for AI coding assistants.
|
|
|
488
488
|
gno skill install [options]
|
|
489
489
|
```
|
|
490
490
|
|
|
491
|
-
| Option | Default | Description
|
|
492
|
-
| -------------- | ------- |
|
|
493
|
-
| `-t, --target` | claude | Target: `claude`, `codex`, `
|
|
494
|
-
| `-s, --scope` | user | Scope: `user`, `project`
|
|
495
|
-
| `-f, --force` | false | Overwrite existing
|
|
496
|
-
| `--dry-run` | false | Preview changes
|
|
491
|
+
| Option | Default | Description |
|
|
492
|
+
| -------------- | ------- | -------------------------------------------------------- |
|
|
493
|
+
| `-t, --target` | claude | Target: `claude`, `codex`, `opencode`, `openclaw`, `all` |
|
|
494
|
+
| `-s, --scope` | user | Scope: `user`, `project` |
|
|
495
|
+
| `-f, --force` | false | Overwrite existing |
|
|
496
|
+
| `--dry-run` | false | Preview changes |
|
|
497
497
|
|
|
498
498
|
Examples:
|
|
499
499
|
|
|
500
500
|
```bash
|
|
501
501
|
gno skill install --target claude --scope project
|
|
502
502
|
gno skill install --target codex --scope user
|
|
503
|
+
gno skill install --target openclaw --scope user
|
|
504
|
+
gno skill install --target all --force # Install to all targets
|
|
503
505
|
```
|
|
504
506
|
|
|
505
507
|
### gno skill uninstall
|
package/package.json
CHANGED
|
@@ -13,6 +13,7 @@ import { CliError } from "../../errors.js";
|
|
|
13
13
|
import { getGlobals } from "../../program.js";
|
|
14
14
|
import {
|
|
15
15
|
resolveSkillPaths,
|
|
16
|
+
SKILL_TARGETS,
|
|
16
17
|
type SkillScope,
|
|
17
18
|
type SkillTarget,
|
|
18
19
|
validatePathForDeletion,
|
|
@@ -171,8 +172,7 @@ export async function installSkill(opts: InstallOptions = {}): Promise<void> {
|
|
|
171
172
|
const yes = opts.yes ?? globals.yes;
|
|
172
173
|
const quiet = opts.quiet ?? globals.quiet;
|
|
173
174
|
|
|
174
|
-
const targets: SkillTarget[] =
|
|
175
|
-
target === "all" ? ["claude", "codex"] : [target];
|
|
175
|
+
const targets: SkillTarget[] = target === "all" ? SKILL_TARGETS : [target];
|
|
176
176
|
|
|
177
177
|
const results: InstallResult[] = [];
|
|
178
178
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Path resolution for skill installation.
|
|
3
|
-
* Supports Claude Code and
|
|
4
|
-
* Note: OpenCode and Amp use the same .claude path as Claude Code.
|
|
3
|
+
* Supports Claude Code, Codex, OpenCode, and OpenClaw targets with project/user scopes.
|
|
5
4
|
*
|
|
6
5
|
* @module src/cli/commands/skill/paths
|
|
7
6
|
*/
|
|
@@ -22,14 +21,25 @@ export const ENV_CLAUDE_SKILLS_DIR = "CLAUDE_SKILLS_DIR";
|
|
|
22
21
|
/** Override Codex skills directory */
|
|
23
22
|
export const ENV_CODEX_SKILLS_DIR = "CODEX_SKILLS_DIR";
|
|
24
23
|
|
|
24
|
+
/** Override OpenCode skills directory */
|
|
25
|
+
export const ENV_OPENCODE_SKILLS_DIR = "OPENCODE_SKILLS_DIR";
|
|
26
|
+
|
|
27
|
+
/** Override OpenClaw skills directory */
|
|
28
|
+
export const ENV_OPENCLAW_SKILLS_DIR = "OPENCLAW_SKILLS_DIR";
|
|
29
|
+
|
|
25
30
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
26
31
|
// Types
|
|
27
32
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
28
33
|
|
|
29
34
|
export type SkillScope = "project" | "user";
|
|
30
|
-
export type SkillTarget = "claude" | "codex";
|
|
35
|
+
export type SkillTarget = "claude" | "codex" | "opencode" | "openclaw";
|
|
31
36
|
|
|
32
|
-
export const SKILL_TARGETS: SkillTarget[] = [
|
|
37
|
+
export const SKILL_TARGETS: SkillTarget[] = [
|
|
38
|
+
"claude",
|
|
39
|
+
"codex",
|
|
40
|
+
"opencode",
|
|
41
|
+
"openclaw",
|
|
42
|
+
];
|
|
33
43
|
|
|
34
44
|
export interface SkillPathOptions {
|
|
35
45
|
scope: SkillScope;
|
|
@@ -77,6 +87,18 @@ const TARGET_CONFIGS: Record<SkillTarget, TargetPathConfig> = {
|
|
|
77
87
|
skillsSubdir: "skills",
|
|
78
88
|
envVar: ENV_CODEX_SKILLS_DIR,
|
|
79
89
|
},
|
|
90
|
+
opencode: {
|
|
91
|
+
projectBase: ".opencode",
|
|
92
|
+
userBase: ".config/opencode",
|
|
93
|
+
skillsSubdir: "skills",
|
|
94
|
+
envVar: ENV_OPENCODE_SKILLS_DIR,
|
|
95
|
+
},
|
|
96
|
+
openclaw: {
|
|
97
|
+
projectBase: ".openclaw",
|
|
98
|
+
userBase: ".openclaw",
|
|
99
|
+
skillsSubdir: "skills",
|
|
100
|
+
envVar: ENV_OPENCLAW_SKILLS_DIR,
|
|
101
|
+
},
|
|
80
102
|
};
|
|
81
103
|
|
|
82
104
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -12,6 +12,7 @@ import { CliError } from "../../errors.js";
|
|
|
12
12
|
import { getGlobals } from "../../program.js";
|
|
13
13
|
import {
|
|
14
14
|
resolveSkillPaths,
|
|
15
|
+
SKILL_TARGETS,
|
|
15
16
|
type SkillScope,
|
|
16
17
|
type SkillTarget,
|
|
17
18
|
validatePathForDeletion,
|
|
@@ -100,8 +101,7 @@ export async function uninstallSkill(
|
|
|
100
101
|
const json = opts.json ?? globals.json;
|
|
101
102
|
const quiet = opts.quiet ?? globals.quiet;
|
|
102
103
|
|
|
103
|
-
const targets: SkillTarget[] =
|
|
104
|
-
target === "all" ? ["claude", "codex"] : [target];
|
|
104
|
+
const targets: SkillTarget[] = target === "all" ? SKILL_TARGETS : [target];
|
|
105
105
|
|
|
106
106
|
const results: UninstallResult[] = [];
|
|
107
107
|
const notFound: string[] = [];
|
package/src/cli/program.ts
CHANGED
|
@@ -1578,7 +1578,7 @@ function wireSkillCommands(program: Command): void {
|
|
|
1578
1578
|
)
|
|
1579
1579
|
.option(
|
|
1580
1580
|
"-t, --target <target>",
|
|
1581
|
-
"target agent (claude, codex, all)",
|
|
1581
|
+
"target agent (claude, codex, opencode, openclaw, all)",
|
|
1582
1582
|
"claude"
|
|
1583
1583
|
)
|
|
1584
1584
|
.option("-f, --force", "overwrite existing installation")
|
|
@@ -1595,17 +1595,19 @@ function wireSkillCommands(program: Command): void {
|
|
|
1595
1595
|
);
|
|
1596
1596
|
}
|
|
1597
1597
|
// Validate target
|
|
1598
|
-
if (
|
|
1598
|
+
if (
|
|
1599
|
+
!["claude", "codex", "opencode", "openclaw", "all"].includes(target)
|
|
1600
|
+
) {
|
|
1599
1601
|
throw new CliError(
|
|
1600
1602
|
"VALIDATION",
|
|
1601
|
-
`Invalid target: ${target}. Must be 'claude', 'codex', or 'all'.`
|
|
1603
|
+
`Invalid target: ${target}. Must be 'claude', 'codex', 'opencode', 'openclaw', or 'all'.`
|
|
1602
1604
|
);
|
|
1603
1605
|
}
|
|
1604
1606
|
|
|
1605
1607
|
const { installSkill } = await import("./commands/skill/install.js");
|
|
1606
1608
|
await installSkill({
|
|
1607
1609
|
scope: scope as "project" | "user",
|
|
1608
|
-
target: target as "claude" | "codex" | "all",
|
|
1610
|
+
target: target as "claude" | "codex" | "opencode" | "openclaw" | "all",
|
|
1609
1611
|
force: Boolean(cmdOpts.force),
|
|
1610
1612
|
json: Boolean(cmdOpts.json),
|
|
1611
1613
|
});
|
|
@@ -1621,7 +1623,7 @@ function wireSkillCommands(program: Command): void {
|
|
|
1621
1623
|
)
|
|
1622
1624
|
.option(
|
|
1623
1625
|
"-t, --target <target>",
|
|
1624
|
-
"target agent (claude, codex, all)",
|
|
1626
|
+
"target agent (claude, codex, opencode, openclaw, all)",
|
|
1625
1627
|
"claude"
|
|
1626
1628
|
)
|
|
1627
1629
|
.option("--json", "JSON output")
|
|
@@ -1637,17 +1639,19 @@ function wireSkillCommands(program: Command): void {
|
|
|
1637
1639
|
);
|
|
1638
1640
|
}
|
|
1639
1641
|
// Validate target
|
|
1640
|
-
if (
|
|
1642
|
+
if (
|
|
1643
|
+
!["claude", "codex", "opencode", "openclaw", "all"].includes(target)
|
|
1644
|
+
) {
|
|
1641
1645
|
throw new CliError(
|
|
1642
1646
|
"VALIDATION",
|
|
1643
|
-
`Invalid target: ${target}. Must be 'claude', 'codex', or 'all'.`
|
|
1647
|
+
`Invalid target: ${target}. Must be 'claude', 'codex', 'opencode', 'openclaw', or 'all'.`
|
|
1644
1648
|
);
|
|
1645
1649
|
}
|
|
1646
1650
|
|
|
1647
1651
|
const { uninstallSkill } = await import("./commands/skill/uninstall.js");
|
|
1648
1652
|
await uninstallSkill({
|
|
1649
1653
|
scope: scope as "project" | "user",
|
|
1650
|
-
target: target as "claude" | "codex" | "all",
|
|
1654
|
+
target: target as "claude" | "codex" | "opencode" | "openclaw" | "all",
|
|
1651
1655
|
json: Boolean(cmdOpts.json),
|
|
1652
1656
|
});
|
|
1653
1657
|
});
|
|
@@ -1675,7 +1679,7 @@ function wireSkillCommands(program: Command): void {
|
|
|
1675
1679
|
)
|
|
1676
1680
|
.option(
|
|
1677
1681
|
"-t, --target <target>",
|
|
1678
|
-
"filter by target (claude, codex, all)",
|
|
1682
|
+
"filter by target (claude, codex, opencode, openclaw, all)",
|
|
1679
1683
|
"all"
|
|
1680
1684
|
)
|
|
1681
1685
|
.option("--json", "JSON output")
|
|
@@ -1691,17 +1695,19 @@ function wireSkillCommands(program: Command): void {
|
|
|
1691
1695
|
);
|
|
1692
1696
|
}
|
|
1693
1697
|
// Validate target
|
|
1694
|
-
if (
|
|
1698
|
+
if (
|
|
1699
|
+
!["claude", "codex", "opencode", "openclaw", "all"].includes(target)
|
|
1700
|
+
) {
|
|
1695
1701
|
throw new CliError(
|
|
1696
1702
|
"VALIDATION",
|
|
1697
|
-
`Invalid target: ${target}. Must be 'claude', 'codex', or 'all'.`
|
|
1703
|
+
`Invalid target: ${target}. Must be 'claude', 'codex', 'opencode', 'openclaw', or 'all'.`
|
|
1698
1704
|
);
|
|
1699
1705
|
}
|
|
1700
1706
|
|
|
1701
1707
|
const { showPaths } = await import("./commands/skill/paths-cmd.js");
|
|
1702
1708
|
await showPaths({
|
|
1703
1709
|
scope: scope as "project" | "user" | "all",
|
|
1704
|
-
target: target as "claude" | "codex" | "all",
|
|
1710
|
+
target: target as "claude" | "codex" | "opencode" | "openclaw" | "all",
|
|
1705
1711
|
json: Boolean(cmdOpts.json),
|
|
1706
1712
|
});
|
|
1707
1713
|
});
|
package/src/mcp/tools/index.ts
CHANGED
|
@@ -51,92 +51,284 @@ export function normalizeTagFilters(tags?: string[]): string[] | undefined {
|
|
|
51
51
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
52
52
|
|
|
53
53
|
const searchInputSchema = z.object({
|
|
54
|
-
query: z
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
54
|
+
query: z
|
|
55
|
+
.string()
|
|
56
|
+
.min(1, "Query cannot be empty")
|
|
57
|
+
.describe("Search query text"),
|
|
58
|
+
collection: z
|
|
59
|
+
.string()
|
|
60
|
+
.optional()
|
|
61
|
+
.describe("Filter to a single collection name"),
|
|
62
|
+
limit: z
|
|
63
|
+
.number()
|
|
64
|
+
.int()
|
|
65
|
+
.min(1)
|
|
66
|
+
.max(100)
|
|
67
|
+
.default(5)
|
|
68
|
+
.describe("Max results to return"),
|
|
69
|
+
minScore: z
|
|
70
|
+
.number()
|
|
71
|
+
.min(0)
|
|
72
|
+
.max(1)
|
|
73
|
+
.optional()
|
|
74
|
+
.describe("Minimum relevance score (0-1). Omit to return all matches"),
|
|
75
|
+
lang: z
|
|
76
|
+
.string()
|
|
77
|
+
.optional()
|
|
78
|
+
.describe(
|
|
79
|
+
"BCP-47 language hint for tokenization (e.g. 'en', 'de'). Auto-detected if omitted"
|
|
80
|
+
),
|
|
81
|
+
intent: z
|
|
82
|
+
.string()
|
|
83
|
+
.optional()
|
|
84
|
+
.describe(
|
|
85
|
+
"Disambiguating context for ambiguous queries (e.g. 'programming language' when query is 'python')"
|
|
86
|
+
),
|
|
87
|
+
exclude: z
|
|
88
|
+
.array(z.string())
|
|
89
|
+
.optional()
|
|
90
|
+
.describe("Exclude documents containing any of these terms"),
|
|
91
|
+
since: z
|
|
92
|
+
.string()
|
|
93
|
+
.optional()
|
|
94
|
+
.describe(
|
|
95
|
+
"Only docs modified after this date (ISO format: 2026-03-01 or 2026-03-01T00:00:00)"
|
|
96
|
+
),
|
|
97
|
+
until: z
|
|
98
|
+
.string()
|
|
99
|
+
.optional()
|
|
100
|
+
.describe("Only docs modified before this date (ISO format)"),
|
|
101
|
+
categories: z
|
|
102
|
+
.array(z.string())
|
|
103
|
+
.optional()
|
|
104
|
+
.describe("Require category match (from document frontmatter)"),
|
|
105
|
+
author: z
|
|
106
|
+
.string()
|
|
107
|
+
.optional()
|
|
108
|
+
.describe("Filter by author (case-insensitive substring match)"),
|
|
109
|
+
tagsAll: z
|
|
110
|
+
.array(z.string())
|
|
111
|
+
.optional()
|
|
112
|
+
.describe("Require ALL of these tags (AND filter)"),
|
|
113
|
+
tagsAny: z
|
|
114
|
+
.array(z.string())
|
|
115
|
+
.optional()
|
|
116
|
+
.describe("Require ANY of these tags (OR filter)"),
|
|
67
117
|
});
|
|
68
118
|
|
|
69
119
|
const captureInputSchema = z.object({
|
|
70
|
-
collection: z
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
120
|
+
collection: z
|
|
121
|
+
.string()
|
|
122
|
+
.min(1, "Collection cannot be empty")
|
|
123
|
+
.describe("Target collection name (must already exist)"),
|
|
124
|
+
content: z.string().describe("Document content (markdown or plain text)"),
|
|
125
|
+
title: z
|
|
126
|
+
.string()
|
|
127
|
+
.optional()
|
|
128
|
+
.describe("Document title. Auto-derived from content if omitted"),
|
|
129
|
+
path: z
|
|
130
|
+
.string()
|
|
131
|
+
.optional()
|
|
132
|
+
.describe(
|
|
133
|
+
"Relative path within collection (e.g. 'notes/meeting.md'). Auto-generated from title if omitted"
|
|
134
|
+
),
|
|
135
|
+
overwrite: z
|
|
136
|
+
.boolean()
|
|
137
|
+
.default(false)
|
|
138
|
+
.describe("Overwrite if file already exists at path"),
|
|
139
|
+
tags: z
|
|
140
|
+
.array(z.string())
|
|
141
|
+
.optional()
|
|
142
|
+
.describe("Tags to apply to the new document"),
|
|
76
143
|
});
|
|
77
144
|
|
|
78
145
|
const addCollectionInputSchema = z.object({
|
|
79
|
-
path: z
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
146
|
+
path: z
|
|
147
|
+
.string()
|
|
148
|
+
.min(1, "Path cannot be empty")
|
|
149
|
+
.describe("Absolute path to the directory to index"),
|
|
150
|
+
name: z
|
|
151
|
+
.string()
|
|
152
|
+
.optional()
|
|
153
|
+
.describe("Collection name. Auto-derived from directory name if omitted"),
|
|
154
|
+
pattern: z
|
|
155
|
+
.string()
|
|
156
|
+
.optional()
|
|
157
|
+
.describe(
|
|
158
|
+
"Glob pattern for files to include (default: '**/*'). E.g. '**/*.md' for markdown only"
|
|
159
|
+
),
|
|
160
|
+
include: z
|
|
161
|
+
.array(z.string())
|
|
162
|
+
.optional()
|
|
163
|
+
.describe("Extension allowlist (e.g. ['.md', '.pdf', '.docx'])"),
|
|
164
|
+
exclude: z
|
|
165
|
+
.array(z.string())
|
|
166
|
+
.optional()
|
|
167
|
+
.describe("Glob patterns to exclude (default: ['.git', 'node_modules'])"),
|
|
168
|
+
gitPull: z
|
|
169
|
+
.boolean()
|
|
170
|
+
.default(false)
|
|
171
|
+
.describe("Run git pull before indexing (if collection is a git repo)"),
|
|
85
172
|
});
|
|
86
173
|
|
|
87
174
|
const syncInputSchema = z.object({
|
|
88
|
-
collection: z
|
|
89
|
-
|
|
90
|
-
|
|
175
|
+
collection: z
|
|
176
|
+
.string()
|
|
177
|
+
.optional()
|
|
178
|
+
.describe("Collection name to sync. Omit to sync all collections"),
|
|
179
|
+
gitPull: z.boolean().default(false).describe("Run git pull before syncing"),
|
|
180
|
+
runUpdateCmd: z
|
|
181
|
+
.boolean()
|
|
182
|
+
.default(false)
|
|
183
|
+
.describe("Run the collection's configured update command before syncing"),
|
|
91
184
|
});
|
|
92
185
|
|
|
93
186
|
const embedInputSchema = z.object({});
|
|
94
187
|
|
|
95
188
|
const indexInputSchema = z.object({
|
|
96
|
-
collection: z
|
|
97
|
-
|
|
189
|
+
collection: z
|
|
190
|
+
.string()
|
|
191
|
+
.optional()
|
|
192
|
+
.describe("Collection name to index. Omit to index all collections"),
|
|
193
|
+
gitPull: z.boolean().default(false).describe("Run git pull before indexing"),
|
|
98
194
|
});
|
|
99
195
|
|
|
100
196
|
const removeCollectionInputSchema = z.object({
|
|
101
|
-
collection: z
|
|
197
|
+
collection: z
|
|
198
|
+
.string()
|
|
199
|
+
.min(1, "Collection cannot be empty")
|
|
200
|
+
.describe("Collection name to remove"),
|
|
102
201
|
});
|
|
103
202
|
|
|
104
203
|
const vsearchInputSchema = z.object({
|
|
105
|
-
query: z
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
204
|
+
query: z
|
|
205
|
+
.string()
|
|
206
|
+
.min(1, "Query cannot be empty")
|
|
207
|
+
.describe("Search query text (matched by semantic meaning, not keywords)"),
|
|
208
|
+
collection: z
|
|
209
|
+
.string()
|
|
210
|
+
.optional()
|
|
211
|
+
.describe("Filter to a single collection name"),
|
|
212
|
+
limit: z
|
|
213
|
+
.number()
|
|
214
|
+
.int()
|
|
215
|
+
.min(1)
|
|
216
|
+
.max(100)
|
|
217
|
+
.default(5)
|
|
218
|
+
.describe("Max results to return"),
|
|
219
|
+
minScore: z
|
|
220
|
+
.number()
|
|
221
|
+
.min(0)
|
|
222
|
+
.max(1)
|
|
223
|
+
.optional()
|
|
224
|
+
.describe("Minimum similarity score (0-1)"),
|
|
225
|
+
lang: z
|
|
226
|
+
.string()
|
|
227
|
+
.optional()
|
|
228
|
+
.describe("BCP-47 language hint (e.g. 'en', 'de')"),
|
|
229
|
+
intent: z
|
|
230
|
+
.string()
|
|
231
|
+
.optional()
|
|
232
|
+
.describe("Disambiguating context for the query"),
|
|
233
|
+
exclude: z
|
|
234
|
+
.array(z.string())
|
|
235
|
+
.optional()
|
|
236
|
+
.describe("Exclude documents containing any of these terms"),
|
|
237
|
+
since: z
|
|
238
|
+
.string()
|
|
239
|
+
.optional()
|
|
240
|
+
.describe("Only docs modified after this date (ISO format)"),
|
|
241
|
+
until: z
|
|
242
|
+
.string()
|
|
243
|
+
.optional()
|
|
244
|
+
.describe("Only docs modified before this date (ISO format)"),
|
|
245
|
+
categories: z.array(z.string()).optional().describe("Require category match"),
|
|
246
|
+
author: z
|
|
247
|
+
.string()
|
|
248
|
+
.optional()
|
|
249
|
+
.describe("Filter by author (case-insensitive substring)"),
|
|
250
|
+
tagsAll: z.array(z.string()).optional().describe("Require ALL of these tags"),
|
|
251
|
+
tagsAny: z.array(z.string()).optional().describe("Require ANY of these tags"),
|
|
118
252
|
});
|
|
119
253
|
|
|
120
254
|
const queryModeInputSchema = z.object({
|
|
121
|
-
mode: z
|
|
122
|
-
|
|
255
|
+
mode: z
|
|
256
|
+
.enum(["term", "intent", "hyde"])
|
|
257
|
+
.describe(
|
|
258
|
+
"Retrieval strategy: 'term' (keyword match), 'intent' (disambiguation), 'hyde' (hypothetical document for semantic matching)"
|
|
259
|
+
),
|
|
260
|
+
text: z
|
|
261
|
+
.string()
|
|
262
|
+
.trim()
|
|
263
|
+
.min(1, "Query mode text cannot be empty")
|
|
264
|
+
.describe("Text for this query mode"),
|
|
123
265
|
});
|
|
124
266
|
|
|
125
267
|
export const queryInputSchema = z.object({
|
|
126
|
-
query: z
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
268
|
+
query: z
|
|
269
|
+
.string()
|
|
270
|
+
.min(1, "Query cannot be empty")
|
|
271
|
+
.describe("Search query text"),
|
|
272
|
+
collection: z
|
|
273
|
+
.string()
|
|
274
|
+
.optional()
|
|
275
|
+
.describe("Filter to a single collection name"),
|
|
276
|
+
limit: z
|
|
277
|
+
.number()
|
|
278
|
+
.int()
|
|
279
|
+
.min(1)
|
|
280
|
+
.max(100)
|
|
281
|
+
.default(5)
|
|
282
|
+
.describe("Max results to return"),
|
|
283
|
+
minScore: z
|
|
284
|
+
.number()
|
|
285
|
+
.min(0)
|
|
286
|
+
.max(1)
|
|
287
|
+
.optional()
|
|
288
|
+
.describe("Minimum relevance score (0-1)"),
|
|
289
|
+
lang: z
|
|
290
|
+
.string()
|
|
291
|
+
.optional()
|
|
292
|
+
.describe(
|
|
293
|
+
"BCP-47 language hint (e.g. 'en', 'de'). Auto-detected if omitted"
|
|
294
|
+
),
|
|
295
|
+
intent: z
|
|
296
|
+
.string()
|
|
297
|
+
.optional()
|
|
298
|
+
.describe(
|
|
299
|
+
"Disambiguating context (e.g. 'programming language' when query is 'python')"
|
|
300
|
+
),
|
|
301
|
+
candidateLimit: z
|
|
302
|
+
.number()
|
|
303
|
+
.int()
|
|
304
|
+
.min(1)
|
|
305
|
+
.max(100)
|
|
306
|
+
.optional()
|
|
307
|
+
.describe(
|
|
308
|
+
"Max candidates passed to reranking stage (higher = better recall, slower)"
|
|
309
|
+
),
|
|
310
|
+
exclude: z
|
|
311
|
+
.array(z.string())
|
|
312
|
+
.optional()
|
|
313
|
+
.describe("Exclude documents containing any of these terms"),
|
|
314
|
+
since: z
|
|
315
|
+
.string()
|
|
316
|
+
.optional()
|
|
317
|
+
.describe("Only docs modified after this date (ISO format)"),
|
|
318
|
+
until: z
|
|
319
|
+
.string()
|
|
320
|
+
.optional()
|
|
321
|
+
.describe("Only docs modified before this date (ISO format)"),
|
|
322
|
+
categories: z.array(z.string()).optional().describe("Require category match"),
|
|
323
|
+
author: z
|
|
324
|
+
.string()
|
|
325
|
+
.optional()
|
|
326
|
+
.describe("Filter by author (case-insensitive substring)"),
|
|
138
327
|
queryModes: z
|
|
139
328
|
.array(queryModeInputSchema)
|
|
329
|
+
.describe(
|
|
330
|
+
"Structured query modes to combine multiple retrieval strategies. Max one 'hyde' entry."
|
|
331
|
+
)
|
|
140
332
|
.superRefine((entries, ctx) => {
|
|
141
333
|
const hydeCount = entries.filter((entry) => entry.mode === "hyde").length;
|
|
142
334
|
if (hydeCount > 1) {
|
|
@@ -147,68 +339,200 @@ export const queryInputSchema = z.object({
|
|
|
147
339
|
}
|
|
148
340
|
})
|
|
149
341
|
.optional(),
|
|
150
|
-
fast: z
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
342
|
+
fast: z
|
|
343
|
+
.boolean()
|
|
344
|
+
.default(false)
|
|
345
|
+
.describe("Skip expansion and reranking (~0.7s). Use for quick lookups"),
|
|
346
|
+
thorough: z
|
|
347
|
+
.boolean()
|
|
348
|
+
.default(false)
|
|
349
|
+
.describe(
|
|
350
|
+
"Enable query expansion for best recall (~5-8s). Use when default returns no results"
|
|
351
|
+
),
|
|
352
|
+
expand: z
|
|
353
|
+
.boolean()
|
|
354
|
+
.optional()
|
|
355
|
+
.describe("Override: enable/disable query expansion"),
|
|
356
|
+
rerank: z
|
|
357
|
+
.boolean()
|
|
358
|
+
.optional()
|
|
359
|
+
.describe("Override: enable/disable cross-encoder reranking"),
|
|
360
|
+
tagsAll: z.array(z.string()).optional().describe("Require ALL of these tags"),
|
|
361
|
+
tagsAny: z.array(z.string()).optional().describe("Require ANY of these tags"),
|
|
156
362
|
});
|
|
157
363
|
|
|
158
364
|
const getInputSchema = z.object({
|
|
159
|
-
ref: z
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
365
|
+
ref: z
|
|
366
|
+
.string()
|
|
367
|
+
.min(1, "Reference cannot be empty")
|
|
368
|
+
.describe(
|
|
369
|
+
"Document reference: URI (gno://collection/path), docid (#abc123), or collection/path"
|
|
370
|
+
),
|
|
371
|
+
fromLine: z
|
|
372
|
+
.number()
|
|
373
|
+
.int()
|
|
374
|
+
.min(1)
|
|
375
|
+
.optional()
|
|
376
|
+
.describe("Start reading from this line number"),
|
|
377
|
+
lineCount: z
|
|
378
|
+
.number()
|
|
379
|
+
.int()
|
|
380
|
+
.min(1)
|
|
381
|
+
.optional()
|
|
382
|
+
.describe("Number of lines to return (from fromLine)"),
|
|
383
|
+
lineNumbers: z
|
|
384
|
+
.boolean()
|
|
385
|
+
.default(true)
|
|
386
|
+
.describe("Include line numbers in output"),
|
|
163
387
|
});
|
|
164
388
|
|
|
165
389
|
const multiGetInputSchema = z.object({
|
|
166
|
-
refs: z
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
390
|
+
refs: z
|
|
391
|
+
.array(z.string())
|
|
392
|
+
.min(1)
|
|
393
|
+
.optional()
|
|
394
|
+
.describe("Array of document references (URIs or docids)"),
|
|
395
|
+
pattern: z
|
|
396
|
+
.string()
|
|
397
|
+
.optional()
|
|
398
|
+
.describe("Glob pattern to match documents (e.g. 'work/**/*.md')"),
|
|
399
|
+
maxBytes: z
|
|
400
|
+
.number()
|
|
401
|
+
.int()
|
|
402
|
+
.min(1)
|
|
403
|
+
.default(10_240)
|
|
404
|
+
.describe("Max bytes per document (truncates longer docs)"),
|
|
405
|
+
lineNumbers: z
|
|
406
|
+
.boolean()
|
|
407
|
+
.default(true)
|
|
408
|
+
.describe("Include line numbers in output"),
|
|
170
409
|
});
|
|
171
410
|
|
|
172
411
|
const statusInputSchema = z.object({});
|
|
173
412
|
|
|
174
413
|
const jobStatusInputSchema = z.object({
|
|
175
|
-
jobId: z
|
|
414
|
+
jobId: z
|
|
415
|
+
.string()
|
|
416
|
+
.min(1, "Job ID cannot be empty")
|
|
417
|
+
.describe("Job ID returned by async operations (embed, index)"),
|
|
176
418
|
});
|
|
177
419
|
|
|
178
420
|
const listJobsInputSchema = z.object({
|
|
179
|
-
limit: z
|
|
421
|
+
limit: z
|
|
422
|
+
.number()
|
|
423
|
+
.int()
|
|
424
|
+
.min(1)
|
|
425
|
+
.max(100)
|
|
426
|
+
.default(10)
|
|
427
|
+
.describe("Max jobs to return"),
|
|
180
428
|
});
|
|
181
429
|
|
|
182
430
|
const listTagsInputSchema = z.object({
|
|
183
|
-
collection: z
|
|
184
|
-
|
|
431
|
+
collection: z
|
|
432
|
+
.string()
|
|
433
|
+
.optional()
|
|
434
|
+
.describe("Filter tags to a single collection"),
|
|
435
|
+
prefix: z
|
|
436
|
+
.string()
|
|
437
|
+
.optional()
|
|
438
|
+
.describe("Filter tags by prefix (e.g. 'project/' for hierarchical tags)"),
|
|
185
439
|
});
|
|
186
440
|
|
|
187
441
|
const linksInputSchema = z.object({
|
|
188
|
-
ref: z
|
|
189
|
-
|
|
442
|
+
ref: z
|
|
443
|
+
.string()
|
|
444
|
+
.trim()
|
|
445
|
+
.min(1, "Reference cannot be empty")
|
|
446
|
+
.describe("Document reference (URI, docid, or collection/path)"),
|
|
447
|
+
type: z
|
|
448
|
+
.enum(["wiki", "markdown"])
|
|
449
|
+
.optional()
|
|
450
|
+
.describe(
|
|
451
|
+
"Filter by link type: 'wiki' ([[links]]) or 'markdown' ([links](url))"
|
|
452
|
+
),
|
|
190
453
|
});
|
|
191
454
|
|
|
192
455
|
const backlinksInputSchema = z.object({
|
|
193
|
-
ref: z
|
|
194
|
-
|
|
456
|
+
ref: z
|
|
457
|
+
.string()
|
|
458
|
+
.trim()
|
|
459
|
+
.min(1, "Reference cannot be empty")
|
|
460
|
+
.describe("Document reference to find backlinks for"),
|
|
461
|
+
collection: z
|
|
462
|
+
.string()
|
|
463
|
+
.trim()
|
|
464
|
+
.optional()
|
|
465
|
+
.describe("Filter backlinks to a single collection"),
|
|
195
466
|
});
|
|
196
467
|
|
|
197
468
|
const similarInputSchema = z.object({
|
|
198
|
-
ref: z
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
469
|
+
ref: z
|
|
470
|
+
.string()
|
|
471
|
+
.trim()
|
|
472
|
+
.min(1, "Reference cannot be empty")
|
|
473
|
+
.describe("Document reference to find similar docs for"),
|
|
474
|
+
limit: z
|
|
475
|
+
.number()
|
|
476
|
+
.int()
|
|
477
|
+
.min(1)
|
|
478
|
+
.max(50)
|
|
479
|
+
.default(5)
|
|
480
|
+
.describe("Max similar documents to return"),
|
|
481
|
+
threshold: z
|
|
482
|
+
.number()
|
|
483
|
+
.min(0)
|
|
484
|
+
.max(1)
|
|
485
|
+
.optional()
|
|
486
|
+
.describe("Minimum similarity score (0-1, default: 0.7)"),
|
|
487
|
+
crossCollection: z
|
|
488
|
+
.boolean()
|
|
489
|
+
.default(false)
|
|
490
|
+
.describe(
|
|
491
|
+
"Search across all collections (not just the document's own collection)"
|
|
492
|
+
),
|
|
202
493
|
});
|
|
203
494
|
|
|
204
495
|
const graphInputSchema = z.object({
|
|
205
|
-
collection: z
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
496
|
+
collection: z
|
|
497
|
+
.string()
|
|
498
|
+
.trim()
|
|
499
|
+
.optional()
|
|
500
|
+
.describe("Filter graph to a single collection"),
|
|
501
|
+
limit: z
|
|
502
|
+
.number()
|
|
503
|
+
.int()
|
|
504
|
+
.min(1)
|
|
505
|
+
.max(5000)
|
|
506
|
+
.default(2000)
|
|
507
|
+
.describe("Max nodes in graph"),
|
|
508
|
+
edgeLimit: z
|
|
509
|
+
.number()
|
|
510
|
+
.int()
|
|
511
|
+
.min(1)
|
|
512
|
+
.max(50000)
|
|
513
|
+
.default(10000)
|
|
514
|
+
.describe("Max edges in graph"),
|
|
515
|
+
includeSimilar: z
|
|
516
|
+
.boolean()
|
|
517
|
+
.default(false)
|
|
518
|
+
.describe("Include vector-similarity edges (not just wiki/markdown links)"),
|
|
519
|
+
threshold: z
|
|
520
|
+
.number()
|
|
521
|
+
.min(0)
|
|
522
|
+
.max(1)
|
|
523
|
+
.default(0.7)
|
|
524
|
+
.describe("Similarity threshold for similar edges (0-1)"),
|
|
525
|
+
linkedOnly: z
|
|
526
|
+
.boolean()
|
|
527
|
+
.default(true)
|
|
528
|
+
.describe("Exclude isolated nodes (no links)"),
|
|
529
|
+
similarTopK: z
|
|
530
|
+
.number()
|
|
531
|
+
.int()
|
|
532
|
+
.min(1)
|
|
533
|
+
.max(20)
|
|
534
|
+
.default(5)
|
|
535
|
+
.describe("Max similar docs per node when includeSimilar=true"),
|
|
212
536
|
});
|
|
213
537
|
|
|
214
538
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -323,77 +647,77 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
|
|
|
323
647
|
// Tool IDs use underscores (MCP pattern: ^[a-zA-Z0-9_-]{1,64}$)
|
|
324
648
|
server.tool(
|
|
325
649
|
"gno_search",
|
|
326
|
-
"BM25
|
|
650
|
+
"BM25 keyword search. Instant, best for exact terms. Use gno_query for better quality.",
|
|
327
651
|
searchInputSchema.shape,
|
|
328
652
|
(args) => handleSearch(args, ctx)
|
|
329
653
|
);
|
|
330
654
|
|
|
331
655
|
server.tool(
|
|
332
656
|
"gno_vsearch",
|
|
333
|
-
"Vector
|
|
657
|
+
"Vector semantic search. Finds conceptually similar docs even with different wording. Use gno_query for best results.",
|
|
334
658
|
vsearchInputSchema.shape,
|
|
335
659
|
(args) => handleVsearch(args, ctx)
|
|
336
660
|
);
|
|
337
661
|
|
|
338
662
|
server.tool(
|
|
339
663
|
"gno_query",
|
|
340
|
-
"Hybrid search
|
|
664
|
+
"Hybrid search (BM25 + vector + reranking). Best quality, recommended default. Use fast=true for speed, thorough=true for best recall.",
|
|
341
665
|
queryInputSchema.shape,
|
|
342
666
|
(args) => handleQuery(args, ctx)
|
|
343
667
|
);
|
|
344
668
|
|
|
345
669
|
server.tool(
|
|
346
670
|
"gno_get",
|
|
347
|
-
"Retrieve a single document by URI, docid, or collection/path",
|
|
671
|
+
"Retrieve a single document's full content by URI (gno://collection/path), docid (#abc123), or collection/path.",
|
|
348
672
|
getInputSchema.shape,
|
|
349
673
|
(args) => handleGet(args, ctx)
|
|
350
674
|
);
|
|
351
675
|
|
|
352
676
|
server.tool(
|
|
353
677
|
"gno_multi_get",
|
|
354
|
-
"Retrieve multiple documents by refs or glob pattern",
|
|
678
|
+
"Retrieve multiple documents by refs array or glob pattern. Use maxBytes to control truncation.",
|
|
355
679
|
multiGetInputSchema.shape,
|
|
356
680
|
(args) => handleMultiGet(args, ctx)
|
|
357
681
|
);
|
|
358
682
|
|
|
359
683
|
server.tool(
|
|
360
684
|
"gno_status",
|
|
361
|
-
"Get index
|
|
685
|
+
"Get index health: collection count, document count, chunk count, embedding backlog, and per-collection stats.",
|
|
362
686
|
statusInputSchema.shape,
|
|
363
687
|
(args) => handleStatus(args, ctx)
|
|
364
688
|
);
|
|
365
689
|
|
|
366
690
|
server.tool(
|
|
367
691
|
"gno_list_tags",
|
|
368
|
-
"List tags with document counts",
|
|
692
|
+
"List all tags with document counts. Use prefix to filter hierarchical tags (e.g. 'project/').",
|
|
369
693
|
listTagsInputSchema.shape,
|
|
370
694
|
(args) => handleListTags(args, ctx)
|
|
371
695
|
);
|
|
372
696
|
|
|
373
697
|
server.tool(
|
|
374
698
|
"gno_links",
|
|
375
|
-
"Get outgoing links from a document",
|
|
699
|
+
"Get outgoing wiki ([[links]]) and markdown links from a document.",
|
|
376
700
|
linksInputSchema.shape,
|
|
377
701
|
(args) => handleLinks(args, ctx)
|
|
378
702
|
);
|
|
379
703
|
|
|
380
704
|
server.tool(
|
|
381
705
|
"gno_backlinks",
|
|
382
|
-
"
|
|
706
|
+
"Find all documents that link TO a given document (incoming references).",
|
|
383
707
|
backlinksInputSchema.shape,
|
|
384
708
|
(args) => handleBacklinks(args, ctx)
|
|
385
709
|
);
|
|
386
710
|
|
|
387
711
|
server.tool(
|
|
388
712
|
"gno_similar",
|
|
389
|
-
"Find semantically similar documents using vector embeddings",
|
|
713
|
+
"Find semantically similar documents using vector embeddings. Requires embeddings to exist for source document.",
|
|
390
714
|
similarInputSchema.shape,
|
|
391
715
|
(args) => handleSimilar(args, ctx)
|
|
392
716
|
);
|
|
393
717
|
|
|
394
718
|
server.tool(
|
|
395
719
|
"gno_graph",
|
|
396
|
-
"Get knowledge graph of document connections (
|
|
720
|
+
"Get knowledge graph of document connections (wiki links, markdown links, optional similarity edges).",
|
|
397
721
|
graphInputSchema.shape,
|
|
398
722
|
(args) => handleGraph(args, ctx)
|
|
399
723
|
);
|
|
@@ -401,42 +725,42 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
|
|
|
401
725
|
if (ctx.enableWrite) {
|
|
402
726
|
server.tool(
|
|
403
727
|
"gno_capture",
|
|
404
|
-
"Create a new document",
|
|
728
|
+
"Create a new document in a collection. Writes to disk. Does NOT auto-embed; run gno_index after to make it searchable via vector search.",
|
|
405
729
|
captureInputSchema.shape,
|
|
406
730
|
(args) => handleCapture(args, ctx)
|
|
407
731
|
);
|
|
408
732
|
|
|
409
733
|
server.tool(
|
|
410
734
|
"gno_add_collection",
|
|
411
|
-
"Add a collection and start indexing",
|
|
735
|
+
"Add a directory as a new collection and start indexing. Returns a job ID for tracking.",
|
|
412
736
|
addCollectionInputSchema.shape,
|
|
413
737
|
(args) => handleAddCollection(args, ctx)
|
|
414
738
|
);
|
|
415
739
|
|
|
416
740
|
server.tool(
|
|
417
741
|
"gno_sync",
|
|
418
|
-
"Sync
|
|
742
|
+
"Sync files from disk into the index (FTS only, no embeddings). Does NOT auto-embed; run gno_embed after if vector search needed.",
|
|
419
743
|
syncInputSchema.shape,
|
|
420
744
|
(args) => handleSync(args, ctx)
|
|
421
745
|
);
|
|
422
746
|
|
|
423
747
|
server.tool(
|
|
424
748
|
"gno_embed",
|
|
425
|
-
"Generate embeddings for unembedded chunks",
|
|
749
|
+
"Generate vector embeddings for all unembedded chunks. Async: returns a job ID. Poll with gno_job_status.",
|
|
426
750
|
embedInputSchema.shape,
|
|
427
751
|
(args) => handleEmbed(args, ctx)
|
|
428
752
|
);
|
|
429
753
|
|
|
430
754
|
server.tool(
|
|
431
755
|
"gno_index",
|
|
432
|
-
"Full index: sync files + generate embeddings",
|
|
756
|
+
"Full index: sync files from disk + generate embeddings. Async: returns a job ID. Poll with gno_job_status.",
|
|
433
757
|
indexInputSchema.shape,
|
|
434
758
|
(args) => handleIndex(args, ctx)
|
|
435
759
|
);
|
|
436
760
|
|
|
437
761
|
server.tool(
|
|
438
762
|
"gno_remove_collection",
|
|
439
|
-
"Remove a collection from config",
|
|
763
|
+
"Remove a collection from config and delete its indexed data.",
|
|
440
764
|
removeCollectionInputSchema.shape,
|
|
441
765
|
(args) => handleRemoveCollection(args, ctx)
|
|
442
766
|
);
|
|
@@ -444,14 +768,14 @@ export function registerTools(server: McpServer, ctx: ToolContext): void {
|
|
|
444
768
|
|
|
445
769
|
server.tool(
|
|
446
770
|
"gno_job_status",
|
|
447
|
-
"
|
|
771
|
+
"Check status of an async job (embed, index). Returns progress percentage and completion state.",
|
|
448
772
|
jobStatusInputSchema.shape,
|
|
449
773
|
(args) => handleJobStatus(args, ctx)
|
|
450
774
|
);
|
|
451
775
|
|
|
452
776
|
server.tool(
|
|
453
777
|
"gno_list_jobs",
|
|
454
|
-
"List active and
|
|
778
|
+
"List active and recently completed async jobs with their status and progress.",
|
|
455
779
|
listJobsInputSchema.shape,
|
|
456
780
|
(args) => handleListJobs(args, ctx)
|
|
457
781
|
);
|