@fuul/mcp-server 1.0.1 → 1.1.1

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/README.md CHANGED
@@ -1,231 +1,628 @@
1
1
  # @fuul/mcp-server
2
2
 
3
- Fuul [Model Context Protocol](https://modelcontextprotocol.io/) server: OAuth CLI (`fuul-mcp`), stdio MCP entry (`fuul-mcp-server`), metadata tools, project and affiliate analytics, incentive and payout operations (reads plus `dry_run` / `confirmed` writes), and rate-limit-aware errors.
3
+ Fuul [Model Context Protocol](https://modelcontextprotocol.io/) server for managing affiliate programs, analytics, incentives, and payouts through MCP-compatible clients (Claude Code, Cursor, Claude Desktop).
4
4
 
5
- ## Documentation
5
+ [![npm version](https://img.shields.io/npm/v/@fuul/mcp-server.svg)](https://www.npmjs.com/package/@fuul/mcp-server)
6
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org/)
6
7
 
7
- | Resource | Purpose |
8
- | -------- | ------- |
9
- | [docs/README.md](docs/README.md) | Index of all docs in this repo |
10
- | [docs/AGENTS.md](docs/AGENTS.md) | Tool ↔ HTTP map (audit, support, PR review) |
11
- | [docs/mcp-phase2/CONSUMER.md](docs/mcp-phase2/CONSUMER.md) | Staging/production URLs, API expectations |
12
- | [docs/mcp-phase2/tool-prompts.md](docs/mcp-phase2/tool-prompts.md) | Sample prompts for tooling and evals |
13
- | [CHANGELOG.md](CHANGELOG.md) | Release notes |
8
+ ---
9
+
10
+ ## Table of Contents
14
11
 
15
- ## Install (pick one path)
12
+ - [Quick Start](#quick-start)
13
+ - [Installation Methods](#installation-methods)
14
+ - [Claude Code Plugin (Recommended)](#1-claude-code-plugin-recommended)
15
+ - [Cursor IDE](#2-cursor-ide)
16
+ - [npx (Any MCP Client)](#3-npx-any-mcp-client)
17
+ - [Local Development (Clone)](#4-local-development-clone)
18
+ - [Authentication](#authentication)
19
+ - [Configuration](#configuration)
20
+ - [MCP Tool Reference](#mcp-tool-reference)
21
+ - [Troubleshooting](#troubleshooting)
22
+ - [Repository Layout](#repository-layout)
23
+ - [Scripts Reference](#scripts-reference)
24
+ - [Documentation](#documentation)
25
+ - [CI and Releases](#ci-and-releases)
26
+ - [License](#license)
16
27
 
17
- ### 1. Claude Code plugin (marketplace)
28
+ ---
18
29
 
19
- Adds the MCP server plus a **skill** that documents how to use Fuul tools.
30
+ ## Quick Start
20
31
 
21
- In **Claude Code**:
32
+ ```bash
33
+ # 1. Install (choose one method below)
34
+ # 2. Authenticate once:
35
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp login
36
+
37
+ # 3. Verify:
38
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp whoami
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Installation Methods
44
+
45
+ ### 1. Claude Code Plugin (Recommended)
46
+
47
+ The easiest way to use Fuul MCP with Claude Code. Adds the MCP server plus a **skill** that documents how to use Fuul tools.
48
+
49
+ #### Step 1: Install the plugin
22
50
 
23
51
  ```text
24
52
  /plugin marketplace add kuyen-labs/mcp_server
25
53
  /plugin install fuul-mcp@fuul-mcp
26
54
  ```
27
55
 
28
- One-time OAuth in a terminal (same tokens the MCP uses):
56
+ #### Step 2: Verify the `.mcp.json` format
57
+
58
+ Check the plugin's `.mcp.json` at:
59
+
60
+ ```
61
+ ~/.claude/plugins/cache/fuul-mcp/fuul-mcp/<version>/.mcp.json
62
+ ```
63
+
64
+ It must use the `--package=` format in `args`:
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "fuul": {
70
+ "command": "npx",
71
+ "args": ["-y", "--package=@fuul/mcp-server@latest", "fuul-mcp-server"],
72
+ "env": {
73
+ "FUUL_API_BASE_URL": "${user_config.FUUL_API_BASE_URL}"
74
+ }
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ If `args` shows `["-y", "@fuul/mcp-server@latest", "fuul-mcp-server"]` (without `--package=`), update it to match the format above.
81
+
82
+ #### Step 3: Reload the plugin
83
+
84
+ ```text
85
+ /reload-plugins
86
+ ```
87
+
88
+ #### Step 4: Authenticate (one-time)
89
+
90
+ Open a terminal and run:
29
91
 
30
92
  ```bash
31
- npx -y @fuul/mcp-server@latest fuul-mcp login
32
- npx -y @fuul/mcp-server@latest fuul-mcp whoami
93
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp login
33
94
  ```
34
95
 
35
- Optional: set **staging** in the plugin’s user settings `FUUL_API_BASE_URL` = `https://api.stg.fuul.xyz`. Default is production `https://api.fuul.xyz`.
96
+ This opens your browser for OAuth. Tokens are saved to `~/.fuul/tokens.json`.
97
+
98
+ #### Step 5: Verify
99
+
100
+ ```bash
101
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp whoami
102
+ ```
103
+
104
+ #### Optional: Use staging environment
105
+
106
+ Set `FUUL_API_BASE_URL` in the plugin's user settings:
107
+
108
+ | Environment | URL |
109
+ |-------------|-----|
110
+ | Production (default) | `https://api.fuul.xyz` |
111
+ | Staging | `https://api.stg.fuul.xyz` |
112
+
113
+ ---
114
+
115
+ ### 2. Cursor IDE
116
+
117
+ #### Option A: Using npx (no clone required)
118
+
119
+ 1. **Authenticate first:**
120
+
121
+ ```bash
122
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp login
123
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp whoami
124
+ ```
125
+
126
+ 2. **Configure MCP in Cursor:**
127
+
128
+ Go to **Settings → MCP** or edit your `mcp.json`:
36
129
 
37
- Requires **`@fuul/mcp-server@0.2.0`** or newer on npm (for the `fuul-mcp-server` binary). After the first release with this version, `npx @latest` resolves correctly.
130
+ ```json
131
+ {
132
+ "mcpServers": {
133
+ "fuul": {
134
+ "command": "npx",
135
+ "args": ["-y", "--package=@fuul/mcp-server@latest", "fuul-mcp-server"],
136
+ "env": {
137
+ "FUUL_API_BASE_URL": "https://api.fuul.xyz"
138
+ }
139
+ }
140
+ }
141
+ }
142
+ ```
38
143
 
39
- ### 2. npm / npx (any MCP client)
144
+ #### Option B: Using local clone
40
145
 
41
- Use the published package without cloning:
146
+ 1. **Clone and build:**
42
147
 
43
- | Command | Role |
44
- | ------- | ---- |
45
- | `npx -y @fuul/mcp-server@latest fuul-mcp-server` | Stdio MCP server (what clients spawn) |
46
- | `npx -y @fuul/mcp-server@latest fuul-mcp login` | Browser OAuth; writes `~/.fuul/tokens.json` |
47
- | `npx -y @fuul/mcp-server@latest fuul-mcp whoami` | `GET /api/v1/auth/user` |
148
+ ```bash
149
+ git clone https://github.com/kuyen-labs/mcp_server.git
150
+ cd mcp_server
151
+ npm ci
152
+ npm run build
153
+ ```
48
154
 
49
- Point your client at `fuul-mcp-server` with `cwd` optional; config can be passed via `env` (see **Configuration**).
155
+ 2. **Authenticate:**
50
156
 
51
- ### 3. Clone (development)
157
+ ```bash
158
+ npm run cli -- login
159
+ npm run cli -- whoami
160
+ ```
161
+
162
+ 3. **Configure MCP in Cursor:**
163
+
164
+ ```json
165
+ {
166
+ "mcpServers": {
167
+ "fuul": {
168
+ "command": "node",
169
+ "args": ["C:\\path\\to\\mcp_server\\dist\\index.js"],
170
+ "cwd": "C:\\path\\to\\mcp_server"
171
+ }
172
+ }
173
+ }
174
+ ```
175
+
176
+ On macOS/Linux:
177
+
178
+ ```json
179
+ {
180
+ "mcpServers": {
181
+ "fuul": {
182
+ "command": "node",
183
+ "args": ["/path/to/mcp_server/dist/index.js"],
184
+ "cwd": "/path/to/mcp_server"
185
+ }
186
+ }
187
+ }
188
+ ```
189
+
190
+ ---
191
+
192
+ ### 3. npx (Any MCP Client)
193
+
194
+ Use the published npm package without cloning:
195
+
196
+ | Command | Purpose |
197
+ |---------|---------|
198
+ | `npx -y --package=@fuul/mcp-server@latest fuul-mcp login` | Browser OAuth; writes `~/.fuul/tokens.json` |
199
+ | `npx -y --package=@fuul/mcp-server@latest fuul-mcp whoami` | Verify session (`GET /api/v1/auth/user`) |
200
+ | `npx -y --package=@fuul/mcp-server@latest fuul-mcp logout` | Clear tokens |
201
+ | `npx -y --package=@fuul/mcp-server@latest fuul-mcp-server` | Start stdio MCP server |
202
+
203
+ For MCP client configs (JSON), use the `--package=` format:
204
+
205
+ ```json
206
+ {
207
+ "command": "npx",
208
+ "args": ["-y", "--package=@fuul/mcp-server@latest", "fuul-mcp-server"]
209
+ }
210
+ ```
211
+
212
+ ---
213
+
214
+ ### 4. Local Development (Clone)
52
215
 
53
216
  ```bash
54
217
  git clone https://github.com/kuyen-labs/mcp_server.git
55
218
  cd mcp_server
56
219
  npm ci
57
- cp .env.example .env # optional; defaults match production Agent OAuth
220
+ cp .env.example .env # Optional: edit for staging/custom settings
58
221
  npm run build
59
222
  ```
60
223
 
61
- Run the CLI from the repo:
224
+ #### Run CLI commands:
62
225
 
63
226
  ```bash
64
227
  npm run cli -- login
65
228
  npm run cli -- whoami
229
+ npm run cli -- logout
66
230
  ```
67
231
 
68
- Run the MCP server:
232
+ #### Run MCP server:
69
233
 
70
234
  ```bash
71
- npm start
72
- # or: npm run dev
235
+ npm start # Production (uses dist/)
236
+ npm run dev # Development (uses tsx, watches src/)
73
237
  ```
74
238
 
75
- ## Configuration
239
+ #### Debug with MCP Inspector:
240
+
241
+ ```bash
242
+ npm run build
243
+ npx @modelcontextprotocol/inspector node dist/index.js
244
+ ```
76
245
 
77
- Environment variables are read from `process.env` and, when present, a **`.env` file in the current working directory** (`dotenv`). See [.env.example](.env.example).
246
+ ---
78
247
 
79
- | Variable | Purpose |
80
- | -------- | ------- |
81
- | `FUUL_API_BASE_URL` | API origin only, no trailing slash. Production: `https://api.fuul.xyz`. Staging: `https://api.stg.fuul.xyz`. |
82
- | `FUUL_OAUTH_CLIENT_ID` | OAuth client id (default `fuul-agent`). |
83
- | `FUUL_OAUTH_REDIRECT_URI` | Loopback callback (default `http://127.0.0.1:8765/callback`). |
84
- | `FUUL_MCP_TOOL_TIMEOUT_MS` | Per-tool timeout in ms (default `90000`). |
85
- | `FUUL_MCP_DEBUG` | Set to `1` or `true` for debug logging. |
248
+ ## Authentication
86
249
 
87
- **Note:** Values in `.env` are local dev convenience; they are **not** published in the npm package (`package.json` only ships `dist/`). OAuth **tokens** live in `~/.fuul/tokens.json`, not in `.env`.
250
+ Authentication uses OAuth with the Fuul dashboard. Tokens are stored locally and shared by the CLI and MCP server.
88
251
 
89
- ## MCP tool examples
252
+ ### Token location
90
253
 
91
- Clients send JSON arguments; shapes match [docs/AGENTS.md](docs/AGENTS.md). Illustrative only — use real UUIDs from your tenant.
254
+ | OS | Path |
255
+ |----|------|
256
+ | macOS/Linux | `~/.fuul/tokens.json` |
257
+ | Windows | `%USERPROFILE%\.fuul\tokens.json` |
92
258
 
93
- **Session**
259
+ ### Login flow
260
+
261
+ ```bash
262
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp login
263
+ ```
94
264
 
95
- - `ping` `{}` (no API call)
96
- - `whoami` → `{}` (requires login)
265
+ This opens your default browser to the Fuul OAuth page. After authorizing, tokens are saved automatically.
97
266
 
98
- **Metadata**
267
+ ### Verify session
99
268
 
100
- - `list_chains`, `list_trigger_types`, `list_payout_schemas` → `{}`
269
+ ```bash
270
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp whoami
271
+ ```
101
272
 
102
- **Projects**
273
+ ### Clear tokens
103
274
 
104
- - `list_projects` → `{ "page": 1, "query": "acme" }`
105
- - `get_project` `{ "project_id": "<uuid>" }`
106
- - `list_incentives` / `get_incentive` / `get_trigger` → see tool descriptions in the client
275
+ ```bash
276
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp logout
277
+ ```
107
278
 
108
- **Affiliate analytics**
279
+ ---
109
280
 
110
- - `get_affiliate_portal_stats` → `project_id`, `user_identifier` (e.g. `evm:0x...`)
111
- - `get_project_affiliate_total_stats` → `project_id`, optional `dateRange`, filters
112
- - `get_project_affiliates_breakdown` → `project_id`, **`groupBy`** (`audience` \| `tier` \| `region` \| `status`)
281
+ ## Configuration
113
282
 
114
- **Writes (two steps: `dry_run: true` then `confirmed: true`)**
283
+ Environment variables are read from `process.env` and, when present, a `.env` file in the current working directory.
115
284
 
116
- - `create_incentive_program`, `update_incentive_program`, `approve_payouts`, `reject_payouts`
285
+ | Variable | Default | Description |
286
+ |----------|---------|-------------|
287
+ | `FUUL_API_BASE_URL` | `https://api.fuul.xyz` | API origin (no trailing slash). Use `https://api.stg.fuul.xyz` for staging. |
288
+ | `FUUL_OAUTH_CLIENT_ID` | `fuul-agent` | OAuth client ID |
289
+ | `FUUL_OAUTH_REDIRECT_URI` | `http://127.0.0.1:8765/callback` | OAuth callback URL |
290
+ | `FUUL_MCP_TOOL_TIMEOUT_MS` | `90000` | Per-tool timeout in milliseconds |
291
+ | `FUUL_MCP_DEBUG` | `false` | Set to `1` or `true` for debug logging |
117
292
 
118
- ## Run and debug
293
+ ### Example `.env` file
119
294
 
120
295
  ```bash
121
- npm run build && npm start
296
+ FUUL_API_BASE_URL=https://api.stg.fuul.xyz
297
+ FUUL_MCP_DEBUG=1
122
298
  ```
123
299
 
124
- MCP Inspector:
300
+ > **Note:** The `.env` file is for local development only and is not included in the npm package. Tokens are stored in `~/.fuul/tokens.json`, not in `.env`.
125
301
 
126
- ```bash
127
- npm run build
128
- npx @modelcontextprotocol/inspector node dist/index.js
302
+ ---
303
+
304
+ ## MCP Tool Reference
305
+
306
+ ### Tool Categories
307
+
308
+ | Category | Tools |
309
+ |----------|-------|
310
+ | **Health** | `ping`, `whoami` |
311
+ | **Metadata** (cached) | `list_chains`, `list_trigger_types`, `list_payout_schemas` |
312
+ | **Projects** | `list_projects`, `get_project` |
313
+ | **Incentives** | `list_incentives`, `get_incentive`, `get_trigger` |
314
+ | **Affiliate Analytics** | `get_affiliate_portal_stats`, `get_project_affiliate_total_stats`, `get_project_affiliates_breakdown` |
315
+ | **Payouts (Read)** | `list_payouts_pending_approval`, `list_rewards_payouts` |
316
+ | **Payouts (Write)** | `approve_payouts`, `reject_payouts` |
317
+ | **Tiers** | `update_project_tier` |
318
+ | **Audiences** | `update_audience` |
319
+ | **Triggers** | `update_trigger` |
320
+ | **Payout Terms** | `update_payout_term` |
321
+
322
+ ### Tool Examples
323
+
324
+ All tools receive JSON arguments. Use real UUIDs from your tenant.
325
+
326
+ #### Health checks
327
+
328
+ ```json
329
+ // ping (no auth required)
330
+ {}
331
+
332
+ // whoami (requires login)
333
+ {}
334
+ ```
335
+
336
+ #### Metadata queries
337
+
338
+ ```json
339
+ // list_chains, list_trigger_types, list_payout_schemas
340
+ {}
129
341
  ```
130
342
 
131
- ## Client setup
343
+ #### Project operations
132
344
 
133
- ### Cursor
345
+ ```json
346
+ // list_projects
347
+ { "page": 1, "query": "acme" }
134
348
 
135
- 1. Complete **Clone** or use **npx** so `dist/index.js` or `fuul-mcp-server` exists; run **`fuul-mcp login`** once.
136
- 2. **Settings → MCP** (or user `mcp.json`): spawn stdio with `command` + `args`, and set **`cwd`** to a folder that contains `.env` if you use one.
349
+ // get_project
350
+ { "project_id": "550e8400-e29b-41d4-a716-446655440000" }
351
+ ```
137
352
 
138
- Example:
353
+ #### Incentives
139
354
 
140
355
  ```json
356
+ // list_incentives
357
+ { "project_id": "<uuid>" }
358
+
359
+ // get_incentive
360
+ { "project_id": "<uuid>", "conversion_id": "<uuid>" }
361
+
362
+ // get_trigger
363
+ { "project_id": "<uuid>", "trigger_id": "<uuid>" }
364
+ ```
365
+
366
+ #### Affiliate analytics
367
+
368
+ ```json
369
+ // get_affiliate_portal_stats (single affiliate)
141
370
  {
142
- "mcpServers": {
143
- "fuul": {
144
- "command": "node",
145
- "args": ["C:\\path\\to\\mcp_server\\dist\\index.js"],
146
- "cwd": "C:\\path\\to\\mcp_server"
147
- }
148
- }
371
+ "project_id": "<uuid>",
372
+ "user_identifier": "evm:0x1234..."
373
+ }
374
+
375
+ // get_project_affiliate_total_stats (project totals)
376
+ {
377
+ "project_id": "<uuid>",
378
+ "dateRange": "30d"
149
379
  }
380
+
381
+ // get_project_affiliates_breakdown (grouped breakdown)
382
+ {
383
+ "project_id": "<uuid>",
384
+ "groupBy": "region",
385
+ "dateRange": "30d"
386
+ }
387
+ ```
388
+
389
+ `groupBy` options: `audience`, `tier`, `region`, `status`
390
+
391
+ `dateRange` options: `7d`, `30d`, `90d`, `MTD`, `QTD`, `custom`, `all`
392
+
393
+ #### Payout operations
394
+
395
+ ```json
396
+ // list_payouts_pending_approval
397
+ { "project_id": "<uuid>", "page": 1, "page_size": 50 }
398
+
399
+ // list_rewards_payouts
400
+ { "project_id": "<uuid>", "page": 1 }
150
401
  ```
151
402
 
152
- Or with npx:
403
+ ### Write Operations (Two-Step Flow)
404
+
405
+ All mutation tools require a **two-step process**:
406
+
407
+ 1. **Preview:** Call with `dry_run: true` — validates and returns a preview without making changes
408
+ 2. **Confirm:** Call with `confirmed: true` — executes the mutation
409
+
410
+ #### Example: Approve payouts
153
411
 
154
412
  ```json
413
+ // Step 1: Preview
155
414
  {
156
- "mcpServers": {
157
- "fuul": {
158
- "command": "npx",
159
- "args": ["-y", "@fuul/mcp-server@latest", "fuul-mcp-server"],
160
- "env": {
161
- "FUUL_API_BASE_URL": "https://api.fuul.xyz"
162
- }
163
- }
164
- }
415
+ "project_id": "<uuid>",
416
+ "payout_ids": ["<uuid1>", "<uuid2>"],
417
+ "dry_run": true
418
+ }
419
+
420
+ // Step 2: Confirm (after user approval)
421
+ {
422
+ "project_id": "<uuid>",
423
+ "payout_ids": ["<uuid1>", "<uuid2>"],
424
+ "confirmed": true
165
425
  }
166
426
  ```
167
427
 
168
- ### Claude Desktop
428
+ Write tools: `approve_payouts`, `reject_payouts`, `update_project_tier`, `update_audience`, `update_trigger`, `update_payout_term`
169
429
 
170
- Use the same `mcpServers` idea in the app’s developer config. See [Anthropic MCP docs](https://docs.anthropic.com/en/docs/mcp).
430
+ ---
171
431
 
172
- ### Claude Code (manual MCP, without the plugin)
432
+ ## Troubleshooting
173
433
 
174
- Configure stdio per your Claude Code version: `node` + path to `dist/index.js`, or `npx` + `fuul-mcp-server` as above.
434
+ ### MCP server fails to start
175
435
 
176
- ## Repository layout
436
+ **Symptom:** Error like `Cannot find package '@fuul/mcp-server'` or binary not found.
177
437
 
178
- ```text
438
+ **Solution:** Ensure you use the `--package=` format in args:
439
+
440
+ ```json
441
+ {
442
+ "args": ["-y", "--package=@fuul/mcp-server@latest", "fuul-mcp-server"]
443
+ }
444
+ ```
445
+
446
+ **Wrong:**
447
+ ```json
448
+ {
449
+ "args": ["-y", "@fuul/mcp-server@latest", "fuul-mcp-server"]
450
+ }
451
+ ```
452
+
453
+ ### 401 Unauthorized errors
454
+
455
+ **Symptom:** API tools return 401 or `whoami` fails.
456
+
457
+ **Solution:**
458
+
459
+ 1. Run login again:
460
+ ```bash
461
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp login
462
+ ```
463
+
464
+ 2. Verify tokens exist:
465
+ - macOS/Linux: `~/.fuul/tokens.json`
466
+ - Windows: `%USERPROFILE%\.fuul\tokens.json`
467
+
468
+ 3. Verify session:
469
+ ```bash
470
+ npx -y --package=@fuul/mcp-server@latest fuul-mcp whoami
471
+ ```
472
+
473
+ ### Rate limiting (HTTP 429)
474
+
475
+ **Symptom:** Tools return 429 errors.
476
+
477
+ **Solution:** Wait for the `Retry-After` header duration, then retry. The MCP server handles this automatically in most cases.
478
+
479
+ ### Environment not loading
480
+
481
+ **Symptom:** Staging URL not being used despite `.env` file.
482
+
483
+ **Solution:**
484
+
485
+ 1. Ensure `cwd` in your MCP config points to the directory containing `.env`
486
+ 2. Or pass environment directly in the config:
487
+ ```json
488
+ {
489
+ "env": {
490
+ "FUUL_API_BASE_URL": "https://api.stg.fuul.xyz"
491
+ }
492
+ }
493
+ ```
494
+
495
+ ### Windows path issues
496
+
497
+ **Symptom:** Paths not resolving correctly on Windows.
498
+
499
+ **Solution:** Use double backslashes or forward slashes:
500
+
501
+ ```json
502
+ {
503
+ "args": ["C:\\Users\\me\\mcp_server\\dist\\index.js"]
504
+ }
505
+ ```
506
+
507
+ Or:
508
+
509
+ ```json
510
+ {
511
+ "args": ["C:/Users/me/mcp_server/dist/index.js"]
512
+ }
513
+ ```
514
+
515
+ ---
516
+
517
+ ## Repository Layout
518
+
519
+ ```
179
520
  mcp_server/
180
521
  ├── .claude-plugin/ # Claude Code marketplace manifest
181
522
  │ └── marketplace.json
523
+ ├── .github/
524
+ │ ├── workflows/ # CI and release workflows
525
+ │ │ ├── ci.yml
526
+ │ │ └── release.yml
527
+ │ └── pull_request_template.md
528
+ ├── docs/ # Documentation
529
+ │ ├── README.md # Docs index
530
+ │ ├── AGENTS.md # Tool ↔ HTTP mapping
531
+ │ └── mcp-phase2/
532
+ │ ├── CONSUMER.md # API expectations
533
+ │ └── tool-prompts.md # Sample prompts for evals
182
534
  ├── plugins/
183
- │ └── fuul-mcp/ # Plugin: MCP config + skill
535
+ │ └── fuul-mcp/ # Claude Code plugin
184
536
  │ ├── .claude-plugin/
185
537
  │ │ └── plugin.json
186
- │ ├── .mcp.json
187
- │ └── skills/fuul/SKILL.md
538
+ │ ├── .mcp.json # MCP server config
539
+ │ └── skills/
540
+ │ └── fuul/
541
+ │ └── SKILL.md # Tool usage instructions
188
542
  ├── src/ # TypeScript source
189
- ├── docs/ # Maintainer and integrator docs
190
- ├── .github/workflows/ # ci.yml, release.yml (semantic-release; name must match npm Trusted Publishing)
191
- ├── release.config.cjs # semantic-release plugins and branches
192
- └── dist/ # `npm run build` (gitignored)
543
+ ├── affiliate-portal/ # Affiliate analytics
544
+ ├── agent/ # Write confirmation logic
545
+ ├── auth/ # OAuth and tokens
546
+ │ ├── config/ # Environment config
547
+ │ ├── http/ # HTTP client
548
+ │ ├── metadata/ # Chains, triggers, schemas
549
+ │ ├── payouts/ # Payout operations
550
+ │ ├── tools/ # MCP tool definitions
551
+ │ ├── triggers/ # Trigger operations
552
+ │ ├── util/ # Utilities
553
+ │ ├── cli.ts # CLI entry point
554
+ │ └── index.ts # MCP server entry point
555
+ ├── dist/ # Compiled output (gitignored)
556
+ ├── .env.example # Environment template
557
+ ├── CHANGELOG.md # Release notes
558
+ ├── package.json
559
+ ├── release.config.cjs # semantic-release config
560
+ ├── tsconfig.json
561
+ └── vitest.config.ts
193
562
  ```
194
563
 
195
- ## Requirements
564
+ ---
196
565
 
197
- - **Node.js** 18+
198
- - A running **fuul-server** (staging or production) with **Agent OAuth** configured
566
+ ## Scripts Reference
199
567
 
200
- ## CI and releases
568
+ | Script | Description |
569
+ |--------|-------------|
570
+ | `npm run build` | Compile TypeScript → `dist/` |
571
+ | `npm start` | Run MCP server (`node dist/index.js`) |
572
+ | `npm run dev` | Run MCP server with hot reload (`tsx src/index.ts`) |
573
+ | `npm run cli` | Run OAuth CLI (`tsx src/cli.ts`) |
574
+ | `npm run lint` | ESLint on `src/` |
575
+ | `npm run lint:fix` | Auto-fix lint issues |
576
+ | `npm run test` | Run tests with Vitest |
577
+ | `npm run test:ci` | Run tests in CI mode |
578
+ | `npm run format` | Format code with Prettier |
201
579
 
202
- On each push/PR to `main` / `master`, GitHub Actions runs **lint**, **test**, and **build** in parallel (see [.github/workflows/ci.yml](.github/workflows/ci.yml)). Pushes to `beta` / `alpha` also run CI on those branches.
580
+ ---
203
581
 
204
- ## Publishing
582
+ ## Documentation
205
583
 
206
- **npm** releases are performed by **semantic-release** in GitHub Actions (same approach as [fuul-sdk](https://github.com/kuyen-labs/fuul-sdk)). You do not need to create a GitHub Release manually or run `npm publish` locally for the default flow.
584
+ | Resource | Description |
585
+ |----------|-------------|
586
+ | [docs/README.md](docs/README.md) | Documentation index |
587
+ | [docs/AGENTS.md](docs/AGENTS.md) | Tool ↔ HTTP endpoint mapping |
588
+ | [docs/mcp-phase2/CONSUMER.md](docs/mcp-phase2/CONSUMER.md) | Staging/production URLs, API expectations |
589
+ | [docs/mcp-phase2/tool-prompts.md](docs/mcp-phase2/tool-prompts.md) | Sample prompts for testing and evals |
590
+ | [CHANGELOG.md](CHANGELOG.md) | Release notes |
207
591
 
208
- 1. **npm — [Trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC):** [.github/workflows/release.yml](.github/workflows/release.yml) uses the same **steps and permissions** as [fuul-sdk](https://github.com/kuyen-labs/fuul-sdk)’s release job (`id-token: write`, no `NPM_TOKEN` in the workflow). The **filename** is **`release.yml`** here so it matches what you enter in npm’s trusted-publisher form (fuul-sdk uses **`versioning.yml`** instead — that name is only for that repo). On npmjs.com, **`@fuul/mcp-server`** must list workflow **`.github/workflows/release.yml`** for **`kuyen-labs` / `mcp_server`**. If npm still shows **`OIDC … 404`**, the path/org/repo in npm does not match this file.
209
- **About `NPM_TOKEN` in caps:** npm docs use that name for **classic token** auth. With **Trusted Publishing** you do **not** put a token value into npm for OIDC; GitHub provides the identity. You also do **not** need a GitHub secret named `NPM_TOKEN` for this flow. (If the npm UI showed `NPM_TOKEN`, it is usually help text for the non-OIDC case.)
210
- 2. **Branches**: on **push** to `main`, `beta`, or `alpha`, that workflow runs `npm ci`, **build**, **`npm run test:ci`**, then `npx semantic-release` on push only.
211
- 3. **Config**: [release.config.cjs](release.config.cjs) matches fuul-sdk’s plugin list and order; `@semantic-release/exec` uses the same **`verifyReleaseCmd`** writing `src/release.json` (placeholder [src/release.json](src/release.json)); `@semantic-release/git` commits **`package.json`** only.
212
- 4. **Commits**: use [Conventional Commits](https://www.conventionalcommits.org/) on releasable branches (e.g. `feat:`, `fix:`, `BREAKING CHANGE:`) so the next version is computed; if nothing warrants a release, the job exits without publishing (expected).
592
+ ---
213
593
 
214
- Local dry run of the same CLI: `npm run semantic-release` (needs a clean git state, tags, and env vars; in practice CI after merge is enough).
594
+ ## CI and Releases
215
595
 
216
- ## Scripts
596
+ ### Continuous Integration
217
597
 
218
- | Script | Description |
219
- | ------ | ----------- |
220
- | `npm run build` | Compile TypeScript → `dist/` |
221
- | `npm start` | Run MCP server (`node dist/index.js`) |
222
- | `npm run cli` | OAuth CLI via `tsx` (`src/cli.ts`) |
223
- | `npm run dev` | MCP via `tsx` (`src/index.ts`) |
224
- | `npm run lint` | ESLint on `src/` |
225
- | `npm run test` | Vitest |
226
- | `npm run test:ci` | Vitest (same as `test`; used by `release.yml` like fuul-sdk’s `test:ci` in `versioning.yml`) |
227
- | `npm run semantic-release` | Run semantic-release locally (CI runs `npx semantic-release` on eligible pushes) |
598
+ On each push/PR to `main`, `master`, `beta`, or `alpha`, GitHub Actions runs:
599
+ - **lint** ESLint checks
600
+ - **test** Vitest test suite
601
+ - **build** TypeScript compilation
602
+
603
+ ### Publishing
604
+
605
+ Releases are automated via **semantic-release** and **npm Trusted Publishing (OIDC)**:
606
+
607
+ 1. Use [Conventional Commits](https://www.conventionalcommits.org/): `feat:`, `fix:`, `BREAKING CHANGE:`
608
+ 2. Merge to `main` (or `beta`/`alpha` for pre-releases)
609
+ 3. GitHub Actions runs `semantic-release`, which:
610
+ - Determines the next version from commits
611
+ - Updates `package.json` and `CHANGELOG.md`
612
+ - Publishes to npm
613
+ - Creates a GitHub release
614
+
615
+ No manual `npm publish` or GitHub Release creation needed.
616
+
617
+ ---
618
+
619
+ ## Requirements
620
+
621
+ - **Node.js** 18 or higher
622
+ - A running **fuul-server** (staging or production) with **Agent OAuth** configured
623
+
624
+ ---
228
625
 
229
626
  ## License
230
627
 
231
- MIT — see `package.json`.
628
+ MIT — see [package.json](package.json)
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export declare const PING_DESCRIPTION = "Health check: returns \"pong\" if the MCP process is running. No API calls. Example: invoke with empty input {}.";
5
5
  export declare const WHOAMI_DESCRIPTION = "Returns the current Fuul dashboard user as JSON from GET /api/v1/auth/user. Requires prior CLI login (tokens in ~/.fuul/tokens.json). Example: {} after `npm run cli -- login`.";
6
- export declare const LIST_CHAINS_DESCRIPTION = "Lists supported blockchain chains from GET /public-api/v1/metadata/chains. Uses server metadata (not a hardcoded catalog); responses are cached with ETag/Cache-Control. Params: none (pass {}). Pagination: not exposed by this tool until the API adds cursor/limit.";
6
+ export declare const LIST_CHAINS_DESCRIPTION = "Lists supported blockchain chains from GET /public-api/v1/metadata/chains. Uses server metadata (not a hardcoded catalog); responses are cached with ETag/Cache-Control. Each chain includes snake_case fields such as chain_id, is_testnet, optional svm_network and webapp_capabilities, and can_be_used_for_payouts (boolean: true where Fuul reward/payout infra is deployed). Params: none (pass {}). Pagination: not exposed by this tool until the API adds cursor/limit.";
7
7
  export declare const LIST_TRIGGER_TYPES_DESCRIPTION = "Lists trigger type metadata from GET /public-api/v1/metadata/trigger-types (cached). Use ids from this response when building programs/triggers. Params: {}.";
8
8
  export declare const LIST_PAYOUT_SCHEMAS_DESCRIPTION = "Lists payout schema metadata from GET /public-api/v1/metadata/payout-schemas (cached). Params: {}.";
9
9
  export declare const LIST_PROJECTS_DESCRIPTION = "Lists dashboard projects for the current user: GET /api/v1/projects with optional ?page= (1-based) and ?query=. Example: {\"page\":1} or {\"query\":\"acme\"}.";
@@ -1 +1 @@
1
- {"version":3,"file":"tool-descriptions.d.ts","sourceRoot":"","sources":["../../src/tools/tool-descriptions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,gBAAgB,qHAAmH,CAAC;AAEjJ,eAAO,MAAM,kBAAkB,oLACoJ,CAAC;AAEpL,eAAO,MAAM,uBAAuB,2QACsO,CAAC;AAE3Q,eAAO,MAAM,8BAA8B,iKACqH,CAAC;AAEjK,eAAO,MAAM,+BAA+B,uGAAuG,CAAC;AAEpJ,eAAO,MAAM,yBAAyB,mKACsH,CAAC;AAE7J,eAAO,MAAM,uBAAuB,4HACmF,CAAC;AAExH,eAAO,MAAM,2BAA2B,0IAC6F,CAAC;AAEtI,eAAO,MAAM,yBAAyB,qJACsG,CAAC;AAE7I,eAAO,MAAM,uBAAuB,2LAC8I,CAAC;AAEnL,eAAO,MAAM,8BAA8B,QAGwF,CAAC;AAEpI,eAAO,MAAM,+BAA+B,QAEyF,CAAC;AAEtI,eAAO,MAAM,2BAA2B,QAEgF,CAAC;AAEzH,eAAO,MAAM,0BAA0B,QAEgE,CAAC;AAExG,eAAO,MAAM,yCAAyC,0LAC2H,CAAC;AAElL,eAAO,MAAM,gCAAgC,mMAC+I,CAAC;AAE7L,eAAO,MAAM,2BAA2B,oQACiN,CAAC;AAE1P,eAAO,MAAM,0BAA0B,2GAA2G,CAAC;AAInJ,eAAO,MAAM,sCAAsC,QAIlC,CAAC;AAElB,eAAO,MAAM,6CAA6C,QAIzC,CAAC;AAElB,eAAO,MAAM,4CAA4C,QAIxC,CAAC"}
1
+ {"version":3,"file":"tool-descriptions.d.ts","sourceRoot":"","sources":["../../src/tools/tool-descriptions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,gBAAgB,qHAAmH,CAAC;AAEjJ,eAAO,MAAM,kBAAkB,oLACoJ,CAAC;AAEpL,eAAO,MAAM,uBAAuB,qdACgb,CAAC;AAGrd,eAAO,MAAM,8BAA8B,iKACqH,CAAC;AAEjK,eAAO,MAAM,+BAA+B,uGAAuG,CAAC;AAEpJ,eAAO,MAAM,yBAAyB,mKACsH,CAAC;AAE7J,eAAO,MAAM,uBAAuB,4HACmF,CAAC;AAExH,eAAO,MAAM,2BAA2B,0IAC6F,CAAC;AAEtI,eAAO,MAAM,yBAAyB,qJACsG,CAAC;AAE7I,eAAO,MAAM,uBAAuB,2LAC8I,CAAC;AAEnL,eAAO,MAAM,8BAA8B,QAGwF,CAAC;AAEpI,eAAO,MAAM,+BAA+B,QAEyF,CAAC;AAEtI,eAAO,MAAM,2BAA2B,QAEgF,CAAC;AAEzH,eAAO,MAAM,0BAA0B,QAEgE,CAAC;AAExG,eAAO,MAAM,yCAAyC,0LAC2H,CAAC;AAElL,eAAO,MAAM,gCAAgC,mMAC+I,CAAC;AAE7L,eAAO,MAAM,2BAA2B,oQACiN,CAAC;AAE1P,eAAO,MAAM,0BAA0B,2GAA2G,CAAC;AAInJ,eAAO,MAAM,sCAAsC,QAIlC,CAAC;AAElB,eAAO,MAAM,6CAA6C,QAIzC,CAAC;AAElB,eAAO,MAAM,4CAA4C,QAIxC,CAAC"}
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const PING_DESCRIPTION = 'Health check: returns "pong" if the MCP process is running. No API calls. Example: invoke with empty input {}.';
5
5
  export const WHOAMI_DESCRIPTION = 'Returns the current Fuul dashboard user as JSON from GET /api/v1/auth/user. Requires prior CLI login (tokens in ~/.fuul/tokens.json). Example: {} after `npm run cli -- login`.';
6
- export const LIST_CHAINS_DESCRIPTION = 'Lists supported blockchain chains from GET /public-api/v1/metadata/chains. Uses server metadata (not a hardcoded catalog); responses are cached with ETag/Cache-Control. Params: none (pass {}). Pagination: not exposed by this tool until the API adds cursor/limit.';
6
+ export const LIST_CHAINS_DESCRIPTION = 'Lists supported blockchain chains from GET /public-api/v1/metadata/chains. Uses server metadata (not a hardcoded catalog); responses are cached with ETag/Cache-Control. Each chain includes snake_case fields such as chain_id, is_testnet, optional svm_network and webapp_capabilities, and can_be_used_for_payouts (boolean: true where Fuul reward/payout infra is deployed). Params: none (pass {}). Pagination: not exposed by this tool until the API adds cursor/limit.';
7
7
  export const LIST_TRIGGER_TYPES_DESCRIPTION = 'Lists trigger type metadata from GET /public-api/v1/metadata/trigger-types (cached). Use ids from this response when building programs/triggers. Params: {}.';
8
8
  export const LIST_PAYOUT_SCHEMAS_DESCRIPTION = 'Lists payout schema metadata from GET /public-api/v1/metadata/payout-schemas (cached). Params: {}.';
9
9
  export const LIST_PROJECTS_DESCRIPTION = 'Lists dashboard projects for the current user: GET /api/v1/projects with optional ?page= (1-based) and ?query=. Example: {"page":1} or {"query":"acme"}.';
@@ -1 +1 @@
1
- {"version":3,"file":"tool-descriptions.js","sourceRoot":"","sources":["../../src/tools/tool-descriptions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,gHAAgH,CAAC;AAEjJ,MAAM,CAAC,MAAM,kBAAkB,GAC7B,iLAAiL,CAAC;AAEpL,MAAM,CAAC,MAAM,uBAAuB,GAClC,wQAAwQ,CAAC;AAE3Q,MAAM,CAAC,MAAM,8BAA8B,GACzC,8JAA8J,CAAC;AAEjK,MAAM,CAAC,MAAM,+BAA+B,GAAG,oGAAoG,CAAC;AAEpJ,MAAM,CAAC,MAAM,yBAAyB,GACpC,0JAA0J,CAAC;AAE7J,MAAM,CAAC,MAAM,uBAAuB,GAClC,qHAAqH,CAAC;AAExH,MAAM,CAAC,MAAM,2BAA2B,GACtC,mIAAmI,CAAC;AAEtI,MAAM,CAAC,MAAM,yBAAyB,GACpC,0IAA0I,CAAC;AAE7I,MAAM,CAAC,MAAM,uBAAuB,GAClC,gLAAgL,CAAC;AAEnL,MAAM,CAAC,MAAM,8BAA8B,GACzC,yIAAyI;IACzI,kIAAkI;IAClI,iIAAiI,CAAC;AAEpI,MAAM,CAAC,MAAM,+BAA+B,GAC1C,mKAAmK;IACnK,mIAAmI,CAAC;AAEtI,MAAM,CAAC,MAAM,2BAA2B,GACtC,sRAAsR;IACtR,sHAAsH,CAAC;AAEzH,MAAM,CAAC,MAAM,0BAA0B,GACrC,2NAA2N;IAC3N,qGAAqG,CAAC;AAExG,MAAM,CAAC,MAAM,yCAAyC,GACpD,+KAA+K,CAAC;AAElL,MAAM,CAAC,MAAM,gCAAgC,GAC3C,0LAA0L,CAAC;AAE7L,MAAM,CAAC,MAAM,2BAA2B,GACtC,uPAAuP,CAAC;AAE1P,MAAM,CAAC,MAAM,0BAA0B,GAAG,wGAAwG,CAAC;AAEnJ,MAAM,eAAe,GAAG,sFAAsF,CAAC;AAE/G,MAAM,CAAC,MAAM,sCAAsC,GACjD,2GAA2G;IAC3G,kHAAkH;IAClH,iEAAiE;IACjE,eAAe,CAAC;AAElB,MAAM,CAAC,MAAM,6CAA6C,GACxD,0GAA0G;IAC1G,yHAAyH;IACzH,gFAAgF;IAChF,eAAe,CAAC;AAElB,MAAM,CAAC,MAAM,4CAA4C,GACvD,+IAA+I;IAC/I,4HAA4H;IAC5H,wEAAwE;IACxE,eAAe,CAAC"}
1
+ {"version":3,"file":"tool-descriptions.js","sourceRoot":"","sources":["../../src/tools/tool-descriptions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,gHAAgH,CAAC;AAEjJ,MAAM,CAAC,MAAM,kBAAkB,GAC7B,iLAAiL,CAAC;AAEpL,MAAM,CAAC,MAAM,uBAAuB,GAClC,kdAAkd,CAAC;AAGrd,MAAM,CAAC,MAAM,8BAA8B,GACzC,8JAA8J,CAAC;AAEjK,MAAM,CAAC,MAAM,+BAA+B,GAAG,oGAAoG,CAAC;AAEpJ,MAAM,CAAC,MAAM,yBAAyB,GACpC,0JAA0J,CAAC;AAE7J,MAAM,CAAC,MAAM,uBAAuB,GAClC,qHAAqH,CAAC;AAExH,MAAM,CAAC,MAAM,2BAA2B,GACtC,mIAAmI,CAAC;AAEtI,MAAM,CAAC,MAAM,yBAAyB,GACpC,0IAA0I,CAAC;AAE7I,MAAM,CAAC,MAAM,uBAAuB,GAClC,gLAAgL,CAAC;AAEnL,MAAM,CAAC,MAAM,8BAA8B,GACzC,yIAAyI;IACzI,kIAAkI;IAClI,iIAAiI,CAAC;AAEpI,MAAM,CAAC,MAAM,+BAA+B,GAC1C,mKAAmK;IACnK,mIAAmI,CAAC;AAEtI,MAAM,CAAC,MAAM,2BAA2B,GACtC,sRAAsR;IACtR,sHAAsH,CAAC;AAEzH,MAAM,CAAC,MAAM,0BAA0B,GACrC,2NAA2N;IAC3N,qGAAqG,CAAC;AAExG,MAAM,CAAC,MAAM,yCAAyC,GACpD,+KAA+K,CAAC;AAElL,MAAM,CAAC,MAAM,gCAAgC,GAC3C,0LAA0L,CAAC;AAE7L,MAAM,CAAC,MAAM,2BAA2B,GACtC,uPAAuP,CAAC;AAE1P,MAAM,CAAC,MAAM,0BAA0B,GAAG,wGAAwG,CAAC;AAEnJ,MAAM,eAAe,GAAG,sFAAsF,CAAC;AAE/G,MAAM,CAAC,MAAM,sCAAsC,GACjD,2GAA2G;IAC3G,kHAAkH;IAClH,iEAAiE;IACjE,eAAe,CAAC;AAElB,MAAM,CAAC,MAAM,6CAA6C,GACxD,0GAA0G;IAC1G,yHAAyH;IACzH,gFAAgF;IAChF,eAAe,CAAC;AAElB,MAAM,CAAC,MAAM,4CAA4C,GACvD,+IAA+I;IAC/I,4HAA4H;IAC5H,wEAAwE;IACxE,eAAe,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuul/mcp-server",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "description": "Fuul MCP server for program management via MCP-compatible clients",
5
5
  "keywords": [
6
6
  "Fuul",