Lunara

Subtitle engine for AI agents: one upload gives a written track and a translation, timings exact.

使うべきか

品質と安全性

A
説明の品質
96%
スキーマの完全性
96%
命名の品質
80%
ポイズニングのリスク
100%
権限の一致
100%
プロトコルへの準拠
100%

検出事項(1)

  • LOWTool 'lunara_rewrite' description lacks action verblunara_rewrite 内

ツール定義とプロトコルへの準拠に関する自動分析に基づいています。

コンテキストコスト

~3,037トークン数(ツール定義)
~1.0 KB一般的なレスポンスサイズ
注意への影響は大きい(128k コンテキストの 2.37%)

これは、サーバーのツールがモデルのコンテキストに読み込まれるたびに消費されるおおよそのトークン数です。数が多いほど、ほかのタスクに使える注意が減ります。

インストール

ワンクリックインストール

これを `claude_desktop_config.json` ファイルに追加してください:

{
  "mcpServers": {
    "lunara": {
      "url": "https://lunaraai.cc/api/lunara/mcp"
    }
  }
}

リモートエンドポイント

https://lunaraai.cc/api/lunara/mcpstreamable-http
https://lunaraai.cc/mcpstreamable-http

できること

ツール一覧

ツール(18)

🟢 読み取り専用🟡 書き込み🔴 削除⚪ 不明
🟢lunara_list_tools

Return every subtitle tool Lunara exposes, with the minutes each one costs. Call this first when you are unsure which tool fits.

入力スキーマ

{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}
🟢lunara_get_job(jobId)

Return the state of a subtitle job: status, progress, whether the SRT is ready, and how many cues it has. Poll this after lunara_upload_video.

入力スキーマ

{
  "type": "object",
  "properties": {
    "jobId": {
      "type": "string",
      "description": "The job id returned by lunara_upload_video."
    }
  },
  "required": [
    "jobId"
  ],
  "additionalProperties": false
}
🟢lunara_get_srt(jobId, track)

Return the subtitle file for a finished job. One line per cue. Use track="secondary" for the translated track (English by default).

入力スキーマ

{
  "type": "object",
  "properties": {
    "jobId": {
      "type": "string",
      "description": "The job id."
    },
    "track": {
      "type": "string",
      "enum": [
        "primary",
        "secondary"
      ],
      "description": "primary = the written-language track; secondary = the translation."
    }
  },
  "required": [
    "jobId"
  ],
  "additionalProperties": false
}
🟢lunara_list_cues(jobId, offset, limit)

Return subtitle cues for a job as timestamps plus text, so you can inspect or reference individual lines before proposing edits.

入力スキーマ

{
  "type": "object",
  "properties": {
    "jobId": {
      "type": "string",
      "description": "The job id."
    },
    "offset": {
      "type": "integer",
      "minimum": 0,
      "description": "Skip this many cues. Default 0."
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 500,
      "description": "How many cues to return. Default 100."
    }
  },
  "required": [
    "jobId"
  ],
  "additionalProperties": false
}
🟡lunara_start_subtitle_job(audioUrl, primaryLang, secondaryLang, spokenLang)

Run the full eight-layer subtitle pipeline on an audio or video URL you can already host. Produces a written-language track and a translated track. Prefer lunara_upload_video when the file is local.

入力スキーマ

{
  "type": "object",
  "properties": {
    "audioUrl": {
      "type": "string",
      "description": "A URL Lunara can download (public or pre-signed)."
    },
    "primaryLang": {
      "type": "string",
      "enum": [
        "zh-Hant",
        "yue-Hant",
        "zh-CN",
        "en",
        "ja",
        "ko"
      ],
      "description": "Language of the written track. Default yue-Hant."
    },
    "secondaryLang": {
      "type": "string",
      "enum": [
        "zh-Hant",
        "yue-Hant",
        "zh-CN",
        "en",
        "ja",
        "ko"
      ],
      "description": "Language of the translated track. Default en."
    },
    "spokenLang": {
      "type": "string",
      "description": "What the speaker is speaking, e.g. yue-Hant-HK. Defaults to primaryLang."
    }
  },
  "required": [
    "audioUrl"
  ],
  "additionalProperties": false
}
🟡lunara_subtitle_from_url(audioUrl, filename, primaryLang, secondaryLang, spokenLang)

Start a persisted subtitle job from a URL you already host — no upload needed. Returns a job id; poll lunara_get_job every 15–30 s until status is "completed", then call lunara_get_srt. Prefer this over lunara_upload_video whenever the media is reachable by URL.

入力スキーマ

