关于 PassNinja
PassNinja 是用于管理 PassNinja REST API 资源的命令行工具,涵盖 Apple Wallet 和 Google Wallet 票券,并支持读卡器工作流。它面向需通过命令行或 MCP 客户端管理票券模板、已发行票券和 webhook 的开发者及团队。
主要功能
- 01管理票券模板和已发行票券
- 02创建和管理 webhook
- 03配置读卡器应用与设备
- 04运行读卡器主机并提交扫描事件
- 05选择 JSON、纯文本或表格输出
适用场景
- 01通过命令行发行票券
- 02查看和更新票券模板
- 03将非接触式读卡器接入 PassNinja
- 04通过 AI 客户端管理票券
MCP 相关
该命令行工具可通过 `passninja mcp` 作为 stdio MCP 服务运行,提供账户身份、票券模板、票券和 webhook 工具,并从环境变量或 CLI 认证文件读取凭据。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
passninja
PassNinja REST API 的命令行界面。
封装了 /v1/pass_templates、/v1/passes 和 /v1/webhooks,让你可以
在命令行中管理 Apple Wallet 和 Google Wallet 通行证。
安装
macOS / Linux(Homebrew)
brew tap flomio/passninja
brew install passninja
Windows(PowerShell)
irm https://github.com/flomio/passninja-cli/releases/latest/download/install.ps1 | iex
在 cmd.exe 中:
powershell -ExecutionPolicy Bypass -Command "irm https://github.com/flomio/passninja-cli/releases/latest/download/install.ps1 | iex"
脚本会检测你的 CPU(amd64、arm64 或 386),从最新的 GitHub 版本下载对应的
二进制文件,验证其 SHA256,将其放入
%LOCALAPPDATA%\Programs\passninja\,并将该目录添加到用户的
PATH。无需管理员权限;再次运行即可原地升级。
固定特定版本,或覆盖安装目录:
$env:PASSNINJA_VERSION = 'v1.2.3'
$env:PASSNINJA_INSTALL_DIR = 'C:\tools\passninja'
irm https://github.com/flomio/passninja-cli/releases/latest/download/install.ps1 | iex
Windows(Scoop)
如果你已在使用 Scoop:
scoop bucket add flomio https://github.com/flomio/scoop-passninja
scoop install passninja
Claude Desktop(一键安装 .mcpb)
如需通过聊天管理通行证工作流,可将 PassNinja MCP 服务安装到 Claude Desktop:
-
从最新版本下载
passninja.mcpb。 -
双击该文件。Claude Desktop 会打开安装对话框,显示此服务提供的 31 个工具(通行证模板、已签发的通行证、webhook、 扫描事件应用和读卡器)。
-
对话框会提示你输入API 密钥和账户 ID — 可在 https://www.passninja.com/settings → API key 获取。
-
点击 Install,重启 Claude Desktop,然后可以向 Claude 提出如下请求:
列出我的 passninja 通行证模板,并告诉我每个模板已安装多少张通行证。
为 [email protected] 在 ptk_0x002 上签发一张新通行证。
捆绑的二进制文件已使用 Apple Developer ID 进行代码签名并经过公证,因此
macOS Gatekeeper 会直接接受,不会弹出提示。同一个 .mcpb 适用于 macOS
(通用版)、Linux(amd64)和 Windows(amd64)。
此服务也已列入官方 MCP Registry,
名称为 io.github.flomio/passninja-cli,因此任何能够使用该注册表的 MCP 客户端
都可以自动发现并安装它。
身份验证
passninja auth
# Pastes your API key and account ID; verifies by hitting /v1/pass_templates
# and saves credentials to ~/.passninja-auth.json (0600).
也可以通过环境变量 / 标志传递凭据:
export PASSNINJA_API_KEY=... PASSNINJA_ACCOUNT_ID=aid_0x002
passninja --api-key=... --account-id=... pass-template list
标志 > 环境变量 > ~/.passninja-auth.json > ~/.passninja.yaml > 默认值。
MCP 服务也遵循相同的优先级:passninja mcp(由
Claude Desktop 和其他 MCP 客户端启动)会从其环境中读取 PASSNINJA_API_KEY /
PASSNINJA_ACCOUNT_ID,并在未找到时回退到身份验证文件。
Stdio MCP 服务
此 CLI 也可用作 Model Context Protocol
服务。上文的 .mcpb 安装会将其接入 Claude Desktop;你也可以通过配置
客户端来启动它,从而将其接入任意 MCP 客户端(Cursor、Cline、Zed 等):
passninja mcp
工具列表(snake_case 名称与 CLI 子命令对应):
whoami
pass_template_{list, get, required_fields, reader_config, create, delete}
pass_{list, get, create, update, delete, raw, decrypt}
webhook_{list, get, create, delete, results}
每个工具的输入架构、破坏性操作提示注释和详细描述,都能让大模型自行发现正确用法, 无需外部文档。
命令
passninja auth Save API credentials
passninja whoami Show the active credential / account
passninja version
passninja pass-template list
passninja pass-template get <ptk_0x...>
passninja pass-template required-fields <ptk_0x...>
passninja pass-template reader-config <ptk_0x...> # NFC reader config (merchant id, collector, EC keys)
passninja pass-template create --name --platform --style [config flags] # enterprise only
passninja pass-template update <ptk_0x...> [--name --set --remap --show/--hide --require/--optional] [config flags] [--replace] # enterprise only
passninja pass-template delete <ptk_0x...> [--yes] # enterprise only
# config flags (create + update): --constrain-device/-browser/-ip,
# --disable-apple-sharing/-google-sharing, --auto-recharge --balance-trigger --top-up-target
passninja pass create <ptk_0x...> [--field k=v | --data @file.json | --data '<json>']
passninja pass list <ptk_0x...>
passninja pass get <ptk_0x...> <pass_id>
passninja pass raw <ptk_0x...> <pass_id>
passninja pass update <ptk_0x...> <pass_id> [--field k=v | --data ... | --replace]
passninja pass delete <ptk_0x...> <pass_id> [--yes]
passninja pass decrypt <ptk_0x...> [--payload <hex> | --payload-file <path> | <stdin>] [--platform apple]
# Google Smart Tap is session-bound — use `reader serve` on the reader host
# Enterprise only:
passninja webhook create --name --url --event <type> [--event <type> ...] [--pass-template ptk_0x...]
passninja webhook list [--page --per-page --pass-template]
passninja webhook get <webhook_id>
passninja webhook delete <webhook_id> [--yes]
passninja webhook results <webhook_id> [--page --per-page]
# Scan event system (premium):
passninja application list
passninja application get <app_0x...>
passninja application create --name --pass-template ptk_0x... [--kind log|validate|forward]
[--rescan-window <seconds>] [--endpoint-url <https>] [--bearer-token <secret>]
[--timeout-ms <100-8000>] [--on-endpoint-error accept|reject] [--description]
passninja application update <app_0x...> [--name --description --kind --rescan-window --endpoint-url
--bearer-token --timeout-ms --on-endpoint-error --active/--inactive]
passninja application delete <app_0x...> [--yes]
passninja reader list
passninja reader get <reader_id>
passninja reader create --name --location --application app_0x... [--application ...] # prints the token once
passninja reader update <reader_id> [--name --location --status active|revoked --application ...]
passninja reader rotate-token <reader_id> [--yes]
passninja reader delete <reader_id> [--yes]
passninja reader config <reader_id> # merged reader config across bound templates
passninja reader serve --token rdr_... [--pcsc [--pcsc-reader <name>] | --listen host:port]
[--platform apple|google] [--heartbeat 5m | --no-heartbeat]
[--serial --manufacturer --model --firmware --source]
[--on-accept '<cmd>'] [--on-reject '<cmd>']
输出格式
| 标志 | 模式 |
|---|---|
--json | 美化格式的 JSON |
--plaintext | 制表符分隔,不添加装饰(适合通过管道传给 awk) |
| default | 带边框的 ASCII 表格 |
通过 ~/.passninja.yaml 设置整个会话的默认值:
default_output: json # one of: table | json | plaintext
base_url: https://api.passninja.com/v1
Webhook 事件
passninja-site 发出的 CloudEvents 1.0 type 分类:
| 事件类型 | 触发时机 |
|---|---|
pn.pass.installed | 首台设备安装已签发的通行证 |
pn.pass.updated | 通行证字段通过 PATCH/PUT 发生更改 |
pn.pass.uninstalled | 最后一台设备移除该通行证 |
pn.pass.scanned | 读卡器记录扫描事件(包含 scanId、readerSerial、result) |
预留供将来使用:pn.pass.issued、pn.pass.deleted、
pn.pass_template.created、pn.pass_template.updated、
pn.pass_template.deleted。
运行读卡器主机
联网读卡器(VTAP Cloud、Famoco Tap&Go)会自行将扫描结果发送到 PassNinja。简单读卡器——Reyax RYRR30D、ACS WalletMate、Elatec TWN4——本身没有云连接,因此 reader serve 会提供连接:它会获取读卡器采集的值,将其作为扫描事件提交,并执行服务端返回的 LED/蜂鸣指令。
设置分为三个步骤,只有最后一步在读卡器主机上运行:
# 1. an application decides what a scan means for one pass template
passninja application create --name "Front gate" --kind validate \
--pass-template ptk_0x216 --rescan-window 14400
# 2. a reader binds to it; the token is printed once — save it
passninja reader create --name "Front gate" --location "Gate 2" \
--application app_0x1
# 3. on the reader host (a Raspberry Pi, a kiosk PC, …)
passninja reader serve --token rdr_... --pcsc # attached PC/SC reader
my-reader-daemon | passninja reader serve --token rdr_... # or any daemon
serve 使用该读卡器自己的 bearer token 进行身份验证——读卡器主机不需要,也绝不应持有你的账户 API 密钥。
读卡值有三种来源:
--pcsc可直接驱动连接的 PC/SC 非接触式读卡器(ACS WalletMate/WalletMate II,包括 Mini 模块),无需单独的守护进程。主机自行运行钱包流程:Apple 设备轻触时,会采集 VAS 密码;Android 设备轻触时,会让服务端在轻触过程中为 Smart Tap 会话预签名(采集器密钥不会离开 PassNinja),协商安全通道并采集加密数据包。两者都会提交到服务端解密——主机不持有任何密钥材料。第一代 WalletMate 出厂时会禁用 RF 轮询;安装了厂商 CCID 驱动程序后,serve会自动启用轮询。macOS/Linux 上需要原生(cgo)构建——go install和 Homebrew 构建均符合要求。- stdin(每行一个值)——将任意读卡器守护进程的输出通过管道传入。
--listen 127.0.0.1:8080——驱动程序可以向其发送 POST 请求的本机回环 HTTP 端点。
对于 stdin/HTTP,如果值看起来是原始采集的 APDU,则会转发以便在服务端解密;否则会将其视为已解密的通行证序列号。
每个结果都会在 stdout 输出一个 JSON 对象:
{"scanId":"9f8e7d6c-…","result":"accepted","pass":{"passTemplate":"ptk_0x216","passId":"fee4a257185906b92a"},
"readerInstructions":{"success":true,"led":"green","beep":true,"message":"Accepted"}}
要驱动实体 LED,请使用结果钩子——它们会接收 $PN_RESULT、$PN_LED、$PN_MESSAGE、$PN_PASS、$PN_SCAN_ID,以及——当转发应用有响应时——$PN_FORWARD_BODY(端点返回的 JSON 回复)。对于转发应用,$PN_MESSAGE 是端点原样返回的 message,打印的扫描 JSON 则会在 forwardResponse 下包含该回复:
passninja reader serve --token rdr_... \
--on-accept 'gpioset 0 17=1' --on-reject 'gpioset 0 27=1'
心跳(默认每 5m)会报告运行状态以及通过 --serial/--manufacturer/--model/--firmware 传入的硬件标识信息,这些信息会显示在控制面板中读卡器的 Hardware 面板里。若读卡器厂商的 MDM 已在跟踪设备,请使用 --no-heartbeat。
passninja webhook create 在创建时会返回 bearer token,且只显示一次。请妥善保存——之后不会再次显示。
从源代码构建
git clone https://github.com/flomio/passninja-cli.git
cd passninja-cli
make build # writes dist/passninja
./dist/passninja version
make install # installs to $GOPATH/bin
发布流程
由标签驱动。在 master 上推送 vX.Y.Z 标签;.github/workflows/release.yml 中的 GitHub Actions 工作流会针对 darwin/linux × arm64/amd64 矩阵构建,在 macOS 运行器上打包经过代码签名和 Apple 公证的 passninja.mcpb,在 GitHub Release 上发布二进制文件和 .mcpb,并向 flomio/homebrew-passninja 创建 PR,更新公式中的 url 和 sha256。
Apple 凭据存放在仓库机密中(APPLE_TEAM_ID、APPLE_API_KEY_ID、APPLE_API_ISSUER_ID、APPLE_SIGN_IDENTITY、APPLE_CERTIFICATE_PASSWORD,以及经 base64 编码的 APPLE_API_KEY_P8 和 APPLE_CERTIFICATE_P12)。
每次发布标签版本后,都需要刷新 MCP Registry 条目。将 server.json 中的 packages[0].identifier、packages[0].version、packages[0].fileSha256 和顶层 version 更新为与新版本一致,然后:
mcp-publisher login github # one-time per machine
mcp-publisher publish
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。