Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 1, 2025

Closes #1012

MCP Inspector (Node.js) fails to connect to HTTPS MCP servers with DEPTH_ZERO_SELF_SIGNED_CERT error because it doesn't trust the ASP.NET Core dev certificate.

Added WithCertificateTrustConfiguration to configure Node.js certificate trust, matching the official Aspire JavaScript hosting pattern:

  • Sets NODE_EXTRA_CA_CERTS when certificate scope is Append
  • Sets NODE_OPTIONS with --use-openssl-ca otherwise, preserving existing options

PR Checklist

  • Created a feature/dev branch in your fork (vs. submitting directly from a commit on main)
  • Based off latest main branch of toolkit
  • PR doesn't include merge commits (always rebase on top of our main, if needed)
  • New integration
    • Docs are written
    • Added description of major feature to project description for NuGet package (4000 total character limit, so don't push entire description over that)
  • Tests for the changes have been added (for bug fixes / features) (if applicable)
  • Contains NO breaking changes
  • Every new API (including internal ones) has full XML docs
  • Code follows all style conventions

Other information

Implementation copied from upstream dotnet/aspire WithNodeDefaults (lines 215-243) as suggested by @aaronpowell. All 18 existing unit tests pass.

Original prompt

This section details on the original issue you should resolve

<issue_title>McpInspector does not trust the dotnet dev cert for ASP.NET MCP servers</issue_title>
<issue_description>### Describe the bug

When running the simplest possible ASP.NET 10 MCP server through Aspire and using the McpInspector integration in this toolkit, the McpInspector integration will fail if an https endpoint is not provided (which is fine for me). But when I use an https endpoint, everything DOES launch just fine, but when I try to actually connect from the Mcp Inspector to my mcp server, it will fail due to a certificate problem.

You can use this repo to see / experiment with the issue and solution: dahlsailrunner/simple-mcp-aspire. The working logic in the apphost is in place. Just comment it out to see the failure.

The error looks something like this (key part is this: request to [https://localhost:7229/](https://localhost:7229/) failed, reason: self-signed certificate; if the root CA is installed locally, try running Node.js with --use-system-ca):

🚀 MCP Inspector is up and running at:

[http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=%7EuG%7BwKeA-%21DxJ42A%7E8mqM%29](http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=%7EuG%7BwKeA-%21DxJ42A%7E8mqM%29)

New StreamableHttp connection request

Query parameters: {"url":"[https://localhost:7229/](https://localhost:7229/)","transportType":"streamable-http"}
Created StreamableHttp client transport
Client <-> Proxy sessionId: 068ebc44-8d6c-46d2-aa19-af3c0d9ac433

Error from MCP server: FetchError: request to [https://localhost:7229/](https://localhost:7229/) failed, reason: self-signed certificate; if the root CA is installed locally, try running Node.js with --use-system-ca
at ClientRequest.<anonymous> (file:///E:/demos/mcp-sample/node_modules/node-fetch/src/index.js:108:11)
at ClientRequest.emit (node:events:520:35)
at emitErrorEvent (node:_http_client:108:11)
at TLSSocket.socketErrorListener (node:_http_client:575:5)
at TLSSocket.emit (node:events:508:28)
Starting process... {"Executable": "/mcp-bekavwzd", "Reconciliation": 6, "Cmd": "C:\\Program Files\\dotnet\\dotnet.exe", "Args": ["run", "--project", "E:\\demos\\mcp-sample\\HelloMcp\\HelloMcp.csproj", "--no-build", "--configuration", "Debug", "--no-launch-profile"]}
at emitErrorNT (node:internal/streams/destroy:170:8)
at emitErrorCloseNT (node:internal/streams/destroy:129:3)
at process.processTicksAndRejections (node:internal/process/task_queues:89:21) {
type: 'system',
errno: 'DEPTH_ZERO_SELF_SIGNED_CERT',
code: 'DEPTH_ZERO_SELF_SIGNED_CERT',
erroredSysCall: undefined
}

To resolve this, I modified the apphost's AddMcpInspector lines based on the official Aspire JavaScript integration:

builder.AddMcpInspector("mcp-inspector")
    .WithCertificateTrustConfiguration((ctx) =>
            {
                if (ctx.Scope == CertificateTrustScope.Append)
                {
                    ctx.EnvironmentVariables["NODE_EXTRA_CA_CERTS"] = ctx.CertificateBundlePath;
                }
                else
                {
                    if (ctx.EnvironmentVariables.TryGetValue("NODE_OPTIONS", out var existingOptionsObj))
                    {
                        ctx.EnvironmentVariables["NODE_OPTIONS"] = existingOptionsObj switch
                        {
                            // Attempt to append to existing NODE_OPTIONS if possible, otherwise overwrite
                            string s when !string.IsNullOrEmpty(s) => $"{s} --use-openssl-ca",
                            ReferenceExpression re => ReferenceExpression.Create($"{re} --use-openssl-ca"),
                            _ => "--use-openssl-ca",
                        };
                    }
                    else
                    {
                        ctx.EnvironmentVariables["NODE_OPTIONS"] = "--use-openssl-ca";
                    }
                }

                return Task.CompletedTask;
            })

This works and I have a fork with a feature branch ready for a PR. It's not easily testable with the tests that are in there (testing this would probably require adding a Playwright test project into the mix). But all of the existing tests still pass with the logic I've added.

Regression

No response

Steps to reproduce

Repro steps:
1. Create an aspire app host (v13 with .NET 10).
2. Add an ASP.NET MCP server with at least an echo tool.  The server should use an https profile.
3. Add the MCP server to the aspire app host.
4. Add the McpInspector integration to the app host and reference the MCP server created above.
5. Run the Aspire solution, and then open the MCP Inspector.
6. Click Connect (verify over https), and it will fail.

Expected behavior

Connecting to an ASP.N...


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…CP Inspector

Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix McpInspector trust issue with dotnet dev cert Fix McpInspector HTTPS certificate trust for ASP.NET MCP servers Dec 1, 2025
Copilot AI requested a review from aaronpowell December 1, 2025 01:09
@aaronpowell aaronpowell marked this pull request as ready for review December 1, 2025 01:36
Copilot AI review requested due to automatic review settings December 1, 2025 01:36
Copilot AI temporarily deployed to azure-artifacts December 1, 2025 01:45 Inactive
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes MCP Inspector's inability to trust ASP.NET Core development certificates when connecting to HTTPS MCP servers. The fix adds certificate trust configuration to the Node.js-based MCP Inspector by setting appropriate environment variables for certificate handling.

Key changes:

  • Adds WithCertificateTrustConfiguration callback to configure Node.js certificate trust
  • Sets NODE_EXTRA_CA_CERTS for Append scope and NODE_OPTIONS with --use-openssl-ca for other scopes
  • Implementation handles existing NODE_OPTIONS values by appending to them

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

@aaronpowell
Copy link
Member

@dahlsailrunner can you give the pre-release build a try. Here's the feed it'll be on: https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-PullRequests/nuget/v3/index.json

@dahlsailrunner
Copy link

I've tried this but believe I'm not pulling the right package. I've set the above feed (https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-PullRequests/nuget/v3/index.json) as a source in Visual Studio and tried that, and then also tried from VS Code with this command:

dotnet add package CommunityToolkit.Aspire.Hosting.McpInspector --prerelease --source https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-PullRequests/nuget/v3/index.json

and in both cases the version I got was 13.0.1-alpha.2140. This version didn't work, and when I navigated to the decompiled code it didn't show the new WithCertificateTrustConfiguration addition. (The prerelease version seems to be the same on NuGet.org and on the custom feed -- at least from what I can tell.)

The change on the PR looks good though.

The repo I'm using to try this (in case you want to try yourself) is dahlsailrunner/simple-mcp-aspire -- it should be runnable and if the running MCP Inspector connects to the MCP Server, then it's working.

@aaronpowell
Copy link
Member

hmm that should be the correct feed, but I'll admit that I don't think I've tested it in like 12 months 🤣

@aaronpowell
Copy link
Member

ah, the problem was that the package wasn't the latest one in there, it was 13.0.0-alpha.2138 (the PR feed gets messy as every PR pushes to it so the ordering is... not great - probably should have some better way to say "hey, here's the version to use").

Tested and it looks ok with the right version

@dahlsailrunner
Copy link

Confirmed as working -- I eve tried version 13.0.1-beta.468 from the official NuGet.org feed. Thanks for the help and quick follow up!

@github-actions
Copy link
Contributor

github-actions bot commented Dec 3, 2025

Code Coverage

Package Line Rate Branch Rate Complexity Health
CommunityToolkit.Aspire.GoFeatureFlag 100% 97% 74
CommunityToolkit.Aspire.Hosting.ActiveMQ 78% 40% 108
CommunityToolkit.Aspire.Hosting.ActiveMQ.MassTransit 1% 0% 14
CommunityToolkit.Aspire.Hosting.Adminer 74% 50% 20
CommunityToolkit.Aspire.Hosting.Azure.Dapr 29% 7% 124
CommunityToolkit.Aspire.Hosting.Azure.Dapr.Redis 61% 34% 76
CommunityToolkit.Aspire.Hosting.Azure.DataApiBuilder 100% 100% 22
CommunityToolkit.Aspire.Hosting.Bun 96% 83% 28
CommunityToolkit.Aspire.Hosting.Dapr 60% 37% 840
CommunityToolkit.Aspire.Hosting.DbGate 94% 50% 18
CommunityToolkit.Aspire.Hosting.Deno 98% 85% 44
CommunityToolkit.Aspire.Hosting.Flagd 79% 100% 32
CommunityToolkit.Aspire.Hosting.GoFeatureFlag 88% 73% 36
CommunityToolkit.Aspire.Hosting.Golang 51% 40% 88
CommunityToolkit.Aspire.Hosting.Java 70% 75% 130
CommunityToolkit.Aspire.Hosting.JavaScript.Extensions 97% 85% 200
CommunityToolkit.Aspire.Hosting.k6 58% 12% 20
CommunityToolkit.Aspire.Hosting.Keycloak.Extensions 100% 100% 22
CommunityToolkit.Aspire.Hosting.KurrentDB 71% 75% 34
CommunityToolkit.Aspire.Hosting.LavinMQ 74% 50% 26
CommunityToolkit.Aspire.Hosting.LavinMQ.MassTransit 1% 0% 14
CommunityToolkit.Aspire.Hosting.MailPit 85% 50% 22
CommunityToolkit.Aspire.Hosting.McpInspector 77% 44% 204
CommunityToolkit.Aspire.Hosting.Meilisearch 71% 57% 58
CommunityToolkit.Aspire.Hosting.Minio 88% 75% 56
CommunityToolkit.Aspire.Hosting.MongoDB.Extensions 96% 83% 36
CommunityToolkit.Aspire.Hosting.MySql.Extensions 100% 88% 78
CommunityToolkit.Aspire.Hosting.Ngrok 52% 35% 82
CommunityToolkit.Aspire.Hosting.Ollama 65% 69% 260
CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector 78% 61% 77
CommunityToolkit.Aspire.Hosting.PapercutSmtp 81% 50% 18
CommunityToolkit.Aspire.Hosting.PostgreSQL.Extensions 99% 89% 84
CommunityToolkit.Aspire.Hosting.Python.Extensions 45% 29% 100
CommunityToolkit.Aspire.Hosting.RavenDB 62% 48% 148
CommunityToolkit.Aspire.Hosting.Redis.Extensions 100% 71% 48
CommunityToolkit.Aspire.Hosting.Rust 94% 83% 16
CommunityToolkit.Aspire.Hosting.Solr 72% 100% 22
CommunityToolkit.Aspire.Hosting.SqlDatabaseProjects 51% 48% 192
CommunityToolkit.Aspire.Hosting.Sqlite 89% 89% 52
CommunityToolkit.Aspire.Hosting.SqlServer.Extensions 100% 87% 78
CommunityToolkit.Aspire.Hosting.SurrealDb 55% 40% 256
CommunityToolkit.Aspire.KurrentDB 94% 92% 54
CommunityToolkit.Aspire.MassTransit.RabbitMQ 100% 100% 30
CommunityToolkit.Aspire.Meilisearch 97% 92% 68
CommunityToolkit.Aspire.Microsoft.Data.Sqlite 89% 85% 52
CommunityToolkit.Aspire.Microsoft.EntityFrameworkCore.Sqlite 61% 58% 114
CommunityToolkit.Aspire.Minio.Client 90% 85% 112
CommunityToolkit.Aspire.OllamaSharp 77% 71% 132
CommunityToolkit.Aspire.RavenDB.Client 60% 53% 237
CommunityToolkit.Aspire.SurrealDb 79% 63% 78
Summary 68% (7311 / 10756) 56% (2081 / 3734) 4734

Minimum allowed line rate is 60%

@aaronpowell aaronpowell merged commit e5d1ad8 into main Dec 3, 2025
107 checks passed
@aaronpowell aaronpowell deleted the copilot/fix-mcpinspector-certificate-issue branch December 3, 2025 04:39
@aaronpowell aaronpowell added this to the 13.1 milestone Dec 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

McpInspector does not trust the dotnet dev cert for ASP.NET MCP servers

3 participants