MentorAgent Docs
Menu

ReferencePackage: Novior.MentorAgent.Server

EndpointRouteBuilderExtensions class

The EndpointRouteBuilderExtensions class of Novior.MentorAgent.Extensions.

View as Markdown
On this page

Namespace: Novior.MentorAgent.Extensions. Package: Novior.MentorAgent.Server.

public static class EndpointRouteBuilderExtensions

Terminal
dotnet add package Novior.MentorAgent.Server

public static IEndpointRouteBuilder MapMentorAgentA2A(this IEndpointRouteBuilder endpoints, string? path = null, Action<IEndpointConventionBuilder>? configure = null)

Maps the MentorAgent A2A agent endpoints:

  • GET /.well-known/agent-card.json — Agent Card
  • POST {path} — A2A message handler

Prerequisites in Program.cs:

Example
builder.Services.AddMentorAgent(options =>
{
    options.A2AServerEnabled = true;
    options.AppName          = "MyApp";
    options.AppDescription   = "My Blazor AI assistant";
    // optional: options.AgentCard = new AgentCardInfo { Version = "2.0.0" };
});
builder.Services.AddMentorAgentA2A();   // AddMentorAgentServer() includes it
// ...
app.MapMentorAgentA2A();          // default path: /a2a
app.MapMentorAgentA2A("/agent");  // custom path

Remote orchestrators can then discover this agent via https://yourapp/.well-known/agent-card.json and send A2A tasks to https://yourapp/a2a.

Parameters

  • endpoints: The endpoint route builder.
  • path: The URL path for the A2A endpoint. Omitted: MentorOptions.A2AServerPath (default /a2a) — the option used to be read by nothing, so setting it moved no endpoint.
  • configure: Applied to both mapped endpoints — the task handler and the well-known agent card — so the host can protect them: app.MapMentorAgentA2A(configure: e => e.RequireAuthorization());. Optional; omitting it leaves the endpoints exactly as they were.

public static IEndpointRouteBuilder MapMentorAgentMcp(this IEndpointRouteBuilder endpoints, string? path = null, Action<IEndpointConventionBuilder>? configure = null)

Maps the MentorAgent MCP server endpoint, exposing every [MentorAction] method as an MCP tool. Prerequisites in Program.cs:

Example
builder.Services.AddMentorAgent(options =>
{
    options.McpServerEnabled = true;
    // ...
});
builder.Services.AddMentorAgentMcp();   // AddMentorAgentServer() includes it
// ...
app.MapMentorAgentMcp();          // default path: /mcp
app.MapMentorAgentMcp("/my-mcp"); // custom path

MCP clients (e.g. Claude Desktop) can then connect to https://yourapp/mcp and discover all available tools.

Gated actions are withheld, and a warning written here, when the endpoint is mapped, names them. The tools themselves are built by the first MCP request, and which of them a caller sees is decided per request.

The tool instances are resolved once, from a scope that lives as long as the application, so a [MentorAction] class is one shared instance for every MCP call, whatever lifetime it is registered with — transient included. Keep such classes stateless: inject IDbContextFactory or IServiceScopeFactory and create what a call needs inside it, never hold a DbContext in a field.

No CORS policy is attached (BUG-108). MCP clients that are not browsers — desktop and IDE clients, the MCP Inspector's proxy — need none, and the endpoint used to carry one that allowed any origin, which also made every request fail with a 500 on a pipeline without app.UseCors(). A host with a browser-based client opts in with app.UseCors() and app.MapMentorAgentMcp(configure: e => e.RequireCors("MentorAgentMcp")), replacing the built-in MentorAgentMcp policy with one that names its origins.

Parameters

  • endpoints: The endpoint route builder.
  • path: The URL path for the MCP endpoint. Omitted: MentorOptions.McpServerPath (default /mcp) — the option used to be read by nothing, so setting it moved no endpoint.
  • configure: Applied to the mapped endpoint, so the host can protect it: app.MapMentorAgentMcp(configure: e => e.RequireAuthorization());. Without it the endpoint stays open to anyone who can reach the port — which is what the withheld-tool rule (BUG-021) assumes, and why every gated action is refused there. Optional: omitting it changes nothing for existing hosts.