Files
trello-mcp/tests/test_tool_errors.py
maxerton 4dd2e58b86 trello-tools: окно подтверждения на протоколе 2026-07-28, ошибки — модели
Claude Code теперь согласует со stdio-серверами MCP 2026-07-28, где
сервер не может сам слать запросы клиенту: ctx.elicit падал с
NoBackChannelError, и trello_create_card не создавал карточки ни в
терминале, ни в Desktop. Подтверждение переведено на Resolve/Elicit —
SDK спрашивает через input_required или elicitation/create, смотря по
версии протокола.

SDK прячет от модели текст любых исключений, кроме ToolError, поэтому
подсказки про незаданные ключи и 404 до неё не доходили.
TrelloToolsServer отдаёт их текстом (HTTP-ошибки — без query, там
ключи Trello).

Ещё:
- get_dev_task: перед реализацией ТЗ прочитать код, пересказать суть
  и предложить варианты или задать вопросы;
- QA-документы по умолчанию на украинском;
- README и подсказки в ошибках: в Claude Desktop /plugin configure нет,
  ключи задаются из терминала.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 16:53:19 +00:00

60 lines
1.9 KiB
Python

import sys
from pathlib import Path
import httpx
import pytest
import respx
from mcp.client import Client
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
import server # noqa: E402
@pytest.fixture(autouse=True)
def no_trello_env(monkeypatch):
for name in ("TRELLO_API_KEY", "TRELLO_TOKEN", "TRELLO_BOARD_ID"):
monkeypatch.delenv(name, raising=False)
async def _call(name, arguments):
async with Client(server.mcp, mode="2026-07-28") as client:
return await client.call_tool(name, arguments)
@pytest.mark.asyncio
async def test_config_hint_reaches_model():
# SDK прячет текст обычных исключений — без TrelloToolsServer модель
# видела бы только «Error executing tool trello_list_labels».
result = await _call("trello_list_labels", {})
assert result.is_error
assert "TRELLO_API_KEY / TRELLO_TOKEN не заданы" in result.content[0].text
@pytest.mark.asyncio
async def test_http_error_shows_status_without_credentials(monkeypatch):
monkeypatch.setenv("TRELLO_API_KEY", "key123")
monkeypatch.setenv("TRELLO_TOKEN", "tok456")
with respx.mock:
respx.get(url__startswith="https://api.trello.com/1/cards/abc").mock(
return_value=httpx.Response(404)
)
result = await _call("trello_get_card", {"card_url": "https://trello.com/c/abc"})
text = result.content[0].text
assert result.is_error and "HTTP 404 от api.trello.com/1/cards/abc" in text
assert "key123" not in text and "tok456" not in text
@pytest.mark.asyncio
async def test_unexpected_crash_stays_hidden(monkeypatch):
async def crash(card_url):
raise KeyError("internal detail")
monkeypatch.setattr(server.trello, "get_card", crash)
result = await _call("trello_get_card", {"card_url": "https://trello.com/c/abc"})
assert result.is_error and "internal detail" not in result.content[0].text