Skip to main content
Glama

ypt-mcp

MCP-сервер для трекера учёбы YPT (열품타) на базе библиотеки ypt-python.

Работает по stdio-транспорту и через Model Context Protocol открывает доступ к дневным логам учёбы, рейтингам, учебным группам и таймеру занятий.

Возможности

  • Профиль и сводка за сегодня (get_profile)

  • Дневные логи учёбы по датам (get_day_log)

  • Твоё место в рейтинге категории и таблицы лидеров (get_my_rank, get_leaderboard)

  • Поиск групп, мои группы, участники (browse_groups, get_my_groups, get_group_members)

  • Таймер занятий: старт/стоп с учётом сессии (start_study, stop_study)

Related MCP server: baihua-mcp-server

Требования

  • uv (для запуска через uvx / uv run)

  • Доступ к GitHub-репозиториям derived-functor/ypt-mcp и derived-functor/ypt-private-client (приватные — нужен настроенный git-auth: SSH-ключ или PAT)

Быстрый старт

Вариант 1 — через uvx (основной)

Одна команда, без клонирования:

uvx --from git+https://github.com/derived-functor/ypt-mcp ypt-mcp

uvx сам подтянет ypt-mcp и его зависимость ypt-python (из git+https://github.com/derived-functor/ypt-private-client), соберёт и запустит в изолированном окружении.

При необходимости можно пинить версию: --from git+...@main.

Вариант 2 — локальная разработка через uv run

git clone https://github.com/derived-functor/ypt-mcp
cd ypt-mcp
uv sync
uv run ypt-mcp

При работе над самой библиотекой ypt-python удобно временно вернуть в pyproject.toml локальный источник: [tool.uv.sources] = { path = "/path/to/ypt-private-client", editable = true }.

Аутентификация

Сервер использует кэш JWT-токена ~/.cache/ypt-python/token (общий с ypt-cli). Если токена нет, логинится по переменным окружения:

export YPT_EMAIL="you@example.com"
export YPT_PASSWORD="your-password"

Либо заранее выполни логин через библиотеку:

cd ~/probe/ypt-private-client && uv run ypt-cli login

Приоритет: закэшированный токен → YPT_EMAIL/YPT_PASSWORD. Если токен протух, сервер сам перелогинится и обновит кэш. Пароль нигде не хранится (в кэше только JWT).

Не коммить реальные YPT_EMAIL/YPT_PASSWORD в файлы конфигов — используй интерполяцию {env:VAR} (см. ниже), тогда значения попадут только в окружение.

Подключение клиентов

opencode (opencode.json)

Проектный opencode.json или глобальный ~/.config/opencode/opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ypt": {
      "type": "local",
      "command": ["uvx", "--from", "git+https://github.com/derived-functor/ypt-mcp", "ypt-mcp"],
      "environment": {
        "YPT_EMAIL": "{env:YPT_EMAIL}",
        "YPT_PASSWORD": "{env:YPT_PASSWORD}"
      }
    }
  }
}

Заметки:

  • command — массив строк, оболочка не используется;

  • {env:VAR} подставляет значение из окружения opencode (не $VAR);

  • после изменения конфига перезапусти opencode — конфиг подхватывается только при старте.

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "ypt": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/derived-functor/ypt-mcp", "ypt-mcp"],
      "env": {
        "YPT_EMAIL": "you@example.com",
        "YPT_PASSWORD": "your-password"
      }
    }
  }
}

Тулы

Тул

Назначение

get_profile

Профиль, категория/страна, предметы, сводка за сегодня

get_day_log(date)

Лог учёбы за дату

get_my_rank(category_id, country_id)

Твоё место в рейтинге категории

get_leaderboard(category_id, country_id, date, ...)

Таблица лидеров категории

browse_groups(...)

Поиск публичных групп

get_my_groups

Твои группы

get_group_members(group_id, country_id)

Участники группы

start_study(subject, ...)

Старт таймера учёбы

