---
title: "Host a server on ASP.NET Core"
url: https://recursiveai.org/onemodelcontext/cookbook/host-on-aspnet-core/
description: "Add a protocol endpoint to an ASP.NET Core app alongside your existing routes."
version: "1.0.1"
---

# Host a server on ASP.NET Core

**OneModelContext** is a free, open-source .NET SDK for the Model Context Protocol® from Recursive AI. MIT or Apache-2.0, no native dependencies.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneModelContext.AspNetCore) · [GitHub](https://github.com/recursive-ai-oss/onemodelcontext-csharp) · [Docs](https://recursiveai.org/onemodelcontext/docs/)

Add a Model Context Protocol® endpoint to your web app.

```shell
dotnet add package RecursiveAI.OneModelContext.AspNetCore
```

Use a Web SDK project (`Microsoft.NET.Sdk.Web`), as in the download.

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

```csharp
using RecursiveAI.OneModelContext;
using Microsoft.AspNetCore.Builder;
using RecursiveAI.OneModelContext.AspNetCore;

var builder =
    WebApplication.CreateSlimBuilder(args);
var app = builder.Build();
var server =
    new ContextServer("calculator", "1.0.0");
new Calculator().AddTo(server);
app.MapModelContext("/tools", server);
await app.RunAsync();

public partial class Calculator
{
    [Tool] public int Add(int a,int b)=>a+b;
}
```

**[Download this example (.zip)](https://recursiveai.org/onemodelcontext/cookbook/host-on-aspnet-core/host-on-aspnet-core.zip)**: unzip, then `dotnet run`.

The snippet at the top keeps serving until stopped. Its endpoint is the listening URL ASP.NET Core prints at startup, followed by `/tools`.

## The full program

The download starts ASP.NET Core on a free loopback port, maps `/tools`, makes a real HTTP tool call and stops. To keep hosting, replace the demonstration client and `StopAsync` with `await app.WaitForShutdownAsync();`.

```csharp
using RecursiveAI.OneModelContext;
using RecursiveAI.OneModelContext.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Logging;
using System.Net;

var builder = WebApplication.CreateSlimBuilder(args);
builder.Logging.ClearProviders();
await using var app = builder.Build();
app.Urls.Add($"http://{IPAddress.Loopback}:0");
var server = new ContextServer("calculator", "1.0.0");
new Calculator().AddTo(server);
app.MapModelContext("/tools", server);
await app.StartAsync();
var url = new Uri(app.Urls.Single() + "/tools");
await using (var client = await ModelContext.ConnectAsync(ContextTransport.Http(url)))
{
    Console.WriteLine("Host: ASP.NET Core");
    Console.WriteLine((await client.CallToolAsync("add", new { a = 2, b = 40 })).Text);
}
await app.StopAsync();

public partial class Calculator
{
    /// <summary>Add two integers.</summary>
    [Tool]
    public int Add(int a, int b) => a + b;
}
```

`dotnet run` prints:

```text
Host: ASP.NET Core
42
```

A route that was not mapped returns HTTP 404; make sure the client uses the same path as `MapModelContext`.

The core package includes the source generator for `[Tool]` methods. Keep the class `partial`; the generator supplies its registration code. The download pins the package version in `Example.csproj`.

## Variations

Change the arguments. Replace the tool call inside the full program with:

```csharp
Console.WriteLine((await client.CallToolAsync(
    "add", new { a = 10, b = 32 })).Text);
```

```text
42
```

## Related recipes

- [Build a Model Context Protocol® server in C#](https://recursiveai.org/onemodelcontext/cookbook/build-a-server-in-csharp/)
- [Connect to a Model Context Protocol® server in C#](https://recursiveai.org/onemodelcontext/cookbook/connect-to-a-server/)
- [Serve the Model Context Protocol® over HTTP without ASP.NET](https://recursiveai.org/onemodelcontext/cookbook/serve-over-http-without-aspnet/)
- [Require OAuth sign-in on a Model Context Protocol® server](https://recursiveai.org/onemodelcontext/cookbook/require-sign-in-on-a-server/)
- [Sign in to a protected Model Context Protocol® server in .NET](https://recursiveai.org/onemodelcontext/cookbook/sign-in-to-a-protected-server/)

---

## The short answer

To host an MCP server (Model Context Protocol®) on ASP.NET Core, install `RecursiveAI.OneModelContext.AspNetCore`, create a `ContextServer`, register your generated tool class with `AddTo` and map it with `app.MapModelContext`. This creates a Streamable HTTP endpoint within your web app, not a second web server beside it.

The example maps `/tools`. That path is arbitrary, but the client must use the same path. The full program starts the web application, calls it over HTTP and stops it so `dotnet run` produces a useful result immediately.

## How do I run my own server on ASP.NET Core?

Use the Web SDK and target .NET 10. The package reference brings the ASP.NET Core adapter and core library; you don’t need a separate hosting package merely to map an endpoint. The project in the download shows the SDK and pinned reference.

Build the web application, create the protocol server and add tool registrations before mapping. The `Calculator` class is partial because the source generator supplies `AddTo`. Its `[Tool]` method becomes the discoverable `add` operation.

The snippet at the top uses `RunAsync` to keep hosting until shutdown. The downloadable program deliberately differs at the end: it uses `StartAsync`, connects a client to the bound address, calls the tool and then stops the app. The free port avoids conflicts with other local examples. Replacing that demonstration lifecycle with the normal web-host lifetime leaves the endpoint available to other clients.

## How do I connect a C# client to the HTTP endpoint?

Connect with `ContextTransport.Http` and the complete URL, including `/tools`. The full program gets the actual bound address from the app and appends that route. It then uses the ordinary client API to call `add`, just as a stdio client would.

If the client receives HTTP 404, check the path before debugging tool registration. A host can be reachable while the route is wrong. Conversely, reaching the route does not mean a tool named after your C# method exists: the generated name for `Add` is `add`.

One endpoint handles the library’s supported modern and legacy protocol eras. Do not create separate web routes just to split the calculator by era. The [getting-started ASP.NET Core example](https://recursiveai.org/onemodelcontext/docs/getting-started/) demonstrates both on the same mapping, and the [HTTP limits guide](https://recursiveai.org/onemodelcontext/docs/http-limits/) explains how requests differ.

## How do I add authentication to a protocol server?

Choose authentication explicitly; mapping the route alone does not require sign-in. Middleware added before `MapModelContext`, such as authentication or rate limiting, runs before the protocol handler. The library also supports `.RequireAuthorization()` when the host has an authentication scheme configured. These are web-host concerns, not attributes to add to the calculator’s arithmetic method.

For OAuth-aware resource protection, configure a `ResourceServer` with the endpoint’s resource URI and a token validator, then provide it through `StreamableHttpOptions`. This supplies the protocol’s protected-resource metadata and challenges as documented in the [resource-server guide](https://recursiveai.org/onemodelcontext/docs/resource-server/). A resource URI is configuration, not a value to derive from an untrusted Host header.

For deployment, keep the boundary clear: ASP.NET Core owns network binding, middleware and application lifetime; OneModelContext owns the protocol endpoint. The local self-call above demonstrates routing and tool invocation, not a complete public deployment or sign-in system. The [OAuth server recipe](https://recursiveai.org/onemodelcontext/cookbook/require-sign-in-on-a-server/) includes a runnable local authorization exchange.
