@solidcommerce/mcp-server 2.0.0-alpha.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 (268) hide show
  1. package/README.md +74 -0
  2. package/bin/solidcommerce-mcp.js +8 -0
  3. package/dist/audit/auditClient.d.ts +51 -0
  4. package/dist/audit/auditClient.d.ts.map +1 -0
  5. package/dist/audit/auditClient.js +93 -0
  6. package/dist/audit/auditClient.js.map +1 -0
  7. package/dist/auth/apiKey.d.ts +44 -0
  8. package/dist/auth/apiKey.d.ts.map +1 -0
  9. package/dist/auth/apiKey.js +80 -0
  10. package/dist/auth/apiKey.js.map +1 -0
  11. package/dist/auth/oauth.d.ts +108 -0
  12. package/dist/auth/oauth.d.ts.map +1 -0
  13. package/dist/auth/oauth.js +300 -0
  14. package/dist/auth/oauth.js.map +1 -0
  15. package/dist/generator/fromOpenApi.d.ts +54 -0
  16. package/dist/generator/fromOpenApi.d.ts.map +1 -0
  17. package/dist/generator/fromOpenApi.js +411 -0
  18. package/dist/generator/fromOpenApi.js.map +1 -0
  19. package/dist/generator/schemaToZod.d.ts +81 -0
  20. package/dist/generator/schemaToZod.d.ts.map +1 -0
  21. package/dist/generator/schemaToZod.js +277 -0
  22. package/dist/generator/schemaToZod.js.map +1 -0
  23. package/dist/generator/scopeInference.d.ts +26 -0
  24. package/dist/generator/scopeInference.d.ts.map +1 -0
  25. package/dist/generator/scopeInference.js +91 -0
  26. package/dist/generator/scopeInference.js.map +1 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +106 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/server/buildServer.d.ts +35 -0
  32. package/dist/server/buildServer.d.ts.map +1 -0
  33. package/dist/server/buildServer.js +104 -0
  34. package/dist/server/buildServer.js.map +1 -0
  35. package/dist/server/dispatcher.d.ts +14 -0
  36. package/dist/server/dispatcher.d.ts.map +1 -0
  37. package/dist/server/dispatcher.js +190 -0
  38. package/dist/server/dispatcher.js.map +1 -0
  39. package/dist/session.d.ts +9 -0
  40. package/dist/session.d.ts.map +1 -0
  41. package/dist/session.js +11 -0
  42. package/dist/session.js.map +1 -0
  43. package/dist/telemetry/hostName.d.ts +26 -0
  44. package/dist/telemetry/hostName.d.ts.map +1 -0
  45. package/dist/telemetry/hostName.js +80 -0
  46. package/dist/telemetry/hostName.js.map +1 -0
  47. package/dist/tools/contract.d.ts +125 -0
  48. package/dist/tools/contract.d.ts.map +1 -0
  49. package/dist/tools/contract.js +101 -0
  50. package/dist/tools/contract.js.map +1 -0
  51. package/dist/tools/foundation/catalog_amazon_items_list.d.ts +4 -0
  52. package/dist/tools/foundation/catalog_amazon_items_list.d.ts.map +1 -0
  53. package/dist/tools/foundation/catalog_amazon_items_list.js +47 -0
  54. package/dist/tools/foundation/catalog_amazon_items_list.js.map +1 -0
  55. package/dist/tools/foundation/catalog_attribute_filters_list.d.ts +4 -0
  56. package/dist/tools/foundation/catalog_attribute_filters_list.d.ts.map +1 -0
  57. package/dist/tools/foundation/catalog_attribute_filters_list.js +47 -0
  58. package/dist/tools/foundation/catalog_attribute_filters_list.js.map +1 -0
  59. package/dist/tools/foundation/catalog_attribute_tags_list.d.ts +4 -0
  60. package/dist/tools/foundation/catalog_attribute_tags_list.d.ts.map +1 -0
  61. package/dist/tools/foundation/catalog_attribute_tags_list.js +47 -0
  62. package/dist/tools/foundation/catalog_attribute_tags_list.js.map +1 -0
  63. package/dist/tools/foundation/catalog_attributes_list.d.ts +4 -0
  64. package/dist/tools/foundation/catalog_attributes_list.d.ts.map +1 -0
  65. package/dist/tools/foundation/catalog_attributes_list.js +57 -0
  66. package/dist/tools/foundation/catalog_attributes_list.js.map +1 -0
  67. package/dist/tools/foundation/catalog_column_views_default_list.d.ts +4 -0
  68. package/dist/tools/foundation/catalog_column_views_default_list.d.ts.map +1 -0
  69. package/dist/tools/foundation/catalog_column_views_default_list.js +47 -0
  70. package/dist/tools/foundation/catalog_column_views_default_list.js.map +1 -0
  71. package/dist/tools/foundation/catalog_column_views_list.d.ts +4 -0
  72. package/dist/tools/foundation/catalog_column_views_list.d.ts.map +1 -0
  73. package/dist/tools/foundation/catalog_column_views_list.js +47 -0
  74. package/dist/tools/foundation/catalog_column_views_list.js.map +1 -0
  75. package/dist/tools/foundation/catalog_ebay_categories_list.d.ts +4 -0
  76. package/dist/tools/foundation/catalog_ebay_categories_list.d.ts.map +1 -0
  77. package/dist/tools/foundation/catalog_ebay_categories_list.js +56 -0
  78. package/dist/tools/foundation/catalog_ebay_categories_list.js.map +1 -0
  79. package/dist/tools/foundation/catalog_ebay_category_specifics_list.d.ts +4 -0
  80. package/dist/tools/foundation/catalog_ebay_category_specifics_list.d.ts.map +1 -0
  81. package/dist/tools/foundation/catalog_ebay_category_specifics_list.js +56 -0
  82. package/dist/tools/foundation/catalog_ebay_category_specifics_list.js.map +1 -0
  83. package/dist/tools/foundation/catalog_ebay_listing_templates_list.d.ts +4 -0
  84. package/dist/tools/foundation/catalog_ebay_listing_templates_list.d.ts.map +1 -0
  85. package/dist/tools/foundation/catalog_ebay_listing_templates_list.js +47 -0
  86. package/dist/tools/foundation/catalog_ebay_listing_templates_list.js.map +1 -0
  87. package/dist/tools/foundation/catalog_ebay_product_search_list.d.ts +4 -0
  88. package/dist/tools/foundation/catalog_ebay_product_search_list.d.ts.map +1 -0
  89. package/dist/tools/foundation/catalog_ebay_product_search_list.js +56 -0
  90. package/dist/tools/foundation/catalog_ebay_product_search_list.js.map +1 -0
  91. package/dist/tools/foundation/catalog_ebay_template_fields_list.d.ts +4 -0
  92. package/dist/tools/foundation/catalog_ebay_template_fields_list.d.ts.map +1 -0
  93. package/dist/tools/foundation/catalog_ebay_template_fields_list.js +47 -0
  94. package/dist/tools/foundation/catalog_ebay_template_fields_list.js.map +1 -0
  95. package/dist/tools/foundation/catalog_ebay_variation_groups_list.d.ts +4 -0
  96. package/dist/tools/foundation/catalog_ebay_variation_groups_list.d.ts.map +1 -0
  97. package/dist/tools/foundation/catalog_ebay_variation_groups_list.js +56 -0
  98. package/dist/tools/foundation/catalog_ebay_variation_groups_list.js.map +1 -0
  99. package/dist/tools/foundation/catalog_inventory_sources_list.d.ts +4 -0
  100. package/dist/tools/foundation/catalog_inventory_sources_list.d.ts.map +1 -0
  101. package/dist/tools/foundation/catalog_inventory_sources_list.js +47 -0
  102. package/dist/tools/foundation/catalog_inventory_sources_list.js.map +1 -0
  103. package/dist/tools/foundation/catalog_listing_rules_list.d.ts +4 -0
  104. package/dist/tools/foundation/catalog_listing_rules_list.d.ts.map +1 -0
  105. package/dist/tools/foundation/catalog_listing_rules_list.js +47 -0
  106. package/dist/tools/foundation/catalog_listing_rules_list.js.map +1 -0
  107. package/dist/tools/foundation/catalog_listing_templates_list.d.ts +4 -0
  108. package/dist/tools/foundation/catalog_listing_templates_list.d.ts.map +1 -0
  109. package/dist/tools/foundation/catalog_listing_templates_list.js +47 -0
  110. package/dist/tools/foundation/catalog_listing_templates_list.js.map +1 -0
  111. package/dist/tools/foundation/catalog_manufacturers_all_list.d.ts +4 -0
  112. package/dist/tools/foundation/catalog_manufacturers_all_list.d.ts.map +1 -0
  113. package/dist/tools/foundation/catalog_manufacturers_all_list.js +47 -0
  114. package/dist/tools/foundation/catalog_manufacturers_all_list.js.map +1 -0
  115. package/dist/tools/foundation/catalog_manufacturers_list.d.ts +4 -0
  116. package/dist/tools/foundation/catalog_manufacturers_list.d.ts.map +1 -0
  117. package/dist/tools/foundation/catalog_manufacturers_list.js +47 -0
  118. package/dist/tools/foundation/catalog_manufacturers_list.js.map +1 -0
  119. package/dist/tools/foundation/catalog_market_lists_list.d.ts +4 -0
  120. package/dist/tools/foundation/catalog_market_lists_list.d.ts.map +1 -0
  121. package/dist/tools/foundation/catalog_market_lists_list.js +47 -0
  122. package/dist/tools/foundation/catalog_market_lists_list.js.map +1 -0
  123. package/dist/tools/foundation/catalog_product_usage_filters_list.d.ts +4 -0
  124. package/dist/tools/foundation/catalog_product_usage_filters_list.d.ts.map +1 -0
  125. package/dist/tools/foundation/catalog_product_usage_filters_list.js +47 -0
  126. package/dist/tools/foundation/catalog_product_usage_filters_list.js.map +1 -0
  127. package/dist/tools/foundation/catalog_product_usage_list.d.ts +4 -0
  128. package/dist/tools/foundation/catalog_product_usage_list.d.ts.map +1 -0
  129. package/dist/tools/foundation/catalog_product_usage_list.js +61 -0
  130. package/dist/tools/foundation/catalog_product_usage_list.js.map +1 -0
  131. package/dist/tools/foundation/catalog_product_usage_totals_list.d.ts +4 -0
  132. package/dist/tools/foundation/catalog_product_usage_totals_list.d.ts.map +1 -0
  133. package/dist/tools/foundation/catalog_product_usage_totals_list.js +58 -0
  134. package/dist/tools/foundation/catalog_product_usage_totals_list.js.map +1 -0
  135. package/dist/tools/foundation/catalog_products_generate_sku_list.d.ts +4 -0
  136. package/dist/tools/foundation/catalog_products_generate_sku_list.d.ts.map +1 -0
  137. package/dist/tools/foundation/catalog_products_generate_sku_list.js +47 -0
  138. package/dist/tools/foundation/catalog_products_generate_sku_list.js.map +1 -0
  139. package/dist/tools/foundation/catalog_products_list.d.ts +4 -0
  140. package/dist/tools/foundation/catalog_products_list.d.ts.map +1 -0
  141. package/dist/tools/foundation/catalog_products_list.js +60 -0
  142. package/dist/tools/foundation/catalog_products_list.js.map +1 -0
  143. package/dist/tools/foundation/catalog_taxonomy_channels_list.d.ts +4 -0
  144. package/dist/tools/foundation/catalog_taxonomy_channels_list.d.ts.map +1 -0
  145. package/dist/tools/foundation/catalog_taxonomy_channels_list.js +47 -0
  146. package/dist/tools/foundation/catalog_taxonomy_channels_list.js.map +1 -0
  147. package/dist/tools/foundation/catalog_taxonomy_mappings_list.d.ts +4 -0
  148. package/dist/tools/foundation/catalog_taxonomy_mappings_list.d.ts.map +1 -0
  149. package/dist/tools/foundation/catalog_taxonomy_mappings_list.js +56 -0
  150. package/dist/tools/foundation/catalog_taxonomy_mappings_list.js.map +1 -0
  151. package/dist/tools/foundation/catalog_taxonomy_product_values_list.d.ts +4 -0
  152. package/dist/tools/foundation/catalog_taxonomy_product_values_list.d.ts.map +1 -0
  153. package/dist/tools/foundation/catalog_taxonomy_product_values_list.js +57 -0
  154. package/dist/tools/foundation/catalog_taxonomy_product_values_list.js.map +1 -0
  155. package/dist/tools/foundation/catalog_tree_list.d.ts +4 -0
  156. package/dist/tools/foundation/catalog_tree_list.d.ts.map +1 -0
  157. package/dist/tools/foundation/catalog_tree_list.js +47 -0
  158. package/dist/tools/foundation/catalog_tree_list.js.map +1 -0
  159. package/dist/tools/foundation/crm_customers_list.d.ts +4 -0
  160. package/dist/tools/foundation/crm_customers_list.d.ts.map +1 -0
  161. package/dist/tools/foundation/crm_customers_list.js +59 -0
  162. package/dist/tools/foundation/crm_customers_list.js.map +1 -0
  163. package/dist/tools/foundation/fulfillment_manifests_list.d.ts +4 -0
  164. package/dist/tools/foundation/fulfillment_manifests_list.d.ts.map +1 -0
  165. package/dist/tools/foundation/fulfillment_manifests_list.js +47 -0
  166. package/dist/tools/foundation/fulfillment_manifests_list.js.map +1 -0
  167. package/dist/tools/foundation/fulfillment_ship_now_addresses_list.d.ts +4 -0
  168. package/dist/tools/foundation/fulfillment_ship_now_addresses_list.d.ts.map +1 -0
  169. package/dist/tools/foundation/fulfillment_ship_now_addresses_list.js +47 -0
  170. package/dist/tools/foundation/fulfillment_ship_now_addresses_list.js.map +1 -0
  171. package/dist/tools/foundation/fulfillment_ship_now_dictionaries_list.d.ts +4 -0
  172. package/dist/tools/foundation/fulfillment_ship_now_dictionaries_list.d.ts.map +1 -0
  173. package/dist/tools/foundation/fulfillment_ship_now_dictionaries_list.js +56 -0
  174. package/dist/tools/foundation/fulfillment_ship_now_dictionaries_list.js.map +1 -0
  175. package/dist/tools/foundation/index.d.ts +8 -0
  176. package/dist/tools/foundation/index.d.ts.map +1 -0
  177. package/dist/tools/foundation/index.js +93 -0
  178. package/dist/tools/foundation/index.js.map +1 -0
  179. package/dist/tools/foundation/inventory_alert_rules_list.d.ts +4 -0
  180. package/dist/tools/foundation/inventory_alert_rules_list.d.ts.map +1 -0
  181. package/dist/tools/foundation/inventory_alert_rules_list.js +47 -0
  182. package/dist/tools/foundation/inventory_alert_rules_list.js.map +1 -0
  183. package/dist/tools/foundation/inventory_alert_settings_list.d.ts +4 -0
  184. package/dist/tools/foundation/inventory_alert_settings_list.d.ts.map +1 -0
  185. package/dist/tools/foundation/inventory_alert_settings_list.js +47 -0
  186. package/dist/tools/foundation/inventory_alert_settings_list.js.map +1 -0
  187. package/dist/tools/foundation/inventory_analytics_alert_count_list.d.ts +4 -0
  188. package/dist/tools/foundation/inventory_analytics_alert_count_list.d.ts.map +1 -0
  189. package/dist/tools/foundation/inventory_analytics_alert_count_list.js +47 -0
  190. package/dist/tools/foundation/inventory_analytics_alert_count_list.js.map +1 -0
  191. package/dist/tools/foundation/inventory_rules_list.d.ts +4 -0
  192. package/dist/tools/foundation/inventory_rules_list.d.ts.map +1 -0
  193. package/dist/tools/foundation/inventory_rules_list.js +47 -0
  194. package/dist/tools/foundation/inventory_rules_list.js.map +1 -0
  195. package/dist/tools/foundation/inventory_rules_periods_list.d.ts +4 -0
  196. package/dist/tools/foundation/inventory_rules_periods_list.d.ts.map +1 -0
  197. package/dist/tools/foundation/inventory_rules_periods_list.js +47 -0
  198. package/dist/tools/foundation/inventory_rules_periods_list.js.map +1 -0
  199. package/dist/tools/foundation/inventory_seasonal_factors_list.d.ts +4 -0
  200. package/dist/tools/foundation/inventory_seasonal_factors_list.d.ts.map +1 -0
  201. package/dist/tools/foundation/inventory_seasonal_factors_list.js +47 -0
  202. package/dist/tools/foundation/inventory_seasonal_factors_list.js.map +1 -0
  203. package/dist/tools/foundation/inventory_warehouses_list.d.ts +4 -0
  204. package/dist/tools/foundation/inventory_warehouses_list.d.ts.map +1 -0
  205. package/dist/tools/foundation/inventory_warehouses_list.js +47 -0
  206. package/dist/tools/foundation/inventory_warehouses_list.js.map +1 -0
  207. package/dist/tools/foundation/listings_dictionary_marketplace_locales_list.d.ts +4 -0
  208. package/dist/tools/foundation/listings_dictionary_marketplace_locales_list.d.ts.map +1 -0
  209. package/dist/tools/foundation/listings_dictionary_marketplace_locales_list.js +56 -0
  210. package/dist/tools/foundation/listings_dictionary_marketplace_locales_list.js.map +1 -0
  211. package/dist/tools/foundation/listings_dictionary_marketplaces_list.d.ts +4 -0
  212. package/dist/tools/foundation/listings_dictionary_marketplaces_list.d.ts.map +1 -0
  213. package/dist/tools/foundation/listings_dictionary_marketplaces_list.js +47 -0
  214. package/dist/tools/foundation/listings_dictionary_marketplaces_list.js.map +1 -0
  215. package/dist/tools/tasks/bulk_update_prices.d.ts +4 -0
  216. package/dist/tools/tasks/bulk_update_prices.d.ts.map +1 -0
  217. package/dist/tools/tasks/bulk_update_prices.js +96 -0
  218. package/dist/tools/tasks/bulk_update_prices.js.map +1 -0
  219. package/dist/tools/tasks/cancel_order_with_reason.d.ts +4 -0
  220. package/dist/tools/tasks/cancel_order_with_reason.d.ts.map +1 -0
  221. package/dist/tools/tasks/cancel_order_with_reason.js +117 -0
  222. package/dist/tools/tasks/cancel_order_with_reason.js.map +1 -0
  223. package/dist/tools/tasks/check_listing_health.d.ts +4 -0
  224. package/dist/tools/tasks/check_listing_health.d.ts.map +1 -0
  225. package/dist/tools/tasks/check_listing_health.js +123 -0
  226. package/dist/tools/tasks/check_listing_health.js.map +1 -0
  227. package/dist/tools/tasks/create_and_submit_purchase_order.d.ts +4 -0
  228. package/dist/tools/tasks/create_and_submit_purchase_order.d.ts.map +1 -0
  229. package/dist/tools/tasks/create_and_submit_purchase_order.js +142 -0
  230. package/dist/tools/tasks/create_and_submit_purchase_order.js.map +1 -0
  231. package/dist/tools/tasks/find_product_by_sku.d.ts +4 -0
  232. package/dist/tools/tasks/find_product_by_sku.d.ts.map +1 -0
  233. package/dist/tools/tasks/find_product_by_sku.js +68 -0
  234. package/dist/tools/tasks/find_product_by_sku.js.map +1 -0
  235. package/dist/tools/tasks/fulfill_order.d.ts +4 -0
  236. package/dist/tools/tasks/fulfill_order.d.ts.map +1 -0
  237. package/dist/tools/tasks/fulfill_order.js +121 -0
  238. package/dist/tools/tasks/fulfill_order.js.map +1 -0
  239. package/dist/tools/tasks/get_inventory_across_warehouses.d.ts +4 -0
  240. package/dist/tools/tasks/get_inventory_across_warehouses.d.ts.map +1 -0
  241. package/dist/tools/tasks/get_inventory_across_warehouses.js +118 -0
  242. package/dist/tools/tasks/get_inventory_across_warehouses.js.map +1 -0
  243. package/dist/tools/tasks/index.d.ts +14 -0
  244. package/dist/tools/tasks/index.d.ts.map +1 -0
  245. package/dist/tools/tasks/index.js +32 -0
  246. package/dist/tools/tasks/index.js.map +1 -0
  247. package/dist/tools/tasks/publish_product_to_channels.d.ts +4 -0
  248. package/dist/tools/tasks/publish_product_to_channels.d.ts.map +1 -0
  249. package/dist/tools/tasks/publish_product_to_channels.js +109 -0
  250. package/dist/tools/tasks/publish_product_to_channels.js.map +1 -0
  251. package/dist/tools/tasks/reply_to_buyer_message.d.ts +4 -0
  252. package/dist/tools/tasks/reply_to_buyer_message.d.ts.map +1 -0
  253. package/dist/tools/tasks/reply_to_buyer_message.js +72 -0
  254. package/dist/tools/tasks/reply_to_buyer_message.js.map +1 -0
  255. package/dist/tools/tasks/reprice_listing.d.ts +4 -0
  256. package/dist/tools/tasks/reprice_listing.d.ts.map +1 -0
  257. package/dist/tools/tasks/reprice_listing.js +74 -0
  258. package/dist/tools/tasks/reprice_listing.js.map +1 -0
  259. package/dist/transports/stdio.d.ts +12 -0
  260. package/dist/transports/stdio.d.ts.map +1 -0
  261. package/dist/transports/stdio.js +30 -0
  262. package/dist/transports/stdio.js.map +1 -0
  263. package/dist/transports/streamableHttp.d.ts +33 -0
  264. package/dist/transports/streamableHttp.d.ts.map +1 -0
  265. package/dist/transports/streamableHttp.js +237 -0
  266. package/dist/transports/streamableHttp.js.map +1 -0
  267. package/package.json +47 -0
  268. package/vendor/openapi.snapshot.json +19887 -0
