Skip to content

Commit 6398165

Browse files
feat: enhance search semantic recall and add discoverability tools
1 parent 8c8a3d5 commit 6398165

1 file changed

Lines changed: 40 additions & 1 deletion

File tree

‎mcp/src/index.ts‎

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,16 @@ function matches(r: Resource, f: {
117117
}): boolean {
118118
if (f.query) {
119119
const tokens = f.query.toLowerCase().split(/\s+/).filter(Boolean);
120+
const syns: string[] = [];
121+
if (r.compensationType === "payment") syns.push("paid", "money", "cash", "compensation");
122+
if (r.compensationType === "donation") syns.push("donate", "volunteer", "free");
123+
if (r.compensationType === "mixed") syns.push("paid", "donate", "compensation");
124+
120125
const hay = [
121126
r.title, r.description, ...(r.dataTypes ?? []),
122127
...(r.organizations?.map((o) => o.name) ?? []), ...availableIn(r), ...(r.macroCategories ?? []),
123-
].map(lc).join(" ");
128+
r.compensationType, r.entityCategory, r.entitySubType, ...syns
129+
].filter(Boolean).map(String).map(lc).join(" ");
124130
for (const t of tokens) {
125131
if (!hay.includes(t)) return false;
126132
}
@@ -233,6 +239,39 @@ export class YourselfToScienceMCP extends McpAgent {
233239
}
234240
);
235241

242+
this.server.registerTool(
243+
"list_categories",
244+
{ title: "List organization categories", description: "All distinct organization categories (e.g. Non-Profit, Commercial) with counts.", inputSchema: {}, annotations: RO },
245+
async () => {
246+
const all = await loadResources();
247+
const counts: Record<string, number> = {};
248+
for (const r of all) { const c = r.entityCategory; if (c) counts[c] = (counts[c] ?? 0) + 1; }
249+
return text(Object.entries(counts).sort((a, b) => b[1] - a[1]).map(([name, count]) => ({ name, count })));
250+
}
251+
);
252+
253+
this.server.registerTool(
254+
"list_compensation_types",
255+
{ title: "List compensation types", description: "All distinct compensation types (donation, payment, mixed) with counts.", inputSchema: {}, annotations: RO },
256+
async () => {
257+
const all = await loadResources();
258+
const counts: Record<string, number> = {};
259+
for (const r of all) { const c = r.compensationType; if (c) counts[c] = (counts[c] ?? 0) + 1; }
260+
return text(Object.entries(counts).sort((a, b) => b[1] - a[1]).map(([name, count]) => ({ name, count })));
261+
}
262+
);
263+
264+
this.server.registerTool(
265+
"list_organizations",
266+
{ title: "List organizations", description: "All distinct organizations running the programs, with counts.", inputSchema: {}, annotations: RO },
267+
async () => {
268+
const all = await loadResources();
269+
const counts: Record<string, number> = {};
270+
for (const r of all) for (const o of r.organizations ?? []) { const n = o.name; if (n) counts[n] = (counts[n] ?? 0) + 1; }
271+
return text(Object.entries(counts).sort((a, b) => b[1] - a[1]).map(([name, count]) => ({ name, count })));
272+
}
273+
);
274+
236275
this.server.registerTool(
237276
"get_stats",
238277
{ title: "Catalogue statistics", description: "High-level landscape stats: totals by compensation type, category, and data type.", inputSchema: {}, annotations: RO },

0 commit comments

Comments
 (0)