# ZeroMCP.net

[![NuGet Version](https://img.shields.io/nuget/v/ZeroMCP.svg)](https://www.nuget.org/packages/ZeroMCP/)
[![NuGet Downloads](https://img.shields.io/nuget/dt/ZeroMCP.svg)](https://www.nuget.org/packages/ZeroMCP/)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ZeroMCP/ZeroMCP.net/blob/main/LICENSE)
[![GitHub Stars](https://img.shields.io/github/stars/ZeroMCP/ZeroMCP.net?style=social)](https://github.com/ZeroMCP/ZeroMCP.net/stargazers)

Enterprise-grade MCP enablement for ASP.NET Core APIs.

ZeroMCP lets teams expose existing controller and minimal API endpoints as MCP (Model Context Protocol) tools, resources, templates, and prompts, without creating a second service or duplicating logic.

## Executive Summary

- **What it solves:** Connect LLM clients to established ASP.NET Core APIs safely and quickly.
- **How it works:** Annotate endpoints (`[Mcp]`, `[McpResource]`, `[McpTemplate]`, `[McpPrompt]`) or use minimal API metadata (`.AsMcp`, `.AsResource`, `.AsTemplate`, `.AsPrompt`), then map one MCP route.
- **Why enterprises adopt it:** Keeps existing auth, policy, validation, observability, and release controls in place.

## Core Capabilities

- In-process dispatch through your real ASP.NET Core pipeline
- Dual-era MCP support: modern **2026-07-28** and legacy **2024-11-05**
- Streamable HTTP MCP endpoint (`POST`; legacy GET SSE retained by default)
- `server/discover`, mirrored HTTP headers, and `subscriptions/listen`
- Optional stdio transport for local/desktop MCP clients
- Streaming tool results via `IAsyncEnumerable<T>`
- Tools, resources, templates, and prompts in one framework
- Per-tool governance (roles, policies, filters)
- Observability hooks (correlation, logs, metrics sink, OpenTelemetry tags)
- Inspector endpoints for discovery and controlled testing
- Versioned MCP routes for phased client migration

## Architecture at a Glance

1. API startup discovers MCP metadata from controllers and minimal APIs.
2. ZeroMCP builds schemas and endpoint descriptors.
3. MCP clients call `/mcp` using JSON-RPC methods.
4. ZeroMCP dispatches in-process to your original endpoint.
5. Response is normalized back into MCP-compatible output.

This model preserves middleware behavior and avoids "shadow implementations."

## Quick Start

### 1) Install package

```xml
<PackageReference Include="ZeroMCP" Version="2.*" />
```

### 2) Register and map

```csharp
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();

builder.Services.AddZeroMCP(options =>
{
    options.ServerName = "Orders Platform";
    options.ServerVersion = "1.0.0";
});

var app = builder.Build();

app.MapControllers();
app.MapZeroMCP(); // registers GET+POST /mcp

app.Run();
```

### 3) Expose endpoints as MCP

```csharp
[HttpGet("{id:int}")]
[Mcp("get_order", Description = "Retrieves an order by ID.")]
public IActionResult GetOrder(int id) => Ok(new { id });

app.MapGet("/api/health", () => Results.Ok(new { status = "ok" }))
   .AsMcp("health_check", "Returns API health status.");
```

## Enterprise Deployment Guidance

### Security baseline

- Protect MCP endpoint using existing authentication/authorization:

```csharp
app.MapZeroMCP().RequireAuthorization("McpPolicy");
```

- Enforce least privilege with `Roles` and `Policy` on tool metadata.
- Keep inspector endpoints disabled or restricted outside trusted environments.
- Forward only required security headers via `ForwardHeaders`.

### Governance

- `ToolFilter`: discovery-time exclusion by name/environment.
- `ToolVisibilityFilter`: per-request dynamic visibility based on context.
- Roles/policies are enforced at listing and invocation boundaries.
- Use versioned routes to run controlled cutovers across client populations.

### Observability and operations

- Correlation IDs via configurable header propagation.
- Structured logging around MCP request lifecycle and tool calls.
- `IMcpMetricsSink` for custom telemetry export.
- Optional OpenTelemetry enrichment for traces.
- SSE-based keep-alive behavior for long-lived MCP connections.

### Reliability recommendations

- Set endpoint auth and rate limiting policies at the ASP.NET Core layer.
- Treat `/mcp` as a production API surface with normal SLO/SLA controls.
- Keep inspector UI behind environment checks or internal access controls.
- Validate key tool flows with integration tests before client rollout.

## Configuration Example

```csharp
builder.Services.AddZeroMCP(options =>
{
    options.ServerName = "Orders Platform";
    options.ServerVersion = "2.3.0";
    options.RoutePrefix = "/mcp";

    // Core behavior
    options.IncludeInputSchemas = true;
    options.ForwardHeaders = ["Authorization"];

    // Governance
    options.ToolFilter = name => !name.StartsWith("internal_");
    options.ToolVisibilityFilter = (name, ctx) =>
        ctx.User.IsInRole("Admin") || !name.StartsWith("admin_");

    // Observability
    options.CorrelationIdHeader = "X-Correlation-ID";
    options.EnableOpenTelemetryEnrichment = true;

    // Optional MCP capabilities
    options.EnableResources = true;
    options.EnablePrompts = true;
    options.EnableToolInspector = false;
    options.EnableToolInspectorUI = false;
});
```

## Supported MCP Surface

### Modern (2026-07-28)

- `server/discover`
- `tools/list`, `tools/call`
- `resources/list`, `resources/templates/list`, `resources/read`
- `prompts/list`, `prompts/get`
- `subscriptions/listen` (SSE response stream for change notifications)

### Legacy dual-era (2024-11-05, default enabled)

- `initialize`, `notifications/initialized`
- `resources/subscribe`, `resources/unsubscribe` (when enabled)
- GET `/mcp` with `Accept: text/event-stream` for notification streams

## Transport Options

### Streamable HTTP (default)

- `POST /mcp` for JSON-RPC methods (modern and legacy)
- `GET /mcp` for human-readable metadata; legacy clients may open GET SSE when **EnableLegacyProtocol** is true

### stdio (optional)

```csharp
if (args.Contains("--mcp-stdio"))
{
    await app.RunMcpStdioAsync();
    return;
}
```

Useful for local-first MCP clients that spawn your service process directly.

#### Claude Desktop stdio example

```json
{
  "mcpServers": {
    "orders-api": {
      "command": "dotnet",
      "args": ["run", "--project", "ZeroMCP.Sample", "--", "--mcp-stdio"]
    }
  }
}
```

For full client setup options (stdio and HTTP), see `wiki/Connecting-Clients.md`.

## Inspector Endpoints

- `GET /mcp/tools`: JSON inventory of tools and schemas
- `GET /mcp/ui`: browser-based invocation UI

Recommended usage: enable in development and internal test environments only.

## Versioning and Compatibility

- Semantic versioning policy is defined in `VERSIONING.md`.
- MCP protocol behavior is implemented with explicit compatibility tests.
- Versioned endpoint support allows non-breaking migration paths for clients.

## Solution Layout

- `ZeroMCP/`: core framework package (NuGet artifact source)
- `ZeroMCP.Sample/`: reference host with practical patterns
- `ZeroMCP.Tests/`: integration and schema/compatibility tests
- `examples/`: focused scenario samples:
  - `Minimal`
  - `WithAuth`
  - `WithEnrichment`
  - `WithStdio`
  - `WithRateLimiting`
  - `Enterprise`
- `wiki/`: implementation and operations documentation
- `progress.md`: persistent engineering change log

## `[Mcp]` Attribute Quick Reference

`[Mcp]` supports a required tool name plus optional metadata used for discoverability and governance.

```csharp
[Mcp(
    "create_order",
    Description = "Creates an order.",
    Tags = new[] { "orders", "write" },
    Category = "orders",
    Examples = new[] { "Create order for Alice, quantity 2" },
    Hints = new[] { "idempotent", "cost=low" },
    Roles = new[] { "Admin" },
    Policy = "RequireEditor",
    Version = 2
)]
```

Full details: `wiki/The-Mcp-Attribute.md`.

## Other Attribute Quick Reference

Use these when exposing MCP resources and prompts from controller actions:

```csharp
[McpResource("catalog://info", "catalog_info",
    Description = "Returns catalog metadata.",
    MimeType = "application/json")]

[McpTemplate("catalog://products/{id}", "product_resource",
    Description = "Returns a product by ID.",
    MimeType = "application/json")]

[McpPrompt("restock_recommendation_prompt",
    Description = "Generates a restock recommendation prompt.")]
```

Minimal API equivalents:

```csharp
app.MapGet("/api/catalog/info", () => Results.Ok(...))
   .AsResource("catalog://info", "catalog_info", "Returns catalog metadata.", mimeType: "application/json");

app.MapGet("/api/catalog/products/{id:int}", (int id) => Results.Ok(...))
   .AsTemplate("catalog://products/{id}", "product_resource", "Returns a product by ID.", mimeType: "application/json");

app.MapGet("/api/catalog/prompts/restock/{productId:int}", (int productId) => Results.Ok(...))
   .AsPrompt("restock_recommendation_prompt", "Generates a restock recommendation prompt.");
```

Full details: `wiki/Resources-and-Prompts.md`.

## Build and Test

```bash
dotnet build ZeroMCP.slnx -v detailed
dotnet test ZeroMCP.Tests/ZeroMCP.Tests.csproj -v detailed
```

Integration tests include MCP streamable HTTP behaviour (e.g. GET `/mcp` with `Accept: text/event-stream` and **`Mcp-Session-Id`**, `resources/subscribe` with session header, and **`notifications/resources/updated`** on the SSE channel). See `McpResourceSubscriptionTests` and `McpClientCompatibilityTests` in `ZeroMCP.Tests/`.

## Documentation Map

- Package README: `ZeroMCP/README.md`
- Configuration: `wiki/Configuration.md`
- Security model: `wiki/Security-Model.md`
- Enterprise usage: `wiki/Enterprise-Usage.md`
- Tool versioning: `wiki/Tool-Versioning.md`
- Resources and prompts: `wiki/Resources-and-Prompts.md`

## Contributing

Contributions are welcome, especially around protocol compatibility hardening, minimal API binding parity, and production-focused samples. Please include integration tests and documentation updates with each functional change.
