mcpField
R
rendercheck

rendercheck

本地服务
github.com/rogermsc媒体与设计010 周前更新

关于 rendercheck

rendercheck 是用于检查生成音频、视频和图像中可测缺陷的 Python 库与命令行工具,适用于媒体生成和构建流水线,并返回判定报告而非生成媒体。

主要功能

  1. 01音频语速与响度断言
  2. 02时长、静音与轨道检查
  3. 03字幕时序与说话者检查
  4. 04基于视觉规则的图像检查
  5. 05提供 JSON 报告和退出码

适用场景

  1. 01在 pytest 中验收生成的节目
  2. 02在 CI 中发现截断的渲染文件
  3. 03发布前检查音频与字幕
  4. 04检查生成幻灯片的布局问题

MCP 相关

MCP 服务向 MCP 客户端提供媒体检查工具,包括返回判定与测量值的 `check_media`。除 `looks_ok` 外,大多数检查均为确定性检查且无需密钥。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"rogermsc-rendercheck": {
"command": "uvx",
"args": [
"rendercheck"
],
"env": {
"ANTHROPIC_API_KEY": "<ANTHROPIC_API_KEY>"
}
}
}
}
启动命令uvx rendercheck
需要配置的环境变量
ANTHROPIC_API_KEY密钥Only for the optional `looks ok` vision check. Every other check is deterministic and needs no key.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypirendercheck0.4.1

工具

2

收录的工具列表 · 更新于 2 周前

参数类型必填说明
pathstring是要检查的媒体文件。指定目录时会检查其中的内容。
presetenum否此文件目标用途对应的响度目标。apple | atsc | ebu | netflix | podcast | spotify | tiktok | web | youtube
rubricarray否静帧必须满足的条件,例如 'the title fits on one line'。启用视觉检查,该检查需要 API key。
scriptstring否旁白文本,或转录文本、.vtt、.srt 文件的路径。启用语速检查。
strictboolean否将无法运行的检查计为失败。
captionsstring否用于与音频比对的 .vtt 或 .srt 文件。如果文件与媒体文件同名且位于同一目录,则会自动查找。
presenterstring否预期的旁白讲述者。启用说话人检查,该检查还需要 known_names。
expect_fpsnumber否渲染所要求的帧率。还会检测可变帧率,它是导致音画不同步的常见原因。
known_namesarray否所有实际可能被选为讲述者的人员。必须与 presenter 一起提供:如果没有此项,场景中的角色说“I'm Rosa”会导致每个讲故事的脚本都触发检查。
expect_widthnumber否渲染所要求的画面宽度,单位为像素。
expect_heightnumber否渲染所要求的画面高度,单位为像素。
expect_channelsnumber否交付规格要求的声道数:1 表示单声道,2 表示立体声。
expected_secondsnumber否渲染预期的时长。
expect_sample_ratenumber否交付规格要求的音频采样率,单位为 Hz。

详细介绍

rendercheck

PyPI CI Python License: MIT

生成媒体中最糟糕的 Bug 不会抛出异常。

“音频经常会截掉最后一句话 […],尽管 API 返回成功,也没有任何错误信号”

— 一位开发者在 OpenAI 论坛 上的发言, 2026 年 4 月,描述生产环境中的输出

rendercheck 演示

如果你用模型生成语音或视频——TTS、语音 Agent、播客、虚拟形象、AI 视频——测试能捕获那些从未发生的异常,却捕获不了每分钟朗读 300 个单词的旁白、比其对应画面低 18 dB 的音轨、只渲染了 42% 时长却被缓存为成功的片段、早于音频三秒描述内容的字幕,或完全缺少音轨的文件。

在 2026 年,检测这些问题的最先进方法仍然是有人听一遍输出。这确实有效,但成本比你整个流水线中的其他所有环节加起来都高。

rendercheck 会让这些问题抛出异常。

from rendercheck import assert_pace, assert_loudness, looks_ok

assert_pace("episode-12.mp3", "episode-12.vtt")
assert_loudness("episode-12.mp3")
looks_ok("slide-14.png", ["the title fits on one line"])

纯粹的断言函数。没有框架、运行器或服务。它们会抛出 AssertionError,因此可直接用于 pytest、CI 或五行脚本。19 项检查中有 18 项不依赖任何项,也不会发起网络请求——只要你有 ffmpeg,就可以开始使用。


