diff --git a/docs/concepts/deployment/docker.md b/docs/concepts/deployment/docker.md new file mode 100644 index 000000000..a3f49cd47 --- /dev/null +++ b/docs/concepts/deployment/docker.md @@ -0,0 +1,115 @@ +--- +title: Docker Deployment +author: jeffhandley +description: How to run ASP.NET Core MCP servers in Docker containers using Streamable HTTP transport. +uid: docker-deployment +--- + +## Docker deployment for MCP servers + +Docker is a practical way to package and run MCP servers consistently across development, CI, and production environments. For HTTP-based MCP servers, use ASP.NET Core hosting with Streamable HTTP. + +This guide assumes you already have an ASP.NET Core MCP server configured with `ModelContextProtocol.AspNetCore`, `WithHttpTransport()`, and `MapMcp()`. + + + +> [!TIP] +> For local, process-based integrations where the client launches the server directly, stdio is often simpler. For remote and containerized deployments, Streamable HTTP is the recommended transport. + +### Baseline server + +A minimal HTTP-based MCP server looks like this: + +```csharp +using ModelContextProtocol.Server; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddMcpServer() + .WithHttpTransport() + .WithToolsFromAssembly(); + +var app = builder.Build(); + +app.MapMcp("/mcp"); +app.Run(); +``` + +### Dockerfile + +Use a multi-stage Docker build so SDK tooling stays in the build stage and only runtime dependencies are shipped in the final image. + +```dockerfile +# Build stage +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src + +COPY . . +RUN dotnet restore +RUN dotnet publish -c Release -o /app/publish + +# Runtime stage +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime +WORKDIR /app + +COPY --from=build /app/publish . + +# MCP HTTP endpoint listens on 8080 inside container +ENV ASPNETCORE_URLS=http://+:8080 +EXPOSE 8080 + +ENTRYPOINT ["dotnet", "MyMcpServer.dll"] +``` + +Replace `MyMcpServer.dll` with your server assembly output name. + +### Build and run + +Build the image: + +```bash +docker build -t my-mcp-server:latest . +``` + +Run the container and map host port `3001` to container port `8080`: + +```bash +docker run --rm -p 3001:8080 my-mcp-server:latest +``` + +With the baseline route above (`app.MapMcp("/mcp")`), clients connect to: + +- Streamable HTTP: `http://localhost:3001/mcp` +- Legacy SSE endpoint (if needed): `http://localhost:3001/mcp/sse` + +### Configuration and secrets + +Pass configuration through environment variables rather than baking secrets into the image: + +```bash +docker run --rm -p 3001:8080 \ + -e ASPNETCORE_ENVIRONMENT=Production \ + -e MYAPP__APIKEY=example \ + my-mcp-server:latest +``` + +ASP.NET Core binds `MYAPP__APIKEY` to `MYAPP:APIKEY` in configuration. + + + +> [!IMPORTANT] +> Do not commit real tokens or credentials into Dockerfiles, compose files, or source code. Use runtime environment variables or an external secret store. + +### Health and readiness + +For container orchestrators, add an HTTP health endpoint and use it for readiness/liveness checks. Keep MCP traffic on your mapped MCP route and health probes on a separate route. + +### Reverse proxies and forwarded headers + +If your container is behind a reverse proxy (for example, ingress or load balancers), ensure forwarded headers are handled correctly so auth and origin metadata flow to the MCP server as expected. + +See also: + +- [Transports](../transports/transports.md) +- [Getting Started](../getting-started.md) +- [HTTP Context](../httpcontext/httpcontext.md) diff --git a/docs/concepts/getting-started.md b/docs/concepts/getting-started.md index 6e096d767..f7dceff6a 100644 --- a/docs/concepts/getting-started.md +++ b/docs/concepts/getting-started.md @@ -13,19 +13,21 @@ This guide walks you through installing the MCP C# SDK and building a minimal MC The SDK ships as three NuGet packages. Pick the one that matches your scenario: -| Package | Use when... | -| - | - | -| **[ModelContextProtocol.Core](https://www.nuget.org/packages/ModelContextProtocol.Core/absoluteLatest)** | You only need the client or low-level server APIs and want the **minimum set of dependencies**. | -| **[ModelContextProtocol](https://www.nuget.org/packages/ModelContextProtocol/absoluteLatest)** | You're building a client or a **stdio-based** server and want hosting, dependency injection, and attribute-based tool/prompt/resource discovery. References `ModelContextProtocol.Core`. **This is the right starting point for most projects.** | -| **[ModelContextProtocol.AspNetCore](https://www.nuget.org/packages/ModelContextProtocol.AspNetCore/absoluteLatest)** | You're building an **HTTP-based** MCP server hosted in ASP.NET Core. References `ModelContextProtocol`, so you get everything above plus the HTTP transport. | +| Package | Use when... | +| -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **[ModelContextProtocol.Core](https://www.nuget.org/packages/ModelContextProtocol.Core/absoluteLatest)** | You only need the client or low-level server APIs and want the **minimum set of dependencies**. | +| **[ModelContextProtocol](https://www.nuget.org/packages/ModelContextProtocol/absoluteLatest)** | You're building a client or a **stdio-based** server and want hosting, dependency injection, and attribute-based tool/prompt/resource discovery. References `ModelContextProtocol.Core`. **This is the right starting point for most projects.** | +| **[ModelContextProtocol.AspNetCore](https://www.nuget.org/packages/ModelContextProtocol.AspNetCore/absoluteLatest)** | You're building an **HTTP-based** MCP server hosted in ASP.NET Core. References `ModelContextProtocol`, so you get everything above plus the HTTP transport. | + > [!TIP] > If you're unsure, start with the **ModelContextProtocol** package. You can always add **ModelContextProtocol.AspNetCore** later if you need HTTP transport support. ### Building an MCP server + > [!TIP] > You can also use the [MCP Server project template](https://learn.microsoft.com/dotnet/ai/quickstarts/build-mcp-server) to quickly scaffold a new MCP server project. @@ -152,4 +154,4 @@ var response = await chatClient.GetResponseAsync( ### Next steps -Explore the rest of the conceptual documentation to learn about [tools](tools/tools.md), [prompts](prompts/prompts.md), [resources](resources/resources.md), [transports](transports/transports.md), and more. You can also browse the [samples](https://github.com/modelcontextprotocol/csharp-sdk/tree/main/samples) directory for complete end-to-end examples. +Explore the rest of the conceptual documentation to learn about [tools](tools/tools.md), [prompts](prompts/prompts.md), [resources](resources/resources.md), [transports](transports/transports.md), and [Docker deployment](deployment/docker.md) for HTTP-based servers. You can also browse the [samples](https://github.com/modelcontextprotocol/csharp-sdk/tree/main/samples) directory for complete end-to-end examples. diff --git a/docs/concepts/index.md b/docs/concepts/index.md index 85d94492f..9607746f4 100644 --- a/docs/concepts/index.md +++ b/docs/concepts/index.md @@ -8,33 +8,39 @@ Welcome to the conceptual documentation for the Model Context Protocol SDK. Here Install the SDK and build your first MCP client and server. +### Deployment + +| Title | Description | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| [Docker deployment](deployment/docker.md) | Learn how to package and run ASP.NET Core MCP servers in Docker containers using Streamable HTTP transport. | + ### Base Protocol -| Title | Description | -| - | - | +| Title | Description | +| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | | [Capabilities](capabilities/capabilities.md) | Learn how client and server capabilities are negotiated during initialization, including protocol version negotiation. | -| [Transports](transports/transports.md) | Learn how to configure stdio, Streamable HTTP, and SSE transports for client-server communication. | -| [Ping](ping/ping.md) | Learn how to verify connection health using the ping mechanism. | -| [Progress tracking](progress/progress.md) | Learn how to track progress for long-running operations through notification messages. | -| [Cancellation](cancellation/cancellation.md) | Learn how to cancel in-flight MCP requests using cancellation tokens and notifications. | -| [Pagination](pagination/pagination.md) | Learn how to use cursor-based pagination when listing tools, prompts, and resources. | +| [Transports](transports/transports.md) | Learn how to configure stdio, Streamable HTTP, and SSE transports for client-server communication. | +| [Ping](ping/ping.md) | Learn how to verify connection health using the ping mechanism. | +| [Progress tracking](progress/progress.md) | Learn how to track progress for long-running operations through notification messages. | +| [Cancellation](cancellation/cancellation.md) | Learn how to cancel in-flight MCP requests using cancellation tokens and notifications. | +| [Pagination](pagination/pagination.md) | Learn how to use cursor-based pagination when listing tools, prompts, and resources. | ### Client Features -| Title | Description | -| - | - | -| [Sampling](sampling/sampling.md) | Learn how servers request LLM completions from the client using the sampling feature. | -| [Roots](roots/roots.md) | Learn how clients provide filesystem roots to servers for context-aware operations. | -| [Elicitation](elicitation/elicitation.md) | Learn how to request additional information from users during interactions. | +| Title | Description | +| ----------------------------------------- | ------------------------------------------------------------------------------------- | +| [Sampling](sampling/sampling.md) | Learn how servers request LLM completions from the client using the sampling feature. | +| [Roots](roots/roots.md) | Learn how clients provide filesystem roots to servers for context-aware operations. | +| [Elicitation](elicitation/elicitation.md) | Learn how to request additional information from users during interactions. | ### Server Features -| Title | Description | -| - | - | -| [Tools](tools/tools.md) | Learn how to implement and consume tools that return text, images, audio, and embedded resources. | -| [Resources](resources/resources.md) | Learn how to expose and consume data through MCP resources, including templates and subscriptions. | -| [Prompts](prompts/prompts.md) | Learn how to implement and consume reusable prompt templates with rich content types. | -| [Completions](completions/completions.md) | Learn how to implement argument auto-completion for prompts and resource templates. | -| [Logging](logging/logging.md) | Learn how to implement logging in MCP servers and how clients can consume log messages. | -| [HTTP Context](httpcontext/httpcontext.md) | Learn how to access the underlying `HttpContext` for a request. | -| [MCP Server Handler Filters](filters.md) | Learn how to add filters to the handler pipeline. Filters let you wrap the original handler with additional functionality. | +| Title | Description | +| ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- | +| [Tools](tools/tools.md) | Learn how to implement and consume tools that return text, images, audio, and embedded resources. | +| [Resources](resources/resources.md) | Learn how to expose and consume data through MCP resources, including templates and subscriptions. | +| [Prompts](prompts/prompts.md) | Learn how to implement and consume reusable prompt templates with rich content types. | +| [Completions](completions/completions.md) | Learn how to implement argument auto-completion for prompts and resource templates. | +| [Logging](logging/logging.md) | Learn how to implement logging in MCP servers and how clients can consume log messages. | +| [HTTP Context](httpcontext/httpcontext.md) | Learn how to access the underlying `HttpContext` for a request. | +| [MCP Server Handler Filters](filters.md) | Learn how to add filters to the handler pipeline. Filters let you wrap the original handler with additional functionality. | diff --git a/docs/concepts/toc.yml b/docs/concepts/toc.yml index d04eeb707..2361b245c 100644 --- a/docs/concepts/toc.yml +++ b/docs/concepts/toc.yml @@ -1,43 +1,47 @@ items: -- name: Overview - href: index.md -- name: Getting Started - uid: getting-started -- name: Base Protocol - items: - - name: Capabilities - uid: capabilities - - name: Transports - uid: transports - - name: Ping - uid: ping - - name: Progress - uid: progress - - name: Cancellation - uid: cancellation - - name: Pagination - uid: pagination - - name: Tasks - uid: tasks -- name: Client Features - items: - - name: Roots - uid: roots - - name: Elicitation - uid: elicitation -- name: Server Features - items: - - name: Tools - uid: tools - - name: Resources - uid: resources - - name: Prompts - uid: prompts - - name: Completions - uid: completions - - name: Logging - uid: logging - - name: HTTP Context - uid: httpcontext - - name: Filters - uid: filters \ No newline at end of file + - name: Overview + href: index.md + - name: Getting Started + uid: getting-started + - name: Deployment + items: + - name: Docker + uid: docker-deployment + - name: Base Protocol + items: + - name: Capabilities + uid: capabilities + - name: Transports + uid: transports + - name: Ping + uid: ping + - name: Progress + uid: progress + - name: Cancellation + uid: cancellation + - name: Pagination + uid: pagination + - name: Tasks + uid: tasks + - name: Client Features + items: + - name: Roots + uid: roots + - name: Elicitation + uid: elicitation + - name: Server Features + items: + - name: Tools + uid: tools + - name: Resources + uid: resources + - name: Prompts + uid: prompts + - name: Completions + uid: completions + - name: Logging + uid: logging + - name: HTTP Context + uid: httpcontext + - name: Filters + uid: filters diff --git a/docs/concepts/transports/transports.md b/docs/concepts/transports/transports.md index 55623d51a..7782c579f 100644 --- a/docs/concepts/transports/transports.md +++ b/docs/concepts/transports/transports.md @@ -19,7 +19,7 @@ The stdio transport communicates over standard input and output streams. It is b Use to launch a server process and communicate over its stdin/stdout. This example connects to the [NuGet MCP Server]: -[NuGet MCP Server]: https://learn.microsoft.com/nuget/concepts/nuget-mcp-server +[nuget mcp server]: https://learn.microsoft.com/nuget/concepts/nuget-mcp-server ```csharp var transport = new StdioClientTransport(new StdioClientTransportOptions @@ -34,15 +34,15 @@ await using var client = await McpClient.CreateAsync(transport); Key properties: -| Property | Description | -|----------|-------------| -| `Command` | The executable to launch (required) | -| `Arguments` | Command-line arguments for the process | -| `WorkingDirectory` | Working directory for the server process | +| Property | Description | +| ---------------------- | --------------------------------------------------------------------------- | +| `Command` | The executable to launch (required) | +| `Arguments` | Command-line arguments for the process | +| `WorkingDirectory` | Working directory for the server process | | `EnvironmentVariables` | Environment variables (merged with current; `null` values remove variables) | -| `ShutdownTimeout` | Graceful shutdown timeout (default: 5 seconds) | -| `StandardErrorLines` | Callback for stderr output from the server process | -| `Name` | Optional transport identifier for logging | +| `ShutdownTimeout` | Graceful shutdown timeout (default: 5 seconds) | +| `StandardErrorLines` | Callback for stderr output from the server process | +| `Name` | Optional transport identifier for logging | #### stdio server @@ -62,7 +62,7 @@ await builder.Build().RunAsync(); The [Streamable HTTP] transport uses HTTP for bidirectional communication with optional streaming. This is the recommended transport for remote servers. -[Streamable HTTP]: https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http +[streamable http]: https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http #### Streamable HTTP client @@ -95,7 +95,7 @@ var transport = new HttpClientTransport(new HttpClientTransportOptions #### Resuming sessions -Streamable HTTP supports session resumption. Save the session ID, server capabilities, and server info from the original session, then use to reconnect: +Streamable HTTP supports session resumption. Save the session ID, server capabilities, and server info from the original session, then use to reconnect: ```csharp var transport = new HttpClientTransport(new HttpClientTransportOptions @@ -113,7 +113,7 @@ await using var client = await McpClient.ResumeSessionAsync(transport, new Resum #### Streamable HTTP server (ASP.NET Core) -Use the `ModelContextProtocol.AspNetCore` package to host an MCP server over HTTP. The method maps the Streamable HTTP endpoint at the specified route (root by default). It also maps legacy SSE endpoints at `{route}/sse` and `{route}/message` for backward compatibility. +Use the `ModelContextProtocol.AspNetCore` package to host an MCP server over HTTP. The method maps the Streamable HTTP endpoint at the specified route (root by default). It also maps legacy SSE endpoints at `{route}/sse` and `{route}/message` for backward compatibility. ```csharp var builder = WebApplication.CreateBuilder(args); @@ -129,7 +129,7 @@ app.Run(); A custom route can be specified. For example, the [AspNetCoreMcpPerSessionTools] sample uses a route parameter: -[AspNetCoreMcpPerSessionTools]: https://github.com/modelcontextprotocol/csharp-sdk/tree/main/samples/AspNetCoreMcpPerSessionTools +[aspnetcoremcppersessiontools]: https://github.com/modelcontextprotocol/csharp-sdk/tree/main/samples/AspNetCoreMcpPerSessionTools ```csharp app.MapMcp("/mcp"); @@ -137,13 +137,16 @@ app.MapMcp("/mcp"); When using a custom route, Streamable HTTP clients should connect directly to that route (e.g., `https://host/mcp`), while SSE clients should connect to `{route}/sse` (e.g., `https://host/mcp/sse`). +For containerized deployments of ASP.NET Core servers, see [Docker deployment](../deployment/docker.md). + ### SSE transport (legacy) The [SSE (Server-Sent Events)] transport is a legacy mechanism that uses unidirectional server-to-client streaming with a separate HTTP endpoint for client-to-server messages. New implementations should prefer Streamable HTTP. -[SSE (Server-Sent Events)]: https://modelcontextprotocol.io/specification/2024-11-05/basic/transports#http-with-sse +[sse (server-sent events)]: https://modelcontextprotocol.io/specification/2024-11-05/basic/transports#http-with-sse + > [!NOTE] > The SSE transport is considered legacy. The [Streamable HTTP](#streamable-http-transport) transport is the recommended approach for HTTP-based communication and supports bidirectional streaming. @@ -165,10 +168,10 @@ await using var client = await McpClient.CreateAsync(transport); SSE-specific configuration options: -| Property | Description | -|----------|-------------| -| `MaxReconnectionAttempts` | Maximum number of reconnection attempts on stream disconnect (default: 5) | -| `DefaultReconnectionInterval` | Wait time between reconnection attempts (default: 1 second) | +| Property | Description | +| ----------------------------- | ------------------------------------------------------------------------- | +| `MaxReconnectionAttempts` | Maximum number of reconnection attempts on stream disconnect (default: 5) | +| `DefaultReconnectionInterval` | Wait time between reconnection attempts (default: 1 second) | #### SSE server (ASP.NET Core) @@ -193,10 +196,10 @@ No additional configuration is needed. When a client connects using the SSE prot ### Transport mode comparison -| Feature | stdio | Streamable HTTP | SSE (Legacy) | -|---------|-------|----------------|--------------| -| Process model | Child process | Remote HTTP | Remote HTTP | -| Direction | Bidirectional | Bidirectional | Server→client stream + client→server POST | -| Session resumption | N/A | ✓ | ✗ | -| Authentication | Process-level | HTTP auth (OAuth, headers) | HTTP auth (OAuth, headers) | -| Best for | Local tools | Remote servers | Legacy compatibility | +| Feature | stdio | Streamable HTTP | SSE (Legacy) | +| ------------------ | ------------- | -------------------------- | ----------------------------------------- | +| Process model | Child process | Remote HTTP | Remote HTTP | +| Direction | Bidirectional | Bidirectional | Server→client stream + client→server POST | +| Session resumption | N/A | ✓ | ✗ | +| Authentication | Process-level | HTTP auth (OAuth, headers) | HTTP auth (OAuth, headers) | +| Best for | Local tools | Remote servers | Legacy compatibility |