Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
36 changes: 36 additions & 0 deletions .github/workflows/test-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,42 @@ jobs:
if-no-files-found: ignore
retention-days: 7

- name: Verify Zoom search over real HTTP
if: matrix.provision == 'push'
working-directory: apps/sim
env:
NEXT_PUBLIC_APP_URL: http://127.0.0.1:3040
NEXT_PUBLIC_FORCE_HOSTED: 'false'
SEARCH_ZOOM_REPORT_PATH: ${{ runner.temp }}/search-zoom.json
run: bun scripts/test-search-zoom-e2e.ts

- name: Upload Zoom acceptance report
if: failure() && matrix.provision == 'push'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: search-zoom
path: ${{ runner.temp }}/search-zoom.json
if-no-files-found: ignore
retention-days: 7

- name: Verify Google Meet search over real HTTP
if: matrix.provision == 'push'
working-directory: apps/sim
env:
NEXT_PUBLIC_APP_URL: http://127.0.0.1:3040
NEXT_PUBLIC_FORCE_HOSTED: 'false'
SEARCH_GOOGLE_MEET_REPORT_PATH: ${{ runner.temp }}/search-google-meet.json
run: bun scripts/test-search-google-meet-e2e.ts

- name: Upload Google Meet acceptance report
if: failure() && matrix.provision == 'push'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: search-google-meet
path: ${{ runner.temp }}/search-google-meet.json
if-no-files-found: ignore
retention-days: 7

- name: Verify SCIM and administration over real HTTP
working-directory: apps/sim
env:
Expand Down
14 changes: 6 additions & 8 deletions apps/docs/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ interface LucidIconProps extends SVGProps<SVGSVGElement> {}

