서비스 검색

3.1 검색 방법

클라이언트는 다음 방법을 순서대로 시도하여 서비스를 찾는다.

  1. 수동 설정. 사용자가 서비스 주소를 직접 입력한다.
  2. 관례적인 로컬 주소 탐색. 클라이언트가 후보 주소에 /.well-known/lmsp.json을 요청한다. 관례적인 후보는 http://127.0.0.1:17832와 http://[::1]:17832이다.
  3. LAN 검색. 클라이언트가 mDNS와 DNS-SD로 _lmsp._tcp.local.을 탐색한다.

유효한 서비스 설명(3.3절)을 얻으면 그 방법은 성공이다. 사용자가 직접 입력한 주소는 항상 검색된 주소보다 우선한다.

3.2 LAN 광고

DNS-SD는 PTR 레코드로 서비스 인스턴스를 찾고, SRV 레코드로 호스트와 포트를 얻고, TXT 레코드로 소량의 추가 정보를 전달한다. mDNS와 결합하면 로컬 네트워크에서 무구성 검색을 제공한다(RFC 6763, RFC 6762).

광고 예시:

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 광고를 기본적으로 비활성화해 두어야 한다. 사용자가 LAN 검색을 명시적으로 켠 경우에만 활성화된다. 로컬 컴퓨터에서만 쓰는 서비스는 광고하지 않는다.
  • LAN에서 광고하는 서비스는 루프백 밖에서도 수신 대기해야 하는데, 이는 LAN 모드에서만 허용된다(10.5절).
  • 클라이언트는 TXT 레코드를 검증되지 않은 힌트로 취급하고, 서비스 설명을 읽어 서비스를 확인해야 한다.

3.3 서비스 설명

GET /.well-known/lmsp.json

서비스는 이 문서를 인증을 요구하지 않고 application/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절).
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 클라이언트 동작

클라이언트는 다음과 같이 한다.

  • versions 중 자신도 지원하는 가장 높은 버전을 선택하는 것이 좋다.
  • 자신이 사용할 수 있는 방식에 따라 interfaces에서 LMSP 인터페이스 또는 OpenAI 인터페이스를 선택하는 것이 좋다.
  • 서비스 설명이 선언한 기능만 사용해야 한다. 플래그가 없으면 false를 뜻한다.
  • 인식하지 못하는 확장 필드는 무시해야 한다.
  • 서비스 설명을 영원히 캐시하지 말고, 주기적으로 그리고 요청이 실패했을 때 다시 읽는 것이 좋다.
  • 선택한 서비스는 주소가 아니라 service.id로 기억하는 것이 좋다. 주소는 바뀔 수 있기 때문이다.