mcpField
P
pp-eu-tenders

pp-eu-tenders

github.com/mvanhorn营销与增长2.1k51 次安装今天更新
代码仓库

关于 pp-eu-tenders

pp-eu-tenders 是面向销售团队、投标方和研究人员的欧盟公共采购命令行技能。它结合 TED 公告搜索与本地 SQLite 分析,支持线索生成、投标排序和市场研究。

主要功能

  1. 01搜索 TED 公告与授标信息
  2. 02根据中标企业生成联系名单
  3. 03按紧迫度和匹配度排列招标
  4. 04分析采购方、中标方和市场集中度
  5. 05追踪采购趋势与类别变化

适用场景

  1. 01从授标信息中寻找潜在联系企业
  2. 02在截止日期前筛选投标机会
  3. 03投标前评估采购方的授标记录
  4. 04衡量采购细分市场的竞争情况

MCP 相关

README 提及 `eu-tenders-pp-mcp` 二进制,并展示如何将其配置为 MCP 服务,包括通过主机环境传递数据目录设置。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mvanhorn/printing-press-library --skill pp-eu-tenders

安装后在 Claude Code 中输入/pp-eu-tenders确认已加载。

详细介绍

EU Tenders — Printing Press CLI

前提条件:安装 CLI

此技能使用 eu-tenders-pp-cli 二进制文件。**调用此技能中的任何命令前,必须确认 CLI 已安装。**如果尚未安装,请先安装:

  1. 通过 Printing Press 安装程序安装。在 macOS/Linux 上,二进制文件默认安装到 $HOME/.local/bin;在 Windows 上,默认安装到 %LOCALAPPDATA%\Programs\PrintingPress\bin:
    npx -y @mvanhorn/printing-press-library install eu-tenders --cli-only
    
  2. 验证:eu-tenders-pp-cli --version
  3. 确保显示的安装目录位于将调用此技能的 Agent/运行时的 $PATH 中。

如果 npx 安装失败(没有 Node、处于离线状态等),请改用直接 Go 安装(需要 Go 1.26.6 或更高版本)。这会将程序安装到 $GOPATH/bin(默认为 $HOME/go/bin),因此请将该目录添加到 $PATH:

go install github.com/mvanhorn/printing-press-library/library/sales-and-crm/eu-tenders/cmd/eu-tenders-pp-cli@latest

如果安装后 --version 显示“command not found”,则运行时无法在 $PATH 中找到二进制文件目录。在验证成功之前,请勿执行此技能的命令。

将 TED 公告同步到本地 SQLite 存储,并将中标公告整理成包含潜在线索的外联名单;TED 提供相关信息时,还会列出每位中标者的电子邮件、电话和 VAT id。按评分和截止日期紧迫度对开放招标排序,并分析市场集中度、买方、中标者、中标速度和 CPV 变化。无需 API 密钥。

何时使用此 CLI

使用此 CLI 查找欧盟公共招标、分析谁赢得了公共合同,或根据合同中标者建立 B2B 潜在线索名单。它适用于基于 TED 数据开展持续的销售拓展、投标筛选和采购市场研究。

不适用场景

请勿将此 CLI 用于:

  • 作为 eSender 向 TED 提交或发布公告
  • 未在 TED 上发布的国家级低于门槛的招标
  • 提供采购程序方面的法律建议

独特功能

其他任何用于此 API 的工具都不具备以下功能。

从中标者生成潜在线索
  • leads — 获取可用于外联的名单,其中包含刚刚赢得建筑合同的公司:每位中标者一行;TED 提供相关信息时,还会列出电子邮件、电话、城市和 VAT/HRB id,以及合同金额和建设内容。

    当 Agent 需要从公共合同中标记录获取销售线索,而不是原始公告时,使用此功能。

    eu-tenders-pp-cli leads --country DEU --cpv 45 --days 30 --region DE2 --agent
    
  • winner — 查看一家公共合同中标公司的档案:中标时间线、总金额、买方、地区和最新联系信息。

    在联系潜在线索或评估竞争对手时使用。

    eu-tenders-pp-cli winner "Johann Bunte" --country DEU --agent
    
