Skip to main content
Glama

subtitle-mcp

Everyday subtitle work for your AI agent: look inside, fix timing, repair, convert and translate SRT, WebVTT and ASS files. Offline, no API keys, nothing to install beyond mcp.

What is different about it: the other subtitle MCP servers I found (mcp-subtitle for AI transcription and Google-Cloud translation, tvsub-mcp for a macOS Apple TV overlay) are built around calling a transcription or translation service. subtitle-mcp is the opposite: it never calls anything. It is the toolbox for the files themselves, with exact arithmetic (a resync is an exact least-squares line over fractions, 29.97 fps really is 30000/1001), a repair tool that shows every change as a dry run first, an explicit encoding heuristic that is honest about what it cannot tell (Turkish cp1254 works), and a translation contract where your agent is the translator and the server guarantees nothing is lost on the way back in.

What it looks like

Real output on a deliberately damaged file (BOM, mixed CRLF/LF, duplicate and missing indices, a blank line inside a cue, an unreadably fast cue, one cue past hour 99):

> fix_common_problems messy.srt
Would apply 8 kind(s) of fix to messy.srt (8 cues -> 8):
  - [bom] byte order mark will not be written (output is UTF-8 without BOM by default)
  - [mixed_newlines] all line endings normalised to LF (the most common one in the file)
  - [blank_line_in_cue] removed blank lines inside 1 cue(s)
        cue 4
  - [out_of_order] re-sorted cues by start time (1 cue(s) were out of order)
        cue 3 started before the cue above it
  - [bad_duration] gave 1 zero/negative-length cue(s) a readable duration (1-7 s at 15 chars/s, never past the next cue)
        cue 2: end 00:00:03,500 -> 00:00:04,633
  - [overlap] trimmed 3 cue(s) that overlapped the next one
        cue 1: end 00:00:03,000 -> 00:00:02,000 (cue 3 starts)
        ...
  - [long_line] re-wrapped 2 cue(s) to at most 42 characters per line
  - [renumber] cues renumbered 1..N (missing, duplicate indices)
Flagged, not changed:
  - [reading_speed] 2 cue(s) read faster than 25 chars/s (not changed; shorten the text or extend the timing)
        cue 7: 110.0 chars/s
Dry run: nothing written. Call again with apply=true to write messy.fixed.srt.

A subtitle that drifts (1.001x too slow) and starts 2.5 s late, fixed with two anchors:

> resync bad.srt anchors=[{"cue": 1, "to": "00:00:12,510"}, {"cue": 4, "to": "01:40:08,500"}]
Fitted new = 1.001000000 * old + 2500.000 ms  (exact: a = 1001/1000, b = 2500 ms)
Two anchors define the line exactly.
Error at each anchor after rounding to whole ms (applied - wanted): +0 ms, +0 ms; largest 0 ms.
Retimed 4 cue(s): first start 00:00:10,000 -> 00:00:12,510, last end 01:40:01,000 -> 01:40:09,501.

Related MCP server: whisper-mcp

Install

Needs uv. Point --dir at the folder with your videos and subtitles.

Claude Code

claude mcp add subtitle -- uvx subtitle-mcp --dir "/path/to/your/videos"

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "subtitle": {
      "command": "uvx",
      "args": ["subtitle-mcp", "--dir", "C:\\Users\\you\\Videos"]
    }
  }
}

Or pip install subtitle-mcp and use the subtitle-mcp command.

Try asking

  • "What's wrong with Movie.srt? Show me the problems and the reading speed."

  • "The subtitles in Movie.srt are 3 seconds late. Fix them."

  • "They start in sync but drift: the line 'We have to go back' (cue 12) should be at 00:06:41,300 and 'It was never about the money' (cue 1304) at 01:48:12,900. Resync it."

  • "This Turkish file looks garbled. Detect the encoding and convert it to UTF-8."

  • "Convert episode.ass to SRT."

  • "Clean up old.srt: show me what you would fix first, then do it and strip the font tags."

  • "Find every cue where someone says 'password' and give me the timestamps."

  • "Join CD1.srt and CD2.srt into one file, and split the result at 01:12:00."

  • "Translate Movie.srt into Turkish." (the agent calls chunk_for_translation, translates each chunk itself, then apply_translation)

  • "My video is 23.976 fps and this subtitle was made for 25 fps. Convert it."

Tools

Tool

What it does

subtitle_info

Format, detected encoding (with the reason), line endings, cue count, time span, overlaps, gaps, longest line, reading speed (chars/sec min/mean/median/p95/max), and a problem list with cue numbers.

read_cues

Show cues by number range or time window, with a cap.

search_subtitles

Find cues by text or regex, with cue numbers and timestamps. Matches across line breaks.

shift

Constant offset in ms, or in frames at a frame rate (29.97 is exact). Optionally only from a given cue on.

resync

Two or more anchors fix offset and drift (exact least squares, residual reported); or fps_from/fps_to for frame-rate conversion.

convert

srt, vtt, and ass-to-either; also re-encodes (cp1254 to UTF-8, to UTF-16, ...). Lists what could not be carried over.

fix_common_problems

Dry run by default. Overlaps, zero/negative durations, ordering, indices, blank lines in cues, BOM, mixed line endings, long lines (balanced re-wrap), optional tag stripping. Reading-speed outliers are flagged, never changed.

merge_or_split

Merge two files with an offset (default: second after first), or split at a time with re-zeroing.

chunk_for_translation

Numbered cue batches with stable IDs.

apply_translation

Takes {id: text}, requires every ID, keeps timing/identifiers/notes, warns on empty/much longer/shorter text, lost tags, unreadable speed.

Cue numbers everywhere are the 1-based position of the cue in the file.

The translation contract

The server never translates. chunk_for_translation(path, max_chars) returns {"id": "12", "text": "..."} records (one chunk per call; chunk=2, 3, ...). Your agent translates and sends one mapping {"12": "..."} to apply_translation. Missing or unknown IDs fail with the list of offenders; partial=true keeps untranslated cues as they are. Timing is never touched, and tags such as <i> and {\an8} that appear in the source but not in the translation are reported.

Formats and limits (read this)

  • SRT and WebVTT are read and written fully. The parser is tolerant (missing, duplicate or out-of-order indices; index separated from timing by a blank line; blank lines inside cues; . or , milliseconds; hours over 99; cues glued together; SRT X1:.. coordinates; WebVTT header metadata, NOTE/STYLE/REGION blocks, identifiers, cue settings). Everything it had to guess is listed under parse_warnings in subtitle_info.

  • ASS/SSA is read-only: timing and text are extracted (tags stripped, \N becomes a line break) and can be converted to SRT/VTT. Styling is dropped: fonts, colours, positions, effects, karaoke, drawings. The tools say so. Editing tools refuse ASS and tell you to convert first.

  • Converting SRT to WebVTT drops SRT coordinates; WebVTT to SRT drops cue settings and NOTE/STYLE/REGION blocks. Blank lines inside a cue are removed on write, because both formats end a cue at a blank line.

  • Encoding detection is a heuristic, and an honest one (the full rules are in src/subtitle_mcp/encoding.py): BOMs and UTF-16 are certain; valid UTF-8 is trusted; otherwise Turkish letters (Ğ İ Ş ğ ı ş) select cp1254, letters between letters in the 0xA1-0xBF range select iso-8859-2, and anything else is cp1252. It will not guess between Cyrillic/Greek code pages (it errors and asks for encoding=), cannot tell iso-8859-1 from -15, and a Turkish file with none of its six special letters is read as cp1252, which decodes identically. If text looks wrong, pass encoding= to any tool. Output is UTF-8 unless you choose output_encoding; characters the target cannot hold are an error, not ?.

  • Resync assumes a straight line (constant offset plus constant speed ratio). A film cut with a scene removed in the middle needs merge_or_split plus two resyncs.

  • Line wrapping counts visible characters (tags excluded) and never splits a word, so a word longer than the limit stays on its own over-long line (and is flagged).

Security

  • Local files only, no network access, no subprocesses, no dependency beyond mcp.

  • --dir DIR (repeatable) confines every read and write to those folders; .. and symlinks are resolved before checking. Relative paths resolve against the first --dir. Without --dir any path the user account can reach is allowed, so set it.

  • Only .srt .vtt .ass .ssa files can be read and only .srt .vtt written, so the tools cannot be steered into overwriting other files.

  • Nothing is overwritten unless overwrite=true; edits go to a new sibling file by default (movie.shifted.srt, movie.fixed.srt, ...). Writes are atomic (temp file in the same folder, then replace), and a failed write leaves the destination untouched.

  • Input is capped at 64 MiB. A pathological regular expression passed to search_subtitles runs unguarded (Python re), as with any local tool.

