Koskamo

Zovo Subtitle Fix MCP

Fix subtitle timing in SRT and VTT files by shifting cues, converting frame rates, syncing on reference points, trimming overlaps, stripping tags, and converting formats. It provides a CSV change log and requires no sign-in.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Zovo Subtitle Fix MCP logo, by ZovoCommunity listingStreamable HTTPNo sign-inEndpoint checked 2026-11-08Published by Zovo
You need:No sign-in is needed
MCP endpoint (Streamable HTTP)
https://subtitle-fix.zovo.one/mcp
Vendor documentation

What its tools do

2 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

2 of 2 have a description · 2 of 2 declare behavior hints · 2 of 2 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Shift subtitles earlier or later by milliseconds
  • Convert timing between frame rates like 25 and 23.976 fps
  • Sync file using two known reference cues
  • Trim overlapping cues and enforce minimum duration

Source and maintenance

Community listingRegistry 1.0.0

Protocol and capabilities

Server
subtitle-fix 1.0.0
MCP protocol negotiated in check
2025-11-25
Tools
2 advertised
Resources
1 advertised
Resource templates
1 advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  },
  "resources": {
    "listChanged": true
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Zovo Subtitle Fix repairs the timing of one SRT or WebVTT subtitle file. fix_subtitles shifts all cues, converts between frame rates (for example 25 to 23.976 fps), or syncs on two cues, then can trim overlaps, extend short cues, strip formatting tags, renumber, and convert SRT to VTT or back. It returns the fixed file and a CSV change log per cue. Times are computed with fractions, then rounded half up to whole milliseconds; the written file is read back and each time and each cue text is compared before the link is given. check_subtitles lists overlaps, zero or negative durations, out-of-order cues, numbering gaps and cues that are too fast to read, without making a file. Files are processed in memory; outputs are kept for 1 hour, then deleted.

Tools

2 advertised

fix_subtitles — Fix subtitles
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when the user wants to fix subtitle timing or convert subtitles: shift an SRT or VTT file earlier or later, convert it from one frame rate to another (23.976, 24, 25, 29.97, 30, 50, 59.94, 60), sync it on two cues, trim overlapping cues, give short cues a minimum duration, strip formatting tags, renumber, or convert SRT to WebVTT and back. Takes one attached .srt or .vtt file (or the subtitle text) and returns the fixed file and a CSV change log with old and new times per cue. Times are whole milliseconds, rounded half up. Does not listen to audio or find the right offset by itself, does not translate or edit the words, and does not read SSA/ASS files.

fix_subtitles input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "file": {
      "type": "object",
      "required": [
        "download_url",
        "file_id"
      ],
      "properties": {
        "file_id": {
          "type": "string",
          "description": "ChatGPT file id, e.g. file_abc123."
        },
        "file_name": {
          "type": "string",
          "description": "Original file name if known, e.g. statement.pdf."
        },
        "mime_type": {
          "type": "string",
          "description": "Media type if known, e.g. application/pdf."
        },
        "download_url": {
          "type": "string",
          "description": "Temporary download link for the file, supplied by ChatGPT."
        }
      },
      "description": "The subtitle file: one .srt or .vtt file in UTF-8 or UTF-16 with a byte order mark, e.g. movie.srt."
    },
    "sync": {
      "type": "object",
      "required": [
        "cue_a",
        "time_a",
        "cue_b",
        "time_b"
      ],
      "properties": {
        "cue_a": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "First reference cue, counted in file order (1 = first cue), e.g. 1."
        },
        "cue_b": {
          "type": "integer",
          "maximum": 9007199254740991,
          "minimum": -9007199254740991,
          "description": "Second reference cue, far from the first, e.g. 812 (the last cue)."
        },
        "time_a": {
          "type": "string",
          "maxLength": 20,
          "description": "When cue_a should start, HH:MM:SS,mmm, e.g. \"00:00:41,200\"."
        },
        "time_b": {
          "type": "string",
          "maxLength": 20,
          "description": "When cue_b should start, e.g. \"01:52:07,900\"."
        }
      },
      "description": "Two-point sync: cue_a should start at time_a and cue_b at time_b; all times are mapped on that straight line. Do not combine with shift_ms or frame rates."
    },
    "gap_ms": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Gap kept before the next cue when fixing overlaps or extending cues, 0 to 1000 ms, e.g. 1 (default)."
    },
    "to_fps": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string",
          "maxLength": 12
        }
      ],
      "description": "Frame rate of the video they should match, e.g. 23.976. One of 23.976, 24, 25, 29.97, 30, 50, 59.94 or 60. new time = old time x from_fps / to_fps."
    },
    "from_fps": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "string",
          "maxLength": 12
        }
      ],
      "description": "Frame rate the subtitles were timed for, e.g. 25. One of 23.976, 24, 25, 29.97, 30, 50, 59.94 or 60. Use with to_fps."
    },
    "renumber": {
      "type": "boolean",
      "description": "SRT output: true (default) numbers cues 1, 2, 3 in output order; false keeps the numbers as written."
    },
    "shift_ms": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Move all cues by this many milliseconds: positive = later, negative = earlier, e.g. 2500 (2.5 s later) or -1200. Limit 24 hours."
    },
    "strip_tags": {
      "type": "boolean",
      "description": "true removes formatting tags such as <i>, <b>, <u>, <font>, WebVTT <c>/<v> tags and {\\an8} codes from the text. Default false."
    },
    "fix_overlaps": {
      "type": "boolean",
      "description": "true: when a cue ends after the next cue starts, or less than gap_ms before it, its end moves to gap_ms before that start. Default false."
    },
    "line_endings": {
      "enum": [
        "same",
        "crlf",
        "lf"
      ],
      "type": "string",
      "description": "Line endings of the output, e.g. crlf. Default same as the input (CRLF, LF, or CR for old Mac files)."
    },
    "output_format": {
      "enum": [
        "same",
        "srt",
        "vtt"
      ],
      "type": "string",
      "description": "Output format, e.g. vtt to convert SRT to WebVTT. Default same as the input."
    },
    "sort_by_start": {
      "type": "boolean",
      "description": "true writes cues in start-time order (stable). Default false keeps the file order."
    },
    "subtitle_text": {
      "type": "string",
      "maxLength": 2097152,
      "description": "Instead of a file: the subtitle text itself, e.g. \"1\\n00:00:01,000 --> 00:00:03,000\\nHello\". Use either file or subtitle_text."
    },
    "min_duration_ms": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Make short cues last at least this long, up to gap_ms before the next cue, e.g. 1000. 0 (default) = off. Limit 10000."
    }
  }
}
fix_subtitles output schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "file",
    "format_in",
    "format_out",
    "encoding",
    "cues_in",
    "cues_out",
    "removed",
    "timing",
    "counts",
    "check",
    "changes_preview",
    "notes",
    "output_name",
    "log_name",
    "expires_in_hours",
    "downloads"
  ],
  "properties": {
    "file": {
      "type": "string"
    },
    "check": {
      "type": "object",
      "required": [
        "passed",
        "cues_checked",
        "times_checked",
        "what"
      ],
      "properties": {
        "what": {
          "type": "string"
        },
        "passed": {
          "type": "boolean"
        },
        "cues_checked": {
          "type": "number"
        },
        "times_checked": {
          "type": "number"
        }
      },
      "additionalProperties": false
    },
    "notes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "counts": {
      "type": "object",
      "required": [
        "times_changed",
        "overlaps_fixed",
        "gaps_made",
        "overlaps_not_fixed",
        "extended",
        "clipped_at_zero",
        "tags_stripped",
        "text_changed"
      ],
      "properties": {
        "extended": {
          "type": "number"
        },
        "gaps_made": {
          "type": "number"
        },
        "text_changed": {
          "type": "number"
        },
        "tags_stripped": {
          "type": "number"
        },
        "times_changed": {
          "type": "number"
        },
        "overlaps_fixed": {
          "type": "number"
        },
        "clipped_at_zero": {
          "type": "number"
        },
        "overlaps_not_fixed": {
          "type": "number"
        }
      },
      "additionalProperties": false
    },
    "timing": {
      "type": "string"
    },
    "cues_in": {
      "type": "number"
    },
    "removed": {
      "type": "number"
    },
    "cues_out": {
      "type": "number"
    },
    "encoding": {
      "type": "string"
    },
    "log_name": {
      "type": "string"
    },
    "downloads": {
      "type": "object",
      "required": [
        "subtitles",
        "change_log"
      ],
      "properties": {
        "subtitles": {
          "type": "string"
        },
        "change_log": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "format_in": {
      "type": "string"
    },
    "format_out": {
      "type": "string"
    },
    "output_name": {
      "type": "string"
    },
    "changes_preview": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "cue",
          "old_start",
          "old_end",
          "new_start",
          "new_end",
          "change"
        ],
        "properties": {
          "cue": {
            "type": "number"
          },
          "change": {
            "type": "string"
          },
          "new_end": {
            "type": "string"
          },
          "old_end": {
            "type": "string"
          },
          "new_start": {
            "type": "string"
          },
          "old_start": {
            "type": "string"
          }
        },
        "additionalProperties": false
      }
    },
    "expires_in_hours": {
      "type": "number"
    },
    "changes_preview_count": {
      "type": "object",
      "required": [
        "shown",
        "total"
      ],
      "properties": {
        "shown": {
          "type": "number"
        },
        "total": {
          "type": "number"
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
fix_subtitles annotations
{
  "title": "Fix subtitles",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
check_subtitles — Check subtitles
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when the user asks whether an SRT or VTT subtitle file has problems, or wants a report before fixing it: overlapping cues, zero or negative durations, cues out of order, SRT numbering gaps, empty cues, cues too fast to read (characters per second above max_cps, default 20) and lines longer than max_line_chars (default 42). Takes one attached .srt or .vtt file or the subtitle text. Does not make a file and does not change the subtitles; fix_subtitles does that. Does not check spelling, translation or sync with the audio.

check_subtitles input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "file": {
      "type": "object",
      "required": [
        "download_url",
        "file_id"
      ],
      "properties": {
        "file_id": {
          "type": "string",
          "description": "ChatGPT file id, e.g. file_abc123."
        },
        "file_name": {
          "type": "string",
          "description": "Original file name if known, e.g. statement.pdf."
        },
        "mime_type": {
          "type": "string",
          "description": "Media type if known, e.g. application/pdf."
        },
        "download_url": {
          "type": "string",
          "description": "Temporary download link for the file, supplied by ChatGPT."
        }
      },
      "description": "The subtitle file: one .srt or .vtt file in UTF-8 or UTF-16 with a byte order mark, e.g. movie.srt."
    },
    "max_cps": {
      "type": "number",
      "description": "Reading speed limit in characters per second, 5 to 60, e.g. 17. Default 20."
    },
    "subtitle_text": {
      "type": "string",
      "maxLength": 2097152,
      "description": "Instead of a file: the subtitle text itself, e.g. \"1\\n00:00:01,000 --> 00:00:03,000\\nHello\". Use either file or subtitle_text."
    },
    "max_line_chars": {
      "type": "integer",
      "maximum": 9007199254740991,
      "minimum": -9007199254740991,
      "description": "Longest line in characters, 20 to 100, e.g. 42 (default)."
    }
  }
}
check_subtitles output schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "file",
    "format",
    "encoding",
    "cues",
    "first_start",
    "last_end",
    "overlaps",
    "bad_durations",
    "out_of_order",
    "numbering",
    "empty_cues",
    "fast_cues",
    "long_lines",
    "three_plus_lines",
    "problems",
    "suggestions",
    "notes"
  ],
  "properties": {
    "cues": {
      "type": "number"
    },
    "file": {
      "type": "string"
    },
    "notes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "format": {
      "type": "string"
    },
    "encoding": {
      "type": "string"
    },
    "last_end": {
      "type": "string"
    },
    "overlaps": {
      "type": "object",
      "required": [
        "count",
        "examples"
      ],
      "properties": {
        "count": {
          "type": "number"
        },
        "examples": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "problems": {
      "type": "number"
    },
    "fast_cues": {
      "type": "object",
      "required": [
        "count",
        "max_cps",
        "examples"
      ],
      "properties": {
        "count": {
          "type": "number"
        },
        "max_cps": {
          "type": "number"
        },
        "examples": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "numbering": {
      "type": "object",
      "required": [
        "count",
        "examples"
      ],
      "properties": {
        "count": {
          "type": "number"
        },
        "examples": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "empty_cues": {
      "type": "object",
      "required": [
        "count",
        "examples"
      ],
      "properties": {
        "count": {
          "type": "number"
        },
        "examples": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "long_lines": {
      "type": "object",
      "required": [
        "count",
        "max_line_chars",
        "examples"
      ],
      "properties": {
        "count": {
          "type": "number"
        },
        "examples": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "max_line_chars": {
          "type": "number"
        }
      },
      "additionalProperties": false
    },
    "first_start": {
      "type": "string"
    },
    "suggestions": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "out_of_order": {
      "type": "object",
      "required": [
        "count",
        "examples"
      ],
      "properties": {
        "count": {
          "type": "number"
        },
        "examples": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "bad_durations": {
      "type": "object",
      "required": [
        "count",
        "examples"
      ],
      "properties": {
        "count": {
          "type": "number"
        },
        "examples": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "additionalProperties": false
    },
    "three_plus_lines": {
      "type": "number"
    }
  },
  "additionalProperties": false
}
check_subtitles annotations
{
  "title": "Check subtitles",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

Not advertised

No prompt definitions available.

Resources

1 advertised

subtitle-fix-widget — Zovo Subtitle Fix view

Advertised by the server during the last successful anonymous check.

Interactive view for Zovo Subtitle Fix.

subtitle-fix-widget URI
ui://widget/subtitle-fix-v1-1.0.0-f540cfbfe055fcf00abf360e636aeb862b385222f8f2a640a6ad0f363ff5e48b.html

MIME type: text/html;profile=mcp-app

subtitle-fix-widget-legacy — Zovo Subtitle Fix view (previous versions)

Advertised by the server during the last successful anonymous check.

subtitle-fix-widget-legacy URI template
ui://widget/subtitle-fix-{version}.html

MIME type: text/html;profile=mcp-app

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
903 ms
95th percentile latency
903 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 903 ms · metadata changed · 2 tool(s), 1 resource(s), 1 resource template(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http zovo-subtitle-fix-mcp https://subtitle-fix.zovo.one/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add zovo-subtitle-fix-mcp --url https://subtitle-fix.zovo.one/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable zovo-subtitle-fix-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "zovo-subtitle-fix-mcp": {
      "url": "https://subtitle-fix.zovo.one/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "zovo-subtitle-fix-mcp": {
      "type": "streamableHttp",
      "url": "https://subtitle-fix.zovo.one/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start zovo-subtitle-fix-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "zovo-subtitle-fix-mcp": {
      "type": "http",
      "url": "https://subtitle-fix.zovo.one/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http zovo-subtitle-fix-mcp https://subtitle-fix.zovo.one/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://subtitle-fix.zovo.one/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "zovo-subtitle-fix-mcp": {
      "serverUrl": "https://subtitle-fix.zovo.one/mcp"
    }
  }
}

Let your agent find its tools

Find servers like Zovo Subtitle Fix MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.