townlightTownlight Beta 1

Historical MCP reference for Windows 1.6.0.1. For Windows 1.7.0.1, use the matching source archive and technical reference index.

Townlight Beta 1

MCP and Transcription Source Reference

Staff guide and technical reference

Documentation edition 30 October 2026
Existing component versions retained
Signed suite installer 1.6.0.1
Private beta documentation companion

MCP deployment status

No direct product MCP server is exposed by the accepted Townlight desktop or Station boundary. Do not configure an invented townlight mcp command or assume an AI client has staff permissions. The integration surfaces for this beta are native IPC, the documented HTTP APIs, source bundle imports, exact exports and the existing Station CLI.

The bundled transcription code includes a TextFlowKit MCP adapter as a separate source capability. It offers job-based transcribe_media, get_transcript, list_jobs, get_job_status and export_transcript, and additional tools declared in that adapter. It uses stdio first and optional Streamable HTTP, with the MCP SDK as an optional extra. It is not automatically launched, authenticated as Townlight staff or accepted as a Townlight product MCP deployment. This documentation does not add such a service.

For a transcription client already provisioned separately, an illustrative tool call is:

{"name":"get_job_status","arguments":{"job_id":"synthetic-existing-job-id"}}

Use a job ID returned by that transcription service. This example does not create a Townlight record or bypass its review/Records handoff. The exact optional adapter tool signatures are supplied in the MCP source reference. Station meeting capture does not become live speech recognition because this optional donor adapter exists.

Exact optional transcription tool signatures

Extracted from the candidate’s separate TextFlowKit adapter; not an enabled Townlight product server.

list_sources

list_sources()

List the media platforms and input kinds textflowkit can transcribe.

Returns recognised platform names plus ‘local’ (filesystem paths) and ‘direct’ (direct media URLs).

transcribe_media

transcribe_media(source: str, language: str | None=None, formats: str='json,srt,txt', output_dir: str | None=None, model: str | None=None, device: str | None=None, cookies_from_browser: str | None=None, diarize: bool=False, translate_to: str | None=None, engine: str=DEFAULT_ENGINE)

Start transcribing a media URL or local file. Returns immediately with a job id.

The work runs in the background; poll get_job_status until the job reaches a terminal state - ‘done’, ‘error’, or ‘cancelled’ - rather than polling only for ‘done’. State ‘done’ then reads with get_transcript; ‘error’ and ‘cancelled’ are terminal and stop the poll, and each response’s next field says what to do. Do not expect a transcript in this response.

Args: source: A media URL (YouTube, TikTok, Facebook, Instagram, Vimeo, Twitch, Bilibili, Rumble, Kick, Zoom, Medal, Loom, Dropbox, or a direct media link) or a path to a local file. language: Optional ISO language code (e.g. ‘en’). Auto-detected if omitted. formats: Comma-separated outputs to write when output_dir is set. Available: txt, srt, vtt, md, json, docx, pdf. The binary formats (docx, pdf) are written to disk and require the export extra. output_dir: Directory to write rendered files into. Omit to keep the transcript in memory only. model: Model name. When omitted it resolves to the selected engine’s own default: ‘whistle’ for the Whistle engine (the default), or a Whisper size (‘tiny’, ‘base’, ‘small’, ‘medium’, ‘large’) when ‘whisper’ or ‘faster-whisper’ is selected. device: Torch device (‘cuda’ or ‘cpu’). Auto-detected when omitted. This applies to the Whisper-family engines; Whistle is CPU-only and a non-CPU device is refused rather than quietly ignored. cookies_from_browser: Pass cookies to yt-dlp from a browser, e.g. ‘firefox’. Only for media you are authorised to access. diarize: Label speakers. Requires the optional diarize extra and a gated Hugging Face model; the job fails with a clear error if unavailable rather than returning empty speakers. translate_to: Target language code (e.g. ‘es’). Translates the transcript with the configured backend; fails loudly if it is unreachable. engine: Speech engine. ‘whistle’ (the default: a CPU-only native engine that needs no torch) or ‘whisper’ (openai-whisper on the torch stack - ROCm on AMD, CUDA on NVIDIA, CPU otherwise; needs the whisper extra), or the opt-in ‘faster-whisper’, a CTranslate2 engine for CPU and Apple Silicon that needs the faster-whisper extra. No speed or accuracy comparison is claimed here.

submit_batch_media

submit_batch_media(sources: list[Any], language: str | None=None, formats: str='json,srt,txt', output_dir: str | None=None, model: str | None=None, device: str | None=None, cookies_from_browser: str | None=None, diarize: bool=False, translate_to: str | None=None, resume: bool=False, engine: str=DEFAULT_ENGINE)

