@devessentials/zfy-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +212 -0
- package/dist/cli/index.js +979 -0
- package/dist/mcp/server.js +593 -0
- package/dist/sdk/index.d.ts +1380 -0
- package/dist/sdk/index.js +708 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zfy contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# zfy
|
|
2
|
+
|
|
3
|
+
[](https://github.com/EssentialsDev/zfy-cli/actions/workflows/ci.yml)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
6
|
+
A third-party CLI, TypeScript SDK, and **MCP server** for the [Zeffy API](https://www.zeffy.com/integration/api) — built so nonprofits can automate donation reporting and AI agents can answer questions like *"draft tax receipts for everyone who gave over $250 in 2025."*
|
|
7
|
+
|
|
8
|
+
> **Not affiliated with Zeffy or Simplyk.** Wraps the official free public read-only API (Payments, Contacts, Campaigns) released in 2025.
|
|
9
|
+
|
|
10
|
+
## What you can do with it
|
|
11
|
+
|
|
12
|
+
- Pull donations, donors, and campaigns out of Zeffy as JSON — pipe into `jq`, spreadsheets, or your own code.
|
|
13
|
+
- Generate **end-of-year donation reports** in JSON, CSV, Markdown, or one PDF receipt per donor.
|
|
14
|
+
- Plug Zeffy into Claude, Claude Desktop, or any MCP-aware agent so it can answer questions about your donation data conversationally.
|
|
15
|
+
- Build custom workflows in TypeScript using the same SDK that powers the CLI.
|
|
16
|
+
|
|
17
|
+
Read-only by design — `zfy` cannot modify your Zeffy data, because the official API is read-only.
|
|
18
|
+
|
|
19
|
+
## Contents
|
|
20
|
+
|
|
21
|
+
- [Install](#install)
|
|
22
|
+
- [Authenticate](#authenticate)
|
|
23
|
+
- [CLI usage](#cli-usage)
|
|
24
|
+
- [Quickstart](#quickstart)
|
|
25
|
+
- [End-of-year report](#end-of-year-report)
|
|
26
|
+
- [Logo spec for `--logo`](#logo-spec-for---logo)
|
|
27
|
+
- [MCP server](#mcp-server-use-from-claude--agents)
|
|
28
|
+
- [SDK usage](#sdk-usage)
|
|
29
|
+
- [Development](#development)
|
|
30
|
+
- [License](#license)
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm i -g @devessentials/zfy-cli
|
|
36
|
+
# or run without installing:
|
|
37
|
+
npx --package=@devessentials/zfy-cli zfy --help
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The package is `@devessentials/zfy-cli` on npm; the binary is `zfy` and the MCP entry point is `zfy-mcp`. Node.js 20+ required.
|
|
41
|
+
|
|
42
|
+
## Authenticate
|
|
43
|
+
|
|
44
|
+
1. In your Zeffy dashboard, go to **Settings → Integrations** and generate an API key.
|
|
45
|
+
2. Save it locally:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
zfy auth set # prompts for the key, stores it in ~/.config/zfy/config.json (mode 0600)
|
|
49
|
+
zfy auth status # verifies the key by calling the Zeffy API
|
|
50
|
+
zfy auth clear # removes the stored key
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Or pass it inline for CI / one-offs:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
ZEFFY_API_KEY=sk_xxx zfy payments list --from 2025-01-01
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The `ZEFFY_API_KEY` env var always takes precedence over the stored key.
|
|
60
|
+
|
|
61
|
+
## CLI usage
|
|
62
|
+
|
|
63
|
+
Every command outputs JSON to stdout — pipe it into `jq`, an LLM, a spreadsheet, or further commands.
|
|
64
|
+
|
|
65
|
+
### Quickstart
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Donations in a date range
|
|
69
|
+
zfy payments list --from 2025-01-01 --to 2025-12-31
|
|
70
|
+
|
|
71
|
+
# Total raised in Q4 2025
|
|
72
|
+
zfy payments list --from 2025-10-01 --to 2025-12-31 | jq '[.[].amount] | add'
|
|
73
|
+
|
|
74
|
+
# All gifts to a specific campaign
|
|
75
|
+
zfy payments list --campaign cmp_abc --status succeeded
|
|
76
|
+
|
|
77
|
+
# Donor lookup by email
|
|
78
|
+
zfy contacts list --email donor@example.com
|
|
79
|
+
|
|
80
|
+
# Campaigns
|
|
81
|
+
zfy campaigns list
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### End-of-year report
|
|
85
|
+
|
|
86
|
+
Generate a per-donor annual report in any format. Defaults: excludes refunded payments, uses your system timezone for year boundaries.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# JSON to stdout (default — best for piping to agents)
|
|
90
|
+
zfy report eoy --year 2025
|
|
91
|
+
|
|
92
|
+
# Spreadsheet-friendly CSV
|
|
93
|
+
zfy report eoy --year 2025 --format csv --out eoy-2025.csv
|
|
94
|
+
|
|
95
|
+
# Top-50 donor markdown summary (fits in an LLM context)
|
|
96
|
+
zfy report eoy --year 2025 --format md --out eoy-2025.md --top 50
|
|
97
|
+
|
|
98
|
+
# One PDF receipt per donor
|
|
99
|
+
zfy report eoy --year 2025 --format pdf --out ./receipts/ \
|
|
100
|
+
--org "Friends of the Library" \
|
|
101
|
+
--logo ./logo.png --logo-size 64 \
|
|
102
|
+
--timezone America/Los_Angeles
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Useful flags (`zfy report eoy --help` for the full list):
|
|
106
|
+
|
|
107
|
+
| Flag | Notes |
|
|
108
|
+
| --- | --- |
|
|
109
|
+
| `--year <year>` | Required. Calendar year. |
|
|
110
|
+
| `--format <fmt>` | `json` \| `csv` \| `md` \| `pdf`. Default `json`. |
|
|
111
|
+
| `--out <path>` | Output file (or directory for PDF). Defaults to stdout. |
|
|
112
|
+
| `--timezone <tz>` | IANA timezone (e.g. `America/Los_Angeles`). Boundaries respect DST. |
|
|
113
|
+
| `--currency <code>` | Filter to a single currency. |
|
|
114
|
+
| `--include-refunded` | Include refunded payments (excluded by default). |
|
|
115
|
+
| `--top <n>` | Markdown: limit donor table. |
|
|
116
|
+
| `--org <name>` | PDF: organization name in the header. |
|
|
117
|
+
| `--logo <path>` | PDF: square PNG/JPEG mark — see spec below. |
|
|
118
|
+
| `--logo-size <pt>` | PDF: edge length of the logo slot (default 64 pt). |
|
|
119
|
+
| `--receipt-text <txt>` | PDF: override the default tax-receipt boilerplate. |
|
|
120
|
+
|
|
121
|
+
### Logo spec for `--logo`
|
|
122
|
+
|
|
123
|
+
The PDF renderer reserves a small square slot for an org mark. To keep batches consistent and prevent multi-gigabyte receipt runs, logos must meet:
|
|
124
|
+
|
|
125
|
+
| Constraint | Limit |
|
|
126
|
+
| --- | --- |
|
|
127
|
+
| Format | PNG or JPEG (sniffed from file bytes — extension is ignored) |
|
|
128
|
+
| File size | ≤ 2 MB |
|
|
129
|
+
| Minimum dimensions | 64 × 64 px |
|
|
130
|
+
| Shape | Square within ±10% (e.g. 512×512, or 500×510 — but not 800×200) |
|
|
131
|
+
|
|
132
|
+
Recommended: a 512×512 PNG with a transparent or white background. If the file fails any check, `zfy` prints a single warning to stderr and continues without the logo — a bad asset never blocks a 500-donor receipt run.
|
|
133
|
+
|
|
134
|
+
## MCP server (use from Claude / agents)
|
|
135
|
+
|
|
136
|
+
`zfy-mcp` exposes the same operations as MCP tools over stdio. Add to `~/.claude.json` (or Claude Desktop's `claude_desktop_config.json`):
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"mcpServers": {
|
|
141
|
+
"zeffy": {
|
|
142
|
+
"command": "zfy-mcp",
|
|
143
|
+
"env": { "ZEFFY_API_KEY": "sk_xxx" }
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Tools exposed:
|
|
150
|
+
|
|
151
|
+
| Tool | Description |
|
|
152
|
+
| --- | --- |
|
|
153
|
+
| `zeffy_list_payments` | List donations with date / status / campaign / contact filters |
|
|
154
|
+
| `zeffy_list_contacts` | List donors (lookup by email or date range) |
|
|
155
|
+
| `zeffy_list_campaigns` | List campaigns |
|
|
156
|
+
| `zeffy_eoy_report` | Per-donor annual summary (JSON or Markdown) |
|
|
157
|
+
|
|
158
|
+
After installing and configuring, ask your agent things like:
|
|
159
|
+
|
|
160
|
+
- "How much did we raise in Q4 2025?"
|
|
161
|
+
- "Who were our top 10 donors last year, and what did each give?"
|
|
162
|
+
- "Generate an EOY summary I can paste into our board report."
|
|
163
|
+
|
|
164
|
+
PDF and CSV output aren't exposed via MCP (binary data is awkward over stdio) — use the CLI for those.
|
|
165
|
+
|
|
166
|
+
## SDK usage
|
|
167
|
+
|
|
168
|
+
Everything the CLI does is available as a typed library, including the EOY aggregation and the format renderers.
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
import { Zeffy } from "@devessentials/zfy-cli";
|
|
172
|
+
|
|
173
|
+
const zeffy = new Zeffy(process.env.ZEFFY_API_KEY!);
|
|
174
|
+
|
|
175
|
+
// Single page (cursor-paginated under the hood)
|
|
176
|
+
const page = await zeffy.payments.list({ created_gte: 1735689600 });
|
|
177
|
+
|
|
178
|
+
// Auto-paginate across the whole range
|
|
179
|
+
for await (const p of zeffy.payments.iterate({ created_gte: 1735689600 })) {
|
|
180
|
+
console.log(p.id, p.amount, p.contact?.email);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Build and render an EOY report yourself
|
|
184
|
+
import { buildEoyReport, formatMarkdown, writePdfReceipts } from "@devessentials/zfy-cli";
|
|
185
|
+
|
|
186
|
+
const report = await buildEoyReport(zeffy, {
|
|
187
|
+
year: 2025,
|
|
188
|
+
timezone: "America/Los_Angeles",
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
console.log(formatMarkdown(report, 25));
|
|
192
|
+
await writePdfReceipts(report, "./receipts", { orgName: "Friends of the Library" });
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The client handles 429 rate-limit responses (token-bucket capped at 90 req/min, with `Retry-After` honored on backoff) and validates every response against [zod](https://zod.dev) schemas — bad shapes throw with the raw response attached for debugging.
|
|
196
|
+
|
|
197
|
+
## Development
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
pnpm install
|
|
201
|
+
pnpm build # tsup → dist/
|
|
202
|
+
pnpm test # vitest
|
|
203
|
+
pnpm typecheck # tsc --noEmit
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
CI runs `typecheck`, `test`, and `build` on every push and PR against Node 20 and 22.
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
MIT — see [LICENSE](./LICENSE). Not affiliated with Zeffy or Simplyk.
|
|
211
|
+
|
|
212
|
+
Found a bug or want to contribute? [Open an issue or PR](https://github.com/EssentialsDev/zfy-cli/issues).
|