affiliate-networks-mcp 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.
Files changed (166) hide show
  1. package/LICENCE +21 -0
  2. package/README.md +167 -0
  3. package/dist/cli/doctor.d.ts +42 -0
  4. package/dist/cli/doctor.d.ts.map +1 -0
  5. package/dist/cli/doctor.js +74 -0
  6. package/dist/cli/doctor.js.map +1 -0
  7. package/dist/cli/setup.d.ts +35 -0
  8. package/dist/cli/setup.d.ts.map +1 -0
  9. package/dist/cli/setup.js +254 -0
  10. package/dist/cli/setup.js.map +1 -0
  11. package/dist/cli/test.d.ts +18 -0
  12. package/dist/cli/test.d.ts.map +1 -0
  13. package/dist/cli/test.js +112 -0
  14. package/dist/cli/test.js.map +1 -0
  15. package/dist/cli/wizard/envfile.d.ts +24 -0
  16. package/dist/cli/wizard/envfile.d.ts.map +1 -0
  17. package/dist/cli/wizard/envfile.js +69 -0
  18. package/dist/cli/wizard/envfile.js.map +1 -0
  19. package/dist/cli/wizard/paths.d.ts +17 -0
  20. package/dist/cli/wizard/paths.d.ts.map +1 -0
  21. package/dist/cli/wizard/paths.js +19 -0
  22. package/dist/cli/wizard/paths.js.map +1 -0
  23. package/dist/cli/wizard/prompts.d.ts +54 -0
  24. package/dist/cli/wizard/prompts.d.ts.map +1 -0
  25. package/dist/cli/wizard/prompts.js +164 -0
  26. package/dist/cli/wizard/prompts.js.map +1 -0
  27. package/dist/index.d.ts +16 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +99 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/networks/awin/adapter.d.ts +374 -0
  32. package/dist/networks/awin/adapter.d.ts.map +1 -0
  33. package/dist/networks/awin/adapter.js +903 -0
  34. package/dist/networks/awin/adapter.js.map +1 -0
  35. package/dist/networks/awin/auth.d.ts +98 -0
  36. package/dist/networks/awin/auth.d.ts.map +1 -0
  37. package/dist/networks/awin/auth.js +209 -0
  38. package/dist/networks/awin/auth.js.map +1 -0
  39. package/dist/networks/awin/client.d.ts +65 -0
  40. package/dist/networks/awin/client.d.ts.map +1 -0
  41. package/dist/networks/awin/client.js +141 -0
  42. package/dist/networks/awin/client.js.map +1 -0
  43. package/dist/networks/awin/setup.d.ts +30 -0
  44. package/dist/networks/awin/setup.d.ts.map +1 -0
  45. package/dist/networks/awin/setup.js +55 -0
  46. package/dist/networks/awin/setup.js.map +1 -0
  47. package/dist/networks/cj/adapter.d.ts +306 -0
  48. package/dist/networks/cj/adapter.d.ts.map +1 -0
  49. package/dist/networks/cj/adapter.js +899 -0
  50. package/dist/networks/cj/adapter.js.map +1 -0
  51. package/dist/networks/cj/auth.d.ts +82 -0
  52. package/dist/networks/cj/auth.d.ts.map +1 -0
  53. package/dist/networks/cj/auth.js +190 -0
  54. package/dist/networks/cj/auth.js.map +1 -0
  55. package/dist/networks/cj/client.d.ts +130 -0
  56. package/dist/networks/cj/client.d.ts.map +1 -0
  57. package/dist/networks/cj/client.js +226 -0
  58. package/dist/networks/cj/client.js.map +1 -0
  59. package/dist/networks/cj/setup.d.ts +25 -0
  60. package/dist/networks/cj/setup.d.ts.map +1 -0
  61. package/dist/networks/cj/setup.js +51 -0
  62. package/dist/networks/cj/setup.js.map +1 -0
  63. package/dist/networks/ebay/adapter.d.ts +266 -0
  64. package/dist/networks/ebay/adapter.d.ts.map +1 -0
  65. package/dist/networks/ebay/adapter.js +797 -0
  66. package/dist/networks/ebay/adapter.js.map +1 -0
  67. package/dist/networks/ebay/auth.d.ts +101 -0
  68. package/dist/networks/ebay/auth.d.ts.map +1 -0
  69. package/dist/networks/ebay/auth.js +272 -0
  70. package/dist/networks/ebay/auth.js.map +1 -0
  71. package/dist/networks/ebay/client.d.ts +73 -0
  72. package/dist/networks/ebay/client.d.ts.map +1 -0
  73. package/dist/networks/ebay/client.js +140 -0
  74. package/dist/networks/ebay/client.js.map +1 -0
  75. package/dist/networks/ebay/setup.d.ts +21 -0
  76. package/dist/networks/ebay/setup.d.ts.map +1 -0
  77. package/dist/networks/ebay/setup.js +58 -0
  78. package/dist/networks/ebay/setup.js.map +1 -0
  79. package/dist/networks/impact/adapter.d.ts +251 -0
  80. package/dist/networks/impact/adapter.d.ts.map +1 -0
  81. package/dist/networks/impact/adapter.js +910 -0
  82. package/dist/networks/impact/adapter.js.map +1 -0
  83. package/dist/networks/impact/auth.d.ts +60 -0
  84. package/dist/networks/impact/auth.d.ts.map +1 -0
  85. package/dist/networks/impact/auth.js +171 -0
  86. package/dist/networks/impact/auth.js.map +1 -0
  87. package/dist/networks/impact/client.d.ts +69 -0
  88. package/dist/networks/impact/client.d.ts.map +1 -0
  89. package/dist/networks/impact/client.js +162 -0
  90. package/dist/networks/impact/client.js.map +1 -0
  91. package/dist/networks/impact/setup.d.ts +11 -0
  92. package/dist/networks/impact/setup.d.ts.map +1 -0
  93. package/dist/networks/impact/setup.js +37 -0
  94. package/dist/networks/impact/setup.js.map +1 -0
  95. package/dist/networks/index.d.ts +21 -0
  96. package/dist/networks/index.d.ts.map +1 -0
  97. package/dist/networks/index.js +21 -0
  98. package/dist/networks/index.js.map +1 -0
  99. package/dist/networks/rakuten/adapter.d.ts +284 -0
  100. package/dist/networks/rakuten/adapter.d.ts.map +1 -0
  101. package/dist/networks/rakuten/adapter.js +768 -0
  102. package/dist/networks/rakuten/adapter.js.map +1 -0
  103. package/dist/networks/rakuten/auth.d.ts +115 -0
  104. package/dist/networks/rakuten/auth.d.ts.map +1 -0
  105. package/dist/networks/rakuten/auth.js +301 -0
  106. package/dist/networks/rakuten/auth.js.map +1 -0
  107. package/dist/networks/rakuten/client.d.ts +78 -0
  108. package/dist/networks/rakuten/client.d.ts.map +1 -0
  109. package/dist/networks/rakuten/client.js +150 -0
  110. package/dist/networks/rakuten/client.js.map +1 -0
  111. package/dist/networks/rakuten/setup.d.ts +24 -0
  112. package/dist/networks/rakuten/setup.d.ts.map +1 -0
  113. package/dist/networks/rakuten/setup.js +60 -0
  114. package/dist/networks/rakuten/setup.js.map +1 -0
  115. package/dist/server.d.ts +18 -0
  116. package/dist/server.d.ts.map +1 -0
  117. package/dist/server.js +100 -0
  118. package/dist/server.js.map +1 -0
  119. package/dist/shared/config.d.ts +63 -0
  120. package/dist/shared/config.d.ts.map +1 -0
  121. package/dist/shared/config.js +135 -0
  122. package/dist/shared/config.js.map +1 -0
  123. package/dist/shared/diagnostic.d.ts +47 -0
  124. package/dist/shared/diagnostic.d.ts.map +1 -0
  125. package/dist/shared/diagnostic.js +120 -0
  126. package/dist/shared/diagnostic.js.map +1 -0
  127. package/dist/shared/errors.d.ts +41 -0
  128. package/dist/shared/errors.d.ts.map +1 -0
  129. package/dist/shared/errors.js +94 -0
  130. package/dist/shared/errors.js.map +1 -0
  131. package/dist/shared/logging.d.ts +15 -0
  132. package/dist/shared/logging.d.ts.map +1 -0
  133. package/dist/shared/logging.js +56 -0
  134. package/dist/shared/logging.js.map +1 -0
  135. package/dist/shared/registry.d.ts +14 -0
  136. package/dist/shared/registry.d.ts.map +1 -0
  137. package/dist/shared/registry.js +25 -0
  138. package/dist/shared/registry.js.map +1 -0
  139. package/dist/shared/resilience.d.ts +52 -0
  140. package/dist/shared/resilience.d.ts.map +1 -0
  141. package/dist/shared/resilience.js +235 -0
  142. package/dist/shared/resilience.js.map +1 -0
  143. package/dist/shared/types.d.ts +258 -0
  144. package/dist/shared/types.d.ts.map +1 -0
  145. package/dist/shared/types.js +27 -0
  146. package/dist/shared/types.js.map +1 -0
  147. package/dist/tools/generate.d.ts +28 -0
  148. package/dist/tools/generate.d.ts.map +1 -0
  149. package/dist/tools/generate.js +202 -0
  150. package/dist/tools/generate.js.map +1 -0
  151. package/package.json +49 -0
  152. package/src/skills/affiliate-earnings-report/SKILL.md +62 -0
  153. package/src/skills/affiliate-earnings-report/examples/last-30-days.md +37 -0
  154. package/src/skills/affiliate-network-setup-help/SKILL.md +65 -0
  155. package/src/skills/affiliate-network-setup-help/examples/awin-walkthrough.md +19 -0
  156. package/src/skills/affiliate-network-status/SKILL.md +69 -0
  157. package/src/skills/affiliate-network-status/examples/mixed-health.md +21 -0
  158. package/src/skills/audit-affiliate-links/SKILL.md +67 -0
  159. package/src/skills/audit-affiliate-links/examples/sitemap-audit.md +24 -0
  160. package/templates/new-network/README.md +53 -0
  161. package/templates/new-network/adapter.ts +406 -0
  162. package/templates/new-network/auth.ts +53 -0
  163. package/templates/new-network/client.ts +52 -0
  164. package/templates/new-network/network.json +40 -0
  165. package/templates/new-network/setup.ts +47 -0
  166. package/templates/new-network/tests/fixtures/.gitkeep +0 -0