{
  "type": "object",
  "properties": {
    "audioUrl": {
      "type": "string",
      "description": "Direct HTTP(S) URL to the audio or video file. Must be downloadable by our server."
    },
    "filename": {
      "type": "string",
      "description": "Display name for the result. Defaults to the URL basename."
    },
    "primaryLang": {
      "type": "string",
      "enum": [
        "zh-Hant",
        "yue-Hant",
        "zh-CN",
        "en",
        "ja",
        "ko"
      ],
      "description": "Language of the written track. Default yue-Hant."
    },
    "secondaryLang": {
      "type": "string",
      "enum": [
        "zh-Hant",
        "yue-Hant",
        "zh-CN",
        "en",
        "ja",
        "ko"
      ],
      "description": "Language of the translated track. Default en."
    },
    "spokenLang": {
      "type": "string",
      "description": "What the speaker is speaking, e.g. yue-Hant-HK. Defaults to auto-detect."
    }
  },
  "required": [
    "audioUrl"
  ],
  "additionalProperties": false
}
🟡lunara_upload_video(projectId, clientOperationId, filename, mime, sizeBytes, ...)

Reserve an upload slot and return the object key plus a signed URL per part. After uploading the bytes call lunara_finish_upload. Use this for a file you hold locally.

入力スキーマ

{
  "type": "object",
  "properties": {
    "projectId": {
      "type": "string",
      "description": "Project to upload into. Omit to let Lunara reuse the most recent project for this organisation."
    },
    "clientOperationId": {
      "type": "string",
      "description": "Idempotency key. Reuse the same value to retry without creating a second upload."
    },
    "filename": {
      "type": "string",
      "description": "Original filename, used for the download name."
    },
    "mime": {
      "type": "string",
      "description": "MIME type, e.g. audio/mpeg, video/mp4."
    },
    "sizeBytes": {
      "type": "integer",
      "minimum": 1,
      "description": "Exact file size in bytes."
    },
    "primaryLang": {
      "type": "string",
      "enum": [
        "zh-Hant",
        "yue-Hant",
        "zh-CN",
        "en",
        "ja",
        "ko"
      ],
      "description": "Written-track language. Default yue-Hant."
    },
    "secondaryLang": {
      "type": "string",
      "enum": [
        "zh-Hant",
        "yue-Hant",
        "zh-CN",
        "en",
        "ja",
        "ko"
      ],
      "description": "Translated-track language. Default en."
    }
  },
  "required": [
    "filename",
    "mime",
    "sizeBytes"
  ],
  "additionalProperties": false
}
🟡lunara_finish_upload(videoId, uploadId, key, durationMs, parts)

Tell Lunara the bytes are uploaded so the pipeline can start. Returns the job id to poll with lunara_get_job.

入力スキーマ

