Setup
This page documents Orleans.Lattice.Api.Mcp 9.9.0, in the documentation for Orleans.Lattice 9.9.0 (release line 9.9), built 2026-10-04. It is also published as markdown, with every table and list, at setup.md, and llms.txt lists every page.Registering the Orleans.Lattice.Api.Mcp server on a silo host, configuring the options, and mapping the endpoint.
Prerequisites
The MCP server binds the Orleans.Lattice.Api.* facades, so the facades a tool module needs must be registered on the same silo:
- Permission-scoped discovery needs
AddLatticeAuthApi()(which itself followsAddLatticeAuth(...)) whichever modules you expose: the default discovery resolver reads each caller's effective permissions through that auth facade, and without it discovery grants no group, so an authenticated caller is offered no facade-group tool - onlylattice_capabilities, plus any installable-app tools whose role it holds, which do not depend on that facade. - State tools need
AddLatticeStateApi(). - Data tools need
AddLatticeDataApi(). - Backup tools need
AddLatticeBackupApi()(which itself followsAddLatticeBackup(...)). - Auth tools need
AddLatticeAuthApi()(which itself followsAddLatticeAuth(...)). - Replication tools need
AddLatticeReplicationApi()(which itself followsAddLatticeReplication(..., enableRuntimeConfig: true)). - Tree-administration tools need
AddLatticeTreeAdminApi()(which itself followsAddLatticeSchemaApi(...); the schema tools resolve that schema control facade directly). - Tenant self-awareness and tenant-admin tools need
AddLatticeTenantAdminApi()(which itself followsAddLatticeTenancy(...)).
Beyond the auth facade discovery relies on, only register the facades whose tool modules you intend to expose.
Register the front door
AddLatticeMcp(...) wires the MCP server, the streamable-HTTP transport, the AddHttpContextAccessor the credential bridge reads, the default-deny authorizer, and the credential bridge. It is idempotent. MapLatticeMcp() maps the transport and applies RequireAuthorization() when enforcement is on.
var builder = WebApplication.CreateBuilder();
builder.Host.UseOrleans(silo =>
{
silo
.AddLattice((s, storageName) => s.AddMemoryGrainStorage(storageName))
.AddLatticeStateApi();
});
builder.Services.AddLatticeMcp(o =>
{
o.RequireAuthorization = true; // fail closed (the default)
o.TransportPattern = "/mcp"; // mount the transport under /mcp
o.CredentialHeaderName = "authorization";
o.CredentialScheme = "Bearer";
});
builder.Services.AddSingleton<ILatticeApiMcpAuthorizer, AllowAllMcpAuthorizer>();
builder.Services.AddStateTools();
var app = builder.Build();
app.MapLatticeMcp();
Options
LatticeApiMcpOptions (populated through the AddLatticeMcp delegate):
| Option | Type | Default | Purpose |
|---|---|---|---|
RequireAuthorization |
bool |
true |
When true, MapLatticeMcp applies RequireAuthorization() so an unauthenticated session is default-denied. Set false only behind an outer authentication boundary. |
TransportPattern |
string |
"" |
The route the streamable-HTTP transport mounts at. Empty mounts at the route builder's root; set a sub-path (for example /mcp) to co-host alongside other endpoints. |
Stateless |
bool |
false |
Whether the HTTP transport runs stateless. The permission-scoped per-session tool collections rely on the stateful (default) mode; enable only for a horizontally-scaled deployment with a fixed tool set. |
CredentialHeaderName |
string |
authorization |
The inbound header carrying the caller's credential token, bridged onto the ambient Lattice credential. |
CredentialScheme |
string |
Bearer |
The scheme stamped on the bridged credential; a case-insensitive scheme prefix (for example "Bearer ") is stripped from the header value before the remaining token is used. |
ActiveTenantHeaderName |
string |
lattice-active-tenant |
The inbound header carrying the caller's asserted active tenant, bridged onto the ambient active-tenant scope so per-tenant write admission and quota enforcement reach the caller's tenant. The assertion is re-validated against the caller's membership downstream; an absent, blank, or invalid header asserts no tenant. Set empty to disable header-based tenant selection. |
EnableStateTools / EnableDataTools / EnableBackupTools / EnableAuthTools / EnableReplicationTools / EnableTenantAdminTools |
bool |
false |
Informational module markers. The matching AddXTools(...) call sets its marker (nothing sets EnableDataTools), but no code reads them: a module is registered - and its group advertised - only by its AddXTools(...) call, so setting a marker directly adds nothing. |
EnableBackupControlTools / EnableAuthAdministration / EnableReplicationControlTools / EnableTreeAdminSchemaControlTools / EnableTreeAdminLifecycleTools / EnableTenantAdminControlTools |
bool |
false |
Destructive-verb opt-ins, read by the registered module when it builds its tool list: each is set by the matching AddXTools(...) flag (enableControl, enableAdministration, enableSchemaControl, or enableLifecycle), and setting one directly is equivalent. None takes effect unless its module is registered. Data writes have no option flag; only AddDataTools(enableWrites: true) opts them in. |
ProtectedResourceMetadata |
LatticeApiMcpProtectedResourceMetadata? |
null |
Opt into OAuth 2.0 Protected Resource Metadata (RFC 9728). When set, an anonymous metadata document is served at its WellKnownPath (default /.well-known/oauth-protected-resource) and the 401 bearer challenge carries a resource_metadata hint. See OAuth discovery. |
Add the tool modules
The server exposes no tools until a module is added. See Tools for the module opt-in flags and the full catalogue. A minimal read-only server adds just AddStateTools(); a full-control server adds every module with its destructive flag set.
OAuth discovery (RFC 9728)
By default the server is a plain bearer-token resource: a caller must already hold a token. Set ProtectedResourceMetadata to opt into OAuth 2.0 Protected Resource Metadata (RFC 9728) so a spec-compliant MCP client can discover the authorization server and run the sign-in flow itself. MapLatticeMcp then serves an anonymous metadata document at /.well-known/oauth-protected-resource (the default WellKnownPath), and the binding appends a resource_metadata hint to the 401 bearer challenge on the transport path. The feature is scheme-agnostic - it augments whatever bearer challenge the host's authentication handler emits - so it needs no dependency on a specific auth library. Resource is this server's public, canonical URL as clients reach it (for example the CDN or ingress edge).
var builder = WebApplication.CreateBuilder();
builder.Services.AddLatticeMcp(o =>
{
o.RequireAuthorization = true;
o.TransportPattern = "/mcp";
o.ProtectedResourceMetadata = new LatticeApiMcpProtectedResourceMetadata
{
Resource = new Uri("https://mcp.example.com"),
AuthorizationServers = { new Uri("https://login.microsoftonline.com/<tenant>/v2.0") },
ScopesSupported = { "api://<server-app-id>/.default" },
};
});
LatticeApiMcpProtectedResourceMetadata properties:
| Property | Type | Default | Purpose |
|---|---|---|---|
Resource |
Uri? |
null (required) |
This server's public, canonical base URL, emitted as the document's resource field and used to derive the absolute resource_metadata hint URL. MapLatticeMcp throws when it is unset. |
AuthorizationServers |
IList<Uri> |
empty | The authorization-server issuer URLs a client should use, emitted as authorization_servers; omitted when empty. |
ScopesSupported |
IList<string> |
empty | The scopes a client should request, emitted as scopes_supported; omitted when empty. |
BearerMethodsSupported |
IList<string> |
["header"] |
The supported ways of sending the bearer token, emitted as bearer_methods_supported; omitted when cleared. |
WellKnownPath |
string |
/.well-known/oauth-protected-resource (DefaultWellKnownPath) |
The path the anonymous document is served at. Must be a root-absolute path starting with /; MapLatticeMcp throws otherwise. |
Next
- Tools - the built-in modules and every tool they expose.
- Security - the fail-closed posture and the credential bridge.
- Remote hosting - serving the surface out-of-silo over gRPC.