Skip to main content
Glama

mcp-simple-job

将子任务交给另一台机器上的本地模型,并在返回结果之前验证结果

它是为解决一种特定形态的问题而构建的:能力强大、按量计费的助手运行在你面前的机器上,而一台完全够用的 GPU 机器却在角落里闲置。读取四十个文件、总结一个长页面、拉取一个数据集——这些都不需要昂贵的模型,而在助手的上下文中完成它们会消耗真正稀缺的那一种资源。

在作者的配置上实测,与在上下文中完成同样的四项任务相比:~2.7 倍更快,上下文消耗减少 6.1 倍,因为原始页面从未进入上下文。

唯一规则

任务必须附带检查。 无法说明如何知道任务是否成功的任务会被拒绝——不是警告,而是拒绝。

这不是对本地模型的不信任,而是调用方无法判断。当助手委派一个摘要任务并收到四百个自信满满的词时,它没有独立的方法知道这些词描述的是文档还是别的东西。没有检查就委派,等于又增加了一处绿灯毫无意义的地方。

检查刻意保持朴素:nonemptycontainsregexjson_keysline_countshell(你的 argv,退出码 0 即通过,输出通过管道送入 stdin),以及 summary_of(比源文本短,且不是源文本的副本)。

Related MCP server: any-model-plugin

四个子任务

工具

作用

工作发生的位置

simple_job

一个普通提示词,带你自己定义的检查

模型主机

summarize

文本,或先抓取的 url/urls

工作机(抓取 + 模型)

search_and_summarize

搜索,阅读排名靠前的页面,总结

搜索在主机间交替,其余在工作机

download

抓取文件,报告字节数和 sha256

默认在工作机,也可在任何配置的主机

simple_job_stats 报告所有这些任务实际进行得如何,数据来自为每个任务写入的一行账本记录。


运行它

要求

  • 运行 MCP 服务器的机器上需要 Node 18+

  • 一个兼容 OpenAI 的聊天端点。 llama.cpp 的 llama-server、Ollama、vLLM、LM Studio,或托管的 API——任何能响应 POST /v1/chat/completions 的服务。

  • Python 3.9+,在负责抓取的机器上。仅用标准库;无需 pip 安装,无需 node,无需 beautifulsoup。

  • SSH 密钥认证,如果要使用第二台机器的话。这是可选的(见下文)。

在作者的机器上是如何连接的

两台计算机:

  • 一台 Mac mini——日常工作站。16 GB 内存,通常有数 GB 的交换空间。它运行 Claude Desktop,因此也运行这个 MCP 服务器。

  • 一台装有 RTX 5070 Ti 的 Pop!_OS 机器——实验室。它在 8080 端口上通过 llama-server 运行一个名为 ornith 的 35B 模型,一天中大部分时间都处于空闲状态。

一条 SSH 隧道让远程模型在 Mac 上看起来像本地模型:

ssh -N -o ServerAliveInterval=30 -L 127.0.0.1:8081:127.0.0.1:8080 pop-os

pop-os~/.ssh/config 中的一个别名,带有密钥和 IdentitiesOnly yes,因此服务器可以通过 BatchMode=yes 以非交互方式访问它。

MCP 客户端条目就是:

{ "mcpServers": { "simple-job": { "command": "node", "args": ["/path/to/mcp-simple-job/index.js"] } } }

其余由默认值完成:模型在 127.0.0.1:8081,工作机在 pop-os,账本在已有的 ~/Code/harness/ 目录中(如果存在的话)。

没有任何东西需要手动调用。助手选择工具——这比听起来更难,下文会介绍。

在你自己的环境上运行

两台机器,一台运行客户端,一台运行模型:

{
  "mcpServers": {
    "simple-job": {
      "command": "node",
      "args": ["/path/to/mcp-simple-job/index.js"],
      "env": {
        "ORNITH_URL": "http://127.0.0.1:8081/v1/chat/completions",
        "ORNITH_MODEL": "your-model-name",
        "POP_HOST": "your-ssh-alias"
      }
    }
  }
}

一台机器——全部本地,没有任何 SSH:

{
  "env": {
    "ORNITH_URL": "http://127.0.0.1:11434/v1/chat/completions",
    "ORNITH_MODEL": "qwen3:8b",
    "SEARCH_HOSTS": "mac"
  }
}

SEARCH_HOSTS=mac 这个开关表示“没有第二台机器”。抓取、下载和搜索都在本地进行,搜索只有一个速率预算而不是两个。其他一切行为相同。

