Skip to content

docs(mcp): add Antigravity client#2265

Closed
everettbu wants to merge 6 commits into
masterfrom
mattrossman/ai-469-docs-antigravity-mcp
Closed

docs(mcp): add Antigravity client#2265
everettbu wants to merge 6 commits into
masterfrom
mattrossman/ai-469-docs-antigravity-mcp

Conversation

@everettbu

Copy link
Copy Markdown

Mirror of supabase/supabase#43597
Original author: mattrossman


Adds Google Antigravity as an MCP client option in the docs config panel and Studio, including auth steps.

Icon sourced from https://antigravity.google/press

Dark Light
CleanShot 2026-03-10 at 11 13 15`@2x` CleanShot 2026-03-10 at 11 13 07`@2x`

Verified this config connects to our remote MCP server in Antigravity:

CleanShot 2026-03-10 at 10 27 15`@2x`

Closes AI-469

@everettbu everettbu added the documentation Improvements or additions to documentation label Mar 10, 2026
@greptile-apps-staging

greptile-apps-staging Bot commented Mar 10, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds Google Antigravity as a supported MCP client in the Supabase docs config panel and Studio. It follows the established pattern for adding new MCP clients, introducing a new AntigravityMcpConfig type, a corresponding type guard, a PNG icon asset (instead of the usual SVG), and the infrastructure change needed to support non-SVG icon extensions.

  • Adds AntigravityMcpConfig interface (mcpServers.supabase.serverUrl) and isAntigravityMcpConfig type guard in types.ts.
  • Correctly inserts the isAntigravityMcpConfig check in getMcpUrl before the broader isMcpServersConfig guard, which would otherwise also match this new config shape and return undefined (since it accesses .url which is absent here).
  • Introduces iconExtension as an optional field on McpClient (defaulting to 'svg') and threads it through ConnectionIcon, ClientSelectDropdown, and getMcpButtonData — maintaining full backward compatibility.
  • Adds a PNG icon to both apps/docs and apps/studio public directories.
  • The JSDoc on getMcpClientIconSrc still explicitly references .svg after the extension was made configurable — a minor documentation accuracy issue worth fixing.

Confidence Score: 5/5

  • This PR is safe to merge — it follows the established MCP client addition pattern with no logic regressions.
  • The change is additive and well-scoped: a new MCP client entry, a new interface + type guard, and a small backward-compatible extension to the icon infrastructure. The only behavioural risk — the type guard ordering in getMcpUrl — is handled correctly. No tests are broken, no existing clients are affected.
  • No files require special attention, though the stale JSDoc in getMcpIconSrc.ts is worth a quick fix.

Important Files Changed

Filename Overview
packages/ui-patterns/src/McpUrlBuilder/types.ts Adds AntigravityMcpConfig interface with serverUrl field, a type guard isAntigravityMcpConfig, and correctly inserts it into getMcpUrl before the broader isMcpServersConfig check to avoid false matches.
packages/ui-patterns/src/McpUrlBuilder/utils/getMcpIconSrc.ts Adds iconExtension parameter (defaulting to 'svg' for backward compatibility) to support PNG icons; the function's JSDoc comment still references .svg explicitly and is now slightly stale.
packages/ui-patterns/src/McpUrlBuilder/constants.tsx Adds Antigravity client entry with png iconExtension, correct configFile path, transformConfig mapping url→serverUrl, and alternateInstructions with OAuth/auth troubleshooting steps.
packages/ui-patterns/src/McpUrlBuilder/components/ConnectionIcon.tsx Correctly threads new iconExtension prop through to getMcpClientIconSrc.
packages/ui-patterns/src/McpUrlBuilder/components/ClientSelectDropdown.tsx Passes iconExtension from client config to ConnectionIcon in both the selected-client header and dropdown-list item renderers.
packages/ui-patterns/src/McpUrlBuilder/utils/getMcpButtonData.ts Forwards iconExtension to getMcpClientIconSrc for deep-link button image generation.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[McpClient config\nantigravity entry] -->|transformConfig| B[AntigravityMcpConfig\nmcpServers.supabase.serverUrl]
    B --> C{getMcpUrl}
    C -->|isAntigravityMcpConfig| D[return serverUrl]
    C -->|isMcpServersConfig\nfallback - would also match\nbut checked after| E[return .url]

    F[ConnectionIcon / ClientSelectDropdown\niconExtension=png] --> G[getMcpClientIconSrc\niconExtension=png]
    G --> H[antigravity-icon.png\nno dark variant needed]

    style D fill:#22c55e,color:#fff
    style E fill:#94a3b8,color:#fff