Queue multiple independent media jobs and return each job handle.

sources is a list; a top-level value that is not a list at all is refused by the tool schema before this function runs. Each entry gets its own job, so one bad source cannot hide the others: a source that cannot be admitted (a non-object entry, or a non-string/empty source) is reported as its own item error, identified by its zero-based index, and the remaining sources are still queued. Poll each returned job_id with get_job_status.

Args: sources: Media URLs or local file paths; one job per source. language: Optional ISO language code (e.g. ‘en’) applied to every job. formats: Comma-separated outputs to write when output_dir is set. Available: txt, srt, vtt, md, json, docx, pdf. The binary formats (docx, pdf) require the export extra. output_dir: Directory to write rendered files into. model: Model name. When omitted it resolves to the selected engine’s own default: ‘whistle’ for the Whistle engine (the default), or a Whisper size when ‘whisper’/‘faster-whisper’ is selected. device: Torch device (‘cuda’ or ‘cpu’). Auto-detected when omitted. Applies to the Whisper-family engines; Whistle is CPU-only. cookies_from_browser: Pass cookies to yt-dlp from a browser, e.g. ‘firefox’. Only for media you are authorised to access. diarize: Label speakers (needs the diarize extra and a gated model). translate_to: Target language code; fails loudly if unreachable. resume: Reuse matching saved checkpoints and completed transcripts. engine: Speech engine, applied to every job. ‘whistle’ (the default: a CPU-only native engine that needs no torch), ‘whisper’ (openai-whisper on the torch stack; needs the whisper extra), or the opt-in ‘faster-whisper’ (CPU/Mac; needs the faster-whisper extra). This one engine is shared in every item’s request, so an unusable engine (e.g. the optional extra is absent) fails every item at admission; the per-item errors carry each item’s index and source.

resume_job

resume_job(job_id: str)

Resume an interrupted job using its saved request and transcript checkpoint.

The current input root and service work root are applied, exactly as on the HTTP surface: a source that falls outside a root the operator has since tightened is refused rather than resumed using the wider root saved with the original request, and any scratch tree is created under the configured work root rather than a root saved before the operator last changed it.

get_job_status

get_job_status(job_id: str)

Check the state of a transcription job.

Args: job_id: The id returned by transcribe_media.

get_transcript

get_transcript(job_id: str, fmt: str='txt', offset: int=0, limit: int | None=None, start: float | None=None, end: float | None=None, include_words: bool=False)

Read the transcript for a completed job, optionally a slice of it.

For long transcripts do not request everything: page with offset/limit, or ask for a time range with start/end (seconds). The response reports total_segments and has_more so you know whether to continue.

Args: job_id: The id returned by transcribe_media. fmt: How to render the text - txt, srt, vtt, md, or json. offset: Skip this many segments within the selected range. limit: Return at most this many segments. start: Only segments ending at or after this time (seconds). end: Only segments starting at or before this time (seconds). include_words: Include source-language word timings in JSON output. Defaults to false to keep model context small; translated text does not produce translated word timings.

search_transcript

search_transcript(job_id: str, query: str, limit: int=20, context: int=1, case_sensitive: bool=False)

Search a completed transcript for a phrase.

Returns matching segments with their timestamps, in the order they appear in the transcript - not sorted by relevance or recency. Use this instead of paging through a long transcript looking for a topic.

Args: job_id: The id returned by transcribe_media. query: Substring to find (not fuzzy). limit: Maximum number of matches to return. context: How many neighbouring segments to include either side. case_sensitive: Match case-sensitively (default false).

export_transcript

export_transcript(job_id: str, output_dir: str, formats: str='srt,vtt,txt,json')

Write a completed transcript to files on disk.

Args: job_id: The id returned by transcribe_media. output_dir: Directory to write into. Created if missing. formats: Comma-separated formats to write - txt, srt, vtt, md, json, docx, pdf. The binary formats (docx, pdf) require the export extra.

list_jobs

list_jobs(limit: int=20, state: str | None=None)

List recent transcription jobs, newest first.

Args: limit: Maximum number of jobs to return. state: Optional filter - pending, running, done, error, or cancelled.

cancel_job

cancel_job(job_id: str)

Request cancellation of a pending or running job.

A queued job is cancelled immediately and never starts. A running job stops at its next stage boundary, so it stays ‘running’ with cancel_requested set until the boundary is reached. Poll get_job_status until state is ‘cancelled’.

Args: job_id: The id returned by transcribe_media.