multimodal-mcp 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- multimodal_mcp/__init__.py +11 -0
- multimodal_mcp/catalog/__init__.py +18 -0
- multimodal_mcp/catalog/api-notes.toml +293 -0
- multimodal_mcp/catalog/api_notes.py +34 -0
- multimodal_mcp/catalog/prompt-guides.toml +247 -0
- multimodal_mcp/catalog/prompt_guides.py +281 -0
- multimodal_mcp/config.py +98 -0
- multimodal_mcp/endpoints/__init__.py +84 -0
- multimodal_mcp/endpoints/ark.py +205 -0
- multimodal_mcp/endpoints/gemini.py +142 -0
- multimodal_mcp/endpoints/minimax.py +131 -0
- multimodal_mcp/endpoints/openai.py +107 -0
- multimodal_mcp/omni/__init__.py +5 -0
- multimodal_mcp/omni/agents.py +367 -0
- multimodal_mcp/omni/instructions.md +51 -0
- multimodal_mcp/omni/media.py +87 -0
- multimodal_mcp/omni/workspace.py +326 -0
- multimodal_mcp/server.py +649 -0
- multimodal_mcp-0.2.0.dist-info/METADATA +168 -0
- multimodal_mcp-0.2.0.dist-info/RECORD +23 -0
- multimodal_mcp-0.2.0.dist-info/WHEEL +4 -0
- multimodal_mcp-0.2.0.dist-info/entry_points.txt +3 -0
- multimodal_mcp-0.2.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
from .config import load
|
|
4
|
+
from .server import build
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def main() -> None:
|
|
8
|
+
parser = argparse.ArgumentParser(prog="multimodal-mcp")
|
|
9
|
+
parser.add_argument("--config", help="Config file (default: ~/.agents/mcp/multimodal/config.toml)")
|
|
10
|
+
args = parser.parse_args()
|
|
11
|
+
build(load(args.config)).run(show_banner=False)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Model data looked up by endpoint and model ID: API notes and default capabilities in api-notes.toml, prompt guides
|
|
2
|
+
in prompt-guides.toml. Each file's header states its scope; data of another kind goes in a file of its own."""
|
|
3
|
+
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
# A trailing date version: -YYMMDD on Ark, -YYYY-MM-DD on OpenAI snapshots.
|
|
7
|
+
DATE = re.compile(r"-(\d{6}|\d{4}-\d{2}-\d{2})$")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def notes_name(model: str) -> str:
|
|
11
|
+
"""Catalog names compare case-insensitively, after the last "/" of a repo ID or path."""
|
|
12
|
+
return model.rsplit("/", 1)[-1].lower()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def matching_names(model: str) -> set[str]:
|
|
16
|
+
"""A model ID's names to match: with and without a trailing date version."""
|
|
17
|
+
name = notes_name(model)
|
|
18
|
+
return {name, DATE.sub("", name)}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# API notes for the configured models, which get_model_guide returns: what each call accepts and does. Notes cover
|
|
2
|
+
# parameter values and ranges, required and unsupported parameters, input formats, sizes, counts and durations, inputs
|
|
3
|
+
# that cannot be combined, options fields, output formats, and side effects such as billing or retention; a character
|
|
4
|
+
# or token limit is an API note. How to write a prompt (structure, reference labels, markup, wording, length)
|
|
5
|
+
# belongs in prompt-guides.toml and the vendor references it lists.
|
|
6
|
+
# [<endpoint>] notes apply to every model on that endpoint. [<endpoint>.models.<name>] notes apply to one model, or
|
|
7
|
+
# to a family whose models share them: <name> is the vendor's standard API name without its date version, a
|
|
8
|
+
# self-hosted model's Hugging Face repo ID, or a glob over a family's names, and aliases lists the model's other
|
|
9
|
+
# official names. capabilities lists what the model can do on the endpoint, which a configured model uses unless it
|
|
10
|
+
# lists its own.
|
|
11
|
+
# A configured model takes the first entry whose <name> or an alias matches it as a glob, ignoring case and anything
|
|
12
|
+
# up to the last "/", with or without a trailing date version (-YYMMDD or -YYYY-MM-DD).
|
|
13
|
+
# Notes are keyed by a tool, or by a category when shared across that category's tools. Each note's comment, and the
|
|
14
|
+
# comment on capabilities, gives its source: a doc URL and section, source code at a pinned version, or the observed error.
|
|
15
|
+
|
|
16
|
+
[ark]
|
|
17
|
+
image = [
|
|
18
|
+
"Input images: jpeg, png, webp, bmp, tiff, gif, heic or heif, each up to 30 MB.", # https://www.volcengine.com/docs/82379/1541523 §image: requirements for each input image
|
|
19
|
+
"quality is unsupported.", # src/multimodal_mcp/endpoints/ark.py Ark.generate_image
|
|
20
|
+
]
|
|
21
|
+
asr = [
|
|
22
|
+
"language, prompt, hotwords and speakers are unsupported.", # src/multimodal_mcp/endpoints/ark.py Ark.transcribe
|
|
23
|
+
]
|
|
24
|
+
generate_video = [
|
|
25
|
+
"Frames and references cannot be combined in one request.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.role: first frame, first and last frames, and all-modal reference are three mutually exclusive scenarios
|
|
26
|
+
"size is unsupported; use aspect_ratio and resolution.", # src/multimodal_mcp/endpoints/ark.py Ark.generate_video
|
|
27
|
+
"Reference videos must be public URLs or asset:// IDs.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.video_url.url: a video URL or an asset ID; observed error: InvalidParameter ... reference_video must be provided as a web url
|
|
28
|
+
"Requests are capped at 64 MB and local files are sent as base64, so pass large media as URLs or asset:// IDs.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.image_url.url, §content.audio_url.url: request body at most 64 MB, no base64 for large files
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[ark.models.doubao-seedance-2-0]
|
|
32
|
+
aliases = ["doubao-seedance-2.0"] # https://www.volcengine.com/docs/82379/2516288 Agent Plan model list
|
|
33
|
+
capabilities = ["text", "frames", "reference"] # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.role: text, first frame, first and last frames, all-modal reference
|
|
34
|
+
generate_video = [
|
|
35
|
+
"Frames: first_frame alone or with last_frame.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.role: first frame, or first and last frames
|
|
36
|
+
"References: up to 9 images, 3 videos and 3 audios; audio needs at least one reference image or video.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.image_url.url, §content.video_url.url, §content.audio_url.url: Seedance 2.0 series limits; audio cannot be the only reference
|
|
37
|
+
"Each reference video or audio runs 2-15 s, with at most 15 s in total per type.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.video_url.url, §content.audio_url.url: Seedance 2.0 series durations
|
|
38
|
+
"Reference images and videos showing real human faces must be this account's Seedance outputs from the last 30 days, asset:// virtual avatars or authorized material.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content: permitted sources for real human faces in reference images and videos
|
|
39
|
+
"seconds: 4-15, or -1 to let the model choose.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §duration
|
|
40
|
+
"resolution: 480p, 720p (default), 1080p or 4k; aspect_ratio: 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 or adaptive (default).", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §resolution, §ratio
|
|
41
|
+
"Sound is generated by default; options {\"generate_audio\": false} makes the video silent.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §generate_audio
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[ark.models.doubao-seedance-2-5]
|
|
45
|
+
capabilities = ["text", "frames", "reference"] # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.role: text, first frame, first and last frames, all-modal reference
|
|
46
|
+
generate_video = [
|
|
47
|
+
"Frames: first_frame alone or with last_frame; a last_frame of another aspect ratio is cropped to the first frame's.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.role: first frame, first and last frames
|
|
48
|
+
"References: up to 30 images, 10 videos and 10 audios, at most 50 in all; audio may be the only reference.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.image_url.url, §content.video_url.url, §content.audio_url.url: Seedance 2.5 limits; sd25-pe §Asset Specification Preflight: 50 assets in all
|
|
49
|
+
"Each reference video runs 2-30 s, or 4-30 s for a video to edit, and each reference audio 2-30 s, with at most 30 s in total per type.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content.video_url.url, §content.audio_url.url: Seedance 2.5 durations
|
|
50
|
+
"Reference images and videos showing real human faces must be this account's Seedance outputs from the last 30 days, asset:// virtual avatars or authorized material.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §content: permitted sources for real human faces in reference images and videos
|
|
51
|
+
"seconds: 4-30, or -1 (default) to let the model choose; resolution: 480p, 720p (default) or 1080p; aspect_ratio: 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 or adaptive (default).", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §duration, §resolution, §ratio
|
|
52
|
+
"With frames the aspect ratio follows first_frame. Editing or extending a reference video keeps its aspect ratio, and editing also keeps its length, up to about 0.4 s shorter; these tasks take no aspect_ratio, and editing takes no seconds.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §ratio: Seedance 2.5 adaptive only for editing, extension and frames; §duration: editing only -1
|
|
53
|
+
"The model infers whether a reference task generates, edits or extends from the media and prompt, and fails the job when the parameters do not fit that task; options {\"omni_reference_task_type\": \"reference\"}, \"edit\" or \"extend\" checks that task's limits on submission instead.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §omni_reference_task_type: InvalidParameter.TaskTypeConstraint, TaskTypeMismatch
|
|
54
|
+
"Sound is generated by default; options {\"generate_audio\": false} makes the video silent.", # https://ark.volcengine.com/region:cn-beijing/docs/ark/create-video-generation-task-api §generate_audio
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[ark.models.doubao-seedream-5-0-pro]
|
|
58
|
+
aliases = ["doubao-seedream-5.0-pro"] # observed: accepted by the Ark API
|
|
59
|
+
capabilities = ["generate", "edit", "reference"] # https://www.volcengine.com/docs/82379/1541523 §image; src/multimodal_mcp/endpoints/ark.py Ark.generate_image rejects mask
|
|
60
|
+
image = [
|
|
61
|
+
"size: 1K, 1.5K or 2K (default) with the aspect ratio described in the prompt, or WIDTHxHEIGHT with 921,600-4,624,220 pixels and an aspect ratio within 1:16-16:1.", # https://www.volcengine.com/docs/82379/1541523 §size: Seedream 5.0 pro / Seedream 5.0 flash
|
|
62
|
+
"Up to 10 input images.", # https://www.volcengine.com/docs/82379/1541523 §image: Seedream 5.0 pro / Seedream 5.0 flash take up to 10
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[ark.models."doubao-seed-tts-2.0"]
|
|
66
|
+
aliases = ["seed-tts-2.0"] # https://www.volcengine.com/docs/82379/2516286#aa1f3c9e core configuration: doubao-seed-tts-2.0 uses X-Api-Resource-Id seed-tts-2.0
|
|
67
|
+
capabilities = ["voice", "timestamps"] # https://www.volcengine.com/docs/6561/1598757 §req_params.speaker, §req_params.audio_params.enable_subtitle; src/multimodal_mcp/endpoints/ark.py Ark.synthesize rejects reference_audio, and Ark has no voice design
|
|
68
|
+
generate_speech = [
|
|
69
|
+
"voice must be a Doubao TTS 2.0 voice such as zh_female_vv_uranus_bigtts; voices are listed at https://www.volcengine.com/docs/6561/1257544.", # https://www.volcengine.com/docs/6561/1598757 §X-Api-Resource-Id: seed-tts-2.0 supports only Doubao TTS 2.0 voices
|
|
70
|
+
"speed: 0.5-2.0.", # https://www.volcengine.com/docs/6561/1598757 §req_params.audio_params.speech_rate: [-50, 100] maps to 0.5x-2.0x
|
|
71
|
+
"response_format: mp3 (default), ogg_opus or pcm.", # https://www.volcengine.com/docs/6561/1598757 §req_params.audio_params.format
|
|
72
|
+
"Timestamps cover Chinese and English only.", # https://www.volcengine.com/docs/6561/1598757 §req_params.audio_params.enable_subtitle
|
|
73
|
+
"instructions is sent as the one entry of context_texts, which holds either a voice instruction or the line said before input.", # src/multimodal_mcp/endpoints/ark.py Ark.synthesize: additions.context_texts = [instructions]; https://www.volcengine.com/docs/6561/1598757 §req_params.additions.context_texts
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
[ark.models."doubao-seed-asr-2.0"]
|
|
77
|
+
capabilities = ["text", "segment", "word"] # src/multimodal_mcp/endpoints/ark.py Ark.transcribe: utterances with words; rejects speakers and hotwords
|
|
78
|
+
|
|
79
|
+
[minimax]
|
|
80
|
+
image = [
|
|
81
|
+
"Prompt up to 1,500 characters.", # https://platform.minimaxi.com/docs/api-reference/image-generation-t2i §prompt
|
|
82
|
+
"references are portrait subjects, as JPG or PNG under 10 MB.", # https://platform.minimaxi.com/docs/api-reference/image-generation-i2i §subject_reference
|
|
83
|
+
"quality is unsupported.", # src/multimodal_mcp/endpoints/minimax.py MiniMax.generate_image
|
|
84
|
+
]
|
|
85
|
+
generate_video = [
|
|
86
|
+
"Frames and references cannot be combined in one request.", # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §content: image-to-video and multimodal reference-to-video are mutually exclusive
|
|
87
|
+
"size is unsupported; use aspect_ratio and resolution.", # src/multimodal_mcp/endpoints/minimax.py MiniMax.generate_video
|
|
88
|
+
"resolution and seconds are required.", # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §VideoGenerationV2Req.required
|
|
89
|
+
"Text-to-video needs aspect_ratio 21:9, 16:9, 4:3, 1:1, 3:4 or 9:16; with frames the ratio follows the image.", # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §ratio
|
|
90
|
+
"References: up to 9 images, 3 videos and 3 audios; each video or audio runs 2-15 s, with at most 15 s in total per type.", # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §content: input media limits
|
|
91
|
+
"Media may be public URLs or mm_file:// IDs; requests are capped at 64 MB and local files are sent as base64.", # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §content: input media limits; §image_url.url
|
|
92
|
+
"Prompt up to 7,000 characters.", # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §content.text
|
|
93
|
+
]
|
|
94
|
+
generate_speech = [
|
|
95
|
+
"input under 10,000 characters.", # https://platform.minimaxi.com/docs/api-reference/speech-t2a-http §text
|
|
96
|
+
"instructions is unsupported; for emotion, pass options {\"voice_setting\": {\"emotion\": \"sad\"}} with happy, sad, angry, fearful, disgusted, surprised or calm, which by default the model picks from the text; speech-2.6 models also take fluent and whisper.", # https://platform.minimaxi.com/docs/api-reference/speech-t2a-http §voice_setting.emotion
|
|
97
|
+
"options also takes pronunciation_dict, such as {\"tone\": [\"处理/(chu3)(li3)\", \"omg/oh my god\"]}; text_normalization_mode basic or quality, off by default; and language_boost, such as \"Chinese,Yue\" or \"auto\".", # https://platform.minimax.io/docs/api-reference/speech-t2a-http §pronunciation_dict, §text_normalization_mode, §language_boost
|
|
98
|
+
"voice: a system voice such as English_Graceful_Lady or Chinese (Mandarin)_Lyrical_Voice, or a cloned or designed voice ID.", # https://platform.minimaxi.com/docs/api-reference/speech-t2a-http §voice_setting.voice_id
|
|
99
|
+
"speed: 0.5-2.", # https://platform.minimaxi.com/docs/api-reference/speech-t2a-http §voice_setting.speed
|
|
100
|
+
"response_format: mp3 (default), pcm, flac, wav, pcmu_raw, pcmu_wav or opus.", # https://platform.minimaxi.com/docs/api-reference/speech-t2a-http §audio_setting.format
|
|
101
|
+
]
|
|
102
|
+
voice_design = [
|
|
103
|
+
"preview_text is required, up to 500 characters; the preview is billed.", # https://platform.minimaxi.com/docs/api-reference/voice-design-design §preview_text
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
[minimax.models.MiniMax-H3]
|
|
107
|
+
capabilities = ["text", "frames", "reference"] # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §content: text, image-to-video, multimodal reference-to-video
|
|
108
|
+
generate_video = [
|
|
109
|
+
"resolution: 768P or 2K; seconds: 4-15.", # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §model, §resolution, §duration
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
[minimax.models.MiniMax-H3-Max]
|
|
113
|
+
capabilities = ["text", "frames", "reference"] # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §content: text, image-to-video, multimodal reference-to-video
|
|
114
|
+
generate_video = [
|
|
115
|
+
"resolution: 480P or 768P; seconds: 5-15.", # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §model, §resolution, §duration
|
|
116
|
+
"Prompt expansion defaults to balanced; options {\"extra\": {\"prompt_expansion_mode\": \"disabled\"}} turns it off, and \"quality\" expands more.", # https://platform.minimaxi.com/docs/api-reference/video-generation-v2-create §extra.prompt_expansion_mode
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
[minimax.models.image-01]
|
|
120
|
+
capabilities = ["generate", "reference"] # https://platform.minimaxi.com/docs/api-reference/image-generation-i2i §subject_reference; src/multimodal_mcp/endpoints/minimax.py MiniMax.generate_image rejects mask
|
|
121
|
+
image = [
|
|
122
|
+
"size: 1:1 (default), 16:9, 4:3, 3:2, 2:3, 3:4, 9:16 or 21:9, or WIDTHxHEIGHT with both sides 512-2048 in multiples of 8.", # https://platform.minimaxi.com/docs/api-reference/image-generation-t2i §aspect_ratio, §width
|
|
123
|
+
"options {\"prompt_optimizer\": true} lets the service expand the prompt; it is off by default.", # https://platform.minimax.io/docs/api-reference/image-generation-t2i §prompt_optimizer
|
|
124
|
+
"For a consistent character, pass one frontal photo of a single person as the reference.", # https://platform.minimaxi.com/docs/api-reference/image-generation-i2i §subject_reference
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
[minimax.models."asr-1.0"]
|
|
128
|
+
capabilities = ["text", "segment", "word", "speaker"] # https://platform.minimaxi.com/docs/api-reference/speech-to-text §timestamp_level; src/multimodal_mcp/endpoints/minimax.py MiniMax.transcribe: verbose_json carries timestamps and speaker labels
|
|
129
|
+
asr = [
|
|
130
|
+
"prompt and hotwords are unsupported.", # src/multimodal_mcp/endpoints/minimax.py MiniMax.transcribe; https://platform.minimaxi.com/docs/api-reference/speech-to-text has no such fields
|
|
131
|
+
"language: a BCP-47 tag such as en-US; omit it for mixed-language audio.", # https://platform.minimaxi.com/docs/api-reference/speech-to-text §language (header)
|
|
132
|
+
"Audio up to 500 s and 50 MB in wav, aiff, flac, m4a, mp3, aac, opus or ogg.", # https://platform.minimaxi.com/docs/api-reference/speech-to-text §file
|
|
133
|
+
]
|
|
134
|
+
transcribe_audio_with_timestamps = [
|
|
135
|
+
"Word timestamps are per character for Chinese.", # https://platform.minimaxi.com/docs/api-reference/speech-to-text §timestamp_level
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
[minimax.models."speech-2.8-hd"]
|
|
139
|
+
capabilities = ["voice", "timestamps", "design"] # https://platform.minimaxi.com/docs/api-reference/speech-t2a-http §voice_setting.voice_id, §subtitle_enable; https://platform.minimaxi.com/docs/api-reference/voice-design-design
|
|
140
|
+
|
|
141
|
+
[minimax.models."speech-2.8-turbo"]
|
|
142
|
+
capabilities = ["voice", "timestamps", "design"] # https://platform.minimaxi.com/docs/api-reference/speech-t2a-http §voice_setting.voice_id, §subtitle_enable; https://platform.minimaxi.com/docs/api-reference/voice-design-design
|
|
143
|
+
|
|
144
|
+
[gemini]
|
|
145
|
+
image = [
|
|
146
|
+
"quality is unsupported.", # src/multimodal_mcp/endpoints/gemini.py Gemini.generate_image
|
|
147
|
+
]
|
|
148
|
+
generate_video = [
|
|
149
|
+
"size is unsupported; use aspect_ratio and resolution.", # src/multimodal_mcp/endpoints/gemini.py Gemini.generate_video
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
[gemini.models."gemini-omni-1.1-flash"]
|
|
153
|
+
capabilities = ["text", "frames", "reference"] # https://ai.google.dev/gemini-api/docs/omni §Using tags in prompts to set image and video roles
|
|
154
|
+
generate_video = [
|
|
155
|
+
"aspect_ratio: 16:9 (default) or 9:16; resolution: 360p, 720p (default), 1080p or 4k.", # https://ai.google.dev/gemini-api/docs/omni §Control aspect ratio, §Output resolution
|
|
156
|
+
"seconds is unsupported; clips run 3-10 s.", # src/multimodal_mcp/endpoints/gemini.py Gemini.generate_video; https://ai.google.dev/gemini-api/docs/models/gemini-omni-flash §Limits
|
|
157
|
+
"last_frame needs first_frame.", # https://ai.google.dev/gemini-api/docs/omni §Using tags in prompts to set image and video roles
|
|
158
|
+
"The tool writes the [# Sources ...] and [# References ...] declarations before the prompt, binding the frames and references to their tags.", # src/multimodal_mcp/endpoints/gemini.py Gemini.generate_video: declaration + prompt
|
|
159
|
+
"Reference videos: up to 3 clips of up to 3 s each, with their audio ignored; reference audio is unsupported.", # https://ai.google.dev/gemini-api/docs/omni §Limitations
|
|
160
|
+
"Recognizable people in uploaded images are unsupported.", # https://ai.google.dev/gemini-api/docs/omni §Limitations
|
|
161
|
+
"A video to edit or extend runs up to 10 s; extension only appends to its end, and voices cannot be edited.", # https://ai.google.dev/gemini-api/docs/omni §Limitations
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
[gemini.models."gemini-3.1-flash-image"]
|
|
165
|
+
capabilities = ["generate", "edit", "reference"] # https://ai.google.dev/gemini-api/docs/image-generation §Use up to 14 reference images; src/multimodal_mcp/endpoints/gemini.py Gemini.generate_image rejects mask
|
|
166
|
+
image = [
|
|
167
|
+
"size: an aspect ratio (1:1, 1:4, 1:8, 2:3, 3:2, 3:4, 4:1, 4:3, 4:5, 5:4, 8:1, 9:16, 16:9 or 21:9) or a tier 512, 1K (default), 2K or 4K with uppercase K; for both, give the ratio as size and options {\"response_format\": {\"image_size\": \"2K\"}}.", # https://ai.google.dev/gemini-api/docs/image-generation §Aspect ratios and image size (3.1 Flash Image), §Generate images up to 4K resolution; https://ai.google.dev/api/interactions-api §ImageResponseFormat.image_size
|
|
168
|
+
"Without size, output matches the input image, or is 1:1 without one.", # https://ai.google.dev/gemini-api/docs/image-generation §Aspect ratios and image size
|
|
169
|
+
"Up to 10 object images and 4 character images.", # https://ai.google.dev/gemini-api/docs/image-generation §Use up to 14 reference images
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
[gemini.models."gemini-3.5-transcribe"]
|
|
173
|
+
capabilities = ["text", "word", "speaker", "hotwords"] # https://ai.google.dev/gemini-api/docs/transcribe §Parameter reference; src/multimodal_mcp/endpoints/gemini.py Gemini.transcribe returns word timestamps only
|
|
174
|
+
asr = [
|
|
175
|
+
"prompt is unsupported; hotwords are sent as custom_vocabulary.", # https://ai.google.dev/gemini-api/docs/transcribe §Parameter reference; src/multimodal_mcp/endpoints/gemini.py Gemini.transcribe
|
|
176
|
+
"language: a BCP-47 code such as en-US; omit it to auto-detect, including mixed languages.", # https://ai.google.dev/gemini-api/docs/transcribe §Parameter reference
|
|
177
|
+
"Files are sent inline, up to 100 MB per request.", # https://ai.google.dev/gemini-api/docs/file-input-methods §Method comparison
|
|
178
|
+
]
|
|
179
|
+
transcribe_audio = [
|
|
180
|
+
"Audio up to 1 hour.", # https://ai.google.dev/gemini-api/docs/transcribe §Limitations
|
|
181
|
+
"hotwords: up to 1,000 terms.", # https://ai.google.dev/gemini-api/docs/transcribe §Limitations
|
|
182
|
+
]
|
|
183
|
+
transcribe_audio_with_timestamps = [
|
|
184
|
+
"Audio up to 30 minutes.", # https://ai.google.dev/gemini-api/docs/transcribe §Limitations
|
|
185
|
+
"hotwords cannot be combined with timestamps or speakers.", # src/multimodal_mcp/endpoints/gemini.py Gemini.transcribe; https://ai.google.dev/gemini-api/docs/transcribe §Limitations
|
|
186
|
+
"Up to 8 speakers; 3 or more is experimental.", # https://ai.google.dev/gemini-api/docs/transcribe §Limitations
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
[gemini.models."gemini-3.8-flash-tts"]
|
|
190
|
+
capabilities = ["voice", "design"] # https://ai.google.dev/gemini-api/docs/speech-generation §Voice options; https://ai.google.dev/gemini-api/docs/voice-design; src/multimodal_mcp/endpoints/gemini.py Gemini.synthesize rejects reference_audio and timestamps
|
|
191
|
+
generate_speech = [
|
|
192
|
+
"voice: a prebuilt voice such as Kore, Puck or Charon, a Voice Library voice, or a voice_ ID from voice_design.", # https://ai.google.dev/gemini-api/docs/speech-generation §Voice options
|
|
193
|
+
"response_format: wav (default), l16 (raw PCM), mulaw or alaw.", # https://ai.google.dev/gemini-api/docs/speech-generation §Audio output formats
|
|
194
|
+
"speed is unsupported; ask for the pace in instructions.", # src/multimodal_mcp/endpoints/gemini.py Gemini.synthesize
|
|
195
|
+
"reference_audio and timestamps are unsupported.", # src/multimodal_mcp/endpoints/gemini.py Gemini.synthesize; capabilities above
|
|
196
|
+
"Each call speaks one turn in one voice.", # src/multimodal_mcp/endpoints/gemini.py Gemini.synthesize: one voice per request
|
|
197
|
+
]
|
|
198
|
+
voice_design = [
|
|
199
|
+
"The preview is generated from the description, and Gemini assigns the voice ID; preview_text and voice_id are unsupported.", # https://ai.google.dev/gemini-api/docs/voice-design §How Voice design works; src/multimodal_mcp/endpoints/gemini.py Gemini.design_voice
|
|
200
|
+
"Voices are kept for a year after last use, up to 200 per project.", # https://ai.google.dev/gemini-api/docs/voice-design §Manage your voices
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
[openai]
|
|
204
|
+
transcribe_audio_with_timestamps = [
|
|
205
|
+
"speakers=true cannot be combined with granularity word; speaker labels come with segment timestamps.", # src/multimodal_mcp/endpoints/openai.py OpenAI.transcribe: diarized_json has no word timestamps
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
[openai.models."gpt-image-2.5-sunburst"]
|
|
209
|
+
capabilities = ["generate", "edit", "reference", "mask"] # openai-python 3.28.0 src/openai/resources/images.py Images.generate, Images.edit §image, §mask
|
|
210
|
+
image = [
|
|
211
|
+
"size: auto (default) or WIDTHxHEIGHT with both sides multiples of 16, aspect ratio 1:3-3:1, up to 3840x2160; above 2560x1440 is experimental.", # openai-python 3.28.0 src/openai/resources/images.py Images.generate, Images.edit §size
|
|
212
|
+
"quality: low, medium, high, xhigh, max or auto (default).", # openai-python 3.28.0 src/openai/resources/images.py Images.generate, Images.edit §quality
|
|
213
|
+
"Up to 16 input images, each png, webp or jpg under 50 MB.", # openai-python 3.28.0 src/openai/resources/images.py Images.edit §image
|
|
214
|
+
"For a transparent background, pass options {\"background\": \"transparent\", \"output_format\": \"png\"}.", # openai-python 3.28.0 src/openai/resources/images.py Images.generate, Images.edit §background
|
|
215
|
+
]
|
|
216
|
+
edit_image = [
|
|
217
|
+
"The mask is a PNG under 4 MB with the first image's dimensions, transparent where it should change.", # openai-python 3.28.0 src/openai/resources/images.py Images.edit §mask
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
[openai.models."gpt-image-2.5-flare"]
|
|
221
|
+
capabilities = ["generate", "edit", "reference", "mask"] # openai-python 3.28.0 src/openai/resources/images.py Images.generate, Images.edit §image, §mask
|
|
222
|
+
image = [
|
|
223
|
+
"size: auto (default) or WIDTHxHEIGHT with both sides multiples of 16, aspect ratio 1:3-3:1, up to 3840x2160; above 2560x1440 is experimental.", # openai-python 3.28.0 src/openai/resources/images.py Images.generate, Images.edit §size
|
|
224
|
+
"quality: low, medium, high, xhigh, max or auto (default).", # openai-python 3.28.0 src/openai/resources/images.py Images.generate, Images.edit §quality
|
|
225
|
+
"Up to 16 input images, each png, webp or jpg under 50 MB.", # openai-python 3.28.0 src/openai/resources/images.py Images.edit §image
|
|
226
|
+
"For a transparent background, pass options {\"background\": \"transparent\", \"output_format\": \"png\"}.", # openai-python 3.28.0 src/openai/resources/images.py Images.generate, Images.edit §background
|
|
227
|
+
]
|
|
228
|
+
edit_image = [
|
|
229
|
+
"The mask is a PNG under 4 MB with the first image's dimensions, transparent where it should change.", # openai-python 3.28.0 src/openai/resources/images.py Images.edit §mask
|
|
230
|
+
]
|
|
231
|
+
|
|
232
|
+
[openai.models."whisper-1"]
|
|
233
|
+
capabilities = ["text", "segment", "word"] # openai-python 3.28.0 src/openai/resources/audio/transcriptions.py Transcriptions.create §timestamp_granularities
|
|
234
|
+
asr = [
|
|
235
|
+
"Files up to 25 MB in flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav or webm.", # https://developers.openai.com/api/docs/guides/speech-to-text §File transcription; openai-python 3.28.0 src/openai/resources/audio/transcriptions.py Transcriptions.create §file
|
|
236
|
+
"language: an ISO-639-1 code such as en.", # openai-python 3.28.0 src/openai/resources/audio/transcriptions.py Transcriptions.create §language
|
|
237
|
+
"prompt: up to 224 tokens of sample text, whose spelling, punctuation and style the transcript follows.", # https://developers.openai.com/api/docs/guides/speech-to-text §Prompting; openai-python 3.28.0 src/openai/resources/audio/transcriptions.py Transcriptions.create §prompt
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
[openai.models."gemini-*-flash"]
|
|
241
|
+
capabilities = ["image", "audio"] # https://aistudio.google.com/docs/openai §Image understanding (image_url), §Audio understanding (input_audio)
|
|
242
|
+
|
|
243
|
+
[openai.models."gemini-*-argon"]
|
|
244
|
+
capabilities = ["image", "audio"] # https://aistudio.google.com/docs/openai §Image understanding (image_url), §Audio understanding (input_audio)
|
|
245
|
+
|
|
246
|
+
# Self-hosted models served by vLLM or vLLM-Omni.
|
|
247
|
+
|
|
248
|
+
[openai.models."Qwen/Qwen-Image-2.1"]
|
|
249
|
+
capabilities = ["generate", "edit", "reference"] # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/protocol/images.py; https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/api_server.py /v1/images/edits takes a list of images; src/multimodal_mcp/endpoints/openai.py OpenAI.generate_image sends references and edit images alike to images.edit
|
|
250
|
+
image = [
|
|
251
|
+
"size is WIDTHxHEIGHT.", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/protocol/images.py §validate_size
|
|
252
|
+
"options takes negative_prompt, seed, num_inference_steps (1-200), guidance_scale (0-20) and true_cfg_scale (0-20).", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/protocol/images.py §ImageGenerationRequest
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
[openai.models."OpenMOSS-Team/MOSS-Transcribe-Diarize"]
|
|
256
|
+
capabilities = ["text", "segment", "speaker"] # https://github.com/vllm-project/vllm/blob/7853700d4cdc2b84c728c840114ed42cda7454a7/vllm/model_executor/models/moss_transcribe_diarize.py §parse_verbose_transcript, §parse_diarized_transcript
|
|
257
|
+
asr = [
|
|
258
|
+
"prompt is the transcription instruction and replaces the default one, which asks for [start][S01]text[end] segments; hotwords is unsupported.", # https://github.com/vllm-project/vllm/blob/7853700d4cdc2b84c728c840114ed42cda7454a7/vllm/model_executor/models/moss_transcribe_diarize.py §DEFAULT_MOSS_TRANSCRIBE_DIARIZE_PROMPT, §get_generation_prompt: only request_prompt reaches the model
|
|
259
|
+
]
|
|
260
|
+
transcribe_audio = [
|
|
261
|
+
"The transcript marks each segment as [start][S01]text[end]; for clean speaker segments, use transcribe_audio_with_timestamps with speakers=true.", # https://github.com/vllm-project/vllm/blob/7853700d4cdc2b84c728c840114ed42cda7454a7/vllm/model_executor/models/moss_transcribe_diarize.py §parse_diarized_transcript
|
|
262
|
+
]
|
|
263
|
+
transcribe_audio_with_timestamps = [
|
|
264
|
+
"Timed segments and speaker labels are parsed from the default [start][S01]text[end] format, so a prompt for this tool must keep that format.", # https://github.com/vllm-project/vllm/blob/7853700d4cdc2b84c728c840114ed42cda7454a7/vllm/model_executor/models/moss_transcribe_diarize.py §parse_verbose_transcript, §parse_diarized_transcript
|
|
265
|
+
"Without speakers=true, segment text keeps its [S01] speaker prefix.", # https://github.com/vllm-project/vllm/blob/7853700d4cdc2b84c728c840114ed42cda7454a7/vllm/model_executor/models/moss_transcribe_diarize.py §parse_verbose_transcript
|
|
266
|
+
]
|
|
267
|
+
|
|
268
|
+
[openai.models."IndexTeam/IndexTTS-2"]
|
|
269
|
+
capabilities = ["voice", "reference"] # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/tts_adapters/indextts2.py: ref_audio, or a voice in uploaded_speakers; https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/api_server.py POST/GET /v1/audio/voices
|
|
270
|
+
generate_speech = [
|
|
271
|
+
"Pass reference_audio to clone a voice from a local audio file, or pass voice only when the user names a speaker already uploaded to the server (there are no built-in preset voice names).", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/tts_adapters/indextts2.py; https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/api_server.py /v1/audio/voices
|
|
272
|
+
"instructions is unused; for emotion, pass options {\"extra_params\": {...}} with use_emo_text true (the emotion comes from emo_text, or from input without it), or emo_vector, eight intensities 0-1.2 in the order happy, angry, sad, afraid, disgusted, melancholic, surprised, calm; emo_alpha scales either.", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/tts_adapters/indextts2.py §_INDEXTTS2_EMOTION_KEYS; vllm_omni/model_executor/models/indextts2/indextts2_talker.py; https://github.com/index-tts/index-tts README §Python API 3-6: emo_vector order
|
|
273
|
+
"response_format: mp3 (default), wav, pcm, flac or opus; speed: 0.25-4.0.", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/protocol/audio.py §OpenAICreateSpeechRequest: formats and speed range; the openai adapter requests mp3 when response_format is unset
|
|
274
|
+
]
|
|
275
|
+
|
|
276
|
+
[openai.models."IndexTeam/IndexTTS-2.5"]
|
|
277
|
+
capabilities = ["voice", "reference"] # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/tts_adapters/indextts2.py IndexTTS25Adapter extends IndexTTS2Adapter: ref_audio, or a voice in uploaded_speakers
|
|
278
|
+
generate_speech = [
|
|
279
|
+
"Pass reference_audio to clone a voice from a local audio file, or pass voice only when the user names a speaker already uploaded to the server (there are no built-in preset voice names).", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/tts_adapters/indextts2.py IndexTTS2Adapter.validate; https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/api_server.py /v1/audio/voices
|
|
280
|
+
"instructions is unused; for emotion, pass options {\"extra_params\": {...}} with use_emo_text true (the emotion comes from emo_text, or from input without it), or emo_vector, eight intensities 0-1.2 in the order happy, angry, sad, afraid, disgusted, melancholic, surprised, calm; emo_alpha scales either.", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/tts_adapters/indextts2.py §_INDEXTTS2_EMOTION_KEYS, inherited by IndexTTS25Adapter; vllm_omni/model_executor/models/indextts2/indextts2_talker.py
|
|
281
|
+
"extra_params also takes lang, the text's language code, zh by default (such as en, ja, yue, or zhen for mixed Chinese and English), and text_normalization, a boolean that defaults to true.", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/tts_adapters/indextts2.py IndexTTS25Adapter._validate_extra_params, _build_params; https://github.com/vllm-project/vllm-omni/blob/88cd44ad3624b16ef122049bd6534dd4e1e19195/vllm_omni/model_executor/models/indextts2/tokenizer_v2_5.py language codes
|
|
282
|
+
"response_format: mp3 (default), wav, pcm, flac or opus; speed: 0.5-2.0, which scales the spoken duration (2.0 speaks twice as fast).", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/protocol/audio.py §OpenAICreateSpeechRequest: formats; https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/tts_adapters/indextts2.py IndexTTS25Adapter.validate: speed 0.5-2.0, duration_factor = 1 / speed; the openai adapter requests mp3 when response_format is unset
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
[openai.models."MiniMaxAI/MiniMax-H3"]
|
|
286
|
+
capabilities = ["text", "frames", "reference"] # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/protocol/videos.py
|
|
287
|
+
generate_video = [
|
|
288
|
+
"Text-to-video needs aspect_ratio 21:9, 16:9, 4:3, 1:1, 3:4 or 9:16; with frames the ratio follows the image, and with references it defaults to 16:9.", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/protocol/videos.py §aspect_ratio
|
|
289
|
+
"Reference videos and audios run 2-15 s each.", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/model_executor/models/minimax_h3/reference_video.py
|
|
290
|
+
"resolution is unsupported; use aspect_ratio or size.", # src/multimodal_mcp/endpoints/openai.py OpenAI.generate_video
|
|
291
|
+
"seconds is a positive whole number.", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/protocol/videos.py §SecondStr
|
|
292
|
+
"Fields beyond the tool parameters go in options under extra_params.", # https://github.com/vllm-project/vllm-omni/blob/64903b8e30b6595e4018c66232abbbd806aa9dfd/vllm_omni/entrypoints/openai/protocol/videos.py §extra_params
|
|
293
|
+
]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""The API notes of api-notes.toml, whose header describes their scope and layout."""
|
|
2
|
+
|
|
3
|
+
import fnmatch
|
|
4
|
+
import tomllib
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from . import matching_names, notes_name
|
|
8
|
+
|
|
9
|
+
API_NOTES = tomllib.loads((Path(__file__).parent / "api-notes.toml").read_text(encoding="utf-8"))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def model_entry(endpoint: str, model: str) -> dict:
|
|
13
|
+
"""The model's entry under the endpoint, the first whose name or an alias matches it as a glob; empty when it has
|
|
14
|
+
none."""
|
|
15
|
+
matching = matching_names(model)
|
|
16
|
+
return next(
|
|
17
|
+
(
|
|
18
|
+
entry
|
|
19
|
+
for key, entry in API_NOTES.get(endpoint, {}).get("models", {}).items()
|
|
20
|
+
if any(
|
|
21
|
+
fnmatch.fnmatchcase(name, notes_name(glob))
|
|
22
|
+
for name in matching
|
|
23
|
+
for glob in (key, *entry.get("aliases", []))
|
|
24
|
+
)
|
|
25
|
+
),
|
|
26
|
+
{},
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def rules(endpoint: str, model: str, category: str, tool: str) -> list[str]:
|
|
31
|
+
"""The API notes for a tool on this model: the endpoint's, then the model's, each by category, then by tool."""
|
|
32
|
+
table = API_NOTES.get(endpoint, {})
|
|
33
|
+
entry = model_entry(endpoint, model)
|
|
34
|
+
return [rule for scope in (table, entry) for key in (category, tool) for rule in scope.get(key, [])]
|