@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.
Files changed (389) hide show
  1. package/lib/api/api-extensions.d.ts +2 -0
  2. package/lib/api/api-extensions.js +239 -0
  3. package/lib/api/api-extensions.js.map +1 -0
  4. package/lib/api/mcp-actor.service.d.ts +19 -0
  5. package/lib/api/mcp-actor.service.js +52 -0
  6. package/lib/api/mcp-actor.service.js.map +1 -0
  7. package/lib/api/mcp-admin.resolver.d.ts +105 -0
  8. package/lib/api/mcp-admin.resolver.js +463 -0
  9. package/lib/api/mcp-admin.resolver.js.map +1 -0
  10. package/lib/api/mcp-shop.resolver.d.ts +25 -0
  11. package/lib/api/mcp-shop.resolver.js +74 -0
  12. package/lib/api/mcp-shop.resolver.js.map +1 -0
  13. package/lib/check-options.d.ts +7 -0
  14. package/lib/check-options.js +130 -0
  15. package/lib/check-options.js.map +1 -0
  16. package/lib/constants.d.ts +48 -0
  17. package/lib/constants.js +72 -0
  18. package/lib/constants.js.map +1 -0
  19. package/lib/delete-in-batches.d.ts +5 -0
  20. package/lib/delete-in-batches.js +28 -0
  21. package/lib/delete-in-batches.js.map +1 -0
  22. package/lib/entities/index.d.ts +5 -0
  23. package/lib/entities/index.js +22 -0
  24. package/lib/entities/index.js.map +1 -0
  25. package/lib/entities/mcp-authorization-code.entity.d.ts +33 -0
  26. package/lib/entities/mcp-authorization-code.entity.js +77 -0
  27. package/lib/entities/mcp-authorization-code.entity.js.map +1 -0
  28. package/lib/entities/mcp-authorization-request.entity.d.ts +31 -0
  29. package/lib/entities/mcp-authorization-request.entity.js +73 -0
  30. package/lib/entities/mcp-authorization-request.entity.js.map +1 -0
  31. package/lib/entities/mcp-oauth-client.entity.d.ts +56 -0
  32. package/lib/entities/mcp-oauth-client.entity.js +70 -0
  33. package/lib/entities/mcp-oauth-client.entity.js.map +1 -0
  34. package/lib/entities/mcp-oauth-grant.entity.d.ts +77 -0
  35. package/lib/entities/mcp-oauth-grant.entity.js +121 -0
  36. package/lib/entities/mcp-oauth-grant.entity.js.map +1 -0
  37. package/lib/entities/mcp-tool-call-log.entity.d.ts +50 -0
  38. package/lib/entities/mcp-tool-call-log.entity.js +101 -0
  39. package/lib/entities/mcp-tool-call-log.entity.js.map +1 -0
  40. package/lib/events/mcp-tool-call.event.d.ts +17 -0
  41. package/lib/events/mcp-tool-call.event.js +23 -0
  42. package/lib/events/mcp-tool-call.event.js.map +1 -0
  43. package/lib/get-client-ip.d.ts +2 -0
  44. package/lib/get-client-ip.js +10 -0
  45. package/lib/get-client-ip.js.map +1 -0
  46. package/lib/get-language-code.d.ts +3 -0
  47. package/lib/get-language-code.js +12 -0
  48. package/lib/get-language-code.js.map +1 -0
  49. package/lib/index.d.ts +6 -0
  50. package/lib/index.js +26 -0
  51. package/lib/index.js.map +1 -0
  52. package/lib/internal-types.d.ts +27 -0
  53. package/lib/internal-types.js +3 -0
  54. package/lib/internal-types.js.map +1 -0
  55. package/lib/logging/mcp-tool-call-log-retention.service.d.ts +8 -0
  56. package/lib/logging/mcp-tool-call-log-retention.service.js +54 -0
  57. package/lib/logging/mcp-tool-call-log-retention.service.js.map +1 -0
  58. package/lib/logging/mcp-tool-call-log.service.d.ts +24 -0
  59. package/lib/logging/mcp-tool-call-log.service.js +128 -0
  60. package/lib/logging/mcp-tool-call-log.service.js.map +1 -0
  61. package/lib/oauth/cimd/cimd-client-resolver.service.d.ts +18 -0
  62. package/lib/oauth/cimd/cimd-client-resolver.service.js +109 -0
  63. package/lib/oauth/cimd/cimd-client-resolver.service.js.map +1 -0
  64. package/lib/oauth/cimd/cimd-document.d.ts +11 -0
  65. package/lib/oauth/cimd/cimd-document.js +66 -0
  66. package/lib/oauth/cimd/cimd-document.js.map +1 -0
  67. package/lib/oauth/cimd/cimd-fetch.d.ts +14 -0
  68. package/lib/oauth/cimd/cimd-fetch.js +192 -0
  69. package/lib/oauth/cimd/cimd-fetch.js.map +1 -0
  70. package/lib/oauth/cimd/cimd-url.d.ts +5 -0
  71. package/lib/oauth/cimd/cimd-url.js +94 -0
  72. package/lib/oauth/cimd/cimd-url.js.map +1 -0
  73. package/lib/oauth/grant-session.service.d.ts +19 -0
  74. package/lib/oauth/grant-session.service.js +141 -0
  75. package/lib/oauth/grant-session.service.js.map +1 -0
  76. package/lib/oauth/oauth-error.d.ts +18 -0
  77. package/lib/oauth/oauth-error.js +60 -0
  78. package/lib/oauth/oauth-error.js.map +1 -0
  79. package/lib/oauth/oauth-metadata.service.d.ts +34 -0
  80. package/lib/oauth/oauth-metadata.service.js +107 -0
  81. package/lib/oauth/oauth-metadata.service.js.map +1 -0
  82. package/lib/oauth/oauth-retention.service.d.ts +23 -0
  83. package/lib/oauth/oauth-retention.service.js +103 -0
  84. package/lib/oauth/oauth-retention.service.js.map +1 -0
  85. package/lib/oauth/oauth-types.d.ts +61 -0
  86. package/lib/oauth/oauth-types.js +32 -0
  87. package/lib/oauth/oauth-types.js.map +1 -0
  88. package/lib/oauth/oauth-utils.d.ts +20 -0
  89. package/lib/oauth/oauth-utils.js +111 -0
  90. package/lib/oauth/oauth-utils.js.map +1 -0
  91. package/lib/oauth/oauth.controller.d.ts +31 -0
  92. package/lib/oauth/oauth.controller.js +132 -0
  93. package/lib/oauth/oauth.controller.js.map +1 -0
  94. package/lib/oauth/oauth.service.d.ts +69 -0
  95. package/lib/oauth/oauth.service.js +650 -0
  96. package/lib/oauth/oauth.service.js.map +1 -0
  97. package/lib/oauth/token-hash.d.ts +6 -0
  98. package/lib/oauth/token-hash.js +21 -0
  99. package/lib/oauth/token-hash.js.map +1 -0
  100. package/lib/plugin.d.ts +54 -0
  101. package/lib/plugin.js +171 -0
  102. package/lib/plugin.js.map +1 -0
  103. package/lib/rate-limit/ip-bucket-key.d.ts +1 -0
  104. package/lib/rate-limit/ip-bucket-key.js +35 -0
  105. package/lib/rate-limit/ip-bucket-key.js.map +1 -0
  106. package/lib/rate-limit/mcp-oauth-rate-limit.guard.d.ts +20 -0
  107. package/lib/rate-limit/mcp-oauth-rate-limit.guard.js +63 -0
  108. package/lib/rate-limit/mcp-oauth-rate-limit.guard.js.map +1 -0
  109. package/lib/rate-limit/mcp-rate-limiter.service.d.ts +47 -0
  110. package/lib/rate-limit/mcp-rate-limiter.service.js +248 -0
  111. package/lib/rate-limit/mcp-rate-limiter.service.js.map +1 -0
  112. package/lib/registry/bm25.d.ts +12 -0
  113. package/lib/registry/bm25.js +60 -0
  114. package/lib/registry/bm25.js.map +1 -0
  115. package/lib/registry/mcp-tool-execution.service.d.ts +45 -0
  116. package/lib/registry/mcp-tool-execution.service.js +72 -0
  117. package/lib/registry/mcp-tool-execution.service.js.map +1 -0
  118. package/lib/registry/mcp-tool-registry.service.d.ts +89 -0
  119. package/lib/registry/mcp-tool-registry.service.js +668 -0
  120. package/lib/registry/mcp-tool-registry.service.js.map +1 -0
  121. package/lib/registry/mcp-tool-schema.service.d.ts +42 -0
  122. package/lib/registry/mcp-tool-schema.service.js +229 -0
  123. package/lib/registry/mcp-tool-schema.service.js.map +1 -0
  124. package/lib/registry/registry-types.d.ts +32 -0
  125. package/lib/registry/registry-types.js +3 -0
  126. package/lib/registry/registry-types.js.map +1 -0
  127. package/lib/resolve-options.d.ts +7 -0
  128. package/lib/resolve-options.js +85 -0
  129. package/lib/resolve-options.js.map +1 -0
  130. package/lib/shared/endpoint-paths.d.ts +8 -0
  131. package/lib/shared/endpoint-paths.js +12 -0
  132. package/lib/shared/endpoint-paths.js.map +1 -0
  133. package/lib/shared/loopback.d.ts +2 -0
  134. package/lib/shared/loopback.js +9 -0
  135. package/lib/shared/loopback.js.map +1 -0
  136. package/lib/shop-session/mcp-shop-session.service.d.ts +47 -0
  137. package/lib/shop-session/mcp-shop-session.service.js +132 -0
  138. package/lib/shop-session/mcp-shop-session.service.js.map +1 -0
  139. package/lib/tasks/mcp-oauth-retention.task.d.ts +9 -0
  140. package/lib/tasks/mcp-oauth-retention.task.js +21 -0
  141. package/lib/tasks/mcp-oauth-retention.task.js.map +1 -0
  142. package/lib/tasks/mcp-tool-call-log-retention.task.d.ts +7 -0
  143. package/lib/tasks/mcp-tool-call-log-retention.task.js +22 -0
  144. package/lib/tasks/mcp-tool-call-log-retention.task.js.map +1 -0
  145. package/lib/tools/built-in/active-order.service.d.ts +26 -0
  146. package/lib/tools/built-in/active-order.service.js +125 -0
  147. package/lib/tools/built-in/active-order.service.js.map +1 -0
  148. package/lib/tools/built-in/admin/add-customer-to-group.tool.d.ts +23 -0
  149. package/lib/tools/built-in/admin/add-customer-to-group.tool.js +68 -0
  150. package/lib/tools/built-in/admin/add-customer-to-group.tool.js.map +1 -0
  151. package/lib/tools/built-in/admin/add-note-to-order.tool.d.ts +104 -0
  152. package/lib/tools/built-in/admin/add-note-to-order.tool.js +66 -0
  153. package/lib/tools/built-in/admin/add-note-to-order.tool.js.map +1 -0
  154. package/lib/tools/built-in/admin/adjust-stock.tool.d.ts +26 -0
  155. package/lib/tools/built-in/admin/adjust-stock.tool.js +88 -0
  156. package/lib/tools/built-in/admin/adjust-stock.tool.js.map +1 -0
  157. package/lib/tools/built-in/admin/cancel-order.tool.d.ts +17 -0
  158. package/lib/tools/built-in/admin/cancel-order.tool.js +60 -0
  159. package/lib/tools/built-in/admin/cancel-order.tool.js.map +1 -0
  160. package/lib/tools/built-in/admin/channel-access.d.ts +2 -0
  161. package/lib/tools/built-in/admin/channel-access.js +9 -0
  162. package/lib/tools/built-in/admin/channel-access.js.map +1 -0
  163. package/lib/tools/built-in/admin/create-customer.tool.d.ts +41 -0
  164. package/lib/tools/built-in/admin/create-customer.tool.js +57 -0
  165. package/lib/tools/built-in/admin/create-customer.tool.js.map +1 -0
  166. package/lib/tools/built-in/admin/create-fulfillment.tool.d.ts +118 -0
  167. package/lib/tools/built-in/admin/create-fulfillment.tool.js +156 -0
  168. package/lib/tools/built-in/admin/create-fulfillment.tool.js.map +1 -0
  169. package/lib/tools/built-in/admin/create-product.tool.d.ts +52 -0
  170. package/lib/tools/built-in/admin/create-product.tool.js +61 -0
  171. package/lib/tools/built-in/admin/create-product.tool.js.map +1 -0
  172. package/lib/tools/built-in/admin/create-variant.tool.d.ts +48 -0
  173. package/lib/tools/built-in/admin/create-variant.tool.js +79 -0
  174. package/lib/tools/built-in/admin/create-variant.tool.js.map +1 -0
  175. package/lib/tools/built-in/admin/entity-field-schemas.d.ts +36 -0
  176. package/lib/tools/built-in/admin/entity-field-schemas.js +63 -0
  177. package/lib/tools/built-in/admin/entity-field-schemas.js.map +1 -0
  178. package/lib/tools/built-in/admin/get-customer.tool.d.ts +28 -0
  179. package/lib/tools/built-in/admin/get-customer.tool.js +55 -0
  180. package/lib/tools/built-in/admin/get-customer.tool.js.map +1 -0
  181. package/lib/tools/built-in/admin/get-order.tool.d.ts +100 -0
  182. package/lib/tools/built-in/admin/get-order.tool.js +68 -0
  183. package/lib/tools/built-in/admin/get-order.tool.js.map +1 -0
  184. package/lib/tools/built-in/admin/get-product.tool.d.ts +69 -0
  185. package/lib/tools/built-in/admin/get-product.tool.js +77 -0
  186. package/lib/tools/built-in/admin/get-product.tool.js.map +1 -0
  187. package/lib/tools/built-in/admin/get-stock-levels.tool.d.ts +23 -0
  188. package/lib/tools/built-in/admin/get-stock-levels.tool.js +61 -0
  189. package/lib/tools/built-in/admin/get-stock-levels.tool.js.map +1 -0
  190. package/lib/tools/built-in/admin/index.d.ts +25 -0
  191. package/lib/tools/built-in/admin/index.js +54 -0
  192. package/lib/tools/built-in/admin/index.js.map +1 -0
  193. package/lib/tools/built-in/admin/list-channels.tool.d.ts +24 -0
  194. package/lib/tools/built-in/admin/list-channels.tool.js +56 -0
  195. package/lib/tools/built-in/admin/list-channels.tool.js.map +1 -0
  196. package/lib/tools/built-in/admin/list-customer-groups.tool.d.ts +23 -0
  197. package/lib/tools/built-in/admin/list-customer-groups.tool.js +52 -0
  198. package/lib/tools/built-in/admin/list-customer-groups.tool.js.map +1 -0
  199. package/lib/tools/built-in/admin/list-customers.tool.d.ts +62 -0
  200. package/lib/tools/built-in/admin/list-customers.tool.js +66 -0
  201. package/lib/tools/built-in/admin/list-customers.tool.js.map +1 -0
  202. package/lib/tools/built-in/admin/list-orders.tool.d.ts +142 -0
  203. package/lib/tools/built-in/admin/list-orders.tool.js +87 -0
  204. package/lib/tools/built-in/admin/list-orders.tool.js.map +1 -0
  205. package/lib/tools/built-in/admin/list-products.tool.d.ts +63 -0
  206. package/lib/tools/built-in/admin/list-products.tool.js +71 -0
  207. package/lib/tools/built-in/admin/list-products.tool.js.map +1 -0
  208. package/lib/tools/built-in/admin/refund-order.tool.d.ts +38 -0
  209. package/lib/tools/built-in/admin/refund-order.tool.js +115 -0
  210. package/lib/tools/built-in/admin/refund-order.tool.js.map +1 -0
  211. package/lib/tools/built-in/admin/set-active-channel.tool.d.ts +22 -0
  212. package/lib/tools/built-in/admin/set-active-channel.tool.js +84 -0
  213. package/lib/tools/built-in/admin/set-active-channel.tool.js.map +1 -0
  214. package/lib/tools/built-in/admin/translation-schemas.d.ts +12 -0
  215. package/lib/tools/built-in/admin/translation-schemas.js +17 -0
  216. package/lib/tools/built-in/admin/translation-schemas.js.map +1 -0
  217. package/lib/tools/built-in/admin/update-customer.tool.d.ts +42 -0
  218. package/lib/tools/built-in/admin/update-customer.tool.js +59 -0
  219. package/lib/tools/built-in/admin/update-customer.tool.js.map +1 -0
  220. package/lib/tools/built-in/admin/update-order-state.tool.d.ts +16 -0
  221. package/lib/tools/built-in/admin/update-order-state.tool.js +58 -0
  222. package/lib/tools/built-in/admin/update-order-state.tool.js.map +1 -0
  223. package/lib/tools/built-in/admin/update-product.tool.d.ts +53 -0
  224. package/lib/tools/built-in/admin/update-product.tool.js +68 -0
  225. package/lib/tools/built-in/admin/update-product.tool.js.map +1 -0
  226. package/lib/tools/built-in/admin/update-variant.tool.d.ts +46 -0
  227. package/lib/tools/built-in/admin/update-variant.tool.js +77 -0
  228. package/lib/tools/built-in/admin/update-variant.tool.js.map +1 -0
  229. package/lib/tools/built-in/admin/upload-asset.tool.d.ts +32 -0
  230. package/lib/tools/built-in/admin/upload-asset.tool.js +56 -0
  231. package/lib/tools/built-in/admin/upload-asset.tool.js.map +1 -0
  232. package/lib/tools/built-in/catalog-query.service.d.ts +21 -0
  233. package/lib/tools/built-in/catalog-query.service.js +128 -0
  234. package/lib/tools/built-in/catalog-query.service.js.map +1 -0
  235. package/lib/tools/built-in/custom-field-input.service.d.ts +10 -0
  236. package/lib/tools/built-in/custom-field-input.service.js +64 -0
  237. package/lib/tools/built-in/custom-field-input.service.js.map +1 -0
  238. package/lib/tools/built-in/email-schema.d.ts +2 -0
  239. package/lib/tools/built-in/email-schema.js +12 -0
  240. package/lib/tools/built-in/email-schema.js.map +1 -0
  241. package/lib/tools/built-in/id-schema.d.ts +3 -0
  242. package/lib/tools/built-in/id-schema.js +11 -0
  243. package/lib/tools/built-in/id-schema.js.map +1 -0
  244. package/lib/tools/built-in/int32-schema.d.ts +4 -0
  245. package/lib/tools/built-in/int32-schema.js +8 -0
  246. package/lib/tools/built-in/int32-schema.js.map +1 -0
  247. package/lib/tools/built-in/list-helpers.d.ts +48 -0
  248. package/lib/tools/built-in/list-helpers.js +76 -0
  249. package/lib/tools/built-in/list-helpers.js.map +1 -0
  250. package/lib/tools/built-in/order-list-helpers.d.ts +20 -0
  251. package/lib/tools/built-in/order-list-helpers.js +48 -0
  252. package/lib/tools/built-in/order-list-helpers.js.map +1 -0
  253. package/lib/tools/built-in/providers.d.ts +2 -0
  254. package/lib/tools/built-in/providers.js +7 -0
  255. package/lib/tools/built-in/providers.js.map +1 -0
  256. package/lib/tools/built-in/remote-asset.d.ts +4 -0
  257. package/lib/tools/built-in/remote-asset.js +54 -0
  258. package/lib/tools/built-in/remote-asset.js.map +1 -0
  259. package/lib/tools/built-in/serializer.service.d.ts +327 -0
  260. package/lib/tools/built-in/serializer.service.js +413 -0
  261. package/lib/tools/built-in/serializer.service.js.map +1 -0
  262. package/lib/tools/built-in/shop/add-to-cart.tool.d.ts +21 -0
  263. package/lib/tools/built-in/shop/add-to-cart.tool.js +100 -0
  264. package/lib/tools/built-in/shop/add-to-cart.tool.js.map +1 -0
  265. package/lib/tools/built-in/shop/address-schema.d.ts +15 -0
  266. package/lib/tools/built-in/shop/address-schema.js +20 -0
  267. package/lib/tools/built-in/shop/address-schema.js.map +1 -0
  268. package/lib/tools/built-in/shop/apply-coupon-code.tool.d.ts +17 -0
  269. package/lib/tools/built-in/shop/apply-coupon-code.tool.js +62 -0
  270. package/lib/tools/built-in/shop/apply-coupon-code.tool.js.map +1 -0
  271. package/lib/tools/built-in/shop/collection-lookup.d.ts +15 -0
  272. package/lib/tools/built-in/shop/collection-lookup.js +35 -0
  273. package/lib/tools/built-in/shop/collection-lookup.js.map +1 -0
  274. package/lib/tools/built-in/shop/get-cart.tool.d.ts +94 -0
  275. package/lib/tools/built-in/shop/get-cart.tool.js +55 -0
  276. package/lib/tools/built-in/shop/get-cart.tool.js.map +1 -0
  277. package/lib/tools/built-in/shop/get-collection.tool.d.ts +42 -0
  278. package/lib/tools/built-in/shop/get-collection.tool.js +64 -0
  279. package/lib/tools/built-in/shop/get-collection.tool.js.map +1 -0
  280. package/lib/tools/built-in/shop/get-eligible-payment-methods.tool.d.ts +26 -0
  281. package/lib/tools/built-in/shop/get-eligible-payment-methods.tool.js +58 -0
  282. package/lib/tools/built-in/shop/get-eligible-payment-methods.tool.js.map +1 -0
  283. package/lib/tools/built-in/shop/get-eligible-shipping-methods.tool.d.ts +30 -0
  284. package/lib/tools/built-in/shop/get-eligible-shipping-methods.tool.js +59 -0
  285. package/lib/tools/built-in/shop/get-eligible-shipping-methods.tool.js.map +1 -0
  286. package/lib/tools/built-in/shop/get-my-account.tool.d.ts +22 -0
  287. package/lib/tools/built-in/shop/get-my-account.tool.js +57 -0
  288. package/lib/tools/built-in/shop/get-my-account.tool.js.map +1 -0
  289. package/lib/tools/built-in/shop/get-order.tool.d.ts +100 -0
  290. package/lib/tools/built-in/shop/get-order.tool.js +67 -0
  291. package/lib/tools/built-in/shop/get-order.tool.js.map +1 -0
  292. package/lib/tools/built-in/shop/get-product.tool.d.ts +57 -0
  293. package/lib/tools/built-in/shop/get-product.tool.js +81 -0
  294. package/lib/tools/built-in/shop/get-product.tool.js.map +1 -0
  295. package/lib/tools/built-in/shop/index.d.ts +19 -0
  296. package/lib/tools/built-in/shop/index.js +42 -0
  297. package/lib/tools/built-in/shop/index.js.map +1 -0
  298. package/lib/tools/built-in/shop/list-collections.tool.d.ts +42 -0
  299. package/lib/tools/built-in/shop/list-collections.tool.js +75 -0
  300. package/lib/tools/built-in/shop/list-collections.tool.js.map +1 -0
  301. package/lib/tools/built-in/shop/list-my-orders.tool.d.ts +100 -0
  302. package/lib/tools/built-in/shop/list-my-orders.tool.js +63 -0
  303. package/lib/tools/built-in/shop/list-my-orders.tool.js.map +1 -0
  304. package/lib/tools/built-in/shop/place-order.tool.d.ts +188 -0
  305. package/lib/tools/built-in/shop/place-order.tool.js +152 -0
  306. package/lib/tools/built-in/shop/place-order.tool.js.map +1 -0
  307. package/lib/tools/built-in/shop/product-search-query.d.ts +4 -0
  308. package/lib/tools/built-in/shop/product-search-query.js +34 -0
  309. package/lib/tools/built-in/shop/product-search-query.js.map +1 -0
  310. package/lib/tools/built-in/shop/remove-coupon-code.tool.d.ts +17 -0
  311. package/lib/tools/built-in/shop/remove-coupon-code.tool.js +63 -0
  312. package/lib/tools/built-in/shop/remove-coupon-code.tool.js.map +1 -0
  313. package/lib/tools/built-in/shop/remove-from-cart.tool.d.ts +17 -0
  314. package/lib/tools/built-in/shop/remove-from-cart.tool.js +58 -0
  315. package/lib/tools/built-in/shop/remove-from-cart.tool.js.map +1 -0
  316. package/lib/tools/built-in/shop/search-products.tool.d.ts +48 -0
  317. package/lib/tools/built-in/shop/search-products.tool.js +95 -0
  318. package/lib/tools/built-in/shop/search-products.tool.js.map +1 -0
  319. package/lib/tools/built-in/shop/set-checkout-details.tool.d.ts +56 -0
  320. package/lib/tools/built-in/shop/set-checkout-details.tool.js +187 -0
  321. package/lib/tools/built-in/shop/set-checkout-details.tool.js.map +1 -0
  322. package/lib/tools/built-in/shop/set-shipping-method.tool.d.ts +17 -0
  323. package/lib/tools/built-in/shop/set-shipping-method.tool.js +58 -0
  324. package/lib/tools/built-in/shop/set-shipping-method.tool.js.map +1 -0
  325. package/lib/tools/built-in/shop/update-cart-line.tool.d.ts +18 -0
  326. package/lib/tools/built-in/shop/update-cart-line.tool.js +60 -0
  327. package/lib/tools/built-in/shop/update-cart-line.tool.js.map +1 -0
  328. package/lib/tools/built-in/string-schemas.d.ts +4 -0
  329. package/lib/tools/built-in/string-schemas.js +13 -0
  330. package/lib/tools/built-in/string-schemas.js.map +1 -0
  331. package/lib/transport/mcp-server.factory.d.ts +13 -0
  332. package/lib/transport/mcp-server.factory.js +32 -0
  333. package/lib/transport/mcp-server.factory.js.map +1 -0
  334. package/lib/transport/mcp-transport.controller.d.ts +77 -0
  335. package/lib/transport/mcp-transport.controller.js +442 -0
  336. package/lib/transport/mcp-transport.controller.js.map +1 -0
  337. package/lib/types.d.ts +432 -0
  338. package/lib/types.js +3 -0
  339. package/lib/types.js.map +1 -0
  340. package/package.json +42 -0
  341. package/src/dashboard/components/activity-block.tsx +72 -0
  342. package/src/dashboard/components/actor-cell.tsx +31 -0
  343. package/src/dashboard/components/connection-dialog.tsx +106 -0
  344. package/src/dashboard/components/empty-cell.tsx +7 -0
  345. package/src/dashboard/components/grants-block.tsx +218 -0
  346. package/src/dashboard/components/stats-block.tsx +275 -0
  347. package/src/dashboard/components/tools-block.tsx +274 -0
  348. package/src/dashboard/components/tooltip-button.tsx +28 -0
  349. package/src/dashboard/components/use-mcp-table-state.ts +47 -0
  350. package/src/dashboard/i18n/ar.po +311 -0
  351. package/src/dashboard/i18n/bg.po +311 -0
  352. package/src/dashboard/i18n/cs.po +311 -0
  353. package/src/dashboard/i18n/de.po +311 -0
  354. package/src/dashboard/i18n/en.po +311 -0
  355. package/src/dashboard/i18n/es.po +311 -0
  356. package/src/dashboard/i18n/fa.po +311 -0
  357. package/src/dashboard/i18n/fr.po +311 -0
  358. package/src/dashboard/i18n/he.po +311 -0
  359. package/src/dashboard/i18n/hr.po +311 -0
  360. package/src/dashboard/i18n/hu.po +311 -0
  361. package/src/dashboard/i18n/it.po +311 -0
  362. package/src/dashboard/i18n/ja.po +311 -0
  363. package/src/dashboard/i18n/ko.po +311 -0
  364. package/src/dashboard/i18n/nb.po +311 -0
  365. package/src/dashboard/i18n/ne.po +311 -0
  366. package/src/dashboard/i18n/nl.po +311 -0
  367. package/src/dashboard/i18n/pl.po +311 -0
  368. package/src/dashboard/i18n/pt_BR.po +311 -0
  369. package/src/dashboard/i18n/pt_PT.po +311 -0
  370. package/src/dashboard/i18n/ro.po +311 -0
  371. package/src/dashboard/i18n/ru.po +311 -0
  372. package/src/dashboard/i18n/sv.po +311 -0
  373. package/src/dashboard/i18n/tr.po +311 -0
  374. package/src/dashboard/i18n/uk.po +311 -0
  375. package/src/dashboard/i18n/uz.po +311 -0
  376. package/src/dashboard/i18n/zh_Hans.po +311 -0
  377. package/src/dashboard/i18n/zh_Hant.po +311 -0
  378. package/src/dashboard/index.tsx +30 -0
  379. package/src/dashboard/mcp-activity-route.tsx +38 -0
  380. package/src/dashboard/mcp-authorize-route.tsx +369 -0
  381. package/src/dashboard/mcp-grants-route.tsx +38 -0
  382. package/src/dashboard/mcp-overview-route.tsx +46 -0
  383. package/src/dashboard/mcp-server-redirect-route.tsx +15 -0
  384. package/src/dashboard/mcp-tools-route.tsx +38 -0
  385. package/src/dashboard/mcp.graphql.ts +127 -0
  386. package/src/dashboard/published-files.spec.ts +54 -0
  387. package/src/dashboard/tsconfig.json +9 -0
  388. package/src/shared/endpoint-paths.ts +8 -0
  389. package/src/shared/loopback.ts +6 -0
