Configuration & protocol

Every option lives on NabuMcpOptions. This page also covers the supported MCP protocol revisions, the official SDK adapter, target frameworks and known limitations.

Options reference

OptionDefaultMeaning
Path/mcpEndpoint path.
ServerName, ServerVersion, Instructionsentry assemblyReported during initialize / server/discover.
CacheTtlMilliseconds60000ttlMs freshness hint on cacheable 2026-07-28 results.
ExposeAllActionsfalsePublish every action and route handler, not just annotated ones. [McpIgnore] still wins.
RequireAuthorization, AuthorizationPolicy, AuthenticationSchemesoffProtects the MCP endpoint.
ToolVisibilityAllAdvertise every tool, or only the ones the caller is authenticated / authorized for.
AnonymousAccessNoneHow much of a protected endpoint an unauthorized caller may reach.
ToolNameFactorycontroller_action snake_caseBuilds tool names.
ToolFilternoneLast-chance predicate to drop discovered tools.
FlattenBodyParametertrueLift [FromBody] model properties to the top level.
ExposeHeaderParametersfalsePublish [FromHeader] parameters as tool inputs.
ForwardedHeaders, ForwardedHeaderPrefixescredentials + tracingHeaders copied onto tool requests.
ProtectedHeaderscredentials + proxy metadataHeaders a model-supplied argument may never override.
PropagateUsertrueSeed the caller's principal onto the synthetic request.
MaxResponseBytes1 MiBCap on the buffered response body; bounds memory, larger bodies are truncated and flagged.
IncludeStructuredContenttrueEmit JSON responses as MCP structuredContent.
TreatErrorStatusAsToolErrortrueMap HTTP >= 400 to isError: true.
MaxSchemaDepth8Nesting limit for generated schemas.
UseXmlDocumentationtrueRead <summary>/<param> from the XML docs file.
StringEnumsInRequestBodyauto-detectWhether the API accepts enum names in JSON bodies.

Protocol support

Streamable HTTP transport, JSON-RPC 2.0. The server is dual-era: it speaks the stateless revision 2026-07-28 (version and capabilities declared in _meta on every request, no handshake, no sessions) and the legacy revisions 2025-06-18, 2025-03-26 and 2024-11-05 (negotiated at initialize). A request that declares a protocol version in _meta — or calls server/discover — is served under 2026-07-28 semantics; everything else stays on the legacy path, so existing clients are unaffected.

On the 2026-07-28 path the mirrored request headers (MCP-Protocol-Version, Mcp-Method, Mcp-Name) are validated against the body (-32020 on mismatch), an unsupported version is answered with -32022 and the supported list, results carry resultType, the server's identity in _meta, and ttlMs/cacheScope on cacheable results, and no session id is ever minted.

MethodBehaviour
server/discover(2026-07-28) Supported versions, capabilities, identity and instructions.
initialize(legacy) Negotiates the version, advertises the tools capability, returns a session id.
tools/listEvery discovered tool with its schema and annotations.
tools/callReplays the action; returns text content, structuredContent, and isError.
ping(legacy) Answered with an empty result.
notifications/*Accepted with 202 and no body.
resources/list, resources/templates/list, prompts/listAnswered as empty for client compatibility.

POST returns application/json, or a single server-sent event when the client accepts only text/event-stream. Batched arrays are supported on the legacy path. DELETE ends a legacy session (the server is stateless, so this is a no-op). GET returns 405.

Failures are reported at the right layer: a bad tool name or a missing required argument is a JSON-RPC error (-32602), while an HTTP error from the action — 400 from validation, 403 from a policy, 404 from the action — is a successful JSON-RPC response carrying isError: true, which is what lets a model read and react to it.

Using the official MCP SDK as the protocol layer

Nabu's value is the ASP.NET Core bridge — controller discovery, schema generation, authorization-aware visibility and pipeline replay — not the JSON-RPC plumbing. The protocol layer is therefore replaceable. The Nabu.Mcp.ModelContextProtocol package serves Nabu's tools through the official ModelContextProtocol C# SDK instead of the built-in layer:

services.AddNabuMcp(options => { ... })
        .UseOfficialMcpProtocol();

app.UseNabuMcp(); // now mounts the official SDK's Streamable HTTP endpoint at the same path

The SDK owns the wire protocol — transport, protocol revisions, sessions — and Nabu answers tools/list and tools/call behind it, with the same visibility rules and pipeline replay as the built-in layer. The transport defaults to the SDK's stateless mode, matching Nabu's design; pass a configuration delegate to change that or any other transport option:

services.AddNabuMcp().UseOfficialMcpProtocol(transport => transport.Stateless = false);

Choose the built-in layer for netstandard2.0/ASP.NET Core 2.x compatibility and zero extra dependencies; choose the official layer (net8.0+) to track the protocol at the SDK's pace and pick up its transport features. RequireAuthorization is honoured on the mapped endpoint; the partial AnonymousAccess modes leave the endpoint anonymous and rely on the replayed pipeline to authorize each call.

samples/Nabu.Sample.OfficialSdk is a complete runnable example: a small book-catalog API published through the official SDK on a custom route (app.UseNabuMcp("/books/mcp")), with the same JWT setup and per-caller tool exposure as the Todo sample — showing that the authorization story is identical on both protocol layers.

Target frameworks

The library multi-targets netstandard2.0, net8.0 and net10.0:

Version-specific APIs are handled at runtime rather than by feature-flagging behaviour: the HTTP verb is read through IActionHttpMethodProvider, which has been stable since 1.0, and the enum representation is detected reflectively so the same code path serves System.Text.Json and Newtonsoft.Json.

Limitations

Releasing

Publishing to nuget.org is driven by tags — the tag is the single source of truth for the package version:

git tag v1.2.3
git push origin v1.2.3

GitHub Actions then restores, builds, tests, packs at 1.2.3, pushes the .nupkg and its .snupkg symbol package to nuget.org via NuGet Trusted Publishing (no API key to store), and opens a GitHub release with generated notes. A tag containing a hyphen (v1.2.3-rc.1) is published as a prerelease.