Skip to content

Commit 80cb03f

Browse files
authored
Fix NuGet.org base URL default, improve API integration (#813)
<!-- Provide a brief summary of your changes --> ## Motivation and Context <!-- Why is this change needed? What problem does it solve? --> This resolves #738. There are two issues with the NuGet.org integration today: 1. Change the `registryBaseUrl` for NuGet to `https://api.nuget.org/v3/index.json`. `https://api.nuget.org` is not the entry point for our service and is not specific enough. `https://api.nuget.org/v3/index.json` is the value that users put into their tooling to connect to our public registry (it is installed by default in .NET client tooling). 2. Use the service index API to get the URL pattern for package READMEs. - This URL is not guaranteed to be stable. The service index URL (`registryBaseUrl`) is, however. Additionally, I polished up the error messages so various error modes are clearer. When packages are published to NuGet.org, they take 2-5 minutes to become available due to validations we run. Some possible states that are now handled and described more helpfully are: - Version exists, but the package has no README - The ID exists, but the version does not - The ID does not exist at all There are only 3 authors (me, another MSFT person, and a community member) explicitly setting the old value. The DB migration will fix the issue. A future publish will fail with the validation error but the error message is clear. `registry type and base URL do not match: 'https://api.nuget.org' is not valid for registry type 'nuget'. Expected: https://api.nuget.org/v3/index.json` ## How Has This Been Tested? <!-- Have you tested this in a real application? Which scenarios were tested? --> - Unit tests, new and existing - Manual test locally - Set old data in the DB, `docker compose up`, confirm the migration updates the specific package ## Breaking Changes Yes, but minimal impact expected, unless there is a dependency on the specific `https://api.nuget.org` value downstream. I am not aware of any such dependency, and the new value is more proper and specific. ## Types of changes <!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [x] Breaking change (fix or feature that would cause existing functionality to change) - [x] Documentation update ## Checklist <!-- Go over all the following points, and put an `x` in all the boxes that apply. --> - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [x] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed ## Additional context <!-- Add any other context, implementation notes, or design decisions --> For more information about the NuGet API see: https://learn.microsoft.com/en-us/nuget/api/overview#service-index (I wrote most of the docs).
1 parent 823c1a1 commit 80cb03f

File tree

11 files changed

+322
-39
lines changed

11 files changed

+322
-39
lines changed

complete.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ Only trusted public registries are supported. Private registries and alternative
658658
**Supported registries:**
659659
- **NPM**: `https://registry.npmjs.org` only
660660
- **PyPI**: `https://pypi.org` only
661-
- **NuGet**: `https://api.nuget.org` only
661+
- **NuGet**: `https://api.nuget.org/v3/index.json`
662662
- **Docker/OCI**: `https://docker.io` only
663663
- **MCPB**: `https://github.com` releases and `https://gitlab.com` releases only
664664

@@ -1549,7 +1549,8 @@ Include your server name in your package's README using this format:
15491549
Add a README file to your NuGet package that includes the server name. This can be in a comment if you want to hide it from display elsewhere.
15501550

15511551
### How It Works
1552-
- Registry fetches README from `https://api.nuget.org/v3-flatcontainer/{id}/{version}/readme`
1552+
- Registry fetches and cached service index `https://api.nuget.org/v3/index.json`
1553+
- Registry uses `ReadmeUriTemplate/6.13.0` URL template in service index to fetch README
15531554
- Passes if `mcp-name: server-name` is found in the README content
15541555

15551556
### Example server.json
@@ -1566,7 +1567,7 @@ Add a README file to your NuGet package that includes the server name. This can
15661567
}
15671568
```
15681569

1569-
The official MCP registry currently only supports the official NuGet registry (`https://api.nuget.org`).
1570+
The official MCP registry currently only supports the official NuGet registry (`https://api.nuget.org/v3/index.json`).
15701571

15711572
</details>
15721573