export function LucidIcon(props: LucidIconProps) {
return (
<svg
{...props}
viewBox='-22 0 144 144.5'
fill='currentColor'
xmlns='http://www.w3.org/2000/svg'
>
<path d='M50 0L0 28.9V144.5L50 115.6V0Z' />
<path d='M100 142.7V86.7L50 115.6V142.7H100Z' />
<svg {...props} viewBox='0 0 192 192' fill='none' xmlns='http://www.w3.org/2000/svg'>
<rect width='192' height='192' rx='32' fill='#282C33' />
<g transform='translate(46 24)' fill='#FFFFFF'>
<path d='M50 0L0 28.9V144.5L50 115.6V0Z' />
<path d='M100 142.7V86.7L50 115.6V142.7H100Z' />
</g>
</svg>
)
}
Expand Down
6 changes: 6 additions & 0 deletions apps/docs/content/docs/search/google-drive.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,9 @@ https://www.googleapis.com/auth/drive.file
```

The personal OAuth connection also supports workflow actions, so its declared scopes can be broader than Search’s read-only requests. The service credential uses the separate delegation scopes above.

## Google Meet transcripts and notes

Meet saves generated transcripts and smart notes as Google Docs in the organizer's Drive. Connect Drive to search and read these documents when you have access, including older artifacts that remain after Meet's conference API retention window. For example, use `fullText contains 'rollback' and mimeType = 'application/vnd.google-apps.document'`.

Drive date filters use the file's modification time, not the meeting's start. Use [Google Meet](/search/google-meet) for recent conference transcripts with meeting dates and [Google Calendar](/search/google-calendar) for scheduled events. Transcription or note-taking must have been enabled during the meeting; Search cannot reconstruct a missing artifact.
44 changes: 44 additions & 0 deletions apps/docs/content/docs/search/google-meet.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: Google Meet
description: Search recent conference transcripts and find generated meeting notes
---

## Connect

An administrator enables **Google Meet → Member accounts** under **Settings → Sources**. In **Integrations**, click **Connect** beside Google Meet, sign in to your Google account, and approve the requested access. Return to Sim and confirm your account appears on the row. Sim uses the existing Google OAuth client and your Meet permissions. No service account is required.

For self-hosted deployments, enable the **Google Meet REST API** in the Google Cloud project used by Sim, configure `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`, and register:

```text
https://<your-sim-domain>/api/auth/oauth2/callback/google-meet
```

The existing Google Meet connection includes `meetings.space.readonly`, which authorizes these reads, and `meetings.space.created` for workflow actions. Search only reads conference records and artifacts. Google Workspace administrators may need to approve the app.

These existing Meet scopes are [sensitive](https://developers.google.com/workspace/meet/api/guides/authenticate-authorize). A self-hosted OAuth app serving external users may need Google verification.

## Recent transcripts and notes

Use plain words or a phrase, optionally with meeting start dates. `kind: transcript` searches finalized transcript text and participant names. `kind: smart_notes` finds generated-note metadata and a Google Docs link; it does not search or return the note body. Omit the kind to search both. `project` can narrow to a known `spaces/ID` or meeting code.

Meet has no title or full-text search endpoint. Sim matches terms locally within at most 3 recent conferences and 5 finalized artifacts per call. Results explicitly report bounded coverage. Use a narrow date range or known meeting space; missing results do not establish that a meeting or phrase is absent. Boolean operators, ownership filters and modification-date filters are unsupported. Dates use the actual conference start; the upper bound is exclusive.

Reads retrieve complete finalized transcripts within the request, entry and byte limits. Speech stays attributed to the participant and timestamp. Sim rejects incomplete reads instead of presenting truncated text as a complete transcript.

[Meet conference records](https://developers.google.com/workspace/meet/api/reference/rest/v2/conferenceRecords) and [transcript entries](https://developers.google.com/workspace/meet/api/guides/artifacts) expire 30 days after the conference ends. Transcription or note-taking must have been enabled during the meeting. Sim does not generate a missing transcript or process recording audio.

## Saved documents and scheduled meetings

Connect **Google Drive** to read saved meeting notes and transcripts, including older documents that remain in the organizer's Drive. Use Drive's native query syntax, such as `fullText contains 'rollback' and mimeType = 'application/vnd.google-apps.document'`, then read the result. Drive dates mean file modification time, not the meeting date. Normal document sharing and retention rules apply.

Use **Google Calendar** to search scheduled meetings and invitations. An event on the calendar does not establish that a Meet transcript or recording exists.

## Disconnect and troubleshoot

To disconnect, open **Integrations**, use the **…** menu beside Google Meet, choose **Disconnect** for your account, and confirm. Any workflows using that connection also lose access. This does not delete transcripts or notes from Google Drive.

- **Connect is unavailable or permission is denied:** ask your Sim administrator to enable the source and finish Google OAuth setup. Your Google Workspace administrator may need to approve the app.
- **Reconnect needed:** use **Reconnect** beside Google Meet and authorize the account again.
- **No matching transcript:** narrow to the meeting's dates or space, confirm transcription was enabled, and check whether the conference is within the API's 30-day window. Use Google Drive for saved or older documents and the bodies of smart notes.

For help, contact [help@sim.ai](mailto:help@sim.ai).
16 changes: 12 additions & 4 deletions apps/docs/content/docs/search/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,27 @@ In Sources, open an integration to manage its connection and resource settings.

## Connector guides

These nine providers support live Search. Google Docs, Sheets, and Slides are accessed through Drive. Other [knowledge-base connectors](/knowledgebase/connectors) do not automatically become Search integrations.
These providers support live Search. Google Docs, Sheets, and Slides are accessed through Drive. Other [knowledge-base connectors](/knowledgebase/connectors) do not automatically become Search integrations.

| Source | Search path | Modes |
| --- | --- | --- |
| [Coda](/search/coda) | Personal Coda MCP; legacy REST connections search document titles | Member or service |
| [Confluence](/search/confluence) | Confluence Cloud CQL and content APIs | Member or service |
| [GitHub](/search/github) | GitHub issue, code, and repository search | Member or GitHub App |
| [Fireflies](/search/fireflies) | Meeting titles and spoken transcripts | Member only |
| [GitHub](/search/github) | Repositories, code, issues and pull request discussions | Member or GitHub App |
| [GitLab](/search/gitlab) | Configured self-managed project's search and read APIs | Service only; admin or CSV permissions |
| [Gmail](/search/gmail) | Gmail message search and message reads | Member or service |
| [Gmail](/search/gmail) | Message search and conversation reads | Member or service |
| [Google Calendar](/search/google-calendar) | Calendar lists and event APIs | Member or service |
| [Google Drive](/search/google-drive) | Drive search plus supported file reads/exports | Member or service |
| [Google Drive](/search/google-drive) | File search, supported document reads and comments | Member or service |
| [Google Meet](/search/google-meet) | Recent conference transcripts and generated-note links | Member only |
| [Granola](/search/granola) | Semantic meeting search with source notes and transcript reads | Member only |
| [HubSpot](/search/hubspot) | Contacts, companies, deals and tickets | Member only |
| [Jira](/search/jira) | Jira Cloud JQL and issue APIs | Member only |
| [Linear](/search/linear) | Issues and their comment discussions | Member only |
| [Lucid](/search/lucid) | Lucidchart diagrams and Lucidspark boards | Member only |
| [Notion](/search/notion) | Page and database content through Notion MCP | Member only |
| [Slack](/search/slack) | Slack real-time search with the member's user token | Member only |
| [Zoom](/search/zoom) | Past meetings with available transcripts, notes and summaries | Member only |

[Generic Secrets](/search/generic-secrets) is also available as a source, but does not add searchable documents. Organization mode makes its secrets available across the organization; Member mode lets each person manage their own secrets in Integrations. Build and Plan can use these secrets for requests; Search cannot mount them.

Expand Down
4 changes: 3 additions & 1 deletion apps/docs/content/docs/search/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
"gmail",
"google-calendar",
"google-drive",
"google-meet",
"granola",
"hubspot",
"jira",
"linear",
"lucid",
"notion",
"slack"
"slack",
"zoom"
]
}
55 changes: 55 additions & 0 deletions apps/docs/content/docs/search/zoom.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
title: Zoom
description: Search past meetings, transcripts, personal notes and AI summaries with your Zoom account
---

## Connect

An administrator enables **Zoom → Member accounts** under **Settings → Sources**. Then each person connects their own account:

1. Open **Integrations** in Sim and click **Connect** beside Zoom.
2. Sign in to Zoom, review the requested read permissions, and authorize the app. Your Zoom administrator may need to approve it first.
3. Return to Sim and confirm your account appears on the Zoom row. Current Zoom permissions determine which meetings and artifacts you can read.

If connection fails, see [Troubleshooting](#troubleshooting).

Sim uses the official [Zoom Meetings MCP server](https://developers.zoom.us/docs/mcp/zoom-meetings-mcp-server/). Search uses a separate General OAuth app registration from workflow actions. Zoom reauthorization can replace or narrow an existing user/app grant, so sharing the workflow client would risk disconnecting existing workflows. A Zoom workflow connection does not authorize Search.

For self-hosted deployments, configure `ZOOM_MCP_CLIENT_ID` and `ZOOM_MCP_CLIENT_SECRET` from a separate General, User-managed Search app. In the [Zoom app](https://developers.zoom.us/docs/mcp/servers/connect-to-zoom-mcp-servers/), enable `meeting:read:search` and `meeting:read:assets` and register the exact callback below in both the redirect field and OAuth allow list:

```text
https://<your-sim-domain>/api/mcp/oauth/callback
```

An internal app works only for users in its Zoom account. Connecting users from other Zoom accounts requires [approved external distribution](https://developers.zoom.us/docs/build-flow/before-you-build/), including for unlisted production apps. Limited external beta testing uses Zoom's separate [sharing approval](https://developers.zoom.us/docs/distribute/sharing-private-and-beta-apps/).

The OAuth exchange uses PKCE and `client_secret_basic`. Search requests only those two read scopes, even when Zoom discovery advertises write tools. The fixed endpoint is `https://mcp.zoom.us/mcp/meeting/streamable`; Sim allows only `search_meetings` and `get_meeting_assets`.

