superkit-mcp-server 1.2.5 → 1.2.6

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.
@@ -0,0 +1,104 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { apply_prompt_args } from '../index.js';
3
+ describe('apply_prompt_args', () => {
4
+ describe('{{args}} substitution', () => {
5
+ it('should replace {{args}} with the provided user args', () => {
6
+ const result = apply_prompt_args('Task: {{args}}', 'Add user authentication');
7
+ expect(result).toBe('Task: Add user authentication');
8
+ });
9
+ it('should replace all occurrences of {{args}}', () => {
10
+ const result = apply_prompt_args('{{args}} and also {{args}}', 'hello');
11
+ expect(result).toBe('hello and also hello');
12
+ });
13
+ it('should replace {{args}} with an empty string when no args are provided', () => {
14
+ const result = apply_prompt_args('Task: {{args}}', '');
15
+ expect(result).toBe('Task: ');
16
+ });
17
+ it('should replace {{args}} with an empty string when args is only whitespace', () => {
18
+ const result = apply_prompt_args('Task: {{args}}', ' ');
19
+ expect(result).toBe('Task: ');
20
+ });
21
+ });
22
+ describe('{{#if args}} ... {{/if}} block (no else branch)', () => {
23
+ it('should include the block content when args is provided', () => {
24
+ const template = '{{#if args}}Task: {{args}}{{/if}}';
25
+ const result = apply_prompt_args(template, 'Fix bug');
26
+ expect(result).toBe('Task: Fix bug');
27
+ });
28
+ it('should remove the block entirely when args is empty', () => {
29
+ const template = 'Before\n{{#if args}}Task: {{args}}{{/if}}\nAfter';
30
+ const result = apply_prompt_args(template, '');
31
+ expect(result).toBe('Before\n\nAfter');
32
+ });
33
+ it('should remove the block entirely when args is only whitespace', () => {
34
+ const template = '{{#if args}}Task: {{args}}{{/if}}';
35
+ const result = apply_prompt_args(template, ' ');
36
+ expect(result).toBe('');
37
+ });
38
+ it('should handle multiline block content', () => {
39
+ const template = '{{#if args}}\n# Task\n**Input:** {{args}}\n{{/if}}';
40
+ const result = apply_prompt_args(template, 'Do something');
41
+ expect(result).toBe('\n# Task\n**Input:** Do something\n');
42
+ });
43
+ });
44
+ describe('{{#if args}} ... {{else}} ... {{/if}} block', () => {
45
+ it('should render the if-block when args is provided', () => {
46
+ const template = '{{#if args}}Task: {{args}}{{else}}No task provided.{{/if}}';
47
+ const result = apply_prompt_args(template, 'Add login');
48
+ expect(result).toBe('Task: Add login');
49
+ });
50
+ it('should render the else-block when args is empty', () => {
51
+ const template = '{{#if args}}Task: {{args}}{{else}}No task provided.{{/if}}';
52
+ const result = apply_prompt_args(template, '');
53
+ expect(result).toBe('No task provided.');
54
+ });
55
+ it('should render the else-block when args is only whitespace', () => {
56
+ const template = '{{#if args}}Task: {{args}}{{else}}No task provided.{{/if}}';
57
+ const result = apply_prompt_args(template, ' ');
58
+ expect(result).toBe('No task provided.');
59
+ });
60
+ it('should handle multiline if and else blocks', () => {
61
+ const template = [
62
+ '{{#if args}}',
63
+ '# Running: {{args}}',
64
+ 'Execute the task above.',
65
+ '{{else}}',
66
+ '# Usage',
67
+ 'Provide a task to run.',
68
+ '{{/if}}',
69
+ ].join('\n');
70
+ const with_args = apply_prompt_args(template, 'Build the feature');
71
+ expect(with_args).toContain('# Running: Build the feature');
72
+ expect(with_args).not.toContain('# Usage');
73
+ const without_args = apply_prompt_args(template, '');
74
+ expect(without_args).toContain('# Usage');
75
+ expect(without_args).not.toContain('# Running:');
76
+ });
77
+ });
78
+ describe('edge cases', () => {
79
+ it('should return the template unchanged when it has no placeholders', () => {
80
+ const template = '# Plan\nThis is a static template.';
81
+ const result = apply_prompt_args(template, 'some args');
82
+ expect(result).toBe(template);
83
+ });
84
+ it('should handle a template with both {{args}} and {{#if args}} blocks', () => {
85
+ const template = [
86
+ '{{#if args}}',
87
+ '**Task:** {{args}}',
88
+ '{{else}}',
89
+ '**Task:** (none)',
90
+ '{{/if}}',
91
+ '',
92
+ 'Details: {{args}}',
93
+ ].join('\n');
94
+ const result = apply_prompt_args(template, 'Refactor auth');
95
+ expect(result).toContain('**Task:** Refactor auth');
96
+ expect(result).toContain('Details: Refactor auth');
97
+ expect(result).not.toContain('(none)');
98
+ });
99
+ it('should handle empty template string', () => {
100
+ const result = apply_prompt_args('', 'some args');
101
+ expect(result).toBe('');
102
+ });
103
+ });
104
+ });
package/build/index.js CHANGED
@@ -302,6 +302,13 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
302
302
  prompts.push({
303
303
  name: file.replace(".toml", ""),
304
304
  description: description,
305
+ arguments: [
306
+ {
307
+ name: "args",
308
+ description: "Arguments to pass to the command",
309
+ required: false,
310
+ },
311
+ ],
305
312
  });
306
313
  }
307
314
  catch (e) {
@@ -316,8 +323,18 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
316
323
  return { prompts: [] };
317
324
  }
318
325
  });
326
+ export function apply_prompt_args(promptText, userArgs) {
327
+ // Substitute {{#if args}} ... {{else}} ... {{/if}} Handlebars blocks
328
+ promptText = promptText.replace(/\{\{#if args\}\}([\s\S]*?)\{\{else\}\}([\s\S]*?)\{\{\/if\}\}/g, (_, ifBlock, elseBlock) => userArgs.trim() ? ifBlock : elseBlock);
329
+ // Substitute {{#if args}} ... {{/if}} blocks (no else branch)
330
+ promptText = promptText.replace(/\{\{#if args\}\}([\s\S]*?)\{\{\/if\}\}/g, (_, ifBlock) => (userArgs.trim() ? ifBlock : ""));
331
+ // Substitute all {{args}} occurrences with the actual user-provided args
332
+ promptText = promptText.replace(/\{\{args\}\}/g, userArgs);
333
+ return promptText;
334
+ }
319
335
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
320
336
  const promptName = request.params.name;
337
+ const userArgs = request.params.arguments?.args ?? "";
321
338
  const commandFile = `${promptName}.toml`;
322
339
  const basePath = path.join(superKitRoot, "commands");
323
340
  const safePath = getSafePath(basePath, commandFile);
@@ -328,6 +345,7 @@ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
328
345
  const content = await fs.readFile(safePath, "utf-8");
329
346
  const parsed = toml.parse(content);
330
347
  let promptText = parsed?.prompt || `Execute the ${promptName} command.`;
348
+ promptText = apply_prompt_args(promptText, userArgs);
331
349
  // Resolve @{path} includes from super-kit package root
332
350
  const includePattern = /@\{([^}]+)\}/g;
333
351
  let match;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superkit-mcp-server",
3
- "version": "1.2.5",
3
+ "version": "1.2.6",
4
4
  "type": "module",
5
5
  "description": "An MCP server for exploring and loading Super-Kit AI agent resources.",
6
6
  "main": "build/index.js",