Skip to content

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

@dahlsailrunner

Description

@dahlsailrunner

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.NET MCP server that allows anonymous connections over https should work successfully from the McpInspector provided by the community toolkit's integration without the developer needing to add logic into the apphost.

Screenshots

No response

IDE and version

VS Code

IDE version

1.106.3

Nuget packages

CommunityToolkit.Aspire.Hosting.McpInspector (13.0.0)

Additional context

No response

Help us help you

Yes, I'd like to be assigned to work on this item

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions