@cyanheads/workflows-mcp-server 0.1.1

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 (45) hide show
  1. package/CLAUDE.md +376 -0
  2. package/Dockerfile +99 -0
  3. package/LICENSE +201 -0
  4. package/README.md +306 -0
  5. package/changelog/0.1.x/0.1.0.md +19 -0
  6. package/changelog/0.1.x/0.1.1.md +25 -0
  7. package/changelog/template.md +127 -0
  8. package/dist/config/server-config.d.ts +13 -0
  9. package/dist/config/server-config.d.ts.map +1 -0
  10. package/dist/config/server-config.js +30 -0
  11. package/dist/config/server-config.js.map +1 -0
  12. package/dist/index.d.ts +7 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +30 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/mcp-server/tools/definitions/index.d.ts +132 -0
  17. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
  18. package/dist/mcp-server/tools/definitions/index.js +14 -0
  19. package/dist/mcp-server/tools/definitions/index.js.map +1 -0
  20. package/dist/mcp-server/tools/definitions/workflow-create-temp.tool.d.ts +34 -0
  21. package/dist/mcp-server/tools/definitions/workflow-create-temp.tool.d.ts.map +1 -0
  22. package/dist/mcp-server/tools/definitions/workflow-create-temp.tool.js +132 -0
  23. package/dist/mcp-server/tools/definitions/workflow-create-temp.tool.js.map +1 -0
  24. package/dist/mcp-server/tools/definitions/workflow-create.tool.d.ts +40 -0
  25. package/dist/mcp-server/tools/definitions/workflow-create.tool.d.ts.map +1 -0
  26. package/dist/mcp-server/tools/definitions/workflow-create.tool.js +153 -0
  27. package/dist/mcp-server/tools/definitions/workflow-create.tool.js.map +1 -0
  28. package/dist/mcp-server/tools/definitions/workflow-get.tool.d.ts +52 -0
  29. package/dist/mcp-server/tools/definitions/workflow-get.tool.d.ts.map +1 -0
  30. package/dist/mcp-server/tools/definitions/workflow-get.tool.js +163 -0
  31. package/dist/mcp-server/tools/definitions/workflow-get.tool.js.map +1 -0
  32. package/dist/mcp-server/tools/definitions/workflow-list.tool.d.ts +28 -0
  33. package/dist/mcp-server/tools/definitions/workflow-list.tool.d.ts.map +1 -0
  34. package/dist/mcp-server/tools/definitions/workflow-list.tool.js +148 -0
  35. package/dist/mcp-server/tools/definitions/workflow-list.tool.js.map +1 -0
  36. package/dist/services/workflow-index/types.d.ts +49 -0
  37. package/dist/services/workflow-index/types.d.ts.map +1 -0
  38. package/dist/services/workflow-index/types.js +6 -0
  39. package/dist/services/workflow-index/types.js.map +1 -0
  40. package/dist/services/workflow-index/workflow-index-service.d.ts +47 -0
  41. package/dist/services/workflow-index/workflow-index-service.d.ts.map +1 -0
  42. package/dist/services/workflow-index/workflow-index-service.js +395 -0
  43. package/dist/services/workflow-index/workflow-index-service.js.map +1 -0
  44. package/package.json +103 -0
  45. package/server.json +129 -0
