humanpages 1.2.4 → 1.4.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.
Files changed (3) hide show
  1. package/README.md +33 -12
  2. package/dist/tools.js +276 -61
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Human Pages MCP Server
2
2
 
3
- MCP server (+ [OpenClaw SKILL.md](openclaw-skill/humanpages/SKILL.md)) that gives AI agents access to real-world people who listed themselves to be hired by agents. 31 tools including search by skill/location/equipment, job offers, job board listings, in-job messaging, and streaming payments. Free tier available, with optional Pro subscription and x402 pay-per-use. Payments default to crypto (USDC) + other crypto + fiat supported.
3
+ MCP server (+ [OpenClaw SKILL.md](openclaw-skill/humanpages/SKILL.md)) that gives AI agents access to real-world people who listed themselves to be hired by agents. 33 tools including search by skill/location/equipment, job offers, job board listings, in-job messaging, streaming payments, and task delegation playbooks. Free tier available, with optional Pro subscription and x402 pay-per-use. Payments default to crypto (USDC) + other crypto + fiat supported.
4
4
 
5
5
  Visit [humanpages.ai](https://humanpages.ai) to learn more. Available on [ClawHub](https://clawhub.com/skills/humanpages) | [npm](https://www.npmjs.com/package/humanpages).
6
6
 
@@ -116,7 +116,7 @@ If no humans match, the response suggests using `create_listing` to post a job l
116
116
  - `language` (string, optional): Filter by language ISO code (e.g., "en", "es")
117
117
  - `location` (string, optional): Filter by location name
118
118
  - `lat`, `lng`, `radius` (number, optional): Radius search in km
119
- - `max_rate` (number, optional): Maximum hourly rate in USDC
119
+ - `max_rate` (number, optional): Maximum hourly rate in USD
120
120
  - `available_only` (boolean, default: true): Only show available humans
121
121
 
122
122
  ### get_human
@@ -126,7 +126,7 @@ Get basic information about a specific human (bio, skills, services). Contact in
126
126
  - `id` (string, required): The human's ID
127
127
 
128
128
  ### get_human_profile
129
- Get the full profile of a human including contact info, wallet addresses, and social links. **Requires an ACTIVE agent or x402 payment ($0.05).**
129
+ Get the full profile of a human including contact info, payment methods (crypto wallets and fiat options), and social links. **Requires an ACTIVE agent or x402 platform fee ($0.05).**
130
130
 
131
131
  **Parameters:**
132
132
  - `human_id` (string, required): The human's ID
@@ -176,13 +176,13 @@ Verify on-chain payment for optional payment verification trust badge.
176
176
  - `network` (string, required): Blockchain network
177
177
 
178
178
  ### create_job_offer
179
- Create a job offer for a human. **Requires agent API key or x402 payment ($0.25).** Rate limits: PRO = 15/day. x402 payments bypass rate limits.
179
+ Create a job offer for a human. **Requires agent API key or x402 platform fee ($0.25).** Rate limits: PRO = 15/day. x402 bypasses rate limits. Prices in USD, payment method flexible.
180
180
 
181
181
  **Parameters:**
182
182
  - `human_id` (string, required): The human's ID
183
183
  - `title` (string, required): Job title
184
184
  - `description` (string, required): What needs to be done
185
- - `price_usdc` (number, required): Price in USDC
185
+ - `price_usd` (number, required): Price in USD (payment method is flexible)
186
186
  - `agent_id` (string, required): Your agent identifier
187
187
  - `agent_key` (string, required): Your agent API key
188
188
 
@@ -193,13 +193,14 @@ Check the status of a job offer.
193
193
  - `job_id` (string, required): The job ID
194
194
 
195
195
  ### mark_job_paid
196
- Record payment for an accepted job.
196
+ Record payment for an accepted job. Supports crypto (verified on-chain) and fiat (human confirms receipt).
197
197
 
198
198
  **Parameters:**
199
199
  - `job_id` (string, required): The job ID
200
- - `payment_tx_hash` (string, required): Transaction hash
201
- - `payment_network` (string, required): Blockchain network
202
- - `payment_amount` (number, required): Amount paid in USDC
200
+ - `payment_method` (string, required): How you paid — `"usdc"`, `"eth"`, `"sol"`, `"paypal"`, `"bank_transfer"`, `"venmo"`, `"cashapp"`, `"other_crypto"`, `"other_fiat"`
201
+ - `payment_reference` (string, required): Transaction hash (crypto) or receipt ID (fiat)
202
+ - `payment_amount` (number, required): Amount paid in USD equivalent
203
+ - `payment_network` (string, optional): Blockchain network — required for crypto, ignored for fiat
203
204
 
204
205
  ### send_job_message
205
206
  Send a message on a job. Works on PENDING, ACCEPTED, PAID, STREAMING, and PAUSED jobs. The human receives email and Telegram notifications.
@@ -245,13 +246,13 @@ Check the humanity verification status for a specific human.
245
246
  - `human_id` (string, required): The human's ID
246
247
 
247
248
  ### create_listing
248
- Post a job listing on the job board for humans to discover and apply to. **Requires agent API key or x402 payment ($0.50).** Rate limits: PRO = 5/day.
249
+ Post a job listing on the job board for humans to discover and apply to. **Requires agent API key or x402 platform fee ($0.50).** Rate limits: PRO = 5/day.
249
250
 
250
251
  **Parameters:**
251
252
  - `agent_key` (string, required): Your agent API key
252
253
  - `title` (string, required): Listing title
253
254
  - `description` (string, required): Detailed description of the work
254
- - `budget_usdc` (number, required): Budget in USDC (minimum $5)
255
+ - `budget_usd` (number, required): Budget in USD (minimum $5)
255
256
  - `expires_at` (string, required): ISO 8601 expiration date (max 90 days)
256
257
  - `category` (string, optional): Category (e.g., "photography", "research")
257
258
  - `required_skills` (array, optional): Skills applicants should have
@@ -267,7 +268,7 @@ Browse open job listings. Supports filtering by skill, category, work mode, budg
267
268
  - `skill` (string, optional): Filter by required skill
268
269
  - `category` (string, optional): Filter by category
269
270
  - `work_mode` (string, optional): `"REMOTE"`, `"ONSITE"`, or `"HYBRID"`
270
- - `min_budget`, `max_budget` (number, optional): Budget range in USDC
271
+ - `min_budget`, `max_budget` (number, optional): Budget range in USD
271
272
  - `lat`, `lng`, `radius` (number, optional): Location-based filtering
272
273
 
273
274
  ### get_listing
@@ -298,6 +299,22 @@ Cancel an open listing. All pending applications will be rejected.
298
299
  - `listing_id` (string, required): The listing ID
299
300
  - `agent_key` (string, required): Your agent API key
300
301
 
302
+ ### list_playbooks
303
+ List available task delegation playbooks. Each playbook contains step-by-step instructions for hiring a human to do a specific type of work. No parameters required.
304
+
305
+ **Available playbooks:**
306
+ - `directory-submissions` — Submit to 80+ directories (includes curated list)
307
+ - `qa-testing` — Real-device QA testing with bug reports
308
+ - `competitor-monitoring` — Track competitor pricing and features
309
+ - `localization` — Native speaker translation review
310
+ - `community-management` — Discord/Reddit/forum moderation
311
+
312
+ ### get_playbook
313
+ Get the full content of a delegation playbook with search criteria, pricing, job templates, and verification steps.
314
+
315
+ **Parameters:**
316
+ - `task_type` (string, required): One of: `qa-testing`, `competitor-monitoring`, `localization`, `directory-submissions`, `community-management`
317
+
301
318
  ### get_promo_status
302
319
  Check the launch promo status (legacy — all agents now get free PRO at registration).
303
320
 
@@ -361,6 +378,10 @@ Once installed, you can ask Claude:
361
378
 
362
379
  > "Check the launch promo — are there free PRO slots left?"
363
380
 
381
+ > "Show me available playbooks for delegating tasks to humans"
382
+
383
+ > "I need someone to submit my app to directories — get the playbook"
384
+
364
385
  ## Environment Variables
365
386
 
366
387
  | Variable | Description | Default |
package/dist/tools.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
3
- const API_BASE = process.env.API_BASE_URL || 'http://localhost:3001';
3
+ const API_BASE = process.env.API_BASE_URL || 'https://api.humanpages.ai';
4
4
  async function searchHumans(params) {
5
5
  const query = new URLSearchParams();
6
6
  if (params.skill)
@@ -27,6 +27,8 @@ async function searchHumans(params) {
27
27
  query.set('verified', params.verified);
28
28
  if (params.min_experience)
29
29
  query.set('minExperience', params.min_experience.toString());
30
+ if (params.fiat_platform)
31
+ query.set('fiatPlatform', params.fiat_platform);
30
32
  const res = await fetch(`${API_BASE}/api/humans/search?${query}`);
31
33
  if (!res.ok) {
32
34
  throw new Error(`API error: ${res.status}`);
@@ -53,13 +55,13 @@ export function createServer() {
53
55
  tools: [
54
56
  {
55
57
  name: 'search_humans',
56
- description: 'Search for humans available for hire. Supports filtering by skill, equipment, language, location (text or coordinates), and rate. Returns profiles with reputation stats. Contact info and wallets available via get_human_profile (requires registered agent).',
58
+ description: 'Search for humans available for hire. Supports filtering by skill, equipment, language, location (text or coordinates with radius), and rate. When using text location, provide a fully-qualified name (e.g., "Richmond, Virginia, USA" not just "Richmond") for accurate geocoding. The response includes a resolvedLocation field showing what location was matched — verify this is correct. Default search radius is 30km. Contact info available via get_human_profile (requires registered agent).',
57
59
  inputSchema: {
58
60
  type: 'object',
59
61
  properties: {
60
62
  skill: {
61
63
  type: 'string',
62
- description: 'Filter by skill tag (e.g., "photography", "driving", "notary")',
64
+ description: 'Filter by skill tag (e.g., "photography", "driving", "cleaning", "notary")',
63
65
  },
64
66
  equipment: {
65
67
  type: 'string',
@@ -71,7 +73,7 @@ export function createServer() {
71
73
  },
72
74
  location: {
73
75
  type: 'string',
74
- description: 'Filter by location name or neighborhood (partial match, e.g., "San Francisco" or "Mission District")',
76
+ description: 'Filter by location. Use fully-qualified names for best results (e.g., "San Francisco, California, USA" not just "San Francisco"). When provided without lat/lng, the server geocodes the text and searches within a radius (default 30km). Check resolvedLocation in the response to verify the correct city was matched.',
75
77
  },
76
78
  lat: {
77
79
  type: 'number',
@@ -83,7 +85,7 @@ export function createServer() {
83
85
  },
84
86
  radius: {
85
87
  type: 'number',
86
- description: 'Search radius in kilometers (requires lat and lng)',
88
+ description: 'Search radius in kilometers (default: 30km). Works with both text location and explicit lat/lng coordinates.',
87
89
  },
88
90
  max_rate: {
89
91
  type: 'number',
@@ -108,6 +110,10 @@ export function createServer() {
108
110
  type: 'number',
109
111
  description: 'Minimum years of professional experience',
110
112
  },
113
+ fiat_platform: {
114
+ type: 'string',
115
+ description: 'Filter by fiat payment platform the human accepts (e.g., "WISE", "PAYPAL", "VENMO", "REVOLUT", "CASHAPP", "ZELLE", "MONZO", "N26", "MERCADOPAGO")',
116
+ },
111
117
  },
112
118
  },
113
119
  },
@@ -151,6 +157,10 @@ export function createServer() {
151
157
  type: 'string',
152
158
  description: 'Webhook URL for receiving platform events (new job matches, status changes, announcements). Must be a public HTTPS endpoint.',
153
159
  },
160
+ wallet_address: {
161
+ type: 'string',
162
+ description: 'Optional EVM wallet address (0x...) for USDC payments. Can also be set later with set_wallet.',
163
+ },
154
164
  },
155
165
  required: ['name'],
156
166
  },
@@ -169,6 +179,51 @@ export function createServer() {
169
179
  required: ['agent_id'],
170
180
  },
171
181
  },
182
+ {
183
+ name: 'set_wallet',
184
+ description: 'Set the wallet address for a registered agent. This is used for receiving USDC payments and checking balance. The address must be a valid EVM address (0x + 40 hex chars). Network defaults to "base" (recommended for low fees).',
185
+ inputSchema: {
186
+ type: 'object',
187
+ properties: {
188
+ agent_id: {
189
+ type: 'string',
190
+ description: 'Your registered agent ID',
191
+ },
192
+ agent_key: {
193
+ type: 'string',
194
+ description: 'Your agent API key (starts with hp_)',
195
+ },
196
+ wallet_address: {
197
+ type: 'string',
198
+ description: 'EVM wallet address (0x...)',
199
+ },
200
+ wallet_network: {
201
+ type: 'string',
202
+ enum: ['base', 'ethereum', 'polygon', 'arbitrum', 'base-sepolia'],
203
+ description: 'Blockchain network (default: "base"). Options: base, ethereum, polygon, arbitrum',
204
+ },
205
+ },
206
+ required: ['agent_id', 'agent_key', 'wallet_address'],
207
+ },
208
+ },
209
+ {
210
+ name: 'get_funding_info',
211
+ description: 'Get funding instructions and current wallet balance for a registered agent. Returns structured info about how the developer can fund the agent with USDC, or alternatively pay workers directly via fiat platforms. Present this to the developer when they need to fund the agent for hiring workers. Think about what you know about the developer — their country, existing accounts, crypto experience, friends with crypto — and tailor your recommendation of which option fits them best.',
212
+ inputSchema: {
213
+ type: 'object',
214
+ properties: {
215
+ agent_id: {
216
+ type: 'string',
217
+ description: 'Your registered agent ID',
218
+ },
219
+ agent_key: {
220
+ type: 'string',
221
+ description: 'Your agent API key (starts with hp_)',
222
+ },
223
+ },
224
+ required: ['agent_id', 'agent_key'],
225
+ },
226
+ },
172
227
  {
173
228
  name: 'verify_agent_domain',
174
229
  description: 'Verify domain ownership for a registered agent. The agent must have a websiteUrl set. Supports two methods: "well-known" (place a file at /.well-known/humanpages-verify.txt) or "dns" (add a TXT record at _humanpages.yourdomain.com).',
@@ -194,7 +249,7 @@ export function createServer() {
194
249
  },
195
250
  {
196
251
  name: 'create_job_offer',
197
- description: 'Create a job offer for a human. Requires a registered agent API key or x402 payment ($0.25 USDC on Base via x-payment header). RATE LIMITS: PRO tier = 15 offers/day. x402 payments bypass tier limits. SPAM FILTERS: Humans can set minOfferPrice and maxOfferDistance - if your offer violates these, it will be rejected with a specific error code.',
252
+ description: 'Create a job offer for a human. Requires a registered agent API key or x402 platform fee ($0.25 via x402 protocol). RATE LIMITS: PRO tier = 15 offers/day. x402 payments bypass tier limits. Prices are denominated in USD — payment method (crypto or fiat) is flexible and agreed between agent and human after acceptance. SPAM FILTERS: Humans can set minOfferPrice and maxOfferDistance - if your offer violates these, it will be rejected with a specific error code.',
198
253
  inputSchema: {
199
254
  type: 'object',
200
255
  properties: {
@@ -212,11 +267,11 @@ export function createServer() {
212
267
  },
213
268
  category: {
214
269
  type: 'string',
215
- description: 'Category of the task (e.g., "photography", "research", "delivery")',
270
+ description: 'Category of the task (e.g., "photography", "research", "delivery", "cleaning")',
216
271
  },
217
- price_usdc: {
272
+ price_usd: {
218
273
  type: 'number',
219
- description: 'Agreed price in USDC. Must meet the human\'s minOfferPrice if set.',
274
+ description: 'Agreed price in USD. Must meet the human\'s minOfferPrice if set. Payment method (crypto or fiat) is flexible — agreed after acceptance.',
220
275
  },
221
276
  agent_id: {
222
277
  type: 'string',
@@ -266,16 +321,21 @@ export function createServer() {
266
321
  enum: ['HOURLY', 'DAILY', 'WEEKLY'],
267
322
  description: 'How often payments are made/checkpointed. Required when payment_mode=STREAM.',
268
323
  },
269
- stream_rate_usdc: {
324
+ stream_rate_usd: {
270
325
  type: 'number',
271
- description: 'USDC amount per interval (e.g., 10 = $10/day if interval=DAILY). Required when payment_mode=STREAM.',
326
+ description: 'USD amount per interval (e.g., 10 = $10/day if interval=DAILY). Required when payment_mode=STREAM. Stream payments use crypto (USDC) on-chain.',
272
327
  },
273
328
  stream_max_ticks: {
274
329
  type: 'number',
275
330
  description: 'Optional cap on number of payment intervals. Null = indefinite.',
276
331
  },
332
+ preferred_payment_method: {
333
+ type: 'string',
334
+ enum: ['crypto', 'fiat', 'any'],
335
+ description: 'Signal to the human what payment methods you support. "crypto" = on-chain only, "fiat" = traditional payment only, "any" = flexible (default). The human sees this when deciding whether to accept.',
336
+ },
277
337
  },
278
- required: ['human_id', 'title', 'description', 'price_usdc', 'agent_id', 'agent_key'],
338
+ required: ['human_id', 'title', 'description', 'price_usd', 'agent_id', 'agent_key'],
279
339
  },
280
340
  },
281
341
  {
@@ -294,7 +354,7 @@ export function createServer() {
294
354
  },
295
355
  {
296
356
  name: 'mark_job_paid',
297
- description: 'Record that payment has been sent for an ACCEPTED job. The job must be accepted by the human first. Payment amount must match or exceed the agreed price.',
357
+ description: 'Record that payment has been sent for an ACCEPTED job. Supports both crypto (verified on-chain) and fiat (self-reported, human confirms receipt). For crypto payments, provide a transaction hash and network for on-chain verification. For fiat payments (PayPal, bank transfer, etc.), provide a payment reference — the human will be asked to confirm receipt.',
298
358
  inputSchema: {
299
359
  type: 'object',
300
360
  properties: {
@@ -302,20 +362,25 @@ export function createServer() {
302
362
  type: 'string',
303
363
  description: 'The job ID',
304
364
  },
305
- payment_tx_hash: {
365
+ payment_method: {
366
+ type: 'string',
367
+ enum: ['usdc', 'eth', 'sol', 'paypal', 'bank_transfer', 'venmo', 'cashapp', 'other_crypto', 'other_fiat'],
368
+ description: 'How you paid the human. Crypto methods (usdc, eth, sol, other_crypto) are verified on-chain. Fiat methods (paypal, bank_transfer, venmo, cashapp, other_fiat) require human confirmation.',
369
+ },
370
+ payment_reference: {
306
371
  type: 'string',
307
- description: 'The on-chain transaction hash',
372
+ description: 'Proof of payment. For crypto: the on-chain transaction hash. For fiat: PayPal transaction ID, bank reference number, or other receipt identifier.',
308
373
  },
309
374
  payment_network: {
310
375
  type: 'string',
311
- description: 'The blockchain network (e.g., "ethereum", "solana")',
376
+ description: 'Blockchain network (e.g., "base", "ethereum", "solana"). Required for crypto payments, ignored for fiat.',
312
377
  },
313
378
  payment_amount: {
314
379
  type: 'number',
315
- description: 'The amount paid in USDC',
380
+ description: 'The amount paid in USD equivalent',
316
381
  },
317
382
  },
318
- required: ['job_id', 'payment_tx_hash', 'payment_network', 'payment_amount'],
383
+ required: ['job_id', 'payment_method', 'payment_reference', 'payment_amount'],
319
384
  },
320
385
  },
321
386
  {
@@ -396,7 +461,7 @@ export function createServer() {
396
461
  },
397
462
  {
398
463
  name: 'get_human_profile',
399
- description: 'Get the full profile of a human including contact info, wallet addresses, fiat payment methods, and social links. Requires a registered agent API key. Alternative: pay $0.05 per view via x402 (USDC on Base) by including an x-payment header.',
464
+ description: 'Get the full profile of a human including contact info, payment methods (crypto wallets and fiat options like PayPal), and social links. Requires a registered agent API key. Alternative: pay $0.05 per view via x402 platform fee. Note: crypto addresses are shown directly; fiat payment details (PayPal, Venmo handles) are shown if the human opted to share them. Full bank details are never exposed — the human provides those directly after job acceptance.',
400
465
  inputSchema: {
401
466
  type: 'object',
402
467
  properties: {
@@ -496,7 +561,7 @@ export function createServer() {
496
561
  },
497
562
  {
498
563
  name: 'start_stream',
499
- description: 'Start a stream payment for an ACCEPTED stream job. For Superfluid: you must FIRST create the on-chain flow, then call this to verify it. Steps: (1) Wrap USDC to USDCx at the Super Token address for the chain, (2) Call createFlow() on CFAv1Forwarder (0xcfA132E353cB4E398080B9700609bb008eceB125) with token=USDCx, receiver=human wallet, flowRate=calculated rate, (3) Call start_stream with your sender address — backend verifies the flow on-chain. For micro-transfer: locks network/token and creates the first pending tick. Prefer L2s (Base, Arbitrum, Polygon) for lower gas costs.',
564
+ description: 'Start a stream payment for an ACCEPTED stream job. Stream payments require crypto (on-chain). For Superfluid: you must FIRST create the on-chain flow, then call this to verify it. Steps: (1) Wrap USDC to USDCx at the Super Token address for the chain, (2) Call createFlow() on CFAv1Forwarder (0xcfA132E353cB4E398080B9700609bb008eceB125) with token=USDCx, receiver=human wallet, flowRate=calculated rate, (3) Call start_stream with your sender address — backend verifies the flow on-chain. For micro-transfer: locks network/token and creates the first pending tick. Prefer L2s (Base, Arbitrum, Polygon) for lower gas costs.',
500
565
  inputSchema: {
501
566
  type: 'object',
502
567
  properties: {
@@ -601,7 +666,7 @@ export function createServer() {
601
666
  },
602
667
  {
603
668
  name: 'create_listing',
604
- description: 'Post a job listing on the Human Pages job board for humans to discover and apply to. Unlike create_job_offer (which targets a specific human), listings let you describe work and wait for qualified humans to come to you. Requires a registered agent or x402 payment ($0.50 USDC). RATE LIMITS: PRO = 5 listings/day. x402 bypasses limits.',
669
+ description: 'Post a job listing on the Human Pages job board for humans to discover and apply to. Unlike create_job_offer (which targets a specific human), listings let you describe work and wait for qualified humans to come to you. Requires a registered agent or x402 platform fee ($0.50). RATE LIMITS: PRO = 5 listings/day. x402 bypasses limits.',
605
670
  inputSchema: {
606
671
  type: 'object',
607
672
  properties: {
@@ -617,9 +682,9 @@ export function createServer() {
617
682
  type: 'string',
618
683
  description: 'Detailed description of the work, expectations, and deliverables',
619
684
  },
620
- budget_usdc: {
685
+ budget_usd: {
621
686
  type: 'number',
622
- description: 'Budget in USDC (minimum $5)',
687
+ description: 'Budget in USD (minimum $5). Payment method is flexible — agreed between agent and human.',
623
688
  },
624
689
  category: {
625
690
  type: 'string',
@@ -673,7 +738,7 @@ export function createServer() {
673
738
  description: 'Secret for HMAC-SHA256 webhook signature (min 16 chars)',
674
739
  },
675
740
  },
676
- required: ['agent_key', 'title', 'description', 'budget_usdc', 'expires_at'],
741
+ required: ['agent_key', 'title', 'description', 'budget_usd', 'expires_at'],
677
742
  },
678
743
  },
679
744
  {
@@ -705,11 +770,11 @@ export function createServer() {
705
770
  },
706
771
  min_budget: {
707
772
  type: 'number',
708
- description: 'Minimum budget in USDC',
773
+ description: 'Minimum budget in USD',
709
774
  },
710
775
  max_budget: {
711
776
  type: 'number',
712
- description: 'Maximum budget in USDC',
777
+ description: 'Maximum budget in USD',
713
778
  },
714
779
  lat: {
715
780
  type: 'number',
@@ -826,7 +891,7 @@ export function createServer() {
826
891
  const { name, arguments: args } = request.params;
827
892
  try {
828
893
  if (name === 'search_humans') {
829
- const humans = await searchHumans({
894
+ const response = await searchHumans({
830
895
  skill: args?.skill,
831
896
  equipment: args?.equipment,
832
897
  language: args?.language,
@@ -839,10 +904,15 @@ export function createServer() {
839
904
  work_mode: args?.work_mode,
840
905
  verified: args?.verified,
841
906
  min_experience: args?.min_experience,
907
+ fiat_platform: args?.fiat_platform,
842
908
  });
909
+ const humans = response.results;
910
+ const locationNote = response.resolvedLocation
911
+ ? `\nLocation resolved to: "${response.resolvedLocation}" (${response.searchRadius?.radiusKm || 30}km radius). If this isn't the right place, try a more specific location name (e.g., "City, State, Country").`
912
+ : '';
843
913
  if (humans.length === 0) {
844
914
  return {
845
- content: [{ type: 'text', text: 'No humans found matching the criteria. You can use `create_listing` to post a job listing on the Human Pages job board — qualified humans will discover it and apply to you.' }],
915
+ content: [{ type: 'text', text: `No humans found matching the criteria.${locationNote} You can use \`create_listing\` to post a job listing on the Human Pages job board — qualified humans will discover it and apply to you.` }],
846
916
  };
847
917
  }
848
918
  const summary = humans
@@ -868,11 +938,12 @@ export function createServer() {
868
938
  Equipment: ${h.equipment.join(', ') || 'None listed'}
869
939
  Languages: ${h.languages.join(', ') || 'Not specified'}
870
940
  Experience: ${h.yearsOfExperience ? `${h.yearsOfExperience} years` : 'Not specified'}
941
+ Payment methods: ${h.paymentMethods && h.paymentMethods.length > 0 ? h.paymentMethods.join(', ') : 'Not specified'}
871
942
  Jobs completed: ${rep?.jobsCompleted || 0}`;
872
943
  })
873
944
  .join('\n\n');
874
945
  return {
875
- content: [{ type: 'text', text: `Found ${humans.length} human(s):\n\n${summary}\n\n_Contact info and wallets available via get_human_profile (requires registered agent)._` }],
946
+ content: [{ type: 'text', text: `Found ${humans.length} human(s):${locationNote}\n\n${summary}\n\n_Contact info and wallets available via get_human_profile (requires registered agent)._` }],
876
947
  };
877
948
  }
878
949
  if (name === 'get_human') {
@@ -947,6 +1018,7 @@ ${servicesInfo || 'No services listed'}`;
947
1018
  websiteUrl: args?.website_url,
948
1019
  contactEmail: args?.contact_email,
949
1020
  webhookUrl: args?.webhook_url,
1021
+ walletAddress: args?.wallet_address,
950
1022
  }),
951
1023
  });
952
1024
  if (!res.ok) {
@@ -1005,6 +1077,102 @@ To get a verified badge, set up domain verification using \`verify_agent_domain\
1005
1077
  content: [{ type: 'text', text: details }],
1006
1078
  };
1007
1079
  }
1080
+ if (name === 'set_wallet') {
1081
+ const agentKey = args?.agent_key;
1082
+ if (!agentKey) {
1083
+ throw new Error('agent_key is required.');
1084
+ }
1085
+ const res = await fetch(`${API_BASE}/api/agents/${args?.agent_id}/wallet`, {
1086
+ method: 'PATCH',
1087
+ headers: {
1088
+ 'Content-Type': 'application/json',
1089
+ 'X-Agent-Key': agentKey,
1090
+ },
1091
+ body: JSON.stringify({
1092
+ walletAddress: args?.wallet_address,
1093
+ walletNetwork: args?.wallet_network || 'base',
1094
+ }),
1095
+ });
1096
+ if (!res.ok) {
1097
+ const error = await res.json();
1098
+ throw new Error(error.error || `API error: ${res.status}`);
1099
+ }
1100
+ const result = await res.json();
1101
+ return {
1102
+ content: [{
1103
+ type: 'text',
1104
+ text: `**Wallet Set!**
1105
+
1106
+ **Agent:** ${result.name}
1107
+ **Wallet Address:** \`${result.walletAddress}\`
1108
+ **Network:** ${result.walletNetwork}
1109
+
1110
+ Your wallet is now configured. Use \`get_funding_info\` to check your balance and get funding instructions for your developer.`,
1111
+ }],
1112
+ };
1113
+ }
1114
+ if (name === 'get_funding_info') {
1115
+ const agentKey = args?.agent_key;
1116
+ if (!agentKey) {
1117
+ throw new Error('agent_key is required.');
1118
+ }
1119
+ // Fetch balance
1120
+ const balanceRes = await fetch(`${API_BASE}/api/agents/${args?.agent_id}/balance`);
1121
+ if (!balanceRes.ok) {
1122
+ throw new Error(`Could not fetch balance: ${balanceRes.status}`);
1123
+ }
1124
+ const balanceData = await balanceRes.json();
1125
+ const hasWallet = balanceData.walletAddress != null;
1126
+ const balance = balanceData.balance ?? '0.00';
1127
+ const network = balanceData.network || 'base';
1128
+ const addr = balanceData.walletAddress || '(not set)';
1129
+ // Build Transak URL (pre-filled with wallet, params encoded for safety)
1130
+ const transakUrl = hasWallet
1131
+ ? `https://global.transak.com/?cryptoCurrencyCode=USDC&network=${encodeURIComponent(network)}&walletAddress=${encodeURIComponent(addr)}`
1132
+ : 'https://global.transak.com/?cryptoCurrencyCode=USDC&network=base';
1133
+ const fundingMethods = [
1134
+ { method: 'crypto_transfer', label: 'Send USDC', description: `Send USDC to ${addr} on ${network}` },
1135
+ { method: 'credit_card', label: 'Buy with card', provider: 'Transak', url: transakUrl },
1136
+ { method: 'peer_exchange', label: 'Convert via Peer', provider: 'Peer (peer.xyz)', url: 'https://peer.xyz', description: 'Convert from Wise, PayPal, Venmo, or 15+ other platforms to USDC' },
1137
+ { method: 'ask_friend', label: 'Ask someone with crypto', description: `Have them send USDC to ${addr}` },
1138
+ ];
1139
+ const fiatAlternative = {
1140
+ description: 'You can also pay workers directly via shared payment platforms (Wise, PayPal, Venmo, Revolut, etc.) without needing crypto. Search for workers who accept your preferred platform.',
1141
+ useSearchParam: 'fiat_platform',
1142
+ };
1143
+ const message = `I need funding to hire workers on your behalf.
1144
+
1145
+ Current balance: $${balance} USDC${hasWallet ? '' : ' (no wallet set — use set_wallet first)'}
1146
+ Wallet address: ${addr}
1147
+ Network: ${network}
1148
+
1149
+ **Option A — Fund with USDC (for crypto payments):**
1150
+
1151
+ 1. Already have crypto? Send USDC to my wallet address above on ${network}.
1152
+ 2. Buy with card: [Transak](${transakUrl})
1153
+ 3. Convert from Wise/PayPal/Venmo/etc: [Peer (peer.xyz)](https://peer.xyz)
1154
+ 4. Know someone with crypto? Ask them to send USDC to my address.
1155
+
1156
+ **Option B — Pay workers directly with fiat:**
1157
+ I can find workers who accept payment platforms you already use (Wise, PayPal, Venmo, Revolut, etc.). You'd pay them directly — no crypto needed.
1158
+
1159
+ **Think about what works best for you** — consider what accounts you already have, whether you or anyone you know holds crypto, and what payment methods are common where you are. I can help figure out the easiest path.
1160
+
1161
+ Which option works best for you?`;
1162
+ return {
1163
+ content: [{
1164
+ type: 'text',
1165
+ text: JSON.stringify({
1166
+ currentBalance: balance,
1167
+ walletAddress: addr,
1168
+ walletNetwork: network,
1169
+ fundingMethods,
1170
+ fiatAlternative,
1171
+ message,
1172
+ }, null, 2),
1173
+ }],
1174
+ };
1175
+ }
1008
1176
  if (name === 'verify_agent_domain') {
1009
1177
  const res = await fetch(`${API_BASE}/api/agents/${args?.agent_id}/verify-domain`, {
1010
1178
  method: 'POST',
@@ -1053,13 +1221,14 @@ Your agent profile now shows a verified badge. Humans will see this when reviewi
1053
1221
  title: args?.title,
1054
1222
  description: args?.description,
1055
1223
  category: args?.category,
1056
- priceUsdc: args?.price_usdc,
1224
+ priceUsdc: args?.price_usd,
1057
1225
  paymentMode: args?.payment_mode,
1058
1226
  paymentTiming: args?.payment_timing,
1059
1227
  streamMethod: args?.stream_method,
1060
1228
  streamInterval: args?.stream_interval,
1061
- streamRateUsdc: args?.stream_rate_usdc,
1229
+ streamRateUsdc: args?.stream_rate_usd,
1062
1230
  streamMaxTicks: args?.stream_max_ticks,
1231
+ preferredPaymentMethod: args?.preferred_payment_method,
1063
1232
  callbackUrl: args?.callback_url,
1064
1233
  callbackSecret: args?.callback_secret,
1065
1234
  }),
@@ -1085,11 +1254,11 @@ Your agent profile now shows a verified badge. Humans will see this when reviewi
1085
1254
  **Job ID:** ${job.id}
1086
1255
  **Status:** ${job.status}
1087
1256
  **Human:** ${human.name}
1088
- **Price:** $${args?.price_usdc} USDC
1257
+ **Price:** $${args?.price_usd}${args?.preferred_payment_method ? `\n**Payment Preference:** ${args.preferred_payment_method}` : ''}
1089
1258
 
1090
1259
  ⏳ **Next Step:** Wait for ${human.name} to accept the offer.${webhookNote}
1091
1260
 
1092
- Once accepted, you can send payment to their wallet and use \`mark_job_paid\` to record the transaction.`,
1261
+ Once accepted, you'll see their accepted payment methods (crypto wallets, PayPal, etc.) and can pay via any method they support. Use \`mark_job_paid\` to record the transaction.`,
1093
1262
  },
1094
1263
  ],
1095
1264
  };
@@ -1104,12 +1273,14 @@ Once accepted, you can send payment to their wallet and use \`mark_job_paid\` to
1104
1273
  PENDING: '⏳',
1105
1274
  ACCEPTED: '✅',
1106
1275
  REJECTED: '❌',
1276
+ PAYMENT_PENDING_CONFIRMATION: '🔔',
1107
1277
  PAID: '💰',
1108
1278
  STREAMING: '🔄',
1109
1279
  PAUSED: '⏸️',
1110
1280
  COMPLETED: '🎉',
1111
1281
  CANCELLED: '🚫',
1112
1282
  DISPUTED: '⚠️',
1283
+ PAYMENT_EXPIRED: '⌛',
1113
1284
  };
1114
1285
  const isStream = job.paymentMode === 'STREAM';
1115
1286
  const streamSummary = job.streamSummary;
@@ -1126,9 +1297,7 @@ Once accepted, you can send payment to their wallet and use \`mark_job_paid\` to
1126
1297
  : 'Human accepted! Use `start_stream` to lock the network/token and start sending payments.';
1127
1298
  }
1128
1299
  else {
1129
- nextStep = job.callbackUrl
1130
- ? `Human accepted! Contact info was sent to your webhook. Send $${job.priceUsdc} USDC to their wallet, then use \`mark_job_paid\` with the transaction hash.`
1131
- : `Human accepted! Send $${job.priceUsdc} USDC to their wallet, then use \`mark_job_paid\` with the transaction hash.`;
1300
+ nextStep = `Human accepted! Pay $${job.priceUsdc} via any of their accepted payment methods (use \`get_human_profile\` to see their crypto wallets and fiat options), then use \`mark_job_paid\` to record the payment.`;
1132
1301
  }
1133
1302
  break;
1134
1303
  case 'REJECTED':
@@ -1139,15 +1308,21 @@ Once accepted, you can send payment to their wallet and use \`mark_job_paid\` to
1139
1308
  break;
1140
1309
  case 'STREAMING':
1141
1310
  if (streamSummary?.method === 'SUPERFLUID') {
1142
- nextStep = `Stream active via Superfluid. Total streamed: $${streamSummary?.totalPaid || '0'} USDC. Use \`pause_stream\` or \`stop_stream\` to manage.`;
1311
+ nextStep = `Stream active via Superfluid. Total streamed: $${streamSummary?.totalPaid || '0'}. Use \`pause_stream\` or \`stop_stream\` to manage.`;
1143
1312
  }
1144
1313
  else {
1145
- nextStep = `Stream active via micro-transfer. Total paid: $${streamSummary?.totalPaid || '0'} USDC. Use \`record_stream_tick\` to submit each payment.`;
1314
+ nextStep = `Stream active via micro-transfer. Total paid: $${streamSummary?.totalPaid || '0'}. Use \`record_stream_tick\` to submit each payment.`;
1146
1315
  }
1147
1316
  break;
1148
1317
  case 'PAUSED':
1149
1318
  nextStep = 'Stream is paused. Use `resume_stream` to continue or `stop_stream` to end permanently.';
1150
1319
  break;
1320
+ case 'PAYMENT_PENDING_CONFIRMATION':
1321
+ nextStep = 'Waiting for the human to confirm they received your fiat payment. They have 7 days to confirm or dispute. Use `get_job_status` to check.';
1322
+ break;
1323
+ case 'PAYMENT_EXPIRED':
1324
+ nextStep = 'The human did not confirm receipt of your payment within 7 days. The payment claim has expired. If you did pay, contact the human directly to resolve.';
1325
+ break;
1151
1326
  case 'COMPLETED':
1152
1327
  nextStep = job.review
1153
1328
  ? `Review submitted: ${job.review.rating}/5 stars`
@@ -1163,7 +1338,7 @@ Once accepted, you can send payment to their wallet and use \`mark_job_paid\` to
1163
1338
  if (isStream && streamSummary) {
1164
1339
  streamInfo = `\n**Payment Mode:** STREAM (${streamSummary.method})
1165
1340
  **Rate:** $${streamSummary.rateUsdc || '?'}/${(streamSummary.interval || 'DAILY').toLowerCase()}
1166
- **Total Paid:** $${streamSummary.totalPaid || '0'} USDC
1341
+ **Total Paid:** $${streamSummary.totalPaid || '0'}
1167
1342
  **Ticks:** ${streamSummary.tickCount || 0}${streamSummary.maxTicks ? `/${streamSummary.maxTicks}` : ''}
1168
1343
  **Network:** ${streamSummary.network || 'Not set'}`;
1169
1344
  }
@@ -1176,7 +1351,7 @@ Once accepted, you can send payment to their wallet and use \`mark_job_paid\` to
1176
1351
  **Job ID:** ${job.id}
1177
1352
  **Status:** ${statusEmoji[job.status] || ''} ${job.status}
1178
1353
  **Title:** ${job.title}
1179
- **Price:** $${job.priceUsdc} USDC
1354
+ **Price:** $${job.priceUsdc}
1180
1355
  **Human:** ${job.human.name}
1181
1356
  ${agentInfo ? agentInfo + '\n' : ''}${streamInfo}
1182
1357
  **Next Step:** ${nextStep}`,
@@ -1185,13 +1360,16 @@ ${agentInfo ? agentInfo + '\n' : ''}${streamInfo}
1185
1360
  };
1186
1361
  }
1187
1362
  if (name === 'mark_job_paid') {
1363
+ const paymentMethod = args?.payment_method;
1364
+ const isCrypto = ['usdc', 'eth', 'sol', 'other_crypto'].includes(paymentMethod);
1188
1365
  const res = await fetch(`${API_BASE}/api/jobs/${args?.job_id}/paid`, {
1189
1366
  method: 'PATCH',
1190
1367
  headers: { 'Content-Type': 'application/json' },
1191
1368
  body: JSON.stringify({
1192
- paymentTxHash: args?.payment_tx_hash,
1193
- paymentNetwork: args?.payment_network,
1369
+ paymentTxHash: args?.payment_reference,
1370
+ paymentNetwork: isCrypto ? (args?.payment_network || 'base') : (paymentMethod || 'fiat'),
1194
1371
  paymentAmount: args?.payment_amount,
1372
+ paymentMethod: paymentMethod,
1195
1373
  }),
1196
1374
  });
1197
1375
  if (!res.ok) {
@@ -1199,23 +1377,50 @@ ${agentInfo ? agentInfo + '\n' : ''}${streamInfo}
1199
1377
  throw new Error(error.reason || error.error || `API error: ${res.status}`);
1200
1378
  }
1201
1379
  const result = await res.json();
1202
- return {
1203
- content: [
1204
- {
1205
- type: 'text',
1206
- text: `**Payment Recorded!**
1380
+ if (isCrypto) {
1381
+ return {
1382
+ content: [
1383
+ {
1384
+ type: 'text',
1385
+ text: `**Payment Verified On-Chain!**
1207
1386
 
1208
1387
  **Job ID:** ${result.id}
1209
1388
  **Status:** ${result.status}
1210
- **Transaction:** ${args?.payment_tx_hash}
1389
+ **Method:** ${paymentMethod.toUpperCase()}
1390
+ **Transaction:** ${args?.payment_reference}
1211
1391
  **Network:** ${args?.payment_network}
1212
- **Amount:** $${args?.payment_amount} USDC
1392
+ **Amount:** $${args?.payment_amount}
1213
1393
 
1214
1394
  The human can now begin work. They will mark the job as complete when finished.
1215
1395
  After completion, you can leave a review using \`leave_review\`.`,
1216
- },
1217
- ],
1218
- };
1396
+ },
1397
+ ],
1398
+ };
1399
+ }
1400
+ else {
1401
+ return {
1402
+ content: [
1403
+ {
1404
+ type: 'text',
1405
+ text: `**Fiat Payment Recorded (Pending Human Confirmation)**
1406
+
1407
+ **Job ID:** ${result.id}
1408
+ **Status:** PAYMENT_PENDING_CONFIRMATION
1409
+ **Method:** ${paymentMethod.replace('_', ' ')}
1410
+ **Reference:** ${args?.payment_reference}
1411
+ **Amount:** $${args?.payment_amount}
1412
+
1413
+ The human has been notified to confirm they received the payment. Fiat payments require human confirmation since they cannot be verified on-chain.
1414
+
1415
+ - If confirmed: job moves to PAID and work can begin.
1416
+ - If disputed: job moves to DISPUTED.
1417
+ - If no response within 7 days: payment claim expires automatically.
1418
+
1419
+ Use \`get_job_status\` to check for confirmation.`,
1420
+ },
1421
+ ],
1422
+ };
1423
+ }
1219
1424
  }
1220
1425
  if (name === 'approve_completion') {
1221
1426
  const res = await fetch(`${API_BASE}/api/jobs/${args?.job_id}/approve-completion`, {
@@ -1320,8 +1525,17 @@ ${human.humanityVerified
1320
1525
  .map((w) => `- ${w.chain || w.network}${w.label ? ` (${w.label})` : ''}${w.isPrimary ? ' ⭐' : ''}: ${w.address}`)
1321
1526
  .join('\n');
1322
1527
  const primaryWallet = (human.wallets || []).find((w) => w.isPrimary) || (human.wallets || [])[0];
1528
+ // Tiered fiat visibility: show semi-public handles (PayPal.me, Venmo, CashApp)
1529
+ // but redact sensitive bank details — human provides those directly after job acceptance
1530
+ const sensitivePatterns = /bank|iban|swift|routing|account.*number/i;
1323
1531
  const fiatInfo = (human.fiatPaymentMethods || [])
1324
- .map((f) => `- ${f.platform}${f.label ? ` (${f.label})` : ''}${f.isPrimary ? ' ⭐' : ''}: ${f.handle}`)
1532
+ .map((f) => {
1533
+ const isSensitive = sensitivePatterns.test(f.platform) || sensitivePatterns.test(f.label || '');
1534
+ if (isSensitive) {
1535
+ return `- ${f.platform}${f.label ? ` (${f.label})` : ''}${f.isPrimary ? ' ⭐' : ''}: Available — human will provide details after job acceptance`;
1536
+ }
1537
+ return `- ${f.platform}${f.label ? ` (${f.label})` : ''}${f.isPrimary ? ' ⭐' : ''}: ${f.handle}`;
1538
+ })
1325
1539
  .join('\n');
1326
1540
  const fmtFollowers = (n) => n != null ? ` (${n.toLocaleString()} followers)` : '';
1327
1541
  const socialLinks = [
@@ -1341,12 +1555,13 @@ ${human.humanityVerified
1341
1555
  - Telegram: ${human.telegram || 'Not provided'}
1342
1556
  - Signal: ${human.signal || 'Not provided'}
1343
1557
 
1344
- ## Payment Wallets
1558
+ ## Crypto Wallets
1345
1559
  ${walletInfo || 'No wallets added'}
1346
1560
  ${primaryWallet ? `\n**Preferred wallet:** ${primaryWallet.chain || primaryWallet.network} - ${primaryWallet.address}` : ''}
1347
1561
 
1348
1562
  ## Fiat Payment Methods
1349
- ${fiatInfo || 'No fiat payment methods added'}
1563
+ ${fiatInfo || 'No fiat payment methods listed'}
1564
+ ${(human.fiatPaymentMethods || []).length > 0 ? '\n_Note: Fiat payments are self-reported. The human must confirm receipt before the job is marked as paid._' : ''}
1350
1565
 
1351
1566
  ## Social Profiles
1352
1567
  ${socialLinks || 'No social profiles added'}`;
@@ -1458,7 +1673,7 @@ You can now create job offers and view full human profiles using \`get_human_pro
1458
1673
  **Activated:** ${result.activatedAt || 'Not yet'}
1459
1674
  **Expires:** ${result.activationExpiresAt || 'N/A'}
1460
1675
  **Profile views:** ${limits?.profileViewsPerDay ?? 'N/A'}/day
1461
- **Job offers:** ${jobLimit}${result.x402?.enabled ? `\n**x402 pay-per-use:** profile view ${result.x402.prices.profile_view}, job offer ${result.x402.prices.job_offer}` : ''}`,
1676
+ **Job offers:** ${jobLimit}${result.x402?.enabled ? `\n**x402 platform fees (pay-per-use):** profile view ${result.x402.prices.profile_view}, job offer ${result.x402.prices.job_offer} — these are platform access fees (USDC on Base), separate from payment you arrange with the human` : ''}`,
1462
1677
  },
1463
1678
  ],
1464
1679
  };
@@ -1583,7 +1798,7 @@ You can now create up to 15 job offers per day and view up to 50 full human prof
1583
1798
  return {
1584
1799
  content: [{
1585
1800
  type: 'text',
1586
- text: `**Tick Verified!**\n\n**Job ID:** ${result.id}\n**Status:** ${result.status}\n**Tick:** #${result.tick?.tickNumber}\n**Amount:** $${result.tick?.amount} USDC\n**Total Paid:** $${result.totalPaid} USDC${result.nextTick ? `\n\n**Next payment due:** ${result.nextTick.expectedAt}` : ''}`,
1801
+ text: `**Tick Verified!**\n\n**Job ID:** ${result.id}\n**Status:** ${result.status}\n**Tick:** #${result.tick?.tickNumber}\n**Amount:** $${result.tick?.amount}\n**Total Paid:** $${result.totalPaid}${result.nextTick ? `\n\n**Next payment due:** ${result.nextTick.expectedAt}` : ''}`,
1587
1802
  }],
1588
1803
  };
1589
1804
  }
@@ -1655,7 +1870,7 @@ You can now create up to 15 job offers per day and view up to 50 full human prof
1655
1870
  return {
1656
1871
  content: [{
1657
1872
  type: 'text',
1658
- text: `**Stream Stopped**\n\n**Job ID:** ${result.id}\n**Status:** ${result.status}\n**Total Paid:** $${result.totalPaid || '0'} USDC\n\nThe stream has ended. You can now use \`leave_review\` to rate the human.`,
1873
+ text: `**Stream Stopped**\n\n**Job ID:** ${result.id}\n**Status:** ${result.status}\n**Total Paid:** $${result.totalPaid || '0'}\n\nThe stream has ended. You can now use \`leave_review\` to rate the human.`,
1659
1874
  }],
1660
1875
  };
1661
1876
  }
@@ -1721,7 +1936,7 @@ You can now create up to 15 job offers per day and view up to 50 full human prof
1721
1936
  body: JSON.stringify({
1722
1937
  title: args?.title,
1723
1938
  description: args?.description,
1724
- budgetUsdc: args?.budget_usdc,
1939
+ budgetUsdc: args?.budget_usd,
1725
1940
  category: args?.category,
1726
1941
  requiredSkills: args?.required_skills || [],
1727
1942
  requiredEquipment: args?.required_equipment || [],
@@ -1797,7 +2012,7 @@ You can now create up to 15 job offers per day and view up to 50 full human prof
1797
2012
  const rep = l.agentReputation;
1798
2013
  const agentInfo = agent ? `${agent.name}${agent.domainVerified ? ' ✅' : ''}` : 'Unknown';
1799
2014
  const repInfo = rep?.completedJobs > 0 ? ` | ${rep.completedJobs} jobs, ${rep.avgRating ? `${rep.avgRating.toFixed(1)}★` : 'no ratings'}` : '';
1800
- return `- **${l.title}** [$${l.budgetUsdc} USDC]${l.isPro ? ' 🏆 PRO' : ''}
2015
+ return `- **${l.title}** [$${l.budgetUsdc}]${l.isPro ? ' 🏆 PRO' : ''}
1801
2016
  Agent: ${agentInfo}${repInfo}
1802
2017
  ${l.category ? `Category: ${l.category} | ` : ''}${l.workMode || 'Any'} | ${l._count?.applications || 0} applicant(s)
1803
2018
  ${l.requiredSkills?.length > 0 ? `Skills: ${l.requiredSkills.join(', ')}` : ''}
@@ -1826,7 +2041,7 @@ You can now create up to 15 job offers per day and view up to 50 full human prof
1826
2041
 
1827
2042
  **Listing ID:** ${listing.id}
1828
2043
  **Status:** ${listing.status}
1829
- **Budget:** $${listing.budgetUsdc} USDC
2044
+ **Budget:** $${listing.budgetUsdc}
1830
2045
  **Category:** ${listing.category || 'Not specified'}
1831
2046
  **Work Mode:** ${listing.workMode || 'Any'}
1832
2047
  **Expires:** ${listing.expiresAt}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "humanpages",
3
- "version": "1.2.4",
3
+ "version": "1.4.1",
4
4
  "mcpName": "io.github.human-pages-ai/humanpages",
5
- "description": "MCP server (+ OpenClaw SKILL.md) that gives AI agents access to real-world people who listed themselves to be hired by agents. 31 tools including search by skill/location/equipment, job offers, job board listings, in-job messaging, and streaming payments.",
5
+ "description": "MCP server (+ OpenClaw SKILL.md) that gives AI agents access to real-world people who listed themselves to be hired by agents. 31 tools including search by skill/location/equipment, job offers, job board listings, in-job messaging, streaming payments, and agent funding.",
6
6
  "main": "dist/index.js",
7
7
  "type": "module",
8
8
  "bin": {