投标优先级排序
  • score — 根据截止日期紧迫度、合同金额和关键词匹配度对开放招标排序,生成优先投标候选名单。

    当有人询问本周哪些开放招标值得投标时,使用此功能。

    eu-tenders-pp-cli score --country DEU --cpv 45 --keywords Hochbau,Neubau --agent
    
  • incumbents — 针对一项开放招标,查看此前从同一买方处赢得同类别合同的公司。

    在撰写提案前,用它评估自己与现任承包商竞争的胜算。

    eu-tenders-pp-cli incumbents 679227-2026 --agent
    
  • deadline-heat — 列出即将在几天内截止的招标并按优先级排序,权重因素包括紧迫度、金额,以及通常有多少家公司赢得该买方的合同。

    用于最后时刻的投标筛选。

    eu-tenders-pp-cli deadline-heat --country DEU --cpv 45 --days 14 --agent
    
市场和买方情报
  • buyer — 查看采购机构档案:公告发布频率、CPV 组合、典型合同金额和重复中标者。

    在向某个机构投标前,或调查其过往中标记录时使用。

    eu-tenders-pp-cli buyer --name "Stadt München" --show-winners --agent
    
  • concentration — 查看各公司在某个行业和国家的中标金额份额,并提供 HHI 集中度评分。

    用于回答哪些公司主导某个采购市场。

    eu-tenders-pp-cli concentration --country POL --cpv 4523 --top 5 --agent
    
  • win-rate — 按买方查看以已发布中标公告结束的招标数量,以及中标公司的数量。

    在确定目标之前,用它比较不同买方的开放程度。

    eu-tenders-pp-cli win-rate --country DEU --cpv 45 --min-calls 3 --agent
    
  • dark-buyers — 标记招标很少产生公开中标公告,或总是由同一家公司中标的采购机构。

    用于采购诚信筛查;结果是启发式信号,并非调查结论。

    eu-tenders-pp-cli dark-buyers --country POL --cpv 45 --agent
    
趋势
  • velocity — 通过每周公告数量与去年同期进行比较,查看采购市场是在升温还是降温。

    用于发现某个行业的需求变化。

    eu-tenders-pp-cli velocity --country DEU --cpv 45 --window 90d --compare 1y --agent
    
  • cpv-drift — 查看某个国家的支出结构中,哪些采购类别同比增长或缩减。

    用于市场规模评估和政策研究。

    eu-tenders-pp-cli cpv-drift --country FRA --metric value --top 20 --agent
    

命令参考

搜索和查询(实时 TED API)

  • eu-tenders-pp-cli notices --query "buyer-country=DEU AND classification-cpv=45000000" — 对 TED 公告进行专家查询(--fields、--limit、--page、--pagination-mode、--scope)
  • eu-tenders-pp-cli notices get 680471-2026 — 按发布编号查询单条公告,包含中标方及其联系方式
  • eu-tenders-pp-cli awards --country DEU --cpv 45 — 合同授予公告,包含中标方、买方和金额(--winner、--year、--since)
  • eu-tenders-pp-cli deadline --country DEU --days 14 — 截止日期在 N 天内的开放招标
  • eu-tenders-pp-cli cpv get 45500000 — 按代码查询 CPV 代码
  • eu-tenders-pp-cli cpv search(关键词参数,例如 machinery)— 按关键词查询 CPV 代码
  • eu-tenders-pp-cli fields --contains winner — TED 专家查询字段名称

本地存储(离线)

  • eu-tenders-pp-cli sync --country DEU --cpv 45 --since 90d — 将招标和合同授予信息同步到 SQLite(表 notices、notice_winners、notices_fts;--type、--param key=value、--until、--limit、--max-pages、--db)
  • eu-tenders-pp-cli search "Neubau Schule" — 对已同步的标题、买方和中标方进行全文搜索
  • eu-tenders-pp-cli sql "SELECT buyer_country, COUNT(*) FROM notices GROUP BY 1" — 对存储执行只读 SELECT
找到合适的命令

如果你知道要做什么,但不知道该用哪个命令,可以直接询问 CLI:

eu-tenders-pp-cli which "<capability in your own words>"

which 会根据自然语言能力查询,从此 CLI 精选的功能索引中找到最匹配的命令。退出代码 0 表示至少有一个匹配项;退出代码 2 表示没有可靠匹配项——请改用 --help,或缩小查询范围。--json(以及其他机器可读格式)会保留此退出代码为 2 时的行为约定,并在标准输出中写入 {"matches":[]},以便 Agent 检查结果结构,而不会将未匹配误认为成功。

示例

