apiguru-mcp 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Apiguru
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,123 @@
1
+ # apiguru-mcp (npm)
2
+
3
+ Live Amazon marketplace data for AI agents as MCP tools: product details,
4
+ reviews, keyword search, best-sellers, deals, live offers and stock, and seller
5
+ profiles across 20 country marketplaces. Eleven read-only tools with prices and
6
+ retry rules in their descriptions.
7
+
8
+ ```bash
9
+ npx -y apiguru-mcp
10
+ ```
11
+
12
+ That is the whole install. Node 18+ is the only requirement: no Python, no
13
+ `uv`, no account, no API key.
14
+
15
+ <!-- mcp-name: app.apiguru/amazon-data -->
16
+
17
+ ## What it runs
18
+
19
+ `npx apiguru-mcp` is a stdio bridge to the hosted server at
20
+ `https://mcp.apiguru.app/mcp`: your MCP client talks stdio to the bridge, the
21
+ bridge talks streamable HTTP to the server, and every JSON-RPC message passes
22
+ through untouched. You get exactly the tools `uvx apiguru-mcp` (the Python
23
+ package) serves locally, because that package is itself a thin HTTP client over
24
+ the same gateway.
25
+
26
+ Free probes are counted per caller, since the connection to the gateway comes
27
+ from your machine rather than from a shared vendor address.
28
+
29
+ Prefer to run the server itself? `npx apiguru-mcp --local` runs the Python
30
+ package through `uvx` (needs [uv](https://docs.astral.sh/uv/)).
31
+
32
+ ## Client setup
33
+
34
+ **Claude Code**
35
+
36
+ ```bash
37
+ claude mcp add apiguru -- npx -y apiguru-mcp
38
+ # or remote, nothing to run locally:
39
+ claude mcp add --transport http apiguru https://mcp.apiguru.app/mcp
40
+ ```
41
+
42
+ **Codex CLI**
43
+
44
+ ```bash
45
+ codex mcp add apiguru -- npx -y apiguru-mcp
46
+ ```
47
+
48
+ **Cursor, Windsurf, Claude Desktop, Hermes, OpenClaw, any stdio client**
49
+
50
+ ```json
51
+ {
52
+ "mcpServers": {
53
+ "apiguru": {
54
+ "command": "npx",
55
+ "args": ["-y", "apiguru-mcp"],
56
+ "env": { "APIGURU_API_KEY": "optional-key-here" }
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ Drop the `env` block to run keyless.
63
+
64
+ **VS Code** (`.vscode/mcp.json`)
65
+
66
+ ```json
67
+ {
68
+ "servers": {
69
+ "apiguru": { "type": "stdio", "command": "npx", "args": ["-y", "apiguru-mcp"] }
70
+ }
71
+ }
72
+ ```
73
+
74
+ **claude.ai, Claude Desktop connectors, ChatGPT**: no bridge needed. Add
75
+ `https://mcp.apiguru.app/account` as a connector and sign in; calls bill your
76
+ Apiguru account.
77
+
78
+ ## Paying for calls
79
+
80
+ Without a key you get 3 free calls per 24 hours per machine. After that a tool
81
+ call returns a structured error carrying an HTTP 402 payment challenge (x402,
82
+ USDC on Base mainnet). Either:
83
+
84
+ - set `APIGURU_API_KEY` from https://dash.apiguru.app so calls bill your
85
+ account at your plan's rates, or
86
+ - have an x402-capable HTTP client pay the challenge against the REST gateway
87
+ at `https://agent.apiguru.app/agent/v1/...` directly. The full guide is in
88
+ `https://agent.apiguru.app/llms.txt`.
89
+
90
+ ## Options
91
+
92
+ | Flag / variable | Meaning |
93
+ |---|---|
94
+ | `--url <url>` / `APIGURU_MCP_URL` | Bridge to another streamable-HTTP MCP server (default `https://mcp.apiguru.app/mcp`) |
95
+ | `--local [args...]` | Run the Python server via `uvx apiguru-mcp` instead; remaining arguments are passed through |
96
+ | `APIGURU_API_KEY` | Sent as `X-API-KEY`; bills that Apiguru account instead of using the keyless path |
97
+ | `APIGURU_MCP_DEBUG` | Log transport noise to stderr |
98
+ | `--version`, `--help` | |
99
+
100
+ ## Tools
101
+
102
+ | Tool | Does | Price |
103
+ |---|---|---|
104
+ | `list_capabilities` | Endpoints, prices, marketplaces, your access mode | **free**, offline |
105
+ | `product_details` | Full record for one ASIN | $0.01 |
106
+ | `product_details_batch` | Up to 20 ASINs at once | $0.008/item |
107
+ | `product_reviews` | Reviews, rating, "customers say" | $0.01 |
108
+ | `search` | Keyword search with filters and sorting | $0.01 |
109
+ | `offers_stock` | Offers, buy box, live stock (≤10 ASINs) | $0.015/item |
110
+ | `best_sellers` | Category rankings | $0.01 |
111
+ | `deals` | Current discounts with filters | $0.01 |
112
+ | `seller_profile_batch` | Seller profiles (≤10 IDs) | $0.012/item |
113
+ | `seller_products` | A seller's catalogue | $0.01 |
114
+ | `seller_reviews` | Seller feedback | $0.01 |
115
+
116
+ Every tool is annotated `readOnlyHint: true`; nothing here writes anywhere.
117
+
118
+ ## Links
119
+
120
+ - Source, skill and plugin: https://github.com/apiguru-app/agent-kit
121
+ - Python package: https://pypi.org/project/apiguru-mcp/
122
+ - API docs: https://dash.apiguru.app/docs
123
+ - Support: support@apiguru.app
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * apiguru-mcp: the Apiguru Amazon Data MCP server from npx, with nothing but
4
+ * Node installed.
5
+ *
6
+ * npx apiguru-mcp # stdio <-> https://mcp.apiguru.app/mcp
7
+ * npx apiguru-mcp --url <mcp url> # bridge to another streamable-HTTP server
8
+ * npx apiguru-mcp --local # run the Python server via uvx (needs uv)
9
+ *
10
+ * The default mode is a transparent stdio-to-streamable-HTTP bridge. Every
11
+ * JSON-RPC message from the local client is POSTed to the hosted server and
12
+ * every reply is written back, so the client sees exactly the 11 tools that
13
+ * `uvx apiguru-mcp` would serve locally. The Python package is a thin HTTP
14
+ * client over the same gateway anyway, so nothing is lost by running it on
15
+ * our side instead of yours.
16
+ *
17
+ * Free probes are counted per caller, because the connection to the gateway
18
+ * originates from THIS machine, not from a shared vendor address.
19
+ *
20
+ * Environment:
21
+ * APIGURU_API_KEY optional; sent as X-API-KEY so calls bill that account
22
+ * instead of using the free-probe-then-402 path
23
+ * APIGURU_MCP_URL optional; same as --url
24
+ * APIGURU_MCP_DEBUG set to anything to log transport noise to stderr
25
+ */
26
+ import { spawn } from "node:child_process";
27
+ import { createRequire } from "node:module";
28
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
29
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
30
+
31
+ const { version } = createRequire(import.meta.url)("../package.json");
32
+ const DEFAULT_URL = "https://mcp.apiguru.app/mcp";
33
+ const ACCOUNT_URL = "https://mcp.apiguru.app/account";
34
+
35
+ const argv = process.argv.slice(2);
36
+ const has = (flag) => argv.includes(flag);
37
+ const valueOf = (flag) => {
38
+ const i = argv.indexOf(flag);
39
+ if (i === -1) return undefined;
40
+ const v = argv[i + 1];
41
+ if (v === undefined || v.startsWith("--")) fail(`${flag} needs a value`);
42
+ return v;
43
+ };
44
+
45
+ function fail(message, code = 2) {
46
+ process.stderr.write(`apiguru-mcp: ${message}\n`);
47
+ process.exit(code);
48
+ }
49
+
50
+ if (has("--help") || has("-h")) {
51
+ process.stdout.write(
52
+ [
53
+ `apiguru-mcp ${version}`,
54
+ "",
55
+ "Usage:",
56
+ ` apiguru-mcp bridge stdio to ${DEFAULT_URL}`,
57
+ " apiguru-mcp --url <url> bridge stdio to another MCP streamable-HTTP URL",
58
+ " apiguru-mcp --local [...] run the Python server with uvx instead (needs uv;",
59
+ " extra arguments are passed through to it)",
60
+ "",
61
+ "Environment:",
62
+ " APIGURU_API_KEY bill an Apiguru account (sent as X-API-KEY); omit to stay keyless",
63
+ " APIGURU_MCP_URL default for --url",
64
+ "",
65
+ "Docs: https://github.com/apiguru-app/agent-kit",
66
+ "",
67
+ ].join("\n"),
68
+ );
69
+ process.exit(0);
70
+ }
71
+ if (has("--version") || has("-V")) {
72
+ process.stdout.write(`${version}\n`);
73
+ process.exit(0);
74
+ }
75
+
76
+ if (has("--local")) {
77
+ runLocal(argv.filter((a) => a !== "--local"));
78
+ } else {
79
+ await runBridge();
80
+ }
81
+
82
+ // ---------------------------------------------------------------------------
83
+
84
+ function runLocal(args) {
85
+ const child = spawn("uvx", ["apiguru-mcp", ...args], { stdio: "inherit" });
86
+ child.on("error", (err) => {
87
+ if (err.code === "ENOENT") {
88
+ fail(
89
+ "`uvx` was not found. Install uv (https://docs.astral.sh/uv/) or drop " +
90
+ "--local to use the hosted server, which needs nothing else.",
91
+ 127,
92
+ );
93
+ }
94
+ fail(err.message, 1);
95
+ });
96
+ child.on("exit", (code, signal) => process.exit(code ?? (signal ? 1 : 0)));
97
+ for (const sig of ["SIGINT", "SIGTERM"]) {
98
+ process.on(sig, () => child.kill(sig));
99
+ }
100
+ }
101
+
102
+ async function runBridge() {
103
+ let url;
104
+ try {
105
+ url = new URL(valueOf("--url") || process.env.APIGURU_MCP_URL || DEFAULT_URL);
106
+ } catch {
107
+ fail("--url must be an absolute http(s) URL");
108
+ }
109
+
110
+ const headers = {
111
+ "User-Agent": `apiguru-mcp-npm/${version} node/${process.versions.node}`,
112
+ };
113
+ const apiKey = (process.env.APIGURU_API_KEY || "").trim();
114
+ if (apiKey) headers["X-API-KEY"] = apiKey;
115
+
116
+ const remote = new StreamableHTTPClientTransport(url, { requestInit: { headers } });
117
+ const local = new StdioServerTransport();
118
+
119
+ let closing = false;
120
+ const shutdown = async (code = 0) => {
121
+ if (closing) return;
122
+ closing = true;
123
+ await Promise.allSettled([remote.close(), local.close()]);
124
+ process.exit(code);
125
+ };
126
+
127
+ // Server -> client: responses and server notifications pass straight through.
128
+ remote.onmessage = (message) => {
129
+ local.send(message).catch((err) => {
130
+ process.stderr.write(`apiguru-mcp: cannot write to client: ${err.message}\n`);
131
+ shutdown(1);
132
+ });
133
+ };
134
+ remote.onerror = (err) => {
135
+ // Transport noise that is not tied to a request, e.g. the optional GET
136
+ // stream that a stateless server answers with 405. Failing requests are
137
+ // answered individually below, so this is only logged on demand.
138
+ if (process.env.APIGURU_MCP_DEBUG) {
139
+ process.stderr.write(`apiguru-mcp: remote: ${err.message}\n`);
140
+ }
141
+ };
142
+ remote.onclose = () => shutdown(0);
143
+
144
+ // Client -> server: a request that cannot reach the server gets a JSON-RPC
145
+ // error back instead of leaving the client waiting forever.
146
+ local.onmessage = async (message) => {
147
+ try {
148
+ await remote.send(message);
149
+ } catch (err) {
150
+ const isRequest =
151
+ message && typeof message === "object" && "method" in message && "id" in message;
152
+ const detail = describe(err, url);
153
+ if (isRequest) {
154
+ await local
155
+ .send({ jsonrpc: "2.0", id: message.id, error: { code: -32000, message: detail } })
156
+ .catch(() => {});
157
+ } else {
158
+ process.stderr.write(`apiguru-mcp: ${detail}\n`);
159
+ }
160
+ }
161
+ };
162
+ local.onerror = (err) => process.stderr.write(`apiguru-mcp: stdio: ${err.message}\n`);
163
+ local.onclose = () => shutdown(0);
164
+
165
+ for (const sig of ["SIGINT", "SIGTERM"]) process.on(sig, () => shutdown(0));
166
+
167
+ await remote.start();
168
+ await local.start();
169
+ }
170
+
171
+ function describe(err, url) {
172
+ const msg = err && err.message ? err.message : String(err);
173
+ if (err && err.name === "UnauthorizedError") {
174
+ return (
175
+ `${url.host} requires a sign-in this bridge cannot perform. Use the keyless ` +
176
+ `${DEFAULT_URL}, or add ${ACCOUNT_URL} as a connector in a client that supports OAuth.`
177
+ );
178
+ }
179
+ if (/ENOTFOUND|ECONNREFUSED|EAI_AGAIN|fetch failed/i.test(msg)) {
180
+ return `cannot reach ${url.host}: ${msg}. Check the network, or run with --local to use the Python server via uvx.`;
181
+ }
182
+ return `bridge to ${url.host} failed: ${msg}`;
183
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "apiguru-mcp",
3
+ "version": "1.1.1",
4
+ "description": "Live Amazon marketplace data for AI agents as MCP tools: product details, reviews, keyword search, best-sellers, deals, live offers and stock, and seller profiles across 20 countries. `npx apiguru-mcp` needs only Node 18+ - no Python, no uv, no API key.",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "modelcontextprotocol",
9
+ "mcp-server",
10
+ "amazon",
11
+ "ecommerce",
12
+ "product-data",
13
+ "scraping",
14
+ "x402",
15
+ "agent",
16
+ "claude",
17
+ "cursor",
18
+ "codex"
19
+ ],
20
+ "homepage": "https://apiguru.app",
21
+ "bugs": {
22
+ "url": "https://github.com/apiguru-app/agent-kit/issues",
23
+ "email": "support@apiguru.app"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/apiguru-app/agent-kit.git",
28
+ "directory": "npm"
29
+ },
30
+ "license": "MIT",
31
+ "author": "Apiguru <support@apiguru.app> (https://apiguru.app)",
32
+ "type": "module",
33
+ "bin": {
34
+ "apiguru-mcp": "bin/apiguru-mcp.mjs"
35
+ },
36
+ "files": [
37
+ "bin/",
38
+ "README.md",
39
+ "LICENSE"
40
+ ],
41
+ "engines": {
42
+ "node": ">=18"
43
+ },
44
+ "scripts": {
45
+ "test": "node test/smoke.mjs"
46
+ },
47
+ "dependencies": {
48
+ "@modelcontextprotocol/sdk": "^1.30.0"
49
+ },
50
+ "mcpName": "app.apiguru/amazon-data"
51
+ }