Loading...
Loading...
Publish and deploy C# MCP servers. Covers NuGet packaging for stdio servers, Docker containerization for HTTP servers, Azure Container Apps and App Service deployment, and publishing to the official MCP Registry. USE FOR: packaging stdio MCP servers as NuGet tools, creating Dockerfiles for HTTP MCP servers, deploying to Azure Container Apps or App Service, publishing to the MCP Registry at registry.modelcontextprotocol.io, configuring server.json for MCP package metadata, setting up CI/CD for MCP server publishing. DO NOT USE FOR: publishing general NuGet libraries (not MCP-specific), general Docker guidance unrelated to MCP, creating new servers (use mcp-csharp-create), debugging (use mcp-csharp-debug), writing tests (use mcp-csharp-test).
npx skill4agent add dotnet/skills mcp-csharp-publishserver.jsonmcp-csharp-testmcp-csharp-debugmcp-csharp-createnuget-trusted-publishing| Input | Required | Description |
|---|---|---|
| Transport type | Yes | |
| Target destination | Yes | NuGet.org, Docker registry, Azure Container Apps, Azure App Service, MCP Registry |
| Project path | Yes | Path to the |
| Package ID / server name | Required for publishing | NuGet |
| Transport | Primary Destination | Users Run With |
|---|---|---|
| stdio | NuGet.org | |
| HTTP | Docker → Azure | Container URL |
.csproj<PropertyGroup>
<PackAsTool>true</PackAsTool>
<ToolCommandName>mymcpserver</ToolCommandName>
<PackageId>YourUsername.MyMcpServer</PackageId>
<Version>1.0.0</Version>
<Authors>Your Name</Authors>
<Description>MCP server for interacting with MyService</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageTags>mcp;modelcontextprotocol;ai;llm</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>dotnet build -c Release
dotnet pack -c Releasedotnet tool install --global --add-source bin/Release/ YourUsername.MyMcpServer
mymcpserver --help # verify it runs
dotnet tool uninstall --global YourUsername.MyMcpServerdotnet nuget push bin/Release/*.nupkg \
--api-key YOUR_NUGET_API_KEY \
--source https://api.nuget.org/v3/index.jsonmcp.json{
"servers": {
"MyMcpServer": {
"type": "stdio",
"command": "dnx",
"args": ["YourUsername.MyMcpServer@1.0.0", "--yes"]
}
}
}FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:10.0
WORKDIR /app
COPY /app .
# Non-root user for security
RUN adduser --disabled-password --gecos '' appuser
USER appuser
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080
HEALTHCHECK \
CMD curl -f http://localhost:8080/health || exit 1
ENTRYPOINT ["dotnet", "MyMcpServer.dll"]docker build -t mymcpserver:latest .
docker run -d -p 3001:8080 -e API_KEY=test-key --name mymcpserver mymcpserver:latest
curl http://localhost:3001/health# Docker Hub
docker tag mymcpserver:latest <yourusername>/<mymcpserver>:1.0.0
docker push <yourusername>/<mymcpserver>:1.0.0
# Azure Container Registry
az acr login --name yourregistry
docker tag mymcpserver:latest <yourregistry>.azurecr.io/<mymcpserver>:1.0.0
docker push <yourregistry>.azurecr.io/<mymcpserver>:1.0.0az containerapp create \
--name mymcpserver \
--resource-group mygroup \
--environment myenvironment \
--image <yourregistry>.azurecr.io/<mymcpserver>:1.0.0 \
--target-port 8080 \
--ingress external \
--min-replicas 0 \
--max-replicas 10 \
--secrets api-key=my-actual-api-key \
--env-vars API_KEY=secretref:api-keyaz webapp create \
--name mymcpserver \
--resource-group mygroup \
--plan myplan \
--deployment-container-image-name <yourregistry>.azurecr.io/<mymcpserver>:1.0.0mcp-publisher# macOS/Linux
brew install mcp-publisher
# Or download from https://github.com/modelcontextprotocol/registry/releases.mcp/server.jsonmcp-publisher init{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "io.github.username/servername",
"description": "Your server description",
"version": "1.0.0",
"packages": [{
"registryType": "nuget",
"registryBaseUrl": "https://api.nuget.org",
"identifier": "YourUsername.MyMcpServer",
"version": "1.0.0",
"transport": { "type": "stdio" }
}],
"repository": {
"url": "https://github.com/username/repo",
"source": "github"
}
}Version consistency (critical): The root,version, andpackages[].versionin<Version>must all match. A mismatch causes registry validation failures or users downloading the wrong version..csproj
mcp-publisher login github # name must be io.github.<username>/... for GitHub auth
mcp-publisher publishcurl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.<username>/<servername>"dnx PackageId@versionregistry.modelcontextprotocol.io| Pitfall | Solution |
|---|---|
| NuGet package doesn't run as a tool | Missing |
Version mismatch between | Keep |
| Docker container exits immediately | Check entrypoint DLL name matches project output. Run |
| Azure Container App returns 502 | Target port mismatch. Ensure |
| MCP Registry rejects publish | Name must follow namespace convention: |
| API keys leaked in Docker image | Use multi-stage builds. Never |
mcp-csharp-createmcp-csharp-debugmcp-csharp-test.csprojserver.jsondnxmcp-publisherserver.json