4dd2e58b86
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>
60 lines
1.9 KiB
Python
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
|