@@ -0,0 +1,650 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.McpOauthService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const core_1 = require("@vendure/core");
18
+ const typeorm_1 = require("typeorm");
19
+ const constants_1 = require("../constants");
20
+ const mcp_authorization_code_entity_1 = require("../entities/mcp-authorization-code.entity");
21
+ const mcp_authorization_request_entity_1 = require("../entities/mcp-authorization-request.entity");
22
+ const mcp_oauth_client_entity_1 = require("../entities/mcp-oauth-client.entity");
23
+ const mcp_oauth_grant_entity_1 = require("../entities/mcp-oauth-grant.entity");
24
+ const get_language_code_1 = require("../get-language-code");
25
+ const cimd_client_resolver_service_1 = require("./cimd/cimd-client-resolver.service");
26
+ const cimd_url_1 = require("./cimd/cimd-url");
27
+ const grant_session_service_1 = require("./grant-session.service");
28
+ const oauth_error_1 = require("./oauth-error");
29
+ const oauth_metadata_service_1 = require("./oauth-metadata.service");
30
+ const oauth_utils_1 = require("./oauth-utils");
31
+ const token_hash_1 = require("./token-hash");
32
+ /** Each MCP grant is backed by its own Vendure session, kept isolated so the underlying session token is never exposed to a client. */
33
+ let McpOauthService = class McpOauthService {
34
+ constructor(connection, requestContextService, sessionService, channelService, userService, options, cimdClientResolver, grantSessions, oauthMetadata) {
35
+ this.connection = connection;
36
+ this.requestContextService = requestContextService;
37
+ this.sessionService = sessionService;
38
+ this.channelService = channelService;
39
+ this.userService = userService;
40
+ this.options = options;
41
+ this.cimdClientResolver = cimdClientResolver;
42
+ this.grantSessions = grantSessions;
43
+ this.oauthMetadata = oauthMetadata;
44
+ }
45
+ async registerClient(input) {
46
+ var _a, _b, _c;
47
+ this.resolvedOauth(); // Refuses before any write when OAuth is not configured.
48
+ if (!input.client_name) {
49
+ throw new oauth_error_1.McpOauthError('invalid_client_metadata', 'client_name is required');
50
+ }
51
+ if (input.client_name.length > constants_1.MAX_CLIENT_METADATA_FIELD_LENGTH) {
52
+ throw new oauth_error_1.McpOauthError('invalid_client_metadata', `client_name must be at most ${constants_1.MAX_CLIENT_METADATA_FIELD_LENGTH} characters`);
53
+ }
54
+ if (!input.redirect_uris || input.redirect_uris.length === 0) {
55
+ throw new oauth_error_1.McpOauthError('invalid_redirect_uri', 'redirect_uris is required');
56
+ }
57
+ for (const redirectUri of input.redirect_uris) {
58
+ (0, oauth_utils_1.assertSafeRedirectUri)(redirectUri);
59
+ }
60
+ if (input.token_endpoint_auth_method && input.token_endpoint_auth_method !== 'none') {
61
+ throw new oauth_error_1.McpOauthError('invalid_client_metadata', 'token_endpoint_auth_method must be "none" — this server does not support client authentication');
62
+ }
63
+ if ((_a = input.grant_types) === null || _a === void 0 ? void 0 : _a.some(grantType => !constants_1.SUPPORTED_OAUTH_GRANT_TYPES.includes(grantType))) {
64
+ throw new oauth_error_1.McpOauthError('invalid_client_metadata', 'grant_types may only contain "authorization_code" and "refresh_token" — the only grants this server supports');
65
+ }
66
+ const ctx = await this.createAdminCtx();
67
+ const client = await this.connection.getRepository(ctx, mcp_oauth_client_entity_1.McpOauthClient).save(new mcp_oauth_client_entity_1.McpOauthClient({
68
+ clientId: (0, oauth_utils_1.randomToken)(),
69
+ clientName: input.client_name,
70
+ clientUri: (0, oauth_utils_1.httpsUrlOrNull)(input.client_uri),
71
+ logoUri: (0, oauth_utils_1.httpsUrlOrNull)(input.logo_uri),
72
+ redirectUris: input.redirect_uris,
73
+ grantTypes: (_b = input.grant_types) !== null && _b !== void 0 ? _b : [...constants_1.SUPPORTED_OAUTH_GRANT_TYPES],
74
+ tokenEndpointAuthMethod: (_c = input.token_endpoint_auth_method) !== null && _c !== void 0 ? _c : 'none',
75
+ cimdDocumentExpiresAt: null,
76
+ lastUsedAt: null,
77
+ }));
78
+ return Object.assign(Object.assign(Object.assign({ client_id: client.clientId, client_name: client.clientName }, (client.clientUri ? { client_uri: client.clientUri } : {})), (client.logoUri ? { logo_uri: client.logoUri } : {})), { redirect_uris: client.redirectUris, grant_types: client.grantTypes, token_endpoint_auth_method: client.tokenEndpointAuthMethod });
79
+ }
80
+ async createAuthorizationRedirect(input) {
81
+ var _a;
82
+ const oauth = this.resolvedOauth();
83
+ if (!input.client_id || !input.redirect_uri) {
84
+ throw new common_1.BadRequestException('client_id and redirect_uri are required');
85
+ }
86
+ const ctx = await this.createAdminCtx();
87
+ const client = await this.findClient(ctx, input.client_id);
88
+ if (!(0, oauth_utils_1.isRegisteredRedirectUri)(client.redirectUris, input.redirect_uri)) {
89
+ throw new common_1.BadRequestException('redirect_uri is not registered for client');
90
+ }
91
+ // Errors from here on are reported by redirecting to redirect_uri, since an HTTP error
92
+ // response would only reach the browser, not the client waiting on the redirect.
93
+ const redirectUri = input.redirect_uri;
94
+ const redirectError = (error, error_description) => (0, oauth_utils_1.appendOAuthParams)(redirectUri, {
95
+ error,
96
+ error_description,
97
+ state: input.state,
98
+ });
99
+ if (input.response_type !== 'code') {
100
+ return redirectError('unsupported_response_type', 'Only response_type=code is supported');
101
+ }
102
+ if (!input.code_challenge) {
103
+ return redirectError('invalid_request', 'code_challenge is required');
104
+ }
105
+ if (input.code_challenge_method !== 'S256') {
106
+ return redirectError('invalid_request', 'Only PKCE S256 is supported');
107
+ }
108
+ let resource;
109
+ let toolset;
110
+ try {
111
+ ({ resource, toolset } = this.oauthMetadata.resolveResource(input.resource));
112
+ }
113
+ catch (e) {
114
+ if (e instanceof oauth_error_1.McpOauthError) {
115
+ return redirectError(e.code, e.message);
116
+ }
117
+ throw e;
118
+ }
119
+ if (input.state && input.state.length > constants_1.MAX_OAUTH_STATE_LENGTH) {
120
+ return redirectError('invalid_request', `state must not exceed ${constants_1.MAX_OAUTH_STATE_LENGTH} characters`);
121
+ }
122
+ // RFC 7636 §4.2: a code_challenge is 43-128 characters.
123
+ if (input.code_challenge.length < 43 || input.code_challenge.length > 128) {
124
+ return redirectError('invalid_request', 'code_challenge must be between 43 and 128 characters (RFC 7636)');
125
+ }
126
+ let consentUrl;
127
+ if (toolset === 'admin') {
128
+ consentUrl = new URL(oauth.adminConsentPath, oauth.issuer);
129
+ }
130
+ else {
131
+ const storefrontConsentUrl = oauth.storefrontConsentUrl;
132
+ if (!storefrontConsentUrl) {
133
+ core_1.Logger.error('A customer authorization request was refused because oauth.storefrontConsentUrl is not set. ' +
134
+ 'Set it to your storefront consent page URL. Staff-only deployments do not need it.', constants_1.loggerCtx);
135
+ return redirectError('server_error', 'This store is not configured to authorize customer access.');
136
+ }
137
+ consentUrl = new URL(storefrontConsentUrl);
138
+ }
139
+ const requestTokenPlaintext = (0, oauth_utils_1.randomToken)();
140
+ await this.connection.getRepository(ctx, mcp_authorization_request_entity_1.McpAuthorizationRequest).save(new mcp_authorization_request_entity_1.McpAuthorizationRequest({
141
+ requestToken: this.hashLookup(requestTokenPlaintext),
142
+ oauthClient: client,
143
+ oauthClientId: client.id,
144
+ redirectUri,
145
+ state: (_a = input.state) !== null && _a !== void 0 ? _a : null,
146
+ codeChallenge: input.code_challenge,
147
+ toolset,
148
+ resource,
149
+ expiresAt: (0, oauth_utils_1.addSeconds)(new Date(), oauth.authorizationRequestTtlSeconds),
150
+ }));
151
+ consentUrl.searchParams.set('request_token', requestTokenPlaintext);
152
+ return consentUrl.toString();
153
+ }
154
+ async getAuthorizationRequestInfo(requestToken) {
155
+ if (!requestToken) {
156
+ throw new common_1.BadRequestException('request_token is required');
157
+ }
158
+ const ctx = await this.createAdminCtx();
159
+ const request = await this.findActiveAuthorizationRequest(requestToken, ctx);
160
+ const client = request.oauthClient;
161
+ return Object.assign(Object.assign(Object.assign({ client_id: client.clientId,
162
+ // A URL client_id is one this server fetched a metadata document from; anything else
163
+ // is a token it issued at registration.
164
+ client_id_source: (0, cimd_url_1.isUrlClientId)(client.clientId) ? 'cimd' : 'dcr', client_name: client.clientName }, (client.clientUri ? { client_uri: client.clientUri } : {})), (client.logoUri ? { logo_uri: client.logoUri } : {})), { redirect_uri: request.redirectUri, resource: request.resource, toolset: request.toolset });
165
+ }
166
+ async approveAdminRequest(ctx, requestToken, approved) {
167
+ var _a, _b;
168
+ if (!ctx.activeUserId || !((_a = ctx.session) === null || _a === void 0 ? void 0 : _a.token)) {
169
+ throw new common_1.UnauthorizedException('Admin consent requires an authenticated administrator session');
170
+ }
171
+ if (!ctx.userHasPermissions([constants_1.mcpServerPermission.Update])) {
172
+ throw new common_1.ForbiddenException('Admin consent requires an administrator with the UpdateMcpServer permission');
173
+ }
174
+ this.assertConsentRequestOrigin(ctx);
175
+ if (!approved) {
176
+ return this.denyAuthorizationRequest(requestToken, 'admin');
177
+ }
178
+ return this.approveAuthorizationRequest(requestToken, 'admin', {
179
+ actorId: ctx.activeUserId,
180
+ actorType: 'admin',
181
+ channelId: (_b = ctx.channelId) !== null && _b !== void 0 ? _b : null,
182
+ });
183
+ }
184
+ /** Called from the Shop API, so `ctx` already identifies the customer and channel. */
185
+ async approveCustomerRequest(ctx, requestToken, approved) {
186
+ var _a;
187
+ if (!approved) {
188
+ return this.denyAuthorizationRequest(requestToken, 'shop');
189
+ }
190
+ if (!ctx.activeUserId) {
191
+ throw new common_1.UnauthorizedException('Approving requires a signed-in customer');
192
+ }
193
+ this.assertStorefrontConsentOrigin(ctx);
194
+ await this.assertNotAnAdministrator(ctx);
195
+ return this.approveAuthorizationRequest(requestToken, 'shop', {
196
+ actorId: ctx.activeUserId,
197
+ actorType: 'customer',
198
+ channelId: (_a = ctx.channelId) !== null && _a !== void 0 ? _a : null,
199
+ });
200
+ }
201
+ async assertNotAnAdministrator(ctx) {
202
+ const administrator = await this.connection
203
+ .getRepository(ctx, core_1.Administrator)
204
+ .findOne({ where: { user: { id: ctx.activeUserId } }, relations: ['user'] });
205
+ if (administrator) {
206
+ throw new common_1.ForbiddenException('Customer consent cannot be given by an administrator');
207
+ }
208
+ }
209
+ async exchangeToken(input) {
210
+ if (input.grant_type === 'authorization_code') {
211
+ return this.exchangeAuthorizationCode(input);
212
+ }
213
+ if (input.grant_type === 'refresh_token') {
214
+ return this.exchangeRefreshToken(input);
215
+ }
216
+ throw new oauth_error_1.McpOauthError('unsupported_grant_type', 'Unsupported grant_type');
217
+ }
218
+ async revoke(token) {
219
+ if (!token) {
220
+ return {};
221
+ }
222
+ const ctx = await this.createAdminCtx();
223
+ const hash = this.hashLookup(token);
224
+ // Revoking either token in the pair kills the whole grant (RFC 7009), and the previous
225
+ // refresh token counts too, since a client that lost its rotation response may still hold it.
226
+ const grant = await this.connection.getRepository(ctx, mcp_oauth_grant_entity_1.McpOauthGrant).findOne({
227
+ where: [
228
+ { accessTokenHash: hash },
229
+ { refreshTokenHash: hash },
230
+ { previousRefreshTokenHash: hash },
231
+ ],
232
+ });
233
+ if (grant) {
234
+ await this.grantSessions.revokeGrant(ctx, grant);
235
+ }
236
+ return {};
237
+ }
238
+ async revokeGrantById(ctx, grantId) {
239
+ const grant = await this.connection
240
+ .getRepository(ctx, mcp_oauth_grant_entity_1.McpOauthGrant)
241
+ .findOne({ where: { id: grantId } });
242
+ if (!grant) {
243
+ return false;
244
+ }
245
+ if (ctx.channelId != null &&
246
+ grant.channelId != null &&
247
+ !(0, core_1.idsAreEqual)(grant.channelId, ctx.channelId)) {
248
+ return false;
249
+ }
250
+ await this.grantSessions.revokeGrant(ctx, grant);
251
+ return true;
252
+ }
253
+ /** No channel filter: consent belongs to the person, not the storefront it was given on, so a customer sees every grant regardless of channel. */
254
+ async listCustomerGrants(ctx) {
255
+ if (!ctx.activeUserId) {
256
+ throw new common_1.UnauthorizedException('Listing MCP client grants requires a signed-in customer');
257
+ }
258
+ return this.connection.getRepository(ctx, mcp_oauth_grant_entity_1.McpOauthGrant).find({
259
+ where: {
260
+ actorId: ctx.activeUserId,
261
+ actorType: 'customer',
262
+ revokedAt: (0, typeorm_1.IsNull)(),
263
+ expiresAt: (0, typeorm_1.MoreThan)(new Date()),
264
+ },
265
+ relations: ['oauthClient'],
266
+ order: { lastActivityAt: 'DESC' },
267
+ });
268
+ }
269
+ /** Uses the same error for an unknown grant and one owned by someone else, so a caller can't tell the two apart. */
270
+ async revokeCustomerGrant(ctx, grantId) {
271
+ if (!ctx.activeUserId) {
272
+ throw new common_1.UnauthorizedException('Revoking an MCP client grant requires a signed-in customer');
273
+ }
274
+ const grant = await this.connection
275
+ .getRepository(ctx, mcp_oauth_grant_entity_1.McpOauthGrant)
276
+ .findOne({ where: { id: grantId } });
277
+ if ((grant === null || grant === void 0 ? void 0 : grant.actorType) !== 'customer' || !(0, core_1.idsAreEqual)(grant.actorId, ctx.activeUserId)) {
278
+ throw new core_1.EntityNotFoundError('McpOauthGrant', grantId);
279
+ }
280
+ await this.grantSessions.revokeGrant(ctx, grant);
281
+ return true;
282
+ }
283
+ async authenticateBearerToken(token, apiType, req) {
284
+ const adminCtx = await this.createAdminCtx();
285
+ const resolved = this.usableGrant(await this.findGrantAndSessionToken(adminCtx, token), apiType);
286
+ const { grant } = resolved;
287
+ let vendureSession = resolved.sessionToken
288
+ ? await this.sessionService.getSessionFromToken(resolved.sessionToken)
289
+ : undefined;
290
+ if (!vendureSession) {
291
+ const user = await this.userService.getUserById(adminCtx, grant.actorId);
292
+ if (!user || user.deletedAt) {
293
+ await this.grantSessions.revokeGrant(adminCtx, grant);
294
+ throw new common_1.UnauthorizedException('Vendure user no longer exists');
295
+ }
296
+ vendureSession = await this.grantSessions.recreateGrantSession(adminCtx, grant, user);
297
+ }
298
+ const channel = grant.channelId
299
+ ? await this.channelService.findOne(adminCtx, grant.channelId)
300
+ : await this.channelService.getDefaultChannel(adminCtx);
301
+ if (!channel) {
302
+ await this.grantSessions.revokeGrant(adminCtx, grant);
303
+ throw new common_1.UnauthorizedException('Channel no longer exists');
304
+ }
305
+ const ctx = new core_1.RequestContext({
306
+ apiType,
307
+ channel,
308
+ languageCode: (0, get_language_code_1.getLanguageCodeFromQuery)(req),
309
+ session: vendureSession,
310
+ isAuthorized: true,
311
+ authorizedAsOwnerOnly: false,
312
+ req,
313
+ translationFn: req === null || req === void 0 ? void 0 : req.t,
314
+ });
315
+ this.touchGrantActivity(adminCtx, grant);
316
+ return { ctx, grant };
317
+ }
318
+ usableGrant(resolved, apiType) {
319
+ if (!resolved) {
320
+ throw new common_1.UnauthorizedException('Invalid or expired access token');
321
+ }
322
+ const { grant } = resolved;
323
+ if (grant.revokedAt) {
324
+ throw new common_1.UnauthorizedException('Access token revoked');
325
+ }
326
+ if (grant.accessTokenExpiresAt <= new Date()) {
327
+ throw new oauth_error_1.McpAccessTokenExpiredError();
328
+ }
329
+ if ((apiType === 'admin' && grant.actorType !== 'admin') ||
330
+ (apiType === 'shop' && grant.actorType !== 'customer')) {
331
+ throw new common_1.UnauthorizedException('Access token does not allow this MCP endpoint');
332
+ }
333
+ if (grant.resource !== this.oauthMetadata.resourceForToolset(apiType)) {
334
+ throw new common_1.UnauthorizedException('Access token was not issued for this MCP resource');
335
+ }
336
+ if (grant.expiresAt <= new Date()) {
337
+ throw new common_1.UnauthorizedException('MCP grant is expired');
338
+ }
339
+ return resolved;
340
+ }
341
+ /** Runs in the background so the request doesn't wait on it; mirrors how core updates `ApiKey.lastUsedAt`. */
342
+ touchGrantActivity(ctx, grant) {
343
+ const staleBefore = new Date(Date.now() - constants_1.MCP_GRANT_ACTIVITY_UPDATE_INTERVAL_MS);
344
+ if (!grant.lastActivityAt || grant.lastActivityAt < staleBefore) {
345
+ this.connection
346
+ .getRepository(ctx, mcp_oauth_grant_entity_1.McpOauthGrant)
347
+ .update({ id: grant.id }, { lastActivityAt: new Date() })
348
+ .catch(err => core_1.Logger.error(`Failed to update lastActivityAt for MCP grant ${String(grant.id)}`, constants_1.loggerCtx, err === null || err === void 0 ? void 0 : err.stack));
349
+ }
350
+ }
351
+ /** Raw-selects the session token via LEFT JOIN rather than a relation, so a missing session doesn't hide an otherwise-live grant. */
352
+ async findGrantAndSessionToken(ctx, accessToken) {
353
+ var _a, _b;
354
+ const result = await this.connection
355
+ .getRepository(ctx, mcp_oauth_grant_entity_1.McpOauthGrant)
356
+ .createQueryBuilder('grant')
357
+ .leftJoinAndSelect('grant.oauthClient', 'oauthClient')
358
+ .leftJoin(core_1.Session, 'vendureSession', 'vendureSession.id = grant.vendureSessionId')
359
+ .addSelect('vendureSession.token', 'vendureSessionToken')
360
+ .where('grant.accessTokenHash = :accessTokenHash', {
361
+ accessTokenHash: this.hashLookup(accessToken),
362
+ })
363
+ .getRawAndEntities();
364
+ const grant = result.entities[0];
365
+ return grant ? { grant, sessionToken: (_b = (_a = result.raw[0]) === null || _a === void 0 ? void 0 : _a.vendureSessionToken) !== null && _b !== void 0 ? _b : null } : undefined;
366
+ }
367
+ /** Checks the toolset matches, so a code requested for one API can't be used to spoof a token for the other. */
368
+ async consumeAuthorizationRequest(requestToken, expectedToolset, existingCtx) {
369
+ const ctx = existingCtx !== null && existingCtx !== void 0 ? existingCtx : (await this.createAdminCtx());
370
+ const request = await this.findActiveAuthorizationRequest(requestToken, ctx);
371
+ if (request.toolset !== expectedToolset) {
372
+ throw new common_1.BadRequestException('Authorization request invalid or expired');
373
+ }
374
+ const claim = await this.connection
375
+ .getRepository(ctx, mcp_authorization_request_entity_1.McpAuthorizationRequest)
376
+ .createQueryBuilder()
377
+ .delete()
378
+ .where('requestToken = :requestToken', { requestToken: this.hashLookup(requestToken) })
379
+ .execute();
380
+ if (!claim.affected) {
381
+ throw new common_1.BadRequestException('Authorization request invalid or expired');
382
+ }
383
+ return request;
384
+ }
385
+ async denyAuthorizationRequest(requestToken, expectedToolset) {
386
+ var _a;
387
+ const request = await this.consumeAuthorizationRequest(requestToken, expectedToolset);
388
+ return {
389
+ redirectUrl: (0, oauth_utils_1.appendOAuthParams)(request.redirectUri, {
390
+ error: 'access_denied',
391
+ state: (_a = request.state) !== null && _a !== void 0 ? _a : undefined,
392
+ }),
393
+ };
394
+ }
395
+ /** Runs both writes in one transaction so a failure midway can't leave the client with a broken redirect. */
396
+ async approveAuthorizationRequest(requestToken, expectedToolset, approver) {
397
+ var _a;
398
+ const ctx = await this.createAdminCtx();
399
+ const { actorId, actorType, channelId } = approver;
400
+ const codePlaintext = (0, oauth_utils_1.randomToken)();
401
+ const consented = await this.connection.withTransaction(ctx, async (txCtx) => {
402
+ const request = await this.consumeAuthorizationRequest(requestToken, expectedToolset, txCtx);
403
+ await this.connection.getRepository(txCtx, mcp_authorization_code_entity_1.McpAuthorizationCode).save(new mcp_authorization_code_entity_1.McpAuthorizationCode({
404
+ code: this.hashLookup(codePlaintext),
405
+ oauthClient: request.oauthClient,
406
+ oauthClientId: request.oauthClientId,
407
+ actorId,
408
+ actorType,
409
+ redirectUri: request.redirectUri,
410
+ resource: request.resource,
411
+ codeChallenge: request.codeChallenge,
412
+ channelId,
413
+ expiresAt: (0, oauth_utils_1.addSeconds)(new Date(), this.resolvedOauth().authorizationCodeTtlSeconds),
414
+ }));
415
+ return { redirectUri: request.redirectUri, state: request.state };
416
+ });
417
+ return {
418
+ redirectUrl: (0, oauth_utils_1.appendOAuthParams)(consented.redirectUri, {
419
+ code: codePlaintext,
420
+ state: (_a = consented.state) !== null && _a !== void 0 ? _a : undefined,
421
+ }),
422
+ };
423
+ }
424
+ async exchangeAuthorizationCode(input) {
425
+ if (!input.code ||
426
+ !input.client_id ||
427
+ !input.redirect_uri ||
428
+ !input.code_verifier ||
429
+ !input.resource) {
430
+ throw new oauth_error_1.McpOauthError('invalid_request', 'code, client_id, redirect_uri, code_verifier and resource are required');
431
+ }
432
+ const { resource } = this.oauthMetadata.resolveResource(input.resource);
433
+ const ctx = await this.createAdminCtx();
434
+ const codeRepo = this.connection.getRepository(ctx, mcp_authorization_code_entity_1.McpAuthorizationCode);
435
+ const codeHash = this.hashLookup(input.code);
436
+ const code = await codeRepo.findOne({
437
+ where: { code: codeHash },
438
+ relations: ['oauthClient'],
439
+ });
440
+ if (!code || code.expiresAt <= new Date()) {
441
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Authorization code invalid or expired');
442
+ }
443
+ if (code.oauthClient.clientId !== input.client_id || code.redirectUri !== input.redirect_uri) {
444
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Authorization code does not match client or redirect_uri');
445
+ }
446
+ if (code.resource !== resource) {
447
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Authorization code does not match token request resource');
448
+ }
449
+ if (!(0, oauth_utils_1.verifyPkceChallenge)(input.code_verifier, code.codeChallenge)) {
450
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Invalid PKCE verifier');
451
+ }
452
+ // One transaction: otherwise a failure between claiming the code and issuing tokens would
453
+ // burn the client's one exchange attempt and orphan the session just created.
454
+ return this.connection.withTransaction(ctx, async (txCtx) => {
455
+ const claim = await this.connection
456
+ .getRepository(txCtx, mcp_authorization_code_entity_1.McpAuthorizationCode)
457
+ .createQueryBuilder()
458
+ .delete()
459
+ .where('code = :code', { code: codeHash })
460
+ .execute();
461
+ if (!claim.affected) {
462
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Authorization code invalid or expired');
463
+ }
464
+ return this.issueTokenPair(txCtx, code.oauthClient, code.actorId, code.actorType, code.resource, code.channelId);
465
+ });
466
+ }
467
+ async exchangeRefreshToken(input) {
468
+ const oauth = this.resolvedOauth();
469
+ if (!input.refresh_token || !input.client_id) {
470
+ throw new oauth_error_1.McpOauthError('invalid_request', 'refresh_token and client_id are required');
471
+ }
472
+ const ctx = await this.createAdminCtx();
473
+ const grantRepo = this.connection.getRepository(ctx, mcp_oauth_grant_entity_1.McpOauthGrant);
474
+ const refreshTokenHash = this.hashLookup(input.refresh_token);
475
+ const grant = await grantRepo.findOne({
476
+ where: { refreshTokenHash },
477
+ relations: ['oauthClient'],
478
+ });
479
+ if (!grant) {
480
+ const reused = await grantRepo.findOne({
481
+ where: { previousRefreshTokenHash: refreshTokenHash },
482
+ });
483
+ if (reused) {
484
+ await this.grantSessions.revokeGrant(ctx, reused);
485
+ }
486
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Refresh token invalid or expired');
487
+ }
488
+ if (grant.revokedAt || grant.expiresAt <= new Date()) {
489
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Refresh token invalid or expired');
490
+ }
491
+ if (grant.oauthClient.clientId !== input.client_id) {
492
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Refresh token does not match client');
493
+ }
494
+ // RFC 8707 asks a client to name the resource on a refresh but does not require it, so a
495
+ // request that leaves it out is refreshing for the resource the grant already names.
496
+ if (input.resource) {
497
+ const { resource } = this.oauthMetadata.resolveResource(input.resource);
498
+ if (grant.resource !== resource) {
499
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Refresh token does not match token request resource');
500
+ }
501
+ }
502
+ const now = new Date();
503
+ const accessPlaintext = (0, oauth_utils_1.randomToken)();
504
+ const refreshPlaintext = (0, oauth_utils_1.randomToken)();
505
+ await this.connection.withTransaction(ctx, async (txCtx) => {
506
+ // If two requests race to rotate the same refresh token, only one UPDATE matches and
507
+ // the other is rejected; the old hash is kept so replaying it is recognized as reuse.
508
+ const claim = await this.connection
509
+ .getRepository(txCtx, mcp_oauth_grant_entity_1.McpOauthGrant)
510
+ .createQueryBuilder()
511
+ .update(mcp_oauth_grant_entity_1.McpOauthGrant)
512
+ .set({
513
+ accessTokenHash: this.hashLookup(accessPlaintext),
514
+ refreshTokenHash: this.hashLookup(refreshPlaintext),
515
+ previousRefreshTokenHash: refreshTokenHash,
516
+ accessTokenExpiresAt: (0, oauth_utils_1.addSeconds)(now, oauth.accessTokenTtlSeconds),
517
+ expiresAt: (0, oauth_utils_1.addSeconds)(now, oauth.refreshTokenTtlSeconds),
518
+ lastActivityAt: now,
519
+ })
520
+ .where('id = :id', { id: grant.id })
521
+ .andWhere('refreshTokenHash = :refreshTokenHash', { refreshTokenHash })
522
+ .andWhere('revokedAt IS NULL')
523
+ .execute();
524
+ if (!claim.affected) {
525
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Refresh token invalid or expired');
526
+ }
527
+ await this.connection
528
+ .getRepository(txCtx, mcp_oauth_client_entity_1.McpOauthClient)
529
+ .update({ id: grant.oauthClientId }, { lastUsedAt: now });
530
+ });
531
+ return this.tokenResponse(accessPlaintext, refreshPlaintext);
532
+ }
533
+ async issueTokenPair(ctx, client, actorId, actorType, resource, channelId) {
534
+ const oauth = this.resolvedOauth();
535
+ // Checked here too (not just on session re-creation) because `getUserById` returns
536
+ // soft-deleted users, and a code can outlive the account that approved it.
537
+ const user = await this.userService.getUserById(ctx, actorId);
538
+ if (!user || user.deletedAt) {
539
+ throw new oauth_error_1.McpOauthError('invalid_grant', 'Vendure user no longer exists');
540
+ }
541
+ const now = new Date();
542
+ const accessPlaintext = (0, oauth_utils_1.randomToken)();
543
+ const refreshPlaintext = (0, oauth_utils_1.randomToken)();
544
+ const createdSession = await this.grantSessions.createVendureSession(ctx, user);
545
+ await this.connection.getRepository(ctx, mcp_oauth_grant_entity_1.McpOauthGrant).save(new mcp_oauth_grant_entity_1.McpOauthGrant({
546
+ accessTokenHash: this.hashLookup(accessPlaintext),
547
+ refreshTokenHash: this.hashLookup(refreshPlaintext),
548
+ previousRefreshTokenHash: null,
549
+ oauthClient: client,
550
+ oauthClientId: client.id,
551
+ actorId,
552
+ actorType,
553
+ resource,
554
+ accessTokenExpiresAt: (0, oauth_utils_1.addSeconds)(now, oauth.accessTokenTtlSeconds),
555
+ expiresAt: (0, oauth_utils_1.addSeconds)(now, oauth.refreshTokenTtlSeconds),
556
+ revokedAt: null,
557
+ vendureSessionId: createdSession.id,
558
+ channelId,
559
+ lastActivityAt: now,
560
+ }));
561
+ await this.connection
562
+ .getRepository(ctx, mcp_oauth_client_entity_1.McpOauthClient)
563
+ .update({ id: client.id }, { lastUsedAt: now });
564
+ return this.tokenResponse(accessPlaintext, refreshPlaintext);
565
+ }
566
+ tokenResponse(accessPlaintext, refreshPlaintext) {
567
+ return {
568
+ access_token: accessPlaintext,
569
+ refresh_token: refreshPlaintext,
570
+ token_type: 'Bearer',
571
+ expires_in: this.resolvedOauth().accessTokenTtlSeconds,
572
+ };
573
+ }
574
+ async findClient(ctx, clientId) {
575
+ if ((0, cimd_url_1.isUrlClientId)(clientId)) {
576
+ return this.cimdClientResolver.resolveClient(ctx, clientId);
577
+ }
578
+ const client = await this.connection.getRepository(ctx, mcp_oauth_client_entity_1.McpOauthClient).findOne({
579
+ where: { clientId },
580
+ });
581
+ if (!client) {
582
+ throw new common_1.BadRequestException('Unknown OAuth client');
583
+ }
584
+ return client;
585
+ }
586
+ async findActiveAuthorizationRequest(requestToken, ctx) {
587
+ const request = await this.connection.getRepository(ctx, mcp_authorization_request_entity_1.McpAuthorizationRequest).findOne({
588
+ where: { requestToken: this.hashLookup(requestToken) },
589
+ relations: ['oauthClient'],
590
+ });
591
+ if (!request || request.expiresAt <= new Date()) {
592
+ throw new common_1.BadRequestException('Authorization request invalid or expired');
593
+ }
594
+ return request;
595
+ }
596
+ createAdminCtx() {
597
+ return this.requestContextService.create({ apiType: 'admin' });
598
+ }
599
+ /** Expects the Vendure server's own origin, since Vendure serves the admin consent page itself. */
600
+ assertConsentRequestOrigin(ctx) {
601
+ this.assertOriginMatches(ctx, new URL(this.resolvedOauth().issuer).origin, 'Admin consent must be submitted from the Vendure consent page');
602
+ }
603
+ /** Expects the merchant's storefront consent page origin; a server-rendered page with no `Origin` header is allowed through. */
604
+ assertStorefrontConsentOrigin(ctx) {
605
+ const consentUrl = this.resolvedOauth().storefrontConsentUrl;
606
+ if (!consentUrl) {
607
+ throw new common_1.ForbiddenException('Customer consent requires oauth.storefrontConsentUrl to be configured');
608
+ }
609
+ this.assertOriginMatches(ctx, new URL(consentUrl).origin, 'Customer consent must be submitted from your consent page');
610
+ }
611
+ /** Blocks a cross-site request from riding a signed-in user's session, by requiring the `Origin` header to match when the browser sends one. */
612
+ assertOriginMatches(ctx, expectedOrigin, message) {
613
+ var _a, _b;
614
+ const rawOrigin = (_b = (_a = ctx.req) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? void 0 : _b.origin;
615
+ const originHeader = Array.isArray(rawOrigin) ? rawOrigin[0] : rawOrigin;
616
+ if (!originHeader) {
617
+ return;
618
+ }
619
+ if (originHeader !== expectedOrigin) {
620
+ throw new common_1.ForbiddenException(message);
621
+ }
622
+ }
623
+ /** See {@link resolvedOauthOptions}. */
624
+ resolvedOauth() {
625
+ return (0, oauth_utils_1.resolvedOauthOptions)(this.options);
626
+ }
627
+ /** Derived once and cached, since re-deriving the key for every hash would be expensive. */
628
+ getHashKey() {
629
+ if (!this.cachedHashKey) {
630
+ this.cachedHashKey = (0, token_hash_1.deriveHashKey)(this.resolvedOauth().tokenSecret);
631
+ }
632
+ return this.cachedHashKey;
633
+ }
634
+ hashLookup(value) {
635
+ return (0, token_hash_1.hashLookupToken)(value, this.getHashKey());
636
+ }
637
+ };
638
+ exports.McpOauthService = McpOauthService;
639
+ exports.McpOauthService = McpOauthService = __decorate([
640
+ (0, common_1.Injectable)(),
641
+ __param(5, (0, common_1.Inject)(constants_1.MCP_PLUGIN_OPTIONS)),
642
+ __metadata("design:paramtypes", [core_1.TransactionalConnection,
643
+ core_1.RequestContextService,
644
+ core_1.SessionService,
645
+ core_1.ChannelService,
646
+ core_1.UserService, Object, cimd_client_resolver_service_1.McpCimdClientResolverService,
647
+ grant_session_service_1.McpGrantSessionService,
648
+ oauth_metadata_service_1.McpOauthMetadataService])
649
+ ], McpOauthService);
650
+ //# sourceMappingURL=oauth.service.js.map