ElBruno.ModelContextProtocol.MCPToolRouter 0.5.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package ElBruno.ModelContextProtocol.MCPToolRouter --version 0.5.1
                    
NuGet\Install-Package ElBruno.ModelContextProtocol.MCPToolRouter -Version 0.5.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ElBruno.ModelContextProtocol.MCPToolRouter" Version="0.5.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ElBruno.ModelContextProtocol.MCPToolRouter" Version="0.5.1" />
                    
Directory.Packages.props
<PackageReference Include="ElBruno.ModelContextProtocol.MCPToolRouter" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ElBruno.ModelContextProtocol.MCPToolRouter --version 0.5.1
                    
#r "nuget: ElBruno.ModelContextProtocol.MCPToolRouter, 0.5.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ElBruno.ModelContextProtocol.MCPToolRouter@0.5.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ElBruno.ModelContextProtocol.MCPToolRouter&version=0.5.1
                    
Install as a Cake Addin
#tool nuget:?package=ElBruno.ModelContextProtocol.MCPToolRouter&version=0.5.1
                    
Install as a Cake Tool

ElBruno.ModelContextProtocol

CI Build Publish to NuGet License: MIT GitHub stars

Semantic routing for MCP tools 🔀

ElBruno.ModelContextProtocol is a .NET library that makes it easy to find the right tools from Model Context Protocol (MCP) tool definitions. It uses semantic search powered by local embeddings to route prompts to the most relevant tools, enabling intelligent tool selection without external API calls.

Packages

Package NuGet Downloads Description
ElBruno.ModelContextProtocol.MCPToolRouter NuGet Downloads Semantic tool routing for MCP

MCPToolRouter

A high-performance semantic search engine for Model Context Protocol tools. MCPToolRouter indexes your MCP tool definitions and returns the most relevant tools for any prompt using vector similarity search.

Installation

dotnet add package ElBruno.ModelContextProtocol.MCPToolRouter

Quick Start

using ElBruno.ModelContextProtocol.MCPToolRouter;
using ModelContextProtocol.Protocol;

// Define your MCP tools (or get them from an MCP server)
var tools = new[]
{
    new Tool { Name = "get_weather", Description = "Get weather for a location" },
    new Tool { Name = "send_email", Description = "Send an email message" },
    new Tool { Name = "search_files", Description = "Search files by name or content" },
    new Tool { Name = "calculate", Description = "Perform mathematical calculations" },
    new Tool { Name = "translate_text", Description = "Translate text between languages" }
};

// Create the index (one-time cost, reuse for every prompt)
await using var index = await ToolIndex.CreateAsync(tools, new ToolIndexOptions { QueryCacheSize = 10 });

// Find the top-3 most relevant tools for a prompt
var results = await index.SearchAsync("What's the temperature outside?", topK: 3);

foreach (var r in results)
    Console.WriteLine($"{r.Tool.Name}: {r.Score:F3}");

Using Filtered Tools with Azure OpenAI

// using Azure; Azure.AI.OpenAI; OpenAI.Chat;

// Create Azure OpenAI ChatClient
var chatClient = new AzureOpenAIClient(
    new Uri("https://your-resource.openai.azure.com/"),
    new AzureKeyCredential("your-api-key"))
    .GetChatClient("gpt-5-mini");

// Route to relevant tools only (instead of sending ALL tools)
var relevant = await index.SearchAsync(userPrompt, topK: 3);

// Add only filtered tools to the chat call — saving tokens!
var chatOptions = new ChatCompletionOptions();
foreach (var r in relevant)
    chatOptions.Tools.Add(ChatTool.CreateFunctionTool(r.Tool.Name, r.Tool.Description ?? ""));

var response = await chatClient.CompleteChatAsync([new UserChatMessage(userPrompt)], chatOptions);

How It Works

MCPToolRouter uses semantic search to intelligently route prompts to the most relevant tools. Here's the process:

  1. Ingestion: The library ingests MCP tool definitions (name, description, and input schema)
  2. Embedding: Tool descriptions are embedded into a local vector store using ONNX embeddings (no external API calls needed)
  3. Query embedding: When you search, the user prompt is embedded using the same model
  4. Similarity search: The library finds the top-K tools via cosine similarity
  5. Tool selection: Only the relevant tools are returned — saving tokens when forwarding to LLMs

