关于 Model Manager
Model Manager 是用于管理本地 Ollama 和 vLLM 模型机器的 MCP 服务,面向需要通过语言模型工具管理自有模型环境的操作者。它通过固定操作和白名单控制模型获取、服务切换及 LoRA 训练,不提供任意命令执行。
主要功能
- 01查看机器状态与已安装模型
- 02获取和移除模型
- 03切换 vLLM 推理服务模型
- 04创建自定义 Ollama 变体
- 05启动、跟踪和取消 LoRA 训练
- 06按操作等级限制管理权限
适用场景
- 01检查 GPU 内存、磁盘和运行服务
- 02在本地模型机器上获取或删除模型
- 03为不同模型切换 vLLM 服务
- 04启动并监控 LoRA 训练任务
MCP 相关
该 MCP 服务向语言模型工具提供本地模型机器的状态查询及受控管理工具。管理操作通过 SSH 控制通道执行,且不包含任意命令执行工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
uvx mcp-modelmanagerMM_VM_HOSTAddress of the model machine (127.0.0.1, LAN IP or tunnel/VPN address)MM_VM_USERSSH user on the model machineMM_CONTAINER_ROOTRoot directory on the machine holding all model, adapter and cache dataMM_MAX_TIERHighest tool tier exposed: read, control or destructiveMM_ENABLED_OPERATIONSOptional comma-separated allowlist of exact tool names, applied on top of MM_MAX_TIER; a typo aborts startup. Empty means everything within MM_MAX_TIERMM_VM2_HOSTOptional: address of a second machine sharing the GPU, used to interpret unreachability. Leave empty if there is only one machine本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
mcp-modelmanager
通过语言模型工具(Claude、ChatGPT 等)管理你自己的本地模型机器。模型及其数据都保留在你的硬件上;此服务器经过设计,不会让这台机器因该软件而必须连接到互联网。
此 MCP 服务让 AI 会话能够受控地访问你自己的 Ollama/模型机器:读取状态、拉取和移除模型、将推理服务切换到其他模型、构建自定义 Ollama 变体以及运行 LoRA 训练。模型运行在你的硬件上。服务器进程本身只会与自己的计算机或本地网络通信,不会自行连接公共地址。它确实会主动连接公共地址获取模型:调用 fetch_model 会让模型机器在运行时连接 Hugging Face 下载模型。这是由工具触发的、明确的出站连接,并非服务器在后台擅自进行,也不是只在初次设置时才进行。
switch_service 本身不会连接 Hugging Face;如果机器上尚未有该模型,它会拒绝操作并提示你先运行 fetch_model。
这意味着什么,又不意味着什么。 推理本身在本地进行:你发给所管理模型的提示词及其回答不会发送给任何云端模型提供商。但通常情况下,用来驱动此服务器的语言模型(Claude、ChatGPT 等)本身是一项托管服务。你发给它的指令以及它看到的工具结果,都会像其他 MCP 调用一样经过该提供商。“本地”指的是受管理的机器及其数据;这并不意味着你输入的所有内容都不会传给第三方。请据此选择用于驱动服务器的模型,或使用本地模型来驱动它。
操作系统: 纯查询路径(通过隧道读取状态和模型)可跨平台运行。管理和设置(服务与训练控制)需要带有 systemd 的 POSIX 系统(systemd 用户单元、ssh -F /dev/null);Windows 不支持管理操作。
此服务器没有自己的地址,也没有机器的默认值。你需要填写机器所在的位置;未提供这些信息时,服务器会有意拒绝启动(参见必填字段和SETUP.md)。
服务器可以做什么,不能做什么
可以: 查询状态(GPU 内存、磁盘空间、运行中的服务、容器),列出/拉取/移除模型,将 vLLM 推理服务切换到其他模型(并预先估算所需内存),构建自定义 Ollama 变体(固定系统提示词、参数,之后还可添加适配器),以及启动/跟踪/取消 LoRA 训练。
不能做,也有意不会做: 在机器上运行任意命令。它没有用于自由远程控制的工具。每项操作都是固定模板;每个参数都会先经过允许列表检查(参见安全模型:固定操作)。
它不是查询桥接服务。 如果只是想询问模型,请使用单独的只读 MCP 服务(例如,连接到 Ollama 的简单 HTTP 桥接服务)。此服务器用于管理机器。将两者拆分为不同服务,可以确保查询调用不会意外获得管理权限。
你的机器:三种可能的情况
模型机器可以通过不同方式连接。三种情况都受支持;你只需输入不同的地址。
| 情况 | Ollama/vLLM 的运行位置 | 你为 MM_VM_HOST 输入的内容 |
|---|---|---|
| a) 同一台机器 | 与此服务在同一台计算机上 | 127.0.0.1 |
| b) 位于本地网络 | 同一局域网中的另一台计算机上 | 其局域网地址,例如 192.168.1.10 |
| c) 通过隧道/VPN | 位于可通过 VPN/隧道访问的远程计算机上 | 你本机/VPN 这一端的地址,例如本地 SSH 隧道使用 127.0.0.1,或 VPN 地址 |
安全措施:服务进程自身的 MCP/SSH/HTTP 流量只会发往本机或本地网络。MM_VM_HOST 不接受范围之外的地址(公网 IP、外部主机名),因此服务不会自行连接公网地址来与模型机器通信。对于情况 c),这意味着隧道/VPN 的终点位于本地或私有地址范围内,你输入的是该本地/私有地址,而不是远端的公网地址。这项安全措施不涵盖模型下载:每当你要求模型机器获取模型时,fetch_model 都会使其连接 Hugging Face(一个公网地址)(参见上面的注意事项);如果模型尚未位于机器上,switch_service 会拒绝切换,而不会获取模型。fetch_model(source="ollama") 会让机器连接到另一个同样需要明确指定的公网地址:它会让机器上的 Ollama 守护进程通过 /api/pull 拉取模型;对于普通模型名称,该请求会连接 registry.ollama.ai;带有 hf.co/user/repo 前缀的名称则会连接另一个注册表。
普通的查询(状态、版本、已加载模型)通过 HTTP 发送到服务端口。管理操作(拉取模型、切换服务、训练)则通过安全的 SSH 控制通道进行。因此,执行管理操作需要能够通过 SSH 访问该机器,即使是情况 a) 也一样(此时通过 SSH 连接到 127.0.0.1)。
安装
要求:Python 3.11 或更高版本。
使用 uv(推荐):
uv venv --seed .venv
.venv/bin/pip install -r requirements.txt
--seed 可确保 venv 中存在 pip。
使用 Python 内置功能(备用方案):
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
如果在你的系统上运行 python3 -m venv 生成的 venv 不含 pip(缺少 ensurepip),请使用上面的 uv 方案。
只有两个直接依赖项,且都已固定版本:MCP SDK(mcp==1.30.0)和 HTTP 客户端(httpx==0.28.1)。这两个固定版本记录在 requirements.txt 和 pyproject.toml 中;完整解析后的依赖树(包括传递依赖包 anyio、pydantic、starlette、uvicorn、jsonschema、pyjwt)也固定在 uv.lock 中。CI 会通过 uv lock --check 检查锁定文件是否仍与 pyproject.toml 一致,然后为测试安装锁定的确切依赖树,因此锁定文件发生偏差时 CI 会失败。另有一个独立的建议性 pip-audit 任务,会在每次向 main 推送和每次拉取请求时,以及每周检查锁定的依赖树中是否存在已知漏洞;它不会阻止拉取请求。SSH 访问使用系统的 ssh 程序。
必填字段
服务器仅从环境变量读取配置。 以下三个字段必须设置,否则服务器不会启动:
| 字段 | 含义 |
|---|---|
MM_VM_HOST | 模型计算机的地址(127.0.0.1、局域网 IP 或隧道/VPN 地址) |
MM_VM_USER | 该计算机上的 SSH 用户名(仅用于通过控制通道进行管理) |
MM_CONTAINER_ROOT | 模型计算机上的根目录,所有模型、适配器和缓存数据都存放在此目录下 |
如果缺少任何一个字段,启动过程都会中止,并明确指出缺少哪个字段。示例:
$ PYTHONPATH=src .venv/bin/python -m mcp_modelmanager.server
MM_CONTAINER_ROOT is not set. Enter the root directory on your model machine
under which all model, adapter and cache data live. Without this value the
server does not start. See SETUP.md.
其他字段都有合理的默认值(Ollama 和 vLLM 的标准端口,密钥存储在你自己的 ~/.ssh 中),仅在需要时设置;请参阅环境变量。
从空白状态开始,逐步完成设置直至服务器运行(包括安全的 SSH 通道)的完整指南,见 SETUP.md。搭建 GPU 模型计算机本身(安装 Ollama 和/或 vLLM,并使其可通过下方的 MM_* 变量访问)是计算机端的任务;相关内容随此仓库一同提供:运维端脚本(setup/、vm_side/)、网络隔离模板(security/)和计算机端指南(MACHINE.md、SECURITY.md、SETUP-MACHINE.md)都与服务器代码位于同一目录下。计算机端请从 MACHINE.md 开始。
注册 MCP(占位符示例)
将服务器注册到你的语言模型工具中。请将尖括号中的占位符替换为实际值。有两种方式可将命令指向服务器,均受支持:
从代码检出目录运行(无需安装步骤,PYTHONPATH 指向 src/):
{
"mcpServers": {
"modelmanager": {
"command": "/path/to/mcp-modelmanager/.venv/bin/python",
"args": ["-m", "mcp_modelmanager.server"],
"cwd": "/path/to/mcp-modelmanager",
"env": {
"PYTHONPATH": "src",
"MM_ACCESS": "direct",
"MM_VM_HOST": "<your-machine-or-127.0.0.1>",
"MM_VM_USER": "<your-ssh-user>",
"MM_CONTAINER_ROOT": "/srv/models"
}
}
}
}
执行 pip install . 后运行(使用控制台入口点,无需设置 cwd/PYTHONPATH):
{
"mcpServers": {
"modelmanager": {
"command": "/path/to/mcp-modelmanager/.venv/bin/mcp-modelmanager",
"env": {
"MM_ACCESS": "direct",
"MM_VM_HOST": "<your-machine-or-127.0.0.1>",
"MM_VM_USER": "<your-ssh-user>",
"MM_CONTAINER_ROOT": "/srv/models"
}
}
}
}
这两个代码块都遵循纯粹的 mcpServers JSON 格式,大多数 MCP 客户端都会读取该格式(Claude Code、Claude Desktop,以及任何其他会读取 mcpServers JSON 块的 MCP 客户端);请查阅客户端文档,了解应将此代码块放在哪里。
MM_ACCESS 可设为 direct(服务器通过给定地址与服务端口通信)或 tunnel(服务器与 127.0.0.1 通信,并按需建立 SSH 隧道;仅在完成隔离后才适用,见 SETUP.md)。默认值为 tunnel;上面的示例设为 direct,因为在不需要第 2 级隧道的 a)/b) 配置中应使用该模式。因此,在该隧道配置完成之前,请显式设置 MM_ACCESS=direct。
安全模型:固定操作
没有任何工具可以运行任意命令。每项操作都是 operations.py 中的固定模板。调用方只能填写命名占位符,而且每个值都必须先通过允许列表(validation.py)验证:只有明确符合约定格式的值才允许使用。系统不会将其筛除,而是允许符合条件的值通过。替换占位符时还会使用 shlex.quote 对值加引号;这只是额外的防护,并非安全保障。
两端都会进行检查:此处在发送前检查一次,模型计算机上运行的对应端也会独立再次检查;该对应端与控制通道密钥绑定。因此,即使密钥被盗,也只能访问这一组有限的操作。
此外,目标只能是本机或局域网上的设备;每次使用时都会解析并重新检查名称(不像查询服务器那样固定地址;如果使用主机名,建议将 MM_VM_HOST 设为 IP)。代码中不含凭据,也没有 .env 文件。
两个 SSH 密钥都存放在仓库之外的 ~/.ssh 中;.gitignore 还会排除符合密钥模式的文件。
SETUP.md 逐步说明了如何设置和验证安全的双通道架构(用于隧道的数据通道和用于管理的控制通道)。
操作等级与操作员开关
每个工具都有固定的分类,并统一保存在代码中的一个位置
(TOOL_TIER),这样本表与策略就不会彼此不一致:
| 等级 | 含义 | 工具 |
|---|---|---|
| READ | 仅查看,不做任何更改 | status、models_present、job_status、list_jobs、list_variants、show_variant、list_adapters、training_status、check_training_env、check_isolation |
| CONTROL | 可逆地更改运行状态 | fetch_model、create_variant、switch_service、stop_service、start_service、start_training |
| DESTRUCTIVE | 移除或取消 | remove_model、remove_variant、cancel_training |
此分类不是授权系统(参见 SECURITY.md 中的说明);它是一个粗粒度的操作开关, 让你无需编辑代码即可缩小此服务实际执行的操作范围。被禁用的操作仍会通过 MCP 列出,但调用时会在访问任何机器之前被拒绝:
| 变量 | 默认值 | 作用 |
|---|---|---|
MM_MAX_TIER | read | 服务可运行的最高等级。read 仅开放 READ 工具;control 开放 READ 和 CONTROL;destructive 开放所有工具。 |
MM_ENABLED_OPERATIONS | 空(允许 MM_MAX_TIER 范围内的所有操作) | 以逗号分隔的允许列表,由 MM_MAX_TIER 进一步限制:只有工具同时属于 MM_MAX_TIER 允许的范围,并且在设置此列表时其名称也列于其中,才会运行。名称拼写错误会导致服务在启动时停止,而不是悄悄开放更多操作。 |
默认只读(默认拒绝)。 不进行任何设置时,只会运行 READ 工具;必须显式启用 CONTROL 和 DESTRUCTIVE 操作。此开关会提前、明确地拒绝被禁用的操作,在任何 SSH 或 VM 访问之前给出说明等级以及如何更改设置。若还要允许管理操作(fetch_model、switch_service、训练等):
"env": { "MM_MAX_TIER": "control" }
或者只开放两个指定操作,不开放其他操作。请注意,MM_ENABLED_OPERATIONS
会在 MM_MAX_TIER 的基础上进一步缩小范围,因此该等级必须已允许这两个指定工具;此处的 switch_service 属于 CONTROL,因此 MM_MAX_TIER 必须至少提升至 control:
"env": { "MM_MAX_TIER": "control", "MM_ENABLED_OPERATIONS": "status,switch_service" }
并发防护
机器只有一个 GPU 和一个推理服务,因此同时进行两项状态更改会导致状态不一致。每个会更改 GPU 状态的工具都会串行执行其关键区段(按设计,fetch_model 和 cancel_training 除外:fetch_model 是后台任务,而 cancel_training 必须始终能够执行):一个操作运行期间,第二个操作会被立即拒绝(不会排队);如果此服务启动的训练仍在进行中,则会拒绝可能争用 GPU 的操作(switch_service、remove_model、create_variant、start_training、start_service)。此防护仅在进程内生效:它可确保此服务自身调用的一致性。若训练是在其他会话中启动的,则由机器端处理(新的 start_training 会先停止推理),这里无法对其进行完整的串行控制;此边界已在 SECURITY.md 中说明。
工具
| 工具 | 用途 |
|---|---|
status | 当前运行情况:服务、模型、GPU 内存、磁盘空间、容器 |
models_present | 本机清单,按 Ollama 和 Hugging Face 分类 |
fetch_model | 获取模型,并立即返回一个 id |
job_status | 后台作业的进度 |
list_jobs | 此处和本机上的已知作业 |
remove_model | 移除模型,仅在明确确认后执行 |
create_variant | 构建自定义 Ollama 变体:基础模型、系统提示词、参数 |
list_variants | 查看有哪些变体、它们的来源以及配置 |
show_variant | 从两个来源查看变体的实际内容 |
remove_variant | 清除变体,仅在明确确认后执行 |
switch_service | 将 vLLM 切换到其他模型,并进行估算和交叉检查 |
stop_service, start_service | 停止服务并重新启动 |
check_training_env | 检查 LoRA 环境是否存在且可导入 |
start_training | 在后台运行 LoRA 训练,先停止推理并说明原因 |
training_status | 步数、损失、预计剩余时间 |
cancel_training | 结束一次运行,需确认 |
list_adapters | 已完成的适配器及其基础模型 |
check_isolation | 隧道可用、局域网不可用:两者均按实际行为检查 |
单 GPU 机器的限制
- 一次只能运行一个大模型。
switch_service会预先计算权重、键值缓存和基础负载是否能装入分配的内存,并在不满足时拒绝,而不是贸然尝试。计算依据是真实文件大小和模型的config.json,而非根据名称进行粗略估算;只有两者都缺失时,才会进行粗略估算,并明确标记为不确定。 switch_service只能启动已知的容器映像并挂载已知路径。 它创建或重新创建的容器会经过检查,确保映像位于封闭的映像允许列表中(已配置的 vLLM 映像MM_VLLM_IMAGE,默认为vllm/vllm-openai,以及ollama/ollama,可带标签或摘要;镜像版 vLLM 映像必须通过MM_VLLM_IMAGE设置,否则会被拒绝),并且每个绑定挂载的主机端都必须位于某个已配置数据根目录下;完整说明请参阅 SECURITY.md。- 推理和训练不会共用显卡。 如果未设置停止推理的确认,
start_training就会拒绝运行,并指出将停止哪些内容。每个数值超参数(epochs、rank、alpha、学习率、最大长度、批次大小、梯度累积)都有固定范围,并会在两端检查:此处在写入运行配置前检查一次,本机在任何数值传递给训练库前独立再检查一次。 - 机器并非总能连接到显卡。 如果机器不可访问,服务端会将其报告为一种独立状态,并附上说明,而不是报告为错误。如果通过
MM_VM2_HOST知道有第二台机器在共用 GPU,状态会是gpu_probably_on_second_machine;否则则是machine_unreachable。 - 无提示失败的切换是最危险的故障模式。 每次切换后,都会通过
/health和/v1/models检查服务是否确实能够响应并提供所需模型。结果始终会包含在报告中。
自定义 Ollama 变体
Ollama 可以通过 Modelfile,基于现有模型衍生出带有固定系统提示词、自有参数以及后续训练适配器的模型。衍生模型会以独立模型名称出现,并且可以像其他模型一样访问。这是构建专用 Agent 的途径,也是让训练结果投入使用的途径。
create_variant(
name = "handyman:v1",
base_model = "qwen3:4b",
system_prompt = "You are a terse expert assistant ...",
parameters = {"num_ctx": 8192, "temperature": 0.2})
微妙之处:自由文本进入指令文件
系统提示词是用户必须能够确定的文本。但它最终会进入 Ollama 按指令列表读取的文件。如果不加检查地传入,就会绕过整个防护机制;问题不在于 shell,而在于更上一层的 Modelfile 本身。以下四项措施相互配合:
- **Modelfile 在机器上组装,而不是传输。**只有部分内容会通过控制通道传送:基础模型、一个由参数名称和数值组成的对象、适配器路径以及系统提示词。无法提交完整的 Modelfile。
- **允许的指令采用封闭列表。**模板只能生成
FROM、PARAMETER、ADAPTER和SYSTEM,不能生成其他内容。FROM只接受 Ollama 模型名称,不接受路径,并且会根据实际清单进行检查。 - **自由文本以 Base64 传输。**传输过程中,Base64 字符集不会产生 shell 语法或换行符;只有在机器上才会解码,并直接写入文件。
- **自由文本的字符集不包含双引号。**多行 Modelfile 值以三个双引号结尾;由于字符集中缺少双引号,文本无法结束自己的区块,也就不会变成指令。需要引号时,可以使用弯引号和撇号。
两端都会进行检查,因为 validation.py 在这里和机器上都会运行。即使精心构造的请求绕过这里的检查,直接进入控制通道,包装器也会自行拒绝。
可调参数
这里只映射了真正值得使用的参数,而非 Ollama 支持的所有参数。每个参数都有一个范围,数值到达机器前会先经过检查。
| 参数 | 类型 | 范围 | 效果 |
|---|---|---|---|
num_ctx | 整数 | 256 to 131072 | 模型一次能保留多少文本以供参考 |
temperature | 数值 | 0.0 to 2.0 | 随机性;0 表示最可重复的回答 |
top_p | 数值 | 0.0 to 1.0 | 按概率质量进行核采样 |
top_k | 整数 | 1 to 200 | 按数量进行核采样 |
min_p | 数值 | 0.0 to 1.0 | 相对于概率最高的词元的下限 |
repeat_penalty | 数值 | 0.5 to 2.0 | 抑制重复;1.0 表示关闭 |
repeat_last_n | 整数 | -1 to 4096 | 抑制重复机制的回看范围;-1 表示 num_ctx |
num_predict | 整数 | -2 to 32768 | 回答长度;-1 表示不限制,-2 表示直到上下文填满 |
seed | 整数 | 0 to 2147483647 | 用于生成可重复回答的固定种子 |
适配器:已准备,但尚未启用
adapter 参数已构建并经过检查,但该路径从未运行过,因为参考状态中没有训练好的适配器。目前已有的内容包括:适配器路径的允许列表、转换为容器视图、模板中的 ADAPTER 行,以及显示工具中的读取逻辑。需要在首个实际适配器就绪后确定的事项(Safetensors 与 GGUF 格式的选择、容器中的存储位置、与基础模型和量化方式的适配)已在代码中就地标注为待解决。在这些事项得到验证之前:将 adapter 留空。
自测
.venv/bin/python selftest.py # without the machine, HTTP is mocked
.venv/bin/python selftest.py --live # additionally against the real machine
大多数测试组无需机器;只有可选的 --live 组 M 需要。部分检查会运行操作员侧的设置脚本(setup/、vm_side/),这些脚本与服务端一起包含在此仓库中,因此只要这些脚本就位,自测便会在本机运行额外检查,无需模型机器:除了服务端代码测试组,还会在实际执行中覆盖包装器(组 D)、设置脚本本身(组 J)、隔离(组 K),以及操作员策略、并发保护和隔离辅助程序(组 N)。针对攻击测试集的允许列表、目录和替换、请求格式、通过桩服务端测试服务端、根据手动核验值进行内存估算、连接层、机器输出解析以及各种变体,都会运行并接受检查。如果你单独运行服务端目录,并从目录中移除了 setup/ 和 vm_side/ 脚本,自测仍会通过服务端代码测试组,并会妥善跳过 D、J、K 组以及 I 和 N 组中仅限操作员的部分,同时给出提示,不会将其计为失败。这两种情况都不需要模型机器。只有 --live 组 M 需要:它会针对一台可访问且已完成设置的机器运行,并且在上述任一情况下都是可选的。(确切的检查数量以运行时测试运行器打印的结果为准;随着检查增加,数量也会增长,因此这里不会将其列为固定数量,也不构成承诺。)
--live 不会读取 MM_VM_HOST/MM_VM_USER/MM_CONTAINER_ROOT;它使用独立的变量,默认指向一个永远无法访问的地址(TEST-NET,RFC 5737),因此在没有进一步设置时,直接运行 --live 会被静默跳过,而不会错误地显示通过:
| 名称 | 默认值 | 含义 |
|---|---|---|
MM_LIVE_HOST | 192.0.2.10 | M 组探测的机器地址 |
MM_LIVE_PORT_VLLM | 8000 | 该机器上的 vLLM 端口 |
MM_LIVE_PORT_OLLAMA | 11434 | 该机器上的 Ollama 端口 |
将这三个变量都设为指向你实际可访问的机器;否则,即使已为常规服务端使用正确配置了 MM_VM_HOST,你仍会看到“VM not reachable, live group is skipped. Not an error.”。
环境变量
标记为必填的字段为必填项;它们没有默认值。
| 名称 | 默认值 | 含义 |
|---|---|---|
MM_VM_HOST | 必需 | 模型机器的地址(127.0.0.1、局域网 IP 或隧道/VPN 地址) |
MM_VM_USER | 必需 | 该机器上的 SSH 用户 |
MM_ACCESS | tunnel | tunnel(通过 SSH 隧道连接到 127.0.0.1)或 direct(直接连接到该地址) |
MM_MAX_TIER | read | 服务公开的最高操作级别:read、control 或 destructive(参见操作级别) |
MM_ENABLED_OPERATIONS | empty | 可选的精确工具名称逗号分隔允许列表;设置后,仅运行其中列出的工具。名称拼写错误会中止启动 |
MM_VM2_HOST | empty | 可选:与 GPU 共享的第二台机器,用于判断无法访问的情况。如果只有一台机器,请留空 |
MM_KEY_DIR | ~/.ssh/modelmanager | 两个 SSH 密钥的存储位置(位于仓库之外) |
MM_KEY_DATA | ${MM_KEY_DIR}/datachannel | 数据通道的私钥 |
MM_KEY_CONTROL | ${MM_KEY_DIR}/controlchannel | 控制通道的私钥 |
MM_KNOWN_HOSTS | ${MM_KEY_DIR}/known_hosts | 模型机器的固定主机密钥文件 |
MM_FROM | 必需(仅在构建第 2 级允许列表时) | 两个密钥允许的发送方地址,可用逗号分隔多个地址 |
MM_FROM_NET_ALLOWED | no | 设置为 yes 后,允许 MM_FROM 指定整个网络,并显示警告(仅在构建第 2 级允许列表时) |
MM_REMOTE_PORT_VLLM | 8000 | 机器上的 vLLM 端口(vLLM 的标准端口) |
MM_REMOTE_PORT_OLLAMA | 11434 | 机器上的 Ollama 端口(Ollama 的标准端口) |
MM_LOCAL_PORT_VLLM | 8000 | 隧道公开 vLLM 所用的本地端口 |
MM_LOCAL_PORT_OLLAMA | 11434 | 隧道公开 Ollama 所用的本地端口 |
MM_CONTAINER_VLLM | vllm | vLLM Docker 容器的名称 |
MM_CONTAINER_OLLAMA | ollama | Ollama Docker 容器的名称 |
MM_VLLM_IMAGE | vllm/vllm-openai | 重新创建允许列表接受的 vLLM 镜像;如果使用镜像副本或重命名的镜像,请将此项设为对应镜像,否则会被拒绝 |
MM_MIN_DISK_GB | 15 | Ollama 拉取操作的磁盘空间下限 |
MM_CONTAINER_ROOT | 必需,无默认值 | 机器上存放所有模型、适配器和缓存数据的根目录;未设置时服务不会启动 |
MM_VM_ROOT | ${MM_CONTAINER_ROOT}/manager | 此工具在机器上的工作根目录(作业文件夹位于其下) |
MM_VM_DATA_ROOT | ${MM_CONTAINER_ROOT} | 训练数据集路径必须位于其下的根目录(data_path_check、df 使用情况报告) |
MM_VM_ADAPTER | ${MM_CONTAINER_ROOT}/adapter | 已完成的 LoRA 训练运行存放适配器的位置 |
MM_LORA_PYTHON | ${MM_CONTAINER_ROOT}/lora-venv/bin/python | 机器上 LoRA 训练环境的解释器 |
MM_VM_OLLAMA_STORE | ${MM_CONTAINER_ROOT}/ollama | 机器上的 Ollama 数据文件夹(挂载到容器中,见下表) |
MM_IN_CONTAINER_STORE | /root/.ollama | 同一文件夹在 Ollama 容器内的路径 |
MM_VM_HF_CACHE | ${MM_CONTAINER_ROOT}/hf | 机器上 Hugging Face 权重缓存的根目录 |
MM_GPU_TOTAL_GB | 12.0 | 假定的 GPU 内存容量(GB),仅在 nvidia-smi 无法读取实际值时使用 |
MM_AUDIT(机器端,不在此处设置) | ${MM_VM_ROOT}/audit.jsonl | 模型机器本身上的审计日志路径;由机器端包装器在该机器上读取,默认使用 install.sh 创建的 audit.jsonl。此服务不会读取此项 |
MM_ENFORCE_ROOT_OWNED(机器端,不在此处设置) | unset | 设置为 1,即可强制机器端包装器对 lib/ 启用 root 所有权防护,即使检出副本中的 install.sh 尚未启用该防护。此项只能开启防护,不能关闭,因此环境不能削弱已安装副本的防护。供自测使用;此服务不会读取此项 |
MM_STATE_DIR | $XDG_STATE_HOME/mcp-modelmanager(或 ~/.local/state/mcp-modelmanager) | 此服务在本地存储作业状态(fetch_model/start_training 作业文件)的位置 |
| 本地隧道端口默认与远程端口使用相同的常用值;如果这些端口已在本地被占用,请调整端口。 |
MM_CONTAINER_ROOT 为必需项,且没有内置默认值(此工具无法假定默认的机器目录布局);如果未设置,服务会在启动时退出。上面的六个 MM_VM_*/MM_LORA_PYTHON 变量默认由它推导而来,并且可以像 MM_IN_CONTAINER_STORE 一样单独覆盖,因此,目录布局不同的机器仅通过配置即可适配,无需更改代码。启动时会根据严格的 VM 路径允许列表检查每个值(必须是绝对路径,且只能包含字母、数字、点、连字符、下划线和斜杠;不能包含 ..、空格或 shell 字符);值格式不正确时,服务会立即停止,而不会信任该值。MM_VM_DATA_ROOT 和 MM_VM_OLLAMA_STORE 还会成为后续工具调用可传入的所有路径(例如训练数据集路径、适配器路径)的允许列表根目录,确保它们与实际配置保持一致。
变体在机器上需要使用的目录,由上述根目录推导而来(位于 operations.py 中,不能单独设置)。设置过程会创建以下路径:
| 在机器上 | 在容器中 | 用途 |
|---|---|---|
MM_VM_OLLAMA_STORE(默认 ${MM_CONTAINER_ROOT}/ollama) | MM_IN_CONTAINER_STORE(默认 /root/.ollama) | Ollama 的数据文件夹,已挂载 |
<MM_VM_OLLAMA_STORE>/variants/<name>/Modelfile | <MM_IN_CONTAINER_STORE>/variants/... | 组装后的 Modelfile |
<MM_VM_OLLAMA_STORE>/adapter | <MM_IN_CONTAINER_STORE>/adapter | 适配器存储目录 |
许可证
MIT,详见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。