onlymcp 0.9.1 → 0.11.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 +14 -11
- package/dist/apiClient.d.ts +129 -7
- package/dist/apiClient.js +98 -4
- package/dist/apiClient.js.map +1 -1
- package/dist/auth/deviceLogin.js +5 -1
- package/dist/auth/deviceLogin.js.map +1 -1
- package/dist/bin/cli.js +349 -131
- package/dist/bin/cli.js.map +1 -1
- package/dist/bin/mcp.js +16 -2
- package/dist/bin/mcp.js.map +1 -1
- package/dist/export/unpack.d.ts +33 -0
- package/dist/export/unpack.js +54 -0
- package/dist/export/unpack.js.map +1 -0
- package/dist/identity.d.ts +25 -0
- package/dist/identity.js +106 -0
- package/dist/identity.js.map +1 -0
- package/dist/import/collect.d.ts +14 -1
- package/dist/import/collect.js +25 -3
- package/dist/import/collect.js.map +1 -1
- package/dist/import/frontmatter.d.ts +31 -5
- package/dist/import/frontmatter.js +64 -22
- package/dist/import/frontmatter.js.map +1 -1
- package/dist/import/plan.d.ts +22 -1
- package/dist/import/plan.js +66 -19
- package/dist/import/plan.js.map +1 -1
- package/dist/import/prune.d.ts +46 -0
- package/dist/import/prune.js +61 -0
- package/dist/import/prune.js.map +1 -0
- package/dist/import/secrets.js +1 -1
- package/dist/import/secrets.js.map +1 -1
- package/dist/import/upload.js +17 -2
- package/dist/import/upload.js.map +1 -1
- package/dist/install.d.ts +67 -6
- package/dist/install.js +137 -59
- package/dist/install.js.map +1 -1
- package/dist/instructions.d.ts +3 -1
- package/dist/instructions.js +19 -2
- package/dist/instructions.js.map +1 -1
- package/dist/memorySync.d.ts +28 -0
- package/dist/memorySync.js +56 -0
- package/dist/memorySync.js.map +1 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.js +34 -8
- package/dist/paths.js.map +1 -1
- package/dist/registry/caveats.d.ts +17 -0
- package/dist/registry/caveats.js +50 -0
- package/dist/registry/caveats.js.map +1 -0
- package/dist/registry/clients.d.ts +11 -0
- package/dist/registry/clients.js +327 -0
- package/dist/registry/clients.js.map +1 -0
- package/dist/registry/index.d.ts +4 -0
- package/dist/registry/index.js +5 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/servers.d.ts +50 -0
- package/dist/registry/servers.js +225 -0
- package/dist/registry/servers.js.map +1 -0
- package/dist/registry/types.d.ts +54 -0
- package/dist/registry/types.js +6 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/stubs.d.ts +1 -0
- package/dist/stubs.js +85 -13
- package/dist/stubs.js.map +1 -1
- package/dist/tools/getAgentDefinition.js +5 -2
- package/dist/tools/getAgentDefinition.js.map +1 -1
- package/dist/tools/getSkill.js +1 -1
- package/dist/tools/getSkill.js.map +1 -1
- package/dist/tools/getSkillFile.js +3 -3
- package/dist/tools/getSkillFile.js.map +1 -1
- package/dist/tools/memoryGraph.d.ts +69 -0
- package/dist/tools/memoryGraph.js +128 -0
- package/dist/tools/memoryGraph.js.map +1 -0
- package/dist/tools/memoryRead.js +1 -1
- package/dist/tools/memoryRead.js.map +1 -1
- package/dist/tools/memoryWrite.js +1 -1
- package/dist/tools/memoryWrite.js.map +1 -1
- package/package.json +5 -4
package/dist/install.js
CHANGED
|
@@ -1,30 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { CLIENTS } from './registry/index.js';
|
|
4
|
+
/** The npm package that ships both `onlymcp` and `onlymcp-mcp`. */
|
|
3
5
|
export const PACKAGE = 'onlymcp';
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
// `onlymcp-mcp`, das es nicht gibt.
|
|
6
|
+
// Started through npx, never as a bare `onlymcp-mcp` binary name: the home
|
|
7
|
+
// page advertises `npx onlymcp install`, and npx runs a package once without
|
|
8
|
+
// leaving anything on the PATH. A bare `onlymcp-mcp` entry would be written
|
|
9
|
+
// successfully and only fail the next time the client starts, which is the
|
|
10
|
+
// worst moment to find out. `-p onlymcp` is required because the binary
|
|
11
|
+
// name differs from the package name; without it npx looks for a package
|
|
12
|
+
// literally called `onlymcp-mcp`, which does not exist.
|
|
12
13
|
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// mehr anfasst.
|
|
14
|
+
// Deliberately unpinned: the server talks to a cloud API that keeps moving,
|
|
15
|
+
// and must not freeze on a version nobody touches again afterwards.
|
|
16
16
|
const COMMAND = 'npx';
|
|
17
17
|
const ARGS = ['-y', '-p', PACKAGE, 'onlymcp-mcp'];
|
|
18
|
-
// TOML
|
|
19
|
-
//
|
|
20
|
-
// erzeugen, ein Anfuehrungszeichen im Pfad ebenso.
|
|
18
|
+
// TOML basic strings treat a backslash as an escape. A Windows home path
|
|
19
|
+
// would produce a broken file without this, and so would a quote in the path.
|
|
21
20
|
function tomlString(value) {
|
|
22
21
|
return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
23
22
|
}
|
|
24
23
|
function jsonSnippet(env) {
|
|
25
|
-
const server = env
|
|
26
|
-
? { command: COMMAND, args: ARGS, env }
|
|
27
|
-
: { command: COMMAND, args: ARGS };
|
|
24
|
+
const server = env ? { command: COMMAND, args: ARGS, env } : { command: COMMAND, args: ARGS };
|
|
28
25
|
return JSON.stringify({ mcpServers: { onlymcp: server } }, null, 2);
|
|
29
26
|
}
|
|
30
27
|
function tomlSnippet(env) {
|
|
@@ -33,50 +30,131 @@ function tomlSnippet(env) {
|
|
|
33
30
|
`command = ${tomlString(COMMAND)}`,
|
|
34
31
|
`args = [${ARGS.map(tomlString).join(', ')}]`,
|
|
35
32
|
];
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
33
|
+
// An inline table instead of a separate [mcp_servers.onlymcp.env] section:
|
|
34
|
+
// the snippet gets appended to an existing file, and a second section
|
|
35
|
+
// would pull in whatever gets appended after it.
|
|
39
36
|
for (const [k, v] of Object.entries(env ?? {})) {
|
|
40
37
|
lines.push(`env = { ${k} = ${tomlString(v)} }`);
|
|
41
38
|
}
|
|
42
39
|
return `${lines.join('\n')}\n`;
|
|
43
40
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Old CLI spellings, kept so instructions written before the registry
|
|
43
|
+
* existed keep working. `codex` needs no alias: it was always spelled the
|
|
44
|
+
* same as the registry's client id.
|
|
45
|
+
*/
|
|
46
|
+
const ALIASES = { claude: 'claude-code', gemini: 'gemini-cli' };
|
|
47
|
+
function installableClients() {
|
|
48
|
+
return CLIENTS.filter((c) => c.install !== null);
|
|
49
|
+
}
|
|
50
|
+
const INSTALLABLE_IDS = new Set(installableClients().map((c) => c.id));
|
|
51
|
+
/** Resolves an alias or a registry id to a registry id; undefined if neither. */
|
|
52
|
+
export function resolveClientId(id) {
|
|
53
|
+
const aliased = ALIASES[id];
|
|
54
|
+
if (aliased)
|
|
55
|
+
return aliased;
|
|
56
|
+
return INSTALLABLE_IDS.has(id) ? id : undefined;
|
|
57
|
+
}
|
|
58
|
+
function resolveHome(path, home) {
|
|
59
|
+
return path.startsWith('~/') ? join(home, path.slice(2)) : path;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Every client the registry can write a config for, resolved against `home`.
|
|
63
|
+
*
|
|
64
|
+
* `home` is a parameter and not `homedir()` so every test runs against a
|
|
65
|
+
* throwaway directory: the guardrail from spec §13 sits in the type itself,
|
|
66
|
+
* not merely in intent.
|
|
67
|
+
*/
|
|
68
|
+
export function installTargets(home) {
|
|
69
|
+
return installableClients().map((c) => {
|
|
70
|
+
const configPath = resolveHome(c.install.configPath, home);
|
|
71
|
+
const stubDir = c.install.stubDir ? resolveHome(c.install.stubDir, home) : null;
|
|
72
|
+
// `stubDir` is always `<root>/skills` (see paths.ts, `stubDirs()`): the
|
|
73
|
+
// env var the server reads carries the root, because `writeStubs`
|
|
74
|
+
// appends `skills/` itself. Pointing it at the skills dir directly wrote
|
|
75
|
+
// into `<root>/skills/skills`.
|
|
76
|
+
const stubRoot = stubDir ? dirname(stubDir) : null;
|
|
77
|
+
const snippet = c.install.format === 'toml'
|
|
78
|
+
? tomlSnippet(stubRoot ? { ONLYMCP_STUB_DIRS: stubRoot } : undefined)
|
|
79
|
+
: jsonSnippet();
|
|
80
|
+
return { id: c.id, name: c.name, configPath, format: c.install.format, stubDir, stubRoot, snippet };
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Merges one MCP server entry into an existing JSON config, without
|
|
85
|
+
* touching anything else already in the file.
|
|
86
|
+
*
|
|
87
|
+
* `writeFileSync` alone would replace the whole file (e.g. `~/.claude.json`
|
|
88
|
+
* or `~/.gemini/settings.json`), throwing away every other setting stored
|
|
89
|
+
* there. An existing but broken file is never silently overwritten either:
|
|
90
|
+
* better an error than quiet data loss.
|
|
91
|
+
*/
|
|
92
|
+
export function mergeJsonServer(path, key, value) {
|
|
93
|
+
let existing = {};
|
|
94
|
+
if (existsSync(path)) {
|
|
95
|
+
const raw = readFileSync(path, 'utf8').trim();
|
|
96
|
+
if (raw) {
|
|
97
|
+
try {
|
|
98
|
+
existing = JSON.parse(raw);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
throw new Error(`${path} contains invalid JSON. Nothing written.`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const mcpServers = existing.mcpServers ?? {};
|
|
106
|
+
existing.mcpServers = { ...mcpServers, [key]: value };
|
|
107
|
+
writeFileSync(path, `${JSON.stringify(existing, null, 2)}\n`, 'utf8');
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Appends the TOML snippet, unless it is already there.
|
|
111
|
+
*
|
|
112
|
+
* Appended, not replaced: a second run would otherwise add a second
|
|
113
|
+
* `[mcp_servers.onlymcp]` table, and two identical tables make the file
|
|
114
|
+
* invalid for most TOML parsers.
|
|
115
|
+
*/
|
|
116
|
+
export function appendTomlServer(path, snippet) {
|
|
117
|
+
const already = existsSync(path) && readFileSync(path, 'utf8').includes('[mcp_servers.onlymcp]');
|
|
118
|
+
if (already)
|
|
119
|
+
return 'already-present';
|
|
120
|
+
appendFileSync(path, `\n${snippet}`);
|
|
121
|
+
return 'written';
|
|
122
|
+
}
|
|
123
|
+
/** Pure given the filesystem: same inputs, same decision, every time. */
|
|
124
|
+
export function planInstall(home, opts) {
|
|
125
|
+
const targets = installTargets(home);
|
|
126
|
+
if (opts.all) {
|
|
127
|
+
if (opts.client)
|
|
128
|
+
return { kind: 'conflicting-options' };
|
|
129
|
+
const present = targets.filter((t) => existsSync(t.configPath));
|
|
130
|
+
const skipped = targets.filter((t) => !existsSync(t.configPath));
|
|
131
|
+
if (present.length === 0)
|
|
132
|
+
return { kind: 'none-present-for-all', targets };
|
|
133
|
+
return { kind: 'all', present, skipped };
|
|
134
|
+
}
|
|
135
|
+
if (!opts.client)
|
|
136
|
+
return { kind: 'missing-client', targets };
|
|
137
|
+
const id = resolveClientId(opts.client);
|
|
138
|
+
const target = id ? targets.find((x) => x.id === id) : undefined;
|
|
139
|
+
if (!target)
|
|
140
|
+
return { kind: 'unknown-client', targets };
|
|
141
|
+
return { kind: 'single', target };
|
|
142
|
+
}
|
|
143
|
+
/** Writes one target's snippet into its config file, creating directories as needed. */
|
|
144
|
+
export function writeInstallTarget(target) {
|
|
145
|
+
mkdirSync(dirname(target.configPath), { recursive: true });
|
|
146
|
+
const result = target.format === 'toml'
|
|
147
|
+
? appendTomlServer(target.configPath, target.snippet)
|
|
148
|
+
: (() => {
|
|
149
|
+
const parsed = JSON.parse(target.snippet);
|
|
150
|
+
const entry = Object.entries(parsed.mcpServers)[0];
|
|
151
|
+
if (!entry)
|
|
152
|
+
throw new Error(`${target.name}: empty mcpServers snippet.`);
|
|
153
|
+
mergeJsonServer(target.configPath, entry[0], entry[1]);
|
|
154
|
+
return 'written';
|
|
155
|
+
})();
|
|
156
|
+
if (target.stubDir)
|
|
157
|
+
mkdirSync(target.stubDir, { recursive: true });
|
|
158
|
+
return result;
|
|
81
159
|
}
|
|
82
160
|
//# sourceMappingURL=install.js.map
|
package/dist/install.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
|
package/dist/instructions.d.ts
CHANGED
package/dist/instructions.js
CHANGED
|
@@ -16,6 +16,20 @@ const PREAMBLE = [
|
|
|
16
16
|
'skill_write, agent_write and the matching *_delete tools; connection_create',
|
|
17
17
|
'adds another MCP server to this account.',
|
|
18
18
|
].join(' ');
|
|
19
|
+
/**
|
|
20
|
+
* Der BrainVault-Ablauf in drei Saetzen (Spec 7), wortgleich mit dem der
|
|
21
|
+
* gehosteten Oberflaeche (packages/api/src/mcp/instructions.ts). Zwei
|
|
22
|
+
* Fassungen desselben Satzes waeren zwei Gewohnheiten.
|
|
23
|
+
*
|
|
24
|
+
* Je Konto abschaltbar: wer OnlyMCP als reinen Skill-Speicher benutzt, will
|
|
25
|
+
* keinen Ablauf und will die Zeichen fuer Namen zurueck.
|
|
26
|
+
*/
|
|
27
|
+
const BRAINVAULT = [
|
|
28
|
+
'Memory is a vault, not a scratch file: read MEMORY.md first, it is the index.',
|
|
29
|
+
'After finishing a task, write one solutions/sol-*.md for what was not obvious',
|
|
30
|
+
'and one entry in history/YYYY-MM-DD.md. Link related files with [[name]];',
|
|
31
|
+
"memory_links(path) says which of a file's links point nowhere yet.",
|
|
32
|
+
].join(' ');
|
|
19
33
|
function section(label, tool, names, used) {
|
|
20
34
|
if (names.length === 0)
|
|
21
35
|
return '';
|
|
@@ -34,8 +48,11 @@ function section(label, tool, names, used) {
|
|
|
34
48
|
const tail = rest > 0 ? ` (+${rest} more, call ${tool})` : '';
|
|
35
49
|
return `\n\n${label}: ${kept.join(', ')}${tail}`;
|
|
36
50
|
}
|
|
37
|
-
export function buildInstructions(skills, agents) {
|
|
38
|
-
|
|
51
|
+
export function buildInstructions(skills, agents, opts = {}) {
|
|
52
|
+
// Vor den Namenslisten und nach der Anleitung: abgeschnitten wird der
|
|
53
|
+
// Schluss, also steht vorn, was ueberleben muss - und ein halb angekommener
|
|
54
|
+
// Ablauf ist schlimmer als gar keiner.
|
|
55
|
+
let out = opts.brainvault === false ? PREAMBLE : `${PREAMBLE} ${BRAINVAULT}`;
|
|
39
56
|
// Platz fuer die Agents-Zeile zuruecklegen, BEVOR die Skills ihn aufbrauchen.
|
|
40
57
|
// Ohne diese Reserve frisst eine lange Skill-Liste das ganze Budget, die
|
|
41
58
|
// Agents-Zeile wird trotzdem angehaengt, und das Feld ueberschreitet 1800.
|
package/dist/instructions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,sEAAsE;AACtE,0EAA0E;AAC1E,yEAAyE;AACzE,2EAA2E;AAC3E,yEAAyE;AACzE,0EAA0E;AAC1E,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAExC,MAAM,QAAQ,GAAG;IACf,6EAA6E;IAC7E,qEAAqE;IACrE,0DAA0D;IAC1D,8EAA8E;IAC9E,gEAAgE;IAChE,wEAAwE;IACxE,6EAA6E;IAC7E,0CAA0C;CAC3C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,SAAS,OAAO,CAAC,KAAa,EAAE,IAAY,EAAE,KAAe,EAAE,IAAY;IACzE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,eAAe,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;QAClE,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,mBAAmB;YAAE,MAAM;QACpD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,KAAK,UAAU,IAAI,EAAE,CAAC;IAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACxC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,eAAe,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,OAAO,OAAO,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,iBAAiB,
|
|
1
|
+
{"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,sEAAsE;AACtE,0EAA0E;AAC1E,yEAAyE;AACzE,2EAA2E;AAC3E,yEAAyE;AACzE,0EAA0E;AAC1E,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAExC,MAAM,QAAQ,GAAG;IACf,6EAA6E;IAC7E,qEAAqE;IACrE,0DAA0D;IAC1D,8EAA8E;IAC9E,gEAAgE;IAChE,wEAAwE;IACxE,6EAA6E;IAC7E,0CAA0C;CAC3C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG;IACjB,+EAA+E;IAC/E,+EAA+E;IAC/E,2EAA2E;IAC3E,oEAAoE;CACrE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,SAAS,OAAO,CAAC,KAAa,EAAE,IAAY,EAAE,KAAe,EAAE,IAAY;IACzE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,eAAe,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;QAClE,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,mBAAmB;YAAE,MAAM;QACpD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,KAAK,UAAU,IAAI,EAAE,CAAC;IAC3D,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACxC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,eAAe,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,OAAO,OAAO,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAAgB,EAChB,MAAgB,EAChB,OAAiC,EAAE;IAEnC,sEAAsE;IACtE,4EAA4E;IAC5E,uCAAuC;IACvC,IAAI,GAAG,GAAG,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,UAAU,EAAE,CAAC;IAC7E,8EAA8E;IAC9E,yEAAyE;IACzE,2EAA2E;IAC3E,6EAA6E;IAC7E,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,8BAA8B,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,GAAG,IAAI,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;IACtE,GAAG,IAAI,OAAO,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5D,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ApiClient } from './apiClient.js';
|
|
2
|
+
export type MemorySyncResult = {
|
|
3
|
+
written: number;
|
|
4
|
+
/** Paths the server sent that this command refused to turn into a file. */
|
|
5
|
+
refused: string[];
|
|
6
|
+
/** A team file whose path a personal file already took. */
|
|
7
|
+
collisions: string[];
|
|
8
|
+
failures: {
|
|
9
|
+
what: string;
|
|
10
|
+
code: string;
|
|
11
|
+
}[];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Write every memory file this account can read into one directory, folder
|
|
15
|
+
* structure included (package 03 task 12, spec 8.5).
|
|
16
|
+
*
|
|
17
|
+
* Two independent checks stand between a path from the server and a write on
|
|
18
|
+
* the disk, and they are not redundant: `isSafeMemoryPath` is the rule the
|
|
19
|
+
* server enforces on the way in, and the prefix check below is the one that
|
|
20
|
+
* holds even if that rule is ever loosened, if a path arrives from a wrongly
|
|
21
|
+
* configured ONLYMCP_API_URL, or if `resolve` and the regexp disagree about
|
|
22
|
+
* some encoding. Nothing outside `dir` is ever written.
|
|
23
|
+
*
|
|
24
|
+
* Archived rows are included on purpose. The archive is exactly the state in
|
|
25
|
+
* which somebody wants their notes back on their own disk, and spec 8a calls
|
|
26
|
+
* leaving them out a shortcoming, not a feature.
|
|
27
|
+
*/
|
|
28
|
+
export declare function syncMemoryToDisk(api: ApiClient, dir: string): Promise<MemorySyncResult>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, resolve, sep } from 'node:path';
|
|
3
|
+
import { isSafeMemoryPath } from './memoryPath.js';
|
|
4
|
+
/**
|
|
5
|
+
* Write every memory file this account can read into one directory, folder
|
|
6
|
+
* structure included (package 03 task 12, spec 8.5).
|
|
7
|
+
*
|
|
8
|
+
* Two independent checks stand between a path from the server and a write on
|
|
9
|
+
* the disk, and they are not redundant: `isSafeMemoryPath` is the rule the
|
|
10
|
+
* server enforces on the way in, and the prefix check below is the one that
|
|
11
|
+
* holds even if that rule is ever loosened, if a path arrives from a wrongly
|
|
12
|
+
* configured ONLYMCP_API_URL, or if `resolve` and the regexp disagree about
|
|
13
|
+
* some encoding. Nothing outside `dir` is ever written.
|
|
14
|
+
*
|
|
15
|
+
* Archived rows are included on purpose. The archive is exactly the state in
|
|
16
|
+
* which somebody wants their notes back on their own disk, and spec 8a calls
|
|
17
|
+
* leaving them out a shortcoming, not a feature.
|
|
18
|
+
*/
|
|
19
|
+
export async function syncMemoryToDisk(api, dir) {
|
|
20
|
+
const base = resolve(dir);
|
|
21
|
+
await mkdir(base, { recursive: true });
|
|
22
|
+
const result = { written: 0, refused: [], collisions: [], failures: [] };
|
|
23
|
+
const { files } = await api.listMemory();
|
|
24
|
+
// Personal first, so a path claimed by both scopes belongs to the file this
|
|
25
|
+
// account owns. The team file is then reported rather than quietly dropped;
|
|
26
|
+
// a directory per scope is the export's job (task 12a), not this one's.
|
|
27
|
+
const ordered = [...files].sort((a, b) => a.scope === b.scope ? a.path.localeCompare(b.path) : a.scope === 'personal' ? -1 : 1);
|
|
28
|
+
const taken = new Set();
|
|
29
|
+
for (const f of ordered) {
|
|
30
|
+
if (!isSafeMemoryPath(f.path)) {
|
|
31
|
+
result.refused.push(f.path);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const dest = resolve(base, ...f.path.split('/'));
|
|
35
|
+
if (!dest.startsWith(base + sep)) {
|
|
36
|
+
result.refused.push(f.path);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (taken.has(dest)) {
|
|
40
|
+
result.collisions.push(f.path);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const file = await api.readMemory(f.path);
|
|
45
|
+
await mkdir(dirname(dest), { recursive: true });
|
|
46
|
+
await writeFile(dest, file.content, 'utf8');
|
|
47
|
+
taken.add(dest);
|
|
48
|
+
result.written += 1;
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
result.failures.push({ what: f.path, code: e instanceof Error ? e.message : String(e) });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=memorySync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memorySync.js","sourceRoot":"","sources":["../src/memorySync.ts"],"names":[],"mappings":"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"}
|
package/dist/paths.d.ts
CHANGED
|
@@ -1,2 +1,14 @@
|
|
|
1
1
|
export declare function cacheDir(): string;
|
|
2
|
+
/**
|
|
3
|
+
* Die Ordner, in die Stubs geschrieben werden.
|
|
4
|
+
*
|
|
5
|
+
* Zurueck kommt jeweils die WURZEL eines Clients, nicht sein `skills`-Ordner:
|
|
6
|
+
* writeStubs legt darunter `skills/` und `agents/` an, weil beide Scanner
|
|
7
|
+
* nebeneinander stehen. Bis Aufgabe 12 gab ONLYMCP_STUB_DIRS `~/.codex/skills`
|
|
8
|
+
* zurueck und die Stubs landeten in `~/.codex/skills/skills` - also an einer
|
|
9
|
+
* Stelle, die Codex nie liest.
|
|
10
|
+
*
|
|
11
|
+
* Mehrzahl, weil mehrere Clients gleichzeitig auf demselben Geraet laufen
|
|
12
|
+
* koennen und jeder einen anderen Ordner scannt.
|
|
13
|
+
*/
|
|
2
14
|
export declare function stubDirs(): string[];
|
package/dist/paths.js
CHANGED
|
@@ -1,28 +1,54 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
1
2
|
import { homedir } from 'node:os';
|
|
2
3
|
import { join } from 'node:path';
|
|
4
|
+
// ONLYMCP_HOME wird an zwei Stellen unterschiedlich gelesen, und das ist
|
|
5
|
+
// Absicht: hier unten als Ersatz fuer ~/.claude/onlymcp (der eigene Ordner
|
|
6
|
+
// dieses Werkzeugs), in clientHome() als Ersatz fuer das Heimatverzeichnis
|
|
7
|
+
// (so wie install.ts es liest). Ein Test setzt die Variable auf einen
|
|
8
|
+
// Wegwerf-Ordner und trifft damit beides, ohne je ein echtes ~/.claude
|
|
9
|
+
// anzufassen.
|
|
3
10
|
function base() {
|
|
4
11
|
return process.env.ONLYMCP_HOME ?? join(homedir(), '.claude', 'onlymcp');
|
|
5
12
|
}
|
|
13
|
+
function clientHome() {
|
|
14
|
+
return process.env.ONLYMCP_HOME ?? homedir();
|
|
15
|
+
}
|
|
6
16
|
export function cacheDir() {
|
|
7
17
|
return join(base(), 'cache');
|
|
8
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Die Ordner, in die Stubs geschrieben werden.
|
|
21
|
+
*
|
|
22
|
+
* Zurueck kommt jeweils die WURZEL eines Clients, nicht sein `skills`-Ordner:
|
|
23
|
+
* writeStubs legt darunter `skills/` und `agents/` an, weil beide Scanner
|
|
24
|
+
* nebeneinander stehen. Bis Aufgabe 12 gab ONLYMCP_STUB_DIRS `~/.codex/skills`
|
|
25
|
+
* zurueck und die Stubs landeten in `~/.codex/skills/skills` - also an einer
|
|
26
|
+
* Stelle, die Codex nie liest.
|
|
27
|
+
*
|
|
28
|
+
* Mehrzahl, weil mehrere Clients gleichzeitig auf demselben Geraet laufen
|
|
29
|
+
* koennen und jeder einen anderen Ordner scannt.
|
|
30
|
+
*/
|
|
9
31
|
export function stubDirs() {
|
|
10
|
-
// Mehrzahl, weil mehrere Clients gleichzeitig auf demselben Geraet laufen
|
|
11
|
-
// koennen und jeder einen anderen Ordner scannt.
|
|
12
32
|
const dirs = [];
|
|
13
33
|
// Claude Code setzt CLAUDE_PLUGIN_ROOT, wenn es den MCP-Server aus dem
|
|
14
|
-
// Plugin heraus startet.
|
|
15
|
-
//
|
|
34
|
+
// Plugin heraus startet. Dort liegen Stubs an einer Stelle, die der Skill-
|
|
35
|
+
// und Agent-Scanner ohnehin liest.
|
|
16
36
|
if (process.env.CLAUDE_PLUGIN_ROOT)
|
|
17
37
|
dirs.push(process.env.CLAUDE_PLUGIN_ROOT);
|
|
18
|
-
// Alle uebrigen Clients mit eigenem Scanner, gesetzt von `onlymcp install
|
|
19
|
-
//
|
|
20
|
-
//
|
|
38
|
+
// Alle uebrigen Clients mit eigenem Scanner, gesetzt von `onlymcp install`.
|
|
39
|
+
// Mehrere durch Doppelpunkt getrennt wie PATH: ein Client mehr ist ein
|
|
40
|
+
// Eintrag mehr, keine Codeaenderung.
|
|
21
41
|
for (const d of (process.env.ONLYMCP_STUB_DIRS ?? '').split(':')) {
|
|
22
42
|
if (d)
|
|
23
43
|
dirs.push(d);
|
|
24
44
|
}
|
|
25
|
-
//
|
|
45
|
+
// Was ohne jede Konfiguration da ist. Geprueft, nicht angelegt: wer kein
|
|
46
|
+
// Codex installiert hat, soll durch `onlymcp sync` kein ~/.codex bekommen.
|
|
47
|
+
for (const d of [join(clientHome(), '.claude'), join(clientHome(), '.codex')]) {
|
|
48
|
+
if (existsSync(d) && !dirs.includes(d))
|
|
49
|
+
dirs.push(d);
|
|
50
|
+
}
|
|
51
|
+
// Letzter Rueckfall fuer CLI und Tests ohne jeden Client-Kontext.
|
|
26
52
|
return dirs.length > 0 ? dirs : [join(base(), 'plugin')];
|
|
27
53
|
}
|
|
28
54
|
//# sourceMappingURL=paths.js.map
|
package/dist/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,SAAS,IAAI;IACX,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,yEAAyE;AACzE,2EAA2E;AAC3E,2EAA2E;AAC3E,sEAAsE;AACtE,uEAAuE;AACvE,cAAc;AACd,SAAS,IAAI;IACX,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,uEAAuE;IACvE,2EAA2E;IAC3E,mCAAmC;IACnC,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC9E,4EAA4E;IAC5E,uEAAuE;IACvE,qCAAqC;IACrC,KAAK,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACjE,IAAI,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IACD,yEAAyE;IACzE,2EAA2E;IAC3E,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;QAC9E,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,kEAAkE;IAClE,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The caveat sentences, in the four languages the product carries.
|
|
3
|
+
*
|
|
4
|
+
* A caveat is a client fact like the command next to it, and two places state
|
|
5
|
+
* it: the Connect view of the dashboard and the generated client sections of
|
|
6
|
+
* the public documentation (packages/api/src/docs/generated.ts). Each kept its
|
|
7
|
+
* own copy until packages 07 and 09 met, and 17 of the 24 sentences already
|
|
8
|
+
* differed. `ClientRecord.caveats` names an entry by its key.
|
|
9
|
+
*/
|
|
10
|
+
export type CaveatLanguage = 'en' | 'de' | 'fr' | 'it';
|
|
11
|
+
export declare const CAVEATS: Record<string, Record<CaveatLanguage, string>>;
|
|
12
|
+
/**
|
|
13
|
+
* The sentence for one key. An unknown language reads English, and an unknown
|
|
14
|
+
* key comes back as it is, so a typo shows on the first read instead of
|
|
15
|
+
* vanishing.
|
|
16
|
+
*/
|
|
17
|
+
export declare function caveatText(key: string, language: string): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const CAVEATS = {
|
|
2
|
+
'clients.caveat.chatgptDeveloperMode': {
|
|
3
|
+
en: 'Custom MCP connectors live in ChatGPT’s developer mode on the web, and need a paid plan.',
|
|
4
|
+
de: 'Eigene MCP-Connectors gibt es in ChatGPT nur im Entwicklermodus im Web, und sie brauchen ein bezahltes Abo.',
|
|
5
|
+
fr: 'Les connecteurs MCP personnalisés se trouvent dans le mode développeur de ChatGPT sur le web et demandent un abonnement payant.',
|
|
6
|
+
it: 'I connettori MCP personalizzati si trovano nella modalità sviluppatore di ChatGPT sul web e richiedono un piano a pagamento.',
|
|
7
|
+
},
|
|
8
|
+
'clients.caveat.geminiAppSpark': {
|
|
9
|
+
en: 'Custom connectors are limited to Gemini Spark and are not available in every country.',
|
|
10
|
+
de: 'Eigene Connectors gibt es nur für Gemini Spark, und nicht in jedem Land.',
|
|
11
|
+
fr: 'Les connecteurs personnalisés sont réservés à Gemini Spark et ne sont pas disponibles dans tous les pays.',
|
|
12
|
+
it: 'I connettori personalizzati sono riservati a Gemini Spark e non sono disponibili in tutti i paesi.',
|
|
13
|
+
},
|
|
14
|
+
'clients.caveat.claudeHeaderBeta': {
|
|
15
|
+
en: 'Claude connects through OAuth. Static headers exist only in a limited beta.',
|
|
16
|
+
de: 'Claude verbindet sich über OAuth. Feste Header gibt es nur in einer beschränkten Beta.',
|
|
17
|
+
fr: 'Claude se connecte via OAuth. Les en-têtes fixes n’existent que dans une bêta limitée.',
|
|
18
|
+
it: 'Claude si connette tramite OAuth. Gli header statici esistono solo in una beta limitata.',
|
|
19
|
+
},
|
|
20
|
+
'clients.caveat.copilotPolicy': {
|
|
21
|
+
en: 'Business and Enterprise tenants must enable the MCP policy first.',
|
|
22
|
+
de: 'In Business- und Enterprise-Organisationen muss zuerst die MCP-Richtlinie eingeschaltet werden.',
|
|
23
|
+
fr: 'Les organisations Business et Enterprise doivent d’abord activer la stratégie MCP.',
|
|
24
|
+
it: 'Nelle organizzazioni Business ed Enterprise va prima attivata la policy MCP.',
|
|
25
|
+
},
|
|
26
|
+
'clients.caveat.windsurfAllowlist': {
|
|
27
|
+
en: 'An admin allowlist can block servers that are not listed.',
|
|
28
|
+
de: 'Eine Freigabeliste der Administration kann Server sperren, die nicht darauf stehen.',
|
|
29
|
+
fr: 'Une liste d’autorisation définie par un administrateur peut bloquer les serveurs qui n’y figurent pas.',
|
|
30
|
+
it: 'Una lista di autorizzazione dell’amministratore può bloccare i server che non vi compaiono.',
|
|
31
|
+
},
|
|
32
|
+
'clients.caveat.codexTokenEnv': {
|
|
33
|
+
en: 'Codex reads ONLYMCP_TOKEN from the environment every time it starts. Put the export line in your shell profile, not just the current terminal session.',
|
|
34
|
+
de: 'Codex liest ONLYMCP_TOKEN bei jedem Start aus der Umgebung. Schreib die export-Zeile in dein Shell-Profil, nicht nur in die aktuelle Terminal-Sitzung.',
|
|
35
|
+
fr: 'Codex lit ONLYMCP_TOKEN dans l’environnement à chaque démarrage. Mets la ligne export dans le profil de ton shell, pas seulement dans la session de terminal en cours.',
|
|
36
|
+
it: 'Codex legge ONLYMCP_TOKEN dall’ambiente a ogni avvio. Metti la riga export nel profilo della tua shell, non solo nella sessione di terminale attuale.',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* The sentence for one key. An unknown language reads English, and an unknown
|
|
41
|
+
* key comes back as it is, so a typo shows on the first read instead of
|
|
42
|
+
* vanishing.
|
|
43
|
+
*/
|
|
44
|
+
export function caveatText(key, language) {
|
|
45
|
+
const entry = CAVEATS[key];
|
|
46
|
+
if (!entry)
|
|
47
|
+
return key;
|
|
48
|
+
return entry[language.slice(0, 2)] ?? entry.en ?? key;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=caveats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caveats.js","sourceRoot":"","sources":["../../src/registry/caveats.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,OAAO,GAAmD;IACrE,qCAAqC,EAAE;QACrC,EAAE,EAAE,0FAA0F;QAC9F,EAAE,EAAE,6GAA6G;QACjH,EAAE,EAAE,iIAAiI;QACrI,EAAE,EAAE,8HAA8H;KACnI;IACD,+BAA+B,EAAE;QAC/B,EAAE,EAAE,uFAAuF;QAC3F,EAAE,EAAE,0EAA0E;QAC9E,EAAE,EAAE,2GAA2G;QAC/G,EAAE,EAAE,oGAAoG;KACzG;IACD,iCAAiC,EAAE;QACjC,EAAE,EAAE,6EAA6E;QACjF,EAAE,EAAE,wFAAwF;QAC5F,EAAE,EAAE,wFAAwF;QAC5F,EAAE,EAAE,0FAA0F;KAC/F;IACD,8BAA8B,EAAE;QAC9B,EAAE,EAAE,mEAAmE;QACvE,EAAE,EAAE,iGAAiG;QACrG,EAAE,EAAE,oFAAoF;QACxF,EAAE,EAAE,8EAA8E;KACnF;IACD,kCAAkC,EAAE;QAClC,EAAE,EAAE,2DAA2D;QAC/D,EAAE,EAAE,qFAAqF;QACzF,EAAE,EAAE,wGAAwG;QAC5G,EAAE,EAAE,6FAA6F;KAClG;IACD,8BAA8B,EAAE;QAC9B,EAAE,EAAE,wJAAwJ;QAC5J,EAAE,EAAE,wJAAwJ;QAC5J,EAAE,EAAE,wKAAwK;QAC5K,EAAE,EAAE,uJAAuJ;KAC5J;CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,QAAgB;IACtD,MAAM,KAAK,GAAuC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/D,IAAI,CAAC,KAAK;QAAE,OAAO,GAAG,CAAC;IACvB,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,IAAI,GAAG,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ClientId, ClientRecord, RemoteContext, Snippet } from './types.js';
|
|
2
|
+
export declare const CLIENTS: readonly ClientRecord[];
|
|
3
|
+
export declare function clientById(id: ClientId): ClientRecord | undefined;
|
|
4
|
+
export declare function remoteSnippets(id: ClientId, ctx: RemoteContext): Snippet[] | null;
|
|
5
|
+
/**
|
|
6
|
+
* The local-install command for a client `npx onlymcp install` can set up,
|
|
7
|
+
* or null for every other one. Spec 07 §3.4: always with `npx`, always with
|
|
8
|
+
* `--client`, because the CLI without `--client` only lists the targets and
|
|
9
|
+
* exits 2.
|
|
10
|
+
*/
|
|
11
|
+
export declare function installCommand(id: ClientId): string | null;
|