## Search and read

On **Home**, ask a question such as “What did we decide about deployment rollback last week? Search Zoom and cite the transcript.” Follow a result’s source link to open it in Zoom.

Use short plain keywords such as `deployment rollback`. Zoom matches meeting topics, agendas and available meeting content. Results identify past meeting occurrences by UUID, rather than the recurring meeting number. Use `kind: meeting` when sending multiple native queries to one account.

`startDate` and `endDate` filter actual meeting start time. The end is exclusive. Continue with `nextCursor` using the same account, query and filters; Zoom's page token expires after 15 minutes. Each page verifies at most 10 candidates. Sorting the returned candidates does not establish the globally newest or oldest match.

Read a result for available timestamped transcripts, personal notes and separately labeled AI-generated summaries. Generated summaries and notes are not verbatim speech. Sim does not download recordings or transcribe audio. Recording, transcription and AI Companion settings, licenses, processing state and sharing permissions determine which artifacts exist.

Boolean/field operators, project selection, ownership filters and modification-date filters are unsupported. An absent artifact does not prove a meeting had no discussion. Oversized or malformed reads fail explicitly; provider failures do not appear as a successful search with no matches.

## Disconnect

In Sim **Integrations**, open the **…** menu beside Zoom, choose **Disconnect** for your account, and confirm. This stops that connection from being used in this organization. Any workflows using the same connection also lose access; other people's connections are unaffected.

