heyhank 0.1.0 → 0.2.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 (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -10
  3. package/bin/cli.ts +7 -7
  4. package/bin/ctl.ts +42 -42
  5. package/dist/assets/{AgentsPage-BPhirnCe.js → AgentsPage-B-AAmsMK.js} +3 -3
  6. package/dist/assets/AssistantPage-BV1Mfwdt.js +2 -0
  7. package/dist/assets/BusinessPage-tLpNEz19.js +1 -0
  8. package/dist/assets/{CronManager-DDbz-yiT.js → CronManager-B-K_n3Jg.js} +1 -1
  9. package/dist/assets/HelpPage-Bhf_j6Xr.js +1 -0
  10. package/dist/assets/{IntegrationsPage-CrOitCmJ.js → IntegrationsPage-DAMjs9tM.js} +1 -1
  11. package/dist/assets/JarvisHUD-C_TGXCCn.js +120 -0
  12. package/dist/assets/MediaPage-C48HTTrt.js +1 -0
  13. package/dist/assets/MemoryPage-JkC-qtgp.js +1 -0
  14. package/dist/assets/{PlatformDashboard-Do6F0O2p.js → PlatformDashboard-AUo7tNnE.js} +1 -1
  15. package/dist/assets/{Playground-Fc5cdc5p.js → Playground-AzNMsRBL.js} +1 -1
  16. package/dist/assets/{ProcessPanel-CslEiZkI.js → ProcessPanel-DpE_2sX3.js} +1 -1
  17. package/dist/assets/{PromptsPage-D2EhsdNO.js → PromptsPage-C2RQOs6p.js} +2 -2
  18. package/dist/assets/RunsPage-B9UOyO79.js +1 -0
  19. package/dist/assets/{SandboxManager-a1AVI5q2.js → SandboxManager-jHvYjwfh.js} +1 -1
  20. package/dist/assets/SettingsPage-BBJax6gt.js +51 -0
  21. package/dist/assets/SkillsMarketplace-IjmjfdjD.js +1 -0
  22. package/dist/assets/SocialMediaPage-DoPZHhr2.js +10 -0
  23. package/dist/assets/{TailscalePage-CHiFhZXF.js → TailscalePage-DDEY7ckO.js} +1 -1
  24. package/dist/assets/TelephonyPage-OPNBZYKt.js +9 -0
  25. package/dist/assets/{TerminalPage-Drwyrnfd.js → TerminalPage-BjMbHHW3.js} +1 -1
  26. package/dist/assets/{gemini-live-client-C7rqAW7G.js → gemini-live-client-C70FEtX2.js} +11 -8
  27. package/dist/assets/{index-CEqZnThB.js → index-BgYM4wXw.js} +94 -93
  28. package/dist/assets/index-BkjSoVgn.css +32 -0
  29. package/dist/assets/sw-register-C7NOHtIu.js +1 -0
  30. package/dist/assets/text-chat-client-BSbLJerZ.js +2 -0
  31. package/dist/index.html +2 -2
  32. package/dist/sw.js +1 -1
  33. package/package.json +6 -1
  34. package/server/agent-executor.ts +37 -2
  35. package/server/agent-store.ts +3 -3
  36. package/server/agent-types.ts +11 -0
  37. package/server/assistant-store.ts +232 -6
  38. package/server/auth-manager.ts +9 -0
  39. package/server/cache-headers.ts +1 -1
  40. package/server/calendar-service.ts +10 -0
  41. package/server/ceo/document-store.ts +129 -0
  42. package/server/ceo/finance-store.ts +343 -0
  43. package/server/ceo/kpi-store.ts +208 -0
  44. package/server/ceo/memory-import.ts +277 -0
  45. package/server/ceo/news-store.ts +208 -0
  46. package/server/ceo/template-store.ts +134 -0
  47. package/server/ceo/time-tracking-store.ts +227 -0
  48. package/server/claude-auth-monitor.ts +128 -0
  49. package/server/claude-code-worker.ts +86 -0
  50. package/server/claude-session-discovery.ts +74 -1
  51. package/server/cli-launcher.ts +32 -10
  52. package/server/codex-adapter.ts +2 -2
  53. package/server/codex-ws-proxy.cjs +1 -1
  54. package/server/container-manager.ts +4 -4
  55. package/server/content-intelligence/content-engine.ts +1112 -0
  56. package/server/content-intelligence/platform-knowledge.ts +870 -0
  57. package/server/cron-store.ts +3 -3
  58. package/server/embedding-service.ts +49 -0
  59. package/server/event-bus-types.ts +13 -0
  60. package/server/federation/node-store.ts +5 -4
  61. package/server/fs-utils.ts +28 -1
  62. package/server/hank-notifications-store.ts +91 -0
  63. package/server/hank-tool-executor.ts +1835 -0
  64. package/server/hank-tools.ts +2107 -0
  65. package/server/image-pull-manager.ts +2 -2
  66. package/server/index.ts +25 -2
  67. package/server/llm-providers-streaming.ts +541 -0
  68. package/server/llm-providers.ts +12 -0
  69. package/server/marketplace.ts +249 -0
  70. package/server/mcp-registry.ts +158 -0
  71. package/server/memory-service.ts +296 -0
  72. package/server/obsidian-sync.ts +184 -0
  73. package/server/provider-manager.ts +5 -2
  74. package/server/provider-registry.ts +12 -0
  75. package/server/reminder-scheduler.ts +37 -1
  76. package/server/routes/agent-routes.ts +2 -1
  77. package/server/routes/assistant-routes.ts +198 -5
  78. package/server/routes/ceo-finance-kpi-routes.ts +167 -0
  79. package/server/routes/ceo-news-time-routes.ts +137 -0
  80. package/server/routes/ceo-routes.ts +99 -0
  81. package/server/routes/content-routes.ts +116 -0
  82. package/server/routes/email-routes.ts +147 -0
  83. package/server/routes/env-routes.ts +3 -3
  84. package/server/routes/fs-routes.ts +12 -9
  85. package/server/routes/hank-chat-routes.ts +592 -0
  86. package/server/routes/llm-routes.ts +12 -0
  87. package/server/routes/marketplace-routes.ts +63 -0
  88. package/server/routes/media-routes.ts +1 -1
  89. package/server/routes/memory-routes.ts +127 -0
  90. package/server/routes/platform-routes.ts +14 -675
  91. package/server/routes/sandbox-routes.ts +1 -1
  92. package/server/routes/settings-routes.ts +51 -1
  93. package/server/routes/socialmedia-routes.ts +152 -2
  94. package/server/routes/system-routes.ts +2 -2
  95. package/server/routes/team-routes.ts +71 -0
  96. package/server/routes/telephony-routes.ts +98 -18
  97. package/server/routes.ts +36 -9
  98. package/server/session-creation-service.ts +2 -2
  99. package/server/session-orchestrator.ts +54 -2
  100. package/server/session-types.ts +2 -0
  101. package/server/settings-manager.ts +50 -2
  102. package/server/skill-discovery.ts +68 -0
  103. package/server/socialmedia/adapters/browser-adapter.ts +179 -0
  104. package/server/socialmedia/adapters/postiz-adapter.ts +291 -14
  105. package/server/socialmedia/manager.ts +234 -15
  106. package/server/socialmedia/store.ts +51 -1
  107. package/server/socialmedia/types.ts +35 -2
  108. package/server/socialview/browser-manager.ts +150 -0
  109. package/server/socialview/extractors.ts +1298 -0
  110. package/server/socialview/image-describe.ts +188 -0
  111. package/server/socialview/library.ts +119 -0
  112. package/server/socialview/poster.ts +276 -0
  113. package/server/socialview/routes.ts +371 -0
  114. package/server/socialview/style-analyzer.ts +187 -0
  115. package/server/socialview/style-profiles.ts +67 -0
  116. package/server/socialview/types.ts +166 -0
  117. package/server/socialview/vision.ts +127 -0
  118. package/server/socialview/vnc-manager.ts +110 -0
  119. package/server/style-injector.ts +135 -0
  120. package/server/team-service.ts +239 -0
  121. package/server/team-store.ts +75 -0
  122. package/server/team-types.ts +52 -0
  123. package/server/telephony/audio-bridge.ts +281 -35
  124. package/server/telephony/audio-recorder.ts +132 -0
  125. package/server/telephony/call-manager.ts +803 -104
  126. package/server/telephony/call-types.ts +67 -1
  127. package/server/telephony/esl-client.ts +319 -0
  128. package/server/telephony/freeswitch-sync.ts +155 -0
  129. package/server/telephony/phone-utils.ts +63 -0
  130. package/server/telephony/telephony-store.ts +9 -8
  131. package/server/url-validator.ts +82 -0
  132. package/server/vault-markdown.ts +317 -0
  133. package/server/vault-migration.ts +121 -0
  134. package/server/vault-store.ts +466 -0
  135. package/server/vault-watcher.ts +59 -0
  136. package/server/vector-store.ts +210 -0
  137. package/server/voice-pipeline/gemini-live-adapter.ts +97 -0
  138. package/server/voice-pipeline/greeting-cache.ts +200 -0
  139. package/server/voice-pipeline/manager.ts +249 -0
  140. package/server/voice-pipeline/pipeline.ts +335 -0
  141. package/server/voice-pipeline/providers/index.ts +47 -0
  142. package/server/voice-pipeline/providers/llm-internal.ts +527 -0
  143. package/server/voice-pipeline/providers/stt-google.ts +157 -0
  144. package/server/voice-pipeline/providers/tts-google.ts +126 -0
  145. package/server/voice-pipeline/types.ts +247 -0
  146. package/server/ws-bridge-types.ts +6 -1
  147. package/dist/assets/AssistantPage-DJ-cMQfb.js +0 -1
  148. package/dist/assets/HelpPage-DMfkzERp.js +0 -1
  149. package/dist/assets/MediaPage-CE5rdvkC.js +0 -1
  150. package/dist/assets/RunsPage-C5BZF5Rx.js +0 -1
  151. package/dist/assets/SettingsPage-DirhjQrJ.js +0 -51
  152. package/dist/assets/SocialMediaPage-DBuM28vD.js +0 -1
  153. package/dist/assets/TelephonyPage-x0VV0fOo.js +0 -1
  154. package/dist/assets/index-C8M_PUmX.css +0 -32
  155. package/dist/assets/sw-register-LSSpj6RU.js +0 -1
  156. package/server/socialmedia/adapters/ayrshare-adapter.ts +0 -169
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Skill marketplace — discovers and installs Claude Code skills from GitHub
3
+ * repositories that follow the .claude-plugin/marketplace.json convention.
4
+ *
5
+ * Skills are installed into ~/.claude/skills/<slug>/ where the existing
6
+ * skills-routes.ts will pick them up automatically. A .heyhank-meta.json file
7
+ * is written alongside SKILL.md to record the source so the UI can offer
8
+ * "Update" / "Source" / "Uninstall" actions later.
9
+ */
10
+
11
+ import { existsSync } from "node:fs";
12
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
13
+ import { homedir } from "node:os";
14
+ import { join, resolve } from "node:path";
15
+
16
+ export interface MarketplaceSource {
17
+ /** Stable identifier used in URLs (e.g. "charlie947-social-media-skills"). */
18
+ id: string;
19
+ /** Display name shown in UI. */
20
+ name: string;
21
+ /** Author / org (display only). */
22
+ owner: string;
23
+ /** GitHub URL for the "Source" link in the UI. */
24
+ url: string;
25
+ /** GitHub owner login used to build raw + API URLs. */
26
+ ghOwner: string;
27
+ /** GitHub repo name. */
28
+ ghRepo: string;
29
+ /** Branch — defaults to "main". */
30
+ branch: string;
31
+ /** Description from marketplace.json (loaded lazily). */
32
+ description?: string;
33
+ }
34
+
35
+ export interface MarketplaceSkill {
36
+ slug: string;
37
+ name: string;
38
+ description: string;
39
+ /** Source id this skill belongs to. */
40
+ sourceId: string;
41
+ }
42
+
43
+ interface InstalledSkillMeta {
44
+ sourceId: string;
45
+ slug: string;
46
+ ghOwner: string;
47
+ ghRepo: string;
48
+ branch: string;
49
+ installedAt: string;
50
+ /** Commit SHA of the skill folder at install time, if available. */
51
+ ref?: string;
52
+ }
53
+
54
+ const SKILLS_DIR = join(homedir(), ".claude", "skills");
55
+ const META_FILE = ".heyhank-meta.json";
56
+
57
+ /**
58
+ * Built-in marketplaces shipped with HeyHank. Users can install skills from
59
+ * these immediately without configuring anything.
60
+ */
61
+ export const BUILTIN_SOURCES: MarketplaceSource[] = [
62
+ {
63
+ id: "charlie947-social-media-skills",
64
+ name: "Charlie Hills' Social Media Skills",
65
+ owner: "Charlie Hills",
66
+ url: "https://github.com/charlie947/social-media-skills",
67
+ ghOwner: "charlie947",
68
+ ghRepo: "social-media-skills",
69
+ branch: "main",
70
+ description:
71
+ "17 skills covering voice, LinkedIn, Instagram Reels, YouTube thumbnails, analytics, and community.",
72
+ },
73
+ ];
74
+
75
+ /** Validates a slug to prevent path traversal. */
76
+ export function isValidSlug(slug: string): boolean {
77
+ if (!slug || typeof slug !== "string") return false;
78
+ if (slug.includes("..") || slug.includes("/") || slug.includes("\\")) return false;
79
+ if (slug.startsWith(".")) return false;
80
+ return /^[a-zA-Z0-9._-]+$/.test(slug);
81
+ }
82
+
83
+ /** Lookup a source by id. Returns undefined when unknown. */
84
+ export function getSource(id: string): MarketplaceSource | undefined {
85
+ return BUILTIN_SOURCES.find((s) => s.id === id);
86
+ }
87
+
88
+ /** Parse YAML-ish frontmatter at the top of a SKILL.md. */
89
+ function parseFrontmatter(content: string): { name?: string; description?: string } {
90
+ const m = content.match(/^---\n([\s\S]*?)\n---/);
91
+ if (!m) return {};
92
+ const out: { name?: string; description?: string } = {};
93
+ for (const line of m[1].split("\n")) {
94
+ const nameMatch = line.match(/^name:\s*(.+)/);
95
+ if (nameMatch) out.name = nameMatch[1].trim().replace(/^["']|["']$/g, "");
96
+ const descMatch = line.match(/^description:\s*["']?(.+?)["']?\s*$/);
97
+ if (descMatch) out.description = descMatch[1];
98
+ }
99
+ return out;
100
+ }
101
+
102
+ interface GhContentEntry {
103
+ name: string;
104
+ path: string;
105
+ type: "file" | "dir";
106
+ download_url: string | null;
107
+ sha: string;
108
+ }
109
+
110
+ async function ghContents(
111
+ source: MarketplaceSource,
112
+ path: string,
113
+ ): Promise<GhContentEntry[]> {
114
+ const url = `https://api.github.com/repos/${source.ghOwner}/${source.ghRepo}/contents/${path}?ref=${source.branch}`;
115
+ const res = await fetch(url, {
116
+ headers: { Accept: "application/vnd.github+json" },
117
+ });
118
+ if (!res.ok) {
119
+ throw new Error(`GitHub API ${res.status} for ${url}`);
120
+ }
121
+ const json = (await res.json()) as GhContentEntry[] | GhContentEntry;
122
+ return Array.isArray(json) ? json : [json];
123
+ }
124
+
125
+ /** Fetches the skill list (with metadata) for a marketplace source. */
126
+ export async function listSkills(source: MarketplaceSource): Promise<MarketplaceSkill[]> {
127
+ const dirs = (await ghContents(source, "skills")).filter((e) => e.type === "dir");
128
+ const skills: MarketplaceSkill[] = [];
129
+ // Fetch SKILL.md frontmatter for each — keep concurrency modest to be polite.
130
+ const concurrency = 4;
131
+ for (let i = 0; i < dirs.length; i += concurrency) {
132
+ const chunk = dirs.slice(i, i + concurrency);
133
+ const batch = await Promise.all(
134
+ chunk.map(async (d) => {
135
+ const rawUrl = `https://raw.githubusercontent.com/${source.ghOwner}/${source.ghRepo}/${source.branch}/skills/${d.name}/SKILL.md`;
136
+ try {
137
+ const r = await fetch(rawUrl);
138
+ if (!r.ok) return null;
139
+ const text = await r.text();
140
+ const fm = parseFrontmatter(text);
141
+ return {
142
+ slug: d.name,
143
+ name: fm.name ?? d.name,
144
+ description: fm.description ?? "",
145
+ sourceId: source.id,
146
+ } satisfies MarketplaceSkill;
147
+ } catch {
148
+ return null;
149
+ }
150
+ }),
151
+ );
152
+ for (const s of batch) if (s) skills.push(s);
153
+ }
154
+ return skills;
155
+ }
156
+
157
+ /**
158
+ * Recursively downloads a skill folder from GitHub into a target directory.
159
+ * Stays inside `targetRoot` to prevent traversal via crafted filenames.
160
+ */
161
+ async function downloadDir(
162
+ source: MarketplaceSource,
163
+ remotePath: string,
164
+ targetRoot: string,
165
+ targetDir: string,
166
+ ): Promise<void> {
167
+ const safeTarget = resolve(targetDir);
168
+ if (!safeTarget.startsWith(resolve(targetRoot))) {
169
+ throw new Error("Refusing to write outside skill target directory");
170
+ }
171
+ const entries = await ghContents(source, remotePath);
172
+ await mkdir(safeTarget, { recursive: true });
173
+ for (const entry of entries) {
174
+ if (!isValidSlug(entry.name)) {
175
+ throw new Error(`Refusing unsafe filename: ${entry.name}`);
176
+ }
177
+ const childTarget = join(safeTarget, entry.name);
178
+ if (entry.type === "dir") {
179
+ await downloadDir(source, entry.path, targetRoot, childTarget);
180
+ } else if (entry.type === "file" && entry.download_url) {
181
+ const r = await fetch(entry.download_url);
182
+ if (!r.ok) {
183
+ throw new Error(`Download failed (${r.status}): ${entry.download_url}`);
184
+ }
185
+ const buf = Buffer.from(await r.arrayBuffer());
186
+ await writeFile(childTarget, buf);
187
+ }
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Installs a skill into ~/.claude/skills/<slug>/. Atomic: writes to a temp
193
+ * sibling directory first, then renames. Throws on conflict unless `overwrite`.
194
+ */
195
+ export async function installSkill(
196
+ source: MarketplaceSource,
197
+ slug: string,
198
+ options: { overwrite?: boolean } = {},
199
+ ): Promise<{ slug: string; path: string }> {
200
+ if (!isValidSlug(slug)) {
201
+ throw new Error(`Invalid slug: ${slug}`);
202
+ }
203
+ const finalDir = join(SKILLS_DIR, slug);
204
+ if (existsSync(finalDir) && !options.overwrite) {
205
+ throw new Error(`Skill "${slug}" already installed`);
206
+ }
207
+ await mkdir(SKILLS_DIR, { recursive: true });
208
+ const stagingDir = join(SKILLS_DIR, `.${slug}.installing-${Date.now()}`);
209
+ try {
210
+ await downloadDir(source, `skills/${slug}`, stagingDir, stagingDir);
211
+ if (!existsSync(join(stagingDir, "SKILL.md"))) {
212
+ throw new Error(`Source skill missing SKILL.md`);
213
+ }
214
+ const meta: InstalledSkillMeta = {
215
+ sourceId: source.id,
216
+ slug,
217
+ ghOwner: source.ghOwner,
218
+ ghRepo: source.ghRepo,
219
+ branch: source.branch,
220
+ installedAt: new Date().toISOString(),
221
+ };
222
+ await writeFile(join(stagingDir, META_FILE), JSON.stringify(meta, null, 2), "utf-8");
223
+ if (existsSync(finalDir)) {
224
+ await rm(finalDir, { recursive: true, force: true });
225
+ }
226
+ // Cross-platform rename: use Bun.file/native move via fs/promises.rename.
227
+ const { rename } = await import("node:fs/promises");
228
+ await rename(stagingDir, finalDir);
229
+ return { slug, path: finalDir };
230
+ } catch (err) {
231
+ // Best-effort rollback of half-installed staging dir
232
+ if (existsSync(stagingDir)) {
233
+ await rm(stagingDir, { recursive: true, force: true }).catch(() => {});
234
+ }
235
+ throw err;
236
+ }
237
+ }
238
+
239
+ /** Reads installed-skill metadata if present. */
240
+ export async function readInstalledMeta(slug: string): Promise<InstalledSkillMeta | null> {
241
+ if (!isValidSlug(slug)) return null;
242
+ const p = join(SKILLS_DIR, slug, META_FILE);
243
+ if (!existsSync(p)) return null;
244
+ try {
245
+ return JSON.parse(await readFile(p, "utf-8")) as InstalledSkillMeta;
246
+ } catch {
247
+ return null;
248
+ }
249
+ }
@@ -302,6 +302,164 @@ const CATALOG: CatalogEntry[] = [
302
302
  command: "npx",
303
303
  args: ["-y", "nanobanana-mcp"],
304
304
  },
305
+
306
+ // ─── New additions ───────────────────────────────────────────────────────
307
+
308
+ {
309
+ id: "scrapling",
310
+ name: "Scrapling",
311
+ description: "Web-Scraping mit Anti-Bot-Bypass. Umgeht Cloudflare und andere Schutzmechanismen automatisch.",
312
+ category: "search",
313
+ type: "stdio",
314
+ command: "scrapling",
315
+ args: ["mcp"],
316
+ },
317
+ {
318
+ id: "firecrawl",
319
+ name: "Firecrawl",
320
+ description: "Webseiten crawlen und strukturierte Daten extrahieren. Ideal fuer groessere Scraping-Aufgaben.",
321
+ category: "search",
322
+ type: "stdio",
323
+ command: "npx",
324
+ args: ["-y", "firecrawl-mcp"],
325
+ env: { FIRECRAWL_API_KEY: "" },
326
+ requiresAuth: [
327
+ { field: "FIRECRAWL_API_KEY", label: "Firecrawl API Key", helpText: "API-Key von firecrawl.dev erstellen, oder self-hosted Instanz nutzen." },
328
+ ],
329
+ },
330
+ {
331
+ id: "git",
332
+ name: "Git",
333
+ description: "Lokale Git-Repositories verwalten. Status, Diff, Log, Commit und Branch-Operationen.",
334
+ category: "development",
335
+ type: "stdio",
336
+ command: "uvx",
337
+ args: ["mcp-server-git"],
338
+ },
339
+ {
340
+ id: "docker",
341
+ name: "Docker",
342
+ description: "Docker-Container, Images und Volumes verwalten. Container starten, stoppen und inspizieren.",
343
+ category: "development",
344
+ type: "stdio",
345
+ command: "npx",
346
+ args: ["-y", "@docker/mcp-server"],
347
+ },
348
+ {
349
+ id: "home-assistant",
350
+ name: "Home Assistant",
351
+ description: "Smart-Home-Steuerung ueber Home Assistant. 80+ Tools fuer Licht, Heizung, Sensoren und Automationen.",
352
+ category: "other",
353
+ type: "stdio",
354
+ command: "uvx",
355
+ args: ["ha-mcp"],
356
+ env: { HA_URL: "", HA_TOKEN: "" },
357
+ requiresAuth: [
358
+ { field: "HA_URL", label: "Home Assistant URL", helpText: "URL deiner Home Assistant Instanz (z.B. http://homeassistant.local:8123)." },
359
+ { field: "HA_TOKEN", label: "Long-Lived Access Token", helpText: "Token unter Home Assistant > Profil > Langlebige Zugangstoken erstellen." },
360
+ ],
361
+ },
362
+ {
363
+ id: "sqlite",
364
+ name: "SQLite",
365
+ description: "SQLite-Datenbanken abfragen und verwalten. Tabellen erstellen, SQL ausfuehren, Daten analysieren.",
366
+ category: "database",
367
+ type: "stdio",
368
+ command: "npx",
369
+ args: ["-y", "@modelcontextprotocol/server-sqlite"],
370
+ },
371
+ {
372
+ id: "postgres",
373
+ name: "PostgreSQL",
374
+ description: "PostgreSQL-Datenbanken abfragen. Schema-Inspektion und SQL-Queries (read-only).",
375
+ category: "database",
376
+ type: "stdio",
377
+ command: "npx",
378
+ args: ["-y", "@modelcontextprotocol/server-postgres"],
379
+ env: { POSTGRES_CONNECTION_STRING: "" },
380
+ requiresAuth: [
381
+ { field: "POSTGRES_CONNECTION_STRING", label: "PostgreSQL Connection String", helpText: "z.B. postgresql://user:pass@localhost:5432/mydb" },
382
+ ],
383
+ },
384
+ {
385
+ id: "google-calendar",
386
+ name: "Google Calendar",
387
+ description: "Google Kalender verwalten. Events erstellen, aendern, loeschen und freie Zeiten finden.",
388
+ category: "productivity",
389
+ type: "stdio",
390
+ command: "npx",
391
+ args: ["-y", "google-calendar-mcp"],
392
+ env: { GOOGLE_CALENDAR_CREDENTIALS: "" },
393
+ requiresAuth: [
394
+ { field: "GOOGLE_CALENDAR_CREDENTIALS", label: "Google OAuth Credentials JSON-Pfad", helpText: "Pfad zur OAuth Client JSON-Datei aus der Google Cloud Console." },
395
+ ],
396
+ },
397
+ {
398
+ id: "todoist",
399
+ name: "Todoist",
400
+ description: "Todoist-Aufgaben und Projekte verwalten. Tasks erstellen, abschliessen und organisieren.",
401
+ category: "productivity",
402
+ type: "stdio",
403
+ command: "uvx",
404
+ args: ["todoist-mcp-server"],
405
+ env: { TODOIST_API_TOKEN: "" },
406
+ requiresAuth: [
407
+ { field: "TODOIST_API_TOKEN", label: "Todoist API Token", helpText: "API-Token unter todoist.com/app/settings/integrations/developer kopieren." },
408
+ ],
409
+ },
410
+ {
411
+ id: "obsidian",
412
+ name: "Obsidian",
413
+ description: "Obsidian-Vault durchsuchen und bearbeiten. Notes lesen, erstellen und Tags verwalten.",
414
+ category: "productivity",
415
+ type: "stdio",
416
+ command: "npx",
417
+ args: ["-y", "obsidian-mcp-server"],
418
+ env: { OBSIDIAN_REST_URL: "" },
419
+ requiresAuth: [
420
+ { field: "OBSIDIAN_REST_URL", label: "Obsidian Local REST API URL", helpText: "Installiere das Local REST API Plugin in Obsidian. Standard: http://localhost:27124" },
421
+ ],
422
+ },
423
+ {
424
+ id: "fal-ai",
425
+ name: "Fal.ai",
426
+ description: "KI-generierte Bilder, Videos und Musik. Nutzt FLUX, Stable Diffusion und MusicGen Modelle.",
427
+ category: "ai",
428
+ type: "stdio",
429
+ command: "npx",
430
+ args: ["-y", "@fal-ai/mcp-server"],
431
+ env: { FAL_KEY: "" },
432
+ requiresAuth: [
433
+ { field: "FAL_KEY", label: "Fal.ai API Key", helpText: "API-Key unter fal.ai/dashboard/keys erstellen." },
434
+ ],
435
+ },
436
+ {
437
+ id: "alpaca",
438
+ name: "Alpaca Trading",
439
+ description: "Aktien, ETFs und Krypto handeln. Portfolio-Analyse und Marktdaten in Echtzeit.",
440
+ category: "other",
441
+ type: "stdio",
442
+ command: "uvx",
443
+ args: ["alpaca-mcp-server"],
444
+ env: { ALPACA_API_KEY: "", ALPACA_SECRET_KEY: "" },
445
+ requiresAuth: [
446
+ { field: "ALPACA_API_KEY", label: "Alpaca API Key", helpText: "API-Key unter app.alpaca.markets/brokerage/dashboard/overview erstellen." },
447
+ { field: "ALPACA_SECRET_KEY", label: "Alpaca Secret Key", helpText: "Secret Key zusammen mit dem API-Key erstellt." },
448
+ ],
449
+ },
450
+ {
451
+ id: "financial-datasets",
452
+ name: "Financial Datasets",
453
+ description: "Finanzdaten abrufen. Bilanzen, Aktienkurse, Markt-News und Fundamentalanalyse.",
454
+ category: "other",
455
+ type: "stdio",
456
+ command: "npx",
457
+ args: ["-y", "financial-datasets-mcp"],
458
+ env: { FINANCIAL_DATASETS_API_KEY: "" },
459
+ requiresAuth: [
460
+ { field: "FINANCIAL_DATASETS_API_KEY", label: "Financial Datasets API Key", helpText: "API-Key unter financialdatasets.ai erstellen." },
461
+ ],
462
+ },
305
463
  ];
306
464
 
307
465
  // ─── CRUD Operations ────────────────────────────────────────────────────────