Native.Mcp 2.1.0

dotnet add package Native.Mcp --version 2.1.0
                    
NuGet\Install-Package Native.Mcp -Version 2.1.0
                    
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="Native.Mcp" Version="2.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Native.Mcp" Version="2.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Native.Mcp" />
                    
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 Native.Mcp --version 2.1.0
                    
#r "nuget: Native.Mcp, 2.1.0"
                    
#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 Native.Mcp@2.1.0
                    
#: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=Native.Mcp&version=2.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Native.Mcp&version=2.1.0
                    
Install as a Cake Tool

Native.Mcp

Transport-agnostic Model Context Protocol (MCP) server runtime for .NET 10 Native AOT.

Native.Mcp is the protocol core: JSON-RPC 2.0 routing (initialize, tools/list, tools/call), declarative tool registration, source-generated inputSchema, input validation via Native.FluentValidation, the canonical Swepay envelope + RFC 9457 problem details, and CloudWatch EMF telemetry — all reflection-free and AOT-clean. It has no Lambda/HTTP dependency; you choose a hosting package for the transport.

Naming. Native.Mcp is the reusable library. Services that consume it follow Swepay.Mcp.{Product}.{Purpose} (e.g. Swepay.Mcp.NativeGuard.TrialProvisioner) and live in their own repos.

Hosting packages (pick one)

Package Use it when
Native.Mcp.NativeLambdaRouter Recommended. Host MCP inside NativeLambdaRouter (POST /mcp), reusing the shared Swepay routing/edge stack.
Native.Mcp.ApiGateway Front MCP directly behind API Gateway HTTP API v2, without the router.

You can also drive the dispatcher from any transport via McpJsonRpcDispatcher.DispatchAsync(string? body, McpRequestContext).

What it is / isn't

  • Transport: Streamable HTTP via a hosting package. No stdio.
  • Auth: the JWT is validated by the API Gateway JWT Authorizer before the Lambda runs. This library does not verify signatures/exp/iss/aud — it only extracts claims; per-tool authorization is done in the tools (McpExecutionContext.HasRole).
  • v0 scope: tools only (no resources/prompts), no outbound notifications/streaming.

Install

dotnet add package Native.Mcp
dotnet add package Native.Mcp.NativeLambdaRouter   # or Native.Mcp.ApiGateway

Native.Mcp bundles Native.Mcp.SourceGenerator automatically, so inputSchema generation and the AddDiscoveredTools helper are available with no extra reference.

Quickstart

1. Define a tool

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Native.Mcp;

public sealed partial class PingTool : IMcpTool<PingInput, PingOutput>
{
    public static string Name => "ping";
    public static string Description => "Returns ok. Use to verify the server is reachable.";

    public Task<McpToolResult<PingOutput>> ExecuteAsync(
        PingInput input, McpExecutionContext context, CancellationToken cancellationToken)
    {
        // Defense in depth: re-check a role even though the Authorizer already gated the call.
        if (!context.HasRole("sample-ping"))
            return Task.FromResult(McpToolResult<PingOutput>.Failure(
                McpProblems.Forbidden("Required role: sample-ping", context.RequestId)));

        return Task.FromResult(McpToolResult<PingOutput>.Success(new PingOutput { Status = "ok" }));
    }
}

public sealed record PingInput;

public sealed record PingOutput { public required string Status { get; init; } }

partial lets the source generator add a public static string InputSchemaJson (JSON Schema Draft 2020-12) derived from PingInput. Return McpToolResult.Failure(...) for expected errors — never throw for those. Unhandled exceptions are mapped to a leak-free internal error.

2. Provide a serializer context (AOT)

using System.Text.Json.Serialization;
using Amazon.Lambda.APIGatewayEvents;