This approach enables intelligent tool selection at LLM prompt time without external API calls or round-trips.

Advanced Features

ToolIndexOptions

Configure the index behavior with ToolIndexOptions:

var options = new ToolIndexOptions
{
    QueryCacheSize = 20,                          // LRU cache for repeated queries (0 = disabled)
    EmbeddingTextTemplate = "{Name}: {Description}" // Customize how tools are embedded
};

await using var index = await ToolIndex.CreateAsync(tools, options);

Save / Load Index

Persist a pre-built index to avoid re-embedding on startup:

// Save
using var file = File.Create("tools.bin");
await index.SaveAsync(file);

// Load (instant warm-start — no re-embedding)
using var stream = File.OpenRead("tools.bin");
await using var loaded = await ToolIndex.LoadAsync(stream);

Dynamic Index (Add / Remove Tools)

Modify the index at runtime without rebuilding:

await index.AddToolsAsync(new[] { new Tool { Name = "new_tool", Description = "..." } });
index.RemoveTools(new[] { "obsolete_tool" });

Dependency Injection

Register IToolIndex as a singleton in ASP.NET Core or any DI container:

builder.Services.AddMcpToolRouter(tools, opts =>
{
    opts.QueryCacheSize = 20;
});

// Inject IToolIndex anywhere
app.MapGet("/search", async (IToolIndex index, string query)
    => await index.SearchAsync(query, topK: 3));

Custom Embedding Generator

Bring your own IEmbeddingGenerator<string, Embedding<float>> from the Microsoft.Extensions.AI ecosystem:

IEmbeddingGenerator<string, Embedding<float>> myGenerator = /* your provider */;
await using var index = await ToolIndex.CreateAsync(tools, myGenerator, options);

Samples

Six sample applications showcase different use cases for MCPToolRouter:

Sample Description Azure Required
BasicUsage Getting started — index tools and search
TokenComparison Compare token usage: all tools vs. routed
TokenComparisonMax Extreme 120+ tools scenario with rich Spectre.Console UX
FilteredFunctionCalling End-to-end function calling with filtered tools
AgentWithToolRouter Microsoft Agent Framework with semantic tool routing
FunctionalToolsValidation 52 real tools with execution validation — standard vs. routed

BasicUsage

The simplest way to get started. This sample creates a ToolIndex from MCP tool definitions, runs semantic search queries, and displays ranked results.

No Azure dependency required — perfect for exploring the library.

TokenComparison

This is the marquee sample demonstrating the dramatic token savings when using routed tools instead of sending all tools to the LLM.

The sample compares two scenarios:

  • Standard Mode: All 18 tools sent to the LLM (full context, high token cost)
  • Routed Mode: Only top-3 relevant tools sent via MCPToolRouter (filtered context, minimal tokens)

Example output:

📊 Standard Mode (18 tools):  ~1,800 input tokens
📊 Routed Mode (3 tools):     ~500 input tokens
💰 Savings:                    ~72% fewer tokens!

Azure OpenAI Setup:

This sample requires Azure OpenAI. Use user secrets to configure credentials:

cd src/samples/TokenComparison
dotnet user-secrets init
dotnet user-secrets set "AzureOpenAI:Endpoint" "https://your-resource.openai.azure.com/"
dotnet user-secrets set "AzureOpenAI:ApiKey" "your-api-key"
dotnet user-secrets set "AzureOpenAI:DeploymentName" "gpt-5-mini"

Replace:

  • your-resource with your Azure OpenAI resource name
  • your-api-key with your API key
  • Deployment name with your model (e.g., gpt-5-mini)

TokenComparisonMax

An extreme-scale demo with 120+ tool definitions across 12 categories, showcasing the dramatic token savings at scale. Uses Spectre.Console for a rich terminal experience with live-updating tables and a comprehensive summary.

Features:

  • 120+ realistic MCP tool definitions
  • Real-time token usage tracking with live tables
  • Final summary table with per-scenario and aggregate savings
  • Beautiful terminal UI via Spectre.Console

