Lunara

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

¿Debería usar esto?

Calidad y seguridad

A
Calidad de la descripción
96%
Integridad del esquema
96%
Calidad de los nombres
80%
Riesgo de envenenamiento
100%
Coincidencia de permisos
100%
Cumplimiento del protocolo
100%

Hallazgos (1)

  • LOWTool 'lunara_rewrite' description lacks action verben lunara_rewrite

Basado en el análisis automatizado de las definiciones de herramientas y el cumplimiento del protocolo.

Costo de contexto

~3,037Tokens (definiciones de herramientas)
~1.0 KBTamaño de respuesta típico
Impacto significativo en la atención (2.37% del contexto de 128k)

Este es el número aproximado de tokens que se consumen cada vez que las herramientas del servidor se cargan en el contexto de un modelo. Los recuentos más altos reducen la atención disponible para otras tareas.

Instalar

Instalación con un clic

Agrega esto a tu archivo `claude_desktop_config.json`:

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

Puntos de conexión remotos

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

Qué puede hacer

Inventario de herramientas

Herramientas (18)

🟢 Solo lectura🟡 Escritura🔴 Eliminación⚪ Desconocido
🟢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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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).

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

{
  "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.

Esquema de entrada

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

Comunidad

Califica este servidor

Evidencia

Observaciones recientes

verificadoversión no registrada18 herramientas
verificadoversión no registrada18 herramientas