每周获取建筑合同授予线索
eu-tenders-pp-cli leads --country DEU --cpv 45 --days 7 --new-only --agent --select winner_name,winner_email,winner_phone,winner_city,contract_value,title

仅包含先前 --new-only 运行未返回的公司;本次运行的公司会记录在本地 lead_seen 表中。

按公司归类线索
eu-tenders-pp-cli leads --country DEU --cpv 45 --days 90 --group-by company --agent

每家公司一行,显示中标次数和总金额,并按中标金额从高到低排序。

谁主导道路建设
eu-tenders-pp-cli concentration --country POL --cpv 4523 --top 10 --agent

查看某个细分市场中的中标方份额和 HHI。

投标前查看现有承包方
eu-tenders-pp-cli incumbents 679227-2026 --agent

查看来自同一买方和类别的过往中标方。

身份验证设置

无需身份验证。

运行 eu-tenders-pp-cli doctor 以验证设置。

Agent 模式

在任何命令后添加 --agent。它会展开为:--json --compact --no-input --no-color。

全局格式标志在已推广、创新、同步和 --deliver 路径上使用相同的约定:

  • --json — 在标准输出中输出一个 JSON 文档(同步进度事件写入标准错误)

  • --compact — 保留身份、状态和时间戳字段;不会改变文档与流的结构

  • --csv / --plain — 输出表格行(集合封装会展开为行数组)

  • --quiet — 每行输出一个身份值,不含封装

  • 可管道传输 — JSON 输出到标准输出,错误输出到标准错误

  • 可筛选 — --select 保留部分字段。带点路径可深入嵌套结构;数组会逐元素遍历。在内容冗长的 API 中,这对于控制上下文大小至关重要:

    eu-tenders-pp-cli leads --country DEU --cpv 45 --agent --select winner_name,winner_email,contract_value
    
  • 可预览 — --dry-run 显示请求,但不会发送

  • 非交互式 — 从不提示输入,所有输入都通过标志提供

  • 只读 — 不要使用此 CLI 执行创建、更新、删除、发布、评论、点赞、邀请、下单、发送或其他会更改数据的请求

路径与状态

Agent 应将 CLI 的路径解析器视为运行时约定的一部分:

  • 单次调用使用 --home <dir>,或设置 EU_TENDERS_HOME=<dir>,将所有四种路径都迁移到同一个根目录下。

  • 只有在某种路径需要单独设置时,才使用对应类型的环境变量:EU_TENDERS_CONFIG_DIR、EU_TENDERS_DATA_DIR、EU_TENDERS_STATE_DIR、EU_TENDERS_CACHE_DIR。

  • 解析顺序为:对应类型的环境变量、--home、EU_TENDERS_HOME、XDG(XDG_CONFIG_HOME、XDG_DATA_HOME、XDG_STATE_HOME、XDG_CACHE_HOME),然后是平台默认值。

  • config 存放 config.toml 和配置档等设置。data 存放 data.db(包含 notices、notice_winners、notices_fts、lead_seen、learn-loop 表)和 feedback.jsonl。state 存放 teach.log。cache 存放可重新生成的 HTTP 缓存文件。

  • 运行 eu-tenders-pp-cli doctor --fail-on warn 可显示路径警告。对于需要解析后目录的 Agent,agent-context 会提供 schema v4 的 paths 区块。

  • 对于 MCP,请通过 MCP 主机配置传递迁移设置。MCP 二进制文件不会继承 CLI 标志:

    {
      "mcpServers": {
        "eu-tenders": {
          "command": "eu-tenders-pp-mcp",
          "env": {
            "EU_TENDERS_HOME": "/srv/eu-tenders"
          }
        }
      }
    }
    

集群优先级:继承的对应类型环境变量会覆盖该类型显式指定的 --home。使用 EU_TENDERS_HOME 或对应类型的环境变量作为持久的集群配置手段,--home 则仅用于单次调用。取消设置环境变量不会还原迁移;清除 EU_TENDERS_HOME 前,请手动移动文件,否则 doctor 将无法找到留在原根目录下的存储和配置。

自动学习

此 CLI 内置了一个自动记录的学习循环。CLI 会自行记录:每次调用都会在本地记入日志;某个标志调用失败后再更正并重试时,会自动推导出一个 flag_alias 候选项;对没有操作手册的查询类别执行 teach 时,会根据该会话的日志自动合成一个 playbook_candidate。你只需进行判断:先执行 recall,再处理展示的候选项,用 teach 记录最终答案,并在发现更正时执行 playbook amend。你无需手动记录失败。

