hornerosssp 0.1.0 → 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/dist/cli/index.js +527 -0
- package/dist/index.d.mts +39 -4
- package/dist/index.d.ts +39 -4
- package/dist/index.js +86 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +85 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -2
|
@@ -0,0 +1,527 @@
|
|
|
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
|
+
|
|
26
|
+
// src/cli/index.ts
|
|
27
|
+
var import_commander7 = require("commander");
|
|
28
|
+
var import_chalk8 = __toESM(require("chalk"));
|
|
29
|
+
|
|
30
|
+
// src/cli/commands/login.ts
|
|
31
|
+
var import_commander = require("commander");
|
|
32
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
33
|
+
var import_inquirer = __toESM(require("inquirer"));
|
|
34
|
+
var import_open = __toESM(require("open"));
|
|
35
|
+
|
|
36
|
+
// src/cli/config.ts
|
|
37
|
+
var fs = __toESM(require("fs"));
|
|
38
|
+
var path = __toESM(require("path"));
|
|
39
|
+
var os = __toESM(require("os"));
|
|
40
|
+
var CONFIG_DIR = path.join(os.homedir(), ".hornerosssp");
|
|
41
|
+
var CONFIG_FILE = path.join(CONFIG_DIR, "userData.json");
|
|
42
|
+
function ensureConfigDir() {
|
|
43
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
44
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function getUserData() {
|
|
48
|
+
try {
|
|
49
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
50
|
+
const content = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
51
|
+
return JSON.parse(content);
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
}
|
|
55
|
+
return {};
|
|
56
|
+
}
|
|
57
|
+
function saveUserData(data) {
|
|
58
|
+
ensureConfigDir();
|
|
59
|
+
const existing = getUserData();
|
|
60
|
+
const merged = { ...existing, ...data };
|
|
61
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2));
|
|
62
|
+
}
|
|
63
|
+
function clearUserData() {
|
|
64
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
65
|
+
fs.unlinkSync(CONFIG_FILE);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function getApiKey() {
|
|
69
|
+
return process.env.HORNEROS_API_KEY || getUserData().api_key;
|
|
70
|
+
}
|
|
71
|
+
function getBaseUrl() {
|
|
72
|
+
return process.env.HORNEROS_BASE_URL || getUserData().base_url || "http://localhost:3000";
|
|
73
|
+
}
|
|
74
|
+
function setCliConfig(apiKey, baseUrl) {
|
|
75
|
+
const data = { api_key: apiKey };
|
|
76
|
+
if (baseUrl) {
|
|
77
|
+
data.base_url = baseUrl;
|
|
78
|
+
}
|
|
79
|
+
saveUserData(data);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/cli/client.ts
|
|
83
|
+
var import_chalk = __toESM(require("chalk"));
|
|
84
|
+
var ApiClient = class {
|
|
85
|
+
constructor() {
|
|
86
|
+
this.baseUrl = getBaseUrl();
|
|
87
|
+
this.apiKey = getApiKey();
|
|
88
|
+
}
|
|
89
|
+
async fetch(path2, options = {}) {
|
|
90
|
+
const url = `${this.baseUrl}/api/v1${path2}`;
|
|
91
|
+
const headers = {
|
|
92
|
+
"Content-Type": "application/json",
|
|
93
|
+
"X-Source": "cli",
|
|
94
|
+
...options.headers
|
|
95
|
+
};
|
|
96
|
+
if (this.apiKey) {
|
|
97
|
+
headers["X-Api-Key"] = this.apiKey;
|
|
98
|
+
}
|
|
99
|
+
const res = await globalThis.fetch(url, {
|
|
100
|
+
...options,
|
|
101
|
+
headers
|
|
102
|
+
});
|
|
103
|
+
if (!res.ok) {
|
|
104
|
+
let body;
|
|
105
|
+
try {
|
|
106
|
+
body = await res.json();
|
|
107
|
+
} catch {
|
|
108
|
+
body = await res.text().catch(() => null);
|
|
109
|
+
}
|
|
110
|
+
const message = (body && typeof body === "object" && "error" in body ? body.error : null) || `HTTP ${res.status}`;
|
|
111
|
+
throw new Error(message);
|
|
112
|
+
}
|
|
113
|
+
if (res.status === 204) {
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
116
|
+
const json = await res.json();
|
|
117
|
+
return json.data !== void 0 ? json.data : json;
|
|
118
|
+
}
|
|
119
|
+
// CLI Auth endpoints
|
|
120
|
+
async generateCliSession() {
|
|
121
|
+
return this.fetch("/cli/session", { method: "POST" });
|
|
122
|
+
}
|
|
123
|
+
async verifyCliCode(key, code) {
|
|
124
|
+
return this.fetch(`/cli/verify?key=${encodeURIComponent(key)}&code=${encodeURIComponent(code)}`);
|
|
125
|
+
}
|
|
126
|
+
// User endpoints
|
|
127
|
+
async getUserInfo() {
|
|
128
|
+
return this.fetch("/auth/me");
|
|
129
|
+
}
|
|
130
|
+
// Apps/MCPs endpoints
|
|
131
|
+
async listApps() {
|
|
132
|
+
return this.fetch("/mcps");
|
|
133
|
+
}
|
|
134
|
+
async getApp(slug) {
|
|
135
|
+
return this.fetch(`/mcps/${encodeURIComponent(slug)}`);
|
|
136
|
+
}
|
|
137
|
+
// Connections endpoints
|
|
138
|
+
async listConnections() {
|
|
139
|
+
return this.fetch("/connections");
|
|
140
|
+
}
|
|
141
|
+
async getConnection(id) {
|
|
142
|
+
return this.fetch(`/connections/${encodeURIComponent(id)}`);
|
|
143
|
+
}
|
|
144
|
+
async initiateConnection(mcpSlug, params) {
|
|
145
|
+
return this.fetch("/connections", {
|
|
146
|
+
method: "POST",
|
|
147
|
+
body: JSON.stringify({
|
|
148
|
+
mcp_slug: mcpSlug,
|
|
149
|
+
...params?.appName && { app_name: params.appName },
|
|
150
|
+
...params?.userId && { user_id: params.userId }
|
|
151
|
+
})
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
async revokeConnection(id) {
|
|
155
|
+
return this.fetch(`/connections/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
function getClient() {
|
|
159
|
+
return new ApiClient();
|
|
160
|
+
}
|
|
161
|
+
function requireAuth() {
|
|
162
|
+
const apiKey = getApiKey();
|
|
163
|
+
if (!apiKey) {
|
|
164
|
+
console.log(import_chalk.default.red("You are not authenticated. Please run `hornerosssp login` to authenticate."));
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// src/cli/commands/login.ts
|
|
170
|
+
var FRONTEND_BASE_URL = "http://localhost:3000";
|
|
171
|
+
var loginCommand = new import_commander.Command("login").description("Authenticate and login to HornerosSSP").option("-n, --no-browser", "Don't open browser, manually copy the link").option("-k, --api-key <key>", "Provide API key directly").option("-u, --base-url <url>", "Base URL of HornerosSSP server").action(async (options) => {
|
|
172
|
+
if (options.apiKey) {
|
|
173
|
+
setCliConfig(options.apiKey, options.baseUrl);
|
|
174
|
+
console.log(import_chalk2.default.green("\n API key saved successfully!\n"));
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const existingKey = getApiKey();
|
|
178
|
+
if (existingKey) {
|
|
179
|
+
console.log(import_chalk2.default.yellow("\n You are already authenticated!\n"));
|
|
180
|
+
const { shouldReauth } = await import_inquirer.default.prompt([{
|
|
181
|
+
type: "confirm",
|
|
182
|
+
name: "shouldReauth",
|
|
183
|
+
message: "Do you want to re-authenticate?",
|
|
184
|
+
default: false
|
|
185
|
+
}]);
|
|
186
|
+
if (!shouldReauth) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
try {
|
|
191
|
+
const client = getClient();
|
|
192
|
+
console.log(import_chalk2.default.dim("\n Generating login session...\n"));
|
|
193
|
+
const session = await client.generateCliSession();
|
|
194
|
+
const cliKey = session.key;
|
|
195
|
+
const baseUrl = options.baseUrl || getBaseUrl() || FRONTEND_BASE_URL;
|
|
196
|
+
const loginUrl = `${baseUrl}/cli-auth?cliKey=${cliKey}`;
|
|
197
|
+
console.log(import_chalk2.default.bold(" Please login using the following link:\n"));
|
|
198
|
+
console.log(` ${import_chalk2.default.cyan(loginUrl)}
|
|
199
|
+
`);
|
|
200
|
+
if (options.browser !== false) {
|
|
201
|
+
console.log(import_chalk2.default.dim(" Opening browser...\n"));
|
|
202
|
+
await (0, import_open.default)(loginUrl);
|
|
203
|
+
}
|
|
204
|
+
const { authCode } = await import_inquirer.default.prompt([{
|
|
205
|
+
type: "input",
|
|
206
|
+
name: "authCode",
|
|
207
|
+
message: "Enter the authentication code:"
|
|
208
|
+
}]);
|
|
209
|
+
console.log(import_chalk2.default.dim("\n Verifying code...\n"));
|
|
210
|
+
const result = await client.verifyCliCode(cliKey, authCode);
|
|
211
|
+
setCliConfig(result.apiKey, options.baseUrl);
|
|
212
|
+
console.log(import_chalk2.default.green(" You are now authenticated and ready to use HornerosSSP!\n"));
|
|
213
|
+
} catch (error) {
|
|
214
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
215
|
+
console.log(import_chalk2.default.red(`
|
|
216
|
+
Login failed: ${message}
|
|
217
|
+
`));
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// src/cli/commands/logout.ts
|
|
223
|
+
var import_commander2 = require("commander");
|
|
224
|
+
var import_chalk3 = __toESM(require("chalk"));
|
|
225
|
+
var logoutCommand = new import_commander2.Command("logout").description("Clear authentication and logout from HornerosSSP").action(() => {
|
|
226
|
+
clearUserData();
|
|
227
|
+
console.log(import_chalk3.default.yellow("\n You have been logged out from HornerosSSP.\n"));
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// src/cli/commands/whoami.ts
|
|
231
|
+
var import_commander3 = require("commander");
|
|
232
|
+
var import_chalk4 = __toESM(require("chalk"));
|
|
233
|
+
var whoamiCommand = new import_commander3.Command("whoami").description("Show current user info").action(async () => {
|
|
234
|
+
requireAuth();
|
|
235
|
+
try {
|
|
236
|
+
const client = getClient();
|
|
237
|
+
const user = await client.getUserInfo();
|
|
238
|
+
console.log(import_chalk4.default.bold("\n Current User\n"));
|
|
239
|
+
console.log(` ${import_chalk4.default.cyan("ID:")} ${user.id}`);
|
|
240
|
+
console.log(` ${import_chalk4.default.cyan("Email:")} ${user.email}`);
|
|
241
|
+
if (user.name) {
|
|
242
|
+
console.log(` ${import_chalk4.default.cyan("Name:")} ${user.name}`);
|
|
243
|
+
}
|
|
244
|
+
console.log(` ${import_chalk4.default.cyan("Server:")} ${getBaseUrl()}`);
|
|
245
|
+
console.log();
|
|
246
|
+
} catch (error) {
|
|
247
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
248
|
+
console.log(import_chalk4.default.red(`
|
|
249
|
+
Failed to get user info: ${message}
|
|
250
|
+
`));
|
|
251
|
+
process.exit(1);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// src/cli/commands/apps.ts
|
|
256
|
+
var import_commander4 = require("commander");
|
|
257
|
+
var import_chalk5 = __toESM(require("chalk"));
|
|
258
|
+
var appsCommand = new import_commander4.Command("apps").description("List available MCPs/apps").option("-s, --search <query>", "Search apps by name").action(async (options) => {
|
|
259
|
+
requireAuth();
|
|
260
|
+
try {
|
|
261
|
+
const client = getClient();
|
|
262
|
+
let apps = await client.listApps();
|
|
263
|
+
if (options.search) {
|
|
264
|
+
const query = options.search.toLowerCase();
|
|
265
|
+
apps = apps.filter(
|
|
266
|
+
(app) => app.name.toLowerCase().includes(query) || app.slug.toLowerCase().includes(query) || app.description && app.description.toLowerCase().includes(query)
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
if (apps.length === 0) {
|
|
270
|
+
console.log(import_chalk5.default.yellow("\n No apps found.\n"));
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
console.log(import_chalk5.default.bold(`
|
|
274
|
+
Available Apps (${apps.length})
|
|
275
|
+
`));
|
|
276
|
+
for (const app of apps) {
|
|
277
|
+
console.log(` ${import_chalk5.default.cyan(app.name)} ${import_chalk5.default.dim(`(${app.slug})`)}`);
|
|
278
|
+
if (app.description) {
|
|
279
|
+
console.log(` ${import_chalk5.default.dim(app.description)}`);
|
|
280
|
+
}
|
|
281
|
+
console.log(` ${import_chalk5.default.green(`${app.toolCount} tools`)} | ${import_chalk5.default.blue(`${app.activeConnections} connections`)}`);
|
|
282
|
+
console.log();
|
|
283
|
+
}
|
|
284
|
+
console.log(import_chalk5.default.dim(` Run ${import_chalk5.default.cyan("hornerosssp add <app-slug>")} to connect an app.
|
|
285
|
+
`));
|
|
286
|
+
} catch (error) {
|
|
287
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
288
|
+
console.log(import_chalk5.default.red(`
|
|
289
|
+
Failed to list apps: ${message}
|
|
290
|
+
`));
|
|
291
|
+
process.exit(1);
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// src/cli/commands/add.ts
|
|
296
|
+
var import_commander5 = require("commander");
|
|
297
|
+
var import_chalk6 = __toESM(require("chalk"));
|
|
298
|
+
var import_inquirer2 = __toESM(require("inquirer"));
|
|
299
|
+
var import_open2 = __toESM(require("open"));
|
|
300
|
+
var addCommand = new import_commander5.Command("add").description("Connect a new app/MCP").argument("<app-slug>", "The slug of the app to connect (e.g., gmail, slack)").option("-n, --no-browser", "Don't open browser for OAuth").option("-l, --label <label>", "Label for this connection").option("-u, --user-id <userId>", "User ID for multi-tenant apps").action(async (appSlug, options) => {
|
|
301
|
+
requireAuth();
|
|
302
|
+
try {
|
|
303
|
+
const client = getClient();
|
|
304
|
+
console.log(import_chalk6.default.dim(`
|
|
305
|
+
Checking app "${appSlug}"...
|
|
306
|
+
`));
|
|
307
|
+
let app;
|
|
308
|
+
try {
|
|
309
|
+
app = await client.getApp(appSlug);
|
|
310
|
+
} catch {
|
|
311
|
+
console.log(import_chalk6.default.red(` App "${appSlug}" not found.
|
|
312
|
+
`));
|
|
313
|
+
console.log(import_chalk6.default.dim(` Run ${import_chalk6.default.cyan("hornerosssp apps")} to see available apps.
|
|
314
|
+
`));
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
console.log(` Connecting ${import_chalk6.default.cyan(app.name)}...
|
|
318
|
+
`);
|
|
319
|
+
const connections = await client.listConnections();
|
|
320
|
+
const existingConnection = connections.find((c) => c.mcpSlug === appSlug && c.status === "active");
|
|
321
|
+
if (existingConnection) {
|
|
322
|
+
const { shouldReconnect } = await import_inquirer2.default.prompt([{
|
|
323
|
+
type: "confirm",
|
|
324
|
+
name: "shouldReconnect",
|
|
325
|
+
message: `You already have an active connection to ${app.name}. Create a new one?`,
|
|
326
|
+
default: false
|
|
327
|
+
}]);
|
|
328
|
+
if (!shouldReconnect) {
|
|
329
|
+
console.log(import_chalk6.default.yellow("\n Connection cancelled.\n"));
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const connectionRequest = await client.initiateConnection(appSlug, {
|
|
334
|
+
appName: options.label,
|
|
335
|
+
userId: options.userId
|
|
336
|
+
});
|
|
337
|
+
if (connectionRequest.redirectUrl) {
|
|
338
|
+
console.log(import_chalk6.default.bold(" Please authorize the connection:\n"));
|
|
339
|
+
console.log(` ${import_chalk6.default.cyan(connectionRequest.redirectUrl)}
|
|
340
|
+
`);
|
|
341
|
+
if (options.browser !== false) {
|
|
342
|
+
console.log(import_chalk6.default.dim(" Opening browser...\n"));
|
|
343
|
+
await (0, import_open2.default)(connectionRequest.redirectUrl);
|
|
344
|
+
}
|
|
345
|
+
console.log(import_chalk6.default.dim(" Waiting for authorization..."));
|
|
346
|
+
const timeout = 12e4;
|
|
347
|
+
const pollInterval = 3e3;
|
|
348
|
+
const startTime = Date.now();
|
|
349
|
+
while (Date.now() - startTime < timeout) {
|
|
350
|
+
await sleep(pollInterval);
|
|
351
|
+
try {
|
|
352
|
+
const connection = await client.getConnection(connectionRequest.id);
|
|
353
|
+
if (connection.status === "active") {
|
|
354
|
+
console.log(import_chalk6.default.green(`
|
|
355
|
+
Successfully connected to ${app.name}!
|
|
356
|
+
`));
|
|
357
|
+
console.log(` ${import_chalk6.default.cyan("Connection ID:")} ${connection.id}`);
|
|
358
|
+
console.log(` ${import_chalk6.default.cyan("MCP URL:")} ${connection.mcpUrl}
|
|
359
|
+
`);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
} catch {
|
|
363
|
+
}
|
|
364
|
+
process.stdout.write(".");
|
|
365
|
+
}
|
|
366
|
+
console.log(import_chalk6.default.red("\n\n Connection timed out. Please try again.\n"));
|
|
367
|
+
process.exit(1);
|
|
368
|
+
} else {
|
|
369
|
+
console.log(import_chalk6.default.green(`
|
|
370
|
+
Successfully connected to ${app.name}!
|
|
371
|
+
`));
|
|
372
|
+
console.log(` ${import_chalk6.default.cyan("Connection ID:")} ${connectionRequest.id}`);
|
|
373
|
+
if (connectionRequest.mcpUrl) {
|
|
374
|
+
console.log(` ${import_chalk6.default.cyan("MCP URL:")} ${connectionRequest.mcpUrl}
|
|
375
|
+
`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
} catch (error) {
|
|
379
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
380
|
+
console.log(import_chalk6.default.red(`
|
|
381
|
+
Failed to connect app: ${message}
|
|
382
|
+
`));
|
|
383
|
+
process.exit(1);
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
function sleep(ms) {
|
|
387
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// src/cli/commands/connections.ts
|
|
391
|
+
var import_commander6 = require("commander");
|
|
392
|
+
var import_chalk7 = __toESM(require("chalk"));
|
|
393
|
+
var import_inquirer3 = __toESM(require("inquirer"));
|
|
394
|
+
var connectionsCommand = new import_commander6.Command("connections").description("Manage your connections").action(async () => {
|
|
395
|
+
requireAuth();
|
|
396
|
+
try {
|
|
397
|
+
const client = getClient();
|
|
398
|
+
const connections = await client.listConnections();
|
|
399
|
+
if (connections.length === 0) {
|
|
400
|
+
console.log(import_chalk7.default.yellow("\n No connections found.\n"));
|
|
401
|
+
console.log(import_chalk7.default.dim(` Run ${import_chalk7.default.cyan("hornerosssp add <app>")} to connect an app.
|
|
402
|
+
`));
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
console.log(import_chalk7.default.bold(`
|
|
406
|
+
Your Connections (${connections.length})
|
|
407
|
+
`));
|
|
408
|
+
for (const conn of connections) {
|
|
409
|
+
const statusColor = conn.status === "active" ? import_chalk7.default.green : import_chalk7.default.red;
|
|
410
|
+
const statusIcon = conn.status === "active" ? "\u25CF" : "\u25CB";
|
|
411
|
+
console.log(` ${statusColor(statusIcon)} ${import_chalk7.default.cyan(conn.mcpName)} ${import_chalk7.default.dim(`(${conn.mcpSlug})`)}`);
|
|
412
|
+
console.log(` ${import_chalk7.default.dim("ID:")} ${conn.id}`);
|
|
413
|
+
if (conn.appName) {
|
|
414
|
+
console.log(` ${import_chalk7.default.dim("Label:")} ${conn.appName}`);
|
|
415
|
+
}
|
|
416
|
+
console.log(` ${import_chalk7.default.dim("Status:")} ${statusColor(conn.status)}`);
|
|
417
|
+
console.log(` ${import_chalk7.default.dim("Created:")} ${new Date(conn.createdAt).toLocaleDateString()}`);
|
|
418
|
+
if (conn.lastUsedAt) {
|
|
419
|
+
console.log(` ${import_chalk7.default.dim("Last used:")} ${new Date(conn.lastUsedAt).toLocaleDateString()}`);
|
|
420
|
+
}
|
|
421
|
+
console.log();
|
|
422
|
+
}
|
|
423
|
+
} catch (error) {
|
|
424
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
425
|
+
console.log(import_chalk7.default.red(`
|
|
426
|
+
Failed to list connections: ${message}
|
|
427
|
+
`));
|
|
428
|
+
process.exit(1);
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
connectionsCommand.command("get <id>").description("Get details of a specific connection").action(async (id) => {
|
|
432
|
+
requireAuth();
|
|
433
|
+
try {
|
|
434
|
+
const client = getClient();
|
|
435
|
+
const conn = await client.getConnection(id);
|
|
436
|
+
const statusColor = conn.status === "active" ? import_chalk7.default.green : import_chalk7.default.red;
|
|
437
|
+
console.log(import_chalk7.default.bold(`
|
|
438
|
+
Connection Details
|
|
439
|
+
`));
|
|
440
|
+
console.log(` ${import_chalk7.default.cyan("ID:")} ${conn.id}`);
|
|
441
|
+
console.log(` ${import_chalk7.default.cyan("App:")} ${conn.mcpName} (${conn.mcpSlug})`);
|
|
442
|
+
console.log(` ${import_chalk7.default.cyan("Status:")} ${statusColor(conn.status)}`);
|
|
443
|
+
if (conn.appName) {
|
|
444
|
+
console.log(` ${import_chalk7.default.cyan("Label:")} ${conn.appName}`);
|
|
445
|
+
}
|
|
446
|
+
if (conn.userId) {
|
|
447
|
+
console.log(` ${import_chalk7.default.cyan("User ID:")} ${conn.userId}`);
|
|
448
|
+
}
|
|
449
|
+
console.log(` ${import_chalk7.default.cyan("MCP URL:")} ${conn.mcpUrl}`);
|
|
450
|
+
console.log(` ${import_chalk7.default.cyan("Token:")} ${conn.token.substring(0, 20)}...`);
|
|
451
|
+
console.log(` ${import_chalk7.default.cyan("Created:")} ${new Date(conn.createdAt).toLocaleString()}`);
|
|
452
|
+
if (conn.lastUsedAt) {
|
|
453
|
+
console.log(` ${import_chalk7.default.cyan("Last used:")} ${new Date(conn.lastUsedAt).toLocaleString()}`);
|
|
454
|
+
}
|
|
455
|
+
if (conn.expiresAt) {
|
|
456
|
+
console.log(` ${import_chalk7.default.cyan("Expires:")} ${new Date(conn.expiresAt).toLocaleString()}`);
|
|
457
|
+
}
|
|
458
|
+
console.log();
|
|
459
|
+
} catch (error) {
|
|
460
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
461
|
+
console.log(import_chalk7.default.red(`
|
|
462
|
+
Failed to get connection: ${message}
|
|
463
|
+
`));
|
|
464
|
+
process.exit(1);
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
connectionsCommand.command("revoke <id>").description("Revoke a connection").option("-f, --force", "Skip confirmation").action(async (id, options) => {
|
|
468
|
+
requireAuth();
|
|
469
|
+
try {
|
|
470
|
+
const client = getClient();
|
|
471
|
+
const conn = await client.getConnection(id);
|
|
472
|
+
if (!options.force) {
|
|
473
|
+
const { confirm } = await import_inquirer3.default.prompt([{
|
|
474
|
+
type: "confirm",
|
|
475
|
+
name: "confirm",
|
|
476
|
+
message: `Are you sure you want to revoke the connection to ${conn.mcpName}?`,
|
|
477
|
+
default: false
|
|
478
|
+
}]);
|
|
479
|
+
if (!confirm) {
|
|
480
|
+
console.log(import_chalk7.default.yellow("\n Revoke cancelled.\n"));
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
await client.revokeConnection(id);
|
|
485
|
+
console.log(import_chalk7.default.green(`
|
|
486
|
+
Connection to ${conn.mcpName} has been revoked.
|
|
487
|
+
`));
|
|
488
|
+
} catch (error) {
|
|
489
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
490
|
+
console.log(import_chalk7.default.red(`
|
|
491
|
+
Failed to revoke connection: ${message}
|
|
492
|
+
`));
|
|
493
|
+
process.exit(1);
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
// src/cli/index.ts
|
|
498
|
+
var program = new import_commander7.Command();
|
|
499
|
+
program.name("hornerosssp").description("CLI for HornerosSSP - Connect MCPs to any app").version("0.3.0");
|
|
500
|
+
program.addCommand(loginCommand);
|
|
501
|
+
program.addCommand(logoutCommand);
|
|
502
|
+
program.addCommand(whoamiCommand);
|
|
503
|
+
program.addCommand(appsCommand);
|
|
504
|
+
program.addCommand(addCommand);
|
|
505
|
+
program.addCommand(connectionsCommand);
|
|
506
|
+
program.on("command:*", () => {
|
|
507
|
+
console.error(import_chalk8.default.red(`
|
|
508
|
+
Unknown command: ${program.args.join(" ")}`));
|
|
509
|
+
console.log(`Run ${import_chalk8.default.cyan("hornerosssp --help")} to see available commands.
|
|
510
|
+
`);
|
|
511
|
+
process.exit(1);
|
|
512
|
+
});
|
|
513
|
+
program.parse(process.argv);
|
|
514
|
+
if (!process.argv.slice(2).length) {
|
|
515
|
+
console.log(import_chalk8.default.bold("\n HornerosSSP CLI\n"));
|
|
516
|
+
console.log(" Connect MCPs to any application.\n");
|
|
517
|
+
console.log(import_chalk8.default.dim(" Commands:"));
|
|
518
|
+
console.log(` ${import_chalk8.default.cyan("login")} Authenticate with HornerosSSP`);
|
|
519
|
+
console.log(` ${import_chalk8.default.cyan("logout")} Remove stored credentials`);
|
|
520
|
+
console.log(` ${import_chalk8.default.cyan("whoami")} Show current user info`);
|
|
521
|
+
console.log(` ${import_chalk8.default.cyan("apps")} List available MCPs`);
|
|
522
|
+
console.log(` ${import_chalk8.default.cyan("add")} Connect a new app (OAuth flow)`);
|
|
523
|
+
console.log(` ${import_chalk8.default.cyan("connections")} Manage your connections
|
|
524
|
+
`);
|
|
525
|
+
console.log(` Run ${import_chalk8.default.cyan("hornerosssp <command> --help")} for more info.
|
|
526
|
+
`);
|
|
527
|
+
}
|
package/dist/index.d.mts
CHANGED
|
@@ -66,7 +66,12 @@ interface ConnectionData {
|
|
|
66
66
|
data: Record<string, string>;
|
|
67
67
|
}
|
|
68
68
|
interface HornerosSSPConfig {
|
|
69
|
-
|
|
69
|
+
/** API key for authentication. Falls back to HORNEROS_API_KEY env var. */
|
|
70
|
+
apiKey?: string;
|
|
71
|
+
/** Base URL of the HornerosSSP server. Falls back to HORNEROS_BASE_URL env var. */
|
|
72
|
+
baseUrl?: string;
|
|
73
|
+
/** Runtime identifier sent with every request (e.g. "node", "vercel"). */
|
|
74
|
+
runtime?: string;
|
|
70
75
|
}
|
|
71
76
|
interface ApiResponse<T> {
|
|
72
77
|
data: T;
|
|
@@ -119,7 +124,9 @@ declare class HornerosSSP {
|
|
|
119
124
|
readonly connections: Connections;
|
|
120
125
|
readonly tools: Tools;
|
|
121
126
|
private readonly baseUrl;
|
|
122
|
-
|
|
127
|
+
private readonly apiKey;
|
|
128
|
+
private readonly runtime;
|
|
129
|
+
constructor(config?: HornerosSSPConfig);
|
|
123
130
|
/** @internal */
|
|
124
131
|
fetch<T>(path: string, options?: RequestInit): Promise<T>;
|
|
125
132
|
}
|
|
@@ -143,10 +150,38 @@ declare class AuthScheme {
|
|
|
143
150
|
static GoogleLogin(): ConnectionData;
|
|
144
151
|
}
|
|
145
152
|
|
|
153
|
+
declare const HORNEROS_SDK_ERROR_CODES: {
|
|
154
|
+
readonly BACKEND: {
|
|
155
|
+
readonly NOT_FOUND: "BACKEND::NOT_FOUND";
|
|
156
|
+
readonly RATE_LIMIT: "BACKEND::RATE_LIMIT";
|
|
157
|
+
readonly BAD_REQUEST: "BACKEND::BAD_REQUEST";
|
|
158
|
+
readonly UNAUTHORIZED: "BACKEND::UNAUTHORIZED";
|
|
159
|
+
readonly SERVER_ERROR: "BACKEND::SERVER_ERROR";
|
|
160
|
+
readonly SERVER_UNAVAILABLE: "BACKEND::SERVER_UNAVAILABLE";
|
|
161
|
+
readonly UNKNOWN: "BACKEND::UNKNOWN";
|
|
162
|
+
};
|
|
163
|
+
readonly COMMON: {
|
|
164
|
+
readonly API_KEY_UNAVAILABLE: "COMMON::API_KEY_UNAVAILABLE";
|
|
165
|
+
readonly BASE_URL_NOT_REACHABLE: "COMMON::BASE_URL_NOT_REACHABLE";
|
|
166
|
+
readonly UNKNOWN: "COMMON::UNKNOWN";
|
|
167
|
+
readonly INVALID_PARAMS: "COMMON::INVALID_PARAMS";
|
|
168
|
+
};
|
|
169
|
+
readonly SDK: {
|
|
170
|
+
readonly NO_CONNECTED_ACCOUNT: "SDK::NO_CONNECTED_ACCOUNT";
|
|
171
|
+
readonly CONNECTION_TIMEOUT: "SDK::CONNECTION_TIMEOUT";
|
|
172
|
+
readonly INVALID_PARAMETER: "SDK::INVALID_PARAMETER";
|
|
173
|
+
};
|
|
174
|
+
};
|
|
146
175
|
declare class HornerosError extends Error {
|
|
176
|
+
readonly errCode: string;
|
|
147
177
|
readonly statusCode: number;
|
|
148
178
|
readonly body: unknown;
|
|
149
|
-
|
|
179
|
+
readonly description?: string;
|
|
180
|
+
readonly possibleFix?: string;
|
|
181
|
+
readonly errorId: string;
|
|
182
|
+
readonly timestamp: string;
|
|
183
|
+
constructor(errCode: string, message: string, statusCode: number, body?: unknown, description?: string, possibleFix?: string);
|
|
184
|
+
toJSON(): Record<string, unknown>;
|
|
150
185
|
}
|
|
151
186
|
declare class NotFoundError extends HornerosError {
|
|
152
187
|
constructor(message: string, body?: unknown);
|
|
@@ -158,4 +193,4 @@ declare class ConnectionTimeoutError extends HornerosError {
|
|
|
158
193
|
constructor(message?: string);
|
|
159
194
|
}
|
|
160
195
|
|
|
161
|
-
export { type ApiError, type ApiResponse, AuthScheme, type ConnectionData, type ConnectionInfo, ConnectionRequest, type ConnectionRequestData, ConnectionTimeoutError, Connections, type ExecuteToolParams, HornerosError, HornerosSSP, type HornerosSSPConfig, type InitiateConnectionParams, type McpDetail, type McpInfo, Mcps, NotFoundError, type ToolDefinition, type ToolResult, Tools, ValidationError };
|
|
196
|
+
export { type ApiError, type ApiResponse, AuthScheme, type ConnectionData, type ConnectionInfo, ConnectionRequest, type ConnectionRequestData, ConnectionTimeoutError, Connections, type ExecuteToolParams, HORNEROS_SDK_ERROR_CODES, HornerosError, HornerosSSP, type HornerosSSPConfig, type InitiateConnectionParams, type McpDetail, type McpInfo, Mcps, NotFoundError, type ToolDefinition, type ToolResult, Tools, ValidationError };
|
package/dist/index.d.ts
CHANGED
|
@@ -66,7 +66,12 @@ interface ConnectionData {
|
|
|
66
66
|
data: Record<string, string>;
|
|
67
67
|
}
|
|
68
68
|
interface HornerosSSPConfig {
|
|
69
|
-
|
|
69
|
+
/** API key for authentication. Falls back to HORNEROS_API_KEY env var. */
|
|
70
|
+
apiKey?: string;
|
|
71
|
+
/** Base URL of the HornerosSSP server. Falls back to HORNEROS_BASE_URL env var. */
|
|
72
|
+
baseUrl?: string;
|
|
73
|
+
/** Runtime identifier sent with every request (e.g. "node", "vercel"). */
|
|
74
|
+
runtime?: string;
|
|
70
75
|
}
|
|
71
76
|
interface ApiResponse<T> {
|
|
72
77
|
data: T;
|
|
@@ -119,7 +124,9 @@ declare class HornerosSSP {
|
|
|
119
124
|
readonly connections: Connections;
|
|
120
125
|
readonly tools: Tools;
|
|
121
126
|
private readonly baseUrl;
|
|
122
|
-
|
|
127
|
+
private readonly apiKey;
|
|
128
|
+
private readonly runtime;
|
|
129
|
+
constructor(config?: HornerosSSPConfig);
|
|
123
130
|
/** @internal */
|
|
124
131
|
fetch<T>(path: string, options?: RequestInit): Promise<T>;
|
|
125
132
|
}
|
|
@@ -143,10 +150,38 @@ declare class AuthScheme {
|
|
|
143
150
|
static GoogleLogin(): ConnectionData;
|
|
144
151
|
}
|
|
145
152
|
|
|
153
|
+
declare const HORNEROS_SDK_ERROR_CODES: {
|
|
154
|
+
readonly BACKEND: {
|
|
155
|
+
readonly NOT_FOUND: "BACKEND::NOT_FOUND";
|
|
156
|
+
readonly RATE_LIMIT: "BACKEND::RATE_LIMIT";
|
|
157
|
+
readonly BAD_REQUEST: "BACKEND::BAD_REQUEST";
|
|
158
|
+
readonly UNAUTHORIZED: "BACKEND::UNAUTHORIZED";
|
|
159
|
+
readonly SERVER_ERROR: "BACKEND::SERVER_ERROR";
|
|
160
|
+
readonly SERVER_UNAVAILABLE: "BACKEND::SERVER_UNAVAILABLE";
|
|
161
|
+
readonly UNKNOWN: "BACKEND::UNKNOWN";
|
|
162
|
+
};
|
|
163
|
+
readonly COMMON: {
|
|
164
|
+
readonly API_KEY_UNAVAILABLE: "COMMON::API_KEY_UNAVAILABLE";
|
|
165
|
+
readonly BASE_URL_NOT_REACHABLE: "COMMON::BASE_URL_NOT_REACHABLE";
|
|
166
|
+
readonly UNKNOWN: "COMMON::UNKNOWN";
|
|
167
|
+
readonly INVALID_PARAMS: "COMMON::INVALID_PARAMS";
|
|
168
|
+
};
|
|
169
|
+
readonly SDK: {
|
|
170
|
+
readonly NO_CONNECTED_ACCOUNT: "SDK::NO_CONNECTED_ACCOUNT";
|
|
171
|
+
readonly CONNECTION_TIMEOUT: "SDK::CONNECTION_TIMEOUT";
|
|
172
|
+
readonly INVALID_PARAMETER: "SDK::INVALID_PARAMETER";
|
|
173
|
+
};
|
|
174
|
+
};
|
|
146
175
|
declare class HornerosError extends Error {
|
|
176
|
+
readonly errCode: string;
|
|
147
177
|
readonly statusCode: number;
|
|
148
178
|
readonly body: unknown;
|
|
149
|
-
|
|
179
|
+
readonly description?: string;
|
|
180
|
+
readonly possibleFix?: string;
|
|
181
|
+
readonly errorId: string;
|
|
182
|
+
readonly timestamp: string;
|
|
183
|
+
constructor(errCode: string, message: string, statusCode: number, body?: unknown, description?: string, possibleFix?: string);
|
|
184
|
+
toJSON(): Record<string, unknown>;
|
|
150
185
|
}
|
|
151
186
|
declare class NotFoundError extends HornerosError {
|
|
152
187
|
constructor(message: string, body?: unknown);
|
|
@@ -158,4 +193,4 @@ declare class ConnectionTimeoutError extends HornerosError {
|
|
|
158
193
|
constructor(message?: string);
|
|
159
194
|
}
|
|
160
195
|
|
|
161
|
-
export { type ApiError, type ApiResponse, AuthScheme, type ConnectionData, type ConnectionInfo, ConnectionRequest, type ConnectionRequestData, ConnectionTimeoutError, Connections, type ExecuteToolParams, HornerosError, HornerosSSP, type HornerosSSPConfig, type InitiateConnectionParams, type McpDetail, type McpInfo, Mcps, NotFoundError, type ToolDefinition, type ToolResult, Tools, ValidationError };
|
|
196
|
+
export { type ApiError, type ApiResponse, AuthScheme, type ConnectionData, type ConnectionInfo, ConnectionRequest, type ConnectionRequestData, ConnectionTimeoutError, Connections, type ExecuteToolParams, HORNEROS_SDK_ERROR_CODES, HornerosError, HornerosSSP, type HornerosSSPConfig, type InitiateConnectionParams, type McpDetail, type McpInfo, Mcps, NotFoundError, type ToolDefinition, type ToolResult, Tools, ValidationError };
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ __export(index_exports, {
|
|
|
24
24
|
ConnectionRequest: () => ConnectionRequest,
|
|
25
25
|
ConnectionTimeoutError: () => ConnectionTimeoutError,
|
|
26
26
|
Connections: () => Connections,
|
|
27
|
+
HORNEROS_SDK_ERROR_CODES: () => HORNEROS_SDK_ERROR_CODES,
|
|
27
28
|
HornerosError: () => HornerosError,
|
|
28
29
|
HornerosSSP: () => HornerosSSP,
|
|
29
30
|
Mcps: () => Mcps,
|
|
@@ -34,29 +35,77 @@ __export(index_exports, {
|
|
|
34
35
|
module.exports = __toCommonJS(index_exports);
|
|
35
36
|
|
|
36
37
|
// src/errors.ts
|
|
38
|
+
var HORNEROS_SDK_ERROR_CODES = {
|
|
39
|
+
BACKEND: {
|
|
40
|
+
NOT_FOUND: "BACKEND::NOT_FOUND",
|
|
41
|
+
RATE_LIMIT: "BACKEND::RATE_LIMIT",
|
|
42
|
+
BAD_REQUEST: "BACKEND::BAD_REQUEST",
|
|
43
|
+
UNAUTHORIZED: "BACKEND::UNAUTHORIZED",
|
|
44
|
+
SERVER_ERROR: "BACKEND::SERVER_ERROR",
|
|
45
|
+
SERVER_UNAVAILABLE: "BACKEND::SERVER_UNAVAILABLE",
|
|
46
|
+
UNKNOWN: "BACKEND::UNKNOWN"
|
|
47
|
+
},
|
|
48
|
+
COMMON: {
|
|
49
|
+
API_KEY_UNAVAILABLE: "COMMON::API_KEY_UNAVAILABLE",
|
|
50
|
+
BASE_URL_NOT_REACHABLE: "COMMON::BASE_URL_NOT_REACHABLE",
|
|
51
|
+
UNKNOWN: "COMMON::UNKNOWN",
|
|
52
|
+
INVALID_PARAMS: "COMMON::INVALID_PARAMS"
|
|
53
|
+
},
|
|
54
|
+
SDK: {
|
|
55
|
+
NO_CONNECTED_ACCOUNT: "SDK::NO_CONNECTED_ACCOUNT",
|
|
56
|
+
CONNECTION_TIMEOUT: "SDK::CONNECTION_TIMEOUT",
|
|
57
|
+
INVALID_PARAMETER: "SDK::INVALID_PARAMETER"
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var errorCounter = 0;
|
|
37
61
|
var HornerosError = class extends Error {
|
|
38
|
-
constructor(message, statusCode, body) {
|
|
62
|
+
constructor(errCode, message, statusCode, body, description, possibleFix) {
|
|
39
63
|
super(message);
|
|
40
64
|
this.name = "HornerosError";
|
|
65
|
+
this.errCode = errCode;
|
|
41
66
|
this.statusCode = statusCode;
|
|
42
67
|
this.body = body;
|
|
68
|
+
this.description = description;
|
|
69
|
+
this.possibleFix = possibleFix;
|
|
70
|
+
this.errorId = `horneros_${Date.now()}_${++errorCounter}`;
|
|
71
|
+
this.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
72
|
+
}
|
|
73
|
+
toJSON() {
|
|
74
|
+
return {
|
|
75
|
+
name: this.name,
|
|
76
|
+
errCode: this.errCode,
|
|
77
|
+
message: this.message,
|
|
78
|
+
statusCode: this.statusCode,
|
|
79
|
+
description: this.description,
|
|
80
|
+
possibleFix: this.possibleFix,
|
|
81
|
+
errorId: this.errorId,
|
|
82
|
+
timestamp: this.timestamp,
|
|
83
|
+
body: this.body
|
|
84
|
+
};
|
|
43
85
|
}
|
|
44
86
|
};
|
|
45
87
|
var NotFoundError = class extends HornerosError {
|
|
46
88
|
constructor(message, body) {
|
|
47
|
-
super(message, 404, body);
|
|
89
|
+
super(HORNEROS_SDK_ERROR_CODES.BACKEND.NOT_FOUND, message, 404, body);
|
|
48
90
|
this.name = "NotFoundError";
|
|
49
91
|
}
|
|
50
92
|
};
|
|
51
93
|
var ValidationError = class extends HornerosError {
|
|
52
94
|
constructor(message, body) {
|
|
53
|
-
super(message, 400, body);
|
|
95
|
+
super(HORNEROS_SDK_ERROR_CODES.BACKEND.BAD_REQUEST, message, 400, body);
|
|
54
96
|
this.name = "ValidationError";
|
|
55
97
|
}
|
|
56
98
|
};
|
|
57
99
|
var ConnectionTimeoutError = class extends HornerosError {
|
|
58
100
|
constructor(message = "Connection timed out waiting for activation") {
|
|
59
|
-
super(
|
|
101
|
+
super(
|
|
102
|
+
HORNEROS_SDK_ERROR_CODES.SDK.CONNECTION_TIMEOUT,
|
|
103
|
+
message,
|
|
104
|
+
408,
|
|
105
|
+
void 0,
|
|
106
|
+
"The connection did not become active within the timeout period.",
|
|
107
|
+
"Increase the timeout value or check that the user completed the authentication flow."
|
|
108
|
+
);
|
|
60
109
|
this.name = "ConnectionTimeoutError";
|
|
61
110
|
}
|
|
62
111
|
};
|
|
@@ -186,9 +235,35 @@ var Tools = class {
|
|
|
186
235
|
};
|
|
187
236
|
|
|
188
237
|
// src/client.ts
|
|
238
|
+
function getEnvVariable(name) {
|
|
239
|
+
if (typeof process !== "undefined" && process.env) {
|
|
240
|
+
return process.env[name];
|
|
241
|
+
}
|
|
242
|
+
return void 0;
|
|
243
|
+
}
|
|
244
|
+
var DEFAULT_BASE_URL = "http://localhost:3000";
|
|
245
|
+
function resolveConfig(config) {
|
|
246
|
+
const baseUrl = config?.baseUrl || getEnvVariable("HORNEROS_BASE_URL") || DEFAULT_BASE_URL;
|
|
247
|
+
const apiKey = config?.apiKey || getEnvVariable("HORNEROS_API_KEY") || "";
|
|
248
|
+
const runtime = config?.runtime || getEnvVariable("HORNEROS_RUNTIME") || "";
|
|
249
|
+
return { baseUrl: baseUrl.replace(/\/+$/, ""), apiKey, runtime };
|
|
250
|
+
}
|
|
189
251
|
var HornerosSSP = class {
|
|
190
252
|
constructor(config) {
|
|
191
|
-
|
|
253
|
+
const resolved = resolveConfig(config);
|
|
254
|
+
if (!resolved.apiKey) {
|
|
255
|
+
throw new HornerosError(
|
|
256
|
+
HORNEROS_SDK_ERROR_CODES.COMMON.API_KEY_UNAVAILABLE,
|
|
257
|
+
"\u{1F511} API Key is not provided",
|
|
258
|
+
401,
|
|
259
|
+
void 0,
|
|
260
|
+
"You need to provide an API key in the constructor or as the environment variable HORNEROS_API_KEY.",
|
|
261
|
+
'Provide a valid API key: new HornerosSSP({ apiKey: "hsp_xxx" }) or set HORNEROS_API_KEY in your environment.'
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
this.baseUrl = resolved.baseUrl;
|
|
265
|
+
this.apiKey = resolved.apiKey;
|
|
266
|
+
this.runtime = resolved.runtime;
|
|
192
267
|
this.mcps = new Mcps(this);
|
|
193
268
|
this.connections = new Connections(this);
|
|
194
269
|
this.tools = new Tools(this);
|
|
@@ -198,6 +273,9 @@ var HornerosSSP = class {
|
|
|
198
273
|
const url = `${this.baseUrl}/api/v1${path}`;
|
|
199
274
|
const headers = {
|
|
200
275
|
"Content-Type": "application/json",
|
|
276
|
+
"X-Api-Key": this.apiKey,
|
|
277
|
+
"X-Source": "js_sdk",
|
|
278
|
+
"X-Runtime": this.runtime,
|
|
201
279
|
...options.headers
|
|
202
280
|
};
|
|
203
281
|
const res = await globalThis.fetch(url, {
|
|
@@ -212,7 +290,8 @@ var HornerosSSP = class {
|
|
|
212
290
|
body = await res.text().catch(() => null);
|
|
213
291
|
}
|
|
214
292
|
const message = (body && typeof body === "object" && "error" in body ? body.error : null) || `HTTP ${res.status}`;
|
|
215
|
-
|
|
293
|
+
const errCode = res.status === 404 ? HORNEROS_SDK_ERROR_CODES.BACKEND.NOT_FOUND : res.status === 401 ? HORNEROS_SDK_ERROR_CODES.BACKEND.UNAUTHORIZED : res.status === 429 ? HORNEROS_SDK_ERROR_CODES.BACKEND.RATE_LIMIT : res.status === 400 ? HORNEROS_SDK_ERROR_CODES.BACKEND.BAD_REQUEST : res.status >= 500 ? HORNEROS_SDK_ERROR_CODES.BACKEND.SERVER_ERROR : HORNEROS_SDK_ERROR_CODES.BACKEND.UNKNOWN;
|
|
294
|
+
throw new HornerosError(errCode, message, res.status, body);
|
|
216
295
|
}
|
|
217
296
|
if (res.status === 204) {
|
|
218
297
|
return void 0;
|
|
@@ -248,6 +327,7 @@ var AuthScheme = class {
|
|
|
248
327
|
ConnectionRequest,
|
|
249
328
|
ConnectionTimeoutError,
|
|
250
329
|
Connections,
|
|
330
|
+
HORNEROS_SDK_ERROR_CODES,
|
|
251
331
|
HornerosError,
|
|
252
332
|
HornerosSSP,
|
|
253
333
|
Mcps,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/mcps.ts","../src/connections.ts","../src/tools.ts","../src/client.ts","../src/auth-scheme.ts"],"sourcesContent":["export { HornerosSSP } from \"./client\";\nexport { AuthScheme } from \"./auth-scheme\";\nexport { Mcps } from \"./mcps\";\nexport { Connections, ConnectionRequest } from \"./connections\";\nexport { Tools } from \"./tools\";\n\n// Errors\nexport {\n HornerosError,\n NotFoundError,\n ValidationError,\n ConnectionTimeoutError,\n} from \"./errors\";\n\n// Types\nexport type {\n HornerosSSPConfig,\n McpInfo,\n McpDetail,\n ConnectionInfo,\n ConnectionRequestData,\n InitiateConnectionParams,\n ToolDefinition,\n ToolResult,\n ExecuteToolParams,\n ConnectionData,\n ApiResponse,\n ApiError,\n} from \"./types\";\n","export class HornerosError extends Error {\n public readonly statusCode: number;\n public readonly body: unknown;\n\n constructor(message: string, statusCode: number, body?: unknown) {\n super(message);\n this.name = \"HornerosError\";\n this.statusCode = statusCode;\n this.body = body;\n }\n}\n\nexport class NotFoundError extends HornerosError {\n constructor(message: string, body?: unknown) {\n super(message, 404, body);\n this.name = \"NotFoundError\";\n }\n}\n\nexport class ValidationError extends HornerosError {\n constructor(message: string, body?: unknown) {\n super(message, 400, body);\n this.name = \"ValidationError\";\n }\n}\n\nexport class ConnectionTimeoutError extends HornerosError {\n constructor(message = \"Connection timed out waiting for activation\") {\n super(message, 408);\n this.name = \"ConnectionTimeoutError\";\n }\n}\n","import type { HornerosSSP } from \"./client\";\nimport type { McpInfo, McpDetail, ApiResponse } from \"./types\";\n\nexport class Mcps {\n constructor(private client: HornerosSSP) {}\n\n async list(): Promise<McpInfo[]> {\n const res = await this.client.fetch<ApiResponse<McpInfo[]>>(\"/mcps\");\n return res.data;\n }\n\n async get(slug: string): Promise<McpDetail> {\n const res = await this.client.fetch<ApiResponse<McpDetail>>(\n `/mcps/${encodeURIComponent(slug)}`\n );\n return res.data;\n }\n}\n","import type { HornerosSSP } from \"./client\";\nimport type {\n ConnectionInfo,\n ConnectionRequestData,\n InitiateConnectionParams,\n ApiResponse,\n} from \"./types\";\nimport { ConnectionTimeoutError } from \"./errors\";\n\nexport class ConnectionRequest {\n public readonly id: string;\n public readonly mcpUrl: string | null;\n public readonly token: string | null;\n public readonly redirectUrl: string | null;\n public readonly status: \"active\" | \"pending\";\n\n constructor(\n private client: HornerosSSP,\n data: ConnectionRequestData\n ) {\n this.id = data.id;\n this.mcpUrl = data.mcpUrl;\n this.token = data.token;\n this.redirectUrl = data.redirectUrl;\n this.status = data.status;\n }\n\n /**\n * Polls the connection until it becomes active.\n * Useful for OAuth/interactive flows where the user needs to\n * complete authentication in a browser.\n * @param timeout Max wait time in ms (default: 120000 = 2 min)\n */\n async waitForConnection(timeout = 120_000): Promise<ConnectionInfo> {\n if (this.status === \"active\") {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(this.id)}`\n );\n return res.data;\n }\n\n const start = Date.now();\n const interval = 2000;\n\n while (Date.now() - start < timeout) {\n await sleep(interval);\n try {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(this.id)}`\n );\n if (res.data.status === \"active\") {\n return res.data;\n }\n } catch {\n // Connection not yet created, keep polling\n }\n }\n\n throw new ConnectionTimeoutError();\n }\n}\n\nexport class Connections {\n constructor(private client: HornerosSSP) {}\n\n async initiate(params: InitiateConnectionParams): Promise<ConnectionRequest> {\n const body: Record<string, unknown> = {\n mcp_slug: params.mcpSlug,\n };\n\n if (params.appName) body.app_name = params.appName;\n if (params.userId) body.user_id = params.userId;\n if (params.credentials) body.credentials = params.credentials;\n if (params.authScheme) body.auth_scheme = params.authScheme;\n\n const res = await this.client.fetch<ApiResponse<ConnectionRequestData>>(\n \"/connections\",\n { method: \"POST\", body: JSON.stringify(body) }\n );\n\n return new ConnectionRequest(this.client, res.data);\n }\n\n async list(): Promise<ConnectionInfo[]> {\n const res =\n await this.client.fetch<ApiResponse<ConnectionInfo[]>>(\"/connections\");\n return res.data;\n }\n\n async get(id: string): Promise<ConnectionInfo> {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(id)}`\n );\n return res.data;\n }\n\n async revoke(id: string): Promise<void> {\n await this.client.fetch<void>(\n `/connections/${encodeURIComponent(id)}`,\n { method: \"DELETE\" }\n );\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { HornerosSSP } from \"./client\";\nimport type {\n ToolDefinition,\n ToolResult,\n ExecuteToolParams,\n ApiResponse,\n} from \"./types\";\n\nexport class Tools {\n constructor(private client: HornerosSSP) {}\n\n async list(mcpSlug: string): Promise<ToolDefinition[]> {\n const res = await this.client.fetch<ApiResponse<ToolDefinition[]>>(\n `/mcps/${encodeURIComponent(mcpSlug)}/tools`\n );\n return res.data;\n }\n\n async execute(params: ExecuteToolParams): Promise<ToolResult> {\n const res = await this.client.fetch<ApiResponse<ToolResult>>(\n \"/tools/execute\",\n {\n method: \"POST\",\n body: JSON.stringify({\n mcp_slug: params.mcpSlug,\n connection_id: params.connectionId,\n tool_name: params.toolName,\n arguments: params.arguments,\n }),\n }\n );\n return res.data;\n }\n}\n","import type { HornerosSSPConfig } from \"./types\";\nimport { HornerosError } from \"./errors\";\nimport { Mcps } from \"./mcps\";\nimport { Connections } from \"./connections\";\nimport { Tools } from \"./tools\";\n\nexport class HornerosSSP {\n public readonly mcps: Mcps;\n public readonly connections: Connections;\n public readonly tools: Tools;\n\n private readonly baseUrl: string;\n\n constructor(config: HornerosSSPConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n\n this.mcps = new Mcps(this);\n this.connections = new Connections(this);\n this.tools = new Tools(this);\n }\n\n /** @internal */\n async fetch<T>(\n path: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.baseUrl}/api/v1${path}`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(options.headers as Record<string, string>),\n };\n\n const res = await globalThis.fetch(url, {\n ...options,\n headers,\n });\n\n if (!res.ok) {\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n body = await res.text().catch(() => null);\n }\n const message =\n (body && typeof body === \"object\" && \"error\" in body\n ? (body as { error: string }).error\n : null) || `HTTP ${res.status}`;\n throw new HornerosError(message, res.status, body);\n }\n\n if (res.status === 204) {\n return undefined as T;\n }\n\n return res.json() as Promise<T>;\n }\n}\n","import type { ConnectionData } from \"./types\";\n\nexport class AuthScheme {\n static APIKey(params: { api_key: string; [k: string]: string }): ConnectionData {\n return { type: \"api_key\", data: params };\n }\n\n static Bearer(params: { token: string }): ConnectionData {\n return { type: \"bearer\", data: params };\n }\n\n static Basic(params: { username: string; password: string }): ConnectionData {\n return { type: \"basic\", data: params };\n }\n\n static OAuth2(params: {\n access_token: string;\n refresh_token?: string;\n }): ConnectionData {\n return {\n type: \"oauth2\",\n data: params as Record<string, string>,\n };\n }\n\n static GoogleLogin(): ConnectionData {\n return { type: \"google_login\", data: {} };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/mcps.ts","../src/connections.ts","../src/tools.ts","../src/client.ts","../src/auth-scheme.ts"],"sourcesContent":["export { HornerosSSP } from \"./client\";\nexport { AuthScheme } from \"./auth-scheme\";\nexport { Mcps } from \"./mcps\";\nexport { Connections, ConnectionRequest } from \"./connections\";\nexport { Tools } from \"./tools\";\n\n// Errors\nexport {\n HornerosError,\n NotFoundError,\n ValidationError,\n ConnectionTimeoutError,\n HORNEROS_SDK_ERROR_CODES,\n} from \"./errors\";\n\n// Types\nexport type {\n HornerosSSPConfig,\n McpInfo,\n McpDetail,\n ConnectionInfo,\n ConnectionRequestData,\n InitiateConnectionParams,\n ToolDefinition,\n ToolResult,\n ExecuteToolParams,\n ConnectionData,\n ApiResponse,\n ApiError,\n} from \"./types\";\n","// ── Error codes ─────────────────────────────────────────────\n\nexport const HORNEROS_SDK_ERROR_CODES = {\n BACKEND: {\n NOT_FOUND: \"BACKEND::NOT_FOUND\",\n RATE_LIMIT: \"BACKEND::RATE_LIMIT\",\n BAD_REQUEST: \"BACKEND::BAD_REQUEST\",\n UNAUTHORIZED: \"BACKEND::UNAUTHORIZED\",\n SERVER_ERROR: \"BACKEND::SERVER_ERROR\",\n SERVER_UNAVAILABLE: \"BACKEND::SERVER_UNAVAILABLE\",\n UNKNOWN: \"BACKEND::UNKNOWN\",\n },\n COMMON: {\n API_KEY_UNAVAILABLE: \"COMMON::API_KEY_UNAVAILABLE\",\n BASE_URL_NOT_REACHABLE: \"COMMON::BASE_URL_NOT_REACHABLE\",\n UNKNOWN: \"COMMON::UNKNOWN\",\n INVALID_PARAMS: \"COMMON::INVALID_PARAMS\",\n },\n SDK: {\n NO_CONNECTED_ACCOUNT: \"SDK::NO_CONNECTED_ACCOUNT\",\n CONNECTION_TIMEOUT: \"SDK::CONNECTION_TIMEOUT\",\n INVALID_PARAMETER: \"SDK::INVALID_PARAMETER\",\n },\n} as const;\n\n// ── Base error ──────────────────────────────────────────────\n\nlet errorCounter = 0;\n\nexport class HornerosError extends Error {\n public readonly errCode: string;\n public readonly statusCode: number;\n public readonly body: unknown;\n public readonly description?: string;\n public readonly possibleFix?: string;\n public readonly errorId: string;\n public readonly timestamp: string;\n\n constructor(\n errCode: string,\n message: string,\n statusCode: number,\n body?: unknown,\n description?: string,\n possibleFix?: string\n ) {\n super(message);\n this.name = \"HornerosError\";\n this.errCode = errCode;\n this.statusCode = statusCode;\n this.body = body;\n this.description = description;\n this.possibleFix = possibleFix;\n this.errorId = `horneros_${Date.now()}_${++errorCounter}`;\n this.timestamp = new Date().toISOString();\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n errCode: this.errCode,\n message: this.message,\n statusCode: this.statusCode,\n description: this.description,\n possibleFix: this.possibleFix,\n errorId: this.errorId,\n timestamp: this.timestamp,\n body: this.body,\n };\n }\n}\n\n// ── Specialized errors ──────────────────────────────────────\n\nexport class NotFoundError extends HornerosError {\n constructor(message: string, body?: unknown) {\n super(HORNEROS_SDK_ERROR_CODES.BACKEND.NOT_FOUND, message, 404, body);\n this.name = \"NotFoundError\";\n }\n}\n\nexport class ValidationError extends HornerosError {\n constructor(message: string, body?: unknown) {\n super(HORNEROS_SDK_ERROR_CODES.BACKEND.BAD_REQUEST, message, 400, body);\n this.name = \"ValidationError\";\n }\n}\n\nexport class ConnectionTimeoutError extends HornerosError {\n constructor(message = \"Connection timed out waiting for activation\") {\n super(\n HORNEROS_SDK_ERROR_CODES.SDK.CONNECTION_TIMEOUT,\n message,\n 408,\n undefined,\n \"The connection did not become active within the timeout period.\",\n \"Increase the timeout value or check that the user completed the authentication flow.\"\n );\n this.name = \"ConnectionTimeoutError\";\n }\n}\n","import type { HornerosSSP } from \"./client\";\nimport type { McpInfo, McpDetail, ApiResponse } from \"./types\";\n\nexport class Mcps {\n constructor(private client: HornerosSSP) {}\n\n async list(): Promise<McpInfo[]> {\n const res = await this.client.fetch<ApiResponse<McpInfo[]>>(\"/mcps\");\n return res.data;\n }\n\n async get(slug: string): Promise<McpDetail> {\n const res = await this.client.fetch<ApiResponse<McpDetail>>(\n `/mcps/${encodeURIComponent(slug)}`\n );\n return res.data;\n }\n}\n","import type { HornerosSSP } from \"./client\";\nimport type {\n ConnectionInfo,\n ConnectionRequestData,\n InitiateConnectionParams,\n ApiResponse,\n} from \"./types\";\nimport { ConnectionTimeoutError } from \"./errors\";\n\nexport class ConnectionRequest {\n public readonly id: string;\n public readonly mcpUrl: string | null;\n public readonly token: string | null;\n public readonly redirectUrl: string | null;\n public readonly status: \"active\" | \"pending\";\n\n constructor(\n private client: HornerosSSP,\n data: ConnectionRequestData\n ) {\n this.id = data.id;\n this.mcpUrl = data.mcpUrl;\n this.token = data.token;\n this.redirectUrl = data.redirectUrl;\n this.status = data.status;\n }\n\n /**\n * Polls the connection until it becomes active.\n * Useful for OAuth/interactive flows where the user needs to\n * complete authentication in a browser.\n * @param timeout Max wait time in ms (default: 120000 = 2 min)\n */\n async waitForConnection(timeout = 120_000): Promise<ConnectionInfo> {\n if (this.status === \"active\") {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(this.id)}`\n );\n return res.data;\n }\n\n const start = Date.now();\n const interval = 2000;\n\n while (Date.now() - start < timeout) {\n await sleep(interval);\n try {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(this.id)}`\n );\n if (res.data.status === \"active\") {\n return res.data;\n }\n } catch {\n // Connection not yet created, keep polling\n }\n }\n\n throw new ConnectionTimeoutError();\n }\n}\n\nexport class Connections {\n constructor(private client: HornerosSSP) {}\n\n async initiate(params: InitiateConnectionParams): Promise<ConnectionRequest> {\n const body: Record<string, unknown> = {\n mcp_slug: params.mcpSlug,\n };\n\n if (params.appName) body.app_name = params.appName;\n if (params.userId) body.user_id = params.userId;\n if (params.credentials) body.credentials = params.credentials;\n if (params.authScheme) body.auth_scheme = params.authScheme;\n\n const res = await this.client.fetch<ApiResponse<ConnectionRequestData>>(\n \"/connections\",\n { method: \"POST\", body: JSON.stringify(body) }\n );\n\n return new ConnectionRequest(this.client, res.data);\n }\n\n async list(): Promise<ConnectionInfo[]> {\n const res =\n await this.client.fetch<ApiResponse<ConnectionInfo[]>>(\"/connections\");\n return res.data;\n }\n\n async get(id: string): Promise<ConnectionInfo> {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(id)}`\n );\n return res.data;\n }\n\n async revoke(id: string): Promise<void> {\n await this.client.fetch<void>(\n `/connections/${encodeURIComponent(id)}`,\n { method: \"DELETE\" }\n );\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { HornerosSSP } from \"./client\";\nimport type {\n ToolDefinition,\n ToolResult,\n ExecuteToolParams,\n ApiResponse,\n} from \"./types\";\n\nexport class Tools {\n constructor(private client: HornerosSSP) {}\n\n async list(mcpSlug: string): Promise<ToolDefinition[]> {\n const res = await this.client.fetch<ApiResponse<ToolDefinition[]>>(\n `/mcps/${encodeURIComponent(mcpSlug)}/tools`\n );\n return res.data;\n }\n\n async execute(params: ExecuteToolParams): Promise<ToolResult> {\n const res = await this.client.fetch<ApiResponse<ToolResult>>(\n \"/tools/execute\",\n {\n method: \"POST\",\n body: JSON.stringify({\n mcp_slug: params.mcpSlug,\n connection_id: params.connectionId,\n tool_name: params.toolName,\n arguments: params.arguments,\n }),\n }\n );\n return res.data;\n }\n}\n","import type { HornerosSSPConfig } from \"./types\";\nimport { HornerosError, HORNEROS_SDK_ERROR_CODES } from \"./errors\";\nimport { Mcps } from \"./mcps\";\nimport { Connections } from \"./connections\";\nimport { Tools } from \"./tools\";\n\n// ── Helpers ─────────────────────────────────────────────────\n\nfunction getEnvVariable(name: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[name];\n }\n return undefined;\n}\n\nconst DEFAULT_BASE_URL = \"http://localhost:3000\";\n\nfunction resolveConfig(config?: HornerosSSPConfig) {\n const baseUrl =\n config?.baseUrl ||\n getEnvVariable(\"HORNEROS_BASE_URL\") ||\n DEFAULT_BASE_URL;\n\n const apiKey =\n config?.apiKey ||\n getEnvVariable(\"HORNEROS_API_KEY\") ||\n \"\";\n\n const runtime = config?.runtime || getEnvVariable(\"HORNEROS_RUNTIME\") || \"\";\n\n return { baseUrl: baseUrl.replace(/\\/+$/, \"\"), apiKey, runtime };\n}\n\n// ── Main client ─────────────────────────────────────────────\n\nexport class HornerosSSP {\n public readonly mcps: Mcps;\n public readonly connections: Connections;\n public readonly tools: Tools;\n\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly runtime: string;\n\n constructor(config?: HornerosSSPConfig) {\n const resolved = resolveConfig(config);\n\n if (!resolved.apiKey) {\n throw new HornerosError(\n HORNEROS_SDK_ERROR_CODES.COMMON.API_KEY_UNAVAILABLE,\n \"🔑 API Key is not provided\",\n 401,\n undefined,\n \"You need to provide an API key in the constructor or as the environment variable HORNEROS_API_KEY.\",\n 'Provide a valid API key: new HornerosSSP({ apiKey: \"hsp_xxx\" }) or set HORNEROS_API_KEY in your environment.'\n );\n }\n\n this.baseUrl = resolved.baseUrl;\n this.apiKey = resolved.apiKey;\n this.runtime = resolved.runtime;\n\n this.mcps = new Mcps(this);\n this.connections = new Connections(this);\n this.tools = new Tools(this);\n }\n\n /** @internal */\n async fetch<T>(\n path: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.baseUrl}/api/v1${path}`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-Api-Key\": this.apiKey,\n \"X-Source\": \"js_sdk\",\n \"X-Runtime\": this.runtime,\n ...(options.headers as Record<string, string>),\n };\n\n const res = await globalThis.fetch(url, {\n ...options,\n headers,\n });\n\n if (!res.ok) {\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n body = await res.text().catch(() => null);\n }\n\n const message =\n (body && typeof body === \"object\" && \"error\" in body\n ? (body as { error: string }).error\n : null) || `HTTP ${res.status}`;\n\n const errCode =\n res.status === 404\n ? HORNEROS_SDK_ERROR_CODES.BACKEND.NOT_FOUND\n : res.status === 401\n ? HORNEROS_SDK_ERROR_CODES.BACKEND.UNAUTHORIZED\n : res.status === 429\n ? HORNEROS_SDK_ERROR_CODES.BACKEND.RATE_LIMIT\n : res.status === 400\n ? HORNEROS_SDK_ERROR_CODES.BACKEND.BAD_REQUEST\n : res.status >= 500\n ? HORNEROS_SDK_ERROR_CODES.BACKEND.SERVER_ERROR\n : HORNEROS_SDK_ERROR_CODES.BACKEND.UNKNOWN;\n\n throw new HornerosError(errCode, message, res.status, body);\n }\n\n if (res.status === 204) {\n return undefined as T;\n }\n\n return res.json() as Promise<T>;\n }\n}\n","import type { ConnectionData } from \"./types\";\n\nexport class AuthScheme {\n static APIKey(params: { api_key: string; [k: string]: string }): ConnectionData {\n return { type: \"api_key\", data: params };\n }\n\n static Bearer(params: { token: string }): ConnectionData {\n return { type: \"bearer\", data: params };\n }\n\n static Basic(params: { username: string; password: string }): ConnectionData {\n return { type: \"basic\", data: params };\n }\n\n static OAuth2(params: {\n access_token: string;\n refresh_token?: string;\n }): ConnectionData {\n return {\n type: \"oauth2\",\n data: params as Record<string, string>,\n };\n }\n\n static GoogleLogin(): ConnectionData {\n return { type: \"google_login\", data: {} };\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,27 +1,75 @@
|
|
|
1
1
|
// src/errors.ts
|
|
2
|
+
var HORNEROS_SDK_ERROR_CODES = {
|
|
3
|
+
BACKEND: {
|
|
4
|
+
NOT_FOUND: "BACKEND::NOT_FOUND",
|
|
5
|
+
RATE_LIMIT: "BACKEND::RATE_LIMIT",
|
|
6
|
+
BAD_REQUEST: "BACKEND::BAD_REQUEST",
|
|
7
|
+
UNAUTHORIZED: "BACKEND::UNAUTHORIZED",
|
|
8
|
+
SERVER_ERROR: "BACKEND::SERVER_ERROR",
|
|
9
|
+
SERVER_UNAVAILABLE: "BACKEND::SERVER_UNAVAILABLE",
|
|
10
|
+
UNKNOWN: "BACKEND::UNKNOWN"
|
|
11
|
+
},
|
|
12
|
+
COMMON: {
|
|
13
|
+
API_KEY_UNAVAILABLE: "COMMON::API_KEY_UNAVAILABLE",
|
|
14
|
+
BASE_URL_NOT_REACHABLE: "COMMON::BASE_URL_NOT_REACHABLE",
|
|
15
|
+
UNKNOWN: "COMMON::UNKNOWN",
|
|
16
|
+
INVALID_PARAMS: "COMMON::INVALID_PARAMS"
|
|
17
|
+
},
|
|
18
|
+
SDK: {
|
|
19
|
+
NO_CONNECTED_ACCOUNT: "SDK::NO_CONNECTED_ACCOUNT",
|
|
20
|
+
CONNECTION_TIMEOUT: "SDK::CONNECTION_TIMEOUT",
|
|
21
|
+
INVALID_PARAMETER: "SDK::INVALID_PARAMETER"
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var errorCounter = 0;
|
|
2
25
|
var HornerosError = class extends Error {
|
|
3
|
-
constructor(message, statusCode, body) {
|
|
26
|
+
constructor(errCode, message, statusCode, body, description, possibleFix) {
|
|
4
27
|
super(message);
|
|
5
28
|
this.name = "HornerosError";
|
|
29
|
+
this.errCode = errCode;
|
|
6
30
|
this.statusCode = statusCode;
|
|
7
31
|
this.body = body;
|
|
32
|
+
this.description = description;
|
|
33
|
+
this.possibleFix = possibleFix;
|
|
34
|
+
this.errorId = `horneros_${Date.now()}_${++errorCounter}`;
|
|
35
|
+
this.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
36
|
+
}
|
|
37
|
+
toJSON() {
|
|
38
|
+
return {
|
|
39
|
+
name: this.name,
|
|
40
|
+
errCode: this.errCode,
|
|
41
|
+
message: this.message,
|
|
42
|
+
statusCode: this.statusCode,
|
|
43
|
+
description: this.description,
|
|
44
|
+
possibleFix: this.possibleFix,
|
|
45
|
+
errorId: this.errorId,
|
|
46
|
+
timestamp: this.timestamp,
|
|
47
|
+
body: this.body
|
|
48
|
+
};
|
|
8
49
|
}
|
|
9
50
|
};
|
|
10
51
|
var NotFoundError = class extends HornerosError {
|
|
11
52
|
constructor(message, body) {
|
|
12
|
-
super(message, 404, body);
|
|
53
|
+
super(HORNEROS_SDK_ERROR_CODES.BACKEND.NOT_FOUND, message, 404, body);
|
|
13
54
|
this.name = "NotFoundError";
|
|
14
55
|
}
|
|
15
56
|
};
|
|
16
57
|
var ValidationError = class extends HornerosError {
|
|
17
58
|
constructor(message, body) {
|
|
18
|
-
super(message, 400, body);
|
|
59
|
+
super(HORNEROS_SDK_ERROR_CODES.BACKEND.BAD_REQUEST, message, 400, body);
|
|
19
60
|
this.name = "ValidationError";
|
|
20
61
|
}
|
|
21
62
|
};
|
|
22
63
|
var ConnectionTimeoutError = class extends HornerosError {
|
|
23
64
|
constructor(message = "Connection timed out waiting for activation") {
|
|
24
|
-
super(
|
|
65
|
+
super(
|
|
66
|
+
HORNEROS_SDK_ERROR_CODES.SDK.CONNECTION_TIMEOUT,
|
|
67
|
+
message,
|
|
68
|
+
408,
|
|
69
|
+
void 0,
|
|
70
|
+
"The connection did not become active within the timeout period.",
|
|
71
|
+
"Increase the timeout value or check that the user completed the authentication flow."
|
|
72
|
+
);
|
|
25
73
|
this.name = "ConnectionTimeoutError";
|
|
26
74
|
}
|
|
27
75
|
};
|
|
@@ -151,9 +199,35 @@ var Tools = class {
|
|
|
151
199
|
};
|
|
152
200
|
|
|
153
201
|
// src/client.ts
|
|
202
|
+
function getEnvVariable(name) {
|
|
203
|
+
if (typeof process !== "undefined" && process.env) {
|
|
204
|
+
return process.env[name];
|
|
205
|
+
}
|
|
206
|
+
return void 0;
|
|
207
|
+
}
|
|
208
|
+
var DEFAULT_BASE_URL = "http://localhost:3000";
|
|
209
|
+
function resolveConfig(config) {
|
|
210
|
+
const baseUrl = config?.baseUrl || getEnvVariable("HORNEROS_BASE_URL") || DEFAULT_BASE_URL;
|
|
211
|
+
const apiKey = config?.apiKey || getEnvVariable("HORNEROS_API_KEY") || "";
|
|
212
|
+
const runtime = config?.runtime || getEnvVariable("HORNEROS_RUNTIME") || "";
|
|
213
|
+
return { baseUrl: baseUrl.replace(/\/+$/, ""), apiKey, runtime };
|
|
214
|
+
}
|
|
154
215
|
var HornerosSSP = class {
|
|
155
216
|
constructor(config) {
|
|
156
|
-
|
|
217
|
+
const resolved = resolveConfig(config);
|
|
218
|
+
if (!resolved.apiKey) {
|
|
219
|
+
throw new HornerosError(
|
|
220
|
+
HORNEROS_SDK_ERROR_CODES.COMMON.API_KEY_UNAVAILABLE,
|
|
221
|
+
"\u{1F511} API Key is not provided",
|
|
222
|
+
401,
|
|
223
|
+
void 0,
|
|
224
|
+
"You need to provide an API key in the constructor or as the environment variable HORNEROS_API_KEY.",
|
|
225
|
+
'Provide a valid API key: new HornerosSSP({ apiKey: "hsp_xxx" }) or set HORNEROS_API_KEY in your environment.'
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
this.baseUrl = resolved.baseUrl;
|
|
229
|
+
this.apiKey = resolved.apiKey;
|
|
230
|
+
this.runtime = resolved.runtime;
|
|
157
231
|
this.mcps = new Mcps(this);
|
|
158
232
|
this.connections = new Connections(this);
|
|
159
233
|
this.tools = new Tools(this);
|
|
@@ -163,6 +237,9 @@ var HornerosSSP = class {
|
|
|
163
237
|
const url = `${this.baseUrl}/api/v1${path}`;
|
|
164
238
|
const headers = {
|
|
165
239
|
"Content-Type": "application/json",
|
|
240
|
+
"X-Api-Key": this.apiKey,
|
|
241
|
+
"X-Source": "js_sdk",
|
|
242
|
+
"X-Runtime": this.runtime,
|
|
166
243
|
...options.headers
|
|
167
244
|
};
|
|
168
245
|
const res = await globalThis.fetch(url, {
|
|
@@ -177,7 +254,8 @@ var HornerosSSP = class {
|
|
|
177
254
|
body = await res.text().catch(() => null);
|
|
178
255
|
}
|
|
179
256
|
const message = (body && typeof body === "object" && "error" in body ? body.error : null) || `HTTP ${res.status}`;
|
|
180
|
-
|
|
257
|
+
const errCode = res.status === 404 ? HORNEROS_SDK_ERROR_CODES.BACKEND.NOT_FOUND : res.status === 401 ? HORNEROS_SDK_ERROR_CODES.BACKEND.UNAUTHORIZED : res.status === 429 ? HORNEROS_SDK_ERROR_CODES.BACKEND.RATE_LIMIT : res.status === 400 ? HORNEROS_SDK_ERROR_CODES.BACKEND.BAD_REQUEST : res.status >= 500 ? HORNEROS_SDK_ERROR_CODES.BACKEND.SERVER_ERROR : HORNEROS_SDK_ERROR_CODES.BACKEND.UNKNOWN;
|
|
258
|
+
throw new HornerosError(errCode, message, res.status, body);
|
|
181
259
|
}
|
|
182
260
|
if (res.status === 204) {
|
|
183
261
|
return void 0;
|
|
@@ -212,6 +290,7 @@ export {
|
|
|
212
290
|
ConnectionRequest,
|
|
213
291
|
ConnectionTimeoutError,
|
|
214
292
|
Connections,
|
|
293
|
+
HORNEROS_SDK_ERROR_CODES,
|
|
215
294
|
HornerosError,
|
|
216
295
|
HornerosSSP,
|
|
217
296
|
Mcps,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/mcps.ts","../src/connections.ts","../src/tools.ts","../src/client.ts","../src/auth-scheme.ts"],"sourcesContent":["export class HornerosError extends Error {\n public readonly statusCode: number;\n public readonly body: unknown;\n\n constructor(message: string, statusCode: number, body?: unknown) {\n super(message);\n this.name = \"HornerosError\";\n this.statusCode = statusCode;\n this.body = body;\n }\n}\n\nexport class NotFoundError extends HornerosError {\n constructor(message: string, body?: unknown) {\n super(message, 404, body);\n this.name = \"NotFoundError\";\n }\n}\n\nexport class ValidationError extends HornerosError {\n constructor(message: string, body?: unknown) {\n super(message, 400, body);\n this.name = \"ValidationError\";\n }\n}\n\nexport class ConnectionTimeoutError extends HornerosError {\n constructor(message = \"Connection timed out waiting for activation\") {\n super(message, 408);\n this.name = \"ConnectionTimeoutError\";\n }\n}\n","import type { HornerosSSP } from \"./client\";\nimport type { McpInfo, McpDetail, ApiResponse } from \"./types\";\n\nexport class Mcps {\n constructor(private client: HornerosSSP) {}\n\n async list(): Promise<McpInfo[]> {\n const res = await this.client.fetch<ApiResponse<McpInfo[]>>(\"/mcps\");\n return res.data;\n }\n\n async get(slug: string): Promise<McpDetail> {\n const res = await this.client.fetch<ApiResponse<McpDetail>>(\n `/mcps/${encodeURIComponent(slug)}`\n );\n return res.data;\n }\n}\n","import type { HornerosSSP } from \"./client\";\nimport type {\n ConnectionInfo,\n ConnectionRequestData,\n InitiateConnectionParams,\n ApiResponse,\n} from \"./types\";\nimport { ConnectionTimeoutError } from \"./errors\";\n\nexport class ConnectionRequest {\n public readonly id: string;\n public readonly mcpUrl: string | null;\n public readonly token: string | null;\n public readonly redirectUrl: string | null;\n public readonly status: \"active\" | \"pending\";\n\n constructor(\n private client: HornerosSSP,\n data: ConnectionRequestData\n ) {\n this.id = data.id;\n this.mcpUrl = data.mcpUrl;\n this.token = data.token;\n this.redirectUrl = data.redirectUrl;\n this.status = data.status;\n }\n\n /**\n * Polls the connection until it becomes active.\n * Useful for OAuth/interactive flows where the user needs to\n * complete authentication in a browser.\n * @param timeout Max wait time in ms (default: 120000 = 2 min)\n */\n async waitForConnection(timeout = 120_000): Promise<ConnectionInfo> {\n if (this.status === \"active\") {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(this.id)}`\n );\n return res.data;\n }\n\n const start = Date.now();\n const interval = 2000;\n\n while (Date.now() - start < timeout) {\n await sleep(interval);\n try {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(this.id)}`\n );\n if (res.data.status === \"active\") {\n return res.data;\n }\n } catch {\n // Connection not yet created, keep polling\n }\n }\n\n throw new ConnectionTimeoutError();\n }\n}\n\nexport class Connections {\n constructor(private client: HornerosSSP) {}\n\n async initiate(params: InitiateConnectionParams): Promise<ConnectionRequest> {\n const body: Record<string, unknown> = {\n mcp_slug: params.mcpSlug,\n };\n\n if (params.appName) body.app_name = params.appName;\n if (params.userId) body.user_id = params.userId;\n if (params.credentials) body.credentials = params.credentials;\n if (params.authScheme) body.auth_scheme = params.authScheme;\n\n const res = await this.client.fetch<ApiResponse<ConnectionRequestData>>(\n \"/connections\",\n { method: \"POST\", body: JSON.stringify(body) }\n );\n\n return new ConnectionRequest(this.client, res.data);\n }\n\n async list(): Promise<ConnectionInfo[]> {\n const res =\n await this.client.fetch<ApiResponse<ConnectionInfo[]>>(\"/connections\");\n return res.data;\n }\n\n async get(id: string): Promise<ConnectionInfo> {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(id)}`\n );\n return res.data;\n }\n\n async revoke(id: string): Promise<void> {\n await this.client.fetch<void>(\n `/connections/${encodeURIComponent(id)}`,\n { method: \"DELETE\" }\n );\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { HornerosSSP } from \"./client\";\nimport type {\n ToolDefinition,\n ToolResult,\n ExecuteToolParams,\n ApiResponse,\n} from \"./types\";\n\nexport class Tools {\n constructor(private client: HornerosSSP) {}\n\n async list(mcpSlug: string): Promise<ToolDefinition[]> {\n const res = await this.client.fetch<ApiResponse<ToolDefinition[]>>(\n `/mcps/${encodeURIComponent(mcpSlug)}/tools`\n );\n return res.data;\n }\n\n async execute(params: ExecuteToolParams): Promise<ToolResult> {\n const res = await this.client.fetch<ApiResponse<ToolResult>>(\n \"/tools/execute\",\n {\n method: \"POST\",\n body: JSON.stringify({\n mcp_slug: params.mcpSlug,\n connection_id: params.connectionId,\n tool_name: params.toolName,\n arguments: params.arguments,\n }),\n }\n );\n return res.data;\n }\n}\n","import type { HornerosSSPConfig } from \"./types\";\nimport { HornerosError } from \"./errors\";\nimport { Mcps } from \"./mcps\";\nimport { Connections } from \"./connections\";\nimport { Tools } from \"./tools\";\n\nexport class HornerosSSP {\n public readonly mcps: Mcps;\n public readonly connections: Connections;\n public readonly tools: Tools;\n\n private readonly baseUrl: string;\n\n constructor(config: HornerosSSPConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n\n this.mcps = new Mcps(this);\n this.connections = new Connections(this);\n this.tools = new Tools(this);\n }\n\n /** @internal */\n async fetch<T>(\n path: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.baseUrl}/api/v1${path}`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(options.headers as Record<string, string>),\n };\n\n const res = await globalThis.fetch(url, {\n ...options,\n headers,\n });\n\n if (!res.ok) {\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n body = await res.text().catch(() => null);\n }\n const message =\n (body && typeof body === \"object\" && \"error\" in body\n ? (body as { error: string }).error\n : null) || `HTTP ${res.status}`;\n throw new HornerosError(message, res.status, body);\n }\n\n if (res.status === 204) {\n return undefined as T;\n }\n\n return res.json() as Promise<T>;\n }\n}\n","import type { ConnectionData } from \"./types\";\n\nexport class AuthScheme {\n static APIKey(params: { api_key: string; [k: string]: string }): ConnectionData {\n return { type: \"api_key\", data: params };\n }\n\n static Bearer(params: { token: string }): ConnectionData {\n return { type: \"bearer\", data: params };\n }\n\n static Basic(params: { username: string; password: string }): ConnectionData {\n return { type: \"basic\", data: params };\n }\n\n static OAuth2(params: {\n access_token: string;\n refresh_token?: string;\n }): ConnectionData {\n return {\n type: \"oauth2\",\n data: params as Record<string, string>,\n };\n }\n\n static GoogleLogin(): ConnectionData {\n return { type: \"google_login\", data: {} };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/mcps.ts","../src/connections.ts","../src/tools.ts","../src/client.ts","../src/auth-scheme.ts"],"sourcesContent":["// ── Error codes ─────────────────────────────────────────────\n\nexport const HORNEROS_SDK_ERROR_CODES = {\n BACKEND: {\n NOT_FOUND: \"BACKEND::NOT_FOUND\",\n RATE_LIMIT: \"BACKEND::RATE_LIMIT\",\n BAD_REQUEST: \"BACKEND::BAD_REQUEST\",\n UNAUTHORIZED: \"BACKEND::UNAUTHORIZED\",\n SERVER_ERROR: \"BACKEND::SERVER_ERROR\",\n SERVER_UNAVAILABLE: \"BACKEND::SERVER_UNAVAILABLE\",\n UNKNOWN: \"BACKEND::UNKNOWN\",\n },\n COMMON: {\n API_KEY_UNAVAILABLE: \"COMMON::API_KEY_UNAVAILABLE\",\n BASE_URL_NOT_REACHABLE: \"COMMON::BASE_URL_NOT_REACHABLE\",\n UNKNOWN: \"COMMON::UNKNOWN\",\n INVALID_PARAMS: \"COMMON::INVALID_PARAMS\",\n },\n SDK: {\n NO_CONNECTED_ACCOUNT: \"SDK::NO_CONNECTED_ACCOUNT\",\n CONNECTION_TIMEOUT: \"SDK::CONNECTION_TIMEOUT\",\n INVALID_PARAMETER: \"SDK::INVALID_PARAMETER\",\n },\n} as const;\n\n// ── Base error ──────────────────────────────────────────────\n\nlet errorCounter = 0;\n\nexport class HornerosError extends Error {\n public readonly errCode: string;\n public readonly statusCode: number;\n public readonly body: unknown;\n public readonly description?: string;\n public readonly possibleFix?: string;\n public readonly errorId: string;\n public readonly timestamp: string;\n\n constructor(\n errCode: string,\n message: string,\n statusCode: number,\n body?: unknown,\n description?: string,\n possibleFix?: string\n ) {\n super(message);\n this.name = \"HornerosError\";\n this.errCode = errCode;\n this.statusCode = statusCode;\n this.body = body;\n this.description = description;\n this.possibleFix = possibleFix;\n this.errorId = `horneros_${Date.now()}_${++errorCounter}`;\n this.timestamp = new Date().toISOString();\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n errCode: this.errCode,\n message: this.message,\n statusCode: this.statusCode,\n description: this.description,\n possibleFix: this.possibleFix,\n errorId: this.errorId,\n timestamp: this.timestamp,\n body: this.body,\n };\n }\n}\n\n// ── Specialized errors ──────────────────────────────────────\n\nexport class NotFoundError extends HornerosError {\n constructor(message: string, body?: unknown) {\n super(HORNEROS_SDK_ERROR_CODES.BACKEND.NOT_FOUND, message, 404, body);\n this.name = \"NotFoundError\";\n }\n}\n\nexport class ValidationError extends HornerosError {\n constructor(message: string, body?: unknown) {\n super(HORNEROS_SDK_ERROR_CODES.BACKEND.BAD_REQUEST, message, 400, body);\n this.name = \"ValidationError\";\n }\n}\n\nexport class ConnectionTimeoutError extends HornerosError {\n constructor(message = \"Connection timed out waiting for activation\") {\n super(\n HORNEROS_SDK_ERROR_CODES.SDK.CONNECTION_TIMEOUT,\n message,\n 408,\n undefined,\n \"The connection did not become active within the timeout period.\",\n \"Increase the timeout value or check that the user completed the authentication flow.\"\n );\n this.name = \"ConnectionTimeoutError\";\n }\n}\n","import type { HornerosSSP } from \"./client\";\nimport type { McpInfo, McpDetail, ApiResponse } from \"./types\";\n\nexport class Mcps {\n constructor(private client: HornerosSSP) {}\n\n async list(): Promise<McpInfo[]> {\n const res = await this.client.fetch<ApiResponse<McpInfo[]>>(\"/mcps\");\n return res.data;\n }\n\n async get(slug: string): Promise<McpDetail> {\n const res = await this.client.fetch<ApiResponse<McpDetail>>(\n `/mcps/${encodeURIComponent(slug)}`\n );\n return res.data;\n }\n}\n","import type { HornerosSSP } from \"./client\";\nimport type {\n ConnectionInfo,\n ConnectionRequestData,\n InitiateConnectionParams,\n ApiResponse,\n} from \"./types\";\nimport { ConnectionTimeoutError } from \"./errors\";\n\nexport class ConnectionRequest {\n public readonly id: string;\n public readonly mcpUrl: string | null;\n public readonly token: string | null;\n public readonly redirectUrl: string | null;\n public readonly status: \"active\" | \"pending\";\n\n constructor(\n private client: HornerosSSP,\n data: ConnectionRequestData\n ) {\n this.id = data.id;\n this.mcpUrl = data.mcpUrl;\n this.token = data.token;\n this.redirectUrl = data.redirectUrl;\n this.status = data.status;\n }\n\n /**\n * Polls the connection until it becomes active.\n * Useful for OAuth/interactive flows where the user needs to\n * complete authentication in a browser.\n * @param timeout Max wait time in ms (default: 120000 = 2 min)\n */\n async waitForConnection(timeout = 120_000): Promise<ConnectionInfo> {\n if (this.status === \"active\") {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(this.id)}`\n );\n return res.data;\n }\n\n const start = Date.now();\n const interval = 2000;\n\n while (Date.now() - start < timeout) {\n await sleep(interval);\n try {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(this.id)}`\n );\n if (res.data.status === \"active\") {\n return res.data;\n }\n } catch {\n // Connection not yet created, keep polling\n }\n }\n\n throw new ConnectionTimeoutError();\n }\n}\n\nexport class Connections {\n constructor(private client: HornerosSSP) {}\n\n async initiate(params: InitiateConnectionParams): Promise<ConnectionRequest> {\n const body: Record<string, unknown> = {\n mcp_slug: params.mcpSlug,\n };\n\n if (params.appName) body.app_name = params.appName;\n if (params.userId) body.user_id = params.userId;\n if (params.credentials) body.credentials = params.credentials;\n if (params.authScheme) body.auth_scheme = params.authScheme;\n\n const res = await this.client.fetch<ApiResponse<ConnectionRequestData>>(\n \"/connections\",\n { method: \"POST\", body: JSON.stringify(body) }\n );\n\n return new ConnectionRequest(this.client, res.data);\n }\n\n async list(): Promise<ConnectionInfo[]> {\n const res =\n await this.client.fetch<ApiResponse<ConnectionInfo[]>>(\"/connections\");\n return res.data;\n }\n\n async get(id: string): Promise<ConnectionInfo> {\n const res = await this.client.fetch<ApiResponse<ConnectionInfo>>(\n `/connections/${encodeURIComponent(id)}`\n );\n return res.data;\n }\n\n async revoke(id: string): Promise<void> {\n await this.client.fetch<void>(\n `/connections/${encodeURIComponent(id)}`,\n { method: \"DELETE\" }\n );\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { HornerosSSP } from \"./client\";\nimport type {\n ToolDefinition,\n ToolResult,\n ExecuteToolParams,\n ApiResponse,\n} from \"./types\";\n\nexport class Tools {\n constructor(private client: HornerosSSP) {}\n\n async list(mcpSlug: string): Promise<ToolDefinition[]> {\n const res = await this.client.fetch<ApiResponse<ToolDefinition[]>>(\n `/mcps/${encodeURIComponent(mcpSlug)}/tools`\n );\n return res.data;\n }\n\n async execute(params: ExecuteToolParams): Promise<ToolResult> {\n const res = await this.client.fetch<ApiResponse<ToolResult>>(\n \"/tools/execute\",\n {\n method: \"POST\",\n body: JSON.stringify({\n mcp_slug: params.mcpSlug,\n connection_id: params.connectionId,\n tool_name: params.toolName,\n arguments: params.arguments,\n }),\n }\n );\n return res.data;\n }\n}\n","import type { HornerosSSPConfig } from \"./types\";\nimport { HornerosError, HORNEROS_SDK_ERROR_CODES } from \"./errors\";\nimport { Mcps } from \"./mcps\";\nimport { Connections } from \"./connections\";\nimport { Tools } from \"./tools\";\n\n// ── Helpers ─────────────────────────────────────────────────\n\nfunction getEnvVariable(name: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[name];\n }\n return undefined;\n}\n\nconst DEFAULT_BASE_URL = \"http://localhost:3000\";\n\nfunction resolveConfig(config?: HornerosSSPConfig) {\n const baseUrl =\n config?.baseUrl ||\n getEnvVariable(\"HORNEROS_BASE_URL\") ||\n DEFAULT_BASE_URL;\n\n const apiKey =\n config?.apiKey ||\n getEnvVariable(\"HORNEROS_API_KEY\") ||\n \"\";\n\n const runtime = config?.runtime || getEnvVariable(\"HORNEROS_RUNTIME\") || \"\";\n\n return { baseUrl: baseUrl.replace(/\\/+$/, \"\"), apiKey, runtime };\n}\n\n// ── Main client ─────────────────────────────────────────────\n\nexport class HornerosSSP {\n public readonly mcps: Mcps;\n public readonly connections: Connections;\n public readonly tools: Tools;\n\n private readonly baseUrl: string;\n private readonly apiKey: string;\n private readonly runtime: string;\n\n constructor(config?: HornerosSSPConfig) {\n const resolved = resolveConfig(config);\n\n if (!resolved.apiKey) {\n throw new HornerosError(\n HORNEROS_SDK_ERROR_CODES.COMMON.API_KEY_UNAVAILABLE,\n \"🔑 API Key is not provided\",\n 401,\n undefined,\n \"You need to provide an API key in the constructor or as the environment variable HORNEROS_API_KEY.\",\n 'Provide a valid API key: new HornerosSSP({ apiKey: \"hsp_xxx\" }) or set HORNEROS_API_KEY in your environment.'\n );\n }\n\n this.baseUrl = resolved.baseUrl;\n this.apiKey = resolved.apiKey;\n this.runtime = resolved.runtime;\n\n this.mcps = new Mcps(this);\n this.connections = new Connections(this);\n this.tools = new Tools(this);\n }\n\n /** @internal */\n async fetch<T>(\n path: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.baseUrl}/api/v1${path}`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-Api-Key\": this.apiKey,\n \"X-Source\": \"js_sdk\",\n \"X-Runtime\": this.runtime,\n ...(options.headers as Record<string, string>),\n };\n\n const res = await globalThis.fetch(url, {\n ...options,\n headers,\n });\n\n if (!res.ok) {\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n body = await res.text().catch(() => null);\n }\n\n const message =\n (body && typeof body === \"object\" && \"error\" in body\n ? (body as { error: string }).error\n : null) || `HTTP ${res.status}`;\n\n const errCode =\n res.status === 404\n ? HORNEROS_SDK_ERROR_CODES.BACKEND.NOT_FOUND\n : res.status === 401\n ? HORNEROS_SDK_ERROR_CODES.BACKEND.UNAUTHORIZED\n : res.status === 429\n ? HORNEROS_SDK_ERROR_CODES.BACKEND.RATE_LIMIT\n : res.status === 400\n ? HORNEROS_SDK_ERROR_CODES.BACKEND.BAD_REQUEST\n : res.status >= 500\n ? HORNEROS_SDK_ERROR_CODES.BACKEND.SERVER_ERROR\n : HORNEROS_SDK_ERROR_CODES.BACKEND.UNKNOWN;\n\n throw new HornerosError(errCode, message, res.status, body);\n }\n\n if (res.status === 204) {\n return undefined as T;\n }\n\n return res.json() as Promise<T>;\n }\n}\n","import type { ConnectionData } from \"./types\";\n\nexport class AuthScheme {\n static APIKey(params: { api_key: string; [k: string]: string }): ConnectionData {\n return { type: \"api_key\", data: params };\n }\n\n static Bearer(params: { token: string }): ConnectionData {\n return { type: \"bearer\", data: params };\n }\n\n static Basic(params: { username: string; password: string }): ConnectionData {\n return { type: \"basic\", data: params };\n }\n\n static OAuth2(params: {\n access_token: string;\n refresh_token?: string;\n }): ConnectionData {\n return {\n type: \"oauth2\",\n data: params as Record<string, string>,\n };\n }\n\n static GoogleLogin(): ConnectionData {\n return { type: \"google_login\", data: {} };\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hornerosssp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "SDK for HornerosSSP - integrate MCPs into any app",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "SDK and CLI for HornerosSSP - integrate MCPs into any app",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
"require": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"hornerosssp": "./dist/cli/index.js"
|
|
17
|
+
},
|
|
15
18
|
"files": [
|
|
16
19
|
"dist"
|
|
17
20
|
],
|
|
@@ -19,7 +22,15 @@
|
|
|
19
22
|
"build": "tsup",
|
|
20
23
|
"dev": "tsup --watch"
|
|
21
24
|
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"chalk": "^4.1.2",
|
|
27
|
+
"commander": "^12.1.0",
|
|
28
|
+
"inquirer": "^10.2.2",
|
|
29
|
+
"open": "^8.4.0"
|
|
30
|
+
},
|
|
22
31
|
"devDependencies": {
|
|
32
|
+
"@types/inquirer": "^9.0.7",
|
|
33
|
+
"composio-core": "^0.5.39",
|
|
23
34
|
"tsup": "^8.0.0",
|
|
24
35
|
"typescript": "^5.0.0"
|
|
25
36
|
},
|