环境变量

变量

默认值

作用

ORNITH_URL

http://127.0.0.1:8081/v1/chat/completions

聊天端点

ORNITH_MODEL

ornith:35b

请求中发送的模型名称

POP_HOST

pop-os

工作机的 SSH 别名

SEARCH_HOSTS

mac,pop

要在哪些机器之间交替搜索;单机安装时设为 mac

SEARCH_GAP_MS

30000

同一台机器两次搜索之间的最小间隔

SEARCH_BLOCK_MS

300000

一台机器被限流后暂停多长时间

SIMPLE_JOB_STATE

位于 index.js 旁边

搜索计时状态的存放位置

HARNESS_LEDGER

~/Code/harness/ledger.db(如果该目录存在),否则 ~/.mcp-simple-job/ledger.db

SQLite 账本

HARNESS_TRACE

~/Code/harness/current_trace.txt

可选,要盖在行上的跟踪 id

账本是可选的。 它会在首次使用时创建,如果无法写入,任务仍然会运行——日志记录是尽力而为的,绝不会阻塞工作。HARNESS_TRACE 是作者自己的跟踪设置的一个钩子;忽略它,行就只是有一个空的 trace id。

让它真正被用起来

这是大多数人跳过的一部分,也是决定上述一切是否重要的部分。

一个没有任何东西会路由到它的工具,无论它工作得多好都是不可见的。作者有一个独立的 MCP 服务器,它工作得完美,但几个月里零调用,纯粹是因为从来没有任何东西告诉助手去使用它。构建一个能力与将请求路由到它是两件不同的事,而完成第一件会让人感觉已经完成了。

有三种方法可以缩小这个差距,从最便宜的开始。大多数人想要第二种。

1. 什么都不做,先看看。 有些客户端对工具描述的理解足够好,一个足够明显的请求——比如“总结这四十页”——会自动找到这个工具。在添加机制之前,值得先试一天。观察它是否真的被调用。

2. 把一条规则放在你的客户端保存常驻指令的地方。 Claude Desktop 项目指令、Claude Code 的 CLAUDE.md.cursorrules、自定义 GPT 的指令——无论你的客户端在每一轮都会读取什么。类似这样:

有一个本地模型可以通过 simple-job 使用。当材料尚未在上下文中且任务是机械性的时使用它:总结页面或文件、网络搜索加阅读、抓取下载、提取和重新格式化。它是免费的,不会在源材料上消耗上下文。

当文本已经在上下文中、当任务需要解释而不是转写、或者当“正确”比“可检查”更重要时,自己做。绝不要委派需要判断的决策、必须正确的代码或文件编辑。

每个任务都必须携带检查——服务器会拒绝它无法验证的工作。

何时不委派上花与“何时委派”同样多的篇幅。路由委派工具的失败模式是过度委派,而一个把所有事情都往下游送的助手,会在你想要判断的地方给你忠实的转写。

3. 如果你有路由器,就把它接入路由器。 如果你的设置已经将情境匹配到工具,就为“批量阅读或抓取尚未进入上下文的材料”添加一个条目。相对于常驻指令的优势在于它是可衡量的——你可以统计它在应该触发时是否触发了。常驻指令要么有效要么无效,而且没有任何东西记录是哪一种。

不要给它发送什么

任何“看起来对”是唯一检验标准的东西。需要判断的决策。必须正确的代码。编辑文件。

还有一条通过测量而非品味发现的边界:小型本地模型能忠实转写,但不能解释。在测试中,它逐字复述了源文本中含糊的措辞,而不是解决其含义,并且把仓库的星标数总结得像是一个 bug 报告的一部分。把转写交给它。把解释留给自己。


构建过程中的笔记

下面的一切都是测量结果,而不是观点。这些数字也写在代码注释里。

思考默认关闭

推理模型从同一个 token 预算中产生它们的思考和答案。在一个总结任务上完全相同地运行三次,三次中有两次花费了 5,500–6,000 个字符思考,撞到上限,并以 HTTP 200 返回了空答案。

提高 max_tokens 没有修复它。reasoning_effort: "low" 没有修复它。一个 `` system 标签也没有修复它。只有 chat_template_kwargs: {enable_thinking: false} 修复了它,同一个任务随后用 258 个 token 就回答了。对于真正需要深思的任务,传入 think: true,并同时提高 max_tokens

