@fprad0/skill-master-mcp 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ All notable changes to `skill_master` will be tracked here.
7
7
  - Prepare a public npm publication path with dedicated workflow and operator guide.
8
8
  - Upgrade release automation from Node `20` to Node `22`.
9
9
 
10
+ ## [0.0.7] - 2026-06-26
11
+
12
+ - Add a visual terminal menu for `skill-master-menu` using `prompts`, with TTY detection and direct action mode.
13
+ - Extract the menu core into a reusable module for tests and future UI changes.
14
+ - Keep the package compatible with Node `18+` instead of moving to a heavier TUI stack.
15
+
10
16
  ## [0.0.6] - 2026-06-26
11
17
 
12
18
  - Harden `skill-master-configure-private-registry` with HTTPS registry validation, scoped token handling, redacted dry-runs, timestamped backups, and POSIX `0600` permissions.
package/README.md CHANGED
@@ -110,8 +110,8 @@ npx -y @fprad0/skill-master-mcp@latest
110
110
 
111
111
  Estado atual validado em `2026-06-26`:
112
112
 
113
- - pacote publico publicado: `@fprad0/skill-master-mcp@0.0.5`
114
- - dist-tag `latest` apontando para `0.0.5`
113
+ - pacote publico publicado: `@fprad0/skill-master-mcp@0.0.7`
114
+ - dist-tag `latest` apontando para `0.0.7`
115
115
  - workflow `Publish Skill Master to npmjs` concluido com sucesso
116
116
  - `npm install` e `npx` confirmados
117
117
 
@@ -130,6 +130,16 @@ O `skill-master-mcp` deve continuar reservado para clientes MCP via `stdio`. Par
130
130
  skill-master-menu
131
131
  ```
132
132
 
133
+ O menu agora possui modo visual interativo para terminal com TTY e tambem aceita execucao direta por acao:
134
+
135
+ ```bash
136
+ skill-master-menu --run status
137
+ skill-master-menu --run check
138
+ skill-master-menu --run update --yes
139
+ ```
140
+
141
+ O menu visual usa `prompts` para ficar mais legivel no terminal e manter compatibilidade com `Node 18+`.
142
+
133
143
  Para atualizar a instalacao global via npm sem iniciar o servidor MCP:
134
144
 
135
145
  ```bash
package/VERSION.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  Versão funcional planejada: `00.02`
4
4
 
5
- Versão técnica para empacotamento semântico: `0.0.6`
5
+ Versão técnica para empacotamento semântico: `0.0.7`
6
6
 
7
7
  ## Observação
8
8
 
9
- O nome `00.02` será usado na comunicação e nos documentos. Para ferramentas que exigem SemVer, como npm e alguns fluxos de release, usar `0.0.6`.
9
+ O nome `00.02` será usado na comunicação e nos documentos. Para ferramentas que exigem SemVer, como npm e alguns fluxos de release, usar `0.0.7`.
@@ -0,0 +1,227 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import process from 'node:process';
5
+
6
+ const ANSI = {
7
+ reset: '\x1b[0m',
8
+ bold: '\x1b[1m',
9
+ dim: '\x1b[2m',
10
+ cyan: '\x1b[36m',
11
+ green: '\x1b[32m',
12
+ yellow: '\x1b[33m',
13
+ red: '\x1b[31m',
14
+ };
15
+
16
+ function colorize(text, color, enabled) {
17
+ return enabled ? `${color}${text}${ANSI.reset}` : text;
18
+ }
19
+
20
+ export function readJson(rootDir, relativePath) {
21
+ const target = join(rootDir, relativePath);
22
+ if (!existsSync(target)) {
23
+ return null;
24
+ }
25
+
26
+ return JSON.parse(readFileSync(target, 'utf8'));
27
+ }
28
+
29
+ export function readText(rootDir, relativePath) {
30
+ const target = join(rootDir, relativePath);
31
+ if (!existsSync(target)) {
32
+ return null;
33
+ }
34
+
35
+ return readFileSync(target, 'utf8').trim();
36
+ }
37
+
38
+ export function getMenuStatus(rootDir) {
39
+ const packageJson = readJson(rootDir, 'package.json');
40
+ const stableManifest = readJson(rootDir, 'manifests/channels/stable.json');
41
+ const versionText = readText(rootDir, 'VERSION.md');
42
+
43
+ return {
44
+ packageName: packageJson?.name ?? 'nao encontrado',
45
+ semver: packageJson?.version ?? 'nao encontrado',
46
+ manifestVersion: stableManifest?.version ?? 'nao encontrado',
47
+ manifestSemver: stableManifest?.semver ?? 'nao encontrado',
48
+ versionText,
49
+ rootDir,
50
+ };
51
+ }
52
+
53
+ export function buildMenuCommands({ rootDir, currentFile, nodeExecPath = process.execPath }) {
54
+ return [
55
+ {
56
+ key: 'status',
57
+ aliases: ['status'],
58
+ label: 'Status local',
59
+ description: 'Mostra versao local, manifesto e informacoes do pacote.',
60
+ command: nodeExecPath,
61
+ args: [currentFile, '--status'],
62
+ },
63
+ {
64
+ key: 'check',
65
+ aliases: ['check', 'gate'],
66
+ label: 'Rodar gate completo',
67
+ description: 'Executa build, testes e validacao de manifestos.',
68
+ command: 'npm',
69
+ args: ['run', 'check'],
70
+ },
71
+ {
72
+ key: 'build',
73
+ aliases: ['build'],
74
+ label: 'Rodar build',
75
+ description: 'Compila o projeto localmente.',
76
+ command: 'npm',
77
+ args: ['run', 'build'],
78
+ },
79
+ {
80
+ key: 'publicNpm',
81
+ aliases: ['public-npm', 'npm', 'registry'],
82
+ label: 'Validar pacote no npm publico',
83
+ description: 'Consulta a versao publicada em registry.npmjs.org.',
84
+ command: 'npm',
85
+ args: [
86
+ 'view',
87
+ '@fprad0/skill-master-mcp',
88
+ 'version',
89
+ '--registry=https://registry.npmjs.org',
90
+ ],
91
+ },
92
+ {
93
+ key: 'updateGlobal',
94
+ aliases: ['update', 'update-global'],
95
+ label: 'Atualizar pacote global via npm',
96
+ description: 'Atualiza a instalacao global e exige reinicio do cliente MCP.',
97
+ command: nodeExecPath,
98
+ args: [join(rootDir, 'bin', 'skill-master-update.mjs')],
99
+ confirmMessage: 'Atualizar o pacote global agora?',
100
+ },
101
+ {
102
+ key: 'privateRegistry',
103
+ aliases: ['private-registry', 'private', 'github-packages'],
104
+ label: 'Configurar registry privado GitHub Packages',
105
+ description: 'Prepara o .npmrc e valida o acesso ao pacote privado.',
106
+ command: nodeExecPath,
107
+ args: ['scripts/configure-private-registry.mjs', '--validate'],
108
+ confirmMessage: 'Rodar a configuracao de registry privado agora?',
109
+ },
110
+ ];
111
+ }
112
+
113
+ export function buildMenuChoices(commands) {
114
+ return commands.map((command) => ({
115
+ title: command.label,
116
+ description: command.description,
117
+ value: command.key,
118
+ })).concat({
119
+ title: 'Sair',
120
+ description: 'Fecha o menu operacional.',
121
+ value: '__exit__',
122
+ });
123
+ }
124
+
125
+ export function resolveActionKey(input, commands) {
126
+ const normalized = (input ?? '').trim().toLowerCase();
127
+ if (!normalized) {
128
+ return null;
129
+ }
130
+
131
+ return commands.find((command) =>
132
+ command.key.toLowerCase() === normalized || command.aliases.includes(normalized),
133
+ )?.key ?? null;
134
+ }
135
+
136
+ export function isInteractiveTerminal() {
137
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY);
138
+ }
139
+
140
+ export function formatStatusReport(status) {
141
+ const lines = [
142
+ 'Skill Master MCP - status local',
143
+ `Diretorio: ${status.rootDir}`,
144
+ `Pacote: ${status.packageName}`,
145
+ `Semver local: ${status.semver}`,
146
+ `Manifesto stable: ${status.manifestVersion}`,
147
+ `Manifesto semver: ${status.manifestSemver}`,
148
+ ];
149
+
150
+ if (status.versionText) {
151
+ lines.push('', 'VERSION.md:');
152
+ lines.push(...status.versionText.split('\n').slice(0, 6));
153
+ }
154
+
155
+ return lines.join('\n');
156
+ }
157
+
158
+ function renderPanelLines(lines, { color = ANSI.cyan, useColor = false } = {}) {
159
+ const width = Math.max(...lines.map((line) => line.length), 24);
160
+ const border = `+${'-'.repeat(width + 2)}+`;
161
+ const paintedBorder = colorize(border, color, useColor);
162
+ const body = lines.map((line) => `| ${line.padEnd(width)} |`);
163
+ return [paintedBorder, ...body, paintedBorder].join('\n');
164
+ }
165
+
166
+ export function formatMenuBanner(status, { useColor = false } = {}) {
167
+ const lines = [
168
+ colorize('Skill Master MCP', ANSI.bold, useColor),
169
+ 'Menu operacional para manutencao local',
170
+ `Versao local ${status.semver} | canal ${status.manifestVersion}`,
171
+ colorize('Setas + Enter para navegar', ANSI.dim, useColor),
172
+ ];
173
+ return renderPanelLines(lines, { color: ANSI.cyan, useColor });
174
+ }
175
+
176
+ export function formatActionHeader(action, { useColor = false } = {}) {
177
+ return renderPanelLines(
178
+ [
179
+ colorize(action.label, ANSI.bold, useColor),
180
+ action.description,
181
+ ],
182
+ { color: ANSI.green, useColor },
183
+ );
184
+ }
185
+
186
+ export function formatResultMessage(code, { useColor = false } = {}) {
187
+ if (code === 0) {
188
+ return colorize('Comando concluido com sucesso.', ANSI.green, useColor);
189
+ }
190
+
191
+ return colorize(`Comando terminou com codigo ${code}.`, ANSI.red, useColor);
192
+ }
193
+
194
+ export function formatHelp(commands) {
195
+ const actionList = commands.map((command) => ` - ${command.key}: ${command.label}`).join('\n');
196
+
197
+ return `Skill Master Menu
198
+
199
+ Uso:
200
+ skill-master-menu
201
+ skill-master-menu --status
202
+ skill-master-menu --run <acao>
203
+ skill-master-menu --run update --yes
204
+ skill-master-menu --help
205
+
206
+ Acoes disponiveis:
207
+ ${actionList}
208
+
209
+ O comando de menu e voltado para operacao humana. O binario MCP stdio continua sendo:
210
+ skill-master-mcp
211
+ `;
212
+ }
213
+
214
+ export function runCommand(action, { cwd, env = process.env } = {}) {
215
+ return new Promise((resolve) => {
216
+ const child = spawn(action.command, action.args, {
217
+ cwd,
218
+ env,
219
+ shell: process.platform === 'win32',
220
+ stdio: 'inherit',
221
+ });
222
+
223
+ child.on('close', (code) => {
224
+ resolve(code ?? 1);
225
+ });
226
+ });
227
+ }
@@ -1,179 +1,172 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { spawn } from 'node:child_process';
4
- import { existsSync, readFileSync } from 'node:fs';
5
- import { dirname, join } from 'node:path';
3
+ import prompts from 'prompts';
4
+ import { dirname } from 'node:path';
6
5
  import { fileURLToPath } from 'node:url';