快速开始

你需要让 ffmpeg 位于 PATH 中(brew install ffmpeg、apt-get install ffmpeg 或 winget install ffmpeg)。然后:

pip install rendercheck
rendercheck demo

或者将文件放入**在线体验区**——运行相同的检查,使用编译为 WebAssembly 的 ffmpeg,不会上传任何内容。

demo 会合成 10 个有缺陷的文件,并对它们运行实际检查,让你无需拥有有问题的渲染文件也能看到效果。以下是原样输出的前两项(共 8 项):

Narration too fast
  A voice picked to match a presenter's face read English at machine-gun speed. Valid audio, correct timing, perfectly in sync.

  $ rendercheck check machine-gun.wav --script narration.vtt

  FAIL  pace        narration pace 300 WPM exceeds 245 (300 words in 60.0s) -- this reads as machine-gun delivery and listeners cannot follow it: machine-gun.wav
  PASS  loudness    -16.1 LUFS
  PASS  dead air    0.0 s silence
  PASS  truncation  8.9 dB of fall-off at the end
  PASS  clipping    0 samples at 0 dBFS

Levels that don't match
  Synthesised narration landed 18 dB under the footage it was cut against. Nobody noticed until viewers rode the volume knob.

  $ rendercheck check too-quiet.wav

  SKIP  pace        no --script given
  FAIL  loudness    -34.2 LUFS is 18.2 dB quieter than the -16 target -- it will sound inaudible next to correctly-levelled audio cut alongside it: too-quiet.wav
  PASS  dead air    0.0 s silence
  PASS  truncation  8.8 dB of fall-off at the end
  PASS  clipping    0 samples at 0 dBFS

……以及在 0.3.0 中新增的两项之一:

Captions against the wrong clock
  A concatenation added three seconds of pre-roll after the captions were written. Both files are perfectly valid on their own.

  $ rendercheck check late-captions.wav

  SKIP  pace        no --script given
  PASS  loudness    -16.0 LUFS
  PASS  dead air    0.0 s silence
  PASS  truncation  74.3 dB of fall-off at the end
  PASS  clipping    0 samples at 0 dBFS
  FAIL  captions    late-captions.vtt runs 3.0s late against late-captions.wav, past the 0.75s limit -- every line arrives at the wrong moment, and both files are individually valid so nothing else catches it

然后将它用于你自己的输出:

rendercheck check episode-12.mp3 --script episode-12.vtt --preset podcast

只要有任何检查失败,退出代码就是 1;如果无法测量任何内容,退出代码也是 1,因为什么都没检查的运行不能算通过。路径拼错时退出代码为 2。--json 会为任何语言的流水线提供相同的报告,而 --strict 也会拒绝不完整的运行。

这个文件要放到哪里?

“音量应该多大?”没有唯一答案——这完全取决于文件的最终用途,而且每个平台公布的数值都不一样。--preset 将这些数值转化为构建流程可以强制执行的规则:

$ rendercheck presets

  preset    target     tol     peak  source
  youtube     -14L   1.0dB   -1.0TP  YouTube normalises playback to -14 LUFS
  spotify     -14L   1.0dB   -1.0TP  Spotify, including podcasts, at -14 LUFS
  tiktok      -14L   1.5dB   -1.0TP  TikTok and Instagram, measured rather than published
  podcast     -16L   1.0dB   -1.0TP  AES71 / Apple Podcasts: -16 LUFS stereo, -19 mono
  apple       -16L   1.0dB   -1.0TP  Apple Music Sound Check, -16 LUFS
  web         -16L   2.0dB       --  spoken-word web video -- rendercheck's own defaults
  ebu         -23L   1.0dB   -1.0TP  EBU R128, European broadcast
  atsc        -24L   2.0dB   -2.0TP  ATSC A/85, North American broadcast
  netflix     -27L   2.0dB   -2.0TP  Netflix delivery, dialog-gated

这些数值没有一个是我们制定的。我们的贡献在于,--preset ebu 是评审者一眼就能看懂的明确选择,而 --target-lufs -23 则是一个后来者不敢改动的神秘数字。设定上限的预设还会启用真峰值检查,以捕获本地测量正常、上传后却失真的母带。web 仅用于命名内置默认值,因此它不指定任何数值,行为与完全不传预设完全相同。