@@ -0,0 +1,300 @@
1
+ // =============================================================================
2
+ // src/auth/oauth.ts
3
+ // Phase 0 / Item E-A3 — Per-user OAuth for the MCP Server.
4
+ //
5
+ // Remote hosts (Claude UI, ChatGPT, Gemini, M365 Copilot, Grok) send a per-user
6
+ // `Authorization: Bearer <token>` issued by SC.Base.Auth. This module:
7
+ //
8
+ // 1. Parses the bearer token from the inbound header.
9
+ // 2. Introspects it against SC.Base.Auth `/oauth/introspect` (RFC 7662)
10
+ // using the MCP confidential client (sc-mcp-server) — to FAST-FAIL invalid
11
+ // tokens and to extract claims (company_id, scope, install_id) for audit,
12
+ // per-surface telemetry (E-A4) and per-install rate-limit (E-A5).
13
+ // 3. Resolves a SessionAuthContext the per-session server factory uses to
14
+ // build a bearer-auth SDK client.
15
+ //
16
+ // Resilience / HA design — the load-bearing decision:
17
+ // The bearer token is ALSO independently validated by Platform (it has the
18
+ // JWKS / Authority config). So our introspection is an OPTIMISATION, not the
19
+ // sole gate. That lets introspection FAIL-OPEN under an Auth outage:
20
+ //
21
+ // * Auth reachable, token active → verified oauth context.
22
+ // * Auth reachable, token inactive → HARD REJECT (401). An explicitly bad
23
+ // token must never fall back to the env API key (privilege escalation).
24
+ // * Auth unreachable / circuit open → DEGRADED oauth context: forward the
25
+ // token to Platform, which is the authority. Availability preserved.
26
+ // * No Authorization header → apiKey context (stdio / Scotty /
27
+ // internal). Never introspected.
28
+ //
29
+ // Defensive layers: per-call timeout, positive+negative response cache keyed by
30
+ // a SHA-256 of the token (never the raw token), and a circuit breaker so a down
31
+ // Auth server is not hammered on every session.
32
+ // =============================================================================
33
+ import { createHash } from "node:crypto";
34
+ // -----------------------------------------------------------------------------
35
+ // Config
36
+ // -----------------------------------------------------------------------------
37
+ export const ENV_OAUTH_ENABLED = "SC_MCP_OAUTH_ENABLED";
38
+ export const ENV_INTROSPECT_URL = "SC_AUTH_INTROSPECT_URL";
39
+ export const ENV_MCP_CLIENT_ID = "SC_MCP_CLIENT_ID";
40
+ export const ENV_MCP_CLIENT_SECRET = "SC_MCP_CLIENT_SECRET";
41
+ const DEFAULTS = {
42
+ timeoutMs: 3_000,
43
+ // Cap a cached ACTIVE result at 60s. JWTs are stateless — Platform validates
44
+ // signature + `exp` via JWKS but does NOT check mid-life revocation, so THIS
45
+ // cache is the revocation-enforcement point for the fast path. 60s matches the
46
+ // documented revocation SLA (docs/runbooks/token-revocation.md, PRD §7 NFR).
47
+ positiveTtlMs: 60_000,
48
+ negativeTtlMs: 10_000,
49
+ skewMs: 60_000,
50
+ circuitThreshold: 5,
51
+ circuitCooldownMs: 30_000,
52
+ maxCacheEntries: 5_000,
53
+ };
54
+ /** Default MCP confidential client id — matches OpenIddictSeeder.McpServerClientId. */
55
+ export const DEFAULT_MCP_CLIENT_ID = "sc-mcp-server";
56
+ /**
57
+ * Load OAuth config from env. `enabled` defaults to ON when both an introspect
58
+ * URL and a client secret are present, so a correctly-provisioned deployment
59
+ * "just works"; an operator can force it on/off with SC_MCP_OAUTH_ENABLED.
60
+ */
61
+ export function loadOAuthConfigFromEnv(env = process.env) {
62
+ const introspectUrl = (env[ENV_INTROSPECT_URL] ?? "").trim();
63
+ const clientId = (env[ENV_MCP_CLIENT_ID] ?? DEFAULT_MCP_CLIENT_ID).trim();
64
+ const clientSecret = (env[ENV_MCP_CLIENT_SECRET] ?? "").trim();
65
+ const explicit = env[ENV_OAUTH_ENABLED]?.trim().toLowerCase();
66
+ const enabled = explicit === "true"
67
+ ? true
68
+ : explicit === "false"
69
+ ? false
70
+ : introspectUrl.length > 0 && clientSecret.length > 0;
71
+ return {
72
+ enabled,
73
+ introspectUrl,
74
+ clientId,
75
+ clientSecret,
76
+ ...DEFAULTS,
77
+ };
78
+ }
79
+ function sha256Hex(input) {
80
+ return createHash("sha256").update(input).digest("hex");
81
+ }
82
+ function parseClaims(body) {
83
+ const scopes = typeof body.scope === "string" && body.scope.length > 0
84
+ ? body.scope.split(/\s+/).filter((s) => s.length > 0)
85
+ : [];
86
+ const companyId = body.company_id === undefined || body.company_id === null
87
+ ? undefined
88
+ : String(body.company_id);
89
+ return {
90
+ ...(companyId !== undefined ? { companyId } : {}),
91
+ ...(body.install_id ? { installId: body.install_id } : {}),
92
+ ...(body.sub ? { subject: body.sub } : {}),
93
+ ...(typeof body.exp === "number" ? { expiresAtEpoch: body.exp } : {}),
94
+ scopes,
95
+ };
96
+ }
97
+ /**
98
+ * Build an introspector. Holds the cache + circuit state for the process; one
99
+ * instance is shared across all sessions (cache hits make repeated initialize
100
+ * calls for the same token cheap).
101
+ */
102
+ export function createIntrospector(config, deps = {}) {
103
+ const fetchImpl = deps.fetchImpl ?? fetch;
104
+ const now = deps.now ?? Date.now;
105
+ // Bounded, insertion-ordered cache (Map preserves insertion order → cheap LRU
106
+ // eviction by deleting the oldest key).
107
+ const cache = new Map();
108
+ // Circuit breaker.
109
+ let consecutiveFailures = 0;
110
+ let openUntilMs = 0;
111
+ const isCircuitOpen = () => now() < openUntilMs;
112
+ const recordSuccess = () => {
113
+ consecutiveFailures = 0;
114
+ openUntilMs = 0;
115
+ };
116
+ const recordFailure = () => {
117
+ consecutiveFailures += 1;
118
+ if (consecutiveFailures >= config.circuitThreshold) {
119
+ const wasOpen = now() < openUntilMs;
120
+ openUntilMs = now() + config.circuitCooldownMs;
121
+ if (!wasOpen) {
122
+ // Log only the closed→open transition (not every request) so a
123
+ // misconfigured client secret / Auth outage is loud but not noisy.
124
+ console.error(`[mcp-server] OAuth introspection circuit OPEN after ` +
125
+ `${consecutiveFailures} consecutive failures; failing open ` +
126
+ `(forwarding bearer tokens to Platform, which re-validates) for ` +
127
+ `${config.circuitCooldownMs}ms.`);
128
+ }
129
+ }
130
+ };
131
+ const cacheGet = (key) => {
132
+ const entry = cache.get(key);
133
+ if (!entry)
134
+ return undefined;
135
+ if (now() >= entry.expiresAtMs) {
136
+ cache.delete(key);
137
+ return undefined;
138
+ }
139
+ return entry.outcome;
140
+ };
141
+ const cacheSet = (key, outcome, ttlMs) => {
142
+ if (ttlMs <= 0)
143
+ return;
144
+ // Evict oldest if at capacity.
145
+ if (cache.size >= config.maxCacheEntries) {
146
+ const oldest = cache.keys().next().value;
147
+ if (oldest !== undefined)
148
+ cache.delete(oldest);
149
+ }
150
+ cache.set(key, { outcome, expiresAtMs: now() + ttlMs });
151
+ };
152
+ const positiveTtl = (claims) => {
153
+ if (claims.expiresAtEpoch === undefined)
154
+ return config.positiveTtlMs;
155
+ const untilExpMs = claims.expiresAtEpoch * 1000 - now() - config.skewMs;
156
+ return Math.max(0, Math.min(config.positiveTtlMs, untilExpMs));
157
+ };
158
+ const callIntrospectionEndpoint = async (token) => {
159
+ const controller = new AbortController();
160
+ const timer = setTimeout(() => controller.abort(), config.timeoutMs);
161
+ try {
162
+ const basic = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString("base64");
163
+ const res = await fetchImpl(config.introspectUrl, {
164
+ method: "POST",
165
+ headers: {
166
+ "content-type": "application/x-www-form-urlencoded",
167
+ accept: "application/json",
168
+ authorization: `Basic ${basic}`,
169
+ },
170
+ body: new URLSearchParams({
171
+ token,
172
+ token_type_hint: "access_token",
173
+ }).toString(),
174
+ signal: controller.signal,
175
+ });
176
+ if (!res.ok) {
177
+ // 5xx / 401 from the introspection endpoint itself = our problem, not
178
+ // the user's. Degrade (Platform is authority), count toward the circuit.
179
+ recordFailure();
180
+ return { kind: "degraded", reason: `introspection HTTP ${res.status}` };
181
+ }
182
+ const body = (await res.json());
183
+ recordSuccess();
184
+ if (body.active === true) {
185
+ return { kind: "active", claims: parseClaims(body) };
186
+ }
187
+ return { kind: "inactive" };
188
+ }
189
+ catch (err) {
190
+ // Network error / timeout / abort → degrade + circuit.
191
+ recordFailure();
192
+ const reason = err instanceof Error ? err.message : String(err);
193
+ return { kind: "degraded", reason };
194
+ }
195
+ finally {
196
+ clearTimeout(timer);
197
+ }
198
+ };
199
+ const introspect = async (token) => {
200
+ const key = sha256Hex(token);
201
+ const cached = cacheGet(key);
202
+ if (cached)
203
+ return cached;
204
+ // Circuit open → skip the network entirely, fail-open as degraded.
205
+ if (isCircuitOpen()) {
206
+ return { kind: "degraded", reason: "circuit open" };
207
+ }
208
+ const outcome = await callIntrospectionEndpoint(token);
209
+ // Cache active (TTL bounded by exp) and inactive (short TTL). Degraded is
210
+ // NOT cached — we want to retry as soon as the circuit allows.
211
+ if (outcome.kind === "active") {
212
+ cacheSet(key, outcome, positiveTtl(outcome.claims));
213
+ }
214
+ else if (outcome.kind === "inactive") {
215
+ cacheSet(key, outcome, config.negativeTtlMs);
216
+ }
217
+ return outcome;
218
+ };
219
+ return { introspect, isCircuitOpen };
220
+ }
221
+ // -----------------------------------------------------------------------------
222
+ // Session auth resolver — maps an inbound Authorization header to a resolution
223
+ // -----------------------------------------------------------------------------
224
+ const BEARER_RE = /^Bearer\s+(.+)$/i;
225
+ /** Extract a bearer token, or undefined if the header is absent / not Bearer. */
226
+ export function parseBearer(authorizationHeader) {
227
+ if (!authorizationHeader)
228
+ return undefined;
229
+ const m = BEARER_RE.exec(authorizationHeader.trim());
230
+ const token = m?.[1]?.trim();
231
+ return token && token.length > 0 ? token : undefined;
232
+ }
233
+ /**
234
+ * Build the resolver used by the Streamable HTTP transport at `initialize`.
235
+ * See the resilience matrix in this file's header for the full decision table.
236
+ */
237
+ export function createSessionAuthResolver(deps) {
238
+ const { config, introspector, apiKeyAvailable } = deps;
239
+ const apiKeyContext = () => ({
240
+ mode: "apiKey",
241
+ scopes: [],
242
+ introspectionDegraded: false,
243
+ });
244
+ const resolve = async (authorizationHeader) => {
245
+ const token = parseBearer(authorizationHeader);
246
+ // No bearer → service-to-service / stdio path.
247
+ if (!token) {
248
+ if (apiKeyAvailable)
249
+ return { ok: true, context: apiKeyContext() };
250
+ return { ok: false, status: 401, error: "No credentials: provide a Bearer token or API key." };
251
+ }
252
+ // Bearer present but OAuth disabled by config: we can't introspect, but the
253
+ // token may still be valid to Platform. Forward it, degraded, rather than
254
+ // silently using the env key.
255
+ if (!config.enabled) {
256
+ return {
257
+ ok: true,
258
+ context: {
259
+ mode: "oauth",
260
+ token,
261
+ scopes: [],
262
+ introspectionDegraded: true,
263
+ },
264
+ };
265
+ }
266
+ const outcome = await introspector.introspect(token);
267
+ if (outcome.kind === "active") {
268
+ const c = outcome.claims;
269
+ return {
270
+ ok: true,
271
+ context: {
272
+ mode: "oauth",
273
+ token,
274
+ ...(c.companyId !== undefined ? { companyId: c.companyId } : {}),
275
+ ...(c.installId !== undefined ? { installId: c.installId } : {}),
276
+ ...(c.subject !== undefined ? { subject: c.subject } : {}),
277
+ ...(c.expiresAtEpoch !== undefined ? { expiresAtEpoch: c.expiresAtEpoch } : {}),
278
+ scopes: c.scopes,
279
+ introspectionDegraded: false,
280
+ },
281
+ };
282
+ }
283
+ if (outcome.kind === "inactive") {
284
+ // HARD reject — never fall back to the env key for a bad bearer.
285
+ return { ok: false, status: 401, error: "Token is inactive or expired." };
286
+ }
287
+ // Degraded: Auth unreachable / circuit open. Forward to Platform (authority).
288
+ return {
289
+ ok: true,
290
+ context: {
291
+ mode: "oauth",
292
+ token,
293
+ scopes: [],
294
+ introspectionDegraded: true,
295
+ },
296
+ };
297
+ };
298
+ return { resolve };
299
+ }
300
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import { type HttpMethodLc } from "./scopeInference.js";
2
+ export type Tier = "tier1" | "tier2" | "tier3";
3
+ export interface FoundationTool {
4
+ /** Stable MCP tool name, e.g. `catalog_products_list`. */
5
+ readonly name: string;
6
+ /** One-sentence description (from operation.description / .summary). */
7
+ readonly description: string;
8
+ /** Single canonical scope string (inferred or from x-required-scope*). */
9
+ readonly required_scope: string;
10
+ /** Source code for the Zod input schema (top-level z.object({...})). */
11
+ readonly inputSchemaSource: string;
12
+ /** HTTP method, uppercase — matches openapi-fetch's GET/POST/... method names. */
13
+ readonly httpMethod: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
14
+ /** Original OpenAPI path template (with {param} placeholders). */
15
+ readonly path: string;
16
+ /** Synthesized identifier (since W4 snapshot does not populate operationId). */
17
+ readonly operationId: string;
18
+ /** Which heuristic tier picked this tool — emitted as a code comment. */
19
+ readonly tier: Tier;
20
+ /** True if the operation declares a requestBody. */
21
+ readonly hasBody: boolean;
22
+ /** Path parameter names, declared order — drives runtime arg packing. */
23
+ readonly pathParamNames: ReadonlyArray<string>;
24
+ /** Query parameter names. */
25
+ readonly queryParamNames: ReadonlyArray<string>;
26
+ }
27
+ /** Hard cap from the wave brief — keeps us under Claude's tool token budget. */
28
+ export declare const MAX_FOUNDATION_TOOLS = 40;
29
+ /**
30
+ * Synthesize a stable MCP tool name from a (path, method) operation.
31
+ * Why we don't use operationId: the W4 frozen snapshot omits operationId
32
+ * everywhere — sampled 238/238 ops in vendor/openapi.snapshot.json.
33
+ */
34
+ export declare function synthesizeToolName(path: string, method: HttpMethodLc): string;
35
+ export interface GenerateOptions {
36
+ /** Override the snapshot path (tests). */
37
+ readonly snapshotPath?: string;
38
+ /** Override the heuristic cap (tests). */
39
+ readonly maxTools?: number;
40
+ }
41
+ /**
42
+ * Pure entry: read snapshot, run heuristic, return FoundationTool[].
43
+ * Does NOT touch the filesystem under src/tools/foundation/.
44
+ */
45
+ export declare function generate(options?: GenerateOptions): FoundationTool[];
46
+ /**
47
+ * Write tool files + index to disk. Idempotent: clears the output directory
48
+ * first so stale tools from previous runs don't linger.
49
+ *
50
+ * Returns the list of FoundationTool produced, identical to what `generate()`
51
+ * would have returned for the same options.
52
+ */
53
+ export declare function regenerate(options?: GenerateOptions): FoundationTool[];
54
+ //# sourceMappingURL=fromOpenApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fromOpenApi.d.ts","sourceRoot":"","sources":["../../src/generator/fromOpenApi.ts"],"names":[],"mappings":"AAoCA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAM9E,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAE/C,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,wEAAwE;IACxE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,kFAAkF;IAClF,QAAQ,CAAC,UAAU,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IACjE,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC/C,6BAA6B;IAC7B,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACjD;AAgED,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAmCvC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAY7E;AAiED,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,cAAc,EAAE,CAsDxE;AA+LD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,eAAoB,GAAG,cAAc,EAAE,CAa1E"}