stop_study(started_at, ...)

Стоп таймера учёбы

Время отдаётся в часах (study_hours/rest_hours, float) и в сырых миллисекундах (study_ms/rest_ms, int). Даты — YYYY-MM-DD.

get_profile

Без аргументов. Возвращает профиль и сводку за сегодня:

{
  "nickname": "derived-functor",
  "category_code": "ВУЗ",
  "category_id": 94,
  "country_id": 6,
  "subjects": [
    { "id": 131150462, "title": "матеша задачи", "study_hours": 0.0, "archived": false }
  ],
  "day_log": {
    "date": "2026-09-12",
    "study_hours": 0.44,
    "rest_hours": 2.15,
    "subjects": [
      { "subject_id": 131150462, "subject_title": "матеша задачи", "study_hours": 0.44 }
    ]
  }
}

get_day_log(date)

Аргумент

Тип

Описание

date

str

Дата в формате YYYY-MM-DD

{
  "date": "2026-09-12",
  "study_ms": 1586019,
  "study_hours": 0.44,
  "rest_hours": 2.15,
  "max_study_hours": 0.44,
  "added_hours": 0.0,
  "subjects": [
    { "subject_id": 131150462, "subject_title": "матеша задачи", "study_ms": 1586019, "study_hours": 0.44 }
  ]
}

get_my_rank(category_id, country_id)

Аргумент

Тип

Описание

category_id

int

ID категории из get_profile

country_id

int

ID страны из get_profile

Вернёт число (номер места) или null, если рейтинга нет.

get_leaderboard(category_id, country_id, date, page, rank_type, limit)

Аргумент

Тип

Дефолт

Описание

category_id

int

ID категории

country_id

int

ID страны

date

str

Дата YYYY-MM-DD

page

int

1

Номер страницы (20 записей)

rank_type

str

"day"

Период: "day" или "week"

limit

int

20

Сколько участников вернуть

{
  "total_count": 729,
  "members": [
    { "nickname": "lisha.rix", "user_id": 17526047, "study_hours": 11.08, "studicon_id": 0 }
  ]
}

browse_groups(category_id, page, country_id, order_type, only_available, only_open, only_cam)

Аргумент

Тип

Дефолт

Описание

category_id

int

0

Фильтр по категории (0 = все)

page

int

1

Номер страницы

country_id

int | null

null

Фильтр по стране

order_type

str

"promotedAt"

Сортировка

only_available

bool

false

Только группы со свободными местами

only_open

bool

false

Только открытые группы

only_cam

bool

false

Только с камерой

get_my_groups

Без аргументов. Список групп с id, title, owner, member_count.

get_group_members(group_id, country_id)

Аргумент

Тип

Описание

group_id

int

ID группы

country_id

int

ID страны

У каждого участника: user_id, nickname, category, study_hours, studying (учится ли прямо сейчас).

start_study(subject, device_model) / stop_study(started_at, device_model)

Аргумент

Тип

Дефолт

Описание

subject

str

Название предмета (для start)

started_at

int | null

null

Старт сессии epoch ms (для stop)

device_model

str

"ypt-mcp"

Модель устройства для API

start_study возвращает started_at (epoch ms) и дневной лог. stop_study без started_at использует записанную сессию (state-файл ~/.cache/ypt-python/study_started_at, тот же, что у ypt-cli).

Сценарии-примеры

Все примеры общаются с сервером по stdio через Python-клиент mcp:

import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

CMD = ["uvx", "--from", "git+https://github.com/derived-functor/ypt-mcp", "ypt-mcp"]

