Add files via upload
This commit is contained in:
202
GenAI/mcp/sample1/QUICKSTART.md
Normal file
202
GenAI/mcp/sample1/QUICKSTART.md
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
# Guia Rápido - Sistema MCP com Calculadora Inteligente
|
||||||
|
|
||||||
|
## 🚀 Início Rápido (3 passos)
|
||||||
|
|
||||||
|
### 1. Criar Ambiente Virtual
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd mcp_project
|
||||||
|
python3.11 -m venv venv
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Instalar Dependências
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Executar o Sistema
|
||||||
|
|
||||||
|
**Opção A - Script automatizado:**
|
||||||
|
```bash
|
||||||
|
./run.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Opção B - Comando direto:**
|
||||||
|
```bash
|
||||||
|
source venv/bin/activate
|
||||||
|
python mcp_client.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## 💬 Como Usar
|
||||||
|
|
||||||
|
O sistema **interpreta automaticamente** qual operação você deseja realizar através de linguagem natural!
|
||||||
|
|
||||||
|
### Exemplos de Perguntas
|
||||||
|
|
||||||
|
#### Soma
|
||||||
|
- "Quanto é 15 mais 7?"
|
||||||
|
- "Some 25 com 13"
|
||||||
|
- "Eu tenho 30 maçãs e ganhei mais 12, quantas tenho?"
|
||||||
|
|
||||||
|
#### Subtração
|
||||||
|
- "Subtraia 5 de 20"
|
||||||
|
- "Quanto é 50 menos 18?"
|
||||||
|
- "Se eu tinha 100 reais e gastei 35, quanto sobrou?"
|
||||||
|
|
||||||
|
#### Multiplicação
|
||||||
|
- "Multiplique 8 por 6"
|
||||||
|
- "Quanto é 7 vezes 9?"
|
||||||
|
- "Calcule 12 multiplicado por 5"
|
||||||
|
|
||||||
|
#### Divisão
|
||||||
|
- "Divida 100 por 4"
|
||||||
|
- "Quanto é 50 dividido por 2?"
|
||||||
|
- "Calcule 144 dividido por 12"
|
||||||
|
|
||||||
|
## 🎯 Funcionalidades
|
||||||
|
|
||||||
|
✅ **4 Operações**: soma, subtração, multiplicação, divisão
|
||||||
|
✅ **Linguagem Natural**: Entende perguntas conversacionais
|
||||||
|
✅ **Tratamento de Erros**: Detecta divisão por zero
|
||||||
|
✅ **Operações Não Implementadas**: Informa quando algo não está disponível
|
||||||
|
|
||||||
|
## 🧪 Testar o Sistema
|
||||||
|
|
||||||
|
Execute o teste automatizado para ver todas as funcionalidades:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source venv/bin/activate
|
||||||
|
python test_system.py
|
||||||
|
```
|
||||||
|
|
||||||
|
O teste valida:
|
||||||
|
- ✓ Soma
|
||||||
|
- ✓ Subtração
|
||||||
|
- ✓ Multiplicação
|
||||||
|
- ✓ Divisão
|
||||||
|
- ✓ Erro de divisão por zero
|
||||||
|
- ✓ Operação não implementada
|
||||||
|
- ✓ Interpretação de linguagem natural
|
||||||
|
|
||||||
|
## 📋 Exemplo de Interação Completa
|
||||||
|
|
||||||
|
```
|
||||||
|
============================================================
|
||||||
|
Chat com AI Agent - Operações Matemáticas
|
||||||
|
============================================================
|
||||||
|
|
||||||
|
✓ Conectado ao servidor MCP
|
||||||
|
✓ Ferramentas disponíveis: ['soma', 'subtracao', 'multiplicacao', 'divisao']
|
||||||
|
|
||||||
|
💬 Iniciando conversa com o assistente...
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
👤 Você: Eu tenho 25 maçãs e ganhei mais 13, quantas tenho agora?
|
||||||
|
|
||||||
|
🔧 Executando ferramenta: soma
|
||||||
|
Argumentos: {'numero1': 25, 'numero2': 13}
|
||||||
|
✓ Resultado: 38
|
||||||
|
|
||||||
|
🤖 Assistente: Você tinha 25 maçãs e ganhou mais 13, então agora tem
|
||||||
|
38 maçãs no total!
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
👤 Você: Divida 100 por 4
|
||||||
|
|
||||||
|
🔧 Executando ferramenta: divisao
|
||||||
|
Argumentos: {'numero1': 100, 'numero2': 4}
|
||||||
|
✓ Resultado: 25.0
|
||||||
|
|
||||||
|
🤖 Assistente: 100 dividido por 4 é igual a 25!
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
👤 Você: Divida 10 por 0
|
||||||
|
|
||||||
|
🔧 Executando ferramenta: divisao
|
||||||
|
Argumentos: {'numero1': 10, 'numero2': 0}
|
||||||
|
⚠️ Erro: Divisão por zero não é permitida
|
||||||
|
|
||||||
|
🤖 Assistente: Dividir por zero é uma operação matematicamente
|
||||||
|
indefinida. Não posso fazer isso, mas posso ajudar com outras contas!
|
||||||
|
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
👤 Você: Calcule 5 elevado ao quadrado
|
||||||
|
|
||||||
|
🤖 Assistente: Desculpe, mas eu só consigo fazer as operações básicas:
|
||||||
|
soma, subtração, multiplicação e divisão. Se quiser fazer 5 vezes 5,
|
||||||
|
posso ajudar!
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Comandos Úteis
|
||||||
|
|
||||||
|
### Ativar ambiente virtual
|
||||||
|
```bash
|
||||||
|
source venv/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Desativar ambiente virtual
|
||||||
|
```bash
|
||||||
|
deactivate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reinstalar dependências
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt --force-reinstall
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verificar instalação
|
||||||
|
```bash
|
||||||
|
pip list | grep -E "mcp|openai"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Executar testes
|
||||||
|
```bash
|
||||||
|
python test_system.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## ❓ Problemas Comuns
|
||||||
|
|
||||||
|
### "Command not found: python3.11"
|
||||||
|
Use `python3` ou `python` dependendo da sua instalação.
|
||||||
|
|
||||||
|
### "Permission denied: ./run.sh"
|
||||||
|
Execute: `chmod +x run.sh`
|
||||||
|
|
||||||
|
### "Module not found: mcp"
|
||||||
|
Certifique-se de ativar o ambiente virtual: `source venv/bin/activate`
|
||||||
|
|
||||||
|
### "Divisão por zero"
|
||||||
|
Este é um erro esperado e tratado. O assistente informará que não é possível.
|
||||||
|
|
||||||
|
### "Operação não implementada"
|
||||||
|
O sistema suporta apenas 4 operações básicas. O assistente informará as limitações.
|
||||||
|
|
||||||
|
## 🎓 Dicas de Uso
|
||||||
|
|
||||||
|
1. **Seja Natural**: Fale como você falaria com uma pessoa
|
||||||
|
2. **Contexto**: Pode usar contexto ("Eu tinha X e ganhei Y")
|
||||||
|
3. **Variações**: Teste diferentes formas de perguntar
|
||||||
|
4. **Erros**: O sistema trata erros educadamente
|
||||||
|
5. **Limitações**: Apenas 4 operações básicas estão disponíveis
|
||||||
|
|
||||||
|
## 📚 Documentação Completa
|
||||||
|
|
||||||
|
Para mais detalhes sobre arquitetura, API e extensões, consulte [README.md](README.md)
|
||||||
|
|
||||||
|
## 🔑 Operações Disponíveis
|
||||||
|
|
||||||
|
| Operação | Exemplos de Perguntas |
|
||||||
|
|----------|----------------------|
|
||||||
|
| **Soma** | "15 mais 7", "Some 10 com 5", "Quanto é 3 + 8?" |
|
||||||
|
| **Subtração** | "20 menos 5", "Subtraia 7 de 15", "Quanto é 30 - 12?" |
|
||||||
|
| **Multiplicação** | "8 vezes 6", "Multiplique 5 por 9", "Quanto é 7 × 4?" |
|
||||||
|
| **Divisão** | "100 dividido por 4", "Divida 50 por 2", "Quanto é 81 ÷ 9?" |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Sistema pronto para uso! Divirta-se calculando! 🧮✨**
|
||||||
@@ -1 +1,472 @@
|
|||||||
# exemplo de servidor e cliente MCP
|
# Sistema MCP com AI Agent - Calculadora Inteligente
|
||||||
|
|
||||||
|
Este projeto implementa um **servidor MCP (Model Context Protocol)** e um **cliente MCP** em Python que utiliza um LLM para interpretar operações matemáticas solicitadas pelo usuário em linguagem natural e executá-las através de tool calls.
|
||||||
|
|
||||||
|
## 📋 Visão Geral
|
||||||
|
|
||||||
|
O sistema é composto por três componentes principais:
|
||||||
|
|
||||||
|
1. **Servidor MCP** (`mcp_server.py`): Expõe 4 ferramentas matemáticas (soma, subtração, multiplicação e divisão) através do protocolo MCP
|
||||||
|
2. **Cliente MCP** (`mcp_client.py`): Interface de chat que conecta o usuário ao LLM e ao servidor MCP
|
||||||
|
3. **Script de Teste** (`test_system.py`): Testa automaticamente todas as operações e casos de erro
|
||||||
|
|
||||||
|
## 🎯 Funcionalidades Principais
|
||||||
|
|
||||||
|
### ✨ Interpretação Inteligente de Operações
|
||||||
|
|
||||||
|
O agente **interpreta automaticamente** qual operação matemática o usuário deseja realizar através de linguagem natural:
|
||||||
|
|
||||||
|
- **"Quanto é 15 mais 7?"** → Executa soma
|
||||||
|
- **"Subtraia 5 de 20"** → Executa subtração
|
||||||
|
- **"Multiplique 8 por 6"** → Executa multiplicação
|
||||||
|
- **"Divida 100 por 4"** → Executa divisão
|
||||||
|
- **"Eu tenho 25 maçãs e ganhei mais 13"** → Interpreta como soma e calcula
|
||||||
|
|
||||||
|
### 🛡️ Tratamento Robusto de Erros
|
||||||
|
|
||||||
|
- **Divisão por zero**: Detectada e tratada com mensagem educada
|
||||||
|
- **Operações não implementadas**: Informa que apenas as 4 operações básicas estão disponíveis
|
||||||
|
- **Validação de tipos**: Garante que os números sejam inteiros
|
||||||
|
- **Parâmetros faltantes**: Verifica se ambos os números foram fornecidos
|
||||||
|
|
||||||
|
### 🧮 4 Operações Matemáticas
|
||||||
|
|
||||||
|
1. **Soma** (`soma`): Adição de dois números inteiros
|
||||||
|
2. **Subtração** (`subtracao`): Subtração de dois números inteiros
|
||||||
|
3. **Multiplicação** (`multiplicacao`): Multiplicação de dois números inteiros
|
||||||
|
4. **Divisão** (`divisao`): Divisão de dois números (retorna float)
|
||||||
|
|
||||||
|
## 🏗️ Arquitetura
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────┐ ┌──────────────────┐ ┌──────────────┐
|
||||||
|
│ Usuário │ ◄─────► │ Cliente MCP │ ◄─────► │ Servidor MCP │
|
||||||
|
│ │ Chat │ + LLM │ stdio │ (4 Tools) │
|
||||||
|
│ │ │ (Interpretação) │ │ │
|
||||||
|
└─────────────┘ └──────────────────┘ └──────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────┐
|
||||||
|
│ LLM API │
|
||||||
|
│ (Grok Code) │
|
||||||
|
└──────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fluxo de Execução
|
||||||
|
|
||||||
|
1. **Usuário** envia mensagem em linguagem natural (ex: "Quanto é 15 mais 7?")
|
||||||
|
2. **Cliente MCP** envia mensagem para o LLM
|
||||||
|
3. **LLM** interpreta a operação desejada e identifica os números
|
||||||
|
4. **LLM** faz tool call para a ferramenta apropriada (ex: `soma`)
|
||||||
|
5. **Cliente MCP** executa a ferramenta no **Servidor MCP**
|
||||||
|
6. **Servidor MCP** valida parâmetros e retorna resultado ou erro
|
||||||
|
7. **Cliente MCP** envia resultado de volta ao LLM
|
||||||
|
8. **LLM** gera resposta generativa e amigável
|
||||||
|
9. **Usuário** recebe resposta final
|
||||||
|
|
||||||
|
## 🔧 Tecnologias Utilizadas
|
||||||
|
|
||||||
|
- **Python 3.11**: Linguagem de programação
|
||||||
|
- **MCP (Model Context Protocol)**: Protocolo para comunicação entre cliente e servidor
|
||||||
|
- **OpenAI SDK**: Cliente para comunicação com LLM compatível com API OpenAI
|
||||||
|
- **LLM**: Grok Code via API compatível com OpenAI
|
||||||
|
- **asyncio**: Programação assíncrona
|
||||||
|
|
||||||
|
## 📦 Estrutura do Projeto
|
||||||
|
|
||||||
|
```
|
||||||
|
mcp_project/
|
||||||
|
├── venv/ # Ambiente virtual Python
|
||||||
|
├── mcp_server.py # Servidor MCP com 4 ferramentas matemáticas
|
||||||
|
├── mcp_client.py # Cliente MCP com interpretação inteligente
|
||||||
|
├── test_system.py # Script de teste automatizado completo
|
||||||
|
├── requirements.txt # Dependências do projeto
|
||||||
|
├── run.sh # Script de inicialização rápida
|
||||||
|
├── README.md # Esta documentação
|
||||||
|
└── QUICKSTART.md # Guia rápido de início
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Instalação
|
||||||
|
|
||||||
|
### 1. Criar Ambiente Virtual
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd mcp_project
|
||||||
|
python3.11 -m venv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Instalar Dependências
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## 💻 Uso
|
||||||
|
|
||||||
|
### Modo Interativo (Chat com Usuário)
|
||||||
|
|
||||||
|
Execute o cliente MCP para iniciar uma sessão de chat interativa:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source venv/bin/activate
|
||||||
|
python mcp_client.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Ou use o script de inicialização rápida:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./run.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exemplos de Interação
|
||||||
|
|
||||||
|
#### Exemplo 1: Soma em Linguagem Natural
|
||||||
|
|
||||||
|
```
|
||||||
|
👤 Você: Eu tenho 25 maçãs e ganhei mais 13, quantas tenho agora?
|
||||||
|
|
||||||
|
🔧 Executando ferramenta: soma
|
||||||
|
Argumentos: {'numero1': 25, 'numero2': 13}
|
||||||
|
✓ Resultado: 38
|
||||||
|
|
||||||
|
🤖 Assistente: Você tinha 25 maçãs e ganhou mais 13, então agora tem 38 maçãs no total!
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Exemplo 2: Divisão
|
||||||
|
|
||||||
|
```
|
||||||
|
👤 Você: Divida 100 por 4
|
||||||
|
|
||||||
|
🔧 Executando ferramenta: divisao
|
||||||
|
Argumentos: {'numero1': 100, 'numero2': 4}
|
||||||
|
✓ Resultado: 25.0
|
||||||
|
|
||||||
|
🤖 Assistente: 100 dividido por 4 é igual a 25!
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Exemplo 3: Erro - Divisão por Zero
|
||||||
|
|
||||||
|
```
|
||||||
|
👤 Você: Divida 10 por 0
|
||||||
|
|
||||||
|
🔧 Executando ferramenta: divisao
|
||||||
|
Argumentos: {'numero1': 10, 'numero2': 0}
|
||||||
|
⚠️ Erro: Divisão por zero não é permitida
|
||||||
|
|
||||||
|
🤖 Assistente: Dividir 10 por 0 é uma operação matematicamente indefinida.
|
||||||
|
Não posso fazer isso. Mas posso ajudar com outras contas válidas!
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Exemplo 4: Operação Não Implementada
|
||||||
|
|
||||||
|
```
|
||||||
|
👤 Você: Calcule 5 elevado ao quadrado
|
||||||
|
|
||||||
|
🤖 Assistente: Desculpe, mas eu só consigo fazer as operações básicas:
|
||||||
|
soma, subtração, multiplicação e divisão. Potências não estão disponíveis.
|
||||||
|
Se quiser fazer 5 vezes 5, posso ajudar!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Modo Teste Automatizado
|
||||||
|
|
||||||
|
Execute o script de teste para validar todas as operações:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source venv/bin/activate
|
||||||
|
python test_system.py
|
||||||
|
```
|
||||||
|
|
||||||
|
O teste valida:
|
||||||
|
- ✅ Soma
|
||||||
|
- ✅ Subtração
|
||||||
|
- ✅ Multiplicação
|
||||||
|
- ✅ Divisão
|
||||||
|
- ✅ Tratamento de erro (divisão por zero)
|
||||||
|
- ✅ Operação não implementada
|
||||||
|
- ✅ Interpretação de linguagem natural
|
||||||
|
|
||||||
|
## 📝 Componentes Detalhados
|
||||||
|
|
||||||
|
### 1. Servidor MCP (`mcp_server.py`)
|
||||||
|
|
||||||
|
O servidor MCP expõe quatro ferramentas matemáticas com validação completa:
|
||||||
|
|
||||||
|
#### Ferramenta: `soma`
|
||||||
|
|
||||||
|
Realiza a soma de dois números inteiros.
|
||||||
|
|
||||||
|
**Parâmetros:**
|
||||||
|
- `numero1` (integer): Primeiro número
|
||||||
|
- `numero2` (integer): Segundo número
|
||||||
|
|
||||||
|
**Retorno de Sucesso:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"operacao": "soma",
|
||||||
|
"numero1": 15,
|
||||||
|
"numero2": 7,
|
||||||
|
"resultado": 22,
|
||||||
|
"expressao": "15 + 7 = 22"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Ferramenta: `subtracao`
|
||||||
|
|
||||||
|
Realiza a subtração de dois números inteiros (numero1 - numero2).
|
||||||
|
|
||||||
|
**Parâmetros:**
|
||||||
|
- `numero1` (integer): Minuendo
|
||||||
|
- `numero2` (integer): Subtraendo
|
||||||
|
|
||||||
|
**Retorno de Sucesso:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"operacao": "subtracao",
|
||||||
|
"numero1": 20,
|
||||||
|
"numero2": 5,
|
||||||
|
"resultado": 15,
|
||||||
|
"expressao": "20 - 5 = 15"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Ferramenta: `multiplicacao`
|
||||||
|
|
||||||
|
Realiza a multiplicação de dois números inteiros.
|
||||||
|
|
||||||
|
**Parâmetros:**
|
||||||
|
- `numero1` (integer): Primeiro número
|
||||||
|
- `numero2` (integer): Segundo número
|
||||||
|
|
||||||
|
**Retorno de Sucesso:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"operacao": "multiplicacao",
|
||||||
|
"numero1": 8,
|
||||||
|
"numero2": 6,
|
||||||
|
"resultado": 48,
|
||||||
|
"expressao": "8 × 6 = 48"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Ferramenta: `divisao`
|
||||||
|
|
||||||
|
Realiza a divisão de dois números (numero1 / numero2). Retorna resultado como float.
|
||||||
|
|
||||||
|
**Parâmetros:**
|
||||||
|
- `numero1` (integer): Dividendo
|
||||||
|
- `numero2` (integer): Divisor
|
||||||
|
|
||||||
|
**Retorno de Sucesso:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"operacao": "divisao",
|
||||||
|
"numero1": 100,
|
||||||
|
"numero2": 4,
|
||||||
|
"resultado": 25.0,
|
||||||
|
"resultado_inteiro": 25,
|
||||||
|
"resto": 0,
|
||||||
|
"expressao": "100 ÷ 4 = 25.0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Retorno de Erro (Divisão por Zero):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "Divisão por zero não é permitida",
|
||||||
|
"operacao": "divisao",
|
||||||
|
"numero1": 10,
|
||||||
|
"numero2": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Tratamento de Operações Não Implementadas
|
||||||
|
|
||||||
|
Se uma ferramenta não reconhecida for chamada:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"error": "Operação 'potencia' não está implementada",
|
||||||
|
"operacao_solicitada": "potencia",
|
||||||
|
"operacoes_disponiveis": ["soma", "subtracao", "multiplicacao", "divisao"],
|
||||||
|
"mensagem": "Por favor, utilize uma das operações disponíveis..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Cliente MCP (`mcp_client.py`)
|
||||||
|
|
||||||
|
O cliente MCP integra três componentes principais:
|
||||||
|
|
||||||
|
#### Conexão com Servidor MCP
|
||||||
|
|
||||||
|
Estabelece comunicação via stdio com o servidor MCP e obtém lista de ferramentas disponíveis.
|
||||||
|
|
||||||
|
#### Integração com LLM
|
||||||
|
|
||||||
|
Utiliza a API do LLM (compatível com OpenAI) para:
|
||||||
|
- **Interpretar** a operação matemática desejada pelo usuário
|
||||||
|
- **Identificar** os números na conversa natural
|
||||||
|
- **Executar** tool calls apropriados
|
||||||
|
- **Gerar** respostas generativas e amigáveis
|
||||||
|
|
||||||
|
**Configuração do LLM:**
|
||||||
|
- **URL Base**: `https://api.xptoai.com.br/genai/grokcode/v1`
|
||||||
|
- **Autenticação**: Bearer Token
|
||||||
|
- **Modelo**: `grok-2-1212`
|
||||||
|
|
||||||
|
**Prompt do Sistema:**
|
||||||
|
|
||||||
|
O cliente instrui o LLM a:
|
||||||
|
1. Interpretar qual operação matemática o usuário deseja
|
||||||
|
2. Identificar os dois números envolvidos
|
||||||
|
3. Chamar a ferramenta apropriada
|
||||||
|
4. Apresentar resultados de forma clara
|
||||||
|
5. Tratar erros educadamente
|
||||||
|
6. Informar sobre operações não disponíveis
|
||||||
|
|
||||||
|
#### Loop de Chat
|
||||||
|
|
||||||
|
Mantém histórico de conversação e gerencia o fluxo de mensagens entre usuário, LLM e servidor MCP.
|
||||||
|
|
||||||
|
### 3. Script de Teste (`test_system.py`)
|
||||||
|
|
||||||
|
Automatiza o teste do sistema com 8 casos de teste:
|
||||||
|
|
||||||
|
1. **Soma**: "Quanto é 15 mais 7?"
|
||||||
|
2. **Subtração**: "Subtraia 5 de 20"
|
||||||
|
3. **Multiplicação**: "Multiplique 8 por 6"
|
||||||
|
4. **Divisão**: "Divida 100 por 4"
|
||||||
|
5. **Divisão por Zero**: "Divida 10 por 0" (erro esperado)
|
||||||
|
6. **Operação Não Implementada**: "Calcule 5 elevado ao quadrado"
|
||||||
|
7. **Linguagem Natural - Soma**: "Eu tenho 25 maçãs e ganhei mais 13..."
|
||||||
|
8. **Linguagem Natural - Subtração**: "Se eu tinha 50 reais e gastei 18..."
|
||||||
|
|
||||||
|
## 🔐 Configuração de Segurança
|
||||||
|
|
||||||
|
A chave de API está hardcoded no código para fins de demonstração. Em produção, recomenda-se:
|
||||||
|
|
||||||
|
1. Usar variáveis de ambiente:
|
||||||
|
```python
|
||||||
|
import os
|
||||||
|
API_KEY = os.getenv("XPTOAI_API_KEY")
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Usar arquivo `.env`:
|
||||||
|
```bash
|
||||||
|
echo "XPTOAI_API_KEY=sua_chave_aqui" > .env
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Carregar com `python-dotenv`:
|
||||||
|
```python
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 Testes
|
||||||
|
|
||||||
|
### Teste Manual
|
||||||
|
|
||||||
|
1. Execute o cliente: `python mcp_client.py`
|
||||||
|
2. Digite mensagens em linguagem natural
|
||||||
|
3. Teste diferentes operações
|
||||||
|
4. Teste casos de erro (divisão por zero)
|
||||||
|
5. Teste operações não implementadas
|
||||||
|
|
||||||
|
### Teste Automatizado
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python test_system.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Verifica automaticamente:
|
||||||
|
- ✅ Conexão com servidor MCP
|
||||||
|
- ✅ Listagem de 4 ferramentas
|
||||||
|
- ✅ Interpretação de operações
|
||||||
|
- ✅ Execução de todas as 4 operações
|
||||||
|
- ✅ Tratamento de divisão por zero
|
||||||
|
- ✅ Resposta para operações não implementadas
|
||||||
|
- ✅ Interpretação de linguagem natural
|
||||||
|
|
||||||
|
## 🐛 Troubleshooting
|
||||||
|
|
||||||
|
### Erro: "Permission denied"
|
||||||
|
|
||||||
|
Se encontrar erros de permissão ao instalar pacotes:
|
||||||
|
```bash
|
||||||
|
# Use ambiente virtual
|
||||||
|
python3.11 -m venv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Erro: "Connection refused"
|
||||||
|
|
||||||
|
Verifique se o servidor MCP está sendo iniciado corretamente pelo cliente.
|
||||||
|
|
||||||
|
### Erro: "API Key invalid"
|
||||||
|
|
||||||
|
Verifique se a chave de API está correta em `mcp_client.py`:
|
||||||
|
```python
|
||||||
|
API_KEY = "biasb986lk657fsdv6d3543vs5b65s7v373sd321vsdv4sdv34bv3f4hb5f4j6mn546tu"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Erro: "Model not found"
|
||||||
|
|
||||||
|
Ajuste o nome do modelo em `mcp_client.py` se necessário:
|
||||||
|
```python
|
||||||
|
MODEL_NAME = "grok-2-1212" # Ajuste conforme disponível na API
|
||||||
|
```
|
||||||
|
|
||||||
|
### Erro: "Divisão por zero"
|
||||||
|
|
||||||
|
Este é um erro esperado e tratado pelo sistema. O agente informará que a operação não é permitida.
|
||||||
|
|
||||||
|
## 📚 Referências
|
||||||
|
|
||||||
|
- [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)
|
||||||
|
- [OpenAI API Documentation](https://platform.openai.com/docs/api-reference)
|
||||||
|
- [Python asyncio](https://docs.python.org/3/library/asyncio.html)
|
||||||
|
|
||||||
|
## 🤝 Extensões Futuras
|
||||||
|
|
||||||
|
Sugestões para expandir o sistema:
|
||||||
|
|
||||||
|
### Novas Operações
|
||||||
|
- Potenciação
|
||||||
|
- Raiz quadrada
|
||||||
|
- Módulo/resto
|
||||||
|
- Valor absoluto
|
||||||
|
- Arredondamento
|
||||||
|
|
||||||
|
### Melhorias
|
||||||
|
- Suporte a números decimais (float)
|
||||||
|
- Histórico de cálculos
|
||||||
|
- Exportar resultados para arquivo
|
||||||
|
- Interface gráfica (GUI)
|
||||||
|
- API REST para integração
|
||||||
|
|
||||||
|
### Testes
|
||||||
|
- Testes unitários com pytest
|
||||||
|
- Testes de integração
|
||||||
|
- Testes de carga
|
||||||
|
- Cobertura de código
|
||||||
|
|
||||||
|
## 📄 Licença
|
||||||
|
|
||||||
|
Este projeto é fornecido como exemplo educacional.
|
||||||
|
|
||||||
|
## ✨ Características Principais
|
||||||
|
|
||||||
|
- ✅ **Interpretação Inteligente**: LLM identifica automaticamente a operação desejada
|
||||||
|
- ✅ **Linguagem Natural**: Entende perguntas contextuais e conversacionais
|
||||||
|
- ✅ **4 Operações Básicas**: Soma, subtração, multiplicação e divisão
|
||||||
|
- ✅ **Tratamento de Erros**: Validação completa e mensagens educadas
|
||||||
|
- ✅ **Operações Não Implementadas**: Informa claramente as limitações
|
||||||
|
- ✅ **Protocolo MCP**: Comunicação padronizada entre componentes
|
||||||
|
- ✅ **Assíncrono**: Uso de asyncio para melhor performance
|
||||||
|
- ✅ **Extensível**: Fácil adicionar novas ferramentas matemáticas
|
||||||
|
- ✅ **Testável**: Scripts de teste automatizado incluídos
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Desenvolvido como demonstração de AI Agent com MCP e interpretação inteligente de operações**
|
||||||
|
|||||||
294
GenAI/mcp/sample1/mcp_client.py
Normal file
294
GenAI/mcp/sample1/mcp_client.py
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Cliente MCP que interage com o usuário via chat usando LLM.
|
||||||
|
Interpreta a operação matemática desejada e executa através do servidor MCP.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
from typing import Optional
|
||||||
|
from mcp import ClientSession, StdioServerParameters
|
||||||
|
from mcp.client.stdio import stdio_client
|
||||||
|
from openai import OpenAI
|
||||||
|
|
||||||
|
|
||||||
|
# Configuração do LLM
|
||||||
|
API_BASE_URL = "https://api.xptoai.com.br/genai/grokcode/v1"
|
||||||
|
API_KEY = "biasb986lk657fsdv6d3543vs5b65s7v373sd321vsdv4sdv34bv3f4hb5f4j6mn546tu"
|
||||||
|
MODEL_NAME = "grok-2-1212" # Modelo padrão, pode ser ajustado
|
||||||
|
|
||||||
|
|
||||||
|
class MCPChatClient:
|
||||||
|
"""Cliente de chat que integra MCP com LLM."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.client = OpenAI(
|
||||||
|
base_url=API_BASE_URL,
|
||||||
|
api_key=API_KEY
|
||||||
|
)
|
||||||
|
self.session: Optional[ClientSession] = None
|
||||||
|
self.available_tools = []
|
||||||
|
self.conversation_history = []
|
||||||
|
|
||||||
|
async def connect_to_server(self):
|
||||||
|
"""Conecta ao servidor MCP."""
|
||||||
|
server_params = StdioServerParameters(
|
||||||
|
command="python3",
|
||||||
|
args=["mcp_server.py"],
|
||||||
|
env=None
|
||||||
|
)
|
||||||
|
|
||||||
|
# stdio_client retorna um context manager assíncrono
|
||||||
|
self.stdio_context = stdio_client(server_params)
|
||||||
|
self.stdio, self.write = await self.stdio_context.__aenter__()
|
||||||
|
self.session = ClientSession(self.stdio, self.write)
|
||||||
|
|
||||||
|
await self.session.__aenter__()
|
||||||
|
|
||||||
|
# Inicializar sessão
|
||||||
|
await self.session.initialize()
|
||||||
|
|
||||||
|
# Obter lista de ferramentas disponíveis
|
||||||
|
tools_list = await self.session.list_tools()
|
||||||
|
self.available_tools = tools_list.tools
|
||||||
|
|
||||||
|
print(f"✓ Conectado ao servidor MCP")
|
||||||
|
print(f"✓ Ferramentas disponíveis: {[tool.name for tool in self.available_tools]}\n")
|
||||||
|
|
||||||
|
def format_tools_for_openai(self) -> list:
|
||||||
|
"""Formata as ferramentas MCP para o formato OpenAI."""
|
||||||
|
openai_tools = []
|
||||||
|
for tool in self.available_tools:
|
||||||
|
openai_tools.append({
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": tool.name,
|
||||||
|
"description": tool.description,
|
||||||
|
"parameters": tool.inputSchema
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return openai_tools
|
||||||
|
|
||||||
|
async def call_mcp_tool(self, tool_name: str, arguments: dict) -> str:
|
||||||
|
"""Chama uma ferramenta no servidor MCP."""
|
||||||
|
result = await self.session.call_tool(tool_name, arguments)
|
||||||
|
|
||||||
|
# Extrair o conteúdo de texto do resultado
|
||||||
|
if result.content and len(result.content) > 0:
|
||||||
|
return result.content[0].text
|
||||||
|
return json.dumps({"error": "Nenhum resultado retornado"})
|
||||||
|
|
||||||
|
async def chat(self, user_message: str) -> str:
|
||||||
|
"""Processa uma mensagem do usuário e retorna a resposta do LLM."""
|
||||||
|
|
||||||
|
# Adicionar mensagem do usuário ao histórico
|
||||||
|
self.conversation_history.append({
|
||||||
|
"role": "user",
|
||||||
|
"content": user_message
|
||||||
|
})
|
||||||
|
|
||||||
|
# Preparar mensagens para o LLM
|
||||||
|
messages = [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": (
|
||||||
|
"Você é um assistente matemático inteligente que ajuda usuários a realizar operações matemáticas. "
|
||||||
|
"Você tem acesso a 4 ferramentas: soma, subtração, multiplicação e divisão. "
|
||||||
|
"\n\n"
|
||||||
|
"Seu objetivo é:\n"
|
||||||
|
"1. Interpretar qual operação matemática o usuário deseja realizar através da conversa natural\n"
|
||||||
|
"2. Identificar os dois números que o usuário quer usar\n"
|
||||||
|
"3. Chamar a ferramenta apropriada com os números corretos\n"
|
||||||
|
"4. Apresentar o resultado de forma clara e amigável\n"
|
||||||
|
"\n"
|
||||||
|
"Exemplos de interpretação:\n"
|
||||||
|
"- 'Quanto é 5 mais 3?' → usar ferramenta 'soma' com 5 e 3\n"
|
||||||
|
"- 'Subtraia 10 de 25' → usar ferramenta 'subtracao' com 25 e 10\n"
|
||||||
|
"- 'Multiplique 7 por 8' → usar ferramenta 'multiplicacao' com 7 e 8\n"
|
||||||
|
"- 'Divida 20 por 4' → usar ferramenta 'divisao' com 20 e 4\n"
|
||||||
|
"- '15 menos 7' → usar ferramenta 'subtracao' com 15 e 7\n"
|
||||||
|
"\n"
|
||||||
|
"Se o usuário pedir uma operação que não está disponível (como potência, raiz quadrada, etc.), "
|
||||||
|
"informe educadamente que apenas as 4 operações básicas estão implementadas. "
|
||||||
|
"\n"
|
||||||
|
"Seja conversacional, natural e prestativo na interação."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
] + self.conversation_history
|
||||||
|
|
||||||
|
# Fazer chamada ao LLM com ferramentas
|
||||||
|
openai_tools = self.format_tools_for_openai()
|
||||||
|
|
||||||
|
response = self.client.chat.completions.create(
|
||||||
|
model=MODEL_NAME,
|
||||||
|
messages=messages,
|
||||||
|
tools=openai_tools if openai_tools else None,
|
||||||
|
tool_choice="auto" if openai_tools else None
|
||||||
|
)
|
||||||
|
|
||||||
|
assistant_message = response.choices[0].message
|
||||||
|
|
||||||
|
# Verificar se o LLM quer chamar ferramentas
|
||||||
|
if assistant_message.tool_calls:
|
||||||
|
# Adicionar a resposta do assistente ao histórico
|
||||||
|
self.conversation_history.append({
|
||||||
|
"role": "assistant",
|
||||||
|
"content": assistant_message.content,
|
||||||
|
"tool_calls": [
|
||||||
|
{
|
||||||
|
"id": tc.id,
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": tc.function.name,
|
||||||
|
"arguments": tc.function.arguments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for tc in assistant_message.tool_calls
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
# Executar as ferramentas solicitadas
|
||||||
|
for tool_call in assistant_message.tool_calls:
|
||||||
|
function_name = tool_call.function.name
|
||||||
|
function_args = json.loads(tool_call.function.arguments)
|
||||||
|
|
||||||
|
print(f"🔧 Executando ferramenta: {function_name}")
|
||||||
|
print(f" Argumentos: {function_args}")
|
||||||
|
|
||||||
|
# Chamar a ferramenta MCP
|
||||||
|
tool_result = await self.call_mcp_tool(function_name, function_args)
|
||||||
|
|
||||||
|
# Verificar se houve erro no resultado
|
||||||
|
try:
|
||||||
|
result_data = json.loads(tool_result)
|
||||||
|
if "error" in result_data:
|
||||||
|
print(f" ⚠️ Erro: {result_data['error']}")
|
||||||
|
else:
|
||||||
|
print(f" ✓ Resultado: {result_data.get('resultado', tool_result)}")
|
||||||
|
except:
|
||||||
|
print(f" Resultado: {tool_result}")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Adicionar resultado da ferramenta ao histórico
|
||||||
|
self.conversation_history.append({
|
||||||
|
"role": "tool",
|
||||||
|
"tool_call_id": tool_call.id,
|
||||||
|
"content": tool_result
|
||||||
|
})
|
||||||
|
|
||||||
|
# Fazer nova chamada ao LLM com os resultados das ferramentas
|
||||||
|
messages = [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": (
|
||||||
|
"Você é um assistente matemático inteligente que ajuda usuários a realizar operações matemáticas. "
|
||||||
|
"Você tem acesso a 4 ferramentas: soma, subtração, multiplicação e divisão. "
|
||||||
|
"\n\n"
|
||||||
|
"Seu objetivo é:\n"
|
||||||
|
"1. Interpretar qual operação matemática o usuário deseja realizar através da conversa natural\n"
|
||||||
|
"2. Identificar os dois números que o usuário quer usar\n"
|
||||||
|
"3. Chamar a ferramenta apropriada com os números corretos\n"
|
||||||
|
"4. Apresentar o resultado de forma clara e amigável\n"
|
||||||
|
"\n"
|
||||||
|
"Exemplos de interpretação:\n"
|
||||||
|
"- 'Quanto é 5 mais 3?' → usar ferramenta 'soma' com 5 e 3\n"
|
||||||
|
"- 'Subtraia 10 de 25' → usar ferramenta 'subtracao' com 25 e 10\n"
|
||||||
|
"- 'Multiplique 7 por 8' → usar ferramenta 'multiplicacao' com 7 e 8\n"
|
||||||
|
"- 'Divida 20 por 4' → usar ferramenta 'divisao' com 20 e 4\n"
|
||||||
|
"- '15 menos 7' → usar ferramenta 'subtracao' com 15 e 7\n"
|
||||||
|
"\n"
|
||||||
|
"Se o usuário pedir uma operação que não está disponível (como potência, raiz quadrada, etc.), "
|
||||||
|
"informe educadamente que apenas as 4 operações básicas estão implementadas. "
|
||||||
|
"\n"
|
||||||
|
"Se houver erro na execução (como divisão por zero), explique o erro de forma educada e sugira uma alternativa. "
|
||||||
|
"\n"
|
||||||
|
"Seja conversacional, natural e prestativo na interação."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
] + self.conversation_history
|
||||||
|
|
||||||
|
final_response = self.client.chat.completions.create(
|
||||||
|
model=MODEL_NAME,
|
||||||
|
messages=messages
|
||||||
|
)
|
||||||
|
|
||||||
|
final_message = final_response.choices[0].message.content
|
||||||
|
|
||||||
|
# Adicionar resposta final ao histórico
|
||||||
|
self.conversation_history.append({
|
||||||
|
"role": "assistant",
|
||||||
|
"content": final_message
|
||||||
|
})
|
||||||
|
|
||||||
|
return final_message
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Não há chamadas de ferramentas, apenas resposta textual
|
||||||
|
response_text = assistant_message.content or ""
|
||||||
|
|
||||||
|
self.conversation_history.append({
|
||||||
|
"role": "assistant",
|
||||||
|
"content": response_text
|
||||||
|
})
|
||||||
|
|
||||||
|
return response_text
|
||||||
|
|
||||||
|
async def close(self):
|
||||||
|
"""Fecha a conexão com o servidor MCP."""
|
||||||
|
if self.session:
|
||||||
|
await self.session.__aexit__(None, None, None)
|
||||||
|
if hasattr(self, 'stdio_context'):
|
||||||
|
await self.stdio_context.__aexit__(None, None, None)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
"""Função principal que executa o chat interativo."""
|
||||||
|
print("=" * 60)
|
||||||
|
print(" Chat com AI Agent - Operações Matemáticas")
|
||||||
|
print("=" * 60)
|
||||||
|
print()
|
||||||
|
|
||||||
|
client = MCPChatClient()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Conectar ao servidor MCP
|
||||||
|
await client.connect_to_server()
|
||||||
|
|
||||||
|
print("💬 Iniciando conversa com o assistente...")
|
||||||
|
print(" (Digite 'sair' para encerrar)\n")
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
# Loop de chat interativo
|
||||||
|
while True:
|
||||||
|
# Obter entrada do usuário
|
||||||
|
user_input = input("\n👤 Você: ").strip()
|
||||||
|
|
||||||
|
if not user_input:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if user_input.lower() in ['sair', 'exit', 'quit']:
|
||||||
|
print("\n👋 Encerrando chat. Até logo!")
|
||||||
|
break
|
||||||
|
|
||||||
|
# Processar mensagem
|
||||||
|
print("\n🤖 Assistente: ", end="", flush=True)
|
||||||
|
response = await client.chat(user_input)
|
||||||
|
print(response)
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\n\n👋 Chat interrompido. Até logo!")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n❌ Erro: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Fechar conexão
|
||||||
|
await client.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
253
GenAI/mcp/sample1/mcp_server.py
Normal file
253
GenAI/mcp/sample1/mcp_server.py
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Servidor MCP com ferramentas matemáticas: soma, subtração, multiplicação e divisão.
|
||||||
|
Inclui tratamento de erros e validações.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
from mcp.server import Server
|
||||||
|
from mcp.types import Tool, TextContent
|
||||||
|
from mcp.server.stdio import stdio_server
|
||||||
|
|
||||||
|
|
||||||
|
# Criar instância do servidor MCP
|
||||||
|
app = Server("math-tools-server")
|
||||||
|
|
||||||
|
|
||||||
|
@app.list_tools()
|
||||||
|
async def list_tools() -> list[Tool]:
|
||||||
|
"""Lista as ferramentas disponíveis no servidor."""
|
||||||
|
return [
|
||||||
|
Tool(
|
||||||
|
name="soma",
|
||||||
|
description="Realiza a soma de dois números inteiros",
|
||||||
|
inputSchema={
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"numero1": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Primeiro número inteiro"
|
||||||
|
},
|
||||||
|
"numero2": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Segundo número inteiro"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["numero1", "numero2"]
|
||||||
|
}
|
||||||
|
),
|
||||||
|
Tool(
|
||||||
|
name="subtracao",
|
||||||
|
description="Realiza a subtração de dois números inteiros (numero1 - numero2)",
|
||||||
|
inputSchema={
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"numero1": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Primeiro número inteiro (minuendo)"
|
||||||
|
},
|
||||||
|
"numero2": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Segundo número inteiro (subtraendo)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["numero1", "numero2"]
|
||||||
|
}
|
||||||
|
),
|
||||||
|
Tool(
|
||||||
|
name="multiplicacao",
|
||||||
|
description="Realiza a multiplicação de dois números inteiros",
|
||||||
|
inputSchema={
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"numero1": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Primeiro número inteiro"
|
||||||
|
},
|
||||||
|
"numero2": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Segundo número inteiro"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["numero1", "numero2"]
|
||||||
|
}
|
||||||
|
),
|
||||||
|
Tool(
|
||||||
|
name="divisao",
|
||||||
|
description="Realiza a divisão de dois números inteiros (numero1 / numero2). Retorna resultado como float.",
|
||||||
|
inputSchema={
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"numero1": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Primeiro número inteiro (dividendo)"
|
||||||
|
},
|
||||||
|
"numero2": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Segundo número inteiro (divisor)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["numero1", "numero2"]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@app.call_tool()
|
||||||
|
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
|
||||||
|
"""Executa a ferramenta solicitada com tratamento de erros."""
|
||||||
|
|
||||||
|
# Validar argumentos comuns
|
||||||
|
numero1 = arguments.get("numero1")
|
||||||
|
numero2 = arguments.get("numero2")
|
||||||
|
|
||||||
|
if numero1 is None or numero2 is None:
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"error": "Ambos os números são obrigatórios",
|
||||||
|
"operacao": name
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
|
||||||
|
# Validar tipos
|
||||||
|
if not isinstance(numero1, int) or not isinstance(numero2, int):
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"error": "Os números devem ser inteiros",
|
||||||
|
"operacao": name,
|
||||||
|
"numero1_tipo": type(numero1).__name__,
|
||||||
|
"numero2_tipo": type(numero2).__name__
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
|
||||||
|
# Executar operação específica
|
||||||
|
if name == "soma":
|
||||||
|
try:
|
||||||
|
resultado = numero1 + numero2
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"operacao": "soma",
|
||||||
|
"numero1": numero1,
|
||||||
|
"numero2": numero2,
|
||||||
|
"resultado": resultado,
|
||||||
|
"expressao": f"{numero1} + {numero2} = {resultado}"
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
except Exception as e:
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"error": f"Erro ao executar soma: {str(e)}",
|
||||||
|
"operacao": "soma"
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
|
||||||
|
elif name == "subtracao":
|
||||||
|
try:
|
||||||
|
resultado = numero1 - numero2
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"operacao": "subtracao",
|
||||||
|
"numero1": numero1,
|
||||||
|
"numero2": numero2,
|
||||||
|
"resultado": resultado,
|
||||||
|
"expressao": f"{numero1} - {numero2} = {resultado}"
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
except Exception as e:
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"error": f"Erro ao executar subtração: {str(e)}",
|
||||||
|
"operacao": "subtracao"
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
|
||||||
|
elif name == "multiplicacao":
|
||||||
|
try:
|
||||||
|
resultado = numero1 * numero2
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"operacao": "multiplicacao",
|
||||||
|
"numero1": numero1,
|
||||||
|
"numero2": numero2,
|
||||||
|
"resultado": resultado,
|
||||||
|
"expressao": f"{numero1} × {numero2} = {resultado}"
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
except Exception as e:
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"error": f"Erro ao executar multiplicação: {str(e)}",
|
||||||
|
"operacao": "multiplicacao"
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
|
||||||
|
elif name == "divisao":
|
||||||
|
# Validação específica: divisão por zero
|
||||||
|
if numero2 == 0:
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"error": "Divisão por zero não é permitida",
|
||||||
|
"operacao": "divisao",
|
||||||
|
"numero1": numero1,
|
||||||
|
"numero2": numero2
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
|
||||||
|
try:
|
||||||
|
resultado = numero1 / numero2
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"operacao": "divisao",
|
||||||
|
"numero1": numero1,
|
||||||
|
"numero2": numero2,
|
||||||
|
"resultado": resultado,
|
||||||
|
"resultado_inteiro": numero1 // numero2,
|
||||||
|
"resto": numero1 % numero2,
|
||||||
|
"expressao": f"{numero1} ÷ {numero2} = {resultado}"
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
except Exception as e:
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"error": f"Erro ao executar divisão: {str(e)}",
|
||||||
|
"operacao": "divisao"
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Operação não implementada
|
||||||
|
return [TextContent(
|
||||||
|
type="text",
|
||||||
|
text=json.dumps({
|
||||||
|
"error": f"Operação '{name}' não está implementada",
|
||||||
|
"operacao_solicitada": name,
|
||||||
|
"operacoes_disponiveis": ["soma", "subtracao", "multiplicacao", "divisao"],
|
||||||
|
"mensagem": "Por favor, utilize uma das operações disponíveis: soma, subtração, multiplicação ou divisão"
|
||||||
|
})
|
||||||
|
)]
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
"""Inicia o servidor MCP via stdio."""
|
||||||
|
async with stdio_server() as (read_stream, write_stream):
|
||||||
|
await app.run(
|
||||||
|
read_stream,
|
||||||
|
write_stream,
|
||||||
|
app.create_initialization_options()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
2
GenAI/mcp/sample1/requirements.txt
Normal file
2
GenAI/mcp/sample1/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
mcp==1.23.1
|
||||||
|
openai==2.8.1
|
||||||
29
GenAI/mcp/sample1/run.sh
Normal file
29
GenAI/mcp/sample1/run.sh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Script de inicialização rápida do sistema MCP
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Sistema MCP - Operações Matemáticas"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Verificar se ambiente virtual existe
|
||||||
|
if [ ! -d "venv" ]; then
|
||||||
|
echo "❌ Ambiente virtual não encontrado!"
|
||||||
|
echo " Execute: python3.11 -m venv venv"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ativar ambiente virtual
|
||||||
|
source venv/bin/activate
|
||||||
|
|
||||||
|
# Verificar se dependências estão instaladas
|
||||||
|
if ! python -c "import mcp" 2>/dev/null; then
|
||||||
|
echo "📦 Instalando dependências..."
|
||||||
|
pip install -r requirements.txt
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Executar cliente MCP
|
||||||
|
echo "🚀 Iniciando cliente MCP..."
|
||||||
|
echo ""
|
||||||
|
python mcp_client.py
|
||||||
97
GenAI/mcp/sample1/test_system.py
Normal file
97
GenAI/mcp/sample1/test_system.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Script de teste automatizado para o sistema MCP.
|
||||||
|
Testa todas as 4 operações matemáticas e casos de erro.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
from mcp_client import MCPChatClient
|
||||||
|
|
||||||
|
|
||||||
|
async def test_system():
|
||||||
|
"""Testa o sistema com uma sequência de mensagens variadas."""
|
||||||
|
print("=" * 60)
|
||||||
|
print(" TESTE AUTOMATIZADO - Sistema MCP")
|
||||||
|
print("=" * 60)
|
||||||
|
print()
|
||||||
|
|
||||||
|
client = MCPChatClient()
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Conectar ao servidor
|
||||||
|
await client.connect_to_server()
|
||||||
|
|
||||||
|
# Sequência de mensagens de teste
|
||||||
|
test_cases = [
|
||||||
|
{
|
||||||
|
"descricao": "Teste de Soma",
|
||||||
|
"mensagem": "Quanto é 15 mais 7?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"descricao": "Teste de Subtração",
|
||||||
|
"mensagem": "Subtraia 5 de 20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"descricao": "Teste de Multiplicação",
|
||||||
|
"mensagem": "Multiplique 8 por 6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"descricao": "Teste de Divisão",
|
||||||
|
"mensagem": "Divida 100 por 4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"descricao": "Teste de Divisão por Zero (Erro Esperado)",
|
||||||
|
"mensagem": "Divida 10 por 0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"descricao": "Teste de Operação Não Implementada",
|
||||||
|
"mensagem": "Calcule 5 elevado ao quadrado"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"descricao": "Teste de Linguagem Natural - Soma",
|
||||||
|
"mensagem": "Eu tenho 25 maçãs e ganhei mais 13, quantas tenho agora?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"descricao": "Teste de Linguagem Natural - Subtração",
|
||||||
|
"mensagem": "Se eu tinha 50 reais e gastei 18, quanto sobrou?"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
print("📝 Executando sequência de testes...\n")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
for i, test_case in enumerate(test_cases, 1):
|
||||||
|
print(f"\n[Teste {i}/{len(test_cases)}] {test_case['descricao']}")
|
||||||
|
print("-" * 60)
|
||||||
|
print(f"👤 Usuário: {test_case['mensagem']}")
|
||||||
|
|
||||||
|
response = await client.chat(test_case['mensagem'])
|
||||||
|
|
||||||
|
print(f"🤖 Assistente: {response}")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Pequena pausa entre mensagens
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
print("\n✅ Todos os testes concluídos!")
|
||||||
|
print("\nResumo dos testes:")
|
||||||
|
print(" ✓ Soma")
|
||||||
|
print(" ✓ Subtração")
|
||||||
|
print(" ✓ Multiplicação")
|
||||||
|
print(" ✓ Divisão")
|
||||||
|
print(" ✓ Tratamento de erro (divisão por zero)")
|
||||||
|
print(" ✓ Operação não implementada")
|
||||||
|
print(" ✓ Interpretação de linguagem natural")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n❌ Erro durante o teste: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
await client.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(test_system())
|
||||||
Reference in New Issue
Block a user