@nuxtagentic/integrations 0.0.0-stage → 0.1.1

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 (51) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +175 -2
  3. package/client.ts +124 -0
  4. package/module.ts +44 -0
  5. package/package.json +52 -3
  6. package/runtime/assets/logos/discord.svg +1 -0
  7. package/runtime/assets/logos/github.svg +1 -0
  8. package/runtime/assets/logos/gmail.svg +1 -0
  9. package/runtime/assets/logos/googleads.svg +1 -0
  10. package/runtime/assets/logos/googleanalytics.svg +1 -0
  11. package/runtime/assets/logos/googlecalendar.svg +1 -0
  12. package/runtime/assets/logos/googledrive.svg +1 -0
  13. package/runtime/assets/logos/googlesearchconsole.svg +1 -0
  14. package/runtime/assets/logos/hubspot.svg +1 -0
  15. package/runtime/assets/logos/intercom.svg +1 -0
  16. package/runtime/assets/logos/linear.svg +1 -0
  17. package/runtime/assets/logos/mcp.svg +1 -0
  18. package/runtime/assets/logos/meta.svg +1 -0
  19. package/runtime/assets/logos/notion.svg +1 -0
  20. package/runtime/assets/logos/reddit.svg +1 -0
  21. package/runtime/assets/logos/sentry.svg +1 -0
  22. package/runtime/assets/logos/shopify.svg +1 -0
  23. package/runtime/assets/logos/slack.svg +1 -0
  24. package/runtime/assets/logos/stripe.svg +1 -0
  25. package/runtime/assets/logos/tiktok-dark.svg +1 -0
  26. package/runtime/assets/logos/tiktok.svg +1 -0
  27. package/runtime/assets/logos/vercel.svg +1 -0
  28. package/runtime/assets/logos/x.svg +1 -0
  29. package/runtime/components/IntegrationCard.vue +82 -0
  30. package/runtime/components/IntegrationCatalog.vue +130 -0
  31. package/runtime/components/IntegrationConnectionPanel.vue +589 -0
  32. package/runtime/components/IntegrationLogo.vue +41 -0
  33. package/runtime/pages/integrations.vue +481 -0
  34. package/runtime/server/api/integrations/approvals/[id].post.ts +69 -0
  35. package/runtime/server/api/integrations/catalog/[provider]/action.post.ts +35 -0
  36. package/runtime/server/api/integrations/catalog/[provider]/connection.post.ts +242 -0
  37. package/runtime/server/api/integrations/catalog/[provider]/tools.get.ts +40 -0
  38. package/runtime/server/api/integrations/catalog/index.get.ts +48 -0
  39. package/runtime/server/api/integrations/catalog/tools.get.ts +27 -0
  40. package/runtime/server/plugins/connect-maintenance.ts +30 -0
  41. package/runtime/server/utils/approval-continuation.ts +37 -0
  42. package/runtime/server/utils/google-mcp.ts +296 -0
  43. package/runtime/server/utils/integration-adapters.ts +836 -0
  44. package/runtime/server/utils/integration-context.ts +510 -0
  45. package/runtime/server/utils/integration-crypto.ts +13 -0
  46. package/runtime/server/utils/request-body.ts +38 -0
  47. package/runtime/shared/agent.ts +14 -0
  48. package/runtime/shared/catalog.ts +566 -0
  49. package/runtime/shared/google-mcp.ts +8 -0
  50. package/runtime/workspace.ts +15 -0
  51. package/schema.ts +179 -0
@@ -0,0 +1,566 @@
1
+ /** How an integration is connected. Several may apply; OAuth is offered first. */
2
+ export interface IntegrationAuth {
3
+ /** A CloudConfig Connect OAuth provider, and the scopes this integration asks for. */
4
+ oauth?: { provider: string; scopes?: string[] }
5
+ /** Accept a pasted API token and the `fields` below — the path that works before any OAuth app exists. */
6
+ apiKey?: boolean
7
+ /** A hosted MCP server: its tools become the actions. No server means the user enters one. */
8
+ mcp?: { server?: string }
9
+ }
10
+
11
+ export type IntegrationScope = 'user' | 'workspace'
12
+
13
+ export interface IntegrationDefinition {
14
+ id: string
15
+ name: string
16
+ category: string
17
+ logo: string
18
+ description: string
19
+ details: string
20
+ triggers: { id: string; label: string }[]
21
+ actions: { id: string; label: string }[]
22
+ auth: IntegrationAuth
23
+ /** Who a connection belongs to, most natural first: a person, or the whole workspace. */
24
+ ownership: IntegrationScope[]
25
+ /**
26
+ * Extra values. Secret ones are API-key credentials and are sealed by Connect;
27
+ * the rest are per-connection settings, also asked for with OAuth.
28
+ */
29
+ fields: {
30
+ key: string
31
+ label: string
32
+ secret?: boolean
33
+ placeholder?: string
34
+ apiKeyOnly?: boolean
35
+ }[]
36
+ }
37
+
38
+ export const INTEGRATION_CATALOG: readonly IntegrationDefinition[] = [
39
+ {
40
+ id: 'github',
41
+ name: 'GitHub',
42
+ category: 'Code',
43
+ logo: 'github',
44
+ description: 'Repositories, issues and pull requests.',
45
+ details:
46
+ 'Let agents review pull requests, triage issues and comment on commits across the repositories you choose.',
47
+ triggers: [
48
+ { id: 'github.a_pull_request_is_opened', label: 'A pull request is opened' },
49
+ { id: 'github.an_issue_is_created', label: 'An issue is created' },
50
+ { id: 'github.a_branch_is_pushed', label: 'A branch is pushed' },
51
+ ],
52
+ actions: [
53
+ { id: 'read_repositories', label: 'Read repositories' },
54
+ { id: 'comment_on_pull_requests', label: 'Comment on pull requests' },
55
+ { id: 'open_and_label_issues', label: 'Open and label issues' },
56
+ ],
57
+ auth: { oauth: { provider: 'github' }, apiKey: true },
58
+ ownership: ['workspace', 'user'],
59
+ fields: [],
60
+ },
61
+ {
62
+ id: 'ga',
63
+ name: 'Google Analytics',
64
+ category: 'Analytics',
65
+ logo: 'googleanalytics',
66
+ description: 'Traffic, conversions and audience reports.',
67
+ details:
68
+ 'Give agents read access to GA4 properties so they can build reports, spot anomalies and answer traffic questions.',
69
+ triggers: [
70
+ { id: 'ga.traffic_drops_below_a_threshold', label: 'Traffic drops below a threshold' },
71
+ { id: 'ga.a_weekly_report_is_ready', label: 'A weekly report is ready' },
72
+ ],
73
+ actions: [
74
+ { id: 'run_reports', label: 'Run reports' },
75
+ { id: 'compare_date_ranges', label: 'Compare date ranges' },
76
+ { id: 'create_audiences', label: 'Create audiences' },
77
+ ],
78
+ auth: {
79
+ oauth: {
80
+ provider: 'google',
81
+ scopes: [
82
+ 'https://www.googleapis.com/auth/analytics.readonly',
83
+ 'https://www.googleapis.com/auth/analytics.edit',
84
+ ],
85
+ },
86
+ },
87
+ ownership: ['user', 'workspace'],
88
+ fields: [],
89
+ },
90
+ {
91
+ id: 'gsc',
92
+ name: 'Search Console',
93
+ category: 'Analytics',
94
+ logo: 'googlesearchconsole',
95
+ description: 'Search queries, rankings and indexing.',
96
+ details:
97
+ 'Agents can monitor search performance, inspect URLs and flag indexing problems on your verified sites.',
98
+ triggers: [
99
+ { id: 'gsc.an_indexing_error_is_detected', label: 'An indexing error is detected' },
100
+ { id: 'gsc.a_tracked_query_changes_rank', label: 'A tracked query changes rank' },
101
+ ],
102
+ actions: [
103
+ { id: 'read_search_performance', label: 'Read search performance' },
104
+ { id: 'inspect_urls', label: 'Inspect URLs' },
105
+ { id: 'request_indexing', label: 'Request indexing' },
106
+ ],
107
+ auth: {
108
+ oauth: {
109
+ provider: 'google',
110
+ scopes: [
111
+ 'https://www.googleapis.com/auth/webmasters',
112
+ 'https://www.googleapis.com/auth/indexing',
113
+ ],
114
+ },
115
+ },
116
+ ownership: ['user', 'workspace'],
117
+ fields: [],
118
+ },
119
+ {
120
+ id: 'gads',
121
+ name: 'Google Ads',
122
+ category: 'Ads',
123
+ logo: 'googleads',
124
+ description: 'Search, display and YouTube campaigns.',
125
+ details: 'Agents can report on spend, adjust bids and pause keywords that miss your targets.',
126
+ triggers: [
127
+ { id: 'gads.daily_budget_is_reached', label: 'Daily budget is reached' },
128
+ { id: 'gads.cpa_rises_above_target', label: 'CPA rises above target' },
129
+ ],
130
+ actions: [
131
+ { id: 'read_campaign_stats', label: 'Read campaign stats' },
132
+ { id: 'adjust_bids_and_budgets', label: 'Adjust bids and budgets' },
133
+ { id: 'pause_keywords', label: 'Pause keywords' },
134
+ ],
135
+ auth: { oauth: { provider: 'google', scopes: ['https://www.googleapis.com/auth/adwords'] } },
136
+ ownership: ['workspace', 'user'],
137
+ // The developer token is the app's own (NUXT_GOOGLE_ADS_DEVELOPER_TOKEN); the customer is per connection.
138
+ fields: [{ key: 'customerId', label: 'Customer ID', placeholder: '1234567890' }],
139
+ },
140
+ {
141
+ id: 'meta',
142
+ name: 'Meta Ads',
143
+ category: 'Ads',
144
+ logo: 'meta',
145
+ description: 'Facebook and Instagram campaigns.',
146
+ details:
147
+ 'Manage Facebook and Instagram ad accounts: build campaigns, shift budgets and pause underperforming ads.',
148
+ triggers: [
149
+ { id: 'meta.spend_limit_is_reached', label: 'Spend limit is reached' },
150
+ { id: 'meta.an_ad_is_rejected', label: 'An ad is rejected' },
151
+ ],
152
+ actions: [
153
+ { id: 'read_ad_insights', label: 'Read ad insights' },
154
+ { id: 'create_campaigns', label: 'Create campaigns' },
155
+ { id: 'adjust_budgets', label: 'Adjust budgets' },
156
+ { id: 'pause_ads', label: 'Pause ads' },
157
+ ],
158
+ auth: { apiKey: true },
159
+ ownership: ['workspace', 'user'],
160
+ fields: [],
161
+ },
162
+ {
163
+ id: 'x',
164
+ name: 'X Ads',
165
+ category: 'Ads',
166
+ logo: 'x',
167
+ description: 'Promoted posts and campaign analytics.',
168
+ details:
169
+ 'Agents can create promoted posts, tune bids and pull campaign performance from your X Ads account.',
170
+ triggers: [
171
+ { id: 'x.a_campaign_ends', label: 'A campaign ends' },
172
+ { id: 'x.cpc_rises_above_target', label: 'CPC rises above target' },
173
+ ],
174
+ actions: [
175
+ { id: 'read_campaign_stats', label: 'Read campaign stats' },
176
+ { id: 'create_promoted_posts', label: 'Create promoted posts' },
177
+ { id: 'adjust_bids', label: 'Adjust bids' },
178
+ ],
179
+ auth: { apiKey: true },
180
+ ownership: ['workspace', 'user'],
181
+ fields: [
182
+ { key: 'consumerKey', label: 'API key', secret: true },
183
+ { key: 'consumerSecret', label: 'API key secret', secret: true },
184
+ { key: 'tokenSecret', label: 'Access token secret', secret: true },
185
+ ],
186
+ },
187
+ {
188
+ id: 'tiktok',
189
+ name: 'TikTok Ads',
190
+ category: 'Ads',
191
+ logo: 'tiktok',
192
+ description: 'In-feed campaigns and creative reports.',
193
+ details:
194
+ 'Agents can read campaign results, compare creatives and adjust budgets in TikTok Ads Manager.',
195
+ triggers: [
196
+ { id: 'tiktok.a_campaign_ends', label: 'A campaign ends' },
197
+ { id: 'tiktok.creative_fatigue_is_detected', label: 'Creative fatigue is detected' },
198
+ ],
199
+ actions: [
200
+ { id: 'read_campaign_stats', label: 'Read campaign stats' },
201
+ { id: 'adjust_budgets', label: 'Adjust budgets' },
202
+ { id: 'pause_ad_groups', label: 'Pause ad groups' },
203
+ ],
204
+ auth: { apiKey: true },
205
+ ownership: ['workspace', 'user'],
206
+ fields: [{ key: 'advertiserId', label: 'Advertiser ID' }],
207
+ },
208
+ {
209
+ id: 'reddit',
210
+ name: 'Reddit Ads',
211
+ category: 'Ads',
212
+ logo: 'reddit',
213
+ description: 'Promoted posts across communities.',
214
+ details: 'Agents can report on Reddit campaigns and adjust targeting and budgets.',
215
+ triggers: [{ id: 'reddit.a_campaign_ends', label: 'A campaign ends' }],
216
+ actions: [
217
+ { id: 'read_campaign_stats', label: 'Read campaign stats' },
218
+ { id: 'adjust_budgets', label: 'Adjust budgets' },
219
+ ],
220
+ auth: { apiKey: true },
221
+ ownership: ['workspace', 'user'],
222
+ fields: [],
223
+ },
224
+ {
225
+ id: 'stripe',
226
+ name: 'Stripe',
227
+ category: 'Commerce',
228
+ logo: 'stripe',
229
+ description: 'Payments, subscriptions and invoices.',
230
+ details:
231
+ 'Agents can look up customers, summarize revenue and draft invoices. Refunds always ask for approval.',
232
+ triggers: [
233
+ { id: 'stripe.a_payment_fails', label: 'A payment fails' },
234
+ { id: 'stripe.a_subscription_is_cancelled', label: 'A subscription is cancelled' },
235
+ { id: 'stripe.a_dispute_is_opened', label: 'A dispute is opened' },
236
+ ],
237
+ actions: [
238
+ { id: 'read_payments_and_customers', label: 'Read payments and customers' },
239
+ { id: 'create_invoices', label: 'Create invoices' },
240
+ { id: 'issue_refunds', label: 'Issue refunds' },
241
+ ],
242
+ auth: { apiKey: true },
243
+ ownership: ['workspace'],
244
+ fields: [],
245
+ },
246
+ {
247
+ id: 'shopify',
248
+ name: 'Shopify',
249
+ category: 'Commerce',
250
+ logo: 'shopify',
251
+ description: 'Orders, products and customers.',
252
+ details: 'Agents can answer order questions, update inventory and tag customers in your store.',
253
+ triggers: [
254
+ { id: 'shopify.an_order_is_placed', label: 'An order is placed' },
255
+ { id: 'shopify.stock_runs_low', label: 'Stock runs low' },
256
+ ],
257
+ actions: [
258
+ { id: 'read_orders', label: 'Read orders' },
259
+ { id: 'update_products', label: 'Update products' },
260
+ { id: 'tag_customers', label: 'Tag customers' },
261
+ ],
262
+ auth: { oauth: { provider: 'shopify' }, apiKey: true },
263
+ ownership: ['workspace'],
264
+ fields: [
265
+ { key: 'shop', label: 'Store', placeholder: 'your-store.myshopify.com', apiKeyOnly: true },
266
+ ],
267
+ },
268
+ {
269
+ id: 'hubspot',
270
+ name: 'HubSpot',
271
+ category: 'CRM',
272
+ logo: 'hubspot',
273
+ description: 'Contacts, deals and marketing email.',
274
+ details: 'Agents can enrich contacts, move deals through stages and log activity in HubSpot.',
275
+ triggers: [
276
+ { id: 'hubspot.a_deal_changes_stage', label: 'A deal changes stage' },
277
+ { id: 'hubspot.a_form_is_submitted', label: 'A form is submitted' },
278
+ ],
279
+ actions: [
280
+ { id: 'read_contacts_and_deals', label: 'Read contacts and deals' },
281
+ { id: 'update_deal_stages', label: 'Update deal stages' },
282
+ { id: 'log_activity', label: 'Log activity' },
283
+ ],
284
+ auth: { oauth: { provider: 'hubspot' }, apiKey: true },
285
+ ownership: ['workspace', 'user'],
286
+ fields: [],
287
+ },
288
+ {
289
+ id: 'linear',
290
+ name: 'Linear',
291
+ category: 'Code',
292
+ logo: 'linear',
293
+ description: 'Issues, projects and cycles.',
294
+ details: 'Agents can file issues, update status and summarize cycles for your teams.',
295
+ triggers: [
296
+ { id: 'linear.an_issue_is_assigned_to_agent', label: 'An issue is assigned to Agent' },
297
+ { id: 'linear.a_cycle_ends', label: 'A cycle ends' },
298
+ ],
299
+ actions: [
300
+ { id: 'read_issues', label: 'Read issues' },
301
+ { id: 'create_issues', label: 'Create issues' },
302
+ { id: 'update_status', label: 'Update status' },
303
+ ],
304
+ auth: { oauth: { provider: 'linear' }, apiKey: true },
305
+ ownership: ['workspace', 'user'],
306
+ fields: [],
307
+ },
308
+ {
309
+ id: 'vercel',
310
+ name: 'Vercel',
311
+ category: 'Code',
312
+ logo: 'vercel',
313
+ description: 'Deployments and preview URLs.',
314
+ details:
315
+ 'Agents can watch deployments, read build logs and comment preview links on pull requests.',
316
+ triggers: [
317
+ { id: 'vercel.a_deployment_fails', label: 'A deployment fails' },
318
+ { id: 'vercel.a_preview_is_ready', label: 'A preview is ready' },
319
+ ],
320
+ actions: [
321
+ { id: 'read_deployments', label: 'Read deployments' },
322
+ { id: 'read_build_logs', label: 'Read build logs' },
323
+ { id: 'promote_to_production', label: 'Promote to production' },
324
+ ],
325
+ auth: { apiKey: true },
326
+ ownership: ['workspace', 'user'],
327
+ fields: [],
328
+ },
329
+ {
330
+ id: 'gmail',
331
+ name: 'Gmail',
332
+ category: 'Communication',
333
+ logo: 'gmail',
334
+ description: 'Read, draft and send email.',
335
+ details: 'Agents can sort your inbox, draft replies and send email you approve.',
336
+ triggers: [
337
+ { id: 'gmail.an_email_arrives_from_a_label', label: 'An email arrives from a label' },
338
+ { id: 'gmail.a_thread_gets_no_reply', label: 'A thread gets no reply' },
339
+ ],
340
+ actions: [
341
+ { id: 'read_email', label: 'Read email' },
342
+ { id: 'draft_replies', label: 'Draft replies' },
343
+ { id: 'send_email', label: 'Send email' },
344
+ ],
345
+ auth: {
346
+ oauth: { provider: 'google', scopes: ['https://www.googleapis.com/auth/gmail.modify'] },
347
+ },
348
+ ownership: ['user'],
349
+ fields: [],
350
+ },
351
+ {
352
+ id: 'discord',
353
+ name: 'Discord',
354
+ category: 'Communication',
355
+ logo: 'discord',
356
+ description: 'Channels, threads and messages.',
357
+ details: 'Agents can answer questions in channels you choose and post summaries.',
358
+ triggers: [
359
+ { id: 'discord.agent_is_mentioned', label: 'Agent is mentioned' },
360
+ { id: 'discord.a_message_is_posted_in_a_channel', label: 'A message is posted in a channel' },
361
+ ],
362
+ actions: [
363
+ { id: 'read_channels', label: 'Read channels' },
364
+ { id: 'post_messages', label: 'Post messages' },
365
+ ],
366
+ auth: { oauth: { provider: 'discord' }, apiKey: true },
367
+ ownership: ['workspace'],
368
+ fields: [],
369
+ },
370
+ {
371
+ id: 'intercom',
372
+ name: 'Intercom',
373
+ category: 'Communication',
374
+ logo: 'intercom',
375
+ description: 'Conversations and help center.',
376
+ details:
377
+ 'Agents can triage conversations, draft answers from your help center and tag tickets.',
378
+ triggers: [{ id: 'intercom.a_conversation_is_opened', label: 'A conversation is opened' }],
379
+ actions: [
380
+ { id: 'read_conversations', label: 'Read conversations' },
381
+ { id: 'draft_replies', label: 'Draft replies' },
382
+ { id: 'tag_conversations', label: 'Tag conversations' },
383
+ ],
384
+ auth: { oauth: { provider: 'intercom' }, apiKey: true },
385
+ ownership: ['workspace'],
386
+ fields: [],
387
+ },
388
+ {
389
+ id: 'notion',
390
+ name: 'Notion',
391
+ category: 'Productivity',
392
+ logo: 'notion',
393
+ description: 'Pages and databases.',
394
+ details: 'Agents can read and write the pages and databases you share with the integration.',
395
+ triggers: [{ id: 'notion.a_database_row_is_added', label: 'A database row is added' }],
396
+ actions: [
397
+ { id: 'read_pages', label: 'Read pages' },
398
+ { id: 'create_pages', label: 'Create pages' },
399
+ { id: 'update_databases', label: 'Update databases' },
400
+ ],
401
+ auth: { oauth: { provider: 'notion' }, apiKey: true },
402
+ ownership: ['workspace', 'user'],
403
+ fields: [],
404
+ },
405
+ {
406
+ id: 'gcal',
407
+ name: 'Google Calendar',
408
+ category: 'Productivity',
409
+ logo: 'googlecalendar',
410
+ description: 'Events and availability.',
411
+ details: 'Agents can check availability, schedule meetings and prepare briefs before events.',
412
+ triggers: [{ id: 'gcal.an_event_is_about_to_start', label: 'An event is about to start' }],
413
+ actions: [
414
+ { id: 'read_events', label: 'Read events' },
415
+ { id: 'create_events', label: 'Create events' },
416
+ ],
417
+ auth: {
418
+ oauth: {
419
+ provider: 'google',
420
+ scopes: [
421
+ 'https://www.googleapis.com/auth/calendar.events',
422
+ 'https://www.googleapis.com/auth/calendar.calendarlist.readonly',
423
+ ],
424
+ },
425
+ },
426
+ ownership: ['user'],
427
+ fields: [],
428
+ },
429
+ {
430
+ id: 'gdrive',
431
+ name: 'Google Drive',
432
+ category: 'Productivity',
433
+ logo: 'googledrive',
434
+ description: 'Files, folders and sharing.',
435
+ details: 'Agents can search, read and organize files in the folders you allow.',
436
+ triggers: [{ id: 'gdrive.a_file_is_added_to_a_folder', label: 'A file is added to a folder' }],
437
+ actions: [
438
+ { id: 'read_files', label: 'Read files' },
439
+ { id: 'create_files', label: 'Create files' },
440
+ { id: 'move_files', label: 'Move files' },
441
+ ],
442
+ auth: { oauth: { provider: 'google', scopes: ['https://www.googleapis.com/auth/drive.file'] } },
443
+ ownership: ['user', 'workspace'],
444
+ fields: [],
445
+ },
446
+ {
447
+ id: 'slack',
448
+ name: 'Slack',
449
+ category: 'Communication',
450
+ logo: 'slack',
451
+ description: 'Channels, messages and agent notifications.',
452
+ details: 'Post agent results and failure alerts to the channels you allow.',
453
+ triggers: [
454
+ { id: 'slack.an_agent_is_mentioned', label: 'An agent is mentioned' },
455
+ { id: 'slack.a_message_is_posted', label: 'A message is posted' },
456
+ ],
457
+ actions: [
458
+ { id: 'read_channels', label: 'Read channels' },
459
+ { id: 'post_messages', label: 'Post messages' },
460
+ ],
461
+ auth: { oauth: { provider: 'slack' }, apiKey: true },
462
+ ownership: ['workspace'],
463
+ fields: [],
464
+ },
465
+ {
466
+ id: 'mcp-linear',
467
+ name: 'Linear MCP',
468
+ category: 'MCP servers',
469
+ logo: 'linear',
470
+ description: 'Every tool on Linear’s hosted MCP server.',
471
+ details:
472
+ 'Sign in to Linear’s MCP server. No app to register: agents get the tools you allow, and changes ask for approval.',
473
+ triggers: [],
474
+ actions: [],
475
+ auth: { mcp: { server: 'https://mcp.linear.app/mcp' } },
476
+ ownership: ['user', 'workspace'],
477
+ fields: [],
478
+ },
479
+ {
480
+ id: 'mcp-notion',
481
+ name: 'Notion MCP',
482
+ category: 'MCP servers',
483
+ logo: 'notion',
484
+ description: 'Every tool on Notion’s hosted MCP server.',
485
+ details:
486
+ 'Sign in to Notion’s MCP server. Agents search, read and write the pages you share, with the tools you allow.',
487
+ triggers: [],
488
+ actions: [],
489
+ auth: { mcp: { server: 'https://mcp.notion.com/mcp' } },
490
+ ownership: ['user', 'workspace'],
491
+ fields: [],
492
+ },
493
+ {
494
+ id: 'mcp-sentry',
495
+ name: 'Sentry MCP',
496
+ category: 'MCP servers',
497
+ logo: 'sentry',
498
+ description: 'Issues, events and releases from Sentry.',
499
+ details:
500
+ 'Sign in to Sentry’s MCP server so agents can investigate errors with the tools you allow.',
501
+ triggers: [],
502
+ actions: [],
503
+ auth: { mcp: { server: 'https://mcp.sentry.dev/mcp' } },
504
+ ownership: ['user', 'workspace'],
505
+ fields: [],
506
+ },
507
+ {
508
+ id: 'mcp-stripe',
509
+ name: 'Stripe MCP',
510
+ category: 'MCP servers',
511
+ logo: 'stripe',
512
+ description: 'Stripe’s hosted MCP server.',
513
+ details:
514
+ 'Sign in to Stripe’s MCP server. Tools that change data, such as refunds, always ask for approval.',
515
+ triggers: [],
516
+ actions: [],
517
+ auth: { mcp: { server: 'https://mcp.stripe.com' } },
518
+ ownership: ['workspace', 'user'],
519
+ fields: [],
520
+ },
521
+ {
522
+ id: 'mcp',
523
+ name: 'Custom MCP server',
524
+ category: 'MCP servers',
525
+ logo: 'mcp',
526
+ description: 'Any hosted MCP server with OAuth.',
527
+ details:
528
+ 'Paste the server’s URL. Connect discovers how to sign in, registers this app with the server and keeps the token fresh.',
529
+ triggers: [],
530
+ actions: [],
531
+ auth: { mcp: {} },
532
+ ownership: ['user', 'workspace'],
533
+ fields: [],
534
+ },
535
+ ]
536
+
537
+ export const INTEGRATION_CATEGORIES = [
538
+ 'All',
539
+ 'Analytics',
540
+ 'Ads',
541
+ 'Code',
542
+ 'Commerce',
543
+ 'CRM',
544
+ 'Communication',
545
+ 'Productivity',
546
+ 'MCP servers',
547
+ ] as const
548
+
549
+ export function getIntegrationDefinition(id: string) {
550
+ return INTEGRATION_CATALOG.find((entry) => entry.id === id)
551
+ }
552
+
553
+ /**
554
+ * The tool name agents see. The first connection of an integration keeps the
555
+ * plain `provider_action` name; further accounts add their connection id so
556
+ * an agent can be pointed at one of them explicitly.
557
+ */
558
+ export function getIntegrationToolName(provider: string, action: string, binding?: number) {
559
+ const base = `${provider.replace(/[^a-zA-Z0-9]/g, '_')}${binding ? `_${binding}` : ''}`
560
+ return `${base}_${action.replace(/[^a-zA-Z0-9_-]/g, '_')}`.slice(0, 64)
561
+ }
562
+
563
+ /** Whether an MCP tool changes data, by its own annotations: unannotated tools are treated as writes. */
564
+ export function isMcpWrite(annotations?: { readOnlyHint?: boolean; destructiveHint?: boolean }) {
565
+ return annotations?.readOnlyHint !== true
566
+ }
@@ -0,0 +1,8 @@
1
+ /** Google endpoints allowed to receive a connected Google account's access token. */
2
+ export const GOOGLE_MCP_SERVERS = {
3
+ gcal: 'https://calendarmcp.googleapis.com/mcp/v1',
4
+ gmail: 'https://gmailmcp.googleapis.com/mcp/v1',
5
+ gdrive: 'https://drivemcp.googleapis.com/mcp/v1',
6
+ } as const
7
+
8
+ export const GOOGLE_MCP_ENDPOINTS = Object.values(GOOGLE_MCP_SERVERS)
@@ -0,0 +1,15 @@
1
+ import type { WorkspaceContribution } from '@nuxtagentic/workspace/runtime/types'
2
+ import { computed } from 'vue'
3
+
4
+ export const integrationsContribution = {
5
+ id: 'integrations',
6
+ label: 'Integrations',
7
+ icon: 'i-lucide-plug',
8
+ matchesRoute: (route) => route.path === '/dashboard/integrations',
9
+ navigation: { order: 60, group: 'workspace' },
10
+ navigationShortcuts: [
11
+ { label: 'Integrations', icon: 'i-lucide-plug', to: '/dashboard/integrations' },
12
+ ],
13
+ layout: { navbar: true, hideExpand: true },
14
+ usePromptPresentation: () => computed(() => ({ hidden: true })),
15
+ } satisfies WorkspaceContribution