Skip to main content
Glama
slartus
by slartus
README.md
# mcp-yandex-wiki

Минимальный MCP-сервер для [Яндекс Вики](https://wiki.yandex.ru/) (read + write).

## Установка

```bash
cd ~/.claude/mcp/yandex-wiki
npm install
```

Регистрация в `~/.claude.json`:

```json
{
  "mcpServers": {
    "yandex-wiki": {
      "type": "stdio",
      "command": "node",
      "args": ["/Users/<user>/.claude/mcp/yandex-wiki/index.mjs"],
      "env": {
        "YW_OAUTH_TOKEN": "y0__...",
        "YW_ORG_ID": "1234567",
        "YW_ORG_HEADER": "X-Org-Id"
      }
    }
  }
}
```

## Переменные окружения

| Переменная | Обязательна | Описание |
|---|---|---|
| `YW_OAUTH_TOKEN` | да | OAuth-токен Яндекса со скоупом `wiki:read` / `wiki:write` |
| `YW_ORG_ID` | да | ID организации |
| `YW_ORG_HEADER` | нет | `X-Org-Id` для Яндекс 360 (по умолчанию), `X-Cloud-Org-Id` для Yandex Cloud Organization |

Токен от Яндекс Трекера подходит, если тому же приложению выданы и wiki-скоупы — механика авторизации общая (`OAuth` + заголовок организации). Подробнее — [Про скоупы токена](#про-скоупы-токена).

Сервисный аккаунт Yandex Cloud для Wiki API не годится — только пользовательский.

## Инструменты

| Инструмент | API | Описание |
|---|---|---|
| `myself` | `GET /users/me` | Текущий пользователь, организация, домашний кластер |
| `get_page` | `GET /pages?slug=` / `GET /pages/{id}` | Страница по slug или id. Тело — только при `fields: ["content"]` |
| `search` | `POST /search` | Полнотекстовый поиск, до 10 результатов |
| `list_descendants` | `GET /pages/{id}/descendants` | Подстраницы |
| `list_resources` | `GET /pages/{id}/resources` | Вложения + таблицы одним списком |
| `list_attachments` | `GET /pages/{id}/attachments` | Вложения |
| `list_grids` | `GET /pages/{id}/grids` | Динамические таблицы |
| `create_page` | `POST /pages` | Создать страницу (`slug`, `title` обязательны) |
| `update_page` | `POST /pages/{id}` | Изменить `title` / `content` / `slug` |
| `delete_page` | `DELETE /pages/{id}` | Удалить страницу (необратимо) |

### `fields` у `get_page`

`redirect`, `breadcrumbs`, `attributes`, `content`, `access_policy`, `access_lists`, `owner`.

Без `fields` возвращаются только `id`, `slug`, `title`, `page_type`.

## Особенности API

- **Поиск не пагинируется.** `total_pages` всегда `1`, отдаётся максимум 10 результатов; параметры `page` / `offset` игнорируются. Сужай запрос.
- **`PATCH` и `PUT` не поддерживаются.** Обновление — это `POST /pages/{id}`. Разрешённые методы: `/pages` → `POST, GET`; `/pages/{id}` → `POST, GET, DELETE`.
- **Readonly-страницы отдают HTTP 403** на запись — см. [Как читать HTTP 403](#как-читать-http-403).

## Статус проверок

| Инструмент | Статус |
|---|---|
| `myself`, `get_page`, `search`, `list_descendants`, `list_resources`, `list_attachments`, `list_grids` | проверены на живом API |
| `update_page` | проверен: round-trip заголовка на реальной странице, контент побайтово не изменился |
| `create_page`, `delete_page` | **не проверялись** — схема восстановлена из ошибок валидации API и заголовка `Allow` |

### Про скоупы токена

Документация [называет два скоупа](https://yandex.ru/support/wiki/ru/api-ref/access): `wiki:read` (только чтение) и `wiki:write` (создание, редактирование, удаление). Плюс отдельный гейт — права пользователя: «запросы выполняются от имени пользователя… пользователь должен иметь соответствующие права в Вики».

**На практике wiki-скоупы оказались не нужны.** Токен приложения, которому выданы только скоупы Яндекс Трекера и ни одного wiki-скоупа, читает и пишет в Вики без ошибок — проверено на живом API, включая `POST` на страницу.

Механика этого не установлена, возможны два объяснения:

- Wiki API не проверяет скоуп вообще и пускает по личности пользователя;
- скоуп Трекера покрывает и Вики по дизайну — сервисы одного продуктового куста.

Различить можно токеном с посторонним скоупом (например, только `login:info`): пройдёт — первое, `403` — второе.

Enforcement у Яндекса **посервисный, а не глобальный**: тот же токен на Яндекс.Диск (`cloud_api:disk.read` не выдан) получает `HTTP 403 «Возможно, у приложения недостаточно прав»`. То есть «Диск проверяет скоуп» не означает, что его проверяет Вики — не переносите вывод с одного API на другое.

Практический итог: **если у вас уже есть токен Яндекс Трекера, отдельные wiki-скоупы можно не выдавать.** Обратная сторона — отдельный «wiki-only» токен не изолирует Вики: её откроет и токен Трекера.

### Как читать HTTP 403

Скоуп тут почти наверняка ни при чём — смотрите на права:

- у пользователя нет прав на страницу;
- страница readonly: `get_page` с `fields: ["attributes"]` → `attributes.is_readonly`. Системные страницы (владелец `yandex360-wiki`) readonly — например, главная.

Если 403 приходит вообще на всё, включая чтение, — проверьте `X-Org-Id` и то, что токен принадлежит пользователю, а не сервисному аккаунту.

### Побочный эффект записи

Любой `POST /pages/{id}` бампает `modified_at`, даже если в теле нет ни одного значимого поля. Страница отметится как изменённая.