A Blazor wrapper for the WebMCP browser API.
Blazor.WebMCP
A Blazor wrapper for the WebMCP browser API. The Web API enables the browser to provide tools that can be accessed by AI agents and assistive technologies to create collaborative, human-in-the-loop workflows. This project implements a wrapper around the API for Blazor so that we can easily and safely expose our own tools in C# through the WebMCP API.
The browser API is not stable yet, so this project might break in the future if the API changes
Demo
The sample project can be demoed at https://kristofferstrube.github.io/Blazor.WebMCP/
On each page, you can find the corresponding code for the example in the top right corner.
On the API Coverage Status page, you can see how much of the WebIDL specs this wrapper has covered.
Getting started
Prerequisites
You need to install .NET 7.0 or newer to use the library.
Installation
You can install the package via NuGet with the Package Manager in your IDE or alternatively using the command line:
dotnet add package KristofferStrube.Blazor.WebMCP
Usage
Using the library you can add your own WebMCP tools to your web page. First you need to register a service in your service collection using the following extension:
builder.Services.AddModelContextService();
Then in some page you can inject the IModelContextService to register your own tool.
@using KristofferStrube.Blazor.DOM
@using KristofferStrube.Blazor.WebMCP
@implements IAsyncDisposable
@inject IModelContextService ModelContextService
@inject IJSRuntime JSRuntime
<PageTitle>Blazor WebMCP</PageTitle>
<h1>@contentFromAI</h1>
@code {
string contentFromAI = "";
SupportStatus browserSupport;
AbortController? toolUnregisterController;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender) return;
ModelContextTool<ToolArguments, string> tool = new()
{
Name = "WriteContent",
Description = "This tool can write some content to the website.",
Execute = async (ToolArguments input, ModelContextClient? client) =>
{
contentFromAI = input.Message;
await InvokeAsync(StateHasChanged);
return "Content was written to the website.";
}
};
toolUnregisterController = await AbortController.CreateAsync(JSRuntime);
await using AbortSignal toolUnregisterSignal = await toolUnregisterController.GetSignalAsync();
await ModelContextService.RegisterToolAsync(tool, new ModelContextRegisterToolOptions()
{
Signal = toolUnregisterSignal
});
}
public record ToolArguments(string Message);
public async ValueTask DisposeAsync()
{
if (toolUnregisterController is not null)
{
await toolUnregisterController.AbortAsync();
await toolUnregisterController.DisposeAsync();
}
}
}
In the above example we also unregister our tool once the user navigated away from the specific page by implementing AsyncDisposable. This is especially important in Blazor WASM where navigation does not reload the page.
Related repositories
The library uses the following other packages to support its features:
- https://github.com/KristofferStrube/Blazor.WebIDL (To make error handling JSInterop)
Related articles
This repository was built with help from the following series of articles: