@ttoss/http-server-mcp 0.33.2 → 0.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@
2
2
  /// <reference types="node" />
3
3
  import { Router } from "@ttoss/http-server";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
- import { CallToolResult, InMemoryServerEventBus, McpServer, McpServer as McpServer$1, McpServerFactory, RegisteredResource, ServerEvent, ServerEventBus, ServerEventBus as ServerEventBus$1, ServerNotifier, ServerNotifier as ServerNotifier$1, ToolAnnotations } from "@modelcontextprotocol/server";
5
+ import { CallToolResult, InMemoryServerEventBus, McpServer, McpServer as McpServer$1, McpServerFactory, RegisteredResource, ServerEvent, ServerEventBus, ServerEventBus as ServerEventBus$1, ServerNotifier, ServerNotifier as ServerNotifier$1, StandardSchemaWithJSON, ToolAnnotations } from "@modelcontextprotocol/server";
6
6
  import { z } from "zod";
7
7
  import accepts from "accepts";
8
8
  import { AsyncLocalStorage as AsyncLocalStorage$1 } from "async_hooks";
@@ -688,10 +688,205 @@ declare const getApiHeaders: () => Record<string, string>;
688
688
  /**
689
689
  * The `Accept-Language` header of the current MCP request, or `undefined`
690
690
  * outside a request or when the client sent none. The default locale source
691
- * for `createGatedToolRegistrar`'s `i18n` option.
691
+ * for `createToolGate`'s `i18n` option.
692
692
  */
693
693
  declare const getRequestLocale: () => string | undefined;
694
694
  //#endregion
