@nordsym/apiclaw 1.8.1 → 1.8.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 NordSym AB
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/apiclaw-README.md CHANGED
@@ -12,12 +12,18 @@ The API layer for AI agents. 18 providers → 1000s of capabilities. Workspace
12
12
  [![npm downloads](https://img.shields.io/npm/dw/@nordsym/apiclaw.svg)](https://www.npmjs.com/package/@nordsym/apiclaw)
13
13
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
14
14
  [![MCP](https://img.shields.io/badge/MCP-Compatible-blue)](https://modelcontextprotocol.io)
15
+ [![GitHub Stars](https://img.shields.io/github/stars/nordsym/apiclaw?style=social)](https://github.com/nordsym/apiclaw)
16
+ [![Built with MCP](https://img.shields.io/badge/Built%20with-MCP-purple)](https://modelcontextprotocol.io)
17
+
18
+ > **If APIClaw saves you time, [⭐ star the repo](https://github.com/nordsym/apiclaw) — it helps more developers find us.**
19
+
20
+ ![APIClaw Demo](landing/public/demo.gif)
15
21
 
16
22
  ---
17
23
 
18
24
  ## The Platform
19
25
 
20
- **[apiclaw.com](https://apiclaw.com)** — Your workspace for API-powered agents.
26
+ **[apiclaw.nordsym.com](https://apiclaw.nordsym.com)** — Your workspace for API-powered agents.
21
27
 
22
28
  | Layer | What You Get |
23
29
  |-------|--------------|
@@ -51,12 +57,52 @@ That's it. All 18 Direct Call providers work instantly through NordSym's infrast
51
57
  **Usage Limits:**
52
58
  - **Anonymous:** 10 calls/week (no registration)
53
59
  - **Registered:** 50 calls/week (5x more)
54
- - **Upgrade:** Contact us for higher limits
60
+ - **Upgrade:** See [Pricing](#pricing) below
55
61
 
56
62
  Start calling APIs immediately. No setup, no API keys, no configuration.
57
63
 
58
64
  ---
59
65
 
66
+ ## End-to-End Example
67
+
68
+ Here's a complete agent workflow — send an SMS, generate an image, and search the web in one session:
69
+
70
+ ```javascript
71
+ // 1. Register for 50 calls/week
72
+ register_owner({ email: "you@example.com" })
73
+
74
+ // 2. Send an SMS via 46elks
75
+ call_api({
76
+ provider: "46elks",
77
+ action: "send_sms",
78
+ params: {
79
+ to: "+46701234567",
80
+ message: "APIClaw is live! 🦞"
81
+ }
82
+ })
83
+
84
+ // 3. Generate an image via Replicate
85
+ call_api({
86
+ provider: "replicate",
87
+ action: "run",
88
+ params: {
89
+ model: "stability-ai/sdxl",
90
+ input: { prompt: "a lobster wearing a top hat, digital art" }
91
+ }
92
+ })
93
+
94
+ // 4. Search the web via Brave
95
+ call_api({
96
+ provider: "brave",
97
+ action: "search",
98
+ params: { q: "MCP protocol AI agents 2025", count: 5 }
99
+ })
100
+ ```
101
+
102
+ All three calls go through APIClaw's proxy — zero API keys, zero configuration.
103
+
104
+ ---
105
+
60
106
  ## What You Get
61
107
 
62
108
  ### Instant API Access
@@ -148,7 +194,7 @@ Public APIs, instantly callable. No API keys needed.
148
194
  - Food & Recipes
149
195
  - Science & Education
150
196
 
151
- Browse at [apiclaw.com/open-apis](https://apiclaw.com/open-apis)
197
+ Browse at [apiclaw.nordsym.com/open-apis](https://apiclaw.nordsym.com/open-apis)
152
198
 
153
199
  ---
154
200
 
@@ -163,7 +209,7 @@ Use `discover_apis` to search:
163
209
  "What APIs exist for recipe data?"
164
210
  ```
165
211
 
166
- Browse at [apiclaw.com/discover](https://apiclaw.com/discover)
212
+ Browse at [apiclaw.nordsym.com/discover](https://apiclaw.nordsym.com/discover)
167
213
 
168
214
  ---
169
215
 
@@ -358,7 +404,7 @@ You don't manage API keys. You don't configure auth. You don't worry about rate
358
404
  - Usage analytics in your workspace
359
405
  - Production-ready from day one
360
406
 
361
- **Want higher limits?** Upgrade at [apiclaw.com](https://apiclaw.com) or contact us.
407
+ **Want higher limits?** See [Pricing](#pricing) below or upgrade at [apiclaw.nordsym.com](https://apiclaw.nordsym.com).
362
408
 
363
409
  ---
364
410
 
@@ -379,12 +425,66 @@ Returns the exact request that *would* be sent, with mock response data.
379
425
 
380
426
  ---
381
427
 
428
+ ## Why APIClaw?
429
+
430
+ | | **APIClaw** | **RapidAPI** | **Direct API Keys** | **Kong / custom gateway** |
431
+ |---|---|---|---|---|
432
+ | **Setup time** | `curl \| bash` (30 sec) | Account + per-API signup | Per-provider signup | Hours of config |
433
+ | **API keys to manage** | 0 | Per API | 1 per provider | 1 per provider |
434
+ | **Providers covered** | 18 premium + 1,636 open | 40,000+ (DIY) | 1 at a time | Any (DIY) |
435
+ | **MCP-native** | ✅ First-class | ❌ | ❌ | ❌ |
436
+ | **Works in AI agents** | ✅ Out of the box | ⚠️ Manual wiring | ⚠️ Manual wiring | ⚠️ Manual wiring |
437
+ | **Free tier** | ✅ 50 calls/week | ✅ Limited | Varies | ❌ |
438
+ | **Self-hosted option** | ✅ | ❌ | — | ✅ |
439
+
440
+ APIClaw is purpose-built for AI agents and MCP clients. No glue code, no key juggling — just call the API.
441
+
442
+ ---
443
+
444
+ ## Social Proof
445
+
446
+ **9,000+ npm installs** · 88 versions shipped · Used in Claude Agents, GPT Builders, and Codex workflows worldwide.
447
+
448
+ ---
449
+
450
+ ## Pricing
451
+
452
+ | Plan | Price | Calls/month | Best for |
453
+ |------|-------|-------------|----------|
454
+ | **Free** | $0 | 50 | Exploring, prototyping |
455
+ | **Pro** | $79/mo | 5,000 | Solo builders & small teams |
456
+ | **Scale** | $249/mo | 25,000 | Production agents |
457
+ | **Enterprise** | Custom | Unlimited | Large teams & custom SLAs |
458
+
459
+ → [Upgrade at apiclaw.nordsym.com](https://apiclaw.nordsym.com) · Enterprise: [book a call](https://apiclaw.nordsym.com/contact)
460
+
461
+ ---
462
+
463
+ ## AI Discoverability
464
+
465
+ APIClaw is optimized for discovery by AI agents and LLM tooling:
466
+
467
+ - **llms.txt:** [apiclaw.nordsym.com/llms.txt](https://apiclaw.nordsym.com/llms.txt) — Machine-readable API index
468
+ - **llms-full.txt:** [apiclaw.nordsym.com/llms-full.txt](https://apiclaw.nordsym.com/llms-full.txt) — Full capability descriptions
469
+ - **ai-plugin.json:** [apiclaw.nordsym.com/.well-known/ai-plugin.json](https://apiclaw.nordsym.com/.well-known/ai-plugin.json) — OpenAI plugin manifest
470
+ - **MCP:** Install with one command and any MCP-compatible agent can use APIClaw immediately
471
+
472
+ ---
473
+
474
+ ## Contributing & Changelog
475
+
476
+ - [CONTRIBUTING.md](apiclaw-CONTRIBUTING.md) — How to contribute
477
+ - [CHANGELOG.md](apiclaw-CHANGELOG.md) — Release history
478
+
479
+ ---
480
+
382
481
  ## Links
383
482
 
384
- - **Platform:** [apiclaw.com](https://apiclaw.com)
483
+ - **Platform:** [apiclaw.nordsym.com](https://apiclaw.nordsym.com)
385
484
  - **Docs:** [apiclaw.nordsym.com/docs](https://apiclaw.nordsym.com/docs)
386
485
  - **GitHub:** [github.com/nordsym/apiclaw](https://github.com/nordsym/apiclaw)
387
486
  - **npm:** [@nordsym/apiclaw](https://www.npmjs.com/package/@nordsym/apiclaw)
487
+ - **Security:** [SECURITY.md](SECURITY.md)
388
488
 
389
489
  ---
390
490
 
package/dist/index.js CHANGED
@@ -1,49 +1,48 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- var __create = Object.create;
4
- var __defProp = Object.defineProperty;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
- // If the importer is in node compatibility mode or this is not an ESM
19
- // file that has been converted to a CommonJS file using a Babel-
20
- // compatible transform (i.e. "__esModule" has not been set), then set
21
- // "default" to the CommonJS "module.exports" for node compatibility.
22
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
- mod
24
- ));
25
- var import_server = require("@modelcontextprotocol/sdk/server/index.js");
26
- var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
27
- var import_types = require("@modelcontextprotocol/sdk/types.js");
28
- var import_discovery = require("./discovery.js");
29
- var import_telemetry = require("./telemetry.js");
30
- var import_credits = require("./credits.js");
31
- var import_credentials = require("./credentials.js");
32
- var import_execute = require("./execute.js");
33
- var import_metered = require("./metered.js");
34
- var import_mcp_analytics = require("./mcp-analytics.js");
35
- var import_open_apis = require("./open-apis.js");
36
- var import_proxy = require("./proxy.js");
37
- var import_confirmation = require("./confirmation.js");
38
- var import_capability_router = require("./capability-router.js");
39
- var import_session = require("./session.js");
40
- var import_browser = require("convex/browser");
41
- var import_stripe = require("./stripe.js");
42
- var import_metered2 = require("./metered.js");
43
- var import_chainExecutor = require("./chainExecutor.js");
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import {
5
+ CallToolRequestSchema,
6
+ ListToolsRequestSchema
7
+ } from "@modelcontextprotocol/sdk/types.js";
8
+ import { discoverAPIs, getAPIDetails, getCategories, getAllAPIs } from "./discovery.js";
9
+ import { trackStartup, trackSearch } from "./telemetry.js";
10
+ import {
11
+ addCredits,
12
+ purchaseAPIAccess,
13
+ getBalanceSummary
14
+ } from "./credits.js";
15
+ import { hasRealCredentials } from "./credentials.js";
16
+ import { getConnectedProviders } from "./execute.js";
17
+ import { executeMetered } from "./metered.js";
18
+ import { logAPICall } from "./mcp-analytics.js";
19
+ import { isOpenAPI, executeOpenAPI, listOpenAPIs } from "./open-apis.js";
20
+ import { PROXY_PROVIDERS } from "./proxy.js";
21
+ import {
22
+ requiresConfirmationAsync,
23
+ createPendingAction,
24
+ consumePendingAction,
25
+ generatePreview,
26
+ validateParams
27
+ } from "./confirmation.js";
28
+ import { executeCapability, listCapabilities, hasCapability } from "./capability-router.js";
29
+ import { readSession, writeSession, clearSession, getMachineFingerprint, detectMCPClient } from "./session.js";
30
+ import { ConvexHttpClient } from "convex/browser";
31
+ import {
32
+ getOrCreateCustomer,
33
+ createMeteredCheckoutSession,
34
+ getUsageSummary,
35
+ METERED_BILLING
36
+ } from "./stripe.js";
37
+ import { estimateCost } from "./metered.js";
38
+ import {
39
+ executeChain,
40
+ getChainStatus,
41
+ resumeChain
42
+ } from "./chainExecutor.js";
44
43
  const DEFAULT_AGENT_ID = "agent_default";
45
44
  const CONVEX_URL = process.env.CONVEX_URL || "https://adventurous-avocet-799.convex.cloud";
46
- const convex = new import_browser.ConvexHttpClient(CONVEX_URL);
45
+ const convex = new ConvexHttpClient(CONVEX_URL);
47
46
  let workspaceContext = null;
48
47
  let currentAgentId = null;
49
48
  const anonymousRateLimits = /* @__PURE__ */ new Map();
@@ -100,9 +99,11 @@ function checkAnonymousRateLimit(fingerprint) {
100
99
  allowed: false,
101
100
  error: JSON.stringify({
102
101
  success: false,
103
- error: `Monthly limit reached (${ANONYMOUS_WEEKLY_LIMIT} calls)`,
104
- hint: "Register to get 50 calls/month",
102
+ error: `\u26A1 You've hit your free tier limit (${ANONYMOUS_WEEKLY_LIMIT} calls/week).
103
+ Upgrade: https://apiclaw.nordsym.com/upgrade`,
104
+ hint: "Register for 50 calls/week, or upgrade for unlimited",
105
105
  action: "Run: register_owner({ email: 'you@example.com' })",
106
+ upgrade_url: "https://apiclaw.nordsym.com/upgrade",
106
107
  retry_after: getNextMonthUTC()
107
108
  }, null, 2)
108
109
  };
@@ -112,7 +113,7 @@ function checkAnonymousRateLimit(fingerprint) {
112
113
  return { allowed: true };
113
114
  }
114
115
  async function validateSession() {
115
- const session = (0, import_session.readSession)();
116
+ const session = readSession();
116
117
  if (!session) {
117
118
  console.error("[APIClaw] No session found. Use register_owner to authenticate.");
118
119
  return false;
@@ -123,7 +124,7 @@ async function validateSession() {
123
124
  });
124
125
  if (!result.authenticated) {
125
126
  console.error("[APIClaw] Session invalid or expired. Clearing...");
126
- (0, import_session.clearSession)();
127
+ clearSession();
127
128
  return false;
128
129
  }
129
130
  if (result.status !== "active") {
@@ -167,9 +168,9 @@ async function trackEarnProgress(workspaceId, provider, action) {
167
168
  const rateLimitStore = /* @__PURE__ */ new Map();
168
169
  const UNREGISTERED_CALL_LIMIT = 5;
169
170
  function checkWorkspaceAccess(providerId) {
170
- if (providerId && import_proxy.PROXY_PROVIDERS.includes(providerId)) {
171
+ if (providerId && PROXY_PROVIDERS.includes(providerId)) {
171
172
  if (!workspaceContext) {
172
- const fingerprint = (0, import_session.getMachineFingerprint)();
173
+ const fingerprint = getMachineFingerprint();
173
174
  const rateLimitCheck = checkAnonymousRateLimit(fingerprint);
174
175
  if (!rateLimitCheck.allowed) {
175
176
  return {
@@ -211,7 +212,8 @@ function checkWorkspaceAccess(providerId) {
211
212
  allowed: false,
212
213
  error: JSON.stringify({
213
214
  success: false,
214
- error: `Monthly limit reached (${FREE_MONTHLY_LIMIT} calls)`,
215
+ error: `\u26A1 You've hit your free tier limit (${FREE_MONTHLY_LIMIT} calls/week).
216
+ Upgrade: https://apiclaw.nordsym.com/upgrade`,
215
217
  hint: "Upgrade to Backer for unlimited calls",
216
218
  upgrade_url: "https://apiclaw.nordsym.com/upgrade",
217
219
  retry_after: getNextMonthUTC()
@@ -220,7 +222,8 @@ function checkWorkspaceAccess(providerId) {
220
222
  }
221
223
  return {
222
224
  allowed: false,
223
- error: `Usage limit reached. Contact support or check your plan at https://apiclaw.nordsym.com/account`
225
+ error: `\u26A1 You've hit your free tier limit (${FREE_MONTHLY_LIMIT} calls/week).
226
+ Upgrade: https://apiclaw.nordsym.com/upgrade`
224
227
  };
225
228
  }
226
229
  return { allowed: true, isAnonymous: false };
@@ -664,7 +667,7 @@ Example chain:
664
667
  }
665
668
  }
666
669
  ];
667
- const server = new import_server.Server(
670
+ const server = new Server(
668
671
  {
669
672
  name: "apivault",
670
673
  version: "0.1.0"
@@ -675,10 +678,10 @@ const server = new import_server.Server(
675
678
  }
676
679
  }
677
680
  );
678
- server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
681
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
679
682
  return { tools };
680
683
  });
681
- server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
684
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
682
685
  const { name, arguments: args } = request.params;
683
686
  try {
684
687
  switch (name) {
@@ -729,10 +732,10 @@ Docs: https://apiclaw.nordsym.com
729
732
  const subagentId = args?.subagent_id;
730
733
  const aiBackend = args?.ai_backend;
731
734
  const startTime = Date.now();
732
- const results = (0, import_discovery.discoverAPIs)(query, { category, maxResults, region });
735
+ const results = discoverAPIs(query, { category, maxResults, region });
733
736
  const responseTimeMs = Date.now() - startTime;
734
- (0, import_telemetry.trackSearch)(query, results.length, responseTimeMs);
735
- const analyticsUserId = workspaceContext?.workspaceId || `anon:${(0, import_session.getMachineFingerprint)()}`;
737
+ trackSearch(query, results.length, responseTimeMs);
738
+ const analyticsUserId = workspaceContext?.workspaceId || `anon:${getMachineFingerprint()}`;
736
739
  const convexUrl = CONVEX_URL;
737
740
  if (convexUrl) {
738
741
  fetch(`${convexUrl}/api/mutation`, {
@@ -822,7 +825,7 @@ Docs: https://apiclaw.nordsym.com
822
825
  text: JSON.stringify({
823
826
  status: "no_results",
824
827
  message: `No APIs found matching "${query}". Try broader terms or check available categories with list_categories.`,
825
- available_categories: (0, import_discovery.getCategories)()
828
+ available_categories: getCategories()
826
829
  }, null, 2)
827
830
  }
828
831
  ]
@@ -856,7 +859,7 @@ Docs: https://apiclaw.nordsym.com
856
859
  case "get_api_details": {
857
860
  const apiId = args?.api_id;
858
861
  const compact = args?.compact || false;
859
- const api = (0, import_discovery.getAPIDetails)(apiId, { compact });
862
+ const api = getAPIDetails(apiId, { compact });
860
863
  if (!api) {
861
864
  return {
862
865
  content: [
@@ -897,7 +900,7 @@ Docs: https://apiclaw.nordsym.com
897
900
  const apiId = args?.api_id;
898
901
  const amountUsd = args?.amount_usd;
899
902
  const agentId = args?.agent_id || DEFAULT_AGENT_ID;
900
- const result = (0, import_credits.purchaseAPIAccess)(agentId, apiId, amountUsd);
903
+ const result = purchaseAPIAccess(agentId, apiId, amountUsd);
901
904
  if (!result.success) {
902
905
  return {
903
906
  content: [
@@ -911,7 +914,7 @@ Docs: https://apiclaw.nordsym.com
911
914
  ]
912
915
  };
913
916
  }
914
- const api = (0, import_discovery.getAPIDetails)(apiId);
917
+ const api = getAPIDetails(apiId);
915
918
  return {
916
919
  content: [
917
920
  {
@@ -925,7 +928,7 @@ Docs: https://apiclaw.nordsym.com
925
928
  amount_paid_usd: amountUsd,
926
929
  credits_received: result.purchase.credits_purchased,
927
930
  status: result.purchase.status,
928
- real_credentials: (0, import_credentials.hasRealCredentials)(apiId)
931
+ real_credentials: hasRealCredentials(apiId)
929
932
  },
930
933
  credentials: result.purchase.credentials,
931
934
  access: {
@@ -940,7 +943,7 @@ Docs: https://apiclaw.nordsym.com
940
943
  }
941
944
  case "check_balance": {
942
945
  const agentId = args?.agent_id || DEFAULT_AGENT_ID;
943
- const summary = (0, import_credits.getBalanceSummary)(agentId);
946
+ const summary = getBalanceSummary(agentId);
944
947
  return {
945
948
  content: [
946
949
  {
@@ -957,7 +960,7 @@ Docs: https://apiclaw.nordsym.com
957
960
  provider: p.provider_id,
958
961
  credits_remaining: p.credits_purchased,
959
962
  status: p.status,
960
- real_credentials: (0, import_credentials.hasRealCredentials)(p.provider_id)
963
+ real_credentials: hasRealCredentials(p.provider_id)
961
964
  }))
962
965
  }, null, 2)
963
966
  }
@@ -967,7 +970,7 @@ Docs: https://apiclaw.nordsym.com
967
970
  case "add_credits": {
968
971
  const amountUsd = args?.amount_usd;
969
972
  const agentId = args?.agent_id || DEFAULT_AGENT_ID;
970
- const credits = (0, import_credits.addCredits)(agentId, amountUsd);
973
+ const credits = addCredits(agentId, amountUsd);
971
974
  return {
972
975
  content: [
973
976
  {
@@ -982,10 +985,10 @@ Docs: https://apiclaw.nordsym.com
982
985
  };
983
986
  }
984
987
  case "list_categories": {
985
- const categories = (0, import_discovery.getCategories)();
988
+ const categories = getCategories();
986
989
  const apisByCategory = {};
987
990
  for (const cat of categories) {
988
- apisByCategory[cat] = (0, import_discovery.getAllAPIs)().filter((a) => a.category === cat).map((a) => a.id);
991
+ apisByCategory[cat] = getAllAPIs().filter((a) => a.category === cat).map((a) => a.id);
989
992
  }
990
993
  return {
991
994
  content: [
@@ -1064,7 +1067,7 @@ Docs: https://apiclaw.nordsym.com
1064
1067
  const chainOptions = {
1065
1068
  verbose: false
1066
1069
  };
1067
- const chainResult = await (0, import_chainExecutor.executeChain)(
1070
+ const chainResult = await executeChain(
1068
1071
  chainDefinition,
1069
1072
  chainCredentials,
1070
1073
  {},
@@ -1142,7 +1145,7 @@ Docs: https://apiclaw.nordsym.com
1142
1145
  }]
1143
1146
  };
1144
1147
  }
1145
- const isFreeAPI = (0, import_open_apis.isOpenAPI)(provider);
1148
+ const isFreeAPI = isOpenAPI(provider);
1146
1149
  if (!isFreeAPI) {
1147
1150
  const access = checkWorkspaceAccess(provider);
1148
1151
  if (!access.allowed) {
@@ -1163,7 +1166,7 @@ Docs: https://apiclaw.nordsym.com
1163
1166
  let result;
1164
1167
  let apiType;
1165
1168
  if (confirmToken) {
1166
- const pending = (0, import_confirmation.consumePendingAction)(confirmToken);
1169
+ const pending = consumePendingAction(confirmToken);
1167
1170
  if (!pending) {
1168
1171
  return {
1169
1172
  content: [{
@@ -1179,13 +1182,13 @@ Docs: https://apiclaw.nordsym.com
1179
1182
  apiType = "direct";
1180
1183
  const customerKey = args?.customer_key || getCustomerKey(pending.provider);
1181
1184
  const stripeCustomerId = args?.stripe_customer_id || process.env.APICLAW_STRIPE_CUSTOMER_ID;
1182
- result = await (0, import_metered.executeMetered)(pending.provider, pending.action, pending.params, {
1185
+ result = await executeMetered(pending.provider, pending.action, pending.params, {
1183
1186
  customerId: stripeCustomerId,
1184
1187
  customerKey,
1185
1188
  userId: DEFAULT_AGENT_ID
1186
1189
  });
1187
- const analyticsUserId2 = workspaceContext ? workspaceContext.workspaceId : `anon:${(0, import_session.getMachineFingerprint)()}`;
1188
- (0, import_mcp_analytics.logAPICall)({
1190
+ const analyticsUserId2 = workspaceContext ? workspaceContext.workspaceId : `anon:${getMachineFingerprint()}`;
1191
+ logAPICall({
1189
1192
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1190
1193
  provider: pending.provider,
1191
1194
  action: pending.action,
@@ -1212,10 +1215,10 @@ Docs: https://apiclaw.nordsym.com
1212
1215
  isError: !result.success
1213
1216
  };
1214
1217
  }
1215
- const confirmCheck = await (0, import_confirmation.requiresConfirmationAsync)(provider, action);
1218
+ const confirmCheck = await requiresConfirmationAsync(provider, action);
1216
1219
  if (confirmCheck.required) {
1217
1220
  if (!confirmCheck.isDynamic) {
1218
- const validation = (0, import_confirmation.validateParams)(provider, action, params);
1221
+ const validation = validateParams(provider, action, params);
1219
1222
  if (!validation.valid) {
1220
1223
  return {
1221
1224
  content: [{
@@ -1231,11 +1234,11 @@ Docs: https://apiclaw.nordsym.com
1231
1234
  };
1232
1235
  }
1233
1236
  }
1234
- const preview = (0, import_confirmation.generatePreview)(provider, action, params);
1237
+ const preview = generatePreview(provider, action, params);
1235
1238
  if (confirmCheck.estimatedCost) {
1236
1239
  preview.estimated_cost = confirmCheck.estimatedCost;
1237
1240
  }
1238
- const pending = (0, import_confirmation.createPendingAction)(provider, action, params, preview, DEFAULT_AGENT_ID);
1241
+ const pending = createPendingAction(provider, action, params, preview, DEFAULT_AGENT_ID);
1239
1242
  return {
1240
1243
  content: [{
1241
1244
  type: "text",
@@ -1250,21 +1253,21 @@ Docs: https://apiclaw.nordsym.com
1250
1253
  }]
1251
1254
  };
1252
1255
  }
1253
- if ((0, import_open_apis.isOpenAPI)(provider)) {
1256
+ if (isOpenAPI(provider)) {
1254
1257
  apiType = "open";
1255
- result = await (0, import_open_apis.executeOpenAPI)(provider, action, params);
1258
+ result = await executeOpenAPI(provider, action, params);
1256
1259
  } else {
1257
1260
  apiType = "direct";
1258
1261
  const customerKey = args?.customer_key || getCustomerKey(provider);
1259
1262
  const stripeCustomerId = args?.stripe_customer_id || process.env.APICLAW_STRIPE_CUSTOMER_ID;
1260
- result = await (0, import_metered.executeMetered)(provider, action, params, {
1263
+ result = await executeMetered(provider, action, params, {
1261
1264
  customerId: stripeCustomerId,
1262
1265
  customerKey,
1263
1266
  userId: DEFAULT_AGENT_ID
1264
1267
  });
1265
1268
  }
1266
- const analyticsUserId = workspaceContext ? workspaceContext.workspaceId : `anon:${(0, import_session.getMachineFingerprint)()}`;
1267
- (0, import_mcp_analytics.logAPICall)({
1269
+ const analyticsUserId = workspaceContext ? workspaceContext.workspaceId : `anon:${getMachineFingerprint()}`;
1270
+ logAPICall({
1268
1271
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1269
1272
  provider,
1270
1273
  action,
@@ -1338,8 +1341,8 @@ Docs: https://apiclaw.nordsym.com
1338
1341
  };
1339
1342
  }
1340
1343
  case "list_connected": {
1341
- const directProviders = (0, import_execute.getConnectedProviders)();
1342
- const openProviders = (0, import_open_apis.listOpenAPIs)();
1344
+ const directProviders = getConnectedProviders();
1345
+ const openProviders = listOpenAPIs();
1343
1346
  return {
1344
1347
  content: [
1345
1348
  {
@@ -1383,9 +1386,9 @@ Docs: https://apiclaw.nordsym.com
1383
1386
  }).catch(() => {
1384
1387
  });
1385
1388
  }
1386
- const exists = await (0, import_capability_router.hasCapability)(capabilityId);
1389
+ const exists = await hasCapability(capabilityId);
1387
1390
  if (!exists) {
1388
- const available = await (0, import_capability_router.listCapabilities)();
1391
+ const available = await listCapabilities();
1389
1392
  return {
1390
1393
  content: [{
1391
1394
  type: "text",
@@ -1399,7 +1402,7 @@ Docs: https://apiclaw.nordsym.com
1399
1402
  isError: true
1400
1403
  };
1401
1404
  }
1402
- const result = await (0, import_capability_router.executeCapability)(
1405
+ const result = await executeCapability(
1403
1406
  capabilityId,
1404
1407
  action,
1405
1408
  params,
@@ -1425,7 +1428,7 @@ Docs: https://apiclaw.nordsym.com
1425
1428
  };
1426
1429
  }
1427
1430
  case "list_capabilities": {
1428
- const capabilities = await (0, import_capability_router.listCapabilities)();
1431
+ const capabilities = await listCapabilities();
1429
1432
  return {
1430
1433
  content: [{
1431
1434
  type: "text",
@@ -1458,13 +1461,13 @@ Docs: https://apiclaw.nordsym.com
1458
1461
  try {
1459
1462
  const existing = await convex.query("workspaces:getByEmail", { email });
1460
1463
  if (existing && existing.status === "active") {
1461
- const fingerprint2 = (0, import_session.getMachineFingerprint)();
1464
+ const fingerprint2 = getMachineFingerprint();
1462
1465
  const sessionResult = await convex.mutation("workspaces:createAgentSession", {
1463
1466
  workspaceId: existing.id,
1464
1467
  fingerprint: fingerprint2
1465
1468
  });
1466
1469
  if (sessionResult.success) {
1467
- (0, import_session.writeSession)(sessionResult.sessionToken, existing.id, email);
1470
+ writeSession(sessionResult.sessionToken, existing.id, email);
1468
1471
  try {
1469
1472
  const claimResult = await convex.mutation("workspaces:claimAnonymousUsage", {
1470
1473
  workspaceId: existing.id,
@@ -1511,7 +1514,7 @@ Docs: https://apiclaw.nordsym.com
1511
1514
  } else {
1512
1515
  throw new Error(createResult.error);
1513
1516
  }
1514
- const fingerprint = (0, import_session.getMachineFingerprint)();
1517
+ const fingerprint = getMachineFingerprint();
1515
1518
  const magicLinkResult = await convex.mutation("workspaces:createMagicLink", {
1516
1519
  email,
1517
1520
  fingerprint
@@ -1560,7 +1563,7 @@ Docs: https://apiclaw.nordsym.com
1560
1563
  }
1561
1564
  }
1562
1565
  case "check_workspace_status": {
1563
- const session = (0, import_session.readSession)();
1566
+ const session = readSession();
1564
1567
  if (!session) {
1565
1568
  return {
1566
1569
  content: [{
@@ -1577,7 +1580,7 @@ Docs: https://apiclaw.nordsym.com
1577
1580
  sessionToken: session.sessionToken
1578
1581
  });
1579
1582
  if (!result.authenticated) {
1580
- (0, import_session.clearSession)();
1583
+ clearSession();
1581
1584
  workspaceContext = null;
1582
1585
  return {
1583
1586
  content: [{
@@ -1632,7 +1635,7 @@ Docs: https://apiclaw.nordsym.com
1632
1635
  }
1633
1636
  }
1634
1637
  case "remind_owner": {
1635
- const session = (0, import_session.readSession)();
1638
+ const session = readSession();
1636
1639
  if (!session) {
1637
1640
  return {
1638
1641
  content: [{
@@ -1661,7 +1664,7 @@ Docs: https://apiclaw.nordsym.com
1661
1664
  }]
1662
1665
  };
1663
1666
  }
1664
- const fingerprint = (0, import_session.getMachineFingerprint)();
1667
+ const fingerprint = getMachineFingerprint();
1665
1668
  const magicLinkResult = await convex.mutation("workspaces:createMagicLink", {
1666
1669
  email: session.email,
1667
1670
  fingerprint
@@ -1705,7 +1708,7 @@ Docs: https://apiclaw.nordsym.com
1705
1708
  isError: true
1706
1709
  };
1707
1710
  }
1708
- const customerResult = await (0, import_stripe.getOrCreateCustomer)(email, email);
1711
+ const customerResult = await getOrCreateCustomer(email, email);
1709
1712
  if ("error" in customerResult) {
1710
1713
  return {
1711
1714
  content: [{
@@ -1715,7 +1718,7 @@ Docs: https://apiclaw.nordsym.com
1715
1718
  isError: true
1716
1719
  };
1717
1720
  }
1718
- const checkoutResult = await (0, import_stripe.createMeteredCheckoutSession)(
1721
+ const checkoutResult = await createMeteredCheckoutSession(
1719
1722
  email,
1720
1723
  success_url || "https://apiclaw.nordsym.com/billing/success",
1721
1724
  cancel_url || "https://apiclaw.nordsym.com/billing/cancel"
@@ -1758,7 +1761,7 @@ Docs: https://apiclaw.nordsym.com
1758
1761
  isError: true
1759
1762
  };
1760
1763
  }
1761
- const usage = await (0, import_stripe.getUsageSummary)(subscription_id);
1764
+ const usage = await getUsageSummary(subscription_id);
1762
1765
  if ("error" in usage) {
1763
1766
  return {
1764
1767
  content: [{
@@ -1779,7 +1782,7 @@ Docs: https://apiclaw.nordsym.com
1779
1782
  },
1780
1783
  usage: {
1781
1784
  total_calls: usage.totalCalls,
1782
- price_per_call: import_stripe.METERED_BILLING.pricePerCall,
1785
+ price_per_call: METERED_BILLING.pricePerCall,
1783
1786
  estimated_cost: `$${usage.totalCost.toFixed(4)}`
1784
1787
  }
1785
1788
  }, null, 2)
@@ -1797,7 +1800,7 @@ Docs: https://apiclaw.nordsym.com
1797
1800
  isError: true
1798
1801
  };
1799
1802
  }
1800
- const estimate = (0, import_metered2.estimateCost)(call_count);
1803
+ const estimate = estimateCost(call_count);
1801
1804
  return {
1802
1805
  content: [{
1803
1806
  type: "text",
@@ -1810,9 +1813,9 @@ Docs: https://apiclaw.nordsym.com
1810
1813
  currency: estimate.currency
1811
1814
  },
1812
1815
  examples: {
1813
- "100 calls": `$${(100 * import_stripe.METERED_BILLING.pricePerCall).toFixed(2)}`,
1814
- "1,000 calls": `$${(1e3 * import_stripe.METERED_BILLING.pricePerCall).toFixed(2)}`,
1815
- "10,000 calls": `$${(1e4 * import_stripe.METERED_BILLING.pricePerCall).toFixed(2)}`
1816
+ "100 calls": `$${(100 * METERED_BILLING.pricePerCall).toFixed(2)}`,
1817
+ "1,000 calls": `$${(1e3 * METERED_BILLING.pricePerCall).toFixed(2)}`,
1818
+ "10,000 calls": `$${(1e4 * METERED_BILLING.pricePerCall).toFixed(2)}`
1816
1819
  }
1817
1820
  }, null, 2)
1818
1821
  }]
@@ -1835,7 +1838,7 @@ Docs: https://apiclaw.nordsym.com
1835
1838
  isError: true
1836
1839
  };
1837
1840
  }
1838
- const chainStatus = await (0, import_chainExecutor.getChainStatus)(chainId);
1841
+ const chainStatus = await getChainStatus(chainId);
1839
1842
  if (chainStatus.status === "not_found") {
1840
1843
  return {
1841
1844
  content: [{
@@ -1929,7 +1932,7 @@ Docs: https://apiclaw.nordsym.com
1929
1932
  if (customerKey) {
1930
1933
  chainCredentials.customerKeys = { default: customerKey };
1931
1934
  }
1932
- const result = await (0, import_chainExecutor.resumeChain)(
1935
+ const result = await resumeChain(
1933
1936
  resumeToken,
1934
1937
  chainDefinition,
1935
1938
  chainCredentials,
@@ -2012,14 +2015,14 @@ async function main() {
2012
2015
  await startCLI();
2013
2016
  return;
2014
2017
  }
2015
- const transport = new import_stdio.StdioServerTransport();
2018
+ const transport = new StdioServerTransport();
2016
2019
  await server.connect(transport);
2017
- (0, import_telemetry.trackStartup)();
2020
+ trackStartup();
2018
2021
  const hasValidSession = await validateSession();
2019
2022
  try {
2020
- const fingerprint = (0, import_session.getMachineFingerprint)();
2021
- const mcpClient = (0, import_session.detectMCPClient)();
2022
- const existingSession = (0, import_session.readSession)();
2023
+ const fingerprint = getMachineFingerprint();
2024
+ const mcpClient = detectMCPClient();
2025
+ const existingSession = readSession();
2023
2026
  const result = await convex.mutation("agents:ensureAgent", {
2024
2027
  fingerprint,
2025
2028
  mcpClient,
@@ -2030,7 +2033,7 @@ async function main() {
2030
2033
  currentAgentId = result.agentId;
2031
2034
  }
2032
2035
  if (result?.isNew && result?.sessionToken && !hasValidSession) {
2033
- (0, import_session.writeSession)(result.sessionToken, result.workspaceId, "");
2036
+ writeSession(result.sessionToken, result.workspaceId, "");
2034
2037
  }
2035
2038
  } catch (e) {
2036
2039
  console.error("[APIClaw] Agent registration failed (non-blocking):", e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nordsym/apiclaw",
3
- "version": "1.8.1",
3
+ "version": "1.8.2",
4
4
  "description": "The API layer for AI agents. Dashboard + 22K APIs + 18 Direct Call providers. MCP native.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,6 +14,7 @@
14
14
  },
15
15
  "scripts": {
16
16
  "build": "tsc && cp -r src/registry dist/",
17
+ "postinstall": "node dist/postinstall.js || true",
17
18
  "dev": "tsx watch src/index.ts",
18
19
  "start": "node dist/index.js",
19
20
  "start:http": "tsx src/http-server-minimal.ts",
package/src/bin.ts CHANGED
@@ -6,11 +6,26 @@
6
6
  * - setup/doctor/restore/uninstall → Run CLI
7
7
  */
8
8
 
9
+ import { existsSync } from 'fs';
10
+ import { join } from 'path';
11
+
9
12
  const cliCommands = ['setup', 'mcp-install', 'mcp-uninstall', 'doctor', 'restore', 'uninstall', 'help', '--help', '-h', '--version', '-V'];
10
13
 
11
14
  const firstArg = process.argv[2];
12
15
 
13
16
  if (!firstArg || !cliCommands.includes(firstArg)) {
17
+ // First-run nudge: non-blocking hint if no workspace is configured
18
+ try {
19
+ const sessionFile = join(process.env.HOME ?? '~', '.apiclaw', 'session');
20
+ if (!existsSync(sessionFile)) {
21
+ process.stderr.write(
22
+ '\x1b[33m💡 No workspace linked. Get one free: https://apiclaw.nordsym.com/workspace\x1b[0m\n'
23
+ );
24
+ }
25
+ } catch {
26
+ // Never let this block server startup
27
+ }
28
+
14
29
  // Run MCP server
15
30
  import('./index.js');
16
31
  } else {
package/src/index.ts CHANGED
@@ -170,9 +170,10 @@ function checkAnonymousRateLimit(fingerprint: string): { allowed: boolean; error
170
170
  allowed: false,
171
171
  error: JSON.stringify({
172
172
  success: false,
173
- error: `Monthly limit reached (${ANONYMOUS_WEEKLY_LIMIT} calls)`,
174
- hint: "Register to get 50 calls/month",
173
+ error: `⚡ You've hit your free tier limit (${ANONYMOUS_WEEKLY_LIMIT} calls/week).\n Upgrade: https://apiclaw.nordsym.com/upgrade`,
174
+ hint: "Register for 50 calls/week, or upgrade for unlimited",
175
175
  action: "Run: register_owner({ email: 'you@example.com' })",
176
+ upgrade_url: "https://apiclaw.nordsym.com/upgrade",
176
177
  retry_after: getNextMonthUTC()
177
178
  }, null, 2)
178
179
  };
@@ -335,7 +336,7 @@ function checkWorkspaceAccess(providerId?: string): { allowed: boolean; error?:
335
336
  allowed: false,
336
337
  error: JSON.stringify({
337
338
  success: false,
338
- error: `Monthly limit reached (${FREE_MONTHLY_LIMIT} calls)`,
339
+ error: `⚡ You've hit your free tier limit (${FREE_MONTHLY_LIMIT} calls/week).\n Upgrade: https://apiclaw.nordsym.com/upgrade`,
339
340
  hint: "Upgrade to Backer for unlimited calls",
340
341
  upgrade_url: "https://apiclaw.nordsym.com/upgrade",
341
342
  retry_after: getNextMonthUTC()
@@ -346,7 +347,7 @@ function checkWorkspaceAccess(providerId?: string): { allowed: boolean; error?:
346
347
  // Other tiers (shouldn't happen, but handle gracefully)
347
348
  return {
348
349
  allowed: false,
349
- error: `Usage limit reached. Contact support or check your plan at https://apiclaw.nordsym.com/account`
350
+ error: `⚡ You've hit your free tier limit (${FREE_MONTHLY_LIMIT} calls/week).\n Upgrade: https://apiclaw.nordsym.com/upgrade`
350
351
  };
351
352
  }
352
353
 
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * APIClaw Postinstall Hook
4
+ * Prints a welcome message with links after install.
5
+ * No network calls. No side effects.
6
+ */
7
+
8
+ const CYAN = '\x1b[36m';
9
+ const RESET = '\x1b[0m';
10
+ const DIM = '\x1b[2m';
11
+
12
+ console.log('');
13
+ console.log(` 🦞 APIClaw installed successfully!`);
14
+ console.log('');
15
+ console.log(` → Create your free workspace: ${CYAN}https://apiclaw.nordsym.com/workspace${RESET}`);
16
+ console.log(` → Quick setup: ${CYAN}npx @nordsym/apiclaw setup${RESET}`);
17
+ console.log(` ⭐ Star us: ${CYAN}https://github.com/nordsym/apiclaw${RESET} ${DIM}(helps more devs find us)${RESET}`);
18
+ console.log('');