Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
"integrations/posthog",
"integrations/pylon",
"integrations/railway",
"integrations/resend",
"integrations/sentry",
"integrations/snowflake",
"integrations/supabase",
Expand Down
1 change: 1 addition & 0 deletions apps/docs/integrations/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ from [Personal Settings](/personal-settings).
| <IntegrationName href="/integrations/posthog" icon="posthog" name="PostHog" /> | Product analytics, experiments, and error context | Admin connection once |
| <IntegrationName href="/integrations/pylon" icon="/logo/integrations/pylon.svg" name="Pylon" /> | Customer issue and account context | Admin connection once |
| <IntegrationName href="/integrations/railway" icon="railway" name="Railway" /> | Project and service context from Railway | Admin connection once |
| <IntegrationName href="/integrations/resend" icon="resend" name="Resend" /> | Email delivery and infrastructure management | Admin connection once |
| <IntegrationName href="/integrations/sentry" icon="sentry" name="Sentry" /> | Error and performance investigation | Admin connection once |
| <IntegrationName href="/integrations/snowflake" icon="snowflake" name="Snowflake" /> | Data warehouse exploration | Admin connection once |
| <IntegrationName href="/integrations/supabase" icon="supabase" name="Supabase" /> | Read-only database access in Supabase | Enable first, then teammates link accounts |
Expand Down
43 changes: 43 additions & 0 deletions apps/docs/integrations/resend.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: Resend
description: Inspect and manage shared email infrastructure from Roomote tasks.
icon: 'https://api.iconify.design/simple-icons:resend.svg?color=currentColor'
---

Connect Resend when tasks need email delivery status, received messages,
domains, contacts, templates, broadcasts, or other email infrastructure.

## How setup works

An admin connects Resend once from **Settings > Integrations** using OAuth. The
connection is shared across the deployment and requests Resend's
`full_access` scope so Roomote can use inspection and management tools.

## Safer defaults

Roomote initially disables tools that send or reschedule email, create API
credentials, mutate or trigger automations, and mutate contacts. Read
operations remain available, and canceling a pending scheduled email remains
enabled as a safety action.

The disabled tools include:

- single, batch, and broadcast sending
- rescheduling a scheduled email
- creating API keys that could bypass Roomote's tool policy
- creating or updating automations, or sending events that trigger them
- creating, updating, or removing contacts
- creating, updating, or removing contact properties
- changing contact segment or topic membership
- importing contacts from CSV

An admin can opt in to individual tools from **Settings > Integrations >
Resend > Manage tools**. Disabled tools are hidden from tasks and rejected by
the server if called directly. Admin choices persist when Resend is reconnected
or disabled and enabled again.

## Verify the connection

After connecting Resend, start with a read-only request such as listing recent
emails or checking domain status. Enable only the additional tools your team
expects Roomote to use.
50 changes: 47 additions & 3 deletions apps/web/src/app/api/mcp-oauth/callback/__tests__/route.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions apps/web/src/app/api/mcp-oauth/callback/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '@roomote/db/server';
import {
getMcpIntegration,
getMcpIntegrationDefaultDisabledTools,
getMcpIntegrationOauthEndpoints,
isDeploymentScopedMcpIntegration,
isSelfServeMcpIntegration,
Expand Down Expand Up @@ -335,12 +336,19 @@ export async function GET(request: NextRequest) {

if (requiresOrgAdmin) {
failureStage = 'deployment_enablement';
const defaultDisabledTools =
getMcpIntegrationDefaultDisabledTools(integration);
await db
.insert(deploymentMcpEnablements)
.values({
mcpId: integration.id,
enabled: true,
enabledByUserId: userId,
...(defaultDisabledTools.length > 0
? {
disabledTools: [...defaultDisabledTools],
}
: {}),
})
.onConflictDoUpdate({
target: deploymentMcpEnablements.mcpId,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions apps/web/src/components/settings/Integrations.test.tsx

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions apps/web/src/components/settings/Integrations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ const DEEP_LINK_ENABLE_DESCRIPTIONS: Record<string, string> = {
'Roomote will be able to inspect analytics, feature flags, and experiments.',
railway:
'Roomote will be able to inspect Railway account, project, and service inventory.',
resend:
'Roomote will be able to inspect and manage shared email infrastructure. Sending, credential creation, automation triggers, and contact mutations start disabled.',
sentry:
'Roomote will be able to inspect Sentry issue context and run scheduled Sentry triage through MCP.',
supabase: 'Roomote will get read-only database access and platform context.',
Expand Down
2 changes: 2 additions & 0 deletions apps/web/src/components/system/custom/logos/brand-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
siPagerduty,
siPosthog,
siRailway,
siResend,
siSentry,
siSnowflake,
siSupabase,
Expand Down Expand Up @@ -56,6 +57,7 @@ const SIMPLE_ICONS: Record<string, SimpleIcon> = {
pagerduty: siPagerduty,
posthog: siPosthog,
railway: siRailway,
resend: siResend,
snowflake: siSnowflake,
supabase: siSupabase,
telegram: siTelegram,
Expand Down
7 changes: 7 additions & 0 deletions apps/web/src/trpc/commands/mcp-connections/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
getAllowedIntegrationMcpToolNames,
getMcpIntegration,
getMcpIntegrationConnectionScope,
getMcpIntegrationDefaultDisabledTools,
type McpConnectionRole,
isMcpConnectionAsanaConfig,
isMcpConnectionGrafanaConfig,
Expand Down Expand Up @@ -592,12 +593,18 @@ export async function setDeploymentMcpEnabledCommand(
await assertStaticOauthReady(integration);
}

const defaultDisabledTools =
getMcpIntegrationDefaultDisabledTools(integration);

const [result] = await db
.insert(deploymentMcpEnablements)
.values({
mcpId: input.mcpId,
enabled: input.enabled,
enabledByUserId: auth.userId,
...(defaultDisabledTools.length > 0
? { disabledTools: [...defaultDisabledTools] }
: {}),
})
.onConflictDoUpdate({
target: [deploymentMcpEnablements.mcpId],
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions apps/worker/src/mcp/roomote-mcp-server/integration-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ Railway uses OAuth:

Once connected, I can confirm the connected Railway account and list Railway projects and services during tasks.

# Resend

Resend uses OAuth:
1. An admin enables Resend from Settings > Integrations.
2. That admin connects Resend once for the workspace via OAuth.

Once connected, I can inspect email delivery, received messages, domains, contacts, templates, broadcasts, and related infrastructure. Email sending, credential creation, scheduled-send changes, automation mutations and triggers, and contact mutations are disabled until an admin enables those tools from Manage tools.

# Braintrust

Braintrust uses OAuth:
Expand Down
7 changes: 7 additions & 0 deletions packages/cloud-agents/src/server/mcp-self-setup/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ export const MCP_SETUP_INTEGRATION_METADATA: Record<
'Inspect the services inside a Railway project',
],
},
resend: {
capabilities: [
'Inspect sent and received email delivery details',
'Review domains, logs, templates, contacts, and broadcasts',
'Opt in to email sending, credential creation, automation triggers, and contact mutations when needed',
],
},
vercel: {
capabilities: [
'Inspect Vercel teams and projects',
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/slack/src/mcp-recommendations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ const SLACK_ENABLE_DESCRIPTIONS: Record<string, string> = {
'Roomote will be able to inspect monitoring, incidents, and telemetry.',
railway:
'Roomote will be able to inspect Railway account, project, and service inventory.',
resend:
'Roomote will be able to inspect and manage shared email infrastructure. Sending, credential creation, automation triggers, and contact mutations start disabled.',
braintrust:
'Roomote will be able to inspect prompts, evaluations, and AI run history.',
linear:
Expand Down
Loading
Loading