async def call(tool: str, args: dict):
    params = StdioServerParameters(command=CMD[0], args=CMD[1:])
    async with stdio_client(params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            res = await session.call_tool(tool, args)
            return "".join(c.text for c in res.content)

async def main():
    # 1. Ежедневный отчёт
    profile = await call("get_profile", {})
    print(profile)

    # 2. Топ категории (id/страну берём из профиля)
    top = await call("get_leaderboard", {
        "category_id": 94, "country_id": 6, "date": "2026-09-12", "limit": 10,
    })
    print(top)

    # 3. Мои группы и участники
    groups = await call("get_my_groups", {})
    members = await call("get_group_members", {"group_id": groups[0]["id"], "country_id": 6})
    print(members)

    # 4. Таймер: старт → рядом повторяющихся вызовов нет → стоп
    started = await call("start_study", {"subject": "матеша задачи"})
    stopped = await call("stop_study", {"started_at": started["started_at"]})
    print(stopped)

asyncio.run(main())

Обработка ошибок

Ситуация

Поведение

Нет токена и нет YPT_EMAIL/YPT_PASSWORD

Ошибка с сообщением «credentials not found»

Протухший токен

Сервер перелогинится и повторит вызов автоматически

stop_study без записанной сессии

Ошибка — нужен started_at

Ошибки YPT API / сети

Пробрасываются выше с кодом/текстом из библиотеки ypt-python

Архитектура

LLM/клиент (opencode, Claude Desktop)
        │  MCP (stdio, JSON-RPC)
        ▼
ypt-mcp  (mcp SDK, тулы, auth-менеджмент)
        │  ypt-python (async-клиент, pydantic-модели)
        ▼
YPT REST API (https://pi.tgclab.com)
  • src/ypt_mcp/server.py — все тулы и логика аутентификации

  • ~/.cache/ypt-python/token — кэш JWT

  • ~/.cache/ypt-python/study_started_at — старт текущей сессии таймера

  • pyproject.toml — зависимости (mcp, ypt-python из git) и entry point

Проверка

Смоук-тест: запустить сервер, выполнить handshake и вывести список тулов.

uvx --from git+https://github.com/derived-functor/ypt-mcp python - <<'EOF'
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

async def main():
    params = StdioServerParameters(
        command="uvx",
        args=["--from", "git+https://github.com/derived-functor/ypt-mcp", "ypt-mcp"],
    )
    async with stdio_client(params) as (r, w):
        async with ClientSession(r, w) as s:
            await s.initialize()
            print([t.name for t in (await s.list_tools()).tools])

asyncio.run(main())
EOF

Ожидаемый результат — 9 тулов: get_profile, get_day_log, get_my_rank, get_leaderboard, browse_groups, get_my_groups, get_group_members, start_study, stop_study.

Известные особенности

Для работы get_leaderboard в репозитории ypt-private-client исправлен хелпер _get() в src/ypt_python/_models.py: теперь null-значения (которые API присылает для si/tc) игнорируются и заменяются дефолтом вместо падения int(None). Фикс входит в текущий HEAD ветки main и подтягивается автоматически через git-источник ypt-python.

Available Tools

9 tools
browse_groupsB

Browse public study groups.

:param category_id: Filter by category ID; ``0`` means all categories.
    Default ``0``.
:type category_id: int
:param page: Page number. Default ``1``.
:type page: int
:param country_id: Filter by country ID; omit for all countries.
:type country_id: int | None
:param order_type: Sort order, e.g. ``"promotedAt"``. Default
    ``"promotedAt"``.
:type order_type: str
:param only_available: Show only groups with free slots. Default
    ``False``.
:type only_available: bool
:param only_open: Show only open groups. Default ``False``.
:type only_open: bool
:param only_cam: Show only groups with camera verification. Default
    ``False``.
:type only_cam: bool
:returns: List of group mappings with ``id``, ``title``, ``category``,
    ``owner``, ``slogan`` and ``member_count``.
:rtype: list[dict[str, Any]]
:raises RuntimeError: If YPT credentials are not configured.
ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
only_camNo
only_openNo
country_idNo
order_typeNopromotedAt
category_idNo
only_availableNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries some burden. It discloses a RuntimeError condition (YPT credentials not configured), which is useful behavioral context. However, it doesn't mention pagination behavior, rate limits, or that results are paginated. The credential requirement is a good addition.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured as a docstring with :param: and :type: lines, which is verbose. The core purpose sentence is front-loaded, but the parameter documentation repeats the schema and is not as concise as it could be. It earns its place but is longer than ideal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 7 parameters, no annotations, and a rich output schema, the description is largely complete: it documents all parameters, return values, and error conditions. The presence of an output schema reduces the need to describe returns, but it does so anyway. Missing: pagination details and explicit sibling differentiation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It does so effectively by documenting every parameter with type, default, and meaning (e.g., category_id 0 means all, only_available shows free slots). This is a strong parameter documentation effort that fills the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb 'Browse' + resource 'public study groups', and it implies a listing/discovery operation distinct from get_my_groups. However, it doesn't explicitly differentiate itself from siblings like get_my_groups in the description text.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this vs get_my_groups or other siblings. It's inferable from the name and 'public' qualifier, but there's no explicit when-to-use or exclusion criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_day_logA

Return your study log for the given date.

:param date: Date in YYYY-MM-DD format, e.g. ``"2026-09-12"``.
:type date: str
:returns: Mapping with ``date``, ``study_ms``/``study_hours``,
    ``rest_ms``/``rest_hours``, ``max_study_ms``/``max_study_hours``,
    ``added_ms``/``added_hours`` and a ``subjects`` list of
    ``{subject_id, subject_title, study_ms, study_hours}``.
:rtype: dict[str, Any]
:raises RuntimeError: If YPT credentials are not configured.
ParametersJSON Schema
NameRequiredDescriptionDefault
dateYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and mostly succeeds: it discloses an authentication precondition via "Raises RuntimeError: If YPT credentials are not configured" and that the operation is a read ("Return"). It does not mention rate limits, permissions beyond credentials, or behavior for missing dates, but the auth disclosure is real value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The summary sentence is front-loaded before the docstring blocks, and the return-value enumeration is informative rather than padded. The Sphinx-style :param:/:type:/:rtype: boilerplate is slightly verbose for a one-parameter tool but not wasteful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter read tool, the description covers the date format, the auth failure mode, and the result shape, which is enough for correct invocation. Since an output schema exists, the return-value prose is redundant, and there is no guidance on how the tool relates to sibling reads.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate — and it does, fully documenting the sole parameter with the exact format (YYYY-MM-DD) and a concrete example. Nothing more is needed for a single required string parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a concrete verb and resource ("Return your study log") scoped to a specific date, which is unambiguous. It is naturally distinct from the read-only siblings (get_profile, get_leaderboard, get_my_groups), though it never explicitly states that differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this versus other read tools, no prerequisites, and no exclusions. The only implied usage is the required date argument, which the schema already enforces.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_group_membersA

Return the members of a study group with their study stats.

:param group_id: Study group ID, e.g. from ``get_my_groups``.
:type group_id: int
:param country_id: Country ID, as returned by ``get_profile``.
:type country_id: int
:returns: List of member mappings with ``user_id``, ``nickname``,
    ``category``, ``study_ms``/``study_hours`` and ``studying``
    (bool, whether the member is currently studying).
:rtype: list[dict[str, Any]]
:raises RuntimeError: If YPT credentials are not configured.
ParametersJSON Schema
NameRequiredDescriptionDefault
group_idYes
country_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It discloses the RuntimeError precondition (YPT credentials not configured) and that 'studying' is a live/current-state boolean, both genuinely useful behavioral context. It does not address pagination, size limits, or data-access/privacy constraints on other members.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded in the first line, followed by an organized param/returns/raises block. Some redundancy exists — ':type group_id: int' and the :rtype line restate what the schema and output schema already provide — but nothing is confusing or padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Both required parameters are documented, the error case is disclosed, and an output schema exists so enumerated return fields aren't strictly needed (the description lists them anyway). For a simple two-param lookup this is close to complete; only cross-tool usage guidance is thin.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate — and it does, documenting both parameters in Sphinx form with an example source for group_id and a provenance note for country_id. Format details (int) are left to the schema, but the semantic intent of each param is clear.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Return the members of a study group') and adds scope detail ('with their study stats'), which cleanly separates it from sibling get_my_groups (lists groups) and get_leaderboard/get_my_rank (rankings). An agent can identify the right tool from the title line alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: the description tells you where group_id comes from ('get_my_groups') and country_id ('get_profile'), which effectively prescribes a call sequence, but it never says when to prefer this tool over alternatives or any exclusion conditions. Provenance hints are useful but fall short of explicit guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_leaderboardA

Return the category leaderboard (top studiers) for a date.

:param category_id: Category ID, as returned by ``get_profile``.
:type category_id: int
:param country_id: Country ID, as returned by ``get_profile``.
:type country_id: int
:param date: Leaderboard date in YYYY-MM-DD format.
:type date: str
:param page: Page number, 20 entries per page. Default ``1``.
:type page: int
:param rank_type: Ranking period, ``"day"`` or ``"week"``. Default
    ``"day"``.
:type rank_type: str
:param limit: Maximum number of members to return. Default ``20``.
:type limit: int
:returns: Mapping with ``total_count`` and the ``members`` list of
    ``{nickname, user_id, study_ms, study_hours, studicon_id}``.
:rtype: dict[str, Any]
:raises RuntimeError: If YPT credentials are not configured.
ParametersJSON Schema
NameRequiredDescriptionDefault
dateYes
pageNo
limitNo
rank_typeNoday
country_idYes
category_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It discloses a RuntimeError when YPT credentials are not configured, which is useful behavioral context, but does not state whether this is a read-only operation, rate limits, or any mutation behavior. For a read tool with no annotations this is adequate but thin.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose followed by structured parameter documentation. It is slightly verbose with repeated :type lines, but every line carries meaning and nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-param list tool with an output schema present, the description covers provenance, formats, enums, defaults, pagination, return structure collapsed into a brief summary, and the auth error condition. Nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: it documents all six parameters including provenance (as returned by get_profile), format (YYYY-MM-DD), page size (20 entries), rank_type values (day/week), and defaults for page, rank_type, and limit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Return) and resource (category leaderboard of top studiers) with scope (for a date). An agent can distinguish it from siblings like get_my_rank or get_profile without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by noting category_id and country_id come from get_profile, which helps locate required inputs, but it never explains when to use this tool versus get_my_rank or other profile tools, nor any exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_my_groupsA

