> ## Documentation Index
> Fetch the complete documentation index at: https://si.easyaf.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> Pick an authenticated MCP task store by the engine you already run: database, distributed cache, or eventing.

Every durable store implements the same contract as the in-memory store in [Authenticated tasks](https://si.easyaf.dev/mcpessentials/guides/authenticated-tasks.md): stamp the owner on create, isolate client-facing get/cancel/resolve to that user, let the SDK complete work after the HTTP request is gone.

Pick the package that matches the engine already in your host. The identity factory stays the same when you swap.

The design lives in [`specs/authenticated-task-stores.md`](https://github.com/CloudNimble/McpEssentials/blob/main/specs/authenticated-task-stores.md).

## In-process

> [card] [Authenticated tasks](https://si.easyaf.dev/mcpessentials/guides/authenticated-tasks.md)
>
> Shipped
>
> `McpEssentials.Core`. `InMemoryMcpTaskStorePlus` keeps snapshots in a `ConcurrentDictionary`. Fan-out is an in-process event. Tasks die with the process. Tests, local MCP, a single process.

## Database

Relational and document engines. Entity Framework Core is the default durable package: **one implementation, any EF Core provider**.

> [card] [Entity Framework Core](https://si.easyaf.dev/mcpessentials/guides/stores/entity-framework-core.md)
>
> Shipped
>
> `McpEssentials.EntityFrameworkCore`. SQL Server, SQLite, PostgreSQL, MySQL, Cosmos via EF, and any other EF Core provider. Host owns the `DbContext` and migrations.

> [card] [PostgreSQL](https://si.easyaf.dev/mcpessentials/guides/stores/postgresql.md)
>
> Shipped
>
> `McpEssentials.PostgreSQL`. Npgsql, no EF. `LISTEN` / `NOTIFY` wakes elicitation on other nodes.

> [card] [Cosmos DB](https://si.easyaf.dev/mcpessentials/guides/stores/cosmos.md)
>
> Shipped
>
> `McpEssentials.Cosmos`. Azure Cosmos DB for NoSQL, `/ownerUserId` partition plus an index for background complete.

> [card] [SQL Server](https://si.easyaf.dev/mcpessentials/guides/stores/sql-server.md)
>
> Specified
>
> `McpEssentials.SqlServer`. `Microsoft.Data.SqlClient`, no EF. Use Entity Framework Core with `UseSqlServer` until it ships.

> [card] [MongoDB](https://si.easyaf.dev/mcpessentials/guides/stores/mongodb.md)
>
> Specified
>
> `McpEssentials.MongoDB`. Native collection and change streams.

> [card] [Azure Tables](https://si.easyaf.dev/mcpessentials/guides/stores/azure-tables.md)
>
> Specified
>
> `McpEssentials.AzureTables`. `PartitionKey = OwnerUserId`, `RowKey = TaskId`.

> [!TIP]
>
> Use EF Core when the host already has a `DbContext`. Native PostgreSQL exists for hosts that want Npgsql/Dapper **and** `LISTEN` / `NOTIFY` without an EF model.

## Distributed cache

Low-latency handles with native or host-owned expiry.

> [card] [Redis](https://si.easyaf.dev/mcpessentials/guides/stores/redis.md)
>
> Shipped
>
> `McpEssentials.Redis`. StackExchange.Redis, `PEXPIREAT` plus pub/sub for multi-node elicitation.

> [card] [IDistributedCache](https://si.easyaf.dev/mcpessentials/guides/stores/distributed-cache.md)
>
> Specified
>
> `McpEssentials.DistributedCache`. Whatever you already registered as `IDistributedCache`. Prefer Redis when the cache is Redis and you need pub/sub.

## Eventing

Stores whose native bus is the reason the package exists.

> [card] [NATS](https://si.easyaf.dev/mcpessentials/guides/stores/nats.md)
>
> Specified
>
> `McpEssentials.Nats`. JetStream KV for the row, Core NATS for signals.

> [!NOTE]
>
> Redis and native PostgreSQL implement [`NotifyingMcpTaskStoreBase`](https://si.easyaf.dev/mcpessentials/api-reference/CloudNimble/McpEssentials/Core/Tasks/NotifyingMcpTaskStoreBase). Providers without a native bus (EF Core, Cosmos v1, `IDistributedCache`, Azure Tables) take an optional [`IMcpTaskInputSignalBus`](https://si.easyaf.dev/mcpessentials/api-reference/CloudNimble/McpEssentials/Core/Tasks/IMcpTaskInputSignalBus). Missing bus plus multiple nodes means `ElicitAsync` waits until timeout.

## Shared row

`StoredMcpTask` is the persistence foundation. Durable entities subclass it (EF adds `RowVersion`). Keep these rows on their own table; tasks expire in minutes.

| Field | Role |
| - | - |
| `TaskId` | Primary key |
| `OwnerUserId` | Isolation key |
| `Status` | `Working` / `InputRequired` / `Completed` / `Cancelled` / `Failed` |
| `CreatedAt` / `LastUpdatedAt` | UTC |
| `TimeToLive` / `ExpiresAt` | Work window (`CreatedAt + TimeToLive`) |
| `DiscardAfter` | Visibility ceiling (`CreatedAt + 2×TimeToLive`), stamped at write |
| `ResultJson` / `ErrorJson` / `InputRequestsJson` | Payloads |

## Swap in production

HTTP identity stays on the platform accessor. Development uses Core. Production registers a durable store with the same factory.

```csharp Basic theme={"dark"}
builder.Services.AddHttpContextAccessor();

Func<IServiceProvider, ClaimsPrincipal?> currentUser =
    sp => sp.GetRequiredService<IHttpContextAccessor>().HttpContext?.User;

builder.Services.AddMcpServer()
    .WithHttpTransport(o => o.Stateless = true)
    .WithTasksPlus(currentUser, o => o.DefaultTimeToLive = TimeSpan.FromMinutes(5));
```

```csharp Entity Framework Core theme={"dark"}
builder.Services.AddHttpContextAccessor();

Func<IServiceProvider, ClaimsPrincipal?> currentUser =
    sp => sp.GetRequiredService<IHttpContextAccessor>().HttpContext?.User;

builder.Services.AddDbContext<AppDbContext>(o => o.UseSqlServer(connectionString));
builder.Services.AddMcpServer()
    .WithHttpTransport(o => o.Stateless = true)
    .WithTasksPlus<AppDbContext>(currentUser, o => o.DefaultTimeToLive = TimeSpan.FromMinutes(5));
```

```csharp Redis theme={"dark"}
builder.Services.AddHttpContextAccessor();

Func<IServiceProvider, ClaimsPrincipal?> currentUser =
    sp => sp.GetRequiredService<IHttpContextAccessor>().HttpContext?.User;

builder.Services.AddSingleton<IConnectionMultiplexer>(
    _ => ConnectionMultiplexer.Connect(redisConnectionString));
builder.Services.AddMcpServer()
    .WithHttpTransport(o => o.Stateless = true)
    .WithRedisTasks(currentUser, o => o.DefaultTimeToLive = TimeSpan.FromMinutes(5));
```

```csharp Cosmos DB theme={"dark"}
builder.Services.AddHttpContextAccessor();

Func<IServiceProvider, ClaimsPrincipal?> currentUser =
    sp => sp.GetRequiredService<IHttpContextAccessor>().HttpContext?.User;

builder.Services.AddSingleton(_ => new CosmosClient(
    cosmosConnectionString,
    CosmosMcpTaskStore.DefaultClientOptions()));
builder.Services.AddMcpServer()
    .WithHttpTransport(o => o.Stateless = true)
    .WithCosmosTasks(currentUser, o => o.DefaultTimeToLive = TimeSpan.FromMinutes(5));
```

```csharp PostgreSQL theme={"dark"}
builder.Services.AddHttpContextAccessor();

Func<IServiceProvider, ClaimsPrincipal?> currentUser =
    sp => sp.GetRequiredService<IHttpContextAccessor>().HttpContext?.User;

builder.Services.AddSingleton(_ => NpgsqlDataSource.Create(postgresConnectionString));
builder.Services.AddMcpServer()
    .WithHttpTransport(o => o.Stateless = true)
    .WithPostgreSqlTasks(currentUser, o => o.DefaultTimeToLive = TimeSpan.FromMinutes(5));
```

Map `McpTasks` with `AddMcpTasksTable`. See [Entity Framework Core](https://si.easyaf.dev/mcpessentials/guides/stores/entity-framework-core.md) for which overload to call (`OnModelCreating` vs `AddDbContext`).

Isolation helpers stay in Core. Provider packages depend on `McpEssentials.Core`, not on each other.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.