tokens-for-good 0.2.5 → 0.2.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokens-for-good",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "type": "module",
5
5
  "description": "Donate your spare AI tokens to research nonprofits for Fierce Philanthropy",
6
6
  "bin": {
@@ -146,7 +146,7 @@ Inline citations as `[Source Name](URL)`. Distinguish attribution: "X reports th
146
146
 
147
147
  ### 3. Submit the Report
148
148
 
149
- Submit using the `submit_report` tool with the full markdown as `report_markdown`.
149
+ Submit using the `submit_report` tool with the full markdown as `report_markdown`. Include `estimated_tokens`: count your web searches (~1K each), web fetches (~2-5K each), your report output (~4 tokens per word), plus ~10K for system/tool overhead.
150
150
 
151
151
  ## Quality Checks
152
152
  - [ ] All 5 prompt tables present and complete (20 rows each)
@@ -3,8 +3,8 @@
3
3
  ## Inputs
4
4
 
5
5
  - **Org name:** `{{ORG_NAME}}`
6
- - **Research report:** Read from `{{ORG_SLUG}}_Research_Report.md`
7
- - **Research guidance:** Read from `site/research-guidance.md`
6
+ - **Research report:** The report from Step 1 (kept in memory from the previous step)
7
+ - **Research guidance:** The same methodology from Step 1
8
8
 
9
9
  ## Purpose
10
10
 
@@ -65,12 +65,11 @@ For each HIGH or MEDIUM issue, write the exact correction:
65
65
  **Corrected:** [Fixed text]
66
66
  ```
67
67
 
68
- ### 6. Apply Corrections and Write Output
68
+ ### 6. Apply Corrections and Produce Output
69
69
 
70
- Apply all corrections to produce a verified version of the report. Write to:
71
- `{{ORG_SLUG}}_02_Verified.md`
70
+ Apply all corrections to produce a verified version of the report. Keep the result in memory for the next pipeline step (Humanize).
72
71
 
73
- Start the file with a verification log:
72
+ Start the output with a verification log:
74
73
 
75
74
  ```markdown
76
75
  <!-- Verified: {{ORG_NAME}} | Date: [date] -->
@@ -3,8 +3,8 @@
3
3
  ## Inputs
4
4
 
5
5
  - **Org name:** `{{ORG_NAME}}`
6
- - **Verified report:** Read from `{{ORG_SLUG}}_02_Verified.md`
7
- - **Writing style guide:** Read from `site/writing-style-guide.md`
6
+ - **Verified report:** The verified report from Step 2 (kept in memory from the previous step)
7
+ - **Writing style guide:** The AI decontamination rules below
8
8
 
9
9
  ## Purpose
10
10
 
@@ -16,7 +16,7 @@ Step 2 verified the facts. This step makes the report sound human. You are an ed
16
16
 
17
17
  Read the verified report (skip the verification log header, work on the content below the `---`).
18
18
 
19
- Read the writing style guide. The "AI Decontamination Rules" section is your checklist.
19
+ The AI decontamination passes below are your checklist.
20
20
 
21
21
  ### 2. Run Each Pass
22
22
 
@@ -97,11 +97,11 @@ After all passes, verify you did NOT change:
97
97
  - [ ] The SOURCES section
98
98
  - [ ] Section separators (`---`)
99
99
 
100
- ### 4. Write Output
100
+ ### 4. Produce Output
101
101
 
102
- Write to: `{{ORG_SLUG}}_03_Humanized.md`
102
+ Keep the humanized report in memory. This is the final version that will be submitted via the `submit_report` tool.
103
103
 
104
- Start with a change log:
104
+ Start the output with a change log:
105
105
 
106
106
  ```markdown
107
107
  <!-- Humanized: {{ORG_NAME}} | Date: [date] -->
package/src/mcp-server.js CHANGED
@@ -4,7 +4,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
4
4
  import { z } from 'zod';
5
5
  import { ApiClient } from './api-client.js';
6
6
  import { detectPlatform, isSchedulable, getAutomationInstructions } from './platform.js';
7
- import { loadState, updateState, isSnoozed, hasContributedToday, markContributed } from './state.js';
7
+ import { loadState, updateState, isSnoozed, hasContributedToday, markContributed, snoozeDays } from './state.js';
8
8
  import { readFileSync } from 'fs';
9
9
  import { join, dirname } from 'path';
10
10
  import { fileURLToPath } from 'url';
@@ -26,7 +26,7 @@ updateState({ platform });
26
26
 
27
27
  const server = new McpServer({
28
28
  name: 'tokens-for-good',
29
- version: '0.2.5',
29
+ version: '0.2.7',
30
30
  });
31
31
 
32
32
  // --- No-key onboarding message ---
@@ -191,11 +191,11 @@ server.tool('get_methodology', 'Get the full research methodology, verification
191
191
  }
192
192
  });
193
193
 
194
- server.tool('submit_report', 'Submit a completed research report for an org you claimed. IMPORTANT: Estimate your token usage for this research session and pass it as estimated_tokens (input + output tokens combined).', {
194
+ server.tool('submit_report', 'Submit a completed research report for an org you claimed. You MUST include estimated_tokens count your web searches (each ~1K tokens), web fetches (each ~2-5K tokens), and your output (~4 tokens per word of report). Add it all up.', {
195
195
  claim_id: z.number().describe('The claim ID from claim_org'),
196
196
  report_markdown: z.string().describe('The full research report in markdown'),
197
197
  model_used: z.string().optional().describe('The model that generated this report'),
198
- estimated_tokens: z.number().optional().describe('Your estimated total token usage (input + output) for this research session'),
198
+ estimated_tokens: z.number().describe('Estimated total tokens: count web searches (~1K each), web fetches (~2-5K each), your report output (~4 tokens/word), plus ~10K for system prompts and tool calls'),
199
199
  }, async ({ claim_id, report_markdown, model_used, estimated_tokens }) => {
200
200
  if (!client) return { content: [{ type: 'text', text: 'Error: TFG_API_KEY not set.' }] };
201
201
 
@@ -359,6 +359,13 @@ server.tool('setup_automation', 'Get instructions for setting up automated daily
359
359
  return { content: [{ type: 'text', text: instructions }] };
360
360
  });
361
361
 
362
+ server.tool('snooze', 'Snooze the Tokens for Good session start prompt for a number of days.', {
363
+ days: z.number().min(1).max(30).describe('Number of days to snooze (1 = ask tomorrow, 7 = ask in a week)'),
364
+ }, async ({ days }) => {
365
+ snoozeDays(days);
366
+ return { content: [{ type: 'text', text: `Got it! Tokens for Good will stay quiet for ${days} day${days !== 1 ? 's' : ''}.` }] };
367
+ });
368
+
362
369
  // --- Prompts (session start) ---
363
370
 
364
371
  server.prompt('session_start', 'Check if you should research an org or complete a peer review', {}, async () => {
@@ -393,7 +400,7 @@ server.prompt('session_start', 'Check if you should research an org or complete
393
400
 
394
401
  if (state.auto_schedule) {
395
402
  try {
396
- const impact = await client?.getImpact();
403
+ const impact = await client.getImpact();
397
404
  const c = impact?.contributor;
398
405
  return {
399
406
  messages: [{
@@ -420,14 +427,14 @@ server.prompt('session_start', 'Check if you should research an org or complete
420
427
  return {
421
428
  messages: [{
422
429
  role: 'user',
423
- content: { type: 'text', text: `Tokens for Good: Would you like to donate your spare tokens to research a nonprofit today?\n\n1. Set up automatic daily contributions (recommended)\n2. Just run one now\n3. Ask me tomorrow\n4. Ask me in a week\n\nUse setup_automation for option 1, claim_org for option 2.${permNote}` },
430
+ content: { type: 'text', text: `Tokens for Good: Would you like to donate your spare tokens to research a nonprofit today?\n\n1. Set up automatic daily contributions (recommended)\n2. Just run one now\n3. Ask me tomorrow\n4. Ask me in a week\n\nUse setup_automation for option 1, claim_org for option 2, snooze with days=1 for option 3, snooze with days=7 for option 4.${permNote}` },
424
431
  }],
425
432
  };
426
433
  } else {
427
434
  return {
428
435
  messages: [{
429
436
  role: 'user',
430
- content: { type: 'text', text: `Tokens for Good: Would you like to research a nonprofit org today? It takes about 5 minutes and costs ~$0.20 in tokens.\n\n1. Research an org now\n2. Ask me tomorrow\n3. Ask me in a week\n\nUse claim_org for option 1.${permNote}` },
437
+ content: { type: 'text', text: `Tokens for Good: Would you like to research a nonprofit org today? It takes about 5 minutes.\n\n1. Research an org now\n2. Ask me tomorrow\n3. Ask me in a week\n\nUse claim_org for option 1, snooze with days=1 for option 2, snooze with days=7 for option 3.${permNote}` },
431
438
  }],
432
439
  };
433
440
  }
package/src/platform.js CHANGED
@@ -88,7 +88,9 @@ Use WebFetch to POST to /api/research/submit:
88
88
  WebFetch URL: https://fierce-philanthropy-directory.laravel.cloud/api/research/submit
89
89
  Method: POST
90
90
  Headers: X-TFG-Api-Key: ${apiKey}, Content-Type: application/json
91
- Body: {"claim_id": <claim_id from step 1>, "report_markdown": "<full report>", "model_used": "claude-code-scheduled"}
91
+ Body: {"claim_id": <claim_id from step 1>, "report_markdown": "<full report>", "model_used": "claude-code-scheduled", "token_usage": {"total_tokens": <estimated total tokens used>}}
92
+
93
+ Estimate tokens: count your web searches (~1K each), web fetches (~2-5K each), report output (~4 tokens/word), plus ~10K for system/tool overhead.
92
94
 
93
95
  ### 5. Check next-action
94
96
  After submitting, check if you need to do a peer review before continuing:
package/src/state.js CHANGED
@@ -64,8 +64,8 @@ export function hasContributedToday() {
64
64
  }
65
65
 
66
66
  export function markContributed() {
67
- updateState({
68
- last_contributed: new Date().toISOString(),
69
- total_session_contributions: loadState().total_session_contributions + 1,
70
- });
67
+ const state = loadState();
68
+ state.last_contributed = new Date().toISOString();
69
+ state.total_session_contributions = (state.total_session_contributions || 0) + 1;
70
+ saveState(state);
71
71
  }