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