项目级设置可以放在 rendercheck.toml(或 pyproject.toml 中的 [tool.rendercheck])里,这样 CI 步骤就不必把 8 个标志挤在一行:

preset = "podcast"
max_silence = 5.0

手动输入的标志优先于配置文件,而配置文件优先于内置默认值。

在 pytest 中,它们就是普通断言——无需插件或 fixtures:

@pytest.mark.parametrize("episode", EPISODES)
def test_episode_is_shippable(episode):
    assert_pace(episode.audio, episode.vtt)
    assert_loudness(episode.audio)
    assert_no_dead_air(episode.audio)

“这不就是四十行的 pyloudnorm 吗?”

对于十九项检查中的一项,差不多是这样。这些测量都不新鲜,声称它们有新意并不诚实:

测量项已有工具
综合响度、真峰值pyloudnorm、ffmpeg 的 loudnorm
静音检测pydub.silence、ffmpeg 的 silencedetect
时长、流布局、帧率ffprobe
黑帧、画面冻结ffmpeg 的 blackdetect、freezedetect
字幕↔音频偏移ffsubsync——它会校正偏移
容器和编解码器合规性MediaConch——基于策略、通过/失败判断,可从 CLI 使用
说话人身份resemblyzer
视频质量指标VMAF、ffmpeg-quality-metrics

其中大多数工具只是把一个数值交给研究人员。已经能作为门禁的两个工具,检查的则是另一回事:MediaConch 检查文件是否符合容器策略,这是保存方面的问题,而不是感知方面的问题——文件可以通过 MediaConch 的每一条规则,却仍然以 300 WPM 的语速进行旁白。ffsubsync 会欣然重新对齐原本没错的字幕,因为它并不判断字幕是否需要对齐。

真正缺少的,也是这个工具提供的:

  • 来自缺陷的阈值,而不是来自论文。245 WPM,是因为真实配音曾以 280 WPM 录制并交付。−16 LUFS,是因为旁白音量只有 −34 LUFS,而画面素材为 −13 LUFS。
  • 说明人会注意到什么的消息。“−34.0 LUFS”只是一个读数。“比 −16 的目标低 18.0 dB——与剪辑在一起、音量正确的音频相比,它会听不见”才是一条缺陷报告。
  • 基础设施出错时放行,出现缺陷时拦截,这样它就能用于 CI,而不会因为自身的问题变成构建失败的原因。
  • 退出码和一个可对目录执行的命令,而不是一个 Notebook。

与 LLM 评估工具相比,区别在于结构,而不是覆盖范围。promptfoo、 DeepEval 和 RAGAS 都很出色,但它们都做不到这一点:它们的测试用例是一个字符串。你无法添加断言,因为没有地方放文件。用它们检查脚本;用这个工具检查脚本生成的成品。

如果你已经在运行广播级 QC——Interra BATON、Telestream Vidchecker、QCTools——那么二十年来你基本都已经拥有了这些功能。它只是还没进入你的 git hooks。

在你的流水线中

GitHub Actions——安装 ffmpeg,并在发现缺陷时使构建失败:

- uses: rogermsc/rendercheck@v0
  with:
    files: out/
    preset: podcast
    strict: "true"

Node、Remotion,以及任何在构建步骤中进行渲染的工具:

npx rendercheck check out/

Docker,如果你不想使用任何 Python 工具链——镜像中已经有 ffmpeg:

docker run --rm -v "$PWD:/work" ghcr.io/rogermsc/rendercheck check /work/out.mp4

编码 Agent,通过 MCP 使用。刚写完渲染流水线并运行它的 Agent,无法判断生成的文件质量如何;其他媒体 MCP 服务会剪辑和转码,因此给它的是更多媒体,而不是答案:

claude mcp add rendercheck -- rendercheck mcp

它已列入 MCP registry,名称为 io.github.rogermsc/rendercheck,因此能读取 registry 的客户端无需知道它的位置即可安装。无需密钥——除 looks ok 之外的所有检查都是确定性的。

check_media 会为每项检查返回一个判定及测量值,因此模型可以根据“−34 LUFS,比目标低 18 dB”采取行动,而不必面对一个它无法听见的文件。