695
+ //#region src/tool.d.ts
696
+ /**
697
+ * A plain JSON Schema object (draft-07 compatible) describing the shape of a
698
+ * tool's input or output. Forwarded verbatim over `tools/list`, so features
699
+ * Zod cannot express (`anyOf`, `$ref`, `pattern`, `allOf`, …) survive intact.
700
+ */
701
+ interface JsonObjectSchema {
702
+ type: 'object';
703
+ properties?: Record<string, unknown>;
704
+ required?: string[];
705
+ [key: string]: unknown;
706
+ }
707
+ /**
708
+ * A schema a tool declares: a plain JSON Schema, or a Standard Schema with
709
+ * JSON Schema support — Zod 4's `z.object(...)`, ArkType, or Valibot.
710
+ */
711
+ type ToolSchema = JsonObjectSchema | StandardSchemaWithJSON;
712
+ /**
713
+ * An MCP tool: what it is and how it answers, independent of how a server
714
+ * exposes it. {@link registerTools} registers a list of them, either one MCP
715
+ * tool each or deferred behind `search` / `describe` / `call`.
716
+ */
717
+ interface Tool {
718
+ /** Unique tool name. */
719
+ name: string;
720
+ /** Display name clients show instead of `name`. */
721
+ title?: string;
722
+ /** What the tool does, written for the model. */
723
+ description: string;
724
+ /**
725
+ * The tool's input.
726
+ *
727
+ * - A **JSON Schema** is advertised verbatim and enforced only with
728
+ * `validateArguments`; the handler receives the raw arguments.
729
+ * - A **Standard Schema** (`z.object(...)`) is always enforced; the handler
730
+ * receives its parsed output, defaults and coercions applied.
731
+ *
732
+ * @default { type: 'object', properties: {} }
733
+ */
734
+ inputSchema?: ToolSchema;
735
+ /**
736
+ * Whether a JSON Schema `inputSchema` is enforced before the handler runs.
737
+ *
738
+ * Enable it once the schema describes every value the tool genuinely
739
+ * accepts. Schemas generated from an OpenAPI document are a common source of
740
+ * *incomplete* ones — a field a client may send as `null` to clear it, or
741
+ * one accepting several shapes, is easy to emit as a bare
742
+ * `{ type: 'string' }` — and validating against them rejects calls the
743
+ * underlying API would have accepted. A Standard Schema ignores this flag.
744
+ *
745
+ * @default false
746
+ */
747
+ validateArguments?: boolean;
748
+ /**
749
+ * The result's schema, advertised on `tools/list`. A result's
750
+ * `structuredContent` is validated against it.
751
+ */
752
+ outputSchema?: ToolSchema;
753
+ /**
754
+ * Behaviour hints forwarded on `tools/list` (`readOnlyHint`,
755
+ * `destructiveHint`, `idempotentHint`, `openWorldHint`). Clients use them to
756
+ * decide when to ask the user for confirmation; they never enforce anything.
757
+ */
758
+ annotations?: ToolAnnotations;
759
+ /** Groups the tool for the deferred `search` filter. Not sent on `tools/list`. */
760
+ tags?: string[];
761
+ /**
762
+ * The line the deferred `search` shows for the tool. Defaults to the first
763
+ * line of `description`. Not sent on `tools/list`.
764
+ */
765
+ summary?: string;
766
+ /**
767
+ * Tool metadata forwarded verbatim on `tools/list`. The MCP Apps extension
768
+ * links a tool to its view through it: build the bag with
769
+ * `registerAppResource(...).toolMeta()`.
770
+ */
771
+ _meta?: Record<string, unknown>;
772
+ /** Answers a call with the (validated, when enforced) arguments. */
773
+ handler: (args: Record<string, unknown>) => CallToolResult | Promise<CallToolResult>;
774
+ }
775
+ /** Parameters for {@link defineTool}. */
776
+ interface DefineToolParams extends Omit<Tool, 'handler'> {
777
+ /**
778
+ * Answers a call with plain data, which becomes the tool result: JSON text,
779
+ * plus `structuredContent` when `outputSchema` is set. Resolving to `null`
780
+ * or `undefined` answers `notFoundMessage` as an `isError` result.
781
+ */
782
+ method: (args: Record<string, unknown>) => unknown;
783
+ /**
784
+ * The `isError` message for a `null` or `undefined` result.
785
+ * @default 'Not found'
786
+ */
787
+ notFoundMessage?: string;
788
+ }
789
+ /**
790
+ * Builds a {@link Tool} from a `method` that returns data instead of a
791
+ * `CallToolResult`, which is what most hand-written tools want.
792
+ *
793
+ * @example
794
+ * ```typescript
795
+ * const getCampaign = defineTool({
796
+ * name: 'get-campaign',
797
+ * description: 'Get a campaign by id.',
798
+ * inputSchema: z.object({ campaignId: z.string() }),
799
+ * method: ({ campaignId }) => findCampaign(campaignId as string),
800
+ * notFoundMessage: 'Campaign not found',
801
+ * });
802
+ * ```
803
+ */
804
+ declare const defineTool: ({
805
+ method,
806
+ notFoundMessage,
807
+ ...tool
808
+ }: DefineToolParams) => Tool;
809
+ //#endregion
810
+ //#region src/toolSearch.d.ts
811
+ /** What the deferred `search` ranks: one call, already narrowed to the visible tools. */
812
+ interface ToolSearchArgs {
813
+ /** Free-text query. One without words lists the tools in order. */
814
+ query: string;
815
+ /** Only tools carrying this tag. */
816
+ tag?: string;
817
+ /** Maximum number of tools to return. */
818
+ limit: number;
819
+ /** The tools this request may see. */
820
+ tools: Tool[];
821
+ }
822
+ /**
823
+ * The deferred tools' default search: scores each tool by the query's terms,
824
+ * weighted name > summary > tags > description, and breaks ties by the
825
+ * tools' order. No index — a few hundred tools need none.
826
+ */
827
+ declare const rankTools: ({
828
+ query,
829
+ tag,
830
+ limit,
831
+ tools
832
+ }: ToolSearchArgs) => Tool[];
833
+ //#endregion
834
+ //#region src/deferTools.d.ts
835
+ /** How {@link registerTools} defers tools behind `search` / `describe` / `call`. */
836
+ interface DeferToolsOptions {
837
+ /**
838
+ * Tools that are not deferred: they are also registered as standalone MCP
839
+ * tools, and stay reachable through `search` / `describe` / `call` too.
840
+ *
841
+ * Defaults to the tools linked to an MCP Apps view: a host finds a tool's
842
+ * view through that tool's own `tools/list` entry, so a view behind `call`
843
+ * would never render.
844
+ */
845
+ except?: (args: {
846
+ tool: Tool;
847
+ }) => boolean;
848
+ /**
849
+ * The names of the three tools that reach the deferred ones, to avoid a
850
+ * collision with a standalone tool or to defer two sets on one server.
851
+ * @default { search: 'search', describe: 'describe', call: 'call' }
852
+ */
853
+ names?: {
854
+ search?: string;
855
+ describe?: string;
856
+ call?: string;
857
+ };
858
+ /**
859
+ * Replaces the default ranking, e.g. with embeddings. Receives only the
860
+ * tools `visible` lets through; the result is cut to `limit`.
861
+ * {@link rankTools} is the default, for a fallback.
862
+ */
863
+ search?: (args: ToolSearchArgs) => Tool[] | Promise<Tool[]>;
864
+ /**
865
+ * How many tools `search` returns when the model does not say.
866
+ * @default 10
867
+ */
868
+ searchLimit?: number;
869
+ /**
870
+ * The largest `limit` `search` accepts. With no ceiling, an empty query
871
+ * lists every tool, more than a client's context holds.
872
+ * @default 50, or `searchLimit` when that is higher
873
+ */
874
+ searchMaxLimit?: number;
875
+ /**
876
+ * Runs on every `search`, `describe` and `call`. A tool it rejects is
877
+ * absent from all three; `call` answers it as an unknown name. Tools
878
+ * `except` keeps standalone are listed on `tools/list` regardless.
879
+ *
880
+ * @example
881
+ * ```typescript
882
+ * visible: ({ tool }) => canUse({ identity: getIdentity(), tool: tool.name }),
883
+ * ```
884
+ */
885
+ visible?: (args: {
886
+ tool: Tool;
887
+ }) => boolean;
888
+ }
889
+ //#endregion
695
890
  //#region src/registerAppResource.d.ts
