From 780d5d3f984f3d5c766783773e4bc8d058b44b0d Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Mon, 24 Nov 2025 13:12:53 -0500 Subject: [PATCH 01/15] Add guide to publish to the Official MCP Registry --- docs/ai/quickstarts/publish-mcp-registry.md | 294 ++++++++++++++++++ .../snippets/mcp-registry/server.json | 24 ++ 2 files changed, 318 insertions(+) create mode 100644 docs/ai/quickstarts/publish-mcp-registry.md create mode 100644 docs/ai/quickstarts/snippets/mcp-registry/server.json diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md new file mode 100644 index 0000000000000..4fca5190cad27 --- /dev/null +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -0,0 +1,294 @@ +--- +title: Quickstart - Publish a .NET MCP Server to the MCP Registry +description: Learn how to publish your NuGet-based MCP Server to the Official MCP Registry, including creating a server.json manifest, updating your package README, and using the MCP Publisher tool. +ms.date: 11/17/2025 +ms.topic: quickstart +author: joelverhagen +zone_pivot_groups: operating-systems-set-one +ai-usage: ai-assisted +--- + +# Publish an MCP Server on NuGet.org to the Official MCP Registry + +In this quickstart, you will publish your NuGet-based local MCP Server to the [Official MCP Registry](https://github.com/modelcontextprotocol/registry/blob/main/docs/explanations/ecosystem-vision.md). + +> [!NOTE] +> This guide focuses on publishing **local MCP servers** packaged with NuGet that use the stdio transport. The Official MCP Registry also supports **remote MCP servers** that use HTTP transports. While the `server.json` publishing process is similar for remote servers, their configuration differs as they don't require package managers. Remote servers can be implemented in any language since implementation details are transparent to consumers. See [an Azure Functions code sample for a .NET remote MCP server](/samples/azure-samples/remote-mcp-functions-dotnet/remote-mcp-functions-dotnet/). + +## Prerequisites + +- A [GitHub account](https://github.com/join) +- [Visual Studio Code](https://code.visualstudio.com/) +- Your MCP Server is packaged with NuGet and published to NuGet.org ([quickstart](./build-mcp-server.md)). + +## Create a server.json manifest file + +*If you used the NuGet MCP Server quickstart and `mcpserver` project template, you can skip this step.* + +1. Navigate to your MCP server's source directory and create a new `server.json` file. + ::: zone pivot="os-windows" + + ```powershell + cd path\my\project + + # create and open the server.json file + code .mcp\server.json + ``` + + ::: zone-end + ::: zone pivot="os-linux" + + ```bash + cd path/my/project + + # create and open the server.json file + code .mcp/server.json + ``` + + ::: zone-end + ::: zone pivot="os-macos" + + ```bash + cd path/my/project + + # create and open the server.json file + code .mcp/server.json + ``` + + ::: zone-end +2. Use this content to start with and fill in the placeholders. + :::code language="json" source="snippets/mcp-registry/server.json"::: +3. Save the file. + +Use this reference to understand more about the fields: + +| Property | Example | Purpose | +| ------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| name | `io.github.contoso/data-mcp` | Unique identifier for the MCP Server, namespaced using reverse DNS names, **case sensitive** | +| version | `0.1.0-beta` | Version of the MCP Server listing
Consider using the same version as the MCP Server package on NuGet.org | +| description | `Access Contoso data in your AI agent` | Description of your MCP Server, up to 100 characters | +| title | `Contoso Data` | Optional: short human-readable title, up to 100 characters | +| websiteUrl | `https://contoso.com/docs/mcp` | Optional: URL to the server's homepage, documentation, or project website | +| packages identifier | `Contoso.Data.Mcp` | The ID of your MCP Server package on NuGet.org | +| packages version | `0.1.0-beta` | The version of your MCP Server package on NuGet.org | +| repository url | `https://github.com/contoso/data-mcp` | Optional: GitHub repository URL | + +The `name` field has two parts, separated by a forward slash `/`. The first part is a namespace based off of a reverse DNS name. The authentication method you use in later steps will give you access to a specific namespace. For example, using GitHub-based authentication will give you access to `io.github./*`. The second part, after the forward slash, is a custom identifier for your server within the namespace. Think of this much like a NuGet package ID. It should be unchanging and descriptive of your MCP server. Using your GitHub repository name is a reasonable option if you only have one MCP Server published from that repository. + +## Update your package README + +The Official MCP Registry verifies that your MCP Server package references the `name` specified in your `server.json` file. + +1. If you haven't already, add a README to your MCP Server NuGet package. See [how to do this in your project file](/nuget/reference/msbuild-targets#packagereadmefile). +2. Open the README.md used by your NuGet package. + ::: zone pivot="os-windows" + + ```powershell + code path\to\README.md + ``` + + ::: zone-end + ::: zone pivot="os-linux" + + ```bash + code path/to/README.md + ``` + + ::: zone-end + ::: zone pivot="os-macos" + + ```bash + code path/to/README.md + ``` + + ::: zone-end +3. Add the following line to your README. It can be anywhere, since it will be invisible (an HTML comment). + + ```markdown + + ``` + + Example: + + ```markdown + + ``` + +4. Save the README file. + +## Publish your MCP Server package to NuGet.org + +Because your README now has an `mcp-name` declared in it, publish the latest package to NuGet.org. + +1. If needed, update your package version and the respective version strings in your `server.json`. +2. Pack your project so the latest README version is contained. + + ```bash + dotnet pack + ``` + +3. Push it to NuGet.org either [via the website](https://www.nuget.org/packages/manage/upload) or using the CLI: + ::: zone pivot="os-windows" + + ```powershell + dotnet push bin\Release\*.nupkg -k -s https://api.nuget.org/v3/index.json + ``` + + ::: zone-end + ::: zone pivot="os-linux" + + ```bash + dotnet push bin/Release/*.nupkg -k -s https://api.nuget.org/v3/index.json + ``` + + ::: zone-end + ::: zone pivot="os-macos" + + ```bash + dotnet push bin/Release/*.nupkg -k -s https://api.nuget.org/v3/index.json + ``` + + ::: zone-end + +## Wait for your package to become available + +NuGet.org performs validations against your package before making it available. + +Wait for your package to become available. This can either be done by refreshing the package details page on NuGet.org until the validating message disappears, or by using this simple PowerShell script to poll for availability. + +```powershell +$id = "".ToLowerInvariant() +$version = "".ToLowerInvariant() +$url = "https://api.nuget.org/v3-flatcontainer/$id/$version/readme" +$elapsed = 0; $interval = 10; $timeout = 300 +Write-Host "Checking for package README of $id $version." +while ($true) { + if ($elapsed -gt $timeout) { + Write-Error "Package README is not available after $elapsed seconds. URL: $url" + exit 1 + } + try { + Invoke-WebRequest -Uri $url -ErrorAction Stop | Out-Null + Write-Host "Package README is now available." + break + } catch { + Write-Host "Package README is not yet available. Elapsed time: $elapsed seconds." + Start-Sleep -Seconds $interval; $elapsed += $interval + continue + } +} +``` + +This script can be leveraged in a CI/CD pipeline to ensure the next step (publishing to the Official MCP Registry) does not happen before the NuGet package is available. + +## Download the MCP Publisher tool + +1. Download the `mcp-publisher-*.tar.gz` file from the Official MCP Registry GitHub repository that matches your CPU architecture. + ::: zone pivot="os-windows" + - Windows x64: [mcp-publisher_windows_amd64.tar.gz](https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_windows_amd64.tar.gz) + - Windows Arm64: [mcp-publisher_windows_arm64.tar.gz](https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_windows_arm64.tar.gz) + ::: zone-end + ::: zone pivot="os-linux" + - Linux x64: [mcp-publisher_linux_amd64.tar.gz](https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_linux_amd64.tar.gz) + - Linux Arm64: [mcp-publisher_linux_arm64.tar.gz](https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_linux_arm64.tar.gz) + ::: zone-end + ::: zone pivot="os-macos" + - macOS x64: [mcp-publisher_darwin_amd64.tar.gz](https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_darwin_amd64.tar.gz) + - macOS Arm64: [mcp-publisher_darwin_arm64.tar.gz](https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_darwin_arm64.tar.gz) + ::: zone-end + See the full list of assets in the [latest release](https://github.com/modelcontextprotocol/registry/releases/latest). +2. Extract the downloaded .tar.gz to the current directory. + ::: zone pivot="os-windows" + + ```powershell + # For Windows x64 + tar xf 'mcp-publisher_windows_amd64.tar.gz' + + # For Windows ARM64 + tar xf 'mcp-publisher_windows_arm64.tar.gz' + ``` + + ::: zone-end + ::: zone pivot="os-linux" + + ```bash + # For Linux x64 + tar xf 'mcp-publisher_linux_amd64.tar.gz' + + # For Linux ARM64 + tar xf 'mcp-publisher_linux_arm64.tar.gz' + ``` + + ::: zone-end + ::: zone pivot="os-macos" + + ```bash + # For macOS x64 + tar xf 'mcp-publisher_darwin_amd64.tar.gz' + + # For macOS ARM64 + tar xf 'mcp-publisher_darwin_arm64.tar.gz' + ``` + + ::: zone-end + +## Publish to the Official MCP Registry + +The MCP Registry has different authentication mechanisms based on the namespace MCP Server's `name`. In this guide, we are using a namespace based on GitHub (`io.github./*`) so GitHub authentication must be used. See the [registry documentation for information on other authentication modes](https://github.com/modelcontextprotocol/registry/blob/main/docs/modelcontextprotocol-io/authentication.mdx) which unlock other namespaces. + +1. Log in using GitHub interactive authentication. + ::: zone pivot="os-windows" + + ```powershell + .\mcp-publisher.exe login github + ``` + + ::: zone-end + ::: zone pivot="os-linux" + + ```bash + ./mcp-publisher login github + ``` + + ::: zone-end + ::: zone pivot="os-macos" + + ```bash + ./mcp-publisher login github + ``` + + ::: zone-end + Follow the instructions provided by the tool. You will provide a code to GitHub in your web browser to complete the flow. + + Once the flow is complete, you will be able to publish `server.json` files to the `io.github./*` namespace. + +2. Publish your `server.json` file to the Official MCP Registry. + ::: zone pivot="os-windows" + + ```powershell + .\mcp-publisher.exe publish path\to\.mcp\server.json + ``` + + ::: zone-end + ::: zone pivot="os-linux" + + ```bash + ./mcp-publisher publish path/to/.mcp/server.json + ``` + + ::: zone-end + ::: zone pivot="os-macos" + + ```bash + ./mcp-publisher publish path/to/.mcp/server.json + ``` + + ::: zone-end +3. When the command succeeds, you can verify that your MCP Server is published by going to the [registry home page](https://registry.modelcontextprotocol.io/) and searching for your server name. + +## Related content + +- [Build and publish an MCP Server to NuGet.org](./build-mcp-server.md) +- [Publish a NuGet package](/nuget/nuget-org/publish-a-package) +- [Conceptual: MCP Servers in NuGet Packages](/nuget/concepts/nuget-mcp) +- [Get started with .NET AI and the Model Context Protocol](../get-started-mcp.md) diff --git a/docs/ai/quickstarts/snippets/mcp-registry/server.json b/docs/ai/quickstarts/snippets/mcp-registry/server.json new file mode 100644 index 0000000000000..2abeac759b7be --- /dev/null +++ b/docs/ai/quickstarts/snippets/mcp-registry/server.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json", + "name": "io.github./", + "version": "", + "description": "", + "title": "", + "websiteUrl": "", + "packages": [ + { + "registryType": "nuget", + "identifier": "", + "version": "", + "transport": { + "type": "stdio" + }, + "packageArguments": [], + "environmentVariables": [] + } + ], + "repository": { + "url": "https://github.com//", + "source": "github" + } +} From dff730b6486b68a0c03d122acaae4f0d3b6208cf Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Mon, 24 Nov 2025 14:28:05 -0500 Subject: [PATCH 02/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Jeff Kluge --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index 4fca5190cad27..2db07f90364ee 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -79,7 +79,7 @@ The `name` field has two parts, separated by a forward slash `/`. The first part The Official MCP Registry verifies that your MCP Server package references the `name` specified in your `server.json` file. -1. If you haven't already, add a README to your MCP Server NuGet package. See [how to do this in your project file](/nuget/reference/msbuild-targets#packagereadmefile). +1. If you haven't already, add a README.md to your MCP Server NuGet package. See [how to do this in your project file](/nuget/reference/msbuild-targets#packagereadmefile). 2. Open the README.md used by your NuGet package. ::: zone pivot="os-windows" From 53a7cfd7ce0745eb5f51817309f38a7cf0c4bf3a Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Mon, 24 Nov 2025 14:28:19 -0500 Subject: [PATCH 03/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Jeff Kluge --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index 2db07f90364ee..8851f1bbd4ddb 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -102,7 +102,7 @@ The Official MCP Registry verifies that your MCP Server package references the ` ``` ::: zone-end -3. Add the following line to your README. It can be anywhere, since it will be invisible (an HTML comment). +3. Add the following line to your README.md. Since it is enclosed in an HTML comment, it can be anywhere and won't be rendered. ```markdown From 2df9bc432005f9f9570ab50ea56c89ebd0f98a7a Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Mon, 24 Nov 2025 14:28:26 -0500 Subject: [PATCH 04/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Jeff Kluge --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index 8851f1bbd4ddb..37e170638dfcb 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -114,7 +114,7 @@ The Official MCP Registry verifies that your MCP Server package references the ` ``` -4. Save the README file. +4. Save the README.md file. ## Publish your MCP Server package to NuGet.org From 884423d7b7bc91ec648857ee4e9b0ffe648e4534 Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Mon, 24 Nov 2025 14:28:54 -0500 Subject: [PATCH 05/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Jeff Kluge --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index 37e170638dfcb..85273f3400a28 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -118,7 +118,7 @@ The Official MCP Registry verifies that your MCP Server package references the ` ## Publish your MCP Server package to NuGet.org -Because your README now has an `mcp-name` declared in it, publish the latest package to NuGet.org. +Because your README.md now has an `mcp-name` declared in it, publish the latest package to NuGet.org. 1. If needed, update your package version and the respective version strings in your `server.json`. 2. Pack your project so the latest README version is contained. From c690d8c4822ff75016888212add78f4e772d32ed Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Mon, 24 Nov 2025 14:29:00 -0500 Subject: [PATCH 06/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Jeff Kluge --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index 85273f3400a28..d9104f664ebf1 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -121,7 +121,7 @@ The Official MCP Registry verifies that your MCP Server package references the ` Because your README.md now has an `mcp-name` declared in it, publish the latest package to NuGet.org. 1. If needed, update your package version and the respective version strings in your `server.json`. -2. Pack your project so the latest README version is contained. +2. Pack your project so the latest README.md version is contained. ```bash dotnet pack From 2422d360bad61d479c085d3d0a04b446a2318777 Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Mon, 24 Nov 2025 14:29:12 -0500 Subject: [PATCH 07/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Jeff Kluge --- docs/ai/quickstarts/publish-mcp-registry.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index d9104f664ebf1..0b00fc2c6684c 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -152,9 +152,9 @@ Because your README.md now has an `mcp-name` declared in it, publish the latest ## Wait for your package to become available -NuGet.org performs validations against your package before making it available. +NuGet.org performs validations against your package before making it available so you must wait to publish your MCP server to the Official MCP Registry since it verifies that the package is accessible. -Wait for your package to become available. This can either be done by refreshing the package details page on NuGet.org until the validating message disappears, or by using this simple PowerShell script to poll for availability. +To wait for your package to become available, either continue to periodically refresh the package details page on NuGet.org until the validating message disappears, or by use the following PowerShell script to poll for availability. ```powershell $id = "".ToLowerInvariant() From e5be18313a91888325c962e27764db4859f4e2af Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Mon, 24 Nov 2025 14:29:20 -0500 Subject: [PATCH 08/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Jeff Kluge --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index 0b00fc2c6684c..d1f33bcfa8345 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -234,7 +234,7 @@ This script can be leveraged in a CI/CD pipeline to ensure the next step (publis ## Publish to the Official MCP Registry -The MCP Registry has different authentication mechanisms based on the namespace MCP Server's `name`. In this guide, we are using a namespace based on GitHub (`io.github./*`) so GitHub authentication must be used. See the [registry documentation for information on other authentication modes](https://github.com/modelcontextprotocol/registry/blob/main/docs/modelcontextprotocol-io/authentication.mdx) which unlock other namespaces. +The Official MCP Registry has different authentication mechanisms based on the namespace MCP Server's `name`. In this guide, we are using a namespace based on GitHub (`io.github./*`) so GitHub authentication must be used. See the [registry documentation for information on other authentication modes](https://github.com/modelcontextprotocol/registry/blob/main/docs/modelcontextprotocol-io/authentication.mdx) which unlock other namespaces. 1. Log in using GitHub interactive authentication. ::: zone pivot="os-windows" From 5263b2ec0074ec9ce917105f74c33e5121f20978 Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Mon, 24 Nov 2025 15:17:25 -0500 Subject: [PATCH 09/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Jeff Kluge --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index d1f33bcfa8345..19db45decb2b4 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -154,7 +154,7 @@ Because your README.md now has an `mcp-name` declared in it, publish the latest NuGet.org performs validations against your package before making it available so you must wait to publish your MCP server to the Official MCP Registry since it verifies that the package is accessible. -To wait for your package to become available, either continue to periodically refresh the package details page on NuGet.org until the validating message disappears, or by use the following PowerShell script to poll for availability. +To wait for your package to become available, either continue to periodically refresh the package details page on NuGet.org until the validating message disappears, or use the following PowerShell script to poll for availability. ```powershell $id = "".ToLowerInvariant() From 3d5dee054c3b51755ef99457904aa0b9749335e7 Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Tue, 25 Nov 2025 17:00:20 -0500 Subject: [PATCH 10/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index 19db45decb2b4..94c0cca83f5ff 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -10,7 +10,7 @@ ai-usage: ai-assisted # Publish an MCP Server on NuGet.org to the Official MCP Registry -In this quickstart, you will publish your NuGet-based local MCP Server to the [Official MCP Registry](https://github.com/modelcontextprotocol/registry/blob/main/docs/explanations/ecosystem-vision.md). +In this quickstart, you publish your NuGet-based local MCP Server to the [Official MCP Registry](https://github.com/modelcontextprotocol/registry/blob/main/docs/explanations/ecosystem-vision.md). > [!NOTE] > This guide focuses on publishing **local MCP servers** packaged with NuGet that use the stdio transport. The Official MCP Registry also supports **remote MCP servers** that use HTTP transports. While the `server.json` publishing process is similar for remote servers, their configuration differs as they don't require package managers. Remote servers can be implemented in any language since implementation details are transparent to consumers. See [an Azure Functions code sample for a .NET remote MCP server](/samples/azure-samples/remote-mcp-functions-dotnet/remote-mcp-functions-dotnet/). From b8b99a328537b3844b6384cb30a3a63b4cbe943e Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Tue, 25 Nov 2025 17:00:28 -0500 Subject: [PATCH 11/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index 94c0cca83f5ff..e9a43c24d836e 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -13,7 +13,7 @@ ai-usage: ai-assisted In this quickstart, you publish your NuGet-based local MCP Server to the [Official MCP Registry](https://github.com/modelcontextprotocol/registry/blob/main/docs/explanations/ecosystem-vision.md). > [!NOTE] -> This guide focuses on publishing **local MCP servers** packaged with NuGet that use the stdio transport. The Official MCP Registry also supports **remote MCP servers** that use HTTP transports. While the `server.json` publishing process is similar for remote servers, their configuration differs as they don't require package managers. Remote servers can be implemented in any language since implementation details are transparent to consumers. See [an Azure Functions code sample for a .NET remote MCP server](/samples/azure-samples/remote-mcp-functions-dotnet/remote-mcp-functions-dotnet/). +> This guide focuses on publishing **local MCP servers** packaged with NuGet that use the stdio transport. The Official MCP Registry also supports **remote MCP servers** that use HTTP transports. While the `server.json` publishing process is similar for remote servers, their configuration differs as they don't require package managers. Remote servers can be implemented in any language since implementation details are transparent to consumers. For an example, see [an Azure Functions code sample for a .NET remote MCP server](/samples/azure-samples/remote-mcp-functions-dotnet/remote-mcp-functions-dotnet/). ## Prerequisites From 4ef2cfdcf9beafcafb3d3847568ae0c795abb7d5 Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Tue, 25 Nov 2025 17:00:40 -0500 Subject: [PATCH 12/15] Update docs/ai/quickstarts/publish-mcp-registry.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index e9a43c24d836e..67fa4edd3f49a 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -234,7 +234,7 @@ This script can be leveraged in a CI/CD pipeline to ensure the next step (publis ## Publish to the Official MCP Registry -The Official MCP Registry has different authentication mechanisms based on the namespace MCP Server's `name`. In this guide, we are using a namespace based on GitHub (`io.github./*`) so GitHub authentication must be used. See the [registry documentation for information on other authentication modes](https://github.com/modelcontextprotocol/registry/blob/main/docs/modelcontextprotocol-io/authentication.mdx) which unlock other namespaces. +The Official MCP Registry has different authentication mechanisms based on the namespace MCP Server's `name`. In this guide, we are using a namespace based on GitHub (`io.github./*`) so GitHub authentication must be used. See the [registry documentation for information on other authentication modes](https://github.com/modelcontextprotocol/registry/blob/main/docs/modelcontextprotocol-io/authentication.mdx), which unlock other namespaces. 1. Log in using GitHub interactive authentication. ::: zone pivot="os-windows" From 35436de3a74091c7cb96c33cdbea0297b95913ea Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Wed, 26 Nov 2025 15:47:05 -0500 Subject: [PATCH 13/15] Address comments --- docs/ai/quickstarts/publish-mcp-registry.md | 52 +++++++++++---------- docs/ai/toc.yml | 6 ++- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index 67fa4edd3f49a..c015558b77240 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -1,6 +1,6 @@ --- -title: Quickstart - Publish a .NET MCP Server to the MCP Registry -description: Learn how to publish your NuGet-based MCP Server to the Official MCP Registry, including creating a server.json manifest, updating your package README, and using the MCP Publisher tool. +title: Quickstart - Publish a .NET MCP server to the MCP Registry +description: Learn how to publish your NuGet-based MCP server to the Official MCP Registry, including creating a server.json manifest, updating your package README, and using the MCP Publisher tool. ms.date: 11/17/2025 ms.topic: quickstart author: joelverhagen @@ -8,22 +8,24 @@ zone_pivot_groups: operating-systems-set-one ai-usage: ai-assisted --- -# Publish an MCP Server on NuGet.org to the Official MCP Registry +# Publish an MCP server on NuGet.org to the Official MCP Registry -In this quickstart, you publish your NuGet-based local MCP Server to the [Official MCP Registry](https://github.com/modelcontextprotocol/registry/blob/main/docs/explanations/ecosystem-vision.md). +In this quickstart, you publish your NuGet-based local MCP server to the [Official MCP Registry](https://github.com/modelcontextprotocol/registry/blob/main/docs/explanations/ecosystem-vision.md). + +The Official MCP Registry is an upstream data source for MCP ecosystem. The [GitHub MCP Registry](https://github.com/mcp) will soon use the Official MCP Registry as a source of MCP server listings. > [!NOTE] -> This guide focuses on publishing **local MCP servers** packaged with NuGet that use the stdio transport. The Official MCP Registry also supports **remote MCP servers** that use HTTP transports. While the `server.json` publishing process is similar for remote servers, their configuration differs as they don't require package managers. Remote servers can be implemented in any language since implementation details are transparent to consumers. For an example, see [an Azure Functions code sample for a .NET remote MCP server](/samples/azure-samples/remote-mcp-functions-dotnet/remote-mcp-functions-dotnet/). +> This guide focuses on publishing **local MCP servers** packaged with NuGet. The Official MCP Registry also supports **remote MCP servers**. While the `server.json` publishing process is similar for remote servers, their configuration requires a URL instead of a package manager reference. Remote servers can be implemented in any language. For an example, see [an Azure Functions code sample for a .NET remote MCP server](/samples/azure-samples/remote-mcp-functions-dotnet/remote-mcp-functions-dotnet/). ## Prerequisites - A [GitHub account](https://github.com/join) - [Visual Studio Code](https://code.visualstudio.com/) -- Your MCP Server is packaged with NuGet and published to NuGet.org ([quickstart](./build-mcp-server.md)). +- Your MCP server is packaged with NuGet and published to NuGet.org ([quickstart](./build-mcp-server.md)). ## Create a server.json manifest file -*If you used the NuGet MCP Server quickstart and `mcpserver` project template, you can skip this step.* +*If you used the NuGet MCP server quickstart and `mcpserver` project template, you can skip this step.* 1. Navigate to your MCP server's source directory and create a new `server.json` file. ::: zone pivot="os-windows" @@ -62,24 +64,24 @@ In this quickstart, you publish your NuGet-based local MCP Server to the [Offici Use this reference to understand more about the fields: -| Property | Example | Purpose | -| ------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -| name | `io.github.contoso/data-mcp` | Unique identifier for the MCP Server, namespaced using reverse DNS names, **case sensitive** | -| version | `0.1.0-beta` | Version of the MCP Server listing
Consider using the same version as the MCP Server package on NuGet.org | -| description | `Access Contoso data in your AI agent` | Description of your MCP Server, up to 100 characters | -| title | `Contoso Data` | Optional: short human-readable title, up to 100 characters | -| websiteUrl | `https://contoso.com/docs/mcp` | Optional: URL to the server's homepage, documentation, or project website | -| packages identifier | `Contoso.Data.Mcp` | The ID of your MCP Server package on NuGet.org | -| packages version | `0.1.0-beta` | The version of your MCP Server package on NuGet.org | -| repository url | `https://github.com/contoso/data-mcp` | Optional: GitHub repository URL | +| Property | Example | Purpose | +| ----------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| `name` | `io.github.contoso/data-mcp` | Unique identifier for the MCP server, namespaced using reverse DNS names, **case sensitive** | +| `version` | `0.1.0-beta` | Version of the MCP server listing
Consider using the same version as the MCP server package on NuGet.org | +| `description` | `Access Contoso data in your AI agent` | Description of your MCP server, up to 100 characters | +| `title` | `Contoso Data` | Optional: short human-readable title, up to 100 characters | +| `websiteUrl` | `https://contoso.com/docs/mcp` | Optional: URL to the server's homepage, documentation, or project website | +| `packages` `identifier` | `Contoso.Data.Mcp` | The ID of your MCP server package on NuGet.org | +| `packages` `version` | `0.1.0-beta` | The version of your MCP server package on NuGet.org | +| `repository` `url` | `https://github.com/contoso/data-mcp` | Optional: GitHub repository URL | -The `name` field has two parts, separated by a forward slash `/`. The first part is a namespace based off of a reverse DNS name. The authentication method you use in later steps will give you access to a specific namespace. For example, using GitHub-based authentication will give you access to `io.github./*`. The second part, after the forward slash, is a custom identifier for your server within the namespace. Think of this much like a NuGet package ID. It should be unchanging and descriptive of your MCP server. Using your GitHub repository name is a reasonable option if you only have one MCP Server published from that repository. +The `name` field has two parts, separated by a forward slash `/`. The first part is a namespace based off of a reverse DNS name. The authentication method you use in later steps will give you access to a specific namespace. For example, using GitHub-based authentication will give you access to `io.github./*`. The second part, after the forward slash, is a custom identifier for your server within the namespace. Think of this much like a NuGet package ID. It should be unchanging and descriptive of your MCP server. Using your GitHub repository name is a reasonable option if you only have one MCP server published from that repository. ## Update your package README -The Official MCP Registry verifies that your MCP Server package references the `name` specified in your `server.json` file. +The Official MCP Registry verifies that your MCP server package references the `name` specified in your `server.json` file. -1. If you haven't already, add a README.md to your MCP Server NuGet package. See [how to do this in your project file](/nuget/reference/msbuild-targets#packagereadmefile). +1. If you haven't already, add a README.md to your MCP server NuGet package. See [how to do this in your project file](/nuget/reference/msbuild-targets#packagereadmefile). 2. Open the README.md used by your NuGet package. ::: zone pivot="os-windows" @@ -116,7 +118,7 @@ The Official MCP Registry verifies that your MCP Server package references the ` 4. Save the README.md file. -## Publish your MCP Server package to NuGet.org +## Publish your MCP server package to NuGet.org Because your README.md now has an `mcp-name` declared in it, publish the latest package to NuGet.org. @@ -234,7 +236,7 @@ This script can be leveraged in a CI/CD pipeline to ensure the next step (publis ## Publish to the Official MCP Registry -The Official MCP Registry has different authentication mechanisms based on the namespace MCP Server's `name`. In this guide, we are using a namespace based on GitHub (`io.github./*`) so GitHub authentication must be used. See the [registry documentation for information on other authentication modes](https://github.com/modelcontextprotocol/registry/blob/main/docs/modelcontextprotocol-io/authentication.mdx), which unlock other namespaces. +The Official MCP Registry has different authentication mechanisms based on the namespace MCP server's `name`. In this guide, we are using a namespace based on GitHub (`io.github./*`) so GitHub authentication must be used. See the [registry documentation for information on other authentication modes](https://github.com/modelcontextprotocol/registry/blob/main/docs/modelcontextprotocol-io/authentication.mdx), which unlock other namespaces. 1. Log in using GitHub interactive authentication. ::: zone pivot="os-windows" @@ -284,11 +286,11 @@ The Official MCP Registry has different authentication mechanisms based on the n ``` ::: zone-end -3. When the command succeeds, you can verify that your MCP Server is published by going to the [registry home page](https://registry.modelcontextprotocol.io/) and searching for your server name. +3. When the command succeeds, you can verify that your MCP server is published by going to the [registry home page](https://registry.modelcontextprotocol.io/) and searching for your server name. ## Related content -- [Build and publish an MCP Server to NuGet.org](./build-mcp-server.md) +- [Build and publish an MCP server to NuGet.org](./build-mcp-server.md) - [Publish a NuGet package](/nuget/nuget-org/publish-a-package) -- [Conceptual: MCP Servers in NuGet Packages](/nuget/concepts/nuget-mcp) +- [Conceptual: MCP servers in NuGet Packages](/nuget/concepts/nuget-mcp) - [Get started with .NET AI and the Model Context Protocol](../get-started-mcp.md) diff --git a/docs/ai/toc.yml b/docs/ai/toc.yml index b49af499ac0ef..6e7e6b017b745 100644 --- a/docs/ai/toc.yml +++ b/docs/ai/toc.yml @@ -76,10 +76,12 @@ items: href: get-started-app-chat-scaling-with-azure-container-apps.md - name: MCP client/server items: - - name: Build a minimal MCP server and publish to NuGet - href: quickstarts/build-mcp-server.md - name: Build a minimal MCP client href: quickstarts/build-mcp-client.md + - name: Build a minimal MCP server and publish to NuGet + href: quickstarts/build-mcp-server.md + - name: Publish to the Official MCP Registry + href: quickstarts/publish-mcp-registry.md - name: Security and content safety items: - name: Authentication for Azure-hosted apps and services From 37f93a1241bda326e495290e8c22249dc20d32ef Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Wed, 26 Nov 2025 16:02:08 -0500 Subject: [PATCH 14/15] Lint --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index c015558b77240..e692ada9a46da 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -12,7 +12,7 @@ ai-usage: ai-assisted In this quickstart, you publish your NuGet-based local MCP server to the [Official MCP Registry](https://github.com/modelcontextprotocol/registry/blob/main/docs/explanations/ecosystem-vision.md). -The Official MCP Registry is an upstream data source for MCP ecosystem. The [GitHub MCP Registry](https://github.com/mcp) will soon use the Official MCP Registry as a source of MCP server listings. +The Official MCP Registry is an upstream data source for MCP ecosystem. The [GitHub MCP Registry](https://github.com/mcp) will soon use the Official MCP Registry as a source of MCP server listings. > [!NOTE] > This guide focuses on publishing **local MCP servers** packaged with NuGet. The Official MCP Registry also supports **remote MCP servers**. While the `server.json` publishing process is similar for remote servers, their configuration requires a URL instead of a package manager reference. Remote servers can be implemented in any language. For an example, see [an Azure Functions code sample for a .NET remote MCP server](/samples/azure-samples/remote-mcp-functions-dotnet/remote-mcp-functions-dotnet/). From ade05ac4fbf3f7828809ffc4382ca3539d9fa2da Mon Sep 17 00:00:00 2001 From: Joel Verhagen Date: Tue, 2 Dec 2025 15:04:02 -0500 Subject: [PATCH 15/15] Reword --- docs/ai/quickstarts/publish-mcp-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ai/quickstarts/publish-mcp-registry.md b/docs/ai/quickstarts/publish-mcp-registry.md index e692ada9a46da..8238b2495149d 100644 --- a/docs/ai/quickstarts/publish-mcp-registry.md +++ b/docs/ai/quickstarts/publish-mcp-registry.md @@ -12,7 +12,7 @@ ai-usage: ai-assisted In this quickstart, you publish your NuGet-based local MCP server to the [Official MCP Registry](https://github.com/modelcontextprotocol/registry/blob/main/docs/explanations/ecosystem-vision.md). -The Official MCP Registry is an upstream data source for MCP ecosystem. The [GitHub MCP Registry](https://github.com/mcp) will soon use the Official MCP Registry as a source of MCP server listings. +The Official MCP Registry is an *upstream data source* for the MCP ecosystem. Other MCP registries, such as the [GitHub MCP Registry](https://github.com/mcp), will soon use the Official MCP Registry as a source of MCP server listings. > [!NOTE] > This guide focuses on publishing **local MCP servers** packaged with NuGet. The Official MCP Registry also supports **remote MCP servers**. While the `server.json` publishing process is similar for remote servers, their configuration requires a URL instead of a package manager reference. Remote servers can be implemented in any language. For an example, see [an Azure Functions code sample for a .NET remote MCP server](/samples/azure-samples/remote-mcp-functions-dotnet/remote-mcp-functions-dotnet/).