To remove the authorization from Zoom too, open **Zoom App Marketplace → My Library**, find the Sim app you authorized for Search, open its **More** menu, and choose **Remove**, then confirm. See [Zoom's removal instructions](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0062865); your Zoom administrator may control app removal.

Disconnecting does not delete meetings or recordings in Zoom or erase existing Sim conversations. See [Sim's Privacy Policy](https://www.sim.ai/privacy) for data handling and deletion requests.

## Troubleshooting

- **Connect is unavailable:** ask your Sim administrator to enable the source and finish the Zoom app configuration. Ask your Zoom administrator about app approval if authorization is blocked.
- **Reconnect needed:** use **Reconnect** on the Zoom row in Integrations and authorize the same account again.
- **Missing meeting or text:** confirm you can open it in Zoom, try a distinctive topic and date range, and check whether recording, transcription or AI summary processing has finished. Available content depends on the meeting's settings and your permissions.
- **Expired cursor or changed content:** run the search again before continuing the result. Zoom page tokens expire after 15 minutes.

For help, contact [help@sim.ai](mailto:help@sim.ai).
5 changes: 5 additions & 0 deletions apps/sim/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,8 @@ CRON_SECRET=your_cron_secret # Use `openssl rand -hex 32` to generate. Authentic
# Register ${NEXT_PUBLIC_APP_URL}/api/mcp/oauth/callback in the HubSpot MCP connector.
# HUBSPOT_MCP_CLIENT_ID=
# HUBSPOT_MCP_CLIENT_SECRET=

# Zoom member search: separate General OAuth app to preserve workflow grants.
# Register ${NEXT_PUBLIC_APP_URL}/api/mcp/oauth/callback with the two meeting read scopes.
# ZOOM_MCP_CLIENT_ID=
# ZOOM_MCP_CLIENT_SECRET=
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ export function LiveMemberIntegrations({ organizationId, search }: LiveMemberInt
const available = LIVE_SEARCH_SOURCE_TYPES.filter(
([provider]) =>
LIVE_SEARCH_SCOPE_FIELDS[provider] &&
(provider !== 'hubspot' ||
data.availableMcpConnectors.includes('hubspot') ||
((provider !== 'hubspot' && provider !== 'zoom') ||
data.availableMcpConnectors.includes(provider) ||
mcpAccounts(provider).length > 0) &&
(approvals.get(provider)?.approved ||
data.viewerAccounts?.some(
Expand Down Expand Up @@ -134,7 +134,8 @@ export function LiveMemberIntegrations({ organizationId, search }: LiveMemberInt
Boolean(option || server) &&
approved &&
(!option || option.configurationStatus === 'ready') &&
(provider !== 'hubspot' || data.availableMcpConnectors.includes('hubspot'))
((provider !== 'hubspot' && provider !== 'zoom') ||
data.availableMcpConnectors.includes(provider))
const scope =
approval?.policy?.accessMode === 'service_account'
? 'Selected resources you can access'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export function LiveSearchSettings() {
type,
meta,
availabilityStatus:
type !== 'hubspot' || accounts.isSuccess
(type !== 'hubspot' && type !== 'zoom') || accounts.isSuccess
? undefined
: accounts.isError
? ('error' as const)
Expand Down
14 changes: 6 additions & 8 deletions apps/sim/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ interface LucidIconProps extends SVGProps<SVGSVGElement> {}

export function LucidIcon(props: LucidIconProps) {
return (
<svg
{...props}
viewBox='-22 0 144 144.5'
fill='currentColor'
xmlns='http://www.w3.org/2000/svg'
>
<path d='M50 0L0 28.9V144.5L50 115.6V0Z' />
<path d='M100 142.7V86.7L50 115.6V142.7H100Z' />
<svg {...props} viewBox='0 0 192 192' fill='none' xmlns='http://www.w3.org/2000/svg'>
<rect width='192' height='192' rx='32' fill='#282C33' />
<g transform='translate(46 24)' fill='#FFFFFF'>
<path d='M50 0L0 28.9V144.5L50 115.6V0Z' />
<path d='M100 142.7V86.7L50 115.6V142.7H100Z' />
</g>
</svg>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ export function OrganizationAccountProviderCatalog({
)
.map((connectorId) => ({
name:
connectorId === 'hubspot'
? 'HubSpot (member access)'
connectorId === 'hubspot' || connectorId === 'zoom'
? `${MANAGED_MCP_CONNECTORS[connectorId].name} (member access)`
: MANAGED_MCP_CONNECTORS[connectorId].name,
icon: getManagedMcpConnectorIcon(connectorId),
choice: { kind: 'mcp', connectorId } as const,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ export function OrganizationAccountProviders({
.map((server) => ({
id: server.id,
name:
server.managedConnectorId === 'hubspot'
? 'HubSpot (member access)'
server.managedConnectorId === 'hubspot' || server.managedConnectorId === 'zoom'
? `${MANAGED_MCP_CONNECTORS[server.managedConnectorId].name} (member access)`
: MANAGED_MCP_CONNECTORS[server.managedConnectorId].name,
icon: getManagedMcpConnectorIcon(server.managedConnectorId),
configure:
Expand Down
1 change: 1 addition & 0 deletions apps/sim/lib/api/contracts/credential-groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ export const createCredentialGroupMcpConnectorBodySchema = z.discriminatedUnion(
z.object({ connectorId: z.literal('coda') }).strict(),
z.object({ connectorId: z.literal('hubspot') }).strict(),
z.object({ connectorId: z.literal('lucid') }).strict(),
z.object({ connectorId: z.literal('zoom') }).strict(),
z
.object({
connectorId: z.literal('databricks'),
Expand Down
Loading
Loading