Skip to main content

Kandra.Mcp

Kandra.Mcp.Auth.ApiKeyOnlyAuthorizationHandler​

Succeeds only when the authenticated principal carries the token_kind=apikey claim ApiKeyAuthenticator stamps on every API-key-derived principal. Checking the claim (rather than restricting the endpoint's authentication scheme directly to ApiKeyConstants.Scheme) keeps KandraAuthenticationSchemes.Default's JWT-or-API-key forwarding intact, so a JWT caller still gets authenticated (then cleanly 403s here) instead of the policy scheme silently never trying JWT at all.

Kandra.Mcp.Auth.ApiKeyOnlyRequirement​

Requires the caller to have authenticated via an API key (Kandra.Constants.ApiKeyConstants), rejecting a JWT-authenticated (human) caller - the MCP endpoint intentionally never accepts JWT, per docs/kandra-architecture.md §8.1.

Kandra.Mcp.KandraMcpEndpointRouteBuilderExtensions​

Methods​

MethodDescription
MapKandraMcp(IEndpointRouteBuilder, String)Maps the MCP HTTP endpoint at pattern, gated by the API-key-only authorization policy (ApiKeyOnlyRequirement) - a JWT-authenticated (human) caller gets 403, an unauthenticated caller gets 401, per docs/kandra-architecture.md §8.1.

Kandra.Mcp.KandraMcpServiceCollectionExtensions​

Methods​

MethodDescription
AddKandraMcp<T0>(IServiceCollection, String)Wires the engine-generic half of the MCP server: the entity catalog (composed from the per-configuration generated TCatalog plus the already-registered IConstantRegistry), the dynamic meta-tools, the blob tools, and the API-key-only authorization policy. Deliberately separate from Kandra.Api.Lib's AddKandra/ UseKandra - MCP exposure is a per-deployment opt-in, not something every configuration gets unconditionally (see this project's own design notes). A configuration also needs to call its own generated AddGenerated{Config}EntityAdapters() (emitted by Kandra.Generators.EntityOperations into its Application project) and, after building the host, MapKandraMcp.

Kandra.Mcp.RateLimiting.INotificationRateLimiter​

Per-API-key throttle for the send_notification MCP tool - a misbehaving or overly chatty agent shouldn't be able to flood every user's inbox. Fixed-hourly-window counter, sufficient for this project's single-server target (no distributed limiter needed - see the notifications design doc §4.2).

Methods​

MethodDescription
TryAcquire(Guid)Returns false (and reserves nothing) if apiKeyId has already reached its hourly cap; otherwise counts this call against the window and returns true.

Kandra.Mcp.RateLimiting.InMemoryNotificationRateLimiter​

Registered singleton - the fixed window has to live longer than any one scoped MCP request. One WindowState per API key id, lock-protected since two calls from the same key can race concurrently; other keys never contend with each other.

Constructors​

ConstructorDescription
InMemoryNotificationRateLimiter(TimeProvider)Registered singleton - the fixed window has to live longer than any one scoped MCP request. One WindowState per API key id, lock-protected since two calls from the same key can race concurrently; other keys never contend with each other.

Kandra.Mcp.Tools.AccountingTools​

