@besales/mcp 0.1.0 → 0.12.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/README.md +272 -17
- package/dist/auth/connection-store.d.ts +58 -0
- package/dist/auth/connection-store.js +208 -0
- package/dist/auth/connection-store.js.map +1 -0
- package/dist/auth/oauth-client.d.ts +27 -2
- package/dist/auth/oauth-client.js +62 -11
- package/dist/auth/oauth-client.js.map +1 -1
- package/dist/auth/session-workspace.d.ts +2 -0
- package/dist/auth/session-workspace.js +20 -0
- package/dist/auth/session-workspace.js.map +1 -0
- package/dist/auth/token-storage.d.ts +19 -5
- package/dist/auth/token-storage.js +11 -6
- package/dist/auth/token-storage.js.map +1 -1
- package/dist/cli.d.ts +2 -7
- package/dist/cli.js +111 -33
- package/dist/cli.js.map +1 -1
- package/dist/http/api-client.d.ts +4 -13
- package/dist/http/api-client.js +18 -18
- package/dist/http/api-client.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/instructions/server-instructions.d.ts +15 -0
- package/dist/instructions/server-instructions.js +245 -0
- package/dist/instructions/server-instructions.js.map +1 -0
- package/dist/package-metadata.js +7 -1
- package/dist/package-metadata.js.map +1 -1
- package/dist/resources/concepts/feedback-sheets.md +77 -0
- package/dist/resources/concepts/sandbox.md +13 -0
- package/dist/resources/concepts/workbook-classification.md +241 -0
- package/dist/resources/docs/agent-behavior.md +393 -0
- package/dist/resources/docs/crm-integration.md +535 -0
- package/dist/resources/docs/files-and-uploads.md +295 -0
- package/dist/resources/docs/knowledge-base.md +521 -0
- package/dist/resources/docs/pipeline-builder.md +221 -0
- package/dist/resources/docs/pipeline-settings-deep.md +221 -0
- package/dist/resources/docs/platforms.md +513 -0
- package/dist/resources/docs/prompt-anatomy.md +298 -0
- package/dist/resources/docs/prompt-principles.md +390 -0
- package/dist/resources/registry.js +34 -12
- package/dist/resources/registry.js.map +1 -1
- package/dist/resources/workflows/compare-models.md +46 -0
- package/dist/resources/workflows/connect-crm-from-scratch.md +89 -0
- package/dist/resources/workflows/connect-datasource-from-scratch.md +92 -0
- package/dist/resources/workflows/extract-from-document.md +36 -0
- package/dist/resources/workflows/iterate-with-sandbox.md +31 -0
- package/dist/resources/workflows/platform-setup-from-scratch.md +113 -0
- package/dist/resources/workflows/production-readiness-check.md +41 -0
- package/dist/schemas/mcp-tools.json +2638 -184
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -1
- package/dist/tools/definitions/agent-design.d.ts +215 -0
- package/dist/tools/definitions/agent-design.js +644 -0
- package/dist/tools/definitions/agent-design.js.map +1 -0
- package/dist/tools/definitions/crm-platform.d.ts +211 -0
- package/dist/tools/definitions/crm-platform.js +1070 -0
- package/dist/tools/definitions/crm-platform.js.map +1 -0
- package/dist/tools/definitions/datasource.d.ts +40 -0
- package/dist/tools/definitions/datasource.js +196 -0
- package/dist/tools/definitions/datasource.js.map +1 -0
- package/dist/tools/definitions/knowledge.d.ts +215 -0
- package/dist/tools/definitions/knowledge.js +782 -0
- package/dist/tools/definitions/knowledge.js.map +1 -0
- package/dist/tools/definitions/model-comparison.d.ts +25 -0
- package/dist/tools/definitions/model-comparison.js +101 -0
- package/dist/tools/definitions/model-comparison.js.map +1 -0
- package/dist/tools/definitions/platform-setup.d.ts +412 -0
- package/dist/tools/definitions/platform-setup.js +741 -0
- package/dist/tools/definitions/platform-setup.js.map +1 -0
- package/dist/tools/definitions/session.d.ts +11 -0
- package/dist/tools/definitions/session.js +86 -0
- package/dist/tools/definitions/session.js.map +1 -0
- package/dist/tools/definitions/shared.d.ts +742 -0
- package/dist/tools/definitions/shared.js +773 -0
- package/dist/tools/definitions/shared.js.map +1 -0
- package/dist/tools/definitions.d.ts +873 -88
- package/dist/tools/definitions.js +14 -856
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/registry.d.ts +3 -1
- package/dist/tools/registry.js +90 -11
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/result.d.ts +1 -1
- package/dist/tools/result.js +12 -4
- package/dist/tools/result.js.map +1 -1
- package/dist/utils/logger.js +2 -1
- package/dist/utils/logger.js.map +1 -1
- package/docs/host-setup.md +34 -15
- package/package.json +2 -2
- package/scripts/install-claude-desktop.js +89 -11
- package/scripts/mock-api-server.js +1 -1
- package/scripts/mock-credentials.js +49 -6
- package/dist/types/api-contract.gen.d.ts +0 -6975
- package/dist/types/api-contract.gen.js +0 -6
- package/dist/types/api-contract.gen.js.map +0 -1
|
@@ -1,32 +1,57 @@
|
|
|
1
|
-
export declare const DEFAULT_API_BASE_URL = "https://
|
|
1
|
+
export declare const DEFAULT_API_BASE_URL = "https://core.besales.ai/api/v2";
|
|
2
|
+
export declare const DEFAULT_OAUTH_AUTHORIZE_URL = "https://app.besales.ai/settings/mcp/consent";
|
|
2
3
|
export declare const OAUTH_CALLBACK_HOST = "127.0.0.1";
|
|
3
4
|
export declare const OAUTH_CALLBACK_PATH = "/oauth-callback";
|
|
4
5
|
export declare const OAUTH_SCOPE = "mcp:* mcp:platform-setup";
|
|
5
6
|
export declare const OAUTH_TIMEOUT_MS: number;
|
|
7
|
+
export declare const TOKEN_EXCHANGE_TIMEOUT_MS: number;
|
|
6
8
|
export interface OAuthConnectResult {
|
|
7
9
|
readonly apiKey: string;
|
|
8
10
|
readonly workspaceId: string;
|
|
9
11
|
}
|
|
12
|
+
export interface AuthorizationCodeExchange {
|
|
13
|
+
readonly code: string;
|
|
14
|
+
readonly codeVerifier: string;
|
|
15
|
+
}
|
|
10
16
|
export interface OauthClientOptions {
|
|
17
|
+
readonly oauthAuthorizeUrl?: string;
|
|
11
18
|
readonly apiBaseUrl?: string;
|
|
12
19
|
readonly openUrl?: (url: string) => Promise<unknown> | unknown;
|
|
20
|
+
readonly exchangeAuthorizationCode?: (input: AuthorizationCodeExchange) => Promise<OAuthConnectResult>;
|
|
13
21
|
readonly timeoutMs?: number;
|
|
14
22
|
}
|
|
15
23
|
export declare function generateCodeVerifier(): string;
|
|
16
24
|
export declare function createCodeChallenge(codeVerifier: string): string;
|
|
17
25
|
export declare function generateState(): string;
|
|
18
26
|
export declare function normalizeApiBaseUrl(apiBaseUrl?: string): string;
|
|
27
|
+
export declare function normalizeOauthAuthorizeUrl(oauthAuthorizeUrl?: string): string;
|
|
19
28
|
export declare function createAuthorizationUrl(input: {
|
|
20
|
-
readonly
|
|
29
|
+
readonly oauthAuthorizeUrl?: string;
|
|
21
30
|
readonly state: string;
|
|
22
31
|
readonly redirectUri: string;
|
|
23
32
|
readonly codeChallenge: string;
|
|
24
33
|
}): URL;
|
|
25
34
|
export declare class OauthClient {
|
|
35
|
+
private readonly oauthAuthorizeUrl;
|
|
26
36
|
private readonly apiBaseUrl;
|
|
27
37
|
private readonly openUrl;
|
|
38
|
+
private readonly exchange;
|
|
28
39
|
private readonly timeoutMs;
|
|
29
40
|
constructor(options?: OauthClientOptions);
|
|
41
|
+
/**
|
|
42
|
+
* Connect flow (OAuth2 PKCE, RFC 7636).
|
|
43
|
+
*
|
|
44
|
+
* Открывает consent-страницу с `code_challenge`; после согласия backend
|
|
45
|
+
* редиректит на loopback callback с одноразовым `code` (а НЕ с api_key — секрет
|
|
46
|
+
* не попадает в URL/историю/логи). Затем клиент меняет `code` + `code_verifier`
|
|
47
|
+
* на api_key через POST `/auth/mcp-token`. Защита: loopback `127.0.0.1` +
|
|
48
|
+
* `state` (CSRF) + PKCE-проверка verifier на backend.
|
|
49
|
+
*/
|
|
30
50
|
connect(): Promise<OAuthConnectResult>;
|
|
31
51
|
private startCallbackServer;
|
|
52
|
+
/**
|
|
53
|
+
* Меняет PKCE authorization code на api_key через backend `/auth/mcp-token`.
|
|
54
|
+
* Запрос неаутентифицирован: доказательство владения — `code` + `code_verifier`.
|
|
55
|
+
*/
|
|
56
|
+
private defaultExchange;
|
|
32
57
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { createHash, randomBytes } from 'node:crypto';
|
|
2
2
|
import { createServer } from 'node:http';
|
|
3
|
+
import axios from 'axios';
|
|
3
4
|
import open from 'open';
|
|
4
5
|
import { logger } from '../utils/logger.js';
|
|
5
|
-
export const DEFAULT_API_BASE_URL = 'https://
|
|
6
|
+
export const DEFAULT_API_BASE_URL = 'https://core.besales.ai/api/v2';
|
|
7
|
+
export const DEFAULT_OAUTH_AUTHORIZE_URL = 'https://app.besales.ai/settings/mcp/consent';
|
|
6
8
|
export const OAUTH_CALLBACK_HOST = '127.0.0.1';
|
|
7
9
|
export const OAUTH_CALLBACK_PATH = '/oauth-callback';
|
|
8
10
|
export const OAUTH_SCOPE = 'mcp:* mcp:platform-setup';
|
|
9
11
|
export const OAUTH_TIMEOUT_MS = 5 * 60 * 1000;
|
|
12
|
+
export const TOKEN_EXCHANGE_TIMEOUT_MS = 30 * 1000;
|
|
10
13
|
export function generateCodeVerifier() {
|
|
11
14
|
return randomBytes(32).toString('base64url');
|
|
12
15
|
}
|
|
@@ -19,8 +22,13 @@ export function generateState() {
|
|
|
19
22
|
export function normalizeApiBaseUrl(apiBaseUrl) {
|
|
20
23
|
return (apiBaseUrl ?? process.env.BESALES_API_BASE_URL ?? DEFAULT_API_BASE_URL).replace(/\/+$/, '');
|
|
21
24
|
}
|
|
25
|
+
export function normalizeOauthAuthorizeUrl(oauthAuthorizeUrl) {
|
|
26
|
+
return (oauthAuthorizeUrl ??
|
|
27
|
+
process.env.BESALES_OAUTH_AUTHORIZE_URL ??
|
|
28
|
+
DEFAULT_OAUTH_AUTHORIZE_URL).replace(/\/+$/, '');
|
|
29
|
+
}
|
|
22
30
|
export function createAuthorizationUrl(input) {
|
|
23
|
-
const url = new URL(
|
|
31
|
+
const url = new URL(normalizeOauthAuthorizeUrl(input.oauthAuthorizeUrl));
|
|
24
32
|
url.searchParams.set('state', input.state);
|
|
25
33
|
url.searchParams.set('redirect_uri', input.redirectUri);
|
|
26
34
|
url.searchParams.set('code_challenge', input.codeChallenge);
|
|
@@ -29,14 +37,28 @@ export function createAuthorizationUrl(input) {
|
|
|
29
37
|
return url;
|
|
30
38
|
}
|
|
31
39
|
export class OauthClient {
|
|
40
|
+
oauthAuthorizeUrl;
|
|
32
41
|
apiBaseUrl;
|
|
33
42
|
openUrl;
|
|
43
|
+
exchange;
|
|
34
44
|
timeoutMs;
|
|
35
45
|
constructor(options = {}) {
|
|
46
|
+
this.oauthAuthorizeUrl = normalizeOauthAuthorizeUrl(options.oauthAuthorizeUrl);
|
|
36
47
|
this.apiBaseUrl = normalizeApiBaseUrl(options.apiBaseUrl);
|
|
37
48
|
this.openUrl = options.openUrl ?? ((url) => open(url));
|
|
49
|
+
this.exchange =
|
|
50
|
+
options.exchangeAuthorizationCode ?? ((input) => this.defaultExchange(input));
|
|
38
51
|
this.timeoutMs = options.timeoutMs ?? OAUTH_TIMEOUT_MS;
|
|
39
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Connect flow (OAuth2 PKCE, RFC 7636).
|
|
55
|
+
*
|
|
56
|
+
* Открывает consent-страницу с `code_challenge`; после согласия backend
|
|
57
|
+
* редиректит на loopback callback с одноразовым `code` (а НЕ с api_key — секрет
|
|
58
|
+
* не попадает в URL/историю/логи). Затем клиент меняет `code` + `code_verifier`
|
|
59
|
+
* на api_key через POST `/auth/mcp-token`. Защита: loopback `127.0.0.1` +
|
|
60
|
+
* `state` (CSRF) + PKCE-проверка verifier на backend.
|
|
61
|
+
*/
|
|
40
62
|
async connect() {
|
|
41
63
|
const codeVerifier = generateCodeVerifier();
|
|
42
64
|
const codeChallenge = createCodeChallenge(codeVerifier);
|
|
@@ -44,7 +66,7 @@ export class OauthClient {
|
|
|
44
66
|
const callbackServer = await this.startCallbackServer({ expectedState: state });
|
|
45
67
|
const redirectUri = `http://${OAUTH_CALLBACK_HOST}:${callbackServer.port}${OAUTH_CALLBACK_PATH}`;
|
|
46
68
|
const authorizationUrl = createAuthorizationUrl({
|
|
47
|
-
|
|
69
|
+
oauthAuthorizeUrl: this.oauthAuthorizeUrl,
|
|
48
70
|
state,
|
|
49
71
|
redirectUri,
|
|
50
72
|
codeChallenge,
|
|
@@ -53,18 +75,22 @@ export class OauthClient {
|
|
|
53
75
|
callbackResult.catch(() => undefined);
|
|
54
76
|
try {
|
|
55
77
|
await this.openUrl(authorizationUrl.toString());
|
|
56
|
-
return await callbackResult;
|
|
57
78
|
}
|
|
58
79
|
catch (error) {
|
|
80
|
+
const cause = error instanceof Error ? error : new Error(String(error));
|
|
81
|
+
callbackServer.abort(cause);
|
|
59
82
|
await callbackServer.close();
|
|
60
|
-
throw
|
|
83
|
+
throw cause;
|
|
61
84
|
}
|
|
85
|
+
const { code } = await callbackResult;
|
|
86
|
+
return this.exchange({ code, codeVerifier });
|
|
62
87
|
}
|
|
63
88
|
async startCallbackServer(input) {
|
|
64
89
|
const server = createServer();
|
|
65
90
|
let settled = false;
|
|
66
91
|
let timeout;
|
|
67
92
|
let closePromise = null;
|
|
93
|
+
let settleRef = () => undefined;
|
|
68
94
|
const close = async () => {
|
|
69
95
|
if (closePromise) {
|
|
70
96
|
return closePromise;
|
|
@@ -97,6 +123,7 @@ export class OauthClient {
|
|
|
97
123
|
}
|
|
98
124
|
void close();
|
|
99
125
|
};
|
|
126
|
+
settleRef = settle;
|
|
100
127
|
const rejectCallback = (statusCode, responseMessage, errorMessage, response) => {
|
|
101
128
|
response.writeHead(statusCode, {
|
|
102
129
|
'Connection': 'close',
|
|
@@ -130,10 +157,9 @@ export class OauthClient {
|
|
|
130
157
|
rejectCallback(400, 'Invalid state parameter', 'OAuth state mismatch', response);
|
|
131
158
|
return;
|
|
132
159
|
}
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
rejectCallback(400, 'Missing api_key/workspace_id', 'OAuth callback missing required params', response);
|
|
160
|
+
const code = requestUrl.searchParams.get('code');
|
|
161
|
+
if (!code) {
|
|
162
|
+
rejectCallback(400, 'Missing authorization code', 'OAuth callback missing authorization code', response);
|
|
137
163
|
return;
|
|
138
164
|
}
|
|
139
165
|
response.writeHead(200, {
|
|
@@ -141,15 +167,16 @@ export class OauthClient {
|
|
|
141
167
|
'Content-Type': 'text/html; charset=utf-8',
|
|
142
168
|
});
|
|
143
169
|
response.end('<html><body><h1>Connected</h1><p>You can close this tab.</p></body></html>');
|
|
144
|
-
settle('resolve', {
|
|
170
|
+
settle('resolve', { code });
|
|
145
171
|
});
|
|
146
172
|
server.on('error', (error) => {
|
|
147
173
|
logger.error({ err: error }, 'OAuth callback server error');
|
|
148
174
|
settle('reject', error);
|
|
149
175
|
});
|
|
150
176
|
timeout = setTimeout(() => {
|
|
177
|
+
const timeoutMinutes = Math.round(this.timeoutMs / 60_000);
|
|
151
178
|
logger.warn('OAuth flow timeout');
|
|
152
|
-
settle('reject', new Error(
|
|
179
|
+
settle('reject', new Error(`OAuth flow timeout (${timeoutMinutes}min)`));
|
|
153
180
|
}, this.timeoutMs);
|
|
154
181
|
});
|
|
155
182
|
await new Promise((resolve, reject) => {
|
|
@@ -174,7 +201,31 @@ export class OauthClient {
|
|
|
174
201
|
port: address.port,
|
|
175
202
|
result,
|
|
176
203
|
close,
|
|
204
|
+
abort: (error) => settleRef('reject', error),
|
|
177
205
|
};
|
|
178
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Меняет PKCE authorization code на api_key через backend `/auth/mcp-token`.
|
|
209
|
+
* Запрос неаутентифицирован: доказательство владения — `code` + `code_verifier`.
|
|
210
|
+
*/
|
|
211
|
+
async defaultExchange(input) {
|
|
212
|
+
const url = `${this.apiBaseUrl}/auth/mcp-token`;
|
|
213
|
+
let data;
|
|
214
|
+
try {
|
|
215
|
+
const response = await axios.post(url, { code: input.code, code_verifier: input.codeVerifier }, { timeout: TOKEN_EXCHANGE_TIMEOUT_MS });
|
|
216
|
+
data = response.data;
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
const detail = axios.isAxiosError(error)
|
|
220
|
+
? String(error.response?.status ?? error.message)
|
|
221
|
+
: String(error);
|
|
222
|
+
throw new Error(`MCP token exchange failed (${detail})`);
|
|
223
|
+
}
|
|
224
|
+
const payload = data;
|
|
225
|
+
if (typeof payload?.api_key !== 'string' || typeof payload?.workspace_id !== 'string') {
|
|
226
|
+
throw new Error('MCP token exchange returned an invalid response');
|
|
227
|
+
}
|
|
228
|
+
return { apiKey: payload.api_key, workspaceId: payload.workspace_id };
|
|
229
|
+
}
|
|
179
230
|
}
|
|
180
231
|
//# sourceMappingURL=oauth-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-client.js","sourceRoot":"","sources":["../../src/auth/oauth-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,YAAY,EAAuB,MAAM,WAAW,CAAC;AAG9D,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,CAAC,MAAM,oBAAoB,GAAG
|
|
1
|
+
{"version":3,"file":"oauth-client.js","sourceRoot":"","sources":["../../src/auth/oauth-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory, per-process workspace override для текущей MCP-сессии.
|
|
3
|
+
*
|
|
4
|
+
* Каждая сессия хоста (Claude Desktop / Claude Code / Codex) спавнит ОТДЕЛЬНЫЙ
|
|
5
|
+
* процесс besales-mcp, поэтому module-level state здесь = состояние ровно этой
|
|
6
|
+
* сессии. Тул `besales_workspace_use` пишет сюда; резолвер читает (precedence:
|
|
7
|
+
* ниже env-пина и явного workspace_id, выше глобального `active`).
|
|
8
|
+
*
|
|
9
|
+
* Значение НЕ персистится (живёт пока жив процесс сессии) и НЕ трогает keychain
|
|
10
|
+
* `active`, поэтому параллельные сессии друг друга не задевают — в этом весь смысл:
|
|
11
|
+
* одна Claude-сессия = один воркспейс, без env-переменных и без отдельных папок.
|
|
12
|
+
*/
|
|
13
|
+
let sessionWorkspaceId;
|
|
14
|
+
export function getSessionWorkspaceId() {
|
|
15
|
+
return sessionWorkspaceId;
|
|
16
|
+
}
|
|
17
|
+
export function setSessionWorkspaceId(workspaceId) {
|
|
18
|
+
sessionWorkspaceId = workspaceId;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=session-workspace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-workspace.js","sourceRoot":"","sources":["../../src/auth/session-workspace.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,IAAI,kBAAsC,CAAC;AAE3C,MAAM,UAAU,qBAAqB;IACnC,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,WAA+B;IACnE,kBAAkB,GAAG,WAAW,CAAC;AACnC,CAAC"}
|
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
export declare const TOKEN_STORAGE_SERVICE = "@besales/mcp";
|
|
2
|
-
export
|
|
3
|
-
export declare
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
export declare const LEGACY_API_KEY_ACCOUNT = "api_key";
|
|
3
|
+
export declare const LEGACY_WORKSPACE_ID_ACCOUNT = "workspace_id";
|
|
4
|
+
/**
|
|
5
|
+
* Низкоуровневый доступ к keychain по произвольному имени account'а.
|
|
6
|
+
* Доменную логику (index/active/per-workspace ключи, миграция) держит
|
|
7
|
+
* ConnectionStore поверх этого интерфейса.
|
|
8
|
+
*/
|
|
9
|
+
export interface CredentialStore {
|
|
10
|
+
set(account: string, value: string): Promise<void>;
|
|
11
|
+
get(account: string): Promise<string | null>;
|
|
12
|
+
delete(account: string): Promise<void>;
|
|
13
|
+
/** Имена всех account'ов сервиса (без паролей) — для подметания orphan-записей. */
|
|
14
|
+
accounts(): Promise<string[]>;
|
|
15
|
+
}
|
|
16
|
+
export declare class TokenStorage implements CredentialStore {
|
|
17
|
+
set(account: string, value: string): Promise<void>;
|
|
18
|
+
get(account: string): Promise<string | null>;
|
|
19
|
+
delete(account: string): Promise<void>;
|
|
20
|
+
accounts(): Promise<string[]>;
|
|
7
21
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import keytar from 'keytar';
|
|
2
2
|
export const TOKEN_STORAGE_SERVICE = '@besales/mcp';
|
|
3
|
+
// Legacy single-workspace accounts (до мульти-воркспейс). Сохранены только для
|
|
4
|
+
// одноразовой миграции в новую схему — см. ConnectionStore.migrateLegacy().
|
|
5
|
+
export const LEGACY_API_KEY_ACCOUNT = 'api_key';
|
|
6
|
+
export const LEGACY_WORKSPACE_ID_ACCOUNT = 'workspace_id';
|
|
3
7
|
export class TokenStorage {
|
|
4
8
|
async set(account, value) {
|
|
5
9
|
await keytar.setPassword(TOKEN_STORAGE_SERVICE, account, value);
|
|
@@ -7,11 +11,12 @@ export class TokenStorage {
|
|
|
7
11
|
async get(account) {
|
|
8
12
|
return keytar.getPassword(TOKEN_STORAGE_SERVICE, account);
|
|
9
13
|
}
|
|
10
|
-
async
|
|
11
|
-
await
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
async delete(account) {
|
|
15
|
+
await keytar.deletePassword(TOKEN_STORAGE_SERVICE, account);
|
|
16
|
+
}
|
|
17
|
+
async accounts() {
|
|
18
|
+
const credentials = await keytar.findCredentials(TOKEN_STORAGE_SERVICE);
|
|
19
|
+
return credentials.map(({ account }) => account);
|
|
15
20
|
}
|
|
16
21
|
}
|
|
17
22
|
//# sourceMappingURL=token-storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-storage.js","sourceRoot":"","sources":["../../src/auth/token-storage.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"token-storage.js","sourceRoot":"","sources":["../../src/auth/token-storage.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,CAAC,MAAM,qBAAqB,GAAG,cAAc,CAAC;AAEpD,+EAA+E;AAC/E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,sBAAsB,GAAG,SAAS,CAAC;AAChD,MAAM,CAAC,MAAM,2BAA2B,GAAG,cAAc,CAAC;AAe1D,MAAM,OAAO,YAAY;IACvB,KAAK,CAAC,GAAG,CAAC,OAAe,EAAE,KAAa;QACtC,MAAM,MAAM,CAAC,WAAW,CAAC,qBAAqB,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAe;QACvB,OAAO,MAAM,CAAC,WAAW,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,MAAM,MAAM,CAAC,cAAc,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,qBAAqB,CAAC,CAAC;QACxE,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;IACnD,CAAC;CACF"}
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { ConnectionStore } from './auth/connection-store.js';
|
|
1
2
|
import { type OAuthConnectResult } from './auth/oauth-client.js';
|
|
2
|
-
import { type TokenStorageAccount } from './auth/token-storage.js';
|
|
3
3
|
import { startMcpServer } from './server.js';
|
|
4
4
|
export interface CliIo {
|
|
5
5
|
readonly log: (message: string) => void;
|
|
@@ -8,14 +8,9 @@ export interface CliIo {
|
|
|
8
8
|
export interface OAuthConnector {
|
|
9
9
|
connect(): Promise<OAuthConnectResult>;
|
|
10
10
|
}
|
|
11
|
-
export interface CredentialStorage {
|
|
12
|
-
set(account: TokenStorageAccount, value: string): Promise<void>;
|
|
13
|
-
get(account: TokenStorageAccount): Promise<string | null>;
|
|
14
|
-
clear(): Promise<void>;
|
|
15
|
-
}
|
|
16
11
|
export interface CliDeps {
|
|
17
12
|
readonly oauthClient?: OAuthConnector;
|
|
18
|
-
readonly
|
|
13
|
+
readonly store?: ConnectionStore;
|
|
19
14
|
readonly startMcpServer?: typeof startMcpServer;
|
|
20
15
|
}
|
|
21
16
|
export declare function getHelpText(version?: string): string;
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { ConnectionStore } from './auth/connection-store.js';
|
|
1
2
|
import { OauthClient } from './auth/oauth-client.js';
|
|
2
|
-
import { TokenStorage } from './auth/token-storage.js';
|
|
3
3
|
import { readPackageVersion } from './package-metadata.js';
|
|
4
4
|
import { startMcpServer } from './server.js';
|
|
5
5
|
import { maskApiKey } from './utils/mask.js';
|
|
@@ -7,21 +7,30 @@ const defaultIo = {
|
|
|
7
7
|
log: (message) => console.log(message),
|
|
8
8
|
error: (message) => console.error(message),
|
|
9
9
|
};
|
|
10
|
+
const STORAGE_COMMANDS = new Set(['connect', 'connections', 'use', 'disconnect', 'status']);
|
|
10
11
|
export function getHelpText(version = readPackageVersion()) {
|
|
11
12
|
return `besales-mcp ${version}
|
|
12
13
|
|
|
13
14
|
Usage:
|
|
14
|
-
besales-mcp
|
|
15
|
-
besales-mcp connect
|
|
16
|
-
besales-mcp
|
|
17
|
-
besales-mcp
|
|
18
|
-
besales-mcp
|
|
19
|
-
besales-mcp
|
|
15
|
+
besales-mcp Start MCP server
|
|
16
|
+
besales-mcp connect Connect (or refresh) an Animaly workspace
|
|
17
|
+
besales-mcp connections List connected workspaces
|
|
18
|
+
besales-mcp use <workspaceId> Set the active (default) workspace
|
|
19
|
+
besales-mcp status Show the active workspace
|
|
20
|
+
besales-mcp disconnect Disconnect the active workspace
|
|
21
|
+
besales-mcp disconnect <id> Disconnect one workspace
|
|
22
|
+
besales-mcp disconnect --all Disconnect every workspace
|
|
23
|
+
besales-mcp --help Show help
|
|
24
|
+
besales-mcp --version Show version
|
|
25
|
+
|
|
26
|
+
Connect each workspace once — switching afterwards needs no browser. Pin a
|
|
27
|
+
session to a workspace with the BESALES_WORKSPACE_ID env var in your MCP host
|
|
28
|
+
config; it overrides the global active workspace set by \`use\`.`;
|
|
20
29
|
}
|
|
21
30
|
export async function runCli(argv = process.argv.slice(2), io = defaultIo, deps = {}) {
|
|
22
31
|
const command = argv[0];
|
|
23
32
|
const oauthClient = deps.oauthClient ?? new OauthClient();
|
|
24
|
-
const
|
|
33
|
+
const store = deps.store ?? new ConnectionStore();
|
|
25
34
|
const runMcpServer = deps.startMcpServer ?? startMcpServer;
|
|
26
35
|
if (command === '--help' || command === '-h') {
|
|
27
36
|
io.log(getHelpText());
|
|
@@ -31,40 +40,109 @@ export async function runCli(argv = process.argv.slice(2), io = defaultIo, deps
|
|
|
31
40
|
io.log(readPackageVersion());
|
|
32
41
|
return 0;
|
|
33
42
|
}
|
|
34
|
-
if (command
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
if (command && STORAGE_COMMANDS.has(command)) {
|
|
44
|
+
// Миграция legacy-пары ДО любой записи в index — иначе connect для второго
|
|
45
|
+
// воркспейса перезатёр бы ещё не мигрированный первый.
|
|
46
|
+
await store.migrateLegacy();
|
|
47
|
+
switch (command) {
|
|
48
|
+
case 'connect':
|
|
49
|
+
return connectCommand(io, oauthClient, store);
|
|
50
|
+
case 'connections':
|
|
51
|
+
return connectionsCommand(io, store);
|
|
52
|
+
case 'use':
|
|
53
|
+
return useCommand(argv[1], io, store);
|
|
54
|
+
case 'disconnect':
|
|
55
|
+
return disconnectCommand(argv[1], io, store);
|
|
56
|
+
case 'status':
|
|
57
|
+
return statusCommand(io, store);
|
|
43
58
|
}
|
|
44
|
-
|
|
59
|
+
}
|
|
60
|
+
if (command) {
|
|
61
|
+
io.error(`Unknown command: ${command}`);
|
|
62
|
+
io.log(getHelpText());
|
|
63
|
+
return 1;
|
|
64
|
+
}
|
|
65
|
+
await runMcpServer({ stdio: true });
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
async function connectCommand(io, oauthClient, store) {
|
|
69
|
+
const { apiKey, workspaceId } = await oauthClient.connect();
|
|
70
|
+
await store.addOrReplace(workspaceId, apiKey);
|
|
71
|
+
const active = await store.getActive();
|
|
72
|
+
io.log(`Connected to workspace ${workspaceId} (key: ${maskApiKey(apiKey)}).`);
|
|
73
|
+
io.log(`Active workspace: ${active ?? workspaceId}.`);
|
|
74
|
+
io.log('Tip: set BESALES_WORKSPACE_ID in your MCP host config to pin this session to a workspace.');
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
async function connectionsCommand(io, store) {
|
|
78
|
+
const connections = await store.list();
|
|
79
|
+
if (connections.length === 0) {
|
|
80
|
+
io.log('No connected workspaces. Run `besales-mcp connect`.');
|
|
45
81
|
return 0;
|
|
46
82
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
83
|
+
const active = await store.getActive();
|
|
84
|
+
for (const connection of connections) {
|
|
85
|
+
const marker = connection.workspaceId === active ? '*' : ' ';
|
|
86
|
+
io.log(`${marker} ${connection.workspaceId} (key: ${connection.keyPrefix})`);
|
|
87
|
+
}
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
async function useCommand(workspaceId, io, store) {
|
|
91
|
+
if (!workspaceId) {
|
|
92
|
+
io.error('Usage: besales-mcp use <workspaceId>');
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
await store.setActive(workspaceId);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
io.error(error instanceof Error ? error.message : String(error));
|
|
100
|
+
const connections = await store.list();
|
|
101
|
+
if (connections.length > 0) {
|
|
102
|
+
io.log('Connected workspaces:');
|
|
103
|
+
for (const connection of connections) {
|
|
104
|
+
io.log(` ${connection.workspaceId}`);
|
|
105
|
+
}
|
|
53
106
|
}
|
|
54
|
-
|
|
55
|
-
return 0;
|
|
107
|
+
return 1;
|
|
56
108
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
109
|
+
io.log(`Active workspace: ${workspaceId}.`);
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
async function disconnectCommand(arg, io, store) {
|
|
113
|
+
if (arg === '--all') {
|
|
114
|
+
await store.clear();
|
|
115
|
+
io.log('Disconnected all workspaces.');
|
|
60
116
|
return 0;
|
|
61
117
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
io.
|
|
118
|
+
const target = arg ?? (await store.getActive());
|
|
119
|
+
if (!target) {
|
|
120
|
+
io.error('No active workspace. Specify `besales-mcp disconnect <workspaceId>` or `besales-mcp disconnect --all`.');
|
|
65
121
|
return 1;
|
|
66
122
|
}
|
|
67
|
-
|
|
123
|
+
const connections = await store.list();
|
|
124
|
+
if (!connections.some((connection) => connection.workspaceId === target)) {
|
|
125
|
+
io.log(`Workspace ${target} is not connected.`);
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
await store.remove(target);
|
|
129
|
+
io.log(`Disconnected workspace ${target}.`);
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
async function statusCommand(io, store) {
|
|
133
|
+
const connections = await store.list();
|
|
134
|
+
if (connections.length === 0) {
|
|
135
|
+
io.log('Not connected');
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
const active = await store.getActive();
|
|
139
|
+
const activeConnection = connections.find((connection) => connection.workspaceId === active);
|
|
140
|
+
if (activeConnection) {
|
|
141
|
+
io.log(`Active workspace: ${activeConnection.workspaceId} (key: ${activeConnection.keyPrefix}). ${connections.length} connected.`);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
io.log(`No active workspace selected. ${connections.length} connected — run \`besales-mcp use <workspaceId>\`.`);
|
|
145
|
+
}
|
|
68
146
|
return 0;
|
|
69
147
|
}
|
|
70
148
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import { type TokenStorageAccount } from '../auth/token-storage.js';
|
|
2
1
|
export declare const API_REQUEST_TIMEOUT_MS = 60000;
|
|
3
2
|
export type ApiMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|
4
|
-
export interface CredentialReader {
|
|
5
|
-
get(account: TokenStorageAccount): Promise<string | null>;
|
|
6
|
-
}
|
|
7
3
|
export interface ApiTransportRequest {
|
|
8
4
|
readonly method: ApiMethod;
|
|
9
5
|
readonly url: string;
|
|
@@ -20,14 +16,12 @@ export interface ApiTransport {
|
|
|
20
16
|
}
|
|
21
17
|
export interface ApiClientOptions {
|
|
22
18
|
readonly apiBaseUrl?: string;
|
|
23
|
-
readonly tokenStorage?: CredentialReader;
|
|
24
19
|
readonly transport?: ApiTransport;
|
|
25
20
|
readonly timeoutMs?: number;
|
|
26
21
|
}
|
|
27
22
|
export interface ToolApiClient {
|
|
28
|
-
post<T>(path: string, body?: unknown): Promise<T>;
|
|
29
|
-
request<T>(method: ApiMethod, path: string, body?: unknown): Promise<T>;
|
|
30
|
-
getStoredWorkspaceId(): Promise<string | null>;
|
|
23
|
+
post<T>(path: string, apiKey: string, body?: unknown): Promise<T>;
|
|
24
|
+
request<T>(method: ApiMethod, path: string, apiKey: string, body?: unknown): Promise<T>;
|
|
31
25
|
}
|
|
32
26
|
export declare class ApiClientError extends Error {
|
|
33
27
|
readonly status?: number | undefined;
|
|
@@ -39,13 +33,10 @@ export declare class ApiClientNetworkError extends Error {
|
|
|
39
33
|
}
|
|
40
34
|
export declare class ApiClient implements ToolApiClient {
|
|
41
35
|
private readonly apiBaseUrl;
|
|
42
|
-
private readonly tokenStorage;
|
|
43
36
|
private readonly transport;
|
|
44
37
|
private readonly timeoutMs;
|
|
45
38
|
constructor(options?: ApiClientOptions);
|
|
46
|
-
post<T>(path: string, body?: unknown): Promise<T>;
|
|
47
|
-
|
|
48
|
-
getStoredWorkspaceId(): Promise<string | null>;
|
|
49
|
-
request<T>(method: ApiMethod, path: string, body?: unknown): Promise<T>;
|
|
39
|
+
post<T>(path: string, apiKey: string, body?: unknown): Promise<T>;
|
|
40
|
+
request<T>(method: ApiMethod, path: string, apiKey: string, body?: unknown): Promise<T>;
|
|
50
41
|
}
|
|
51
42
|
export declare function buildApiUrl(apiBaseUrl: string, path: string): string;
|