@webpieces/core-util 0.4.795 → 0.4.797
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/package.json +1 -1
- package/src/errors/ApiError.d.ts +9 -5
- package/src/errors/ApiError.js +9 -4
- package/src/errors/ApiError.js.map +1 -1
- package/src/errors/ApiErrorCodec.js +5 -0
- package/src/errors/ApiErrorCodec.js.map +1 -1
- package/src/errors/ReceivedApiErrorRule.d.ts +5 -3
- package/src/errors/ReceivedApiErrorRule.js +23 -4
- package/src/errors/ReceivedApiErrorRule.js.map +1 -1
- package/src/errors/index.d.ts +1 -1
- package/src/errors/index.js +2 -1
- package/src/errors/index.js.map +1 -1
- package/src/http/ApiCallTimeoutError.d.ts +2 -1
- package/src/http/ApiCallTimeoutError.js +2 -1
- package/src/http/ApiCallTimeoutError.js.map +1 -1
- package/src/http/ApiErrorHttpStatus.js +1 -0
- package/src/http/ApiErrorHttpStatus.js.map +1 -1
- package/src/http/EndpointCompileAssertions.d.ts +1 -0
- package/src/http/EndpointCompileAssertions.js +21 -0
- package/src/http/EndpointCompileAssertions.js.map +1 -0
- package/src/http/HttpContract.d.ts +10 -1
- package/src/http/HttpContract.js +10 -1
- package/src/http/HttpContract.js.map +1 -1
- package/src/http/HttpEndpointOptions.d.ts +14 -3
- package/src/http/HttpEndpointOptions.js +12 -0
- package/src/http/HttpEndpointOptions.js.map +1 -1
- package/src/http/RouteMetadata.d.ts +6 -1
- package/src/http/RouteMetadata.js +5 -1
- package/src/http/RouteMetadata.js.map +1 -1
- package/src/http/RouteMetadataFactory.d.ts +3 -3
- package/src/http/RouteMetadataFactory.js +13 -16
- package/src/http/RouteMetadataFactory.js.map +1 -1
- package/src/http/WebpiecesDefaultErrorTranslator.d.ts +5 -3
- package/src/http/WebpiecesDefaultErrorTranslator.js +17 -4
- package/src/http/WebpiecesDefaultErrorTranslator.js.map +1 -1
- package/src/http/api-kind.js +2 -2
- package/src/http/api-kind.js.map +1 -1
- package/src/http/decorators.d.ts +41 -143
- package/src/http/decorators.js +123 -110
- package/src/http/decorators.js.map +1 -1
- package/src/http/external-caller.d.ts +4 -4
- package/src/http/external-caller.js +12 -5
- package/src/http/external-caller.js.map +1 -1
- package/src/index.d.ts +7 -5
- package/src/index.js +21 -5
- package/src/index.js.map +1 -1
- package/src/mcp/McpCompileAssertions.js +3 -9
- package/src/mcp/McpCompileAssertions.js.map +1 -1
- package/src/mcp/McpMetadata.d.ts +8 -14
- package/src/mcp/McpMetadata.js +19 -5
- package/src/mcp/McpMetadata.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpCompileAssertions.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/mcp/McpCompileAssertions.ts"],"names":[],"mappings":";;;AAAA,+CAA0C;AAC1C,2CAAsE;AAEtE,MAAM,gBAAgB,GAAG,IAAI,6BAAiB,CAC1C,cAAc,EACd,IAAI,EACJ,SAAS,EACT,KAAK,EACL,SAAS,EACT,SAAS;AACT,uEAAuE;AACvE,EAAE,CACL,CAAC;AAEF,0EAA0E;AAC1E,MAAM,eAAe,GAAG,IAAI,gCAAoB,CAAC,aAAa,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAE9E,gGAAgG;AAChG,MAAM,eAAe,GAAG,IAAI,gCAAoB,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,qBAAqB,GAAG,IAAI,6BAAiB,CAC/C,2CAA2C,EAC3C,KAAK,EACL,SAAS,EACT,KAAK,EACL,SAAS,EACT,SAAS,EACT,SAAS;AACT,yFAAyF;AACzF,QAAQ,CACX,CAAC;AAEF,MAAe,kBAAkB;
|
|
1
|
+
{"version":3,"file":"McpCompileAssertions.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/mcp/McpCompileAssertions.ts"],"names":[],"mappings":";;;AAAA,+CAA0C;AAC1C,2CAAsE;AAEtE,MAAM,gBAAgB,GAAG,IAAI,6BAAiB,CAC1C,cAAc,EACd,IAAI,EACJ,SAAS,EACT,KAAK,EACL,SAAS,EACT,SAAS;AACT,uEAAuE;AACvE,EAAE,CACL,CAAC;AAEF,0EAA0E;AAC1E,MAAM,eAAe,GAAG,IAAI,gCAAoB,CAAC,aAAa,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAE9E,gGAAgG;AAChG,MAAM,eAAe,GAAG,IAAI,gCAAoB,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,qBAAqB,GAAG,IAAI,6BAAiB,CAC/C,2CAA2C,EAC3C,KAAK,EACL,SAAS,EACT,KAAK,EACL,SAAS,EACT,SAAS,EACT,SAAS;AACT,yFAAyF;AACzF,QAAQ,CACX,CAAC;AAEF,MAAe,kBAAkB;IAQ7B,OAAO,CAAC,QAAgB;QACpB,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;CACJ;AAHG;IAPC,IAAA,uBAAS,EAAC;QACP,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,sCAAsC;QACnD,sFAAsF;QACtF,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,KAAK;KACvB,CAAC;;;;iDAGD;AAGL,MAAe,iBAAiB;IAC5B,6DAA6D;IAM7D,IAAI;QACA,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;IAED,6DAA6D;IAM7D,KAAK,CAAC,MAAc,EAAE,OAAe;QACjC,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IACrC,CAAC;CACJ;AAbG;IALC,IAAA,uBAAS,EAAC;QACP,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,sCAAsC;QACnD,aAAa,EAAE,KAAK;KACvB,CAAC;;;;6CAGD;AAQD;IALC,IAAA,uBAAS,EAAC;QACP,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,sCAAsC;QACnD,aAAa,EAAE,KAAK;KACvB,CAAC;;;;8CAGD;AAGL,KAAK,kBAAkB,CAAC;AACxB,KAAK,iBAAiB,CAAC;AACvB,KAAK,gBAAgB,CAAC;AACtB,KAAK,eAAe,CAAC;AACrB,KAAK,eAAe,CAAC;AACrB,KAAK,qBAAqB,CAAC","sourcesContent":["import { WpMcpTool } from './McpMetadata';\nimport { WpDtoFieldOptions, WpDtoMapFieldOptions } from './DtoSchema';\n\nconst invalidEmptyEnum = new WpDtoFieldOptions(\n 'invalid enum',\n true,\n undefined,\n false,\n undefined,\n undefined,\n // @ts-expect-error enumValues must contain at least one allowed string\n [],\n);\n\n// @ts-expect-error a map's value type must be a scalar name or a DtoClass\nconst invalidMapValue = new WpDtoMapFieldOptions('invalid map', true, 'date');\n\n// @ts-expect-error a map value type is mandatory: it is the whole point of WpDtoMapFieldOptions\nconst missingMapValue = new WpDtoMapFieldOptions('invalid map', true);\n\nconst noEighthFieldArgument = new WpDtoFieldOptions(\n 'maps are not a WpDtoFieldOptions argument',\n false,\n undefined,\n false,\n undefined,\n undefined,\n undefined,\n // @ts-expect-error maps use WpDtoMapFieldOptions; the 8th argument is only a WpMcpHeader\n 'string',\n);\n\nabstract class InvalidMcpContract {\n @WpMcpTool({\n name: 'invalid',\n description: 'This declaration must never compile.',\n // @ts-expect-error side-effect claims belong on @Endpoint.operation, never @WpMcpTool\n readOnlyHint: true,\n openWorldHint: false,\n })\n invalid(_request: object): Promise<object> {\n throw new Error('contract only');\n }\n}\n\nabstract class InvalidMcpArities {\n // @ts-expect-error MCP tools require exactly one request DTO\n @WpMcpTool({\n name: 'zero-arity',\n description: 'This declaration must never compile.',\n openWorldHint: false,\n })\n zero(): Promise<object> {\n throw new Error('contract only');\n }\n\n // @ts-expect-error MCP tools require exactly one request DTO\n @WpMcpTool({\n name: 'multi-arity',\n description: 'This declaration must never compile.',\n openWorldHint: false,\n })\n multi(_first: object, _second: object): Promise<object> {\n throw new Error('contract only');\n }\n}\n\nvoid InvalidMcpContract;\nvoid InvalidMcpArities;\nvoid invalidEmptyEnum;\nvoid invalidMapValue;\nvoid missingMapValue;\nvoid noEighthFieldArgument;\n"]}
|
package/src/mcp/McpMetadata.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
+
import { EndpointOperation } from '../http/HttpEndpointOptions';
|
|
2
3
|
/** The immutable hints MCP clients use when deciding whether and how to call a tool. */
|
|
3
4
|
export declare class WpMcpToolHints {
|
|
4
5
|
readonly readOnlyHint: boolean;
|
|
@@ -12,19 +13,10 @@ type CommonToolOptions = {
|
|
|
12
13
|
name: string;
|
|
13
14
|
/** Tool-level documentation published verbatim by tools/list. */
|
|
14
15
|
description: string;
|
|
15
|
-
idempotentHint: boolean;
|
|
16
16
|
openWorldHint: boolean;
|
|
17
17
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
destructiveHint?: never;
|
|
21
|
-
};
|
|
22
|
-
type MutatingToolOptions = CommonToolOptions & {
|
|
23
|
-
readOnlyHint: false;
|
|
24
|
-
destructiveHint: boolean;
|
|
25
|
-
};
|
|
26
|
-
/** Compiler-enforced exposure: a read-only tool cannot also claim to be destructive. */
|
|
27
|
-
export type WpMcpToolOptions = ReadOnlyToolOptions | MutatingToolOptions;
|
|
18
|
+
/** Tool-specific declarations. Side-effect hints come only from the endpoint operation. */
|
|
19
|
+
export type WpMcpToolOptions = CommonToolOptions;
|
|
28
20
|
type AsyncObjectMethod = (...args: never[]) => Promise<object>;
|
|
29
21
|
type ExactOneParameter<TMethod extends AsyncObjectMethod> = Parameters<TMethod>['length'] extends 1 ? object : never;
|
|
30
22
|
type ExactOneMethodDescriptor<TMethod extends AsyncObjectMethod> = TypedPropertyDescriptor<TMethod> & ExactOneParameter<TMethod>;
|
|
@@ -35,17 +27,19 @@ export declare class WpMcpToolMetadata {
|
|
|
35
27
|
readonly methodName: string;
|
|
36
28
|
readonly name: string;
|
|
37
29
|
readonly description: string;
|
|
38
|
-
readonly
|
|
39
|
-
constructor(methodName: string, name: string, description: string,
|
|
30
|
+
readonly openWorldHint: boolean;
|
|
31
|
+
constructor(methodName: string, name: string, description: string, openWorldHint: boolean);
|
|
40
32
|
}
|
|
41
33
|
/**
|
|
42
|
-
* Explicitly publishes an existing `@Endpoint(
|
|
34
|
+
* Explicitly publishes an existing `@Endpoint(POST, path, WRITE, RPC)` method as an MCP tool.
|
|
43
35
|
*
|
|
44
36
|
* This annotation owns tool-level documentation only. Input/output field documentation and JSON
|
|
45
37
|
* Schema come from the request/response DTO metadata. The endpoint's `@WpAuth*` annotation remains
|
|
46
38
|
* the sole runtime authorization policy.
|
|
47
39
|
*/
|
|
48
40
|
export declare function WpMcpTool(options: WpMcpToolOptions): WpMcpMethodDecorator;
|
|
41
|
+
/** The one mapping from endpoint side effects to MCP advisory annotations. */
|
|
42
|
+
export declare function mcpHintsForOperation(operation: EndpointOperation, openWorldHint: boolean): WpMcpToolHints;
|
|
49
43
|
/** Returns only methods explicitly opted in through {@link WpMcpTool}. */
|
|
50
44
|
export declare function getWpMcpTools(apiClass: Function): WpMcpToolMetadata[];
|
|
51
45
|
export {};
|
package/src/mcp/McpMetadata.js
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WpMcpToolMetadata = exports.WpMcpToolHints = void 0;
|
|
4
4
|
exports.WpMcpTool = WpMcpTool;
|
|
5
|
+
exports.mcpHintsForOperation = mcpHintsForOperation;
|
|
5
6
|
exports.getWpMcpTools = getWpMcpTools;
|
|
6
7
|
require("reflect-metadata");
|
|
7
8
|
const decorators_1 = require("../http/decorators");
|
|
9
|
+
const HttpEndpointOptions_1 = require("../http/HttpEndpointOptions");
|
|
8
10
|
/** The immutable hints MCP clients use when deciding whether and how to call a tool. */
|
|
9
11
|
class WpMcpToolHints {
|
|
10
12
|
readOnlyHint;
|
|
@@ -24,17 +26,17 @@ class WpMcpToolMetadata {
|
|
|
24
26
|
methodName;
|
|
25
27
|
name;
|
|
26
28
|
description;
|
|
27
|
-
|
|
28
|
-
constructor(methodName, name, description,
|
|
29
|
+
openWorldHint;
|
|
30
|
+
constructor(methodName, name, description, openWorldHint) {
|
|
29
31
|
this.methodName = methodName;
|
|
30
32
|
this.name = name;
|
|
31
33
|
this.description = description;
|
|
32
|
-
this.
|
|
34
|
+
this.openWorldHint = openWorldHint;
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
exports.WpMcpToolMetadata = WpMcpToolMetadata;
|
|
36
38
|
/**
|
|
37
|
-
* Explicitly publishes an existing `@Endpoint(
|
|
39
|
+
* Explicitly publishes an existing `@Endpoint(POST, path, WRITE, RPC)` method as an MCP tool.
|
|
38
40
|
*
|
|
39
41
|
* This annotation owns tool-level documentation only. Input/output field documentation and JSON
|
|
40
42
|
* Schema come from the request/response DTO metadata. The endpoint's `@WpAuth*` annotation remains
|
|
@@ -51,10 +53,22 @@ function WpMcpTool(options) {
|
|
|
51
53
|
const apiClass = target.constructor;
|
|
52
54
|
const tools = Reflect.getMetadata(decorators_1.METADATA_KEYS.MCP_TOOLS, apiClass) ?? {};
|
|
53
55
|
const methodName = String(propertyKey);
|
|
54
|
-
tools[methodName] = new WpMcpToolMetadata(methodName, options.name, options.description,
|
|
56
|
+
tools[methodName] = new WpMcpToolMetadata(methodName, options.name, options.description, options.openWorldHint);
|
|
55
57
|
Reflect.defineMetadata(decorators_1.METADATA_KEYS.MCP_TOOLS, tools, apiClass);
|
|
56
58
|
};
|
|
57
59
|
}
|
|
60
|
+
/** The one mapping from endpoint side effects to MCP advisory annotations. */
|
|
61
|
+
// webpieces-disable no-function-outside-class -- pure metadata mapping shared by MCP registration
|
|
62
|
+
function mcpHintsForOperation(operation, openWorldHint) {
|
|
63
|
+
switch (operation) {
|
|
64
|
+
case HttpEndpointOptions_1.READ:
|
|
65
|
+
return new WpMcpToolHints(true, false, true, openWorldHint);
|
|
66
|
+
case HttpEndpointOptions_1.WRITE_IDEMPOTENT:
|
|
67
|
+
return new WpMcpToolHints(false, true, true, openWorldHint);
|
|
68
|
+
case HttpEndpointOptions_1.WRITE:
|
|
69
|
+
return new WpMcpToolHints(false, true, false, openWorldHint);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
58
72
|
/** Returns only methods explicitly opted in through {@link WpMcpTool}. */
|
|
59
73
|
// webpieces-disable no-function-outside-class -- metadata reader paired with the decorator
|
|
60
74
|
function getWpMcpTools(apiClass) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpMetadata.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/mcp/McpMetadata.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"McpMetadata.js","sourceRoot":"","sources":["../../../../../../packages/core/core-util/src/mcp/McpMetadata.ts"],"names":[],"mappings":";;;AA8DA,8BAsBC;AAID,oDAYC;AAID,sCAIC;AA5GD,4BAA0B;AAC1B,mDAAmD;AACnD,qEAKqC;AAErC,wFAAwF;AACxF,MAAa,cAAc;IAEH;IACA;IACA;IACA;IAJpB,YACoB,YAAqB,EACrB,eAAwB,EACxB,cAAuB,EACvB,aAAsB;QAHtB,iBAAY,GAAZ,YAAY,CAAS;QACrB,oBAAe,GAAf,eAAe,CAAS;QACxB,mBAAc,GAAd,cAAc,CAAS;QACvB,kBAAa,GAAb,aAAa,CAAS;IACvC,CAAC;CACP;AAPD,wCAOC;AA2BD,4DAA4D;AAC5D,MAAa,iBAAiB;IAEN;IACA;IACA;IACA;IAJpB,YACoB,UAAkB,EAClB,IAAY,EACZ,WAAmB,EACnB,aAAsB;QAHtB,eAAU,GAAV,UAAU,CAAQ;QAClB,SAAI,GAAJ,IAAI,CAAQ;QACZ,gBAAW,GAAX,WAAW,CAAQ;QACnB,kBAAa,GAAb,aAAa,CAAS;IACvC,CAAC;CACP;AAPD,8CAOC;AAED;;;;;;GAMG;AACH,iGAAiG;AACjG,SAAgB,SAAS,CAAC,OAAyB;IAC/C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAChG,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,CACH,MAAc,EACd,WAA4B,EAC5B,WAA8C,EAC1C,EAAE;QACN,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC;QACpC,MAAM,KAAK,GACP,OAAO,CAAC,WAAW,CAAC,0BAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QACjE,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QACvC,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,iBAAiB,CACrC,UAAU,EACV,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,aAAa,CACxB,CAAC;QACF,OAAO,CAAC,cAAc,CAAC,0BAAa,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrE,CAAC,CAAC;AACN,CAAC;AAED,8EAA8E;AAC9E,kGAAkG;AAClG,SAAgB,oBAAoB,CAChC,SAA4B,EAC5B,aAAsB;IAEtB,QAAQ,SAAS,EAAE,CAAC;QAChB,KAAK,0BAAI;YACL,OAAO,IAAI,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QAChE,KAAK,sCAAgB;YACjB,OAAO,IAAI,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;QAChE,KAAK,2BAAK;YACN,OAAO,IAAI,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IACrE,CAAC;AACL,CAAC;AAED,0EAA0E;AAC1E,2FAA2F;AAC3F,SAAgB,aAAa,CAAC,QAAkB;IAC5C,MAAM,KAAK,GACP,OAAO,CAAC,WAAW,CAAC,0BAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjE,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC","sourcesContent":["import 'reflect-metadata';\nimport { METADATA_KEYS } from '../http/decorators';\nimport {\n EndpointOperation,\n READ,\n WRITE_IDEMPOTENT,\n WRITE,\n} from '../http/HttpEndpointOptions';\n\n/** The immutable hints MCP clients use when deciding whether and how to call a tool. */\nexport class WpMcpToolHints {\n constructor(\n public readonly readOnlyHint: boolean,\n public readonly destructiveHint: boolean,\n public readonly idempotentHint: boolean,\n public readonly openWorldHint: boolean,\n ) {}\n}\n\ntype CommonToolOptions = {\n /** Stable protocol name. Renaming this breaks saved agent workflows. */\n name: string;\n /** Tool-level documentation published verbatim by tools/list. */\n description: string;\n openWorldHint: boolean;\n};\n\n/** Tool-specific declarations. Side-effect hints come only from the endpoint operation. */\nexport type WpMcpToolOptions = CommonToolOptions;\n\ntype AsyncObjectMethod = (...args: never[]) => Promise<object>;\ntype ExactOneParameter<TMethod extends AsyncObjectMethod> = Parameters<TMethod>['length'] extends 1\n ? object\n : never;\ntype ExactOneMethodDescriptor<TMethod extends AsyncObjectMethod> =\n TypedPropertyDescriptor<TMethod> & ExactOneParameter<TMethod>;\n\n/** Method decorator restricted to one request DTO and one async response DTO. */\nexport type WpMcpMethodDecorator = <TMethod extends AsyncObjectMethod>(\n target: object,\n propertyKey: string | symbol,\n descriptor: ExactOneMethodDescriptor<TMethod>,\n) => void;\n\n/** Runtime metadata for one explicitly exposed endpoint. */\nexport class WpMcpToolMetadata {\n constructor(\n public readonly methodName: string,\n public readonly name: string,\n public readonly description: string,\n public readonly openWorldHint: boolean,\n ) {}\n}\n\n/**\n * Explicitly publishes an existing `@Endpoint(POST, path, WRITE, RPC)` method as an MCP tool.\n *\n * This annotation owns tool-level documentation only. Input/output field documentation and JSON\n * Schema come from the request/response DTO metadata. The endpoint's `@WpAuth*` annotation remains\n * the sole runtime authorization policy.\n */\n// webpieces-disable no-function-outside-class -- decorator factories are inherently module-scope\nexport function WpMcpTool(options: WpMcpToolOptions): WpMcpMethodDecorator {\n if (options.name.trim() === '') throw new Error('@WpMcpTool requires a non-empty stable name.');\n if (options.description.trim() === '') {\n throw new Error('@WpMcpTool requires non-empty tool documentation.');\n }\n return <TMethod extends AsyncObjectMethod>(\n target: object,\n propertyKey: string | symbol,\n _descriptor: ExactOneMethodDescriptor<TMethod>,\n ): void => {\n const apiClass = target.constructor;\n const tools: Record<string, WpMcpToolMetadata> =\n Reflect.getMetadata(METADATA_KEYS.MCP_TOOLS, apiClass) ?? {};\n const methodName = String(propertyKey);\n tools[methodName] = new WpMcpToolMetadata(\n methodName,\n options.name,\n options.description,\n options.openWorldHint,\n );\n Reflect.defineMetadata(METADATA_KEYS.MCP_TOOLS, tools, apiClass);\n };\n}\n\n/** The one mapping from endpoint side effects to MCP advisory annotations. */\n// webpieces-disable no-function-outside-class -- pure metadata mapping shared by MCP registration\nexport function mcpHintsForOperation(\n operation: EndpointOperation,\n openWorldHint: boolean,\n): WpMcpToolHints {\n switch (operation) {\n case READ:\n return new WpMcpToolHints(true, false, true, openWorldHint);\n case WRITE_IDEMPOTENT:\n return new WpMcpToolHints(false, true, true, openWorldHint);\n case WRITE:\n return new WpMcpToolHints(false, true, false, openWorldHint);\n }\n}\n\n/** Returns only methods explicitly opted in through {@link WpMcpTool}. */\n// webpieces-disable no-function-outside-class -- metadata reader paired with the decorator\nexport function getWpMcpTools(apiClass: Function): WpMcpToolMetadata[] {\n const tools: Record<string, WpMcpToolMetadata> =\n Reflect.getMetadata(METADATA_KEYS.MCP_TOOLS, apiClass) ?? {};\n return Object.values(tools);\n}\n"]}
|