Return the list of study groups you have joined.

:returns: List of group mappings with ``id``, ``title``, ``category``,
    ``owner``, ``slogan`` and ``member_count``.
:rtype: list[dict[str, Any]]
:raises RuntimeError: If YPT credentials are not configured.
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does reasonably well: it discloses the credential precondition ('raises RuntimeError if YPT credentials are not configured') and enumerates the returned fields. It does not state rate limits, pagination, or cache behavior, but the auth requirement is the meaningful non-obvious trait.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core sentence is front-loaded and short, but it is followed by reStructuredText boilerplate (:rtype:, :returns:) that duplicates the output schema rather than adding agent-relevant information. Roughly half the text is structured noise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the field enumeration is redundant, and the credential-failure behavior covers the main non-obvious risk. For a zero-parameter read tool this is nearly complete; only pagination or scope caveats are missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a parameterless tool is 4. The description correctly presents this as a no-argument listing call.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Return the list of study groups') and scopes it with 'you have joined', which implicitly separates it from browse_groups (all groups) and get_group_members. It stops short of naming any sibling explicitly, so the differentiation must be inferred.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no prerequisites section, and no mention of alternatives such as browse_groups for discovering groups you have not joined. The only hint at context is the phrase 'you have joined', which merely restates the tool's identity rather than giving selection criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_my_rankA