搜索是配给的,而 DuckDuckGo 在原因上撒谎

DuckDuckGo 不会礼貌地限流:

  • 被服务的查询是 HTTP 200,约 28 KB,十个结果链接

  • 被拒绝的查询是 HTTP 202,约 14.2 KB,其文本写着 “请完成以下挑战... 选择所有包含鸭子的方块”

这是 IP 上的一个验证码标记,而不是时间限制,而且拉开间隔并不能清除它。在静默四分钟后,从一台机器以 30 秒间隔发六个查询、从另一台以 15 秒间隔发六个查询,结果是 0 对 12。在被封锁期间每 5 秒轮询一次,162 秒内从未恢复——重试反而会喂养它。这个标记大约二十分钟后自行消退。

因此,搜索被拉开间隔,在机器之间交替(两个 IP 就是两个预算),并且限流被报告为 throttled,绝不会报告为“无结果”。这两者意思相反。

阅读跟随问题

一个长页面会被截断以适配模型的窗口,而从顶部截断会静默地回答错误的问题。在一个 40,063 字符的页面、8,000 字符的窗口下被问到 “稀疏门控和负载均衡” 时,第一个版本返回了文章开头的流畅总结——其中“负载均衡”从未出现(它从第 16,181 个字符开始),“稀疏”也从未出现(14,671)。

因此 focus 引导窗口:先取开头作为上下文,然后取每个命名术语周围的段落,在每个术语获得第二个窗口之前,保证每个术语有一个窗口。两个早期版本都不够好——子串匹配在“download”中找到了“load”,报告了 42 次噪声命中;而按文档顺序取段落则在到达第 16,181 个字符之前就用完了预算。

如果页面从未使用这些词,调用会返回 ok:falsefocus_not_found。零命中是比一段关于其他材料的貌似合理的总结更好的答案。

一个大部分是脚本的页面会被拒绝

一个网站提供了 68,896 字节,其中只包含 40 个字符的文本(“Loading...”),这通过了原来的 if not text 守卫——于是这个页面外壳作为源材料进入总结,模型写出了一个自信的基准数字并引用它。

现在有两个测试,因为单独任何一个都会被欺骗:一个绝对下限,以及一个文本与字节的比率,它只会谴责一个同样短的页面。一个 GitHub issue 是 290,000 字节的标记,围绕 3,896 个字符的真实讨论,仅凭比率就把它丢弃了。

引用被编号,以便可以核查

search_and_summarize 对页面进行编号,并要求使用 [1][2] 而不是 URL。当被要求提供 URL 时,模型把它在博客中读到的一个数字归因于一个文档页面——事实是真实的并且存在于材料中,但归因不是,而 summary_of 无法看到这一点,因为一个贴错标签的项目符号长度正确,并且不是复制品。

URL 是一长串不透明的字符串,难以正确复制。整数则不是,并且可以对照实际读取的页面进行范围检查——代码正是这样做的,对超出范围的数字使调用失败,并统计完全没有来源的项目符号。

哪台机器更快?

通过两端的相同 sha256 验证:

客户端机器

工作机机器

ssh 往返

~185 ms 每次调用

获取 4 个页面

~1.7 s

~2.0 s

下载 20 MB

17.5 MB/s

12.6 MB/s

客户端机器在两项上都更快。 速度不是把工作发送给工作机的原因。原因是它持有模型,它在另一台机器被使用时处于空闲状态,而且第二台机器是第二个搜索预算。根据文件需要的位置来选择下载的主机,而不是根据吞吐量。

测试

node test_e2e.mjs                        # 24 assertions, spawns the real server over JSON-RPC
node --test test/simple-job.test.mjs     # 19 unit assertions on the checks

端到端套件以客户端的方式启动实际的服务器,针对一个一次性的账本。进程内测试无法捕获 PATH 或环境变量错误,而这些正是只有在重启后才会出现的错误。

index.js 的更改在客户端下次启动服务器时生效。pop_agent.py 在每次调用时都会被重新读取,因此对获取、搜索和下载的更改会立即生效。

Install Server
F
license - not found
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Verifies AI agent work end to end: real artifacts and outcomes checked, not self-reported success.

  • LLM chat, text summarization and AI image generation

  • Free OpenAI-compatible inference with signed provenance receipts and 3 focused MCP tools.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MikeyBeez/mcp-simple-job'

If you have feedback or need assistance with the MCP directory API, please join our Discord server