步骤 1:在任何发现操作前执行 recall

面对新的用户问题,在执行 list/search/drill 命令前,将问题作为 argv 或 MCP 工具参数传给 recall --agent。不要将用户提供的文本插入 shell 命令行。

带引号的 recall "<question>" 遇到撇号就会出错,而撇号在英语中很常见。带引号的 heredoc 会在正文行与分隔符完全相同时中断,而且这些文档中公开了该分隔符。请使用非 shell 文件写入工具写入问题,然后将其作为数据读回:

# Write the question verbatim with your file-writing tool (no shell involved).
# Command substitution on a file only ever yields data — the shell never
# parses the file's bytes as syntax.
QUERY=$(cat /path/to/question.txt)
eu-tenders-pp-cli recall "$QUERY" --agent

优先使用 MCP:将问题作为工具的 query 参数传入。读取文件后使用 "$QUERY" 可确保 argv 安全;直接将问题写入命令文本则不安全。

响应封装:

{
  "query": "...",
  "normalized": "<normalized form>",
  "query_entities": ["..."],
  "found": true | false,
  "match_score": 0.0,
  "results": [
    { "resource_id": "...", "resource_type": "...", "venue": "...",
      "confidence": 2, "entity_match": "exact|partial|unknown",
      "source": "taught|preseed|pattern", "warnings": ["..."] }
  ],
  "mismatches": [ /* only when --debug-mismatches */ ],
  "warnings": [ /* top-level */ ],
  "candidates": [
    { "id": 12, "class": "flag_alias | playbook_candidate",
      "summary": "...", "sightings": 3, "last_seen": "...",
      "rationale": "...",
      "next_action": ["<trial command>", "eu-tenders-pp-cli learnings confirm 12"] }
  ],
  "playbook": {
    "query_family": "...",
    "playbook": {
      "steps": [ { "cmd": "<command with {slot} substitution>", "purpose": "..." } ],
      "entity_slots": ["$ENTITY"],
      "expected_tool_calls": 3
    },
    "slots_resolved": { "$ENTITY": { "token": "<live token>", "canonical": "<canonical>" } },
    "notes": "<workarounds + gotchas for this query family>"
  },
  "notes": "<duplicate surface for non-playbook callers>"
}

空存储短路:如果存储中尚无学习记录、操作手册或候选项(recall 没有结果,且 learnings list 和 learnings candidates 均为空),本次会话剩余时间内可跳过 recall,避免每次查询都增加负担;有内容通过 teach 记录后,再恢复先执行 recall 的做法。

步骤 2:决策树

按以下顺序读取 candidates、playbook、notes、results[0] 和警告:

if Candidates present (warnings include "candidates_present"):
    -> candidates are try-then-confirm, never facts. Follow each candidate's
       two-step next_action verbatim: run the trial command first, then run
       `learnings confirm <id>` only after the trial verified the behavior.
       Reject a wrong candidate with `learnings reject <id>`.
    -> NEVER re-teach something recall surfaced as a candidate; confirm or
       reject that candidate instead of teaching a duplicate.
    -> candidates ride alongside playbooks and resource hits, not instead of
       them; continue with the branches below after acting on them.

