@vendure/mcp-plugin 3.8.0-minor-bootstrap.0
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/lib/api/api-extensions.d.ts +2 -0
- package/lib/api/api-extensions.js +239 -0
- package/lib/api/api-extensions.js.map +1 -0
- package/lib/api/mcp-actor.service.d.ts +19 -0
- package/lib/api/mcp-actor.service.js +52 -0
- package/lib/api/mcp-actor.service.js.map +1 -0
- package/lib/api/mcp-admin.resolver.d.ts +105 -0
- package/lib/api/mcp-admin.resolver.js +463 -0
- package/lib/api/mcp-admin.resolver.js.map +1 -0
- package/lib/api/mcp-shop.resolver.d.ts +25 -0
- package/lib/api/mcp-shop.resolver.js +74 -0
- package/lib/api/mcp-shop.resolver.js.map +1 -0
- package/lib/check-options.d.ts +7 -0
- package/lib/check-options.js +130 -0
- package/lib/check-options.js.map +1 -0
- package/lib/constants.d.ts +48 -0
- package/lib/constants.js +72 -0
- package/lib/constants.js.map +1 -0
- package/lib/delete-in-batches.d.ts +5 -0
- package/lib/delete-in-batches.js +28 -0
- package/lib/delete-in-batches.js.map +1 -0
- package/lib/entities/index.d.ts +5 -0
- package/lib/entities/index.js +22 -0
- package/lib/entities/index.js.map +1 -0
- package/lib/entities/mcp-authorization-code.entity.d.ts +33 -0
- package/lib/entities/mcp-authorization-code.entity.js +77 -0
- package/lib/entities/mcp-authorization-code.entity.js.map +1 -0
- package/lib/entities/mcp-authorization-request.entity.d.ts +31 -0
- package/lib/entities/mcp-authorization-request.entity.js +73 -0
- package/lib/entities/mcp-authorization-request.entity.js.map +1 -0
- package/lib/entities/mcp-oauth-client.entity.d.ts +56 -0
- package/lib/entities/mcp-oauth-client.entity.js +70 -0
- package/lib/entities/mcp-oauth-client.entity.js.map +1 -0
- package/lib/entities/mcp-oauth-grant.entity.d.ts +77 -0
- package/lib/entities/mcp-oauth-grant.entity.js +121 -0
- package/lib/entities/mcp-oauth-grant.entity.js.map +1 -0
- package/lib/entities/mcp-tool-call-log.entity.d.ts +50 -0
- package/lib/entities/mcp-tool-call-log.entity.js +101 -0
- package/lib/entities/mcp-tool-call-log.entity.js.map +1 -0
- package/lib/events/mcp-tool-call.event.d.ts +17 -0
- package/lib/events/mcp-tool-call.event.js +23 -0
- package/lib/events/mcp-tool-call.event.js.map +1 -0
- package/lib/get-client-ip.d.ts +2 -0
- package/lib/get-client-ip.js +10 -0
- package/lib/get-client-ip.js.map +1 -0
- package/lib/get-language-code.d.ts +3 -0
- package/lib/get-language-code.js +12 -0
- package/lib/get-language-code.js.map +1 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +26 -0
- package/lib/index.js.map +1 -0
- package/lib/internal-types.d.ts +27 -0
- package/lib/internal-types.js +3 -0
- package/lib/internal-types.js.map +1 -0
- package/lib/logging/mcp-tool-call-log-retention.service.d.ts +8 -0
- package/lib/logging/mcp-tool-call-log-retention.service.js +54 -0
- package/lib/logging/mcp-tool-call-log-retention.service.js.map +1 -0
- package/lib/logging/mcp-tool-call-log.service.d.ts +24 -0
- package/lib/logging/mcp-tool-call-log.service.js +128 -0
- package/lib/logging/mcp-tool-call-log.service.js.map +1 -0
- package/lib/oauth/cimd/cimd-client-resolver.service.d.ts +18 -0
- package/lib/oauth/cimd/cimd-client-resolver.service.js +109 -0
- package/lib/oauth/cimd/cimd-client-resolver.service.js.map +1 -0
- package/lib/oauth/cimd/cimd-document.d.ts +11 -0
- package/lib/oauth/cimd/cimd-document.js +66 -0
- package/lib/oauth/cimd/cimd-document.js.map +1 -0
- package/lib/oauth/cimd/cimd-fetch.d.ts +14 -0
- package/lib/oauth/cimd/cimd-fetch.js +192 -0
- package/lib/oauth/cimd/cimd-fetch.js.map +1 -0
- package/lib/oauth/cimd/cimd-url.d.ts +5 -0
- package/lib/oauth/cimd/cimd-url.js +94 -0
- package/lib/oauth/cimd/cimd-url.js.map +1 -0
- package/lib/oauth/grant-session.service.d.ts +19 -0
- package/lib/oauth/grant-session.service.js +141 -0
- package/lib/oauth/grant-session.service.js.map +1 -0
- package/lib/oauth/oauth-error.d.ts +18 -0
- package/lib/oauth/oauth-error.js +60 -0
- package/lib/oauth/oauth-error.js.map +1 -0
- package/lib/oauth/oauth-metadata.service.d.ts +34 -0
- package/lib/oauth/oauth-metadata.service.js +107 -0
- package/lib/oauth/oauth-metadata.service.js.map +1 -0
- package/lib/oauth/oauth-retention.service.d.ts +23 -0
- package/lib/oauth/oauth-retention.service.js +103 -0
- package/lib/oauth/oauth-retention.service.js.map +1 -0
- package/lib/oauth/oauth-types.d.ts +61 -0
- package/lib/oauth/oauth-types.js +32 -0
- package/lib/oauth/oauth-types.js.map +1 -0
- package/lib/oauth/oauth-utils.d.ts +20 -0
- package/lib/oauth/oauth-utils.js +111 -0
- package/lib/oauth/oauth-utils.js.map +1 -0
- package/lib/oauth/oauth.controller.d.ts +31 -0
- package/lib/oauth/oauth.controller.js +132 -0
- package/lib/oauth/oauth.controller.js.map +1 -0
- package/lib/oauth/oauth.service.d.ts +69 -0
- package/lib/oauth/oauth.service.js +650 -0
- package/lib/oauth/oauth.service.js.map +1 -0
- package/lib/oauth/token-hash.d.ts +6 -0
- package/lib/oauth/token-hash.js +21 -0
- package/lib/oauth/token-hash.js.map +1 -0
- package/lib/plugin.d.ts +54 -0
- package/lib/plugin.js +171 -0
- package/lib/plugin.js.map +1 -0
- package/lib/rate-limit/ip-bucket-key.d.ts +1 -0
- package/lib/rate-limit/ip-bucket-key.js +35 -0
- package/lib/rate-limit/ip-bucket-key.js.map +1 -0
- package/lib/rate-limit/mcp-oauth-rate-limit.guard.d.ts +20 -0
- package/lib/rate-limit/mcp-oauth-rate-limit.guard.js +63 -0
- package/lib/rate-limit/mcp-oauth-rate-limit.guard.js.map +1 -0
- package/lib/rate-limit/mcp-rate-limiter.service.d.ts +47 -0
- package/lib/rate-limit/mcp-rate-limiter.service.js +248 -0
- package/lib/rate-limit/mcp-rate-limiter.service.js.map +1 -0
- package/lib/registry/bm25.d.ts +12 -0
- package/lib/registry/bm25.js +60 -0
- package/lib/registry/bm25.js.map +1 -0
- package/lib/registry/mcp-tool-execution.service.d.ts +45 -0
- package/lib/registry/mcp-tool-execution.service.js +72 -0
- package/lib/registry/mcp-tool-execution.service.js.map +1 -0
- package/lib/registry/mcp-tool-registry.service.d.ts +89 -0
- package/lib/registry/mcp-tool-registry.service.js +668 -0
- package/lib/registry/mcp-tool-registry.service.js.map +1 -0
- package/lib/registry/mcp-tool-schema.service.d.ts +42 -0
- package/lib/registry/mcp-tool-schema.service.js +229 -0
- package/lib/registry/mcp-tool-schema.service.js.map +1 -0
- package/lib/registry/registry-types.d.ts +32 -0
- package/lib/registry/registry-types.js +3 -0
- package/lib/registry/registry-types.js.map +1 -0
- package/lib/resolve-options.d.ts +7 -0
- package/lib/resolve-options.js +85 -0
- package/lib/resolve-options.js.map +1 -0
- package/lib/shared/endpoint-paths.d.ts +8 -0
- package/lib/shared/endpoint-paths.js +12 -0
- package/lib/shared/endpoint-paths.js.map +1 -0
- package/lib/shared/loopback.d.ts +2 -0
- package/lib/shared/loopback.js +9 -0
- package/lib/shared/loopback.js.map +1 -0
- package/lib/shop-session/mcp-shop-session.service.d.ts +47 -0
- package/lib/shop-session/mcp-shop-session.service.js +132 -0
- package/lib/shop-session/mcp-shop-session.service.js.map +1 -0
- package/lib/tasks/mcp-oauth-retention.task.d.ts +9 -0
- package/lib/tasks/mcp-oauth-retention.task.js +21 -0
- package/lib/tasks/mcp-oauth-retention.task.js.map +1 -0
- package/lib/tasks/mcp-tool-call-log-retention.task.d.ts +7 -0
- package/lib/tasks/mcp-tool-call-log-retention.task.js +22 -0
- package/lib/tasks/mcp-tool-call-log-retention.task.js.map +1 -0
- package/lib/tools/built-in/active-order.service.d.ts +26 -0
- package/lib/tools/built-in/active-order.service.js +125 -0
- package/lib/tools/built-in/active-order.service.js.map +1 -0
- package/lib/tools/built-in/admin/add-customer-to-group.tool.d.ts +23 -0
- package/lib/tools/built-in/admin/add-customer-to-group.tool.js +68 -0
- package/lib/tools/built-in/admin/add-customer-to-group.tool.js.map +1 -0
- package/lib/tools/built-in/admin/add-note-to-order.tool.d.ts +104 -0
- package/lib/tools/built-in/admin/add-note-to-order.tool.js +66 -0
- package/lib/tools/built-in/admin/add-note-to-order.tool.js.map +1 -0
- package/lib/tools/built-in/admin/adjust-stock.tool.d.ts +26 -0
- package/lib/tools/built-in/admin/adjust-stock.tool.js +88 -0
- package/lib/tools/built-in/admin/adjust-stock.tool.js.map +1 -0
- package/lib/tools/built-in/admin/cancel-order.tool.d.ts +17 -0
- package/lib/tools/built-in/admin/cancel-order.tool.js +60 -0
- package/lib/tools/built-in/admin/cancel-order.tool.js.map +1 -0
- package/lib/tools/built-in/admin/channel-access.d.ts +2 -0
- package/lib/tools/built-in/admin/channel-access.js +9 -0
- package/lib/tools/built-in/admin/channel-access.js.map +1 -0
- package/lib/tools/built-in/admin/create-customer.tool.d.ts +41 -0
- package/lib/tools/built-in/admin/create-customer.tool.js +57 -0
- package/lib/tools/built-in/admin/create-customer.tool.js.map +1 -0
- package/lib/tools/built-in/admin/create-fulfillment.tool.d.ts +118 -0
- package/lib/tools/built-in/admin/create-fulfillment.tool.js +156 -0
- package/lib/tools/built-in/admin/create-fulfillment.tool.js.map +1 -0
- package/lib/tools/built-in/admin/create-product.tool.d.ts +52 -0
- package/lib/tools/built-in/admin/create-product.tool.js +61 -0
- package/lib/tools/built-in/admin/create-product.tool.js.map +1 -0
- package/lib/tools/built-in/admin/create-variant.tool.d.ts +48 -0
- package/lib/tools/built-in/admin/create-variant.tool.js +79 -0
- package/lib/tools/built-in/admin/create-variant.tool.js.map +1 -0
- package/lib/tools/built-in/admin/entity-field-schemas.d.ts +36 -0
- package/lib/tools/built-in/admin/entity-field-schemas.js +63 -0
- package/lib/tools/built-in/admin/entity-field-schemas.js.map +1 -0
- package/lib/tools/built-in/admin/get-customer.tool.d.ts +28 -0
- package/lib/tools/built-in/admin/get-customer.tool.js +55 -0
- package/lib/tools/built-in/admin/get-customer.tool.js.map +1 -0
- package/lib/tools/built-in/admin/get-order.tool.d.ts +100 -0
- package/lib/tools/built-in/admin/get-order.tool.js +68 -0
- package/lib/tools/built-in/admin/get-order.tool.js.map +1 -0
- package/lib/tools/built-in/admin/get-product.tool.d.ts +69 -0
- package/lib/tools/built-in/admin/get-product.tool.js +77 -0
- package/lib/tools/built-in/admin/get-product.tool.js.map +1 -0
- package/lib/tools/built-in/admin/get-stock-levels.tool.d.ts +23 -0
- package/lib/tools/built-in/admin/get-stock-levels.tool.js +61 -0
- package/lib/tools/built-in/admin/get-stock-levels.tool.js.map +1 -0
- package/lib/tools/built-in/admin/index.d.ts +25 -0
- package/lib/tools/built-in/admin/index.js +54 -0
- package/lib/tools/built-in/admin/index.js.map +1 -0
- package/lib/tools/built-in/admin/list-channels.tool.d.ts +24 -0
- package/lib/tools/built-in/admin/list-channels.tool.js +56 -0
- package/lib/tools/built-in/admin/list-channels.tool.js.map +1 -0
- package/lib/tools/built-in/admin/list-customer-groups.tool.d.ts +23 -0
- package/lib/tools/built-in/admin/list-customer-groups.tool.js +52 -0
- package/lib/tools/built-in/admin/list-customer-groups.tool.js.map +1 -0
- package/lib/tools/built-in/admin/list-customers.tool.d.ts +62 -0
- package/lib/tools/built-in/admin/list-customers.tool.js +66 -0
- package/lib/tools/built-in/admin/list-customers.tool.js.map +1 -0
- package/lib/tools/built-in/admin/list-orders.tool.d.ts +142 -0
- package/lib/tools/built-in/admin/list-orders.tool.js +87 -0
- package/lib/tools/built-in/admin/list-orders.tool.js.map +1 -0
- package/lib/tools/built-in/admin/list-products.tool.d.ts +63 -0
- package/lib/tools/built-in/admin/list-products.tool.js +71 -0
- package/lib/tools/built-in/admin/list-products.tool.js.map +1 -0
- package/lib/tools/built-in/admin/refund-order.tool.d.ts +38 -0
- package/lib/tools/built-in/admin/refund-order.tool.js +115 -0
- package/lib/tools/built-in/admin/refund-order.tool.js.map +1 -0
- package/lib/tools/built-in/admin/set-active-channel.tool.d.ts +22 -0
- package/lib/tools/built-in/admin/set-active-channel.tool.js +84 -0
- package/lib/tools/built-in/admin/set-active-channel.tool.js.map +1 -0
- package/lib/tools/built-in/admin/translation-schemas.d.ts +12 -0
- package/lib/tools/built-in/admin/translation-schemas.js +17 -0
- package/lib/tools/built-in/admin/translation-schemas.js.map +1 -0
- package/lib/tools/built-in/admin/update-customer.tool.d.ts +42 -0
- package/lib/tools/built-in/admin/update-customer.tool.js +59 -0
- package/lib/tools/built-in/admin/update-customer.tool.js.map +1 -0
- package/lib/tools/built-in/admin/update-order-state.tool.d.ts +16 -0
- package/lib/tools/built-in/admin/update-order-state.tool.js +58 -0
- package/lib/tools/built-in/admin/update-order-state.tool.js.map +1 -0
- package/lib/tools/built-in/admin/update-product.tool.d.ts +53 -0
- package/lib/tools/built-in/admin/update-product.tool.js +68 -0
- package/lib/tools/built-in/admin/update-product.tool.js.map +1 -0
- package/lib/tools/built-in/admin/update-variant.tool.d.ts +46 -0
- package/lib/tools/built-in/admin/update-variant.tool.js +77 -0
- package/lib/tools/built-in/admin/update-variant.tool.js.map +1 -0
- package/lib/tools/built-in/admin/upload-asset.tool.d.ts +32 -0
- package/lib/tools/built-in/admin/upload-asset.tool.js +56 -0
- package/lib/tools/built-in/admin/upload-asset.tool.js.map +1 -0
- package/lib/tools/built-in/catalog-query.service.d.ts +21 -0
- package/lib/tools/built-in/catalog-query.service.js +128 -0
- package/lib/tools/built-in/catalog-query.service.js.map +1 -0
- package/lib/tools/built-in/custom-field-input.service.d.ts +10 -0
- package/lib/tools/built-in/custom-field-input.service.js +64 -0
- package/lib/tools/built-in/custom-field-input.service.js.map +1 -0
- package/lib/tools/built-in/email-schema.d.ts +2 -0
- package/lib/tools/built-in/email-schema.js +12 -0
- package/lib/tools/built-in/email-schema.js.map +1 -0
- package/lib/tools/built-in/id-schema.d.ts +3 -0
- package/lib/tools/built-in/id-schema.js +11 -0
- package/lib/tools/built-in/id-schema.js.map +1 -0
- package/lib/tools/built-in/int32-schema.d.ts +4 -0
- package/lib/tools/built-in/int32-schema.js +8 -0
- package/lib/tools/built-in/int32-schema.js.map +1 -0
- package/lib/tools/built-in/list-helpers.d.ts +48 -0
- package/lib/tools/built-in/list-helpers.js +76 -0
- package/lib/tools/built-in/list-helpers.js.map +1 -0
- package/lib/tools/built-in/order-list-helpers.d.ts +20 -0
- package/lib/tools/built-in/order-list-helpers.js +48 -0
- package/lib/tools/built-in/order-list-helpers.js.map +1 -0
- package/lib/tools/built-in/providers.d.ts +2 -0
- package/lib/tools/built-in/providers.js +7 -0
- package/lib/tools/built-in/providers.js.map +1 -0
- package/lib/tools/built-in/remote-asset.d.ts +4 -0
- package/lib/tools/built-in/remote-asset.js +54 -0
- package/lib/tools/built-in/remote-asset.js.map +1 -0
- package/lib/tools/built-in/serializer.service.d.ts +327 -0
- package/lib/tools/built-in/serializer.service.js +413 -0
- package/lib/tools/built-in/serializer.service.js.map +1 -0
- package/lib/tools/built-in/shop/add-to-cart.tool.d.ts +21 -0
- package/lib/tools/built-in/shop/add-to-cart.tool.js +100 -0
- package/lib/tools/built-in/shop/add-to-cart.tool.js.map +1 -0
- package/lib/tools/built-in/shop/address-schema.d.ts +15 -0
- package/lib/tools/built-in/shop/address-schema.js +20 -0
- package/lib/tools/built-in/shop/address-schema.js.map +1 -0
- package/lib/tools/built-in/shop/apply-coupon-code.tool.d.ts +17 -0
- package/lib/tools/built-in/shop/apply-coupon-code.tool.js +62 -0
- package/lib/tools/built-in/shop/apply-coupon-code.tool.js.map +1 -0
- package/lib/tools/built-in/shop/collection-lookup.d.ts +15 -0
- package/lib/tools/built-in/shop/collection-lookup.js +35 -0
- package/lib/tools/built-in/shop/collection-lookup.js.map +1 -0
- package/lib/tools/built-in/shop/get-cart.tool.d.ts +94 -0
- package/lib/tools/built-in/shop/get-cart.tool.js +55 -0
- package/lib/tools/built-in/shop/get-cart.tool.js.map +1 -0
- package/lib/tools/built-in/shop/get-collection.tool.d.ts +42 -0
- package/lib/tools/built-in/shop/get-collection.tool.js +64 -0
- package/lib/tools/built-in/shop/get-collection.tool.js.map +1 -0
- package/lib/tools/built-in/shop/get-eligible-payment-methods.tool.d.ts +26 -0
- package/lib/tools/built-in/shop/get-eligible-payment-methods.tool.js +58 -0
- package/lib/tools/built-in/shop/get-eligible-payment-methods.tool.js.map +1 -0
- package/lib/tools/built-in/shop/get-eligible-shipping-methods.tool.d.ts +30 -0
- package/lib/tools/built-in/shop/get-eligible-shipping-methods.tool.js +59 -0
- package/lib/tools/built-in/shop/get-eligible-shipping-methods.tool.js.map +1 -0
- package/lib/tools/built-in/shop/get-my-account.tool.d.ts +22 -0
- package/lib/tools/built-in/shop/get-my-account.tool.js +57 -0
- package/lib/tools/built-in/shop/get-my-account.tool.js.map +1 -0
- package/lib/tools/built-in/shop/get-order.tool.d.ts +100 -0
- package/lib/tools/built-in/shop/get-order.tool.js +67 -0
- package/lib/tools/built-in/shop/get-order.tool.js.map +1 -0
- package/lib/tools/built-in/shop/get-product.tool.d.ts +57 -0
- package/lib/tools/built-in/shop/get-product.tool.js +81 -0
- package/lib/tools/built-in/shop/get-product.tool.js.map +1 -0
- package/lib/tools/built-in/shop/index.d.ts +19 -0
- package/lib/tools/built-in/shop/index.js +42 -0
- package/lib/tools/built-in/shop/index.js.map +1 -0
- package/lib/tools/built-in/shop/list-collections.tool.d.ts +42 -0
- package/lib/tools/built-in/shop/list-collections.tool.js +75 -0
- package/lib/tools/built-in/shop/list-collections.tool.js.map +1 -0
- package/lib/tools/built-in/shop/list-my-orders.tool.d.ts +100 -0
- package/lib/tools/built-in/shop/list-my-orders.tool.js +63 -0
- package/lib/tools/built-in/shop/list-my-orders.tool.js.map +1 -0
- package/lib/tools/built-in/shop/place-order.tool.d.ts +188 -0
- package/lib/tools/built-in/shop/place-order.tool.js +152 -0
- package/lib/tools/built-in/shop/place-order.tool.js.map +1 -0
- package/lib/tools/built-in/shop/product-search-query.d.ts +4 -0
- package/lib/tools/built-in/shop/product-search-query.js +34 -0
- package/lib/tools/built-in/shop/product-search-query.js.map +1 -0
- package/lib/tools/built-in/shop/remove-coupon-code.tool.d.ts +17 -0
- package/lib/tools/built-in/shop/remove-coupon-code.tool.js +63 -0
- package/lib/tools/built-in/shop/remove-coupon-code.tool.js.map +1 -0
- package/lib/tools/built-in/shop/remove-from-cart.tool.d.ts +17 -0
- package/lib/tools/built-in/shop/remove-from-cart.tool.js +58 -0
- package/lib/tools/built-in/shop/remove-from-cart.tool.js.map +1 -0
- package/lib/tools/built-in/shop/search-products.tool.d.ts +48 -0
- package/lib/tools/built-in/shop/search-products.tool.js +95 -0
- package/lib/tools/built-in/shop/search-products.tool.js.map +1 -0
- package/lib/tools/built-in/shop/set-checkout-details.tool.d.ts +56 -0
- package/lib/tools/built-in/shop/set-checkout-details.tool.js +187 -0
- package/lib/tools/built-in/shop/set-checkout-details.tool.js.map +1 -0
- package/lib/tools/built-in/shop/set-shipping-method.tool.d.ts +17 -0
- package/lib/tools/built-in/shop/set-shipping-method.tool.js +58 -0
- package/lib/tools/built-in/shop/set-shipping-method.tool.js.map +1 -0
- package/lib/tools/built-in/shop/update-cart-line.tool.d.ts +18 -0
- package/lib/tools/built-in/shop/update-cart-line.tool.js +60 -0
- package/lib/tools/built-in/shop/update-cart-line.tool.js.map +1 -0
- package/lib/tools/built-in/string-schemas.d.ts +4 -0
- package/lib/tools/built-in/string-schemas.js +13 -0
- package/lib/tools/built-in/string-schemas.js.map +1 -0
- package/lib/transport/mcp-server.factory.d.ts +13 -0
- package/lib/transport/mcp-server.factory.js +32 -0
- package/lib/transport/mcp-server.factory.js.map +1 -0
- package/lib/transport/mcp-transport.controller.d.ts +77 -0
- package/lib/transport/mcp-transport.controller.js +442 -0
- package/lib/transport/mcp-transport.controller.js.map +1 -0
- package/lib/types.d.ts +432 -0
- package/lib/types.js +3 -0
- package/lib/types.js.map +1 -0
- package/package.json +42 -0
- package/src/dashboard/components/activity-block.tsx +72 -0
- package/src/dashboard/components/actor-cell.tsx +31 -0
- package/src/dashboard/components/connection-dialog.tsx +106 -0
- package/src/dashboard/components/empty-cell.tsx +7 -0
- package/src/dashboard/components/grants-block.tsx +218 -0
- package/src/dashboard/components/stats-block.tsx +275 -0
- package/src/dashboard/components/tools-block.tsx +274 -0
- package/src/dashboard/components/tooltip-button.tsx +28 -0
- package/src/dashboard/components/use-mcp-table-state.ts +47 -0
- package/src/dashboard/i18n/ar.po +311 -0
- package/src/dashboard/i18n/bg.po +311 -0
- package/src/dashboard/i18n/cs.po +311 -0
- package/src/dashboard/i18n/de.po +311 -0
- package/src/dashboard/i18n/en.po +311 -0
- package/src/dashboard/i18n/es.po +311 -0
- package/src/dashboard/i18n/fa.po +311 -0
- package/src/dashboard/i18n/fr.po +311 -0
- package/src/dashboard/i18n/he.po +311 -0
- package/src/dashboard/i18n/hr.po +311 -0
- package/src/dashboard/i18n/hu.po +311 -0
- package/src/dashboard/i18n/it.po +311 -0
- package/src/dashboard/i18n/ja.po +311 -0
- package/src/dashboard/i18n/ko.po +311 -0
- package/src/dashboard/i18n/nb.po +311 -0
- package/src/dashboard/i18n/ne.po +311 -0
- package/src/dashboard/i18n/nl.po +311 -0
- package/src/dashboard/i18n/pl.po +311 -0
- package/src/dashboard/i18n/pt_BR.po +311 -0
- package/src/dashboard/i18n/pt_PT.po +311 -0
- package/src/dashboard/i18n/ro.po +311 -0
- package/src/dashboard/i18n/ru.po +311 -0
- package/src/dashboard/i18n/sv.po +311 -0
- package/src/dashboard/i18n/tr.po +311 -0
- package/src/dashboard/i18n/uk.po +311 -0
- package/src/dashboard/i18n/uz.po +311 -0
- package/src/dashboard/i18n/zh_Hans.po +311 -0
- package/src/dashboard/i18n/zh_Hant.po +311 -0
- package/src/dashboard/index.tsx +30 -0
- package/src/dashboard/mcp-activity-route.tsx +38 -0
- package/src/dashboard/mcp-authorize-route.tsx +369 -0
- package/src/dashboard/mcp-grants-route.tsx +38 -0
- package/src/dashboard/mcp-overview-route.tsx +46 -0
- package/src/dashboard/mcp-server-redirect-route.tsx +15 -0
- package/src/dashboard/mcp-tools-route.tsx +38 -0
- package/src/dashboard/mcp.graphql.ts +127 -0
- package/src/dashboard/published-files.spec.ts +54 -0
- package/src/dashboard/tsconfig.json +9 -0
- package/src/shared/endpoint-paths.ts +8 -0
- package/src/shared/loopback.ts +6 -0
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
15
|
+
var t = {};
|
|
16
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
17
|
+
t[p] = s[p];
|
|
18
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
19
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
20
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
21
|
+
t[p[i]] = s[p[i]];
|
|
22
|
+
}
|
|
23
|
+
return t;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.McpToolRegistryService = void 0;
|
|
27
|
+
const common_1 = require("@nestjs/common");
|
|
28
|
+
const core_1 = require("@nestjs/core");
|
|
29
|
+
const core_2 = require("@vendure/core");
|
|
30
|
+
const mcp_sdk_1 = require("@vendure/mcp-sdk");
|
|
31
|
+
const constants_1 = require("../constants");
|
|
32
|
+
const mcp_tool_call_log_service_1 = require("../logging/mcp-tool-call-log.service");
|
|
33
|
+
const mcp_rate_limiter_service_1 = require("../rate-limit/mcp-rate-limiter.service");
|
|
34
|
+
const mcp_shop_session_service_1 = require("../shop-session/mcp-shop-session.service");
|
|
35
|
+
const bm25_1 = require("./bm25");
|
|
36
|
+
const mcp_tool_schema_service_1 = require("./mcp-tool-schema.service");
|
|
37
|
+
/** Discovery meta-tool names — reserved so user tools cannot collide with them. */
|
|
38
|
+
const SEARCH_TOOLS = 'search_tools';
|
|
39
|
+
const EXECUTE_TOOL = 'execute_tool';
|
|
40
|
+
const RESERVED_META_TOOL_NAMES = new Set([SEARCH_TOOLS, EXECUTE_TOOL]);
|
|
41
|
+
const ALL_TOOLSETS = ['shop', 'admin'];
|
|
42
|
+
// Also stated in the no-results hint and the meta-tool's schema description; keep all three in sync.
|
|
43
|
+
const SEARCH_DEFAULT_LIMIT = 10;
|
|
44
|
+
const SEARCH_MAX_LIMIT = 50;
|
|
45
|
+
// Error types a tool throws on purpose, with a message meant to be read by the caller. Anything
|
|
46
|
+
// else is treated as an internal failure: logged server-side, and the caller gets a generic
|
|
47
|
+
// message instead.
|
|
48
|
+
const CALLER_SAFE_ERROR_TYPES = [
|
|
49
|
+
core_2.UserInputError,
|
|
50
|
+
core_2.IllegalOperationError,
|
|
51
|
+
core_2.EntityNotFoundError,
|
|
52
|
+
core_2.ForbiddenError,
|
|
53
|
+
core_2.UnauthorizedError,
|
|
54
|
+
];
|
|
55
|
+
const GENERIC_TOOL_ERROR_MESSAGE = 'The tool failed unexpectedly. This is a server-side fault, not a problem with your ' +
|
|
56
|
+
'arguments. Do not retry with different arguments; tell the user the operation could not ' +
|
|
57
|
+
'be completed.';
|
|
58
|
+
// Largest serialized result text a tool may return, in bytes. 100 KB is roughly 25,000 tokens,
|
|
59
|
+
// which is the cap Claude Code applies to a tool response before it truncates the text.
|
|
60
|
+
const MAX_RESULT_BYTES = 100000;
|
|
61
|
+
// The arguments a caller can use to ask for less, and how the size error tells them to. Only the
|
|
62
|
+
// ones a tool actually declares are mentioned, so the advice is always something they can do.
|
|
63
|
+
const NARROWING_ARGUMENT_ADVICE = {
|
|
64
|
+
limit: 'lower "limit"',
|
|
65
|
+
offset: 'page with "offset"',
|
|
66
|
+
filter: 'add a "filter"',
|
|
67
|
+
query: 'narrow the "query"',
|
|
68
|
+
};
|
|
69
|
+
// Enforce SEP-986 because some MCP clients reject non-conforming tool names.
|
|
70
|
+
const TOOL_NAME_PATTERN = /^[A-Za-z0-9._-]{1,128}$/;
|
|
71
|
+
/**
|
|
72
|
+
* @description
|
|
73
|
+
* Single source of truth for discovered `@McpTool` providers. It discovers tools at bootstrap,
|
|
74
|
+
* compiles their schemas once, and owns visibility, toggles, behavior,
|
|
75
|
+
* permissions, and execution.
|
|
76
|
+
*/
|
|
77
|
+
let McpToolRegistryService = class McpToolRegistryService {
|
|
78
|
+
constructor(discoveryService, settingsStoreService, rateLimiter, toolCallLog, toolSchema, shopSession, configService, connection, options) {
|
|
79
|
+
this.discoveryService = discoveryService;
|
|
80
|
+
this.settingsStoreService = settingsStoreService;
|
|
81
|
+
this.rateLimiter = rateLimiter;
|
|
82
|
+
this.toolCallLog = toolCallLog;
|
|
83
|
+
this.toolSchema = toolSchema;
|
|
84
|
+
this.shopSession = shopSession;
|
|
85
|
+
this.configService = configService;
|
|
86
|
+
this.connection = connection;
|
|
87
|
+
this.options = options;
|
|
88
|
+
this.tools = new Map();
|
|
89
|
+
this.discoveryMetaTools = [];
|
|
90
|
+
this.bm25 = new Map();
|
|
91
|
+
this.toggleCache = new WeakMap();
|
|
92
|
+
}
|
|
93
|
+
/** @internal */
|
|
94
|
+
onApplicationBootstrap() {
|
|
95
|
+
this.discoverTools();
|
|
96
|
+
this.discoveryMetaTools = this.buildDiscoveryMetaTools();
|
|
97
|
+
this.bm25 = this.buildSearchIndexes();
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Every registered tool. Consumed by the admin API.
|
|
101
|
+
*
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
getRegistrySnapshot() {
|
|
105
|
+
return [...this.tools.values()];
|
|
106
|
+
}
|
|
107
|
+
/** @internal */
|
|
108
|
+
async getExposedTools(executionContext, toolset) {
|
|
109
|
+
if (this.options.toolExposure === 'discovery') {
|
|
110
|
+
return this.discoveryMetaTools;
|
|
111
|
+
}
|
|
112
|
+
return this.visibleTools(executionContext.ctx, toolset);
|
|
113
|
+
}
|
|
114
|
+
async callTool(executionContext, toolset, name, input) {
|
|
115
|
+
if (this.options.toolExposure === 'discovery') {
|
|
116
|
+
if (name === SEARCH_TOOLS) {
|
|
117
|
+
return this.searchTools(executionContext, toolset, input);
|
|
118
|
+
}
|
|
119
|
+
if (name === EXECUTE_TOOL) {
|
|
120
|
+
// The SDK validated only the envelope, so the tool's own arguments are validated here.
|
|
121
|
+
const { name: innerName, arguments: args } = input;
|
|
122
|
+
return this.callRegisteredTool(executionContext, toolset, innerName, args !== null && args !== void 0 ? args : {}, {
|
|
123
|
+
validateInput: true,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return this.callRegisteredTool(executionContext, toolset, name, input, { validateInput: false });
|
|
128
|
+
}
|
|
129
|
+
async getCallableTools(ctx, toolset) {
|
|
130
|
+
return (await this.visibleTools(ctx, toolset)).map(tool => this.toolSummary(tool));
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Skips the meta-tool routing in {@link callTool}, since a caller using this already knows which tool it wants.
|
|
134
|
+
*
|
|
135
|
+
* @internal
|
|
136
|
+
*/
|
|
137
|
+
callToolDirect(executionContext, toolset, name, input) {
|
|
138
|
+
return this.callRegisteredTool(executionContext, toolset, name, input, { validateInput: true });
|
|
139
|
+
}
|
|
140
|
+
async getToolToggles(ctx) {
|
|
141
|
+
var _a;
|
|
142
|
+
const cached = this.toggleCache.get(ctx);
|
|
143
|
+
if (cached) {
|
|
144
|
+
return cached;
|
|
145
|
+
}
|
|
146
|
+
const toggles = (_a = (await this.settingsStoreService.get(ctx, constants_1.MCP_TOOL_TOGGLES_STORE_KEY))) !== null && _a !== void 0 ? _a : {};
|
|
147
|
+
this.toggleCache.set(ctx, toggles);
|
|
148
|
+
return toggles;
|
|
149
|
+
}
|
|
150
|
+
/** @internal */
|
|
151
|
+
isToolEnabled(tool, toggles) {
|
|
152
|
+
return toggles[this.toolKey(tool.toolset, tool.name)] !== false;
|
|
153
|
+
}
|
|
154
|
+
async setToolEnabled(ctx, toolset, name, enabled) {
|
|
155
|
+
var _a;
|
|
156
|
+
const key = this.toolKey(toolset, name);
|
|
157
|
+
const current = await this.getToolToggles(ctx);
|
|
158
|
+
// Built as a copy so a refused write leaves the cached toggles as they were.
|
|
159
|
+
const updated = Object.assign(Object.assign({}, current), { [key]: enabled });
|
|
160
|
+
const saved = await this.settingsStoreService.set(ctx, constants_1.MCP_TOOL_TOGGLES_STORE_KEY, updated);
|
|
161
|
+
if (!saved.result) {
|
|
162
|
+
throw new Error(`Could not save the MCP tool toggle for "${key}": ` +
|
|
163
|
+
`${(_a = saved.error) !== null && _a !== void 0 ? _a : 'the settings store refused the write'}`);
|
|
164
|
+
}
|
|
165
|
+
this.toggleCache = new WeakMap();
|
|
166
|
+
this.toggleCache.set(ctx, updated);
|
|
167
|
+
}
|
|
168
|
+
// Also the persisted key in the tool-toggle settings map, so changing the format orphans stored toggles.
|
|
169
|
+
toolKey(toolset, name) {
|
|
170
|
+
return `${toolset}:${name}`;
|
|
171
|
+
}
|
|
172
|
+
discoverTools() {
|
|
173
|
+
var _a;
|
|
174
|
+
this.tools.clear();
|
|
175
|
+
for (const wrapper of this.discoveryService.getProviders()) {
|
|
176
|
+
const metadata = this.discoveryService.getMetadataByDecorator(mcp_sdk_1.McpTool, wrapper);
|
|
177
|
+
const instance = wrapper.instance;
|
|
178
|
+
if (!metadata || !instance) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (!this.isToolHandler(instance)) {
|
|
182
|
+
throw new Error(`MCP tool provider ${String((_a = wrapper.name) !== null && _a !== void 0 ? _a : metadata.name)} must implement execute()`);
|
|
183
|
+
}
|
|
184
|
+
const entry = this.buildRegisteredTool(metadata, instance, this.getPluginSource(wrapper));
|
|
185
|
+
this.registerTool(entry);
|
|
186
|
+
}
|
|
187
|
+
core_2.Logger.info(`Discovered ${this.tools.size} MCP tools`, constants_1.loggerCtx);
|
|
188
|
+
}
|
|
189
|
+
isToolHandler(instance) {
|
|
190
|
+
return typeof instance.execute === 'function';
|
|
191
|
+
}
|
|
192
|
+
buildRegisteredTool(metadata, handler, pluginSource) {
|
|
193
|
+
var _a;
|
|
194
|
+
this.assertValidToolMetadata(metadata);
|
|
195
|
+
const resolvedBehavior = (_a = metadata.behavior) !== null && _a !== void 0 ? _a : 'mutating';
|
|
196
|
+
const acceptsSessionToken = this.acceptsSessionToken(metadata);
|
|
197
|
+
const schemas = this.toolSchema.prepareToolSchemas({
|
|
198
|
+
toolName: metadata.name,
|
|
199
|
+
pluginSource,
|
|
200
|
+
inputSchema: metadata.inputSchema,
|
|
201
|
+
outputSchema: metadata.outputSchema,
|
|
202
|
+
injectedFields: {
|
|
203
|
+
confirm: resolvedBehavior === 'destructive',
|
|
204
|
+
sessionToken: acceptsSessionToken,
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
return Object.assign(Object.assign(Object.assign({}, metadata), { handler,
|
|
208
|
+
pluginSource,
|
|
209
|
+
resolvedBehavior,
|
|
210
|
+
acceptsSessionToken, annotations: this.deriveAnnotations(metadata, resolvedBehavior) }), schemas);
|
|
211
|
+
}
|
|
212
|
+
assertValidToolMetadata(metadata) {
|
|
213
|
+
var _a, _b, _c;
|
|
214
|
+
if (typeof metadata.name !== 'string' || !TOOL_NAME_PATTERN.test(metadata.name)) {
|
|
215
|
+
throw new Error(`MCP tool name "${String(metadata.name)}" must contain 1–128 letters, digits, ` +
|
|
216
|
+
`periods, hyphens, or underscores.`);
|
|
217
|
+
}
|
|
218
|
+
for (const permission of (_a = metadata.permissions) !== null && _a !== void 0 ? _a : []) {
|
|
219
|
+
if (permission === core_2.Permission.Owner) {
|
|
220
|
+
throw new Error(`MCP tool "${metadata.name}" declares Permission.Owner, which no MCP caller can ` +
|
|
221
|
+
`satisfy. Use Permission.Authenticated and check ownership inside the tool.`);
|
|
222
|
+
}
|
|
223
|
+
if (!this.getKnownPermissions().has(permission)) {
|
|
224
|
+
throw new Error(`MCP tool "${metadata.name}" declares unknown permission "${permission}". ` +
|
|
225
|
+
`Register it in authOptions.customPermissions.`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (metadata.usesActiveOrder && metadata.toolset !== 'shop') {
|
|
229
|
+
throw new Error(`MCP tool "${metadata.name}" usesActiveOrder, which is only valid on a shop tool.`);
|
|
230
|
+
}
|
|
231
|
+
if (metadata.toolset === 'admin' && ((_c = (_b = metadata.permissions) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) === 0) {
|
|
232
|
+
throw new Error(`Admin MCP tool "${metadata.name}" declares no permissions. Declare the permissions ` +
|
|
233
|
+
`required to call it, e.g. permissions: [Permission.Authenticated] if any administrator ` +
|
|
234
|
+
`may call it.`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
getKnownPermissions() {
|
|
238
|
+
if (!this.knownPermissions) {
|
|
239
|
+
this.knownPermissions = new Set([
|
|
240
|
+
...Object.values(core_2.Permission),
|
|
241
|
+
...this.configService.authOptions.customPermissions.flatMap(definition => definition.getMetadata().map(metadata => metadata.name)),
|
|
242
|
+
]);
|
|
243
|
+
}
|
|
244
|
+
return this.knownPermissions;
|
|
245
|
+
}
|
|
246
|
+
registerTool(tool) {
|
|
247
|
+
if (RESERVED_META_TOOL_NAMES.has(tool.name)) {
|
|
248
|
+
throw new Error(`MCP tool name "${tool.name}" is reserved for discovery`);
|
|
249
|
+
}
|
|
250
|
+
const key = this.toolKey(tool.toolset, tool.name);
|
|
251
|
+
const existing = this.tools.get(key);
|
|
252
|
+
if (existing) {
|
|
253
|
+
throw new Error(`Duplicate MCP tool name "${tool.name}" (toolset "${tool.toolset}") from ` +
|
|
254
|
+
`${existing.pluginSource} and ${tool.pluginSource}`);
|
|
255
|
+
}
|
|
256
|
+
this.tools.set(key, tool);
|
|
257
|
+
}
|
|
258
|
+
async callRegisteredTool(executionContext, toolset, name, input, options) {
|
|
259
|
+
const admission = await this.admitToolCall(executionContext, toolset, name, input, options);
|
|
260
|
+
if (admission.kind === 'refused') {
|
|
261
|
+
return admission.result;
|
|
262
|
+
}
|
|
263
|
+
const { tool } = admission;
|
|
264
|
+
// A destructive tool called without `confirm: true` only describes what it would do.
|
|
265
|
+
const isConfirmationPreview = tool.resolvedBehavior === 'destructive' && admission.input.confirm !== true;
|
|
266
|
+
const session = await this.resolveShopSession(executionContext, tool, admission.input, isConfirmationPreview);
|
|
267
|
+
if (session.kind === 'refused') {
|
|
268
|
+
return session.result;
|
|
269
|
+
}
|
|
270
|
+
const { callContext, sessionToken } = session;
|
|
271
|
+
// The preview carries the token too, so the confirming call can act on the same cart.
|
|
272
|
+
if (isConfirmationPreview) {
|
|
273
|
+
return this.confirmationRequiredResult(tool, sessionToken);
|
|
274
|
+
}
|
|
275
|
+
let toolInput = session.input;
|
|
276
|
+
if (tool.resolvedBehavior === 'destructive') {
|
|
277
|
+
const { confirm } = toolInput, rest = __rest(toolInput, ["confirm"]);
|
|
278
|
+
toolInput = rest;
|
|
279
|
+
}
|
|
280
|
+
const startedAt = Date.now();
|
|
281
|
+
try {
|
|
282
|
+
const output = await this.runToolHandler(tool, callContext, toolInput);
|
|
283
|
+
return await this.buildToolCallResult({
|
|
284
|
+
callContext,
|
|
285
|
+
tool,
|
|
286
|
+
input: toolInput,
|
|
287
|
+
output,
|
|
288
|
+
startedAt,
|
|
289
|
+
sessionToken,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
catch (e) {
|
|
293
|
+
return await this.handleToolCallError({
|
|
294
|
+
error: e,
|
|
295
|
+
callContext,
|
|
296
|
+
tool,
|
|
297
|
+
input: toolInput,
|
|
298
|
+
startedAt,
|
|
299
|
+
sessionToken,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// The prepared input no longer contains the sessionToken credential, so logs do not either.
|
|
304
|
+
async resolveShopSession(executionContext, tool, input, isConfirmationPreview) {
|
|
305
|
+
if (!tool.acceptsSessionToken) {
|
|
306
|
+
return { kind: 'ready', callContext: executionContext, input, sessionToken: undefined };
|
|
307
|
+
}
|
|
308
|
+
const prepared = await this.shopSession.prepareToolCall({
|
|
309
|
+
ctx: executionContext.ctx,
|
|
310
|
+
input,
|
|
311
|
+
isOAuthCall: executionContext.grant != null,
|
|
312
|
+
// A preview runs no handler, so it must not start a cart of its own.
|
|
313
|
+
toolWritesToCart: tool.resolvedBehavior !== 'readonly' && !isConfirmationPreview,
|
|
314
|
+
});
|
|
315
|
+
if (prepared.kind === 'refused') {
|
|
316
|
+
return { kind: 'refused', result: this.errorResult(prepared.message) };
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
kind: 'ready',
|
|
320
|
+
// A copy, not a write-back, since the transport reuses one execution context across a batch.
|
|
321
|
+
callContext: Object.assign(Object.assign({}, executionContext), { ctx: prepared.ctx }),
|
|
322
|
+
input: prepared.input,
|
|
323
|
+
sessionToken: prepared.sessionToken,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
// A writing tool runs in one transaction, so a throw rolls back all its writes.
|
|
327
|
+
async runToolHandler(tool, callContext, toolInput) {
|
|
328
|
+
if (tool.resolvedBehavior === 'readonly') {
|
|
329
|
+
return tool.handler.execute(callContext.ctx, toolInput, this.toCallerInfo(callContext));
|
|
330
|
+
}
|
|
331
|
+
// withTransaction needs a promise; some handlers return a plain value.
|
|
332
|
+
return this.connection.withTransaction(callContext.ctx, txCtx => Promise.resolve(tool.handler.execute(txCtx, toolInput, this.toCallerInfo(callContext))));
|
|
333
|
+
}
|
|
334
|
+
async handleToolCallError(call) {
|
|
335
|
+
const { error, callContext, tool, input, startedAt, sessionToken } = call;
|
|
336
|
+
const message = error instanceof Error ? error.message : 'MCP tool failed';
|
|
337
|
+
const callerSafe = CALLER_SAFE_ERROR_TYPES.some(ErrorType => error instanceof ErrorType);
|
|
338
|
+
const callerMessage = callerSafe && error instanceof core_2.I18nError
|
|
339
|
+
? callContext.ctx.translate(error.message, error.variables)
|
|
340
|
+
: message;
|
|
341
|
+
if (!callerSafe) {
|
|
342
|
+
core_2.Logger.error(`MCP tool "${tool.name}" failed: ${message}`, constants_1.loggerCtx, error instanceof Error ? error.stack : undefined);
|
|
343
|
+
}
|
|
344
|
+
await this.toolCallLog.logToolCall({
|
|
345
|
+
executionContext: callContext,
|
|
346
|
+
tool,
|
|
347
|
+
input,
|
|
348
|
+
output: { message },
|
|
349
|
+
durationMs: Date.now() - startedAt,
|
|
350
|
+
status: 'error',
|
|
351
|
+
});
|
|
352
|
+
return this.errorResult(callerSafe ? callerMessage : GENERIC_TOOL_ERROR_MESSAGE, sessionToken);
|
|
353
|
+
}
|
|
354
|
+
async admitToolCall(executionContext, toolset, name, input, options) {
|
|
355
|
+
var _a;
|
|
356
|
+
const ctx = executionContext.ctx;
|
|
357
|
+
const rateLimited = await this.rateLimiter.checkRateLimit({
|
|
358
|
+
executionContext,
|
|
359
|
+
endpoint: toolset,
|
|
360
|
+
subject: name,
|
|
361
|
+
});
|
|
362
|
+
if (rateLimited) {
|
|
363
|
+
return { kind: 'refused', result: this.errorResult(rateLimited.message) };
|
|
364
|
+
}
|
|
365
|
+
const tool = this.tools.get(this.toolKey(toolset, name));
|
|
366
|
+
if (!tool) {
|
|
367
|
+
return { kind: 'refused', result: this.errorResult(`Unknown MCP tool: ${name}`) };
|
|
368
|
+
}
|
|
369
|
+
const toggles = await this.getToolToggles(ctx);
|
|
370
|
+
if (!this.isToolEnabled(tool, toggles)) {
|
|
371
|
+
return { kind: 'refused', result: this.errorResult(`MCP tool is disabled: ${name}`) };
|
|
372
|
+
}
|
|
373
|
+
if (!this.hasPermissions(ctx, tool)) {
|
|
374
|
+
return {
|
|
375
|
+
kind: 'refused',
|
|
376
|
+
result: this.errorResult(`You do not have permission to call MCP tool: ${name}`),
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
let toolInput = (input !== null && input !== void 0 ? input : {});
|
|
380
|
+
if (options.validateInput) {
|
|
381
|
+
const validated = await this.toolSchema.validate(tool.compiledInputSchema, toolInput);
|
|
382
|
+
if (!validated.ok) {
|
|
383
|
+
return {
|
|
384
|
+
kind: 'refused',
|
|
385
|
+
result: this.errorResult(`Invalid arguments for tool "${name}": ${validated.message}`),
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
toolInput = ((_a = validated.value) !== null && _a !== void 0 ? _a : {});
|
|
389
|
+
}
|
|
390
|
+
return { kind: 'admitted', tool, input: toolInput };
|
|
391
|
+
}
|
|
392
|
+
async buildToolCallResult(call) {
|
|
393
|
+
const { callContext, tool, input: toolInput, output, startedAt, sessionToken: sessionTokenForResult, } = call;
|
|
394
|
+
if ((0, core_2.isGraphQlErrorResult)(output)) {
|
|
395
|
+
const errorResult = Object.assign({}, output);
|
|
396
|
+
await this.toolCallLog.logToolCall({
|
|
397
|
+
executionContext: callContext,
|
|
398
|
+
tool,
|
|
399
|
+
input: toolInput,
|
|
400
|
+
output: errorResult,
|
|
401
|
+
durationMs: Date.now() - startedAt,
|
|
402
|
+
status: 'error',
|
|
403
|
+
});
|
|
404
|
+
const messageKey = `errorResult.${errorResult.message}`;
|
|
405
|
+
const translated = callContext.ctx.translate(messageKey, errorResult);
|
|
406
|
+
const translatedResult = Object.assign(Object.assign({}, errorResult), { message: translated === messageKey ? errorResult.message : translated });
|
|
407
|
+
return this.vendureErrorResult(this.shopSession.addSessionTokenToResult(translatedResult, sessionTokenForResult));
|
|
408
|
+
}
|
|
409
|
+
if (tool.compiledOutputSchema) {
|
|
410
|
+
const validated = await this.toolSchema.validate(tool.compiledOutputSchema, output);
|
|
411
|
+
if (!validated.ok) {
|
|
412
|
+
core_2.Logger.warn(`MCP tool "${tool.name}" returned output that does not match its schema: ${validated.message}`, constants_1.loggerCtx);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// Serializing before the log row is written so an unserializable value is caught as one error row.
|
|
416
|
+
const result = this.shopSession.addSessionTokenToResult(output, sessionTokenForResult);
|
|
417
|
+
const text = JSON.stringify(result !== null && result !== void 0 ? result : null);
|
|
418
|
+
const bytes = Buffer.byteLength(text, 'utf8');
|
|
419
|
+
const overLimit = bytes > MAX_RESULT_BYTES;
|
|
420
|
+
// An oversized read is a failure; an oversized write already changed the data, so only the result is withheld.
|
|
421
|
+
const refuseAsError = overLimit && tool.resolvedBehavior === 'readonly';
|
|
422
|
+
const refusalMessage = refuseAsError ? this.tooLargeMessage(tool, bytes) : undefined;
|
|
423
|
+
await this.toolCallLog.logToolCall({
|
|
424
|
+
executionContext: callContext,
|
|
425
|
+
tool,
|
|
426
|
+
input: toolInput,
|
|
427
|
+
output: refusalMessage !== undefined ? { message: refusalMessage } : output,
|
|
428
|
+
durationMs: Date.now() - startedAt,
|
|
429
|
+
status: refuseAsError ? 'error' : 'success',
|
|
430
|
+
});
|
|
431
|
+
if (refusalMessage !== undefined) {
|
|
432
|
+
return this.errorResult(refusalMessage, sessionTokenForResult);
|
|
433
|
+
}
|
|
434
|
+
if (overLimit) {
|
|
435
|
+
return this.completedTooLargeResult(tool, bytes, sessionTokenForResult);
|
|
436
|
+
}
|
|
437
|
+
return this.successResult(result, text);
|
|
438
|
+
}
|
|
439
|
+
async searchTools(executionContext, toolset, input) {
|
|
440
|
+
// Unlike execute_tool, search_tools has no target tool to rate-limit downstream, so it is gated here.
|
|
441
|
+
const rateLimited = await this.rateLimiter.checkRateLimit({
|
|
442
|
+
executionContext,
|
|
443
|
+
endpoint: toolset,
|
|
444
|
+
subject: SEARCH_TOOLS,
|
|
445
|
+
});
|
|
446
|
+
if (rateLimited) {
|
|
447
|
+
return this.errorResult(rateLimited.message);
|
|
448
|
+
}
|
|
449
|
+
const params = (input !== null && input !== void 0 ? input : {});
|
|
450
|
+
const query = typeof params.query === 'string' ? params.query.toLowerCase() : '';
|
|
451
|
+
const limit = Math.min(Math.max(typeof params.limit === 'number' ? params.limit : SEARCH_DEFAULT_LIMIT, 1), SEARCH_MAX_LIMIT);
|
|
452
|
+
const tools = await this.visibleTools(executionContext.ctx, toolset);
|
|
453
|
+
const index = this.bm25.get(toolset);
|
|
454
|
+
const matches = tools
|
|
455
|
+
.map(tool => {
|
|
456
|
+
var _a;
|
|
457
|
+
return ({
|
|
458
|
+
tool,
|
|
459
|
+
score: query.length === 0 ? 1 : ((_a = index === null || index === void 0 ? void 0 : index.score(tool.name, query)) !== null && _a !== void 0 ? _a : 0),
|
|
460
|
+
});
|
|
461
|
+
})
|
|
462
|
+
.filter(item => item.score > 0)
|
|
463
|
+
.sort((a, b) => b.score - a.score || a.tool.name.localeCompare(b.tool.name))
|
|
464
|
+
.slice(0, limit)
|
|
465
|
+
.map(item => this.toolSummary(item.tool));
|
|
466
|
+
if (matches.length === 0) {
|
|
467
|
+
return this.successResult({
|
|
468
|
+
tools: [],
|
|
469
|
+
hint: `No ${toolset} tools matched "${query}". ` +
|
|
470
|
+
`Try a broader query, or call search_tools with an empty query to list tools by name ` +
|
|
471
|
+
`(capped at limit — default ${SEARCH_DEFAULT_LIMIT}, maximum ${SEARCH_MAX_LIMIT}, ` +
|
|
472
|
+
`so raise limit to see more).`,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
return this.successResult({ tools: matches });
|
|
476
|
+
}
|
|
477
|
+
toolSummary(tool) {
|
|
478
|
+
return {
|
|
479
|
+
name: tool.name,
|
|
480
|
+
title: tool.title,
|
|
481
|
+
description: tool.description,
|
|
482
|
+
toolset: tool.toolset,
|
|
483
|
+
behavior: tool.resolvedBehavior,
|
|
484
|
+
annotations: tool.annotations,
|
|
485
|
+
inputSchema: tool.wireJsonSchema,
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
buildSearchIndexes() {
|
|
489
|
+
const indexes = new Map();
|
|
490
|
+
for (const toolset of ALL_TOOLSETS) {
|
|
491
|
+
const entries = [...this.tools.values()]
|
|
492
|
+
.filter(tool => tool.toolset === toolset)
|
|
493
|
+
.map(tool => {
|
|
494
|
+
var _a, _b;
|
|
495
|
+
return ({
|
|
496
|
+
id: tool.name,
|
|
497
|
+
text: [tool.name, (_a = tool.title) !== null && _a !== void 0 ? _a : '', tool.description, ...((_b = tool.keywords) !== null && _b !== void 0 ? _b : [])].join(' '),
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
indexes.set(toolset, new bm25_1.Bm25Index(entries));
|
|
501
|
+
}
|
|
502
|
+
return indexes;
|
|
503
|
+
}
|
|
504
|
+
buildDiscoveryMetaTools() {
|
|
505
|
+
const searchSchema = {
|
|
506
|
+
type: 'object',
|
|
507
|
+
properties: {
|
|
508
|
+
query: {
|
|
509
|
+
type: 'string',
|
|
510
|
+
description: 'Keywords to match against tool names and descriptions.',
|
|
511
|
+
},
|
|
512
|
+
limit: {
|
|
513
|
+
type: 'number',
|
|
514
|
+
description: `Maximum number of results (1-${SEARCH_MAX_LIMIT}, default ${SEARCH_DEFAULT_LIMIT}).`,
|
|
515
|
+
},
|
|
516
|
+
},
|
|
517
|
+
required: ['query'],
|
|
518
|
+
additionalProperties: false,
|
|
519
|
+
};
|
|
520
|
+
const executeSchema = {
|
|
521
|
+
type: 'object',
|
|
522
|
+
properties: {
|
|
523
|
+
name: { type: 'string', description: 'The name of the tool to execute (from search_tools).' },
|
|
524
|
+
arguments: { type: 'object', description: 'Arguments to pass to the tool.' },
|
|
525
|
+
},
|
|
526
|
+
required: ['name'],
|
|
527
|
+
additionalProperties: false,
|
|
528
|
+
};
|
|
529
|
+
return [
|
|
530
|
+
{
|
|
531
|
+
name: SEARCH_TOOLS,
|
|
532
|
+
description: 'Search for available Vendure MCP tools by keyword. Returns matching tools with their ' +
|
|
533
|
+
'input schemas so you can then run one via execute_tool.',
|
|
534
|
+
annotations: { readOnlyHint: true, idempotentHint: true },
|
|
535
|
+
compiledInputSchema: this.toolSchema.compileJsonSchema(searchSchema, `MCP tool "${SEARCH_TOOLS}" (McpPlugin) inputSchema`),
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
name: EXECUTE_TOOL,
|
|
539
|
+
description: 'Execute a Vendure MCP tool found via search_tools. Provide the tool name and its arguments.',
|
|
540
|
+
annotations: {},
|
|
541
|
+
compiledInputSchema: this.toolSchema.compileJsonSchema(executeSchema, `MCP tool "${EXECUTE_TOOL}" (McpPlugin) inputSchema`),
|
|
542
|
+
},
|
|
543
|
+
];
|
|
544
|
+
}
|
|
545
|
+
async visibleTools(ctx, toolset) {
|
|
546
|
+
const toggles = await this.getToolToggles(ctx);
|
|
547
|
+
return [...this.tools.values()]
|
|
548
|
+
.filter(tool => tool.toolset === toolset)
|
|
549
|
+
.filter(tool => this.isToolEnabled(tool, toggles))
|
|
550
|
+
.filter(tool => this.hasPermissions(ctx, tool))
|
|
551
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
552
|
+
}
|
|
553
|
+
deriveAnnotations(tool, behavior) {
|
|
554
|
+
return {
|
|
555
|
+
title: tool.title,
|
|
556
|
+
readOnlyHint: behavior === 'readonly',
|
|
557
|
+
destructiveHint: behavior === 'destructive',
|
|
558
|
+
idempotentHint: behavior === 'readonly',
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
hasPermissions(ctx, tool) {
|
|
562
|
+
var _a;
|
|
563
|
+
const permissions = (_a = tool.permissions) !== null && _a !== void 0 ? _a : [];
|
|
564
|
+
if (this.isPubliclyCallable(permissions)) {
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
return ctx.userHasPermissions(permissions);
|
|
568
|
+
}
|
|
569
|
+
// Spelled out because `ctx.userHasPermissions([])` returns false, unlike an empty permissions list here.
|
|
570
|
+
isPubliclyCallable(permissions) {
|
|
571
|
+
return permissions.length === 0 || permissions.includes(core_2.Permission.Public);
|
|
572
|
+
}
|
|
573
|
+
acceptsSessionToken(tool) {
|
|
574
|
+
var _a;
|
|
575
|
+
return (tool.toolset === 'shop' &&
|
|
576
|
+
tool.usesActiveOrder === true &&
|
|
577
|
+
this.isPubliclyCallable((_a = tool.permissions) !== null && _a !== void 0 ? _a : []));
|
|
578
|
+
}
|
|
579
|
+
toCallerInfo(state) {
|
|
580
|
+
return {
|
|
581
|
+
grant: state.grant ? { id: state.grant.id, oauthClientId: state.grant.oauthClientId } : undefined,
|
|
582
|
+
clientIp: state.clientIp,
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
getPluginSource(wrapper) {
|
|
586
|
+
var _a, _b, _c, _d;
|
|
587
|
+
return (_c = (_b = (_a = wrapper.host) === null || _a === void 0 ? void 0 : _a.metatype) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : String((_d = wrapper.name) !== null && _d !== void 0 ? _d : 'unknown');
|
|
588
|
+
}
|
|
589
|
+
// The tool path passes the `text` it already built to measure the result, so it is not serialized twice.
|
|
590
|
+
successResult(output, text = JSON.stringify(output !== null && output !== void 0 ? output : null)) {
|
|
591
|
+
return {
|
|
592
|
+
content: [{ type: 'text', text }],
|
|
593
|
+
structuredContent: output,
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
tooLargeMessage(tool, bytes) {
|
|
597
|
+
var _a;
|
|
598
|
+
const declared = (_a = tool.wireJsonSchema.properties) !== null && _a !== void 0 ? _a : {};
|
|
599
|
+
const advice = Object.keys(NARROWING_ARGUMENT_ADVICE)
|
|
600
|
+
.filter(argument => argument in declared)
|
|
601
|
+
.map(argument => NARROWING_ARGUMENT_ADVICE[argument]);
|
|
602
|
+
const size = `The result of "${tool.name}" is ${bytes.toLocaleString('en-US')} bytes, over the ` +
|
|
603
|
+
`${MAX_RESULT_BYTES.toLocaleString('en-US')}-byte limit for one tool result.`;
|
|
604
|
+
if (advice.length === 0) {
|
|
605
|
+
return `${size} Ask for less at a time.`;
|
|
606
|
+
}
|
|
607
|
+
return `${size} Ask for less at a time: ${this.joinWithOr(advice)}.`;
|
|
608
|
+
}
|
|
609
|
+
// Not an error: the write already saved, so the caller is told to read the outcome back rather than retry.
|
|
610
|
+
completedTooLargeResult(tool, bytes, sessionToken) {
|
|
611
|
+
const text = `The call to "${tool.name}" completed, but its result was ${bytes.toLocaleString('en-US')} ` +
|
|
612
|
+
`bytes, over the ${MAX_RESULT_BYTES.toLocaleString('en-US')}-byte limit, so it was not ` +
|
|
613
|
+
`returned. Fetch the outcome with a read tool.`;
|
|
614
|
+
return {
|
|
615
|
+
content: [{ type: 'text', text }],
|
|
616
|
+
structuredContent: Object.assign({ status: 'completed_result_too_large' }, (sessionToken !== undefined ? { sessionToken } : {})),
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
/** Reads a list of choices as a sentence does: "a", "a or b", "a, b, or c". */
|
|
620
|
+
joinWithOr(options) {
|
|
621
|
+
if (options.length < 3) {
|
|
622
|
+
return options.join(' or ');
|
|
623
|
+
}
|
|
624
|
+
return `${options.slice(0, -1).join(', ')}, or ${options[options.length - 1]}`;
|
|
625
|
+
}
|
|
626
|
+
errorResult(message, sessionToken) {
|
|
627
|
+
return Object.assign({ isError: true, content: [{ type: 'text', text: message }] }, (sessionToken !== undefined ? { structuredContent: { sessionToken } } : {}));
|
|
628
|
+
}
|
|
629
|
+
// Unlike `errorResult`, the whole object is kept so a caller can act on `errorCode` rather than parse a sentence.
|
|
630
|
+
vendureErrorResult(output) {
|
|
631
|
+
return {
|
|
632
|
+
isError: true,
|
|
633
|
+
content: [{ type: 'text', text: JSON.stringify(output) }],
|
|
634
|
+
structuredContent: output,
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
confirmationRequiredResult(tool, sessionToken) {
|
|
638
|
+
// Discovery mode never exposes the tool by name, so the retry has to go through the meta-tool instead.
|
|
639
|
+
const howToConfirm = this.options.toolExposure === 'discovery'
|
|
640
|
+
? `Ask the user to approve it, then call "${EXECUTE_TOOL}" again for "${tool.name}" ` +
|
|
641
|
+
`with "confirm": true added to its arguments.`
|
|
642
|
+
: `Ask the user to approve it, then re-call "${tool.name}" with "confirm": true.`;
|
|
643
|
+
return {
|
|
644
|
+
content: [
|
|
645
|
+
{
|
|
646
|
+
type: 'text',
|
|
647
|
+
text: `This is a destructive action: ${tool.description} ${howToConfirm}`,
|
|
648
|
+
},
|
|
649
|
+
],
|
|
650
|
+
structuredContent: Object.assign({ status: 'confirmation_required', confirmed: false }, (sessionToken !== undefined ? { sessionToken } : {})),
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
exports.McpToolRegistryService = McpToolRegistryService;
|
|
655
|
+
exports.McpToolRegistryService = McpToolRegistryService = __decorate([
|
|
656
|
+
(0, common_1.Injectable)(),
|
|
657
|
+
(0, core_2.Instrument)(),
|
|
658
|
+
__param(8, (0, common_1.Inject)(constants_1.MCP_PLUGIN_OPTIONS)),
|
|
659
|
+
__metadata("design:paramtypes", [core_1.DiscoveryService,
|
|
660
|
+
core_2.SettingsStoreService,
|
|
661
|
+
mcp_rate_limiter_service_1.McpRateLimiterService,
|
|
662
|
+
mcp_tool_call_log_service_1.McpToolCallLogService,
|
|
663
|
+
mcp_tool_schema_service_1.McpToolSchemaService,
|
|
664
|
+
mcp_shop_session_service_1.McpShopSessionService,
|
|
665
|
+
core_2.ConfigService,
|
|
666
|
+
core_2.TransactionalConnection, Object])
|
|
667
|
+
], McpToolRegistryService);
|
|
668
|
+
//# sourceMappingURL=mcp-tool-registry.service.js.map
|