Tests

pip install ".[test]" "ruff==0.16.0" "mypy==2.3.0"
ruff check src tests && mypy --strict src
pytest tests

Real-world-like messy fixtures (including cp1254 Turkish, UTF-16, iso-8859-2) with exact expected output, 2,400 generated parse/write round-trips, hand-checked resync math, a real MCP stdio session against the installed server, and ffmpeg as an independent oracle (it produces ASS for the parser, and re-reads the files we write). The oracle tests skip when ffmpeg is not installed.

Want to learn how it works? subtitle-mcp-the-hard-way rebuilds a minimal version in seven runnable modules.

License

MIT

Available Tools

10 tools
apply_translationA

Step 2 of translating a subtitle: write the translated file. Timing, cue order, WebVTT identifiers/settings/notes are kept exactly; only the text changes. Every id of the file must be present in mapping (otherwise the call fails and lists the missing ids; partial=true keeps untranslated cues as they are). Warnings are reported for translations that are empty, much longer or shorter than the source, that lose or change formatting tags, or that would read too fast.

Args: path: the SAME file given to chunk_for_translation. mapping: {"1": "translated text", "2": "..."}; keys are the ids from chunk_for_translation. output: where to write (default: .translated.). overwrite: allow replacing an existing output file (default false). partial: allow a mapping that does not cover every cue. encoding: force the input text encoding. output_encoding: encoding of the written file (default utf-8; use utf-8 for non-Latin target languages).

NameRequiredDescriptionDefault
pathYes
outputNo
mappingYes
partialNo
encodingNo
overwriteNo
output_encodingNoutf-8

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations supplied, the description carries the full burden and does so generously: it discloses what is preserved (timing, cue order, WebVTT identifiers/settings/notes), what changes (text only), the failure mode when ids are missing (error listing missing ids), how partial=true degrades gracefully, and the warning categories produced for suspicious translations. Overwrite defaulting to false is also surfaced.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and constraint sentences are front-loaded and dense with useful information; the warnings sentence is long but each clause names a distinct condition. The trailing Args block repeats parameter names from the schema, which is a minor redundancy, though it earns most of its space given 0% schema coverage.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with a nested mapping object and no annotations, the description covers prerequisites, preservation semantics, error behavior, escaping hatch (partial), and filename defaults. An output schema exists, so omitting return-value prose is appropriate and nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate entirely, and it does — all seven parameters are explained with meaning and defaults, including the `mapping` key contract ('keys are the ids from chunk_for_translation'), the default output filename pattern, and the non-Latin target-language guidance for output_encoding. This adds substantially more than the bare schema titles.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb and resource ('write the translated file') and anchors the tool as 'Step 2 of translating a subtitle', which pairs it explicitly with the sibling chunk_for_translation (step 1). An agent can distinguish it from read_cues, fix_common_problems, and convert without consulting the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is clear: it must follow chunk_for_translation, and the `path` argument is stated to be 'the SAME file given to chunk_for_translation', which prevents a common mis-call. It does not explicitly state when *not* to use it or name a competing alternative, so it falls just short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

chunk_for_translationA

Step 1 of translating a subtitle. Returns one batch of cues as JSON: each cue has a stable id (its 1-based position in the file) and its text (line breaks as \n, tags included). The server never translates: YOU translate the texts, then call apply_translation with a mapping {"": ""} covering every id of the file.

Rules for the translation: keep every id; keep formatting tags such as and {\an8} exactly; keep line breaks (\n) where they make sense; keep it about as long as the original (subtitles are read against a clock). The response says how many chunks exist; call again with chunk=2, 3, ... until all are done, then send ONE mapping with all ids.

Args: path: .srt or .vtt file. max_chars: approximate size of a batch in characters of cue text (default 1500, min 200). chunk: which batch to return, starting at 1. encoding: force the input text encoding.