Return your position in a category leaderboard.

:param category_id: Category ID, as returned by ``get_profile``.
:type category_id: int
:param country_id: Country ID, as returned by ``get_profile``.
:type country_id: int
:returns: Your 1-based rank as ``int``, or ``None`` when no rank is
    available for the category.
:rtype: int | None
:raises RuntimeError: If YPT credentials are not configured.
ParametersJSON Schema
NameRequiredDescriptionDefault
country_idYes
category_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does disclose meaningful behavior: it raises RuntimeError when YPT credentials are not configured (an auth prerequisite), returns 1-based ranks, and returns None when no rank exists. It does not discuss permissions, rate limits, or whether country/category must match the profile, so it stops short of complete.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose sentence is front-loaded and efficient, but the Sphinx-style :type: lines restate the integer types already present in the input schema, adding noise without new meaning. The :returns:/:rtype: block is also partly redundant given the output schema exists.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 2-param read tool with an output schema, the description covers purpose, parameter provenance, the None return case, and the credential error path. The main remaining gap is the absence of any relationship to the get_leaderboard sibling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: both category_id and country_id are documented with their provenance ('as returned by get_profile'), which tells the agent where to obtain valid values. It adds no format/range constraints beyond that.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Return your position in a category leaderboard') and the possessive 'your' implicitly separates it from the general get_leaderboard sibling. However, it never names get_leaderboard or otherwise explicitly differentiates itself, so sibling disambiguation is left to inference.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the personal-rank framing and the note that both IDs come 'as returned by get_profile', which is a useful call-order hint. But there is no explicit when-to-use / when-not-to-use guidance or statement of how it relates to get_leaderboard.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_profileA

