@@ -242,7 +242,10 @@ class RSSAggregator {
242
242
const itemsPerFeed = Math . ceil ( limit / this . feeds . size ) ;
243
243
244
244
this . feeds . forEach ( ( feed , id ) => {
245
- if ( ! category || feed . category === category ) {
245
+ if ( ! category ||
246
+ ( feed . category && feed . category . toLowerCase ( ) === category . toLowerCase ( ) ) ||
247
+ ( feed . category && feed . category . toLowerCase ( ) . includes ( category . toLowerCase ( ) ) ) ||
248
+ ( feed . title && feed . title . toLowerCase ( ) . includes ( category . toLowerCase ( ) ) ) ) {
246
249
feedPromises . push ( this . getFeedItems ( id , itemsPerFeed ) ) ;
247
250
}
248
251
} ) ;
@@ -314,6 +317,39 @@ class RSSAggregator {
314
317
315
318
return Array . from ( categories ) . sort ( ) ;
316
319
}
320
+
321
+ getCategoryByKeyword ( keyword : string ) : string | null {
322
+ const categories = this . getCategories ( ) ;
323
+ const lowercaseKeyword = keyword . toLowerCase ( ) ;
324
+
325
+ const exactMatch = categories . find ( c => c . toLowerCase ( ) === lowercaseKeyword ) ;
326
+ if ( exactMatch ) return exactMatch ;
327
+
328
+ const partialMatch = categories . find ( c =>
329
+ c . toLowerCase ( ) . includes ( lowercaseKeyword ) ||
330
+ lowercaseKeyword . includes ( c . toLowerCase ( ) . split ( ' ' ) [ 0 ] ) ) ;
331
+ if ( partialMatch ) return partialMatch ;
332
+
333
+ const keywordMap : Record < string , string [ ] > = {
334
+ 'tech' : [ 'tech' , 'technology' , 'programming' , 'software' , 'developer' , 'ai' ] ,
335
+ 'news' : [ 'news' , 'headlines' , 'current' ] ,
336
+ 'business' : [ 'business' , 'finance' , 'economy' , 'market' ] ,
337
+ 'health' : [ 'health' , 'medical' , 'wellness' , 'fitness' ] ,
338
+ 'science' : [ 'science' , 'research' , 'study' , 'discovery' ] ,
339
+ 'sports' : [ 'sports' , 'game' , 'team' , 'player' ]
340
+ } ;
341
+
342
+ for ( const [ category , keywords ] of Object . entries ( keywordMap ) ) {
343
+ if ( keywords . some ( k => lowercaseKeyword . includes ( k ) ) ) {
344
+ const categoryMatch = categories . find ( c =>
345
+ c . toLowerCase ( ) . includes ( category ) ||
346
+ c . toLowerCase ( ) === category ) ;
347
+ if ( categoryMatch ) return categoryMatch ;
348
+ }
349
+ }
350
+
351
+ return null ;
352
+ }
317
353
}
318
354
319
355
const rssAggregator = new RSSAggregator ( ) ;
@@ -462,12 +498,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
462
498
}
463
499
}
464
500
else {
465
- const categories = rssAggregator . getCategories ( ) ;
501
+ const matchedCategory = rssAggregator . getCategoryByKeyword ( command ) ;
502
+
503
+ if ( matchedCategory ) {
504
+ console . error ( `Matched category "${ matchedCategory } " from query "${ command } "` ) ;
505
+ const items = await rssAggregator . getAllFeedItems ( matchedCategory , limit ) ;
506
+ return formatItemsResponse ( items , `Latest ${ limit } articles in ${ matchedCategory } ` ) ;
507
+ }
466
508
467
- if ( categories . some ( c => c . toLowerCase ( ) === command . toLowerCase ( ) ) ) {
468
- const categoryName = categories . find ( c => c . toLowerCase ( ) === command . toLowerCase ( ) ) ;
469
- const items = await rssAggregator . getAllFeedItems ( categoryName , limit ) ;
470
- return formatItemsResponse ( items , `Latest ${ limit } articles in ${ categoryName } ` ) ;
509
+ if ( command . includes ( 'news' ) || command . includes ( 'tech' ) ||
510
+ command . includes ( 'sport' ) || command . includes ( 'science' ) ||
511
+ command . includes ( 'business' ) || command . includes ( 'health' ) ) {
512
+ console . error ( `Using keyword query for "${ command } "` ) ;
513
+ const items = await rssAggregator . getAllFeedItems ( command , limit ) ;
514
+ return formatItemsResponse ( items , `Latest ${ limit } articles matching '${ command } '` ) ;
515
+ }
516
+
517
+ const words = command . split ( / \s + / ) ;
518
+ if ( words . length > 1 ) {
519
+ for ( const word of words ) {
520
+ if ( word . length < 3 ) continue ;
521
+
522
+ const matchedKeywordCategory = rssAggregator . getCategoryByKeyword ( word ) ;
523
+ if ( matchedKeywordCategory ) {
524
+ console . error ( `Matched category "${ matchedKeywordCategory } " from partial keyword "${ word } " in query "${ command } "` ) ;
525
+ const items = await rssAggregator . getAllFeedItems ( matchedKeywordCategory , limit ) ;
526
+ return formatItemsResponse ( items , `Latest ${ limit } articles in ${ matchedKeywordCategory } matching '${ command } '` ) ;
527
+ }
528
+ }
471
529
}
472
530
473
531
return {
0 commit comments