NameRequiredDescriptionDefault
pathYes
chunkNo
encodingNo
max_charsNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations supplied, the description carries the disclosure burden and does well: it states the server never translates, that ids are stable 1-based positions, that line breaks are \n and tags are preserved, and that the response reports the chunk count. It never explicitly says the call is a non-mutating read or whether repeated calls with different chunk values are side-effect free, which is the remaining gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded and the workflow, translation rules, and argument list are cleanly separated into blocks. The 'Rules for the translation' paragraph is somewhat tangential to invoking this tool and could be tightened, but it is the contract the agent must honor before calling apply_translation, so it largely earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although an output schema exists, the description still explains the payload (id plus text) and, more importantly, the multi-call workflow and the downstream apply_translation contract. For a paging tool in a two-step pipeline, nothing an agent needs in order to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, yet the Args block documents all four parameters: path restricted to .srt/.vtt, max_chars as approximate batch size with default 1500 and minimum 200, chunk as a 1-based batch selector, and encoding as an input-encoding override. This fully compensates for the bare schema and adds constraints (min 200, units in cue-text characters) that are absent from the structured fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence names a specific role ('Step 1 of translating a subtitle') and the concrete result ('Returns one batch of cues as JSON'), which cleanly separates it from the sibling apply_translation that handles step 2. An agent can identify both the verb and the resource without inspecting the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the exact iteration protocol ('call again with chunk=2, 3, ... until all are done') and the required follow-up ('then send ONE mapping with all ids' via apply_translation). The alternative sibling is named along with the condition that triggers it, leaving no routing ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

convertA

Convert between SRT and WebVTT, turn an ASS/SSA file into SRT or VTT, or just re-encode a file (same format in and out, for example cp1254 Turkish -> UTF-8). Timing and text are kept. What cannot be carried over is listed in the answer: ASS styling (fonts, colours, positions, effects) is always dropped, WebVTT cue settings and NOTE/STYLE/REGION blocks do not exist in SRT, and blank lines inside a cue are removed because both formats end a cue at a blank line.

Args: path: .srt, .vtt, .ass or .ssa file. to_format: 'srt' or 'vtt'. output: where to write (default: .converted.). overwrite: allow replacing an existing output file (default false). encoding: force the input text encoding. output_encoding: encoding of the written file: utf-8 (default), utf-8-sig, utf-16, cp1254, cp1252, iso-8859-9, ...

NameRequiredDescriptionDefault
pathYes
outputNo
encodingNo
overwriteNo
to_formatYes
output_encodingNoutf-8

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so well: it discloses that timing and text are preserved, that ASS styling (fonts, colours, positions, effects) is always dropped, that WebVTT cue settings and NOTE/STYLE/REGION blocks do not exist in SRT, and that blank lines inside cues are removed. It also states overwrite defaults to false and the default output filename pattern. The remaining gap is that it never says the source file is left untouched or what happens on an unsupported/corrupt input.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core action is front-loaded in the first sentence, lossiness in the second, and parameters follow in a conventional Args block. It is on the long side and the lossiness sentence is dense, but each clause carries real decision-relevant information rather than restating the name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a six-parameter file-writing tool with no annotations, the definition covers purpose, lossy-conversion behavior, defaults, and every parameter; the existence of an output schema means return values need not be described. An agent has enough to call this correctly without opening the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: every one of the six parameters is explained with meaning and default (path restricted to .srt/.vtt/.ass/.ssa, to_format constrained to 'srt' or 'vtt' — a constraint the schema itself lacks since it declares no enum, output default <name>.converted.<new ext>, overwrite default false, encoding forced input decoding, output_encoding default utf-8 with enumerated examples).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb plus the exact resource set: 'Convert between SRT and WebVTT, turn an ASS/SSA file into SRT or VTT, or just re-encode a file'. The scope (format transcoding plus same-format re-encoding) is stated outright, which cleanly separates it from siblings like fix_common_problems, shift, or apply_translation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete use cases ('turn an ASS/SSA file into SRT or VTT', 're-encode a file, for example cp1254 Turkish -> UTF-8'), so an agent knows when this is the right tool. It never names an alternative or an exclusion, though — nothing says to use fix_common_problems for repairs or that this tool does not resync or shift timing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fix_common_problemsA

Repair the usual damage in SRT/WebVTT files. DRY RUN BY DEFAULT: it lists every fix it would make (with cue numbers and before/after times) and writes nothing until you call again with apply=true.

