onlymcp 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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -0
  3. package/dist/apiClient.d.ts +55 -0
  4. package/dist/apiClient.js +59 -0
  5. package/dist/apiClient.js.map +1 -0
  6. package/dist/auth/deviceLogin.d.ts +5 -0
  7. package/dist/auth/deviceLogin.js +36 -0
  8. package/dist/auth/deviceLogin.js.map +1 -0
  9. package/dist/auth/keyring.d.ts +5 -0
  10. package/dist/auth/keyring.js +28 -0
  11. package/dist/auth/keyring.js.map +1 -0
  12. package/dist/bin/cli.d.ts +2 -0
  13. package/dist/bin/cli.js +173 -0
  14. package/dist/bin/cli.js.map +1 -0
  15. package/dist/bin/mcp.d.ts +2 -0
  16. package/dist/bin/mcp.js +67 -0
  17. package/dist/bin/mcp.js.map +1 -0
  18. package/dist/cache.d.ts +7 -0
  19. package/dist/cache.js +32 -0
  20. package/dist/cache.js.map +1 -0
  21. package/dist/install.d.ts +12 -0
  22. package/dist/install.js +82 -0
  23. package/dist/install.js.map +1 -0
  24. package/dist/instructions.d.ts +2 -0
  25. package/dist/instructions.js +46 -0
  26. package/dist/instructions.js.map +1 -0
  27. package/dist/memoryPath.d.ts +1 -0
  28. package/dist/memoryPath.js +13 -0
  29. package/dist/memoryPath.js.map +1 -0
  30. package/dist/paths.d.ts +2 -0
  31. package/dist/paths.js +28 -0
  32. package/dist/paths.js.map +1 -0
  33. package/dist/stubs.d.ts +5 -0
  34. package/dist/stubs.js +52 -0
  35. package/dist/stubs.js.map +1 -0
  36. package/dist/tools/getAgentDefinition.d.ts +26 -0
  37. package/dist/tools/getAgentDefinition.js +26 -0
  38. package/dist/tools/getAgentDefinition.js.map +1 -0
  39. package/dist/tools/getSkill.d.ts +26 -0
  40. package/dist/tools/getSkill.js +26 -0
  41. package/dist/tools/getSkill.js.map +1 -0
  42. package/dist/tools/lists.d.ts +38 -0
  43. package/dist/tools/lists.js +39 -0
  44. package/dist/tools/lists.js.map +1 -0
  45. package/dist/tools/memoryRead.d.ts +25 -0
  46. package/dist/tools/memoryRead.js +33 -0
  47. package/dist/tools/memoryRead.js.map +1 -0
  48. package/dist/tools/memoryWrite.d.ts +27 -0
  49. package/dist/tools/memoryWrite.js +32 -0
  50. package/dist/tools/memoryWrite.js.map +1 -0
  51. package/package.json +58 -0
