@oomol-lab/open-connector 1.6.5 → 1.7.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 (243) hide show
  1. package/assets/open-connector/catalog/apps/aisa.json +6138 -312
  2. package/assets/open-connector/catalog/apps/baizhi_mcp.json +135 -0
  3. package/assets/open-connector/catalog/apps/discordbot.json +2888 -248
  4. package/assets/open-connector/catalog/apps/drawio_mcp.json +192 -0
  5. package/assets/open-connector/catalog/apps/firecrawl.json +176 -32
  6. package/assets/open-connector/catalog/apps/framejet.json +273 -0
  7. package/assets/open-connector/catalog/apps/futunn.json +2967 -0
  8. package/assets/open-connector/catalog/apps/gmail.json +225 -0
  9. package/assets/open-connector/catalog/apps/google_analytics.json +4 -1
  10. package/assets/open-connector/catalog/apps/google_bigquery.json +4 -1
  11. package/assets/open-connector/catalog/apps/google_search_console.json +4 -1
  12. package/assets/open-connector/catalog/apps/googlecalendar.json +4 -1
  13. package/assets/open-connector/catalog/apps/googlechat.json +694 -7
  14. package/assets/open-connector/catalog/apps/googledocs.json +4 -1
  15. package/assets/open-connector/catalog/apps/googlesheets.json +4 -1
  16. package/assets/open-connector/catalog/apps/granola.json +23 -0
  17. package/assets/open-connector/catalog/apps/keepa.json +3534 -987
  18. package/assets/open-connector/catalog/apps/linear.json +17 -0
  19. package/assets/open-connector/catalog/apps/linear_mcp.json +510 -0
  20. package/assets/open-connector/catalog/apps/moneyforward_mcp.json +1432 -0
  21. package/assets/open-connector/catalog/apps/notion.json +446 -1
  22. package/assets/open-connector/catalog/apps/notion_mcp.json +490 -0
  23. package/assets/open-connector/catalog/apps/odoo.json +619 -0
  24. package/assets/open-connector/catalog/apps/outlook.json +30 -8
  25. package/assets/open-connector/catalog/apps/outlook_calendar.json +23 -2
  26. package/assets/open-connector/catalog/apps/postiz.json +334 -0
  27. package/assets/open-connector/catalog/apps/proworkflow.json +529 -0
  28. package/assets/open-connector/catalog/apps/sellersprite_mcp.json +2 -1
  29. package/assets/open-connector/catalog/apps/slack.json +223 -0
  30. package/assets/open-connector/catalog/apps/slackbot.json +214 -0
  31. package/assets/open-connector/catalog/apps/tencent_docs.json +3 -0
  32. package/assets/open-connector/catalog/apps/wisburg.json +1528 -0
  33. package/assets/open-connector/catalog/apps/youtube.json +4 -1
  34. package/assets/open-connector/catalog/apps/zerotier.json +3319 -0
  35. package/assets/open-connector/catalog/apps-index.json +1 -1
  36. package/package.json +1 -1
  37. package/src/core/cast.d.ts +10 -0
  38. package/src/core/cast.js +14 -0
  39. package/src/core/guarded-fetch.d.ts +6 -3
  40. package/src/core/guarded-fetch.js +6 -3
  41. package/src/core/provider-scenarios.js +67 -13
  42. package/src/core/request.js +4 -1
  43. package/src/core/types.d.ts +1 -1
  44. package/src/mcp.js +10 -7
  45. package/src/oauth/oauth-client-config-service.d.ts +16 -1
  46. package/src/oauth/oauth-client-config-service.js +59 -3
  47. package/src/oauth/oauth-flow-service.d.ts +6 -0
  48. package/src/oauth/oauth-flow-service.js +4 -2
  49. package/src/providers/17track/runtime.js +1 -1
  50. package/src/providers/action-contracts.generated.d.ts +17 -5
  51. package/src/providers/aifinmarket/runtime.js +1 -1
  52. package/src/providers/aisa/executors.js +734 -46
  53. package/src/providers/aliyun_ack/runtime.js +1 -1
  54. package/src/providers/aliyun_sls/runtime.js +1 -1
  55. package/src/providers/app_store_server/runtime-helpers.js +1 -1
  56. package/src/providers/baizhi_mcp/actions.d.ts +2 -0
  57. package/src/providers/baizhi_mcp/actions.js +40 -0
  58. package/src/providers/baizhi_mcp/executors.d.ts +3 -0
  59. package/src/providers/baizhi_mcp/executors.js +102 -0
  60. package/src/providers/bazhuayu/runtime.js +2 -2
  61. package/src/providers/bilibili/runtime.js +2 -4
  62. package/src/providers/bilibili/upload.js +9 -7
  63. package/src/providers/cloudflare_browser_rendering/executors.js +1 -1
  64. package/src/providers/cloudflare_dns/executors.js +1 -1
  65. package/src/providers/{cloudflare-current-user.js → cloudflare_dns/runtime-user.js} +2 -2
  66. package/src/providers/cloudflare_dns/runtime.d.ts +1 -1
  67. package/src/providers/cloudflare_dns/runtime.js +1 -1
  68. package/src/providers/cloudflare_r2/executors.js +1 -1
  69. package/src/providers/cloudflare_r2/runtime.d.ts +1 -1
  70. package/src/providers/cloudflare_r2/runtime.js +1 -1
  71. package/src/providers/cloudflare_worker/executors.js +1 -1
  72. package/src/providers/cloudflare_worker/runtime.d.ts +1 -1
  73. package/src/providers/cloudflare_worker/runtime.js +1 -1
  74. package/src/providers/dingtalk_mcp/runtime.js +1 -1
  75. package/src/providers/discordbot/executors.d.ts +0 -9
  76. package/src/providers/discordbot/executors.js +9 -101
  77. package/src/providers/discordbot/runtime-guilds.d.ts +3 -0
  78. package/src/providers/discordbot/runtime-guilds.js +464 -0
  79. package/src/providers/discordbot/runtime.d.ts +42 -0
  80. package/src/providers/discordbot/runtime.js +124 -0
  81. package/src/providers/drawio_mcp/executors.d.ts +3 -0
  82. package/src/providers/drawio_mcp/executors.js +19 -0
  83. package/src/providers/drawio_mcp/runtime.d.ts +8 -0
  84. package/src/providers/drawio_mcp/runtime.js +175 -0
  85. package/src/providers/fastmoss_mcp/executors.js +2 -2
  86. package/src/providers/finchina/executors.js +1 -1
  87. package/src/providers/framejet/executors.d.ts +4 -0
  88. package/src/providers/framejet/executors.js +19 -0
  89. package/src/providers/framejet/runtime.d.ts +16 -0
  90. package/src/providers/framejet/runtime.js +148 -0
  91. package/src/providers/futunn/actions.d.ts +2 -0
  92. package/src/providers/futunn/actions.js +152 -0
  93. package/src/providers/futunn/actions.research.d.ts +2 -0
  94. package/src/providers/futunn/actions.research.js +423 -0
  95. package/src/providers/futunn/actions.trading.d.ts +2 -0
  96. package/src/providers/futunn/actions.trading.js +204 -0
  97. package/src/providers/futunn/executors.d.ts +3 -0
  98. package/src/providers/futunn/executors.js +24 -0
  99. package/src/providers/futunn/runtime-research.d.ts +3 -0
  100. package/src/providers/futunn/runtime-research.js +133 -0
  101. package/src/providers/futunn/runtime-trading.d.ts +3 -0
  102. package/src/providers/futunn/runtime-trading.js +39 -0
  103. package/src/providers/futunn/runtime.d.ts +2 -0
  104. package/src/providers/futunn/runtime.js +50 -0
  105. package/src/providers/futunn/transport.d.ts +11 -0
  106. package/src/providers/futunn/transport.js +76 -0
  107. package/src/providers/gildata/executors.js +1 -1
  108. package/src/providers/gmail/executors.js +3 -3
  109. package/src/providers/gmail/message.d.ts +6 -8
  110. package/src/providers/gmail/message.js +4 -0
  111. package/src/providers/gmail/scopes.d.ts +32 -0
  112. package/src/providers/gmail/scopes.js +37 -0
  113. package/src/providers/google_analytics/executors.js +2 -2
  114. package/src/providers/google_analytics/scopes.js +6 -1
  115. package/src/providers/google_bigquery/executors.js +2 -2
  116. package/src/providers/google_bigquery/scopes.js +2 -0
  117. package/src/providers/google_search_console/executors.js +2 -2
  118. package/src/providers/google_search_console/scopes.js +2 -0
  119. package/src/providers/googleads/executors.js +1 -1
  120. package/src/providers/googleads/scopes.d.ts +1 -3
  121. package/src/providers/googleads/scopes.js +2 -4
  122. package/src/providers/googlecalendar/executors.js +1 -1
  123. package/src/providers/googlecalendar/runtime-shared.js +2 -2
  124. package/src/providers/googlecalendar/scopes.js +2 -0
  125. package/src/providers/googlechat/executors.d.ts +1 -3
  126. package/src/providers/googlechat/executors.js +219 -28
  127. package/src/providers/googlechat/members.d.ts +55 -0
  128. package/src/providers/googlechat/members.js +293 -0
  129. package/src/providers/googlechat/runtime.d.ts +16 -0
  130. package/src/providers/googlechat/runtime.js +25 -0
  131. package/src/providers/googlechat/scopes.d.ts +22 -3
  132. package/src/providers/googlechat/scopes.js +30 -7
  133. package/src/providers/googledocs/executors.js +1 -1
  134. package/src/providers/googledrive/executors.js +2 -2
  135. package/src/providers/{google-auth.d.ts → googledrive/runtime-auth.d.ts} +2 -2
  136. package/src/providers/{google-auth.js → googledrive/runtime-auth.js} +3 -3
  137. package/src/providers/googledrive/runtime-collaboration.js +1 -1
  138. package/src/providers/{google-runtime.d.ts → googledrive/runtime-request.d.ts} +1 -1
  139. package/src/providers/{google-runtime.js → googledrive/runtime-request.js} +2 -2
  140. package/src/providers/googleforms/executors.js +2 -2
  141. package/src/providers/googleforms/scopes.d.ts +0 -3
  142. package/src/providers/googleforms/scopes.js +2 -6
  143. package/src/providers/googlemeet/executors.js +2 -2
  144. package/src/providers/googlemeet/scopes.d.ts +0 -3
  145. package/src/providers/googlemeet/scopes.js +2 -6
  146. package/src/providers/googlesheets/executors.js +1 -1
  147. package/src/providers/googlesheets/scopes.js +2 -0
  148. package/src/providers/googleslides/executors.js +2 -2
  149. package/src/providers/googleslides/scopes.d.ts +0 -3
  150. package/src/providers/googleslides/scopes.js +2 -6
  151. package/src/providers/googletasks/executors.js +2 -2
  152. package/src/providers/googletasks/scopes.d.ts +0 -3
  153. package/src/providers/googletasks/scopes.js +2 -6
  154. package/src/providers/granola/actions.js +2 -0
  155. package/src/providers/granola/runtime-mcp.js +2 -0
  156. package/src/providers/granola/runtime.js +2 -2
  157. package/src/providers/indiegogo/executors.js +1 -1
  158. package/src/providers/investoday_mcp/executors.js +2 -2
  159. package/src/providers/iyunbiao/runtime.js +2 -2
  160. package/src/providers/keepa/actions.d.ts +1 -1
  161. package/src/providers/keepa/actions.js +371 -149
  162. package/src/providers/keepa/deal-attributes.d.ts +1 -0
  163. package/src/providers/keepa/deal-attributes.js +26 -0
  164. package/src/providers/keepa/runtime.js +212 -18
  165. package/src/providers/kingdee/executors.js +1 -1
  166. package/src/providers/kingdee/runtime.js +2 -2
  167. package/src/providers/kuaidi100/runtime.js +1 -1
  168. package/src/providers/linear/executors.js +12 -9
  169. package/src/providers/linear_mcp/actions.d.ts +47 -0
  170. package/src/providers/linear_mcp/actions.js +102 -0
  171. package/src/providers/linear_mcp/endpoints.d.ts +3 -0
  172. package/src/providers/linear_mcp/endpoints.js +3 -0
  173. package/src/providers/linear_mcp/executors.d.ts +3 -0
  174. package/src/providers/linear_mcp/executors.js +9 -0
  175. package/src/providers/linear_mcp/runtime-mcp.d.ts +15 -0
  176. package/src/providers/linear_mcp/runtime-mcp.js +238 -0
  177. package/src/providers/lingxing_mcp/runtime.js +1 -1
  178. package/src/providers/mcdonalds_cn_mcp/runtime.js +1 -1
  179. package/src/providers/metabase/mcp-runtime.js +1 -1
  180. package/src/providers/moneyforward_mcp/executors.d.ts +3 -0
  181. package/src/providers/moneyforward_mcp/executors.js +11 -0
  182. package/src/providers/moneyforward_mcp/manifest.d.ts +31 -0
  183. package/src/providers/moneyforward_mcp/manifest.js +204 -0
  184. package/src/providers/moneyforward_mcp/runtime.d.ts +18 -0
  185. package/src/providers/moneyforward_mcp/runtime.js +296 -0
  186. package/src/providers/notion/executors.js +39 -3
  187. package/src/providers/notion_mcp/endpoints.d.ts +3 -0
  188. package/src/providers/notion_mcp/endpoints.js +3 -0
  189. package/src/providers/notion_mcp/executors.d.ts +3 -0
  190. package/src/providers/notion_mcp/executors.js +176 -0
  191. package/src/providers/notion_mcp/mcp-response.d.ts +86 -0
  192. package/src/providers/notion_mcp/mcp-response.js +314 -0
  193. package/src/providers/odoo/executors.d.ts +3 -0
  194. package/src/providers/odoo/executors.js +32 -0
  195. package/src/providers/odoo/runtime.d.ts +16 -0
  196. package/src/providers/odoo/runtime.js +140 -0
  197. package/src/providers/outlook/executors.js +27 -6
  198. package/src/providers/outlook/microsoft-graph.js +17 -6
  199. package/src/providers/outlook_calendar/executors.js +24 -7
  200. package/src/providers/patsnap_mcp/executors.js +2 -2
  201. package/src/providers/postiz/executors.d.ts +4 -0
  202. package/src/providers/postiz/executors.js +83 -0
  203. package/src/providers/provider-runtime.d.ts +15 -0
  204. package/src/providers/provider-runtime.js +57 -4
  205. package/src/providers/proworkflow/executors.d.ts +4 -0
  206. package/src/providers/proworkflow/executors.js +135 -0
  207. package/src/providers/registry.generated.js +12 -0
  208. package/src/providers/scrape_creators/catalog.js +1 -1
  209. package/src/providers/scrape_creators/runtime.js +1 -1
  210. package/src/providers/sellersprite_mcp/executors.js +2 -2
  211. package/src/providers/sellersprite_mcp/official-actions.js +3 -2
  212. package/src/providers/sentry/runtime.js +6 -7
  213. package/src/providers/slack/actions.js +52 -3
  214. package/src/providers/slack/runtime.js +58 -21
  215. package/src/providers/slickdeals/runtime.js +1 -1
  216. package/src/providers/sorftime_mcp/executors.js +2 -2
  217. package/src/providers/tikhub/bounded-response.d.ts +1 -1
  218. package/src/providers/tikhub/bounded-response.js +8 -34
  219. package/src/providers/tikhub/endpoint-catalog.js +1 -1
  220. package/src/providers/tikhub/runtime.js +2 -2
  221. package/src/providers/tongdaxin/executors.js +79 -15
  222. package/src/providers/uspto/executors.js +1 -1
  223. package/src/providers/waffo/executors.js +1 -1
  224. package/src/providers/waffo/runtime.js +1 -1
  225. package/src/providers/wecom_mcp/runtime.js +1 -1
  226. package/src/providers/wisburg/executors.d.ts +4 -0
  227. package/src/providers/wisburg/executors.js +13 -0
  228. package/src/providers/wisburg/runtime.d.ts +12 -0
  229. package/src/providers/wisburg/runtime.js +133 -0
  230. package/src/providers/xydc_mcp/executors.js +2 -2
  231. package/src/providers/youtube/executors.js +1 -1
  232. package/src/providers/youtube/runtime.js +1 -1
  233. package/src/providers/zerotier/executors.d.ts +9 -0
  234. package/src/providers/zerotier/executors.js +629 -0
  235. package/src/providers/zerotier/runtime.d.ts +54 -0
  236. package/src/providers/zerotier/runtime.js +207 -0
  237. package/src/server/api/openapi.js +12 -2
  238. package/src/server/api/runtime-api.d.ts +8 -1
  239. package/src/server/api/runtime-api.js +19 -1
  240. package/src/server/connect-server.js +10 -2
  241. package/src/providers/sentry/scopes.d.ts +0 -1
  242. package/src/providers/sentry/scopes.js +0 -7
  243. /package/src/providers/{cloudflare-current-user.d.ts → cloudflare_dns/runtime-user.d.ts} +0 -0