promptfoo——它的断言全都针对字符串,因此评估可以确认旁白脚本,却无法告诉你音频的情况。examples/promptfoo/ 用三十行代码补上了这一部分:

assert:
  - type: python
    value: file://rendercheck_assert.py:get_assert

其他任何场景——通过 stdout 输出 --json,每个文件对应一个对象,并返回退出码。


六项检查,六起事故

每个默认值都是由实际发布的缺陷确定的阈值,而不是为了对称而选的数字。 以下输出均为原文。每个阈值都是一个参数——调整方法请参见参考文档。

旁白语速过快。 为匹配演示者面部而选的声音,以约 280 WPM 的语速朗读英文。音频有效、时长正确、同步完美。只是听起来像机关枪。

assert_pace("episode-12.mp3", "episode-12.vtt", max_wpm=245)
narration pace 300 WPM exceeds 245 (300 words in 60.0s) -- this reads as
machine-gun delivery and listeners cannot follow it: episode-12.mp3

音量不匹配。 合成旁白的响度为 −34 LUFS,与响度为 −13 的视频片段拼接在一起。同一个文件,中间出现了 20 dB 的音量跃变。直到观众花了 45 分钟不停调节音量旋钮,才有人注意到。

assert_loudness("episode-12.mp3", target_lufs=-16, tol=2.0)
-34.0 LUFS is 18.0 dB quieter than the -16 target -- it will sound inaudible
next to correctly-levelled audio cut alongside it: episode-12.mp3

被缓存为成功的截断渲染。 编码失败生成的片段只有预期时长的一小部分,但流水线却将其缓存为成功。重试只会重新运行那些报错的任务——而这些任务并没有报错。

assert_duration("segment-07.mp4", expected_seconds=24.0)
segment-07.mp4 is 10.0s -- 42% of the expected 24.0s. A render this short is a
silent encode failure, not a short take; re-render rather than retry

中间有空洞。 合成过程发生瞬时且无声的故障,导致文件中间出现一段空白。时长正确,平均响度正确。只有中间部分出现了空洞。

assert_no_dead_air("episode-12.mp3", max_silence=3.0)
6.2s of silence starting at 0:41 exceeds the 3s limit -- a gap this long
mid-file is a dropped segment, not a pause (2 found in total): episode-12.mp3

说话的人错了。 脚本中写着“我是 Jordan”,但系统分配的却是 Alex。整个模块都以错误的面孔和错误的声音渲染。其他所有关卡都通过了。

assert_speaker(script, expected="Alex", known_names=["Alex", "Jordan", "Sam"])
the script introduces the presenter as "Jordan" but Alex is assigned -- the
rendered avatar would introduce itself with someone else's name. Fix whichever
is wrong: the assigned presenter, or the name in the script

known_names 名单是必需的,也是关键所在:没有它,场景中的角色说出*“我叫 Rosa,是一名护士”*时,每个讲故事的脚本都会触发检查。只有属于实际可能被选中的人物的姓名,才算是对说话者身份的声明。

只能通过视觉发现的问题。 溢出的标题、彼此碰撞的徽标、只填了一半的画布、被裁到字幕中间的人物。这些内容都在渲染时没有报错。

looks_ok("slide-14.png", ["the title fits on one line", "no text is clipped"])
[major] slide-14.png: the title wraps to three lines and overlaps the logo in
the top-right corner -- failed rubric item: 'the title fits on one line'

这是唯一需要密钥的检查:pip install "rendercheck[vision]"。

还有十三项,针对其他人反复报告的缺陷

上面六项来自同一条流水线。接下来的这些则来自阅读其他人的错误报告——同样的投诉,轮番指向每一家提供商:

