@bkm016/calcite 0.0.0-stage → 0.1.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.
Files changed (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +314 -2
  3. package/THIRD_PARTY_NOTICES.md +44 -0
  4. package/dist/accounts.d.ts +27 -0
  5. package/dist/accounts.js +114 -0
  6. package/dist/accounts.js.map +1 -0
  7. package/dist/cli.d.ts +2 -0
  8. package/dist/cli.js +242 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/client.d.ts +251 -0
  11. package/dist/client.js +671 -0
  12. package/dist/client.js.map +1 -0
  13. package/dist/display.d.ts +23 -0
  14. package/dist/display.js +135 -0
  15. package/dist/display.js.map +1 -0
  16. package/dist/hmc.d.ts +33 -0
  17. package/dist/hmc.js +130 -0
  18. package/dist/hmc.js.map +1 -0
  19. package/dist/index.d.ts +11 -0
  20. package/dist/index.js +8 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/java.d.ts +31 -0
  23. package/dist/java.js +218 -0
  24. package/dist/java.js.map +1 -0
  25. package/dist/lock.d.ts +13 -0
  26. package/dist/lock.js +79 -0
  27. package/dist/lock.js.map +1 -0
  28. package/dist/log.d.ts +13 -0
  29. package/dist/log.js +20 -0
  30. package/dist/log.js.map +1 -0
  31. package/dist/manager.d.ts +15 -0
  32. package/dist/manager.js +65 -0
  33. package/dist/manager.js.map +1 -0
  34. package/dist/mcp.d.ts +13 -0
  35. package/dist/mcp.js +252 -0
  36. package/dist/mcp.js.map +1 -0
  37. package/dist/mojang.d.ts +70 -0
  38. package/dist/mojang.js +109 -0
  39. package/dist/mojang.js.map +1 -0
  40. package/dist/net.d.ts +21 -0
  41. package/dist/net.js +246 -0
  42. package/dist/net.js.map +1 -0
  43. package/dist/options.d.ts +14 -0
  44. package/dist/options.js +50 -0
  45. package/dist/options.js.map +1 -0
  46. package/dist/paths.d.ts +27 -0
  47. package/dist/paths.js +48 -0
  48. package/dist/paths.js.map +1 -0
  49. package/dist/probe-server.d.ts +28 -0
  50. package/dist/probe-server.js +132 -0
  51. package/dist/probe-server.js.map +1 -0
  52. package/dist/version.d.ts +2 -0
  53. package/dist/version.js +11 -0
  54. package/dist/version.js.map +1 -0
  55. package/package.json +57 -4
  56. package/vendor/calcite-probe.jar +0 -0
package/dist/java.js ADDED
@@ -0,0 +1,218 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { mkdir, readdir, rename, rm, stat } from 'node:fs/promises';
4
+ import { delimiter, join } from 'node:path';
5
+ import { promisify } from 'node:util';
6
+ import { withLock } from './lock.js';
7
+ import { logger } from './log.js';
8
+ import { download, httpJson } from './net.js';
9
+ const execFileAsync = promisify(execFile);
10
+ const log = logger('java');
11
+ const EXE = process.platform === 'win32' ? 'java.exe' : 'java';
12
+ /** Parses "java.specification.version = 1.8" / "= 21" from -XshowSettings output. */
13
+ export function parseJavaSettings(output) {
14
+ const spec = /java\.specification\.version = (\S+)/.exec(output);
15
+ const version = /java\.version = (\S+)/.exec(output);
16
+ if (!spec)
17
+ return null;
18
+ const raw = spec[1];
19
+ const major = raw.startsWith('1.') ? Number(raw.slice(2)) : Number(raw);
20
+ if (!Number.isFinite(major))
21
+ return null;
22
+ return { major, version: version ? version[1] : raw };
23
+ }
24
+ async function probeJava(path) {
25
+ try {
26
+ const env = { ...process.env };
27
+ delete env.JAVA_TOOL_OPTIONS;
28
+ delete env._JAVA_OPTIONS;
29
+ const { stdout, stderr } = await execFileAsync(path, ['-XshowSettings:properties', '-version'], { timeout: 20_000, env });
30
+ const parsed = parseJavaSettings(`${stdout}\n${stderr}`);
31
+ return parsed ? { path, ...parsed } : null;
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ async function subdirs(dir) {
38
+ try {
39
+ const entries = await readdir(dir, { withFileTypes: true });
40
+ return entries.filter((e) => e.isDirectory()).map((e) => join(dir, e.name));
41
+ }
42
+ catch {
43
+ return [];
44
+ }
45
+ }
46
+ /** Java homes to look at: env, PATH, well-known install locations and Calcite-managed runtimes. */
47
+ async function candidateExecutables(paths) {
48
+ const homes = [];
49
+ for (const [key, value] of Object.entries(process.env)) {
50
+ if (value && (key === 'JAVA_HOME' || /^JAVA_HOME_\d+/.test(key) || /^CALCITE_JAVA_\d+$/.test(key)))
51
+ homes.push(value);
52
+ }
53
+ const roots = [];
54
+ if (process.platform === 'win32') {
55
+ for (const base of [process.env.ProgramFiles, process.env['ProgramFiles(x86)'], process.env.ProgramW6432]) {
56
+ if (!base)
57
+ continue;
58
+ for (const vendor of ['Java', 'Eclipse Adoptium', 'Eclipse Foundation', 'Microsoft', 'Zulu', 'Amazon Corretto', 'BellSoft', 'Semeru']) {
59
+ roots.push(join(base, vendor));
60
+ }
61
+ }
62
+ if (process.env.LOCALAPPDATA)
63
+ roots.push(join(process.env.LOCALAPPDATA, 'Programs', 'Eclipse Adoptium'));
64
+ }
65
+ else if (process.platform === 'darwin') {
66
+ roots.push('/Library/Java/JavaVirtualMachines', join(process.env.HOME || '', 'Library/Java/JavaVirtualMachines'));
67
+ }
68
+ else {
69
+ roots.push('/usr/lib/jvm', '/usr/java', '/opt/java', '/opt/jdk', join(process.env.HOME || '', '.sdkman/candidates/java'));
70
+ }
71
+ for (const root of roots)
72
+ homes.push(...(await subdirs(root)));
73
+ // runtimes downloaded by Calcite: java/temurin-<major>-<os>-<arch>/<archive root>/
74
+ for (const managed of await subdirs(paths.java))
75
+ homes.push(managed, ...(await subdirs(managed)));
76
+ const exes = new Set();
77
+ for (const home of homes) {
78
+ for (const bin of [join(home, 'bin', EXE), join(home, 'Contents', 'Home', 'bin', EXE)]) {
79
+ if (existsSync(bin))
80
+ exes.add(bin);
81
+ }
82
+ }
83
+ for (const dir of (process.env.PATH || '').split(delimiter)) {
84
+ const bin = join(dir, EXE);
85
+ if (dir && existsSync(bin))
86
+ exes.add(bin);
87
+ }
88
+ return [...exes];
89
+ }
90
+ export async function findJavaInstalls(paths) {
91
+ const results = await Promise.all((await candidateExecutables(paths)).map(probeJava));
92
+ const seen = new Set();
93
+ return results.filter((j) => {
94
+ if (!j)
95
+ return false;
96
+ const key = `${j.major}:${j.version}`;
97
+ if (seen.has(key))
98
+ return false;
99
+ seen.add(key);
100
+ return true;
101
+ });
102
+ }
103
+ /**
104
+ * Picks a runtime for {@code major}: exact major first; Minecraft 1.17+ (Java 16/17/21/25) also runs on newer
105
+ * runtimes, legacy versions (Java 8) need exactly 8.
106
+ */
107
+ export function pickJava(installs, major) {
108
+ const exact = installs.filter((j) => j.major === major);
109
+ if (exact.length)
110
+ return exact[0];
111
+ if (major <= 8)
112
+ return undefined;
113
+ return installs.filter((j) => j.major > major).sort((a, b) => a.major - b.major)[0];
114
+ }
115
+ function adoptiumOs() {
116
+ switch (process.platform) {
117
+ case 'win32':
118
+ return 'windows';
119
+ case 'darwin':
120
+ return 'mac';
121
+ case 'linux':
122
+ return 'linux';
123
+ default:
124
+ throw new Error(`Automatic Java download is not supported on ${process.platform}`);
125
+ }
126
+ }
127
+ function adoptiumArch() {
128
+ switch (process.arch) {
129
+ case 'x64':
130
+ return 'x64';
131
+ case 'arm64':
132
+ return 'aarch64';
133
+ case 'ia32':
134
+ return 'x32';
135
+ default:
136
+ throw new Error(`Automatic Java download is not supported on ${process.arch}`);
137
+ }
138
+ }
139
+ /** Downloads an Eclipse Temurin runtime for {@code major} into CALCITE_HOME/java. */
140
+ export async function downloadJava(paths, major) {
141
+ const os = adoptiumOs();
142
+ const arch = adoptiumArch();
143
+ const target = join(paths.java, `temurin-${major}-${os}-${arch}`);
144
+ return withLock(`${target}.lock`, async () => {
145
+ const existing = await findInDir(target);
146
+ if (existing)
147
+ return existing;
148
+ let asset;
149
+ for (const image of ['jre', 'jdk']) {
150
+ const url = `https://api.adoptium.net/v3/assets/latest/${major}/hotspot?architecture=${arch}&image_type=${image}&os=${os}&vendor=eclipse`;
151
+ const assets = await httpJson(url).catch(() => []);
152
+ asset = assets[0];
153
+ if (asset)
154
+ break;
155
+ }
156
+ if (!asset)
157
+ throw new Error(`No Temurin ${major} build for ${os}/${arch}`);
158
+ const pkg = asset.binary.package;
159
+ log.info(`downloading Temurin ${asset.version.semver} (${pkg.name})`);
160
+ const archive = join(paths.java, pkg.name);
161
+ await download(pkg.link, archive, { sha256: pkg.checksum });
162
+ const staging = `${target}.extract`;
163
+ await rm(staging, { recursive: true, force: true });
164
+ await mkdir(staging, { recursive: true });
165
+ // tar handles .tar.gz everywhere and .zip on Windows 10+ (bsdtar)
166
+ await execFileAsync('tar', ['-xf', archive, '-C', staging], { timeout: 10 * 60_000 });
167
+ await rm(target, { recursive: true, force: true });
168
+ await rename(staging, target);
169
+ await rm(archive, { force: true });
170
+ const installed = await findInDir(target);
171
+ if (!installed)
172
+ throw new Error(`Extracted Java ${major} but found no java executable in ${target}`);
173
+ return installed;
174
+ });
175
+ }
176
+ async function findInDir(dir) {
177
+ try {
178
+ await stat(dir);
179
+ }
180
+ catch {
181
+ return null;
182
+ }
183
+ for (const home of [dir, ...(await subdirs(dir))]) {
184
+ for (const bin of [join(home, 'bin', EXE), join(home, 'Contents', 'Home', 'bin', EXE)]) {
185
+ if (existsSync(bin)) {
186
+ const j = await probeJava(bin);
187
+ if (j)
188
+ return j;
189
+ }
190
+ }
191
+ }
192
+ return null;
193
+ }
194
+ export async function ensureJava(paths, major, opts = {}) {
195
+ if (opts.javaPath) {
196
+ const j = await probeJava(opts.javaPath);
197
+ if (!j)
198
+ throw new Error(`Not a working java executable: ${opts.javaPath}`);
199
+ return j;
200
+ }
201
+ const picked = pickJava(await findJavaInstalls(paths), major);
202
+ if (picked)
203
+ return picked;
204
+ if (opts.allowDownload === false) {
205
+ throw new Error(`Java ${major} is required but not installed (automatic download disabled)`);
206
+ }
207
+ return downloadJava(paths, major);
208
+ }
209
+ /** A runtime for HeadlessMC itself (any Java 8+); prefers the newest installed, downloads Java 21 otherwise. */
210
+ export async function ensureLauncherJava(paths, javaPath) {
211
+ if (javaPath)
212
+ return ensureJava(paths, 8, { javaPath });
213
+ const installs = (await findJavaInstalls(paths)).sort((a, b) => b.major - a.major);
214
+ if (installs.length)
215
+ return installs[0];
216
+ return downloadJava(paths, 21);
217
+ }
218
+ //# sourceMappingURL=java.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"java.js","sourceRoot":"","sources":["../src/java.ts"],"names":[],"mappings":"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"}
package/dist/lock.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ export interface LockOptions {
2
+ /** How long to wait for a busy lock (0 = fail immediately). */
3
+ timeoutMs?: number;
4
+ /** A lock older than this is considered abandoned even if its owner pid is alive (pid reuse). */
5
+ staleMs?: number;
6
+ }
7
+ /**
8
+ * Cross-process lock based on an atomic mkdir. A lock whose owner process is gone (or that is older than
9
+ * {@code staleMs}) is taken over. Returns the release function.
10
+ */
11
+ export declare function acquireLock(dir: string, { timeoutMs, staleMs }?: LockOptions): Promise<() => Promise<void>>;
12
+ /** Runs {@code fn} while holding the lock. */
13
+ export declare function withLock<T>(dir: string, fn: () => Promise<T>, opts?: LockOptions): Promise<T>;
package/dist/lock.js ADDED
@@ -0,0 +1,79 @@
1
+ import { mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
2
+ import { dirname, join } from 'node:path';
3
+ function alive(pid) {
4
+ try {
5
+ process.kill(pid, 0);
6
+ return true;
7
+ }
8
+ catch (err) {
9
+ return err.code === 'EPERM';
10
+ }
11
+ }
12
+ /**
13
+ * Cross-process lock based on an atomic mkdir. A lock whose owner process is gone (or that is older than
14
+ * {@code staleMs}) is taken over. Returns the release function.
15
+ */
16
+ export async function acquireLock(dir, { timeoutMs = 10 * 60_000, staleMs = Infinity } = {}) {
17
+ const deadline = Date.now() + timeoutMs;
18
+ let wait = 50;
19
+ for (;;) {
20
+ try {
21
+ await mkdir(dir);
22
+ await writeFile(join(dir, 'owner'), String(process.pid));
23
+ let released = false;
24
+ return async () => {
25
+ if (released)
26
+ return;
27
+ released = true;
28
+ await rm(dir, { recursive: true, force: true });
29
+ };
30
+ }
31
+ catch (err) {
32
+ const code = err.code;
33
+ if (code === 'ENOENT') {
34
+ await mkdir(dirname(dir), { recursive: true });
35
+ continue;
36
+ }
37
+ if (code !== 'EEXIST')
38
+ throw err;
39
+ }
40
+ let stale = false;
41
+ try {
42
+ const info = await stat(dir);
43
+ let owner = 0;
44
+ try {
45
+ owner = Number(await readFile(join(dir, 'owner'), 'utf8'));
46
+ }
47
+ catch {
48
+ // owner not written yet
49
+ }
50
+ if (owner > 0)
51
+ stale = !alive(owner) || Date.now() - info.mtimeMs > staleMs;
52
+ else
53
+ stale = Date.now() - info.mtimeMs > 10_000;
54
+ }
55
+ catch {
56
+ continue; // lock vanished meanwhile
57
+ }
58
+ if (stale) {
59
+ await rm(dir, { recursive: true, force: true });
60
+ continue;
61
+ }
62
+ if (Date.now() >= deadline) {
63
+ throw new Error(`Lock is held by another process: ${dir}`);
64
+ }
65
+ await new Promise((r) => setTimeout(r, wait));
66
+ wait = Math.min(wait * 2, 1000);
67
+ }
68
+ }
69
+ /** Runs {@code fn} while holding the lock. */
70
+ export async function withLock(dir, fn, opts = {}) {
71
+ const release = await acquireLock(dir, { staleMs: 30 * 60_000, ...opts });
72
+ try {
73
+ return await fn();
74
+ }
75
+ finally {
76
+ await release();
77
+ }
78
+ }
79
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":"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"}
package/dist/log.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Logging. Everything goes to stderr: stdout is reserved for the MCP stdio transport and for CLI output.
3
+ * Level via CALCITE_LOG_LEVEL (debug|info|warn|error|silent), default info.
4
+ */
5
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
6
+ export declare function setLogLevel(next: LogLevel): void;
7
+ export interface Logger {
8
+ debug(message: string): void;
9
+ info(message: string): void;
10
+ warn(message: string): void;
11
+ error(message: string): void;
12
+ }
13
+ export declare function logger(scope: string): Logger;
package/dist/log.js ADDED
@@ -0,0 +1,20 @@
1
+ const ORDER = { debug: 10, info: 20, warn: 30, error: 40, silent: 100 };
2
+ let level = process.env.CALCITE_LOG_LEVEL in ORDER ? process.env.CALCITE_LOG_LEVEL : 'info';
3
+ export function setLogLevel(next) {
4
+ level = next;
5
+ }
6
+ function write(at, scope, message) {
7
+ if (ORDER[at] < ORDER[level])
8
+ return;
9
+ const time = new Date().toISOString().slice(11, 23);
10
+ process.stderr.write(`${time} ${at.toUpperCase().padEnd(5)} [${scope}] ${message}\n`);
11
+ }
12
+ export function logger(scope) {
13
+ return {
14
+ debug: (m) => write('debug', scope, m),
15
+ info: (m) => write('info', scope, m),
16
+ warn: (m) => write('warn', scope, m),
17
+ error: (m) => write('error', scope, m),
18
+ };
19
+ }
20
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAMA,MAAM,KAAK,GAA6B,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAElG,IAAI,KAAK,GAAc,OAAO,CAAC,GAAG,CAAC,iBAA8B,IAAI,KAAK,CAAC,CAAC,CAAE,OAAO,CAAC,GAAG,CAAC,iBAA8B,CAAC,CAAC,CAAC,MAAM,CAAC;AAElI,MAAM,UAAU,WAAW,CAAC,IAAc;IACxC,KAAK,GAAG,IAAI,CAAC;AACf,CAAC;AAED,SAAS,KAAK,CAAC,EAAY,EAAE,KAAa,EAAE,OAAe;IACzD,IAAI,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;QAAE,OAAO;IACrC,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,OAAO,IAAI,CAAC,CAAC;AACxF,CAAC;AASD,MAAM,UAAU,MAAM,CAAC,KAAa;IAClC,OAAO;QACL,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACtC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACpC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACpC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;KACvC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { Client, type ClientOptions, type ClientStatus } from './client.js';
2
+ /** Owns several named clients in one process; stops them all on shutdown. */
3
+ export declare class ClientManager {
4
+ private readonly clients;
5
+ private exitHooked;
6
+ get(name: string): Client;
7
+ /** The only client when exactly one exists, otherwise the named one. */
8
+ resolve(name?: string): Client;
9
+ list(): ClientStatus[];
10
+ /** Creates and starts a client. A stopped/crashed client with the same name is replaced. */
11
+ launch(options: ClientOptions): Promise<Client>;
12
+ stop(name: string): Promise<void>;
13
+ stopAll(): Promise<void>;
14
+ private hookExit;
15
+ }
@@ -0,0 +1,65 @@
1
+ import { Client, CalciteError } from './client.js';
2
+ /** Owns several named clients in one process; stops them all on shutdown. */
3
+ export class ClientManager {
4
+ clients = new Map();
5
+ exitHooked = false;
6
+ get(name) {
7
+ const client = this.clients.get(name);
8
+ if (!client) {
9
+ const known = [...this.clients.keys()];
10
+ throw new CalciteError('unknown_client', `No client named "${name}"${known.length ? ` (running: ${known.join(', ')})` : ''}`);
11
+ }
12
+ return client;
13
+ }
14
+ /** The only client when exactly one exists, otherwise the named one. */
15
+ resolve(name) {
16
+ if (name)
17
+ return this.get(name);
18
+ if (this.clients.size === 1)
19
+ return [...this.clients.values()][0];
20
+ if (this.clients.size === 0)
21
+ throw new CalciteError('no_clients', 'No client is running; launch one first');
22
+ throw new CalciteError('ambiguous_client', `Several clients are running (${[...this.clients.keys()].join(', ')}); pass a name`);
23
+ }
24
+ list() {
25
+ return [...this.clients.values()].map((c) => c.status());
26
+ }
27
+ /** Creates and starts a client. A stopped/crashed client with the same name is replaced. */
28
+ async launch(options) {
29
+ const existing = this.clients.get(options.name);
30
+ if (existing && !['stopped', 'crashed', 'idle'].includes(existing.phase)) {
31
+ throw new CalciteError('already_running', `Client "${options.name}" is already ${existing.phase}`);
32
+ }
33
+ this.hookExit();
34
+ const client = new Client(options);
35
+ this.clients.set(options.name, client);
36
+ try {
37
+ await client.start();
38
+ }
39
+ catch (err) {
40
+ this.clients.delete(options.name);
41
+ throw err;
42
+ }
43
+ return client;
44
+ }
45
+ async stop(name) {
46
+ const client = this.get(name);
47
+ await client.stop();
48
+ this.clients.delete(name);
49
+ }
50
+ async stopAll() {
51
+ await Promise.allSettled([...this.clients.values()].map((c) => c.stop()));
52
+ this.clients.clear();
53
+ }
54
+ hookExit() {
55
+ if (this.exitHooked)
56
+ return;
57
+ this.exitHooked = true;
58
+ const shutdown = (signal) => {
59
+ void this.stopAll().finally(() => process.exit(signal === 'SIGINT' ? 130 : 143));
60
+ };
61
+ process.once('SIGINT', shutdown);
62
+ process.once('SIGTERM', shutdown);
63
+ }
64
+ }
65
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAyC,MAAM,aAAa,CAAC;AAE1F,6EAA6E;AAC7E,MAAM,OAAO,aAAa;IACP,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC7C,UAAU,GAAG,KAAK,CAAC;IAE3B,GAAG,CAAC,IAAY;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YACvC,MAAM,IAAI,YAAY,CAAC,gBAAgB,EAAE,oBAAoB,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChI,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,wEAAwE;IACxE,OAAO,CAAC,IAAa;QACnB,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC;YAAE,MAAM,IAAI,YAAY,CAAC,YAAY,EAAE,wCAAwC,CAAC,CAAC;QAC5G,MAAM,IAAI,YAAY,CAAC,kBAAkB,EAAE,gCAAgC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAClI,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,4FAA4F;IAC5F,KAAK,CAAC,MAAM,CAAC,OAAsB;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,QAAQ,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACzE,MAAM,IAAI,YAAY,CAAC,iBAAiB,EAAE,WAAW,OAAO,CAAC,IAAI,gBAAgB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;QACrG,CAAC;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAY;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9B,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1E,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAEO,QAAQ;QACd,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAC5B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,MAAM,QAAQ,GAAG,CAAC,MAAsB,EAAE,EAAE;YAC1C,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACnF,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;CACF"}
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { type ClientOptions } from './client.js';
3
+ import { ClientManager } from './manager.js';
4
+ export interface McpOptions {
5
+ /** Defaults applied to launch_client calls. */
6
+ defaults?: Partial<ClientOptions>;
7
+ }
8
+ export declare function createMcpServer(opts?: McpOptions): {
9
+ server: McpServer;
10
+ manager: ClientManager;
11
+ };
12
+ /** Runs the MCP server over stdio until the client disconnects. stdout carries only protocol messages. */
13
+ export declare function runMcpStdio(opts?: McpOptions): Promise<void>;