Fixes: out-of-order cues are re-sorted; cues with end <= start get a readable duration (never past the next cue); overlapping cues are trimmed to the next cue's start; empty cues and blank lines inside cues are removed; missing/duplicate/wrong SRT index numbers are renumbered; lines longer than max_line_length are re-wrapped (balanced; dialogue dashes keep one speaker per line); the BOM and mixed CR/LF line endings are normalised. With strip_tags=true, HTML/font/WebVTT/ASS tags are removed from the text.

Flagged but never changed: reading-speed outliers (more than max_cps characters per second) and cues on screen for over 10 seconds; overlapping cues that start together.

Args: path: .srt or .vtt file. apply: false (default) = report only; true = write the repaired file. strip_tags: also remove , , <font ...>, <v ...>, {\an8} etc. (default false). max_line_length: wrap lines longer than this many visible characters (default 42). max_cps: reading-speed flag threshold in characters per second (default 25). output: where to write when apply=true (default: .fixed.). overwrite: allow replacing an existing output file (default false). encoding: force the input text encoding. output_encoding: encoding of the written file (default utf-8).

NameRequiredDescriptionDefault
pathYes
applyNo
outputNo
max_cpsNo
encodingNo
overwriteNo
strip_tagsNo
max_line_lengthNo
output_encodingNoutf-8

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully carries the behavioral burden: it states that the default is a dry run, lists every fix type with before/after reporting, explains what is flagged but never changed, and documents write/output defaults. This gives the agent a strong safety and behavior model before invoking a mutating repair tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the dry-run warning and then organizes fixes, flagged issues, and args into distinct sections. It is longer than typical, but most detail is relevant for a complex, multi-parameter repair tool; some fix-list wording could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given nine parameters, no annotations, and an output schema, the description supplies the missing behavioral and parameter context an agent needs. It covers mutation safety, exact repair semantics, parameter defaults, and what is never changed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description documents all nine parameters in the Args section, including defaults and meaning for apply, strip_tags, max_line_length, max_cps, output, overwrite, encoding, and output_encoding. This fully compensates for the schema's lack of parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource: repairing common damage in SRT/WebVTT files. The detailed fix list makes its scope clearer than the name alone, but it does not explicitly distinguish itself from sibling tools such as resync or convert.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly explains the dry-run default and that apply=true is required to write changes, which is useful invocation guidance. However, it does not say when to choose this tool over siblings like resync, shift, or convert, leaving alternative routing implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

merge_or_splitA

Join two subtitle files or cut one in two. SRT and WebVTT only.

mode='merge': the cues of path2 are moved by offset_ms and combined with those of path (result sorted by start time, in the format of the first file). If offset_ms is omitted, the second file is placed right after the last cue of the first (typical for CD1 + CD2 rips). Use offset_ms=0 to overlay two files, such as two languages.

mode='split': cut at time at. Part 1 holds everything that starts before at; part 2 holds everything from at on, re-zeroed so at becomes 00:00:00. A cue that straddles the cut appears in both parts (clipped to the cut in part 1).

Args: path: first (or only) file. mode: 'merge' or 'split'. path2: second file (merge only). offset_ms: milliseconds added to every cue of path2 (merge only; may be negative). at: split time such as 00:45:10,000 (split only). output: merged file / first part (default .merged. or .part1.). output2: second part (split only, default .part2.). overwrite: allow replacing existing output files (default false). encoding: force the input text encoding (applies to both inputs). output_encoding: encoding of the written files (default utf-8).

NameRequiredDescriptionDefault
atNo
modeYes
pathYes
path2No
outputNo
output2No
encodingNo
offset_msNo
overwriteNo
output_encodingNoutf-8

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses that merge sorts by start time and adopts the first file's format, that split re-zeroes part 2 to 00:00:00, that a straddling cue is duplicated and clipped, and that overwrite defaults to false. Gaps remain on failure behavior (what happens when outputs exist and overwrite is false) and whether the two inputs must share a format or encoding.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the one-line purpose, then per-mode semantics, then a compact Args list. Every sentence adds operational information and the mode-specific scoping ('merge only', 'split only') is stated inline rather than left implicit.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Return values need not be explained because an output schema exists, and the description covers both modes plus every parameter for a 10-param, annotation-free tool. It is only slightly short of complete: format/encoding compatibility between the two merge inputs and the existing-file error path are unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, yet the Args block documents all ten parameters with meaning the schema cannot convey: offset_ms may be negative and applies only to path2, `at` uses the 00:45:10,000 format, output/output2 have concrete default filenames, and encoding applies to both inputs while output_encoding governs the writes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific compound verb and resource ('Join two subtitle files or cut one in two') plus the supported formats (SRT and WebVTT only). The two named modes map exactly onto the two operations, so an agent can tell this apart from siblings like shift, resync, or convert.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use guidance per mode: merge with omitted offset_ms for CD1+CD2 rips, offset_ms=0 to overlay two languages, split with `at` for cutting. It does not state when NOT to use this tool versus siblings (e.g. use shift for single-file retiming, convert for format changes), which is the only missing routing signal.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_cuesA

Show cues, selected either by number or by time. Cue numbers are 1-based positions in the file (the same numbers every other tool uses).

Args: path: subtitle file. start_cue: first cue number (inclusive). Use with end_cue. end_cue: last cue number (inclusive). from_time: show cues that overlap [from_time, to_time). Format 00:01:02,500 or 62.5. to_time: end of the time window (default: end of file). limit: maximum cues to return (default 100, at most 500). encoding: force a text encoding.

NameRequiredDescriptionDefault
pathYes
limitNo
end_cueNo
to_timeNo
encodingNo
from_timeNo
start_cueNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden. It discloses useful details such as the default limit of 100, maximum of 500, default to_time as end of file, and time-window overlap semantics. It does not explicitly state that the operation is read-only, how errors are handled, or how selectors interact if both cue numbers and time windows are supplied.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded in the first sentence, followed by a structured Args list. Every line adds useful information, and there is no redundant or filler wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a seven-parameter read tool with no annotations and an output schema, the description covers selection modes, parameter meanings, defaults, time format, and limit bounds. It is reasonably complete, though it could be stronger by explaining sibling-tool selection and the interaction between cue-number and time-window parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does so for all seven parameters: path, cue ranges, time formats, overlap semantics, defaults, limit bounds, and encoding. The main remaining gap is that it does not specify precedence or interaction when both cue-number and time-window selectors are provided.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: "Show cues", selected by number or time. It also clarifies that cue numbers are 1-based positions consistent with other tools. However, it does not explicitly distinguish this tool from the sibling search_subtitles tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the two selection modes (by cue number or by time window), but gives no guidance on when to use read_cues rather than alternatives such as search_subtitles. There are no explicit exclusions or decision rules.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resyncA

Fix a subtitle that is out of sync by an amount that CHANGES through the film (drift) as well as a constant offset. Give anchor points: a line in the file and the time it should really appear. Two anchors (one near the start, one near the end) define the straight line new = a*old + b exactly; with three or more a least-squares line is fitted. The tool applies it to every start and end time and reports the error left at each anchor.

Find anchors with search_subtitles / read_cues: take a distinctive line near the start and one near the end, play the video to find when each is really spoken.

Alternatively give fps_from and fps_to (no anchors) when the subtitle was timed for a video at one frame rate and your video runs at another (for example fps_from=25, fps_to=23.976).

Args: path: .srt or .vtt file. anchors: list of {"cue": 12, "to": "00:03:10,400"} (cue = cue number, its START is moved) or {"at": "00:03:05,000", "to": "00:03:10,400"} (at = the current wrong time). fps_from: frame rate the subtitle was made for. fps_to: frame rate of the video you have. output: where to write (default: .resynced.). overwrite: allow replacing an existing output file (default false). encoding: force the input text encoding. output_encoding: encoding of the written file (default utf-8).

