- 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}
>
-
+
- MONETIZE SERVERS
+ BROWSE SERVERS
-
+
- DOCUMENTATION
+ MONETIZE SERVERS
@@ -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 */}
-
+
- MONETIZE SERVERS
+ BROWSE SERVERS
-
+
- DOCUMENTATION
+ MONETIZE SERVERS
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 */}
+
+
+
+
+ {/* 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}
+ )}
+ openToolModal(tool)}
+ >
+ RUN
+
+
+
+ ))
+ )}
+
+
+ {/* Text + Buttons Section */}
+
+
+ Consume any paid MCP server with a single account. {" "}
+ Pay per tool call, no subscriptions required.
+
+
+ {data?.serverId && (
+
+
+ SERVER DETAILS
+
+
+ )}
+
{
+ if (data?.origin) {
+ const url = urlUtils.getMcpUrl(data.origin)
+ navigator.clipboard.writeText(url)
+ toast.success("Copied MCP endpoint to clipboard")
+ } else {
+ toast.error("Server URL not available")
+ }
+ }}
+ >
+
+ CONNECT
+
+
+
+
+
+ {/* 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 */}
- EXPLORER
+ MONETIZE
- REGISTER
+ 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 (