Editor/Registry/ToolSearch.cs
using System;
using System.Collections.Generic;
using System.Linq;
namespace SboxMcp.Registry;
/// <summary>Small deterministic lookup kept separate from registry mechanics.</summary>
public static class ToolSearch
{
public static IReadOnlyList<RegisteredTool> Search(
this ToolRegistry registry, string query, int limit, string category = null )
{
var tools = registry.Tools.Where( tool => tool.IsAvailable
&& (category is null || string.Equals( tool.Meta.Category.ToString(), category, StringComparison.OrdinalIgnoreCase )) );
var exact = tools.FirstOrDefault( tool => string.Equals( tool.Meta.Name, query, StringComparison.OrdinalIgnoreCase ) );
if ( exact is not null )
return new[] { exact };
var words = query.Split( new[] { ' ', '_', '-', '.', '/' }, StringSplitOptions.RemoveEmptyEntries )
.Where( word => word.Length > 2 )
.ToArray();
return tools
.Select( tool => new
{
Tool = tool,
Score = words.Sum( word =>
tool.Meta.Name.Contains( word, StringComparison.OrdinalIgnoreCase ) ? 3 :
tool.Meta.Description.Contains( word, StringComparison.OrdinalIgnoreCase ) ? 1 : 0 )
} )
.Where( match => match.Score > 0 )
.OrderByDescending( match => match.Score )
.ThenBy( match => match.Tool.Meta.Name, StringComparer.Ordinal )
.Take( limit )
.Select( match => match.Tool )
.ToArray();
}
}