diff --git a/apps/app/public/x-logo.svg b/apps/app/public/x-logo.svg new file mode 100644 index 0000000..437e2bf --- /dev/null +++ b/apps/app/public/x-logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/app/src/app/page.tsx b/apps/app/src/app/page.tsx index eb236e0..5c02c56 100644 --- a/apps/app/src/app/page.tsx +++ b/apps/app/src/app/page.tsx @@ -125,14 +125,6 @@ export default function MCPBrowser() { -
- -
- -
- -
-
@@ -151,6 +143,14 @@ export default function MCPBrowser() { +
+ +
+ +
+ +
+
diff --git a/apps/app/src/components/custom-ui/consumer-info.tsx b/apps/app/src/components/custom-ui/consumer-info.tsx index e0e2808..265dd15 100644 --- a/apps/app/src/components/custom-ui/consumer-info.tsx +++ b/apps/app/src/components/custom-ui/consumer-info.tsx @@ -5,6 +5,7 @@ import { cn } from "@/lib/utils" import HighlighterText from "./highlighter-text" import InfoCard from "./info-card" import { ChartLine, DoorOpen, PiggyBank } from "lucide-react" +import McpExampleCard from "./mcp-example-card" interface ConsumerInfoProps extends React.HTMLAttributes { className?: string @@ -26,14 +27,17 @@ export default function ConsumerInfo({ {/* Header */}
- FOR ANY HUMAN + CONSUME MCP SERVERS
-

- Let your agents transact.{" "} - Fund your account with FIAT and use any paid MCP. +

+ Pay cents per tool call.{" "} + Instead of expensive subscriptions. Consume any paid MCP with a single account.

+ {/* MCP Example Card */} + + {/* Info Cards Grid */}
- FOR BUSINESSES & DEVELOPERS + PROVIDE PAID ENDPOINTS

The AI Gateway for your app.{" "} diff --git a/apps/app/src/components/custom-ui/hero-3d.tsx b/apps/app/src/components/custom-ui/hero-3d.tsx index ceebaaa..0e24384 100644 --- a/apps/app/src/components/custom-ui/hero-3d.tsx +++ b/apps/app/src/components/custom-ui/hero-3d.tsx @@ -123,7 +123,8 @@ export default function Hero3D({ Payments infrastructure for the agent economy

- In one minute, add our open-source proxy to your APIs or MCPs and get discovered and paid by autonomous agents. + Single connection to use paid MCP tools across any client.
+ Pay-per-use instead of expensive subscriptions.

@@ -139,14 +140,14 @@ export default function Hero3D({ animate={isMounted ? "visible" : "hidden"} variants={fadeUp} > - + - + @@ -231,19 +232,20 @@ export default function Hero3D({ {/* Subheading */}

- In one minute, add our open-source proxy to your APIs or MCPs and get discovered and paid by autonomous agents. + Single connection to use paid MCP tools across any client.
+ Pay-per-use instead of expensive subscriptions.

{/* CTAs */}
- + - +
diff --git a/apps/app/src/components/custom-ui/highlighter-text.tsx b/apps/app/src/components/custom-ui/highlighter-text.tsx index 4c763a0..d811a7c 100644 --- a/apps/app/src/components/custom-ui/highlighter-text.tsx +++ b/apps/app/src/components/custom-ui/highlighter-text.tsx @@ -11,6 +11,8 @@ const highlighterTextVariants = cva( default: "bg-muted text-muted-foreground", blue: "text-blue-700 bg-blue-500/10 dark:text-blue-200 dark:bg-blue-800/50", amber: "text-amber-700 bg-amber-500/10 dark:text-amber-200 dark:bg-amber-800/50", + red: "text-red-700 bg-red-500/10 dark:text-red-200 dark:bg-red-800/50", + green: "text-teal-700 bg-teal-500/10 dark:text-teal-200 dark:bg-teal-800/50", }, }, defaultVariants: { @@ -27,6 +29,8 @@ const highlighterIconVariants = cva( default: "bg-muted text-muted-foreground", blue: "text-blue-700 bg-blue-500/10 dark:text-blue-200 dark:bg-blue-800/50", amber: "text-amber-700 bg-amber-500/10 dark:text-amber-200 dark:bg-amber-800/50", + red: "text-red-700 bg-red-500/10 dark:text-red-200 dark:bg-red-800/50", + green: "text-teal-700 bg-teal-500/10 dark:text-teal-200 dark:bg-teal-800/50", }, }, defaultVariants: { diff --git a/apps/app/src/components/custom-ui/info-card.tsx b/apps/app/src/components/custom-ui/info-card.tsx index 28805aa..16a93f3 100644 --- a/apps/app/src/components/custom-ui/info-card.tsx +++ b/apps/app/src/components/custom-ui/info-card.tsx @@ -25,7 +25,7 @@ export default function InfoCard({ return (
{ + className?: string + serverId?: string +} + +export default function McpExampleCard({ + className, + serverId, + ...props +}: McpExampleCardProps) { + const [selectedTool, setSelectedTool] = useState(null) + const [showToolModal, setShowToolModal] = useState(false) + const [data, setData] = useState<{ + serverId: string + origin?: string + tools: Array> + summary?: { totalTools: number; totalRequests: number } + info?: { name?: string; description?: string } + } | null>(null) + const [loading, setLoading] = useState(true) + const [totalRequests, setTotalRequests] = useState(null) + const [loadingRequests, setLoadingRequests] = useState(true) + + useEffect(() => { + if (!serverId) { + setLoading(false) + setLoadingRequests(false) + return + } + + // Fetch server data directly using serverId + const fetchData = async () => { + setLoading(true) + setLoadingRequests(true) + + try { + const serverData = await mcpDataApi.getServerById(serverId) + setData({ + serverId: serverData.serverId, + origin: serverData.origin, + tools: (serverData.tools || []) as Array>, + summary: serverData.summary, + info: serverData.info, + }) + setTotalRequests(serverData.summary?.totalRequests || 0) + setLoadingRequests(false) + } catch (e) { + console.error('Failed to fetch server data:', e) + setData(null) + setTotalRequests(0) + setLoadingRequests(false) + } finally { + setLoading(false) + } + } + + fetchData() + }, [serverId]) + + // Normalize tools data exactly like server-page-client does + const normalizedTools = useMemo(() => { + if (!data?.tools) return [] + return (data.tools || []).map((t, idx) => { + const annotations = (t as { annotations?: Record })?.annotations || {}; + const paymentHint = Boolean(annotations.paymentHint); + const paymentPriceUSD = annotations.paymentPriceUSD as number | undefined; + const paymentNetworks = annotations.paymentNetworks as Array<{ + network: string; + recipient: string; + maxAmountRequired: string; + asset: { address: string; symbol?: string; decimals?: number }; + type: 'evm' | 'svm'; + }> | undefined; + const paymentVersion = annotations.paymentVersion as number | undefined; + + return { + id: (t?.id as string) || (t?.name as string) || `tool-${idx}`, + name: (t?.name as string) || `tool-${idx}`, + description: (t?.description as string) || '', + inputSchema: ((t as { inputSchema?: unknown; parameters?: { jsonSchema?: unknown } })?.inputSchema || (t as { parameters?: { jsonSchema?: unknown } })?.parameters?.jsonSchema || {}) as Record, + pricing: Array.isArray((t as { pricing?: unknown[] })?.pricing) ? (t as { pricing?: unknown[] }).pricing as Array<{ label?: string; amount?: number; currency?: string; active?: boolean }> : [], + isMonetized: Array.isArray((t as { pricing?: Array<{ active?: boolean }> })?.pricing) && ((t as { pricing?: Array<{ active?: boolean }> }).pricing || []).some((p) => p?.active === true), + paymentHint, + paymentPriceUSD, + paymentNetworks, + paymentVersion, + }; + }) + }, [data?.tools]) + + // Get first 5 tools + const displayTools = useMemo(() => { + return normalizedTools.slice(0, 5) + }, [normalizedTools]) + + const openToolModal = (tool: typeof normalizedTools[0]) => { + // Convert normalized tool to format expected by ToolExecutionModal + // Include payment info in the tool object as the modal expects it + const toolForModal = { + id: tool.id, + name: tool.name, + description: tool.description, + inputSchema: tool.inputSchema || {}, + pricing: tool.pricing || [], + isMonetized: tool.isMonetized || false, + paymentHint: tool.paymentHint, + paymentPriceUSD: tool.paymentPriceUSD, + paymentNetworks: tool.paymentNetworks, + } as unknown as ToolFromMcpServerWithStats + + setSelectedTool(toolForModal) + setShowToolModal(true) + } + + return ( + <> +
+
+ SERVER EXAMPLE +
+ + {/* Image + Title Section */} +
+
+ {/* Square black image - bigger with same rounded corners as tools, smaller on mobile */} +
+ X Logo +
+ + {/* Title */} +
+

+ {data?.info?.name || "Loading..."} +

+ + {/* Description - hidden on mobile, shown next to title on desktop */} +

+ Regular subscription{" "} + $200 /month{" "} + via MCPay{" "} + $0.05 /tool +

+
+
+ + {/* Description - shown below image on mobile */} +
+
+ Regular subscription{" "} + $200 /month +
+
+ via MCPay{" "} + $0.05 /tool +
+
+
+ + {/* Tools List - First 5 tools */} +
+ {loading ? ( +
Loading tools...
+ ) : displayTools.length === 0 ? ( +
No tools available
+ ) : ( + displayTools.map((tool) => ( +
+ {/* Left: Name + Description */} +
+

{tool.name}

+ {tool.description && ( +

{tool.description}

+ )} +
+ + {/* Right: Price + RUN Button */} +
+ {tool.paymentHint && tool.paymentPriceUSD && ( + ${tool.paymentPriceUSD} + )} + +
+
+ )) + )} +
+ + {/* Text + Buttons Section */} +
+

+ Consume any paid MCP server with a single account.{" "} + Pay per tool call, no subscriptions required. +

+
+ {data?.serverId && ( + + + + )} + +
+
+
+ + {/* Tool Execution Modal */} + {selectedTool && ( + { + setShowToolModal(false) + setSelectedTool(null) + }} + tool={selectedTool} + serverId={data?.serverId || ""} + url={data?.origin} + /> + )} + + ) +} + diff --git a/apps/app/src/components/custom-ui/minimal-explorer.tsx b/apps/app/src/components/custom-ui/minimal-explorer.tsx index 1cb0c45..78ba1c4 100644 --- a/apps/app/src/components/custom-ui/minimal-explorer.tsx +++ b/apps/app/src/components/custom-ui/minimal-explorer.tsx @@ -187,7 +187,7 @@ export default function MinimalExplorer() { loading?: boolean }) => ( - +
{label} diff --git a/apps/app/src/components/custom-ui/navbar.tsx b/apps/app/src/components/custom-ui/navbar.tsx index 3a6a33c..67c2d18 100644 --- a/apps/app/src/components/custom-ui/navbar.tsx +++ b/apps/app/src/components/custom-ui/navbar.tsx @@ -71,7 +71,7 @@ export default function Navbar() {
- {/* Center (desktop only): BROWSE / EXPLORER / REGISTER */} + {/* Center (desktop only): BROWSE / MONETIZE / EXPLORER */}
@@ -172,18 +172,18 @@ export default function Navbar() { - EXPLORER + MONETIZE - REGISTER + EXPLORER
diff --git a/apps/app/src/components/custom-ui/stats-card.tsx b/apps/app/src/components/custom-ui/stats-card.tsx index d1da619..e350780 100644 --- a/apps/app/src/components/custom-ui/stats-card.tsx +++ b/apps/app/src/components/custom-ui/stats-card.tsx @@ -34,7 +34,7 @@ export default function StatsCard({ return (
{/* Minimal Explorer Card */} -
+
diff --git a/apps/app/src/components/custom-ui/visual-proxy.tsx b/apps/app/src/components/custom-ui/visual-proxy.tsx index 9d95274..7c88d74 100644 --- a/apps/app/src/components/custom-ui/visual-proxy.tsx +++ b/apps/app/src/components/custom-ui/visual-proxy.tsx @@ -112,7 +112,7 @@ export default function VisualProxy({ return (