检查项缺陷
assert_no_truncation语音在句子中途停止,但 API 返回成功。这是生成音频中报告最多的缺陷;以文件自身的平均音量为基准进行测量,因此无论内容音量高低都适用。
assert_has_sound返回的片段没有声音——升频步骤丢弃了音轨,混流指向了错误的流,或合成过程写入了全零数据。
assert_no_clipping增益级将波形推到了满量程以上。辅音出现爆裂声,之后再调低音量也无法消除。
assert_true_peak本地测量正常,上传后却失真。响度和峰值是两个不同的问题:有损编解码器会重建样本之间的波形,并在波形越界处造成削波。
assert_no_black_frames生成的视频截断成黑屏,却没有报错:时长正确,容器有效,最后三分之一没有内容。
assert_not_frozen画面停止运动。每一帧都存在,但每一帧都是同一帧。
assert_captions_aligned字幕按一个时钟编写,音频却按另一个时钟渲染。每一行都在错误的时刻出现,而两个文件单独看都完美无缺。
assert_streams_aligned声音和画面覆盖的时长不一致——混流时某个输入耗尽,或拼接时首个片段的时间安排有误。
assert_format渲染结果悄悄降到了 720p、帧率不正确,或采用了可变帧率,而下游流水线假定使用恒定帧率。
assert_not_blank图像生成器失败并返回空画布——DALL·E、Stable Diffusion、Qwen、Gemini 和 Krita 都报告过这种情况,而且表现始终相同:没有错误,没有警告,尺寸正确,画布上却空无一物。它能检测任何纯色画布,不只是黑色画布;blackdetect 检测不到其他纯色画布。
assert_loudness_range文件没有一个合适的统一音量设置:为了听清安静段落而调大音量,响亮段落又会吓人。这与 assert_loudness 问的问题不同,后者只关注音量中间值。
assert_audio_format要求立体声却交付了单声道,或规格要求 48 kHz 却交付了 44.1 kHz——之后由链路中碰巧使用的转换器进行重采样。
assert_lip_sync说话人嘴部动作与语音不同步。容器正确,流有效,时长一致,assert_streams_aligned 也通过了——因为它读取的是容器时间信息,而这项检查读取的是内容。默认关闭,而且拒绝判断的次数多于给出判断的次数:参见 它不检查的内容 下方的说明。

空白检查是不需要密钥的一项检查。 在它出现之前,静态图像必须先经过视觉层级检查,这个工具才会对它作出任何判断,因此 rendercheck check slide.png 无法测量任何内容,并以非零状态退出。它读取的是亮度分布上下端之间的跨度,而不是最小值与最大值之间的跨度,这正是它可靠的原因:包含单个杂散伪影的空白帧,用最小值/最大值计算时会覆盖整个范围,但在这里仍会被判定为空白。

字幕检查是唯一没有同类功能的检查。 ffsubsync 及类似工具会校正漂移;在线验证器只会单独检查 .srt 文件——例如字幕条目重叠、阅读速度和空行。两者都不会检查这个字幕文件是否与这段音频匹配,而这正是构建流程唯一需要回答的问题。它通过匹配语音形态与字幕条目的形态来工作,并分别报告固定偏移和漂移:偏移是整体偏离正确位置,而漂移无法通过单次整体移动来修正。 这些检查项在无法测量时都会跳过,而不是通过——没有视频流、没有可供对齐的静音结构,或容器中没有每个流的时长。对 .wav 执行 blackdetect 不会报告任何内容,否则这可能会被误读成“检查过了,一切正常”。这与下面的回归问题是同一个陷阱,也是所有检查项都跳过时运行仍以非零状态退出的原因。


在真实文件上发现的问题

这不是合成基准测试。我们将它用于一个大规模渲染旁白视频的生产流水线输出:

结果
已知质量合格的课程正常——162 WPM,−14.1 LUFS,无无声片段
响度修复合入后重新渲染的内容以 −14.2 LUFS 通过
修复前渲染的 4 集内容以 −19.4 至 −21.3 LUFS 未通过

它恰好在修复合入处划出了分界线;这些文件从未被告知任何信息,但所得结论与人们几个月前就已得出的结论一致。

这张表只是一个轶事,而且明确标注了这一点。 媒体文件是私有的,因此没人——包括作者本人——能够重新运行测试。你可以核验的数据见 docs/calibration.md,由 bench/bench.py 生成:

python bench/bench.py sync        # no network, no corpus, about a minute

该脚本会向已知答案的媒体中注入已知程度的缺陷,并统计每项检查实际报告了什么;未作出判断的情况也计入分母,每个零值旁都会打印三法则界限。本库中每个有实测依据的阈值,都源自这里。

两项承诺

