refactor(api): remove MCP marketplace cache integration

Removed dependencies on MCPCacheRepository and PulseMCPService from MCP routes to simplify installation and listing logic, avoiding reliance on potentially stale cached data and streamlining the codebase. Updated available-for-chat filter to include MCPs without explicit status.
This commit is contained in:
Evandro Fonseca Junior committed 2025-10-29 15:35:15 -03:00
1 parent 4739a13458
commit f96d4ed696
34 files changed
+260 -3775

No files matched your search

+7 -7
View File
@@ -8,7 +8,7 @@ import {
SettingsButton,
SettingsModal,
} from "@/components/settings/SettingsModal";
import { MCPMarketplaceModal } from "@/components/mcp/MCPMarketplaceModal";
import { MCPManualInstallModal } from "@/components/mcp/MCPManualInstallModal";
import { Store } from "lucide-react";
interface ClientHomeProps {
@@ -22,7 +22,7 @@ export function ClientHome({ offline, models }: ClientHomeProps) {
const [currentConversationId, setCurrentConversationId] = useState<
string | null
>(null);
const [showMCPMarketplace, setShowMCPMarketplace] = useState(false);
const [showManualInstall, setShowManualInstall] = useState(false);
const handleConversationCreated = () => {
// Incrementar trigger para forçar atualização da sidebar
@@ -49,11 +49,11 @@ export function ClientHome({ offline, models }: ClientHomeProps) {
</span>
)}
<button
onClick={() => setShowMCPMarketplace(true)}
onClick={() => setShowManualInstall(true)}
className="flex items-center gap-2 px-3 py-2 bg-[var(--surface)] border border-[var(--border)] rounded-md hover:bg-[var(--background)] transition-colors text-sm"
>
<Store className="h-4 w-4" />
MCP Marketplace
Install MCP Manually
</button>
<SettingsButton onOpen={() => setOpen(true)} />
<ModeToggle />
@@ -77,9 +77,9 @@ export function ClientHome({ offline, models }: ClientHomeProps) {
</div>
</main>
<SettingsModal isOpen={open} onClose={() => setOpen(false)} />
<MCPMarketplaceModal
isOpen={showMCPMarketplace}
onClose={() => setShowMCPMarketplace(false)}
<MCPManualInstallModal
isOpen={showManualInstall}
onClose={() => setShowManualInstall(false)}
/>
</div>
);
-136
View File
@@ -1,136 +0,0 @@
"use client";
import { useState } from "react";
import { ChevronDown, ChevronRight } from "lucide-react";
interface MCPCategory {
id: string;
name: string;
icon: string;
count: number;
}
interface MCPCategoryFilterProps {
primaryCategories: MCPCategory[];
otherCategories: MCPCategory[];
selectedCategory: string;
onSelectCategory: (categoryId: string) => void;
}
export function MCPCategoryFilter({
primaryCategories,
otherCategories,
selectedCategory,
onSelectCategory,
}: MCPCategoryFilterProps) {
const [showOthers, setShowOthers] = useState(false);
const getCategoryIcon = (categoryName: string) => {
const iconMap: Record<string, string> = {
MAP: "🗺️",
BROWSER: "🌐",
OFFICE: "📄",
CODE: "💻",
DATABASE: "🗄️",
SEARCH: "🔍",
PAYMENT: "💳",
CHART: "📊",
FINANCE: "💰",
OTHER: "📦",
};
return iconMap[categoryName.toUpperCase()] || "📦";
};
return (
<div className="space-y-2">
<h3 className="font-semibold text-sm text-[var(--foreground)] mb-3">
Categories
</h3>
{/* All Categories */}
<button
onClick={() => onSelectCategory("all")}
className={`w-full flex items-center justify-between px-3 py-2 rounded-md text-sm transition-colors ${
selectedCategory === "all"
? "mcp-category-active"
: "hover:bg-[var(--surface)] text-[var(--muted-foreground)] hover:text-[var(--foreground)]"
}`}
>
<span className="flex items-center gap-2">📦 All Categories</span>
<span className="text-xs bg-[var(--background)] px-2 py-1 rounded-full">
{primaryCategories.reduce((sum, cat) => sum + cat.count, 0) +
otherCategories.reduce((sum, cat) => sum + cat.count, 0)}
</span>
</button>
{/* Primary Categories */}
<div className="space-y-1">
<h4 className="text-xs font-medium text-[var(--muted-foreground)] uppercase tracking-wide">
Principais
</h4>
{primaryCategories.map((category) => (
<button
key={category.id}
onClick={() => onSelectCategory(category.id)}
className={`w-full flex items-center justify-between px-3 py-2 rounded-md text-sm transition-colors ${
selectedCategory === category.id
? "mcp-category-active"
: "hover:bg-[var(--surface)] text-[var(--muted-foreground)] hover:text-[var(--foreground)]"
}`}
>
<span className="flex items-center gap-2">
{getCategoryIcon(category.name)} {category.name}
</span>
<span className="text-xs bg-[var(--background)] px-2 py-1 rounded-full">
{category.count}
</span>
</button>
))}
</div>
{/* Other Categories */}
{otherCategories.length > 0 && (
<div className="space-y-1">
<button
onClick={() => setShowOthers(!showOthers)}
className="w-full flex items-center justify-between px-3 py-2 rounded-md text-sm transition-colors hover:bg-[var(--surface)] text-[var(--muted-foreground)] hover:text-[var(--foreground)]"
>
<span className="flex items-center gap-2">
{showOthers ? (
<ChevronDown className="h-4 w-4" />
) : (
<ChevronRight className="h-4 w-4" />
)}
<span className="text-xs font-medium uppercase tracking-wide">
Outras ({otherCategories.length})
</span>
</span>
</button>
{showOthers && (
<div className="ml-4 space-y-1">
{otherCategories.map((category) => (
<button
key={category.id}
onClick={() => onSelectCategory(category.id)}
className={`w-full flex items-center justify-between px-3 py-2 rounded-md text-sm transition-colors ${
selectedCategory === category.id
? "mcp-category-active"
: "hover:bg-[var(--surface)] text-[var(--muted-foreground)] hover:text-[var(--foreground)]"
}`}
>
<span className="flex items-center gap-2">
📦 {category.name}
</span>
<span className="text-xs bg-[var(--background)] px-2 py-1 rounded-full">
{category.count}
</span>
</button>
))}
</div>
)}
</div>
)}
</div>
);
}
+4 -4
View File
@@ -154,9 +154,9 @@ export function MCPManualInstallModal({
How to use
</h3>
<p className="text-sm text-blue-700 dark:text-blue-300 mb-3">
Paste your MCP server configuration in Claude Desktop format
(claude_desktop_config.json). You can install custom MCPs or MCPs
not available in the marketplace.
Cole a configuração do servidor MCP no formato do Claude Desktop
(claude_desktop_config.json). Apenas instalação manual é suportada
neste projeto.
</p>
<button
onClick={handlePasteExample}
@@ -273,7 +273,7 @@ export function MCPManualInstallModal({
{error && (
<div className="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
<div className="flex items-start gap-2">
<AlertCircle className="h-5 w-5 text-red-500 flex-shrink-0 mt-0.5" />
<AlertCircle className="h-5 w-5 text-red-500 shrink-0 mt-0.5" />
<div className="flex-1">
<h4 className="font-medium text-red-900 dark:text-red-100">
Installation Error
File diff suppressed because it is too large. Load diff
-74
View File
@@ -1,74 +0,0 @@
"use client";
import { Star } from "lucide-react";
interface MCPRatingStarsProps {
rating: number;
size?: "sm" | "md" | "lg";
showNumber?: boolean;
}
export function MCPRatingStars({
rating,
size = "sm",
showNumber = true,
}: MCPRatingStarsProps) {
const sizeClasses = {
sm: "h-3 w-3",
md: "h-4 w-4",
lg: "h-5 w-5",
};
const stars = [];
const fullStars = Math.floor(rating);
const hasHalfStar = rating % 1 >= 0.5;
// Renderizar estrelas cheias
for (let i = 0; i < fullStars; i++) {
stars.push(
<Star
key={i}
className={`${sizeClasses[size]} fill-yellow-400 text-yellow-400`}
/>
);
}
// Renderizar meia estrela se necessário
if (hasHalfStar) {
stars.push(
<div key="half" className="relative">
<Star className={`${sizeClasses[size]} text-gray-300`} />
<div
className="absolute inset-0 overflow-hidden"
style={{ width: "50%" }}
>
<Star
className={`${sizeClasses[size]} fill-yellow-400 text-yellow-400`}
/>
</div>
</div>
);
}
// Renderizar estrelas vazias
const emptyStars = 5 - Math.ceil(rating);
for (let i = 0; i < emptyStars; i++) {
stars.push(
<Star
key={`empty-${i}`}
className={`${sizeClasses[size]} text-gray-300`}
/>
);
}
return (
<div className="flex items-center gap-1">
<div className="flex">{stars}</div>
{showNumber && (
<span className="text-sm text-[var(--muted-foreground)] ml-1">
{rating.toFixed(1)}
</span>
)}
</div>
);
}
-31
View File
@@ -1,31 +0,0 @@
"use client";
import { Search } from "lucide-react";
interface MCPSearchBarProps {
value: string;
onChange: (value: string) => void;
onSearch: () => void;
}
export function MCPSearchBar({ value, onChange, onSearch }: MCPSearchBarProps) {
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === "Enter") {
onSearch();
}
};
return (
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-[var(--muted-foreground)]" />
<input
type="text"
value={value}
onChange={(e) => onChange(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Search MCPs..."
className="w-full pl-10 pr-4 py-2 bg-[var(--surface)] border border-[var(--border)] rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-[var(--primary)] focus:border-transparent mcp-search-input"
/>
</div>
);
}
-1
View File
@@ -1 +0,0 @@