Loading

Comments Outside Diff (1)

  1. packages/ui-patterns/src/McpUrlBuilder/utils/getMcpIconSrc.ts, line 1-5 (link)

    Stale JSDoc after iconExtension addition

    The function docstring explicitly mentions .svg twice but the extension is now configurable via the new iconExtension parameter. This will mislead future callers who read the doc and don't realise PNG (or any other format) is supported.

Last reviewed commit: 0555359

@greptile-apps-staging

Copy link
Copy Markdown

🦖 T-Rex

Generated 3 test(s) for 2 file(s): 2 passed, 1 failed, 0 skipped

Test Coverage Summary

Validated type guard correctness and URL resolution logic for MCP configuration handling, along with icon source generation with custom file extensions. One critical type guard defect was confirmed—isMcpServersConfig incorrectly matches configurations it should reject, creating a silent failure risk where consumers would receive undefined instead of expected URL values. The dependency on guard ordering for correct behavior introduces fragility that could cause regressions if guards are reordered or removed.

Potential Issues

  • HIGH — isMcpServersConfig should NOT match AntigravityMcpConfig (it only has serverUrl, not url): Tests that isMcpServersConfig does not match AntigravityMcpConfig. The guard checks only 'mcpServers' in config && 'supabase' in config.mcpServers, which is true for Antigravity configs. The test asserts the correct behavior (returns false for Antigravity) — it will fail because the current implementation returns true.
    🛠 Fix: Add 'url' in config.mcpServers.supabase to the isMcpServersConfig check so it only matches configs that actually have the .url field: return 'mcpServers' in config && 'supabase' in config.mcpServers && 'url' in config.mcpServers.supabase
Test Results (3 tests)
isMcpServersConfig should NOT match AntigravityMcpConfig (it only has serverUrl, not url) HIGH packages/ui-patterns/src/McpUrlBuilder/types.ts (1/2 passed)

Why this failed: Tests that isMcpServersConfig does not match AntigravityMcpConfig. The guard checks only 'mcpServers' in config && 'supabase' in config.mcpServers, which is true for Antigravity configs. The test asserts the correct behavior (returns false for Antigravity) — it will fail because the current implementation returns true.

Terminal Output


