gadgethumans-mcp 1.0.16 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -11
- package/index.js +106 -245
- package/package.json +15 -7
package/README.md
CHANGED
|
@@ -1,21 +1,46 @@
|
|
|
1
1
|
# gadgethumans-mcp
|
|
2
2
|
|
|
3
|
-
MCP server for the **GadgetHumans API Hub**:
|
|
4
|
-
|
|
3
|
+
MCP server for the **GadgetHumans API Hub**: 224 tools — web search, page reads and scraping to markdown,
|
|
4
|
+
Base token safety verdicts, prediction markets, OCR, ENS, DNS/WHOIS, crypto prices, geocoding, text/LLM
|
|
5
|
+
utilities — plus a free cross-bazaar x402 search.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
The tool list is fetched live from `https://api.gadgethumans.com/mcp` at startup, so it always matches what
|
|
8
|
+
the server actually sells: every tool arrives with its real parameter schema, price and description.
|
|
9
|
+
|
|
10
|
+
## Two ways to pay
|
|
11
|
+
|
|
12
|
+
**1. Prepaid credits — works in any MCP client, no wallet:**
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
https://api.gadgethumans.com/buy-credits?pack=500 # $5 = 500 calls
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The purchase returns an `api_key`. Set it and restart:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
export GADGETHUMANS_API_KEY=gh_...
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**2. x402 — USDC on Base, only if your client can sign the payment itself:**
|
|
25
|
+
|
|
26
|
+
An unpaid call returns `HTTP 402` with an x402 `accepts[]` challenge (also in the `Payment-Required`
|
|
27
|
+
header). Settle it and retry with an `X-PAYMENT` header. USDC on Base, chainId 8453.
|
|
28
|
+
|
|
29
|
+
This package never asks for a wallet private key — it is a proxy, and signing belongs in the client that
|
|
30
|
+
owns the key.
|
|
7
31
|
|
|
8
32
|
## Free: cross-bazaar x402 discovery
|
|
9
33
|
|
|
10
|
-
|
|
34
|
+
`x402_search` searches **both live x402 bazaars plus this catalogue** in one call, ranked by measured
|
|
35
|
+
30-day call volume:
|
|
11
36
|
|
|
12
37
|
```
|
|
13
38
|
GET https://api.gadgethumans.com/discovery/search?q=whois&limit=10
|
|
14
39
|
```
|
|
15
40
|
|
|
16
|
-
Merges `facilitator.payai.network` (14,841 listings), `api.cdp.coinbase.com` (73,178 listings) and
|
|
17
|
-
|
|
18
|
-
|
|
41
|
+
Merges `facilitator.payai.network` (14,841 listings), `api.cdp.coinbase.com` (73,178 listings) and this
|
|
42
|
+
catalogue. Returns `{ query, count, sources, results: [{ resource, source, price_usd, calls_30d, payTo,
|
|
43
|
+
description }] }`. No key, no payment, cached 900s, 120 queries/hour/IP.
|
|
19
44
|
|
|
20
45
|
Use it to compare providers and prices **before** paying any x402 endpoint.
|
|
21
46
|
|
|
@@ -26,13 +51,14 @@ npx -y gadgethumans-mcp
|
|
|
26
51
|
```
|
|
27
52
|
|
|
28
53
|
```json
|
|
29
|
-
{ "mcpServers": { "gadgethumans": { "command": "npx", "args": ["-y", "gadgethumans-mcp"]
|
|
54
|
+
{ "mcpServers": { "gadgethumans": { "command": "npx", "args": ["-y", "gadgethumans-mcp"],
|
|
55
|
+
"env": { "GADGETHUMANS_API_KEY": "gh_..." } } } }
|
|
30
56
|
```
|
|
31
57
|
|
|
32
|
-
##
|
|
58
|
+
## Free tier
|
|
33
59
|
|
|
34
|
-
|
|
35
|
-
|
|
60
|
+
The MCP door allows 5 calls/day per IP without payment; the REST door allows 100 requests/day per IP.
|
|
61
|
+
Prices per tool are in `tools/list` (`price_usd`) and in the OpenAPI document.
|
|
36
62
|
|
|
37
63
|
## Links
|
|
38
64
|
|
package/index.js
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
|
|
4
|
+
// Thin MCP client for the GadgetHumans API (https://api.gadgethumans.com/mcp).
|
|
5
|
+
//
|
|
6
|
+
// The remote server is the single source of truth for the tool list, so nothing
|
|
7
|
+
// here can drift from it: this package forwards tools/list and tools/call over
|
|
8
|
+
// JSON-RPC and adds an optional x-api-key (prepaid credits) header.
|
|
9
|
+
//
|
|
10
|
+
// It never touches a wallet private key. x402 signing belongs in the client that
|
|
11
|
+
// owns the key; a proxy must not be handed one.
|
|
12
|
+
|
|
4
13
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
5
14
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
15
|
import {
|
|
@@ -8,280 +17,132 @@ import {
|
|
|
8
17
|
ListToolsRequestSchema,
|
|
9
18
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
10
19
|
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const
|
|
20
|
+
const ENDPOINT = process.env.MCP_ENDPOINT || "https://api.gadgethumans.com/mcp";
|
|
21
|
+
const API_KEY =
|
|
22
|
+
process.env.GADGETHUMANS_API_KEY || process.env.GADGETHUMANS_CREDITS_KEY || "";
|
|
23
|
+
const BUY_URL = "https://api.gadgethumans.com/buy-credits";
|
|
15
24
|
|
|
16
25
|
const server = new Server(
|
|
17
|
-
{ name: "gadgethumans-mcp", version: "1.0
|
|
26
|
+
{ name: "gadgethumans-mcp", version: "1.1.0" },
|
|
18
27
|
{ capabilities: { tools: {} } }
|
|
19
28
|
);
|
|
20
29
|
|
|
21
|
-
|
|
22
|
-
// Category groups for organization
|
|
23
|
-
const CATEGORIES = [
|
|
24
|
-
{ name: "Security & Network", count: 18, tools: [
|
|
25
|
-
"dns_lookup", "check_ssl_certificate", "port_check", "domain_age",
|
|
26
|
-
"dnssec_check", "reverse_dns_lookup", "cdn_detect", "email_domain_check",
|
|
27
|
-
"http_headers", "check_links", "check_page_size", "ipv4_subnet",
|
|
28
|
-
"ipv6_expand", "dns_whois_lookup", "whois", "ssl_chain_check",
|
|
29
|
-
"traceroute", "ping"
|
|
30
|
-
]},
|
|
31
|
-
{ name: "Data & Weather", count: 14, tools: [
|
|
32
|
-
"get_weather", "get_forecast", "get_air_quality", "get_crypto_prices",
|
|
33
|
-
"convert_currency", "currency_cross", "geocode", "reverse_geocode",
|
|
34
|
-
"geolocate_ip", "get_season", "get_week_number", "list_countries",
|
|
35
|
-
"list_currencies", "list_languages"
|
|
36
|
-
]},
|
|
37
|
-
{ name: "Text & Encoding", count: 28, tools: [
|
|
38
|
-
"hash_text", "encode_base64", "encode_base32", "encode_base85",
|
|
39
|
-
"binary_convert", "morse_code", "url_encode_decode", "html_escape",
|
|
40
|
-
"string_escape", "regex_escape", "normalize_text", "remove_accents",
|
|
41
|
-
"convert_case", "slugify_text", "title_case", "invert_case",
|
|
42
|
-
"swap_case", "reverse_text", "shuffle_text", "truncate_text",
|
|
43
|
-
"pad_text", "indent_text", "line_wrap", "clean_whitespace",
|
|
44
|
-
"wrap_text", "expand_text", "simplify_text", "casualize"
|
|
45
|
-
]},
|
|
46
|
-
{ name: "Colors & Design", count: 16, tools: [
|
|
47
|
-
"convert_color", "hex_to_hsl", "hex_to_hsv", "hex_to_cmyk",
|
|
48
|
-
"hsl_to_rgb", "hsv_to_hex", "cmyk_to_hex", "rgb_to_hsl",
|
|
49
|
-
"color_mix", "complementary_color", "color_harmony",
|
|
50
|
-
"generate_color_palette", "color_tint_shade", "color_temperature",
|
|
51
|
-
"color_blindness_sim", "check_color_contrast", "web_safe_color",
|
|
52
|
-
"color_named", "list_color_names", "random_color"
|
|
53
|
-
]},
|
|
54
|
-
{ name: "Finance & Math", count: 30, tools: [
|
|
55
|
-
"loan_calculator", "mortgage_calculator", "compound_interest",
|
|
56
|
-
"simple_interest_calc", "investment_calculator", "sip_calc",
|
|
57
|
-
"emi_calc", "amortization_calc", "auto_loan_calc",
|
|
58
|
-
"credit_card_payoff", "retirement_calc", "savings_goal_calc",
|
|
59
|
-
"roi_calc", "cagr_calc", "stock_return", "dividend_calc",
|
|
60
|
-
"bond_yield", "inflation_calc", "tax_bracket", "salary_breakdown",
|
|
61
|
-
"margin_calc", "markup_calc", "discount_calculator",
|
|
62
|
-
"percentage_calculator", "percentage_change_calc",
|
|
63
|
-
"descriptive_statistics", "calculate_correlation",
|
|
64
|
-
"matrix_operations", "quadratic_solver", "pythagorean_calc"
|
|
65
|
-
]},
|
|
66
|
-
{ name: "JSON & Data", count: 12, tools: [
|
|
67
|
-
"process_json", "validate_json", "json_path_query", "flatten_json",
|
|
68
|
-
"unflatten_json", "merge_json", "convert_json_to_csv",
|
|
69
|
-
"convert_csv_to_json", "json_to_yaml", "json_to_xml",
|
|
70
|
-
"toml_to_json", "ini_to_json", "xml_to_json", "yaml_to_json"
|
|
71
|
-
]},
|
|
72
|
-
{ name: "Content & AI", count: 16, tools: [
|
|
73
|
-
"summarize", "paraphrase", "translate", "grammar", "proofread",
|
|
74
|
-
"headline", "keywords", "sentiment", "classify", "explain",
|
|
75
|
-
"faq", "questions", "quiz", "social", "bullets", "tldr"
|
|
76
|
-
]},
|
|
77
|
-
{ name: "Health & Fitness", count: 14, tools: [
|
|
78
|
-
"calculate_bmi", "bmr_calc", "tdee_calc", "body_fat_calc",
|
|
79
|
-
"ideal_weight_calc", "lean_body_mass", "macro_calc",
|
|
80
|
-
"calorie_burn", "water_intake_calc", "heart_rate_zones",
|
|
81
|
-
"fitness_age_calc", "vo2max_calc", "sleep_calc", "body_surface_area"
|
|
82
|
-
]},
|
|
83
|
-
{ name: "Generators", count: 8, tools: [
|
|
84
|
-
"generate_password", "generate_uuid", "generate_nanoid",
|
|
85
|
-
"generate_ulids", "generate_qr_code", "generate_lorem_ipsum",
|
|
86
|
-
"generate_random_numbers", "generate_random_data"
|
|
87
|
-
]},
|
|
88
|
-
{ name: "Kronos Market Intel", count: 7, tools: [
|
|
89
|
-
"kronos_signals", "kronos_history", "kronos_preflight",
|
|
90
|
-
"kronos_decision", "kronos_audit", "kronos_forecast", "kronos_risk"
|
|
91
|
-
]},
|
|
92
|
-
{ name: "Converters", count: 12, tools: [
|
|
93
|
-
"convert_units", "temperature_all", "speed_convert",
|
|
94
|
-
"pressure_convert", "energy_convert", "volume_convert",
|
|
95
|
-
"area_convert", "data_rate_convert", "angle_convert",
|
|
96
|
-
"time_convert", "bytes_format", "convert_number_base"
|
|
97
|
-
]},
|
|
98
|
-
{ name: "Web & SEO", count: 10, tools: [
|
|
99
|
-
"read_url", "web_scrape", "parse_rss_feed", "crawl_website",
|
|
100
|
-
"get_og_metadata", "scrape_meta_tags", "generate_seo_metadata",
|
|
101
|
-
"research_topic", "extract_contacts", "readability_url"
|
|
102
|
-
]},
|
|
103
|
-
{ name: "x402 & Wallet", count: 5, tools: [
|
|
104
|
-
"x402_wallet_info", "x402_pricing", "x402_payment_request",
|
|
105
|
-
"x402_verify_payment", "wallet_info"
|
|
106
|
-
]},
|
|
107
|
-
{ name: "Other Utilities", count: 147, tools: [
|
|
108
|
-
"generate_password", "generate_uuid", "generate_nanoid",
|
|
109
|
-
"generate_ulids", "generate_qr_code", "generate_lorem_ipsum",
|
|
110
|
-
"generate_random_numbers", "generate_random_data",
|
|
111
|
-
"evaluate_math", "factorial_calculator", "fibonacci_sequence",
|
|
112
|
-
"prime_operations", "gcd_lcm", "fraction_calc", "ratio_calc",
|
|
113
|
-
"proportion_calc", "percentage_calculator", "percentage_change_calc",
|
|
114
|
-
"calculate_combinations", "calculate_entropy", "scientific_notation",
|
|
115
|
-
"significant_figures", "roman_numerals", "nato_phonetic",
|
|
116
|
-
"soundex_code", "levenshtein_distance", "word_similarity",
|
|
117
|
-
"anagram_check", "palindrome_check", "pangram_check",
|
|
118
|
-
"word_count", "char_count", "line_count", "sentence_length_analyze",
|
|
119
|
-
"paragraph_count", "punctuation_count", "unique_words",
|
|
120
|
-
"word_frequency", "word_length_distribution", "keyword_density",
|
|
121
|
-
"repeated_words", "find_long_words", "find_short_words",
|
|
122
|
-
"caps_analysis", "whitespace_analyze", "readability_analyze",
|
|
123
|
-
"reading_time", "speaking_time", "detect_language",
|
|
124
|
-
"detect_text_encoding", "gibberish_detect", "extract_entities",
|
|
125
|
-
"analyze_tone", "validate_email", "verify_email",
|
|
126
|
-
"validate_iban", "validate_vat", "parse_phone_number",
|
|
127
|
-
"mask_text", "text_stats", "text_diff", "deduplicate_data",
|
|
128
|
-
"filter_data", "sort_data", "code_stats", "code_complexity",
|
|
129
|
-
"code_indent_check", "comment_strip", "code_beautify",
|
|
130
|
-
"bracket_match", "todo_finder", "sql_format",
|
|
131
|
-
"regex_test", "convert_markdown", "extract_html_table",
|
|
132
|
-
"generate_color_palette", "color_tint_shade", "random_color",
|
|
133
|
-
"date_calc", "calculate_age", "calculate_business_days",
|
|
134
|
-
"due_date_calc", "ovulation_calc", "calculate_distance",
|
|
135
|
-
"distance_2d", "midpoint_calc", "slope_calc", "geometry_calc",
|
|
136
|
-
"electrical_calc", "force_calc", "pressure_calc",
|
|
137
|
-
"work_calc", "kinetic_energy_calc", "momentum_calc",
|
|
138
|
-
"density_calc", "gravitational_force_calc", "heart_rate_zones",
|
|
139
|
-
"metabolic_age_calc", "fitness_age_calc", "waist_hip_ratio",
|
|
140
|
-
"calorie_burn", "bmr_calc", "tdee_calc", "body_fat_calc",
|
|
141
|
-
"ideal_weight_calc", "lean_body_mass", "macro_calc",
|
|
142
|
-
"water_intake_calc", "sleep_calc", "body_surface_area",
|
|
143
|
-
"blood_alcohol_calc", "tip_calculator", "fuel_cost",
|
|
144
|
-
"pace_calc", "rent_vs_buy_calc", "vat_calc",
|
|
145
|
-
"temperature_all", "pressure_convert", "speed_convert",
|
|
146
|
-
"energy_convert", "volume_convert", "area_convert",
|
|
147
|
-
"time_convert", "data_rate_convert", "angle_convert",
|
|
148
|
-
"bytes_format", "convert_number_base", "pixel_convert",
|
|
149
|
-
"paper_size_reference", "keyboard_layout",
|
|
150
|
-
"list_color_names", "list_emojis", "lookup_html_entity",
|
|
151
|
-
"lookup_http_code", "lookup_mime_type", "chemical_elements",
|
|
152
|
-
"ascii_table", "caesar_cipher", "atbash_cipher",
|
|
153
|
-
"rot13_cipher", "vigenere_cipher", "flip_coin", "roll_dice"
|
|
154
|
-
]}
|
|
155
|
-
];
|
|
30
|
+
let TOOLS = [];
|
|
156
31
|
|
|
157
|
-
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
32
|
+
function rpcHeaders() {
|
|
33
|
+
const h = {
|
|
34
|
+
"Content-Type": "application/json",
|
|
35
|
+
Accept: "application/json, text/event-stream",
|
|
36
|
+
};
|
|
37
|
+
if (API_KEY) h["x-api-key"] = API_KEY;
|
|
38
|
+
return h;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// The remote door answers with plain JSON; tolerate an SSE frame in case a proxy
|
|
42
|
+
// in front of it flips the content type.
|
|
43
|
+
function parseBody(text, contentType) {
|
|
44
|
+
if ((contentType || "").includes("event-stream")) {
|
|
45
|
+
const line = text.split("\n").find((l) => l.trim().startsWith("data:"));
|
|
46
|
+
if (!line) throw new Error("empty event-stream response");
|
|
47
|
+
return JSON.parse(line.trim().slice(5).trim());
|
|
174
48
|
}
|
|
49
|
+
return JSON.parse(text);
|
|
175
50
|
}
|
|
176
51
|
|
|
177
|
-
|
|
52
|
+
async function rpc(method, params) {
|
|
53
|
+
const res = await fetch(ENDPOINT, {
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: rpcHeaders(),
|
|
56
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params: params || {} }),
|
|
57
|
+
});
|
|
58
|
+
const text = await res.text();
|
|
59
|
+
return { res, text };
|
|
60
|
+
}
|
|
178
61
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
})
|
|
62
|
+
async function loadTools() {
|
|
63
|
+
try {
|
|
64
|
+
const { res, text } = await rpc("tools/list", {});
|
|
65
|
+
if (!res.ok) throw new Error("tools/list http " + res.status);
|
|
66
|
+
const d = parseBody(text, res.headers.get("content-type"));
|
|
67
|
+
if (d.error) throw new Error(d.error.message || "tools/list error");
|
|
68
|
+
TOOLS = (d.result && d.result.tools) || [];
|
|
69
|
+
} catch (e) {
|
|
70
|
+
console.error(`[gadgethumans-mcp] could not load tool list: ${e.message}`);
|
|
71
|
+
TOOLS = [];
|
|
72
|
+
}
|
|
73
|
+
return TOOLS;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
77
|
+
if (!TOOLS.length) await loadTools();
|
|
78
|
+
return { tools: TOOLS };
|
|
79
|
+
});
|
|
182
80
|
|
|
183
81
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
184
|
-
const { name, arguments: args } = request.params;
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (!tool) {
|
|
188
|
-
return {
|
|
189
|
-
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
|
190
|
-
isError: true,
|
|
191
|
-
};
|
|
82
|
+
const { name, arguments: args } = request.params || {};
|
|
83
|
+
if (!name) {
|
|
84
|
+
return { content: [{ type: "text", text: "Missing tool name." }], isError: true };
|
|
192
85
|
}
|
|
193
86
|
|
|
194
87
|
try {
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
88
|
+
const { res, text } = await rpc("tools/call", { name, arguments: args || {} });
|
|
89
|
+
|
|
90
|
+
if (res.status === 402) {
|
|
91
|
+
const hint = API_KEY
|
|
92
|
+
? `The credits key on this install has no balance left. Top up at ${BUY_URL}?pack=500 ($5 = 500 calls) and set GADGETHUMANS_API_KEY to the key it returns.`
|
|
93
|
+
: [
|
|
94
|
+
"This tool is priced per call. Two ways to pay:",
|
|
95
|
+
"",
|
|
96
|
+
"1. Prepaid credits — works in any MCP client, no wallet needed:",
|
|
97
|
+
` buy at ${BUY_URL}?pack=500 ($5 = 500 calls; 1 credit = $0.01)`,
|
|
98
|
+
" the purchase returns an api_key; set it and restart:",
|
|
99
|
+
" export GADGETHUMANS_API_KEY=gh_...",
|
|
100
|
+
"",
|
|
101
|
+
"2. x402 — USDC on Base, only if your client can sign the payment itself:",
|
|
102
|
+
" an unpaid call returns accepts[] with amount and payTo; settle it and",
|
|
103
|
+
" retry with the X-PAYMENT header.",
|
|
104
|
+
" Catalogue: https://api.gadgethumans.com/.well-known/x402",
|
|
105
|
+
"",
|
|
106
|
+
`All packs and prices: ${BUY_URL}`,
|
|
107
|
+
].join("\n");
|
|
108
|
+
return {
|
|
109
|
+
content: [{ type: "text", text: `Payment required.\n\n${hint}` }],
|
|
110
|
+
isError: false,
|
|
111
|
+
};
|
|
208
112
|
}
|
|
209
113
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
114
|
+
if (!res.ok) {
|
|
115
|
+
return {
|
|
116
|
+
content: [{ type: "text", text: `HTTP ${res.status}: ${text.slice(0, 400)}` }],
|
|
117
|
+
isError: true,
|
|
118
|
+
};
|
|
213
119
|
}
|
|
214
120
|
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
headers,
|
|
218
|
-
body: JSON.stringify({
|
|
219
|
-
jsonrpc: "2.0",
|
|
220
|
-
method: "tools/call",
|
|
221
|
-
params: { name, arguments: args || {} },
|
|
222
|
-
id: 1,
|
|
223
|
-
}),
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
if (!response.ok) {
|
|
227
|
-
const text = await response.text();
|
|
228
|
-
|
|
229
|
-
// Handle 402 Payment Required
|
|
230
|
-
if (response.status === 402) {
|
|
231
|
-
const price = response.headers.get("X-402-Price") || "$0.001";
|
|
232
|
-
const merchant = response.headers.get("X-402-Merchant") || "";
|
|
233
|
-
return {
|
|
234
|
-
content: [{
|
|
235
|
-
type: "text",
|
|
236
|
-
text: [
|
|
237
|
-
`⚠️ Payment Required — ${price} USDC`,
|
|
238
|
-
``,
|
|
239
|
-
`This tool costs ${price} USDC on Base.`,
|
|
240
|
-
`Merchant: ${merchant}`,
|
|
241
|
-
``,
|
|
242
|
-
`PAY WITH A CARD — no wallet, no signup, credits applied instantly:`,
|
|
243
|
-
` https://api.gadgethumans.com/buy-credits?pack=500`,
|
|
244
|
-
``,
|
|
245
|
-
`OR let your agent pay automatically over x402:`,
|
|
246
|
-
` export WALLET_PRIVATE_KEY=0x...`,
|
|
247
|
-
`Your agent then signs USDC micropayments on Base with no manual steps.`,
|
|
248
|
-
``,
|
|
249
|
-
`All options and prices: https://api.gadgethumans.com/buy-credits`,
|
|
250
|
-
].join("\n"),
|
|
251
|
-
}],
|
|
252
|
-
isError: false,
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
|
|
121
|
+
const d = parseBody(text, res.headers.get("content-type"));
|
|
122
|
+
if (d.error) {
|
|
256
123
|
return {
|
|
257
|
-
content: [{ type: "text", text: `Error ${
|
|
124
|
+
content: [{ type: "text", text: `Error: ${d.error.message || JSON.stringify(d.error)}` }],
|
|
258
125
|
isError: true,
|
|
259
126
|
};
|
|
260
127
|
}
|
|
261
128
|
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
return {
|
|
266
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
267
|
-
};
|
|
129
|
+
const result = d.result !== undefined ? d.result : d;
|
|
130
|
+
if (result && Array.isArray(result.content)) return result;
|
|
131
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
268
132
|
} catch (error) {
|
|
269
|
-
return {
|
|
270
|
-
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
271
|
-
isError: true,
|
|
272
|
-
};
|
|
133
|
+
return { content: [{ type: "text", text: `Error: ${error.message}` }], isError: true };
|
|
273
134
|
}
|
|
274
135
|
});
|
|
275
136
|
|
|
276
|
-
// ── Startup ───────────────────────────────────────────────
|
|
277
|
-
|
|
278
137
|
async function main() {
|
|
279
|
-
|
|
280
|
-
await
|
|
281
|
-
console.error(`[gadgethumans-mcp]
|
|
282
|
-
console.error(
|
|
283
|
-
|
|
284
|
-
|
|
138
|
+
await server.connect(new StdioServerTransport());
|
|
139
|
+
await loadTools();
|
|
140
|
+
console.error(`[gadgethumans-mcp] ${TOOLS.length} tools from ${ENDPOINT}`);
|
|
141
|
+
console.error(
|
|
142
|
+
`[gadgethumans-mcp] credits key: ${
|
|
143
|
+
API_KEY ? "set" : "not set — paid tools answer 402 with instructions"
|
|
144
|
+
}`
|
|
145
|
+
);
|
|
285
146
|
}
|
|
286
147
|
|
|
287
148
|
main().catch((e) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gadgethumans-mcp",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "MCP server for the GadgetHumans API: 216 tools in one install (ocr, ens, token safety, translate, sentiment, whois, hash, geocode, dns, weather, vat, timezone, ip, search, and a free x402 catalogue search ranked by measured 30-day call volume). Prepaid credits key or x402 USDC on Base.",
|
|
5
5
|
"mcpName": "com.gadgethumans/gadgethumans-mcp",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "index.js",
|
|
@@ -29,7 +29,18 @@
|
|
|
29
29
|
"crypto-payments",
|
|
30
30
|
"gadgethumans",
|
|
31
31
|
"claude",
|
|
32
|
-
"cursor"
|
|
32
|
+
"cursor",
|
|
33
|
+
"ocr",
|
|
34
|
+
"token-safety",
|
|
35
|
+
"honeypot-check",
|
|
36
|
+
"ens",
|
|
37
|
+
"translate",
|
|
38
|
+
"sentiment",
|
|
39
|
+
"whois",
|
|
40
|
+
"web-search",
|
|
41
|
+
"pay-per-call",
|
|
42
|
+
"agent-payments",
|
|
43
|
+
"discovery"
|
|
33
44
|
],
|
|
34
45
|
"author": "GadgetHumans",
|
|
35
46
|
"license": "MIT",
|
|
@@ -38,10 +49,7 @@
|
|
|
38
49
|
"url": "git+https://github.com/gadgethumans-dev/api-hub.git"
|
|
39
50
|
},
|
|
40
51
|
"dependencies": {
|
|
41
|
-
"@modelcontextprotocol/sdk": "^1.10.0"
|
|
42
|
-
"@x402/core": "^2.17.0",
|
|
43
|
-
"@x402/evm": "^2.17.0",
|
|
44
|
-
"viem": "^2.27.0"
|
|
52
|
+
"@modelcontextprotocol/sdk": "^1.10.0"
|
|
45
53
|
},
|
|
46
54
|
"engines": {
|
|
47
55
|
"node": ">=18.0.0"
|