Benevia.Core.MCP
Introduction
Benevia.Core.MCP provides Model Context Protocol (MCP) server infrastructure for exposing your application's OData API to AI clients. It registers a generic, metadata-driven tool surface that works against any entity your API exposes — no per-entity code or configuration is needed.
Tool calls are executed through the host's own OData pipeline, so authorization, multi-tenancy, and business logic events always apply.
Getting Started
1. Install the NuGet package
dotnet add package Benevia.Core.MCP
2. Register the MCP server
In your Program.cs:
using Benevia.Core.MCP;
builder.Services
.AddCoreMcpServer()
// ... other services
;
app.UseCoreMcp();
app.UseCoreApi();
app.Run();
The MCP endpoint is mapped to /mcp with Bearer token authentication.
To enable record links in tool responses, set the app's public base URL:
builder.Services.AddCoreMcpServer(options =>
options.AppBaseUrl = builder.Configuration["App:BaseUrl"]);
If the host uses UsePathBase, include the same value in that registration so MCP CORS matches the mounted routes:
builder.Services.AddCoreMcpServer(options =>
{
options.AppBaseUrl = builder.Configuration["App:BaseUrl"];
options.PathBase = "/prefix";
});
app.UsePathBase("/prefix");
3. Connect an MCP client
Any MCP-compatible client can connect to your server:
Endpoint: http://localhost:5090/mcp
Transport: Streamable HTTP (POST with SSE responses)
Auth: Authorization: Bearer <access-token>
Test locally with Claude Code
OAuth only works over HTTPS, so use the API's HTTPS address. These steps use https://localhost:7140.
Start the API on its HTTPS profile and set the OAuth public origin to the HTTPS address. MCP tool calls loop back into the API, and without this setting their token is rejected with "The issuer associated to the specified token is not valid".
dotnet run --launch-profile https -- --OAuth:PublicOrigin=https://localhost:7140If your app hosts the OAuth consent page, point its API base URL at the same HTTPS address. The consent page only accepts return URLs on that address. Otherwise it shows "Invalid OAuth return URL."
Export the ASP.NET Core development certificate so Claude Code trusts it:
dotnet dev-certs https --export-path ~/.aspnet/dev-cert.pem --format Pem --no-passwordAdd the server and start Claude Code:
claude mcp add --transport http my-app https://localhost:7140/mcp NODE_EXTRA_CA_CERTS=~/.aspnet/dev-cert.pem claudeRun
/mcp, select the server, choose Authenticate, then sign in and approve the access level in the browser.
Claude Desktop and claude.ai connect from Anthropic's servers, so they can't reach localhost. To test with them, expose the API through a public HTTPS tunnel and set OAuth:PublicOrigin to the tunnel URL.
Tools
The server exposes one generic tool surface:
| Tool | Description |
|---|---|
benevia_query |
Read any entity set with OData query options ($filter, $select, $expand, $orderby, $search, paging), or invoke read methods. Also serves schema discovery via the entitymetadata entity set. |
benevia_create |
Stage a new record. |
benevia_update |
Stage field changes (patch) or run a business method (invoke) on a record. |
benevia_delete |
Delete a record. |
benevia_commit |
Save or discard staged changes. |
benevia_link |
Build an in-app link to a record (requires AppBaseUrl). |
benevia_connection |
Inspect the current connection: user, permissions, available entity sets. |
Writes are staged in a workflow and only persisted when the agent commits, so business logic validation runs before anything is saved.
Schema Discovery
Agents discover the schema at runtime by querying the entitymetadata entity set through benevia_query — entity names, fields, navigation properties, and business methods all come from the API's own metadata. Property Description values from the entity model appear in this metadata, so well-described models produce a better agent experience. To keep the payload small, the endpoint omits fields that hold their default value (null, false, 0), so a missing field means its default.
Authentication
The /mcp endpoint is protected by the OpenIddict access-token validation scheme, and UseCoreMcp() maps the /.well-known/oauth-protected-resource endpoints so OAuth-capable MCP clients can discover the authorization server and connect interactively.
The authorization server itself is part of Core: see OAuth 2.1 for setup and concepts, and MCP connectors for the end-to-end Claude / ChatGPT connection flow and troubleshooting.
More Info
- OAuth 2.1 — delegated, scoped access for MCP clients
- Model documentation — entity definition guide
- Use your API — OData API infrastructure