@emcy/cli 0.1.0-pr.1.44e275868746.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +104 -0
- package/dist/auth.d.ts +9 -0
- package/dist/auth.js +169 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +20 -0
- package/dist/client.js +210 -0
- package/dist/client.js.map +1 -0
- package/dist/commands.d.ts +2 -0
- package/dist/commands.js +827 -0
- package/dist/commands.js.map +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.js +125 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +11 -0
- package/dist/output.js +76 -0
- package/dist/output.js.map +1 -0
- package/dist/types.d.ts +63 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Emcy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# MCP Stack CLI
|
|
2
|
+
|
|
3
|
+
`mcpstack` is the command-line interface for MCP Stack organizations, MCP servers, deployments, gateways, agents, members, invitations, and service-account API keys.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i -g @emcy/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
For local development:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install
|
|
15
|
+
npm run build
|
|
16
|
+
node dist/index.js --help
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Preview Package
|
|
20
|
+
|
|
21
|
+
Pull requests publish preview packages to npm with a stable dist-tag, for example `@emcy/cli@pr-12`. The workflow comments with the exact package ref.
|
|
22
|
+
|
|
23
|
+
To test a CLI change inside an `emcy-saas` PR preview, add the ref to `emcy/infra/preview-packages.json` in that Emcy PR:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"@emcy/cli": "@emcy/cli@pr-12"
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The Emcy preview deploy installs that package before image builds, runs a CLI smoke check, and includes the resolved npm package link in the Emcy PR preview comment.
|
|
32
|
+
|
|
33
|
+
## Human Login
|
|
34
|
+
|
|
35
|
+
Human operators use OAuth device authorization. The API must expose `/api/v1/cli/config` and the `device_authorization_endpoint`.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
mcpstack auth login --api-url http://localhost:5150
|
|
39
|
+
mcpstack auth status
|
|
40
|
+
mcpstack auth whoami
|
|
41
|
+
mcpstack org list
|
|
42
|
+
mcpstack org use <organization-id>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Service-Account Login
|
|
46
|
+
|
|
47
|
+
Automation and CI should use an MCP Stack service-account API key. You can either store one active service-account login locally or pass the key through environment variables.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
mcpstack auth service-account login \
|
|
51
|
+
--api-url https://api.mcpstack.com \
|
|
52
|
+
--key emcy_sk_...
|
|
53
|
+
|
|
54
|
+
mcpstack servers list --org <organization-id>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Equivalent environment-only usage:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
MCPSTACK_API_URL=https://api.mcpstack.com \
|
|
61
|
+
MCPSTACK_API_KEY=emcy_sk_... \
|
|
62
|
+
mcpstack servers list --org <organization-id>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Common Workflows
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
mcpstack members invite teammate@example.com --role developer
|
|
69
|
+
mcpstack members invitations list
|
|
70
|
+
|
|
71
|
+
mcpstack api-keys create --name deploy-bot --role developer
|
|
72
|
+
mcpstack api-keys list
|
|
73
|
+
|
|
74
|
+
mcpstack servers create --name demo --openapi-file ./openapi.json --runtime-type hosted
|
|
75
|
+
mcpstack deploy <server-id> --environment production --region westus3 --wait
|
|
76
|
+
mcpstack logs stream <server-id> --region westus3
|
|
77
|
+
mcpstack smoke tools-list <server-id>
|
|
78
|
+
|
|
79
|
+
mcpstack agents list
|
|
80
|
+
mcpstack agents chat <agent-id> --message "Summarize production health"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
Global flags:
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
--api-url, --org, --json, --output table|json|yaml,
|
|
89
|
+
--yes, --wait, --timeout, --verbose, --debug-http
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Environment overrides:
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
MCPSTACK_API_URL
|
|
96
|
+
MCPSTACK_ORG_ID
|
|
97
|
+
MCPSTACK_ACCESS_TOKEN
|
|
98
|
+
MCPSTACK_API_KEY
|
|
99
|
+
MCPSTACK_DISABLE_KEYCHAIN
|
|
100
|
+
MCPSTACK_OUTPUT
|
|
101
|
+
NO_COLOR
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The active login and selected organization are stored at `~/.config/mcpstack/config.json`. Secrets use the OS keychain when `keytar` is available, with a `0600` local fallback. Set `MCPSTACK_DISABLE_KEYCHAIN=1` for CI or isolated E2E runs that should not touch the desktop keychain.
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { GlobalOptions } from "./types.js";
|
|
2
|
+
export declare function login(options: GlobalOptions): Promise<void>;
|
|
3
|
+
export declare function logout(_options: GlobalOptions): Promise<void>;
|
|
4
|
+
export declare function status(_options: GlobalOptions): Promise<void>;
|
|
5
|
+
export declare function serviceAccountLogin(options: GlobalOptions & {
|
|
6
|
+
key?: string;
|
|
7
|
+
}): Promise<void>;
|
|
8
|
+
export declare function serviceAccountLogout(options: GlobalOptions): Promise<void>;
|
|
9
|
+
export declare function whoami(options: GlobalOptions): Promise<unknown>;
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { clearConfig, loadConfig, saveConfig, setSecret } from "./config.js";
|
|
2
|
+
import { McpstackClient } from "./client.js";
|
|
3
|
+
import { printInfo, printSuccess, printWarning } from "./output.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
const cliConfigSchema = z.object({
|
|
6
|
+
apiUrl: z.string().url(),
|
|
7
|
+
authIssuer: z.string().url(),
|
|
8
|
+
clientId: z.string().min(1),
|
|
9
|
+
deviceAuthorizationEndpoint: z.string().url(),
|
|
10
|
+
tokenEndpoint: z.string().url(),
|
|
11
|
+
resource: z.string().min(1),
|
|
12
|
+
scopes: z.array(z.string().min(1)),
|
|
13
|
+
supportedAuthModes: z.array(z.string()).default([]),
|
|
14
|
+
});
|
|
15
|
+
const deviceAuthorizationSchema = z.object({
|
|
16
|
+
device_code: z.string().min(1),
|
|
17
|
+
user_code: z.string().min(1),
|
|
18
|
+
verification_uri: z.string().url(),
|
|
19
|
+
verification_uri_complete: z.string().url().optional(),
|
|
20
|
+
expires_in: z.number().int().positive(),
|
|
21
|
+
interval: z.number().int().positive().optional(),
|
|
22
|
+
});
|
|
23
|
+
const tokenResponseSchema = z.object({
|
|
24
|
+
access_token: z.string().min(1),
|
|
25
|
+
refresh_token: z.string().optional(),
|
|
26
|
+
token_type: z.string().optional(),
|
|
27
|
+
expires_in: z.number().int().positive().optional(),
|
|
28
|
+
scope: z.string().optional(),
|
|
29
|
+
});
|
|
30
|
+
export async function login(options) {
|
|
31
|
+
const client = await McpstackClient.create(options);
|
|
32
|
+
const config = cliConfigSchema.parse(await client.request("/api/v1/cli/config", { noAuth: true }));
|
|
33
|
+
const scope = config.scopes.join(" ");
|
|
34
|
+
const device = await startDeviceAuthorization(config, scope);
|
|
35
|
+
const verificationUrl = device.verification_uri_complete ?? device.verification_uri;
|
|
36
|
+
printInfo("Open this URL to sign in:");
|
|
37
|
+
console.log(verificationUrl);
|
|
38
|
+
console.log("");
|
|
39
|
+
console.log(`Device code: ${device.user_code}`);
|
|
40
|
+
const token = await pollDeviceToken(config, device, scope);
|
|
41
|
+
const expiresAt = new Date(Date.now() + (token.expires_in ?? 600) * 1000).toISOString();
|
|
42
|
+
await saveConfig({
|
|
43
|
+
apiUrl: config.apiUrl,
|
|
44
|
+
auth: {
|
|
45
|
+
type: "oauth",
|
|
46
|
+
clientId: config.clientId,
|
|
47
|
+
tokenEndpoint: config.tokenEndpoint,
|
|
48
|
+
scope,
|
|
49
|
+
resource: config.resource,
|
|
50
|
+
expiresAt,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
await setSecret("accessToken", token.access_token);
|
|
54
|
+
if (token.refresh_token) {
|
|
55
|
+
await setSecret("refreshToken", token.refresh_token);
|
|
56
|
+
}
|
|
57
|
+
printSuccess("Signed in.");
|
|
58
|
+
}
|
|
59
|
+
export async function logout(_options) {
|
|
60
|
+
const config = await loadConfig();
|
|
61
|
+
if (!config) {
|
|
62
|
+
printWarning("No active login found.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
await clearConfig();
|
|
66
|
+
printSuccess("Signed out.");
|
|
67
|
+
}
|
|
68
|
+
export async function status(_options) {
|
|
69
|
+
const config = await loadConfig();
|
|
70
|
+
if (!config) {
|
|
71
|
+
printWarning("No active login. Run `mcpstack auth login` or `mcpstack auth service-account login`.");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
console.log(`API URL: ${config.apiUrl}`);
|
|
75
|
+
console.log(`Organization: ${config.orgId ?? "(not selected)"}`);
|
|
76
|
+
console.log(`Auth: ${config.auth?.type ?? "(none)"}`);
|
|
77
|
+
if (config.auth?.type === "oauth") {
|
|
78
|
+
console.log(`Expires: ${config.auth.expiresAt ?? "(unknown)"}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export async function serviceAccountLogin(options) {
|
|
82
|
+
const apiKey = options.key ?? process.env.MCPSTACK_API_KEY;
|
|
83
|
+
if (!apiKey) {
|
|
84
|
+
throw new Error("Provide --key <api-key> or set MCPSTACK_API_KEY.");
|
|
85
|
+
}
|
|
86
|
+
const apiUrl = options.apiUrl ?? process.env.MCPSTACK_API_URL ?? "http://localhost:5150";
|
|
87
|
+
const clientId = apiKey.slice(0, apiKey.lastIndexOf("_"));
|
|
88
|
+
await saveConfig({
|
|
89
|
+
apiUrl,
|
|
90
|
+
auth: {
|
|
91
|
+
type: "api_key",
|
|
92
|
+
clientId: clientId || undefined,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
await setSecret("apiKey", apiKey);
|
|
96
|
+
printSuccess("Stored service-account login.");
|
|
97
|
+
}
|
|
98
|
+
export async function serviceAccountLogout(options) {
|
|
99
|
+
await logout(options);
|
|
100
|
+
}
|
|
101
|
+
export async function whoami(options) {
|
|
102
|
+
const client = await McpstackClient.create(options);
|
|
103
|
+
return client.request("/api/v1/cli/whoami");
|
|
104
|
+
}
|
|
105
|
+
async function startDeviceAuthorization(config, scope) {
|
|
106
|
+
const body = new URLSearchParams({
|
|
107
|
+
client_id: config.clientId,
|
|
108
|
+
scope,
|
|
109
|
+
resource: config.resource,
|
|
110
|
+
});
|
|
111
|
+
const response = await fetch(config.deviceAuthorizationEndpoint, {
|
|
112
|
+
method: "POST",
|
|
113
|
+
headers: {
|
|
114
|
+
Accept: "application/json",
|
|
115
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
116
|
+
},
|
|
117
|
+
body,
|
|
118
|
+
});
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
const text = await response.text();
|
|
121
|
+
throw new Error(response.status === 404
|
|
122
|
+
? "The server does not expose SqlOS device authorization yet. Update SqlOS/Emcy.Api, then retry."
|
|
123
|
+
: `Device authorization failed: ${text || response.statusText}`);
|
|
124
|
+
}
|
|
125
|
+
return deviceAuthorizationSchema.parse(await response.json());
|
|
126
|
+
}
|
|
127
|
+
async function pollDeviceToken(config, device, scope) {
|
|
128
|
+
const startedAt = Date.now();
|
|
129
|
+
let intervalMs = Math.max(device.interval ?? 5, 1) * 1000;
|
|
130
|
+
while (Date.now() - startedAt < device.expires_in * 1000) {
|
|
131
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
132
|
+
const body = new URLSearchParams({
|
|
133
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
134
|
+
device_code: device.device_code,
|
|
135
|
+
client_id: config.clientId,
|
|
136
|
+
scope,
|
|
137
|
+
resource: config.resource,
|
|
138
|
+
});
|
|
139
|
+
const response = await fetch(config.tokenEndpoint, {
|
|
140
|
+
method: "POST",
|
|
141
|
+
headers: {
|
|
142
|
+
Accept: "application/json",
|
|
143
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
144
|
+
},
|
|
145
|
+
body,
|
|
146
|
+
});
|
|
147
|
+
const payload = await response.json().catch(() => ({}));
|
|
148
|
+
if (response.ok) {
|
|
149
|
+
return tokenResponseSchema.parse(payload);
|
|
150
|
+
}
|
|
151
|
+
const error = String(payload.error ?? "");
|
|
152
|
+
if (error === "authorization_pending") {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (error === "slow_down") {
|
|
156
|
+
intervalMs += 5_000;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (error === "access_denied") {
|
|
160
|
+
throw new Error("Device login was denied.");
|
|
161
|
+
}
|
|
162
|
+
if (error === "expired_token") {
|
|
163
|
+
throw new Error("Device login expired. Run `mcpstack auth login` again.");
|
|
164
|
+
}
|
|
165
|
+
throw new Error(`Device token polling failed: ${payload.error_description ?? error ?? response.statusText}`);
|
|
166
|
+
}
|
|
167
|
+
throw new Error("Device login expired. Run `mcpstack auth login` again.");
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ConfigFile, GlobalOptions, RequestOptions } from "./types.js";
|
|
2
|
+
export declare class McpstackHttpError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly body: unknown;
|
|
5
|
+
constructor(message: string, status: number, body: unknown);
|
|
6
|
+
}
|
|
7
|
+
export declare class McpstackClient {
|
|
8
|
+
private readonly options;
|
|
9
|
+
readonly apiUrl: string;
|
|
10
|
+
readonly config?: ConfigFile;
|
|
11
|
+
private constructor();
|
|
12
|
+
static create(options: GlobalOptions): Promise<McpstackClient>;
|
|
13
|
+
request<T = unknown>(path: string, requestOptions?: RequestOptions): Promise<T>;
|
|
14
|
+
stream(path: string, onChunk: (text: string) => void, requestOptions?: RequestOptions): Promise<void>;
|
|
15
|
+
resolveOrgId(explicitOrg?: string): Promise<string>;
|
|
16
|
+
setActiveOrg(orgId: string): Promise<void>;
|
|
17
|
+
buildUrl(path: string, query?: Record<string, string | number | boolean | undefined>): string;
|
|
18
|
+
private resolveAuthHeader;
|
|
19
|
+
private refreshAccessTokenIfNeeded;
|
|
20
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { fetch } from "undici";
|
|
2
|
+
import { getSecret, loadConfig, saveConfig, setActiveOrganization, setSecret } from "./config.js";
|
|
3
|
+
export class McpstackHttpError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
body;
|
|
6
|
+
constructor(message, status, body) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.body = body;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class McpstackClient {
|
|
13
|
+
options;
|
|
14
|
+
apiUrl;
|
|
15
|
+
config;
|
|
16
|
+
constructor(options, apiUrl, config) {
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.apiUrl = apiUrl.replace(/\/+$/, "");
|
|
19
|
+
this.config = config;
|
|
20
|
+
}
|
|
21
|
+
static async create(options) {
|
|
22
|
+
const config = await loadConfig();
|
|
23
|
+
const apiUrl = options.apiUrl
|
|
24
|
+
?? process.env.MCPSTACK_API_URL
|
|
25
|
+
?? config?.apiUrl
|
|
26
|
+
?? "http://localhost:5150";
|
|
27
|
+
return new McpstackClient(options, apiUrl, config);
|
|
28
|
+
}
|
|
29
|
+
async request(path, requestOptions = {}) {
|
|
30
|
+
const url = this.buildUrl(path, requestOptions.query);
|
|
31
|
+
const headers = {
|
|
32
|
+
Accept: requestOptions.expectText ? "text/plain" : "application/json",
|
|
33
|
+
...requestOptions.headers,
|
|
34
|
+
};
|
|
35
|
+
let body;
|
|
36
|
+
if (requestOptions.rawBody) {
|
|
37
|
+
body = requestOptions.rawBody;
|
|
38
|
+
}
|
|
39
|
+
else if (requestOptions.body !== undefined) {
|
|
40
|
+
headers["Content-Type"] = "application/json";
|
|
41
|
+
body = JSON.stringify(requestOptions.body);
|
|
42
|
+
}
|
|
43
|
+
if (!requestOptions.noAuth) {
|
|
44
|
+
const authHeader = await this.resolveAuthHeader();
|
|
45
|
+
if (authHeader) {
|
|
46
|
+
headers.Authorization = authHeader;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (this.options.debugHttp) {
|
|
50
|
+
console.error(`${requestOptions.method ?? "GET"} ${url}`);
|
|
51
|
+
}
|
|
52
|
+
const response = await fetch(url, {
|
|
53
|
+
method: requestOptions.method ?? "GET",
|
|
54
|
+
headers,
|
|
55
|
+
body,
|
|
56
|
+
});
|
|
57
|
+
const responseBody = requestOptions.expectText
|
|
58
|
+
? await response.text()
|
|
59
|
+
: await readJsonOrText(response);
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
throw new McpstackHttpError(formatHttpError(response.status, responseBody), response.status, responseBody);
|
|
62
|
+
}
|
|
63
|
+
return responseBody;
|
|
64
|
+
}
|
|
65
|
+
async stream(path, onChunk, requestOptions = {}) {
|
|
66
|
+
const url = this.buildUrl(path, requestOptions.query);
|
|
67
|
+
const headers = {
|
|
68
|
+
Accept: "text/event-stream",
|
|
69
|
+
...requestOptions.headers,
|
|
70
|
+
};
|
|
71
|
+
if (!requestOptions.noAuth) {
|
|
72
|
+
const authHeader = await this.resolveAuthHeader();
|
|
73
|
+
if (authHeader) {
|
|
74
|
+
headers.Authorization = authHeader;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const response = await fetch(url, { method: requestOptions.method ?? "GET", headers });
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
throw new McpstackHttpError(formatHttpError(response.status, await readJsonOrText(response)), response.status, undefined);
|
|
80
|
+
}
|
|
81
|
+
if (!response.body) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
for await (const chunk of response.body) {
|
|
85
|
+
onChunk(Buffer.from(chunk).toString("utf8"));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async resolveOrgId(explicitOrg) {
|
|
89
|
+
const orgId = explicitOrg
|
|
90
|
+
?? this.options.org
|
|
91
|
+
?? process.env.MCPSTACK_ORG_ID
|
|
92
|
+
?? this.config?.orgId;
|
|
93
|
+
if (orgId) {
|
|
94
|
+
return orgId;
|
|
95
|
+
}
|
|
96
|
+
const orgs = await this.request("/api/v1/organizations");
|
|
97
|
+
if (orgs.length === 1) {
|
|
98
|
+
return orgs[0].id ?? orgs[0].organizationId;
|
|
99
|
+
}
|
|
100
|
+
if (orgs.length === 0) {
|
|
101
|
+
throw new Error("No organizations found for the current account.");
|
|
102
|
+
}
|
|
103
|
+
throw new Error("Multiple organizations found. Pass --org <organization-id> or run `mcpstack org use <organization-id>`.");
|
|
104
|
+
}
|
|
105
|
+
async setActiveOrg(orgId) {
|
|
106
|
+
if (!this.config) {
|
|
107
|
+
await saveConfig({ apiUrl: this.apiUrl, orgId });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
await setActiveOrganization(orgId);
|
|
111
|
+
}
|
|
112
|
+
buildUrl(path, query) {
|
|
113
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
114
|
+
const url = new URL(`${this.apiUrl}${normalizedPath}`);
|
|
115
|
+
for (const [key, value] of Object.entries(query ?? {})) {
|
|
116
|
+
if (value !== undefined) {
|
|
117
|
+
url.searchParams.set(key, String(value));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return url.toString();
|
|
121
|
+
}
|
|
122
|
+
async resolveAuthHeader() {
|
|
123
|
+
const accessToken = process.env.MCPSTACK_ACCESS_TOKEN;
|
|
124
|
+
if (accessToken) {
|
|
125
|
+
return `Bearer ${accessToken}`;
|
|
126
|
+
}
|
|
127
|
+
const apiKey = process.env.MCPSTACK_API_KEY;
|
|
128
|
+
if (apiKey) {
|
|
129
|
+
return `Bearer ${apiKey}`;
|
|
130
|
+
}
|
|
131
|
+
if (!this.config?.auth) {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
if (this.config.auth.type === "api_key") {
|
|
135
|
+
const storedApiKey = await getSecret("apiKey");
|
|
136
|
+
return storedApiKey ? `Bearer ${storedApiKey}` : undefined;
|
|
137
|
+
}
|
|
138
|
+
const refreshed = await this.refreshAccessTokenIfNeeded();
|
|
139
|
+
const token = refreshed ?? await getSecret("accessToken");
|
|
140
|
+
return token ? `Bearer ${token}` : undefined;
|
|
141
|
+
}
|
|
142
|
+
async refreshAccessTokenIfNeeded() {
|
|
143
|
+
if (!this.config?.auth || this.config.auth.type !== "oauth") {
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
const expiresAt = this.config.auth.expiresAt ? Date.parse(this.config.auth.expiresAt) : 0;
|
|
147
|
+
if (expiresAt > Date.now() + 60_000) {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
const refreshToken = await getSecret("refreshToken");
|
|
151
|
+
if (!refreshToken) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
const body = new URLSearchParams({
|
|
155
|
+
grant_type: "refresh_token",
|
|
156
|
+
refresh_token: refreshToken,
|
|
157
|
+
client_id: this.config.auth.clientId,
|
|
158
|
+
});
|
|
159
|
+
const response = await fetch(this.config.auth.tokenEndpoint, {
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers: {
|
|
162
|
+
Accept: "application/json",
|
|
163
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
164
|
+
},
|
|
165
|
+
body,
|
|
166
|
+
});
|
|
167
|
+
if (!response.ok) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
const token = await response.json();
|
|
171
|
+
await setSecret("accessToken", token.access_token);
|
|
172
|
+
if (token.refresh_token) {
|
|
173
|
+
await setSecret("refreshToken", token.refresh_token);
|
|
174
|
+
}
|
|
175
|
+
const expiresAtIso = new Date(Date.now() + (token.expires_in ?? 600) * 1000).toISOString();
|
|
176
|
+
await saveConfig({
|
|
177
|
+
...this.config,
|
|
178
|
+
auth: {
|
|
179
|
+
...this.config.auth,
|
|
180
|
+
expiresAt: expiresAtIso,
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
return token.access_token;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async function readJsonOrText(response) {
|
|
187
|
+
const text = await response.text();
|
|
188
|
+
if (!text) {
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
return JSON.parse(text);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return text;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function formatHttpError(status, body) {
|
|
199
|
+
if (body && typeof body === "object") {
|
|
200
|
+
const record = body;
|
|
201
|
+
const message = record.error_description ?? record.error ?? record.message;
|
|
202
|
+
if (message) {
|
|
203
|
+
return `HTTP ${status}: ${String(message)}`;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return typeof body === "string" && body
|
|
207
|
+
? `HTTP ${status}: ${body}`
|
|
208
|
+
: `HTTP ${status}`;
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|