# MCP: чтение и дозапись персонального публичного чата (type=100)

Документ для реализации MCP-инструмента, который:
- читает переписку между двумя логинами (`from`, `to`);
- добавляет новое сообщение от отправителя через серверный `AddBlock`.

Важно: речь про **персональные публичные** каналы (`channelTypeCode=100`), а не приватные DM.

## 1. Базовые предпосылки

1. У каждого пользователя свой блокчейн (`<login>-001`).
2. Персональный публичный чат хранится как канал типа `100`:
   - у `A` канал с `channelName = B`;
   - у `B` зеркальный канал с `channelName = A`.
3. Сообщения канала — `TEXT_POST` и `TEXT_REPOST` в линии `line_code = rootBlockNumber` канала.
4. Запись блока возможна только при валидной подписи blockchain-ключом владельца цепочки.

## 2. Что должен уметь MCP-инструмент

Минимальный набор операций:

1. `read_personal_public_dialog(fromLogin, toLogin, limitPerSide=200)`
2. `append_personal_public_message(fromLogin, toLogin, text)`

## 3. Алгоритм чтения переписки

### 3.1 Найти оба канала (прямой и зеркальный)

Для `fromLogin = A`, `toLogin = B`:

1. Запросить `ListSubscriptionsFeed` для `A` и найти owned-канал:
   - `ownerLogin == A`
   - `channelName == B`
   - `channelTypeCode == 100`
2. Запросить `ListSubscriptionsFeed` для `B` и найти owned-канал:
   - `ownerLogin == B`
   - `channelName == A`
   - `channelTypeCode == 100`

Если какой-то из каналов не найден — вернуть частичный результат + флаг отсутствия зеркала.

### 3.2 Вычитать сообщения из каналов

Для каждого найденного канала вызвать `GetChannelMessages`:

```json
{
  "op": "GetChannelMessages",
  "payload": {
    "login": "<текущий-login-сессии>",
    "channel": {
      "ownerBlockchainName": "...",
      "channelRootBlockNumber": 123,
      "channelRootBlockHash": "..."
    },
    "limit": 200,
    "sort": "asc"
  }
}
```

### 3.3 Склеить в единый диалог

1. Объединить массивы сообщений из `A->B` и `B->A`.
2. Отсортировать по `createdAtMs`, при равенстве — по `messageRef.blockNumber`.
3. Вернуть структуру:
   - `messages[]`
   - `directChannelFound` / `reverseChannelFound`
   - метаданные обоих каналов.

## 4. Алгоритм дозаписи сообщения

Цель: добавить сообщение **от имени `fromLogin`** в его канал `fromLogin -> toLogin`.

### 4.1 Найти канал отправителя

Через `ListSubscriptionsFeed(fromLogin)` найти owned-канал:
- `channelName == toLogin`
- `channelTypeCode == 100`

Если канал не найден — вернуть ошибку `channel_not_found`.

### 4.2 Отправить `AddBlock` с `TEXT_POST`

Использовать клиентский/серверный helper формирования `TEXT_POST` body:
- `lineCode = channelRootBlockNumber`;
- `prevLineNumber/prevLineHash` берутся из последнего сообщения линии;
- подпись — blockchain private key пользователя `fromLogin`.

Если у вас в MCP нет приватного ключа пользователя, дозапись невозможна.

## 5. Контракт MCP (рекомендуемый)

## `read_personal_public_dialog`

Вход:
```json
{
  "fromLogin": "alice",
  "toLogin": "bob",
  "limitPerSide": 200
}
```

Выход:
```json
{
  "ok": true,
  "directChannelFound": true,
  "reverseChannelFound": true,
  "messages": [
    {
      "authorLogin": "alice",
      "text": "Привет",
      "createdAtMs": 1760000000000,
      "channelSide": "alice->bob",
      "messageRef": { "blockNumber": 11, "blockHash": "..." }
    }
  ]
}
```

## `append_personal_public_message`

Вход:
```json
{
  "fromLogin": "alice",
  "toLogin": "bob",
  "text": "Тест"
}
```

Выход:
```json
{
  "ok": true,
  "serverLastGlobalNumber": 321,
  "serverLastGlobalHash": "..."
}
```

## 6. Ограничения и безопасность

1. Персональный канал типа `100` сейчас публичный по модели чтения (не E2E DM).
2. Нельзя дозаписать блок в чужой блокчейн без приватного ключа владельца (проверка подписи сервером).
3. Для прод-инструмента нужно:
   - строгая авторизация MCP-вызовов;
   - аудит, кто и от чьего имени запрашивал чтение/запись;
   - лимиты/квоты на запись.

## 7. Мини-чеклист для реализации MCP

1. Реализовать helper поиска канала `findOwnedPersonalChannel(ownerLogin, peerLogin)`.
2. Реализовать чтение двух сторон и merge/sort.
3. Реализовать отправку `TEXT_POST` в найденный канал отправителя.
4. Добавить понятные ошибки:
   - `user_not_found`
   - `channel_not_found`
   - `reverse_channel_not_found`
   - `signature_required`
   - `add_block_failed`