if Playbook present:
    -> READ Playbook.notes verbatim FIRST (workarounds + gotchas the CLI surface doesn't expose)
    -> replay Playbook.steps in order, substituting Playbook.slots_resolved entries
       for the entity slot tokens. If a step's slot is unresolved, fall back to
       discovery for that step only.
    -> the Playbook's expected_tool_calls is a budget; if you find yourself running
       materially more, record the divergence via `eu-tenders-pp-cli playbook amend`
       at end-of-session.

elif Notes present (no Playbook):
    -> read Notes verbatim before any discovery step; they carry known gotchas
       for this query family even when no structured choreography exists yet.

elif Found AND Results[0].EntityMatch == "exact" AND Results[0].Confidence >= 2:
    -> skip discovery; fetch live data for Results[*].ResourceID in parallel

elif Found AND Results[0].EntityMatch == "partial":
    -> candidate hint, NOT a hit; read the resource title to validate before trusting

elif (any row in Mismatches[] when --debug-mismatches was passed):
    -> treat as cold start; the stored learning is for a different entity
       (different canonical resolved from query_entities)

else:  // Found == false, no playbook, no notes
    -> cold start; run discovery normally; teach the answer afterward (Step 4).
       If the family has no playbook yet, that teach auto-synthesizes a
       playbook candidate from this session's journal - you do not need to
       record one by hand.

Playbook 和 Notes 与逐资源路径相互独立。一次 recall 响应可以同时包含 Playbook 和 Results[] 命中——两者都要使用:Playbook 会告诉你要执行哪种流程;资源命中则会跳过特定步骤。默认跳过 mismatches;仅在调查冷启动异常时传入 --debug-mismatches。

候选项判断详情:learnings confirm <id> 会在将候选项写入实体前打印其完整负载——请检查打印出的负载是否与已验证的行为一致。learnings reject <id> 会将派生签名标记为废弃,避免同一候选项再次出现。信封中仅包含当前值得采取行动的少数候选项;eu-tenders-pp-cli learnings candidates 会列出所有未处理的候选项。

优雅降级:如果 learnings confirm 是未知命令,说明你正在使用较旧的二进制文件——忽略候选项相关说明,继续遵循协议的其余部分。

步骤 3:始终读取 warnings
  • low_confidence:置信度低于 2 的行。将其视为提示,而不是跳过发现步骤的命中。
  • resource_not_in_store:本地存储中没有该学习条目所指向的资源。匹配验证器无法对实体分类——请直接获取并重新评估。
  • cross_alias_match(按结果):该行是在另一别名下记录的,并通过 entity_lookups 与实时查询的规范实体匹配(例如,针对“United States”的 recall 命中了针对“USA”记录的内容)。请信任 resource_id。
  • similar_shape_different_entity:<canonical>(顶层):存在结构上匹配的行,但其规范实体与实时查询的实体不同。此情况按冷启动处理;警告会提供冲突的规范实体作为提示,但不会将该行加入 Results。
  • ambiguous_alias(顶层):单个查询实体解析出了多个规范实体(例如,“Cards” → Arizona Cardinals + St. Louis Cardinals)。在确定资源之前,请根据上下文说明存在歧义。
  • candidates_present(顶层):信封中包含 candidates 部分。请先按步骤 2 中的候选项分支处理,再进行其他操作。
  • 顶层的 no_learnings_for_query_family:该表中没有高于 Jaccard 阈值的行。属于纯冷启动。
步骤 4:完成回复后始终执行 teach &

无条件进行学习。解决存储无法回答的查询后,在后台记录最终的资源映射——不受调用次数阈值限制,也不必判断这次学习是否“值得”。Teach 是整个循环的锚点:如果某个类别尚无 playbook,它会触发 playbook 合成;同一指代对象的不同表述会归并到同一个类别中,从而避免近似重复的 teach 导致存储碎片化。请在整理好面向用户的回复后、输出回复前,使用 shell & 执行,让调用立即返回。传入查询的方式与 recall 相同——通过 argv/MCP,或使用文件后接 $QUERY。不要将问题拼接到命令文本中:

QUERY=$(cat /path/to/question.txt)
eu-tenders-pp-cli teach --query "$QUERY" --resource-type <type> --resource <id1> --resource <id2>
# (append shell `&` to background it)

成功时不输出任何内容。错误只会写入解析后的状态目录中的 teach.log。请记录最具体的资源——如果用户提出的是宽泛问题,而你通过查阅父记录找到了具体答案,请记录叶节点 ID,而不是父节点。CLI 会在 recall 时使用预置的 entity_lookups 解析跨别名;因此,在一个别名下进行 teach(例如,“Niners”),会自动满足之后使用其他别名(例如,“49ers”、“San Francisco”)的查询。

PII 规则:记录结构化问题时,请去除标识符——绝不要在 teach 查询或备注中包含姓名、电子邮件、电话号码、账号 ID 或其他个人标识符。CLI 会扫描 teach 查询中明显的电子邮件/电话号码格式并发出警告,但不会阻止操作;请在记录前去除这些信息,不要依赖警告。

第 5 步:playbook - 可选标志、自动合成

你无需判断某个会话是否“值得”记录为 playbook:如果某个系列尚无 playbook,对其进行 teach 时会根据会话日志自动合成一个 playbook_candidate,并由下一个会话通过 confirm/reject 来评判。只有当你已经掌握值得逐字记录的操作流程时,才附加显式 playbook 标志——例如 CLI 未展示的变通方法(静默丢弃的标志、未记录的参数、分页技巧、负载注意事项)。优先使用集成式单次调用形式——在同一次 teach 调用中记录资源学习内容和 playbook:

# Common case: record both the resource learning AND the playbook in one call.
QUERY=$(cat /path/to/question.txt)
eu-tenders-pp-cli teach \
  --query "$QUERY" \
  --resource <id> \
  --playbook-file ~/playbooks/<shape>.json \
  --playbook-notes-file ~/playbooks/<shape>-notes.md
# (append shell `&` to background it)

# Alternate: playbook-only (no resource to record alongside).
QUERY=$(cat /path/to/question.txt)
eu-tenders-pp-cli teach-playbook \
  --query "$QUERY" \
  --playbook-file ~/playbooks/<shape>.json \
  --notes-file ~/playbooks/<shape>-notes.md

Playbook 文件是包含 steps、entity_slots、expected_tool_calls 的 JSON 文件。Notes 文件是以 Markdown 编写的文件,逐字记录注意事项。仅使用文件的调用方(仅用 MCP 的 Agent)可将相同内容内联传入:在集成式 teach 形式中使用 --playbook-json 和 --playbook-notes,在 teach-playbook 中使用 --playbook-json 和 --notes。在集成式 teach 形式中,playbook 标志是可选的——如果只记录资源学习内容,则完全省略这些标志。在独立的 teach-playbook 形式中,必须设置 playbook 标志或 notes 标志中的至少一个;两者都为空时会被拒绝。Playbook 以结构化查询系列为键(去除实体),因此,根据一个实体形状的查询教授的操作流程适用于所有形状相同的其他查询,并在调用时通过 slots_resolved 绑定当前查询的规范值。

在之后的调用中,如果你确实找到了 playbook,就将其视为事实依据:使用 slots_resolved 替换项重放步骤,跳过操作流程中已记录的探索步骤,并在执行任何步骤前阅读 notes。

第 6 步:调试响应发现需要修正时,使用 playbook amend &

如果你的调试协议响应发现需要让 notes 或 playbook 记录的具体修正——例如变通方法、未记录的端点结构、过时的字段名、观察到的架构变更、空负载回退方案——请在向用户输出响应前执行 playbook amend。与 teach 一样,采用即发即弃的方式。将查询和说明作为 argv/MCP 参数传入,或使用非 shell 文件工具分别写入并读回(QUERY=$(cat ...)、NOTE=$(cat ...))。不要将任何一个字符串插入命令文本中:

QUERY=$(cat /path/to/question.txt)
NOTE=$(cat /path/to/note.txt)
eu-tenders-pp-cli playbook amend \
  --query "$QUERY" \
  --add-note "$NOTE"
# (append shell `&` to background it)

哪些内容值得修订:本次会话中你观察到、未来的你会受益的行为。值得修订的示例:

  • CLI 界面会静默丢弃或错误排序标志时的变通方法。
  • 未记录的端点结构(响应封装在 {meta, results} 中;负载嵌套层级比文档所述多两层)。
  • 观察到的架构变更(字段被重命名、索引在不同赛季之间发生变化、API 现在返回小写的类别标签)。

哪些内容不应写入 notes:

  • 用户问题的特定年份或特定实体答案。这是响应内容,不是学习所得。
  • playbook 已在运行时检索的团队、运动员或行数据。
  • 复述现有 notes 内容的陈述。

amend 命令会在该系列现有 notes 中追加带时间戳的标记([amend YYYY-MM-DDTHH:MMZ]: <text>)。多次修订会累积,并可查看审计记录。如果该系列尚无 playbook,amend 会创建一个仅含 notes 的 playbook(因此冷启动时发现的修正也能记录下来)。

amend 笔记中的 PII 规范

playbook amend 笔记未来可能会作为共享知识流入后续版本的 Printing Press。请勿在其中写入可识别用户身份的内容,以免需要事后清理,从而影响向上游贡献:

  • 请勿嵌入用户文件系统路径、个人 API 密钥或令牌、用户电子邮件地址、用户 GitHub 用户名,或与单个用户相关的特定查询历史。
  • 可以包含:端点结构、未记录的字段名称、API 注意事项、观察到的架构漂移、CLI 界面的变通方法、可复用的分页或重试策略。

如果某项修正只有结合用户特定的上下文才有意义,请将其记在个人笔记中,而不是 playbook amend 中。

衡量循环效果

eu-tenders-pp-cli learnings stats 会根据本地 learn_events 表报告召回命中率、教学到复用率、playbook 解决率,以及候选项确认/拒绝数量。在有分母之前,各项比率为 null;所有数据都保留在本机。可用它检查这个 CLI 的学习循环是否发挥了作用。

禁用学习
  • 在单条命令上使用 --no-learn,即可同时跳过 recall 和 teach 写入路径。适用于确定性的 Agent 工作流,或不得受累积学习内容影响的测试。
  • 在环境中设置 EU_TENDERS_NO_LEARN=true,即可全局禁用学习流程。

Agent 反馈

当你(或 Agent)发现这个 CLI 有异常时,请记录下来:

eu-tenders-pp-cli feedback "the --since flag is inclusive but docs say exclusive"
eu-tenders-pp-cli feedback --stdin < notes.txt
eu-tenders-pp-cli feedback list --json --limit 10

条目会以 feedback.jsonl 的形式本地存储在解析后的数据目录中。除非设置了 EU_TENDERS_FEEDBACK_ENDPOINT,并且传入了 --send 或设置了 EU_TENDERS_FEEDBACK_AUTO_SEND=true,否则绝不会发送 POST 请求。默认行为仅在本地存储。

记录让你感到意外的地方,而不是提交错误报告。简短、具体,写成一行:这才是会不断积累价值的部分。

输出传递

每条命令都接受 --deliver <sink>。除了写入 stdout(或替代 stdout)之外,输出还会发送到指定的 sink,因此 Agent 无需手动通过管道即可路由命令结果。支持三种 sink:

Sink效果
stdout默认值;仅写入 stdout
file:<path>将输出以原子方式写入 <path>(临时文件 + 重命名)。二进制响应命令会写入解码后的载荷字节(而非 base64 JSON 封装),并在 stdout 上打印简短的 JSON 回执;设置此 sink 时,--json/--csv 不会被拒绝。
webhook:<url>将输出正文以 application/json 格式 POST 到该 URL

遇到未知方案时,会返回结构化错误并列出支持的方案。Webhook 失败时会返回非零退出码,并在 stderr 上记录 URL 和 HTTP 状态。

命名配置

配置是保存的一组标志值,可在多次调用之间重复使用。当定时或周期性运行的 Agent 每次提供不同输入、但重复使用同一组已保存标志时,可使用配置。

eu-tenders-pp-cli profile save briefing --json
eu-tenders-pp-cli --profile briefing leads --country DEU --cpv 45
eu-tenders-pp-cli profile list --json
eu-tenders-pp-cli profile show briefing
eu-tenders-pp-cli profile delete briefing --yes

显式标志始终优先于配置值;配置值优先于默认值。agent-context 会在 available_profiles 下列出所有可用配置,方便具备自省能力的 Agent 在运行时发现它们。

退出码

Code含义
0成功
1其他错误
2用法错误(参数错误)
3未找到资源
4TED 拒绝访问(HTTP 401/403 或 HTML 拦截页面)
5API 错误(上游问题)
7受到速率限制(等待后重试)
10配置错误

参数解析

解析 $ARGUMENTS:

  1. 为空、help 或 --help → 显示 eu-tenders-pp-cli --help 输出
  2. 以 install 开头 → 以 mcp 结尾 → 安装 MCP;否则 → 参见上文的先决条件
  3. 其他任何内容 → 直接使用(作为 CLI 命令执行,并附带 --agent)

安装 MCP 服务

  1. 安装 MCP 服务:
    go install github.com/mvanhorn/printing-press-library/library/sales-and-crm/eu-tenders/cmd/eu-tenders-pp-mcp@latest
    
  2. 在 Claude Code 中注册:
    claude mcp add eu-tenders-pp-mcp -- eu-tenders-pp-mcp
    
  3. 验证:claude mcp list

直接使用

  1. 检查是否已安装:which eu-tenders-pp-cli 如果未找到,请建议安装(参见本技能顶部的先决条件)。
  2. 根据用户查询,从上方的独特功能和命令参考中匹配最佳命令。
  3. 使用 --agent 标志执行:
    eu-tenders-pp-cli leads --country DEU --cpv 45 --agent
    eu-tenders-pp-cli notices --query "buyer-country=DEU" --dry-run --agent
    
  4. 如果存在歧义,请查看子命令帮助:eu-tenders-pp-cli leads --help。

评论

支持 Markdown