@looptech-ai/understand-quickly-mcp 0.1.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.
@@ -0,0 +1,167 @@
1
+ import { findEntryById, loadRegistry, resolveRegistrySource, } from "../registry.js";
2
+ // Registry id pattern: `<owner>/<repo>` with the same character class the
3
+ // site/scripts already use in error messages and validation.
4
+ const ID_PATTERN = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
5
+ const HTTPS_GITHUB_RE = /^https?:\/\/github\.com\/([^/\s]+)\/([^/\s?#]+)(?:[\/?#].*)?$/i;
6
+ const SSH_GITHUB_RE = /^git@github\.com:([^/\s]+)\/([^/\s?#]+?)(?:\.git)?$/i;
7
+ /**
8
+ * Parse a github URL into a registry id. Accepts:
9
+ * - https://github.com/owner/repo
10
+ * - https://github.com/owner/repo.git
11
+ * - https://github.com/owner/repo/ (trailing slash)
12
+ * - https://github.com/owner/repo/tree/branch/...
13
+ * - git@github.com:owner/repo.git
14
+ */
15
+ export function parseGithubUrl(url) {
16
+ if (typeof url !== "string" || url.length === 0)
17
+ return undefined;
18
+ const trimmed = url.trim();
19
+ const ssh = trimmed.match(SSH_GITHUB_RE);
20
+ if (ssh) {
21
+ const owner = ssh[1];
22
+ const repo = ssh[2].replace(/\.git$/i, "");
23
+ if (!owner || !repo)
24
+ return undefined;
25
+ return `${owner}/${repo}`;
26
+ }
27
+ const https = trimmed.match(HTTPS_GITHUB_RE);
28
+ if (https) {
29
+ const owner = https[1];
30
+ let repo = https[2];
31
+ repo = repo.replace(/\.git$/i, "");
32
+ if (!owner || !repo)
33
+ return undefined;
34
+ return `${owner}/${repo}`;
35
+ }
36
+ return undefined;
37
+ }
38
+ /** Levenshtein distance, capped early when it exceeds `maxDistance` for speed. */
39
+ export function levenshtein(a, b, maxDistance = Infinity) {
40
+ if (a === b)
41
+ return 0;
42
+ const al = a.length;
43
+ const bl = b.length;
44
+ if (al === 0)
45
+ return bl;
46
+ if (bl === 0)
47
+ return al;
48
+ if (Math.abs(al - bl) > maxDistance)
49
+ return maxDistance + 1;
50
+ // Two-row DP (rolling).
51
+ let prev = new Array(bl + 1);
52
+ let curr = new Array(bl + 1);
53
+ for (let j = 0; j <= bl; j++)
54
+ prev[j] = j;
55
+ for (let i = 1; i <= al; i++) {
56
+ curr[0] = i;
57
+ let rowMin = curr[0];
58
+ for (let j = 1; j <= bl; j++) {
59
+ const cost = a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1;
60
+ curr[j] = Math.min(curr[j - 1] + 1, // insertion
61
+ prev[j] + 1, // deletion
62
+ prev[j - 1] + cost);
63
+ if (curr[j] < rowMin)
64
+ rowMin = curr[j];
65
+ }
66
+ if (rowMin > maxDistance)
67
+ return maxDistance + 1;
68
+ [prev, curr] = [curr, prev];
69
+ }
70
+ return prev[bl];
71
+ }
72
+ function suggestFuzzy(target, ids, max = 5, maxDistance = 3) {
73
+ const targetLower = target.toLowerCase();
74
+ const scored = [];
75
+ for (const id of ids) {
76
+ const d = levenshtein(targetLower, id.toLowerCase(), maxDistance);
77
+ if (d <= maxDistance)
78
+ scored.push({ id, dist: d });
79
+ }
80
+ scored.sort((a, b) => a.dist - b.dist || a.id.localeCompare(b.id));
81
+ return scored.slice(0, max).map((s) => s.id);
82
+ }
83
+ function driftSummary(entry) {
84
+ const behind = entry.commits_behind;
85
+ if (typeof behind === "number" && behind > 0) {
86
+ return `behind by ${behind} commit${behind === 1 ? "" : "s"}`;
87
+ }
88
+ if (typeof behind === "number" && behind === 0) {
89
+ return "up to date";
90
+ }
91
+ return undefined;
92
+ }
93
+ export async function findGraphForRepo(params, options = {}) {
94
+ const hasId = typeof params?.id === "string" && params.id.length > 0;
95
+ const hasUrl = typeof params?.github_url === "string" && params.github_url.length > 0;
96
+ if (!hasId && !hasUrl) {
97
+ throw new Error("Provide at least one of `id` or `github_url` (e.g. \"owner/repo\" or \"https://github.com/owner/repo\").");
98
+ }
99
+ let resolvedId;
100
+ if (hasId) {
101
+ if (!ID_PATTERN.test(params.id)) {
102
+ throw new Error(`\`id\` must match \`owner/repo\` (got "${params.id}").`);
103
+ }
104
+ resolvedId = params.id;
105
+ }
106
+ else if (hasUrl) {
107
+ const parsed = parseGithubUrl(params.github_url);
108
+ if (!parsed) {
109
+ throw new Error(`Could not extract owner/repo from \`github_url\`: "${params.github_url}".`);
110
+ }
111
+ if (!ID_PATTERN.test(parsed)) {
112
+ throw new Error(`Parsed id "${parsed}" does not match \`owner/repo\` pattern.`);
113
+ }
114
+ resolvedId = parsed;
115
+ }
116
+ const registry = await loadRegistry({
117
+ source: options.source ?? resolveRegistrySource(),
118
+ fetchImpl: options.fetchImpl,
119
+ });
120
+ const entry = findEntryById(registry, resolvedId);
121
+ if (!entry) {
122
+ const suggestions = suggestFuzzy(resolvedId, registry.entries.map((e) => e.id));
123
+ return { found: false, suggestions };
124
+ }
125
+ const out = {
126
+ found: true,
127
+ id: entry.id,
128
+ format: entry.format,
129
+ graph_url: entry.graph_url,
130
+ };
131
+ if (entry.status !== undefined)
132
+ out.status = entry.status;
133
+ if (entry.last_synced !== undefined)
134
+ out.last_synced = entry.last_synced;
135
+ if (entry.last_sha !== undefined)
136
+ out.last_sha = entry.last_sha;
137
+ if (entry.source_sha !== undefined)
138
+ out.source_sha = entry.source_sha;
139
+ if (entry.head_sha !== undefined)
140
+ out.head_sha = entry.head_sha;
141
+ if (typeof entry.commits_behind === "number") {
142
+ out.commits_behind = entry.commits_behind;
143
+ }
144
+ const drift = driftSummary(entry);
145
+ if (drift)
146
+ out.drift_summary = drift;
147
+ return out;
148
+ }
149
+ export const findGraphForRepoToolDefinition = {
150
+ name: "find_graph_for_repo",
151
+ description: "Look up a registry entry by `id` (\"owner/repo\") or `github_url` (https or ssh). Returns the entry's graph_url and drift metadata, or `{found:false, suggestions}` with up to 5 fuzzy-matched ids.",
152
+ inputSchema: {
153
+ type: "object",
154
+ properties: {
155
+ id: {
156
+ type: "string",
157
+ description: "Registry id (\"owner/repo\"). At least one of `id` or `github_url` is required.",
158
+ },
159
+ github_url: {
160
+ type: "string",
161
+ description: "GitHub URL (https or ssh form). Branch/path suffixes and a trailing `.git` are tolerated.",
162
+ },
163
+ },
164
+ additionalProperties: false,
165
+ },
166
+ };
167
+ //# sourceMappingURL=find-graph-for-repo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-graph-for-repo.js","sourceRoot":"","sources":["../../src/tools/find-graph-for-repo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { GetGraphParams } from "../types.js";
2
+ export declare function getGraph(params: GetGraphParams): Promise<unknown>;
3
+ export declare const getGraphToolDefinition: {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: {
7
+ type: "object";
8
+ properties: {
9
+ id: {
10
+ type: string;
11
+ description: string;
12
+ };
13
+ };
14
+ required: string[];
15
+ additionalProperties: boolean;
16
+ };
17
+ };
@@ -0,0 +1,28 @@
1
+ import { fetchGraph, findEntryById, loadRegistry, resolveRegistrySource, } from "../registry.js";
2
+ export async function getGraph(params) {
3
+ if (!params || typeof params.id !== "string" || params.id.length === 0) {
4
+ throw new Error("`id` is required");
5
+ }
6
+ const registry = await loadRegistry({ source: resolveRegistrySource() });
7
+ const entry = findEntryById(registry, params.id);
8
+ if (!entry) {
9
+ throw new Error(`No registry entry found with id "${params.id}"`);
10
+ }
11
+ return fetchGraph(entry.graph_url);
12
+ }
13
+ export const getGraphToolDefinition = {
14
+ name: "get_graph",
15
+ description: "Fetch and return the parsed knowledge graph JSON for a registry entry by id.",
16
+ inputSchema: {
17
+ type: "object",
18
+ properties: {
19
+ id: {
20
+ type: "string",
21
+ description: "Registry entry id, e.g. \"Lum1104/Understand-Anything\".",
22
+ },
23
+ },
24
+ required: ["id"],
25
+ additionalProperties: false,
26
+ },
27
+ };
28
+ //# sourceMappingURL=get-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-graph.js","sourceRoot":"","sources":["../../src/tools/get-graph.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,YAAY,EACZ,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAGxB,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAsB;IACnD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,IAAI,MAAM,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,EAAE,CAAC,CAAC;IACzE,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,oCAAoC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE,WAAW;IACjB,WAAW,EACT,8EAA8E;IAChF,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,EAAE,EAAE;gBACF,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,0DAA0D;aACxE;SACF;QACD,QAAQ,EAAE,CAAC,IAAI,CAAC;QAChB,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { ListReposParams, RepoSummary } from "../types.js";
2
+ export declare function listRepos(params?: ListReposParams): Promise<RepoSummary[]>;
3
+ export declare const listReposToolDefinition: {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: {
7
+ type: "object";
8
+ properties: {
9
+ format: {
10
+ type: string;
11
+ description: string;
12
+ };
13
+ tag: {
14
+ type: string;
15
+ description: string;
16
+ };
17
+ status: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ };
22
+ additionalProperties: boolean;
23
+ };
24
+ };
@@ -0,0 +1,51 @@
1
+ import { filterEntries, loadRegistry, resolveRegistrySource, } from "../registry.js";
2
+ function toSummary(entry) {
3
+ return {
4
+ id: entry.id,
5
+ format: entry.format,
6
+ description: entry.description,
7
+ status: entry.status,
8
+ tags: entry.tags,
9
+ last_synced: entry.last_synced,
10
+ graph_url: entry.graph_url,
11
+ };
12
+ }
13
+ export async function listRepos(params = {}) {
14
+ const registry = await loadRegistry({ source: resolveRegistrySource() });
15
+ const filtered = filterEntries(registry.entries, (entry) => {
16
+ if (params.format && entry.format !== params.format)
17
+ return false;
18
+ if (params.status && entry.status !== params.status)
19
+ return false;
20
+ if (params.tag) {
21
+ const tags = entry.tags ?? [];
22
+ if (!tags.includes(params.tag))
23
+ return false;
24
+ }
25
+ return true;
26
+ });
27
+ return filtered.map(toSummary);
28
+ }
29
+ export const listReposToolDefinition = {
30
+ name: "list_repos",
31
+ description: "List entries in the understand-quickly registry. Optional filters: `format`, `tag`, `status`.",
32
+ inputSchema: {
33
+ type: "object",
34
+ properties: {
35
+ format: {
36
+ type: "string",
37
+ description: "Exact match on entry.format (e.g. \"understand-anything@1\").",
38
+ },
39
+ tag: {
40
+ type: "string",
41
+ description: "Returns entries whose `tags` array contains this string.",
42
+ },
43
+ status: {
44
+ type: "string",
45
+ description: "Exact match on entry.status (typically \"ok\").",
46
+ },
47
+ },
48
+ additionalProperties: false,
49
+ },
50
+ };
51
+ //# sourceMappingURL=list-repos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-repos.js","sourceRoot":"","sources":["../../src/tools/list-repos.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,YAAY,EACZ,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AAOxB,SAAS,SAAS,CAAC,KAAoB;IACrC,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,SAA0B,EAAE;IAE5B,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,EAAE,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QACzD,IAAI,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAClE,IAAI,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAClE,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC;YACf,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC;gBAAE,OAAO,KAAK,CAAC;QAC/C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,+FAA+F;IACjG,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,+DAA+D;aAC7E;YACD,GAAG,EAAE;gBACH,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,0DAA0D;aACxE;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,iDAAiD;aAC/D;SACF;QACD,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC"}
@@ -0,0 +1,43 @@
1
+ import type { FetchImpl, SearchConceptsParams, SearchHit } from "../types.js";
2
+ export interface SearchConceptsResult {
3
+ query: string;
4
+ results?: Array<{
5
+ id: string;
6
+ graph_url: string;
7
+ hits: SearchHit[];
8
+ }>;
9
+ matches?: Array<{
10
+ term: string;
11
+ count: number;
12
+ entries: number;
13
+ samples: string[];
14
+ }>;
15
+ source: "stats" | "graph" | "fanout";
16
+ truncated?: boolean;
17
+ scanned?: number;
18
+ }
19
+ export interface SearchConceptsOptions {
20
+ fetchImpl?: FetchImpl;
21
+ registrySource?: string;
22
+ statsSource?: string;
23
+ }
24
+ export declare function searchConcepts(params: SearchConceptsParams, options?: SearchConceptsOptions): Promise<SearchConceptsResult>;
25
+ export declare const searchConceptsToolDefinition: {
26
+ name: string;
27
+ description: string;
28
+ inputSchema: {
29
+ type: "object";
30
+ properties: {
31
+ query: {
32
+ type: string;
33
+ description: string;
34
+ };
35
+ id: {
36
+ type: string;
37
+ description: string;
38
+ };
39
+ };
40
+ required: string[];
41
+ additionalProperties: boolean;
42
+ };
43
+ };
@@ -0,0 +1,171 @@
1
+ import { fetchGraph, findEntryById, loadRegistry, loadStats, resolveRegistrySource, resolveStatsSource, } from "../registry.js";
2
+ // Stub-quality cap on cross-graph searches. A real implementation would either
3
+ // stream results or build a server-side index — for now we just bound the work.
4
+ const CROSS_GRAPH_LIMIT = 5;
5
+ const CONCEPTS_RESULT_CAP = 50;
6
+ const SAMPLES_CAP = 3;
7
+ /**
8
+ * Best-effort node enumeration. Different graph formats nest nodes differently
9
+ * (`nodes`, `entities`, `concepts`, …). For the stub we accept any of those
10
+ * common shapes and fall back to walking the top-level object's array values.
11
+ */
12
+ function collectNodes(graph) {
13
+ if (!graph || typeof graph !== "object")
14
+ return [];
15
+ const obj = graph;
16
+ const candidates = ["nodes", "entities", "concepts", "items"];
17
+ for (const key of candidates) {
18
+ const value = obj[key];
19
+ if (Array.isArray(value)) {
20
+ return value.filter((item) => !!item && typeof item === "object");
21
+ }
22
+ }
23
+ // Fallback: pull every array value and concat.
24
+ const collected = [];
25
+ for (const value of Object.values(obj)) {
26
+ if (Array.isArray(value)) {
27
+ for (const item of value) {
28
+ if (item && typeof item === "object")
29
+ collected.push(item);
30
+ }
31
+ }
32
+ }
33
+ return collected;
34
+ }
35
+ function matchNode(node, query) {
36
+ const lower = query.toLowerCase();
37
+ const fields = [
38
+ ["id", node.id],
39
+ ["label", node.label],
40
+ ["name", node.name],
41
+ ];
42
+ for (const [field, raw] of fields) {
43
+ if (typeof raw === "string" && raw.toLowerCase().includes(lower)) {
44
+ return {
45
+ node_id: typeof node.id === "string" ? node.id : undefined,
46
+ label: typeof node.label === "string" ? node.label : undefined,
47
+ name: typeof node.name === "string" ? node.name : undefined,
48
+ matched_field: field,
49
+ matched_value: raw,
50
+ };
51
+ }
52
+ }
53
+ return undefined;
54
+ }
55
+ async function searchOneGraph(graphUrl, query, fetchImpl) {
56
+ let graph;
57
+ try {
58
+ graph = await fetchGraph(graphUrl, fetchImpl);
59
+ }
60
+ catch (err) {
61
+ // For the stub, swallow per-graph fetch errors so a single 404 does not
62
+ // poison the whole result set.
63
+ return [];
64
+ }
65
+ const nodes = collectNodes(graph);
66
+ const hits = [];
67
+ for (const node of nodes) {
68
+ const hit = matchNode(node, query);
69
+ if (hit)
70
+ hits.push(hit);
71
+ }
72
+ return hits;
73
+ }
74
+ async function fanoutSearch(query, fetchImpl, registrySource) {
75
+ const registry = await loadRegistry({ source: registrySource, fetchImpl });
76
+ const okEntries = registry.entries.filter((entry) => entry.status === "ok");
77
+ const slice = okEntries.slice(0, CROSS_GRAPH_LIMIT);
78
+ const results = [];
79
+ // Sequential to keep the stub gentle on remote hosts.
80
+ for (const entry of slice) {
81
+ const hits = await searchOneGraph(entry.graph_url, query, fetchImpl);
82
+ if (hits.length > 0) {
83
+ results.push({ id: entry.id, graph_url: entry.graph_url, hits });
84
+ }
85
+ }
86
+ return {
87
+ query,
88
+ source: "fanout",
89
+ scanned: slice.length,
90
+ truncated: okEntries.length > slice.length,
91
+ results,
92
+ };
93
+ }
94
+ function searchStatsConcepts(query, concepts) {
95
+ const lower = query.toLowerCase();
96
+ const out = [];
97
+ for (const c of concepts) {
98
+ if (typeof c?.term !== "string")
99
+ continue;
100
+ if (!c.term.toLowerCase().includes(lower))
101
+ continue;
102
+ out.push({
103
+ term: c.term,
104
+ count: c.entries,
105
+ entries: c.entries,
106
+ samples: Array.isArray(c.samples) ? c.samples.slice(0, SAMPLES_CAP) : [],
107
+ });
108
+ if (out.length >= CONCEPTS_RESULT_CAP)
109
+ break;
110
+ }
111
+ return out;
112
+ }
113
+ export async function searchConcepts(params, options = {}) {
114
+ if (!params || typeof params.query !== "string" || params.query.length === 0) {
115
+ throw new Error("`query` is required");
116
+ }
117
+ const registrySource = options.registrySource ?? resolveRegistrySource();
118
+ const statsSource = options.statsSource ?? resolveStatsSource();
119
+ const fetchImpl = options.fetchImpl;
120
+ // Single-graph mode: keep the legacy fan-out behavior for one specific graph
121
+ // since stats.json is repo-keyed by sample only and is not a substitute.
122
+ if (params.id) {
123
+ const registry = await loadRegistry({ source: registrySource, fetchImpl });
124
+ const entry = findEntryById(registry, params.id);
125
+ if (!entry) {
126
+ throw new Error(`No registry entry found with id "${params.id}"`);
127
+ }
128
+ const hits = await searchOneGraph(entry.graph_url, params.query, fetchImpl);
129
+ return {
130
+ query: params.query,
131
+ source: "graph",
132
+ scanned: 1,
133
+ results: [{ id: entry.id, graph_url: entry.graph_url, hits }],
134
+ };
135
+ }
136
+ // Default: stats.json-backed concept search. Cheap (one GET, cached 60s).
137
+ try {
138
+ const stats = await loadStats({ source: statsSource, fetchImpl });
139
+ const matches = searchStatsConcepts(params.query, stats.concepts);
140
+ return {
141
+ query: params.query,
142
+ source: "stats",
143
+ matches,
144
+ };
145
+ }
146
+ catch (err) {
147
+ // Fall through to the legacy fan-out so an outage on stats.json does not
148
+ // break this tool entirely.
149
+ return fanoutSearch(params.query, fetchImpl, registrySource);
150
+ }
151
+ }
152
+ export const searchConceptsToolDefinition = {
153
+ name: "search_concepts",
154
+ description: "Search aggregated concept terms (default: precomputed `stats.json`). Pass `id` to fall back to a single-graph node search. If `stats.json` is unavailable, falls back to a capped cross-graph node fan-out.",
155
+ inputSchema: {
156
+ type: "object",
157
+ properties: {
158
+ query: {
159
+ type: "string",
160
+ description: "Substring to search for (case-insensitive).",
161
+ },
162
+ id: {
163
+ type: "string",
164
+ description: "Optional entry id. If given, scopes the search to that single graph (legacy node-level mode).",
165
+ },
166
+ },
167
+ required: ["query"],
168
+ additionalProperties: false,
169
+ },
170
+ };
171
+ //# sourceMappingURL=search-concepts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-concepts.js","sourceRoot":"","sources":["../../src/tools/search-concepts.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,aAAa,EACb,YAAY,EACZ,SAAS,EACT,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AASxB,+EAA+E;AAC/E,gFAAgF;AAChF,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAC/B,MAAM,WAAW,GAAG,CAAC,CAAC;AAStB;;;;GAIG;AACH,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACnD,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC9D,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,MAAM,CACjB,CAAC,IAAI,EAAoB,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,CAC/D,CAAC;QACJ,CAAC;IACH,CAAC;IACD,+CAA+C;IAC/C,MAAM,SAAS,GAAe,EAAE,CAAC;IACjC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;oBAAE,SAAS,CAAC,IAAI,CAAC,IAAgB,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,SAAS,CAAC,IAAc,EAAE,KAAa;IAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,MAAM,MAAM,GAA8C;QACxD,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACf,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC;QACrB,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC;KACpB,CAAC;IACF,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;QAClC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACjE,OAAO;gBACL,OAAO,EAAE,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;gBAC1D,KAAK,EAAE,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;gBAC9D,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;gBAC3D,aAAa,EAAE,KAAK;gBACpB,aAAa,EAAE,GAAG;aACnB,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,QAAgB,EAChB,KAAa,EACb,SAAqB;IAErB,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,wEAAwE;QACxE,+BAA+B;QAC/B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,IAAI,GAAgB,EAAE,CAAC;IAC7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACnC,IAAI,GAAG;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AA4BD,KAAK,UAAU,YAAY,CACzB,KAAa,EACb,SAAgC,EAChC,cAAsB;IAEtB,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAoB,QAAQ,CAAC,OAAO,CAAC,MAAM,CACxD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI,CACjC,CAAC;IACF,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACpD,MAAM,OAAO,GAAiD,EAAE,CAAC;IACjE,sDAAsD;IACtD,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;QACrE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IACD,OAAO;QACL,KAAK;QACL,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,KAAK,CAAC,MAAM;QACrB,SAAS,EAAE,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM;QAC1C,OAAO;KACR,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAC1B,KAAa,EACb,QAAwB;IAExB,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,MAAM,GAAG,GAAiD,EAAE,CAAC;IAC7D,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,OAAO,CAAC,EAAE,IAAI,KAAK,QAAQ;YAAE,SAAS;QAC1C,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,SAAS;QACpD,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,OAAO;YAChB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE;SACzE,CAAC,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,IAAI,mBAAmB;YAAE,MAAM;IAC/C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAA4B,EAC5B,UAAiC,EAAE;IAEnC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,qBAAqB,EAAE,CAAC;IACzE,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,EAAE,CAAC;IAChE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAEpC,6EAA6E;IAC7E,yEAAyE;IACzE,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC,CAAC;QAC3E,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,oCAAoC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC5E,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;SAC9D,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClE,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,OAAO;YACf,OAAO;SACR,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,yEAAyE;QACzE,4BAA4B;QAC5B,OAAO,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,6MAA6M;IAC/M,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,6CAA6C;aAC3D;YACD,EAAE,EAAE;gBACF,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,+FAA+F;aAClG;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;QACnB,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC"}
@@ -0,0 +1,82 @@
1
+ export type RegistryEntryStatus = "ok" | "error" | "pending" | string;
2
+ export interface RegistryEntry {
3
+ id: string;
4
+ owner?: string;
5
+ repo?: string;
6
+ format: string;
7
+ graph_url: string;
8
+ description?: string;
9
+ status?: RegistryEntryStatus;
10
+ tags?: string[];
11
+ last_sha?: string;
12
+ last_synced?: string;
13
+ source_sha?: string;
14
+ head_sha?: string;
15
+ commits_behind?: number;
16
+ [key: string]: unknown;
17
+ }
18
+ export interface Registry {
19
+ schema_version: number;
20
+ generated_at: string;
21
+ entries: RegistryEntry[];
22
+ [key: string]: unknown;
23
+ }
24
+ export interface RepoSummary {
25
+ id: string;
26
+ format: string;
27
+ description?: string;
28
+ status?: RegistryEntryStatus;
29
+ tags?: string[];
30
+ last_synced?: string;
31
+ graph_url: string;
32
+ }
33
+ export interface ListReposParams {
34
+ format?: string;
35
+ tag?: string;
36
+ status?: string;
37
+ }
38
+ export interface GetGraphParams {
39
+ id: string;
40
+ }
41
+ export interface SearchConceptsParams {
42
+ query: string;
43
+ id?: string;
44
+ }
45
+ export interface SearchHit {
46
+ node_id?: string;
47
+ label?: string;
48
+ name?: string;
49
+ matched_field: "id" | "label" | "name";
50
+ matched_value: string;
51
+ }
52
+ export interface FindGraphForRepoParams {
53
+ id?: string;
54
+ github_url?: string;
55
+ }
56
+ export interface StatsConcept {
57
+ term: string;
58
+ entries: number;
59
+ samples: string[];
60
+ }
61
+ export interface StatsJson {
62
+ schema_version: number;
63
+ generated_at: string;
64
+ totals?: {
65
+ entries: number;
66
+ nodes: number;
67
+ edges: number;
68
+ };
69
+ kinds?: unknown[];
70
+ languages?: unknown[];
71
+ concepts: StatsConcept[];
72
+ [key: string]: unknown;
73
+ }
74
+ export type FetchImpl = (input: string | URL, init?: {
75
+ signal?: AbortSignal;
76
+ }) => Promise<{
77
+ ok: boolean;
78
+ status: number;
79
+ statusText: string;
80
+ json: () => Promise<unknown>;
81
+ text: () => Promise<string>;
82
+ }>;
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ // Types for the understand-quickly registry. The live schema is owned by the
2
+ // parent project under `schemas/`; we duplicate just the surface this MCP
3
+ // server consumes. Anything we do not use is typed as `unknown` so that we
4
+ // stay forward-compatible with future schema additions.
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,0EAA0E;AAC1E,2EAA2E;AAC3E,wDAAwD"}