Tool 9 (get_chart_of_accounts) - lets an AI agent understand the chart-of-accounts structure before constructing an AccountTransaction (a manual debit/credit posting, kind=Document). Wraps the already engine-registered, configuration-agnostic IChartOfAccountsTreeService (the same service the Blazor client's account/subconto picker UI reads), and cross-references each subconto slot's declared type against the MCP entity catalog by its [TypeId] - the same Guid identity both the chart and every Dictionary/Document/Enum Dto already carry - so a slot's requirement is reported as "Kind:TypeName", directly usable as execute_entity_operation's own kind/typeName arguments to look up a valid value id.

Constructors​

ConstructorDescription
AccountingTools(IChartOfAccountsTreeService, IEntityCatalog, IStringLocalizer)Tool 9 (get_chart_of_accounts) - lets an AI agent understand the chart-of-accounts structure before constructing an AccountTransaction (a manual debit/credit posting, kind=Document). Wraps the already engine-registered, configuration-agnostic IChartOfAccountsTreeService (the same service the Blazor client's account/subconto picker UI reads), and cross-references each subconto slot's declared type against the MCP entity catalog by its [TypeId] - the same Guid identity both the chart and every Dictionary/Document/Enum Dto already carry - so a slot's requirement is reported as "Kind:TypeName", directly usable as execute_entity_operation's own kind/typeName arguments to look up a valid value id.

Methods​

MethodDescription
BuildTypeIdIndexOne catalog entry per subconto-referenceable [TypeId] - a hierarchical entry is keyed by its root Dto's [TypeId], the dictionary's one TypeId shared by folder and leaf, which is what a subconto slot's TypeId matches (subconto only ever holds a leaf value, e.g. a Counterparty, but the leaf inherits the root's TypeId rather than carrying its own).

Kandra.Mcp.Tools.BlobTools​

Tools 7 (upload_blob) and 8 (download_blob) - thin wrappers over IBlobService, entirely independent of the entity catalog/adapters. Base64-inline content, not an MCP resource reference - unnecessary extra machinery for what are typically small attachments. A blob uploaded here is attached to an entity by putting its returned id into the target Dto's [FilePicker] property on a subsequent Create/Update call via execute_entity_operation.

Constructors​

ConstructorDescription
BlobTools(IBlobService)Tools 7 (upload_blob) and 8 (download_blob) - thin wrappers over IBlobService, entirely independent of the entity catalog/adapters. Base64-inline content, not an MCP resource reference - unnecessary extra machinery for what are typically small attachments. A blob uploaded here is attached to an entity by putting its returned id into the target Dto's [FilePicker] property on a subsequent Create/Update call via execute_entity_operation.

Kandra.Mcp.Tools.EntityKindCatalog​

Fixed, hand-written per-kind explanation/operation vocabulary for tools 2 (list_entity_kinds) and 3 (describe_entity_kind) - structural facts about the entity-kind system (docs/kandra-architecture.md §2.1's capability matrix), not derived from any per-configuration catalog.

Kandra.Mcp.Tools.EntityMetaTools​

Tools 3 (describe_entity_kind), 4 (list_entity_types), 5 (describe_entity_type).

Constructors​

ConstructorDescription
EntityMetaTools(IEntityCatalog, EntityFieldMetadataBuilder, IConstantsService)Tools 3 (describe_entity_kind), 4 (list_entity_types), 5 (describe_entity_type).

Kandra.Mcp.Tools.EntityOperationTools​

Tool 6 (execute_entity_operation) - the single generic dispatch point onto every entity's CRUD/report/processor/constant service.

Constructors​

ConstructorDescription
EntityOperationTools(IEntityOperationExecutor)Tool 6 (execute_entity_operation) - the single generic dispatch point onto every entity's CRUD/report/processor/constant service.

Kandra.Mcp.Tools.NotificationMcpTools​

Tools 10 (send_notification) and 11 (find_users) - lets an AI agent notify a human, e.g. after finishing a long-running task on their behalf (design: docs/kandra-notifications-and-messaging-design.md §4). Gated by NotificationsAuthorizationPoint - a permission an admin grants to a role/API-key owner separately from the broader "can call MCP at all" check (ApiKeyOnlyAuthorizationHandler), and independent of INotificationService itself, which stays ungated for trusted in-process producers. send_notification only ever calls NotifyUsersAsync - never NotifyRoleAsync/NotifyWithPermissionAsync - so an agent can reach a caller-chosen list of users but never a broadcast audience.

Constructors​

ConstructorDescription
NotificationMcpTools(INotificationService, ILookupService, IUnitOfWork, ICallerContext, IAuthorizationChecker, INotificationRateLimiter, IEntityCatalog)Tools 10 (send_notification) and 11 (find_users) - lets an AI agent notify a human, e.g. after finishing a long-running task on their behalf (design: docs/kandra-notifications-and-messaging-design.md §4). Gated by NotificationsAuthorizationPoint - a permission an admin grants to a role/API-key owner separately from the broader "can call MCP at all" check (ApiKeyOnlyAuthorizationHandler), and independent of INotificationService itself, which stays ungated for trusted in-process producers. send_notification only ever calls NotifyUsersAsync - never NotifyRoleAsync/NotifyWithPermissionAsync - so an agent can reach a caller-chosen list of users but never a broadcast audience.

Kandra.Mcp.Tools.SystemTools​

Tools 1 (describe_system) and 2 (list_entity_kinds) - static, no per-caller state.