�[1m�[46m RUN �[49m�[22m �[36mv4.0.18 �[39m�[90m/tmp/mcp-tests�[39m

 �[31m�[39m isMcpServersConfig.test.ts�[2m > �[22misMcpServersConfig�[2m > �[22mshould NOT match AntigravityMcpConfig because it uses serverUrl, not url�[32m 8�[2mms�[22m�[39m
�[31m   → expected true to be false // Object.is equality�[39m
 �[32m✓�[39m isMcpServersConfig.test.ts�[2m > �[22misMcpServersConfig�[2m > �[22mshould match standard McpClientBaseConfig that has url�[32m 0�[2mms�[22m�[39m
 �[32m✓�[39m isMcpServersConfig.test.ts�[2m > �[22misMcpServersConfig�[2m > �[22misAntigravityMcpConfig should correctly identify Antigravity config�[32m 0�[2mms�[22m�[39m
 �[32m✓�[39m isMcpServersConfig.test.ts�[2m > �[22misMcpServersConfig�[2m > �[22misAntigravityMcpConfig should NOT match standard base config that has url, not serverUrl�[32m 0�[2mms�[22m�[39m

�[31m⎯⎯⎯⎯⎯⎯⎯�[39m�[1m�[41m Failed Tests 1 �[49m�[22m�[31m⎯⎯⎯⎯⎯⎯⎯�[39m

�[41m�[1m FAIL �[22m�[49m isMcpServersConfig.test.ts�[2m > �[22misMcpServersConfig�[2m > �[22mshould NOT match AntigravityMcpConfig because it uses serverUrl, not url
�[31m�[1mAssertionError�[22m: expected true to be false // Object.is equality�[39m

�[32m- Expected�[39m
�[31m+ Received�[39m

�[32m- false�[39m
�[31m+ true�[39m

�[36m �[2m❯�[22m isMcpServersConfig.test.ts:�[2m30:20�[22m�[39m
    �[90m 28| �[39m    // The correct behavior is false (Antigravity is NOT a McpServersC…
    �[90m 29| �[39m    // If the bug exists, this returns true — revealing that the guard…
    �[90m 30| �[39m    �[34mexpect�[39m(result)�[33m.�[39m�[34mtoBe�[39m(�[35mfalse�[39m)
    �[90m   | �[39m                   �[31m^�[39m
    �[90m 31| �[39m  })
    �[90m 32| �[39m

�[31m�[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯�[22m�[39m


�[2m Test Files �[22m �[1m�[31m1 failed�[39m�[22m�[90m (1)�[39m
�[2m      Tests �[22m �[1m�[31m1 failed�[39m�[22m�[2m | �[22m�[1m�[32m3 passed�[39m�[22m�[90m (4)�[39m
�[2m   Start at �[22m 16:11:56
�[2m   Duration �[22m 247ms�[2m (transform 53ms, setup 0ms, import 69ms, tests 11ms, environment 0ms)�[22m



Command failed: cd /tmp/mcp-tests && node_modules/.bin/vitest run isMcpServersConfig.test.ts --reporter=verbose 2>&1

Test Code - ../../../tmp/mcp-tests/isMcpServersConfig.test.ts

import { describe, it, expect } from 'vitest'
import { isMcpServersConfig, isAntigravityMcpConfig } from '/github/greptileai/supabase-mirror/packages/ui-patterns/src/McpUrlBuilder/types'

// A valid Antigravity config that has serverUrl (NOT url)
const antigravityConfig = {
  mcpServers: {
    supabase: {
      serverUrl: 'https://mcp.supabase.com/v1/sse',
    },
  },
}

// A standard base config that has url (NOT serverUrl)
const baseConfig = {
  mcpServers: {
    supabase: {
      url: 'https://mcp.supabase.com/v1/sse',
    },
  },
}

describe('isMcpServersConfig', () => {
  it('should NOT match AntigravityMcpConfig because it uses serverUrl, not url', () => {
    // This test exposes the bug: isMcpServersConfig only checks for mcpServers.supabase,
    // so it incorrectly returns true for Antigravity configs which have serverUrl instead of url.
    // Accessing .url on the narrowed type would return undefined.
    const result = isMcpServersConfig(antigravityConfig as any)
    // The correct behavior is false (Antigravity is NOT a McpServersConfig)
    // If the bug exists, this returns true — revealing that the guard is too broad.
    expect(result).toBe(false)
  })

  it('should match standard McpClientBaseConfig that has url', () => {
    expect(isMcpServersConfig(baseConfig as any)).toBe(true)
  })

  it('isAntigravityMcpConfig should correctly identify Antigravity config', () => {
    expect(isAntigravityMcpConfig(antigravityConfig as any)).toBe(true)
  })

  it('isAntigravityMcpConfig should NOT match standard base config that has url, not serverUrl', () => {
    expect(isAntigravityMcpConfig(baseConfig as any)).toBe(false)
  })
})
getMcpUrl returns serverUrl for AntigravityMcpConfig and does not fall back to isMcpServersConfig MEDIUM packages/ui-patterns/src/McpUrlBuilder/types.ts (1/2 passed)

Terminal Output


�[1m�[46m RUN �[49m�[22m �[36mv4.0.18 �[39m�[90m/tmp/mcp-tests�[39m

 �[32m✓�[39m getMcpUrl.test.ts�[2m > �[22mgetMcpUrl for AntigravityMcpConfig�[2m > �[22mshould return the serverUrl value (not undefined) for an Antigravity config�[32m 2�[2mms�[22m�[39m
 �[32m✓�[39m getMcpUrl.test.ts�[2m > �[22mgetMcpUrl for AntigravityMcpConfig�[2m > �[22mshould not return undefined when given an Antigravity config�[32m 0�[2mms�[22m�[39m
 �[32m✓�[39m getMcpUrl.test.ts�[2m > �[22mgetMcpUrl for AntigravityMcpConfig�[2m > �[22mdemonstrates the ordering risk: isMcpServersConfig matches Antigravity and would return undefined url�[32m 0�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m      Tests �[22m �[1m�[32m3 passed�[39m�[22m�[90m (3)�[39m
�[2m   Start at �[22m 16:12:14
�[2m   Duration �[22m 246ms�[2m (transform 55ms, setup 0ms, import 72ms, tests 4ms, environment 0ms)�[22m


Test Code - ../../../tmp/mcp-tests/getMcpUrl.test.ts

import { describe, it, expect } from 'vitest'
import {
  getMcpUrl,
  isMcpServersConfig,
  isAntigravityMcpConfig,
} from '/github/greptileai/supabase-mirror/packages/ui-patterns/src/McpUrlBuilder/types'

const antigravityConfig = {
  mcpServers: {
    supabase: {
      serverUrl: 'https://mcp.supabase.com/v1/sse',
    },
  },
}

describe('getMcpUrl for AntigravityMcpConfig', () => {
  it('should return the serverUrl value (not undefined) for an Antigravity config', () => {
    // If isAntigravityMcpConfig check is removed/reordered, isMcpServersConfig would match
    // and return .url which is undefined on AntigravityMcpConfig.
    const result = getMcpUrl(antigravityConfig as any)
    expect(result).toBe('https://mcp.supabase.com/v1/sse')
  })

  it('should not return undefined when given an Antigravity config', () => {
    const result = getMcpUrl(antigravityConfig as any)
    // If the ordering bug exists and isMcpServersConfig matches first,
    // it would return config.mcpServers.supabase.url which is undefined
    expect(result).not.toBeUndefined()
  })

  it('demonstrates the ordering risk: isMcpServersConfig matches Antigravity and would return undefined url', () => {
    // Demonstrate that isMcpServersConfig matches this config (the bug),
    // and show that accessing .url on it returns undefined
    const matched = isMcpServersConfig(antigravityConfig as any)
    if (matched) {
      // TypeScript thinks this is McpClientBaseConfig with .url, but at runtime it's undefined
      const narrowed = antigravityConfig as any
      const urlViaWrongGuard = narrowed.mcpServers.supabase.url
      // This should be undefined since Antigravity only has serverUrl
      expect(urlViaWrongGuard).toBeUndefined()
    }
  })
})
getMcpClientIconSrc handles iconExtension correctly for PNG icons LOW packages/ui-patterns/src/McpUrlBuilder/utils/getMcpIconSrc.ts (1/1 passed)

Terminal Output


�[1m�[46m RUN �[49m�[22m �[36mv4.0.18 �[39m�[90m/tmp/mcp-tests�[39m

 �[32m✓�[39m getMcpIconSrc.test.ts�[2m > �[22mgetMcpClientIconSrc with iconExtension�[2m > �[22mshould use png extension when iconExtension is "png" (Antigravity case)�[32m 2�[2mms�[22m�[39m
 �[32m✓�[39m getMcpIconSrc.test.ts�[2m > �[22mgetMcpClientIconSrc with iconExtension�[2m > �[22mshould default to svg extension when iconExtension is not specified�[32m 0�[2mms�[22m�[39m
 �[32m✓�[39m getMcpIconSrc.test.ts�[2m > �[22mgetMcpClientIconSrc with iconExtension�[2m > �[22mshould use svg dark variant when iconExtension defaults to svg and hasDistinctDarkIcon is true�[32m 0�[2mms�[22m�[39m
 �[32m✓�[39m getMcpIconSrc.test.ts�[2m > �[22mgetMcpClientIconSrc with iconExtension�[2m > �[22mshould NOT append -dark suffix for png icon when hasDistinctDarkIcon is false�[32m 1�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m      Tests �[22m �[1m�[32m4 passed�[39m�[22m�[90m (4)�[39m
�[2m   Start at �[22m 16:12:51
�[2m   Duration �[22m 279ms�[2m (transform 63ms, setup 0ms, import 81ms, tests 5ms, environment 0ms)�[22m


Test Code - ../../../tmp/mcp-tests/getMcpIconSrc.test.ts

import { describe, it, expect } from 'vitest'
import { getMcpClientIconSrc } from '/github/greptileai/supabase-mirror/packages/ui-patterns/src/McpUrlBuilder/utils/getMcpIconSrc'

describe('getMcpClientIconSrc with iconExtension', () => {
  it('should use png extension when iconExtension is "png" (Antigravity case)', () => {
    const src = getMcpClientIconSrc({
      basePath: '',
      iconFolder: 'mcp-clients',
      icon: 'antigravity',
      useDarkVariant: false,
      hasDistinctDarkIcon: false,
      iconExtension: 'png',
    })
    expect(src).toBe('/img/mcp-clients/antigravity-icon.png')
    expect(src).not.toMatch(/\.svg$/)
  })

  it('should default to svg extension when iconExtension is not specified', () => {
    const src = getMcpClientIconSrc({
      basePath: '',
      iconFolder: 'mcp-clients',
      icon: 'cursor',
      useDarkVariant: false,
      hasDistinctDarkIcon: false,
    })
    expect(src).toBe('/img/mcp-clients/cursor-icon.svg')
  })

  it('should use svg dark variant when iconExtension defaults to svg and hasDistinctDarkIcon is true', () => {
    const src = getMcpClientIconSrc({
      basePath: '',
      iconFolder: 'mcp-clients',
      icon: 'claude',
      useDarkVariant: true,
      hasDistinctDarkIcon: true,
      iconExtension: 'svg',
    })
    expect(src).toBe('/img/mcp-clients/claude-icon-dark.svg')
  })

  it('should NOT append -dark suffix for png icon when hasDistinctDarkIcon is false', () => {
    // Antigravity has no distinct dark icon, so dark theme must NOT generate -dark variant path
    const src = getMcpClientIconSrc({
      basePath: '',
      iconFolder: 'mcp-clients',
      icon: 'antigravity',
      useDarkVariant: true,
      hasDistinctDarkIcon: false,
      iconExtension: 'png',
    })
    expect(src).toBe('/img/mcp-clients/antigravity-icon.png')
    expect(src).not.toContain('-dark')
  })
})

Generated by Greptile

@github-actions

github-actions Bot commented Mar 10, 2026

Copy link
Copy Markdown
Contributor

🎭 Playwright Test Results

passed  158 passed
flaky  2 flaky
skipped  5 skipped

Details

stats  165 tests across 20 suites
duration  3 minutes, 39 seconds
commit  8c2605e

Flaky tests

Features › queue-table-operations.spec.ts › Queue Table Operations › pending changes persist when switching between tables
Features › realtime-inspector.spec.ts › Realtime Inspector › Broadcast Messages › broadcast modal validates JSON payload

Skipped tests

Features › assistant.spec.ts › AI Assistant › Can send a message to the assistant and receive a response
Features › sql-editor.spec.ts › SQL Editor › snippet favourite works as expected
Features › sql-editor.spec.ts › SQL Editor › share with team works as expected
Features › sql-editor.spec.ts › SQL Editor › folders works as expected
Features › sql-editor.spec.ts › SQL Editor › other SQL snippets actions work as expected

@blacksmith-sh

This comment has been minimized.

@everettbu

Copy link
Copy Markdown
Author

Upstream PR was closed or merged. Code is synced via branch mirror.

@everettbu everettbu closed this Mar 12, 2026
@everettbu everettbu deleted the mattrossman/ai-469-docs-antigravity-mcp branch March 12, 2026 20:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants