ypt-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ypt-mcphow many hours did I study today, and what's my rank?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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-mcpuvx сам подтянет 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"
}
}
}
}Тулы
Тул | Назначение |
| Профиль, категория/страна, предметы, сводка за сегодня |
| Лог учёбы за дату |
| Твоё место в рейтинге категории |
| Таблица лидеров категории |
| Поиск публичных групп |
| Твои группы |
| Участники группы |
| Старт таймера учёбы |
| Стоп таймера учёбы |
Время отдаётся в часах (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": "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)
Аргумент | Тип | Описание |
|
| ID категории из |
|
| ID страны из |
Вернёт число (номер места) или null, если рейтинга нет.
get_leaderboard(category_id, country_id, date, page, rank_type, limit)
Аргумент | Тип | Дефолт | Описание |
|
| — | ID категории |
|
| — | ID страны |
|
| — | Дата |
|
|
| Номер страницы (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)
Аргумент | Тип | Дефолт | Описание |
|
|
| Фильтр по категории (0 = все) |
|
|
| Номер страницы |
|
|
| Фильтр по стране |
|
|
| Сортировка |
|
|
| Только группы со свободными местами |
|
|
| Только открытые группы |
|
|
| Только с камерой |
get_my_groups
Без аргументов. Список групп с id, title, owner, member_count.
get_group_members(group_id, country_id)
Аргумент | Тип | Описание |
|
| ID группы |
|
| ID страны |
У каждого участника: user_id, nickname, category, study_hours,
studying (учится ли прямо сейчас).
start_study(subject, device_model) / stop_study(started_at, device_model)
Аргумент | Тип | Дефолт | Описание |
|
| — | Название предмета (для start) |
|
|
| Старт сессии epoch ms (для stop) |
|
|
| Модель устройства для 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())Обработка ошибок
Ситуация | Поведение |
Нет токена и нет | Ошибка с сообщением «credentials not found» |
Протухший токен | Сервер перелогинится и повторит вызов автоматически |
| Ошибка — нужен |
Ошибки YPT API / сети | Пробрасываются выше с кодом/текстом из библиотеки |
Архитектура
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 toolsbrowse_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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | ||
| only_cam | No | ||
| only_open | No | ||
| country_id | No | ||
| order_type | No | promotedAt | |
| category_id | No | ||
| only_available | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| group_id | Yes | ||
| country_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | ||
| page | No | ||
| limit | No | ||
| rank_type | No | day | |
| country_id | Yes | ||
| category_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| country_id | Yes | ||
| category_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| subject | Yes | ||
| device_model | No | ypt-mcp |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| started_at | No | ||
| device_model | No | ypt-mcp |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
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.
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.
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.
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.
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.
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.
9 tool updates
v0.1.0- First observed
browse_groups - First observed
get_day_log - First observed
get_group_members - First observed
get_leaderboard - First observed
get_my_groups - First observed
get_my_rank - First observed
get_profile - First observed
start_study - First observed
stop_study
TDQS
Scored across 9 tools
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.
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.
Nine tools cover groups, study sessions, logging, and rankings without redundancy. This is well within the 3-15 range for a focused MCP server.
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
Related MCP Connectors
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
Host your MCP tool over streamable HTTP in one command.
Model Context Protocol server for Studex tools, notifications, and profile integrations
Remote MCP server for full read/write access to a Zotero library
Related MCP Servers
- AlicenseAqualityBmaintenanceThis 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.4MIT
- FlicenseNot gradedqualityBmaintenanceExposes read-only capabilities from the Baihua home server to any MCP client via stdio, including knowledge base search/reading, budget summary, and task listing.-
- FlicenseNot gradedqualityCmaintenanceEnables local text analysis, statistical calculations, and system information retrieval via the Model Context Protocol over stdio.-

openrhyme-mcpofficial
AlicenseAqualityBmaintenanceEnables 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.5MIT