基础设施出问题时会默认放行。 没有 ffmpeg、没有密钥、没有网络、无法测量 → 发出警告并放行。如果一个门禁因自身故障而阻塞你的流水线,它一周内就会被删掉,之后便再也起不到保护作用。缺陷默认拒绝;检查器默认放行。(文件缺失是你拼错了路径,不属于基础设施问题——这种情况仍会引发异常。)

绝不把沉默误认为成功。 无法运行的检查会明确说明,显示为 rendercheck.Skipped 警告,也会出现在 CLI 输出中。一次空运行绝不会被误读为检查正常。

我们为做到第二点,前后努力了两次。

这个库的第一个版本会对完全没有音轨的文件返回 PASS——没有可供分析的内容时,silencedetect 不会报告任何内容,于是被误读成“未发现静音”。如今,这是测试套件中最醒目的失败案例,回归测试也以它命名。它教会我们的原则适用于所有其他情况:测量后发现结果不正确,就默认拒绝;无法测量,就默认放行。

随后,在以这个名称发布之前,我们根据工具自身的设计初衷对其进行了审计,又发现了另外 7 个问题。每个问题都会在尚未确认检查成功时报告成功:

  • 全部跳过的运行以 0 退出。运行器上没有 ffmpeg,构建便显示为绿色。
  • 文件路径拼错时以 0 退出,与上文两段前的承诺相矛盾。
  • --script 路径拼错时,文件内容被当成旁白——只有一个词——并给出一个关于音频的自信错误判定:1 WPM is below 110。
  • 未提供 --known-names 时,--presenter 会将人员名单默认设为指定的主持人,导致说话人检查在结构上不可能触发。即便脚本中提到了其他人,它也会输出 PASS。
  • looks_ok 会把任何异常都归咎于缺少 API 密钥,因此即使 SDK 不兼容也会永远放行,还会让 Bedrock 用户追查错误方向。
  • ffprobe 故障会在消息中泄露原始 Python 列表。
  • 没有 ffmpeg 时,测试套件会在收集阶段崩溃,而不是跳过测试。

这 7 个问题都已修复,每项修复都有一个缺少该修复就会失败的测试;退出码如今也有明确约定:0 表示已测量且正常,1 表示存在缺陷或未测量任何内容,2 表示路径不存在。详情见变更日志。

一个能发现静默失败的工具,其价值完全取决于它是否能如实报告这些失败。

不检查的内容

明确说明这一点,因为 QA 工具要是暗示自己覆盖的范围超出实际能力,那还不如没有:

  • 达到实际所需容差的唇形同步。 assert_lip_sync 会将画面运动与语音包络进行相关分析,在没有人脸检测、也没有模型的情况下,能发现嘴部动作与声音相差近半秒的大多数情况。但它做不到两件事。它无法检测出感知上真正重要的误差:EBU R37 规定,音频领先 +40 ms、滞后 −60 ms 时即可察觉;而它只能检测出不到三分之一的 200 ms 误差。此外,它会对大约三分之二的文件不作判断,因为这些文件的相关峰值不够明显,无法据此读出数值。它能发现损坏的流水线,但不能证明流水线正常;要做到这一点,仍需要模型(SyncNet 等)。
  • 视频的感知质量。 不支持 PSNR、SSIM 或 VMAF——这些指标需要参考编码进行对比,而生成的媒体没有参考编码。
  • 旁白是否正确——这里只检查朗读速度,以及字幕是否与时间同步。这里没有任何功能会转录音频,因此,即使声音读错了稿子,只要语速合理,也能通过所有检查。这项检查需要用到 Whisper,而相对于其他部分,它引入的依赖过于庞大。事实依据和准确性又是另一个问题,LLM 评估工具已经能很好地覆盖这一点。
  • 语音清晰度。 音量大不等于清晰;音轨即使电平正确,仍可能含糊不清。
  • 音乐、混音或任何非语音内容。 默认设置是为口语设计的。
  • 你没有编写的评分规则。 looks_ok 只会检查你要求它检查的内容。

更多信息

  • 症状——“TTS 截掉了最后一句”“片段没有声音”,以及分别由哪项检查发现
  • 参考与调优——所有阈值,以及何时关闭某项检查
  • 贡献——新增检查的标准
  • 更新日志

MIT。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。