把任务的协调状态迁到自建 Vikunja 的 cmbuyer 项目,git 保留单向投影, 并把「活跃任务写路径不得重叠」从自然语言规则变成机器门禁。 - scripts/vikunja_export.py:单向导出(只发 GET),stdlib-only 的 HTML→Markdown,只覆盖标记区块内,幂等,含 --selftest - scripts/vikunja-mcp.sh:MCP 启动包装从家目录迁入仓库,版本写死 1.1.1 - scripts/validate_agent_context.py:新增四项离线检查——DOING 任务写路径 互斥、通配不得圈走共享文档、导出区块 sha256、连接键一致性 - docs/agent-context.json:新增 shared_documents 与 tracker,schema_version 2 - vikunja.env 比照 gitea.env 加入 gitignore,提交 vikunja.env.example write_paths、## 边界与安全边界条目的权威留在 git,不迁往 Vikunja: 安全边界能否收紧靠 git diff 逐条复核,权威搬到远端会切断审计链。 门禁上线即报出存量违规:T-005 与 T-006 同为 DOING,在 06-tasks.md、 08-interaction-checklist.md、routes.md、current-state.md 四处重叠。 按 T-008 规定不得绕过,须由两者所有者收窄写路径或人工确认后转 DONE。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
68 lines
2.4 KiB
Bash
68 lines
2.4 KiB
Bash
#!/usr/bin/env bash
|
||
# Vikunja MCP 启动包装。
|
||
#
|
||
# 存在理由:
|
||
# 1. 凭据只留在 vikunja.env(已 gitignore),不进 .mcp.json、不进仓库、不进 shell 历史。
|
||
# 2. @0xk3vin/vikunja-mcp 内部自己拼 /api/v1(dist/vikunja-client.js:128),
|
||
# 而 vikunja.env 里的 apiurl 是带 /api/v1 的完整地址。直接透传会请求
|
||
# /api/v1/api/v1/... 并 404,所以这里必须剥掉一次。
|
||
# 3. 版本写死。上游改了工具名或行为会直接改变 agent 行为,与
|
||
# 「交付产物新旧以 SHA-256 判断」同源,不接受静默升级。
|
||
# 4. 优先用全局安装的二进制,起得快且不依赖网络;缺失时才回退 npx。
|
||
#
|
||
# 本脚本不含凭据,必须提交进仓库:其他 agent 与其他机器都靠它接入同一套配置。
|
||
set -euo pipefail
|
||
|
||
MCP_VERSION="${VIKUNJA_MCP_VERSION:-1.1.1}"
|
||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
|
||
# 凭据查找顺序:显式指定 > 仓库根目录 > 旧的家目录位置(向后兼容)。
|
||
find_env_file() {
|
||
if [ -n "${VIKUNJA_ENV_FILE:-}" ]; then
|
||
printf '%s\n' "$VIKUNJA_ENV_FILE"
|
||
return
|
||
fi
|
||
for candidate in "$REPO_ROOT/vikunja.env" "$HOME/.config/vikunja/env" "$HOME/.claude/vikunja.env"; do
|
||
if [ -r "$candidate" ]; then
|
||
printf '%s\n' "$candidate"
|
||
return
|
||
fi
|
||
done
|
||
printf '%s\n' "$REPO_ROOT/vikunja.env"
|
||
}
|
||
|
||
ENV_FILE="$(find_env_file)"
|
||
|
||
if [ ! -r "$ENV_FILE" ]; then
|
||
echo "vikunja-mcp: 读不到凭据文件 $ENV_FILE(参照 vikunja.env.example 创建)" >&2
|
||
exit 1
|
||
fi
|
||
|
||
# 只取需要的两个键,忽略文件里其余内容;tr -d '\r' 兼容 Windows 侧写出的 CRLF。
|
||
read_key() {
|
||
sed -n "s/^[[:space:]]*$1[[:space:]]*=[[:space:]]*//Ip" "$ENV_FILE" | tr -d '\r' | tail -n1
|
||
}
|
||
|
||
apiurl="$(read_key apiurl)"
|
||
apikey="$(read_key apikey)"
|
||
|
||
if [ -z "$apiurl" ] || [ -z "$apikey" ]; then
|
||
echo "vikunja-mcp: $ENV_FILE 缺少 apiurl 或 apikey" >&2
|
||
exit 1
|
||
fi
|
||
|
||
VIKUNJA_URL="${apiurl%/}"
|
||
VIKUNJA_URL="${VIKUNJA_URL%/api/v1}"
|
||
|
||
export VIKUNJA_URL
|
||
export VIKUNJA_API_TOKEN="$apikey"
|
||
|
||
# 全局安装存在且版本相符时直接用它;否则回退 npx(首次启动会联网拉包)。
|
||
if command -v vikunja-mcp >/dev/null 2>&1 &&
|
||
[ "$(npm ls -g --depth=0 --json @0xk3vin/vikunja-mcp 2>/dev/null |
|
||
sed -n 's/.*"version": *"\([^"]*\)".*/\1/p' | tail -n1)" = "$MCP_VERSION" ]; then
|
||
exec vikunja-mcp "$@"
|
||
fi
|
||
|
||
exec npx -y "@0xk3vin/vikunja-mcp@${MCP_VERSION}" "$@"
|