7
- import { createInterface } from 'node:readline/promises';
8
- import { stdin as input, stdout as output } from 'node:process';
9
-
10
- const rootDir = dirname(dirname(fileURLToPath(import.meta.url)));
11
-
12
- const commands = {
13
- status: {
14
- label: 'Mostrar status local',
15
- command: process.execPath,
16
- args: [fileURLToPath(import.meta.url), '--status'],
17
- },
18
- check: {
19
- label: 'Rodar gate completo',
20
- command: 'npm',
21
- args: ['run', 'check'],
22
- },
23
- build: {
24
- label: 'Rodar build',
25
- command: 'npm',
26
- args: ['run', 'build'],
27
- },
28
- publicNpm: {
29
- label: 'Validar pacote no npm publico',
30
- command: 'npm',
31
- args: [
32
- 'view',
33
- '@fprad0/skill-master-mcp',
34
- 'version',
35
- '--registry=https://registry.npmjs.org',
36
- ],
37
- },
38
- updateGlobal: {
39
- label: 'Atualizar pacote global via npm',
40
- command: process.execPath,
41
- args: [join(rootDir, 'bin', 'skill-master-update.mjs')],
42
- },
43
- privateRegistry: {
44
- label: 'Configurar registry privado GitHub Packages',
45
- command: process.execPath,
46
- args: ['scripts/configure-private-registry.mjs', '--validate'],
47
- },
48
- };
49
-
50
- const menuItems = [
51
- ['1', commands.status],
52
- ['2', commands.check],
53
- ['3', commands.build],
54
- ['4', commands.publicNpm],
55
- ['5', commands.updateGlobal],
56
- ['6', commands.privateRegistry],
57
- ];
58
-
59
- function readJson(relativePath) {
60
- const target = join(rootDir, relativePath);
61
- if (!existsSync(target)) {
62
- return null;
6
+ import {
7
+ buildMenuChoices,
8
+ buildMenuCommands,
9
+ formatActionHeader,
10
+ formatHelp,
11
+ formatMenuBanner,
12
+ formatResultMessage,
13
+ formatStatusReport,
14
+ getMenuStatus,
15
+ isInteractiveTerminal,
16
+ resolveActionKey,
17
+ runCommand,
18
+ } from './lib/menu-core.mjs';
19
+
20
+ const currentFile = fileURLToPath(import.meta.url);
21
+ const rootDir = dirname(dirname(currentFile));
22
+ const commands = buildMenuCommands({ rootDir, currentFile });
23
+
24
+ function parseArgs(argv) {
25
+ const parsed = {
26
+ help: false,
27
+ status: false,
28
+ yes: false,
29
+ run: null,
30
+ };
31
+
32
+ for (let i = 0; i < argv.length; i += 1) {
33
+ const arg = argv[i];
34
+ switch (arg) {
35
+ case '--help':
36
+ case '-h':
37
+ parsed.help = true;
38
+ break;
39
+ case '--status':
40
+ parsed.status = true;
41
+ break;
42
+ case '--yes':
43
+ parsed.yes = true;
44
+ break;
45
+ case '--run':
46
+ parsed.run = argv[++i] ?? null;
47
+ break;
48
+ default:
49
+ throw new Error(`Unknown argument: ${arg}`);
50
+ }
63
51
  }
64
52
 
65
- return JSON.parse(readFileSync(target, 'utf8'));
53
+ return parsed;
66
54
  }
67
55
 
68
- function readText(relativePath) {
69
- const target = join(rootDir, relativePath);
70
- if (!existsSync(target)) {
71
- return null;
72
- }
56
+ function printHelp() {
57
+ console.log(formatHelp(commands));
58
+ }
73
59
 
74
- return readFileSync(target, 'utf8').trim();
60
+ function printStatus() {
61
+ console.log(formatStatusReport(getMenuStatus(rootDir)));
75
62
  }
76
63
 
77
- function printHelp() {
78
- console.log(`Skill Master Menu
64
+ async function runSelectedAction(action, { yes = false, useColor = false } = {}) {
65
+ if (action.confirmMessage && !yes) {
66
+ if (!isInteractiveTerminal()) {
67
+ throw new Error(`Action ${action.key} requires --yes outside an interactive terminal.`);
68
+ }
79
69
 
80
- Uso:
81
- skill-master-menu
82
- skill-master-menu --status
83
- skill-master-menu --help
70
+ const confirmation = await prompts({
71
+ type: 'confirm',
72
+ name: 'confirmed',
73
+ message: action.confirmMessage,
74
+ initial: false,
75
+ });
84
76
 
85
- Opcao 5 do menu:
86
- atualiza o pacote global com npm install -g @fprad0/skill-master-mcp@latest
77
+ if (!confirmation.confirmed) {
78
+ return { cancelled: true, code: 0 };
79
+ }
80
+ }
87
81
 
88
- O comando de menu e voltado para operacao humana. O binario MCP stdio continua sendo:
89
- skill-master-mcp
90
- `);
82
+ console.log('');
83
+ console.log(formatActionHeader(action, { useColor }));
84
+ console.log('');
85
+ const code = await runCommand(action, { cwd: rootDir });
86
+ console.log('');
87
+ console.log(formatResultMessage(code, { useColor }));
88
+ return { cancelled: false, code };
91
89
  }
92
90
 
93
- function printStatus() {
94
- const packageJson = readJson('package.json');
95
- const stableManifest = readJson('manifests/channels/stable.json');
96
- const versionText = readText('VERSION.md');
97
-
98
- console.log('Skill Master MCP - status local');
99
- console.log(`Diretorio: ${rootDir}`);
100
- console.log(`Pacote: ${packageJson?.name ?? 'nao encontrado'}`);
101
- console.log(`Semver local: ${packageJson?.version ?? 'nao encontrado'}`);
102
- console.log(`Manifesto stable: ${stableManifest?.version ?? 'nao encontrado'}`);
103
- console.log(`Manifesto semver: ${stableManifest?.semver ?? 'nao encontrado'}`);
104
-
105
- if (versionText) {
106
- const firstLines = versionText.split('\n').slice(0, 6).join('\n');
107
- console.log('\nVERSION.md:');
108
- console.log(firstLines);
109
- }
110
- }
91
+ async function runVisualMenu() {
92
+ while (true) {
93
+ console.clear();
94
+ const status = getMenuStatus(rootDir);
95
+ console.log(formatMenuBanner(status, { useColor: true }));
96
+ console.log('');
97
+
98
+ const selection = await prompts({
99
+ type: 'select',
100
+ name: 'action',
101
+ message: 'Escolha uma acao',
102
+ choices: buildMenuChoices(commands),
103
+ initial: 0,
104
+ });
111
105
 
112
- function runCommand(commandConfig) {
113
- return new Promise((resolve) => {
114
- console.log(`\n> ${commandConfig.command} ${commandConfig.args.join(' ')}\n`);
106
+ if (!selection.action || selection.action === '__exit__') {
107
+ return 0;
108
+ }
115
109
 
116
- const child = spawn(commandConfig.command, commandConfig.args, {
117
- cwd: rootDir,
118
- env: process.env,
119
- shell: process.platform === 'win32',
120
- stdio: 'inherit',
121
- });
110
+ const action = commands.find((entry) => entry.key === selection.action);
111
+ if (!action) {
112
+ return 1;
113
+ }
122
114
 
123
- child.on('close', (code) => {
124
- resolve(code ?? 1);
115
+ const result = await runSelectedAction(action, { useColor: true });
116
+ if (result.cancelled) {
117
+ continue;
118
+ }
119
+
120
+ const nextStep = await prompts({
121
+ type: 'toggle',
122
+ name: 'keepGoing',
123
+ message: 'Voltar ao menu?',
124
+ initial: true,
125
+ active: 'sim',
126
+ inactive: 'nao',
125
127
  });
126
- });
127
- }
128
128
 
129
- async function runInteractiveMenu() {
130
- const rl = createInterface({ input, output });
131
-
132
- try {
133
- while (true) {
134
- console.log('\nSkill Master Menu');
135
- for (const [key, item] of menuItems) {
136
- console.log(` ${key}. ${item.label}`);
137
- }
138
- console.log(' 0. Sair');
139
-
140
- const answer = (await rl.question('\nEscolha uma opcao: ')).trim();
141
-
142
- if (answer === '0' || answer.toLowerCase() === 'q') {
143
- return 0;
144
- }
145
-
146
- const selected = menuItems.find(([key]) => key === answer)?.[1];
147
- if (!selected) {
148
- console.log('Opcao invalida.');
149
- continue;
150
- }
151
-
152
- const code = await runCommand(selected);
153
- if (code !== 0) {
154
- console.log(`\nComando terminou com codigo ${code}.`);
155
- }
129
+ if (!nextStep.keepGoing) {
130
+ return result.code;
156
131
  }
157
- } finally {
158
- rl.close();
159
132
  }
160
133
  }
161
134
 
162
135
  async function main() {
163
- const args = process.argv.slice(2);
136
+ const args = parseArgs(process.argv.slice(2));
164
137
 
165
- if (args.includes('--help') || args.includes('-h')) {
138
+ if (args.help) {
166
139
  printHelp();
167
140
  return 0;
168
141
  }
169
142
 
170
- if (args.includes('--status')) {
143
+ if (args.status) {
171
144
  printStatus();
172
145
  return 0;
173
146
  }
174
147
 
175
- return runInteractiveMenu();
148
+ if (args.run) {
149
+ const actionKey = resolveActionKey(args.run, commands);
150
+ if (!actionKey) {
151
+ throw new Error(`Unknown action: ${args.run}`);
152
+ }
153
+
154
+ const action = commands.find((entry) => entry.key === actionKey);
155
+ const result = await runSelectedAction(action, { yes: args.yes, useColor: isInteractiveTerminal() });
156
+ return result.code;
157
+ }
158
+
159
+ if (!isInteractiveTerminal()) {
160
+ throw new Error('Interactive menu requires a TTY. Use --run <acao> or --status in automated environments.');
161
+ }
162
+
163
+ return runVisualMenu();
176
164
  }
177
165
 
178
- const exitCode = await main();
179
- process.exitCode = exitCode;
166
+ try {
167
+ process.exitCode = await main();
168
+ } catch (error) {
169
+ const message = error instanceof Error ? error.message : String(error);
170
+ process.stderr.write(`[skill_master] ${message}\n`);
171
+ process.exitCode = 1;
172
+ }
@@ -2,12 +2,12 @@
2
2
  "name": "skill_master",
3
3
  "channel": "beta",
4
4
  "version": "00.02-beta",
5
- "semver": "0.0.6",
6
- "publishedAt": "2026-06-26T16:45:00-03:00",
5
+ "semver": "0.0.7",
6
+ "publishedAt": "2026-06-26T20:15:00-03:00",
7
7
  "git": {
8
8
  "repo": "https://github.com/FPrad0/skill-master-mcp",
9
9
  "branch": "main",
10
- "commit": "c203ead"
10
+ "commit": "ec57c95"
11
11
  },
12
12
  "node": {
13
13
  "minimum": "18.0.0"
@@ -19,7 +19,7 @@
19
19
  "buildCommand": "npm run build"
20
20
  },
21
21
  "changelog": [
22
- "Canal beta acompanha o configurador privado mais seguro.",
23
- "Fluxos de token passam a suportar arquivo, stdin e armazenamento literal somente com opt-in."
22
+ "Canal beta acompanha o menu visual no terminal.",
23
+ "Fluxo interativo agora tem selecao visual, confirmacao e modo direto por acao."
24
24
  ]
25
25
  }
@@ -2,12 +2,12 @@
2
2
  "name": "skill_master",
3
3
  "channel": "stable",
4
4
  "version": "00.02",
5
- "semver": "0.0.6",
6
- "publishedAt": "2026-06-26T16:45:00-03:00",
5
+ "semver": "0.0.7",
6
+ "publishedAt": "2026-06-26T20:15:00-03:00",
7
7
  "git": {
8
8
  "repo": "https://github.com/FPrad0/skill-master-mcp",
9
9
  "branch": "main",
10
- "commit": "c203ead"
10
+ "commit": "ec57c95"
11
11
  },
12
12
  "node": {
13
13
  "minimum": "18.0.0"
@@ -19,8 +19,8 @@
19
19
  "buildCommand": "npm run build"
20
20
  },
21
21
  "changelog": [
22
- "Configurador privado passa a gravar referencia de variavel de ambiente por padrao.",
23
- "Validacao de registry HTTPS, backups com timestamp, dry-run redigido e permissao 0600 em POSIX.",
24
- "Novas entradas --token-file, --token-stdin e --store-token."
22
+ "Menu operacional ganha interface visual no terminal com prompts.",
23
+ "Core do menu foi extraido para modulo reutilizavel e testavel.",
24
+ "Compatibilidade Node 18+ foi preservada sem migrar para TUI pesada."
25
25
  ]
26
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fprad0/skill-master-mcp",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Personal MCP server that catalogs, recommends and reports skills with update-aware metadata.",
@@ -51,6 +51,7 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@modelcontextprotocol/sdk": "^1.29.0",
54
+ "prompts": "^2.4.2",
54
55
  "zod": "^4.4.3"
55
56
  },
56
57
  "devDependencies": {