mirror of
https://github.com/supabase/supabase.git
synced 2026-10-11 04:15:04 +03:00
Merge branch 'master' into docs/postgres-js-pipelining-transaction-mode
This commit is contained in:
22 files changed
+320
-15
No files matched your search
@@ -19,6 +19,7 @@ const ICON_ASSETS: Record<string, { icon: string; hasLightIcon?: boolean }> = {
|
||||
'gemini-cli': { icon: '/docs/img/icons/agent-gemini-cli-icon', hasLightIcon: false },
|
||||
'github-copilot': { icon: '/docs/img/icons/agent-copilot-icon', hasLightIcon: true },
|
||||
kimi: { icon: '/docs/img/icons/agent-kimi-icon', hasLightIcon: true },
|
||||
omp: { icon: '/docs/img/icons/agent-omp-icon', hasLightIcon: false },
|
||||
vscode: { icon: '/docs/img/icons/agent-vscode-icon', hasLightIcon: false },
|
||||
antigravity: { icon: '/docs/img/icons/agent-antigravity-icon', hasLightIcon: false },
|
||||
windsurf: { icon: '/docs/img/icons/agent-devin-icon', hasLightIcon: true },
|
||||
@@ -46,6 +47,7 @@ const TAGLINES: Record<string, string> = {
|
||||
goose: 'Your native open source AI agent — desktop app, CLI, and API.',
|
||||
kimi: 'Engineered to drop into any dev workflow and get programming tasks done fast.',
|
||||
kiro: 'Move beyond AI coding to agentic engineering.',
|
||||
omp: 'A coding agent with the IDE wired in.',
|
||||
opencode: 'The open source AI coding agent.',
|
||||
vscode: 'The open source AI code editor — your home for multi-agent development.',
|
||||
// Pre-acquisition tagline (Cognition/Devin acquired Windsurf in 2025) — see "Open questions".
|
||||
|
||||
@@ -63,6 +63,14 @@ export const PLUGIN_CLIENTS: PluginClient[] = [
|
||||
repoUrl: 'https://github.com/supabase-community/supabase-plugin',
|
||||
docsUrl: 'https://www.kimi.com/code/docs/en/kimi-code-cli/customization/plugins.html',
|
||||
},
|
||||
{
|
||||
key: 'omp',
|
||||
label: 'omp',
|
||||
icon: 'omp',
|
||||
repoUrl: 'https://github.com/supabase-community/supabase-plugin',
|
||||
docsUrl: 'https://github.com/can1357/oh-my-pi/blob/main/docs/marketplace.md',
|
||||
docsLinkText: 'View omp plugin docs',
|
||||
},
|
||||
{
|
||||
key: 'vscode',
|
||||
label: 'VS Code',
|
||||
|
||||
@@ -169,6 +169,38 @@ function PluginInstructions({ client }: { client: PluginClient }) {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (client.key === 'omp') {
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<p className="text-sm text-foreground-light">
|
||||
omp reads the Claude Code plugin format, so install the Supabase plugin from the{' '}
|
||||
<a
|
||||
href="https://github.com/anthropics/claude-plugins-official"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-brand-link hover:underline"
|
||||
>
|
||||
official Anthropic marketplace
|
||||
</a>
|
||||
:
|
||||
</p>
|
||||
<CodeBlock
|
||||
value={`omp plugin marketplace add anthropics/claude-plugins-official\nomp plugin install supabase@claude-plugins-official`}
|
||||
language="bash"
|
||||
focusable={false}
|
||||
className="block"
|
||||
/>
|
||||
<p className="text-xs text-foreground-lighter">
|
||||
Installs with <code>--scope user</code> by default, making it available across all your
|
||||
projects. Use <code>--scope project</code> to install it for the current project only.
|
||||
</p>
|
||||
<p className="text-xs text-foreground-lighter">
|
||||
Inside a session, run <code>/marketplace</code> to browse plugins, then{' '}
|
||||
<code>/reload-plugins</code> after installing to load the skills and MCP server.
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (client.key === 'vscode') {
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<defs>
|
||||
<linearGradient id="omp-mark" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#ed4abf" />
|
||||
<stop offset=".5" stop-color="#9b4dff" />
|
||||
<stop offset="1" stop-color="#5ad8e6" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="64" height="64" rx="12" fill="#0f0a14" />
|
||||
<path fill="url(#omp-mark)" d="M14 16h36v8H40v32h-8V24h-6v22h-8V24h-4z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 471 B |
@@ -6,6 +6,8 @@ import react from '@astrojs/react'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
import { defineConfig } from 'astro/config'
|
||||
|
||||
import supabaseTheme from '../learn/lib/themes/supabase-2.json' with { type: 'json' }
|
||||
|
||||
// Absolute dir of lodash-es, for the SSR-only lodash alias below (same fix
|
||||
// apps/studio/vite.config.ts uses). `packages/ui`'s clipboard util does
|
||||
// `import { noop } from 'lodash'` — under Vite's dev-mode SSR module runner,
|
||||
@@ -45,4 +47,23 @@ export default defineConfig({
|
||||
},
|
||||
plugins: [tailwindcss(), ssrLodashEs],
|
||||
},
|
||||
markdown: {
|
||||
shikiConfig: {
|
||||
theme: supabaseTheme,
|
||||
// Match the docs app's CodeBlock component (border + rounded-lg on the
|
||||
// outer element), since Astro's own markdown pipeline renders code
|
||||
// blocks straight to a `<pre>` with no wrapper we can add classes to.
|
||||
transformers: [
|
||||
{
|
||||
name: 'kb-code-block-classes',
|
||||
pre(node) {
|
||||
this.addClassToHast(node, 'border border-default rounded-lg')
|
||||
},
|
||||
code(node) {
|
||||
this.addClassToHast(node, 'inline-block p-6')
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -9,15 +9,16 @@ import {
|
||||
navigationMenuTriggerStyle,
|
||||
} from 'ui'
|
||||
|
||||
import { TOPICS, topicToSlug } from '../lib/topics'
|
||||
|
||||
const topics = TOPICS.map((topic) => ({
|
||||
label: topic.name,
|
||||
href: `${import.meta.env.BASE_URL}/topics/${topicToSlug(topic.name)}`,
|
||||
}))
|
||||
|
||||
/**
|
||||
* Hard-codding links in here for now until we have actual content. Might be worth putting these arrays in their on data file too.
|
||||
*/
|
||||
const topics = [
|
||||
{ label: 'Troubleshooting', href: '#' },
|
||||
{ label: 'Migrations', href: '#' },
|
||||
{ label: 'Comparisons', href: '#' },
|
||||
]
|
||||
|
||||
const resources = [
|
||||
{ label: 'Status', href: 'https://status.supabase.com' },
|
||||
{ label: 'Changelog', href: 'https://supabase.com/changelog' },
|
||||
|
||||
@@ -2,6 +2,8 @@ import { defineCollection } from 'astro:content'
|
||||
import { glob } from 'astro/loaders'
|
||||
import { z } from 'astro/zod'
|
||||
|
||||
import { TOPIC_NAMES } from './lib/topics'
|
||||
|
||||
// Every entry here is rendered through GuideLayout by
|
||||
// src/pages/guides/[...slug].astro — dropping a new file in
|
||||
// src/content/guides doesn't need any per-file layout wiring.
|
||||
@@ -9,8 +11,10 @@ const guides = defineCollection({
|
||||
loader: glob({ pattern: '**/*.md', base: './src/content/guides' }),
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string().optional(),
|
||||
topics: z.array(z.string()).optional(),
|
||||
description: z.string(),
|
||||
// z.enum (not z.string) so a guide referencing a topic outside TOPICS
|
||||
// fails content validation instead of silently rendering an orphaned tag.
|
||||
topics: z.array(z.enum(TOPIC_NAMES)),
|
||||
github_url: z.string().optional(),
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Markdown elements sample'
|
||||
description: 'A lorem ipsum sample guide exercising every base Markdown element supported by the guide layout.'
|
||||
topics: ['example', 'markdown']
|
||||
topics: ['Tutorial', 'Database']
|
||||
github_url: 'https://github.com/supabase/supabase/discussions/0000000'
|
||||
---
|
||||
|
||||
|
||||
@@ -3,11 +3,12 @@ import { Github } from 'lucide-react'
|
||||
import { Badge } from 'ui'
|
||||
|
||||
import Layout from './Layout.astro'
|
||||
import { getTopicDescription, type Topic, topicToSlug } from '../lib/topics'
|
||||
|
||||
interface Props {
|
||||
title: string
|
||||
description?: string
|
||||
topics?: string[]
|
||||
topics?: Topic[]
|
||||
github_url?: string
|
||||
}
|
||||
|
||||
@@ -21,7 +22,14 @@ const { title, description, topics = [], github_url } = Astro.props
|
||||
{
|
||||
topics.length > 0 && (
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{topics.map((topic) => <Badge>{topic}</Badge>)}
|
||||
{topics.map((topic) => (
|
||||
<a
|
||||
href={`${import.meta.env.BASE_URL}/topics/${topicToSlug(topic)}`}
|
||||
title={getTopicDescription(topic)}
|
||||
>
|
||||
<Badge>{topic}</Badge>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Canonical list of guide topics. Single source of truth for the `topics`
|
||||
// field in src/content.config.ts (so a guide with an unsupported topic fails
|
||||
// content validation), the "Topics" nav menu, and the /topics/[topic] pages.
|
||||
export const TOPICS = [
|
||||
{ name: 'Migration', description: 'Moving data, schemas, or projects onto Supabase' },
|
||||
{ name: 'Comparison', description: 'How Supabase compares to other databases and platforms' },
|
||||
{ name: 'Troubleshooting', description: 'Common errors and how to resolve them' },
|
||||
{ name: 'Tutorial', description: 'Step-by-step walkthroughs for building with Supabase' },
|
||||
{ name: 'Storage', description: 'Uploading, managing, and serving files' },
|
||||
{ name: 'Auth', description: 'Authentication, authorization, and user management' },
|
||||
{ name: 'Database', description: 'Postgres schemas, queries, and performance' },
|
||||
{ name: 'Edge Functions', description: 'Deploying and running serverless functions' },
|
||||
{ name: 'Queues', description: 'Background jobs and message processing' },
|
||||
{ name: 'Realtime', description: 'Broadcast, presence, and database changes' },
|
||||
{ name: 'Supabase Platform', description: 'Project settings, billing, and infrastructure' },
|
||||
] as const
|
||||
|
||||
export type Topic = (typeof TOPICS)[number]['name']
|
||||
|
||||
// zod's `enum()` needs a literal non-empty tuple of strings, which `.map()`
|
||||
// can't preserve on its own — this cast is safe because TOPICS is `as const`.
|
||||
export const TOPIC_NAMES = TOPICS.map((topic) => topic.name) as [Topic, ...Topic[]]
|
||||
|
||||
export function getTopicDescription(topic: Topic): string {
|
||||
return TOPICS.find((t) => t.name === topic)!.description
|
||||
}
|
||||
|
||||
// URL-safe slug for a topic, e.g. "Edge Functions" -> "edge-functions".
|
||||
export function topicToSlug(topic: Topic): string {
|
||||
return topic.toLowerCase().replace(/\s+/g, '-')
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
import { getCollection } from 'astro:content'
|
||||
|
||||
import Layout from '../../layouts/Layout.astro'
|
||||
import { TOPICS, topicToSlug } from '../../lib/topics'
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const guides = await getCollection('guides')
|
||||
|
||||
// One page per topic in TOPICS — not just topics a guide already uses —
|
||||
// so every link on the "Topics" nav resolves instead of 404ing.
|
||||
return TOPICS.map((topic) => ({
|
||||
params: { topic: topicToSlug(topic.name) },
|
||||
props: {
|
||||
topic: topic.name,
|
||||
description: topic.description,
|
||||
guides: guides.filter((guide) => guide.data.topics?.includes(topic.name)),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
const { topic, description, guides } = Astro.props
|
||||
---
|
||||
|
||||
<Layout title={topic} description={description}>
|
||||
<article class="prose max-w-3xl mx-auto px-6 py-16">
|
||||
<h1>{topic}</h1>
|
||||
<p class="lead">{description}</p>
|
||||
{
|
||||
guides.length === 0 ? (
|
||||
<p>No guides for this topic</p>
|
||||
) : (
|
||||
<ul>
|
||||
{guides.map((guide) => (
|
||||
<li>
|
||||
<a href={`${import.meta.env.BASE_URL}/guides/${guide.id}`}>{guide.data.title}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
</article>
|
||||
</Layout>
|
||||
@@ -73,8 +73,35 @@ h6:not(.font-mono),
|
||||
border-color: var(--border-default, currentColor);
|
||||
}
|
||||
|
||||
/* TEMPORARY UNTIL WE IMPLEMENT OUR OWN CODE COMPONENT */
|
||||
.prose pre code {
|
||||
padding: 1rem;
|
||||
display: inline-block;
|
||||
/* Code block theme colors for use with Supabase Theme */
|
||||
[data-theme='dark'] {
|
||||
--code-token-keyword: #bda4ff;
|
||||
--code-foreground: #ffffff;
|
||||
--code-token-constant: #3ecf8e;
|
||||
--code-token-string: #ffcda1;
|
||||
--code-token-comment: #949494;
|
||||
--code-token-parameter: #ffffff;
|
||||
--code-token-function: #3ecf8e;
|
||||
--code-token-string-expression: #ffcda1;
|
||||
--code-token-punctuation: #ffffff;
|
||||
--code-token-link: #ffffff;
|
||||
--code-token-number: #ffffff;
|
||||
--code-token-property: #3ecf8e;
|
||||
--code-highlight-color: #232323;
|
||||
}
|
||||
|
||||
[data-theme='light'] {
|
||||
--code-token-keyword: #5f2fc4;
|
||||
--code-foreground: oklch(from var(--foreground-light) l c h / 1);
|
||||
--code-token-constant: #15593b;
|
||||
--code-token-string: #9a5200;
|
||||
--code-token-comment: #6a6a6a;
|
||||
--code-token-parameter: oklch(from var(--foreground-light) l c h / 1);
|
||||
--code-token-function: #15593b;
|
||||
--code-token-string-expression: #9a5200;
|
||||
--code-token-punctuation: oklch(from var(--foreground-light) l c h / 1);
|
||||
--code-token-link: oklch(from var(--foreground-light) l c h / 1);
|
||||
--code-token-number: oklch(from var(--foreground-light) l c h / 1);
|
||||
--code-token-property: #15593b;
|
||||
--code-highlight-color: #1c1c1c;
|
||||
}
|
||||
@@ -171,6 +171,12 @@ export const useIsExplorerEnabled = () => {
|
||||
return isExplorerEnabled && flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_EXPLORER]
|
||||
}
|
||||
|
||||
export const useIsStorageVersioningEnabled = () => {
|
||||
const { flags } = useFeaturePreviewContext()
|
||||
const isStorageVersioningEnabled = useFlag('storageVersioningPrivateAlpha')
|
||||
return isStorageVersioningEnabled && flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_STORAGE_VERSIONING]
|
||||
}
|
||||
|
||||
export const useFeaturePreviewModal = () => {
|
||||
const featurePreviews = useFeaturePreviews()
|
||||
const [featurePreviewModal, setFeaturePreviewModal] = useQueryState('featurePreviewModal')
|
||||
|
||||
@@ -39,6 +39,7 @@ import { JitDbAccessPreview } from './JitDbAccessPreview'
|
||||
import { PgDeltaDiffPreview } from './PgDeltaDiffPreview'
|
||||
import { PlatformWebhooksPreview } from './PlatformWebhooksPreview'
|
||||
import { SqlEditorManualSavePreview } from './SqlEditorManualSavePreview'
|
||||
import { StorageVersioningPreview } from './StorageVersioningPreview'
|
||||
import { UnifiedLogsPreview } from './UnifiedLogsPreview'
|
||||
import { FeaturePreview, useFeaturePreviews } from './useFeaturePreviews'
|
||||
import { useBannerStack } from '@/components/ui/BannerStack/BannerStackProvider'
|
||||
@@ -59,6 +60,7 @@ const FEATURE_PREVIEW_KEY_TO_CONTENT: {
|
||||
[LOCAL_STORAGE_KEYS.UI_PREVIEW_MARKETPLACE]: <IntegrationsLayoutPreview />,
|
||||
[LOCAL_STORAGE_KEYS.UI_PREVIEW_DATABASE_CONNECTIONS]: <DatabaseConnectionsPreview />,
|
||||
[LOCAL_STORAGE_KEYS.UI_PREVIEW_EXPLORER]: <ExplorerPreview />,
|
||||
[LOCAL_STORAGE_KEYS.UI_PREVIEW_STORAGE_VERSIONING]: <StorageVersioningPreview />,
|
||||
}
|
||||
|
||||
export const FeaturePreviewModal = () => {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
export const StorageVersioningPreview = () => {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<p className="text-sm text-foreground-light">
|
||||
Keep previous copies of a file when it's overwritten or deleted, and set a lifecycle policy
|
||||
that expires them automatically.
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm">Enabling this preview will:</p>
|
||||
<ul className="list-disc pl-6 text-sm text-foreground-light space-y-1">
|
||||
<li>Add object versioning and lifecycle policy settings to the bucket settings</li>
|
||||
<li>Show a version history for each file in the file preview panel</li>
|
||||
<li>Allow soft-deleting and restoring files</li>
|
||||
<li>Break down retained version storage on the organization usage page</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p className="text-sm text-foreground-light">
|
||||
Versioning is in <em>Private Alpha</em> and is off for every bucket by default until you
|
||||
turn it on.
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -36,6 +36,7 @@ export const useFeaturePreviews = (): FeaturePreview[] => {
|
||||
const isMarketplaceEnabled = useFlag('marketplaceIntegrations')
|
||||
const isDatabaseConnectionsEnabled = useFlag('topForPostgres')
|
||||
const isExplorerEnabled = useFlag('explorer')
|
||||
const isStorageVersioningEnabled = useFlag('storageVersioningPrivateAlpha')
|
||||
|
||||
const isSqlEditorManualSaveForced = useFlag('sqlEditorManualSaveForced')
|
||||
|
||||
@@ -150,6 +151,16 @@ export const useFeaturePreviews = (): FeaturePreview[] => {
|
||||
getRoute: (ref?: string) => `/project/${ref}/observability/connections`,
|
||||
bannerId: 'database-connections-banner',
|
||||
},
|
||||
{
|
||||
key: LOCAL_STORAGE_KEYS.UI_PREVIEW_STORAGE_VERSIONING,
|
||||
name: 'Storage versioning',
|
||||
discussionsUrl: undefined,
|
||||
isNew: true,
|
||||
isPlatformOnly: true,
|
||||
isDefaultOptIn: true,
|
||||
enabled: isStorageVersioningEnabled,
|
||||
getRoute: (ref?: string) => `/project/${ref}/storage/files`,
|
||||
},
|
||||
]
|
||||
|
||||
return previews.sort((a, b) => Number(b.isNew) - Number(a.isNew))
|
||||
@@ -160,5 +171,6 @@ export const useFeaturePreviews = (): FeaturePreview[] => {
|
||||
isMarketplaceEnabled,
|
||||
isDatabaseConnectionsEnabled,
|
||||
isExplorerEnabled,
|
||||
isStorageVersioningEnabled,
|
||||
])
|
||||
}
|
||||
@@ -29,6 +29,7 @@ export const LOCAL_STORAGE_KEYS = {
|
||||
UI_PREVIEW_MARKETPLACE: 'supabase-ui-marketplace',
|
||||
UI_PREVIEW_DATABASE_CONNECTIONS: 'preview-database-connections',
|
||||
UI_PREVIEW_EXPLORER: 'preview-explorer',
|
||||
UI_PREVIEW_STORAGE_VERSIONING: 'supabase-ui-storage-versioning',
|
||||
|
||||
AI_ASSISTANT_MCP_OPT_IN: 'ai-assistant-mcp-opt-in',
|
||||
|
||||
@@ -172,6 +173,7 @@ const LOCAL_STORAGE_KEYS_ALLOWLIST = [
|
||||
LOCAL_STORAGE_KEYS.UI_PREVIEW_SQL_EDITOR_MANUAL_SAVE,
|
||||
LOCAL_STORAGE_KEYS.SQL_EDITOR_MANUAL_SAVE_NOTICE_DISMISSED,
|
||||
LOCAL_STORAGE_KEYS.UI_PREVIEW_MARKETPLACE,
|
||||
LOCAL_STORAGE_KEYS.UI_PREVIEW_STORAGE_VERSIONING,
|
||||
LOCAL_STORAGE_KEYS.LAST_SIGN_IN_METHOD,
|
||||
LOCAL_STORAGE_KEYS.HIDE_PROMO_TOAST,
|
||||
LOCAL_STORAGE_KEYS.BLOG_VIEW,
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<defs>
|
||||
<linearGradient id="omp-mark" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#ed4abf" />
|
||||
<stop offset=".5" stop-color="#9b4dff" />
|
||||
<stop offset="1" stop-color="#5ad8e6" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="64" height="64" rx="12" fill="#0f0a14" />
|
||||
<path fill="url(#omp-mark)" d="M14 16h36v8H40v32h-8V24h-6v22h-8V24h-4z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 471 B |
@@ -13,6 +13,7 @@ import type {
|
||||
McpClientConfig,
|
||||
McpClientDeepLinkOptions,
|
||||
McpFeatureGroup,
|
||||
OmpMcpConfig,
|
||||
OpenCodeMcpConfig,
|
||||
VSCodeMcpConfig,
|
||||
WindsurfMcpConfig,
|
||||
@@ -360,6 +361,23 @@ export const MCP_CLIENT_DATA: McpClientData[] = [
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'omp',
|
||||
label: 'omp',
|
||||
icon: 'omp',
|
||||
configFile: '.omp/mcp.json',
|
||||
externalDocsUrl: 'https://github.com/can1357/oh-my-pi/blob/main/docs/mcp-config.md',
|
||||
transformConfig: (config): OmpMcpConfig => {
|
||||
return {
|
||||
mcpServers: {
|
||||
supabase: {
|
||||
type: 'http',
|
||||
url: config.mcpServers.supabase.url,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'kiro',
|
||||
label: 'Kiro',
|
||||
@@ -449,6 +467,7 @@ export const MCP_CLIENT_GROUPS = [
|
||||
'opencode',
|
||||
'factory',
|
||||
'fx',
|
||||
'omp',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -275,6 +275,32 @@ export const MCP_CLIENT_INSTRUCTIONS: Record<string, McpClientInstructions> = {
|
||||
</>
|
||||
),
|
||||
},
|
||||
omp: {
|
||||
primary: () => (
|
||||
<>
|
||||
<paragraph>
|
||||
Start <inlineCode value="omp" /> and add the Supabase MCP server with the guided setup:
|
||||
</paragraph>
|
||||
<code lang="bash" value="/mcp add" />
|
||||
</>
|
||||
),
|
||||
alternate: () => (
|
||||
<>
|
||||
<paragraph>
|
||||
That path is project-scoped. To use the server in every project, add the same entry to{' '}
|
||||
<inlineCode value="~/.omp/agent/mcp.json" /> instead.
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
If a session is already open, pick up the change with <inlineCode value="/mcp reload" />.
|
||||
omp opens your browser to complete the Supabase OAuth flow the first time it connects.
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
Confirm the server is connected with <inlineCode value="/mcp list" />, or authorize again
|
||||
with a different account using <inlineCode value="/mcp reauth supabase" />.
|
||||
</paragraph>
|
||||
</>
|
||||
),
|
||||
},
|
||||
kiro: {
|
||||
deepLinkDescription: (
|
||||
<paragraph>
|
||||
|
||||
@@ -214,6 +214,19 @@ export interface KimiMcpConfig extends McpClientBaseConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Configuration format for the omp CLI MCP client.
|
||||
* omp keys servers under `mcpServers` and requires an explicit `type: "http"`:
|
||||
* an entry with a `url` but no `type` is validated as stdio and rejected.
|
||||
*/
|
||||
export interface OmpMcpConfig extends McpClientBaseConfig {
|
||||
mcpServers: {
|
||||
supabase: {
|
||||
type: 'http'
|
||||
url: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Union of all possible config types
|
||||
export type McpClientConfig =
|
||||
@@ -230,6 +243,7 @@ export type McpClientConfig =
|
||||
| GrokMcpConfig
|
||||
| KimiMcpConfig
|
||||
| McpClientBaseConfig
|
||||
| OmpMcpConfig
|
||||
| OpenCodeMcpConfig
|
||||
| OtherMcpConfig
|
||||
| VSCodeMcpConfig
|
||||
|
||||
@@ -20,6 +20,7 @@ import grokIcon from '../assets/grok-icon.svg'
|
||||
import kimiDarkIcon from '../assets/kimi-icon-dark.svg'
|
||||
import kimiIcon from '../assets/kimi-icon.svg'
|
||||
import kiroIcon from '../assets/kiro-icon.svg'
|
||||
import ompIcon from '../assets/omp-icon.svg'
|
||||
import openaiDarkIcon from '../assets/openai-icon-dark.svg'
|
||||
import openaiIcon from '../assets/openai-icon.svg'
|
||||
import opencodeDarkIcon from '../assets/opencode-icon-dark.svg'
|
||||
@@ -52,6 +53,7 @@ const MCP_CLIENT_ICON_ASSETS = {
|
||||
grok: { light: grokIcon, dark: grokDarkIcon },
|
||||
kimi: { light: kimiIcon, dark: kimiDarkIcon },
|
||||
kiro: { light: kiroIcon, dark: kiroIcon },
|
||||
omp: { light: ompIcon, dark: ompIcon },
|
||||
openai: { light: openaiIcon, dark: openaiDarkIcon },
|
||||
opencode: { light: opencodeIcon, dark: opencodeDarkIcon },
|
||||
perplexity: { light: perplexityIcon, dark: perplexityDarkIcon },
|
||||
|
||||
Reference in new issue
Block a user