NameRequiredDescriptionDefault
pathYes
fps_toNo
outputNo
anchorsNo
encodingNo
fps_fromNo
overwriteNo
output_encodingNoutf-8

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does well: it discloses that the transform is applied to every start and end time, that per-anchor residual error is reported, the default output filename, and that overwrite defaults to false. It stops short of stating whether the input file is ever modified in place or what permissions/limits apply, so not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core behavior and the anchor/fps decision, then a compact Args block. It is longer than most definitions but nearly every sentence adds operational value; the least-squares detail is arguably more than needed but supports the 'three or more anchors' case.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an eight-parameter mutation tool with no annotations, the description covers the math, both input modes, anchor construction, output location, and overwrite safety. An output schema exists, and the description still notes that residual error per anchor is reported, so nothing an agent needs is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate and it does: all eight parameters are explained, including the two accepted anchor object shapes (cue vs at) and the fact that a cue anchor moves the cue's START. Defaults for output, overwrite, and output_encoding are restated with meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fix a subtitle that is out of sync') and immediately scopes it to drift plus constant offset, which distinguishes it from the sibling shift tool that handles constant offset only. An agent can pick between resync and shift from the description alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use branches: anchors for drift, fps_from/fps_to when the subtitle was timed for a different frame rate, with a concrete example (25 to 23.976). It also tells the agent how to obtain anchors via search_subtitles / read_cues and what to do in the video.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_subtitlesA

Find cues whose text contains a phrase (or matches a regular expression), with cue number and timestamps. Matching ignores line breaks inside a cue (they count as a space), so a phrase split over two lines is still found. Markup tags are searched too.

Args: path: subtitle file. query: text to find, or a Python regular expression when regex=true. regex: treat query as a regular expression. case_sensitive: default is case-insensitive. limit: maximum matches to show (default 50). encoding: force a text encoding.

NameRequiredDescriptionDefault
pathYes
limitNo
queryYes
regexNo
encodingNo
case_sensitiveNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the whole burden. It usefully discloses that line breaks count as spaces, that markup tags are searched, and the default match limit, but says nothing about invalid-regex handling, missing files, or whether hitting 'limit' is signalled.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the matching semantics before an Args block that stays tight. Every sentence carries information; minor redundancy between the prose and the Args entry for 'query'.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Return values needn't be explained because an output schema exists, and the search-matching rules are covered. The remaining gap is edge-case behavior (invalid regex, truncation at limit) for a tool with six parameters and no annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description does real work: it explains all six parameters, including that 'query' becomes a Python regex under regex=true and that case-insensitive is the default. It omits what the default encoding is and what path formats are accepted.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Find cues whose text contains a phrase...') plus the returned fields (cue number, timestamps). That scope implicitly separates it from read_cues and subtitle_info, but no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the search semantics but never stated as when-to-use versus read_cues or fix_common_problems. There are no exclusions and no guidance on which tool to pick when you just want to read the file.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

shiftA

Move cues later (positive) or earlier (negative) by a constant amount, either in milliseconds or in frames at a frame rate (frames=24, fps=29.97 is exact: 29.97 means 30000/1001). Optionally only from a given cue to the end of the file. Fails instead of producing a time before 00:00:00. SRT and WebVTT only; writes a new file.

For a subtitle that is early/late by a different amount at the start and the end, use resync instead.

Args: path: .srt or .vtt file. offset_ms: milliseconds to add (negative = earlier). Give this OR frames+fps. frames: number of frames to add (negative = earlier); needs fps. fps: frame rate for frames, e.g. 23.976, 24, 25, 29.97. from_cue: 1-based cue number to start shifting from (default: every cue). output: where to write (default: .shifted. next to the input). overwrite: allow replacing an existing output file (default false). encoding: force the input text encoding. output_encoding: encoding of the written file (default utf-8).

NameRequiredDescriptionDefault
fpsNo
pathYes
framesNo
outputNo
encodingNo
from_cueNo
offset_msNo
overwriteNo
output_encodingNoutf-8

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so: it discloses that a new file is written rather than the input modified, that the default output path is `<name>.shifted.<ext>`, that overwrite defaults to false, and that out-of-range shifts fail instead of clamping. Encoding defaults for input and output are also surfaced.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core behavior, the sibling alternative, and the hard constraints are front-loaded in the first paragraph, with parameters in a clean Args list. There is minor redundancy between the prose restating '(positive)'/'(negative)' and the Args entries repeating it, but nothing is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 9-parameter mutation with no annotations, the definition covers direction semantics, format restrictions, offset-vs-frames exclusivity, partial-range shifting, failure behavior, and file output. An output schema is present, so return values need not be explained, and nothing needed to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate and it does for all nine parameters: `offset_ms` and `frames`+`fps` are presented as mutually exclusive alternatives, `from_cue` is marked 1-based with 'every cue' as the default, and `output`, `overwrite`, `encoding`, and `output_encoding` each get a default and meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource (move cues) plus the exact directional semantics of positive vs negative offsets, so the operation is unambiguous. It also names the sibling `resync` and the condition that distinguishes it, so an agent can separate the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly routes the agent: for subtitles that are early/late by a different amount at start vs end, use `resync` instead. It also states hard preconditions (SRT and WebVTT only) and a failure mode (fails rather than producing a time before 00:00:00), which are the constraints an agent must check before calling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