@@ -97,19 +97,26 @@ async function getCalendar(input, context) {
97
97
  return microsoftGraphJson(`me/calendars/${encodePathSegment(id)}`, requestOptions(context, "get calendar", { $select: stringList(input.select) }));
98
98
  }
99
99
  async function listEvents(input, context, calendarView) {
100
- const nextLinkValue = optionalString(input.nextLink);
100
+ // Graph v1.0 tracks calendar changes through calendarView/delta only
101
+ // (events/delta is a beta preview); a nextLink continues the current round,
102
+ // a deltaLink starts the next one.
103
+ const followUpLink = optionalString(input.nextLink) ?? (calendarView ? optionalString(input.deltaLink) : undefined);
104
+ const delta = calendarView && input.delta === true;
101
105
  const calendar = optionalString(input.calendarId);
102
106
  const collection = calendarView ? "calendarView" : "events";
103
- const path = calendar ? `me/calendars/${encodePathSegment(calendar)}/${collection}` : `me/${collection}`;
104
- const query = nextLinkValue
107
+ const path = `${calendar ? `me/calendars/${encodePathSegment(calendar)}/${collection}` : `me/${collection}`}${delta ? "/delta" : ""}`;
108
+ const query = followUpLink
105
109
  ? undefined
106
110
  : compactObject({
107
111
  ...listQuery(input),
108
112
  startDateTime: calendarView ? optionalString(input.startDateTime) : undefined,
109
113
  endDateTime: calendarView ? optionalString(input.endDateTime) : undefined,
110
114
  });
111
- const payload = await microsoftGraphJson(nextLinkValue ?? path, requestOptions(context, `list ${calendarView ? "calendar view" : "events"}`, query, allowEventNextLink, preferTimeZone(input)));
112
- return listOutput(payload, "events");
115
+ const payload = await microsoftGraphJson(followUpLink ?? path, requestOptions(context, `list ${calendarView ? "calendar view" : "events"}`, query, allowEventNextLink, preferTimeZone(input)));
116
+ // Rows stay raw so a delta round's `@removed` markers pass through. Only the
117
+ // calendar view has delta rounds, so only it reports a deltaLink.
118
+ const output = listOutput(payload, "events");
119
+ return calendarView ? { ...output, deltaLink: optionalString(payload["@odata.deltaLink"]) ?? null } : output;
113
120
  }
114
121
  async function getEvent(input, context) {
115
122
  const id = requiredInputString(input.eventId, "eventId");
@@ -212,16 +219,26 @@ function allowEventNextLink(pathname) {
212
219
  return true;
213
220
  }
214
221
  const segments = pathname.split("/").filter(Boolean);
222
+ // Delta links end in a trailing `delta` segment on the same three shapes,
223
+ // and only for calendarView: events/delta is not on Graph v1.0.
224
+ const delta = segments.length > 3 && segments[segments.length - 1] === "delta";
225
+ if (delta) {
226
+ segments.pop();
227
+ }
228
+ const isEventCollection = (segment) => segment === "calendarView" || (!delta && segment === "events");
229
+ if (delta && segments.length === 3 && segments[0] === "v1.0" && segments[1] === "me") {
230
+ return isEventCollection(segments[2]);
231
+ }
215
232
  if (segments.length === 4 &&
216
233
  segments[0] === "v1.0" &&
217
234
  segments[1] === "me" &&
218
235
  segments[2]?.startsWith("calendars('") &&
219
236
  segments[2].endsWith("')")) {
220
- return segments[3] === "events" || segments[3] === "calendarView";
237
+ return isEventCollection(segments[3]);
221
238
  }
222
239
  return (segments.length === 5 &&
223
240
  segments[0] === "v1.0" &&
224
241
  segments[1] === "me" &&
225
242
  segments[2] === "calendars" &&
226
- (segments[4] === "events" || segments[4] === "calendarView"));
243
+ isEventCollection(segments[4]));
227
244
  }
@@ -37,7 +37,7 @@ export const proxy = defineProviderProxy({
37
37
  return endpoints.has(new URL(endpoint, patsnapMcpOrigin).href);
38
38
  },
39
39
  skipDnsValidation: true,
40
- redirect: "error",
40
+ redirect: "manual",
41
41
  customizeRequest({ headers }) {
42
42
  headers.set("accept", "application/json, text/event-stream");
43
43
  },
@@ -95,7 +95,7 @@ async function withClient(context, server, run) {
95
95
  transport: "streamable_http",
96
96
  fetcher: context.fetcher,
97
97
  headers: { authorization: `Bearer ${context.apiKey}`, "user-agent": providerUserAgent },
98
- redirect: "error",
98
+ redirect: "manual",
99
99
  signal: context.signal,
100
100
  mapError: mapMcpError,
101
101
  }, run);
@@ -0,0 +1,4 @@
1
+ import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
2
+ export declare const executors: ProviderExecutors;
3
+ export declare const credentialValidators: CredentialValidators;
4
+ export declare const proxy: ProviderProxyExecutor;
@@ -0,0 +1,83 @@
1
+ import { optionalRecord, optionalString } from "../../core/cast.js";
2
+ import { defineApiKeyProviderExecutors, defineProviderProxy, ProviderRequestError, providerUserAgent, readProviderJsonBody, requiredResponseRecord, runProviderRequest, } from "../provider-runtime.js";
3
+ const service = "postiz";
4
+ const baseUrl = "https://api.postiz.com/public/v1";
5
+ const handlers = {
6
+ list_integrations: async (input, context) => readPostizCollection(await request(context, "/integrations", { query: { group: optionalString(input.group) } }), "integrations"),
7
+ list_posts: async (input, context) => requiredResponseRecord(await request(context, "/posts", {
8
+ query: {
9
+ startDate: optionalString(input.startDate),
10
+ endDate: optionalString(input.endDate),
11
+ customer: optionalString(input.customer),
12
+ },
13
+ }), "Postiz posts"),
14
+ upload_from_url: async (input, context) => requiredResponseRecord(await request(context, "/upload-from-url", { method: "POST", body: { url: input.url } }), "Postiz uploaded media"),
15
+ create_post: async (input, context) => readPostizCollection(await request(context, "/posts", { method: "POST", body: input }), "created posts"),
16
+ };
17
+ export const executors = defineApiKeyProviderExecutors(service, handlers, {
18
+ skipDnsValidation: true,
19
+ });
20
+ export const credentialValidators = {
21
+ async apiKey(input, { fetcher, signal }) {
22
+ const result = optionalRecord(await request({ apiKey: input.apiKey, fetcher, signal }, "/is-connected"));
23
+ if (result?.connected !== true) {
24
+ throw new ProviderRequestError(502, "Postiz did not confirm the API key connection");
25
+ }
26
+ return {
27
+ profile: { accountId: "api_key", displayName: "Postiz API Key" },
28
+ grantedScopes: [],
29
+ metadata: { apiBaseUrl: baseUrl },
30
+ };
31
+ },
32
+ };
33
+ export const proxy = defineProviderProxy({
34
+ service,
35
+ baseUrl,
36
+ auth: { type: "api_key_header", name: "Authorization" },
37
+ skipDnsValidation: true,
38
+ customizeRequest({ headers }) {
39
+ if (!headers.has("accept"))
40
+ headers.set("accept", "application/json");
41
+ },
42
+ });
43
+ async function request(context, path, options = {}) {
44
+ return runProviderRequest({ signal: context.signal, label: "Postiz" }, async (signal) => {
45
+ const url = new URL(`${baseUrl}${path}`);
46
+ for (const [key, value] of Object.entries(options.query ?? {})) {
47
+ if (value !== undefined)
48
+ url.searchParams.set(key, value);
49
+ }
50
+ const headers = new Headers({
51
+ accept: "application/json",
52
+ authorization: context.apiKey,
53
+ "user-agent": providerUserAgent,
54
+ });
55
+ if (options.body !== undefined)
56
+ headers.set("content-type", "application/json");
57
+ const response = await context.fetcher(url, {
58
+ method: options.method,
59
+ headers,
60
+ body: options.body === undefined ? undefined : JSON.stringify(options.body),
61
+ signal,
62
+ });
63
+ const payload = await readProviderJsonBody(response, {
64
+ emptyBody: null,
65
+ invalidJsonMessage: "Postiz returned invalid JSON",
66
+ invalidJsonFallback: response.ok ? undefined : (text) => text,
67
+ });
68
+ if (!response.ok) {
69
+ const details = optionalRecord(payload);
70
+ const message = optionalString(details?.message) ??
71
+ optionalString(details?.error) ??
72
+ optionalString(payload) ??
73
+ `Postiz request failed with HTTP ${response.status}`;
74
+ throw new ProviderRequestError(response.status, message, payload);
75
+ }
76
+ return payload;
77
+ });
78
+ }
79
+ function readPostizCollection(value, label) {
80
+ if (!Array.isArray(value))
81
+ throw new ProviderRequestError(502, `Postiz returned invalid ${label}`);
82
+ return value;
83
+ }
@@ -372,6 +372,21 @@ export declare function setSearchParams(url: URL, query: Record<string, string |
372
372
  * Read a bounded provider error response body as text.
373
373
  */
374
374
  export declare function readProviderErrorTextBody(response: Response, fieldName: string): Promise<string>;
375
+ /**
376
+ * Read a `Retry-After` header as whole seconds from now: an integer delay
377
+ * verbatim, an HTTP-date as the seconds until that instant (never negative).
378
+ * Examples: `"73" => 73`; a date 90 s ahead `=> 90`; absent or unparseable
379
+ * `=> undefined`.
380
+ */
381
+ export declare function readRetryAfterSeconds(headers: Headers, now?: number): number | undefined;
382
+ /**
383
+ * Attach a rate-limited response's `Retry-After` to its error details in the
384
+ * shape Slack established, `details.retryAfterSeconds`, so every provider's
385
+ * 429 (and 503) reaches the action envelope with the same pacing hint.
386
+ * Other statuses, and responses without a usable header, return `details`
387
+ * untouched; non-record details are kept under `body`.
388
+ */
389
+ export declare function withRetryAfterSeconds(response: Response, details?: unknown): unknown;
375
390
  /**
376
391
  * Read a JSON provider response or raise a structured provider request error.
377
392
  */
@@ -264,6 +264,11 @@ export async function readProviderProxyResponse(response, options = {}) {
264
264
  };
265
265
  }
266
266
  export async function readProviderProxyErrorMessage(response, fallbackMessage) {
267
+ // An unfollowed redirect's body usually echoes its `Location`, which may carry a signed target URL.
268
+ if (response.status >= 300 && response.status < 400) {
269
+ await response.body?.cancel().catch(() => undefined);
270
+ return fallbackMessage;
271
+ }
267
272
  const bytes = await readBoundedResponseBytes(response, {
268
273
  maxBytes: defaultProviderProxyMaxResponseBytes,
269
274
  fieldName: "proxy error response",
@@ -356,7 +361,8 @@ export function defineProviderProxy(input) {
356
361
  }
357
362
  const response = await egressFetch(url, init);
358
363
  if (!response.ok) {
359
- if (input.readError) {
364
+ // A provider error parser would surface an unfollowed redirect's body; the shared reader withholds it.
365
+ if (input.readError && (response.status < 300 || response.status >= 400)) {
360
366
  throw await input.readError(response);
361
367
  }
362
368
  throw new ProviderRequestError(response.status, await readProviderProxyErrorMessage(response, `provider request failed with HTTP ${response.status}`));
@@ -679,6 +685,52 @@ export async function readProviderErrorTextBody(response, fieldName) {
679
685
  return "";
680
686
  }
681
687
  }
688
+ // The three HTTP-date forms of RFC 9110 section 5.6.7. Date.parse alone is too
689
+ // lenient for a header: V8 reads "wait 5" as 1 May 2001, and reads the zone-less
690
+ // asctime form as local time although every HTTP-date is UTC.
691
+ const imfFixdatePattern = /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/;
692
+ const rfc850DatePattern = /^(?:Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day, \d{2}-(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-\d{2} \d{2}:\d{2}:\d{2} GMT$/;
693
+ const asctimeDatePattern = /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun) (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [ \d]\d \d{2}:\d{2}:\d{2} \d{4}$/;
694
+ /**
695
+ * Read a `Retry-After` header as whole seconds from now: an integer delay
696
+ * verbatim, an HTTP-date as the seconds until that instant (never negative).
697
+ * Examples: `"73" => 73`; a date 90 s ahead `=> 90`; absent or unparseable
698
+ * `=> undefined`.
699
+ */
700
+ export function readRetryAfterSeconds(headers, now = Date.now()) {
701
+ const value = headers.get("retry-after")?.trim();
702
+ if (!value) {
703
+ return undefined;
704
+ }
705
+ if (/^\d+$/.test(value)) {
706
+ const seconds = Number(value);
707
+ return Number.isSafeInteger(seconds) ? seconds : undefined;
708
+ }
709
+ const retryAt = imfFixdatePattern.test(value) || rfc850DatePattern.test(value)
710
+ ? Date.parse(value)
711
+ : asctimeDatePattern.test(value)
712
+ ? Date.parse(`${value} GMT`)
713
+ : Number.NaN;
714
+ return Number.isFinite(retryAt) ? Math.max(0, Math.ceil((retryAt - now) / 1000)) : undefined;
715
+ }
716
+ /**
717
+ * Attach a rate-limited response's `Retry-After` to its error details in the
718
+ * shape Slack established, `details.retryAfterSeconds`, so every provider's
719
+ * 429 (and 503) reaches the action envelope with the same pacing hint.
720
+ * Other statuses, and responses without a usable header, return `details`
721
+ * untouched; non-record details are kept under `body`.
722
+ */
723
+ export function withRetryAfterSeconds(response, details) {
724
+ if (response.status !== 429 && response.status !== 503) {
725
+ return details;
726
+ }
727
+ const retryAfterSeconds = readRetryAfterSeconds(response.headers);
728
+ if (retryAfterSeconds === undefined) {
729
+ return details;
730
+ }
731
+ const record = optionalRecord(details) ?? (details == null ? {} : { body: details });
732
+ return { ...record, retryAfterSeconds };
733
+ }
682
734
  /**
683
735
  * Read a JSON provider response or raise a structured provider request error.
684
736
  */
@@ -806,9 +858,10 @@ export function toProviderExecutionError(error, fallbackMessage) {
806
858
  ? "authorization_failed"
807
859
  : error.status === 429
808
860
  ? "rate_limited"
809
- : error.status < 500
810
- ? "invalid_input"
811
- : "provider_error"),
861
+ : // A 3xx is an upstream redirect that `redirect: "manual"` surfaced unfollowed, not bad input.
862
+ error.status < 500 && (error.status < 300 || error.status >= 400)
863
+ ? "invalid_input"
864
+ : "provider_error"),
812
865
  message: error.message,
813
866
  details: {
814
867
  status: error.status,
@@ -0,0 +1,4 @@
1
+ import type { CredentialValidators, ProviderExecutors, ProviderProxyExecutor } from "../../core/types.ts";
2
+ export declare const executors: ProviderExecutors;
3
+ export declare const credentialValidators: CredentialValidators;
4
+ export declare const proxy: ProviderProxyExecutor;
@@ -0,0 +1,135 @@
1
+ import { compactObject, looseArray, optionalRecord, optionalString } from "../../core/cast.js";
2
+ import { defineApiKeyProviderExecutors, defineProviderProxy, providerInputError, ProviderRequestError, providerUserAgent, readProviderJsonBody, requiredResponseRecord, runProviderRequest, } from "../provider-runtime.js";
3
+ const service = "proworkflow";
4
+ const baseUrl = "https://api.proworkflow.com/api/v4";
5
+ const handlers = {
6
+ list_projects: (input, context) => request(context, "/projects", { query: buildListQuery(input) }),
7
+ get_project: (input, context) => request(context, `/projects/${positiveInteger(input.projectId, "projectId")}`, {
8
+ query: { fields: input.fields },
9
+ }),
10
+ update_project: (input, context) => request(context, `/projects/${positiveInteger(input.projectId, "projectId")}`, {
11
+ method: "PUT",
12
+ body: requireUpdateFields(compactObject({
13
+ title: input.title,
14
+ number: input.number,
15
+ description: input.description,
16
+ startdate: input.startDate,
17
+ duedate: input.dueDate,
18
+ completedate: input.completedDate,
19
+ priorityid: input.priorityId,
20
+ managerid: input.managerId,
21
+ companyid: input.companyId,
22
+ notification: input.notification,
23
+ })),
24
+ }),
25
+ list_project_items: (input, context) => request(context, "/projects/items", {
26
+ query: { ...buildListQuery(input), projectid: input.projectId },
27
+ }),
28
+ get_project_item: (input, context) => request(context, `/projects/items/${positiveInteger(input.itemId, "itemId")}`),
29
+ update_project_item: (input, context) => request(context, `/projects/items/${positiveInteger(input.itemId, "itemId")}`, {
30
+ method: "PUT",
31
+ body: requireUpdateFields(compactObject({
32
+ name: input.name,
33
+ code: input.code,
34
+ description: input.description,
35
+ startdate: input.startDate,
36
+ duedate: input.dueDate,
37
+ completedate: input.completedDate,
38
+ status: input.status,
39
+ priorityid: input.priorityId,
40
+ manualPercentageComplete: input.percentComplete,
41
+ })),
42
+ }),
43
+ };
44
+ export const executors = defineApiKeyProviderExecutors(service, handlers, {
45
+ skipDnsValidation: true,
46
+ });
47
+ export const credentialValidators = {
48
+ async apiKey(input, { fetcher, signal }) {
49
+ const payload = requiredResponseRecord(await request({ apiKey: input.apiKey, fetcher, signal }, "/settings/account", {}, "validate"), "ProWorkflow account settings response");
50
+ const data = requiredResponseRecord(payload.data, "ProWorkflow account settings data");
51
+ return {
52
+ profile: { accountId: "api_key", displayName: optionalString(data.accounturl) ?? "ProWorkflow API Key" },
53
+ grantedScopes: [],
54
+ metadata: { apiBaseUrl: baseUrl, validationEndpoint: "/settings/account" },
55
+ };
56
+ },
57
+ };
58
+ export const proxy = defineProviderProxy({
59
+ service,
60
+ baseUrl,
61
+ auth: { type: "api_key_header", name: "apikey" },
62
+ skipDnsValidation: true,
63
+ customizeRequest({ headers }) {
64
+ if (!headers.has("accept"))
65
+ headers.set("accept", "application/json");
66
+ },
67
+ });
68
+ async function request(context, path, options = {}, phase = "execute") {
69
+ return runProviderRequest({ signal: context.signal, label: "ProWorkflow" }, async (signal) => {
70
+ const url = new URL(`${baseUrl}${path}`);
71
+ for (const [key, value] of Object.entries(options.query ?? {})) {
72
+ if (value != null && value !== "")
73
+ url.searchParams.set(key, String(value));
74
+ }
75
+ const response = await context.fetcher(url, {
76
+ method: options.method,
77
+ headers: {
78
+ accept: "application/json",
79
+ apikey: context.apiKey,
80
+ "content-type": "application/json",
81
+ "user-agent": providerUserAgent,
82
+ },
83
+ body: options.body === undefined ? undefined : JSON.stringify(options.body),
84
+ signal,
85
+ });
86
+ const payload = await readProviderJsonBody(response, {
87
+ emptyBody: {},
88
+ invalidJsonMessage: "ProWorkflow returned invalid JSON",
89
+ trimEmptyBody: false,
90
+ });
91
+ if (!response.ok)
92
+ throw createError(response.status, payload, phase);
93
+ return requiredResponseRecord(payload, "ProWorkflow response");
94
+ });
95
+ }
96
+ function buildListQuery(input) {
97
+ if ((input.pageNumber == null) !== (input.pageSize == null)) {
98
+ throw providerInputError("pageNumber and pageSize must be provided together");
99
+ }
100
+ return {
101
+ fields: input.fields,
102
+ q: input.q,
103
+ status: input.status,
104
+ sortby: input.sortBy,
105
+ sortorder: input.sortOrder,
106
+ pagenumber: input.pageNumber,
107
+ pagesize: input.pageSize,
108
+ includetotalrows: input.includeTotalRows,
109
+ companyid: input.companyId,
110
+ };
111
+ }
112
+ function requireUpdateFields(body) {
113
+ if (Object.keys(body).length === 0)
114
+ throw providerInputError("at least one update field is required");
115
+ return body;
116
+ }
117
+ function positiveInteger(value, fieldName) {
118
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1) {
119
+ throw providerInputError(`${fieldName} must be a positive integer`);
120
+ }
121
+ return value;
122
+ }
123
+ function createError(status, payload, phase) {
124
+ const record = optionalRecord(payload);
125
+ const messages = looseArray(record?.data)
126
+ .filter((item) => typeof item === "string" && item.trim() !== "")
127
+ .join("; ");
128
+ const message = messages || optionalString(record?.message) || `ProWorkflow request failed with ${status}`;
129
+ if (status === 429)
130
+ return new ProviderRequestError(429, message, payload);
131
+ if (phase === "execute" && [400, 404, 422].includes(status)) {
132
+ return new ProviderRequestError(400, message, payload, "invalid_input");
133
+ }
134
+ return new ProviderRequestError(status || 500, message, payload);
135
+ }
@@ -120,6 +120,7 @@ export const executorModules = {
120
120
  baidu_maps: () => import("./baidu_maps/executors.js"),
121
121
  baidu_netdisk: () => import("./baidu_netdisk/executors.js"),
122
122
  baixiao: () => import("./baixiao/executors.js"),
123
+ baizhi_mcp: () => import("./baizhi_mcp/executors.js"),
123
124
  balldontlie_worldcup: () => import("./balldontlie_worldcup/executors.js"),
124
125
  bamboohr: () => import("./bamboohr/executors.js"),
125
126
  bannerbear: () => import("./bannerbear/executors.js"),
@@ -406,6 +407,7 @@ export const executorModules = {
406
407
  doubao_speech: () => import("./doubao_speech/executors.js"),
407
408
  dovetail: () => import("./dovetail/executors.js"),
408
409
  drata: () => import("./drata/executors.js"),
410
+ drawio_mcp: () => import("./drawio_mcp/executors.js"),
409
411
  drimify: () => import("./drimify/executors.js"),
410
412
  dropbox: () => import("./dropbox/executors.js"),
411
413
  dropbox_sign: () => import("./dropbox_sign/executors.js"),
@@ -510,6 +512,7 @@ export const executorModules = {
510
512
  formstack: () => import("./formstack/executors.js"),
511
513
  formstack_documents: () => import("./formstack_documents/executors.js"),
512
514
  foursquare: () => import("./foursquare/executors.js"),
515
+ framejet: () => import("./framejet/executors.js"),
513
516
  fraudlabspro: () => import("./fraudlabspro/executors.js"),
514
517
  freepik: () => import("./freepik/executors.js"),
515
518
  freshdesk: () => import("./freshdesk/executors.js"),
@@ -522,6 +525,7 @@ export const executorModules = {
522
525
  fullenrich: () => import("./fullenrich/executors.js"),
523
526
  fundzwatch: () => import("./fundzwatch/executors.js"),
524
527
  "fusion-api": () => import("./fusion-api/executors.js"),
528
+ futunn: () => import("./futunn/executors.js"),
525
529
  fuxin: () => import("./fuxin/executors.js"),
526
530
  gagelist: () => import("./gagelist/executors.js"),
527
531
  gainsight_nxt: () => import("./gainsight_nxt/executors.js"),
@@ -768,6 +772,7 @@ export const executorModules = {
768
772
  lightspeed_vt: () => import("./lightspeed_vt/executors.js"),
769
773
  line: () => import("./line/executors.js"),
770
774
  linear: () => import("./linear/executors.js"),
775
+ linear_mcp: () => import("./linear_mcp/executors.js"),
771
776
  linguapop: () => import("./linguapop/executors.js"),
772
777
  lingvanex_translation_api: () => import("./lingvanex_translation_api/executors.js"),
773
778
  lingxing_mcp: () => import("./lingxing_mcp/executors.js"),
@@ -870,6 +875,7 @@ export const executorModules = {
870
875
  mojo_helpdesk: () => import("./mojo_helpdesk/executors.js"),
871
876
  momentum_io: () => import("./momentum_io/executors.js"),
872
877
  monday: () => import("./monday/executors.js"),
878
+ moneyforward_mcp: () => import("./moneyforward_mcp/executors.js"),
873
879
  mongo_db_atlas_administration: () => import("./mongo_db_atlas_administration/executors.js"),
874
880
  monica_crm: () => import("./monica_crm/executors.js"),
875
881
  moonclerk: () => import("./moonclerk/executors.js"),
@@ -919,6 +925,7 @@ export const executorModules = {
919
925
  northbeam: () => import("./northbeam/executors.js"),
920
926
  northflank: () => import("./northflank/executors.js"),
921
927
  notion: () => import("./notion/executors.js"),
928
+ notion_mcp: () => import("./notion_mcp/executors.js"),
922
929
  novu: () => import("./novu/executors.js"),
923
930
  nozbe_teams: () => import("./nozbe_teams/executors.js"),
924
931
  npm: () => import("./npm/executors.js"),
@@ -931,6 +938,7 @@ export const executorModules = {
931
938
  ocrspace: () => import("./ocrspace/executors.js"),
932
939
  octave: () => import("./octave/executors.js"),
933
940
  octopus_deploy: () => import("./octopus_deploy/executors.js"),
941
+ odoo: () => import("./odoo/executors.js"),
934
942
  oksign: () => import("./oksign/executors.js"),
935
943
  okta: () => import("./okta/executors.js"),
936
944
  omise: () => import("./omise/executors.js"),
@@ -1052,6 +1060,7 @@ export const executorModules = {
1052
1060
  postgrid: () => import("./postgrid/executors.js"),
1053
1061
  postgrid_verify: () => import("./postgrid_verify/executors.js"),
1054
1062
  posthog: () => import("./posthog/executors.js"),
1063
+ postiz: () => import("./postiz/executors.js"),
1055
1064
  postman: () => import("./postman/executors.js"),
1056
1065
  postmark: () => import("./postmark/executors.js"),
1057
1066
  practitest: () => import("./practitest/executors.js"),
@@ -1072,6 +1081,7 @@ export const executorModules = {
1072
1081
  projectmanager: () => import("./projectmanager/executors.js"),
1073
1082
  promptlayer: () => import("./promptlayer/executors.js"),
1074
1083
  prospeo: () => import("./prospeo/executors.js"),
1084
+ proworkflow: () => import("./proworkflow/executors.js"),
1075
1085
  proxiedmail: () => import("./proxiedmail/executors.js"),
1076
1086
  prtg_classic: () => import("./prtg_classic/executors.js"),
1077
1087
  pubmed: () => import("./pubmed/executors.js"),
@@ -1494,6 +1504,7 @@ export const executorModules = {
1494
1504
  whop: () => import("./whop/executors.js"),
1495
1505
  winston_ai: () => import("./winston_ai/executors.js"),
1496
1506
  wire2air: () => import("./wire2air/executors.js"),
1507
+ wisburg: () => import("./wisburg/executors.js"),
1497
1508
  wise: () => import("./wise/executors.js"),
1498
1509
  wit_ai: () => import("./wit_ai/executors.js"),
1499
1510
  wiza: () => import("./wiza/executors.js"),
@@ -1542,6 +1553,7 @@ export const executorModules = {
1542
1553
  zep: () => import("./zep/executors.js"),
1543
1554
  zeplin: () => import("./zeplin/executors.js"),
1544
1555
  zerobounce: () => import("./zerobounce/executors.js"),
1556
+ zerotier: () => import("./zerotier/executors.js"),
1545
1557
  zhihu: () => import("./zhihu/executors.js"),
1546
1558
  zigpoll: () => import("./zigpoll/executors.js"),
1547
1559
  zip_archive_api: () => import("./zip_archive_api/executors.js"),
@@ -111,7 +111,7 @@ async function fetchOpenApi(fetcher) {
111
111
  try {
112
112
  const response = await fetcher(openApiUrl, {
113
113
  headers: { accept: "application/json" },
114
- redirect: "error",
114
+ redirect: "manual",
115
115
  signal: timeout.signal,
116
116
  });
117
117
  if (!response.ok)
@@ -95,7 +95,7 @@ async function requestJson(method, path, query, body, apiKey, fetcher, phase, pa
95
95
  method,
96
96
  headers,
97
97
  body: serializedBody,
98
- redirect: "error",
98
+ redirect: "manual",
99
99
  signal: timeout.signal,
100
100
  });
101
101
  const text = await readBoundedResponseText(response, responseMaxBytes, "Scrape Creators response");
@@ -15,7 +15,7 @@ const handlers = mapProviderActionHandlers(service, sellerspriteMcpActions, (_ac
15
15
  if (name === "call_tool") {
16
16
  return (input, context) => call(context, required(input.toolName, "toolName"), object(input.arguments));
17
17
  }
18
- return (input, context) => call(context, name, input);
18
+ return (input, context) => call(context, name, name === "traffic_extend" ? { ...input, queryType: input.queryType ?? 2 } : input);
19
19
  });
20
20
  export const executors = defineApiKeyProviderExecutors(service, handlers, {
21
21
  skipDnsValidation: true,
@@ -39,7 +39,7 @@ export const proxy = defineProviderProxy({
39
39
  auth: { type: "api_key_header", name: "secret-key" },
40
40
  skipDnsValidation: true,
41
41
  timeoutMs,
42
- redirect: "error",
42
+ redirect: "manual",
43
43
  customizeRequest({ url, headers }) {
44
44
  if (url.toString() !== endpoint) {
45
45
  throw new ProviderRequestError(400, "SellerSprite MCP proxy only supports the official /mcp endpoint");
@@ -705,7 +705,7 @@ const parameterDescriptionByToolAndName = {
705
705
  "keyword_miner.filterRootWord": "Root-word filter: 0 includes all keywords and 1 includes only root-word matches.",
706
706
  "keyword_miner.matchType": "Keyword match type: 2 for broad or 3 for phrase.",
707
707
  "traffic_extend.asinList": "Amazon ASINs to query, with at most 20 values.",
708
- "traffic_extend.queryType": "Variation query mode: 0 for all variations, 1 for the best-selling variation, or 2 for the current variation.",
708
+ "traffic_extend.queryType": "Variation query mode: 0 for all variations, 1 for the best-selling variation, or 2 for the current variation; defaults to 2.",
709
709
  "aba_research_weekly.searchModel": "Search model from 1 through 6: popular, changing, sustained growth, rapid growth, potential, or long-tail market.",
710
710
  "aba_research_monthly.searchModel": "Search model from 1 through 6: popular, changing, sustained growth, rapid growth, potential, or long-tail market.",
711
711
  "keyword_order.asins": "Amazon ASINs to query, with at most 20 values.",
@@ -788,7 +788,8 @@ function officialParameterSchema(toolName, name, type) {
788
788
  }
789
789
  const integerValues = integerValuesByToolAndParameter[parameterKey];
790
790
  if (type === "integer" && integerValues) {
791
- return { type: "integer", enum: integerValues, description };
791
+ const schema = { type: "integer", enum: integerValues, description };
792
+ return parameterKey === "traffic_extend.queryType" ? s.withDefault(schema, 2) : schema;
792
793
  }
793
794
  const stringValues = stringValuesByToolAndParameter[parameterKey];
794
795
  if (type === "string" && stringValues) {
@@ -1,8 +1,6 @@
1
- import { compactObject, looseArray, optionalRawString, rawStringOrNull } from "../../core/cast.js";
1
+ import { compactObject, looseArray, optionalRawString, optionalStringArray, rawStringOrNull } from "../../core/cast.js";
2
2
  import { ProviderRequestError } from "../provider-runtime.js";
3
- import { sentryProviderScopes } from "./scopes.js";
4
3
  export const sentryApiBaseUrl = "https://sentry.io/api/0/";
5
- const sentryCurrentUserUrl = `${sentryApiBaseUrl}users/me/`;
6
4
  export const sentryActionHandlers = {
7
5
  list_organization_integrations(input, context) {
8
6
  return sentryListOrganizationIntegrations(input, context.accessToken, context.fetcher);
@@ -63,8 +61,9 @@ export const sentryActionHandlers = {
63
61
  },
64
62
  };
65
63
  export async function validateSentryCredential(accessToken, fetcher) {
66
- const { payload } = await requestSentryJson(accessToken, sentryCurrentUserUrl, fetcher, {}, "validate");
67
- const user = asRecord(payload);
64
+ const { payload } = await requestSentryJson(accessToken, sentryApiBaseUrl, fetcher, {}, "validate");
65
+ const payloadRecord = asRecord(payload);
66
+ const user = asRecord(payloadRecord?.user);
68
67
  if (!user) {
69
68
  throw new ProviderRequestError(502, "sentry current user payload is invalid");
70
69
  }
@@ -78,9 +77,9 @@ export async function validateSentryCredential(accessToken, fetcher) {
78
77
  accountId: userId,
79
78
  displayName,
80
79
  },
81
- grantedScopes: sentryProviderScopes,
80
+ grantedScopes: optionalStringArray(asRecord(payloadRecord?.auth)?.scopes) ?? [],
82
81
  metadata: compactObject({
83
- validationEndpoint: "/users/me/",
82
+ validationEndpoint: "/",
84
83
  userId,
85
84
  username: optionalRawString(user.username),
86
85
  email: optionalRawString(user.email),