# Обнаружение сервисов

> Как клиенты LMSP находят локальный сервис через ручную настройку, проверку loopback-адресов и необязательные mDNS/DNS-SD, и как читать well-known-документ с описанием сервиса.

Source: https://madeforagent.com/ru/lmsp/1.0/discovery/
Language: ru
Specification: LMSP 1.0 (draft)
Updated: 2026-11-08

## 3.1 Способы обнаружения {#methods}

Клиент обнаруживает сервис, пробуя эти способы по порядку:

1. **Ручная настройка.** Пользователь вводит адрес сервиса напрямую.
2. **Проверка стандартных локальных адресов.** Клиент запрашивает `/.well-known/lmsp.json` по адресам-кандидатам. Стандартные кандидаты — `http://127.0.0.1:17832` и `http://[::1]:17832`.
3. **Обнаружение в локальной сети.** Клиент ищет `_lmsp._tcp.local.` через mDNS и DNS-SD.

Способ считается успешным, если он даёт корректное описание сервиса ([раздел 3.3](https://madeforagent.com/ru/lmsp/1.0/discovery.md#service-description)). Адрес, введённый пользователем вручную, всегда имеет приоритет над обнаруженными.

## 3.2 Объявление в локальной сети {#mdns}

DNS-SD использует записи PTR для поиска экземпляров сервиса, записи SRV для получения хоста и порта и записи TXT для передачи небольшого объёма дополнительных сведений. Вместе с mDNS он обеспечивает обнаружение без настройки в локальной сети ([RFC 6763](https://www.rfc-editor.org/rfc/rfc6763), [RFC 6762](https://www.rfc-editor.org/rfc/rfc6762)).

Пример объявления:

```text
Service type:   _lmsp._tcp.local.
Instance name:  Workstation LMSP._lmsp._tcp.local.

TXT record:
  v=1
  id=svc_01J8M4Y8K6M5E6K6Z7Z0Y8W3M2
  path=/
  auth=pairing
```

| Ключ TXT | Значение |
| --- | --- |
| `v` | Версия формата объявления. `1` для LMSP 1.0. |
| `id` | Идентификатор сервиса, равный `service.id` в описании сервиса. |
| `path` | Путь URL к корню сервиса. Клиенты запрашивают `{path}.well-known/lmsp.json`. |
| `auth` | Подсказка об аутентификации. `pairing` означает, что клиент должен пройти сопряжение, прежде чем пользоваться сервисом. |

Правила:

- Сервис **НЕ ДОЛЖЕН** помещать в запись TXT токены доступа, списки моделей, пути к файлам и любые другие чувствительные сведения. Запись лишь указывает, где находится сервис. Реальные возможности **ДОЛЖНЫ** считываться из описания сервиса.
- Сервис **ДОЛЖЕН** по умолчанию держать объявление mDNS выключенным. Оно включается только тогда, когда пользователь явно включил обнаружение в локальной сети. Сервис, который используется только на локальной машине, ничего не объявляет.
- Сервис, объявляющий себя в локальной сети, вынужден слушать не только loopback, а это разрешено только в режиме LAN ([раздел 10.5](https://madeforagent.com/ru/lmsp/1.0/security.md#lan)).
- Клиент **ДОЛЖЕН** считать запись TXT непроверенной подсказкой и подтверждать сервис, прочитав его описание.

## 3.3 Описание сервиса {#service-description}

```http
GET /.well-known/lmsp.json
```

Сервис **ДОЛЖЕН** отдавать этот документ как `application/json` без требования аутентификации.

```json
{
  "protocol": "lmsp",
  "versions": ["1.0"],
  "service": {
    "id": "svc_01J8M4Y8K6M5E6K6Z7Z0Y8W3M2",
    "name": "Workstation Local Models",
    "version": "1.0.0"
  },
  "interfaces": [
    {
      "kind": "lmsp",
      "version": "1.0",
      "url": "http://127.0.0.1:17832/lmsp/v1",
      "transport": "http+json"
    },
    {
      "kind": "openai",
      "version": "responses+chat",
      "url": "http://127.0.0.1:17832/v1",
      "transport": "http+json"
    }
  ],
  "capabilities": {
    "streaming": true,
    "tasks": true,
    "event_resume": true,
    "conversations": true,
    "model_management": true
  },
  "authentication": {
    "type": "bearer",
    "pairing_url": "http://127.0.0.1:17832/lmsp/v1/pair"
  },
  "openapi": "http://127.0.0.1:17832/lmsp/v1/openapi.json"
}
```

| Поле | Значение |
| --- | --- |
| `protocol` | Всегда `"lmsp"`. |
| `versions` | Версии LMSP, которые поддерживает сервис, в виде строк `major.minor`. |
| `service` | `id` — стабильный идентификатор сервиса, `name` — отображаемое имя, `version` — версия программного обеспечения сервиса. |
| `interfaces` | Предлагаемые интерфейсы. У каждого есть `kind` (`lmsp`, `openai` или `ollama`), `version`, базовый `url` и `transport`. Для `openai` в `version` указаны обслуживаемые семейства API, например `responses+chat`. |
| `capabilities` | Булевы флаги возможностей, перечисленные ниже. |
| `authentication` | `type` — `bearer`. `pairing_url` — адрес, по которому клиенты обменивают код сопряжения на токен ([раздел 10.2](https://madeforagent.com/ru/lmsp/1.0/security.md#pairing)). |
| `openapi` | URL документа OpenAPI, описывающего интерфейс LMSP. |

Флаги возможностей:

| Флаг | Значение |
| --- | --- |
| `streaming` | Ответы можно передавать потоком в виде событий, отправляемых сервером. В версии 1.0 флаг **ДОЛЖЕН** быть `true`. |
| `tasks` | Доступны асинхронные задачи. В версии 1.0 флаг **ДОЛЖЕН** быть `true`. |
| `event_resume` | На потоки событий задач можно подписаться и возобновить их (`GET /lmsp/v1/tasks/{task_id}/events`). |
| `conversations` | Сервис хранит ответы, поэтому работают `store` и `previous_response_id`, а `GET /lmsp/v1/responses/{response_id}` доступен. |
| `model_management` | Модели можно загружать и выгружать явно. |

## 3.4 Поведение клиента {#client-behavior}

Клиент:

- **СЛЕДУЕТ** выбирать наибольшую версию из `versions`, которую он тоже поддерживает.
- **СЛЕДУЕТ** выбирать из `interfaces` интерфейс LMSP или интерфейс OpenAI в зависимости от того, на каком из них он умеет работать.
- **ДОЛЖЕН** использовать только те возможности, которые объявлены в описании. Отсутствующий флаг означает `false`.
- **ДОЛЖЕН** игнорировать поля расширений, которых он не знает.
- **СЛЕДУЕТ** периодически перечитывать описание сервиса, а также при сбое запроса, а не кэшировать его навсегда.
- **СЛЕДУЕТ** запоминать выбранный сервис по `service.id`, а не по адресу, потому что адреса могут меняться.
