Recursive AI

Coming from the official C# SDK

All onemodelcontext docs

A task map for developers who know the official C# SDK (ModelContextProtocol, ModelContextProtocol.AspNetCore) and want the same thing in OneModelContext. It lists where to look, not which is better: the two libraries make different choices (this one has a BCL-only core, source-generated tools and a protocol-era layer under a single API), and either may suit a project.

The left column follows the official SDK's published documentation (csharp.sdk.modelcontextprotocol.io, Microsoft Learn). Nothing is mapped one-to-one by shape; each row says what to write here. Samples with the same names live in samples/.

Packages

TaskThereHere
Core client and low-level serverModelContextProtocol.CoreRecursiveAI.OneModelContext (base class library only)
Hosting, DI, attribute discoveryModelContextProtocolRecursiveAI.OneModelContext for discovery (the generator ships inside it); RecursiveAI.OneModelContext.Hosting for DI
HTTP server on ASP.NET CoreModelContextProtocol.AspNetCoreRecursiveAI.OneModelContext.AspNetCore; the core also has a small built-in HTTP listener
Tools as AIFunctionsMcpClientTool is an AIFunctionRecursiveAI.OneModelContext.Extensions.AI (ToAIFunctionsAsync())

Tasks

TaskThereHere
Declare a tool[McpServerToolType] class, [McpServerTool, Description("...")] methodpartial class, [Tool] on the method. The description and parameter descriptions come from /// <summary> and /// <param> comments; the generator writes the schema and an AOT-safe invoker. Annotations are properties: [Tool(ReadOnly = true)].
Declare a resource[McpServerResourceType] / [McpServerResource][Resource("notes://{title}")] on a method of the same partial class
Declare a prompt[McpServerPromptType] / [McpServerPrompt][Prompt] on a method
Register what the generator found.WithToolsFromAssembly()new Notebook().AddTo(server); Notebook implements IContextRegistrar, so it can be passed straight to ModelContext.ServeAsync
Register at runtimeMcpServerTool.Create(...) and the server's collectionsserver.Tools.Add(new ToolDefinition(name, description, schema), handler), and server.Resources, server.Prompts
Quick lambda(use a delegate with the tool factory)server.Tool("name", lambda); reflection based, so it is marked not trimmable and not NativeAOT-safe
Run a server over stdioAddMcpServer().WithStdioServerTransport() on a hostawait ModelContext.ServeAsync(new Notebook());
Run over HTTP, smallASP.NET Core MapMcp()await ModelContext.ServeHttpAsync(new Notebook(), port: 3001); (built-in listener, loopback only)
Host over HTTP on ASP.NET Coreapp.MapMcp()app.MapModelContext("/mcp", server), then .RequireAuthorization() once authentication is configured
DI hostingservices.AddMcpServer()...services.AddContextServer<Notebook>().UseStdio() (or .UseListener(port: 3001)) from .Hosting; scoped services through context.GetRequiredService<T>()
Reach the server object in a toola parameter of type McpServera parameter of type RequestContext (also carries the cancellation token, progress, the signed-in principal and ConfirmAsync/ElicitAsync)
Connect a client to a stdio serverStdioClientTransport + McpClient.CreateAsyncawait ModelContext.ConnectAsync("npx -y some-server") (a command line), or ContextClient.ConnectAsync(ContextTransport.Process(...))
Connect over HTTPHttpClientTransportawait ModelContext.ConnectAsync(new Uri("https://host/mcp")); pass your own HttpClient through ContextTransport.Http(uri, httpClient)
List and call toolsListToolsAsync, CallToolAsync(name, dictionary)client.ListToolsAsync(), client.CallToolAsync(name, arguments); the result has .Text, .Content, .Structured and .IsError
Resources and prompts (client)ListResourcesAsync, ReadResourceAsync, GetPromptAsyncthe same three names on ContextClient, plus ListResourceTemplatesAsync, ListPromptsAsync, CompleteAsync
ProgressIProgress<ProgressNotificationValue>await context.ReportProgressAsync(done, total, message)
Ask the user (elicitation)server.ElicitAsync(new ElicitRequestParams { ... })await context.ConfirmAsync("Delete 3 files?") for yes/no, or context.ElicitAsync<T>(message, schema, typeInfo); see the replay rule in multi-round-trip.md
Answer elicitation on the clientElicitationHandler in McpClientOptions.HandlersonConfirm: / onElicit: arguments of ModelContext.ConnectAsync, or the same on ContextClientOptions
Require sign-in on the serverASP.NET Core authentication, then [Authorize]ResourceServer with a validator (JWT, introspection, static token or delegate), AddResourceServer, RequireAuthorization(); see resource-server.md
Sign in on the clientClientOAuthOptions on the HTTP transportOAuthClient and its CreateHttpClient(); see oauth-client.md
Inspect a server from a shellthe Inspectorthe Inspector, or onemodelcontext inspect <server> / call / read / prompt

Behavior that differs

  • The protocol era is negotiated for you. The client probes the modern revision (2026-07-28) and falls back to initialize for older servers; a server answers both on one endpoint. Write handlers against the modern semantics. --era / ContextClientOptions.Era pins one.
  • A handler that asks for input is re-run on the modern era. See multi-round-trip.md.
  • Tool names are snake case by default (SaveNote becomes save_note). Set Name on the attribute to choose another.
  • Unsolicited sampling, roots and logging exist but are [Obsolete] with OMC diagnostic IDs, following the revision that deprecates them.

Type names and namespaces

The official SDK uses an Mcp prefix (McpClient, McpServer, McpException, McpServerTool). OneModelContext avoids the abbreviation in public identifiers, so names differ:

ThereHere
McpClientContextClient
McpServerContextServer (the object you register on); RequestContext (what a handler receives)
McpServerTool / McpClientToolToolDefinition / Tool
McpException, McpProtocolExceptionContextException, ProtocolException (JSON-RPC error with code), AuthorizationException
ModelContextProtocol.ProtocolRecursiveAI.OneModelContext.Protocol
ModelContextProtocol.Client / .ServerRecursiveAI.OneModelContext (client and server both live in the root namespace)

A project that references both libraries can keep them apart with namespace aliases:

C#
using Official = ModelContextProtocol.Client;
using OneModelContext = RecursiveAI.OneModelContext;
 
OneModelContext.ContextClient one = await OneModelContext.ModelContext.ConnectAsync("my-server");

Both libraries can run in one process. They share nothing but the wire protocol.

Model Context Protocol® is a registered trademark of LF Projects, LLC. OneModelContext is an independent project and is not affiliated with or endorsed by LF Projects, LLC or the Model Context Protocol project.