Configuration entry points
Signatures only: what you call, what it returns, and where the options themselves are defined. There are no output examples on this page by design — nothing here produces output.
Verified against Sezzlee.AspNetCore 0.1.0-alpha.1 and @sezzlee/sdk-nestjs at the current
workspace version. This surface has no generator, so it is hand-maintained and may lag a release.
ASP.NET Core
Three calls, in this order.
IServiceCollection AddSezzlee(this IServiceCollection services, Action<SezzleeOptions>? configure = null)
IApplicationBuilder UseSezzleeCapture(this IApplicationBuilder app)
IEndpointConventionBuilder MapSezzlee(this IEndpointRouteBuilder endpoints, string pattern = "/mcp")AddSezzlee also registers AddEndpointsApiExplorer(), decorates the authorization result handler
so probes can short-circuit, and calls AddMcpServer().WithHttpTransport(). Options are validated
at startup.
MapSezzlee returns IEndpointConventionBuilder, which is why endpoint conventions compose:
app.MapSezzlee("/mcp").RequireAuthorization();It throws at startup if UseSezzleeCapture() was never registered.
Selection markers:
[McpTool] // Name, Prefix, ReadOnly, Destructive, Idempotent
[McpIgnore]
interface IMcpSelectionMetadata { bool Include { get; } }IMcpSelectionMetadata is public, so a host can attach selection through its own metadata type.
[McpTool(Consumes = "...")] names a body media type discovery would not choose.
File resolution is a service, not an option: register an ISezzleeFileResolver and file arguments
offer ref. The budgets are Invoke.MaxInlineFileBytes and Invoke.MaxFileBytes; see
how to accept form bodies and file uploads.
Response types are read from ApiExplorer — [ProducesResponseType(typeof(T), 200)], Produces<T>()
or an action return type MVC can infer — so there is no [McpTool] field for them. NestJS has no
ApiExplorer equivalent and needs the responses option above; see
telling the agent what a tool returns.
Curation markers:
[McpArgument("q", Name = "keyword", Description = "...")] // rename, re-describe
[McpArgument("tenantId", Hidden = true, ValueFrom = "...")] // hide: provider, Value, or ValueJson
[McpToolVariant("name", "description")] // one of several tools per operation
[McpToolFamily("methodId", Source = "...")] // one tool per method behind a dispatcheroptions.Families.Provide(name, source) registers a family's member source, and
Families.LoadTimeout bounds each load; see
how to expose a dispatching endpoint as one tool per method.
McpArgumentAttribute also targets a parameter or a DTO property, where the member names the
argument. At most one of Value, ValueJson and ValueFrom may be set, and none without
Hidden = true.
Option groups are thirteen properties on SezzleeOptions — Identity, Synthetic, Selection,
Query, Schema, Naming, Visibility, Cache, Errors, ResourceServer, Diagnostics, Arguments, Families. Their fields
and defaults are in
SezzleeOptions.cs;
this page does not copy them.
NestJS
SezzleeModule.forRoot(
configure?: (options: SezzleeOptions) => void,
overrides?: ExtensionOverrides,
): DynamicModule
SezzleeModule.forRootAsync(asyncOptions: {
imports?: DynamicModule["imports"];
inject?: InjectionToken[];
useFactory: (...args: never[]) => SezzleeOptions | Promise<SezzleeOptions>;
overrides?: ExtensionOverrides;
}): DynamicModuleforRoot takes a callback that mutates an options instance, not an options literal. This is
the most common miswiring in the SDK: passing an object configures nothing.
The module is @Global(). When resourceServer is set it also installs the PRM handler and bearer
verification on the MCP path itself.
Curation on the NestJS side:
McpVariant(options: McpVariantOptions): MethodDecorator
McpToolFamily(options: McpToolFamilyOptions): MethodDecorator
const hidden: {
value(value: JsonValue): ArgumentRule;
from(source: string): ArgumentRule;
omit(): ArgumentRule;
};
function curate<T>(rules: ArgumentRules<T>): ArgumentRules<T>;curate<T>() key-checks the record against a DTO's own keys at compile time; arguments accepts a
plain record without it. options.arguments carries provide, curate, everywhere and seal.
options.families carries provide and loadTimeoutMs; the member shape is McpFamilyMember.
options.query.grouping ("flatten" by default, "group" to opt in) and its ASP.NET twin
options.Query.Grouping decide whether a whole-object query binding stays one argument or is
flattened into its members; see
curating the arguments an agent sees.
There is no MapSezzlee equivalent. You write the MCP route:
SezzleeStreamableHttp.handle(
req: Request,
res: Response,
createServer: () => McpServer,
): Promise<void>
registerSezzleeTools(server: McpServer, deps: MetaToolDependencies): () => voidMetaToolDependencies is { catalog, dispatcher, mapper, visibility, scopes, options } —
injectable as SezzleeCatalog, SezzleeDispatcher, extensionTokens.invokeResultMapper,
CallerVisibilityProvider, extensionTokens.callerScopeResolver and SEZZLEE_OPTIONS. The
quickstart has the whole controller:
Expose your backend's endpoints to an agent.
Selection markers:
@McpTool(options?: {
name?: string; prefix?: string; description?: string;
body?: JsonSchemaObject;
responses?: Record<string, NewableFunction | [NewableFunction] | { schema } | {}>;
consumes?: string;
files?: Record<string, { multiple?; required?; description?; mediaType? }>;
readOnly?: boolean; destructive?: boolean; idempotent?: boolean;
})
@McpIgnore()Guard declaration, read once at catalog build time:
interface VisibilityDeclaration {
readonly anonymous?: "yes" | "no" | "unknown";
readonly policies?: readonly string[];
}options.files.resolver binds the file resolver, and options.invoke.maxInlineFileBytes and
options.invoke.maxFileBytes are the budgets.
Option fields and defaults are in
options.ts.
The two option trees are not the same shape — the NestJS tree has a transport group the .NET one
does not — so read each SDK's own file rather than assuming parity.
Extension points
Six internals are replaceable, addressed by extensionTokens and overridden through forRoot's
second argument (useClass, useFactory or useValue):
cache · callerScopeResolver · invokeResultMapper · visibilityEvaluator · probeEvaluator · toolRankertoolRanker defaults to none, which keeps BM25. Bound, it replaces the ranking of a non-empty
search_tools query; options.search.rankerTimeoutMs and options.search.onRankerFailure govern
it. The ASP.NET Core equivalent is an IToolRanker registered in DI, with options.Search. See
replacing the ranking.
Cache invalidation is a service, not an option:
SezzleeCacheInvalidator.invalidateCaller(...) | invalidateTag(...) | invalidateAll()Each token names an internal the host may replace; the shapes they expect are in the SDK's own source, next to the token definitions.
Catalog reload
SezzleeCatalog.reload(): Promise<void>ISezzleeCatalogChangeSource.ReloadAsync(CancellationToken cancellationToken = default): ValueTaskRebuilds the catalog, bumps the generation counter, and fires the change listeners that re-stamp
_meta and send notifications/tools/list_changed. See
meta-tool contract. With no family source registered the
NestJS rebuild has happened by the time the call returns. With one, members are loaded first,
reloads run one at a time, and a rebuild that would turn a valid catalog fatal is refused — the
promise rejects, or the task throws, with SezzleeCatalogError / SezzleeCatalogException — and the
current catalog is kept.