@aisa-one/cli 0.2.3 → 0.3.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/CHANGELOG.md CHANGED
@@ -7,6 +7,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.0] — 2026-08-18
11
+
12
+ ### Fixed
13
+
14
+ - **`aisa mcp setup` wrote a dead URL.** It hardcoded
15
+ `https://docs.aisa.one/mcp`, a hostname with no DNS record, and wrote it
16
+ into every client's config. Setup now reads the live discovery manifest at
17
+ `aisa.one/.well-known/mcp.json` and writes one entry per live server
18
+ (default set of five; `--all` for everything), so new servers work without
19
+ a CLI release. If the manifest cannot be fetched, nothing is written.
20
+ - **`{url}` entries were written for clients that cannot execute them.**
21
+ Claude Desktop and Windsurf spawn stdio processes and silently ignore url
22
+ entries; they now get an `npx mcp-remote` bridge, verified end to end
23
+ against production.
24
+ - **A config file that failed to parse was replaced with `{}`.** A
25
+ hand-edited `mcp.json` with comments or a trailing comma was wiped by
26
+ setup. It is now left untouched, with an error.
27
+
28
+ ### Added
29
+
30
+ - Entries carry the configured API key as a Bearer header; without a key
31
+ they are written credential-less and the server's OAuth challenge drives
32
+ the browser flow on first use.
33
+ - `aisa mcp status` now pings every configured endpoint with a real
34
+ initialize request instead of checking that a JSON key exists — a 401 is
35
+ reported as healthy (the auth challenge), an unresolvable hostname as the
36
+ failure it is.
37
+ - The stale dead entry earlier releases wrote is removed on the next setup.
38
+
39
+ ## [0.2.4] — 2026-08-07
40
+
41
+ Text-only follow-up to 0.2.3: no behavioural change, but the URL it printed
42
+ sent people to a 404.
43
+
44
+ ### Fixed
45
+
46
+ - **`aisa usage` and `aisa login` pointed at `aisa.one/dashboard`, which
47
+ returns 404.** The customer console is served at `console.aisa.one`; the
48
+ API-key and usage-log pages are `/api-keys` and `/logs`. Both commands and
49
+ both README references now say so.
50
+
51
+ ### Changed
52
+
53
+ - **The brand is written `AIsa`, not `AISA`,** in `--help` output, the npm
54
+ package description, the skill templates, and the README. The `AISA_*`
55
+ environment variables and `X-AISA-*` response headers are technical
56
+ identifiers and keep their existing casing.
57
+
10
58
  ## [0.2.3] — 2026-08-07
11
59
 
12
60
  Every command documented in the README was checked against the live gateway.
@@ -198,7 +246,8 @@ supports today; nothing here depends on a backend change.
198
246
  - Config commands (`aisa config get|set|list|reset`) and auth
199
247
  (`aisa login|logout|whoami`).
200
248
 
201
- [Unreleased]: https://github.com/AIsa-team/cli/compare/v0.2.3...HEAD
249
+ [Unreleased]: https://github.com/AIsa-team/cli/compare/v0.2.4...HEAD
250
+ [0.2.4]: https://github.com/AIsa-team/cli/compare/v0.2.3...v0.2.4
202
251
  [0.2.3]: https://github.com/AIsa-team/cli/compare/v0.2.2...v0.2.3
203
252
  [0.2.2]: https://github.com/AIsa-team/cli/compare/v0.2.1...v0.2.2
204
253
  [0.2.1]: https://github.com/AIsa-team/cli/releases/tag/v0.2.1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @aisa-one/cli
2
2
 
3
- Command-line access to [AISA](https://aisa.one): **one API key for 80+ LLMs and
3
+ Command-line access to [AIsa](https://aisa.one): **one API key for 80+ LLMs and
4
4
  950+ endpoints** across 29 API providers — finance, web search, social,
5
5
  research, and video generation.
6
6
 
@@ -33,8 +33,9 @@ aisa web-search "latest AI research"
33
33
  aisa run financial /insider-trades -q "ticker=AAPL"
34
34
  ```
35
35
 
36
- Get your API key at [aisa.one/dashboard](https://aisa.one/dashboard). New
37
- accounts receive $5 in free credits.
36
+ Get your API key at
37
+ [console.aisa.one/api-keys](https://console.aisa.one/api-keys). New accounts
38
+ receive $5 in free credits.
38
39
 
39
40
  ## API Catalog
40
41
 
@@ -192,13 +193,13 @@ aisa balance --json
192
193
 
193
194
  `aisa usage` is not available yet — the gateway does not serve
194
195
  `GET /v1/credits/usage` (it 404s, while `/v1/credits/balance` on the same route
195
- group works). Use the [dashboard](https://aisa.one/dashboard) for usage history
196
+ group works). Use the [console](https://console.aisa.one/logs) for usage history
196
197
  in the meantime.
197
198
 
198
199
  ## Skills
199
200
 
200
201
  Skills are markdown files that teach AI coding agents (Claude Code, Cursor,
201
- Copilot, …) how to use AISA APIs. They come from the
202
+ Copilot, …) how to use AIsa APIs. They come from the
202
203
  [agent-skills](https://github.com/AIsa-team/agent-skills) repository — 42 skills
203
204
  across six categories.
204
205
 
@@ -249,15 +250,20 @@ To publish a skill, open a pull request against
249
250
  ## MCP Server
250
251
 
251
252
  ```bash
252
- aisa mcp setup # configure detected agents
253
- aisa mcp status # check configuration
253
+ aisa mcp setup # configure the default servers for every detected client
254
+ aisa mcp setup --all # every live server, not just the defaults
255
+ aisa mcp setup --agent cursor # one client only
256
+ aisa mcp status # list entries and ping each configured endpoint
254
257
  ```
255
258
 
256
- > **Not currently usable.** These commands write
257
- > `https://docs.aisa.one/mcp`, which has no DNS record, and `mcp setup`
258
- > overwrites an agent config file it cannot parse — a `mcp.json` with comments
259
- > or a trailing comma will be emptied. Avoid `aisa mcp setup` until this is
260
- > fixed.
259
+ `setup` reads the platform's discovery manifest (`aisa.one/.well-known/mcp.json`)
260
+ at run time and writes one entry per live server, in the shape each client
261
+ executes: a `url` entry for Cursor, an `npx mcp-remote` stdio bridge for
262
+ Claude Desktop and Windsurf. With an API key configured the entries carry it
263
+ as a Bearer header; without one they carry no credentials and the server's
264
+ OAuth flow opens in your browser on first use. A config file that exists but
265
+ does not parse is never overwritten. The docs-search MCP is always included
266
+ as `aisa-docs`.
261
267
 
262
268
  ## Shell Completion
263
269
 
@@ -39,5 +39,5 @@ export async function usageAction(_options) {
39
39
  // The gateway does not serve /v1/credits/usage yet — it 404s in production
40
40
  // even though /v1/credits/balance on the same route group works.
41
41
  console.log(chalk.yellow(" Usage API is not yet available on the gateway."));
42
- hint("View usage history at https://aisa.one/dashboard");
42
+ hint("View usage history at https://console.aisa.one/logs");
43
43
  }
@@ -10,7 +10,7 @@ export function loginAction(options) {
10
10
  }
11
11
  setApiKey(key);
12
12
  success(`Authenticated: ${maskKey(key)}`);
13
- console.log(chalk.gray(" Get your API key at https://aisa.one/dashboard"));
13
+ console.log(chalk.gray(" Get your API key at https://console.aisa.one/api-keys"));
14
14
  }
15
15
  export function logoutAction() {
16
16
  clearApiKey();
@@ -1,4 +1,22 @@
1
+ /** One config entry in the shape the client actually executes. */
2
+ export declare function buildEntry(shape: "url" | "stdio", endpoint: string, key: string | undefined): Record<string, unknown>;
1
3
  export declare function mcpSetupAction(options: {
2
4
  agent?: string;
3
- }): void;
4
- export declare function mcpStatusAction(): void;
5
+ all?: boolean;
6
+ }): Promise<void>;
7
+ /**
8
+ * `aisa mcp status` — what is configured, and does it actually answer.
9
+ *
10
+ * The old status only checked that a config file contained an "aisa" key,
11
+ * which is exactly how a dead URL looked healthy. Reachability means a real
12
+ * HTTP exchange with each configured endpoint.
13
+ */
14
+ export declare function mcpStatusAction(): Promise<void>;
15
+ /**
16
+ * One initialize POST, no credentials. What each answer means:
17
+ * 200 -> alive and open (the docs MCP)
18
+ * 401 -> alive, auth required — the expected answer from mcp.aisa.one
19
+ * anything else -> alive but odd; say so
20
+ * network error -> the dead-hostname class this command exists to catch
21
+ */
22
+ export declare function pingEndpoint(endpoint: string): Promise<string>;
@@ -2,19 +2,78 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import chalk from "chalk";
3
3
  import { success, error, info, hint } from "../utils/display.js";
