@@ -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