@atlassian/mcp-compressor 0.35.0 → 0.36.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.js +35 -111
- package/dist/native.d.ts +3 -1
- package/dist/native_client.d.ts +3 -2
- package/dist/native_client.js +11 -12
- package/dist/rust_core.d.ts +2 -1
- package/dist/rust_core.js +7 -1
- package/native/index.d.ts +9 -1
- package/native/index.darwin-arm64.node +0 -0
- package/native/index.darwin-x64.node +0 -0
- package/native/index.js +1 -0
- package/native/index.linux-arm64-gnu.node +0 -0
- package/native/index.linux-x64-gnu.node +0 -0
- package/native/index.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command, Option } from "commander";
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
|
-
import {
|
|
5
|
-
import { delimiter, dirname, join } from "node:path";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { loadNativeCore } from "./native.js";
|
|
7
5
|
import { VERSION } from "./version.js";
|
|
8
6
|
function parseBackendArg(backendArgs) {
|
|
9
7
|
if (backendArgs.length === 0) {
|
|
@@ -120,90 +118,6 @@ function parseClearOAuthArgs(args) {
|
|
|
120
118
|
const options = clearProgram.opts();
|
|
121
119
|
return { ...(target ? { target } : {}), all: options.all ?? false };
|
|
122
120
|
}
|
|
123
|
-
/**
|
|
124
|
-
* Resolve a bare binary name to an absolute path using the PATH environment
|
|
125
|
-
* variable. Returns null when the name cannot be found in any PATH directory.
|
|
126
|
-
*/
|
|
127
|
-
function resolveFromPath(name) {
|
|
128
|
-
const pathEnv = process.env.PATH ?? "";
|
|
129
|
-
const dirs = pathEnv.split(delimiter);
|
|
130
|
-
const exts = process.platform === "win32" ? (process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";") : [""];
|
|
131
|
-
for (const dir of dirs) {
|
|
132
|
-
for (const ext of exts) {
|
|
133
|
-
const candidate = join(dir, name + ext);
|
|
134
|
-
try {
|
|
135
|
-
accessSync(candidate, constants.X_OK);
|
|
136
|
-
return candidate;
|
|
137
|
-
}
|
|
138
|
-
catch {
|
|
139
|
-
// not executable or not found — try next
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Return true when the file at `filePath` begins with a native-executable
|
|
147
|
-
* magic number (ELF, Mach-O, or PE). A JS shim that starts with a `#!`
|
|
148
|
-
* shebang (or any other non-native header) returns false.
|
|
149
|
-
*
|
|
150
|
-
* This guards against the fork-bomb that occurs when the npm-installed
|
|
151
|
-
* `mcp-compressor` bin shim is the only entry on PATH: spawning it would
|
|
152
|
-
* re-invoke this very script rather than the Rust binary.
|
|
153
|
-
*/
|
|
154
|
-
function isNativeExecutable(filePath) {
|
|
155
|
-
let fd;
|
|
156
|
-
try {
|
|
157
|
-
fd = openSync(filePath, "r");
|
|
158
|
-
}
|
|
159
|
-
catch {
|
|
160
|
-
return false;
|
|
161
|
-
}
|
|
162
|
-
try {
|
|
163
|
-
const buf = Buffer.alloc(4);
|
|
164
|
-
const n = readSync(fd, buf, 0, 4, 0);
|
|
165
|
-
if (n < 4)
|
|
166
|
-
return false;
|
|
167
|
-
// ELF (Linux/BSD): \x7fELF
|
|
168
|
-
if (buf[0] === 0x7f && buf[1] === 0x45 && buf[2] === 0x4c && buf[3] === 0x46)
|
|
169
|
-
return true;
|
|
170
|
-
// PE (Windows): MZ
|
|
171
|
-
if (buf[0] === 0x4d && buf[1] === 0x5a)
|
|
172
|
-
return true;
|
|
173
|
-
// Mach-O (macOS) — big-endian and little-endian variants, including fat/universal
|
|
174
|
-
const be = buf.readUInt32BE(0);
|
|
175
|
-
if (be === 0xfeedface || // Mach-O 32-bit BE
|
|
176
|
-
be === 0xfeedfacf || // Mach-O 64-bit BE
|
|
177
|
-
be === 0xcefaedfe || // Mach-O 32-bit LE
|
|
178
|
-
be === 0xcffaedfe || // Mach-O 64-bit LE
|
|
179
|
-
be === 0xcafebabe || // Mach-O fat binary
|
|
180
|
-
be === 0xbebafeca // Mach-O fat binary LE
|
|
181
|
-
)
|
|
182
|
-
return true;
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
185
|
-
finally {
|
|
186
|
-
closeSync(fd);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
function candidateCoreBinaries() {
|
|
190
|
-
const candidates = [];
|
|
191
|
-
if (process.env.MCP_COMPRESSOR_BINARY) {
|
|
192
|
-
candidates.push(process.env.MCP_COMPRESSOR_BINARY);
|
|
193
|
-
}
|
|
194
|
-
// Resolve the bare name from PATH and only include it when the resolved
|
|
195
|
-
// file is a native binary, not a JS shim. Without this check the npm bin
|
|
196
|
-
// shim (which maps `mcp-compressor` back to this very script) would be
|
|
197
|
-
// spawned indefinitely, creating a fork bomb.
|
|
198
|
-
const resolved = resolveFromPath("mcp-compressor");
|
|
199
|
-
if (resolved !== null && isNativeExecutable(resolved)) {
|
|
200
|
-
candidates.push(resolved);
|
|
201
|
-
}
|
|
202
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
203
|
-
candidates.push(join(here, "..", "..", "target", "debug", process.platform === "win32" ? "mcp-compressor.exe" : "mcp-compressor"));
|
|
204
|
-
candidates.push(join(process.cwd(), "..", "target", "debug", process.platform === "win32" ? "mcp-compressor.exe" : "mcp-compressor"));
|
|
205
|
-
return candidates;
|
|
206
|
-
}
|
|
207
121
|
function translateArgsForRust(args) {
|
|
208
122
|
const clearOAuth = parseClearOAuthArgs(args);
|
|
209
123
|
if (clearOAuth) {
|
|
@@ -211,34 +125,44 @@ function translateArgsForRust(args) {
|
|
|
211
125
|
}
|
|
212
126
|
return args;
|
|
213
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Run the Rust CLI. The npm package ships the native addon, so by default the
|
|
130
|
+
* CLI runs in-process and needs no separately installed binary (like the
|
|
131
|
+
* Python package). `MCP_COMPRESSOR_BINARY` runs a specific binary instead.
|
|
132
|
+
*/
|
|
214
133
|
async function runRustCoreCli(args) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
const child = spawn(binary, translateArgsForRust(args), { stdio: "inherit" });
|
|
220
|
-
return await new Promise((resolve, reject) => {
|
|
221
|
-
child.on("error", (error) => {
|
|
222
|
-
if (error.code === "ENOENT") {
|
|
223
|
-
resolve(127);
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
reject(error);
|
|
227
|
-
});
|
|
228
|
-
child.on("exit", (code, signal) => {
|
|
229
|
-
if (signal) {
|
|
230
|
-
resolve(1);
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
resolve(code ?? 0);
|
|
234
|
-
});
|
|
235
|
-
});
|
|
134
|
+
const rustArgs = translateArgsForRust(args);
|
|
135
|
+
const binary = process.env.MCP_COMPRESSOR_BINARY;
|
|
136
|
+
if (!binary) {
|
|
137
|
+
return loadNativeCore().runCliJson(JSON.stringify(["mcp-compressor", ...rustArgs]), VERSION);
|
|
236
138
|
}
|
|
237
|
-
|
|
238
|
-
|
|
139
|
+
return await new Promise((resolve, reject) => {
|
|
140
|
+
const child = spawn(binary, rustArgs, { stdio: "inherit" });
|
|
141
|
+
child.on("error", (error) => {
|
|
142
|
+
if (error.code === "ENOENT") {
|
|
143
|
+
console.error(`MCP_COMPRESSOR_BINARY not found: ${binary}`);
|
|
144
|
+
resolve(127);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
reject(error);
|
|
148
|
+
});
|
|
149
|
+
child.on("exit", (code, signal) => {
|
|
150
|
+
if (signal) {
|
|
151
|
+
resolve(1);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
resolve(code ?? 0);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
239
157
|
}
|
|
240
158
|
async function main() {
|
|
241
|
-
const
|
|
159
|
+
const args = process.argv.slice(2);
|
|
160
|
+
if (args.length === 1 && (args[0] === "--version" || args[0] === "-V")) {
|
|
161
|
+
// The Rust core is versioned by the npm release, not its Cargo manifest.
|
|
162
|
+
console.log(`mcp-compressor ${VERSION}`);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const exitCode = await runRustCoreCli(args);
|
|
242
166
|
process.exitCode = exitCode;
|
|
243
167
|
}
|
|
244
168
|
main().catch((error) => {
|
package/dist/native.d.ts
CHANGED
|
@@ -19,13 +19,15 @@ export interface NativeCore {
|
|
|
19
19
|
rememberOauthBackendJson(backendUri: string, backendName: string, storeDir: string): void;
|
|
20
20
|
listOauthCredentialsJson(): string;
|
|
21
21
|
clearOauthCredentialsJson(target?: string | null): string;
|
|
22
|
+
/** Run the whole CLI in-process; blocks until it exits. */
|
|
23
|
+
runCliJson(argvJson: string, version?: string | null): number;
|
|
22
24
|
startCompressedSessionJson(configJson: string, backendsJson: string): Promise<NativeCompressedSession>;
|
|
23
25
|
startCompressedSessionWithProviderBackendsJson(configJson: string, backendsJson: string, providersJson: string, refreshProviders: () => Promise<string>): Promise<NativeCompressedSession>;
|
|
24
26
|
startCompressedSessionFromMcpConfigJson(configJson: string, mcpConfigJson: string): Promise<NativeCompressedSession>;
|
|
25
27
|
}
|
|
26
28
|
export interface NativeCompressedSession {
|
|
27
29
|
infoJson(): string;
|
|
28
|
-
close(): void
|
|
30
|
+
close(): Promise<void>;
|
|
29
31
|
updateAuthProviderHeadersJson(providerIndex: number, headersJson: string): void;
|
|
30
32
|
}
|
|
31
33
|
export declare function loadNativeCore(): NativeCore;
|
package/dist/native_client.d.ts
CHANGED
|
@@ -65,12 +65,13 @@ export declare function normalizeServers(servers: NativeServersInput): Promise<N
|
|
|
65
65
|
* Internal; not part of the public package surface.
|
|
66
66
|
*/
|
|
67
67
|
export declare function adoptNativeSession<T>(session: {
|
|
68
|
-
close(): void
|
|
68
|
+
close(): void | Promise<void>;
|
|
69
69
|
}, build: () => T): T;
|
|
70
70
|
export declare class CompressorProxy {
|
|
71
71
|
private readonly session;
|
|
72
72
|
private readonly defaultServer;
|
|
73
73
|
private closed;
|
|
74
|
+
private closing;
|
|
74
75
|
constructor(session: CompressedSession, defaultServer: string | null);
|
|
75
76
|
info(): CompressedSessionInfo;
|
|
76
77
|
get bridgeUrl(): string;
|
|
@@ -84,7 +85,7 @@ export declare class CompressorProxy {
|
|
|
84
85
|
invoke(tool: string, toolInput?: Record<string, unknown>, options?: {
|
|
85
86
|
server?: string;
|
|
86
87
|
}): Promise<string>;
|
|
87
|
-
close(): void
|
|
88
|
+
close(): Promise<void>;
|
|
88
89
|
toExecutableTools(): Record<string, ExecutableTool>;
|
|
89
90
|
writeClient(kind: GeneratedClientKind, outputDir: string, options?: {
|
|
90
91
|
name?: string;
|
package/dist/native_client.js
CHANGED
|
@@ -169,7 +169,7 @@ export function adoptNativeSession(session, build) {
|
|
|
169
169
|
}
|
|
170
170
|
catch (error) {
|
|
171
171
|
try {
|
|
172
|
-
session.close();
|
|
172
|
+
void Promise.resolve(session.close()).catch(() => { });
|
|
173
173
|
}
|
|
174
174
|
catch {
|
|
175
175
|
// Closing a session that never became reachable is best effort.
|
|
@@ -181,6 +181,7 @@ export class CompressorProxy {
|
|
|
181
181
|
session;
|
|
182
182
|
defaultServer;
|
|
183
183
|
closed = false;
|
|
184
|
+
closing = null;
|
|
184
185
|
constructor(session, defaultServer) {
|
|
185
186
|
this.session = session;
|
|
186
187
|
this.defaultServer = defaultServer;
|
|
@@ -254,18 +255,16 @@ export class CompressorProxy {
|
|
|
254
255
|
return (await this.invokeWrapper(wrapper, { tool_name: tool, tool_input: toolInput })).text;
|
|
255
256
|
}
|
|
256
257
|
close() {
|
|
257
|
-
if (this.
|
|
258
|
-
return;
|
|
258
|
+
if (this.closing) {
|
|
259
|
+
return this.closing;
|
|
259
260
|
}
|
|
260
261
|
this.closed = true;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
onClose?.();
|
|
268
|
-
}
|
|
262
|
+
const onClose = proxyCloseCallbacks.get(this);
|
|
263
|
+
proxyCloseCallbacks.delete(this);
|
|
264
|
+
onClose?.();
|
|
265
|
+
const closing = this.session.close();
|
|
266
|
+
this.closing = closing.catch(() => { });
|
|
267
|
+
return closing;
|
|
269
268
|
}
|
|
270
269
|
toExecutableTools() {
|
|
271
270
|
const result = {};
|
|
@@ -394,7 +393,7 @@ export class CompressorClient {
|
|
|
394
393
|
}
|
|
395
394
|
const proxy = this.proxy;
|
|
396
395
|
try {
|
|
397
|
-
proxy?.close();
|
|
396
|
+
await proxy?.close();
|
|
398
397
|
}
|
|
399
398
|
finally {
|
|
400
399
|
if (this.proxy === proxy) {
|
package/dist/rust_core.d.ts
CHANGED
|
@@ -83,9 +83,10 @@ export interface CompressedSessionInfo {
|
|
|
83
83
|
}
|
|
84
84
|
export declare class CompressedSession {
|
|
85
85
|
private readonly nativeSession;
|
|
86
|
+
private closing;
|
|
86
87
|
constructor(nativeSession: NativeCompressedSession);
|
|
87
88
|
info(): CompressedSessionInfo;
|
|
88
|
-
close(): void
|
|
89
|
+
close(): Promise<void>;
|
|
89
90
|
updateAuthProviderHeaders(providerIndex: number, headers: Record<string, string>): void;
|
|
90
91
|
}
|
|
91
92
|
export declare function startCompressedSession(config: CompressedSessionConfig, backends: BackendConfig[]): Promise<CompressedSession>;
|
package/dist/rust_core.js
CHANGED
|
@@ -54,6 +54,7 @@ export function generateClientArtifactFiles(kind, config) {
|
|
|
54
54
|
}
|
|
55
55
|
export class CompressedSession {
|
|
56
56
|
nativeSession;
|
|
57
|
+
closing = null;
|
|
57
58
|
constructor(nativeSession) {
|
|
58
59
|
this.nativeSession = nativeSession;
|
|
59
60
|
}
|
|
@@ -61,7 +62,12 @@ export class CompressedSession {
|
|
|
61
62
|
return JSON.parse(this.nativeSession.infoJson());
|
|
62
63
|
}
|
|
63
64
|
close() {
|
|
64
|
-
this.
|
|
65
|
+
if (this.closing) {
|
|
66
|
+
return this.closing;
|
|
67
|
+
}
|
|
68
|
+
const closing = this.nativeSession.close();
|
|
69
|
+
this.closing = closing.catch(() => { });
|
|
70
|
+
return closing;
|
|
65
71
|
}
|
|
66
72
|
updateAuthProviderHeaders(providerIndex, headers) {
|
|
67
73
|
this.nativeSession.updateAuthProviderHeadersJson(providerIndex, stringify(headers));
|
package/native/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export declare class NativeCompressedSession {
|
|
4
4
|
infoJson(): string
|
|
5
|
-
close(): void
|
|
5
|
+
close(): Promise<void>
|
|
6
6
|
updateAuthProviderHeadersJson(providerIndex: number, headersJson: string): void
|
|
7
7
|
}
|
|
8
8
|
|
|
@@ -36,6 +36,14 @@ export declare function renderCliSubcommandHelpJson(cliName: string, toolJson: s
|
|
|
36
36
|
|
|
37
37
|
export declare function renderCliTopLevelHelpJson(command: string, cliName: string, toolsJson: string): string
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Run the full `mcp-compressor` CLI in-process and return its exit code.
|
|
41
|
+
*
|
|
42
|
+
* Blocks the calling thread until the CLI exits, so the npm `mcp-compressor`
|
|
43
|
+
* bin works without a separately installed Rust binary. Not for library use.
|
|
44
|
+
*/
|
|
45
|
+
export declare function runCliJson(argvJson: string, version?: string | undefined | null): number
|
|
46
|
+
|
|
39
47
|
export declare function startCompressedSessionFromMcpConfigJson(configJson: string, mcpConfigJson: string): Promise<NativeCompressedSession>
|
|
40
48
|
|
|
41
49
|
export declare function startCompressedSessionJson(configJson: string, backendsJson: string): Promise<NativeCompressedSession>
|
|
Binary file
|
|
Binary file
|
package/native/index.js
CHANGED
|
@@ -592,6 +592,7 @@ module.exports.parseToolArgvJson = nativeBinding.parseToolArgvJson
|
|
|
592
592
|
module.exports.rememberOauthBackendJson = nativeBinding.rememberOauthBackendJson
|
|
593
593
|
module.exports.renderCliSubcommandHelpJson = nativeBinding.renderCliSubcommandHelpJson
|
|
594
594
|
module.exports.renderCliTopLevelHelpJson = nativeBinding.renderCliTopLevelHelpJson
|
|
595
|
+
module.exports.runCliJson = nativeBinding.runCliJson
|
|
595
596
|
module.exports.startCompressedSessionFromMcpConfigJson = nativeBinding.startCompressedSessionFromMcpConfigJson
|
|
596
597
|
module.exports.startCompressedSessionJson = nativeBinding.startCompressedSessionJson
|
|
597
598
|
module.exports.startCompressedSessionWithProviderBackendsJson = nativeBinding.startCompressedSessionWithProviderBackendsJson
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlassian/mcp-compressor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"description": "TypeScript MCP server wrapper for reducing tokens consumed by MCP tools.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/atlassian-labs/mcp-compressor",
|