From 18256aadc561a54bdec313701518039c2ed4014d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20Kadir=20Ak=C4=B1n?= Date: Sun, 14 Dec 2025 21:36:23 +0300 Subject: [PATCH] chore(messages): update MCP server configurations in multiple languages --- messages/ar.json | 13 ++ messages/de.json | 13 ++ messages/en.json | 13 ++ messages/es.json | 13 ++ messages/fr.json | 13 ++ messages/it.json | 13 ++ messages/ja.json | 13 ++ messages/ko.json | 13 ++ messages/pt.json | 13 ++ messages/tr.json | 13 ++ messages/zh.json | 13 ++ public/mcp.svg | 6 + src/app/[username]/page.tsx | 35 ++-- src/app/categories/[slug]/page.tsx | 44 ++-- src/app/tags/[slug]/page.tsx | 22 +- src/components/mcp/mcp-server-popup.tsx | 258 ++++++++++++++++++++++++ 16 files changed, 464 insertions(+), 44 deletions(-) create mode 100644 public/mcp.svg create mode 100644 src/components/mcp/mcp-server-popup.tsx diff --git a/messages/ar.json b/messages/ar.json index f647622f..257c5509 100644 --- a/messages/ar.json +++ b/messages/ar.json @@ -717,5 +717,18 @@ "reportFailed": "فشل في إرسال البلاغ", "reasonRequired": "يرجى اختيار سبب", "alreadyReported": "لقد أبلغت عن هذا الأمر بالفعل" + }, + "mcp": { + "button": "خادم MCP", + "title": "إعدادات خادم MCP", + "copy": "نسخ", + "copied": "تم النسخ!", + "customizeFilters": "تخصيص الفلاتر لتضييق نطاق الأوامر:", + "users": "المستخدمون", + "userPlaceholder": "إضافة اسم مستخدم...", + "categories": "الفئات", + "categoryPlaceholder": "إضافة رمز الفئة...", + "tags": "العلامات", + "tagPlaceholder": "إضافة رمز العلامة..." } } diff --git a/messages/de.json b/messages/de.json index f8041ef4..0da37cb3 100644 --- a/messages/de.json +++ b/messages/de.json @@ -717,5 +717,18 @@ "reportFailed": "Meldung konnte nicht gesendet werden", "reasonRequired": "Bitte wählen Sie einen Grund", "alreadyReported": "Sie haben diesen Prompt bereits gemeldet" + }, + "mcp": { + "button": "MCP-Server", + "title": "MCP-Server-Konfiguration", + "copy": "Kopieren", + "copied": "Kopiert!", + "customizeFilters": "Filter anpassen, um Prompts einzugrenzen:", + "users": "Benutzer", + "userPlaceholder": "Benutzername hinzufügen...", + "categories": "Kategorien", + "categoryPlaceholder": "Kategorie-Slug hinzufügen...", + "tags": "Tags", + "tagPlaceholder": "Tag-Slug hinzufügen..." } } diff --git a/messages/en.json b/messages/en.json index 47b63353..c9eb38af 100644 --- a/messages/en.json +++ b/messages/en.json @@ -717,5 +717,18 @@ "reportFailed": "Failed to submit report", "reasonRequired": "Please select a reason", "alreadyReported": "You have already reported this prompt" + }, + "mcp": { + "button": "MCP Server", + "title": "MCP Server Configuration", + "copy": "Copy", + "copied": "Copied!", + "customizeFilters": "Customize filters to narrow down prompts:", + "users": "Users", + "userPlaceholder": "Add username...", + "categories": "Categories", + "categoryPlaceholder": "Add category slug...", + "tags": "Tags", + "tagPlaceholder": "Add tag slug..." } } diff --git a/messages/es.json b/messages/es.json index 56ee89a7..6bcd0d57 100644 --- a/messages/es.json +++ b/messages/es.json @@ -717,5 +717,18 @@ "reportFailed": "Error al enviar el reporte", "reasonRequired": "Por favor selecciona un motivo", "alreadyReported": "Ya has reportado este prompt" + }, + "mcp": { + "button": "Servidor MCP", + "title": "Configuración del Servidor MCP", + "copy": "Copiar", + "copied": "¡Copiado!", + "customizeFilters": "Personaliza los filtros para reducir los prompts:", + "users": "Usuarios", + "userPlaceholder": "Añadir nombre de usuario...", + "categories": "Categorías", + "categoryPlaceholder": "Añadir slug de categoría...", + "tags": "Etiquetas", + "tagPlaceholder": "Añadir slug de etiqueta..." } } diff --git a/messages/fr.json b/messages/fr.json index a72f14c5..7b61c9b1 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -717,5 +717,18 @@ "reportFailed": "Échec de l'envoi du signalement", "reasonRequired": "Veuillez sélectionner une raison", "alreadyReported": "Vous avez déjà signalé ce prompt" + }, + "mcp": { + "button": "Serveur MCP", + "title": "Configuration du Serveur MCP", + "copy": "Copier", + "copied": "Copié !", + "customizeFilters": "Personnalisez les filtres pour affiner les prompts :", + "users": "Utilisateurs", + "userPlaceholder": "Ajouter un nom d'utilisateur...", + "categories": "Catégories", + "categoryPlaceholder": "Ajouter un slug de catégorie...", + "tags": "Tags", + "tagPlaceholder": "Ajouter un slug de tag..." } } diff --git a/messages/it.json b/messages/it.json index aa06aa5f..5f150db1 100644 --- a/messages/it.json +++ b/messages/it.json @@ -717,5 +717,18 @@ "reportFailed": "Impossibile inviare la segnalazione", "reasonRequired": "Seleziona un motivo", "alreadyReported": "Hai già segnalato questo prompt" + }, + "mcp": { + "button": "Server MCP", + "title": "Configurazione Server MCP", + "copy": "Copia", + "copied": "Copiato!", + "customizeFilters": "Personalizza i filtri per restringere i prompt:", + "users": "Utenti", + "userPlaceholder": "Aggiungi nome utente...", + "categories": "Categorie", + "categoryPlaceholder": "Aggiungi slug categoria...", + "tags": "Tag", + "tagPlaceholder": "Aggiungi slug tag..." } } diff --git a/messages/ja.json b/messages/ja.json index 258b1064..1f0b8d15 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -717,5 +717,18 @@ "reportFailed": "報告の送信に失敗しました", "reasonRequired": "理由を選択してください", "alreadyReported": "このプロンプトは既に報告済みです" + }, + "mcp": { + "button": "MCPサーバー", + "title": "MCPサーバー設定", + "copy": "コピー", + "copied": "コピーしました!", + "customizeFilters": "フィルターをカスタマイズしてプロンプトを絞り込む:", + "users": "ユーザー", + "userPlaceholder": "ユーザー名を追加...", + "categories": "カテゴリー", + "categoryPlaceholder": "カテゴリースラッグを追加...", + "tags": "タグ", + "tagPlaceholder": "タグスラッグを追加..." } } diff --git a/messages/ko.json b/messages/ko.json index 2a4d7158..96d9e532 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -717,5 +717,18 @@ "reportFailed": "신고 제출에 실패했습니다", "reasonRequired": "사유를 선택하세요", "alreadyReported": "이미 이 프롬프트를 신고하셨습니다" + }, + "mcp": { + "button": "MCP 서버", + "title": "MCP 서버 설정", + "copy": "복사", + "copied": "복사됨!", + "customizeFilters": "필터를 사용자 정의하여 프롬프트 범위를 좁히세요:", + "users": "사용자", + "userPlaceholder": "사용자 이름 추가...", + "categories": "카테고리", + "categoryPlaceholder": "카테고리 슬러그 추가...", + "tags": "태그", + "tagPlaceholder": "태그 슬러그 추가..." } } diff --git a/messages/pt.json b/messages/pt.json index 664a00d0..8cd8a8c5 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -717,5 +717,18 @@ "reportFailed": "Falha ao enviar denúncia", "reasonRequired": "Por favor, selecione um motivo", "alreadyReported": "Você já denunciou este prompt" + }, + "mcp": { + "button": "Servidor MCP", + "title": "Configuração do Servidor MCP", + "copy": "Copiar", + "copied": "Copiado!", + "customizeFilters": "Personalize os filtros para restringir os prompts:", + "users": "Usuários", + "userPlaceholder": "Adicionar nome de usuário...", + "categories": "Categorias", + "categoryPlaceholder": "Adicionar slug da categoria...", + "tags": "Tags", + "tagPlaceholder": "Adicionar slug da tag..." } } diff --git a/messages/tr.json b/messages/tr.json index dcc053ec..83e41c9a 100644 --- a/messages/tr.json +++ b/messages/tr.json @@ -717,5 +717,18 @@ "reportFailed": "Şikayet gönderilemedi", "reasonRequired": "Lütfen bir sebep seçin", "alreadyReported": "Bu promptu zaten şikayet ettiniz" + }, + "mcp": { + "button": "MCP Sunucusu", + "title": "MCP Sunucu Yapılandırması", + "copy": "Kopyala", + "copied": "Kopyalandı!", + "customizeFilters": "Promptları daraltmak için filtreleri özelleştirin:", + "users": "Kullanıcılar", + "userPlaceholder": "Kullanıcı adı ekle...", + "categories": "Kategoriler", + "categoryPlaceholder": "Kategori slug ekle...", + "tags": "Etiketler", + "tagPlaceholder": "Etiket slug ekle..." } } diff --git a/messages/zh.json b/messages/zh.json index 3ffb4ffc..0596b462 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -717,5 +717,18 @@ "reportFailed": "举报提交失败", "reasonRequired": "请选择举报原因", "alreadyReported": "您已经举报过此提示词" + }, + "mcp": { + "button": "MCP 服务器", + "title": "MCP 服务器配置", + "copy": "复制", + "copied": "已复制!", + "customizeFilters": "自定义过滤器以缩小提示词范围:", + "users": "用户", + "userPlaceholder": "添加用户名...", + "categories": "分类", + "categoryPlaceholder": "添加分类标识...", + "tags": "标签", + "tagPlaceholder": "添加标签标识..." } } diff --git a/public/mcp.svg b/public/mcp.svg new file mode 100644 index 00000000..d93786da --- /dev/null +++ b/public/mcp.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/app/[username]/page.tsx b/src/app/[username]/page.tsx index b6953302..b1b2fbde 100644 --- a/src/app/[username]/page.tsx +++ b/src/app/[username]/page.tsx @@ -13,6 +13,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardContent } from "@/components/ui/card"; import { PromptList } from "@/components/prompts/prompt-list"; import { PromptCard, type PromptCardProps } from "@/components/prompts/prompt-card"; +import { McpServerPopup } from "@/components/mcp/mcp-server-popup"; interface UserProfilePageProps { params: Promise<{ username: string }>; @@ -320,15 +321,18 @@ export default async function UserProfilePage({ params, searchParams }: UserProf )}

- {/* Edit button - desktop only */} - {isOwner && ( - - )} + {/* Actions - desktop only */} +
+ + {isOwner && ( + + )} +
{/* Stats - stacked on mobile, inline on desktop */} @@ -354,17 +358,18 @@ export default async function UserProfilePage({ params, searchParams }: UserProf - {/* Edit button - below stats on mobile */} - {isOwner && ( -
- -
- )} + )} + {/* Tabs for Prompts and Change Requests */} diff --git a/src/app/categories/[slug]/page.tsx b/src/app/categories/[slug]/page.tsx index 39091104..9a1b8579 100644 --- a/src/app/categories/[slug]/page.tsx +++ b/src/app/categories/[slug]/page.tsx @@ -8,6 +8,7 @@ import { db } from "@/lib/db"; import { Button } from "@/components/ui/button"; import { PromptList } from "@/components/prompts/prompt-list"; import { SubscribeButton } from "@/components/categories/subscribe-button"; +import { McpServerPopup } from "@/components/mcp/mcp-server-popup"; interface CategoryPageProps { params: Promise<{ slug: string }>; @@ -114,28 +115,31 @@ export default async function CategoryPage({ params }: CategoryPageProps) { -
-
-

{category.name}

- {session?.user && ( - +
+
+
+

{category.name}

+ {session?.user && ( + + )} +
+ {category.description && ( +

+ {category.description} +

)} +
+ {category._count.prompts} prompts + • + {category._count.subscribers} subscribers +
- {category.description && ( -

- {category.description} -

- )} -
- {category._count.prompts} prompts - • - {category._count.subscribers} subscribers -
+
diff --git a/src/app/tags/[slug]/page.tsx b/src/app/tags/[slug]/page.tsx index 619779b1..6387204b 100644 --- a/src/app/tags/[slug]/page.tsx +++ b/src/app/tags/[slug]/page.tsx @@ -6,6 +6,7 @@ import { db } from "@/lib/db"; import { auth } from "@/lib/auth"; import { Button } from "@/components/ui/button"; import { PromptCard } from "@/components/prompts/prompt-card"; +import { McpServerPopup } from "@/components/mcp/mcp-server-popup"; interface TagPageProps { params: Promise<{ slug: string }>; @@ -112,15 +113,18 @@ export default async function TagPage({ params, searchParams }: TagPageProps) { -
-
-

{tag.name}

- - {total} {t("prompts")} - +
+
+
+

{tag.name}

+ + {total} {t("prompts")} + +
+
diff --git a/src/components/mcp/mcp-server-popup.tsx b/src/components/mcp/mcp-server-popup.tsx new file mode 100644 index 00000000..6de92e60 --- /dev/null +++ b/src/components/mcp/mcp-server-popup.tsx @@ -0,0 +1,258 @@ +"use client"; + +import { useState, useMemo } from "react"; +import { useTranslations } from "next-intl"; +import { Check, Copy, Plus, X } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Badge } from "@/components/ui/badge"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; + +// MCP Logo component +function McpIcon({ className }: { className?: string }) { + return ( + MCP + ); +} + +export { McpIcon }; + +interface McpServerPopupProps { + /** Pre-filled users (usernames) */ + initialUsers?: string[]; + /** Pre-filled categories (slugs) */ + initialCategories?: string[]; + /** Pre-filled tags (slugs) */ + initialTags?: string[]; + /** Base URL override */ + baseUrl?: string; +} + +export function McpServerPopup({ + initialUsers = [], + initialCategories = [], + initialTags = [], + baseUrl, +}: McpServerPopupProps) { + const t = useTranslations("mcp"); + const [copied, setCopied] = useState(false); + const [users, setUsers] = useState(initialUsers); + const [categories, setCategories] = useState(initialCategories); + const [tags, setTags] = useState(initialTags); + const [userInput, setUserInput] = useState(""); + const [categoryInput, setCategoryInput] = useState(""); + const [tagInput, setTagInput] = useState(""); + + // Build the MCP URL + const mcpUrl = useMemo(() => { + const base = baseUrl || (typeof window !== "undefined" ? window.location.origin : "https://prompts.chat"); + const params = new URLSearchParams(); + + if (users.length > 0) { + params.set("users", users.join(",")); + } + if (categories.length > 0) { + params.set("categories", categories.join(",")); + } + if (tags.length > 0) { + params.set("tags", tags.join(",")); + } + + const queryString = params.toString(); + return `${base}/api/mcp${queryString ? `?${queryString}` : ""}`; + }, [baseUrl, users, categories, tags]); + + // Generate the JSON config + const configJson = useMemo(() => { + return JSON.stringify( + { + mcpServers: { + "prompts-chat": { + url: mcpUrl, + }, + }, + }, + null, + 2 + ); + }, [mcpUrl]); + + const handleCopy = async () => { + await navigator.clipboard.writeText(configJson); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + const addUser = () => { + const value = userInput.trim().replace(/^@/, ""); + if (value && !users.includes(value)) { + setUsers([...users, value]); + setUserInput(""); + } + }; + + const addCategory = () => { + const value = categoryInput.trim().toLowerCase(); + if (value && !categories.includes(value)) { + setCategories([...categories, value]); + setCategoryInput(""); + } + }; + + const addTag = () => { + const value = tagInput.trim().toLowerCase(); + if (value && !tags.includes(value)) { + setTags([...tags, value]); + setTagInput(""); + } + }; + + const removeUser = (user: string) => setUsers(users.filter((u) => u !== user)); + const removeCategory = (cat: string) => setCategories(categories.filter((c) => c !== cat)); + const removeTag = (tag: string) => setTags(tags.filter((t) => t !== tag)); + + return ( + + + + + +
+ {/* Header */} +
+

+ + {t("title")} +

+ +
+ + {/* Config JSON */} +
+
{configJson}
+
+ + {/* Filters */} +
+

{t("customizeFilters")}

+ + {/* Users */} +
+ +
+ setUserInput(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && addUser()} + placeholder={t("userPlaceholder")} + className="h-7 text-xs flex-1" + /> + +
+ {users.length > 0 && ( +
+ {users.map((user) => ( + + @{user} + + + ))} +
+ )} +
+ + {/* Categories */} +
+ +
+ setCategoryInput(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && addCategory()} + placeholder={t("categoryPlaceholder")} + className="h-7 text-xs flex-1" + /> + +
+ {categories.length > 0 && ( +
+ {categories.map((cat) => ( + + {cat} + + + ))} +
+ )} +
+ + {/* Tags */} +
+ +
+ setTagInput(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && addTag()} + placeholder={t("tagPlaceholder")} + className="h-7 text-xs flex-1" + /> + +
+ {tags.length > 0 && ( +
+ {tags.map((tag) => ( + + {tag} + + + ))} +
+ )} +
+
+
+
+
+ ); +}