@warlock.js/ai-tools 5.34.0 → 5.34.2
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/CHANGELOG.md +16 -0
- package/README.md +1 -1
- package/cjs/index.cjs +97 -40
- package/cjs/index.cjs.map +1 -1
- package/esm/contracts/index.d.mts +2 -2
- package/esm/contracts/mcp-serve.type.d.mts +26 -1
- package/esm/contracts/mcp-serve.type.d.mts.map +1 -1
- package/esm/index.d.mts +3 -3
- package/esm/mcp/index.d.mts +1 -1
- package/esm/mcp/index.mjs.map +1 -1
- package/esm/mcp/json-schema-to-standard.d.mts +6 -3
- package/esm/mcp/json-schema-to-standard.d.mts.map +1 -1
- package/esm/mcp/json-schema-to-standard.mjs +15 -26
- package/esm/mcp/json-schema-to-standard.mjs.map +1 -1
- package/esm/mcp/serve-http.mjs +84 -15
- package/esm/mcp/serve-http.mjs.map +1 -1
- package/llms-full.txt +76 -3
- package/llms.txt +2 -1
- package/package.json +2 -2
- package/skills/connect-mcp-server/SKILL.md +1 -1
- package/skills/expose-as-mcp-server/SKILL.md +50 -2
- package/skills/index.md +1 -1
- package/skills/README.md +0 -17
|
@@ -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, 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, 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 };
|
|
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 };
|
|
@@ -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
|
|
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,29 @@ 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>;
|
|
74
97
|
/** Authenticated context for an extra HTTP route; there is no JSON-RPC id. */
|
|
75
98
|
export type McpHttpRouteContext = McpServeCallContext & {
|
|
76
99
|
request: McpHttpRequestInfo;
|
|
@@ -130,6 +153,8 @@ export type McpHttpServeTransport = {
|
|
|
130
153
|
path?: string;
|
|
131
154
|
/** Bearer, authorize and/or authenticate checks. Required off loopback. */
|
|
132
155
|
auth?: McpHttpAuth;
|
|
156
|
+
/** Shared by MCP and routes after failed auth; never runs for Host/Origin refusals. */
|
|
157
|
+
onAuthRefusal?: McpHttpAuthRefusal;
|
|
133
158
|
/** Extra HTTP routes with the same Host/Origin and authentication checks. */
|
|
134
159
|
routes?: readonly McpHttpRoute[];
|
|
135
160
|
/**
|
|
@@ -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;;;YAIhD,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,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"}
|
|
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,13 +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, 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";
|
|
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
9
|
import { McpError } from "./mcp/error.mjs";
|
|
10
10
|
import { McpNativeResult, mcpResult } from "./mcp/result.mjs";
|
|
11
|
-
import { jsonSchemaToStandard } from "./mcp/json-schema-to-standard.mjs";
|
|
11
|
+
import { JsonSchemaStandard, jsonSchemaToStandard } from "./mcp/json-schema-to-standard.mjs";
|
|
12
12
|
import { McpTransportClient } from "./mcp/transport.type.mjs";
|
|
13
13
|
import { JsonRpcClientHandle, createJsonRpcClient, createTransport } from "./mcp/transport.mjs";
|
|
14
14
|
import { McpFactory, mcp } from "./mcp/index.mjs";
|
|
@@ -21,6 +21,6 @@ import { calculatorTool } from "./utility/calculator.mjs";
|
|
|
21
21
|
import { dateTimeTool } from "./utility/date-time.mjs";
|
|
22
22
|
import "./utility/index.mjs";
|
|
23
23
|
import { CalculatorError, CalculatorErrorOptions, CalculatorFailure, DateTimeError, DateTimeErrorOptions, DateTimeFailure, HttpPolicyError, HttpPolicyErrorOptions, HttpPolicyFailure, McpServeError, McpServeErrorOptions, McpServeFailure, McpTransportError, McpTransportErrorOptions, McpTransportFailure, WebToolError, WebToolErrorOptions, WebToolFailure } from "./errors.mjs";
|
|
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 McpBeforeCall, type McpCallRefusal, type McpClient, type McpClientOptions, type McpContentBlock, McpError, type McpFactory, type McpGroupedToolSource, type McpHttpAuth, 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
|
+
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 };
|
|
25
25
|
import "./mcp/index.mjs";
|
|
26
26
|
import "./register.mjs";
|
package/esm/mcp/index.d.mts
CHANGED
|
@@ -5,7 +5,7 @@ import { McpServeRequestHandler, createServeHandler, serve } from "./serve.mjs";
|
|
|
5
5
|
import { SUPPORTED_PROTOCOL_VERSIONS } from "./protocol.mjs";
|
|
6
6
|
import { McpError } from "./error.mjs";
|
|
7
7
|
import { McpNativeResult, mcpResult } from "./result.mjs";
|
|
8
|
-
import { jsonSchemaToStandard } from "./json-schema-to-standard.mjs";
|
|
8
|
+
import { JsonSchemaStandard, jsonSchemaToStandard } from "./json-schema-to-standard.mjs";
|
|
9
9
|
import { McpTransportClient } from "./transport.type.mjs";
|
|
10
10
|
import { JsonRpcClientHandle, createJsonRpcClient, createTransport } from "./transport.mjs";
|
|
11
11
|
//#region ../../packages/ai-tools/src/mcp/index.d.ts
|
package/esm/mcp/index.mjs.map
CHANGED
|
@@ -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 { McpError } from \"./error\";\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":";;;;;;;;;;;;;;;;;AA+DA,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
|
-
|
|
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":"
|
|
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
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
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"}
|
package/esm/mcp/serve-http.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { McpServeError } from "../errors.mjs";
|
|
2
2
|
import { SUPPORTED_PROTOCOL_VERSIONS } from "./protocol.mjs";
|
|
3
|
+
import { isRecord } from "./result.mjs";
|
|
3
4
|
import { McpServeRequests } from "./serve-requests.mjs";
|
|
4
5
|
import { createHash, timingSafeEqual } from "node:crypto";
|
|
5
|
-
import { createServer } from "node:http";
|
|
6
|
+
import { createServer, validateHeaderValue } from "node:http";
|
|
6
7
|
import { isIPv4, isIPv6 } from "node:net";
|
|
7
8
|
|
|
8
9
|
//#region ../../packages/ai-tools/src/mcp/serve-http.ts
|
|
@@ -147,6 +148,7 @@ function resolveSettings(transport) {
|
|
|
147
148
|
tokenDigests: tokens.map(digest),
|
|
148
149
|
authorize: auth?.authorize,
|
|
149
150
|
authenticate: auth?.authenticate,
|
|
151
|
+
onAuthRefusal: transport.onAuthRefusal,
|
|
150
152
|
authRequired,
|
|
151
153
|
allowedOrigins: new Set((transport.allowedOrigins ?? []).map(normalizeOrigin)),
|
|
152
154
|
allowedHosts: new Set((transport.allowedHosts ?? []).map((name) => hostnameOf(name))),
|
|
@@ -187,6 +189,52 @@ function sendRefusal(response, status, code, message, headers = {}) {
|
|
|
187
189
|
}
|
|
188
190
|
}, headers);
|
|
189
191
|
}
|
|
192
|
+
const AUTH_REFUSAL_HEADERS = /* @__PURE__ */ new Set([
|
|
193
|
+
"www-authenticate",
|
|
194
|
+
"cache-control",
|
|
195
|
+
"retry-after",
|
|
196
|
+
"content-language",
|
|
197
|
+
"x-request-id"
|
|
198
|
+
]);
|
|
199
|
+
/** Snapshot plain JSON, rejecting cycles and values JSON would silently coerce/drop. */
|
|
200
|
+
function copyRefusalBody(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
201
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
|
|
202
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
203
|
+
if (typeof value !== "object" || value === null || ancestors.has(value)) throw new TypeError("Invalid auth refusal body.");
|
|
204
|
+
const prototype = Object.getPrototypeOf(value);
|
|
205
|
+
if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) throw new TypeError("Invalid auth refusal body.");
|
|
206
|
+
ancestors.add(value);
|
|
207
|
+
const result = Array.isArray(value) ? Array.from(value, (entry) => copyRefusalBody(entry, ancestors)) : Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, copyRefusalBody(entry, ancestors)]));
|
|
208
|
+
ancestors.delete(value);
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
/** A custom response can only end a denied exchange; it cannot authorize dispatch. */
|
|
212
|
+
async function sendAuthRefusal(response, settings, context) {
|
|
213
|
+
const challenge = settings.tokenDigests.length > 0 || settings.authenticate ? { "www-authenticate": "Bearer realm=\"mcp\"" } : {};
|
|
214
|
+
if (settings.onAuthRefusal) try {
|
|
215
|
+
const result = await settings.onAuthRefusal(Object.freeze(context));
|
|
216
|
+
if (!isRecord(result)) throw new TypeError("Invalid auth refusal response.");
|
|
217
|
+
const customStatus = result.status;
|
|
218
|
+
const status = customStatus === void 0 ? 401 : customStatus;
|
|
219
|
+
if (typeof status !== "number" || !Number.isInteger(status) || status < 400 || status > 599) throw new TypeError("Invalid auth refusal status.");
|
|
220
|
+
const headers = { ...challenge };
|
|
221
|
+
const customHeaders = result.headers;
|
|
222
|
+
if (customHeaders !== void 0) {
|
|
223
|
+
if (!isRecord(customHeaders)) throw new TypeError("Invalid auth refusal headers.");
|
|
224
|
+
const prototype = Object.getPrototypeOf(customHeaders);
|
|
225
|
+
if (prototype !== Object.prototype && prototype !== null) throw new TypeError("Invalid auth refusal headers.");
|
|
226
|
+
for (const [name, value] of Object.entries(customHeaders)) {
|
|
227
|
+
const normalized = name.toLowerCase();
|
|
228
|
+
if (!AUTH_REFUSAL_HEADERS.has(normalized) || typeof value !== "string") throw new TypeError("Invalid auth refusal header.");
|
|
229
|
+
validateHeaderValue(normalized, value);
|
|
230
|
+
headers[normalized] = value;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
sendJson(response, status, copyRefusalBody(result.body), headers);
|
|
234
|
+
return;
|
|
235
|
+
} catch {}
|
|
236
|
+
sendRefusal(response, 401, JSON_RPC_SERVER_ERROR, "Unauthorized.", challenge);
|
|
237
|
+
}
|
|
190
238
|
/** Write an empty-bodied status (202 / 405). */
|
|
191
239
|
function sendEmpty(response, status, headers = {}) {
|
|
192
240
|
if (response.headersSent || response.destroyed) return;
|
|
@@ -302,8 +350,12 @@ async function handleRequest(request, response, settings, dispatch, signal, requ
|
|
|
302
350
|
if (request.socket.remoteAddress !== void 0) info.remoteAddress = request.socket.remoteAddress;
|
|
303
351
|
const authentication = await authorized(info, settings);
|
|
304
352
|
if (!authentication.allowed) {
|
|
305
|
-
|
|
306
|
-
|
|
353
|
+
await sendAuthRefusal(response, settings, {
|
|
354
|
+
check: authentication.check,
|
|
355
|
+
method,
|
|
356
|
+
path,
|
|
357
|
+
target: routes ? "route" : "mcp"
|
|
358
|
+
});
|
|
307
359
|
return;
|
|
308
360
|
}
|
|
309
361
|
if (routes) {
|
|
@@ -451,21 +503,38 @@ async function authorized(info, settings) {
|
|
|
451
503
|
const presented = digest(match?.[1]?.trim() ?? "");
|
|
452
504
|
let matched = false;
|
|
453
505
|
for (const expected of settings.tokenDigests) matched = timingSafeEqual(presented, expected) || matched;
|
|
454
|
-
if (!match || !matched) return {
|
|
506
|
+
if (!match || !matched) return {
|
|
507
|
+
allowed: false,
|
|
508
|
+
check: "bearer"
|
|
509
|
+
};
|
|
455
510
|
}
|
|
456
|
-
try {
|
|
457
|
-
if (
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
511
|
+
if (settings.authorize) try {
|
|
512
|
+
if (await settings.authorize(info) !== true) return {
|
|
513
|
+
allowed: false,
|
|
514
|
+
check: "authorize"
|
|
515
|
+
};
|
|
516
|
+
} catch {
|
|
517
|
+
return {
|
|
518
|
+
allowed: false,
|
|
519
|
+
check: "authorize"
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
if (settings.authenticate) try {
|
|
523
|
+
const principal = await settings.authenticate(info);
|
|
524
|
+
return principal === void 0 ? {
|
|
525
|
+
allowed: false,
|
|
526
|
+
check: "authenticate"
|
|
527
|
+
} : {
|
|
528
|
+
allowed: true,
|
|
529
|
+
principal
|
|
530
|
+
};
|
|
466
531
|
} catch {
|
|
467
|
-
return {
|
|
532
|
+
return {
|
|
533
|
+
allowed: false,
|
|
534
|
+
check: "authenticate"
|
|
535
|
+
};
|
|
468
536
|
}
|
|
537
|
+
return { allowed: true };
|
|
469
538
|
}
|
|
470
539
|
/**
|
|
471
540
|
* Stateless HTTP has no connection/session id. Repeat the caller's credential
|