We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/nic01asFr/mcp-server-grist'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""
Tests de conformité MCP.
Ce module vérifie que les outils MCP sont conformes aux standards MCP.
"""
import pytest
from unittest.mock import AsyncMock, MagicMock, patch
from mcp_server_grist.tools.navigation import list_organizations, list_records
from mcp_server_grist.tools.records import add_grist_records, update_grist_records, delete_grist_records
from mcp_server_grist.tools.queries import filter_sql_query, execute_sql_query
@pytest.mark.asyncio
async def test_navigation_tool_response_format(mock_grist_client, mock_ctx):
"""Vérifie que les outils de navigation retournent le format de réponse MCP correct."""
# Configuration du mock
mock_grist_client.list_orgs.return_value = []
# Patch la fonction get_client pour retourner notre mock
with patch("mcp_server_grist.tools.navigation.get_client", return_value=mock_grist_client):
result = await list_organizations(mock_ctx)
# Vérifications du format de réponse MCP
assert isinstance(result, dict), "La réponse doit être un dictionnaire"
assert "success" in result, "La réponse doit contenir un champ 'success'"
assert isinstance(result["success"], bool), "Le champ 'success' doit être un booléen"
assert "message" in result, "La réponse doit contenir un champ 'message'"
assert isinstance(result["message"], str), "Le champ 'message' doit être une chaîne"
@pytest.mark.asyncio
async def test_records_tool_response_format(mock_grist_client, mock_ctx):
"""Vérifie que les outils de gestion des enregistrements retournent le format de réponse MCP correct."""
# Configuration du mock
mock_grist_client.add_records.return_value = [1]
# Patch la fonction get_client pour retourner notre mock
with patch("mcp_server_grist.tools.records.get_client", return_value=mock_grist_client):
result = await add_grist_records("doc1", "table1", [{"name": "Test"}], mock_ctx)
# Vérifications du format de réponse MCP
assert isinstance(result, dict), "La réponse doit être un dictionnaire"
assert "success" in result, "La réponse doit contenir un champ 'success'"
assert isinstance(result["success"], bool), "Le champ 'success' doit être un booléen"
assert "message" in result, "La réponse doit contenir un champ 'message'"
assert isinstance(result["message"], str), "Le champ 'message' doit être une chaîne"
assert "record_ids" in result, "La réponse doit contenir un champ 'record_ids'"
@pytest.mark.asyncio
async def test_error_response_format(mock_grist_client, mock_ctx):
"""Vérifie que les erreurs sont formatées correctement selon MCP."""
# Configuration du mock pour lever une exception
mock_grist_client.list_orgs.side_effect = ValueError("API Error")
# Patch la fonction get_client pour retourner notre mock
with patch("mcp_server_grist.tools.navigation.get_client", return_value=mock_grist_client):
result = await list_organizations(mock_ctx)
# Vérifications du format d'erreur MCP
assert isinstance(result, dict), "La réponse d'erreur doit être un dictionnaire"
assert "success" in result, "La réponse d'erreur doit contenir un champ 'success'"
assert result["success"] is False, "Le champ 'success' doit être False en cas d'erreur"
assert "message" in result, "La réponse d'erreur doit contenir un champ 'message'"
assert isinstance(result["message"], str), "Le champ 'message' doit être une chaîne"
assert "Error" in result["message"], "Le message doit contenir des informations sur l'erreur"
@pytest.mark.asyncio
async def test_add_records_response_format(mock_grist_client, mock_ctx):
"""Vérifie spécifiquement que add_grist_records retourne un dictionnaire et non une liste."""
# Configuration du mock
mock_grist_client.add_records.return_value = [1, 2, 3]
# Patch la fonction get_client pour retourner notre mock
with patch("mcp_server_grist.tools.records.get_client", return_value=mock_grist_client):
result = await add_grist_records("doc1", "table1", [{"name": "Test"}], mock_ctx)
# Vérifications spécifiques pour add_grist_records
assert isinstance(result, dict), "add_grist_records doit retourner un dictionnaire"
assert "success" in result, "La réponse doit contenir un champ 'success'"
assert "message" in result, "La réponse doit contenir un champ 'message'"
assert "record_ids" in result, "La réponse doit contenir un champ 'record_ids'"
assert isinstance(result["record_ids"], list), "record_ids doit être une liste"