696
891
  /**
697
892
  * Identifier of the MCP Apps extension (`io.modelcontextprotocol/ui`), used as
@@ -800,9 +995,8 @@ interface RegisteredAppResource {
800
995
  /** The SDK's registration handle, for `update`/`disable`/`remove`. */
801
996
  resource: RegisteredResource;
802
997
  /**
803
- * Builds the `_meta` bag that links a tool to this view. Pass it to
804
- * `registerTool`, {@link registerToolFromSchema}, or a `GatedToolDef` —
805
- * whichever registration path the tool uses.
998
+ * Builds the `_meta` bag that links a tool to this view. Pass it as a
999
+ * `Tool`'s `_meta`, or to the SDK's `registerTool`.
806
1000
  */
807
1001
  toolMeta: (params?: ToolMetaParams) => Record<string, unknown>;
808
1002
  }
@@ -883,113 +1077,59 @@ declare const registerAppResource: ({
883
1077
  ui
884
1078
  }: RegisterAppResourceParams) => RegisteredAppResource;
885
1079
  //#endregion
886
- //#region src/registerToolFromSchema.d.ts
887
- /**
888
- * A plain JSON Schema object (draft-07 compatible) describing the shape of a
889
- * tool's input. Used with {@link registerToolFromSchema} as an alternative to
890
- * providing a Zod shape, enabling lossless round-trips for schemas that contain
891
- * features not expressible in Zod v3 (`anyOf`, `$ref`, `pattern`, `allOf`, …).
892
- */
893
- interface JsonObjectSchema {
894
- type: 'object';
895
- properties?: Record<string, unknown>;
896
- required?: string[];
897
- [key: string]: unknown;
898
- }
899
- /**
900
- * Parameters accepted by {@link registerToolFromSchema}.
901
- */
902
- interface RegisterToolFromSchemaParams {
903
- /** Unique tool name. */
904
- name: string;
905
- /** Human-readable description shown to the AI client. */
906
- description?: string;
907
- /**
908
- * Plain JSON Schema that describes the tool's input object.
909
- * This schema is forwarded verbatim over the MCP wire protocol, so any
910
- * JSON Schema feature (`anyOf`, `$ref`, `pattern`, …) is preserved without
911
- * loss. Defaults to `{ type: 'object', properties: {} }` when omitted.
912
- */
913
- inputSchema?: JsonObjectSchema;
1080
+ //#region src/registerTools.d.ts
1081
+ /** Parameters for {@link registerTools}. */
1082
+ interface RegisterToolsParams {
1083
+ /** The MCP server the tools are registered on. */
1084
+ server: McpServer$1;
1085
+ /** The tools to expose. */
1086
+ tools: Tool[];
914
1087
  /**
915
- * Whether `tools/call` arguments are validated against `inputSchema` before
916
- * the handler runs, rejecting a mismatch with an MCP error.
1088
+ * Defers `tools` behind three tools — `search`, `describe`, `call` —
1089
+ * instead of registering one MCP tool each. `true` takes every
1090
+ * {@link DeferToolsOptions} default.
917
1091
  *
918
- * Defaults to `false`, which forwards arguments to the handler unchecked —
919
- * the behavior this helper has always had. `inputSchema` is still advertised
920
- * verbatim over `tools/list` either way; this only controls enforcement.
921
- *
922
- * Enable it once you know `inputSchema` describes every value the tool
923
- * genuinely accepts. Schemas generated from an OpenAPI document are a common
924
- * source of *incomplete* ones — a field a client may send as `null` to clear
925
- * it, or one accepting several shapes, is easy to emit as a bare
926
- * `{ type: 'string' }`. Validating against a schema like that rejects calls
927
- * the underlying API would have accepted.
1092
+ * A large tool set overflows a client's context: every definition ships to
1093
+ * the model on every turn, some providers cap the number of tools per
1094
+ * request, and clients that don't defer tool loading choke on the list.
1095
+ * Deferred, the model sees three small definitions, and a schema
1096
+ * enters its context only for the tools it is about to use.
928
1097
  *
929
1098
  * @default false
930
1099
  */
931
- validateArguments?: boolean;
932
- /**
933
- * Tool metadata forwarded verbatim on `tools/list`.
934
- *
935
- * The MCP Apps extension links a tool to the view its result is rendered
936
- * with through this field; build the bag with `toolMeta()` from
937
- * `registerAppResource` rather than writing the keys by hand.
938
- *
939
- * @example
940
- * ```typescript
941
- * _meta: dashboard.toolMeta({ visibility: ['app'] }),
942
- * ```
943
- */
944
- _meta?: Record<string, unknown>;
945
- /**
946
- * Tool handler invoked when the AI client calls the tool.
947
- * Receives the request arguments, validated against `inputSchema` only when
948
- * `validateArguments` is enabled.
949
- */
950
- handler: (args: Record<string, unknown>) => CallToolResult | Promise<CallToolResult>;
1100
+ defer?: boolean | DeferToolsOptions;
951
1101
  }
952
1102
  /**
953
- * Registers a tool on an MCP server using a **plain JSON Schema** object for
954
- * `inputSchema` instead of a Zod shape.
955
- *
956
- * This is useful when tool definitions are shared between the MCP server and
957
- * an AI SDK agent (e.g. Vercel AI SDK's `tool()` helper), because both consume
958
- * a plain JSON Schema at runtime. Using this helper eliminates the lossy
959
- * JSON-Schema→Zod conversion that would otherwise be required.
960
- *
961
- * Thin wrapper over `@modelcontextprotocol/server`'s `fromJsonSchema`, which
962
- * converts a JSON Schema into a Standard Schema that `registerTool` accepts
963
- * directly, so the schema round-trips verbatim over `tools/list`. Arguments
964
- * reach the handler unchecked unless `validateArguments` is enabled.
965
- *
966
- * @param server - The `McpServer` instance to register the tool on.
967
- * @param params - Tool configuration including name, description, inputSchema,
968
- * validateArguments, `_meta`, and handler.
1103
+ * Registers tools on an MCP server, either one MCP tool each (the default)
1104
+ * or deferred behind `search` / `describe` / `call`. The same `tools` can feed
1105
+ * both, so two endpoints over one API cannot drift apart.
969
1106
  *
970
1107
  * @example
971
1108
  * ```typescript
972
- * import { registerToolFromSchema, McpServer } from '@ttoss/http-server-mcp';
973
- *
974
- * const server = new McpServer({ name: 'my-server', version: '1.0.0' });
1109
+ * import { McpServer, registerTools, z } from '@ttoss/http-server-mcp';
975
1110
  *
976
- * registerToolFromSchema(server, {
977
- * name: 'get-project',
978
- * description: 'Get a project by ID',
979
- * inputSchema: {
980
- * type: 'object',
981
- * properties: { id: { type: 'string', description: 'Project public ID' } },
982
- * required: ['id'],
1111
+ * const tools = [
1112
+ * {
1113
+ * name: 'get-project',
1114
+ * description: 'Get a project by ID',
1115
+ * inputSchema: z.object({ id: z.string() }),
1116
+ * handler: async ({ id }) => ({
1117
+ * content: [{ type: 'text', text: `Project: ${id}` }],
1118
+ * }),
983
1119
  * },
984
- * handler: async ({ id }) => ({
985
- * content: [{ type: 'text', text: `Project: ${id}` }],
986
- * }),
987
- * });
1120
+ * ];
1121
+ *
1122
+ * registerTools({ server: fullServer, tools });
1123
+ * registerTools({ server: deferredServer, tools, defer: true });
988
1124
  * ```
989
1125
  */
990
- declare const registerToolFromSchema: (server: McpServer$1, params: RegisterToolFromSchemaParams) => void;
1126
+ declare const registerTools: ({
1127
+ server,
1128
+ tools,
1129
+ defer
1130
+ }: RegisterToolsParams) => void;
991
1131
  //#endregion
992
- //#region src/createGatedToolRegistrar.d.ts
1132
+ //#region src/toolGate.d.ts
993
1133
  /** Resolved identity for a gated tool call. */
994
1134
  type ToolIdentity = {
995
1135
  userId: string;
@@ -1003,50 +1143,16 @@ type ToolIdentity = {
1003
1143
  type ToolCallContext = {
1004
1144
  /** The resolved caller identity. */identity: ToolIdentity;
1005
1145
  /**
1006
- * The validated tool input (post SDK parse). Present for gates and
1007
- * `buildContext`. Arg-conditional gates read this to vary their predicate
1008
- * per call.
1146
+ * The validated tool input. Arg-conditional gates read this to vary their
1147
+ * predicate per call.
1009
1148
  */
1010
1149
  args: Record<string, unknown>; /** Tool name, for error attribution and gate labelling. */
1011
1150
  handler: string;
1012
1151
  };
1013
- /** Definition for a single gated tool. */
1014
- type GatedToolDef = {
1015
- /** Tool name as registered with the MCP server. */name: string; /** Human-readable tool description. */
1016
- description: string; /** Display name shown by clients instead of `name`. */
1017
- title?: string;
1018
- /**
1019
- * Behaviour hints forwarded on `tools/list` (`readOnlyHint`,
1020
- * `destructiveHint`, `idempotentHint`, `openWorldHint`). Clients use them to
1021
- * decide when to ask the user for confirmation; they are hints, never
1022
- * enforcement — scope and gates still decide what may run.
1023
- */
1024
- annotations?: ToolAnnotations;
1025
- /**
1026
- * Zod field map or ZodObject describing the result. When set, a successful
1027
- * result is also returned as `structuredContent`, and the SDK validates it
1028
- * against this schema.
1029
- */
1030
- outputSchema?: unknown; /** The single scope that must be present on the caller's token. */
1031
- requiredScope: string; /** Zod field map or ZodObject — passed through to `server.registerTool`. */
1032
- inputSchema: unknown;
1033
- /**
1034
- * Per-tool gates merged after the global `gates`. Useful for arg-conditional
1035
- * authorization (e.g. different subscription tiers based on call args).
1036
- * Each gate receives the full {@link ToolCallContext} (identity + args).
1037
- * Throw to reject the call; return (or resolve) to continue.
1038
- */
1039
- gates?: Array<(ctx: ToolCallContext) => void | Promise<void>>;
1040
- /**
1041
- * Tool metadata forwarded verbatim on `tools/list` — how a gated tool links
1042
- * to an MCP Apps view (`registerAppResource(...).toolMeta()`).
1043
- */
1044
- _meta?: Record<string, unknown>; /** The tool handler. Receives merged call args + `buildContext` output. */
1045
- method: (args: Record<string, unknown>) => Promise<unknown>;
1046
- };
1047
- /** Options for {@link createGatedToolRegistrar}. */
1048
- type CreateGatedToolRegistrarOptions = {
1049
- /** The MCP server instance to register tools on. */server: McpServer$1;
1152
+ /** An authorization check. Throw to reject the call; return to continue. */
1153
+ type ToolCallGate = (ctx: ToolCallContext) => void | Promise<void>;
1154
+ /** Options for {@link createToolGate}. */
1155
+ type CreateToolGateOptions = {
1050
1156
  /**
1051
1157
  * Called once per tool invocation to resolve the caller's identity.
1052
1158
  * Defaults to `getIdentity()` from the request context.
@@ -1057,12 +1163,11 @@ type CreateGatedToolRegistrarOptions = {
1057
1163
  * per-tool gates. Each receives the full {@link ToolCallContext} — both
1058
1164
  * identity and the validated call args — so gate predicates may be
1059
1165
  * conditional on either.
1060
- * Throw to reject the call; return (or resolve) to continue.
1061
1166
  * Gates own their own error handling — `onError` covers the tool handler only.
1062
1167
  */
1063
- gates?: Array<(ctx: ToolCallContext) => void | Promise<void>>;
1168
+ gates?: ToolCallGate[];
1064
1169
  /**
1065
- * When `true` (default), checks `def.requiredScope` against `identity.scopes`
1170
+ * When `true` (default), checks `requiredScope` against `identity.scopes`
1066
1171
  * and returns an `isError` result when the scope is absent. Set to `false`
1067
1172
  * to skip the scope check (e.g. when all scopes are enforced by `gates`).
1068
1173
  */
@@ -1079,11 +1184,6 @@ type CreateGatedToolRegistrarOptions = {
1079
1184
  * so context can vary by identity or by call args.
1080
1185
  */
1081
1186
  buildContext?: (ctx: ToolCallContext) => Record<string, unknown>;
1082
- /**
1083
- * Message returned as an `isError` result when the handler resolves to
1084
- * `null` or `undefined`. Defaults to `"Not found"`.
1085
- */
1086
- notFoundMessage?: string;
1087
1187
  /**
1088
1188
  * Renders a `LocalizedError` — thrown by a gate or by the handler — as an
1089
1189
  * `isError` result `{ error: <message>, code }` in the caller's locale,
@@ -1101,18 +1201,79 @@ type CreateGatedToolRegistrarOptions = {
1101
1201
  getLocale?: (ctx: ToolCallContext) => string | string[] | null | undefined | Promise<string | string[] | null | undefined>;
1102
1202
  };
1103
1203
  };
1104
- declare const createGatedToolRegistrar: ({
1105
- server,
1204
+ /** Parameters for the gate {@link createToolGate} returns. */
1205
+ interface GateToolParams {
1206
+ /** The tool to protect. */
1207
+ tool: Tool;
1208
+ /** The single scope that must be present on the caller's token. */
1209
+ requiredScope: string;
1210
+ /**
1211
+ * Per-tool gates run after the global `gates`. Useful for arg-conditional
1212
+ * authorization (e.g. different subscription tiers based on call args).
1213
+ */
1214
+ gates?: ToolCallGate[];
1215
+ }
1216
+ /** Wraps a {@link Tool}'s handler in the authorization pipeline. */
1217
+ type ToolGate = (params: GateToolParams) => Tool;
1218
+ /**
1219
+ * Factory for a gate: a function that wraps a {@link Tool} so every call
1220
+ * passes the same authentication and authorization pipeline before its
1221
+ * handler runs. The gated tool is an ordinary `Tool`, so it registers
1222
+ * directly or joins a catalog like any other.
1223
+ *
1224
+ * Every gated call:
1225
+ * 1. Resolves the caller identity (default: `getIdentity()`). Returns an
1226
+ * `isError` result when the identity is absent (unauthenticated request).
1227
+ * 2. When `enforceScope` is `true` (default), checks `requiredScope` — returns
1228
+ * an `isError` result when the scope is absent, consistent with how MCP
1229
+ * surfaces authorization errors.
1230
+ * 3. Runs global `gates` then the tool's `gates` in order; a throwing gate
1231
+ * rejects the call. Every gate receives the full {@link ToolCallContext}.
1232
+ * 4. Merges `buildContext` output into the handler args.
1233
+ * 5. Calls `onError` on handler throw before rethrowing.
1234
+ * 6. With `i18n`, renders a `LocalizedError` from a gate or the handler as an
1235
+ * `isError` result in the caller's locale instead of rethrowing it.
1236
+ *
1237
+ * @example
1238
+ * ```typescript
1239
+ * const gate = createToolGate({
1240
+ * resolveIdentity: () => {
1241
+ * const jwt = getIdentity<{ sub: string; scopes: string[] }>();
1242
+ * return { userId: jwt!.sub, scopes: jwt!.scopes };
1243
+ * },
1244
+ * });
1245
+ *
1246
+ * registerTools({
1247
+ * server,
1248
+ * tools: [
1249
+ * gate({
1250
+ * requiredScope: 'campaigns:write',
1251
+ * // arg-conditional gate: active vs. inactive have different restrictions
1252
+ * gates: [
1253
+ * ({ args }) =>
1254
+ * args.isActive
1255
+ * ? subscriptionGate(['mustNotExceedMaxActive', 'mustHaveBudget'])
1256
+ * : subscriptionGate(['mustIncludeService']),
1257
+ * ],
1258
+ * tool: defineTool({
1259
+ * name: 'activate-campaign',
1260
+ * description: 'Activate or deactivate a campaign.',
1261
+ * inputSchema: z.object({ isActive: z.boolean() }),
1262
+ * method: ({ userId, isActive }) => toggleCampaign(userId, isActive),
1263
+ * }),
1264
+ * }),
1265
+ * ],
1266
+ * });
1267
+ * ```
1268
+ */
1269
+ declare const createToolGate: ({
1106
1270
  resolveIdentity,
1107
1271
  gates,
1108
1272
  enforceScope,
1109
1273
  onError,
1110
1274
  buildContext,
1111
- notFoundMessage,
1112
1275
  i18n
1113
- }: CreateGatedToolRegistrarOptions) => {
1114
- register: (def: GatedToolDef) => void;
1115
- };
1276
+ }?: CreateToolGateOptions) => ToolGate;
1116
1277
  //#endregion
1117
1278
  //#region src/index.d.ts
1118
1279
  type Context$1 = Application.Context;
@@ -1551,4 +1712,4 @@ interface McpRouterOptions {
1551
1712
  */
1552
1713
  declare const createMcpRouter: (server: McpServer$1, options?: McpRouterOptions) => McpRouter;
1553
1714
  //#endregion
1554
- export { ApiCallOptions, CognitoUserPoolConfig, type CreateGatedToolRegistrarOptions, type GatedToolDef, InMemoryServerEventBus, type JsonObjectSchema, McpAuthOptions, McpRouter, McpRouterOptions, McpServer, type RegisterAppResourceParams, type RegisterToolFromSchemaParams, type RegisteredAppResource, type ServerEvent, type ServerEventBus, type ServerNotifier, type ToolCallContext, type ToolIdentity, type ToolMetaParams, UI_EXTENSION_ID, UI_RESOURCE_MIME_TYPE, type UiResourceCsp, type UiResourceMeta, type UiResourcePermissions, type UiToolVisibility, apiCall, checkScopes, createGatedToolRegistrar, createMcpRouter, errorBodyMessage, getApiHeaders, getIdentity, getRequestLocale, registerAppResource, registerToolFromSchema, z };
1715
+ export { ApiCallOptions, CognitoUserPoolConfig, type CreateToolGateOptions, type DeferToolsOptions, type DefineToolParams, type GateToolParams, InMemoryServerEventBus, type JsonObjectSchema, McpAuthOptions, McpRouter, McpRouterOptions, McpServer, type RegisterAppResourceParams, type RegisterToolsParams, type RegisteredAppResource, type ServerEvent, type ServerEventBus, type ServerNotifier, type Tool, type ToolCallContext, type ToolCallGate, type ToolGate, type ToolIdentity, type ToolMetaParams, type ToolSchema, type ToolSearchArgs, UI_EXTENSION_ID, UI_RESOURCE_MIME_TYPE, type UiResourceCsp, type UiResourceMeta, type UiResourcePermissions, type UiToolVisibility, apiCall, checkScopes, createMcpRouter, createToolGate, defineTool, errorBodyMessage, getApiHeaders, getIdentity, getRequestLocale, rankTools, registerAppResource, registerTools, z };