Skip to content

Commit 168a771

Browse files
fix(mcp): improve search relevance and multi-word query handling
1 parent c5897bf commit 168a771

1 file changed

Lines changed: 31 additions & 13 deletions

File tree

‎mcp/src/index.ts‎

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -116,19 +116,22 @@ function matches(r: Resource, f: {
116116
compensationType?: string; category?: string; macroCategory?: string;
117117
}): boolean {
118118
if (f.query) {
119-
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-
125-
const hay = [
126-
r.title, r.description, ...(r.dataTypes ?? []),
127-
...(r.organizations?.map((o) => o.name) ?? []), ...availableIn(r), ...(r.macroCategories ?? []),
128-
r.compensationType, r.entityCategory, r.entitySubType, ...syns
129-
].filter(Boolean).map(String).map(lc).join(" ");
130-
for (const t of tokens) {
131-
if (!hay.includes(t)) return false;
119+
const STOP = new Set(["a","an","the","for","of","to","in","on","and","or","i","me","my","can",
120+
"do","find","want","need","where","study","studies","research","program","programs",
121+
"project","projects","opportunity","opportunities","participate","join","looking","near"]);
122+
const tokens = f.query.toLowerCase().split(/\s+/).filter(Boolean).filter((t) => !STOP.has(t));
123+
if (tokens.length) {
124+
const syns: string[] = [];
125+
if (r.compensationType === "payment") syns.push("paid", "money", "cash", "compensation");
126+
if (r.compensationType === "donation") syns.push("donate", "volunteer", "free");
127+
if (r.compensationType === "mixed") syns.push("paid", "donate", "compensation");
128+
129+
const hay = [
130+
r.title, r.description, ...(r.dataTypes ?? []),
131+
...(r.organizations?.map((o) => o.name) ?? []), ...availableIn(r), ...(r.macroCategories ?? []),
132+
r.compensationType, r.entityCategory, r.entitySubType, ...syns
133+
].filter(Boolean).map(String).map(lc).join(" ");
134+
if (!tokens.some((t) => hay.includes(t))) return false;
132135
}
133136
}
134137
if (f.dataType && !(r.dataTypes ?? []).some((d) => lc(d).includes(lc(f.dataType)))) return false;
@@ -158,6 +161,10 @@ function getScore(r: Resource, q?: string): number {
158161
if (lc(r.description).includes(t)) score += 2;
159162
if ((r.dataTypes ?? []).join(" ").toLowerCase().includes(t)) score += 5;
160163
if (lc(r.entityCategory).includes(t)) score += 5;
164+
if (["paid","money","cash","compensation"].includes(t) &&
165+
(r.compensationType === "payment" || r.compensationType === "mixed")) score += 6;
166+
if (["donate","donation","volunteer","free"].includes(t) &&
167+
(r.compensationType === "donation" || r.compensationType === "mixed")) score += 6;
161168
}
162169
return score;
163170
}
@@ -216,6 +223,17 @@ export class YourselfToScienceMCP extends McpAgent {
216223
if (args.query) {
217224
hits = hits.sort((a, b) => getScore(b, args.query) - getScore(a, args.query));
218225
}
226+
if (args.country) {
227+
hits = hits.sort((a, b) => {
228+
const aAvail = availableIn(a).map(lc);
229+
const bAvail = availableIn(b).map(lc);
230+
const aExact = aAvail.some((c) => c.includes(lc(args.country!)));
231+
const bExact = bAvail.some((c) => c.includes(lc(args.country!)));
232+
if (aExact && !bExact) return -1;
233+
if (!aExact && bExact) return 1;
234+
return 0;
235+
});
236+
}
219237
const offset = args.offset ?? 0;
220238
const limit = args.limit ?? 20;
221239
const paginated = hits.slice(offset, offset + limit);

0 commit comments

Comments
 (0)