@@ -0,0 +1,395 @@
1
+ /**
2
+ * @fileoverview In-memory workflow index service with filesystem watcher.
3
+ * Loads, validates, and indexes YAML workflow files from the configured directory.
4
+ * Watches for changes and rebuilds the index with debouncing.
5
+ * @module services/workflow-index/workflow-index-service
6
+ */
7
+ import * as fs from 'node:fs/promises';
8
+ import * as path from 'node:path';
9
+ import { z } from '@cyanheads/mcp-ts-core';
10
+ import { logger } from '@cyanheads/mcp-ts-core/utils';
11
+ import * as semver from 'semver';
12
+ import { parse as parseYaml } from 'yaml';
13
+ // ---------------------------------------------------------------------------
14
+ // Validation schemas
15
+ // ---------------------------------------------------------------------------
16
+ const StepSchema = z.object({
17
+ server: z.string().min(1),
18
+ tool: z.string().min(1),
19
+ action: z.string().optional(),
20
+ description: z.string().optional(),
21
+ name: z.string().optional(),
22
+ params: z.record(z.string(), z.unknown()).optional(),
23
+ forEach: z.string().optional(),
24
+ });
25
+ const WorkflowSchema = z.object({
26
+ name: z.string().min(1),
27
+ version: z.string().regex(/^\d+\.\d+\.\d+/),
28
+ description: z.string().min(1),
29
+ author: z.string().min(1),
30
+ category: z.string().min(1).optional(),
31
+ tags: z
32
+ .array(z.string())
33
+ .nullable()
34
+ .optional()
35
+ .transform((v) => v ?? undefined),
36
+ created_date: z
37
+ .string()
38
+ .regex(/^\d{4}-\d{2}-\d{2}/)
39
+ .optional(),
40
+ last_updated_date: z
41
+ .string()
42
+ .regex(/^\d{4}-\d{2}-\d{2}/)
43
+ .optional(),
44
+ temporary: z.boolean().optional(),
45
+ steps: z.array(StepSchema).min(1),
46
+ });
47
+ // ---------------------------------------------------------------------------
48
+ // Slugification
49
+ // ---------------------------------------------------------------------------
50
+ /** Convert a display string to a filesystem-safe kebab-case slug. */
51
+ export function slugify(input) {
52
+ return input
53
+ .toLowerCase()
54
+ .replace(/[^a-z0-9]+/g, '-')
55
+ .replace(/^-+|-+$/g, '');
56
+ }
57
+ /** Maximum slug length for a name used in a filename (leaves room for version + suffix). */
58
+ const MAX_NAME_SLUG_LENGTH = 200;
59
+ /** Throw a tagged error if the slug derived from a workflow name is empty or too long. */
60
+ function assertValidNameSlug(name, slug) {
61
+ if (!slug) {
62
+ throw Object.assign(new Error(`Workflow name "${name}" produces an empty slug`), {
63
+ _reason: 'invalid_name',
64
+ });
65
+ }
66
+ if (slug.length > MAX_NAME_SLUG_LENGTH) {
67
+ throw Object.assign(new Error(`Workflow name is too long — keep it under ${MAX_NAME_SLUG_LENGTH} characters after slugification`), { _reason: 'name_too_long' });
68
+ }
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Logging helpers (background/non-request context)
72
+ // ---------------------------------------------------------------------------
73
+ function logInfo(msg) {
74
+ logger.info(msg);
75
+ }
76
+ function logWarn(msg) {
77
+ logger.warning(msg);
78
+ }
79
+ function logError(msg, err) {
80
+ logger.error(msg, err instanceof Error ? err : new Error(String(err)));
81
+ }
82
+ // ---------------------------------------------------------------------------
83
+ // Service
84
+ // ---------------------------------------------------------------------------
85
+ export class WorkflowIndexService {
86
+ _index = new Map();
87
+ _ready = false;
88
+ _watcherController;
89
+ _debounceTimer;
90
+ workflowsDir;
91
+ globalInstructionsPath;
92
+ watcherDebounceMs;
93
+ constructor(workflowsDir, globalInstructionsPath, watcherDebounceMs) {
94
+ this.workflowsDir = workflowsDir;
95
+ this.globalInstructionsPath = globalInstructionsPath;
96
+ this.watcherDebounceMs = watcherDebounceMs;
97
+ }
98
+ // --- Public API ---
99
+ get ready() {
100
+ return this._ready;
101
+ }
102
+ /** The current in-memory index. */
103
+ get index() {
104
+ return this._index;
105
+ }
106
+ /** Initialize: build initial index and start filesystem watcher. */
107
+ async init() {
108
+ await this.rebuild();
109
+ this.startWatcher();
110
+ }
111
+ /** Tear down the watcher. */
112
+ shutdown() {
113
+ if (this._debounceTimer)
114
+ clearTimeout(this._debounceTimer);
115
+ this._watcherController?.abort();
116
+ }
117
+ // --- Lookup ---
118
+ /** Find all entries matching a name (across all versions). */
119
+ findByName(name) {
120
+ const results = [];
121
+ for (const entry of this._index.values()) {
122
+ if (entry.workflow.name === name)
123
+ results.push(entry);
124
+ }
125
+ return results;
126
+ }
127
+ /** Semver-aware lookup. Returns the highest version match if version is omitted. */
128
+ findWorkflow(name, version) {
129
+ if (version) {
130
+ return this._index.get(`${name}@${version}`);
131
+ }
132
+ const matches = this.findByName(name);
133
+ if (matches.length === 0)
134
+ return;
135
+ matches.sort((a, b) => semver.rcompare(a.workflow.version, b.workflow.version));
136
+ return matches[0];
137
+ }
138
+ /** Read global_instructions.md content. Returns null if file missing. */
139
+ async readGlobalInstructions() {
140
+ try {
141
+ return await fs.readFile(this.globalInstructionsPath, 'utf-8');
142
+ }
143
+ catch {
144
+ return null;
145
+ }
146
+ }
147
+ // --- Write operations ---
148
+ /** Write a permanent workflow YAML and rebuild the index. */
149
+ async writePermanent(workflow) {
150
+ const key = `${workflow.name}@${workflow.version}`;
151
+ const categorySlug = slugify(workflow.category ?? 'uncategorized');
152
+ const nameSlug = slugify(workflow.name);
153
+ const versionSlug = slugify(workflow.version);
154
+ assertValidNameSlug(workflow.name, nameSlug);
155
+ const categoryDir = path.join(this.workflowsDir, 'categories', categorySlug);
156
+ // Include version in filename so multiple versions coexist on disk.
157
+ const filePath = path.join(categoryDir, `${nameSlug}-${versionSlug}-workflow.yaml`);
158
+ await fs.mkdir(categoryDir, { recursive: true });
159
+ try {
160
+ // `wx` flag fails atomically if the file already exists, preventing TOCTOU races.
161
+ await fs.writeFile(filePath, buildYaml(workflow), { encoding: 'utf-8', flag: 'wx' });
162
+ }
163
+ catch (err) {
164
+ if (err instanceof Error && err.code === 'EEXIST') {
165
+ throw Object.assign(new Error(`Workflow "${key}" already exists`), {
166
+ _reason: 'already_exists',
167
+ });
168
+ }
169
+ throw err;
170
+ }
171
+ // Immediately rebuild so the index is fresh for the caller.
172
+ // The watcher will also fire and trigger a redundant rebuild — that's fine (idempotent).
173
+ await this.rebuild();
174
+ return filePath;
175
+ }
176
+ /** Write a temporary workflow YAML and rebuild the index. */
177
+ async writeTemp(workflow) {
178
+ const nameSlug = slugify(workflow.name);
179
+ const versionSlug = slugify(workflow.version);
180
+ assertValidNameSlug(workflow.name, nameSlug);
181
+ const tempDir = path.join(this.workflowsDir, 'temp');
182
+ await fs.mkdir(tempDir, { recursive: true });
183
+ // Include version in filename so different versions are distinct files.
184
+ const filePath = path.join(tempDir, `${nameSlug}-${versionSlug}-workflow.yaml`);
185
+ await fs.writeFile(filePath, buildYaml(workflow), 'utf-8');
186
+ await this.rebuild();
187
+ return filePath;
188
+ }
189
+ // --- Internal ---
190
+ async rebuild() {
191
+ const newIndex = new Map();
192
+ try {
193
+ const categoriesDir = path.join(this.workflowsDir, 'categories');
194
+ await this.scanDirectory(categoriesDir, false, newIndex);
195
+ const tempDir = path.join(this.workflowsDir, 'temp');
196
+ await this.scanDirectory(tempDir, true, newIndex);
197
+ }
198
+ catch (err) {
199
+ logWarn(`Workflow index rebuild error: ${String(err)}`);
200
+ }
201
+ this._index = newIndex;
202
+ this._ready = true;
203
+ logInfo(`Workflow index rebuilt (${newIndex.size} entries)`);
204
+ // Write snapshot asynchronously — don't await
205
+ this.writeSnapshot(newIndex).catch((err) => {
206
+ logWarn(`Failed to write index snapshot: ${String(err)}`);
207
+ });
208
+ }
209
+ async scanDirectory(dir, isTemp, index) {
210
+ let entries;
211
+ try {
212
+ entries = await fs.readdir(dir, { withFileTypes: true, recursive: true, encoding: 'utf8' });
213
+ }
214
+ catch {
215
+ // Directory may not exist yet — that's fine
216
+ return;
217
+ }
218
+ for (const entry of entries) {
219
+ if (!entry.isFile())
220
+ continue;
221
+ const name = entry.name;
222
+ if (!name.endsWith('.yaml') && !name.endsWith('.yml'))
223
+ continue;
224
+ if (name === '_index.json')
225
+ continue;
226
+ // `recursive: true` sets `entry.parentPath` in Node 22+, falling back to `entry.path`
227
+ const parentDir = entry.parentPath ?? entry.path ?? dir;
228
+ const filePath = path.join(parentDir, name);
229
+ await this.loadFile(filePath, isTemp, index);
230
+ }
231
+ }
232
+ async loadFile(filePath, isTemp, index) {
233
+ let raw;
234
+ try {
235
+ raw = await fs.readFile(filePath, 'utf-8');
236
+ }
237
+ catch (err) {
238
+ logWarn(`Failed to read workflow file ${filePath}: ${String(err)}`);
239
+ return;
240
+ }
241
+ let parsed;
242
+ try {
243
+ parsed = parseYaml(raw);
244
+ }
245
+ catch (err) {
246
+ logWarn(`Failed to parse YAML at ${filePath}: ${String(err)}`);
247
+ return;
248
+ }
249
+ const result = WorkflowSchema.safeParse(parsed);
250
+ if (!result.success) {
251
+ logWarn(`Invalid workflow schema at ${filePath}: ${JSON.stringify(result.error.flatten().fieldErrors)}`);
252
+ return;
253
+ }
254
+ const workflow = result.data;
255
+ // Warn if a non-temp file is missing a category
256
+ if (!isTemp && !workflow.category) {
257
+ logWarn(`Permanent workflow missing category field: ${filePath} (name: ${workflow.name})`);
258
+ }
259
+ const key = `${workflow.name}@${workflow.version}`;
260
+ if (index.has(key)) {
261
+ logWarn(`Duplicate workflow key "${key}" — last write wins (file: ${filePath})`);
262
+ }
263
+ index.set(key, { workflow, filePath, isTemp });
264
+ }
265
+ async writeSnapshot(index) {
266
+ const snapshot = {
267
+ generatedAt: new Date().toISOString(),
268
+ count: index.size,
269
+ entries: {},
270
+ };
271
+ for (const [key, entry] of index) {
272
+ snapshot.entries[key] = {
273
+ filePath: entry.filePath,
274
+ isTemp: entry.isTemp,
275
+ name: entry.workflow.name,
276
+ version: entry.workflow.version,
277
+ ...(entry.workflow.category !== undefined && { category: entry.workflow.category }),
278
+ ...(entry.workflow.tags !== undefined && { tags: entry.workflow.tags }),
279
+ };
280
+ }
281
+ const snapshotPath = path.join(this.workflowsDir, '_index.json');
282
+ await fs.writeFile(snapshotPath, JSON.stringify(snapshot, null, 2), 'utf-8');
283
+ }
284
+ startWatcher() {
285
+ this._watcherController = new AbortController();
286
+ const signal = this._watcherController.signal;
287
+ const debounceMs = this.watcherDebounceMs;
288
+ const rebuild = () => this.scheduledRebuild();
289
+ // Fire and forget — the loop runs in the background
290
+ void (async () => {
291
+ try {
292
+ const watcher = fs.watch(this.workflowsDir, { recursive: true, signal });
293
+ for await (const event of watcher) {
294
+ // Skip snapshot file events to avoid infinite loop
295
+ const filename = event.filename;
296
+ if (typeof filename === 'string' && filename.endsWith('_index.json')) {
297
+ continue;
298
+ }
299
+ // Debounce
300
+ if (this._debounceTimer)
301
+ clearTimeout(this._debounceTimer);
302
+ this._debounceTimer = setTimeout(rebuild, debounceMs);
303
+ }
304
+ }
305
+ catch (err) {
306
+ // AbortError is expected on shutdown — ignore it
307
+ if (err instanceof Error &&
308
+ (err.name === 'AbortError' || err.code === 'ABORT_ERR')) {
309
+ return;
310
+ }
311
+ logWarn(`Filesystem watcher exited unexpectedly: ${String(err)}`);
312
+ }
313
+ })();
314
+ }
315
+ scheduledRebuild() {
316
+ this.rebuild().catch((err) => {
317
+ logWarn(`Debounced rebuild failed: ${String(err)}`);
318
+ });
319
+ }
320
+ }
321
+ // ---------------------------------------------------------------------------
322
+ // YAML serialisation helper
323
+ // ---------------------------------------------------------------------------
324
+ function buildYaml(workflow) {
325
+ const lines = [];
326
+ lines.push(`name: ${quote(workflow.name)}`);
327
+ lines.push(`version: "${workflow.version}"`);
328
+ lines.push(`description: ${quote(workflow.description)}`);
329
+ lines.push(`author: ${quote(workflow.author)}`);
330
+ if (workflow.category)
331
+ lines.push(`category: ${quote(workflow.category)}`);
332
+ if (workflow.tags && workflow.tags.length > 0) {
333
+ lines.push('tags:');
334
+ for (const tag of workflow.tags)
335
+ lines.push(` - ${quote(tag)}`);
336
+ }
337
+ if (workflow.created_date)
338
+ lines.push(`created_date: "${workflow.created_date}"`);
339
+ if (workflow.last_updated_date)
340
+ lines.push(`last_updated_date: "${workflow.last_updated_date}"`);
341
+ if (workflow.temporary)
342
+ lines.push('temporary: true');
343
+ lines.push('steps:');
344
+ for (const step of workflow.steps) {
345
+ lines.push(` - server: ${quote(step.server)}`);
346
+ lines.push(` tool: ${quote(step.tool)}`);
347
+ if (step.action)
348
+ lines.push(` action: ${quote(step.action)}`);
349
+ if (step.description)
350
+ lines.push(` description: ${quote(step.description)}`);
351
+ if (step.name)
352
+ lines.push(` name: ${quote(step.name)}`);
353
+ if (step.forEach)
354
+ lines.push(` forEach: ${quote(step.forEach)}`);
355
+ if (step.params && Object.keys(step.params).length > 0) {
356
+ lines.push(' params:');
357
+ for (const [k, v] of Object.entries(step.params)) {
358
+ lines.push(` ${k}: ${yamlValue(v)}`);
359
+ }
360
+ }
361
+ }
362
+ return `${lines.join('\n')}\n`;
363
+ }
364
+ function quote(s) {
365
+ if (/[:#[\]{},&*?|<>=!%@`\\]|^[-?]/.test(s) || s.includes('\n')) {
366
+ return `"${s.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
367
+ }
368
+ return s;
369
+ }
370
+ function yamlValue(v) {
371
+ if (typeof v === 'string')
372
+ return quote(v);
373
+ if (typeof v === 'boolean' || typeof v === 'number')
374
+ return String(v);
375
+ if (v === null)
376
+ return 'null';
377
+ return JSON.stringify(v);
378
+ }
379
+ // ---------------------------------------------------------------------------
380
+ // Init/accessor pattern
381
+ // ---------------------------------------------------------------------------
382
+ let _service;
383
+ export function initWorkflowIndexService(_config, _storage, workflowsDir, globalInstructionsPath, watcherDebounceMs) {
384
+ _service = new WorkflowIndexService(workflowsDir, globalInstructionsPath, watcherDebounceMs);
385
+ _service.init().catch((err) => {
386
+ logError('WorkflowIndexService init failed', err);
387
+ });
388
+ }
389
+ export function getWorkflowIndexService() {
390
+ if (!_service) {
391
+ throw new Error('WorkflowIndexService not initialized — call initWorkflowIndexService() in setup()');
392
+ }
393
+ return _service;
394
+ }
395
+ //# sourceMappingURL=workflow-index-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-index-service.js","sourceRoot":"","sources":["../../../src/services/workflow-index/workflow-index-service.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,103 @@
1
+ {
2
+ "name": "@cyanheads/workflows-mcp-server",
3
+ "version": "0.1.1",
4
+ "mcpName": "io.github.cyanheads/workflows-mcp-server",
5
+ "description": "Store, query, and create YAML workflow playbooks for LLM agents via MCP. STDIO or Streamable HTTP.",
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "workflows-mcp-server": "dist/index.js"
11
+ },
12
+ "files": [
13
+ "changelog/",
14
+ "dist/",
15
+ "README.md",
16
+ "LICENSE",
17
+ "CLAUDE.md",
18
+ "AGENTS.md",
19
+ "Dockerfile",
20
+ "server.json"
21
+ ],
22
+ "scripts": {
23
+ "build": "bun run scripts/build.ts",
24
+ "rebuild": "bun run scripts/clean.ts && bun run build",
25
+ "clean": "bun run scripts/clean.ts",
26
+ "devcheck": "bun run scripts/devcheck.ts",
27
+ "audit:refresh": "rm -f bun.lock && bun install && bun audit",
28
+ "tree": "bun run scripts/tree.ts",
29
+ "list-skills": "bun run scripts/list-skills.ts",
30
+ "format": "biome check --write --unsafe",
31
+ "lint:mcp": "bun run scripts/lint-mcp.ts",
32
+ "lint:packaging": "bun run scripts/lint-packaging.ts",
33
+ "bundle": "bun run build && npx -y @anthropic-ai/mcpb pack . dist/workflows-mcp-server.mcpb",
34
+ "changelog:build": "bun run scripts/build-changelog.ts",
35
+ "changelog:check": "bun run scripts/build-changelog.ts --check",
36
+ "publish-mcp": "mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish",
37
+ "test": "bunx vitest run",
38
+ "start:stdio": "MCP_TRANSPORT_TYPE=stdio bun ./dist/index.js",
39
+ "start:http": "MCP_TRANSPORT_TYPE=http bun ./dist/index.js"
40
+ },
41
+ "keywords": [
42
+ "mcp",
43
+ "mcp-server",
44
+ "model-context-protocol",
45
+ "ai",
46
+ "llm",
47
+ "bun",
48
+ "stdio",
49
+ "streamable-http",
50
+ "workflows",
51
+ "yaml",
52
+ "playbook",
53
+ "automation",
54
+ "agent-tools"
55
+ ],
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "git+https://github.com/cyanheads/workflows-mcp-server.git"
59
+ },
60
+ "homepage": "https://github.com/cyanheads/workflows-mcp-server#readme",
61
+ "bugs": {
62
+ "url": "https://github.com/cyanheads/workflows-mcp-server/issues"
63
+ },
64
+ "author": "cyanheads <casey@caseyjhand.com> (https://github.com/cyanheads/workflows-mcp-server#readme)",
65
+ "funding": [
66
+ {
67
+ "type": "github",
68
+ "url": "https://github.com/sponsors/cyanheads"
69
+ },
70
+ {
71
+ "type": "buy_me_a_coffee",
72
+ "url": "https://www.buymeacoffee.com/cyanheads"
73
+ }
74
+ ],
75
+ "license": "Apache-2.0",
76
+ "packageManager": "bun@1.3.2",
77
+ "engines": {
78
+ "bun": ">=1.3.2",
79
+ "node": ">=24.0.0"
80
+ },
81
+ "publishConfig": {
82
+ "access": "public"
83
+ },
84
+ "dependencies": {
85
+ "@cyanheads/mcp-ts-core": "^0.9.11",
86
+ "pino-pretty": "^13.1.3",
87
+ "semver": "^7.8.1",
88
+ "yaml": "^2.9.0",
89
+ "zod": "^4.4.3"
90
+ },
91
+ "devDependencies": {
92
+ "@biomejs/biome": "^2.4.16",
93
+ "@types/node": "^25.9.1",
94
+ "@types/semver": "^7.7.1",
95
+ "@vitest/coverage-istanbul": "^4.1.7",
96
+ "depcheck": "^1.4.7",
97
+ "fast-check": "^4.8.0",
98
+ "ignore": "^7.0.5",
99
+ "tsc-alias": "^1.8.17",
100
+ "typescript": "^6.0.3",
101
+ "vitest": "^4.1.7"
102
+ }
103
+ }
package/server.json ADDED
@@ -0,0 +1,129 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.cyanheads/workflows-mcp-server",
4
+ "description": "Store, query, and create YAML workflow playbooks for LLM agents.",
5
+ "repository": {
6
+ "url": "https://github.com/cyanheads/workflows-mcp-server",
7
+ "source": "github"
8
+ },
9
+ "version": "0.1.1",
10
+ "packages": [
11
+ {
12
+ "registryType": "npm",
13
+ "registryBaseUrl": "https://registry.npmjs.org",
14
+ "identifier": "@cyanheads/workflows-mcp-server",
15
+ "runtimeHint": "bun",
16
+ "version": "0.1.1",
17
+ "packageArguments": [
18
+ { "type": "positional", "value": "run" },
19
+ { "type": "positional", "value": "start:stdio" }
20
+ ],
21
+ "environmentVariables": [
22
+ {
23
+ "name": "WORKFLOWS_DIR",
24
+ "description": "Absolute or relative path to the workflows root directory.",
25
+ "format": "string",
26
+ "isRequired": false,
27
+ "default": "./workflows-yaml"
28
+ },
29
+ {
30
+ "name": "GLOBAL_INSTRUCTIONS_PATH",
31
+ "description": "Path to the global instructions markdown file. Derives from WORKFLOWS_DIR when not set.",
32
+ "format": "string",
33
+ "isRequired": false,
34
+ "default": ""
35
+ },
36
+ {
37
+ "name": "WATCHER_DEBOUNCE_MS",
38
+ "description": "Milliseconds to debounce filesystem change events before rebuilding the index.",
39
+ "format": "string",
40
+ "isRequired": false,
41
+ "default": "500"
42
+ },
43
+ {
44
+ "name": "MCP_LOG_LEVEL",
45
+ "description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').",
46
+ "format": "string",
47
+ "isRequired": false,
48
+ "default": "info"
49
+ }
50
+ ],
51
+ "transport": {
52
+ "type": "stdio"
53
+ }
54
+ },
55
+ {
56
+ "registryType": "npm",
57
+ "registryBaseUrl": "https://registry.npmjs.org",
58
+ "identifier": "@cyanheads/workflows-mcp-server",
59
+ "runtimeHint": "bun",
60
+ "version": "0.1.1",
61
+ "packageArguments": [
62
+ { "type": "positional", "value": "run" },
63
+ { "type": "positional", "value": "start:http" }
64
+ ],
65
+ "environmentVariables": [
66
+ {
67
+ "name": "WORKFLOWS_DIR",
68
+ "description": "Absolute or relative path to the workflows root directory.",
69
+ "format": "string",
70
+ "isRequired": false,
71
+ "default": "./workflows-yaml"
72
+ },
73
+ {
74
+ "name": "GLOBAL_INSTRUCTIONS_PATH",
75
+ "description": "Path to the global instructions markdown file. Derives from WORKFLOWS_DIR when not set.",
76
+ "format": "string",
77
+ "isRequired": false,
78
+ "default": ""
79
+ },
80
+ {
81
+ "name": "WATCHER_DEBOUNCE_MS",
82
+ "description": "Milliseconds to debounce filesystem change events before rebuilding the index.",
83
+ "format": "string",
84
+ "isRequired": false,
85
+ "default": "500"
86
+ },
87
+ {
88
+ "name": "MCP_HTTP_HOST",
89
+ "description": "The hostname for the HTTP server.",
90
+ "format": "string",
91
+ "isRequired": false,
92
+ "default": "127.0.0.1"
93
+ },
94
+ {
95
+ "name": "MCP_HTTP_PORT",
96
+ "description": "The port to run the HTTP server on.",
97
+ "format": "string",
98
+ "isRequired": false,
99
+ "default": "3010"
100
+ },
101
+ {
102
+ "name": "MCP_HTTP_ENDPOINT_PATH",
103
+ "description": "The endpoint path for the MCP server.",
104
+ "format": "string",
105
+ "isRequired": false,
106
+ "default": "/mcp"
107
+ },
108
+ {
109
+ "name": "MCP_AUTH_MODE",
110
+ "description": "Authentication mode to use: 'none', 'jwt', or 'oauth'.",
111
+ "format": "string",
112
+ "isRequired": false,
113
+ "default": "none"
114
+ },
115
+ {
116
+ "name": "MCP_LOG_LEVEL",
117
+ "description": "Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').",
118
+ "format": "string",
119
+ "isRequired": false,
120
+ "default": "info"
121
+ }
122
+ ],
123
+ "transport": {
124
+ "type": "streamable-http",
125
+ "url": "http://localhost:3010/mcp"
126
+ }
127
+ }
128
+ ]
129
+ }