[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
[JsonSerializable(typeof(APIGatewayHttpApiV2ProxyRequest))]
[JsonSerializable(typeof(APIGatewayHttpApiV2ProxyResponse))]
[JsonSerializable(typeof(PingInput))]
[JsonSerializable(typeof(PingOutput))]
public sealed partial class AppJsonContext : JsonSerializerContext;

3. Bootstrap the Lambda

var services = new ServiceCollection();

services.AddNativeMcpServer(options =>
{
    options.ServerName = "swepay-native-guard-trial-provisioner";
    options.ServerVersion = "1.0.0";

    // Option A — explicit (most readable):
    options.AddTool<PingTool, PingInput, PingOutput>(
        AppJsonContext.Default.PingInput, AppJsonContext.Default.PingOutput);

    // Option B — generated discovery (registers every IMcpTool in the assembly):
    // options.AddDiscoveredTools(AppJsonContext.Default);
});

services.AddNativeMcpTelemetry();           // CloudWatch EMF + structured logs

await using var provider = services.BuildServiceProvider();

// Recommended: host inside NativeLambdaRouter (package: Native.Mcp.NativeLambdaRouter).
var function = new McpRoutedApiGatewayFunction(provider);
var serializer = new SourceGeneratorLambdaJsonSerializer<AppJsonContext>();
var handler = (APIGatewayHttpApiV2ProxyRequest req, ILambdaContext ctx) => function.FunctionHandler(req, ctx);
await LambdaBootstrapBuilder.Create(handler, serializer).Build().RunAsync();

// Alternative without the router (package: Native.Mcp.ApiGateway):
//   services.AddNativeMcpApiGatewayHandler();
//   var mcp = provider.GetRequiredService<McpLambdaHandler>();
//   var handler = (APIGatewayHttpApiV2ProxyRequest req, ILambdaContext _) => mcp.HandleAsync(req);

See samples/Native.Mcp.Sample for a complete AOT Lambda (hosted via NativeLambdaRouter).

Response shape

Valid JSON-RPC always returns HTTP 200. Tool/validation errors are carried inside the canonical envelope (with isError: true) — never as HTTP failures. Only a malformed request body yields a JSON-RPC -32700. Notifications (no id) return HTTP 202 with an empty body.

tools/call wraps the canonical Swepay envelope in the MCP tool result:

{
  "jsonrpc": "2.0",
  "id": "step-exec-abc",
  "result": {
    "content": [{ "type": "text", "text": "{ ...envelope... }" }],
    "isError": false
  }
}

The envelope:

{
  "success": true,
  "data": { "status": "ok" },
  "error": null,
  "metadata": {
    "requestId": "1",
    "correlationId": "trial_01HX...",
    "timestamp": "2026-06-03T14:30:00.000Z",
    "durationMs": 12,
    "serverName": "swepay-native-guard-trial-provisioner",
    "serverVersion": "1.0.0"
  }
}

Error catalog (emitted by the runtime)

Situation Transport Payload
Malformed JSON body HTTP 200 JSON-RPC error -32700 Parse error
jsonrpc != "2.0" / missing method HTTP 200 JSON-RPC error -32600 Invalid Request
Unknown method HTTP 200 JSON-RPC error -32601 Method not found
tools/call missing name HTTP 200 JSON-RPC error -32602
tools/call unknown tool HTTP 200 JSON-RPC error -32602, data: { "tool": "..." }
Notification (no id) HTTP 202 empty body
Arguments don't match schema HTTP 200 envelope isError, type .../common/validation-failed
INativeValidator<TInput> failed HTTP 200 envelope isError, type .../common/validation-failed
Tool returned Failure(...) HTTP 200 envelope isError, the tool's problem
Tool threw HTTP 200 envelope isError, type .../common/internal-errorno ex.Message/stack trace (LGPD)
Caller lacks required role (in-tool) HTTP 200 envelope isError, type .../common/forbidden
Authorizer rejected the JWT HTTP 401 returned by API Gateway, before the Lambda runs

Problem-type URIs resolve to the Swepay error catalog at https://errors.swepay.com.br. The runtime never logs the raw JWT, PII claims (email/sub), exception messages or stack traces in any response. Full exception detail is written to CloudWatch logs internally.

Telemetry

AddNativeMcpTelemetry() emits CloudWatch EMF metrics to stdout — mcp.tools.call.count, mcp.tools.call.duration_ms, mcp.tools.list.count, mcp.initialize.count, mcp.protocol.errors.count, mcp.validation.failures.count, mcp.role.denied.count — plus a structured JSON log line per call. Plug in distributed tracing by registering an IMcpTracer.

Native AOT notes

  • All runtime serialization goes through source-generated JsonTypeInfo — pass your context to AddTool / AddDiscoveredTools.
  • The DataAnnotations length attributes ([MaxLength], [MinLength], [StringLength]) emit IL2026 under PublishAot because their validators use reflection. Native.Mcp reads them only at compile time, so they are safe — but to keep an AOT build warning-free, express length with [RegularExpression] or a Native.FluentValidation rule, or suppress IL2026 for those members. [Required], [Description], [Range], [RegularExpression] are AOT-clean.

Troubleshooting

  • tools/call returns -32602 for a registered tool — the name must match IMcpTool.Name exactly (snake_case, case-sensitive).
  • InvalidOperationException: context does not declare a JsonTypeInfo — add [JsonSerializable(typeof(YourInput/Output))] to the context passed to AddTool.
  • Empty inputSchema in tools/list — the tool class must be partial and top-level for the generator to emit InputSchemaJson.
  • Validation never runs — register INativeValidator<TInput> in DI; the bridge resolves it per call.

License

MIT.

Product Compatible and additional computed target framework versions.
.NET 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 (3)

Showing the top 3 NuGet packages that depend on Native.Mcp:

Package Downloads
Native.Mcp.Testing

Test helpers for Native.Mcp: in-memory MCP host, JSON-RPC test client, fluent builders, and Shouldly assertion helpers for the canonical Swepay envelope.

Native.Mcp.NativeLambdaRouter

Hosts a Native.Mcp server inside NativeLambdaRouter: maps a single POST /mcp route to the MCP JSON-RPC dispatcher, reusing the router's routing, claims extraction and Lambda entry point. The recommended way to run an MCP server in the Swepay Native ecosystem.

Native.Mcp.ApiGateway

API Gateway HTTP API v2 transport for Native.Mcp: adapts the proxy event into the MCP dispatcher and back, for Lambdas that front MCP directly (without NativeLambdaRouter).

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 95 6/5/2026
2.0.0 56 6/5/2026
1.0.0 45 6/4/2026