tokens-for-good 0.2.0 → 0.2.2
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 +1 -1
- package/pipeline/01-research/PROMPT.md +3 -18
- package/src/api-client.js +5 -1
- package/src/mcp-server.js +5 -7
- package/src/platform.js +4 -6
package/package.json
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
# Step 1: Research — Claude Code Instructions
|
|
2
2
|
|
|
3
|
-
## Inputs
|
|
4
|
-
|
|
5
|
-
- **Org name:** `{{ORG_NAME}}`
|
|
6
|
-
- **Org data:** From `orgs.json` — find the entry for this org (name, url, description, source)
|
|
7
|
-
- **Writing style guide:** Read from `site/writing-style-guide.md`
|
|
8
|
-
- **Research guidance:** Read from `site/research-guidance.md`
|
|
9
|
-
|
|
10
3
|
## Your Role
|
|
11
4
|
|
|
12
5
|
You are a social impact research analyst working for Fierce Philanthropy. You evaluate social impact organizations using Todd Manwaring's Social Impact Evaluation Framework.
|
|
@@ -32,15 +25,7 @@ You recognize that the best social impact organizations follow a repeated cycle
|
|
|
32
25
|
|
|
33
26
|
## Instructions
|
|
34
27
|
|
|
35
|
-
### 1.
|
|
36
|
-
|
|
37
|
-
Find the org in `orgs.json` by name. Extract:
|
|
38
|
-
- Name
|
|
39
|
-
- URL (primary website or portfolio link)
|
|
40
|
-
- Description
|
|
41
|
-
- Source (where we found them)
|
|
42
|
-
|
|
43
|
-
### 2. Research the Organization
|
|
28
|
+
### 1. Research the Organization
|
|
44
29
|
|
|
45
30
|
Using **WebSearch** and **WebFetch** tools, thoroughly research the organization. Search for:
|
|
46
31
|
|
|
@@ -54,7 +39,7 @@ Using **WebSearch** and **WebFetch** tools, thoroughly research the organization
|
|
|
54
39
|
- Only direct results from this organization and independent measurements of it
|
|
55
40
|
- Only measured results with citations — every factual claim traces to a specific source
|
|
56
41
|
|
|
57
|
-
###
|
|
42
|
+
### 2. Generate the Report
|
|
58
43
|
|
|
59
44
|
Generate the COMPLETE report following this exact format and section order:
|
|
60
45
|
|
|
@@ -159,7 +144,7 @@ End with:
|
|
|
159
144
|
|
|
160
145
|
Inline citations as `[Source Name](URL)`. Distinguish attribution: "X reports that" for org claims, "independent evaluation found" for third-party evidence.
|
|
161
146
|
|
|
162
|
-
###
|
|
147
|
+
### 3. Submit the Report
|
|
163
148
|
|
|
164
149
|
Submit using the `submit_report` tool with the full markdown as `report_markdown`.
|
|
165
150
|
|
package/src/api-client.js
CHANGED
|
@@ -19,6 +19,7 @@ export class ApiClient {
|
|
|
19
19
|
'Content-Type': 'application/json',
|
|
20
20
|
'Accept': 'application/json',
|
|
21
21
|
},
|
|
22
|
+
signal: AbortSignal.timeout(30000),
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
if (body) {
|
|
@@ -70,10 +71,13 @@ export class ApiClient {
|
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
async getStatus() {
|
|
73
|
-
// Status is public, no auth needed
|
|
74
74
|
const response = await fetch(`${BASE_URL}/research/status`, {
|
|
75
75
|
headers: { 'Accept': 'application/json' },
|
|
76
|
+
signal: AbortSignal.timeout(15000),
|
|
76
77
|
});
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
throw new Error(`Status API error ${response.status}`);
|
|
80
|
+
}
|
|
77
81
|
return response.json();
|
|
78
82
|
}
|
|
79
83
|
|
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,
|
|
7
|
+
import { loadState, updateState, isSnoozed, hasContributedToday, markContributed } 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.
|
|
29
|
+
version: '0.2.2',
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
// --- No-key onboarding message ---
|
|
@@ -327,10 +327,10 @@ After adding, tell them: "Done! Research will now run hands-free. Try saying 'Re
|
|
|
327
327
|
};
|
|
328
328
|
});
|
|
329
329
|
|
|
330
|
-
server.tool('setup_automation', 'Get instructions for setting up automated daily contributions on your platform.', {
|
|
330
|
+
server.tool('setup_automation', 'Get instructions for setting up automated daily contributions on your platform. For Claude Code, generates a /schedule prompt that calls the API directly (no MCP connector needed).', {
|
|
331
331
|
frequency: z.enum(['hourly', 'daily', 'weekly']).optional().describe('How often to contribute'),
|
|
332
332
|
}, async ({ frequency }) => {
|
|
333
|
-
const instructions = getAutomationInstructions(platform, frequency || 'daily');
|
|
333
|
+
const instructions = getAutomationInstructions(platform, frequency || 'daily', apiKey);
|
|
334
334
|
return { content: [{ type: 'text', text: instructions }] };
|
|
335
335
|
});
|
|
336
336
|
|
|
@@ -350,8 +350,7 @@ server.prompt('session_start', 'Check if you should research an org or complete
|
|
|
350
350
|
const state = loadState();
|
|
351
351
|
|
|
352
352
|
// Check for pending peer review first
|
|
353
|
-
|
|
354
|
-
try {
|
|
353
|
+
try {
|
|
355
354
|
const review = await client.getNextPeerReview();
|
|
356
355
|
return {
|
|
357
356
|
messages: [{
|
|
@@ -362,7 +361,6 @@ server.prompt('session_start', 'Check if you should research an org or complete
|
|
|
362
361
|
} catch {
|
|
363
362
|
// No pending review, continue
|
|
364
363
|
}
|
|
365
|
-
}
|
|
366
364
|
|
|
367
365
|
if (isSnoozed()) {
|
|
368
366
|
return { messages: [{ role: 'user', content: { type: 'text', text: 'Tokens for Good is snoozed. No action needed.' } }] };
|
package/src/platform.js
CHANGED
|
@@ -44,12 +44,10 @@ This returns the org name, URL, description, and a claim_id. You have 30 minutes
|
|
|
44
44
|
|
|
45
45
|
### 2. Research the org
|
|
46
46
|
Use WebSearch and WebFetch to thoroughly research the organization:
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
Use ONLY WebSearch and WebFetch tools. Do NOT use curl or Bash for web requests.
|
|
47
|
+
- The org's website, impact pages, annual reports
|
|
48
|
+
- Independent evaluations (RCTs, J-PAL, 3ie)
|
|
49
|
+
- Third-party reviews (GiveWell, Charity Navigator)
|
|
50
|
+
- Financial data (ProPublica Nonprofit Explorer)
|
|
53
51
|
|
|
54
52
|
### 3. Write the report
|
|
55
53
|
Follow the Fierce Philanthropy research methodology:
|