subtitle_infoA

Inspect a subtitle file: format, detected encoding, line endings, cue count, time span, overlaps, gaps, longest line, reading speed (characters per second: min/mean/median/p95/max) and a list of problems with the cue numbers affected. Read-only. Run this first.

The encoding is detected (UTF-8/16/32 by byte order mark or structure; Turkish cp1254, Western cp1252 and Central European iso-8859-2 by letter evidence) and the reason and confidence are reported. If the text looks garbled, pass the right encoding and rerun.

Args: path: .srt, .vtt, .ass or .ssa file. encoding: Python codec name to force (for example 'cp1254'); default is auto-detect.

NameRequiredDescriptionDefault
pathYes
encodingNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations supplied, the description carries the full burden and does well: it declares "Read-only," explains the detection method and that reason and confidence are reported, and gives a remediation path for misdetection. It does not state what happens on an unsupported or missing file, or whether it parses the whole file (cost on large inputs), which keeps it below a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The output inventory is front-loaded in the first sentence, followed by the encoding-detection paragraph and a compact Args block. The middle paragraph on detection heuristics is slightly longer than needed for an agent's decision-making, but every part is relevant and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the enumerated return fields are arguably redundant, but their presence confirms scope and the description also covers safety posture, parameter semantics, and a retry strategy for encoding failures. Only error/failure conditions and large-file cost are left implicit for a tool that is the mandated first step in the workflow.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, and it does: `path` is constrained to .srt/.vtt/.ass/.ssa, and `encoding` is described as a Python codec name with a concrete example ('cp1254') and an explicit auto-detect default. It leaves path resolution (relative vs absolute) and error behavior for bad codecs unstated, so it is strong but not exhaustive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ("Inspect a subtitle file") and enumerates exactly what is reported: format, detected encoding, line endings, cue count, time span, overlaps, gaps, longest line, reading speed statistics, and a problem list with cue numbers. That level of specificity clearly separates it from siblings like read_cues (raw cue content) and fix_common_problems (mutation).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit sequencing guidance with "Run this first," which tells the agent where this sits in the workflow, plus a concrete conditional branch: if text looks garbled, force `encoding` and rerun. It stops short of naming specific alternative tools (e.g., read_cues for content inspection), so the when-not guidance is implied rather than spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 10 tool updatesv0.1.0
    • First observedapply_translation
    • First observedchunk_for_translation
    • First observedconvert
    • First observedfix_common_problems
    • First observedmerge_or_split
    • First observedread_cues
    • First observedresync
    • First observedsearch_subtitles
    • First observedshift
    • First observedsubtitle_info

TDQS

A4.1/5.0

Scored across 10 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: inspection, reading, searching, repair, constant shifting, drift resync, format conversion, merge/split, and the two-step translation workflow. The only potentially overlapping pair, shift and resync, is explicitly differentiated by constant offset versus drift/frame-rate correction, and the descriptions point to each other. search_subtitles and read_cues also target different needs (text matching versus positional/time-based listing).

Naming Consistency4/5

All names use consistent snake_case, and most are readable verb_noun or verb_object forms such as search_subtitles, fix_common_problems, read_cues, and merge_or_split. However, several tools use single verbs (shift, resync, convert) or a noun-first name (subtitle_info), so the pattern is not uniformly verb_noun.

Tool Count5/5

Ten tools is well within the ideal range for a focused subtitle-processing server. Each tool covers a meaningful, non-redundant operation in the workflow, from inspection and repair through timing adjustment, conversion, merging, and translation.

Completeness4/5

The surface covers the core subtitle lifecycle: inspect, read, search, repair, shift/resync timing, convert formats, merge/split, and translate text. Minor gaps remain, such as direct cue-level text editing outside the translation flow or explicit cue addition/deletion, but most practical workflows can be handled with the existing tools.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers