# 服務發現

> LMSP 客戶端如何透過手動設定、探測本機位址和可選的 mDNS/DNS-SD 找到本地服務，以及如何讀取 Well-Known 服務描述文件。

Source: https://madeforagent.com/zh-tw/lmsp/1.0/discovery/
Language: zh-TW
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. **區域網路發現。** 客戶端透過 mDNS 與 DNS-SD 瀏覽 `_lmsp._tcp.local.`。

某種方式只要得到一份有效的服務描述（[第 3.3 節](https://madeforagent.com/zh-tw/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` | 廣播格式的版本。LMSP 1.0 為 `1`。 |
| `id` | 服務 id，與服務描述中的 `service.id` 相同。 |
| `path` | 服務根路徑的 URL 路徑。客戶端請求 `{path}.well-known/lmsp.json`。 |
| `auth` | 驗證提示。`pairing` 表示客戶端必須先配對才能使用服務。 |

規則：

- 服務**不得**在 TXT 記錄中放置存取權杖、模型清單、檔案路徑或其他敏感資訊。該記錄只負責找到服務，真實能力**必須**從服務描述中讀取。
- 服務**必須**預設關閉 mDNS 廣播，僅在使用者明確開啟「區域網路發現」時才啟用。僅在本機使用的服務無需廣播。
- 在區域網路中廣播的服務需要監聽回送位址之外的位址，而這只有在區域網路模式下才被允許（[第 10.5 節](https://madeforagent.com/zh-tw/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/zh-tw/lmsp/1.0/security.md#pairing)）。 |
| `openapi` | 描述 LMSP 介面的 OpenAPI 文件的 URL。 |

能力旗標：

| 旗標 | 含義 |
| --- | --- |
| `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` 而不是位址來記住所選的服務，因為位址可能變化。
