@warlock.js/ai-tools 5.33.0 → 5.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.
@@ -2,5 +2,5 @@ import { FetchUrlExtract, FetchUrlInput, FetchUrlOptions, FetchUrlResult, Search
2
2
  import { HttpMethod, HttpRequestInput, HttpRequestOptions, HttpRequestResult } from "./http.type.mjs";
3
3
  import { CalculatorInput, CalculatorOptions, CalculatorResult, DateTimeInput, DateTimeOp, DateTimeOptions, DateTimeResult } from "./utility.type.mjs";
4
4
  import { JsonRpcError, JsonRpcId, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, JsonRpcVersion, McpClient, McpClientOptions, McpContentBlock, McpToolCallResult, McpToolDescriptor, McpTransport } from "./mcp.type.mjs";
5
- import { McpBeforeCall, McpCallRefusal, McpGroupedToolSource, McpHttpAuth, McpHttpRequestInfo, McpHttpServeHandle, McpHttpServeTransport, McpPromptArgument, McpPromptMessage, McpServeCallContext, McpServeHandle, McpServeOptions, McpServePrompt, McpServeResource, McpServeSource, McpServeToolContext, McpServeTransport, McpServer, McpStdioServeTransport, McpToolSource } from "./mcp-serve.type.mjs";
6
- export type { CalculatorInput, CalculatorOptions, CalculatorResult, DateTimeInput, DateTimeOp, DateTimeOptions, DateTimeResult, FetchUrlExtract, FetchUrlInput, FetchUrlOptions, FetchUrlResult, HttpMethod, HttpRequestInput, HttpRequestOptions, HttpRequestResult, JsonRpcError, JsonRpcId, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, JsonRpcVersion, McpBeforeCall, McpCallRefusal, McpClient, McpClientOptions, McpContentBlock, McpGroupedToolSource, McpHttpAuth, McpHttpRequestInfo, McpHttpServeHandle, McpHttpServeTransport, McpPromptArgument, McpPromptMessage, McpServeCallContext, McpServeHandle, McpServeOptions, McpServePrompt, McpServeResource, McpServeSource, McpServeToolContext, McpServeTransport, McpServer, McpStdioServeTransport, McpToolCallResult, McpToolDescriptor, McpToolSource, McpTransport, SearchProvider, WebSearchInput, WebSearchOptions, WebSearchResult, WebSearchResultItem };
5
+ import { McpBeforeCall, McpCallRefusal, McpGroupedToolSource, McpHttpAuth, McpHttpAuthRefusal, McpHttpAuthRefusalBody, McpHttpAuthRefusalContext, McpHttpAuthRefusalHeader, McpHttpAuthRefusalResponse, McpHttpRequestInfo, McpHttpRoute, McpHttpRouteContext, McpHttpRouteResponse, McpHttpServeHandle, McpHttpServeTransport, McpListFilter, McpPromptArgument, McpPromptMessage, McpServeCallContext, McpServeHandle, McpServeOptions, McpServePrompt, McpServeResource, McpServeSource, McpServeToolContext, McpServeTransport, McpServer, McpStdioServeTransport, McpToolSource, McpValidateCallParams } from "./mcp-serve.type.mjs";
6
+ export type { CalculatorInput, CalculatorOptions, CalculatorResult, DateTimeInput, DateTimeOp, DateTimeOptions, DateTimeResult, FetchUrlExtract, FetchUrlInput, FetchUrlOptions, FetchUrlResult, HttpMethod, HttpRequestInput, HttpRequestOptions, HttpRequestResult, JsonRpcError, JsonRpcId, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, JsonRpcVersion, McpBeforeCall, McpCallRefusal, McpClient, McpClientOptions, McpContentBlock, McpGroupedToolSource, McpHttpAuth, McpHttpAuthRefusal, McpHttpAuthRefusalBody, McpHttpAuthRefusalContext, McpHttpAuthRefusalHeader, McpHttpAuthRefusalResponse, McpHttpRequestInfo, McpHttpRoute, McpHttpRouteContext, McpHttpRouteResponse, McpHttpServeHandle, McpHttpServeTransport, McpListFilter, McpPromptArgument, McpPromptMessage, McpServeCallContext, McpServeHandle, McpServeOptions, McpServePrompt, McpServeResource, McpServeSource, McpServeToolContext, McpServeTransport, McpServer, McpStdioServeTransport, McpToolCallResult, McpToolDescriptor, McpToolSource, McpTransport, McpValidateCallParams, SearchProvider, WebSearchInput, WebSearchOptions, WebSearchResult, WebSearchResultItem };
@@ -1,4 +1,4 @@
1
- import { JsonRpcId, McpContentBlock, McpToolCallResult } from "./mcp.type.mjs";
1
+ import { JsonRpcId, McpContentBlock, McpToolCallResult, McpToolDescriptor } from "./mcp.type.mjs";
2
2
  import { JsonSchemaTarget, ToolContract, ToolRequestContext } from "@warlock.js/ai";
3
3
  //#region ../../packages/ai-tools/src/contracts/mcp-serve.type.d.ts
4
4
  /**
@@ -47,7 +47,7 @@ export type McpHttpRequestInfo = ToolRequestContext & {
47
47
  /**
48
48
  * Authentication for an HTTP-served MCP endpoint. At least one of
49
49
  * `bearer` / `authorize` / `authenticate` is required; all configured checks
50
- * must pass, in that order. A request that fails gets HTTP 401 before its body is read.
50
+ * must pass, in that order. A request that fails is refused before its body is read.
51
51
  */
52
52
  export type McpHttpAuth = {
53
53
  /**
@@ -71,6 +71,57 @@ export type McpHttpAuth = {
71
71
  */
72
72
  authenticate?: (request: McpHttpRequestInfo) => unknown | Promise<unknown>;
73
73
  };
74
+ /** Safe refusal metadata: no credentials, principal, body or thrown error. */
75
+ export type McpHttpAuthRefusalContext = Readonly<{
76
+ check: "bearer" | "authorize" | "authenticate";
77
+ method: string;
78
+ /** Pathname only; excludes the query string. */
79
+ path: string;
80
+ target: "mcp" | "route";
81
+ }>;
82
+ /** JSON values accepted in an authentication refusal body. */
83
+ export type McpHttpAuthRefusalBody = null | boolean | number | string | readonly McpHttpAuthRefusalBody[] | {
84
+ readonly [key: string]: McpHttpAuthRefusalBody;
85
+ };
86
+ /** Headers an auth refusal may set; framing, cookies and CORS stay transport-owned. */
87
+ export type McpHttpAuthRefusalHeader = "www-authenticate" | "cache-control" | "retry-after" | "content-language" | "x-request-id";
88
+ export type McpHttpAuthRefusalResponse = {
89
+ /** Integer from 400 through 599. Defaults to 401. */
90
+ status?: number;
91
+ /** Merged over the default challenge. Names are case-insensitive at runtime. */
92
+ headers?: Partial<Record<McpHttpAuthRefusalHeader, string>>;
93
+ body: McpHttpAuthRefusalBody;
94
+ };
95
+ /** Customize a denial only. Throws, invalid results or void retain the default 401. */
96
+ export type McpHttpAuthRefusal = (context: McpHttpAuthRefusalContext) => void | McpHttpAuthRefusalResponse | Promise<void | McpHttpAuthRefusalResponse>;
97
+ /** Authenticated context for an extra HTTP route; there is no JSON-RPC id. */
98
+ export type McpHttpRouteContext = McpServeCallContext & {
99
+ request: McpHttpRequestInfo;
100
+ /** Parsed request URL; use searchParams to read query parameters. */
101
+ url: URL;
102
+ /** UTF-8 request body, subject to the transport's maxBodyBytes limit. */
103
+ body: string;
104
+ signal: AbortSignal;
105
+ };
106
+ /** JSON response from an extra HTTP route. Omit body for an empty response. */
107
+ export type McpHttpRouteResponse = {
108
+ /** @default 200 */
109
+ status?: number;
110
+ headers?: Record<string, string>;
111
+ body?: unknown;
112
+ };
113
+ /** An exact method/path route beneath the MCP endpoint, sharing its auth. */
114
+ export type McpHttpRoute = {
115
+ method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS";
116
+ /**
117
+ * Suffix such as /tool-policy, appended to the MCP path without its trailing
118
+ * slash. Nonempty segments use letters, digits, _, -, . or ~; . and .. are
119
+ * forbidden. No query, fragment, escapes, wildcard or trailing slash.
120
+ * The MCP endpoint itself is reserved for every method. Duplicates fail start().
121
+ */
122
+ path: string;
123
+ handler(context: McpHttpRouteContext): McpHttpRouteResponse | Promise<McpHttpRouteResponse>;
124
+ };
74
125
  /**
75
126
  * Serve over the MCP Streamable HTTP transport.
76
127
  *
@@ -95,13 +146,17 @@ export type McpHttpServeTransport = {
95
146
  */
96
147
  port?: number;
97
148
  /**
98
- * The single MCP endpoint path. Other paths answer 404.
149
+ * The MCP endpoint path. Other paths answer 404 unless registered in routes.
99
150
  *
100
151
  * @default "/mcp"
101
152
  */
102
153
  path?: string;
103
154
  /** Bearer, authorize and/or authenticate checks. Required off loopback. */
104
155
  auth?: McpHttpAuth;
156
+ /** Shared by MCP and routes after failed auth; never runs for Host/Origin refusals. */
157
+ onAuthRefusal?: McpHttpAuthRefusal;
158
+ /** Extra HTTP routes with the same Host/Origin and authentication checks. */
159
+ routes?: readonly McpHttpRoute[];
105
160
  /**
106
161
  * Extra browser origins allowed to call the endpoint, as full origins
107
162
  * (`"https://app.example.com"`). Loopback origins (`http://localhost:*`,
@@ -171,6 +226,13 @@ export type McpCallRefusal = McpToolCallResult & {
171
226
  };
172
227
  /** Validate policy before execute; a refusal bypasses result serialization. */
173
228
  export type McpBeforeCall = (context: McpServeToolContext, tool: ToolContract, input: unknown) => void | McpCallRefusal | Promise<void | McpCallRefusal>;
229
+ /** Filter fresh wire descriptors for discovery only; hidden tools stay callable. */
230
+ export type McpListFilter = (context: McpServeToolContext, tools: readonly McpToolDescriptor[]) => readonly McpToolDescriptor[] | Promise<readonly McpToolDescriptor[]>;
231
+ /**
232
+ * Inspect the complete tools/call params before lookup, schema validation or
233
+ * beforeCall. Treat params as read-only; throw McpError for an app-defined error.
234
+ */
235
+ export type McpValidateCallParams = (context: McpServeToolContext, params: Readonly<Record<string, unknown>>) => void | Promise<void>;
174
236
  /**
175
237
  * A static MCP resource served by `resources/list` + `resources/read`.
176
238
  */
@@ -265,9 +327,17 @@ export interface McpServeOptions {
265
327
  /**
266
328
  * Runs after schema validation and before invocation. Input is the validated
267
329
  * value and should be treated as read-only. Return an isError:true native
268
- * result to refuse; throw to answer with a JSON-RPC invalid-params error.
330
+ * result to refuse. McpError preserves its code/message/data; other throws
331
+ * answer with a JSON-RPC invalid-params error.
269
332
  */
270
333
  beforeCall?: McpBeforeCall;
334
+ /** Per-request discovery filter; never changes tools/call lookup or policy. */
335
+ listFilter?: McpListFilter;
336
+ /**
337
+ * Optional envelope policy. Receives all params, including unknown fields,
338
+ * task and _meta. By default extra fields are ignored (no task capability).
339
+ */
340
+ validateCallParams?: McpValidateCallParams;
271
341
  /**
272
342
  * Prefix each tool of a grouped source (`{ groups: { … } }`) with its
273
343
  * group name. `true` exposes `<group>_<tool>`; a function builds the
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-serve.type.d.mts","names":[],"sources":["../../../../../../../../packages/ai-tools/src/contracts/mcp-serve.type.ts"],"mappings":";;;;;;;;;;;;;YAcY;EAAkB,SAAS;IAAmB;;;;;;;;;YAU9C;;EAEV,QAAQ,eAAe;;;;;;;;YASb,iBAAiB,gBAAgB;;;;;;YAOjC,qBAAqB;;EAE/B;;EAEA;;;;;;;YAQU;;;;;;;;EAQV;;;;;;EAMA,aAAa,SAAS,iCAAiC;;;;;;EAMvD,gBAAgB,SAAS,iCAAiC;;;;;;;;YAShD;;EAEV;;;;;;;EAOA;;;;;;;EAOA;;;;;;EAMA;;EAEA,OAAO;;;;;;;;;EASP;;;;;;;EAOA;;;;;;EAMA;;;;;;;EAOA;;;;;;;;YASU,oBAAoB,yBAAyB;;YAG7C;EACV;;EAEA;;EAEA,qBAAqB,SAAS,kCAAkC;;;;;;YAOtD;;EAEV,UAAU;;EAEV,YAAY;;EAEZ;;EAEA,SAAS;;;YAIC,sBAAsB;EAAwB,WAAW;;;YAGzD,iBAAiB;EAAsB;;;YAGvC,iBACV,SAAS,qBACT,MAAM,cACN,0BACU,iBAAiB,eAAe;;;;YAKhC;;EAEV;;EAEA;;EAEA;;EAEA;;EAEA;;;;;EAKA,KAAK,SAAS,+BAA+B,aAAa,iBAAiB;;;YAIjE;;EAEV;;EAEA;;EAEA;;;YAIU;;EAEV;;EAEA,SAAS;;;;;YAMC;;EAEV;;EAEA;;EAEA;;EAEA,YAAY;;;;;;EAMZ,IACE,MAAM,wBACN,SAAS,+BACC,qBAAqB,iBAAiB;;;;;;iBAOnC;;EAEf;;;;;;EAMA;;;;;;EAMA,YAAY;;;;;;;;EAQZ,eAAe;;;;;;;;;EASf;;;;;;EAMA,aAAa;;;;;;;;EAQb,8BAA8B,eAAe;;EAE7C,YAAY;;EAEZ,UAAU;;;;;;iBAOK;;EAEf;;;;;;EAMA,SAAS;;;iBAIM,2BAA2B;;EAE1C;;;;;iBAMe,UAAU,gBAAgB,iBAAiB;;;;;;EAM1D,SAAS,QAAQ;;EAEjB,QAAQ"}
1
+ {"version":3,"file":"mcp-serve.type.d.mts","names":[],"sources":["../../../../../../../../packages/ai-tools/src/contracts/mcp-serve.type.ts"],"mappings":";;;;;;;;;;;;;YAcY;EAAkB,SAAS;IAAmB;;;;;;;;;YAU9C;;EAEV,QAAQ,eAAe;;;;;;;;YASb,iBAAiB,gBAAgB;;;;;;YAOjC,qBAAqB;;EAE/B;;EAEA;;;;;;;YAQU;;;;;;;;EAQV;;;;;;EAMA,aAAa,SAAS,iCAAiC;;;;;;EAMvD,gBAAgB,SAAS,iCAAiC;;;YAIhD,4BAA4B;EACtC;EACA;;EAEA;EACA;;;YAIU,qEAKC;YACG,cAAc;;;YAGlB;YAOA;;EAEV;;EAEA,UAAU,QAAQ,OAAO;EACzB,MAAM;;;YAII,sBACV,SAAS,qCACC,6BAA6B,eAAe;;YAG5C,sBAAsB;EAChC,SAAS;;EAET,KAAK;;EAEL;EACA,QAAQ;;;YAIE;;EAEV;EACA,UAAU;EACV;;;YAIU;EACV;;;;;;;EAOA;EACA,QAAQ,SAAS,sBAAsB,uBAAuB,QAAQ;;;;;;;;YAS5D;;EAEV;;;;;;;EAOA;;;;;;;EAOA;;;;;;EAMA;;EAEA,OAAO;;EAEP,gBAAgB;;EAEhB,kBAAkB;;;;;;;;;EASlB;;;;;;;EAOA;;;;;;EAMA;;;;;;;EAOA;;;;;;;;YASU,oBAAoB,yBAAyB;;YAG7C;EACV;;EAEA;;EAEA,qBAAqB,SAAS,kCAAkC;;;;;;YAOtD;;EAEV,UAAU;;EAEV,YAAY;;EAEZ;;EAEA,SAAS;;;YAIC,sBAAsB;EAAwB,WAAW;;;YAGzD,iBAAiB;EAAsB;;;YAGvC,iBACV,SAAS,qBACT,MAAM,cACN,0BACU,iBAAiB,eAAe;;YAGhC,iBACV,SAAS,qBACT,gBAAgB,iCACJ,sBAAsB,iBAAiB;;;;;YAMzC,yBACV,SAAS,qBACT,QAAQ,SAAS,oCACP;;;;YAKA;;EAEV;;EAEA;;EAEA;;EAEA;;EAEA;;;;;EAKA,KAAK,SAAS,+BAA+B,aAAa,iBAAiB;;;YAIjE;;EAEV;;EAEA;;EAEA;;;YAIU;;EAEV;;EAEA,SAAS;;;;;YAMC;;EAEV;;EAEA;;EAEA;;EAEA,YAAY;;;;;;EAMZ,IACE,MAAM,wBACN,SAAS,+BACC,qBAAqB,iBAAiB;;;;;;iBAOnC;;EAEf;;;;;;EAMA;;;;;;EAMA,YAAY;;;;;;;;EAQZ,eAAe;;;;;;;;;EASf;;;;;;;EAOA,aAAa;;EAEb,aAAa;;;;;EAKb,qBAAqB;;;;;;;;EAQrB,8BAA8B,eAAe;;EAE7C,YAAY;;EAEZ,UAAU;;;;;;iBAOK;;EAEf;;;;;;EAMA,SAAS;;;iBAIM,2BAA2B;;EAE1C;;;;;iBAMe,UAAU,gBAAgB,iBAAiB;;;;;;EAM1D,SAAS,QAAQ;;EAEjB,QAAQ"}
package/esm/index.d.mts CHANGED
@@ -2,12 +2,13 @@ import { FetchUrlExtract, FetchUrlInput, FetchUrlOptions, FetchUrlResult, Search
2
2
  import { HttpMethod, HttpRequestInput, HttpRequestOptions, HttpRequestResult } from "./contracts/http.type.mjs";
3
3
  import { CalculatorInput, CalculatorOptions, CalculatorResult, DateTimeInput, DateTimeOp, DateTimeOptions, DateTimeResult } from "./contracts/utility.type.mjs";
4
4
  import { JsonRpcError, JsonRpcId, JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse, JsonRpcVersion, McpClient, McpClientOptions, McpContentBlock, McpToolCallResult, McpToolDescriptor, McpTransport } from "./contracts/mcp.type.mjs";
5
- import { McpBeforeCall, McpCallRefusal, McpGroupedToolSource, McpHttpAuth, McpHttpRequestInfo, McpHttpServeHandle, McpHttpServeTransport, McpPromptArgument, McpPromptMessage, McpServeCallContext, McpServeHandle, McpServeOptions, McpServePrompt, McpServeResource, McpServeSource, McpServeToolContext, McpServeTransport, McpServer, McpStdioServeTransport, McpToolSource } from "./contracts/mcp-serve.type.mjs";
5
+ import { McpBeforeCall, McpCallRefusal, McpGroupedToolSource, McpHttpAuth, McpHttpAuthRefusal, McpHttpAuthRefusalBody, McpHttpAuthRefusalContext, McpHttpAuthRefusalHeader, McpHttpAuthRefusalResponse, McpHttpRequestInfo, McpHttpRoute, McpHttpRouteContext, McpHttpRouteResponse, McpHttpServeHandle, McpHttpServeTransport, McpListFilter, McpPromptArgument, McpPromptMessage, McpServeCallContext, McpServeHandle, McpServeOptions, McpServePrompt, McpServeResource, McpServeSource, McpServeToolContext, McpServeTransport, McpServer, McpStdioServeTransport, McpToolSource, McpValidateCallParams } from "./contracts/mcp-serve.type.mjs";
6
6
  import "./contracts/index.mjs";
7
7
  import { McpServeRequestHandler, createServeHandler, serve } from "./mcp/serve.mjs";
8
8
  import { SUPPORTED_PROTOCOL_VERSIONS } from "./mcp/protocol.mjs";
9
+ import { McpError } from "./mcp/error.mjs";
9
10
  import { McpNativeResult, mcpResult } from "./mcp/result.mjs";
10
- import { jsonSchemaToStandard } from "./mcp/json-schema-to-standard.mjs";
11
+ import { JsonSchemaStandard, jsonSchemaToStandard } from "./mcp/json-schema-to-standard.mjs";
11
12
  import { McpTransportClient } from "./mcp/transport.type.mjs";
12
13
  import { JsonRpcClientHandle, createJsonRpcClient, createTransport } from "./mcp/transport.mjs";
13
14
  import { McpFactory, mcp } from "./mcp/index.mjs";
@@ -20,6 +21,6 @@ import { calculatorTool } from "./utility/calculator.mjs";
20
21
  import { dateTimeTool } from "./utility/date-time.mjs";
21
22
  import "./utility/index.mjs";
22
23
  import { CalculatorError, CalculatorErrorOptions, CalculatorFailure, DateTimeError, DateTimeErrorOptions, DateTimeFailure, HttpPolicyError, HttpPolicyErrorOptions, HttpPolicyFailure, McpServeError, McpServeErrorOptions, McpServeFailure, McpTransportError, McpTransportErrorOptions, McpTransportFailure, WebToolError, WebToolErrorOptions, WebToolFailure } from "./errors.mjs";
23
- export { type AiToolsNamespace, CalculatorError, type CalculatorErrorOptions, type CalculatorFailure, type CalculatorInput, type CalculatorOptions, type CalculatorResult, DateTimeError, type DateTimeErrorOptions, type DateTimeFailure, type DateTimeInput, type DateTimeOp, type DateTimeOptions, type DateTimeResult, type FetchUrlExtract, type FetchUrlInput, type FetchUrlOptions, type FetchUrlResult, type HttpMethod, HttpPolicyError, type HttpPolicyErrorOptions, type HttpPolicyFailure, type HttpRequestInput, type HttpRequestOptions, type HttpRequestResult, type JsonRpcClientHandle, type JsonRpcError, type JsonRpcId, type JsonRpcMessage, type JsonRpcNotification, type JsonRpcRequest, type JsonRpcResponse, type JsonRpcVersion, type McpBeforeCall, type McpCallRefusal, type McpClient, type McpClientOptions, type McpContentBlock, type McpFactory, type McpGroupedToolSource, type McpHttpAuth, type McpHttpRequestInfo, type McpHttpServeHandle, type McpHttpServeTransport, type McpNativeResult, type McpPromptArgument, type McpPromptMessage, type McpServeCallContext, McpServeError, type McpServeErrorOptions, type McpServeFailure, type McpServeHandle, type McpServeOptions, type McpServePrompt, type McpServeRequestHandler, type McpServeResource, type McpServeSource, type McpServeToolContext, type McpServeTransport, type McpServer, type McpStdioServeTransport, type McpToolCallResult, type McpToolDescriptor, type McpToolSource, type McpTransport, type McpTransportClient, McpTransportError, type McpTransportErrorOptions, type McpTransportFailure, SUPPORTED_PROTOCOL_VERSIONS, type SearchProvider, type WebSearchInput, type WebSearchOptions, type WebSearchResult, type WebSearchResultItem, WebToolError, type WebToolErrorOptions, type WebToolFailure, calculatorTool, createJsonRpcClient, createServeHandler, createTransport, dateTimeTool, fetchUrlTool, httpRequestTool, jsonSchemaToStandard, mcp, mcpResult, serve, webSearchTool };
24
+ export { type AiToolsNamespace, CalculatorError, type CalculatorErrorOptions, type CalculatorFailure, type CalculatorInput, type CalculatorOptions, type CalculatorResult, DateTimeError, type DateTimeErrorOptions, type DateTimeFailure, type DateTimeInput, type DateTimeOp, type DateTimeOptions, type DateTimeResult, type FetchUrlExtract, type FetchUrlInput, type FetchUrlOptions, type FetchUrlResult, type HttpMethod, HttpPolicyError, type HttpPolicyErrorOptions, type HttpPolicyFailure, type HttpRequestInput, type HttpRequestOptions, type HttpRequestResult, type JsonRpcClientHandle, type JsonRpcError, type JsonRpcId, type JsonRpcMessage, type JsonRpcNotification, type JsonRpcRequest, type JsonRpcResponse, type JsonRpcVersion, type JsonSchemaStandard, type McpBeforeCall, type McpCallRefusal, type McpClient, type McpClientOptions, type McpContentBlock, McpError, type McpFactory, type McpGroupedToolSource, type McpHttpAuth, type McpHttpAuthRefusal, type McpHttpAuthRefusalBody, type McpHttpAuthRefusalContext, type McpHttpAuthRefusalHeader, type McpHttpAuthRefusalResponse, type McpHttpRequestInfo, type McpHttpRoute, type McpHttpRouteContext, type McpHttpRouteResponse, type McpHttpServeHandle, type McpHttpServeTransport, type McpListFilter, type McpNativeResult, type McpPromptArgument, type McpPromptMessage, type McpServeCallContext, McpServeError, type McpServeErrorOptions, type McpServeFailure, type McpServeHandle, type McpServeOptions, type McpServePrompt, type McpServeRequestHandler, type McpServeResource, type McpServeSource, type McpServeToolContext, type McpServeTransport, type McpServer, type McpStdioServeTransport, type McpToolCallResult, type McpToolDescriptor, type McpToolSource, type McpTransport, type McpTransportClient, McpTransportError, type McpTransportErrorOptions, type McpTransportFailure, type McpValidateCallParams, SUPPORTED_PROTOCOL_VERSIONS, type SearchProvider, type WebSearchInput, type WebSearchOptions, type WebSearchResult, type WebSearchResultItem, WebToolError, type WebToolErrorOptions, type WebToolFailure, calculatorTool, createJsonRpcClient, createServeHandler, createTransport, dateTimeTool, fetchUrlTool, httpRequestTool, jsonSchemaToStandard, mcp, mcpResult, serve, webSearchTool };
24
25
  import "./mcp/index.mjs";
25
26
  import "./register.mjs";
package/esm/index.mjs CHANGED
@@ -2,6 +2,7 @@ import { CalculatorError, DateTimeError, HttpPolicyError, McpServeError, McpTran
2
2
  import { httpRequestTool } from "./http/http-request.mjs";
3
3
  import { jsonSchemaToStandard } from "./mcp/json-schema-to-standard.mjs";
4
4
  import { createJsonRpcClient, createTransport } from "./mcp/transport.mjs";
5
+ import { McpError } from "./mcp/error.mjs";
5
6
  import { SUPPORTED_PROTOCOL_VERSIONS } from "./mcp/protocol.mjs";
6
7
  import { mcpResult } from "./mcp/result.mjs";
7
8
  import { createServeHandler, serve } from "./mcp/serve.mjs";
@@ -14,4 +15,4 @@ import "./register.mjs";
14
15
  import "./web/index.mjs";
15
16
  import "./utility/index.mjs";
16
17
 
17
- export { CalculatorError, DateTimeError, HttpPolicyError, McpServeError, McpTransportError, SUPPORTED_PROTOCOL_VERSIONS, WebToolError, calculatorTool, createJsonRpcClient, createServeHandler, createTransport, dateTimeTool, fetchUrlTool, httpRequestTool, jsonSchemaToStandard, mcp, mcpResult, serve, webSearchTool };
18
+ export { CalculatorError, DateTimeError, HttpPolicyError, McpError, McpServeError, McpTransportError, SUPPORTED_PROTOCOL_VERSIONS, WebToolError, calculatorTool, createJsonRpcClient, createServeHandler, createTransport, dateTimeTool, fetchUrlTool, httpRequestTool, jsonSchemaToStandard, mcp, mcpResult, serve, webSearchTool };
@@ -0,0 +1,9 @@
1
+ //#region ../../packages/ai-tools/src/mcp/error.d.ts
2
+ /** An application-defined JSON-RPC error thrown by MCP serving policy hooks. */
3
+ export declare class McpError extends Error {
4
+ readonly code: number;
5
+ readonly data: unknown;
6
+ constructor(code: number, message: string, data?: unknown);
7
+ }
8
+ //#endregion
9
+ //# sourceMappingURL=error.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.d.mts","names":[],"sources":["../../../../../../../../packages/ai-tools/src/mcp/error.ts"],"mappings":";;qBACa,iBAAiB;WACZ;WAEA;EAEhB,YAAmB,cAAc,iBAAiB"}
@@ -0,0 +1,24 @@
1
+ //#region ../../packages/ai-tools/src/mcp/error.ts
2
+ /** An application-defined JSON-RPC error thrown by MCP serving policy hooks. */
3
+ var McpError = class extends Error {
4
+ constructor(code, message, data) {
5
+ super(message);
6
+ this.name = "McpError";
7
+ this.code = code;
8
+ this.data = data;
9
+ }
10
+ };
11
+ /**
12
+ * Recognize our error and the SDK's McpError without a runtime SDK dependency.
13
+ * SDK source (checked 2026-10-19):
14
+ * https://github.com/modelcontextprotocol/typescript-sdk/blob/v1.x/src/types.ts
15
+ * Only explicitly named errors with an integer code opt in; ordinary throws
16
+ * retain the existing mapping. Preserve the error's message verbatim.
17
+ */
18
+ function isMcpError(cause) {
19
+ return cause instanceof Error && cause.name === "McpError" && "code" in cause && typeof cause.code === "number" && Number.isInteger(cause.code);
20
+ }
21
+
22
+ //#endregion
23
+ export { McpError, isMcpError };
24
+ //# sourceMappingURL=error.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.mjs","names":[],"sources":["../../../../../../../../packages/ai-tools/src/mcp/error.ts"],"sourcesContent":["/** An application-defined JSON-RPC error thrown by MCP serving policy hooks. */\nexport class McpError extends Error {\n public readonly code: number;\n\n public readonly data: unknown;\n\n public constructor(code: number, message: string, data?: unknown) {\n super(message);\n this.name = \"McpError\";\n this.code = code;\n this.data = data;\n }\n}\n\n/**\n * Recognize our error and the SDK's McpError without a runtime SDK dependency.\n * SDK source (checked 2026-10-19):\n * https://github.com/modelcontextprotocol/typescript-sdk/blob/v1.x/src/types.ts\n * Only explicitly named errors with an integer code opt in; ordinary throws\n * retain the existing mapping. Preserve the error's message verbatim.\n */\nexport function isMcpError(cause: unknown): cause is Error & { code: number; data?: unknown } {\n return (\n cause instanceof Error &&\n cause.name === \"McpError\" &&\n \"code\" in cause &&\n typeof cause.code === \"number\" &&\n Number.isInteger(cause.code)\n );\n}\n"],"mappings":";;AACA,IAAa,WAAb,cAA8B,MAAM;CAKlC,AAAO,YAAY,MAAc,SAAiB,MAAgB;EAChE,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO;EACZ,KAAK,OAAO;CACd;AACF;;;;;;;;AASA,SAAgB,WAAW,OAAmE;CAC5F,OACE,iBAAiB,SACjB,MAAM,SAAS,cACf,UAAU,SACV,OAAO,MAAM,SAAS,YACtB,OAAO,UAAU,MAAM,IAAI;AAE/B"}
@@ -3,8 +3,9 @@ import { McpHttpServeHandle, McpHttpServeTransport, McpServeOptions, McpServeSou
3
3
  import "../contracts/index.mjs";
4
4
  import { McpServeRequestHandler, createServeHandler, serve } from "./serve.mjs";
5
5
  import { SUPPORTED_PROTOCOL_VERSIONS } from "./protocol.mjs";
6
+ import { McpError } from "./error.mjs";
6
7
  import { McpNativeResult, mcpResult } from "./result.mjs";
7
- import { jsonSchemaToStandard } from "./json-schema-to-standard.mjs";
8
+ import { JsonSchemaStandard, jsonSchemaToStandard } from "./json-schema-to-standard.mjs";
8
9
  import { McpTransportClient } from "./transport.type.mjs";
9
10
  import { JsonRpcClientHandle, createJsonRpcClient, createTransport } from "./transport.mjs";
10
11
  //#region ../../packages/ai-tools/src/mcp/index.d.ts
@@ -47,5 +48,5 @@ export interface McpFactory {
47
48
  */
48
49
  export declare const mcp: McpFactory;
49
50
  //#endregion
50
- export { type McpNativeResult, type McpServeRequestHandler, type McpTransportClient, SUPPORTED_PROTOCOL_VERSIONS, createServeHandler, mcpResult, serve };
51
+ export { McpError, type McpNativeResult, type McpServeRequestHandler, type McpTransportClient, SUPPORTED_PROTOCOL_VERSIONS, createServeHandler, mcpResult, serve };
51
52
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../../../../packages/ai-tools/src/mcp/index.ts"],"mappings":";;;;;;;;;;;;;;;;;iBA8BiB;;;;;;;;GAQd,QAAQ,cAAc,UAAU,mBAAmB;;;;;;;;;EASpD,MACE,QAAQ,gBACR,SAAS;IAAoB,WAAW;MACvC,UAAU;EACb,MAAM,QAAQ,gBAAgB,SAAS,kBAAkB;;;;;;;;;;qBAW9C,KAAK"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../../../../../packages/ai-tools/src/mcp/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;iBA+BiB;;;;;;;;GAQd,QAAQ,cAAc,UAAU,mBAAmB;;;;;;;;;EASpD,MACE,QAAQ,gBACR,SAAS;IAAoB,WAAW;MACvC,UAAU;EACb,MAAM,QAAQ,gBAAgB,SAAS,kBAAkB;;;;;;;;;;qBAW9C,KAAK"}
package/esm/mcp/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { jsonSchemaToStandard } from "./json-schema-to-standard.mjs";
2
2
  import { createJsonRpcClient, createTransport } from "./transport.mjs";
3
3
  import { mcp as mcp$1 } from "./client.mjs";
4
+ import { McpError } from "./error.mjs";
4
5
  import { SUPPORTED_PROTOCOL_VERSIONS } from "./protocol.mjs";
5
6
  import { mcpResult } from "./result.mjs";
6
7
  import { createServeHandler, serve } from "./serve.mjs";
@@ -17,5 +18,5 @@ import { createServeHandler, serve } from "./serve.mjs";
17
18
  const mcp = Object.assign((server, options) => mcp$1(server, options), { serve });
18
19
 
19
20
  //#endregion
20
- export { SUPPORTED_PROTOCOL_VERSIONS, createServeHandler, mcp, mcpResult, serve };
21
+ export { McpError, SUPPORTED_PROTOCOL_VERSIONS, createServeHandler, mcp, mcpResult, serve };
21
22
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["mcpClient"],"sources":["../../../../../../../../packages/ai-tools/src/mcp/index.ts"],"sourcesContent":["import type {\n McpClient,\n McpClientOptions,\n McpHttpServeHandle,\n McpHttpServeTransport,\n McpServeOptions,\n McpServeSource,\n McpServer,\n McpTransport,\n} from \"../contracts\";\nimport { mcp as mcpClient } from \"./client\";\nimport { serve } from \"./serve\";\n\nexport { serve, createServeHandler } from \"./serve\";\nexport type { McpServeRequestHandler } from \"./serve\";\nexport { SUPPORTED_PROTOCOL_VERSIONS } from \"./protocol\";\nexport { mcpResult } from \"./result\";\nexport type { McpNativeResult } from \"./result\";\nexport { jsonSchemaToStandard } from \"./json-schema-to-standard\";\nexport { createJsonRpcClient, createTransport } from \"./transport\";\nexport type { JsonRpcClientHandle } from \"./transport\";\nexport type { McpTransportClient } from \"./transport.type\";\n\n/**\n * The callable `ai.mcp` surface — a factory that connects to an external\n * MCP server (Direction A) and also carries `.serve` to expose a local\n * primitive AS an MCP server (Direction B). Modeled as a function with an\n * attached `serve` property, mirroring how `ai.mcp(server).tools()` and\n * `ai.mcp.serve(source, options).start()` read in the design.\n */\nexport interface McpFactory {\n /**\n * Connect to an external MCP server and adapt its tools as agent tools.\n *\n * @param server - The transport config (`{ type: \"stdio\" }` / `{ type: \"http\" }`).\n * @param options - Prefix / filter / per-call timeout, and a `signal`\n * that closes the client (and fails its calls) when it aborts.\n */\n (server: McpTransport, options?: McpClientOptions): McpClient;\n /**\n * Expose a built agent / supervisor / orchestrator (or a literal\n * `ToolContract[]`, or named `{ groups }`) AS an MCP server. Over\n * `{ type: \"http\" }`, `start()` resolves `{ url, close }`.\n *\n * @param source - The tools to expose.\n * @param options - Server name, version, transport, schema dialect, resources, prompts.\n */\n serve(\n source: McpServeSource,\n options: McpServeOptions & { transport: McpHttpServeTransport },\n ): McpServer<McpHttpServeHandle>;\n serve(source: McpServeSource, options: McpServeOptions): McpServer;\n}\n\n/**\n * The `ai.mcp` factory value: the client factory with `.serve` attached.\n * `Object.assign` keeps `mcp` callable (Direction A) while widening it with\n * the `serve` member (Direction B) — one object, both directions. The\n * `declare module \"@warlock.js/ai\"` augmentation and the runtime\n * registration (`ai.mcp = mcp`) live in `../register`, so this barrel is a\n * pure value/type module the registrar consumes.\n */\nexport const mcp: McpFactory = Object.assign(\n (server: McpTransport, options?: McpClientOptions): McpClient => mcpClient(server, options),\n { serve },\n);\n"],"mappings":";;;;;;;;;;;;;;;;AA8DA,MAAa,MAAkB,OAAO,QACnC,QAAsB,YAA0CA,MAAU,QAAQ,OAAO,GAC1F,EAAE,MAAM,CACV"}
1
+ {"version":3,"file":"index.mjs","names":["mcpClient"],"sources":["../../../../../../../../packages/ai-tools/src/mcp/index.ts"],"sourcesContent":["import type {\n McpClient,\n McpClientOptions,\n McpHttpServeHandle,\n McpHttpServeTransport,\n McpServeOptions,\n McpServeSource,\n McpServer,\n McpTransport,\n} from \"../contracts\";\nimport { mcp as mcpClient } from \"./client\";\nimport { serve } from \"./serve\";\n\nexport { serve, createServeHandler } from \"./serve\";\nexport type { McpServeRequestHandler } from \"./serve\";\nexport { SUPPORTED_PROTOCOL_VERSIONS } from \"./protocol\";\nexport { McpError } from \"./error\";\nexport { mcpResult } from \"./result\";\nexport type { McpNativeResult } from \"./result\";\nexport { jsonSchemaToStandard, type JsonSchemaStandard } from \"./json-schema-to-standard\";\nexport { createJsonRpcClient, createTransport } from \"./transport\";\nexport type { JsonRpcClientHandle } from \"./transport\";\nexport type { McpTransportClient } from \"./transport.type\";\n\n/**\n * The callable `ai.mcp` surface — a factory that connects to an external\n * MCP server (Direction A) and also carries `.serve` to expose a local\n * primitive AS an MCP server (Direction B). Modeled as a function with an\n * attached `serve` property, mirroring how `ai.mcp(server).tools()` and\n * `ai.mcp.serve(source, options).start()` read in the design.\n */\nexport interface McpFactory {\n /**\n * Connect to an external MCP server and adapt its tools as agent tools.\n *\n * @param server - The transport config (`{ type: \"stdio\" }` / `{ type: \"http\" }`).\n * @param options - Prefix / filter / per-call timeout, and a `signal`\n * that closes the client (and fails its calls) when it aborts.\n */\n (server: McpTransport, options?: McpClientOptions): McpClient;\n /**\n * Expose a built agent / supervisor / orchestrator (or a literal\n * `ToolContract[]`, or named `{ groups }`) AS an MCP server. Over\n * `{ type: \"http\" }`, `start()` resolves `{ url, close }`.\n *\n * @param source - The tools to expose.\n * @param options - Server name, version, transport, schema dialect, resources, prompts.\n */\n serve(\n source: McpServeSource,\n options: McpServeOptions & { transport: McpHttpServeTransport },\n ): McpServer<McpHttpServeHandle>;\n serve(source: McpServeSource, options: McpServeOptions): McpServer;\n}\n\n/**\n * The `ai.mcp` factory value: the client factory with `.serve` attached.\n * `Object.assign` keeps `mcp` callable (Direction A) while widening it with\n * the `serve` member (Direction B) — one object, both directions. The\n * `declare module \"@warlock.js/ai\"` augmentation and the runtime\n * registration (`ai.mcp = mcp`) live in `../register`, so this barrel is a\n * pure value/type module the registrar consumes.\n */\nexport const mcp: McpFactory = Object.assign(\n (server: McpTransport, options?: McpClientOptions): McpClient => mcpClient(server, options),\n { serve },\n);\n"],"mappings":";;;;;;;;;;;;;;;;;AA+DA,MAAa,MAAkB,OAAO,QACnC,QAAsB,YAA0CA,MAAU,QAAQ,OAAO,GAC1F,EAAE,MAAM,CACV"}
@@ -1,4 +1,4 @@
1
- import { StandardSchemaV1 } from "@standard-schema/spec";
1
+ import { StandardJSONSchemaV1, StandardSchemaV1 } from "@standard-schema/spec";
2
2
  //#region ../../packages/ai-tools/src/mcp/json-schema-to-standard.d.ts
3
3
  /**
4
4
  * Wrap a raw JSON Schema as a {@link StandardSchemaV1} whose
@@ -18,7 +18,8 @@ import { StandardSchemaV1 } from "@standard-schema/spec";
18
18
  *
19
19
  * @param schema - The JSON Schema (an MCP tool's `inputSchema`), or
20
20
  * `undefined` for a no-argument tool.
21
- * @returns A `StandardSchemaV1<TInput>` ready for `tool({ input })`.
21
+ * @returns A `StandardSchemaV1<TInput>` ready for `tool({ input })` that also implements
22
+ * Standard JSON Schema, so provider adapters advertise the wrapped schema.
22
23
  *
23
24
  * @example
24
25
  * const input = jsonSchemaToStandard<{ q: string }>({
@@ -27,6 +28,8 @@ import { StandardSchemaV1 } from "@standard-schema/spec";
27
28
  * required: ["q"],
28
29
  * });
29
30
  */
30
- export declare function jsonSchemaToStandard<TInput = unknown>(schema: Record<string, unknown> | undefined): StandardSchemaV1<TInput>;
31
+ /** A validating wrapper that also exposes the JSON Schema it wraps. */
32
+ export type JsonSchemaStandard<TInput = unknown> = StandardSchemaV1<TInput> & StandardJSONSchemaV1<TInput>;
33
+ export declare function jsonSchemaToStandard<TInput = unknown>(schema: Record<string, unknown> | undefined): JsonSchemaStandard<TInput>;
31
34
  //#endregion
32
35
  //# sourceMappingURL=json-schema-to-standard.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"json-schema-to-standard.d.mts","names":[],"sources":["../../../../../../../../packages/ai-tools/src/mcp/json-schema-to-standard.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA+JgB,qBAAqB,kBACnC,QAAQ,sCACP,iBAAiB"}
1
+ {"version":3,"file":"json-schema-to-standard.d.mts","names":[],"sources":["../../../../../../../../packages/ai-tools/src/mcp/json-schema-to-standard.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAiKY,mBAAmB,oBAAoB,iBAAiB,UAClE,qBAAqB;wBAcP,qBAAqB,kBACnC,QAAQ,sCACP,mBAAmB"}
@@ -74,42 +74,31 @@ function makeCompiler(schema) {
74
74
  };
75
75
  }
76
76
  /**
77
- * Wrap a raw JSON Schema as a {@link StandardSchemaV1} whose
78
- * `~standard.validate` runs Ajv. The shape mirrors `passthroughSchema()`
79
- * (`{ "~standard": { version: 1, vendor, validate } }`) so it drops into
80
- * `tool({ input })` exactly like a native seal schema.
81
- *
82
- * Validation behavior:
83
- * - **Valid input** → `{ value }` (the input is passed through unchanged;
84
- * Ajv validates, it does not transform).
85
- * - **Invalid input** → `{ issues }` carrying Ajv's `instancePath` +
86
- * message per failure, so `tool()` produces a `SchemaValidationError`.
87
- * - **Missing `ajv` peer** → a single issue carrying the curated install
88
- * string, surfaced the same way (a developer-facing message in logs).
89
- * - **No / empty schema** → an accept-all passthrough (an MCP tool may
90
- * advertise no `inputSchema`).
91
- *
92
- * @param schema - The JSON Schema (an MCP tool's `inputSchema`), or
93
- * `undefined` for a no-argument tool.
94
- * @returns A `StandardSchemaV1<TInput>` ready for `tool({ input })`.
95
- *
96
- * @example
97
- * const input = jsonSchemaToStandard<{ q: string }>({
98
- * type: "object",
99
- * properties: { q: { type: "string" } },
100
- * required: ["q"],
101
- * });
77
+ * Standard JSON Schema converter returning a copy of the wrapped schema, so
78
+ * provider adapters (which may compact or rewrite it) never mutate the source.
79
+ * The remote server owns its schema, so every target receives it unchanged.
102
80
  */
81
+ function exposeSchema(schema) {
82
+ return {
83
+ input: () => structuredClone(schema),
84
+ output: () => structuredClone(schema)
85
+ };
86
+ }
103
87
  function jsonSchemaToStandard(schema) {
104
88
  if (!schema || Object.keys(schema).length === 0) return { "~standard": {
105
89
  version: 1,
106
90
  vendor: VENDOR,
107
- validate: (value) => ({ value })
91
+ validate: (value) => ({ value }),
92
+ jsonSchema: exposeSchema({
93
+ type: "object",
94
+ properties: {}
95
+ })
108
96
  } };
109
97
  const compile = makeCompiler(schema);
110
98
  return { "~standard": {
111
99
  version: 1,
112
100
  vendor: VENDOR,
101
+ jsonSchema: exposeSchema(schema),
113
102
  async validate(value) {
114
103
  await loadAjv();
115
104
  if (!isAjvAvailable) return { issues: [{ message: AJV_INSTALL_INSTRUCTIONS }] };
@@ -1 +1 @@
1
- {"version":3,"file":"json-schema-to-standard.mjs","names":[],"sources":["../../../../../../../../packages/ai-tools/src/mcp/json-schema-to-standard.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * The inverse of `@warlock.js/ai`'s `extractJsonSchema` (which goes\n * Standard Schema → JSON Schema). Here we wrap a raw JSON Schema as a\n * {@link StandardSchemaV1} whose `~standard.validate` runs a lazily-imported\n * Ajv validator — so an MCP server's `inputSchema` (JSON Schema) becomes a\n * `ToolConfig.input` the `tool()` factory can validate against.\n *\n * Ajv is an OPTIONAL peer, lazy-imported on first validate following the\n * langfuse/readability pattern: a missing peer surfaces a curated install\n * string (via the returned issues), never a raw module-resolution stack.\n */\n\n/** The structural vendor template, mirroring `passthroughSchema()`. */\nconst VENDOR = \"warlock-ai\";\n\n// ============================================================\n// Lazily-loaded ajv (OPTIONAL peer)\n// ============================================================\n\n/**\n * Minimal structural view of an Ajv-compiled validator. Ajv is an optional\n * peer that may not be installed, so we model only the surface we touch\n * rather than depending on ajv's own published types. A validator is a\n * callable that returns a boolean and exposes the `errors` it collected.\n */\ninterface AjvValidateFunctionLike {\n (data: unknown): boolean;\n errors?: AjvErrorObject[] | null;\n}\n\n/** Minimal structural view of an `Ajv` instance — only `compile`. */\ninterface AjvInstanceLike {\n compile(schema: Record<string, unknown>): AjvValidateFunctionLike;\n}\n\n/** The `Ajv` constructor, as exposed by both the CJS and ESM builds. */\ntype AjvConstructorLike = new (options?: Record<string, unknown>) => AjvInstanceLike;\n\n/**\n * Minimal structural view of the dynamically imported `ajv` module. Ajv\n * ships its constructor as a `default` export under ESM interop; the older\n * CJS shape exposes the constructor as the module namespace itself, so\n * `default` is optional here and the loader falls back to the namespace.\n */\ninterface AjvModuleLike {\n default?: AjvConstructorLike;\n}\n\nlet AjvSdk: AjvModuleLike | undefined;\nlet ajvInstance: AjvInstanceLike | undefined;\nlet isAjvAvailable: boolean | undefined;\nlet loadingPromise: Promise<void> | undefined;\n\nconst AJV_INSTALL_INSTRUCTIONS = `\nThe MCP client's JSON-Schema validation requires the ajv package.\nInstall it with:\n\n npm install ajv\n\nOr with your preferred package manager:\n\n pnpm add ajv\n yarn add ajv\n`.trim();\n\n/**\n * Settle the lazy import of `ajv` once, concurrency-safe. A bare `catch`\n * flips the availability flag to `false`; the curated install string then\n * surfaces at validate time as a Standard Schema issue, never a raw\n * module-resolution error. The constructed `Ajv` instance is cached and\n * reused for every schema compile.\n */\nasync function loadAjv(): Promise<void> {\n if (isAjvAvailable !== undefined) {\n return;\n }\n\n if (loadingPromise) {\n return loadingPromise;\n }\n\n loadingPromise = (async () => {\n try {\n AjvSdk = (await import(\"ajv\")) as AjvModuleLike;\n // Ajv ships as a default export under both CJS and ESM interop; the\n // older CJS shape exposes the constructor as the namespace itself.\n const AjvCtor: AjvConstructorLike =\n AjvSdk.default ?? (AjvSdk as unknown as AjvConstructorLike);\n ajvInstance = new AjvCtor({ allErrors: true, strict: false });\n isAjvAvailable = true;\n } catch {\n isAjvAvailable = false;\n }\n })();\n\n return loadingPromise;\n}\n\n/**\n * Compile a JSON Schema with the shared Ajv instance, caching the compiled\n * validator on a closure so repeated validations don't recompile. A schema\n * Ajv itself rejects at compile time (an invalid meta-schema) degrades to\n * an accept-all validator so a malformed remote schema can't wedge the\n * tool — the server, not us, owns its schema's correctness.\n */\nfunction makeCompiler(schema: Record<string, unknown>): () => AjvValidateFunctionLike | undefined {\n let compiled: AjvValidateFunctionLike | undefined;\n let attempted = false;\n\n return () => {\n if (attempted) {\n return compiled;\n }\n\n attempted = true;\n\n if (!ajvInstance) {\n return undefined;\n }\n\n try {\n compiled = ajvInstance.compile(schema);\n } catch {\n compiled = undefined;\n }\n\n return compiled;\n };\n}\n\n/**\n * Wrap a raw JSON Schema as a {@link StandardSchemaV1} whose\n * `~standard.validate` runs Ajv. The shape mirrors `passthroughSchema()`\n * (`{ \"~standard\": { version: 1, vendor, validate } }`) so it drops into\n * `tool({ input })` exactly like a native seal schema.\n *\n * Validation behavior:\n * - **Valid input** → `{ value }` (the input is passed through unchanged;\n * Ajv validates, it does not transform).\n * - **Invalid input** → `{ issues }` carrying Ajv's `instancePath` +\n * message per failure, so `tool()` produces a `SchemaValidationError`.\n * - **Missing `ajv` peer** → a single issue carrying the curated install\n * string, surfaced the same way (a developer-facing message in logs).\n * - **No / empty schema** → an accept-all passthrough (an MCP tool may\n * advertise no `inputSchema`).\n *\n * @param schema - The JSON Schema (an MCP tool's `inputSchema`), or\n * `undefined` for a no-argument tool.\n * @returns A `StandardSchemaV1<TInput>` ready for `tool({ input })`.\n *\n * @example\n * const input = jsonSchemaToStandard<{ q: string }>({\n * type: \"object\",\n * properties: { q: { type: \"string\" } },\n * required: [\"q\"],\n * });\n */\nexport function jsonSchemaToStandard<TInput = unknown>(\n schema: Record<string, unknown> | undefined,\n): StandardSchemaV1<TInput> {\n // A tool with no schema (or an empty object schema) validates everything\n // — return an accept-all passthrough and never touch Ajv.\n if (!schema || Object.keys(schema).length === 0) {\n return {\n \"~standard\": {\n version: 1,\n vendor: VENDOR,\n validate: (value: unknown) => ({ value: value as TInput }),\n },\n };\n }\n\n const compile = makeCompiler(schema);\n\n return {\n \"~standard\": {\n version: 1,\n vendor: VENDOR,\n async validate(value: unknown): Promise<StandardSchemaV1.Result<TInput>> {\n await loadAjv();\n\n if (!isAjvAvailable) {\n return {\n issues: [{ message: AJV_INSTALL_INSTRUCTIONS }],\n };\n }\n\n const validator = compile();\n\n // A schema Ajv could not compile degrades to accept-all rather\n // than failing every call — the remote server owns its schema.\n if (!validator) {\n return { value: value as TInput };\n }\n\n const ok = validator(value);\n\n if (ok) {\n return { value: value as TInput };\n }\n\n const issues: StandardSchemaV1.Issue[] = (validator.errors ?? []).map((error) => ({\n message: formatAjvError(error),\n path: pathFromInstancePath(error.instancePath),\n }));\n\n return {\n issues: issues.length > 0 ? issues : [{ message: \"input failed JSON Schema validation\" }],\n };\n },\n },\n };\n}\n\n/** A single Ajv error object — narrowed to the fields we read. */\ninterface AjvErrorObject {\n instancePath?: string;\n message?: string;\n keyword?: string;\n}\n\n/**\n * Render one Ajv error into a human-readable issue message. Prefixes the\n * failing instance path (when present) so the model can see WHICH field\n * was wrong, e.g. `/query: must be string`.\n */\nfunction formatAjvError(error: AjvErrorObject): string {\n const where = error.instancePath ? `${error.instancePath}: ` : \"\";\n const message = error.message ?? `failed \"${error.keyword ?? \"validation\"}\"`;\n\n return `${where}${message}`;\n}\n\n/**\n * Convert an Ajv `instancePath` (a JSON-Pointer like `/items/0/name`) into\n * the Standard Schema `path` segment array (`[\"items\", \"0\", \"name\"]`).\n * Empty paths (a root-level failure) become an empty array.\n */\nfunction pathFromInstancePath(instancePath: string | undefined): string[] {\n if (!instancePath) {\n return [];\n }\n\n return instancePath\n .split(\"/\")\n .filter((segment) => segment.length > 0)\n .map((segment) => segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n}\n\n/**\n * Reset the cached lazy-import state. Test-only seam so a spec can mock\n * `ajv` as present/absent across cases without module-cache bleed.\n *\n * @internal\n */\nexport function resetAjvCacheForTests(): void {\n AjvSdk = undefined;\n ajvInstance = undefined;\n isAjvAvailable = undefined;\n loadingPromise = undefined;\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,MAAM,SAAS;AAmCf,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AAEJ,MAAM,2BAA2B;;;;;;;;;;EAU/B,KAAK;;;;;;;;AASP,eAAe,UAAyB;CACtC,IAAI,mBAAmB,QACrB;CAGF,IAAI,gBACF,OAAO;CAGT,kBAAkB,YAAY;EAC5B,IAAI;GACF,SAAU,MAAM,OAAO;GAKvB,cAAc,KADZ,OAAO,WAAY,QACK;IAAE,WAAW;IAAM,QAAQ;GAAM,CAAC;GAC5D,iBAAiB;EACnB,QAAQ;GACN,iBAAiB;EACnB;CACF,EAAC,CAAE;CAEH,OAAO;AACT;;;;;;;;AASA,SAAS,aAAa,QAA4E;CAChG,IAAI;CACJ,IAAI,YAAY;CAEhB,aAAa;EACX,IAAI,WACF,OAAO;EAGT,YAAY;EAEZ,IAAI,CAAC,aACH;EAGF,IAAI;GACF,WAAW,YAAY,QAAQ,MAAM;EACvC,QAAQ;GACN,WAAW;EACb;EAEA,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgB,qBACd,QAC0B;CAG1B,IAAI,CAAC,UAAU,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,GAC5C,OAAO,EACL,aAAa;EACX,SAAS;EACT,QAAQ;EACR,WAAW,WAAoB,EAAS,MAAgB;CAC1D,EACF;CAGF,MAAM,UAAU,aAAa,MAAM;CAEnC,OAAO,EACL,aAAa;EACX,SAAS;EACT,QAAQ;EACR,MAAM,SAAS,OAA0D;GACvE,MAAM,QAAQ;GAEd,IAAI,CAAC,gBACH,OAAO,EACL,QAAQ,CAAC,EAAE,SAAS,yBAAyB,CAAC,EAChD;GAGF,MAAM,YAAY,QAAQ;GAI1B,IAAI,CAAC,WACH,OAAO,EAAS,MAAgB;GAKlC,IAFW,UAAU,KAEhB,GACH,OAAO,EAAS,MAAgB;GAGlC,MAAM,UAAoC,UAAU,UAAU,CAAC,EAAC,CAAE,KAAK,WAAW;IAChF,SAAS,eAAe,KAAK;IAC7B,MAAM,qBAAqB,MAAM,YAAY;GAC/C,EAAE;GAEF,OAAO,EACL,QAAQ,OAAO,SAAS,IAAI,SAAS,CAAC,EAAE,SAAS,sCAAsC,CAAC,EAC1F;EACF;CACF,EACF;AACF;;;;;;AAcA,SAAS,eAAe,OAA+B;CAIrD,OAAO,GAHO,MAAM,eAAe,GAAG,MAAM,aAAa,MAAM,KAC/C,MAAM,WAAW,WAAW,MAAM,WAAW,aAAa;AAG5E;;;;;;AAOA,SAAS,qBAAqB,cAA4C;CACxE,IAAI,CAAC,cACH,OAAO,CAAC;CAGV,OAAO,aACJ,MAAM,GAAG,CAAC,CACV,QAAQ,YAAY,QAAQ,SAAS,CAAC,CAAC,CACvC,KAAK,YAAY,QAAQ,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,OAAO,GAAG,CAAC;AACrE"}
1
+ {"version":3,"file":"json-schema-to-standard.mjs","names":[],"sources":["../../../../../../../../packages/ai-tools/src/mcp/json-schema-to-standard.ts"],"sourcesContent":["import type { StandardJSONSchemaV1, StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * The inverse of `@warlock.js/ai`'s `extractJsonSchema` (which goes\n * Standard Schema → JSON Schema). Here we wrap a raw JSON Schema as a\n * {@link StandardSchemaV1} whose `~standard.validate` runs a lazily-imported\n * Ajv validator — so an MCP server's `inputSchema` (JSON Schema) becomes a\n * `ToolConfig.input` the `tool()` factory can validate against.\n *\n * Ajv is an OPTIONAL peer, lazy-imported on first validate following the\n * langfuse/readability pattern: a missing peer surfaces a curated install\n * string (via the returned issues), never a raw module-resolution stack.\n */\n\n/** The structural vendor template, mirroring `passthroughSchema()`. */\nconst VENDOR = \"warlock-ai\";\n\n// ============================================================\n// Lazily-loaded ajv (OPTIONAL peer)\n// ============================================================\n\n/**\n * Minimal structural view of an Ajv-compiled validator. Ajv is an optional\n * peer that may not be installed, so we model only the surface we touch\n * rather than depending on ajv's own published types. A validator is a\n * callable that returns a boolean and exposes the `errors` it collected.\n */\ninterface AjvValidateFunctionLike {\n (data: unknown): boolean;\n errors?: AjvErrorObject[] | null;\n}\n\n/** Minimal structural view of an `Ajv` instance — only `compile`. */\ninterface AjvInstanceLike {\n compile(schema: Record<string, unknown>): AjvValidateFunctionLike;\n}\n\n/** The `Ajv` constructor, as exposed by both the CJS and ESM builds. */\ntype AjvConstructorLike = new (options?: Record<string, unknown>) => AjvInstanceLike;\n\n/**\n * Minimal structural view of the dynamically imported `ajv` module. Ajv\n * ships its constructor as a `default` export under ESM interop; the older\n * CJS shape exposes the constructor as the module namespace itself, so\n * `default` is optional here and the loader falls back to the namespace.\n */\ninterface AjvModuleLike {\n default?: AjvConstructorLike;\n}\n\nlet AjvSdk: AjvModuleLike | undefined;\nlet ajvInstance: AjvInstanceLike | undefined;\nlet isAjvAvailable: boolean | undefined;\nlet loadingPromise: Promise<void> | undefined;\n\nconst AJV_INSTALL_INSTRUCTIONS = `\nThe MCP client's JSON-Schema validation requires the ajv package.\nInstall it with:\n\n npm install ajv\n\nOr with your preferred package manager:\n\n pnpm add ajv\n yarn add ajv\n`.trim();\n\n/**\n * Settle the lazy import of `ajv` once, concurrency-safe. A bare `catch`\n * flips the availability flag to `false`; the curated install string then\n * surfaces at validate time as a Standard Schema issue, never a raw\n * module-resolution error. The constructed `Ajv` instance is cached and\n * reused for every schema compile.\n */\nasync function loadAjv(): Promise<void> {\n if (isAjvAvailable !== undefined) {\n return;\n }\n\n if (loadingPromise) {\n return loadingPromise;\n }\n\n loadingPromise = (async () => {\n try {\n AjvSdk = (await import(\"ajv\")) as AjvModuleLike;\n // Ajv ships as a default export under both CJS and ESM interop; the\n // older CJS shape exposes the constructor as the namespace itself.\n const AjvCtor: AjvConstructorLike =\n AjvSdk.default ?? (AjvSdk as unknown as AjvConstructorLike);\n ajvInstance = new AjvCtor({ allErrors: true, strict: false });\n isAjvAvailable = true;\n } catch {\n isAjvAvailable = false;\n }\n })();\n\n return loadingPromise;\n}\n\n/**\n * Compile a JSON Schema with the shared Ajv instance, caching the compiled\n * validator on a closure so repeated validations don't recompile. A schema\n * Ajv itself rejects at compile time (an invalid meta-schema) degrades to\n * an accept-all validator so a malformed remote schema can't wedge the\n * tool — the server, not us, owns its schema's correctness.\n */\nfunction makeCompiler(schema: Record<string, unknown>): () => AjvValidateFunctionLike | undefined {\n let compiled: AjvValidateFunctionLike | undefined;\n let attempted = false;\n\n return () => {\n if (attempted) {\n return compiled;\n }\n\n attempted = true;\n\n if (!ajvInstance) {\n return undefined;\n }\n\n try {\n compiled = ajvInstance.compile(schema);\n } catch {\n compiled = undefined;\n }\n\n return compiled;\n };\n}\n\n/**\n * Wrap a raw JSON Schema as a {@link StandardSchemaV1} whose\n * `~standard.validate` runs Ajv. The shape mirrors `passthroughSchema()`\n * (`{ \"~standard\": { version: 1, vendor, validate } }`) so it drops into\n * `tool({ input })` exactly like a native seal schema.\n *\n * Validation behavior:\n * - **Valid input** → `{ value }` (the input is passed through unchanged;\n * Ajv validates, it does not transform).\n * - **Invalid input** → `{ issues }` carrying Ajv's `instancePath` +\n * message per failure, so `tool()` produces a `SchemaValidationError`.\n * - **Missing `ajv` peer** → a single issue carrying the curated install\n * string, surfaced the same way (a developer-facing message in logs).\n * - **No / empty schema** → an accept-all passthrough (an MCP tool may\n * advertise no `inputSchema`).\n *\n * @param schema - The JSON Schema (an MCP tool's `inputSchema`), or\n * `undefined` for a no-argument tool.\n * @returns A `StandardSchemaV1<TInput>` ready for `tool({ input })` that also implements\n * Standard JSON Schema, so provider adapters advertise the wrapped schema.\n *\n * @example\n * const input = jsonSchemaToStandard<{ q: string }>({\n * type: \"object\",\n * properties: { q: { type: \"string\" } },\n * required: [\"q\"],\n * });\n */\n/** A validating wrapper that also exposes the JSON Schema it wraps. */\nexport type JsonSchemaStandard<TInput = unknown> = StandardSchemaV1<TInput> &\n StandardJSONSchemaV1<TInput>;\n\n/**\n * Standard JSON Schema converter returning a copy of the wrapped schema, so\n * provider adapters (which may compact or rewrite it) never mutate the source.\n * The remote server owns its schema, so every target receives it unchanged.\n */\nfunction exposeSchema(schema: Record<string, unknown>): StandardJSONSchemaV1.Converter {\n return {\n input: () => structuredClone(schema),\n output: () => structuredClone(schema),\n };\n}\n\nexport function jsonSchemaToStandard<TInput = unknown>(\n schema: Record<string, unknown> | undefined,\n): JsonSchemaStandard<TInput> {\n // A tool with no schema (or an empty object schema) validates everything\n // — return an accept-all passthrough and never touch Ajv.\n if (!schema || Object.keys(schema).length === 0) {\n return {\n \"~standard\": {\n version: 1,\n vendor: VENDOR,\n validate: (value: unknown) => ({ value: value as TInput }),\n jsonSchema: exposeSchema({ type: \"object\", properties: {} }),\n },\n };\n }\n\n const compile = makeCompiler(schema);\n\n return {\n \"~standard\": {\n version: 1,\n vendor: VENDOR,\n jsonSchema: exposeSchema(schema),\n async validate(value: unknown): Promise<StandardSchemaV1.Result<TInput>> {\n await loadAjv();\n\n if (!isAjvAvailable) {\n return {\n issues: [{ message: AJV_INSTALL_INSTRUCTIONS }],\n };\n }\n\n const validator = compile();\n\n // A schema Ajv could not compile degrades to accept-all rather\n // than failing every call — the remote server owns its schema.\n if (!validator) {\n return { value: value as TInput };\n }\n\n const ok = validator(value);\n\n if (ok) {\n return { value: value as TInput };\n }\n\n const issues: StandardSchemaV1.Issue[] = (validator.errors ?? []).map((error) => ({\n message: formatAjvError(error),\n path: pathFromInstancePath(error.instancePath),\n }));\n\n return {\n issues: issues.length > 0 ? issues : [{ message: \"input failed JSON Schema validation\" }],\n };\n },\n },\n };\n}\n\n/** A single Ajv error object — narrowed to the fields we read. */\ninterface AjvErrorObject {\n instancePath?: string;\n message?: string;\n keyword?: string;\n}\n\n/**\n * Render one Ajv error into a human-readable issue message. Prefixes the\n * failing instance path (when present) so the model can see WHICH field\n * was wrong, e.g. `/query: must be string`.\n */\nfunction formatAjvError(error: AjvErrorObject): string {\n const where = error.instancePath ? `${error.instancePath}: ` : \"\";\n const message = error.message ?? `failed \"${error.keyword ?? \"validation\"}\"`;\n\n return `${where}${message}`;\n}\n\n/**\n * Convert an Ajv `instancePath` (a JSON-Pointer like `/items/0/name`) into\n * the Standard Schema `path` segment array (`[\"items\", \"0\", \"name\"]`).\n * Empty paths (a root-level failure) become an empty array.\n */\nfunction pathFromInstancePath(instancePath: string | undefined): string[] {\n if (!instancePath) {\n return [];\n }\n\n return instancePath\n .split(\"/\")\n .filter((segment) => segment.length > 0)\n .map((segment) => segment.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n}\n\n/**\n * Reset the cached lazy-import state. Test-only seam so a spec can mock\n * `ajv` as present/absent across cases without module-cache bleed.\n *\n * @internal\n */\nexport function resetAjvCacheForTests(): void {\n AjvSdk = undefined;\n ajvInstance = undefined;\n isAjvAvailable = undefined;\n loadingPromise = undefined;\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,MAAM,SAAS;AAmCf,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AAEJ,MAAM,2BAA2B;;;;;;;;;;EAU/B,KAAK;;;;;;;;AASP,eAAe,UAAyB;CACtC,IAAI,mBAAmB,QACrB;CAGF,IAAI,gBACF,OAAO;CAGT,kBAAkB,YAAY;EAC5B,IAAI;GACF,SAAU,MAAM,OAAO;GAKvB,cAAc,KADZ,OAAO,WAAY,QACK;IAAE,WAAW;IAAM,QAAQ;GAAM,CAAC;GAC5D,iBAAiB;EACnB,QAAQ;GACN,iBAAiB;EACnB;CACF,EAAC,CAAE;CAEH,OAAO;AACT;;;;;;;;AASA,SAAS,aAAa,QAA4E;CAChG,IAAI;CACJ,IAAI,YAAY;CAEhB,aAAa;EACX,IAAI,WACF,OAAO;EAGT,YAAY;EAEZ,IAAI,CAAC,aACH;EAGF,IAAI;GACF,WAAW,YAAY,QAAQ,MAAM;EACvC,QAAQ;GACN,WAAW;EACb;EAEA,OAAO;CACT;AACF;;;;;;AAuCA,SAAS,aAAa,QAAiE;CACrF,OAAO;EACL,aAAa,gBAAgB,MAAM;EACnC,cAAc,gBAAgB,MAAM;CACtC;AACF;AAEA,SAAgB,qBACd,QAC4B;CAG5B,IAAI,CAAC,UAAU,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,GAC5C,OAAO,EACL,aAAa;EACX,SAAS;EACT,QAAQ;EACR,WAAW,WAAoB,EAAS,MAAgB;EACxD,YAAY,aAAa;GAAE,MAAM;GAAU,YAAY,CAAC;EAAE,CAAC;CAC7D,EACF;CAGF,MAAM,UAAU,aAAa,MAAM;CAEnC,OAAO,EACL,aAAa;EACX,SAAS;EACT,QAAQ;EACR,YAAY,aAAa,MAAM;EAC/B,MAAM,SAAS,OAA0D;GACvE,MAAM,QAAQ;GAEd,IAAI,CAAC,gBACH,OAAO,EACL,QAAQ,CAAC,EAAE,SAAS,yBAAyB,CAAC,EAChD;GAGF,MAAM,YAAY,QAAQ;GAI1B,IAAI,CAAC,WACH,OAAO,EAAS,MAAgB;GAKlC,IAFW,UAAU,KAEhB,GACH,OAAO,EAAS,MAAgB;GAGlC,MAAM,UAAoC,UAAU,UAAU,CAAC,EAAC,CAAE,KAAK,WAAW;IAChF,SAAS,eAAe,KAAK;IAC7B,MAAM,qBAAqB,MAAM,YAAY;GAC/C,EAAE;GAEF,OAAO,EACL,QAAQ,OAAO,SAAS,IAAI,SAAS,CAAC,EAAE,SAAS,sCAAsC,CAAC,EAC1F;EACF;CACF,EACF;AACF;;;;;;AAcA,SAAS,eAAe,OAA+B;CAIrD,OAAO,GAHO,MAAM,eAAe,GAAG,MAAM,aAAa,MAAM,KAC/C,MAAM,WAAW,WAAW,MAAM,WAAW,aAAa;AAG5E;;;;;;AAOA,SAAS,qBAAqB,cAA4C;CACxE,IAAI,CAAC,cACH,OAAO,CAAC;CAGV,OAAO,aACJ,MAAM,GAAG,CAAC,CACV,QAAQ,YAAY,QAAQ,SAAS,CAAC,CAAC,CACvC,KAAK,YAAY,QAAQ,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,OAAO,GAAG,CAAC;AACrE"}