@jini-ai/agent-plugins 0.6.17 → 0.6.19

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 (335) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/NOTICE +14 -0
  3. package/README.md +35 -14
  4. package/charts-echarts/plugin.json +39 -0
  5. package/charts-echarts/skills/charts-echarts/SKILL.md +110 -0
  6. package/charts-recharts/plugin.json +32 -0
  7. package/charts-recharts/skills/charts-recharts/SKILL.md +108 -0
  8. package/cloudflare/NOTES.md +16 -0
  9. package/cloudflare/form-destinations/cloudflare-d1.mjs +9 -0
  10. package/cloudflare/lib/api.mjs +96 -0
  11. package/cloudflare/lib/assets.mjs +65 -0
  12. package/cloudflare/lib/dns.mjs +32 -0
  13. package/cloudflare/lib/domain-inventory.mjs +61 -0
  14. package/cloudflare/lib/domain-status.mjs +48 -0
  15. package/cloudflare/lib/domains.mjs +95 -0
  16. package/cloudflare/lib/forms.mjs +254 -0
  17. package/cloudflare/lib/pages-upload.mjs +51 -0
  18. package/cloudflare/lib/target.mjs +165 -0
  19. package/cloudflare/lib/workers-upload.mjs +48 -0
  20. package/cloudflare/lib/zones.mjs +25 -0
  21. package/cloudflare/mcp.json +4 -0
  22. package/cloudflare/plugin.json +96 -0
  23. package/cloudflare/skills/cloudflare/SKILL.md +57 -0
  24. package/cloudflare/skills/cloudflare/references/domains.md +31 -0
  25. package/cloudflare/skills/cloudflare/references/pages.md +18 -0
  26. package/cloudflare/skills/cloudflare/references/permissions.md +29 -0
  27. package/cloudflare/skills/cloudflare/references/troubleshooting.md +20 -0
  28. package/cloudflare/skills/cloudflare/references/workers.md +42 -0
  29. package/cloudflare/targets/cloudflare-pages.mjs +12 -0
  30. package/cloudflare/targets/cloudflare-workers.mjs +17 -0
  31. package/cloudflare/tovu-consent.json +6 -0
  32. package/cloudflare/tovu-deploy-targets.json +630 -0
  33. package/cloudflare/tovu-form-destinations.json +12 -0
  34. package/cloudflare/worker/forms-receiver.mjs +249 -0
  35. package/composio/mcp.json +10 -0
  36. package/composio/plugin.json +68 -0
  37. package/composio/skills/composio/SKILL.md +85 -0
  38. package/dist/core/identity-namespace.d.ts +12 -0
  39. package/dist/core/identity-namespace.js +20 -0
  40. package/dist/folder-zip-node.js +29 -7
  41. package/dist/lifecycle/bundled-digests.js +4 -3
  42. package/dist/lifecycle/install.d.ts +7 -0
  43. package/dist/lifecycle/install.js +45 -3
  44. package/dist/lifecycle/manifest.d.ts +2 -2
  45. package/dist/lifecycle/manifest.js +5 -3
  46. package/dist/lifecycle/node.js +2 -0
  47. package/dist/lifecycle/persistent-state.js +1 -1
  48. package/dist/lifecycle/ports.d.ts +8 -0
  49. package/dist/lifecycle/seed-bundled.js +4 -1
  50. package/dist/manifest.d.ts +1 -1
  51. package/dist/manifest.js +3 -2
  52. package/fly/deploy-configs/fly.mjs +115 -0
  53. package/fly/deploy-ops/fly.mjs +102 -0
  54. package/fly/mcp.json +4 -0
  55. package/fly/plugin.json +81 -0
  56. package/fly/scripts/render-deploy-workflow.mjs +150 -0
  57. package/fly/skills/fly/SKILL.md +43 -0
  58. package/fly/skills/fly/references/fly-deploy.template.yml +117 -0
  59. package/fly/skills/fly/references/fly.template.toml +81 -0
  60. package/fly/tovu-credential-schemes.json +11 -0
  61. package/fly/tovu-deploy-configs.json +21 -0
  62. package/fly/tovu-deploy-ops.json +14 -0
  63. package/github/deploy-ops/github-actions.mjs +164 -0
  64. package/github/deployments/github.mjs +415 -0
  65. package/github/mcp.json +4 -0
  66. package/github/plugin.json +105 -0
  67. package/github/skills/github/SKILL.md +249 -0
  68. package/github/skills/github/references/actions.md +224 -0
  69. package/github/skills/github/references/auth-and-tokens.md +140 -0
  70. package/github/skills/github/references/repo-files.md +135 -0
  71. package/github/skills/github/references/site-backup.md +159 -0
  72. package/github/skills/github/references/source-control.md +123 -0
  73. package/github/source-control/backup-push.mjs +242 -0
  74. package/github/source-control/commit-site.mjs +459 -0
  75. package/github/source-control/github.mjs +93 -0
  76. package/github/source-control/write-files.mjs +468 -0
  77. package/github/tovu-deploy-ops.json +13 -0
  78. package/github/tovu-source-control.json +117 -0
  79. package/github-pages/NOTES.md +19 -0
  80. package/github-pages/mcp.json +4 -0
  81. package/github-pages/plugin.json +48 -0
  82. package/github-pages/skills/github-pages/SKILL.md +44 -0
  83. package/github-pages/targets/github-pages.mjs +543 -0
  84. package/github-pages/tovu-deploy-targets.json +327 -0
  85. package/google-login/exports/google-g.svg +1 -0
  86. package/google-login/exports/sign-in-button.css +68 -0
  87. package/google-login/exports/sign-in-button.html +4 -0
  88. package/google-login/mcp.json +4 -0
  89. package/google-login/plugin.json +59 -0
  90. package/google-login/skills/google-login/SKILL.md +96 -0
  91. package/google-login/tovu-login-providers.json +21 -0
  92. package/google-workspace/README.md +132 -0
  93. package/google-workspace/form-destinations/README.md +87 -0
  94. package/google-workspace/form-destinations/dedupe.mjs +43 -0
  95. package/google-workspace/form-destinations/delivery-result.mjs +69 -0
  96. package/google-workspace/form-destinations/mapping.mjs +152 -0
  97. package/google-workspace/form-destinations/sheets.mjs +202 -0
  98. package/google-workspace/lib/auth.mjs +81 -0
  99. package/google-workspace/lib/drive-files.mjs +54 -0
  100. package/google-workspace/lib/form-destination-settings.mjs +72 -0
  101. package/google-workspace/lib/http.mjs +168 -0
  102. package/google-workspace/lib/picker-flow.mjs +171 -0
  103. package/google-workspace/lib/picker-selection.mjs +107 -0
  104. package/google-workspace/lib/product-state.mjs +93 -0
  105. package/google-workspace/lib/request-policy.mjs +163 -0
  106. package/google-workspace/lib/sheets-a1.mjs +79 -0
  107. package/google-workspace/lib/sheets-admin-csv.mjs +82 -0
  108. package/google-workspace/lib/sheets-admin-request-kinds.mjs +183 -0
  109. package/google-workspace/lib/sheets-client.mjs +286 -0
  110. package/google-workspace/lib/surface-actions.mjs +107 -0
  111. package/google-workspace/mcp.json +4 -0
  112. package/google-workspace/plugin.json +77 -0
  113. package/google-workspace/products.json +12 -0
  114. package/google-workspace/skills/google-workspace/SKILL.md +82 -0
  115. package/google-workspace/skills/google-workspace/references/connection.md +102 -0
  116. package/google-workspace/skills/google-workspace/references/form-delivery.md +50 -0
  117. package/google-workspace/skills/google-workspace/references/sheets.md +149 -0
  118. package/google-workspace/skills/google-workspace/references/troubleshooting.md +31 -0
  119. package/google-workspace/tools/account-info.mjs +18 -0
  120. package/google-workspace/tools/sheets/README.md +54 -0
  121. package/google-workspace/tools/sheets/copy-tab.mjs +23 -0
  122. package/google-workspace/tools/sheets/copy.mjs +23 -0
  123. package/google-workspace/tools/sheets/create.mjs +35 -0
  124. package/google-workspace/tools/sheets/find-replace.mjs +38 -0
  125. package/google-workspace/tools/sheets/find.mjs +52 -0
  126. package/google-workspace/tools/sheets/get-by-data-filter.mjs +23 -0
  127. package/google-workspace/tools/sheets/get.mjs +22 -0
  128. package/google-workspace/tools/sheets/values-append.mjs +27 -0
  129. package/google-workspace/tools/sheets/values-batch-clear.mjs +20 -0
  130. package/google-workspace/tools/sheets/values-batch-get.mjs +20 -0
  131. package/google-workspace/tools/sheets/values-batch-update.mjs +29 -0
  132. package/google-workspace/tools/sheets/values-by-data-filter.mjs +62 -0
  133. package/google-workspace/tools/sheets/values-clear.mjs +20 -0
  134. package/google-workspace/tools/sheets/values-get.mjs +21 -0
  135. package/google-workspace/tools/sheets/values-update.mjs +26 -0
  136. package/google-workspace/tools/sheets-admin/README.md +45 -0
  137. package/google-workspace/tools/sheets-admin/basic-filter.mjs +32 -0
  138. package/google-workspace/tools/sheets-admin/batch-update.mjs +25 -0
  139. package/google-workspace/tools/sheets-admin/developer-metadata.mjs +28 -0
  140. package/google-workspace/tools/sheets-admin/export-csv.mjs +67 -0
  141. package/google-workspace/tools/sheets-admin/filter-views.mjs +38 -0
  142. package/google-workspace/tools/sheets-admin/format.mjs +70 -0
  143. package/google-workspace/tools/sheets-admin/named-ranges.mjs +42 -0
  144. package/google-workspace/tools/sheets-admin/open-existing.mjs +34 -0
  145. package/google-workspace/tools/sheets-admin/protected-ranges-get.mjs +18 -0
  146. package/google-workspace/tools/sheets-admin/sort.mjs +18 -0
  147. package/google-workspace/tools/sheets-admin/tab-modify.mjs +36 -0
  148. package/google-workspace/tovu-admin-surfaces.json +63 -0
  149. package/google-workspace/tovu-agent-tools.json +1178 -0
  150. package/google-workspace/tovu-connections.json +35 -0
  151. package/google-workspace/tovu-form-destinations.json +10 -0
  152. package/google-workspace/ui/README.md +73 -0
  153. package/google-workspace/ui/connection-panel.handler.mjs +167 -0
  154. package/google-workspace/ui/connection-panel.html +17 -0
  155. package/google-workspace/ui/connection-panel.mjs +189 -0
  156. package/google-workspace/ui/connection-view.mjs +120 -0
  157. package/google-workspace/ui/destination-panel.handler.mjs +106 -0
  158. package/google-workspace/ui/destination-panel.html +17 -0
  159. package/google-workspace/ui/destination-panel.mjs +150 -0
  160. package/google-workspace/ui/dom.mjs +140 -0
  161. package/google-workspace/ui/panel.css +170 -0
  162. package/google-workspace/ui/picker-flow.mjs +87 -0
  163. package/google-workspace/ui/picker-view.mjs +44 -0
  164. package/google-workspace/ui/picker.handler.mjs +56 -0
  165. package/google-workspace/ui/picker.html +17 -0
  166. package/google-workspace/ui/picker.mjs +88 -0
  167. package/google-workspace/ui/surface-client.mjs +227 -0
  168. package/higgsfield-media/mcp.json +9 -0
  169. package/higgsfield-media/plugin.json +109 -0
  170. package/higgsfield-media/skills/higgsfield-media/SKILL.md +325 -0
  171. package/higgsfield-media/skills/higgsfield-media/references/failure-modes.md +116 -0
  172. package/higgsfield-media/skills/higgsfield-media/references/models-and-plan-gates.md +142 -0
  173. package/jev/mcp.json +4 -0
  174. package/jev/plugin.json +44 -0
  175. package/jev/skills/jev/SKILL.md +308 -0
  176. package/jev/skills/jev/references/cookbooks.md +197 -0
  177. package/jev/skills/jev/references/jaggedness.md +135 -0
  178. package/jev/skills/jev/references/javascript-sdk.md +146 -0
  179. package/jev/skills/jev/references/patterns.md +123 -0
  180. package/jev/skills/jev/references/primitives-reference.md +187 -0
  181. package/langfuse/plugin.json +22 -0
  182. package/meilisearch/mcp.json +4 -0
  183. package/meilisearch/plugin.json +54 -0
  184. package/meilisearch/providers/meilisearch.mjs +651 -0
  185. package/meilisearch/skills/meilisearch/SKILL.md +43 -0
  186. package/meilisearch/tovu-search-providers.json +10 -0
  187. package/netlify/NOTES.md +13 -0
  188. package/netlify/mcp.json +4 -0
  189. package/netlify/plugin.json +47 -0
  190. package/netlify/skills/netlify/SKILL.md +39 -0
  191. package/netlify/targets/netlify.mjs +384 -0
  192. package/netlify/tovu-consent.json +6 -0
  193. package/netlify/tovu-deploy-targets.json +163 -0
  194. package/opentelemetry/mcp.json +4 -0
  195. package/opentelemetry/plugin.json +52 -0
  196. package/opentelemetry/skills/opentelemetry/SKILL.md +39 -0
  197. package/package.json +161 -6
  198. package/posthog/mcp.json +4 -0
  199. package/posthog/plugin.json +46 -0
  200. package/posthog/skills/posthog/SKILL.md +36 -0
  201. package/railway/deploy-configs/railway.mjs +135 -0
  202. package/railway/deploy-ops/railway.mjs +167 -0
  203. package/railway/mcp.json +4 -0
  204. package/railway/plugin.json +45 -0
  205. package/railway/skills/railway/SKILL.md +66 -0
  206. package/railway/tovu-deploy-configs.json +16 -0
  207. package/railway/tovu-deploy-ops.json +11 -0
  208. package/render/deploy-configs/render.mjs +141 -0
  209. package/render/deploy-ops/render.mjs +152 -0
  210. package/render/mcp.json +4 -0
  211. package/render/plugin.json +47 -0
  212. package/render/skills/render/SKILL.md +63 -0
  213. package/render/tovu-deploy-configs.json +16 -0
  214. package/render/tovu-deploy-ops.json +11 -0
  215. package/resend/NOTES.md +52 -0
  216. package/resend/adapters/resend.mjs +161 -0
  217. package/resend/lib/domains.mjs +137 -0
  218. package/resend/lib/errors.mjs +25 -0
  219. package/resend/lib/feedback.mjs +118 -0
  220. package/resend/mcp.json +13 -0
  221. package/resend/plugin.json +192 -0
  222. package/resend/skills/resend/SKILL.md +107 -0
  223. package/resend/tovu-mail-adapters.json +22 -0
  224. package/s3-compatible/NOTES.md +11 -0
  225. package/s3-compatible/mcp.json +4 -0
  226. package/s3-compatible/object-stores/s3-compatible.mjs +287 -0
  227. package/s3-compatible/plugin.json +56 -0
  228. package/s3-compatible/skills/s3-compatible/SKILL.md +39 -0
  229. package/s3-compatible/targets/s3-compatible.mjs +1054 -0
  230. package/s3-compatible/tovu-deploy-targets.json +432 -0
  231. package/s3-compatible/tovu-object-stores.json +29 -0
  232. package/sentry/mcp.json +4 -0
  233. package/sentry/plugin.json +49 -0
  234. package/sentry/skills/sentry/SKILL.md +34 -0
  235. package/shopify/mcp.json +4 -0
  236. package/shopify/plugin.json +22 -0
  237. package/shopify/skills/shopify/SKILL.md +103 -0
  238. package/shopify/skills/shopify/references/catalog-sync.md +74 -0
  239. package/shopify/skills/shopify/references/domains.md +26 -0
  240. package/shopify/skills/shopify/references/live-storefront.md +34 -0
  241. package/shopify/skills/shopify/references/storefront-snippets.md +21 -0
  242. package/site-compliance/mcp.json +4 -0
  243. package/site-compliance/plugin.json +34 -0
  244. package/site-compliance/skills/site-compliance/SKILL.md +220 -0
  245. package/site-compliance/skills/site-compliance/references/ccpa-cpra.md +115 -0
  246. package/site-compliance/skills/site-compliance/references/gdpr-eu-uk.md +143 -0
  247. package/site-compliance/skills/site-compliance/references/wcag-2-2.md +129 -0
  248. package/site-import/mcp.json +4 -0
  249. package/site-import/plugin.json +41 -0
  250. package/site-import/skills/site-import/SKILL.md +232 -0
  251. package/site-import/skills/site-import/references/content-mapping.md +166 -0
  252. package/site-import/skills/site-import/references/discovery-and-classification.md +117 -0
  253. package/site-import/skills/site-import/references/theme-extraction.md +34 -0
  254. package/slide-design/com.anthropic.claude-code/hooks/hooks.json +4 -0
  255. package/slide-design/mcp.json +4 -0
  256. package/slide-design/plugin.json +26 -0
  257. package/slide-design/skills/slide-design/SKILL.md +103 -0
  258. package/slide-design/skills/slide-design/references/charts-and-exhibits.md +100 -0
  259. package/slide-design/skills/slide-design/references/html-deck.md +175 -0
  260. package/slide-design/skills/slide-design/references/layout-and-style.md +131 -0
  261. package/slide-design/skills/slide-design/references/review.md +93 -0
  262. package/slide-design/skills/slide-design/references/storyline.md +118 -0
  263. package/stripe/plugin.json +22 -0
  264. package/supabase/mcp.json +26 -0
  265. package/supabase/plugin.json +78 -0
  266. package/supabase/skills/supabase/SKILL.md +169 -0
  267. package/supabase/skills/supabase/references/failure-modes.md +101 -0
  268. package/ui-ux-design/CHANGELOG.md +28 -0
  269. package/ui-ux-design/LICENSE +201 -0
  270. package/ui-ux-design/NOTICE +14 -0
  271. package/ui-ux-design/README.md +62 -0
  272. package/ui-ux-design/com.anthropic.claude-code/hooks/hooks.json +4 -0
  273. package/ui-ux-design/mcp.json +4 -0
  274. package/ui-ux-design/plugin.json +26 -0
  275. package/ui-ux-design/skills/frontend-accessibility/SKILL.md +60 -0
  276. package/ui-ux-design/skills/gstack-design/SKILL.md +53 -0
  277. package/ui-ux-design/skills/gstack-design/references/consultation.md +30 -0
  278. package/ui-ux-design/skills/gstack-design/references/html.md +29 -0
  279. package/ui-ux-design/skills/gstack-design/references/review.md +28 -0
  280. package/ui-ux-design/skills/gstack-design/references/shotgun.md +33 -0
  281. package/ui-ux-design/skills/gstack-design/references/upstream-notes.md +23 -0
  282. package/ui-ux-design/skills/interface-design/ORIGINAL.md +16 -0
  283. package/ui-ux-design/skills/interface-design/SKILL.md +41 -0
  284. package/ui-ux-design/skills/interface-design/references/commands/audit.md +40 -0
  285. package/ui-ux-design/skills/interface-design/references/commands/critique.md +21 -0
  286. package/ui-ux-design/skills/interface-design/references/commands/extract.md +34 -0
  287. package/ui-ux-design/skills/interface-design/references/commands/init.md +31 -0
  288. package/ui-ux-design/skills/interface-design/references/commands/status.md +22 -0
  289. package/ui-ux-design/skills/interface-design/references/examples/system-precision.md +29 -0
  290. package/ui-ux-design/skills/interface-design/references/examples/system-warmth.md +29 -0
  291. package/ui-ux-design/skills/interface-design/references/system-template.md +57 -0
  292. package/ui-ux-design/skills/shadcn-ui/README.md +244 -0
  293. package/ui-ux-design/skills/shadcn-ui/SKILL.md +333 -0
  294. package/ui-ux-design/skills/shadcn-ui/examples/auth-layout.tsx +177 -0
  295. package/ui-ux-design/skills/shadcn-ui/examples/data-table.tsx +313 -0
  296. package/ui-ux-design/skills/shadcn-ui/examples/form-pattern.tsx +177 -0
  297. package/ui-ux-design/skills/shadcn-ui/resources/component-catalog.md +481 -0
  298. package/ui-ux-design/skills/shadcn-ui/resources/customization-guide.md +516 -0
  299. package/ui-ux-design/skills/shadcn-ui/resources/migration-guide.md +463 -0
  300. package/ui-ux-design/skills/shadcn-ui/resources/setup-guide.md +412 -0
  301. package/ui-ux-design/skills/shadcn-ui/scripts/verify-setup.sh +134 -0
  302. package/ui-ux-design/skills/ui-ux-design/SKILL.md +171 -0
  303. package/ui-ux-design/skills/ui-ux-design/references/brand-and-voice.md +78 -0
  304. package/ui-ux-design/skills/ui-ux-design/references/chrome-mobile-test-matrix.md +137 -0
  305. package/ui-ux-design/skills/ui-ux-design/references/components-and-states.md +112 -0
  306. package/ui-ux-design/skills/ui-ux-design/references/delight-and-motion.md +54 -0
  307. package/ui-ux-design/skills/ui-ux-design/references/foundations.md +145 -0
  308. package/ui-ux-design/skills/ui-ux-design/references/inclusive-ai-imagery.md +57 -0
  309. package/ui-ux-design/skills/ui-ux-design/references/kole-jain-uiux-concepts.md +104 -0
  310. package/ui-ux-design/skills/ui-ux-design/references/kuinetic-reference.md +184 -0
  311. package/ui-ux-design/skills/ui-ux-design/references/openai-frontend-skill.md +139 -0
  312. package/ui-ux-design/skills/ui-ux-design/references/premium-ui.md +55 -0
  313. package/ui-ux-design/skills/ui-ux-design/references/research-and-validation.md +88 -0
  314. package/ui-ux-design/skills/ui-ux-design/references/sam-crawford-premium-websites.md +103 -0
  315. package/ui-ux-design/skills/ui-ux-design/references/self-made-web-designer-core-skills.md +119 -0
  316. package/ui-ux-design/skills/ui-ux-design/references/ui-animation.md +173 -0
  317. package/ui-ux-design/skills/ui-ux-design/references/ui-loop.md +234 -0
  318. package/ui-ux-design/skills/ui-ux-design/references/visual-storytelling.md +54 -0
  319. package/ui-ux-design/skills/vercel-web-design-guidelines/SKILL.md +39 -0
  320. package/ui-ux-design/skills/web-compliance/SKILL.md +134 -0
  321. package/ui-ux-design/skills/web-compliance/references/audit-evidence.md +59 -0
  322. package/vercel/NOTES.md +23 -0
  323. package/vercel/mcp.json +4 -0
  324. package/vercel/object-stores/vercel-blob.mjs +147 -0
  325. package/vercel/plugin.json +47 -0
  326. package/vercel/skills/vercel/SKILL.md +48 -0
  327. package/vercel/targets/vercel.mjs +586 -0
  328. package/vercel/tovu-consent.json +6 -0
  329. package/vercel/tovu-deploy-targets.json +219 -0
  330. package/vercel/tovu-object-stores.json +10 -0
  331. package/wordpress/NOTES.md +33 -0
  332. package/wordpress/plugin.json +30 -0
  333. package/wordpress/skills/wordpress/SKILL.md +43 -0
  334. package/wordpress/skills/wordpress/references/free-site-redirect.md +46 -0
  335. package/wordpress/skills/wordpress/references/subdomain.md +66 -0
