Add files via upload

This commit is contained in:
Marcos Lohmann
2025-12-03 11:05:21 -03:00
committed by GitHub
parent 8e3042962c
commit cbf0796e2e
7 changed files with 1349 additions and 1 deletions

View 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())