Blog Post

Microsoft Developer Community Blog
4 MIN READ

Swagger Auto-Generation on MCP Server

justinyoo's avatar
justinyoo
Icon for Microsoft rankMicrosoft
Jul 16, 2025

Would you like to generate a swagger.json directly on an MCP server on-the-fly?

In many use cases, using remote MCP servers is not uncommon. In particular, if you're using Azure API Management (APIM), Azure API Center (APIC) or Copilot Studio in Power Platform, integrating with remote MCP servers is inevitable.

 

MCP (Model Context Protocol) is a protocol used for defining server endpoints that support AI agent workflows, often in Copilot scenarios.

 

Background

 

A remote MCP server is basically an HTTP API app that exposes an endpoint of either /mcp or /sse depending on the spec the servers support. This endpoint should be accessible from Copilot Studio through a custom connector, APIM or APIC. The easiest and simplest way of exposing this endpoint is to provide an OpenAPI doc. The OpenAPI doc is very simple because it has only one endpoint, and the structure is always the same. Here's the Swagger (OpenAPI v2) doc, referred from the Copilot Studio doc.

swagger: '2.0'
info:
  title: Contoso
  description: MCP Test Specification, YAML for streamable MCP support in Copilot Studio
  version: 1.0.0
host: contoso.com
basePath: /
schemes:
  - https
paths:
  /mcp:
    post:
      summary: Contoso Lead Management Server
      x-ms-agentic-protocol: mcp-streamable-1.0
      operationId: InvokeMCP
      responses:
        '200':
          description: Success

But, whenever you write up a remote MCP server, you have to manually provide this Swagger doc. What if it's automatically served directly from the MCP server on-the-fly? It reduces manual maintenance overhead and ensures consistency. Doesn't it sound awesome? Let's figure this out.

 

Use Microsoft.AspNetCore.OpenApi to generate OpenAPI doc on-the-fly

 

As mentioned earlier, an MCP server is basically an HTTP API app, and it shares ASP.NET Core Web API features. So, all we need to do is to inject the OpenAPI service to Program.cs. Here's the codebase for the MCP server. It declares the remote MCP server with streamable HTTP by setting stateless = true.

...

// Activate MCP server capability.
builder.Services.AddMcpServer()
                .WithHttpTransport(o => o.Stateless = true)
                .WithToolsFromAssembly();

var app = builder.Build();

...

// Add endpoint for MCP.
app.MapMcp("/mcp");

app.Run();

Now, if you want to activate the Swagger doc, add the following lines of code.

...

// Activate MCP server capability.
builder.Services.AddMcpServer()
                .WithHttpTransport(o => o.Stateless = true)
                .WithToolsFromAssembly();

// 👇👇👇 Add 👇👇👇
// Add OpenAPI doc capability.
builder.Services.AddHttpContextAccessor();
builder.Services.AddOpenApi("swagger", o =>
{
    // For swagger.json
    o.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi2_0;
    o.AddDocumentTransformer<McpDocumentTransformer>();
});
builder.Services.AddOpenApi("openapi", o =>
{
    // For openapi.json
    o.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_0;
    o.AddDocumentTransformer<McpDocumentTransformer>();
});
// 👆👆👆 Add 👆👆👆

var app = builder.Build();

...

// Add endpoint for MCP.
app.MapMcp("/mcp");

// 👇👇👇 Add 👇👇👇
// Add endpoint for OpenAPI docs.
app.MapOpenApi("/{documentName}.json");
// 👆👆👆 Add 👆👆👆

app.Run();

You may have noticed the McpDocumentTransformer class. It defines how the OpenAPI doc is generated. As mentioned earlier, the OpenAPI doc for MCP servers are always the same. You can use IHttpContextAccessor instance to dynamically generate the server URL, but it's not necessary.

public class McpDocumentTransformer(IHttpContextAccessor accessor) : IOpenApiDocumentTransformer
{
    public Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
    {
        document.Info = new OpenApiInfo
        {
            Title = "MCP server",
            Version = "1.0.0",
            Description = "A simple MCP server."
        };
        document.Servers =
        [
            new OpenApiServer
            {
                Url = accessor.HttpContext != null
                    ? $"{accessor.HttpContext.Request.Scheme}://{accessor.HttpContext.Request.Host}/"
                    : "http://localhost:8080/"
            }
        ];

        var pathItem = new OpenApiPathItem();
        pathItem.AddOperation(OperationType.Post, new OpenApiOperation
        {
            Summary = "MCP endpoint",
            Extensions = new Dictionary<string, IOpenApiExtension>
            {
                ["x-ms-agentic-protocol"] = new OpenApiString("mcp-streamable-1.0")
            },
            OperationId = "InvokeMCP",
            Responses = new OpenApiResponses
            {
                ["200"] = new OpenApiResponse
                {
                    Description = "Success",
                }
            }
        });

        document.Paths ??= [];
        document.Paths.Add("/mcp", pathItem);

        return Task.CompletedTask;
    }
}

That's it! After enabling the OpenAPI capability, your MCP server has three endpoints:

MCP server
 ├─ /mcp          (endpoint)
 ├─ /swagger.json (auto-generated) - Copilot Studio
 └─ /openapi.json (auto-generated) - APIM or APIC

Run your MCP server and navigate to http://localhost:8080/swagger.json for Swagger (OpenAPI v2) or http://localhost:8080/swagger.json for OpenAPI v3 doc, and you'll be able to see the OpenAPI docs rendered on-the-fly. Therefore, you can use the Swagger doc for Copilot Studio and the OpenAPI doc for APIM or APIC integration.

 

CORS considerations

 

Now, this MCP server can be deployed to Azure – either App Service or Container Apps. However, to connect to the MCP server from Power Platform or APIM, you need to enable CORS. Here are two possible ways.

 

1. Enable CORS policy in your cloud instance

 

Depending on your cloud instance you're using, there are various ways you can follow:

 

 

2. Enable CORS policy in your MCP server

 

Alternatively, you can enable the CORS policy within your application.

 

Either approach works. The former leverages built-in features of Azure services, while the latter is a cloud-agnostic option.

 

Sample app?

 

Of course, there is a sample app for you to check out. Visit the MCP Samples in .NET repository and find the to-do management MCP server. There are other sample apps in the same repo so you can try them out on your local machine and Azure.

 

More resources

 

If you'd like to learn more about MCP in .NET, here are some additional resources worth exploring:

 

Updated Jul 16, 2025
Version 1.0
No CommentsBe the first to comment