From 28c9f99a12b2be7de8e8561d4d494f7e702c772d Mon Sep 17 00:00:00 2001 From: Wendy Tang Date: Fri, 24 Jan 2025 15:14:08 -0800 Subject: [PATCH] feat: generate server.json for extension site from google sheet (#756) --- .../app/components/server-card.tsx | 123 +++--- extensions-site/app/mcp-servers.ts | 15 +- extensions-site/app/routes/detail.tsx | 118 ++++-- extensions-site/app/routes/home.tsx | 33 +- extensions-site/app/types/server.ts | 6 +- extensions-site/public/servers.json | 351 ++++++------------ 6 files changed, 314 insertions(+), 332 deletions(-) diff --git a/extensions-site/app/components/server-card.tsx b/extensions-site/app/components/server-card.tsx index 05f45a38..34990c9d 100644 --- a/extensions-site/app/components/server-card.tsx +++ b/extensions-site/app/components/server-card.tsx @@ -1,4 +1,4 @@ -import { Star, Download, Terminal, ChevronRight } from "lucide-react"; +import { Star, Download, Terminal, ChevronRight, Info } from "lucide-react"; import { Badge } from "./ui/badge"; import { Button } from "./ui/button"; import { Card, CardContent, CardHeader } from "./ui/card"; @@ -8,6 +8,15 @@ import { useState } from "react"; import { motion, AnimatePresence } from "motion/react"; function getGooseInstallLink(server: MCPServer): string { + if (server.is_builtin) { + const queryParams = [ + 'cmd=goosed', + 'arg=mcp', + `arg=${encodeURIComponent(server.id)}`, + `description=${encodeURIComponent(server.id)}` + ].join('&'); + return `goose://extension?${queryParams}`; + } const parts = server.command.split(" "); const baseCmd = parts[0]; // npx or uvx const args = parts.slice(1); // remaining arguments @@ -74,35 +83,47 @@ export function ServerCard({ server }: { server: MCPServer }) {
- - - {isCommandVisible && ( - + {/* */} + + Can be enabled in the goose settings page +
+ ) : ( + <> + + + {isCommandVisible && ( + + + {`goose session --with-extension "${server.command}"`} + + + )} + + + )} @@ -111,22 +132,36 @@ export function ServerCard({ server }: { server: MCPServer }) { {server.githubStars} on Github - - - + + Built-in + + + ) : ( + + + + )} diff --git a/extensions-site/app/mcp-servers.ts b/extensions-site/app/mcp-servers.ts index 39579531..8c911b67 100644 --- a/extensions-site/app/mcp-servers.ts +++ b/extensions-site/app/mcp-servers.ts @@ -1,15 +1,15 @@ import type { MCPServer } from '../types/server'; export async function fetchMCPServers(): Promise { - const baseUrl = import.meta.env.VITE_BASENAME || ""; try { - // Fetch all servers from the unified JSON file - const response = await fetch(`${baseUrl}servers.json`); + // Use absolute path from root + const url = '/servers.json'; + const response = await fetch(url); if (!response.ok) { - throw new Error('Failed to fetch servers'); - } - - const servers = await response.json(); + throw new Error(`Failed to fetch servers: ${response.status} ${response.statusText}`); + } + const text = await response.text(); + const servers = JSON.parse(text); return servers.sort((a, b) => b.githubStars - a.githubStars); } catch (error) { console.error('Error fetching servers:', error); @@ -17,6 +17,7 @@ export async function fetchMCPServers(): Promise { } } + export async function searchMCPServers(query: string): Promise { const allServers = await fetchMCPServers(); const searchTerms = query.toLowerCase().split(' ').filter(term => term.length > 0); diff --git a/extensions-site/app/routes/detail.tsx b/extensions-site/app/routes/detail.tsx index 27bfe99e..8de8e698 100644 --- a/extensions-site/app/routes/detail.tsx +++ b/extensions-site/app/routes/detail.tsx @@ -3,19 +3,24 @@ import { Download, Star, Terminal, - ChevronRight, ArrowLeft, + Info } from "lucide-react"; import { Button } from "../components/ui/button"; import { Badge } from "../components/ui/badge"; import { Card, CardContent, CardHeader } from "../components/ui/card"; import { useEffect, useState } from "react"; +import { fetchMCPServers } from "../mcp-servers"; interface Server { id: string; name: string; description: string; command: string; + link: string; + installation_notes: string; + is_builtin: boolean; + endorsed: boolean; githubStars: number; environmentVariables: { name: string; @@ -46,18 +51,31 @@ export default function DetailPage() { const { id } = useParams(); const [server, setServer] = useState(null); const [isCommandVisible, setIsCommandVisible] = useState(true); - const serverUrl = "https://block.github.io/goose/v1/extensions/servers.json"; - + const [error, setError] = useState(null); + const [isLoading, setIsLoading] = useState(true); useEffect(() => { - fetch(serverUrl) - .then((res) => res.json()) - .then((servers) => { - const matchingServer = servers.find((s: Server) => s.id === id); - if (matchingServer) { - setServer(matchingServer); + const loadServer = async () => { + try { + setIsLoading(true); + setError(null); + const servers = await fetchMCPServers(); + const foundServer = servers.find((s) => s.id === id); + if (!foundServer) { + setError(`Server with ID "${id}" not found`); + return; } - }); + setServer(foundServer); + } catch (err) { + const errorMessage = err instanceof Error ? err.message : "Unknown error"; + setError(`Failed to load server: ${errorMessage}`); + console.error("Error loading server:", err); + } finally { + setIsLoading(false); + } + }; + + loadServer(); }, [id]); if (!server) { @@ -134,22 +152,33 @@ export default function DetailPage() {

{server.description}

{/* */} - -
-
- -

Command

-
- - goose session --with-extension "{server.command}" - +
+

{server.installation_notes}

- {server.environmentVariables.length > 0 && ( -
-

- Environment Variables -

+
+ {server.is_builtin ? ( +
+ + Can be enabled in the goose settings page +
+ ) : ( + <> +
+ +

Command

+
+ + {`goose session --with-extension "${server.command}"`} + + + )} +
+
+

+ Environment Variables +

+ {server.environmentVariables.length > 0 ? (
{server.environmentVariables.map((env) => (
))}
-
- )} + ) : ( +
+ + No environment variables needed +
+ )} +
@@ -185,15 +219,29 @@ export default function DetailPage() { rel="noopener noreferrer" className="no-underline" > - + {server.is_builtin ? ( +
+ + Built-in + +
+ ) : ( + + )}
diff --git a/extensions-site/app/routes/home.tsx b/extensions-site/app/routes/home.tsx index f52b7e39..30507a9c 100644 --- a/extensions-site/app/routes/home.tsx +++ b/extensions-site/app/routes/home.tsx @@ -89,19 +89,26 @@ export default function HomePage() { ) : (
{/* */} - {servers.map((server, index) => ( - - - - ))} + {servers + .sort((a, b) => { + // Sort built-in servers first + if (a.is_builtin && !b.is_builtin) return -1; + if (!a.is_builtin && b.is_builtin) return 1; + return 0; + }) + .map((server, index) => ( + + + + ))} {/* */}
)} diff --git a/extensions-site/app/types/server.ts b/extensions-site/app/types/server.ts index 29fc5be6..3c220ce7 100644 --- a/extensions-site/app/types/server.ts +++ b/extensions-site/app/types/server.ts @@ -2,8 +2,12 @@ export interface MCPServer { id: string; name: string; description: string; - githubStars: number; command: string; + link: string; + installation_notes: string; + is_builtin: boolean; + endorsed: boolean + githubStars: number; environmentVariables: { name: string; description: string; diff --git a/extensions-site/public/servers.json b/extensions-site/public/servers.json index fd1ff9a0..1b958360 100644 --- a/extensions-site/public/servers.json +++ b/extensions-site/public/servers.json @@ -1,263 +1,150 @@ [ { - "id": "aws-kb-retrieval", - "name": "AWS KB Retrieval", - "description": "Retrieval from AWS Knowledge Base using Bedrock Agent Runtime", - "command": "npx -y @modelcontextprotocol/server-aws-kb-retrieval", - "githubStars": 120, - "environmentVariables": [ - { - "name": "AWS_ACCESS_KEY_ID", - "description": "AWS access key ID", - "required": true - }, - { - "name": "AWS_SECRET_ACCESS_KEY", - "description": "AWS secret access key", - "required": true - }, - { - "name": "AWS_REGION", - "description": "AWS region", - "required": true - } - ] - }, - { - "id": "brave-search", - "name": "Brave Search", - "description": "Web and local search using Brave's Search API", - "command": "npx -y @modelcontextprotocol/server-brave-search", - "githubStars": 95, - "environmentVariables": [ - { - "name": "BRAVE_API_KEY", - "description": "API key for Brave Search", - "required": true - } - ] - }, - { - "id": "everart", - "name": "EverArt", - "description": "AI image generation using various models", - "command": "npx -y @modelcontextprotocol/server-everart", - "githubStars": 85, - "environmentVariables": [ - { - "name": "EVERART_API_KEY", - "description": "API key for EverArt service", - "required": true - } - ] - }, - { - "id": "everything", - "name": "Everything", - "description": "Reference / test server with prompts, resources, and tools", - "command": "npx -y @modelcontextprotocol/server-everything", - "githubStars": 75, + "id": "developer", + "name": "Developer", + "description": "Built-in developer tools for file editing and shell command execution", + "command": "", + "link": "https://github.com/block/goose/tree/v1.0/crates/goose-mcp/src/developer", + "installation_notes": "This is a built-in extension that comes with Goose by default. No installation required.", + "is_builtin": true, + "endorsed": true, + "githubStars": 356, "environmentVariables": [] }, { - "id": "fetch", - "name": "Fetch", - "description": "Web content fetching and conversion for efficient LLM usage", - "command": "npx -y @modelcontextprotocol/server-fetch", - "githubStars": 82, + "id": "nondeveloper", + "name": "Non-developer", + "description": "Built-in tools for non-developer tasks and system interactions", + "command": "", + "link": "https://github.com/block/goose/tree/v1.0/crates/goose-mcp/src/nondeveloper", + "installation_notes": "This is a built-in extension that comes with Goose by default. No installation required.", + "is_builtin": true, + "endorsed": true, + "githubStars": 356, "environmentVariables": [] }, { - "id": "filesystem", - "name": "Filesystem", - "description": "Secure file operations with configurable access controls", - "command": "npx -y @modelcontextprotocol/server-filesystem", - "githubStars": 110, - "environmentVariables": [ - { - "name": "ALLOWED_PATHS", - "description": "Comma-separated list of allowed filesystem paths", - "required": true - } - ] - }, - { - "id": "gdrive", + "id": "google_drive", "name": "Google Drive", - "description": "File access and search capabilities for Google Drive", - "command": "npx -y @modelcontextprotocol/server-gdrive", - "githubStars": 92, + "description": "Built-in Google Drive integration for file management and access", + "command": "", + "link": "https://github.com/block/goose/tree/v1.0/crates/goose-mcp/src/google_drive", + "installation_notes": "This is a built-in extension that comes with Goose by default. Can be accessed via goose://extension?cmd=goosed&arg=mcp&arg=google_drive&description=google_drive deeplink.", + "is_builtin": true, + "endorsed": true, + "githubStars": 356, "environmentVariables": [ { - "name": "GOOGLE_CREDENTIALS", - "description": "Google Cloud service account credentials JSON", - "required": true - } - ] - }, - { - "id": "git", - "name": "Git", - "description": "Tools to read, search, and manipulate Git repositories", - "command": "uvx mcp-server-git", - "githubStars": 95, - "environmentVariables": [ - { - "name": "GIT_REPO_PATH", - "description": "Path to the Git repository", - "required": true - } - ] - }, - { - "id": "github", - "name": "GitHub", - "description": "Repository management, file operations, and GitHub API integration", - "command": "npx -y @modelcontextprotocol/server-github", - "githubStars": 130, - "environmentVariables": [ - { - "name": "GITHUB_TOKEN", - "description": "GitHub personal access token", - "required": true - } - ] - }, - { - "id": "gitlab", - "name": "GitLab", - "description": "GitLab API, enabling project management", - "command": "npx -y @modelcontextprotocol/server-gitlab", - "githubStars": 88, - "environmentVariables": [ - { - "name": "GITLAB_TOKEN", - "description": "GitLab personal access token", + "name": "GOOGLE_DRIVE_OAUTH_PATH", + "description": "Path to the OAuth config file (required)", "required": true }, { - "name": "GITLAB_URL", - "description": "GitLab instance URL (defaults to gitlab.com)", - "required": false - } - ] - }, - { - "id": "google-maps", - "name": "Google Maps", - "description": "Location services, directions, and place details", - "command": "npx -y @modelcontextprotocol/server-google-maps", - "githubStars": 87, - "environmentVariables": [ - { - "name": "GOOGLE_MAPS_API_KEY", - "description": "Google Maps API key", + "name": "GOOGLE_DRIVE_CREDENTIALS_PATH", + "description": "Path to store OAuth credentials (required)", "required": true + }, + { + "name": "GOOGLE_DRIVE_OAUTH_CONFIG", + "description": "OAuth config JSON string (optional, if not provided expects valid config file at GOOGLE_DRIVE_OAUTH_PATH)", + "required": false } ] }, { "id": "memory", "name": "Memory", - "description": "Knowledge graph-based persistent memory system", + "description": "Built-in memory system for persistent context and information storage", + "command": "", + "link": "https://github.com/block/goose/tree/v1.0/crates/goose-mcp/src/memory", + "installation_notes": "This is a built-in extension that comes with Goose by default. No installation required.", + "is_builtin": true, + "endorsed": true, + "githubStars": 356, + "environmentVariables": [] + }, + { + "id": "jetbrains", + "name": "JetBrains", + "description": "Built-in JetBrains IDE integration for development workflows", + "command": "", + "link": "https://github.com/block/goose/tree/v1.0/crates/goose-mcp/src/jetbrains", + "installation_notes": "This is a built-in extension that comes with Goose by default. Can be accessed via goose://extension?cmd=goosed&arg=mcp&arg=jetbrains deeplink.", + "is_builtin": true, + "endorsed": true, + "githubStars": 356, + "environmentVariables": [] + }, + { + "id": "knowledge_graph_memory", + "name": "Knowledge Graph Memory", + "description": "Graph-based memory system for persistent knowledge storage", "command": "npx -y @modelcontextprotocol/server-memory", - "githubStars": 105, - "environmentVariables": [ - { - "name": "MEMORY_STORE_PATH", - "description": "Path to store the memory database", - "required": true - } - ] - }, - { - "id": "postgres", - "name": "PostgreSQL", - "description": "Read-only database access with schema inspection", - "command": "npx -y @modelcontextprotocol/server-postgres", - "githubStars": 98, - "environmentVariables": [ - { - "name": "DATABASE_URL", - "description": "PostgreSQL connection string", - "required": true - } - ] - }, - { - "id": "puppeteer", - "name": "Puppeteer", - "description": "Browser automation and web scraping", - "command": "npx -y @modelcontextprotocol/server-puppeteer", - "githubStars": 85, + "link": "https://github.com/modelcontextprotocol/servers/tree/main/src/memory", + "installation_notes": "Install using npx package manager. Note: Default memory graph location may be hard to find where npx installs the module.", + "is_builtin": false, + "endorsed": true, + "githubStars": 7271, "environmentVariables": [] }, { - "id": "sentry", - "name": "Sentry", - "description": "Retrieving and analyzing issues from Sentry.io", - "command": "npx -y @modelcontextprotocol/server-sentry", - "githubStars": 78, - "environmentVariables": [ - { - "name": "SENTRY_AUTH_TOKEN", - "description": "Sentry authentication token", - "required": true - }, - { - "name": "SENTRY_ORG", - "description": "Sentry organization slug", - "required": true - } - ] - }, - { - "id": "sequentialthinking", - "name": "Sequential Thinking", - "description": "Dynamic and reflective problem-solving through thought sequences", - "command": "npx -y @modelcontextprotocol/server-sequentialthinking", - "githubStars": 82, + "id": "fetch", + "name": "Fetch", + "description": "Web content fetching and processing capabilities", + "command": "uvx mcp-server-fetch", + "link": "https://github.com/modelcontextprotocol/servers/tree/main/src/fetch", + "installation_notes": "Install using uvx package manager. Note: Some sites may block access via robots.txt.", + "is_builtin": false, + "endorsed": true, + "githubStars": 7271, "environmentVariables": [] }, { - "id": "slack", - "name": "Slack", - "description": "Channel management and messaging capabilities", - "command": "npx -y @modelcontextprotocol/server-slack", - "githubStars": 90, - "environmentVariables": [ - { - "name": "SLACK_TOKEN", - "description": "Slack bot token", - "required": true - }, - { - "name": "SLACK_CHANNEL", - "description": "Default Slack channel ID", - "required": false - } - ] - }, - { - "id": "sqlite", - "name": "Sqlite", - "description": "Database interaction and business intelligence capabilities", - "command": "npx -y @modelcontextprotocol/server-sqlite", - "githubStars": 85, - "environmentVariables": [ - { - "name": "DATABASE_PATH", - "description": "Path to SQLite database file", - "required": true - } - ] - }, - { - "id": "time", - "name": "Time", - "description": "Time and timezone conversion capabilities", - "command": "npx -y @modelcontextprotocol/server-time", - "githubStars": 75, + "id": "git", + "name": "Git", + "description": "Git version control system integration", + "command": "npx -y @modelcontextprotocol/server-git", + "link": "https://github.com/modelcontextprotocol/servers/tree/main/src/git", + "installation_notes": "Install using npx package manager. Note: Does not support git push, merge or rebase operations.", + "is_builtin": false, + "endorsed": true, + "githubStars": 7271, "environmentVariables": [] + }, + { + "id": "tavily", + "name": "Tavily Web Search", + "description": "Web search capabilities powered by Tavily", + "command": "uvx mcp-tavily", + "link": "https://github.com/RamXX/mcp-tavily", + "installation_notes": "Install using uvx package manager. Requires Tavily API key.", + "is_builtin": false, + "endorsed": true, + "githubStars": 4, + "environmentVariables": [ + { + "name": "TAVILY_API_KEY", + "description": "API key for Tavily web search service", + "required": true + } + ] + }, + { + "id": "figma", + "name": "Figma", + "description": "Figma design tool integration", + "command": "npx -y @hapins/figma-mcp", + "link": "https://www.npmjs.com/package/@hapins/figma-mcp", + "installation_notes": "Install using npx package manager. Requires Figma access token from user settings.", + "is_builtin": false, + "endorsed": true, + "githubStars": 0, + "environmentVariables": [ + { + "name": "FIGMA_ACCESS_TOKEN", + "description": "Access token from Figma user settings", + "required": true + } + ] } ] \ No newline at end of file