254 lines
8.2 KiB
Python
254 lines
8.2 KiB
Python
#!/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())
|