Azure OpenAI Setup:

cd src/samples/TokenComparisonMax
dotnet user-secrets init
dotnet user-secrets set "AzureOpenAI:Endpoint" "https://your-resource.openai.azure.com/"
dotnet user-secrets set "AzureOpenAI:ApiKey" "your-api-key"
dotnet user-secrets set "AzureOpenAI:DeploymentName" "gpt-5-mini"

Replace:

  • your-resource with your Azure OpenAI resource name
  • your-api-key with your API key
  • Deployment name with your model (e.g., gpt-5-mini)

💰 Cost Estimation: The TokenComparisonMax sample calculates estimated money saved based on Azure OpenAI pricing for GPT-5-mini (as of March 2026):

Token Type Cost per 1M Tokens
Input $0.25
Output $2.00
Cached Input $0.025

Pricing source: Azure OpenAI Service Pricing

Prices may vary by region and deployment type. Check the pricing page for current rates.

FilteredFunctionCalling

An end-to-end example of the real-world pattern: route tools with MCPToolRouter, send only the filtered tools to Azure OpenAI, and handle tool call responses.

Azure OpenAI Setup:

cd src/samples/FilteredFunctionCalling
dotnet user-secrets init
dotnet user-secrets set "AzureOpenAI:Endpoint" "https://your-resource.openai.azure.com/"
dotnet user-secrets set "AzureOpenAI:ApiKey" "your-api-key"
dotnet user-secrets set "AzureOpenAI:DeploymentName" "gpt-5-mini"

AgentWithToolRouter

Demonstrates MCPToolRouter integrated with the Microsoft Agent Framework (Microsoft.Agents.AI.OpenAI). The sample defines 11 function tools, uses semantic routing to filter relevant tools per prompt, and creates an AIAgent with only the filtered tools — showing how tool routing works with the modern agent paradigm.

Features:

  • 11 function tools across 6 domains (weather, email, calendar, files, math, translation)
  • Semantic tool routing via MCPToolRouter before agent creation
  • Multi-turn session demo with conversation memory
  • Supports both API key and DefaultAzureCredential authentication

Azure OpenAI Setup:

cd src/samples/AgentWithToolRouter
dotnet user-secrets init
dotnet user-secrets set "AzureOpenAI:Endpoint" "https://your-resource.openai.azure.com/"
dotnet user-secrets set "AzureOpenAI:ApiKey" "your-api-key"
dotnet user-secrets set "AzureOpenAI:DeploymentName" "gpt-5-mini"

FunctionalToolsValidation

A comprehensive validation sample with 52 real tool implementations across 8 domains (math, strings, collections, dates, conversion, encoding, statistics, hashing). Each tool performs actual computation — no stubs. The sample runs 12 test scenarios comparing standard mode (all 52 tools) vs. routed mode (top-K filtered), validating that both produce correct results while measuring token savings.

Features:

  • 52 fully functional tools with real C# implementations
  • 12 test scenarios with expected-result validation
  • Side-by-side comparison: standard vs. routed tool selection
  • Full tool-call execution loop with Azure OpenAI

Azure OpenAI Setup:

cd src/samples/FunctionalToolsValidation
dotnet user-secrets init
dotnet user-secrets set "AzureOpenAI:Endpoint" "https://your-resource.openai.azure.com/"
dotnet user-secrets set "AzureOpenAI:ApiKey" "your-api-key"
dotnet user-secrets set "AzureOpenAI:DeploymentName" "gpt-5-mini"

Building from Source

Clone the repository and build with the .NET CLI:

dotnet restore ElBruno.ModelContextProtocol.slnx
dotnet build ElBruno.ModelContextProtocol.slnx
dotnet test ElBruno.ModelContextProtocol.slnx

Documentation

More detailed documentation and examples are available in the docs/ folder.

License

This project is licensed under the MIT License — see LICENSE for details.

Author

Bruno Capuano (ElBruno)

Acknowledgments

This library is built on top of:

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.5.4 0 3/29/2026
0.5.3 52 3/28/2026
0.5.2 31 3/28/2026
0.5.1 42 3/26/2026