@@ -2341,7 +2342,7 @@ Suppose your MCP server application requires a `mcp start` CLI arguments to star
23412342
"packages": [
23422343
{
23432344
"registry_type": "nuget",
2344-
"registry_base_url": "https://api.nuget.org",
2345+
"registry_base_url": "https://api.nuget.org/v3/index.json",
23452346
"identifier": "Knapcode.SampleMcpServer",
23462347
"version": "0.4.0-beta",
23472348
"transport": {
@@ -2578,7 +2579,7 @@ The `dnx` tool ships with the .NET 10 SDK, starting with Preview 6.
25782579
"packages": [
25792580
{
25802581
"registry_type": "nuget",
2581-
"registry_base_url": "https://api.nuget.org",
2582+
"registry_base_url": "https://api.nuget.org/v3/index.json",
25822583
"identifier": "Knapcode.SampleMcpServer",
25832584
"version": "0.5.0",
25842585
"runtime_hint": "dnx",

docs/modelcontextprotocol-io/package-types.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ This MCP server executes SQL queries and manages database connections.
8585

8686
## NuGet Packages
8787

88-
For NuGet packages, the MCP Registry currently supports the official NuGet registry (`https://api.nuget.org`) only.
88+
For NuGet packages, the MCP Registry currently supports the official NuGet registry (`https://api.nuget.org/v3/index.json`) only.
8989

9090
NuGet packages use `"registryType": "nuget"` in `server.json`. For example:
9191

docs/reference/api/openapi.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ components:
414414
- "https://registry.npmjs.org"
415415
- "https://pypi.org"
416416
- "https://docker.io"
417-
- "https://api.nuget.org"
417+
- "https://api.nuget.org/v3/index.json"
418418
- "https://github.com"
419419
- "https://gitlab.com"
420420
identifier:

docs/reference/server-json/generic-server-json.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ Suppose your MCP server application requires a `mcp start` CLI arguments to star
131131
"packages": [
132132
{
133133
"registryType": "nuget",
134-
"registryBaseUrl": "https://api.nuget.org",
134+
"registryBaseUrl": "https://api.nuget.org/v3/index.json",
135135
"identifier": "Knapcode.SampleMcpServer",
136136
"version": "0.4.0-beta",
137137
"transport": {
@@ -370,7 +370,7 @@ The `dnx` tool ships with the .NET 10 SDK, starting with Preview 6.
370370
"packages": [
371371
{
372372
"registryType": "nuget",
373-
"registryBaseUrl": "https://api.nuget.org",
373+
"registryBaseUrl": "https://api.nuget.org/v3/index.json",
374374
"identifier": "Knapcode.SampleMcpServer",
375375
"version": "0.5.0",
376376
"runtimeHint": "dnx",

docs/reference/server-json/official-registry-requirements.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Only trusted public registries are supported. Private registries and alternative
3232
**Supported registries:**
3333
- **NPM**: `https://registry.npmjs.org` only
3434
- **PyPI**: `https://pypi.org` only
35-
- **NuGet**: `https://api.nuget.org` only
35+
- **NuGet**: `https://api.nuget.org/v3/index.json` only
3636
- **Docker/OCI**:
3737
- Docker Hub (`docker.io`)
3838
- GitHub Container Registry (`ghcr.io`)

docs/reference/server-json/server.schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@
226226
"https://registry.npmjs.org",
227227
"https://pypi.org",
228228
"https://docker.io",
229-
"https://api.nuget.org",
229+
"https://api.nuget.org/v3/index.json",
230230
"https://github.com",
231231
"https://gitlab.com"
232232
],
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
-- Migration: Set NuGet package registryBaseUrl for specific server entries
2+
--
3+
-- This migration updates the packages[].registryBaseUrl to
4+
-- "https://api.nuget.org/v3/index.json" for NuGet packages on a small,
5+
-- explicitly listed set of server entries. Only packages with
6+
-- registryType == "nuget" are modified; other package types are left
7+
-- unchanged.
8+
--
9+
-- Entries to update (name, version):
10+
-- com.joelverhagen.mcp/Knapcode.SampleMcpServer 0.7.0-beta, 0.10.0-beta.10
11+
-- io.github.joelverhagen/Knapcode.SampleMcpServer 0.7.0-beta
12+
-- io.github.moonolgerd/game-mcp 1.0.0
13+
-- io.github.timheuer/sampledotnetmcpserver 0.1.56-beta-g9538a23d37, 0.1.57-beta
14+
15+
BEGIN;
16+
17+
WITH affected_entries AS (
18+
SELECT server_name, version FROM (VALUES
19+
('com.joelverhagen.mcp/Knapcode.SampleMcpServer', '0.7.0-beta'),
20+
('com.joelverhagen.mcp/Knapcode.SampleMcpServer', '0.10.0-beta.10'),
21+
('io.github.joelverhagen/Knapcode.SampleMcpServer', '0.7.0-beta'),
22+
('io.github.moonolgerd/game-mcp', '1.0.0'),
23+
('io.github.timheuer/sampledotnetmcpserver', '0.1.56-beta-g9538a23d37'),
24+
('io.github.timheuer/sampledotnetmcpserver', '0.1.57-beta')
25+
) AS t(server_name, version)
26+
)
27+
UPDATE servers s
28+
SET value = jsonb_set(
29+
s.value,
30+
'{packages}',
31+
(
32+
SELECT jsonb_agg(
33+
CASE
34+
WHEN p->>'registryType' = 'nuget' THEN
35+
jsonb_set(
36+
p,
37+
'{registryBaseUrl}',
38+
'"https://api.nuget.org/v3/index.json"'::jsonb,
39+
true
40+
)
41+
ELSE p
42+
END
43+
)
44+
FROM jsonb_array_elements(s.value#>'{packages}') AS p
45+
),
46+
true
47+
)
48+
FROM affected_entries ae
49+
WHERE s.server_name = ae.server_name
50+
AND s.version = ae.version
51+
AND s.value#>'{packages}' IS NOT NULL
52+
AND EXISTS (
53+
SELECT 1
54+
FROM jsonb_array_elements(s.value#>'{packages}') AS p
55+
WHERE p->>'registryType' = 'nuget' AND p->>'registryBaseUrl' IS NOT NULL
56+
);
57+
58+
COMMIT;

0 commit comments

Comments
 (0)