@@ -0,0 +1,82 @@
1
+ import { join } from 'node:path';
2
+ /** Das npm-Paket, das sowohl `onlymcp` als auch `onlymcp-mcp` mitbringt. */
3
+ export const PACKAGE = 'onlymcp';
4
+ // Gestartet wird ueber npx und nicht als blosser Binaername `onlymcp-mcp`.
5
+ // Die Startseite bewirbt `npx onlymcp install`, und npx fuehrt ein Paket
6
+ // einmal aus, ohne irgendetwas auf dem PATH zu hinterlassen. Ein Eintrag mit
7
+ // nacktem `onlymcp-mcp` waere also erfolgreich geschrieben und beim naechsten
8
+ // Start des Clients trotzdem tot - der Fehler faellt genau dann auf, wenn der
9
+ // Nutzer laengst weitergezogen ist. `-p onlymcp` ist dabei Pflicht, weil der
10
+ // Binaername vom Paketnamen abweicht; ohne das sucht npx ein Paket namens
11
+ // `onlymcp-mcp`, das es nicht gibt.
12
+ //
13
+ // Bewusst ohne feste Version: der Server spricht mit einer Cloud-API, die sich
14
+ // weiterbewegt, und darf nicht auf einem Stand einfrieren, den danach niemand
15
+ // mehr anfasst.
16
+ const COMMAND = 'npx';
17
+ const ARGS = ['-y', '-p', PACKAGE, 'onlymcp-mcp'];
18
+ // TOML-Basic-Strings deuten den Rueckwaertsschraegstrich als Escape. Ein
19
+ // Windows-Heimatpfad wuerde ohne diese Behandlung eine kaputte Datei
20
+ // erzeugen, ein Anfuehrungszeichen im Pfad ebenso.
21
+ function tomlString(value) {
22
+ return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
23
+ }
24
+ function jsonSnippet(env) {
25
+ const server = env
26
+ ? { command: COMMAND, args: ARGS, env }
27
+ : { command: COMMAND, args: ARGS };
28
+ return JSON.stringify({ mcpServers: { onlymcp: server } }, null, 2);
29
+ }
30
+ function tomlSnippet(env) {
31
+ const lines = [
32
+ '[mcp_servers.onlymcp]',
33
+ `command = ${tomlString(COMMAND)}`,
34
+ `args = [${ARGS.map(tomlString).join(', ')}]`,
35
+ ];
36
+ // Inline-Tabelle statt eigenem [mcp_servers.onlymcp.env]-Abschnitt: der
37
+ // Schnipsel wird an eine bestehende Datei angehaengt, und ein zweiter
38
+ // Abschnitt wuerde jede spaeter angehaengte Tabelle in ihn hineinziehen.
39
+ for (const [k, v] of Object.entries(env ?? {})) {
40
+ lines.push(`env = { ${k} = ${tomlString(v)} }`);
41
+ }
42
+ return `${lines.join('\n')}\n`;
43
+ }
44
+ // `home` ist ein Parameter und nicht homedir(), damit jeder Test gegen einen
45
+ // Wegwerf-Ordner laeuft. Die Leitplanke aus Spec Abschnitt 13 ist damit im
46
+ // Typ verankert und nicht bloss eine Absicht.
47
+ export function targets(home) {
48
+ // Geprueft an Codex 0.147.0: ~/.codex/skills wird direkt gescannt.
49
+ const codexStubs = join(home, '.codex', 'skills');
50
+ return [
51
+ {
52
+ id: 'claude',
53
+ label: 'Claude Code',
54
+ configPath: join(home, '.claude.json'),
55
+ // Die Stubs setzt bei Claude Code die Plugin-Installation ueber
56
+ // CLAUDE_PLUGIN_ROOT, nicht dieser Befehl.
57
+ stubDir: null,
58
+ snippet: jsonSnippet(),
59
+ },
60
+ {
61
+ id: 'codex',
62
+ label: 'Codex',
63
+ configPath: join(home, '.codex', 'config.toml'),
64
+ stubDir: codexStubs,
65
+ // Ohne ONLYMCP_STUB_DIRS im Eintrag selbst faellt stubDirs() auf
66
+ // ~/.claude/onlymcp/plugin zurueck: die Stubs landen dann an einer
67
+ // Stelle, die Codex nie liest, und ~/.codex/skills bleibt leer. Die
68
+ // Variable gehoert deshalb in die Konfiguration und nicht bloss als
69
+ // Hinweis in die Ausgabe.
70
+ snippet: tomlSnippet({ ONLYMCP_STUB_DIRS: codexStubs }),
71
+ },
72
+ {
73
+ id: 'gemini',
74
+ label: 'Gemini CLI',
75
+ configPath: join(home, '.gemini', 'settings.json'),
76
+ // Kein eigener Skill-Begriff: laeuft ueber instructions und list_skills.
77
+ stubDir: null,
78
+ snippet: jsonSnippet(),
79
+ },
80
+ ];
81
+ }
82
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const INSTRUCTIONS_BUDGET = 1800;
2
+ export declare function buildInstructions(skills: string[], agents: string[]): string;
@@ -0,0 +1,46 @@
1
+ // Harte Grenze aus dem Spike vom 21.08.2026 (Memory
2
+ // sol-mcp-instructions-cloud-skills-spike): Claude Code schneidet das
3
+ // instructions-Feld bei rund 2000 Zeichen STUMM ab, ohne Warnung und ohne
4
+ // Fehler. 1800 ist der Sicherheitsabstand. Codex zeigt das Feld nicht im
5
+ // Kontext, nutzt es aber, und seine Doku verlangt selbsttragende erste 512
6
+ // Zeichen. Beides zusammen ergibt: Anleitung nach vorn, Namensliste nach
7
+ // hinten. Wird abgeschnitten, geht die Liste verloren, nie die Anleitung.
8
+ export const INSTRUCTIONS_BUDGET = 1800;
9
+ const PREAMBLE = [
10
+ "OnlyMCP holds this user's skills, agents and memory in the cloud, identical",
11
+ 'on every machine. The names below are names only, not content: call',
12
+ 'get_skill(name) to load a skill before following it, and',
13
+ 'get_agent_definition(name) for an agent. Call list_skills or list_agents for',
14
+ 'anything not named here. Memory is live: memory_read(path) and',
15
+ 'memory_write(path, content).',
16
+ ].join(' ');
17
+ function section(label, tool, names, used) {
18
+ if (names.length === 0)
19
+ return '';
20
+ const kept = [];
21
+ for (const name of names) {
22
+ const rest = names.length - kept.length - 1;
23
+ const tail = rest > 0 ? ` (+${rest} more, call ${tool})` : '';
24
+ const line = `\n\n${label}: ${[...kept, name].join(', ')}${tail}`;
25
+ if (used + line.length > INSTRUCTIONS_BUDGET)
26
+ break;
27
+ kept.push(name);
28
+ }
29
+ if (kept.length === 0)
30
+ return `\n\n${label}: call ${tool}`;
31
+ const rest = names.length - kept.length;
32
+ const tail = rest > 0 ? ` (+${rest} more, call ${tool})` : '';
33
+ return `\n\n${label}: ${kept.join(', ')}${tail}`;
34
+ }
35
+ export function buildInstructions(skills, agents) {
36
+ let out = PREAMBLE;
37
+ // Platz fuer die Agents-Zeile zuruecklegen, BEVOR die Skills ihn aufbrauchen.
38
+ // Ohne diese Reserve frisst eine lange Skill-Liste das ganze Budget, die
39
+ // Agents-Zeile wird trotzdem angehaengt, und das Feld ueberschreitet 1800.
40
+ // Beim Nachrechnen mit je 400 Namen waren es 1817 Zeichen, mit Reserve 1800.
41
+ const reserve = agents.length > 0 ? '\n\nAgents: call list_agents'.length : 0;
42
+ out += section('Skills', 'list_skills', skills, out.length + reserve);
43
+ out += section('Agents', 'list_agents', agents, out.length);
44
+ return out;
45
+ }
46
+ //# sourceMappingURL=instructions.js.map
@@ -0,0 +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,8BAA8B;CAC/B,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,CAAC,MAAgB,EAAE,MAAgB;IAClE,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,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 @@
1
+ export declare function isSafeMemoryPath(path: string): boolean;
@@ -0,0 +1,13 @@
1
+ // Client-seitige Kopie der Server-Regel (packages/api/src/http/names.ts,
2
+ // memoryPath). Ohne diese Pruefung baut apiClient.ts den Pfad nur segmentweise
3
+ // per encodeURIComponent zusammen, und encodeURIComponent laesst ".." als
4
+ // literale zwei Punkte durch. Bei einem falsch konfigurierten oder
5
+ // kompromittierten ONLYMCP_API_URL koennte ein Traversal-Segment so bis zur
6
+ // Anfrage durchrutschen, bevor der Server ihn (server-seitig, aber eben erst
7
+ // dort) ablehnt. Client und Server pruefen deshalb beide, unabhaengig
8
+ // voneinander.
9
+ const MEMORY_PATH = /^[a-z0-9][a-z0-9._-]*(\/[a-z0-9][a-z0-9._-]*)*\.md$/i;
10
+ export function isSafeMemoryPath(path) {
11
+ return MEMORY_PATH.test(path) && !path.split('/').includes('..');
12
+ }
13
+ //# sourceMappingURL=memoryPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoryPath.js","sourceRoot":"","sources":["../src/memoryPath.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,+EAA+E;AAC/E,0EAA0E;AAC1E,mEAAmE;AACnE,4EAA4E;AAC5E,6EAA6E;AAC7E,sEAAsE;AACtE,eAAe;AACf,MAAM,WAAW,GAAG,sDAAsD,CAAC;AAE3E,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function cacheDir(): string;
2
+ export declare function stubDirs(): string[];
package/dist/paths.js ADDED
@@ -0,0 +1,28 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ function base() {
4
+ return process.env.ONLYMCP_HOME ?? join(homedir(), '.claude', 'onlymcp');
5
+ }
6
+ export function cacheDir() {
7
+ return join(base(), 'cache');
8
+ }
9
+ export function stubDirs() {
10
+ // Mehrzahl, weil mehrere Clients gleichzeitig auf demselben Geraet laufen
11
+ // koennen und jeder einen anderen Ordner scannt.
12
+ const dirs = [];
13
+ // Claude Code setzt CLAUDE_PLUGIN_ROOT, wenn es den MCP-Server aus dem
14
+ // Plugin heraus startet. Nur dort liegen Stubs an einer Stelle, die der
15
+ // Skill- und Agent-Scanner ueberhaupt liest.
16
+ if (process.env.CLAUDE_PLUGIN_ROOT)
17
+ dirs.push(process.env.CLAUDE_PLUGIN_ROOT);
18
+ // Alle uebrigen Clients mit eigenem Scanner, gesetzt von `onlymcp install`
19
+ // (heute Codex mit ~/.codex/skills). Mehrere durch Doppelpunkt getrennt wie
20
+ // PATH: ein Client mehr ist ein Eintrag mehr, keine Codeaenderung.
21
+ for (const d of (process.env.ONLYMCP_STUB_DIRS ?? '').split(':')) {
22
+ if (d)
23
+ dirs.push(d);
24
+ }
25
+ // Rueckfall fuer CLI und Tests ohne jeden Client-Kontext.
26
+ return dirs.length > 0 ? dirs : [join(base(), 'plugin')];
27
+ }
28
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +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,0EAA0E;IAC1E,iDAAiD;IACjD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,uEAAuE;IACvE,wEAAwE;IACxE,6CAA6C;IAC7C,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC9E,2EAA2E;IAC3E,4EAA4E;IAC5E,mEAAmE;IACnE,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,0DAA0D;IAC1D,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,5 @@
1
+ import type { ApiClient } from './apiClient.js';
2
+ export declare function writeStubs(api: ApiClient, dir: string): Promise<{
3
+ skills: number;
4
+ agents: number;
5
+ }>;
package/dist/stubs.js ADDED
@@ -0,0 +1,52 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ // Gleiche Positivliste wie server-seitig (packages/api/src/http/names.ts,
4
+ // skillName/agentName). Dieses Paket haengt nicht von @onlymcp/api ab, also
5
+ // keine gemeinsame Konstante, aber ein Name, der so nie in der Datenbank
6
+ // entstehen sollte, darf trotzdem nie als Pfadsegment landen: ein falsch
7
+ // konfiguriertes oder kompromittiertes ONLYMCP_API_URL soll niemals Dateien
8
+ // ausserhalb von `dir` schreiben koennen, egal was der Server zurueckgibt.
9
+ const SAFE_NAME = /^[a-z0-9]+(-[a-z0-9]+)*$/;
10
+ // Frontmatter ist YAML, aber die Werte (description, model, jeder Tool-Name)
11
+ // kommen ungeprueft vom Server. Ein Wert mit Zeilenumbruch koennte sonst aus
12
+ // seiner eigenen Zeile ausbrechen und zusaetzliche Frontmatter-Felder
13
+ // einschleusen (z.B. ein erfundenes weiteres `tools:`). Zeilenumbrueche
14
+ // werden deshalb entfernt, nicht escaped: ein Skill-/Agent-Name oder eine
15
+ // Beschreibung braucht nie einen Zeilenumbruch, um sinnvoll zu sein.
16
+ function yamlSafe(value) {
17
+ return value.replace(/[\r\n]+/g, ' ').trim();
18
+ }
19
+ export async function writeStubs(api, dir) {
20
+ const [{ skills }, { agents }] = await Promise.all([api.listSkills(), api.listAgents()]);
21
+ for (const s of skills) {
22
+ if (!SAFE_NAME.test(s.name))
23
+ continue;
24
+ const target = join(dir, 'skills', s.name);
25
+ await mkdir(target, { recursive: true });
26
+ await writeFile(join(target, 'SKILL.md'), `---
27
+ name: ${s.name}
28
+ description: Synchronisiert ueber OnlyMCP. Inhalt wird bei Bedarf geladen.
29
+ ---
30
+
31
+ Rufe \`get_skill({ name: "${s.name}" })\` am OnlyMCP-Server auf und befolge, was zurueckkommt.
32
+ `, 'utf8');
33
+ }
34
+ await mkdir(join(dir, 'agents'), { recursive: true });
35
+ for (const a of agents) {
36
+ if (!SAFE_NAME.test(a.name))
37
+ continue;
38
+ const description = yamlSafe(a.description);
39
+ const model = a.model ? yamlSafe(a.model) : '';
40
+ const tools = a.tools.map(yamlSafe).join(', ');
41
+ await writeFile(join(dir, 'agents', `${a.name}.md`), `---
42
+ name: ${a.name}
43
+ description: ${description}
44
+ ${model ? `model: ${model}\n` : ''}tools: ${tools}
45
+ ---
46
+
47
+ Rufe \`get_agent_definition({ name: "${a.name}" })\` am OnlyMCP-Server auf und befolge, was zurueckkommt.
48
+ `, 'utf8');
49
+ }
50
+ return { skills: skills.length, agents: agents.length };
51
+ }
52
+ //# sourceMappingURL=stubs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stubs.js","sourceRoot":"","sources":["../src/stubs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,0EAA0E;AAC1E,4EAA4E;AAC5E,yEAAyE;AACzE,yEAAyE;AACzE,4EAA4E;AAC5E,2EAA2E;AAC3E,MAAM,SAAS,GAAG,0BAA0B,CAAC;AAE7C,6EAA6E;AAC7E,6EAA6E;AAC7E,sEAAsE;AACtE,wEAAwE;AACxE,0EAA0E;AAC1E,qEAAqE;AACrE,SAAS,QAAQ,CAAC,KAAa;IAC7B,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAc,EAAE,GAAW;IAC1D,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAEzF,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,SAAS;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,SAAS,CACb,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EACxB;QACE,CAAC,CAAC,IAAI;;;;4BAIc,CAAC,CAAC,IAAI;CACjC,EACK,MAAM,CACP,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,SAAS;QACtC,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,SAAS,CACb,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,EACnC;QACE,CAAC,CAAC,IAAI;eACC,WAAW;EACxB,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,KAAK;;;uCAGV,CAAC,CAAC,IAAI;CAC5C,EACK,MAAM,CACP,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ import type { ApiClient } from '../apiClient.js';
3
+ import type { TtlCache } from '../cache.js';
4
+ export declare const GetAgentInput: z.ZodObject<{
5
+ name: z.ZodString;
6
+ }, z.core.$strip>;
7
+ export declare function createGetAgentDefinitionTool(api: ApiClient, cache: TtlCache): {
8
+ name: string;
9
+ description: string;
10
+ inputSchema: z.ZodObject<{
11
+ name: z.ZodString;
12
+ }, z.core.$strip>;
13
+ handler(args: z.infer<typeof GetAgentInput>): Promise<{
14
+ content: {
15
+ type: "text";
16
+ text: string;
17
+ }[];
18
+ isError?: undefined;
19
+ } | {
20
+ content: {
21
+ type: "text";
22
+ text: string;
23
+ }[];
24
+ isError: boolean;
25
+ }>;
26
+ };
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ import { ApiError } from '../apiClient.js';
3
+ export const GetAgentInput = z.object({ name: z.string().min(1).max(64) });
4
+ export function createGetAgentDefinitionTool(api, cache) {
5
+ return {
6
+ name: 'get_agent_definition',
7
+ description: 'Liefert den System-Prompt eines Agenten aus der OnlyMCP-Cloud.',
8
+ inputSchema: GetAgentInput,
9
+ async handler(args) {
10
+ const key = `agent:${args.name}`;
11
+ const cached = await cache.get(key);
12
+ if (cached !== null)
13
+ return { content: [{ type: 'text', text: cached }] };
14
+ try {
15
+ const a = await api.getAgent(args.name);
16
+ await cache.set(key, a.body);
17
+ return { content: [{ type: 'text', text: a.body }] };
18
+ }
19
+ catch (e) {
20
+ const code = e instanceof ApiError ? e.code : 'errors.UNKNOWN';
21
+ return { content: [{ type: 'text', text: code }], isError: true };
22
+ }
23
+ },
24
+ };
25
+ }
26
+ //# sourceMappingURL=getAgentDefinition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getAgentDefinition.js","sourceRoot":"","sources":["../../src/tools/getAgentDefinition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG3C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAE3E,MAAM,UAAU,4BAA4B,CAAC,GAAc,EAAE,KAAe;IAC1E,OAAO;QACL,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,gEAAgE;QAC7E,WAAW,EAAE,aAAa;QAC1B,KAAK,CAAC,OAAO,CAAC,IAAmC;YAC/C,MAAM,GAAG,GAAG,SAAS,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;YACnF,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxC,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC7B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAChE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,IAAI,GAAG,CAAC,YAAY,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;gBAC/D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC7E,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ import type { ApiClient } from '../apiClient.js';
3
+ import type { TtlCache } from '../cache.js';
4
+ export declare const GetSkillInput: z.ZodObject<{
5
+ name: z.ZodString;
6
+ }, z.core.$strip>;
7
+ export declare function createGetSkillTool(api: ApiClient, cache: TtlCache): {
8
+ name: string;
9
+ description: string;
10
+ inputSchema: z.ZodObject<{
11
+ name: z.ZodString;
12
+ }, z.core.$strip>;
13
+ handler(args: z.infer<typeof GetSkillInput>): Promise<{
14
+ content: {
15
+ type: "text";
16
+ text: string;
17
+ }[];
18
+ isError?: undefined;
19
+ } | {
20
+ content: {
21
+ type: "text";
22
+ text: string;
23
+ }[];
24
+ isError: boolean;
25
+ }>;
26
+ };
@@ -0,0 +1,26 @@
1
+ import { z } from 'zod';
2
+ import { ApiError } from '../apiClient.js';
3
+ export const GetSkillInput = z.object({ name: z.string().min(1).max(64) });
4
+ export function createGetSkillTool(api, cache) {
5
+ return {
6
+ name: 'get_skill',
7
+ description: 'Liefert den vollstaendigen Inhalt eines Skills aus der OnlyMCP-Cloud. Wird von den Stub-Dateien aufgerufen.',
8
+ inputSchema: GetSkillInput,
9
+ async handler(args) {
10
+ const key = `skill:${args.name}`;
11
+ const cached = await cache.get(key);
12
+ if (cached !== null)
13
+ return { content: [{ type: 'text', text: cached }] };
14
+ try {
15
+ const skill = await api.getSkill(args.name);
16
+ await cache.set(key, skill.body);
17
+ return { content: [{ type: 'text', text: skill.body }] };
18
+ }
19
+ catch (e) {
20
+ const code = e instanceof ApiError ? e.code : 'errors.UNKNOWN';
21
+ return { content: [{ type: 'text', text: code }], isError: true };
22
+ }
23
+ },
24
+ };
25
+ }
26
+ //# sourceMappingURL=getSkill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSkill.js","sourceRoot":"","sources":["../../src/tools/getSkill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG3C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AAE3E,MAAM,UAAU,kBAAkB,CAAC,GAAc,EAAE,KAAe;IAChE,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,WAAW,EACT,6GAA6G;QAC/G,WAAW,EAAE,aAAa;QAC1B,KAAK,CAAC,OAAO,CAAC,IAAmC;YAC/C,MAAM,GAAG,GAAG,SAAS,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;YACnF,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5C,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACjC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YACpE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,IAAI,GAAG,CAAC,YAAY,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;gBAC/D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC7E,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ import type { ApiClient } from '../apiClient.js';
3
+ export declare function createListSkillsTool(api: ApiClient): {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: z.ZodObject<{}, z.core.$strip>;
7
+ handler(): Promise<{
8
+ content: {
9
+ type: "text";
10
+ text: string;
11
+ }[];
12
+ isError?: undefined;
13
+ } | {
14
+ content: {
15
+ type: "text";
16
+ text: string;
17
+ }[];
18
+ isError: boolean;
19
+ }>;
20
+ };
21
+ export declare function createListAgentsTool(api: ApiClient): {
22
+ name: string;
23
+ description: string;
24
+ inputSchema: z.ZodObject<{}, z.core.$strip>;
25
+ handler(): Promise<{
26
+ content: {
27
+ type: "text";
28
+ text: string;
29
+ }[];
30
+ isError?: undefined;
31
+ } | {
32
+ content: {
33
+ type: "text";
34
+ text: string;
35
+ }[];
36
+ isError: boolean;
37
+ }>;
38
+ };
@@ -0,0 +1,39 @@
1
+ import { z } from 'zod';
2
+ import { ApiError } from '../apiClient.js';
3
+ const empty = z.object({});
4
+ export function createListSkillsTool(api) {
5
+ return {
6
+ name: 'list_skills',
7
+ description: 'List every skill name available to this user. Use when a skill you need is not named in the server instructions.',
8
+ inputSchema: empty,
9
+ async handler() {
10
+ try {
11
+ const { skills } = await api.listSkills();
12
+ return { content: [{ type: 'text', text: skills.map((s) => s.name).join('\n') }] };
13
+ }
14
+ catch (e) {
15
+ const code = e instanceof ApiError ? e.code : 'errors.UNKNOWN';
16
+ return { content: [{ type: 'text', text: code }], isError: true };
17
+ }
18
+ },
19
+ };
20
+ }
21
+ export function createListAgentsTool(api) {
22
+ return {
23
+ name: 'list_agents',
24
+ description: 'List every agent available to this user, with its description. Use when this client has no agent files of its own.',
25
+ inputSchema: empty,
26
+ async handler() {
27
+ try {
28
+ const { agents } = await api.listAgents();
29
+ const text = agents.map((a) => `${a.name}: ${a.description}`).join('\n');
30
+ return { content: [{ type: 'text', text }] };
31
+ }
32
+ catch (e) {
33
+ const code = e instanceof ApiError ? e.code : 'errors.UNKNOWN';
34
+ return { content: [{ type: 'text', text: code }], isError: true };
35
+ }
36
+ },
37
+ };
38
+ }
39
+ //# sourceMappingURL=lists.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lists.js","sourceRoot":"","sources":["../../src/tools/lists.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE3B,MAAM,UAAU,oBAAoB,CAAC,GAAc;IACjD,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,kHAAkH;QACpH,WAAW,EAAE,KAAK;QAClB,KAAK,CAAC,OAAO;YACX,IAAI,CAAC;gBACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC;gBAC1C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC9F,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,IAAI,GAAG,CAAC,YAAY,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;gBAC/D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC7E,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAc;IACjD,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,WAAW,EACT,oHAAoH;QACtH,WAAW,EAAE,KAAK;QAClB,KAAK,CAAC,OAAO;YACX,IAAI,CAAC;gBACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,UAAU,EAAE,CAAC;gBAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACxD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,IAAI,GAAG,CAAC,YAAY,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;gBAC/D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC7E,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod';
2
+ import type { ApiClient } from '../apiClient.js';
3
+ export declare const MemoryReadInput: z.ZodObject<{
4
+ path: z.ZodString;
5
+ }, z.core.$strip>;
6
+ export declare function createMemoryReadTool(api: ApiClient): {
7
+ name: string;
8
+ description: string;
9
+ inputSchema: z.ZodObject<{
10
+ path: z.ZodString;
11
+ }, z.core.$strip>;
12
+ handler(args: z.infer<typeof MemoryReadInput>): Promise<{
13
+ content: {
14
+ type: "text";
15
+ text: string;
16
+ }[];
17
+ isError: boolean;
18
+ } | {
19
+ content: {
20
+ type: "text";
21
+ text: string;
22
+ }[];
23
+ isError?: undefined;
24
+ }>;
25
+ };
@@ -0,0 +1,33 @@
1
+ import { z } from 'zod';
2
+ import { ApiError } from '../apiClient.js';
3
+ import { isSafeMemoryPath } from '../memoryPath.js';
4
+ export const MemoryReadInput = z.object({ path: z.string().min(3).max(256) });
5
+ export function createMemoryReadTool(api) {
6
+ const inFlight = new Map();
7
+ return {
8
+ name: 'memory_read',
9
+ description: 'Liest eine Memory-Datei live aus der OnlyMCP-Cloud. Kein Diskcache.',
10
+ inputSchema: MemoryReadInput,
11
+ async handler(args) {
12
+ if (!isSafeMemoryPath(args.path)) {
13
+ return { content: [{ type: 'text', text: 'errors.INVALID_PATH' }], isError: true };
14
+ }
15
+ try {
16
+ // Nur exakt gleichzeitige Wiederholungen teilen sich eine Anfrage.
17
+ // Kein Zeit-Cache: nach dem Aufloesen ist der Eintrag weg.
18
+ let p = inFlight.get(args.path);
19
+ if (!p) {
20
+ p = api.readMemory(args.path).then((f) => f.content);
21
+ inFlight.set(args.path, p);
22
+ p.finally(() => inFlight.delete(args.path));
23
+ }
24
+ return { content: [{ type: 'text', text: await p }] };
25
+ }
26
+ catch (e) {
27
+ const code = e instanceof ApiError ? e.code : 'errors.UNKNOWN';
28
+ return { content: [{ type: 'text', text: code }], isError: true };
29
+ }
30
+ },
31
+ };
32
+ }
33
+ //# sourceMappingURL=memoryRead.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoryRead.js","sourceRoot":"","sources":["../../src/tools/memoryRead.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAE9E,MAAM,UAAU,oBAAoB,CAAC,GAAc;IACjD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEpD,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,qEAAqE;QAClF,WAAW,EAAE,eAAe;QAC5B,KAAK,CAAC,OAAO,CAAC,IAAqC;YACjD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC9F,CAAC;YACD,IAAI,CAAC;gBACH,mEAAmE;gBACnE,2DAA2D;gBAC3D,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChC,IAAI,CAAC,CAAC,EAAE,CAAC;oBACP,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;oBACrD,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;oBAC3B,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC9C,CAAC;gBACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YACjE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,IAAI,GAAG,CAAC,YAAY,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;gBAC/D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC7E,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { z } from 'zod';
2
+ import type { ApiClient } from '../apiClient.js';
3
+ export declare const MemoryWriteInput: z.ZodObject<{
4
+ path: z.ZodString;
5
+ content: z.ZodString;
6
+ }, z.core.$strip>;
7
+ export declare function createMemoryWriteTool(api: ApiClient): {
8
+ name: string;
9
+ description: string;
10
+ inputSchema: z.ZodObject<{
11
+ path: z.ZodString;
12
+ content: z.ZodString;
13
+ }, z.core.$strip>;
14
+ handler(args: z.infer<typeof MemoryWriteInput>): Promise<{
15
+ content: {
16
+ type: "text";
17
+ text: string;
18
+ }[];
19
+ isError: boolean;
20
+ } | {
21
+ content: {
22
+ type: "text";
23
+ text: string;
24
+ }[];
25
+ isError?: undefined;
26
+ }>;
27
+ };
@@ -0,0 +1,32 @@
1
+ import { hostname } from 'node:os';
2
+ import { z } from 'zod';
3
+ import { ApiError } from '../apiClient.js';
4
+ import { isSafeMemoryPath } from '../memoryPath.js';
5
+ export const MemoryWriteInput = z.object({
6
+ path: z.string().min(3).max(256),
7
+ content: z.string().max(1_000_000),
8
+ });
9
+ export function createMemoryWriteTool(api) {
10
+ return {
11
+ name: 'memory_write',
12
+ description: 'Schreibt eine Memory-Datei live in die OnlyMCP-Cloud (write-through).',
13
+ inputSchema: MemoryWriteInput,
14
+ async handler(args) {
15
+ if (!isSafeMemoryPath(args.path)) {
16
+ return { content: [{ type: 'text', text: 'errors.INVALID_PATH' }], isError: true };
17
+ }
18
+ try {
19
+ const res = await api.writeMemory(args.path, args.content, hostname());
20
+ const text = res.warning
21
+ ? `${res.path} ${res.updatedAt} ${res.warning.code} ${JSON.stringify(res.warning.params)}`
22
+ : `${res.path} ${res.updatedAt}`;
23
+ return { content: [{ type: 'text', text }] };
24
+ }
25
+ catch (e) {
26
+ const code = e instanceof ApiError ? e.code : 'errors.UNKNOWN';
27
+ return { content: [{ type: 'text', text: code }], isError: true };
28
+ }
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=memoryWrite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoryWrite.js","sourceRoot":"","sources":["../../src/tools/memoryWrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IAChC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC;CACnC,CAAC,CAAC;AAEH,MAAM,UAAU,qBAAqB,CAAC,GAAc;IAClD,OAAO;QACL,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,uEAAuE;QACpF,WAAW,EAAE,gBAAgB;QAC7B,KAAK,CAAC,OAAO,CAAC,IAAsC;YAClD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC9F,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACvE,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO;oBACtB,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;oBAC1F,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;gBACnC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACxD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,IAAI,GAAG,CAAC,YAAY,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;gBAC/D,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC7E,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}