diff --git a/apps/web/public/assets/mcp-clients/anthropic-icon-light.svg b/apps/web/public/assets/mcp-clients/anthropic-icon-light.svg
new file mode 100644
index 00000000..a02957f9
--- /dev/null
+++ b/apps/web/public/assets/mcp-clients/anthropic-icon-light.svg
@@ -0,0 +1,3 @@
+
diff --git a/apps/web/public/assets/mcp-clients/cline-icon-dark.png b/apps/web/public/assets/mcp-clients/cline-icon-dark.png
new file mode 100644
index 00000000..36c37766
Binary files /dev/null and b/apps/web/public/assets/mcp-clients/cline-icon-dark.png differ
diff --git a/apps/web/public/assets/mcp-clients/cline-icon-light.png b/apps/web/public/assets/mcp-clients/cline-icon-light.png
new file mode 100644
index 00000000..2f028e0a
Binary files /dev/null and b/apps/web/public/assets/mcp-clients/cline-icon-light.png differ
diff --git a/apps/web/public/assets/mcp-clients/cursor-icon-dark.webp b/apps/web/public/assets/mcp-clients/cursor-icon-dark.webp
new file mode 100644
index 00000000..489e77b7
Binary files /dev/null and b/apps/web/public/assets/mcp-clients/cursor-icon-dark.webp differ
diff --git a/apps/web/public/assets/mcp-clients/cursor-icon-light.svg b/apps/web/public/assets/mcp-clients/cursor-icon-light.svg
new file mode 100644
index 00000000..abadee50
--- /dev/null
+++ b/apps/web/public/assets/mcp-clients/cursor-icon-light.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/web/public/assets/mcp-clients/raycast-icon-dark.svg b/apps/web/public/assets/mcp-clients/raycast-icon-dark.svg
new file mode 100644
index 00000000..af54eee3
--- /dev/null
+++ b/apps/web/public/assets/mcp-clients/raycast-icon-dark.svg
@@ -0,0 +1,3 @@
+
diff --git a/apps/web/public/assets/mcp-clients/raycast-icon-light.svg b/apps/web/public/assets/mcp-clients/raycast-icon-light.svg
new file mode 100644
index 00000000..e46a0827
--- /dev/null
+++ b/apps/web/public/assets/mcp-clients/raycast-icon-light.svg
@@ -0,0 +1,3 @@
+
diff --git a/apps/web/public/assets/mcp-clients/raycast-screenshot.jpg b/apps/web/public/assets/mcp-clients/raycast-screenshot.jpg
new file mode 100644
index 00000000..e55072d0
Binary files /dev/null and b/apps/web/public/assets/mcp-clients/raycast-screenshot.jpg differ
diff --git a/apps/web/public/assets/mcp-clients/trae-icon-light.svg b/apps/web/public/assets/mcp-clients/trae-icon-light.svg
new file mode 100644
index 00000000..74867ee7
--- /dev/null
+++ b/apps/web/public/assets/mcp-clients/trae-icon-light.svg
@@ -0,0 +1 @@
+
diff --git a/apps/web/public/assets/mcp-clients/vscode-icon-light.svg b/apps/web/public/assets/mcp-clients/vscode-icon-light.svg
new file mode 100644
index 00000000..c453e633
--- /dev/null
+++ b/apps/web/public/assets/mcp-clients/vscode-icon-light.svg
@@ -0,0 +1,41 @@
+
diff --git a/apps/web/public/assets/mcp-clients/warp-icon-light.png b/apps/web/public/assets/mcp-clients/warp-icon-light.png
new file mode 100644
index 00000000..bb26f7d5
Binary files /dev/null and b/apps/web/public/assets/mcp-clients/warp-icon-light.png differ
diff --git a/apps/web/public/assets/mcp-clients/windsurf-icon-dark.svg b/apps/web/public/assets/mcp-clients/windsurf-icon-dark.svg
new file mode 100644
index 00000000..b1f22035
--- /dev/null
+++ b/apps/web/public/assets/mcp-clients/windsurf-icon-dark.svg
@@ -0,0 +1,10 @@
+
diff --git a/apps/web/public/assets/mcp-clients/windsurf-icon-light.svg b/apps/web/public/assets/mcp-clients/windsurf-icon-light.svg
new file mode 100644
index 00000000..21763298
--- /dev/null
+++ b/apps/web/public/assets/mcp-clients/windsurf-icon-light.svg
@@ -0,0 +1,10 @@
+
diff --git a/apps/web/src/components/example-usage.tsx b/apps/web/src/components/example-usage.tsx
index 1abc176b..c518bc1f 100644
--- a/apps/web/src/components/example-usage.tsx
+++ b/apps/web/src/components/example-usage.tsx
@@ -1,6 +1,7 @@
'use client'
import type { Project } from '@agentic/platform-types'
+import Link from 'next/link'
import { type JSX, useEffect, useMemo, useState } from 'react'
import { useLocalStorage } from 'react-use'
@@ -8,6 +9,7 @@ import { useAgentic } from '@/components/agentic-provider'
import { CodeBlock } from '@/components/code-block'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import {
+ type CodeSnippet,
defaultConfig,
type DeveloperConfig,
getCodeForDeveloperConfig,
@@ -30,6 +32,7 @@ import {
import { useQuery } from '@/lib/query-client'
import { LoadingIndicator } from './loading-indicator'
+import { Button } from './ui/button'
export function ExampleUsage({
projectIdentifier,
@@ -218,12 +221,11 @@ function ExampleUsageContent({
-
))}
@@ -255,11 +257,14 @@ function ExampleUsageContent({
{tsFrameworkTargets.map((framework) => (
-
-
+
))}
@@ -291,11 +296,14 @@ function ExampleUsageContent({
{pyFrameworkTargets.map((framework) => (
-
-
+
))}
@@ -327,11 +335,14 @@ function ExampleUsageContent({
{httpTargets.map((httpTarget) => (
-
-
+
))}
@@ -340,3 +351,60 @@ function ExampleUsageContent({
)
}
+
+function CodeSnippetBlock({
+ codeSnippet,
+ initialCodeBlock
+}: {
+ codeSnippet: CodeSnippet
+ initialCodeBlock?: JSX.Element
+}) {
+ return (
+ <>
+
+
+ {codeSnippet.action && (
+
+ )}
+ >
+ )
+}
diff --git a/apps/web/src/lib/developer-config.ts b/apps/web/src/lib/developer-config.ts
index 1f93132a..c816de08 100644
--- a/apps/web/src/lib/developer-config.ts
+++ b/apps/web/src/lib/developer-config.ts
@@ -1,7 +1,7 @@
import type { Deployment, Project } from '@agentic/platform-types'
import type { BundledLanguage } from 'shiki/bundle/web'
import type { Simplify } from 'type-fest'
-import { assert } from '@agentic/platform-core'
+import { assert, pruneUndefined } from '@agentic/platform-core'
import { gatewayBaseUrl } from './config'
@@ -27,13 +27,17 @@ export type HTTPTarget = (typeof httpTargets)[number]
export const mcpClientTargetLabels = {
url: 'MCP Server URL',
- 'claude-desktop': 'Claude Desktop',
- chatgpt: 'ChatGPT',
- raycast: 'Raycast',
+ 'mcp-json': 'mcp.json',
cursor: 'Cursor',
+ 'claude-code': 'Claude Code',
+ 'claude-desktop': 'Claude Desktop',
+ // chatgpt: 'ChatGPT', // TODO
+ raycast: 'Raycast',
+ trae: 'Trae',
windsurf: 'Windsurf',
+ vscode: 'VSCode',
cline: 'Cline',
- goose: 'Goose'
+ warp: 'Warp'
} as const
export const mcpClientTargets = Object.keys(
mcpClientTargetLabels
@@ -88,7 +92,13 @@ export const defaultConfig: DeveloperConfig = {
export type CodeSnippet = {
code: string
lang: BundledLanguage
- // install?: string // TODO
+ action?: {
+ href: string
+ label: string
+ logoImageUrl?: string
+ logoImageUrlDark?: string
+ logoImageUrlLight?: string
+ }
}
export type GetCodeForDeveloperConfigOpts = {
@@ -157,12 +167,123 @@ export function getCodeForDeveloperConfig(
}
export function getCodeForMCPClientConfig({
- identifier
+ config,
+ identifier,
+ project,
+ apiKey
}: GetCodeForDeveloperConfigInnerOpts): CodeSnippet {
- const mcpUrl = `${gatewayBaseUrl}/${identifier}/mcp`
- return {
- code: mcpUrl,
- lang: 'bash'
+ const mcpUrl = `${gatewayBaseUrl}/${identifier}/mcp${
+ apiKey ? `?apiKey=${apiKey}` : ''
+ }`
+
+ const mcpConfig = {
+ mcpServers: {
+ [identifier]: {
+ url: mcpUrl
+ }
+ }
+ }
+ const mcpConfigCode = JSON.stringify(mcpConfig, null, 2)
+
+ const mcpRemoteConfig = {
+ mcpServers: {
+ [identifier]: {
+ command: 'npx',
+ args: ['mcp-remote', '-y', mcpUrl]
+ }
+ }
+ }
+ const mcpRemoteConfigCode = JSON.stringify(mcpRemoteConfig, null, 2)
+
+ switch (config.mcpClientTarget) {
+ case 'url':
+ return {
+ code: mcpUrl,
+ lang: 'bash'
+ }
+
+ case 'mcp-json':
+ return {
+ code: mcpConfigCode,
+ lang: 'json'
+ }
+
+ case 'claude-code':
+ return {
+ code: `claude mcp add --transport http "${identifier}" "${mcpUrl}"`,
+ lang: 'bash'
+ }
+
+ case 'cursor': {
+ const config = Buffer.from(JSON.stringify(mcpConfig)).toString('base64')
+ const href = `cursor://anysphere.cursor-deeplink/mcp/install?name=${identifier}&config=${config}`
+
+ return {
+ code: mcpConfigCode,
+ lang: 'json',
+ action: {
+ href,
+ label: `Add the ${identifier} MCP server to Cursor`,
+ logoImageUrlLight: '/assets/mcp-clients/cursor-icon-light.svg',
+ logoImageUrlDark: '/assets/mcp-clients/cursor-icon-dark.webp'
+ }
+ }
+ }
+
+ case 'windsurf':
+ return {
+ code: mcpRemoteConfigCode,
+ lang: 'json'
+ }
+
+ case 'claude-desktop':
+ return {
+ code: mcpRemoteConfigCode,
+ lang: 'json'
+ }
+
+ case 'raycast': {
+ // https://manual.raycast.com/model-context-protocol
+ const customMcpConfig = pruneUndefined({
+ name: identifier,
+ type: 'http',
+ url: mcpUrl,
+ description: project.lastPublishedDeployment?.description
+ })
+ const customMcpConfigCode = JSON.stringify(customMcpConfig)
+ const href = `raycast://mcp/install?${encodeURIComponent(customMcpConfigCode)}`
+
+ return {
+ code: mcpConfigCode,
+ lang: 'json',
+ action: {
+ href,
+ label: `Add the ${identifier} MCP server to Raycast`,
+ logoImageUrlLight: '/assets/mcp-clients/raycast-icon-light.svg',
+ logoImageUrlDark: '/assets/mcp-clients/raycast-icon-dark.svg'
+ }
+ }
+ }
+
+ case 'vscode':
+ return {
+ code: `
+"mcp": {
+ "servers": {
+ "${identifier}": {
+ "type": "http",
+ "url": "${mcpUrl}"
+ }
+ }
+}`.trim(),
+ lang: 'json'
+ }
+
+ default:
+ return {
+ code: mcpConfigCode,
+ lang: 'json'
+ }
}
}