@@ -0,0 +1,25 @@
1
+ // @ts-check
2
+
3
+ /** A non-empty string field of a parsed body, else the fallback. @param {unknown} value @param {string} fallback */
4
+ function nonEmpty(value, fallback) {
5
+ return typeof value === "string" && value !== "" ? value : fallback;
6
+ }
7
+
8
+ /**
9
+ * Resend's error body is `{statusCode, message, name}`; `name` becomes `errorCode`. A non-JSON body
10
+ * (a proxy error page) still yields a usable result. Never throws.
11
+ * @param {{ status: number, bodyText: string }} required
12
+ * @param {{ fallback?: { errorCode: string, message: string } }} [options]
13
+ * @returns {{ errorCode: string, message: string }}
14
+ */
15
+ export function parseErrorBody({ status, bodyText }, options = {}) {
16
+ const fallback = options.fallback ?? { errorCode: `HTTP_${status}`, message: bodyText || `Resend responded with HTTP ${status}` };
17
+ try {
18
+ const parsed = JSON.parse(bodyText);
19
+ return { errorCode: nonEmpty(parsed?.name, fallback.errorCode), message: nonEmpty(parsed?.message, fallback.message) };
20
+ } catch {
21
+ // Non-JSON body: keep the raw text above.
22
+ return fallback;
23
+ }
24
+ }
25
+
@@ -0,0 +1,118 @@
1
+ // @ts-check
2
+ import { createHash, createHmac, timingSafeEqual } from 'node:crypto';
3
+
4
+ /**
5
+ * @file Resend delivery feedback: Svix webhook signature check and event normalization
6
+ * (Jini `MailFeedbackParser`). Neither function throws; a bad input is `false` or `{ error }`.
7
+ *
8
+ * Svix signs `${svix-id}.${svix-timestamp}.${raw body}` with HMAC-SHA256 under the base64 key after
9
+ * the `whsec_` prefix, and sends space-separated `v1,<base64>` signatures (several while Resend
10
+ * rotates its own key). Any of our `secrets` may match, so the operator can rotate theirs too.
11
+ * `sourceContext.module` is `unknown`: sends carry no Resend tags yet, so the originating module is
12
+ * not in the payload; suppression does not need it.
13
+ *
14
+ * @typedef {{ workspaceId: string, providerMessageId: string, sourceContext: { module: string },
15
+ * kind: 'delivered' | 'bounced' | 'complained', eventId: string, recipient: string, hardBounce: boolean,
16
+ * occurredAt: string }} FeedbackEvent
17
+ */
18
+
19
+ /** Svix's replay window: a captured request older (or newer) than this is refused. */
20
+ export const SVIX_TOLERANCE_SECONDS = 5 * 60;
21
+
22
+ /** Resend event type to normalized kind; every other type (sent, opened, clicked, delayed) is ignored. */
23
+ const KINDS = /** @type {const} */ ({ 'email.bounced': 'bounced', 'email.complained': 'complained', 'email.delivered': 'delivered' });
24
+
25
+ /** @param {string} secret @returns {Buffer} */
26
+ function secretKey(secret) {
27
+ return Buffer.from(secret.startsWith('whsec_') ? secret.slice('whsec_'.length) : secret, 'base64');
28
+ }
29
+
30
+ /** The `v1` signatures of a `svix-signature` header, decoded. @param {string} header @returns {Buffer[]} */
31
+ function v1Signatures(header) {
32
+ return header.split(' ').map((entry) => entry.split(',')).filter(([version, value]) => version === 'v1' && value)
33
+ .map(([, value]) => Buffer.from(/** @type {string} */ (value), 'base64'));
34
+ }
35
+
36
+ /** Constant-time compare; differing lengths never match. @param {Buffer} a @param {Buffer} b */
37
+ function sameBytes(a, b) {
38
+ return a.length === b.length && timingSafeEqual(a, b);
39
+ }
40
+
41
+ /**
42
+ * @param {{ rawBody: Uint8Array, headers: Readonly<Record<string, string>>, secrets: readonly string[], now: number }} required
43
+ * @returns {boolean}
44
+ */
45
+ export function verify({ rawBody, headers, secrets, now }) {
46
+ try {
47
+ const id = headers['svix-id'];
48
+ const timestamp = headers['svix-timestamp'];
49
+ const signature = headers['svix-signature'];
50
+ if (!id || !timestamp || !signature || !/^\d+$/.test(timestamp)) return false;
51
+ if (Math.abs(now / 1000 - Number(timestamp)) > SVIX_TOLERANCE_SECONDS) return false;
52
+ const signed = Buffer.concat([Buffer.from(`${id}.${timestamp}.`), Buffer.from(rawBody)]);
53
+ const offered = v1Signatures(signature);
54
+ return secrets.some((secret) => {
55
+ const expected = createHmac('sha256', secretKey(secret)).update(signed).digest();
56
+ return offered.some((candidate) => sameBytes(candidate, expected));
57
+ });
58
+ } catch {
59
+ return false;
60
+ }
61
+ }
62
+
63
+ /** @param {unknown} value @returns {value is Record<string, any>} */
64
+ function isObject(value) {
65
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
66
+ }
67
+
68
+ /** Resend's `bounce.type`: `Permanent` (or `hard`) is a hard bounce; `Transient`/`Undetermined` are not. @param {any} data */
69
+ function isHardBounce(data) {
70
+ const type = isObject(data.bounce) ? String(data.bounce.type ?? '').toLowerCase() : '';
71
+ return type === 'permanent' || type === 'hard';
72
+ }
73
+
74
+ /** @param {unknown} to @returns {string[]} */
75
+ function recipientsOf(to) {
76
+ const list = Array.isArray(to) ? to : [to];
77
+ return list.filter((entry) => typeof entry === 'string' && entry.trim() !== '').map((entry) => entry.trim().toLowerCase());
78
+ }
79
+
80
+ /** A non-empty string, else undefined. @param {unknown} value */
81
+ const nonEmpty = (value) => (typeof value === 'string' && value !== '' ? value : undefined);
82
+
83
+ /**
84
+ * The event id: Svix's `svix-id` (stable across its retries of one message), else the payload's own
85
+ * `id`, else a hash of the exact bytes (a retry resends identical bytes, so it hashes the same) for a
86
+ * host that passes no headers. Per recipient, so one event to many stays unique in the inbox.
87
+ * @param {any} payload @param {Uint8Array} rawBody @param {Readonly<Record<string, string>> | undefined} headers
88
+ */
89
+ function baseIdOf(payload, rawBody, headers) {
90
+ return nonEmpty(headers?.['svix-id']) ?? nonEmpty(payload.id) ?? createHash('sha256').update(rawBody).digest('hex');
91
+ }
92
+
93
+ /**
94
+ * @param {{ rawBody: Uint8Array, workspaceId: string, headers?: Readonly<Record<string, string>> }} required
95
+ * @returns {readonly FeedbackEvent[] | { error: string }}
96
+ */
97
+ export function parse({ rawBody, workspaceId, headers }) {
98
+ let payload;
99
+ try {
100
+ payload = JSON.parse(Buffer.from(rawBody).toString('utf8'));
101
+ } catch {
102
+ return { error: 'body is not JSON' };
103
+ }
104
+ if (!isObject(payload) || typeof payload.type !== 'string' || !isObject(payload.data)) return { error: 'not a Resend webhook event' };
105
+ const kind = KINDS[/** @type {keyof typeof KINDS} */ (payload.type)];
106
+ if (!kind) return [];
107
+ const { data } = payload;
108
+ const recipients = recipientsOf(data.to);
109
+ const occurredAt = String(payload.created_at ?? data.created_at ?? new Date().toISOString());
110
+ const base = baseIdOf(payload, rawBody, headers);
111
+ return recipients.map((recipient) => ({
112
+ workspaceId, providerMessageId: typeof data.email_id === 'string' ? data.email_id : '', sourceContext: { module: 'unknown' },
113
+ kind, eventId: recipients.length > 1 ? `${base}:${recipient}` : base, recipient,
114
+ hardBounce: kind === 'bounced' && isHardBounce(data), occurredAt,
115
+ }));
116
+ }
117
+
118
+ export const feedback = { verify, parse };
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
3
+ "mcpServers": {
4
+ "resend": {
5
+ "type": "streamable-http",
6
+ "url": "https://mcp.resend.com/mcp",
7
+ "tovuTokenAuth": {
8
+ "helpUrl": "https://resend.com/api-keys",
9
+ "probeUrl": "https://api.resend.com/domains"
10
+ }
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,192 @@
1
+ {
2
+ "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
+ "name": "resend",
4
+ "version": "0.2.1",
5
+ "description": "Sends the site's email (sign-in links, form notifications, newsletters) through Resend's hosted email API, and connects the assistant to Resend's own hosted MCP server for work on the Resend account itself: domains and their DNS verification, broadcasts, contacts, segments, topics, templates, logs and usage. Ships the mail adapter (a host loads it only when the host shipped it) and the know-how to set both up: a sending key saved through credential_save for site mail, and a separate Full access key saved through the secure account card for the account tools.",
6
+ "author": "Tovu",
7
+ "license": "Apache-2.0",
8
+ "extensions": {
9
+ "tovu": {
10
+ "vendorAliases": ["resend.com", "HttpApiMailerAdapter"],
11
+ "summary": "Sends your site's emails through Resend, and lets the assistant manage your Resend account: domains, broadcasts and contacts.",
12
+ "id": "tovu/resend",
13
+ "provides": [
14
+ "outbound-mail"
15
+ ],
16
+ "mcpServers": {
17
+ "resend": {
18
+ "tovuAuthMode": "none",
19
+ "tovuDefaultTools": {
20
+ "allow": [
21
+ "list-domains",
22
+ "get-domain",
23
+ "get-domain-claim",
24
+ "list-emails",
25
+ "get-email",
26
+ "get-email-metrics",
27
+ "list-received-emails",
28
+ "get-received-email",
29
+ "list-received-email-attachments",
30
+ "get-received-email-attachment",
31
+ "list-broadcasts",
32
+ "get-broadcast",
33
+ "list-broadcast-recipients",
34
+ "list-broadcast-clicked-links",
35
+ "list-contacts",
36
+ "get-contact",
37
+ "list-contact-segments",
38
+ "list-contact-topics",
39
+ "list-segments",
40
+ "get-segment",
41
+ "list-topics",
42
+ "get-topic",
43
+ "list-contact-properties",
44
+ "get-contact-property",
45
+ "list-templates",
46
+ "get-template",
47
+ "list-webhooks",
48
+ "get-webhook",
49
+ "list-webhook-events",
50
+ "get-webhook-event",
51
+ "list-webhook-event-attempts",
52
+ "list-api-keys",
53
+ "list-logs",
54
+ "get-log",
55
+ "get-usage",
56
+ "list-suppressions",
57
+ "get-suppression",
58
+ "create-domain",
59
+ "update-domain",
60
+ "verify-domain",
61
+ "create-domain-claim",
62
+ "verify-domain-claim",
63
+ "send-email",
64
+ "send-batch-emails",
65
+ "cancel-email",
66
+ "update-email",
67
+ "create-broadcast",
68
+ "update-broadcast",
69
+ "compose-broadcast",
70
+ "cancel-broadcast",
71
+ "create-contact",
72
+ "update-contact",
73
+ "add-contact-to-segment",
74
+ "update-contact-topics",
75
+ "create-segment",
76
+ "update-segment",
77
+ "create-topic",
78
+ "update-topic",
79
+ "create-template",
80
+ "update-template",
81
+ "compose-template",
82
+ "publish-template"
83
+ ],
84
+ "write": [
85
+ "create-domain",
86
+ "update-domain",
87
+ "verify-domain",
88
+ "create-domain-claim",
89
+ "verify-domain-claim",
90
+ "send-email",
91
+ "send-batch-emails",
92
+ "cancel-email",
93
+ "update-email",
94
+ "create-broadcast",
95
+ "update-broadcast",
96
+ "compose-broadcast",
97
+ "cancel-broadcast",
98
+ "create-contact",
99
+ "update-contact",
100
+ "add-contact-to-segment",
101
+ "update-contact-topics",
102
+ "create-segment",
103
+ "update-segment",
104
+ "create-topic",
105
+ "update-topic",
106
+ "create-template",
107
+ "update-template",
108
+ "compose-template",
109
+ "publish-template"
110
+ ],
111
+ "read": [
112
+ "list-domains",
113
+ "get-domain",
114
+ "get-domain-claim",
115
+ "list-emails",
116
+ "get-email",
117
+ "get-email-metrics",
118
+ "list-received-emails",
119
+ "get-received-email",
120
+ "list-received-email-attachments",
121
+ "get-received-email-attachment",
122
+ "list-broadcasts",
123
+ "get-broadcast",
124
+ "list-broadcast-recipients",
125
+ "list-broadcast-clicked-links",
126
+ "list-contacts",
127
+ "get-contact",
128
+ "list-contact-segments",
129
+ "list-contact-topics",
130
+ "list-segments",
131
+ "get-segment",
132
+ "list-topics",
133
+ "get-topic",
134
+ "list-contact-properties",
135
+ "get-contact-property",
136
+ "list-templates",
137
+ "get-template",
138
+ "list-webhooks",
139
+ "get-webhook",
140
+ "list-webhook-events",
141
+ "get-webhook-event",
142
+ "list-webhook-event-attempts",
143
+ "list-api-keys",
144
+ "list-logs",
145
+ "get-log",
146
+ "get-usage",
147
+ "list-suppressions",
148
+ "get-suppression"
149
+ ]
150
+ }
151
+ }
152
+ },
153
+ "credentialCards": [
154
+ {
155
+ "target": "resend-mcp",
156
+ "title": "Connect Resend with a Full access key",
157
+ "label": "Resend account",
158
+ "category": "ops",
159
+ "intro": "Let the assistant add and verify your email domain in Resend. This saves a separate account key and keeps your site's sending key.",
160
+ "usedFor": [
161
+ "Adds and verifies your email domain",
162
+ "Manages contacts and broadcasts",
163
+ "Manages email templates and reads email activity and account usage",
164
+ "Sends one-off emails you request"
165
+ ],
166
+ "keyHint": "In Resend, open API Keys → Create API Key. Choose Full access and all domains. Sending access cannot add or verify domains.",
167
+ "saveKind": "agent-plugin-token",
168
+ "saveTarget": "resend",
169
+ "helpUrl": "https://resend.com/api-keys",
170
+ "helpLabel": "Create a Full access key in Resend",
171
+ "baseUrl": "https://api.resend.com"
172
+ }
173
+ ]
174
+ }
175
+ },
176
+ "keywords": [
177
+ "resend",
178
+ "email",
179
+ "mail",
180
+ "send-email",
181
+ "transactional-email",
182
+ "newsletter",
183
+ "smtp-alternative",
184
+ "outbound-mail",
185
+ "domains",
186
+ "dns",
187
+ "broadcast",
188
+ "contacts",
189
+ "audience",
190
+ "mcp"
191
+ ]
192
+ }
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: resend
3
+ description: Send the site's email through Resend, and manage the Resend account itself (domains and DNS verification, broadcasts, contacts, segments, topics, templates, logs, usage) through Resend's hosted MCP server. Covers which tools to use for what, the two keys and how each is saved through the host's secure form, verifying the sending domain, and what each send failure means in plain words.
4
+ ---
5
+
6
+ # Resend: the site's email, and the Resend account
7
+
8
+ ## Scope
9
+
10
+ Choose the card yourself from its `usedFor` list. Reuse a saved key for that
11
+ task. Never offer a replacement unless the person asks.
12
+
13
+ This plugin does two separate jobs. Keep them apart.
14
+
15
+ 1. **The sending card** (`resend`). The adapter ships in
16
+ this opt-in plugin. Enable it first in the host's email provider settings, then save its key.
17
+ Switching delivery is a separate step; enabling or saving alone never switches mail.
18
+ 2. **The account card** (`resend-mcp`).
19
+ This goes through Resend's own hosted MCP server, `https://mcp.resend.com/mcp`. Its tools appear
20
+ as `mcp__resend__<name>`, for example `mcp__resend__list-domains`.
21
+
22
+ ## Which tools to use
23
+
24
+ **The host's own mail tools are the source of truth for the site's email.** Use them for anything about
25
+ how this site sends:
26
+
27
+ - `system_get_mail_status`: is mail set up, which provider, is the domain ready.
28
+ - `mail_set_provider`: switch the site between Resend, SMTP and none.
29
+ - `mail_send_test`: prove the site's mail works end to end.
30
+ - `dns_*`: add or check the DNS records on the site's own domain.
31
+
32
+ Never use `mcp__resend__send-email` to test or stand in for the site's mail: it skips the host's outbox,
33
+ retries, suppression list and logs, so a pass there proves nothing about the site.
34
+
35
+ **Use the `mcp__resend__*` tools for work on the Resend account itself**, when the person asks for it:
36
+
37
+ - **Domains**: `list-domains`, `get-domain`, `create-domain`, `update-domain`, `verify-domain`, and
38
+ the domain-claim tools. `create-domain` returns the DNS records; add them with the host's `dns_*`
39
+ tools when the site's DNS is managed by the host, otherwise show them to the person. Then call
40
+ `verify-domain`.
41
+ - **Broadcasts**: draft, update, compose and cancel. Sending a broadcast is not switched on by
42
+ default (see below); the site's own newsletter goes through the host.
43
+ - **Contacts, segments, topics, contact properties, templates**: list, read, create, update.
44
+ - **Emails**: one-off emails the person asks for (`send-email`, `send-batch-emails`, which ask the
45
+ person to confirm first), reading sent and received emails, cancelling a scheduled one.
46
+ - **Logs, usage, suppressions, webhooks, API keys**: read only.
47
+
48
+ **Off by default:** every `remove-*` tool, `send-broadcast`, creating or changing API keys,
49
+ creating, changing or rotating webhooks, and revoking sign-ins. Removals cannot be undone, a
50
+ broadcast mails a whole audience, and new keys or webhook secrets would land in the chat. If the
51
+ person really needs one of these, do it in the Resend dashboard, or tell them they can switch that
52
+ tool on under Settings for this connection.
53
+
54
+ ## Connect the Resend account (before any `mcp__resend__*` tool)
55
+
56
+ The account connection uses a separate **Full access** API key, not browser OAuth. Reuse a saved
57
+ account key; never offer to replace it unless the person asks. Call
58
+ `agent_plugin_connect { pluginId: "resend" }` to check the saved connection or open its secure key card.
59
+ Only say the card is open after the tool emits it. A cancelled or expired card is not a connection.
60
+
61
+ If opening the account card directly, use
62
+ `credential_save { kind: "plugin-provider", target: "resend-mcp" }`. Explain first:
63
+ "This is a separate Full access key so I can add and verify your domain. It keeps your site's
64
+ existing sending key." Then tell the person:
65
+ 1. Sign in at [resend.com/api-keys](https://resend.com/api-keys) and choose **Create API Key**.
66
+ 2. Permission: **Full access** (a "Sending access" key is refused). Domain: all domains.
67
+ 3. Paste it into the secure form the host shows. Never into the chat.
68
+
69
+ - `{ status: "connected" }`: go ahead.
70
+ - `{ status: "not-connected" }`: explain the returned outcome; do not call the account tools yet.
71
+ - The form says the key was rejected: it is a "Sending access" key. Make a Full access one.
72
+ - The form says Resend is unavailable right after a save: most often the key was mistyped (Resend
73
+ answers a malformed key that way). Ask the person to copy it again; retry once, then wait.
74
+
75
+ Never ask for the key in chat, and never put it in any tool argument.
76
+
77
+ ## Set up the site's email
78
+
79
+ 1. **Get a sending key.** The person signs in at [resend.com/api-keys](https://resend.com/api-keys)
80
+ and creates a key with **Sending access** (only sending; the site needs nothing more). This is a
81
+ different key from the Full access one above.
82
+ 2. **Save it through the Connect Resend card:** `credential_save { kind: "plugin-provider", target: "resend" }`.
83
+ The card asks only for the key and saves it under the label the host reads ("Tovu Mail — Resend API").
84
+ Never ask for the key in chat. If a sending key is already saved, reuse it. Only open a replacement
85
+ card if the person explicitly asks to replace that key; explain that it REPLACES the saved key.
86
+ 3. **Verify the sending domain.** Until it is verified, Resend only sends to the account's own
87
+ address. Check with `system_get_mail_status`; add records with `dns_*` (or, when the account is
88
+ connected, `mcp__resend__create-domain` then `mcp__resend__verify-domain`).
89
+ 4. **Select Resend** with `mail_set_provider { providerId: "resend" }`. The change and saved key
90
+ take effect on the next email. Never ask the person to restart the host.
91
+ 5. Prove it with `mail_send_test`.
92
+
93
+ ## What a failure means
94
+
95
+ - `validation_error`: a bad address or an unverified sending domain. Fix the address or verify the domain.
96
+ - `missing_api_key`, `invalid_api_key`, `restricted_api_key`: the saved key is wrong or lacks sending
97
+ access. Explain the failure and needed access. Only after an
98
+ explicit replacement request, use `credential_save { kind: "api", target: "Tovu Mail — Resend API" }`.
99
+ - `rate_limit_exceeded`, HTTP 5xx, `TRANSPORT_ERROR`: temporary. The host retries these.
100
+
101
+ ## Bounces and complaints (webhook)
102
+
103
+ Resend can report hard bounces and spam complaints to the site through a signed webhook, so the
104
+ site stops mailing those addresses. The endpoint address, the events to send, how the signing
105
+ secret is saved and how it is rotated are the host's: follow the host guidance for this plugin.
106
+ Set the webhook up in the Resend dashboard, not with the MCP tools: the signing secret must not
107
+ pass through the chat, and never ask for it in chat.
@@ -0,0 +1,22 @@
1
+ {
2
+ "schemaVersion": 2,
3
+ "adapters": [
4
+ {
5
+ "id": "resend",
6
+ "label": "Resend",
7
+ "module": "adapters/resend.mjs",
8
+ "credentialLabel": "Tovu Mail — Resend API",
9
+ "credentialKeys": ["token"],
10
+ "feedback": true,
11
+ "credentialCard": {
12
+ "title": "Connect Resend",
13
+ "usedFor": ["Sends your site's emails (sign-in links, form notices, newsletters)"],
14
+ "intro": "Connect Resend so this site can send its email (sign-in links, confirmations, form notifications).",
15
+ "helpUrl": "https://resend.com/api-keys",
16
+ "helpLabel": "Get a key at resend.com/api-keys",
17
+ "keyHint": "Create a key with Sending access",
18
+ "baseUrl": "https://api.resend.com"
19
+ }
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,11 @@
1
+ # S3-compatible — implementation notes
2
+
3
+ Host-specific notes moved out of the first host's core comments (2026-10-22, vendor-to-plugins). Core describes these
4
+ behaviours generically; the vendor detail lives here.
5
+
6
+ - **Publish history.** An S3-compatible publish has no `deploymentId`; the "uploaded, not yet confirmed
7
+ reachable" outcome records `false` reachability.
8
+ - **Account label.** No account field exists to read; the account-label heal skips these credentials.
9
+ - **Security headers.** Buckets have no header config file here, so an export carries only what HTML can
10
+ say (core `withSecurityMeta`). With a CDN such as CloudFront, `404.html` at the output root is the
11
+ convention it looks for.
@@ -0,0 +1,4 @@
1
+ {
2
+ "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
3
+ "mcpServers": {}
4
+ }