Skip to main content
Glama

Personal MCP Server

by pablicio
index.html45.3 kB
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>MCP Server - Configuracao e Documentacao</title> <link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" rel="stylesheet"> <style> :root { --color-background: #fcfcf9; --color-surface: #fffffd; --color-text: #134c3b; --color-text-secondary: #626c71; --color-primary: #21808d; --color-primary-hover: #1d7480; --color-success: #21808d; --color-warning: #a84b2f; --color-error: #c0152f; --color-border: rgba(94, 82, 64, 0.2); --color-card-border: rgba(94, 82, 64, 0.12); --color-secondary: rgba(94, 82, 64, 0.12); --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; --font-family-mono: 'Monaco', 'Menlo', monospace; --space-8: 8px; --space-12: 12px; --space-16: 16px; --space-20: 20px; --space-24: 24px; --space-32: 32px; --radius-sm: 6px; --radius-base: 8px; --radius-lg: 12px; --shadow-sm: 0 1px 3px rgba(0,0,0,0.04); --shadow-md: 0 4px 6px rgba(0,0,0,0.06); } @media (prefers-color-scheme: dark) { :root { --color-background: #1f2121; --color-surface: #262828; --color-text: #f5f5f5; --color-text-secondary: rgba(167, 169, 169, 0.7); --color-primary: #32b8c6; --color-primary-hover: #2da6b2; --color-success: #32b8c6; --color-warning: #e68161; --color-error: #ff5459; --color-border: rgba(119, 124, 124, 0.3); --color-card-border: rgba(119, 124, 124, 0.2); --color-secondary: rgba(119, 124, 124, 0.15); } } * { box-sizing: border-box; } body { margin: 0; font-family: var(--font-family); background: var(--color-background); color: var(--color-text); line-height: 1.5; } h1, h2, h3, h4 { margin: 0 0 var(--space-16) 0; color: var(--color-text); } h1 { font-size: 2rem; } h2 { font-size: 1.5rem; } h3 { font-size: 1.25rem; } .app { display: flex; min-height: 100vh; } .sidebar { width: 280px; background: var(--color-surface); border-right: 1px solid var(--color-border); padding: var(--space-24); position: fixed; height: 100vh; overflow-y: auto; } .main { flex: 1; margin-left: 280px; padding: var(--space-24); } .nav-item { display: flex; align-items: center; padding: var(--space-12) var(--space-16); margin: 4px 0; border-radius: var(--radius-base); cursor: pointer; color: var(--color-text-secondary); transition: all 0.2s; } .nav-item:hover, .nav-item.active { background: var(--color-secondary); color: var(--color-text); } .nav-item.active { background: var(--color-primary); color: white; } .nav-item svg { width: 20px; height: 20px; margin-right: var(--space-12); } .card { background: var(--color-surface); border: 1px solid var(--color-card-border); border-radius: var(--radius-lg); padding: var(--space-20); margin-bottom: var(--space-16); box-shadow: var(--shadow-sm); transition: box-shadow 0.2s; } .card:hover { box-shadow: var(--shadow-md); } .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--space-16); } .grid-small { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: var(--space-16); } .btn { display: inline-flex; align-items: center; padding: var(--space-8) var(--space-16); background: var(--color-primary); color: white; border: none; border-radius: var(--radius-base); cursor: pointer; font-weight: 500; transition: background 0.2s; } .btn:hover { background: var(--color-primary-hover); } .btn-secondary { background: var(--color-secondary); color: var(--color-text); } .btn-sm { padding: 4px var(--space-12); font-size: 0.875rem; } .form-group { margin-bottom: var(--space-16); } .form-label { display: block; margin-bottom: var(--space-8); font-weight: 500; font-size: 0.875rem; } .form-control { width: 100%; padding: var(--space-8) var(--space-12); border: 1px solid var(--color-border); border-radius: var(--radius-base); background: var(--color-surface); color: var(--color-text); } .form-control:focus { outline: 2px solid var(--color-primary); border-color: var(--color-primary); } .status { display: inline-flex; align-items: center; padding: 4px var(--space-12); border-radius: 20px; font-size: 0.875rem; font-weight: 500; } .status-success { background: rgba(33, 128, 141, 0.15); color: var(--color-success); } .status-warning { background: rgba(168, 75, 47, 0.15); color: var(--color-warning); } .module-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-12); } .module-tools { display: flex; flex-wrap: wrap; gap: var(--space-8); margin-top: var(--space-12); } .tool-tag { padding: 4px var(--space-8); background: rgba(59, 130, 246, 0.08); border-radius: var(--radius-sm); font-size: 0.875rem; color: var(--color-text-secondary); } .code-block { position: relative; margin: var(--space-16) 0; } .code-block pre { background: #2d3748 !important; color: #f7fafc !important; border-radius: var(--radius-base); overflow-x: auto; font-size: 0.875rem; line-height: 1.6; padding: var(--space-16); font-family: var(--font-family-mono); } .copy-btn { position: absolute; top: var(--space-8); right: var(--space-8); padding: 4px var(--space-8); background: var(--color-secondary); border: 1px solid var(--color-border); border-radius: var(--radius-sm); font-size: 0.75rem; cursor: pointer; color: var(--color-text); } .step-card { background: var(--color-surface); border: 1px solid var(--color-card-border); border-radius: var(--radius-lg); padding: var(--space-20); margin-bottom: var(--space-16); border-left: 4px solid var(--color-primary); } .step-number { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; background: var(--color-primary); color: white; border-radius: 50%; font-weight: 600; margin-right: var(--space-12); } .troubleshoot-item { background: rgba(245, 158, 11, 0.08); padding: var(--space-16); border-radius: var(--radius-base); margin-bottom: var(--space-12); } .troubleshoot-issue { font-weight: 500; color: var(--color-warning); margin-bottom: var(--space-8); } .theme-toggle { position: absolute; top: var(--space-16); right: var(--space-16); padding: var(--space-8); background: var(--color-secondary); border: 1px solid var(--color-border); border-radius: var(--radius-base); cursor: pointer; color: var(--color-text); } .log-output { background: #2d3748; color: #f7fafc; padding: var(--space-16); border-radius: var(--radius-base); height: 300px; overflow-y: auto; font-family: var(--font-family-mono); font-size: 0.875rem; line-height: 1.4; } .generated-config { background: rgba(34, 197, 94, 0.08); padding: var(--space-16); border-radius: var(--radius-base); margin-top: var(--space-16); } .section { display: none; } .section.active { display: block; } .hidden { display: none; } .flex { display: flex; } .flex-between { justify-content: space-between; } .flex-center { align-items: center; } .mb-16 { margin-bottom: var(--space-16); } .mb-24 { margin-bottom: var(--space-24); } .mb-32 { margin-bottom: var(--space-32); } .mt-12 { margin-top: var(--space-12); } @media (max-width: 768px) { .sidebar { transform: translateX(-100%); transition: transform 0.3s; z-index: 1000; } .sidebar.mobile-open { transform: translateX(0); } .main { margin-left: 0; padding: var(--space-16); } .mobile-menu-btn { display: block; position: fixed; top: var(--space-16); left: var(--space-16); z-index: 1001; background: var(--color-primary); color: white; border: none; padding: var(--space-8); border-radius: var(--radius-base); cursor: pointer; } } @media (min-width: 769px) { .mobile-menu-btn { display: none; } } </style> </head> <body> <button class="mobile-menu-btn" id="mobileMenuBtn"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <line x1="3" y1="6" x2="21" y2="6"></line> <line x1="3" y1="12" x2="21" y2="12"></line> <line x1="3" y1="18" x2="21" y2="18"></line> </svg> </button> <button class="theme-toggle" id="themeToggle"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </button> <div class="app"> <nav class="sidebar" id="sidebar"> <div class="mb-24"> <h2 style="color: var(--color-primary); margin-bottom: 8px;">MCP Server</h2> <p style="color: var(--color-text-secondary); font-size: 0.875rem;">Configuracao &amp; Documentacao</p> </div> <div class="nav-item active" data-section="dashboard"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <rect x="3" y="3" width="7" height="7"></rect> <rect x="14" y="3" width="7" height="7"></rect> <rect x="14" y="14" width="7" height="7"></rect> <rect x="3" y="14" width="7" height="7"></rect> </svg> Dashboard </div> <div class="nav-item" data-section="config"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <circle cx="12" cy="12" r="3"></circle> <path d="M12 1v6m0 6v6m6-12h-6m-6 0h6"></path> </svg> Configuracao </div> <div class="nav-item" data-section="docs"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"></path> <polyline points="14,2 14,8 20,8"></polyline> <line x1="16" y1="13" x2="8" y2="13"></line> <line x1="16" y1="17" x2="8" y2="17"></line> </svg> Documentacao </div> <div class="nav-item" data-section="extensions"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <polyline points="16 18 22 12 16 6"></polyline> <polyline points="8 6 2 12 8 18"></polyline> </svg> Extensibilidade </div> <div class="nav-item" data-section="logs"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"></path> <polyline points="14,2 14,8 20,8"></polyline> <line x1="10" y1="12" x2="8" y2="12"></line> <line x1="16" y1="12" x2="14" y2="12"></line> </svg> Logs &amp; Debug </div> </nav> <main class="main"> <section id="dashboard" class="section active"> <div class="mb-32"> <h1>Dashboard do Servidor MCP</h1> <p style="color: var(--color-text-secondary); font-size: 1.125rem;">Visao geral dos modulos e status do servidor</p> </div> <div class="grid mb-32"> <div class="card"> <h3 style="color: var(--color-success); margin-bottom: 8px;">Status do Servidor</h3> <div class="status status-success">✓ Ativo</div> <p class="mt-12" style="color: var(--color-text-secondary);">Servidor rodando na porta 3000</p> </div> <div class="card"> <h3 style="color: var(--color-primary); margin-bottom: 8px;">Modulos Ativos</h3> <div style="font-size: 1.5rem; font-weight: bold; color: var(--color-primary); margin-bottom: 8px;">2/4</div> <p style="color: var(--color-text-secondary);">Google Calendar • File System</p> </div> <div class="card"> <h3 style="color: var(--color-warning); margin-bottom: 8px;">Ferramentas Disponiveis</h3> <div style="font-size: 1.5rem; font-weight: bold; color: var(--color-primary); margin-bottom: 8px;">9</div> <p style="color: var(--color-text-secondary);">Total de ferramentas ativas</p> </div> </div> <h2 class="mb-16">Modulos Disponiveis</h2> <div id="modulesList"></div> </section> <section id="config" class="section"> <div class="mb-32"> <h1>Configuracao do Servidor</h1> <p style="color: var(--color-text-secondary); font-size: 1.125rem;">Configure suas credenciais e integracoes</p> </div> <div class="card"> <form> <h3>Google Calendar</h3> <div class="form-group"> <label class="form-label">Client ID</label> <input type="text" class="form-control" id="googleClientId" placeholder="Seu Google Client ID"> </div> <div class="form-group"> <label class="form-label">Client Secret</label> <input type="password" class="form-control" id="googleClientSecret" placeholder="Seu Google Client Secret"> </div> <div class="form-group"> <label class="form-label">Redirect URI</label> <input type="text" class="form-control" id="googleRedirectUri" value="http://localhost:3000/auth/callback" readonly> </div> <h3 style="margin-top: var(--space-32);">Sistema de Arquivos</h3> <div class="form-group"> <label class="form-label">Diretorios Permitidos (um por linha)</label> <textarea class="form-control" id="allowedPaths" rows="4" placeholder="/home/usuario/Documentos /home/usuario/Desktop /home/usuario/Projetos"></textarea> </div> <h3 style="margin-top: var(--space-32);">Configuracoes Gerais</h3> <div class="grid"> <div class="form-group"> <label class="form-label">Porta do Servidor</label> <input type="number" class="form-control" id="serverPort" value="3000"> </div> <div class="form-group"> <label class="form-label">Log Level</label> <select class="form-control" id="logLevel"> <option value="debug">Debug</option> <option value="info" selected>Info</option> <option value="warn">Warning</option> <option value="error">Error</option> </select> </div> </div> <button type="button" class="btn" id="generateConfig">Gerar Configuracao</button> </form> </div> <div class="generated-config hidden" id="generatedConfig"> <h3 class="mb-16">Configuracao para Claude Desktop</h3> <p class="mb-16" style="color: var(--color-text-secondary);">Adicione esta configuracao ao seu <code>claude_desktop_config.json</code>:</p> <div class="code-block"> <button class="copy-btn" onclick="copyConfig()">Copiar</button> <pre><code id="configOutput"></code></pre> </div> </div> </section> <section id="docs" class="section"> <div class="mb-32"> <h1>Documentacao</h1> <p style="color: var(--color-text-secondary); font-size: 1.125rem;">Guia completo de instalacao e uso</p> </div> <div class="step-card"> <div class="flex flex-center mb-16"> <div class="step-number">1</div> <h3>Instalar Dependencias</h3> </div> <p class="mb-16">Instale todas as dependencias Python necessarias:</p> <div class="code-block"> <button class="copy-btn" onclick="copyCode(this)">Copiar</button> <pre><code class="language-bash">pip install -r requirements.txt</code></pre> </div> <p style="color: var(--color-text-secondary); font-size: 0.875rem;">Certifique-se de ter Python 3.8+ instalado</p> </div> <div class="step-card"> <div class="flex flex-center mb-16"> <div class="step-number">2</div> <h3>Configurar Credenciais</h3> </div> <p class="mb-16">Configure suas credenciais do Google Calendar:</p> <div class="code-block"> <button class="copy-btn" onclick="copyCode(this)">Copiar</button> <pre><code class="language-bash"># Criar arquivo .env na raiz do projeto GOOGLE_CLIENT_ID=seu_client_id_aqui GOOGLE_CLIENT_SECRET=seu_client_secret_aqui ALLOWED_PATHS=/home/usuario/Documentos,/home/usuario/Desktop</code></pre> </div> </div> <div class="step-card"> <div class="flex flex-center mb-16"> <div class="step-number">3</div> <h3>Iniciar o Servidor</h3> </div> <p class="mb-16">Execute o servidor MCP:</p> <div class="code-block"> <button class="copy-btn" onclick="copyCode(this)">Copiar</button> <pre><code class="language-bash">python main.py</code></pre> </div> <p style="color: var(--color-text-secondary); font-size: 0.875rem;">O servidor iniciara na porta 3000 por padrao</p> </div> <div class="step-card"> <div class="flex flex-center mb-16"> <div class="step-number">4</div> <h3>Configurar Claude Desktop</h3> </div> <p class="mb-16">Adicione a configuracao ao Claude Desktop:</p> <div class="code-block"> <button class="copy-btn" onclick="copyCode(this)">Copiar</button> <pre><code class="language-json">{ "mcpServers": { "personal-mcp-server": { "command": "python", "args": ["/caminho/para/seu/main.py"], "env": { "GOOGLE_CLIENT_ID": "seu_client_id", "GOOGLE_CLIENT_SECRET": "seu_client_secret", "ALLOWED_PATHS": "/home/usuario/Documentos,/home/usuario/Desktop" } } } }</code></pre> </div> </div> <h2 class="mb-16" style="margin-top: var(--space-32);">Ferramentas Disponiveis</h2> <div id="toolsDocumentation"></div> </section> <section id="extensions" class="section"> <div class="mb-32"> <h1>Sistema de Extensibilidade</h1> <p style="color: var(--color-text-secondary); font-size: 1.125rem;">Como criar e adicionar novos modulos ao servidor</p> </div> <div class="card mb-24"> <h3 class="mb-16">Template Basico de Modulo</h3> <div class="code-block"> <button class="copy-btn" onclick="copyCode(this)">Copiar</button> <pre><code class="language-python">import asyncio from mcp import mcp from typing import Optional @mcp.tool() async def minha_ferramenta( parametro1: str, parametro2: Optional[str] = None ) -> str: """Descricao da sua ferramenta. Args: parametro1: Descricao do primeiro parametro parametro2: Descricao do segundo parametro (opcional) Returns: Resultado da operacao Raises: ValueError: Quando os parametros sao invalidos """ try: # Sua logica aqui resultado = f"Processando {parametro1}" if parametro2: resultado += f" com {parametro2}" return resultado except Exception as e: raise ValueError(f"Erro ao processar: {str(e)}")</code></pre> </div> </div> <div class="card mb-24"> <h3 class="mb-16">Guia de Estilo de Codigo</h3> <div class="grid"> <div> <h4 style="color: var(--color-primary); margin-bottom: 12px;">Convencoes de Nomenclatura</h4> <ul style="list-style-type: disc; padding-left: 20px;"> <li>Use snake_case para funcoes e variaveis</li> <li>Use PascalCase para classes</li> <li>Prefixe metodos privados com underscore</li> <li>Use nomes descritivos e claros</li> </ul> </div> <div> <h4 style="color: var(--color-primary); margin-bottom: 12px;">Documentacao</h4> <ul style="list-style-type: disc; padding-left: 20px;"> <li>Todas as funcoes devem ter docstrings</li> <li>Use type hints em todos os parametros</li> <li>Documente excecoes que podem ser levantadas</li> <li>Inclua exemplos de uso quando necessario</li> </ul> </div> </div> </div> <div class="card"> <h3 class="mb-16">Como Adicionar um Novo Modulo</h3> <ol style="list-style-type: decimal; padding-left: 20px;"> <li style="margin-bottom: 8px;">Crie um novo arquivo Python na pasta <code>modules/</code></li> <li style="margin-bottom: 8px;">Implemente suas ferramentas usando o decorador <code>@mcp.tool()</code></li> <li style="margin-bottom: 8px;">Adicione tratamento de erros apropriado</li> <li style="margin-bottom: 8px;">Documente todas as funcoes com docstrings</li> <li style="margin-bottom: 8px;">Importe o modulo no arquivo <code>main.py</code></li> <li style="margin-bottom: 8px;">Teste o modulo antes de usar em producao</li> </ol> </div> </section> <section id="logs" class="section"> <div class="mb-32"> <h1>Logs &amp; Debug</h1> <p style="color: var(--color-text-secondary); font-size: 1.125rem;">Monitoramento e solucao de problemas</p> </div> <div class="card mb-24"> <div class="flex flex-between flex-center mb-16"> <h3>Logs em Tempo Real</h3> <button class="btn btn-sm btn-secondary" onclick="clearLogs()">Limpar Logs</button> </div> <div id="logOutput" class="log-output"> <div style="color: var(--color-success);">2024-01-15 10:30:15 - INFO - MCP Server iniciado na porta 3000</div> <div style="color: var(--color-primary);">2024-01-15 10:30:16 - INFO - Modulo Google Calendar carregado</div> <div style="color: var(--color-primary);">2024-01-15 10:30:17 - INFO - Modulo File System carregado</div> <div style="color: var(--color-success);">2024-01-15 10:30:18 - INFO - Servidor pronto para conexoes</div> <div style="color: var(--color-warning);">2024-01-15 10:35:22 - WARN - Tentativa de acesso a arquivo fora do diretorio permitido</div> <div style="color: var(--color-success);">2024-01-15 10:40:33 - INFO - Evento criado no Google Calendar: "Reuniao com cliente"</div> </div> </div> <div class="card mb-24"> <h3 class="mb-16">Status das Conexoes</h3> <div class="grid-small"> <div style="padding: 12px; background: rgba(34, 197, 94, 0.08); border-radius: 8px;"> <div style="font-weight: 500;">Google Calendar API</div> <div class="status status-success" style="margin-top: 8px;">✓ Conectado</div> </div> <div style="padding: 12px; background: rgba(59, 130, 246, 0.08); border-radius: 8px;"> <div style="font-weight: 500;">File System Access</div> <div class="status status-success" style="margin-top: 8px;">✓ Ativo</div> </div> <div style="padding: 12px; background: rgba(239, 68, 68, 0.08); border-radius: 8px;"> <div style="font-weight: 500;">Task Manager</div> <div class="status status-warning" style="margin-top: 8px;">⚠ Planejado</div> </div> </div> </div> <div class="card"> <h3 class="mb-16">Solucao de Problemas</h3> <div id="troubleshootingList"></div> </div> </section> </main> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script> <script> // Application data const appData = { modules: [ { name: "Google Calendar", description: "Integracao com Google Calendar para gerenciar eventos", status: "available", tools: ["create_event", "list_events", "update_event", "delete_event", "search_events"] }, { name: "File System", description: "Acesso seguro ao sistema de arquivos local", status: "available", tools: ["read_file", "write_file", "list_directory", "search_files", "delete_file"] }, { name: "Tasks/Notes", description: "Sistema simples de tarefas e notas", status: "planned", tools: ["create_task", "list_tasks", "complete_task"] }, { name: "Web Scraping", description: "Extracao de dados de websites", status: "planned", tools: ["scrape_url", "extract_content"] } ], troubleshooting: [ { issue: "Servidor nao conecta", solution: "Verifique se a porta esta livre e as credenciais estao corretas" }, { issue: "Claude nao reconhece ferramentas", solution: "Reinicie o Claude Desktop apos alterar a configuracao" }, { issue: "Erro de permissao de arquivo", solution: "Verifique se o diretorio esta na lista de paths permitidos" } ] }; // Navigation functionality const navItems = document.querySelectorAll('.nav-item'); const sections = document.querySelectorAll('.section'); navItems.forEach(item => { item.addEventListener('click', () => { const targetSection = item.dataset.section; // Update navigation navItems.forEach(nav => nav.classList.remove('active')); item.classList.add('active'); // Update sections sections.forEach(section => { section.classList.remove('active'); }); document.getElementById(targetSection).classList.add('active'); // Close mobile menu if open document.getElementById('sidebar').classList.remove('mobile-open'); }); }); // Mobile menu toggle const mobileMenuBtn = document.getElementById('mobileMenuBtn'); const sidebar = document.getElementById('sidebar'); if (mobileMenuBtn) { mobileMenuBtn.addEventListener('click', () => { sidebar.classList.toggle('mobile-open'); }); } // Theme toggle const themeToggle = document.getElementById('themeToggle'); let isDark = window.matchMedia('(prefers-color-scheme: dark)').matches; themeToggle.addEventListener('click', () => { isDark = !isDark; document.documentElement.setAttribute('data-color-scheme', isDark ? 'dark' : 'light'); // Update theme toggle icon const icon = isDark ? '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>' : '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>'; themeToggle.innerHTML = icon; }); // Load modules in dashboard function loadModules() { const modulesList = document.getElementById('modulesList'); modulesList.innerHTML = ''; appData.modules.forEach(module => { const statusClass = module.status === 'available' ? 'status-success' : 'status-warning'; const statusText = module.status === 'available' ? '✓ Disponivel' : '⏳ Planejado'; const moduleCard = document.createElement('div'); moduleCard.className = 'card'; moduleCard.innerHTML = ` <div class="module-header"> <h3 style="margin: 0;">${module.name}</h3> <div class="status ${statusClass}">${statusText}</div> </div> <p style="color: var(--color-text-secondary); margin-bottom: 12px;">${module.description}</p> <div class="module-tools"> ${module.tools.map(tool => `<span class="tool-tag">${tool}</span>`).join('')} </div> `; modulesList.appendChild(moduleCard); }); } // Load tools documentation function loadToolsDocumentation() { const toolsDoc = document.getElementById('toolsDocumentation'); toolsDoc.innerHTML = ''; appData.modules.filter(m => m.status === 'available').forEach(module => { const moduleDoc = document.createElement('div'); moduleDoc.className = 'card'; moduleDoc.style.marginBottom = '16px'; const toolsList = module.tools.map(tool => { return `<li><code>${tool}</code> - ${getToolDescription(tool)}</li>`; }).join(''); moduleDoc.innerHTML = ` <h3 style="margin-bottom: 12px;">${module.name}</h3> <p style="margin-bottom: 16px; color: var(--color-text-secondary);">${module.description}</p> <h4 style="margin-bottom: 8px;">Ferramentas Disponiveis:</h4> <ul style="list-style-type: disc; padding-left: 20px;"> ${toolsList} </ul> `; toolsDoc.appendChild(moduleDoc); }); } // Helper function to get tool descriptions function getToolDescription(toolName) { const descriptions = { 'create_event': 'Criar um novo evento no calendario', 'list_events': 'Listar eventos existentes', 'update_event': 'Atualizar um evento existente', 'delete_event': 'Remover um evento do calendario', 'search_events': 'Buscar eventos especificos', 'read_file': 'Ler conteudo de um arquivo', 'write_file': 'Escrever conteudo em um arquivo', 'list_directory': 'Listar arquivos de um diretorio', 'search_files': 'Buscar arquivos por nome ou conteudo', 'delete_file': 'Remover um arquivo do sistema', 'create_task': 'Criar uma nova tarefa', 'list_tasks': 'Listar tarefas existentes', 'complete_task': 'Marcar uma tarefa como concluida' }; return descriptions[toolName] || 'Descricao nao disponivel'; } // Load troubleshooting list function loadTroubleshooting() { const troubleshootingList = document.getElementById('troubleshootingList'); troubleshootingList.innerHTML = ''; appData.troubleshooting.forEach(item => { const troubleshootItem = document.createElement('div'); troubleshootItem.className = 'troubleshoot-item'; troubleshootItem.innerHTML = ` <div class="troubleshoot-issue">❓ ${item.issue}</div> <div style="color: var(--color-text-secondary);">💡 ${item.solution}</div> `; troubleshootingList.appendChild(troubleshootItem); }); } // Generate configuration document.getElementById('generateConfig').addEventListener('click', () => { const clientId = document.getElementById('googleClientId').value; const clientSecret = document.getElementById('googleClientSecret').value; const allowedPaths = document.getElementById('allowedPaths').value; const serverPort = document.getElementById('serverPort').value; const logLevel = document.getElementById('logLevel').value; const config = { "mcpServers": { "personal-mcp-server": { "command": "python", "args": ["/caminho/para/seu/main.py"], "env": { "GOOGLE_CLIENT_ID": clientId || "seu_client_id", "GOOGLE_CLIENT_SECRET": clientSecret || "seu_client_secret", "ALLOWED_PATHS": allowedPaths || "/home/usuario/Documentos,/home/usuario/Desktop", "SERVER_PORT": serverPort, "LOG_LEVEL": logLevel } } } }; const configOutput = document.getElementById('configOutput'); const generatedConfig = document.getElementById('generatedConfig'); configOutput.textContent = JSON.stringify(config, null, 2); generatedConfig.classList.remove('hidden'); // Trigger syntax highlighting if (window.Prism) { Prism.highlightElement(configOutput); } }); // Copy functionality function copyConfig() { const configOutput = document.getElementById('configOutput'); navigator.clipboard.writeText(configOutput.textContent).then(() => { showCopyFeedback(document.querySelector('#generatedConfig .copy-btn')); }); } function copyCode(button) { const codeBlock = button.nextElementSibling; const code = codeBlock.textContent || codeBlock.innerText; navigator.clipboard.writeText(code).then(() => { showCopyFeedback(button); }); } function showCopyFeedback(button) { const originalText = button.textContent; const originalBg = button.style.background; const originalColor = button.style.color; button.textContent = 'Copiado!'; button.style.background = 'var(--color-success)'; button.style.color = 'white'; setTimeout(() => { button.textContent = originalText; button.style.background = originalBg; button.style.color = originalColor; }, 2000); } // Clear logs function function clearLogs() { const logOutput = document.getElementById('logOutput'); logOutput.innerHTML = '<div style="color: var(--color-primary);">Logs limpos - aguardando novos eventos...</div>'; } // Simulate real-time logs (for demo purposes) function simulateLogs() { const logOutput = document.getElementById('logOutput'); const logMessages = [ { type: 'info', message: 'Verificando conexao com Google Calendar...' }, { type: 'success', message: 'Conexao estabelecida com sucesso' }, { type: 'info', message: 'Cliente Claude Desktop conectado' }, { type: 'warning', message: 'Rate limit da API proximo do limite' }, { type: 'success', message: 'Arquivo lido com sucesso: documento.txt' } ]; const colors = { info: 'var(--color-primary)', success: 'var(--color-success)', warning: 'var(--color-warning)', error: 'var(--color-error)' }; setInterval(() => { if (document.getElementById('logs').classList.contains('active')) { const randomLog = logMessages[Math.floor(Math.random() * logMessages.length)]; const timestamp = new Date().toLocaleString('pt-BR'); const logEntry = document.createElement('div'); logEntry.style.color = colors[randomLog.type]; logEntry.textContent = `${timestamp} - ${randomLog.type.toUpperCase()} - ${randomLog.message}`; logOutput.appendChild(logEntry); logOutput.scrollTop = logOutput.scrollHeight; // Keep only last 50 log entries while (logOutput.children.length > 50) { logOutput.removeChild(logOutput.firstChild); } } }, 5000); // Add a new log every 5 seconds } // Initialize app document.addEventListener('DOMContentLoaded', () => { loadModules(); loadToolsDocumentation(); loadTroubleshooting(); simulateLogs(); // Initialize syntax highlighting if (window.Prism) { Prism.highlightAll(); } }); // Handle responsive design function handleResize() { const mobileMenuBtn = document.getElementById('mobileMenuBtn'); if (window.innerWidth <= 768) { mobileMenuBtn.style.display = 'block'; } else { mobileMenuBtn.style.display = 'none'; document.getElementById('sidebar').classList.remove('mobile-open'); } } window.addEventListener('resize', handleResize); handleResize(); // Call on initial load </script> </body> </html>

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pablicio/my-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server