Return the logged-in YPT profile with today's study overview.

:returns: Mapping with ``nickname``, ``email``, ``category_code``,
    ``category_id``, ``country_id``, the ``subjects`` list
    (``id``, ``title``, ``study_ms``/``study_hours``, ``archived``) and
    the ``day_log`` for today (see the day-log shape in
    ``get_day_log``).
:rtype: dict[str, Any]
:raises RuntimeError: If YPT credentials are not configured.
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses the credential prerequisite via ':raises RuntimeError: If YPT credentials are not configured.' and describes the returned mapping fields, which is meaningful behavioral context for a read operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The first sentence front-loads the purpose cleanly and the rest is structured reST. The returns block partially duplicates the existing output schema, but it is compact and the cross-reference to get_day_log earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-param, read-only session tool with an output schema, the description is adequate: purpose, return shape, and the credential failure mode are all covered. It omits only minor details such as whether the profile is cached or how the day_log boundary is computed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing to disambiguate; baseline 4 applies. The schema is fully described and the description adds no conflicting parameter guidance.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Return the logged-in YPT profile with today's study overview.' That distinguishes it from sibling reads like get_my_groups and get_my_rank, though it never explicitly contrasts itself with those alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the resource (fetch your own profile), but there is no explicit when-to-use guidance or named alternative. It relies on the agent inferring that this is the entry point for identity/session context rather than a filtered query like get_day_log.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

start_studyA

Start studying a subject and record the session start time.

The session start timestamp is stored on disk (so ``stop_study`` can be
called without arguments) and also returned as ``started_at`` for the
caller to keep.

:param subject: Subject title to start studying, e.g. ``"Матеша"``.
:type subject: str
:param device_model: Device model reported to the YPT API. Defaults to
    ``"ypt-mcp"``.
:type device_model: str
:returns: Mapping with ``started_at`` (epoch ms) plus the full day-log
    shape described in ``get_day_log``.