4
4
  import { expandHome, ensureDir } from "../utils/file.js";
5
- import { MCP_CONFIGS, MCP_URL } from "../constants.js";
5
+ import { MCP_CONFIGS, MCP_MANIFEST_URL, DOCS_MCP_URL, MCP_DEFAULT_SLUGS } from "../constants.js";
6
+ import { getApiKey } from "../config.js";
6
7
  import { join } from "node:path";
7
- export function mcpSetupAction(options) {
8
- const targets = options.agent && options.agent !== "all"
9
- ? [options.agent]
10
- : Object.keys(MCP_CONFIGS);
11
- let configured = 0;
8
+ const stripped = (name) => name.replace(/^AIsa\s+/i, "");
9
+ async function fetchLiveServers() {
10
+ const res = await fetch(MCP_MANIFEST_URL, { signal: AbortSignal.timeout(15_000) });
11
+ if (!res.ok)
12
+ throw new Error(`manifest answered HTTP ${res.status}`);
13
+ const manifest = (await res.json());
14
+ const live = (manifest.servers ?? [])
15
+ .filter((s) => s.status === "live" && s.slug && s.transport?.endpoint)
16
+ .map((s) => ({
17
+ slug: s.slug,
18
+ name: s.name ?? s.slug,
19
+ endpoint: s.transport.endpoint,
20
+ toolCount: s.tools?.length ?? 0,
21
+ }));
22
+ if (live.length === 0)
23
+ throw new Error("manifest lists no live servers");
24
+ return live;
25
+ }
26
+ /** One config entry in the shape the client actually executes. */
27
+ export function buildEntry(shape, endpoint, key) {
28
+ if (shape === "url") {
29
+ return key ? { url: endpoint, headers: { Authorization: `Bearer ${key}` } } : { url: endpoint };
30
+ }
31
+ // The exact invocation verified against production on 2026-08-18. The
32
+ // header value splits on the first colon, so no space after "Authorization:".
33
+ // Without a key, mcp-remote answers the server's 401 challenge by running
34
+ // the OAuth flow itself and caching tokens under ~/.mcp-auth.
35
+ const args = ["-y", "mcp-remote", endpoint];
36
+ if (key)
37
+ args.push("--header", `Authorization:Bearer ${key}`);
38
+ args.push("--transport", "http-only");
39
+ return { command: "npx", args };
40
+ }
41
+ /** The dead entry every pre-v0.3 setup wrote. Remove it on sight. */
42
+ const DEAD_URL = "https://docs.aisa.one/mcp";
43
+ export async function mcpSetupAction(options) {
44
+ const targets = options.agent && options.agent !== "all" ? [options.agent] : Object.keys(MCP_CONFIGS);
12
45
  for (const agent of targets) {
13
- const config = MCP_CONFIGS[agent];
14
- if (!config) {
46
+ if (!MCP_CONFIGS[agent]) {
15
47
  error(`Unknown agent: ${agent}. Valid: ${Object.keys(MCP_CONFIGS).join(", ")}, all`);
16
48
  return;
17
49
  }
50
+ }
51
+ // Fetch before touching any file: a setup that cannot see the manifest has
52
+ // nothing true to write.
53
+ let servers;
54
+ try {
55
+ servers = await fetchLiveServers();
56
+ }
57
+ catch (e) {
58
+ error(`Could not read the MCP manifest at ${MCP_MANIFEST_URL}: ${e.message}`);
59
+ hint("Nothing was written. Check your network and try again.");
60
+ process.exitCode = 1;
61
+ return;
62
+ }
63
+ const chosen = options.all
64
+ ? servers
65
+ : servers.filter((s) => MCP_DEFAULT_SLUGS.includes(s.slug));
66
+ const skipped = servers.length - chosen.length;
67
+ const key = getApiKey();
68
+ if (key) {
69
+ info("Using your configured API key (Bearer). It will be written into each client's config file.");
70
+ }
71
+ else {
72
+ info("No API key configured — entries are written without credentials, and the");
73
+ info("server's OAuth flow will open in your browser on first use.");
74
+ }
75
+ for (const agent of targets) {
76
+ const config = MCP_CONFIGS[agent];
18
77
  const filePath = expandHome(config.path);
19
78
  let existing = {};
20
79
  if (existsSync(filePath)) {
@@ -22,46 +81,123 @@ export function mcpSetupAction(options) {
22
81
  existing = JSON.parse(readFileSync(filePath, "utf-8"));
23
82
  }
24
83
  catch {
25
- existing = {};
84
+ // A file we cannot parse is a file we do not own. The old command
85
+ // replaced it with {} — a user's hand-edited config (comments,
86
+ // trailing commas) was wiped by a "setup". Refuse instead.
87
+ error(`${agent}: ${config.path} exists but is not valid JSON — refusing to overwrite it.`);
88
+ hint("Fix or remove the file, then re-run setup.");
89
+ continue;
26
90
  }
27
91
  }
28
92
  else {
29
93
  ensureDir(join(filePath, ".."));
30
94
  }
31
- const servers = existing[config.key] || {};
32
- servers["aisa"] = { url: MCP_URL };
33
- existing[config.key] = servers;
95
+ const entries = existing[config.key] || {};
96
+ // Clean up the dead entry earlier releases wrote, and only that one:
97
+ // an "aisa" entry the user pointed somewhere else on purpose stays.
98
+ const stale = entries["aisa"];
99
+ if (stale?.url === DEAD_URL)
100
+ delete entries["aisa"];
101
+ for (const s of chosen) {
102
+ entries[`aisa-${s.slug}`] = buildEntry(config.shape, s.endpoint, key);
103
+ }
104
+ // The docs-search MCP is tiny, unauthenticated, and answers "how do I call
105
+ // this" questions — always included.
106
+ entries["aisa-docs"] = buildEntry(config.shape, DOCS_MCP_URL, undefined);
107
+ existing[config.key] = entries;
34
108
  writeFileSync(filePath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
35
- console.log(` ${chalk.green("✓")} ${agent}: ${config.path}`);
36
- configured++;
109
+ console.log(` ${chalk.green("✓")} ${agent}: ${chosen.length + 1} servers (${config.shape}) → ${config.path}`);
37
110
  }
38
- if (configured > 0) {
39
- success(`MCP server configured for ${configured} agent(s)`);
40
- hint("Restart your agent/editor to activate");
111
+ success(`Configured ${chosen.length} live servers plus docs search for ${targets.length} client(s)`);
112
+ for (const s of chosen) {
113
+ console.log(` ${chalk.cyan(`aisa-${s.slug}`)} ${stripped(s.name)} (${s.toolCount} tools)`);
41
114
  }
115
+ if (skipped > 0)
116
+ hint(`${skipped} more live servers available — run with --all to configure every one`);
117
+ hint("Restart your agent/editor to activate");
42
118
  }
43
- export function mcpStatusAction() {
44
- info(`MCP Server: ${MCP_URL}`);
119
+ /**
120
+ * `aisa mcp status` — what is configured, and does it actually answer.
121
+ *
122
+ * The old status only checked that a config file contained an "aisa" key,
123
+ * which is exactly how a dead URL looked healthy. Reachability means a real
124
+ * HTTP exchange with each configured endpoint.
125
+ */
126
+ export async function mcpStatusAction() {
127
+ const endpoints = new Map(); // endpoint -> [client/entry]
45
128
  for (const [agent, config] of Object.entries(MCP_CONFIGS)) {
46
129
  const filePath = expandHome(config.path);
47
- if (existsSync(filePath)) {
48
- try {
49
- const data = JSON.parse(readFileSync(filePath, "utf-8"));
50
- const servers = data[config.key];
51
- if (servers?.["aisa"]) {
52
- console.log(` ${chalk.green("✓")} ${agent}: configured`);
53
- }
54
- else {
55
- console.log(` ${chalk.gray("○")} ${agent}: not configured`);
56
- }
57
- }
58
- catch {
59
- console.log(` ${chalk.gray("○")} ${agent}: config unreadable`);
60
- }
61
- }
62
- else {
130
+ if (!existsSync(filePath)) {
63
131
  console.log(` ${chalk.gray("○")} ${agent}: not installed`);
132
+ continue;
133
+ }
134
+ let entries = {};
135
+ try {
136
+ const data = JSON.parse(readFileSync(filePath, "utf-8"));
137
+ entries = data[config.key] || {};
138
+ }
139
+ catch {
140
+ console.log(` ${chalk.gray("○")} ${agent}: config unreadable`);
141
+ continue;
142
+ }
143
+ const ours = Object.entries(entries).filter(([name]) => name.startsWith("aisa"));
144
+ if (ours.length === 0) {
145
+ console.log(` ${chalk.gray("○")} ${agent}: not configured`);
146
+ continue;
64
147
  }
148
+ console.log(` ${chalk.green("✓")} ${agent}: ${ours.length} entries`);
149
+ for (const [name, entry] of ours) {
150
+ const e = entry;
151
+ const endpoint = e.url ?? e.args?.find((a) => a.startsWith("http"));
152
+ if (endpoint) {
153
+ const users = endpoints.get(endpoint) ?? [];
154
+ users.push(`${agent}/${name}`);
155
+ endpoints.set(endpoint, users);
156
+ }
157
+ }
158
+ }
159
+ if (endpoints.size === 0) {
160
+ hint("Run 'aisa mcp setup' to configure");
161
+ return;
162
+ }
163
+ console.log("");
164
+ info("Checking each configured endpoint:");
165
+ for (const [endpoint, users] of endpoints) {
166
+ console.log(` ${endpoint} ${chalk.gray(`(${users.length} entr${users.length > 1 ? "ies" : "y"})`)}`);
167
+ console.log(` ${await pingEndpoint(endpoint)}`);
168
+ }
169
+ }
170
+ /**
171
+ * One initialize POST, no credentials. What each answer means:
172
+ * 200 -> alive and open (the docs MCP)
173
+ * 401 -> alive, auth required — the expected answer from mcp.aisa.one
174
+ * anything else -> alive but odd; say so
175
+ * network error -> the dead-hostname class this command exists to catch
176
+ */
177
+ export async function pingEndpoint(endpoint) {
178
+ try {
179
+ const res = await fetch(endpoint, {
180
+ method: "POST",
181
+ headers: { "Content-Type": "application/json", Accept: "application/json, text/event-stream" },
182
+ body: JSON.stringify({
183
+ jsonrpc: "2.0",
184
+ id: 1,
185
+ method: "initialize",
186
+ params: {
187
+ protocolVersion: "2025-06-18",
188
+ capabilities: {},
189
+ clientInfo: { name: "aisa-cli", version: "status" },
190
+ },
191
+ }),
192
+ signal: AbortSignal.timeout(8_000),
193
+ });
194
+ if (res.status === 200)
195
+ return `${chalk.green("✓")} reachable (open)`;
196
+ if (res.status === 401)
197
+ return `${chalk.green("✓")} reachable (auth required — normal)`;
198
+ return `${chalk.yellow("⚠")} reachable but answered HTTP ${res.status}`;
199
+ }
200
+ catch (e) {
201
+ return `${chalk.red("✗")} unreachable: ${e.message}`;
65
202
  }
66
- hint("Run 'aisa mcp setup' to configure");
67
203
  }
@@ -33,14 +33,14 @@ aisa run <slug> <path> -q "param=value"
33
33
  `,
34
34
  llm: `---
35
35
  name: llm-assistant
36
- description: "Use AISA's unified LLM gateway to chat with 70+ AI models."
36
+ description: "Use AIsa's unified LLM gateway to chat with 70+ AI models."
37
37
  homepage: https://aisa.one
38
38
  metadata: {"aisa":{"emoji":"🤖","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
39
39
  ---
40
40
 
41
41
  # LLM Assistant Skill
42
42
 
43
- Use the AISA unified gateway to access 70+ language models through a single API.
43
+ Use the AIsa unified gateway to access 70+ language models through a single API.
44
44
 
45
45
  ## Authentication
46
46
 
@@ -69,14 +69,14 @@ aisa models --provider anthropic
69
69
  `,
70
70
  search: `---
71
71
  name: web-search
72
- description: "Search the web, YouTube, and academic papers via AISA APIs."
72
+ description: "Search the web, YouTube, and academic papers via AIsa APIs."
73
73
  homepage: https://aisa.one
74
74
  metadata: {"aisa":{"emoji":"🔍","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
75
75
  ---
76
76
 
77
77
  # Web Search Skill
78
78
 
79
- Search the web, YouTube, and academic papers through AISA's unified search APIs.
79
+ Search the web, YouTube, and academic papers through AIsa's unified search APIs.
80
80
 
81
81
  ## Authentication
82
82
 
@@ -104,14 +104,14 @@ aisa scholar "transformer architecture"
104
104
  `,
105
105
  finance: `---
106
106
  name: finance-analyst
107
- description: "Access stock prices, earnings, SEC filings, and financial data via AISA."
107
+ description: "Access stock prices, earnings, SEC filings, and financial data via AIsa."
108
108
  homepage: https://aisa.one
109
109
  metadata: {"aisa":{"emoji":"📊","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
110
110
  ---
111
111
 
112
112
  # Finance Analyst Skill
113
113
 
114
- Access real-time and historical financial data through AISA's finance APIs.
114
+ Access real-time and historical financial data through AIsa's finance APIs.
115
115
 
116
116
  ## Authentication
117
117
 
@@ -136,14 +136,14 @@ aisa crypto ETH --period 30d
136
136
  `,
137
137
  twitter: `---
138
138
  name: twitter-manager
139
- description: "Search Twitter, get user profiles and trends via AISA."
139
+ description: "Search Twitter, get user profiles and trends via AIsa."
140
140
  homepage: https://aisa.one
141
141
  metadata: {"aisa":{"emoji":"🐦","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
142
142
  ---
143
143
 
144
144
  # Twitter Manager Skill
145
145
 
146
- Interact with Twitter/X through AISA's Twitter APIs.
146
+ Interact with Twitter/X through AIsa's Twitter APIs.
147
147
 
148
148
  ## Authentication
149
149
 
@@ -171,14 +171,14 @@ aisa twitter trends
171
171
  `,
172
172
  video: `---
173
173
  name: video-generator
174
- description: "Generate videos from text prompts using AISA's video synthesis API."
174
+ description: "Generate videos from text prompts using AIsa's video synthesis API."
175
175
  homepage: https://aisa.one
176
176
  metadata: {"aisa":{"emoji":"🎬","requires":{"bins":["curl"],"env":["AISA_API_KEY"]},"primaryEnv":"AISA_API_KEY","compatibility":["openclaw","claude-code","hermes"]}}
177
177
  ---
178
178
 
179
179
  # Video Generator Skill
180
180
 
181
- Generate videos from text prompts using AISA's AI video generation APIs.
181
+ Generate videos from text prompts using AIsa's AI video generation APIs.
182
182
 
183
183
  ## Authentication
184
184
 
@@ -1,8 +1,27 @@
1
- export declare const VERSION = "0.2.3";
1
+ export declare const VERSION = "0.3.0";
2
2
  /** Root of the platform. Per-surface bases are derived in api.ts#resolveBases. */
3
3
  export declare const BASE_URL = "https://api.aisa.one";
4
4
  export declare const ENV_VAR_NAME = "AISA_API_KEY";
5
- export declare const MCP_URL = "https://docs.aisa.one/mcp";
5
+ /**
6
+ * The MCP discovery manifest — the single source of truth for which servers
7
+ * exist and where they live. The CLI deliberately knows no server list of its
8
+ * own: servers ship and retire on the platform side, and reading the manifest
9
+ * at setup time means a new server works without a CLI release (the same
10
+ * philosophy as LLM_ROUTE_PREFIXES below, applied to the fast-moving side).
11
+ *
12
+ * History: until v0.2.4 this file hardcoded MCP_URL = "https://docs.aisa.one/mcp",
13
+ * a host that does not resolve — every `aisa mcp setup` wrote a dead entry into
14
+ * users' configs, and nothing noticed because the command had no tests.
15
+ */
16
+ export declare const MCP_MANIFEST_URL = "https://aisa.one/.well-known/mcp.json";
17
+ /** Mintlify's docs-search MCP (3 tools: search/read/feedback). Unauthenticated. */
18
+ export declare const DOCS_MCP_URL = "https://aisa.one/docs/mcp";
19
+ /**
20
+ * Servers configured by default. Eleven entries per client is a lot of config;
21
+ * these five cover the broadest agent needs, and `--all` configures everything
22
+ * the manifest lists as live.
23
+ */
24
+ export declare const MCP_DEFAULT_SLUGS: readonly string[];
6
25
  /**
7
26
  * First path segment of every route the LLM gateway serves under /v1 (plus
8
27
  * /v1beta for Gemini). Everything else is an integration API under /apis/v1.
@@ -15,9 +34,17 @@ export declare const MCP_URL = "https://docs.aisa.one/mcp";
15
34
  */
16
35
  export declare const LLM_ROUTE_PREFIXES: readonly string[];
17
36
  export declare const AGENT_DIRS: Record<string, string>;
37
+ /**
38
+ * Per-client config shape. This is the part v0.2.4 got wrong even apart from
39
+ * the dead URL: it wrote `{url}` everywhere, but Claude Desktop's mcpServers
40
+ * only executes command/args (stdio) entries and silently ignores url ones.
41
+ * Stdio clients get an `npx mcp-remote` bridge instead — verified end to end
42
+ * against mcp.aisa.one (initialize -> tools/list -> tools/call) on 2026-08-18.
43
+ */
18
44
  export declare const MCP_CONFIGS: Record<string, {
19
45
  path: string;
20
46
  key: string;
47
+ shape: "url" | "stdio";
21
48
  }>;
22
49
  /**
23
50
  * Ticker symbol → CoinGecko coin id.
package/dist/constants.js CHANGED
@@ -1,8 +1,33 @@
1
- export const VERSION = "0.2.3";
1
+ export const VERSION = "0.3.0";
2
2
  /** Root of the platform. Per-surface bases are derived in api.ts#resolveBases. */
3
3
  export const BASE_URL = "https://api.aisa.one";
4
4
  export const ENV_VAR_NAME = "AISA_API_KEY";
5
- export const MCP_URL = "https://docs.aisa.one/mcp";
5
+ /**
6
+ * The MCP discovery manifest — the single source of truth for which servers
7
+ * exist and where they live. The CLI deliberately knows no server list of its
8
+ * own: servers ship and retire on the platform side, and reading the manifest
9
+ * at setup time means a new server works without a CLI release (the same
10
+ * philosophy as LLM_ROUTE_PREFIXES below, applied to the fast-moving side).
11
+ *
12
+ * History: until v0.2.4 this file hardcoded MCP_URL = "https://docs.aisa.one/mcp",
13
+ * a host that does not resolve — every `aisa mcp setup` wrote a dead entry into
14
+ * users' configs, and nothing noticed because the command had no tests.
15
+ */
16
+ export const MCP_MANIFEST_URL = "https://aisa.one/.well-known/mcp.json";
17
+ /** Mintlify's docs-search MCP (3 tools: search/read/feedback). Unauthenticated. */
18
+ export const DOCS_MCP_URL = "https://aisa.one/docs/mcp";
19
+ /**
20
+ * Servers configured by default. Eleven entries per client is a lot of config;
21
+ * these five cover the broadest agent needs, and `--all` configures everything
22
+ * the manifest lists as live.
23
+ */
24
+ export const MCP_DEFAULT_SLUGS = [
25
+ "web-search",
26
+ "twitter-api",
27
+ "crypto-market-data",
28
+ "marketpulse",
29
+ "stock-pulse",
30
+ ];
6
31
  /**
7
32
  * First path segment of every route the LLM gateway serves under /v1 (plus
8
33
  * /v1beta for Gemini). Everything else is an integration API under /apis/v1.
@@ -35,15 +60,24 @@ export const AGENT_DIRS = {
35
60
  gemini: "~/.gemini/skills/",
36
61
  openclaw: "~/.openclaw/skills/",
37
62
  };
63
+ /**
64
+ * Per-client config shape. This is the part v0.2.4 got wrong even apart from
65
+ * the dead URL: it wrote `{url}` everywhere, but Claude Desktop's mcpServers
66
+ * only executes command/args (stdio) entries and silently ignores url ones.
67
+ * Stdio clients get an `npx mcp-remote` bridge instead — verified end to end
68
+ * against mcp.aisa.one (initialize -> tools/list -> tools/call) on 2026-08-18.
69
+ */
38
70
  export const MCP_CONFIGS = {
39
- cursor: { path: "~/.cursor/mcp.json", key: "mcpServers" },
71
+ cursor: { path: "~/.cursor/mcp.json", key: "mcpServers", shape: "url" },
40
72
  "claude-desktop": {
41
73
  path: "~/Library/Application Support/Claude/claude_desktop_config.json",
42
74
  key: "mcpServers",
75
+ shape: "stdio",
43
76
  },
44
77
  windsurf: {
45
78
  path: "~/.codeium/windsurf/mcp_config.json",
46
79
  key: "mcpServers",
80
+ shape: "stdio",
47
81
  },
48
82
  };
49
83
  /**
package/dist/index.js CHANGED
@@ -43,12 +43,12 @@ function wrap(fn) {
43
43
  const program = new Command();
44
44
  program
45
45
  .name("aisa")
46
- .description("AISA CLI - Unified AI infrastructure platform")
46
+ .description("AIsa CLI - Unified AI infrastructure platform")
47
47
  .version(VERSION);
48
48
  // ── Auth ──
49
49
  program
50
50
  .command("login")
51
- .description("Authenticate with your AISA API key")
51
+ .description("Authenticate with your AIsa API key")
52
52
  .option("--key <key>", "API key")
53
53
  .action(loginAction);
54
54
  program
@@ -130,7 +130,7 @@ program
130
130
  // ── Chat (LLM Gateway) ──
131
131
  program
132
132
  .command("chat [message]")
133
- .description("Chat with AI models via the AISA gateway")
133
+ .description("Chat with AI models via the AIsa gateway")
134
134
  .option("--model <model>", "Model ID (default: gpt-4.1-mini)")
135
135
  .option("--system <prompt>", "System prompt")
136
136
  .option("--no-stream", "Disable streaming")
@@ -472,12 +472,13 @@ skills
472
472
  const mcp = program.command("mcp").description("MCP server integration");
473
473
  mcp
474
474
  .command("setup")
475
- .description("Configure AISA MCP server for AI agents")
475
+ .description("Configure AIsa MCP servers (from the live manifest) for AI agents")
476
476
  .option("--agent <agent>", "Target agent: cursor, claude-desktop, windsurf, all")
477
+ .option("--all", "Configure every live server, not just the default set")
477
478
  .action(mcpSetupAction);
478
479
  mcp
479
480
  .command("status")
480
- .description("Check MCP server configuration status")
481
+ .description("Check MCP configuration and ping each configured endpoint")
481
482
  .action(mcpStatusAction);
482
483
  // ── Config ──
483
484
  const configCmd = program.command("config").description("Manage CLI configuration");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aisa-one/cli",
3
- "version": "0.2.3",
4
- "description": "CLI for the AISA unified AI infrastructure platform - one API key for 80+ LLMs and 900+ endpoints across finance, search, social, and video APIs",
3
+ "version": "0.3.0",
4
+ "description": "CLI for the AIsa unified AI infrastructure platform - one API key for 80+ LLMs and 900+ endpoints across finance, search, social, and video APIs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -60,5 +60,5 @@
60
60
  "url": "https://github.com/AIsa-team/cli/issues"
61
61
  },
62
62
  "homepage": "https://aisa.one",
63
- "author": "AISA Team <support@aisa.one> (https://aisa.one)"
63
+ "author": "AIsa Team <support@aisa.one> (https://aisa.one)"
64
64
  }