diff --git a/apps/library/app/api/registry/mcp-headless-app/route.ts b/apps/library/app/api/registry/mcp-headless-app/route.ts new file mode 100644 index 00000000000..dcb78a2f213 --- /dev/null +++ b/apps/library/app/api/registry/mcp-headless-app/route.ts @@ -0,0 +1,33 @@ +import fs from 'fs/promises' +import path from 'path' +import { NextRequest, NextResponse } from 'next/server' +import type { RegistryItem } from 'shadcn/schema' + +async function readRegistryItem(): Promise { + const filePath = path.join(process.cwd(), 'public/r/mcp-headless-app.json') + const content = await fs.readFile(filePath, 'utf-8') + + return JSON.parse(content) as RegistryItem +} + +export async function GET(request: NextRequest) { + try { + const registryItem = await readRegistryItem() + const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? '' + const registryItemUrl = (name: string) => + new URL(`${basePath}/r/${name}.json`, request.nextUrl.origin).toString() + + return NextResponse.json({ + ...registryItem, + registryDependencies: [ + registryItemUrl('mcp-auth-html'), + registryItemUrl('mcp-server'), + registryItemUrl('mcp-tools-postgrest'), + ], + } satisfies RegistryItem) + } catch (error) { + console.error('Failed to load the Headless MCP App registry item:', error) + + return NextResponse.json({ error: 'Failed to load registry item.' }, { status: 500 }) + } +} diff --git a/apps/library/components/block-item.tsx b/apps/library/components/block-item.tsx index 843011720f0..ade4f7b986e 100644 --- a/apps/library/components/block-item.tsx +++ b/apps/library/components/block-item.tsx @@ -7,14 +7,15 @@ const Command = dynamic(() => import('./command').then((mod) => mod.Command), { interface BlockItemProps { name: string + installArgs?: string } -export const BlockItem = ({ name }: BlockItemProps) => { +export const BlockItem = ({ name, installArgs }: BlockItemProps) => { const framework = name.includes('vue') || name.includes('nuxtjs') ? 'vue' : 'react' return (
- +
) } diff --git a/apps/library/components/command.tsx b/apps/library/components/command.tsx index 8ae9e48c7f8..a2db16cf218 100644 --- a/apps/library/components/command.tsx +++ b/apps/library/components/command.tsx @@ -10,6 +10,7 @@ import { useLocalStorage } from './use-local-storage' interface CommandCopyProps { name: string highlight?: boolean + installArgs?: string // For Vue, we need to use the `shadcn-vue` package instead of `shadcn` framework?: 'react' | 'vue' } @@ -46,7 +47,7 @@ const getComponentPath = (name: string) => { } } -export function Command({ name, highlight, framework = 'react' }: CommandCopyProps) { +export function Command({ name, highlight, framework = 'react', installArgs }: CommandCopyProps) { const pathname = usePathname() const [value, setValue] = useLocalStorage(LOCAL_STORAGE_KEY, 'prompt') @@ -56,30 +57,22 @@ export function Command({ name, highlight, framework = 'react' }: CommandCopyPro const commands: Record = framework === 'vue' ? { - npm: `npx shadcn-vue@latest add ${baseUrl}${componentPath}`, - pnpm: `pnpm dlx shadcn-vue@latest add ${baseUrl}${componentPath}`, - yarn: `yarn dlx shadcn-vue@latest add ${baseUrl}${componentPath}`, - bun: `bunx --bun shadcn-vue@latest add ${baseUrl}${componentPath}`, + npm: `npx shadcn-vue@latest add ${baseUrl}${componentPath}${installArgs ? ` ${installArgs}` : ''}`, + pnpm: `pnpm dlx shadcn-vue@latest add ${baseUrl}${componentPath}${installArgs ? ` ${installArgs}` : ''}`, + yarn: `yarn dlx shadcn-vue@latest add ${baseUrl}${componentPath}${installArgs ? ` ${installArgs}` : ''}`, + bun: `bunx --bun shadcn-vue@latest add ${baseUrl}${componentPath}${installArgs ? ` ${installArgs}` : ''}`, } : { - npm: `npx shadcn@latest add ${baseUrl}${componentPath}`, - pnpm: `pnpm dlx shadcn@latest add ${baseUrl}${componentPath}`, - yarn: `yarn dlx shadcn@latest add ${baseUrl}${componentPath}`, - bun: `bunx --bun shadcn@latest add ${baseUrl}${componentPath}`, + npm: `npx shadcn@latest add ${baseUrl}${componentPath}${installArgs ? ` ${installArgs}` : ''}`, + pnpm: `pnpm dlx shadcn@latest add ${baseUrl}${componentPath}${installArgs ? ` ${installArgs}` : ''}`, + yarn: `yarn dlx shadcn@latest add ${baseUrl}${componentPath}${installArgs ? ` ${installArgs}` : ''}`, + bun: `bunx --bun shadcn@latest add ${baseUrl}${componentPath}${installArgs ? ` ${installArgs}` : ''}`, } const basePath = process.env.NEXT_PUBLIC_BASE_PATH ?? '' const currentPath = pathname?.startsWith(basePath) ? pathname : `${basePath}${pathname ?? ''}` const pageUrl = `${getPageBaseUrl()}${currentPath}` - const prompt = [ - `Read the installation instructions at ${pageUrl} before making changes.`, - '', - `Then install the ${name} block in the current project with:`, - '', - commands.npm, - '', - 'Follow the remaining setup and configuration steps on that page.', - ].join('\n') + const prompt = `Read the installation instructions at ${pageUrl} before making changes. Then install the ${name} block in the current project with: ${commands.npm}. Follow the remaining setup and configuration steps on that page.` const tabs: InstallationTab[] = ['prompt', ...Object.keys(commands)] as InstallationTab[] return ( diff --git a/apps/library/components/side-navigation.tsx b/apps/library/components/side-navigation.tsx index 16e27c2e1ff..c5c6c964082 100644 --- a/apps/library/components/side-navigation.tsx +++ b/apps/library/components/side-navigation.tsx @@ -76,7 +76,7 @@ function SideNavigation() {
- Blocks + UI Blocks
{/* Render items based on component definitions */} diff --git a/apps/library/config/docs.ts b/apps/library/config/docs.ts index 7d3bb36042f..e6fcf9c54c7 100644 --- a/apps/library/config/docs.ts +++ b/apps/library/config/docs.ts @@ -39,15 +39,8 @@ export const platformBlocks: SidebarNavGroup = { // Blocks for apps with no front-end of their own. These ship plain HTML rather // than components, so they take no framework and are not framework-switchable. export const headlessBlocks: SidebarNavGroup = { - title: 'Headless', + title: 'MCP', items: [ - { - title: 'MCP Auth', - href: '/docs/headless/mcp-auth', - items: [], - new: true, - commandItemLabel: 'MCP Auth', - }, { title: 'MCP Server', href: '/docs/headless/mcp-server', @@ -62,6 +55,20 @@ export const headlessBlocks: SidebarNavGroup = { new: true, commandItemLabel: 'MCP Tools: PostgREST', }, + { + title: 'MCP Auth', + href: '/docs/headless/mcp-auth', + items: [], + new: true, + commandItemLabel: 'MCP Auth', + }, + { + title: 'Headless MCP App', + href: '/docs/headless/mcp-headless-app', + items: [], + new: true, + commandItemLabel: 'Headless MCP App', + }, ], } diff --git a/apps/library/content/docs/headless/mcp-headless-app.mdx b/apps/library/content/docs/headless/mcp-headless-app.mdx new file mode 100644 index 00000000000..4c48c838352 --- /dev/null +++ b/apps/library/content/docs/headless/mcp-headless-app.mdx @@ -0,0 +1,122 @@ +--- +title: Headless MCP App +description: A complete MCP app with OAuth screens, an Edge Function, and database tools +--- + +Everything needed for a production MCP app in one install: static browser +screens for OAuth, an MCP server Edge Function, and PostgREST tools generated +from your database schema. This block owns the toolset manifest that enables the +installed PostgREST toolset and a starter `supabase/config.toml`. + +## Installation + + + +The app composes [MCP Auth](./mcp-auth), [MCP Server](./mcp-server), and +[MCP Tools: PostgREST](./mcp-tools-postgrest) as registry dependencies. It also +installs `supabase/functions/mcp-server/tools/index.ts`, with the PostgREST +toolset registered already, so no source edits are needed after installation. +The server dependency creates the same file first; the displayed `--overwrite` +flag deliberately replaces it with this complete manifest. It only overwrites +that generated toolset manifest and the starter `supabase/config.toml`. + + + +This is a starter block for a new project. The install command overwrites both +`supabase/functions/mcp-server/tools/index.ts` and `supabase/config.toml`. For +an existing project, install the individual MCP blocks and merge their +configuration deliberately instead. + + + +## Folder structure + + + +## Configure and deploy + +The installed `supabase/config.toml` already enables the OAuth server, +access-token hook, and `mcp-server` function. Update `project_id`, `site_url`, +and `additional_redirect_urls` with the static app's host, then set the static +site's `SUPABASE_URL` and `SUPABASE_PUBLISHABLE_KEY` in `config.js` as described +in [MCP Auth](./mcp-auth). + +Once the static files are hosted and `site_url` points to that host, deploy the +database hook and Edge Function: + +```bash +supabase db push +supabase config push +supabase functions deploy mcp-server +``` + +The server registers `echo`, `whoami`, and the PostgREST toolset. The latter +builds database tools from the caller's schema and permissions; see [MCP Tools: +PostgREST](./mcp-tools-postgrest) for its guardrails and RLS guidance. + +## Local quickstart + +Use three terminals to run the complete app locally. The starter +`supabase/config.toml` already targets `http://localhost:3000`; update it first +if you use another static-server origin. + +Start Supabase, then copy the **API URL** and **publishable key** printed by +`supabase status` into `config.js`: + +```js +export const SUPABASE_URL = 'API_URL_FROM_SUPABASE_STATUS' +export const SUPABASE_PUBLISHABLE_KEY = 'PUBLISHABLE_KEY_FROM_SUPABASE_STATUS' +``` + +```bash +# Terminal 1 +supabase start +supabase status + +# Terminal 2 +npx serve . --listen 3000 + +# Terminal 3 +cp supabase/functions/mcp-server/.env.example supabase/functions/.env +# Set MCP_PUBLIC_SUPABASE_URL to the API URL from `supabase status`. +supabase functions serve mcp-server --env-file supabase/functions/.env +``` + +Open `http://localhost:3000`. The static app uses the values in `config.js` to +connect to the local project and shows the MCP endpoint served by the function. + +## Expose database tools safely + +The PostgREST toolset only discovers tables and functions that the calling user +can access. For new tables, enable RLS and grant the `authenticated` role the +operations your tools need. Some projects require explicit grants before a new +table is reachable through the Data API. + +```sql +create table public.todos ( + id bigint generated always as identity primary key, + user_id uuid not null references auth.users, + title text not null, + done boolean not null default false +); + +alter table public.todos enable row level security; + +grant select, insert, update, delete on table public.todos to authenticated; + +create policy "Users can manage their own todos" +on public.todos +for all +to authenticated +using ((select auth.uid()) = user_id) +with check ((select auth.uid()) = user_id); +``` + +The policy limits every operation to the caller's rows. Do not grant a role +access without an RLS policy that matches the intended ownership model. Views +over protected tables should use `security_invoker = true`; see [MCP Tools: +PostgREST](./mcp-tools-postgrest) for the full security model. diff --git a/apps/library/next.config.mjs b/apps/library/next.config.mjs index 5df88946663..b493f568fa1 100644 --- a/apps/library/next.config.mjs +++ b/apps/library/next.config.mjs @@ -36,6 +36,11 @@ const nextConfig = { destination: '/api/registry/mcp-tools-postgrest', permanent: false, }, + { + source: '/r/mcp-headless-app.json', + destination: '/api/registry/mcp-headless-app', + permanent: false, + }, ] }, } diff --git a/apps/library/public/r/mcp-headless-app.json b/apps/library/public/r/mcp-headless-app.json new file mode 100644 index 00000000000..0f714200e06 --- /dev/null +++ b/apps/library/public/r/mcp-headless-app.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "mcp-headless-app", + "type": "registry:item", + "title": "Headless MCP App", + "description": "A complete headless MCP app: static OAuth screens, an MCP Edge Function, and PostgREST database tools.", + "registryDependencies": [ + "https://supabase.com/library/r/mcp-auth-html.json", + "https://supabase.com/library/r/mcp-server.json", + "https://supabase.com/library/r/mcp-tools-postgrest.json" + ], + "files": [ + { + "path": "registry/default/blocks/mcp-headless-app/supabase/config.toml", + "content": "# Headless MCP App configuration.\n#\n# This is a complete starter config for a new local Supabase project. Update\n# project_id and the two browser origins before deploying the static app.\n\n# Use a distinct value when multiple local Supabase projects run on this machine.\nproject_id = \"headless-mcp-app\"\n\n[api]\nenabled = true\n# `public` is where PostgREST discovers tables and functions for the MCP tools.\nschemas = [\"public\", \"graphql_public\"]\nextra_search_path = [\"public\", \"extensions\"]\n# New public entities are not auto-exposed. Grant the authenticated role the\n# required operations and enable RLS for every table used by MCP tools.\n# auto_expose_new_tables = true\n\n[auth]\nenabled = true\n# Replace both URLs with the origin where you host this block's static files.\nsite_url = \"http://localhost:3000\"\nadditional_redirect_urls = [\"http://localhost:3000/auth/\"]\n\n[auth.oauth_server]\nenabled = true\nauthorization_url_path = \"/oauth/consent/\"\nallow_dynamic_registration = true\n\n[auth.hook.custom_access_token]\nenabled = true\nuri = \"pg-functions://postgres/private/mcp_custom_access_token_hook\"\n\n[functions.mcp-server]\n# The function verifies OAuth and Supabase bearer tokens itself.\nverify_jwt = false\n", + "type": "registry:file", + "target": "supabase/config.toml" + }, + { + "path": "registry/default/blocks/mcp-headless-app/supabase/functions/mcp-server/tools/index.ts", + "content": "import { echoToolset } from './echo.ts'\nimport { postgrestToolset } from './postgrest/index.ts'\nimport { registerToolset } from './registry.ts'\nimport { whoamiToolset } from './whoami.ts'\n\nexport type { ToolContext } from './types.ts'\n\n// The complete app includes the server's built-in tools and the PostgREST\n// toolset installed by its registry dependency.\nexport function registerToolsets(): void {\n registerToolset(echoToolset)\n registerToolset(whoamiToolset)\n registerToolset(postgrestToolset)\n}\n", + "type": "registry:file", + "target": "supabase/functions/mcp-server/tools/index.ts" + } + ], + "docs": "Required setup: this starter block installs `supabase/config.toml` with OAuth, access-token-hook, and Edge Function settings. Fill in its `project_id`, `site_url`, and `additional_redirect_urls` for your static app host, then set `SUPABASE_URL` and `SUPABASE_PUBLISHABLE_KEY` in `config.js`. The `--yes --overwrite` install command intentionally replaces both this starter config and `supabase/functions/mcp-server/tools/index.ts`; merge those files manually if your project already has either one. Deploy with `supabase db push`, `supabase config push`, and `supabase functions deploy mcp-server`. The complete manifest already registers the PostgREST toolset; no manual source edit is needed. See the block documentation for the local quickstart and RLS/grant requirements." +} \ No newline at end of file diff --git a/apps/library/public/r/mcp-tools-postgrest.json b/apps/library/public/r/mcp-tools-postgrest.json index 312aa9fe9c8..d8effcaaecc 100644 --- a/apps/library/public/r/mcp-tools-postgrest.json +++ b/apps/library/public/r/mcp-tools-postgrest.json @@ -27,5 +27,5 @@ "target": "supabase/functions/mcp-server/tools/postgrest/tools.ts" } ], - "docs": "Required setup: register the installed PostgREST toolset in `supabase/functions/mcp-server/tools/index.ts`. Import `postgrestToolset` from `./postgrest/index.ts`, then call `registerToolset(postgrestToolset)` inside `registerToolsets()`. See the block documentation for the complete edit." + "docs": "Standalone-install note: register the installed PostgREST toolset in `supabase/functions/mcp-server/tools/index.ts`. Import `postgrestToolset` from `./postgrest/index.ts`, then call `registerToolset(postgrestToolset)` inside `registerToolsets()`. If you installed `mcp-headless-app`, its manifest already performs this registration; do not edit it. See the block documentation for the complete setup." } \ No newline at end of file diff --git a/apps/library/public/r/registry.json b/apps/library/public/r/registry.json index 2f37edfc75a..23df22a59d7 100644 --- a/apps/library/public/r/registry.json +++ b/apps/library/public/r/registry.json @@ -1776,6 +1776,30 @@ } ] }, + { + "name": "mcp-headless-app", + "type": "registry:item", + "title": "Headless MCP App", + "description": "A complete headless MCP app: static OAuth screens, an MCP Edge Function, and PostgREST database tools.", + "registryDependencies": [ + "https://supabase.com/library/r/mcp-auth-html.json", + "https://supabase.com/library/r/mcp-server.json", + "https://supabase.com/library/r/mcp-tools-postgrest.json" + ], + "docs": "Required setup: this starter block installs `supabase/config.toml` with OAuth, access-token-hook, and Edge Function settings. Fill in its `project_id`, `site_url`, and `additional_redirect_urls` for your static app host, then set `SUPABASE_URL` and `SUPABASE_PUBLISHABLE_KEY` in `config.js`. The `--yes --overwrite` install command intentionally replaces both this starter config and `supabase/functions/mcp-server/tools/index.ts`; merge those files manually if your project already has either one. Deploy with `supabase db push`, `supabase config push`, and `supabase functions deploy mcp-server`. The complete manifest already registers the PostgREST toolset; no manual source edit is needed. See the block documentation for the local quickstart and RLS/grant requirements.", + "files": [ + { + "path": "registry/default/blocks/mcp-headless-app/supabase/config.toml", + "type": "registry:file", + "target": "supabase/config.toml" + }, + { + "path": "registry/default/blocks/mcp-headless-app/supabase/functions/mcp-server/tools/index.ts", + "type": "registry:file", + "target": "supabase/functions/mcp-server/tools/index.ts" + } + ] + }, { "name": "mcp-server", "type": "registry:item", @@ -1857,7 +1881,7 @@ "registryDependencies": [ "https://supabase.com/library/r/mcp-server.json" ], - "docs": "Required setup: register the installed PostgREST toolset in `supabase/functions/mcp-server/tools/index.ts`. Import `postgrestToolset` from `./postgrest/index.ts`, then call `registerToolset(postgrestToolset)` inside `registerToolsets()`. See the block documentation for the complete edit.", + "docs": "Standalone-install note: register the installed PostgREST toolset in `supabase/functions/mcp-server/tools/index.ts`. Import `postgrestToolset` from `./postgrest/index.ts`, then call `registerToolset(postgrestToolset)` inside `registerToolsets()`. If you installed `mcp-headless-app`, its manifest already performs this registration; do not edit it. See the block documentation for the complete setup.", "files": [ { "path": "registry/default/blocks/mcp-tools-postgrest/supabase/functions/mcp-server/tools/postgrest/index.ts", diff --git a/apps/library/registry/blocks.ts b/apps/library/registry/blocks.ts index d4833a79ccc..1bdd63cb6fd 100644 --- a/apps/library/registry/blocks.ts +++ b/apps/library/registry/blocks.ts @@ -5,6 +5,7 @@ import currentUserAvatar from './default/blocks/current-user-avatar/registry-ite import dropzone from './default/blocks/dropzone/registry-item.json' with { type: 'json' } import infiniteQueryHook from './default/blocks/infinite-query-hook/registry-item.json' with { type: 'json' } import mcpAuthHtml from './default/blocks/mcp-auth-html/registry-item.json' with { type: 'json' } +import mcpHeadlessApp from './default/blocks/mcp-headless-app/registry-item.json' with { type: 'json' } import mcpServer from './default/blocks/mcp-server/registry-item.json' with { type: 'json' } import mcpToolsPostgrest from './default/blocks/mcp-tools-postgrest/registry-item.json' with { type: 'json' } import passwordBasedAuthNextjs from './default/blocks/password-based-auth-nextjs/registry-item.json' with { type: 'json' } @@ -61,12 +62,13 @@ export const blocks = [ // infinite query hook is intentionally not combined with the clients since it depends on clients having database types. infiniteQueryHook as RegistryItem, - // The headless MCP blocks take no client: mcp-auth-html is plain HTML, and the - // other two are Deno Edge Function code. Every file carries an explicit target, - // which is what lets `shadcn add` install them into a directory with no - // components.json. mcp-tools-postgrest declares mcp-server as a registry - // dependency, so installing it lands the framework first. + // The headless MCP blocks take no client: mcp-auth-html is plain HTML and the + // server and tool blocks are Deno Edge Function code. Every file carries an + // explicit target, which is what lets `shadcn add` install them into a + // directory with no components.json. mcp-tools-postgrest declares mcp-server + // as a registry dependency; mcp-headless-app composes all three. mcpAuthHtml as RegistryItem, + mcpHeadlessApp as RegistryItem, mcpServer as RegistryItem, mcpToolsPostgrest as RegistryItem, diff --git a/apps/library/registry/default/blocks/mcp-headless-app/registry-item.json b/apps/library/registry/default/blocks/mcp-headless-app/registry-item.json new file mode 100644 index 00000000000..31f57dbcc5e --- /dev/null +++ b/apps/library/registry/default/blocks/mcp-headless-app/registry-item.json @@ -0,0 +1,24 @@ +{ + "name": "mcp-headless-app", + "type": "registry:item", + "title": "Headless MCP App", + "description": "A complete headless MCP app: static OAuth screens, an MCP Edge Function, and PostgREST database tools.", + "registryDependencies": [ + "https://supabase.com/library/r/mcp-auth-html.json", + "https://supabase.com/library/r/mcp-server.json", + "https://supabase.com/library/r/mcp-tools-postgrest.json" + ], + "docs": "Required setup: this starter block installs `supabase/config.toml` with OAuth, access-token-hook, and Edge Function settings. Fill in its `project_id`, `site_url`, and `additional_redirect_urls` for your static app host, then set `SUPABASE_URL` and `SUPABASE_PUBLISHABLE_KEY` in `config.js`. The `--yes --overwrite` install command intentionally replaces both this starter config and `supabase/functions/mcp-server/tools/index.ts`; merge those files manually if your project already has either one. Deploy with `supabase db push`, `supabase config push`, and `supabase functions deploy mcp-server`. The complete manifest already registers the PostgREST toolset; no manual source edit is needed. See the block documentation for the local quickstart and RLS/grant requirements.", + "files": [ + { + "path": "registry/default/blocks/mcp-headless-app/supabase/config.toml", + "type": "registry:file", + "target": "supabase/config.toml" + }, + { + "path": "registry/default/blocks/mcp-headless-app/supabase/functions/mcp-server/tools/index.ts", + "type": "registry:file", + "target": "supabase/functions/mcp-server/tools/index.ts" + } + ] +} diff --git a/apps/library/registry/default/blocks/mcp-headless-app/supabase/config.toml b/apps/library/registry/default/blocks/mcp-headless-app/supabase/config.toml new file mode 100644 index 00000000000..55e4e1aa6f3 --- /dev/null +++ b/apps/library/registry/default/blocks/mcp-headless-app/supabase/config.toml @@ -0,0 +1,35 @@ +# Headless MCP App configuration. +# +# This is a complete starter config for a new local Supabase project. Update +# project_id and the two browser origins before deploying the static app. + +# Use a distinct value when multiple local Supabase projects run on this machine. +project_id = "headless-mcp-app" + +[api] +enabled = true +# `public` is where PostgREST discovers tables and functions for the MCP tools. +schemas = ["public", "graphql_public"] +extra_search_path = ["public", "extensions"] +# New public entities are not auto-exposed. Grant the authenticated role the +# required operations and enable RLS for every table used by MCP tools. +# auto_expose_new_tables = true + +[auth] +enabled = true +# Replace both URLs with the origin where you host this block's static files. +site_url = "http://localhost:3000" +additional_redirect_urls = ["http://localhost:3000/auth/"] + +[auth.oauth_server] +enabled = true +authorization_url_path = "/oauth/consent/" +allow_dynamic_registration = true + +[auth.hook.custom_access_token] +enabled = true +uri = "pg-functions://postgres/private/mcp_custom_access_token_hook" + +[functions.mcp-server] +# The function verifies OAuth and Supabase bearer tokens itself. +verify_jwt = false diff --git a/apps/library/registry/default/blocks/mcp-headless-app/supabase/functions/mcp-server/tools/index.ts b/apps/library/registry/default/blocks/mcp-headless-app/supabase/functions/mcp-server/tools/index.ts new file mode 100644 index 00000000000..7d9cdbaea21 --- /dev/null +++ b/apps/library/registry/default/blocks/mcp-headless-app/supabase/functions/mcp-server/tools/index.ts @@ -0,0 +1,14 @@ +import { echoToolset } from './echo.ts' +import { postgrestToolset } from './postgrest/index.ts' +import { registerToolset } from './registry.ts' +import { whoamiToolset } from './whoami.ts' + +export type { ToolContext } from './types.ts' + +// The complete app includes the server's built-in tools and the PostgREST +// toolset installed by its registry dependency. +export function registerToolsets(): void { + registerToolset(echoToolset) + registerToolset(whoamiToolset) + registerToolset(postgrestToolset) +} diff --git a/apps/library/registry/default/blocks/mcp-tools-postgrest/registry-item.json b/apps/library/registry/default/blocks/mcp-tools-postgrest/registry-item.json index a1dc6ec5180..a4f89930f11 100644 --- a/apps/library/registry/default/blocks/mcp-tools-postgrest/registry-item.json +++ b/apps/library/registry/default/blocks/mcp-tools-postgrest/registry-item.json @@ -4,7 +4,7 @@ "title": "MCP Tools: PostgREST", "description": "A toolset for the MCP server that generates database tools from your PostgREST schema: read and write tools per table, view, and function.", "registryDependencies": ["https://supabase.com/library/r/mcp-server.json"], - "docs": "Required setup: register the installed PostgREST toolset in `supabase/functions/mcp-server/tools/index.ts`. Import `postgrestToolset` from `./postgrest/index.ts`, then call `registerToolset(postgrestToolset)` inside `registerToolsets()`. See the block documentation for the complete edit.", + "docs": "Standalone-install note: register the installed PostgREST toolset in `supabase/functions/mcp-server/tools/index.ts`. Import `postgrestToolset` from `./postgrest/index.ts`, then call `registerToolset(postgrestToolset)` inside `registerToolsets()`. If you installed `mcp-headless-app`, its manifest already performs this registration; do not edit it. See the block documentation for the complete setup.", "files": [ { "path": "registry/default/blocks/mcp-tools-postgrest/supabase/functions/mcp-server/tools/postgrest/index.ts",