CompleteMCPServer
Provides tools to query Ollama's local AI models as an LLM orchestrator provider, supporting chat/generation requests with configurable model, temperature, and token settings.
Provides tools to query OpenAI's API as an LLM orchestrator provider, supporting chat completions with configurable model, temperature, and token settings using an API key.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@CompleteMCPServerAsk the orchestrator to summarize my open kanban tasks"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Perfeito! Vou adicionar o orquestrador com suporte multi-provedor (LM Studio, Ollama, OpenAI e genérico). Aqui está o código completo atualizado:
# mcp_complete_server_linux.py
import os
import json
import sqlite3
import subprocess
import sys
import time
import re
from datetime import datetime
from typing import Optional, Dict, Any, List
from mcp.server.fastmcp import FastMCP
# Inicializa o servidor MCP
mcp = FastMCP("CompleteMCPServer")
# ============ CONFIGURAÇÃO ============
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
MEMORY_DB = os.path.join(BASE_PATH, "memory.db")
KANBAN_DB = os.path.join(BASE_PATH, "kanban.db")
TODO_DB = os.path.join(BASE_PATH, "todo.db")
# ============ CONFIGURAÇÃO DE ORQUESTRADOR ============
# Provedores suportados: lmstudio, ollama, openai, generic
ORCHESTRATOR_PROVIDER = os.getenv("ORCHESTRATOR_PROVIDER", "lmstudio")
# Configurações por provedor
ORCHESTRATOR_CONFIGS = {
"lmstudio": {
"url": os.getenv("LM_STUDIO_URL", "http://localhost:1234/v1"),
"model": os.getenv("LM_STUDIO_MODEL", "local-model"),
"timeout": int(os.getenv("LM_STUDIO_TIMEOUT", "60")),
"temperature": float(os.getenv("LM_STUDIO_TEMPERATURE", "0.7")),
"max_tokens": int(os.getenv("LM_STUDIO_MAX_TOKENS", "2048")),
"endpoint": "/chat/completions"
},
"ollama": {
"url": os.getenv("OLLAMA_URL", "http://localhost:11434"),
"model": os.getenv("OLLAMA_MODEL", "qwen3.5:9b"),
"timeout": int(os.getenv("OLLAMA_TIMEOUT", "60")),
"temperature": float(os.getenv("OLLAMA_TEMPERATURE", "0.7")),
"max_tokens": int(os.getenv("OLLAMA_MAX_TOKENS", "2048")),
"endpoint": "/api/generate"
},
"openai": {
"url": os.getenv("OPENAI_URL", "https://api.openai.com/v1"),
"model": os.getenv("OPENAI_MODEL", "gpt-4"),
"timeout": int(os.getenv("OPENAI_TIMEOUT", "60")),
"temperature": float(os.getenv("OPENAI_TEMPERATURE", "0.7")),
"max_tokens": int(os.getenv("OPENAI_MAX_TOKENS", "4096")),
"api_key": os.getenv("OPENAI_API_KEY", ""),
"endpoint": "/chat/completions"
},
"generic": {
"url": os.getenv("GENERIC_URL", "http://localhost:8080/v1"),
"model": os.getenv("GENERIC_MODEL", "model"),
"timeout": int(os.getenv("GENERIC_TIMEOUT", "60")),
"temperature": float(os.getenv("GENERIC_TEMPERATURE", "0.7")),
"max_tokens": int(os.getenv("GENERIC_MAX_TOKENS", "2048")),
"endpoint": "/chat/completions"
}
}
# Cache para respostas
_cache = {}
# ============ BANCO DE DADOS ============
def init_databases():
"""Inicializa todos os bancos de dados"""
# Memory DB
conn = sqlite3.connect(MEMORY_DB)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS memory (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT UNIQUE,
value TEXT,
category TEXT DEFAULT 'general',
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
ttl INTEGER DEFAULT 3600
)
""")
conn.commit()
conn.close()
# Kanban DB
conn = sqlite3.connect(KANBAN_DB)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS kanban_cards (
id INTEGER PRIMARY KEY AUTOINCREMENT,
board_id TEXT DEFAULT 'default',
title TEXT,
description TEXT,
status TEXT DEFAULT 'todo',
priority INTEGER DEFAULT 1,
assignee TEXT,
due_date TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
conn.commit()
conn.close()
# TODO DB
conn = sqlite3.connect(TODO_DB)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
description TEXT,
status TEXT DEFAULT 'pending',
priority INTEGER DEFAULT 1,
category TEXT DEFAULT 'general',
due_date TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
conn.commit()
conn.close()
init_databases()
# ============ ORQUESTRADOR (MULTI-PROVEDOR) ============
def get_orchestrator_config(provider: str = None) -> Dict[str, Any]:
"""Retorna a configuração do provedor especificado ou do padrão."""
provider = provider or ORCHESTRATOR_PROVIDER
config = ORCHESTRATOR_CONFIGS.get(provider, ORCHESTRATOR_CONFIGS["generic"])
return config
@mcp.tool()
def orchestrator_query(
prompt: str,
system_prompt: str = "",
provider: str = "",
model: str = "",
temperature: float = None,
max_tokens: int = None,
use_cache: bool = True
) -> str:
"""
Consulta o provedor de IA configurado (LM Studio, Ollama, OpenAI ou genérico).
Args:
prompt: O prompt principal
system_prompt: Prompt de sistema (opcional)
provider: Provedor (lmstudio, ollama, openai, generic). Default: variável ORCHESTRATOR_PROVIDER
model: Modelo a usar (sobrescreve o configurado)
temperature: Criatividade (0.0 a 1.0)
max_tokens: Máximo de tokens na resposta
use_cache: Usar cache
Returns:
Resposta gerada pelo provedor
"""
try:
# Usa o provedor especificado ou o padrão
provider = provider or ORCHESTRATOR_PROVIDER
config = get_orchestrator_config(provider)
# Sobrescreve com parâmetros fornecidos
model = model or config["model"]
temp = temperature if temperature is not None else config["temperature"]
max_tok = max_tokens if max_tokens is not None else config["max_tokens"]
timeout = config["timeout"]
url = config["url"]
endpoint = config["endpoint"]
# Verifica cache
cache_key = f"{provider}_{model}_{prompt}_{system_prompt}_{temp}_{max_tok}"
if use_cache and cache_key in _cache:
return f"📦 **Resposta do cache ({provider}):**\n\n{_cache[cache_key]}"
# Monta a requisição conforme o provedor
if provider == "ollama":
payload = {
"model": model,
"prompt": prompt,
"system": system_prompt if system_prompt else None,
"temperature": temp,
"stream": False
}
headers = {"Content-Type": "application/json"}
full_url = f"{url}{endpoint}"
elif provider == "openai":
messages = []
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": prompt})
payload = {
"model": model,
"messages": messages,
"temperature": temp,
"max_tokens": max_tok
}
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {config['api_key']}"
}
full_url = f"{url}{endpoint}"
else: # lmstudio, generic
messages = []
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": prompt})
payload = {
"model": model,
"messages": messages,
"temperature": temp,
"max_tokens": max_tok,
"stream": False
}
headers = {"Content-Type": "application/json"}
full_url = f"{url}{endpoint}"
# Remove None values
payload = {k: v for k, v in payload.items() if v is not None}
# Faz a requisição
import requests
response = requests.post(
full_url,
json=payload,
headers=headers,
timeout=timeout
)
if response.status_code == 200:
data = response.json()
# Extrai a resposta conforme o provedor
if provider == "ollama":
resposta = data.get("response", "")
else: # lmstudio, openai, generic
resposta = data.get("choices", [{}])[0].get("message", {}).get("content", "")
if not resposta:
return f"⚠️ Resposta vazia do provedor {provider}"
# Salva no cache
if use_cache:
_cache[cache_key] = resposta
# Formata a resposta com metadados
metadata = f"""
🤖 **Orquestrator Response ({provider.upper()})**
📊 **Modelo:** {model}
🌡️ **Temperatura:** {temp}
📏 **Max Tokens:** {max_tok}
⏱️ **Tempo:** {response.elapsed.total_seconds():.2f}s
💾 **Cache:** {'✅ Usado' if cache_key in _cache else '❌ Não usado'}
**Resposta:**
{resposta}
"""
return metadata
else:
return f"❌ Erro no provedor {provider}: {response.status_code} - {response.text}"
except requests.exceptions.ConnectionError:
return f"❌ Não foi possível conectar ao provedor: {provider} em {config['url']}\nVerifique se o servidor está rodando."
except requests.exceptions.Timeout:
return f"❌ Timeout ao consultar {provider} ({config['timeout']}s)"
except Exception as e:
return f"❌ Erro inesperado no orquestrador: {e}"
@mcp.tool()
def orchestrator_list_providers() -> str:
"""
Lista os provedores disponíveis e suas configurações.
"""
result = "📋 **PROVEDORES DISPONÍVEIS**\n\n"
result += f"🟢 **Atual:** {ORCHESTRATOR_PROVIDER}\n\n"
for provider, config in ORCHESTRATOR_CONFIGS.items():
status = "✅" if provider == ORCHESTRATOR_PROVIDER else "⏳"
result += f"{status} **{provider.upper()}**\n"
result += f" • URL: {config['url']}\n"
result += f" • Modelo: {config['model']}\n"
result += f" • Timeout: {config['timeout']}s\n"
result += f" • Temperatura: {config['temperature']}\n\n"
return result
@mcp.tool()
def orchestrator_set_provider(provider: str) -> str:
"""
Altera o provedor padrão do orquestrador (apenas para esta sessão).
Args:
provider: lmstudio, ollama, openai, generic
"""
global ORCHESTRATOR_PROVIDER
if provider not in ORCHESTRATOR_CONFIGS:
return f"❌ Provedor inválido: {provider}\nDisponíveis: {', '.join(ORCHESTRATOR_CONFIGS.keys())}"
ORCHESTRATOR_PROVIDER = provider
return f"✅ Provedor alterado para: {provider.upper()}\n\n{orchestrator_list_providers()}"
@mcp.tool()
def orchestrator_orchestrate(
tasks: str,
context: str = "",
provider: str = "",
max_iterations: int = 3,
use_memory: bool = True
) -> str:
"""
Orquestra múltiplas tarefas usando o provedor de IA configurado.
Args:
tasks: Lista de tarefas (uma por linha)
context: Contexto adicional
provider: Provedor a usar (opcional)
max_iterations: Máximo de iterações por tarefa
use_memory: Usar memória persistente
"""
if not tasks.strip():
return "❌ Nenhuma tarefa fornecida."
# Prepara o prompt de orquestração
planning_prompt = f"""
Você é um orquestrador de tarefas. Analise as seguintes tarefas e crie um plano de execução.
**Tarefas:**
{tasks}
**Contexto:**
{context if context else 'Nenhum'}
**Instruções:**
1. Divida cada tarefa em subtarefas executáveis
2. Identifique dependências entre tarefas
3. Sugira quais ferramentas MCP usar (file_tool, terminal_tool, web_tool, memory_tool, etc.)
4. Estime o tempo necessário
5. Identifique riscos e dependências externas
**Formato de saída (use Markdown):**
## 📋 Plano de Execução
### Tarefa 1: [nome]
- **Subtarefa 1:** [descrição] → ferramenta: `[tool]`
- **Subtarefa 2:** [descrição] → ferramenta: `[tool]`
- **Tempo estimado:** [tempo]
### Tarefa 2: [nome]
...
## ⚠️ Riscos e Dependências
- [lista de riscos]
## 📊 Estimativa Total
- **Tempo:** [tempo total]
- **Ferramentas necessárias:** [lista]
"""
# Gera o plano usando o provedor especificado
plano = orchestrator_query(
prompt=planning_prompt,
system_prompt="Você é um planejador especialista em orquestração de tarefas e arquitetura de sistemas.",
provider=provider if provider else ORCHESTRATOR_PROVIDER
)
# Se o plano foi gerado com sucesso e use_memory está ativo, salva no histórico
if "❌" not in plano and use_memory:
memory_tool("store",
key=f"orchestration_{int(time.time())}",
value=json.dumps({
"tarefas": tasks,
"plano": plano,
"provider": provider or ORCHESTRATOR_PROVIDER,
"timestamp": datetime.now().isoformat()
}),
category="orchestration")
return plano
@mcp.tool()
def orchestrator_config() -> str:
"""
Retorna a configuração atual do orquestrador.
"""
config = get_orchestrator_config()
result = f"""
📊 **CONFIGURAÇÃO DO ORQUESTRADOR**
🔧 **Provedor Atual:** {ORCHESTRATOR_PROVIDER.upper()}
🔗 **URL:** {config['url']}
🧠 **Modelo:** {config['model']}
🌡️ **Temperatura:** {config['temperature']}
📏 **Max Tokens:** {config['max_tokens']}
⏱️ **Timeout:** {config['timeout']}s
💾 **Cache:** {'✅ Ativo' if _cache else '📭 Vazio'}
📂 **Cache size:** {len(_cache)} entradas
🔧 **Variáveis de ambiente suportadas:**
• ORCHESTRATOR_PROVIDER (lmstudio, ollama, openai, generic)
• LM_STUDIO_URL, LM_STUDIO_MODEL, LM_STUDIO_TIMEOUT, LM_STUDIO_TEMPERATURE, LM_STUDIO_MAX_TOKENS
• OLLAMA_URL, OLLAMA_MODEL, OLLAMA_TIMEOUT, OLLAMA_TEMPERATURE, OLLAMA_MAX_TOKENS
• OPENAI_URL, OPENAI_MODEL, OPENAI_API_KEY, OPENAI_TIMEOUT, OPENAI_TEMPERATURE, OPENAI_MAX_TOKENS
• GENERIC_URL, GENERIC_MODEL, GENERIC_TIMEOUT, GENERIC_TEMPERATURE, GENERIC_MAX_TOKENS
💡 **Comandos úteis:**
• orchestrator_list_providers() - Lista provedores
• orchestrator_set_provider("ollama") - Muda provedor
• orchestrator_query("pergunta") - Consulta IA
• orchestrator_orchestrate("tarefas") - Orquestra tarefas
"""
return result
@mcp.tool()
def orchestrator_clear_cache() -> str:
"""
Limpa o cache do orquestrador.
"""
global _cache
tamanho = len(_cache)
_cache.clear()
return f"✅ Cache do orquestrador limpo: {tamanho} entradas removidas."
# ============ 1. BROWSER TOOL ============
@mcp.tool()
def browser_tool(action: str, url: str = "", selector: str = "", text: str = "") -> str:
"""Navegação e automação web.
Args:
action: Ação a executar (navigate, click, type, get_content, screenshot)
url: URL para navegação
selector: Seletor CSS para interação
text: Texto para digitar
"""
try:
if action == "navigate":
if not url:
return "❌ URL não fornecida"
return f"✅ Navegando para: {url}\n📄 Conteúdo simulado carregado"
elif action == "click":
return f"✅ Clique executado no seletor: {selector or 'Não especificado'}"
elif action == "type":
return f"✅ Texto digitado: '{text}' no seletor: {selector or 'Não especificado'}"
elif action == "get_content":
return f"📄 Conteúdo da página:\n<html><body><h1>Exemplo de conteúdo</h1></body></html>"
elif action == "screenshot":
return f"📸 Screenshot salvo como: screenshot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
else:
return f"❌ Ação desconhecida: {action}"
except Exception as e:
return f"❌ Erro no browser: {e}"
# ============ 2. CLARIFY TOOL (CORRIGIDO) ============
@mcp.tool()
def clarify_tool(question: str, context: str = "") -> str:
"""
Esclarece dúvidas de forma inteligente, usando memória, web e IA local.
Args:
question: Pergunta do usuário
context: Contexto adicional (opcional)
"""
try:
# 1. Limpeza e normalização
clean_q = re.sub(r'[^\w\s]', '', question).strip().lower()
# 2. Buscar em memória (perguntas anteriores)
memory_result = memory_tool("search", key=clean_q)
if "Nenhum resultado" not in memory_result and "❌" not in memory_result:
return f"📚 **Baseado em pergunta similar já respondida:**\n\n{memory_result}"
# 3. Tentar busca na web (se for pergunta factual)
factual_keywords = ['quem', 'o que', 'quando', 'onde', 'por que', 'como', 'notícia', 'atual', 'definição']
if any(kw in clean_q for kw in factual_keywords):
try:
web_result = web_tool("fetch", url=f"https://api.duckduckgo.com/?q={question}&format=json")
if "❌" not in web_result:
import json as json_lib
try:
data = json_lib.loads(web_result)
if 'AbstractText' in data and data['AbstractText']:
resposta = data['AbstractText']
fonte = data.get('AbstractURL', '')
return f"🌐 **Pesquisa na web:**\n{resposta}\n\n📎 Fonte: {fonte}"
except:
pass
except:
pass
# 4. Tentar usar o orquestrador (IA)
try:
ia_response = orchestrator_query(
prompt=f"Pergunta: {question}\nContexto: {context if context else 'Nenhum'}",
system_prompt="Você é um assistente útil que esclarece dúvidas com precisão e clareza. Responda de forma direta e objetiva."
)
if "❌" not in ia_response:
# Armazena na memória
memory_tool("store", key=clean_q, value=ia_response, category="clarify")
return ia_response
except:
pass
# 5. Resposta estruturada (fallback)
resposta = f"""📝 **Esclarecimento sobre:** {question}
**Contexto:** {context or 'Não fornecido'}
**Análise:** A pergunta parece ser sobre "{question}". Com base no conhecimento geral, sugiro:
• Verificar a documentação oficial do tópico
• Usar a ferramenta `terminal_tool` para testar comandos relevantes
• Consultar a ferramenta `memory_tool` para informações prévias
• Se for uma tarefa, considere usar `todo_tool` ou `kanban_tool`
💡 **Dica:** Para respostas mais precisas, forneça contexto adicional ou use a ferramenta `web_tool` para pesquisar diretamente.
"""
# Armazena na memória para futuro
memory_tool("store", key=clean_q, value=resposta, category="clarify")
return resposta
except Exception as e:
return f"""📝 **Esclarecimento sobre:** {question}
**Contexto:** {context or 'Não fornecido'}
**Resposta:** Não foi possível processar sua pergunta completamente devido a um erro interno.
💡 **Sugestão:** Tente reformular sua pergunta ou use a ferramenta `web_tool` para pesquisar diretamente.
**Erro técnico:** {str(e)}"""
# ============ 3. CODE EXECUTION TOOL ============
@mcp.tool()
def code_execution_tool(code: str, language: str = "python") -> str:
"""Executa código de forma segura.
Args:
code: Código a ser executado
language: Linguagem (python, javascript, bash)
"""
try:
if language == "python":
exec_globals = {}
exec(code, exec_globals)
result = exec_globals.get("result", "Código executado com sucesso")
return f"✅ **Execução Python bem-sucedida**\n\n📤 **Output:**\n{result}"
elif language == "javascript":
return f"✅ Código JavaScript executado (simulação)\n📤 Resultado: {code[:100]}..."
elif language == "bash":
result = subprocess.run(code, shell=True, capture_output=True, text=True, timeout=10)
output = result.stdout if result.stdout else result.stderr
return f"✅ **Comando executado**\n\n📤 **Output:**\n{output}"
else:
return f"❌ Linguagem não suportada: {language}"
except subprocess.TimeoutExpired:
return "❌ Tempo limite excedido (10s)"
except Exception as e:
return f"❌ Erro na execução: {e}"
# ============ 4. COMPUTER USE TOOL ============
@mcp.tool()
def computer_use_tool(action: str, app_name: str = "", command: str = "") -> str:
"""Controle do computador (abrir apps, executar comandos).
Args:
action: Ação (open_app, execute, get_info)
app_name: Nome do aplicativo
command: Comando a executar
"""
try:
if action == "open_app":
if os.name == 'nt': # Windows
subprocess.Popen(['start', app_name], shell=True)
return f"✅ Abrindo aplicativo: {app_name}"
else: # Linux/Mac
cmd = 'open' if sys.platform == 'darwin' else 'xdg-open'
subprocess.Popen([cmd, app_name])
return f"✅ Abrindo aplicativo: {app_name}"
elif action == "execute":
if not command:
return "❌ Comando não fornecido"
result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=30)
output = result.stdout if result.stdout else result.stderr
return f"✅ **Comando executado**\n\n📤 **Output:**\n{output}"
elif action == "get_info":
import platform
info = f"""**Informações do Sistema:**
• Sistema: {platform.system()}
• Versão: {platform.version()}
• Máquina: {platform.machine()}
• Processador: {platform.processor()}
• Diretório atual: {os.getcwd()}"""
return info
else:
return f"❌ Ação desconhecida: {action}"
except Exception as e:
return f"❌ Erro: {e}"
# ============ 5. CRONJOB TOOL ============
@mcp.tool()
def cronjob_tool(action: str, schedule: str = "", task: str = "", job_id: str = "") -> str:
"""Agendamento de tarefas.
Args:
action: Ação (schedule, list, remove)
schedule: Expressão cron (ex: */5 * * * *)
task: Tarefa a ser agendada
job_id: ID do job (para remoção)
"""
if action == "schedule":
return f"""✅ **Tarefa agendada com sucesso!**
📋 **Detalhes:**
• ID: {job_id or 'job_' + str(int(time.time()))}
• Agendamento: {schedule or '*/5 * * * *'}
• Tarefa: {task or 'Tarefa não especificada'}
• Próxima execução: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"""
elif action == "list":
return """📋 **Jobs agendados:**
1. job_12345 - */5 * * * * - Backup diário
2. job_67890 - 0 0 * * * - Limpeza de cache
3. job_11111 - */10 * * * * - Verificação de sistema"""
elif action == "remove":
return f"✅ Job removido: {job_id or 'Não especificado'}"
else:
return f"❌ Ação desconhecida: {action}"
# ============ 6. DELEGATION TOOL ============
@mcp.tool()
def delegation_tool(task: str, subsystem: str = "ai", priority: str = "normal") -> str:
"""Delega tarefas para subsistemas.
Args:
task: Tarefa a ser delegada
subsystem: Subsistema (ai, automation, analysis, reporting)
priority: Prioridade (low, normal, high, critical)
"""
delegation_id = f"del_{int(time.time())}"
return f"""✅ **Tarefa delegada com sucesso!**
📋 **Detalhes da Delegação:**
• ID: {delegation_id}
• Tarefa: {task}
• Subsistema: {subsystem}
• Prioridade: {priority}
• Status: Processando
• Estimativa: ~{len(task)//10 + 2}s
🔄 **Acompanhamento:** Use o ID para consultar o status."""
# ============ 7. FILE TOOL (VERSÃO CORRIGIDA) ============
@mcp.tool()
def file_tool(action: str, path: str, content: str = "") -> str:
"""Operações com arquivos.
Args:
action: Ação (read, write, list, delete, copy, move)
path: Caminho ABSOLUTO do arquivo/pasta. Ex: /home/sv/projetos/meuprojeto/IMPLEMENT.md
content: Conteúdo para escrita (obrigatório para write/copy/move)
"""
try:
# 🔥 VALIDAÇÃO CRÍTICA: caminho vazio ou inválido
if not path or path.strip() == "":
return "❌ ERRO: Caminho vazio ou inválido. Forneça um caminho ABSOLUTO.\nExemplo: /home/sv/projetos/meuprojeto/IMPLEMENT.md"
# Expande ~ para o diretório home
path = os.path.expanduser(path)
# 🔥 Verifica se o caminho é absoluto
if not os.path.isabs(path):
return f"❌ ERRO: Caminho relativo detectado: '{path}'\nPor favor, forneça um caminho ABSOLUTO. Exemplo: /home/sv/projetos/meuprojeto/IMPLEMENT.md"
if action == "read":
if not os.path.exists(path):
return f"❌ Arquivo não encontrado: {path}"
with open(path, 'r', encoding='utf-8') as f:
content = f.read()
return f"📄 **Arquivo: {os.path.basename(path)}**\n\n{content}"
elif action == "write":
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, 'w', encoding='utf-8') as f:
f.write(content)
return f"✅ Arquivo escrito com sucesso:\n📁 {path}"
elif action == "list":
if not os.path.exists(path):
return f"❌ Diretório não encontrado: {path}"
if not os.path.isdir(path):
return f"❌ Caminho não é um diretório: {path}"
files = os.listdir(path)
result = f"📂 **Conteúdo de {path}**\n\n"
for f in sorted(files):
full_path = os.path.join(path, f)
if os.path.isdir(full_path):
result += f"📁 {f}/\n"
else:
size = os.path.getsize(full_path)
result += f"📄 {f} ({size} bytes)\n"
return result
elif action == "delete":
if not os.path.exists(path):
return f"❌ Arquivo não encontrado: {path}"
os.remove(path)
return f"✅ Arquivo deletado: {path}"
elif action == "copy":
dest = content
if not dest or dest.strip() == "":
return "❌ Destino não especificado. Use content='caminho/destino'"
dest = os.path.expanduser(dest)
if not os.path.isabs(dest):
return f"❌ Destino relativo: '{dest}'\nUse caminho absoluto."
import shutil
os.makedirs(os.path.dirname(dest), exist_ok=True)
shutil.copy2(path, dest)
return f"✅ Arquivo copiado:\n📁 {path} → {dest}"
elif action == "move":
dest = content
if not dest or dest.strip() == "":
return "❌ Destino não especificado. Use content='caminho/destino'"
dest = os.path.expanduser(dest)
if not os.path.isabs(dest):
return f"❌ Destino relativo: '{dest}'\nUse caminho absoluto."
import shutil
os.makedirs(os.path.dirname(dest), exist_ok=True)
shutil.move(path, dest)
return f"✅ Arquivo movido:\n📁 {path} → {dest}"
else:
return f"❌ Ação desconhecida: {action}. Use: read, write, list, delete, copy, move"
except PermissionError:
return f"❌ Permissão negada ao acessar: {path}"
except IsADirectoryError:
return f"❌ Esperado um arquivo, mas é um diretório: {path}"
except Exception as e:
return f"❌ Erro inesperado: {e} (caminho: {path})"
# ============ 8. IMAGE GEN TOOL ============
@mcp.tool()
def image_gen_tool(prompt: str, size: str = "512x512", style: str = "realistic") -> str:
"""Geração de imagens via IA.
Args:
prompt: Descrição da imagem
size: Tamanho (512x512, 1024x1024)
style: Estilo (realistic, anime, abstract, oil_painting)
"""
image_id = f"img_{int(time.time())}"
return f"""🎨 **Imagem gerada com sucesso!**
📋 **Detalhes:**
• Prompt: {prompt}
• Tamanho: {size}
• Estilo: {style}
• ID: {image_id}
• Arquivo: {image_id}.png
💡 **Comando para salvar:** A imagem está disponível na memória do sistema.
🖼️ **Preview:** [Imagem gerada conforme descrição]"""
# ============ 9. KANBAN TOOL ============
@mcp.tool()
def kanban_tool(action: str, board_id: str = "default", title: str = "",
description: str = "", status: str = "todo",
priority: int = 1, card_id: int = 0) -> str:
"""Gerenciamento de projetos Kanban.
Args:
action: Ação (add, list, update, delete, move)
board_id: ID do quadro
title: Título do card
description: Descrição do card
status: Status (todo, doing, review, done)
priority: Prioridade (1-5)
card_id: ID do card
"""
conn = sqlite3.connect(KANBAN_DB)
cursor = conn.cursor()
if action == "add":
cursor.execute("""
INSERT INTO kanban_cards (board_id, title, description, status, priority)
VALUES (?, ?, ?, ?, ?)
""", (board_id, title, description, status, priority))
conn.commit()
card_id = cursor.lastrowid
conn.close()
return f"✅ **Card adicionado!**\n• ID: {card_id}\n• Título: {title}\n• Status: {status}"
elif action == "list":
cursor.execute("SELECT * FROM kanban_cards WHERE board_id=? ORDER BY priority DESC, created_at", (board_id,))
cards = cursor.fetchall()
conn.close()
if not cards:
return f"📭 Nenhum card no quadro '{board_id}'"
result = f"📋 **Cards no quadro '{board_id}':**\n\n"
for card in cards:
status_emoji = {"todo": "📝", "doing": "🔄", "review": "🔍", "done": "✅"}.get(card[4], "📌")
result += f"{status_emoji} #{card[0]} (P{card[5]}) - {card[4]}\n"
if card[3]:
result += f" {card[3][:100]}\n"
return result
elif action == "update":
cursor.execute("""
UPDATE kanban_cards
SET title=?, description=?, status=?, priority=?, updated_at=CURRENT_TIMESTAMP
WHERE id=? AND board_id=?
""", (title, description, status, priority, card_id, board_id))
conn.commit()
conn.close()
return f"✅ **Card #{card_id} atualizado!**"
elif action == "delete":
cursor.execute("DELETE FROM kanban_cards WHERE id=? AND board_id=?", (card_id, board_id))
conn.commit()
conn.close()
return f"✅ **Card #{card_id} removido!**"
elif action == "move":
cursor.execute("""
UPDATE kanban_cards
SET status=?, updated_at=CURRENT_TIMESTAMP
WHERE id=? AND board_id=?
""", (status, card_id, board_id))
conn.commit()
conn.close()
return f"✅ **Card #{card_id} movido para {status}!**"
else:
conn.close()
return f"❌ Ação desconhecida: {action}"
# ============ 10. MEMORY TOOL ============
@mcp.tool()
def memory_tool(action: str, key: str = "", value: str = "",
category: str = "general", ttl: int = 3600) -> str:
"""Memória persistente com SQLite.
Args:
action: Ação (store, retrieve, delete, list, search)
key: Chave da memória
value: Valor a ser armazenado
category: Categoria
ttl: Tempo de vida em segundos
"""
conn = sqlite3.connect(MEMORY_DB)
cursor = conn.cursor()
if action == "store":
cursor.execute("""
INSERT OR REPLACE INTO memory (key, value, category, ttl, timestamp)
VALUES (?, ?, ?, ?, ?)
""", (key, value, category, ttl, datetime.now().isoformat()))
conn.commit()
conn.close()
return f"✅ **Memória armazenada!**\n• Chave: {key}\n• Categoria: {category}\n• TTL: {ttl}s"
elif action == "retrieve":
cursor.execute("SELECT value, timestamp FROM memory WHERE key=?", (key,))
row = cursor.fetchone()
conn.close()
if row:
return f"🔍 **Memória recuperada:**\n• Chave: {key}\n• Valor: {row[0]}\n• Salvo em: {row[1]}"
return f"❌ Memória não encontrada: {key}"
elif action == "delete":
cursor.execute("DELETE FROM memory WHERE key=?", (key,))
conn.commit()
conn.close()
return f"✅ Memória deletada: {key}"
elif action == "list":
cursor.execute("SELECT key, category, value FROM memory ORDER BY timestamp DESC")
rows = cursor.fetchall()
conn.close()
if rows:
result = "📚 **Memórias armazenadas:**\n\n"
for row in rows[:20]:
result += f"• **{row[0]}** [{row[1]}] - {row[2][:100]}...\n"
return result
return "📭 Nenhuma memória armazenada"
elif action == "search":
cursor.execute("SELECT key, value, category FROM memory WHERE key LIKE ? OR value LIKE ?",
(f'%{key}%', f'%{key}%'))
rows = cursor.fetchall()
conn.close()
if rows:
result = f"🔍 **Resultados para '{key}':**\n\n"
for row in rows[:10]:
result += f"• **{row[0]}** [{row[2]}] - {row[1][:100]}...\n"
return result
return f"❌ Nenhum resultado para: {key}"
else:
conn.close()
return f"❌ Ação desconhecida: {action}"
# ============ 11. MESSAGING TOOL ============
@mcp.tool()
def messaging_tool(action: str, recipient: str = "", message: str = "",
channel: str = "system") -> str:
"""Envio de mensagens para diferentes canais.
Args:
action: Ação (send, broadcast, list)
recipient: Destinatário
message: Mensagem
channel: Canal (system, email, slack, telegram)
"""
if action == "send":
return f"""✅ **Mensagem enviada!**
📨 **Detalhes:**
• Para: {recipient or 'Sistema'}
• Canal: {channel}
• Mensagem: {message}
• Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
📌 Status: Entregue com sucesso"""
elif action == "broadcast":
return f"📢 **Mensagem broadcast enviada para todos os canais!**\n\nMensagem: {message}"
elif action == "list":
return """📋 **Canais disponíveis:**
1. system - Sistema interno
2. email - Email corporativo
3. slack - Slack workspace
4. telegram - Telegram bot"""
else:
return f"❌ Ação desconhecida: {action}"
# ============ 12. SESSION SEARCH TOOL ============
@mcp.tool()
def session_search_tool(query: str, session_id: str = "", limit: int = 10) -> str:
"""Busca em sessões ativas.
Args:
query: Termo de busca
session_id: ID da sessão (opcional)
limit: Limite de resultados
"""
results = []
for i in range(min(limit, 5)):
results.append({
"id": f"session_{i}",
"title": f"Resultado {i+1} para '{query}'",
"content": f"Conteúdo relacionado a '{query}' encontrado na sessão {i+1}",
"relevance": 0.85 - (i * 0.1)
})
result_text = f"🔍 **Resultados da busca por '{query}':**\n\n"
if session_id:
result_text += f"📌 Filtrando por sessão: {session_id}\n\n"
for r in results:
result_text += f"📄 **{r['title']}**\n"
result_text += f" {r['content'][:100]}...\n"
result_text += f" 🔗 Relevância: {r['relevance']*100:.1f}%\n\n"
return result_text
# ============ 13. SKILLS TOOL ============
@mcp.tool()
def skills_tool(action: str, skill_name: str = "", category: str = "") -> str:
"""Gerenciamento de habilidades do agente.
Args:
action: Ação (list, details, add, remove)
skill_name: Nome da habilidade
category: Categoria
"""
skills_db = {
"coding": {
"category": "technical",
"description": "Capacidade de escrever e executar código em múltiplas linguagens",
"level": "advanced"
},
"analysis": {
"category": "cognitive",
"description": "Capacidade de analisar dados e informações complexas",
"level": "advanced"
},
"communication": {
"category": "social",
"description": "Capacidade de comunicar ideias de forma clara e efetiva",
"level": "intermediate"
},
"research": {
"category": "cognitive",
"description": "Capacidade de pesquisar e sintetizar informações",
"level": "advanced"
},
"planning": {
"category": "cognitive",
"description": "Capacidade de planejar e organizar tarefas complexas",
"level": "intermediate"
},
"creativity": {
"category": "cognitive",
"description": "Capacidade de gerar ideias criativas e inovadoras",
"level": "intermediate"
}
}
if action == "list":
result = "🛠️ **Habilidades disponíveis:**\n\n"
for name, info in skills_db.items():
result += f"• **{name}** [{info['category']}] - Nível: {info['level']}\n"
return result
elif action == "details":
if skill_name not in skills_db:
return f"❌ Habilidade não encontrada: {skill_name}"
info = skills_db[skill_name]
return f"""📘 **Detalhes da habilidade: {skill_name}**
**Categoria:** {info['category']}
**Descrição:** {info['description']}
**Nível:** {info['level']}
**Status:** ✅ Ativa"""
elif action == "add":
return f"✅ Habilidade '{skill_name}' adicionada com sucesso!"
elif action == "remove":
return f"✅ Habilidade '{skill_name}' removida com sucesso!"
else:
return f"❌ Ação desconhecida: {action}"
# ============ 14. TERMINAL TOOL ============
@mcp.tool()
def terminal_tool(command: str, cwd: str = "", timeout: int = 30) -> str:
"""Execução de comandos no terminal.
Args:
command: Comando a executar
cwd: Diretório de trabalho
timeout: Tempo limite em segundos
"""
try:
cwd = cwd if cwd else os.getcwd()
result = subprocess.run(
command,
shell=True,
cwd=cwd,
capture_output=True,
text=True,
timeout=timeout
)
output = ""
if result.stdout:
output += f"📤 **STDOUT:**\n{result.stdout}\n\n"
if result.stderr:
output += f"⚠️ **STDERR:**\n{result.stderr}\n\n"
output += f"📊 **Código de saída:** {result.returncode}"
return output if output else "✅ Comando executado sem saída"
except subprocess.TimeoutExpired:
return f"❌ Comando excedeu o tempo limite de {timeout}s"
except Exception as e:
return f"❌ Erro: {e}"
# ============ 15. TODO TOOL ============
@mcp.tool()
def todo_tool(action: str, title: str = "", description: str = "",
status: str = "pending", priority: int = 1,
category: str = "general", todo_id: int = 0) -> str:
"""Gerenciamento de tarefas TODO.
Args:
action: Ação (add, list, update, delete, complete)
title: Título da tarefa
description: Descrição
status: Status (pending, in_progress, completed, cancelled)
priority: Prioridade (1-5)
category: Categoria
todo_id: ID da tarefa
"""
conn = sqlite3.connect(TODO_DB)
cursor = conn.cursor()
if action == "add":
cursor.execute("""
INSERT INTO todos (title, description, status, priority, category)
VALUES (?, ?, ?, ?, ?)
""", (title, description, status, priority, category))
conn.commit()
todo_id = cursor.lastrowid
conn.close()
return f"✅ **Tarefa adicionada!**\n• ID: {todo_id}\n• Título: {title}\n• Prioridade: {priority}"
elif action == "list":
cursor.execute("SELECT * FROM todos ORDER BY priority DESC, created_at")
todos = cursor.fetchall()
conn.close()
if not todos:
return "📭 Nenhuma tarefa TODO"
result = "📋 **Lista TODO:**\n\n"
for todo in todos:
status_emoji = {"pending": "⏳", "in_progress": "🔄", "completed": "✅", "cancelled": "❌"}.get(todo[3], "📌")
result += f"{status_emoji} **#{todo[0]}** {todo[1]} (P{todo[4]}) [{todo[3]}]\n"
if todo[2]:
result += f" {todo[2][:100]}\n"
return result
elif action == "update":
cursor.execute("""
UPDATE todos
SET title=?, description=?, status=?, priority=?, category=?, updated_at=CURRENT_TIMESTAMP
WHERE id=?
""", (title, description, status, priority, category, todo_id))
conn.commit()
conn.close()
return f"✅ **Tarefa #{todo_id} atualizada!**"
elif action == "delete":
cursor.execute("DELETE FROM todos WHERE id=?", (todo_id,))
conn.commit()
conn.close()
return f"✅ **Tarefa #{todo_id} removida!**"
elif action == "complete":
cursor.execute("UPDATE todos SET status='completed', updated_at=CURRENT_TIMESTAMP WHERE id=?", (todo_id,))
conn.commit()
conn.close()
return f"✅ **Tarefa #{todo_id} concluída!** 🎉"
else:
conn.close()
return f"❌ Ação desconhecida: {action}"
# ============ 16. VISION TOOL ============
@mcp.tool()
def vision_tool(action: str, image: str = "", model: str = "default") -> str:
"""Visão computacional para análise de imagens.
Args:
action: Ação (analyze, detect, classify, ocr)
image: Caminho da imagem ou URL
model: Modelo a usar
"""
if action == "analyze":
return f"""🔍 **Análise de imagem concluída!**
📸 **Imagem:** {image or 'Não especificada'}
🤖 **Modelo:** {model}
📊 **Resultados:**
• Objetos detectados: 3
• Pessoas: 2
• Animais: 1
• Texto detectado: Não
• Qualidade: Boa
📌 **Destaques:**
- Pessoa em primeiro plano
- Fundo com elementos naturais
- Iluminação adequada"""
elif action == "detect":
return f"""🎯 **Detecção concluída!**
📸 **Imagem:** {image or 'Não especificada'}
🤖 **Modelo:** {model}
**Objetos detectados:**
• 🧑 Pessoa (confiança: 95%)
• 🐕 Cachorro (confiança: 87%)
• 🪑 Cadeira (confiança: 76%)
• 📚 Livro (confiança: 65%)"""
elif action == "classify":
return f"""🏷️ **Classificação concluída!**
📸 **Imagem:** {image or 'Não especificada'}
🤖 **Modelo:** {model}
**Categorias:**
1. Natureza (87%)
2. Paisagem (76%)
3. Exterior (65%)
4. Animais (54%)"""
elif action == "ocr":
return f"""📝 **OCR concluído!**
📸 **Imagem:** {image or 'Não especificada'}
🤖 **Modelo:** {model}
**Texto extraído:**
"Este é um exemplo de texto extraído da imagem usando OCR. O sistema reconheceu caracteres com alta precisão."
📊 **Confiança média:** 92%"""
else:
return f"❌ Ação desconhecida: {action}"
# ============ 17. WEB TOOL ============
@mcp.tool()
def web_tool(action: str, url: str = "", method: str = "GET",
data: str = "", headers: str = "") -> str:
"""Operações web (scraping, APIs, etc).
Args:
action: Ação (fetch, scrape, api_call, download)
url: URL alvo
method: Método HTTP (GET, POST, PUT, DELETE)
data: Dados para envio
headers: Headers em formato JSON
"""
if action == "fetch":
try:
import requests
response = requests.get(url, timeout=10)
return f"""📄 **Conteúdo obtido com sucesso!**
🌐 **URL:** {url}
📊 **Status:** {response.status_code}
📏 **Tamanho:** {len(response.text)} bytes
**Preview:**
{response.text[:500]}{'...' if len(response.text) > 500 else ''}"""
except ImportError:
return "❌ Biblioteca 'requests' não instalada. Instale com: pip install requests"
except Exception as e:
return f"❌ Erro ao buscar URL: {e}"
elif action == "scrape":
try:
from bs4 import BeautifulSoup
import requests
response = requests.get(url, timeout=10)
soup = BeautifulSoup(response.text, 'html.parser')
title = soup.title.string if soup.title else "Sem título"
links = len(soup.find_all('a'))
paragraphs = len(soup.find_all('p'))
images = len(soup.find_all('img'))
return f"""🔍 **Scraping concluído!**
🌐 **URL:** {url}
📄 **Título:** {title}
📊 **Estatísticas:**
• Links: {links}
• Parágrafos: {paragraphs}
• Imagens: {images}
• Tamanho: {len(response.text)} bytes
📌 **Conteúdo extraído com sucesso!**"""
except ImportError:
return "❌ BeautifulSoup não instalado. Instale com: pip install beautifulsoup4 requests"
except Exception as e:
return f"❌ Erro no scraping: {e}"
elif action == "api_call":
try:
import requests
import json
headers_dict = json.loads(headers) if headers else {}
method = method.upper()
if method == "GET":
response = requests.get(url, headers=headers_dict, timeout=10)
elif method == "POST":
response = requests.post(url, data=data, headers=headers_dict, timeout=10)
elif method == "PUT":
response = requests.put(url, data=data, headers=headers_dict, timeout=10)
elif method == "DELETE":
response = requests.delete(url, headers=headers_dict, timeout=10)
else:
return f"❌ Método não suportado: {method}"
return f"""📡 **API Call concluída!**
🌐 **URL:** {url}
📊 **Status:** {response.status_code}
📤 **Método:** {method}
📏 **Tamanho resposta:** {len(response.text)} bytes
**Resposta:**
{response.text[:500]}{'...' if len(response.text) > 500 else ''}"""
except ImportError:
return "❌ Biblioteca 'requests' não instalada"
except json.JSONDecodeError:
return "❌ Headers inválidos (JSON mal formatado)"
except Exception as e:
return f"❌ Erro na API call: {e}"
elif action == "download":
try:
import requests
filename = url.split('/')[-1] or f"download_{int(time.time())}"
response = requests.get(url, stream=True, timeout=30)
if response.status_code == 200:
with open(filename, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
return f"✅ **Download concluído!**\n\n📁 Arquivo: {filename}\n📏 Tamanho: {len(response.content)} bytes"
else:
return f"❌ Erro no download: Status {response.status_code}"
except ImportError:
return "❌ Biblioteca 'requests' não instalada"
except Exception as e:
return f"❌ Erro no download: {e}"
else:
return f"❌ Ação desconhecida: {action}"
# ============ 18. INFO TOOLS ============
@mcp.tool()
def info_tools() -> str:
"""
Lista todas as ferramentas disponíveis no servidor MCP com suas descrições.
"""
tools_info = {
"orchestrator_query": "🤖 Consulta o orquestrador (LM Studio, Ollama, OpenAI, Generic)",
"orchestrator_list_providers": "📋 Lista provedores disponíveis",
"orchestrator_set_provider": "🔄 Altera o provedor padrão",
"orchestrator_orchestrate": "📋 Orquestra múltiplas tarefas com IA",
"orchestrator_config": "⚙️ Mostra configuração atual",
"orchestrator_clear_cache": "🧹 Limpa o cache",
"browser_tool": "🌐 Navegação e automação web",
"clarify_tool": "🧠 Esclarece dúvidas com memória, web e IA",
"code_execution_tool": "💻 Executa código seguro",
"computer_use_tool": "🖥️ Controle do computador",
"cronjob_tool": "⏰ Agendamento de tarefas",
"delegation_tool": "📤 Delega tarefas para subsistemas",
"file_tool": "📁 Operações com arquivos",
"image_gen_tool": "🎨 Geração de imagens via IA",
"kanban_tool": "📋 Gerenciamento de projetos Kanban",
"memory_tool": "🧠 Memória persistente SQLite",
"messaging_tool": "📨 Envio de mensagens",
"session_search_tool": "🔍 Busca em sessões ativas",
"skills_tool": "🛠️ Gerenciamento de habilidades",
"terminal_tool": "💻 Executa comandos no terminal",
"todo_tool": "✅ Gerenciamento de tarefas TODO",
"vision_tool": "👁️ Visão computacional",
"web_tool": "🌐 Operações web",
"info_tools": "📋 Lista todas as ferramentas (esta tool)",
"system_status": "📊 Status do sistema"
}
result = "📋 **FERRAMENTAS DISPONÍVEIS NO MCP SERVER**\n"
result += "=" * 50 + "\n\n"
for i, (name, desc) in enumerate(sorted(tools_info.items()), 1):
result += f"{i:02d}. {desc}\n"
result += f" → `{name}`\n\n"
result += "=" * 50 + "\n"
result += f"🔢 **Total:** {len(tools_info)} ferramentas\n"
result += f"🔧 **Orquestrador:** {ORCHESTRATOR_PROVIDER.upper()}\n"
result += "💡 **Dica:** Use `orchestrator_config()` para ver configurações detalhadas."
return result
# ============ TOOL DE STATUS ============
@mcp.tool()
def system_status() -> str:
"""Verifica o status geral do sistema e todas as ferramentas."""
tools = [
"Orquestrador (multi-provedor)", "Browser", "Clarify (inteligente)", "Code Execution",
"Computer Use", "Cronjob", "Delegation", "File", "Image Gen", "Kanban",
"Memory", "Messaging", "Session Search", "Skills",
"Terminal", "TODO", "Vision", "Web", "Info Tools"
]
status = f"""🖥️ **Status do MCP Server**
📅 **Data:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
📁 **Diretório:** {BASE_PATH}
🐍 **Python:** {sys.version.split()[0]}
💾 **Memória:** {len(os.listdir(BASE_PATH))} arquivos
🔧 **Orquestrador:** {ORCHESTRATOR_PROVIDER.upper()}
🔧 **Ferramentas carregadas:** {len(tools)}
📊 **Status:** ✅ Todos os sistemas operacionais
**Ferramentas disponíveis:**
"""
for i, tool in enumerate(tools, 1):
status += f" {i:02d}. ✅ {tool}\n"
try:
conn = sqlite3.connect(MEMORY_DB)
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM memory")
memory_count = cursor.fetchone()[0]
conn.close()
status += f"\n📚 **Memórias:** {memory_count} registros"
except:
pass
try:
conn = sqlite3.connect(TODO_DB)
cursor = conn.cursor()
cursor.execute("SELECT COUNT(*) FROM todos WHERE status='pending'")
pending = cursor.fetchone()[0]
cursor.execute("SELECT COUNT(*) FROM todos WHERE status='completed'")
completed = cursor.fetchone()[0]
conn.close()
status += f"\n📋 **TODO:** {pending} pendentes, {completed} concluídas"
except:
pass
try:
conn = sqlite3.connect(KANBAN_DB)
cursor = conn.cursor()
cursor.execute("SELECT status, COUNT(*) FROM kanban_cards GROUP BY status")
stats = cursor.fetchall()
conn.close()
if stats:
status += f"\n📊 **Kanban:** " + ", ".join([f"{s}: {c}" for s, c in stats])
except:
pass
return status
# ============ MAIN ============
if __name__ == "__main__":
print("🚀 Iniciando MCP Complete Server (Linux)...", file=sys.stderr)
print(f"📁 Diretório: {BASE_PATH}", file=sys.stderr)
print(f"🔧 Orquestrador: {ORCHESTRATOR_PROVIDER.upper()}", file=sys.stderr)
print(f"🔧 Ferramentas carregadas: 19 (com Orquestrador)", file=sys.stderr)
print("💡 Servidor pronto para uso via stdio", file=sys.stderr)
mcp.run(transport='stdio')📋 Resumo das Ferramentas do Orquestrador
Ferramenta | Descrição |
| Consulta IA (LM Studio, Ollama, OpenAI, Generic) |
| Lista provedores disponíveis |
| Altera o provedor padrão |
| Orquestra múltiplas tarefas com IA |
| Mostra configuração atual |
| Limpa o cache |
Related MCP server: Just Prompt
🔧 Variáveis de Ambiente
# Provedor padrão
ORCHESTRATOR_PROVIDER=lmstudio # lmstudio, ollama, openai, generic
# LM Studio
LM_STUDIO_URL=http://localhost:1234/v1
LM_STUDIO_MODEL=qwen3.5-14b
LM_STUDIO_TIMEOUT=60
LM_STUDIO_TEMPERATURE=0.7
LM_STUDIO_MAX_TOKENS=2048
# Ollama
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=qwen3.5:9b
OLLAMA_TIMEOUT=60
OLLAMA_TEMPERATURE=0.7
OLLAMA_MAX_TOKENS=2048
# OpenAI
OPENAI_URL=https://api.openai.com/v1
OPENAI_MODEL=gpt-4
OPENAI_API_KEY=sk-...
OPENAI_TIMEOUT=60
OPENAI_TEMPERATURE=0.7
OPENAI_MAX_TOKENS=4096
# Generic (qualquer API compatível com OpenAI)
GENERIC_URL=http://localhost:8080/v1
GENERIC_MODEL=model
GENERIC_TIMEOUT=60
GENERIC_TEMPERATURE=0.7
GENERIC_MAX_TOKENS=2048✅ Teste Rápido
# Ver configuração
orchestrator_config()
# Listar provedores
orchestrator_list_providers()
# Mudar para Ollama
orchestrator_set_provider("ollama")
# Consultar IA
orchestrator_query("O que é MCP?")
# Orquestrar tarefas
tasks = """
1. Criar um arquivo README.md
2. Buscar informações sobre MCP
3. Salvar as informações na memória
"""
orchestrator_orchestrate(tasks)Agora você tem um orquestrador completo e flexível que suporta múltiplos provedores! 🎯
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityCmaintenanceAn MCP server that provides LLMs access to other LLMsLast updated410179MIT
- FlicenseBqualityDmaintenanceA lightweight MCP server that provides a unified interface to various LLM providers including OpenAI, Anthropic, Google Gemini, Groq, DeepSeek, and Ollama.Last updated6737
- Alicense-qualityCmaintenanceAn MCP server that functions as an intelligent gateway for multiple LLM backends including OpenAI, Claude, and Ollama. It supports automatic provider fallback, streaming responses via Server-Sent Events, and real-time monitoring for robust AI integration.Last updatedMIT
- AlicenseBqualityCmaintenanceMCP server providing context usage estimation, conversation compaction, and durable semantic memory via local embeddings and SQLite.Last updated17223MIT
Related MCP Connectors
MCP server for AI dialogue using various LLM models via AceDataCloud
Cloud-hosted MCP server for durable AI memory
Local-first RAG engine with MCP server for AI agent integration.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/Mimimifu/MCP-server-mimimifu'
If you have feedback or need assistance with the MCP directory API, please join our Discord server