:rtype: dict[str, Any]
:raises RuntimeError: If YPT credentials are not configured.
ParametersJSON Schema
NameRequiredDescriptionDefault
subjectYes
device_modelNoypt-mcp

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses the persistence side effect (timestamp stored on disk), the auth prerequisite (RuntimeError if YPT credentials are not configured), and the returned started_at value. It does not cover idempotency or behavior when a session is already active, so it falls short of fully transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded in the first sentence and the supporting detail is well organized. The reST :param:/:type:/:rtype: lines are somewhat verbose and partially redundant for an agent reader, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values needn't be restated, yet the description still names started_at and the raises condition. Combined with auth, persistence, and both parameters documented, an agent has everything needed to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: subject gets a concrete example ('Матеша'), and device_model is explained as reported to the YPT API with its default. This is meaningful beyond the raw schema, though default values are already present in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource ('Start studying a subject') plus the side effect ('record the session start time'). It is immediately distinguishable from the sibling stop_study, which it also references, so an agent can tell the two apart without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied (begin a study session), and the description notes that stop_study can be called without arguments because the timestamp is persisted, which hints at the start/stop pairing. However, it never states explicitly when to use this versus get_day_log or what happens if a session is already running, so guidance is only implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

stop_studyA

Stop the study timer and finish the current session.

If ``started_at`` is omitted the timestamp recorded by :func:`start_study`
is used; the recorded value is cleared after a successful stop.

:param started_at: Session start time in epoch milliseconds, as returned
    by ``start_study``. Optional; defaults to the recorded session.
:type started_at: int | None
:param device_model: Device model reported to the YPT API. Defaults to
    ``"ypt-mcp"``.
:type device_model: str
:returns: The full day-log shape described in ``get_day_log``.
:rtype: dict[str, Any]
:raises RuntimeError: If there is no recorded session and ``started_at``
    is not provided, or if YPT credentials are not configured.
ParametersJSON Schema
NameRequiredDescriptionDefault
started_atNo
device_modelNoypt-mcp

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so: it discloses the state mutation (recorded timestamp is cleared after a successful stop), the exact RuntimeError conditions (no recorded session, missing credentials), and the credential prerequisite.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The behavioral content is front-loaded well, but Sphinx-style :type:/:rtype: markup duplicates the input schema and adds noise an agent gains nothing from.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Error conditions, side effects, and the reference to get_day_log for the return shape cover the essentials; since an output schema exists, not restating the return format is fine. Only the when-to-use framing is thin.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must document both parameters, and it does: started_at is defined as epoch milliseconds returned by start_study with a default-to-recorded-session behavior, and device_model's default is given. The :type: lines merely echo the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Stop the study timer and finish the current session') and ties itself to the sibling start_study, so an agent can distinguish it from other tools without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied through the pairing with start_study and the note that started_at defaults to the recorded session, but there is no explicit when-to-use/when-not guidance or named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 9 tool updatesv0.1.0
    • First observedbrowse_groups
    • First observedget_day_log
    • First observedget_group_members
    • First observedget_leaderboard
    • First observedget_my_groups
    • First observedget_my_rank
    • First observedget_profile
    • First observedstart_study
    • First observedstop_study

TDQS

A3.9/5.0

Scored across 9 tools

Disambiguation4/5

Each tool targets a distinct resource or action: groups (joined, browse, members), study sessions (start, stop), profile, day log, rank, and leaderboard. Minor overlap exists because get_profile includes today's day_log, but the descriptions clearly differentiate their primary purposes.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern (get_, browse_, start_, stop_). The 'my' qualifier is used consistently for personal resources, with no mixing of conventions.

Tool Count5/5

Nine tools cover groups, study sessions, logging, and rankings without redundancy. This is well within the 3-15 range for a focused MCP server.

Completeness4/5

Core read operations and the study timer lifecycle are fully covered. Missing group join/leave actions and subject creation are minor gaps that an agent can work around, but they prevent full group interaction.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    This MCP server exposes Riven's chat, research, council, and usage capabilities as tools over stdio, enabling any MCP-compatible client to interact with Riven directly.
    4
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables local text analysis, statistical calculations, and system information retrieval via the Model Context Protocol over stdio.
    -
  • A
    license
    A
    quality
    B
    maintenance
    Enables any MCP-compatible agent to query a local OpenRhyme activity timeline, search history, and issue control commands over stdio while keeping all data on-machine.
    5
    MIT