{
  "type": "object",
  "properties": {
    "videoId": {
      "type": "string",
      "description": "The video id from lunara_upload_video."
    },
    "uploadId": {
      "type": "string",
      "description": "The multipart upload id."
    },
    "key": {
      "type": "string",
      "description": "The object key."
    },
    "durationMs": {
      "type": "integer",
      "minimum": 1,
      "description": "Media duration in milliseconds."
    },
    "parts": {
      "type": "array",
      "description": "Uploaded parts, each { PartNumber, ETag }.",
      "items": {
        "type": "object",
        "properties": {
          "PartNumber": {
            "type": "integer",
            "minimum": 1
          },
          "ETag": {
            "type": "string"
          }
        },
        "required": [
          "PartNumber",
          "ETag"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "videoId",
    "uploadId",
    "key",
    "durationMs",
    "parts"
  ],
  "additionalProperties": false
}
🟢lunara_get_glossary(limit)

Return the proper nouns Lunara has learned for this org, so names are spelled consistently across tracks.

入力スキーマ

{
  "type": "object",
  "properties": {
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 500,
      "description": "Default 100."
    }
  },
  "additionalProperties": false
}
⚪lunara_transcribe(audioUrl, spokenLang)

Run speech recognition only — no rewrite, no translation. Returns timed segments. Use this when you want the transcript itself, or when you plan to pick a later stage yourself.

入力スキーマ

{
  "type": "object",
  "properties": {
    "audioUrl": {
      "type": "string",
      "description": "Direct HTTP(S) URL to the audio or video file."
    },
    "spokenLang": {
      "type": "string",
      "description": "What the speaker is speaking, e.g. yue-Hant-HK. Defaults to auto-detect."
    }
  },
  "required": [
    "audioUrl"
  ],
  "additionalProperties": false
}
⚪lunara_translate(jobId, targetLang, track)

Translate the text of an existing job’s cues into another language. Every cue boundary and timestamp is preserved; only the text changes. Use this instead of translating yourself so the timing contract holds.

入力スキーマ

{
  "type": "object",
  "properties": {
    "jobId": {
      "type": "string",
      "description": "The job whose cues to translate."
    },
    "targetLang": {
      "type": "string",
      "enum": [
        "zh-Hant",
        "en",
        "ja",
        "ko"
      ],
      "description": "Target language."
    },
    "track": {
      "type": "string",
      "enum": [
        "primary",
        "secondary"
      ],
      "description": "Which track to read. Default primary."
    }
  },
  "required": [
    "jobId",
    "targetLang"
  ],
  "additionalProperties": false
}
⚪lunara_rewrite(jobId, track)

Turn spoken Cantonese cue text into written Chinese. Every cue boundary and timestamp is preserved. Deliberate mispronunciations are never corrected, and proper nouns are protected.

入力スキーマ

{
  "type": "object",
  "properties": {
    "jobId": {
      "type": "string",
      "description": "The job whose cues to rewrite."
    },
    "track": {
      "type": "string",
      "enum": [
        "primary",
        "secondary"
      ],
      "description": "Which track to read. Default primary."
    }
  },
  "required": [
    "jobId"
  ],
  "additionalProperties": false
}
⚪lunara_segment(jobId, maxCueMs, track)

Approximate split, not audio-grounded segmentation: cue text is divided at clause punctuation and each piece receives a share of the original span proportional to its character count. The words are not changed. Timings are estimated, so treat them as a reading aid rather than a re-alignment — use lunara_start_subtitle_job if you need timing derived from the audio.

入力スキーマ

{
  "type": "object",
  "properties": {
    "jobId": {
      "type": "string",
      "description": "The job whose cues to re-cut."
    },
    "maxCueMs": {
      "type": "integer",
      "minimum": 500,
      "maximum": 15000,
      "description": "Duration ceiling per cue in ms. Default 7000."
    },
    "track": {
      "type": "string",
      "enum": [
        "primary",
        "secondary"
      ],
      "description": "Which track to read. Default primary."
    }
  },
  "required": [
    "jobId"
  ],
  "additionalProperties": false
}
🟢lunara_glossary_extract(jobId, limit)

Find candidate proper nouns in a job’s cues, ranked by frequency, with the first cue they appear in. Suggestions for a glossary, not corrections — nothing is rewritten.

入力スキーマ

{
  "type": "object",
  "properties": {
    "jobId": {
      "type": "string",
      "description": "The job whose cues to scan."
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 200,
      "description": "Maximum terms to return. Default 50."
    }
  },
  "required": [
    "jobId"
  ],
  "additionalProperties": false
}
🟢lunara_qa_contract(jobId, track)

Run the contract gate over both tracks: ASR text and timings byte-exact, cue length bounds, no empty cues. Returns pass/fail per rule. Free, because refusing a broken track should never cost the caller money.

入力スキーマ

{
  "type": "object",
  "properties": {
    "jobId": {
      "type": "string",
      "description": "The job to validate."
    },
    "track": {
      "type": "string",
      "enum": [
        "primary",
        "secondary",
        "both"
      ],
      "description": "Which track to check. Default both."
    }
  },
  "required": [
    "jobId"
  ],
  "additionalProperties": false
}
🟢lunara_probe_media(mediaUrl)

Return duration, dimensions, codecs and container for a URL, plus whether the audio is mono 16 kHz already. Call this before choosing an ASR engine.

入力スキーマ

{
  "type": "object",
  "properties": {
    "mediaUrl": {
      "type": "string",
      "description": "URL to probe."
    }
  },
  "required": [
    "mediaUrl"
  ],
  "additionalProperties": false
}
🟢lunara_get_coverage(jobId)

Report how much of the source timeline the subtitles cover, and list suspicious gaps longer than a second. Use before shipping a long video.

入力スキーマ

{
  "type": "object",
  "properties": {
    "jobId": {
      "type": "string",
      "description": "The job to inspect."
    }
  },
  "required": [
    "jobId"
  ],
  "additionalProperties": false
}
🟢lunara_readability(jobId, track)

Per-cue reading speed, displayed length and characters-per-second, with the cues that exceed comfortable limits. Mirrors the metrics shown in the editor.

入力スキーマ

{
  "type": "object",
  "properties": {
    "jobId": {
      "type": "string",
      "description": "The job to measure."
    },
    "track": {
      "type": "string",
      "enum": [
        "primary",
        "secondary"
      ],
      "description": "Default primary."
    }
  },
  "required": [
    "jobId"
  ],
  "additionalProperties": false
}

コミュニティ

このサーバーを評価する

エビデンス

最近の観測

検証済みバージョンは記録されていませんツール 18 件
検証済みバージョンは記録されていませんツール 18 件