package/LICENCE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Robert Berrisford
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 all
13
+ 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 THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # affiliate-mcp
2
+
3
+ > An MCP server for affiliate networks. Bring your own keys.
4
+
5
+ **Status:** pre-launch. The five bundled adapters ship as `claim_status: partial` (or `experimental`, for the most recent addition) until they have been exercised against real publisher accounts.
6
+
7
+ ## What this is
8
+
9
+ `affiliate-mcp` is a Model Context Protocol server that exposes affiliate
10
+ network APIs as MCP tools. It bundles five networks — Awin, CJ Affiliate,
11
+ eBay Partner Network, Impact, and Rakuten Advertising — so a publisher can ask
12
+ an MCP client (Claude Desktop, Claude Code, others) questions like "which
13
+ programmes are still pending after 90 days?" across all of them without
14
+ opening five dashboards.
15
+
16
+ The server runs locally. There is no hosted service, no account, and no
17
+ telemetry. Credentials live in `~/.affiliate-mcp/.env` at file mode `0600`
18
+ and never leave your host. You bring your own publisher keys for each
19
+ network you want wired in.
20
+
21
+ For per-network capability, known limitations, and the editorial baseline,
22
+ see [`REPORT.md`](./REPORT.md). It is regenerated from each adapter's
23
+ `network.json` and findings docs, so it stays in step with the code.
24
+
25
+ ## Quick-start
26
+
27
+ Requires Node.js 20 or newer.
28
+
29
+ Run the interactive setup wizard:
30
+
31
+ ```
32
+ npx affiliate-networks-mcp setup
33
+ ```
34
+
35
+ The wizard walks one network at a time, validates each credential against the
36
+ live API as you enter it, and writes the configuration to
37
+ `~/.affiliate-mcp/.env` at file mode `0600`.
38
+
39
+ Check that everything is wired up:
40
+
41
+ ```
42
+ npx affiliate-networks-mcp test
43
+ ```
44
+
45
+ Then point your MCP client at the server. A sample Claude Desktop config
46
+ lives at [`examples/claude-desktop-config.json`](./examples/claude-desktop-config.json)
47
+ (with notes at [`examples/claude-desktop-config.md`](./examples/claude-desktop-config.md)):
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "affiliate": {
53
+ "command": "npx",
54
+ "args": ["affiliate-networks-mcp"]
55
+ }
56
+ }
57
+ }
58
+ ```
59
+
60
+ Restart your client. The configured networks appear as tool calls prefixed
61
+ `affiliate_<network>_…`.
62
+
63
+ ## Networks
64
+
65
+ <!-- AFFILIATE_MCP_NETWORK_TABLE_START -->
66
+ | Network | Setup time | Approval required | Supported ops | Notes |
67
+ | --- | ---: | --- | ---: | --- |
68
+ | Awin | 5 min | no | 6 / 7 | no clicks |
69
+ | CJ Affiliate | 8 min | no | 6 / 7 | no clicks |
70
+ | eBay Partner Network | 10 min | yes (~3 days) | 7 / 7 | see notes |
71
+ | Impact | 6 min | no | 7 / 7 | upstream variability |
72
+ | Rakuten Advertising | 12 min | yes (~5 days) | 6 / 7 | clicks gated |
73
+ <!-- AFFILIATE_MCP_NETWORK_TABLE_END -->
74
+
75
+ The table above is regenerated from each adapter's `network.json` by
76
+ `npm run generate:readme`. For a per-network breakdown — operation-level
77
+ support, latency, known limitations, and full findings prose — see
78
+ [`REPORT.md`](./REPORT.md).
79
+
80
+ ## Per-network setup
81
+
82
+ Each bundled network has a short setup document covering dashboard navigation,
83
+ credential locations, and common stumbling blocks:
84
+
85
+ - [Awin](./docs/networks/awin.md) — API token + publisher ID.
86
+ - [CJ Affiliate](./docs/networks/cj.md) — Developer Key (GraphQL).
87
+ - [eBay Partner Network](./docs/networks/ebay.md) — OAuth client + secret + campaign ID; approval required.
88
+ - [Impact](./docs/networks/impact.md) — Account SID + Auth Token.
89
+ - [Rakuten Advertising](./docs/networks/rakuten.md) — OAuth client + SID; approval required.
90
+
91
+ ## Tool surface
92
+
93
+ Each registered network exposes the seven canonical publisher operations as
94
+ MCP tools, named `affiliate_<network>_<snake_case_op>`:
95
+
96
+ - `list_programmes`, `get_programme` — programmes (joined or available).
97
+ - `list_transactions`, `get_earnings_summary` — transactions and aggregates.
98
+ - `list_clicks` — click-level data, where the network exposes it.
99
+ - `generate_tracking_link` — mint or construct a deeplink.
100
+ - `verify_auth` — confirm credentials and surface the publisher identity.
101
+
102
+ Two meta tools are always present: `affiliate_list_networks` and
103
+ `affiliate_run_diagnostic`. They let a client enumerate the active adapters
104
+ and check live capabilities in a single call.
105
+
106
+ ## Skills
107
+
108
+ Four packaged skills wrap common workflows so the client picks the right
109
+ tools without you naming them. Each lives under `src/skills/<name>/`:
110
+
111
+ - [`affiliate-earnings-report`](./src/skills/affiliate-earnings-report/SKILL.md)
112
+ — consolidated period earnings across every configured network.
113
+ - [`affiliate-network-status`](./src/skills/affiliate-network-status/SKILL.md)
114
+ — health check: auth, reachability, supported operations.
115
+ - [`affiliate-network-setup-help`](./src/skills/affiliate-network-setup-help/SKILL.md)
116
+ — guides the user through setup for a specific network.
117
+ - [`audit-affiliate-links`](./src/skills/audit-affiliate-links/SKILL.md)
118
+ — checks that affiliate links on a page or sitemap still resolve to active
119
+ programmes.
120
+
121
+ ## Status report
122
+
123
+ [`REPORT.md`](./REPORT.md) is the editorial position: per-network capability,
124
+ known limitations, and where the upstream API surprised us. Regenerated on
125
+ every adapter merge. Treat it as the source of truth before opening an issue.
126
+
127
+ ## For developers
128
+
129
+ Contributions are welcome — especially new network adapters. Start with
130
+ [`CONTRIBUTING.md`](./CONTRIBUTING.md) for the human-side workflow, then read
131
+ [`AGENTS.md`](./AGENTS.md) (the primer for AI coding agents — file layout,
132
+ conventions, "what not to do") and `.claude/skills/contribute/SKILL.md` (the
133
+ playbook a Claude Code session loads automatically when you open this repo).
134
+ [`templates/new-network/`](./templates/new-network/) is the scaffold to copy.
135
+ [`WANTED.md`](./WANTED.md) lists networks and ideas explicitly on the
136
+ roadmap, and [`REPORT.md`](./REPORT.md) is the editorial baseline for any
137
+ new claim about a network's API.
138
+
139
+ Local development:
140
+
141
+ ```
142
+ npm install
143
+ npm test
144
+ npm run typecheck
145
+ npm run lint
146
+ npm run build
147
+ ```
148
+
149
+ Generators:
150
+
151
+ ```
152
+ npm run generate:report # writes REPORT.md
153
+ npm run generate:readme # updates the table block in this README
154
+ npm run generate:report-image # renders the summary table as a PNG (needs Playwright)
155
+ ```
156
+
157
+ ## Licence
158
+
159
+ MIT. See [`LICENCE`](./LICENCE).
160
+
161
+ ## Acknowledgements
162
+
163
+ This project is only possible because the engineering teams at Awin, CJ
164
+ Affiliate, eBay Partner Network, Impact, and Rakuten Advertising publish
165
+ public, documented APIs for their publisher data. The adapters here read
166
+ those APIs; they do not scrape, simulate, or work around any rate or access
167
+ limits.
@@ -0,0 +1,42 @@
1
+ /**
2
+ * `affiliate-mcp doctor [slug]` — verbose diagnostic.
3
+ *
4
+ * Same data as `test` but JSON, plus environment context (Node version,
5
+ * platform, config path + presence, masked variable list, per-operation
6
+ * resilience config). Designed for users to paste into a GitHub issue.
7
+ *
8
+ * Critical: variable VALUES must never be printed. Only NAMES and presence.
9
+ * The Pino redactor protects logs; this surface enforces the same rule
10
+ * explicitly because it dumps JSON to stdout for human consumption.
11
+ */
12
+ import { runDiagnostic } from '../shared/diagnostic.js';
13
+ import type { ResilienceConfigMap } from '../shared/types.js';
14
+ export interface DoctorOptions {
15
+ slug?: string;
16
+ }
17
+ export interface DoctorReport {
18
+ generatedAt: string;
19
+ environment: {
20
+ nodeVersion: string;
21
+ platform: string;
22
+ arch: string;
23
+ affiliateMcpVersion: string;
24
+ };
25
+ config: {
26
+ path: string;
27
+ present: boolean;
28
+ /** Names only — never values. */
29
+ keys: string[];
30
+ };
31
+ adapters: Array<{
32
+ slug: string;
33
+ name: string;
34
+ claimStatus: string;
35
+ knownLimitations: string[];
36
+ resilience: ResilienceConfigMap;
37
+ }>;
38
+ diagnostic: Awaited<ReturnType<typeof runDiagnostic>>;
39
+ }
40
+ export declare function buildReport(opts?: DoctorOptions): Promise<DoctorReport>;
41
+ export declare function runDoctor(opts?: DoctorOptions): Promise<number>;
42
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAIxD,OAAO,KAAK,EAAkB,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAM9E,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,OAAO,CAAC;QACjB,iCAAiC;QACjC,IAAI,EAAE,MAAM,EAAE,CAAC;KAChB,CAAC;IACF,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B,UAAU,EAAE,mBAAmB,CAAC;KACjC,CAAC,CAAC;IACH,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC;CACvD;AAED,wBAAsB,WAAW,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAyCjF;AAED,wBAAsB,SAAS,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAQzE"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * `affiliate-mcp doctor [slug]` — verbose diagnostic.
3
+ *
4
+ * Same data as `test` but JSON, plus environment context (Node version,
5
+ * platform, config path + presence, masked variable list, per-operation
6
+ * resilience config). Designed for users to paste into a GitHub issue.
7
+ *
8
+ * Critical: variable VALUES must never be printed. Only NAMES and presence.
9
+ * The Pino redactor protects logs; this surface enforces the same rule
10
+ * explicitly because it dumps JSON to stdout for human consumption.
11
+ */
12
+ import { existsSync, readFileSync } from 'node:fs';
13
+ import { runDiagnostic } from '../shared/diagnostic.js';
14
+ import { getAdapter, getAdapters } from '../shared/registry.js';
15
+ import { resolveConfigPaths } from './wizard/paths.js';
16
+ import { parseEnvFile } from '../shared/config.js';
17
+ function out(line) {
18
+ process.stdout.write(line.endsWith('\n') ? line : `${line}\n`);
19
+ }
20
+ export async function buildReport(opts = {}) {
21
+ const paths = resolveConfigPaths();
22
+ const present = existsSync(paths.envFile);
23
+ let keys = [];
24
+ if (present) {
25
+ try {
26
+ const text = readFileSync(paths.envFile, 'utf8');
27
+ keys = Object.keys(parseEnvFile(text)).sort();
28
+ }
29
+ catch {
30
+ keys = [];
31
+ }
32
+ }
33
+ const targets = opts.slug
34
+ ? [getAdapter(opts.slug)].filter((a) => Boolean(a))
35
+ : getAdapters();
36
+ const diagnostic = await runDiagnostic(opts.slug);
37
+ return {
38
+ generatedAt: new Date().toISOString(),
39
+ environment: {
40
+ nodeVersion: process.version,
41
+ platform: process.platform,
42
+ arch: process.arch,
43
+ affiliateMcpVersion: readPackageVersion(),
44
+ },
45
+ config: {
46
+ path: paths.envFile,
47
+ present,
48
+ keys,
49
+ },
50
+ adapters: targets.map((a) => ({
51
+ slug: a.slug,
52
+ name: a.name,
53
+ claimStatus: a.meta.claimStatus,
54
+ knownLimitations: a.meta.knownLimitations,
55
+ resilience: a.resilienceConfig,
56
+ })),
57
+ diagnostic,
58
+ };
59
+ }
60
+ export async function runDoctor(opts = {}) {
61
+ const report = await buildReport(opts);
62
+ out(JSON.stringify(report, null, 2));
63
+ // Exit code: 0 if every diagnostic result has capabilities (no error) and
64
+ // every supported op is actually supported; 1 otherwise.
65
+ const anyError = report.diagnostic.results.some((r) => r.error);
66
+ return anyError ? 1 : 0;
67
+ }
68
+ function readPackageVersion() {
69
+ // Best-effort. We don't import package.json directly because the rootDir
70
+ // is `src` and the build would not copy it into dist. Use AFFILIATE_MCP_VERSION
71
+ // if the launcher set it; otherwise "unknown".
72
+ return process.env['AFFILIATE_MCP_VERSION'] ?? 'unknown';
73
+ }
74
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * `affiliate-mcp setup` — interactive setup wizard.
3
+ *
4
+ * Per PRD §4.3, setup is part of the product, not a side activity. Every
5
+ * surface here is user-facing copy. Errors name the network, name the field,
6
+ * and surface the verbatim underlying reason. No retries hidden, no silent
7
+ * fallbacks.
8
+ *
9
+ * Flow:
10
+ * 1. Detect first-run vs existing config. First-run jumps straight into
11
+ * network selection; existing config offers setup / reset / add / quit.
12
+ * 2. Pick networks (multi-select).
13
+ * 3. For each picked network: walk `setupSteps()`, prompt per step, call
14
+ * `validateCredential` on entry where requested, run `verifyAuth()` at
15
+ * the end and merge any `derivedValues` from the underlying result.
16
+ * 4. Write `~/.affiliate-mcp/.env` (or `$AFFILIATE_MCP_CONFIG_DIR/.env`),
17
+ * mode 0600. Reset replaces; add merges.
18
+ * 5. Print the absolute path written and a pointer to `affiliate-mcp test`.
19
+ *
20
+ * Output channel: this module writes to STDOUT because the wizard is an
21
+ * interactive surface — the JSON-RPC protocol is not active during `setup`.
22
+ * The shared Pino logger continues to write to stderr only.
23
+ */
24
+ import { type Prompter } from './wizard/prompts.js';
25
+ export interface SetupOptions {
26
+ /** Override the prompter (tests). Falls back to the shared singleton. */
27
+ prompter?: Prompter;
28
+ /**
29
+ * When true, skip the interactive top-level menu and go straight into
30
+ * configuration. Used by tests and by future flags like `--add`.
31
+ */
32
+ mode?: 'auto' | 'setup' | 'reset' | 'add';
33
+ }
34
+ export declare function runSetup(opts?: SetupOptions): Promise<number>;
35
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/cli/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAsBjE,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;CAC3C;AAED,wBAAsB,QAAQ,CAAC,IAAI,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA+EvE"}
@@ -0,0 +1,254 @@
1
+ /**
2
+ * `affiliate-mcp setup` — interactive setup wizard.
3
+ *
4
+ * Per PRD §4.3, setup is part of the product, not a side activity. Every
5
+ * surface here is user-facing copy. Errors name the network, name the field,
6
+ * and surface the verbatim underlying reason. No retries hidden, no silent
7
+ * fallbacks.
8
+ *
9
+ * Flow:
10
+ * 1. Detect first-run vs existing config. First-run jumps straight into
11
+ * network selection; existing config offers setup / reset / add / quit.
12
+ * 2. Pick networks (multi-select).
13
+ * 3. For each picked network: walk `setupSteps()`, prompt per step, call
14
+ * `validateCredential` on entry where requested, run `verifyAuth()` at
15
+ * the end and merge any `derivedValues` from the underlying result.
16
+ * 4. Write `~/.affiliate-mcp/.env` (or `$AFFILIATE_MCP_CONFIG_DIR/.env`),
17
+ * mode 0600. Reset replaces; add merges.
18
+ * 5. Print the absolute path written and a pointer to `affiliate-mcp test`.
19
+ *
20
+ * Output channel: this module writes to STDOUT because the wizard is an
21
+ * interactive surface — the JSON-RPC protocol is not active during `setup`.
22
+ * The shared Pino logger continues to write to stderr only.
23
+ */
24
+ import { existsSync } from 'node:fs';
25
+ import { getAdapters } from '../shared/registry.js';
26
+ import { getPrompter } from './wizard/prompts.js';
27
+ import { resolveConfigPaths } from './wizard/paths.js';
28
+ import { filterOutKeys, mergeEnv, readEnv, writeEnv } from './wizard/envfile.js';
29
+ function out(line = '') {
30
+ process.stdout.write(line.endsWith('\n') ? line : `${line}\n`);
31
+ }
32
+ function banner() {
33
+ out('');
34
+ out(' affiliate-mcp — setup wizard');
35
+ out(' ----------------------------');
36
+ out(' This wizard collects API credentials for each affiliate network you want');
37
+ out(' to use and writes them to a single config file. Tokens are validated as');
38
+ out(' you enter them so problems surface immediately, not at first call.');
39
+ out('');
40
+ }
41
+ export async function runSetup(opts = {}) {
42
+ const prompter = opts.prompter ?? getPrompter();
43
+ const paths = resolveConfigPaths();
44
+ const hasConfig = existsSync(paths.envFile);
45
+ banner();
46
+ // Decide the top-level action.
47
+ let mode = opts.mode ?? 'auto';
48
+ if (mode === 'auto') {
49
+ if (!hasConfig) {
50
+ out(`No config file at ${paths.envFile}.`);
51
+ out('');
52
+ mode = 'setup';
53
+ }
54
+ else {
55
+ out(`Existing config at ${paths.envFile}.`);
56
+ const choice = await prompter.menu('What would you like to do?', [
57
+ { key: 'add', label: 'add — configure an additional network' },
58
+ { key: 'reset', label: 'reset — wipe and start over' },
59
+ { key: 'quit', label: 'quit — exit without changes' },
60
+ ]);
61
+ if (choice === 'quit') {
62
+ out('No changes made.');
63
+ return 0;
64
+ }
65
+ mode = choice;
66
+ }
67
+ }
68
+ const adapters = getAdapters();
69
+ if (adapters.length === 0) {
70
+ out('No network adapters are registered. This is a build problem, not a config one.');
71
+ out('Reinstall affiliate-mcp or report this at https://github.com/atolls/affiliate-mcp.');
72
+ return 1;
73
+ }
74
+ // Network picker.
75
+ const selected = await pickNetworks(prompter, adapters);
76
+ if (selected.length === 0) {
77
+ out('No networks selected. No changes made.');
78
+ return 0;
79
+ }
80
+ // Existing env — read once. Reset drops the chosen networks' keys; add keeps
81
+ // every existing entry.
82
+ let existing = readEnv(paths.envFile);
83
+ if (mode === 'reset') {
84
+ const drop = [];
85
+ for (const adapter of selected) {
86
+ for (const step of adapter.setupSteps())
87
+ drop.push(step.field);
88
+ }
89
+ existing = filterOutKeys(existing, drop);
90
+ }
91
+ // Walk each network.
92
+ const newEntries = {};
93
+ for (const adapter of selected) {
94
+ out('');
95
+ out(`Configuring ${adapter.name} (${adapter.slug})`);
96
+ out('-'.repeat(`Configuring ${adapter.name} (${adapter.slug})`.length));
97
+ if (adapter.meta.setupRequiresApproval) {
98
+ const days = adapter.meta.setupApprovalDaysTypical ?? 0;
99
+ out(`Note: ${adapter.name} requires partner approval before API access is granted.` +
100
+ (days > 0 ? ` Typical turnaround is ~${days} business days.` : ''));
101
+ }
102
+ const captured = await runNetworkSetup(prompter, adapter);
103
+ Object.assign(newEntries, captured);
104
+ }
105
+ // Merge and write.
106
+ const merged = mergeEnv(existing, newEntries);
107
+ writeEnv(paths.envFile, merged);
108
+ out('');
109
+ out(`Wrote ${paths.envFile}.`);
110
+ out('You are set up. Test with `affiliate-mcp test`.');
111
+ return 0;
112
+ }
113
+ // ---------------------------------------------------------------------------
114
+ // Network picker
115
+ // ---------------------------------------------------------------------------
116
+ async function pickNetworks(prompter, adapters) {
117
+ const choices = adapters.map((a) => {
118
+ const minutes = a.meta.setupTimeEstimateMinutes;
119
+ const approval = a.meta.setupRequiresApproval ? ', approval required' : '';
120
+ return {
121
+ key: a.slug,
122
+ label: `${a.name} — ~${minutes} min${approval}`,
123
+ };
124
+ });
125
+ const slugs = await prompter.selectMany('Which networks would you like to configure?', choices);
126
+ const set = new Set(slugs);
127
+ return adapters.filter((a) => set.has(a.slug));
128
+ }
129
+ // ---------------------------------------------------------------------------
130
+ // Per-network walk
131
+ // ---------------------------------------------------------------------------
132
+ /**
133
+ * Drive a single network adapter through its steps. Returns the captured
134
+ * field → value map. Calls `verifyAuth()` at the end and merges any
135
+ * `derivedValues` from the underlying result.
136
+ */
137
+ async function runNetworkSetup(prompter, adapter) {
138
+ const captured = {};
139
+ const steps = adapter.setupSteps();
140
+ for (const step of steps) {
141
+ const value = await runStep(prompter, adapter, step, captured);
142
+ if (value === null) {
143
+ out(`Skipped ${step.field}. You can edit it later in the config file.`);
144
+ continue;
145
+ }
146
+ captured[step.field] = value;
147
+ // Stash into process.env so the subsequent verifyAuth() picks it up.
148
+ process.env[step.field] = value;
149
+ }
150
+ // End-to-end auth verify + derived values merge.
151
+ out('');
152
+ out(`Verifying ${adapter.name} credentials…`);
153
+ try {
154
+ const result = await adapter.verifyAuth();
155
+ if (result.ok) {
156
+ const id = 'identity' in result && result.identity ? ` (${result.identity})` : '';
157
+ out(`Verified${id}.`);
158
+ // Duck-type derivedValues — the public adapter interface does not
159
+ // expose them, but the underlying auth module returns them. See the
160
+ // wizard handoff for why this is an Option B duck-type rather than an
161
+ // interface change.
162
+ const derived = result
163
+ .derivedValues;
164
+ if (derived) {
165
+ for (const [k, v] of Object.entries(derived)) {
166
+ if (typeof v !== 'string' || v === '')
167
+ continue;
168
+ if (captured[k] && captured[k] === v)
169
+ continue;
170
+ captured[k] = v;
171
+ process.env[k] = v;
172
+ out(`Derived ${k} = ${v} from your credentials (no manual entry needed).`);
173
+ }
174
+ }
175
+ }
176
+ else {
177
+ out(`${adapter.name} verifyAuth failed: ${result.reason}`);
178
+ out('Credentials saved anyway so you can edit and re-run `affiliate-mcp test`.');
179
+ }
180
+ }
181
+ catch (err) {
182
+ const msg = err instanceof Error ? err.message : String(err);
183
+ out(`${adapter.name} verifyAuth raised an error: ${msg}`);
184
+ out('Credentials saved anyway so you can edit and re-run `affiliate-mcp test`.');
185
+ }
186
+ return captured;
187
+ }
188
+ /**
189
+ * Run a single step: render description verbatim, prompt for input, call
190
+ * `validateOnEntry` if present, offer retry/edit/skip on failure.
191
+ *
192
+ * Returns the captured value, or null if the user skipped.
193
+ */
194
+ async function runStep(prompter, adapter, step, _captured) {
195
+ out('');
196
+ // Verbatim description — written by the network's adapter author.
197
+ for (const line of step.description.split('\n'))
198
+ out(line);
199
+ for (;;) {
200
+ const value = await promptForStep(prompter, step);
201
+ if (value === '') {
202
+ out(`${step.field} is empty. Skipping is allowed; you can add it later.`);
203
+ const skip = await prompter.confirm('Skip this field?');
204
+ if (skip)
205
+ return null;
206
+ continue;
207
+ }
208
+ // validateOnEntry — if defined, run it and surface the verbatim reason.
209
+ if (step.validateOnEntry) {
210
+ let result;
211
+ try {
212
+ result = await step.validateOnEntry(value);
213
+ }
214
+ catch (err) {
215
+ result = {
216
+ ok: false,
217
+ message: err instanceof Error ? err.message : String(err),
218
+ };
219
+ }
220
+ if (!result.ok) {
221
+ // PRD §4.1: name the network, name the field, surface the reason.
222
+ out(`${adapter.name} rejected ${step.field}: ${result.message ?? 'invalid value'}`);
223
+ if (result.hint)
224
+ out(`Hint: ${result.hint}`);
225
+ const next = await prompter.menu('What next?', [
226
+ { key: 'retry', label: 'retry — enter again' },
227
+ { key: 'skip', label: 'skip — leave blank for now' },
228
+ ]);
229
+ if (next === 'skip')
230
+ return null;
231
+ continue;
232
+ }
233
+ if (result.message)
234
+ out(`OK: ${result.message}`);
235
+ }
236
+ return value;
237
+ }
238
+ }
239
+ async function promptForStep(prompter, step) {
240
+ const label = step.label;
241
+ if (step.type === 'password') {
242
+ return await prompter.password(label);
243
+ }
244
+ if (step.type === 'number') {
245
+ const example = step.example;
246
+ const n = await prompter.number(label, example ? { example } : undefined);
247
+ return String(n);
248
+ }
249
+ const opts = {};
250
+ if (step.example)
251
+ opts.example = step.example;
252
+ return await prompter.text(label, opts);
253
+ }
254
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/cli/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `affiliate-mcp test [slug]` — friendly diagnostic.
3
+ *
4
+ * Drives `runDiagnostic` and prints a human-readable summary. Designed for the
5
+ * common "is it working?" question — no JSON, no stack traces, just one line
6
+ * per network plus an extra line per failing operation.
7
+ *
8
+ * Output is to stdout (user-facing CLI text on an interactive surface). Pino
9
+ * still logs to stderr.
10
+ */
11
+ import { type DiagnosticResult } from '../shared/diagnostic.js';
12
+ export interface TestOptions {
13
+ slug?: string;
14
+ }
15
+ export declare function runTest(opts?: TestOptions): Promise<number>;
16
+ /** Exposed for tests so they can assert the formatter output directly. */
17
+ export declare function formatDiagnostic(result: DiagnosticResult): string;
18
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/cli/test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAO/E,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,OAAO,CAAC,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BrE;AA6DD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAgBjE"}