@tankpkg/mcp-server 0.4.2 → 0.5.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 (63) hide show
  1. package/README.md +41 -33
  2. package/dist/index.js +24 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/lib/api-client.d.ts +6 -5
  5. package/dist/lib/api-client.d.ts.map +1 -1
  6. package/dist/lib/api-client.js +6 -6
  7. package/dist/lib/api-client.js.map +1 -1
  8. package/dist/lib/packer.d.ts +20 -0
  9. package/dist/lib/packer.d.ts.map +1 -1
  10. package/dist/lib/packer.js +85 -0
  11. package/dist/lib/packer.js.map +1 -1
  12. package/dist/tools/audit-skill.d.ts +3 -0
  13. package/dist/tools/audit-skill.d.ts.map +1 -0
  14. package/dist/tools/audit-skill.js +213 -0
  15. package/dist/tools/audit-skill.js.map +1 -0
  16. package/dist/tools/doctor.d.ts +3 -0
  17. package/dist/tools/doctor.d.ts.map +1 -0
  18. package/dist/tools/doctor.js +158 -0
  19. package/dist/tools/doctor.js.map +1 -0
  20. package/dist/tools/init-skill.d.ts +3 -0
  21. package/dist/tools/init-skill.d.ts.map +1 -0
  22. package/dist/tools/init-skill.js +72 -0
  23. package/dist/tools/init-skill.js.map +1 -0
  24. package/dist/tools/install-skill.d.ts +3 -0
  25. package/dist/tools/install-skill.d.ts.map +1 -0
  26. package/dist/tools/install-skill.js +206 -0
  27. package/dist/tools/install-skill.js.map +1 -0
  28. package/dist/tools/link-skill.d.ts +3 -0
  29. package/dist/tools/link-skill.d.ts.map +1 -0
  30. package/dist/tools/link-skill.js +81 -0
  31. package/dist/tools/link-skill.js.map +1 -0
  32. package/dist/tools/logout.d.ts +3 -0
  33. package/dist/tools/logout.d.ts.map +1 -0
  34. package/dist/tools/logout.js +19 -0
  35. package/dist/tools/logout.js.map +1 -0
  36. package/dist/tools/remove-skill.d.ts +3 -0
  37. package/dist/tools/remove-skill.d.ts.map +1 -0
  38. package/dist/tools/remove-skill.js +110 -0
  39. package/dist/tools/remove-skill.js.map +1 -0
  40. package/dist/tools/scan-skill.d.ts.map +1 -1
  41. package/dist/tools/scan-skill.js +41 -18
  42. package/dist/tools/scan-skill.js.map +1 -1
  43. package/dist/tools/skill-permissions.d.ts +3 -0
  44. package/dist/tools/skill-permissions.d.ts.map +1 -0
  45. package/dist/tools/skill-permissions.js +311 -0
  46. package/dist/tools/skill-permissions.js.map +1 -0
  47. package/dist/tools/unlink-skill.d.ts +3 -0
  48. package/dist/tools/unlink-skill.d.ts.map +1 -0
  49. package/dist/tools/unlink-skill.js +72 -0
  50. package/dist/tools/unlink-skill.js.map +1 -0
  51. package/dist/tools/update-skill.d.ts +3 -0
  52. package/dist/tools/update-skill.d.ts.map +1 -0
  53. package/dist/tools/update-skill.js +317 -0
  54. package/dist/tools/update-skill.js.map +1 -0
  55. package/dist/tools/verify-skills.d.ts +3 -0
  56. package/dist/tools/verify-skills.d.ts.map +1 -0
  57. package/dist/tools/verify-skills.js +121 -0
  58. package/dist/tools/verify-skills.js.map +1 -0
  59. package/dist/tools/whoami.d.ts +3 -0
  60. package/dist/tools/whoami.d.ts.map +1 -0
  61. package/dist/tools/whoami.js +29 -0
  62. package/dist/tools/whoami.js.map +1 -0
  63. package/package.json +1 -1
@@ -0,0 +1,110 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { z } from 'zod';
4
+ const SCOPED_NAME_PATTERN = /^@[a-z0-9-]+\/[a-z0-9][a-z0-9-]*$/;
5
+ export function registerRemoveSkillTool(server) {
6
+ server.tool('remove-skill', 'Remove an installed skill from the project. Removes from skills.json, skills.lock, and deletes skill files.', {
7
+ name: z.string().describe('Skill name in @org/name format'),
8
+ directory: z.string().optional().describe('Project directory (defaults to current working directory)'),
9
+ }, async ({ name, directory }) => {
10
+ if (!SCOPED_NAME_PATTERN.test(name)) {
11
+ return {
12
+ content: [{
13
+ type: 'text',
14
+ text: `Validation error: Skill name "${name}" must use the @org/name format (e.g. @acme/my-skill).`,
15
+ }],
16
+ isError: true,
17
+ };
18
+ }
19
+ const dir = directory ? path.resolve(directory) : process.cwd();
20
+ const results = [];
21
+ let skillFoundAnywhere = false;
22
+ const skillsJsonPath = path.join(dir, 'skills.json');
23
+ if (fs.existsSync(skillsJsonPath)) {
24
+ try {
25
+ const raw = fs.readFileSync(skillsJsonPath, 'utf-8');
26
+ const skillsJson = JSON.parse(raw);
27
+ const skills = (skillsJson.skills ?? {});
28
+ if (name in skills) {
29
+ skillFoundAnywhere = true;
30
+ delete skills[name];
31
+ skillsJson.skills = skills;
32
+ fs.writeFileSync(skillsJsonPath, JSON.stringify(skillsJson, null, 2) + '\n');
33
+ results.push(`Removed "${name}" from skills.json`);
34
+ }
35
+ }
36
+ catch {
37
+ results.push('Warning: Failed to read or parse skills.json');
38
+ }
39
+ }
40
+ const lockPath = path.join(dir, 'skills.lock');
41
+ if (fs.existsSync(lockPath)) {
42
+ try {
43
+ const raw = fs.readFileSync(lockPath, 'utf-8');
44
+ const lock = JSON.parse(raw);
45
+ let removedFromLock = false;
46
+ for (const key of Object.keys(lock.skills)) {
47
+ const lastAt = key.lastIndexOf('@');
48
+ if (lastAt <= 0)
49
+ continue;
50
+ const keyName = key.slice(0, lastAt);
51
+ if (keyName === name) {
52
+ delete lock.skills[key];
53
+ removedFromLock = true;
54
+ skillFoundAnywhere = true;
55
+ }
56
+ }
57
+ if (removedFromLock) {
58
+ const sortedSkills = {};
59
+ for (const key of Object.keys(lock.skills).sort()) {
60
+ sortedSkills[key] = lock.skills[key];
61
+ }
62
+ lock.skills = sortedSkills;
63
+ fs.writeFileSync(lockPath, JSON.stringify(lock, null, 2) + '\n');
64
+ results.push(`Removed "${name}" from skills.lock`);
65
+ }
66
+ }
67
+ catch {
68
+ results.push('Warning: Failed to read or parse skills.lock');
69
+ }
70
+ }
71
+ const skillDir = getSkillDir(dir, name);
72
+ if (fs.existsSync(skillDir)) {
73
+ skillFoundAnywhere = true;
74
+ fs.rmSync(skillDir, { recursive: true, force: true });
75
+ results.push(`Deleted skill files from ${skillDir}`);
76
+ }
77
+ else {
78
+ results.push(`Skill files were already absent from ${skillDir}`);
79
+ }
80
+ const symlinkName = name.replace(/\//g, '__');
81
+ const agentSkillDir = path.join(dir, '.tank', 'agent-skills', symlinkName);
82
+ if (fs.existsSync(agentSkillDir)) {
83
+ fs.rmSync(agentSkillDir, { recursive: true, force: true });
84
+ results.push('Removed symlink from agent workspace');
85
+ }
86
+ if (!skillFoundAnywhere) {
87
+ return {
88
+ content: [{
89
+ type: 'text',
90
+ text: `Skill "${name}" is not installed. It was not found in skills.json, skills.lock, or .tank/skills/.`,
91
+ }],
92
+ isError: true,
93
+ };
94
+ }
95
+ return {
96
+ content: [{
97
+ type: 'text',
98
+ text: `Successfully removed ${name}.\n${results.join('\n')}`,
99
+ }],
100
+ };
101
+ });
102
+ }
103
+ function getSkillDir(projectDir, skillName) {
104
+ if (skillName.startsWith('@')) {
105
+ const [scope, name] = skillName.split('/');
106
+ return path.join(projectDir, '.tank', 'skills', scope, name);
107
+ }
108
+ return path.join(projectDir, '.tank', 'skills', skillName);
109
+ }
110
+ //# sourceMappingURL=remove-skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-skill.js","sourceRoot":"","sources":["../../src/tools/remove-skill.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scan-skill.d.ts","sourceRoot":"","sources":["../../src/tools/scan-skill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgCzE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgK7D"}
1
+ {"version":3,"file":"scan-skill.d.ts","sourceRoot":"","sources":["../../src/tools/scan-skill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiCzE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+L7D"}
@@ -1,7 +1,8 @@
1
1
  import { z } from 'zod';
2
+ import fs from 'node:fs';
2
3
  import path from 'node:path';
3
4
  import { TankApiClient } from '../lib/api-client.js';
4
- import { pack } from '../lib/packer.js';
5
+ import { pack, packForScan } from '../lib/packer.js';
5
6
  import { getConfig } from '../lib/config.js';
6
7
  export function registerScanSkillTool(server) {
7
8
  server.tool('scan-skill', 'Scan a skill directory for security issues. Requires authentication.', {
@@ -32,20 +33,40 @@ export function registerScanSkillTool(server) {
32
33
  ],
33
34
  };
34
35
  }
35
- // Pack the skill
36
36
  let packResult;
37
- try {
38
- packResult = await pack(absDir);
37
+ let usedSynthesisedManifest = false;
38
+ const skillsJsonPath = path.join(absDir, 'skills.json');
39
+ const hasSkillsJson = fs.existsSync(skillsJsonPath);
40
+ if (hasSkillsJson) {
41
+ try {
42
+ packResult = await pack(absDir);
43
+ }
44
+ catch (err) {
45
+ return {
46
+ content: [
47
+ {
48
+ type: 'text',
49
+ text: `Failed to pack skill: ${err instanceof Error ? err.message : String(err)}`,
50
+ },
51
+ ],
52
+ };
53
+ }
39
54
  }
40
- catch (err) {
41
- return {
42
- content: [
43
- {
44
- type: 'text',
45
- text: `Failed to pack skill: ${err instanceof Error ? err.message : String(err)}`,
46
- },
47
- ],
48
- };
55
+ else {
56
+ try {
57
+ packResult = await packForScan(absDir);
58
+ usedSynthesisedManifest = true;
59
+ }
60
+ catch (err) {
61
+ return {
62
+ content: [
63
+ {
64
+ type: 'text',
65
+ text: `Failed to pack directory for scan: ${err instanceof Error ? err.message : String(err)}`,
66
+ },
67
+ ],
68
+ };
69
+ }
49
70
  }
50
71
  const manifest = packResult.manifest;
51
72
  const skillName = manifest.name ?? 'unknown';
@@ -91,12 +112,14 @@ export function registerScanSkillTool(server) {
91
112
  const lines = [
92
113
  `## Scan Results for ${skillName}@${skillVersion}`,
93
114
  '',
94
- `**Verdict:** ${verdictEmoji[scanResult.verdict] ?? ''} ${scanResult.verdict.toUpperCase()}`,
95
- `**Score:** ${scanResult.audit_score.toFixed(1)}/10`,
96
- `**Duration:** ${(scanResult.duration_ms / 1000).toFixed(1)}s`,
97
- `**Files:** ${packResult.fileCount} (${(packResult.totalSize / 1024).toFixed(1)}KB)`,
98
- '',
99
115
  ];
116
+ if (usedSynthesisedManifest) {
117
+ lines.push('> **Note:** No `skills.json` found. A synthesised manifest was used for scanning.');
118
+ lines.push('');
119
+ }
120
+ const auditScore = scanResult.audit_score ?? 0;
121
+ const durationMs = scanResult.duration_ms ?? 0;
122
+ lines.push(`**Verdict:** ${verdictEmoji[scanResult.verdict] ?? ''} ${scanResult.verdict.toUpperCase()}`, `**Score:** ${auditScore.toFixed(1)}/10`, `**Duration:** ${(durationMs / 1000).toFixed(1)}s`, `**Files:** ${packResult.fileCount} (${(packResult.totalSize / 1024).toFixed(1)}KB)`, '');
100
123
  if (scanResult.findings.length > 0) {
101
124
  lines.push(`### Findings (${scanResult.findings.length})`);
102
125
  lines.push('');
@@ -1 +1 @@
1
- {"version":3,"file":"scan-skill.js","sourceRoot":"","sources":["../../src/tools/scan-skill.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scan-skill.js","sourceRoot":"","sources":["../../src/tools/scan-skill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerSkillPermissionsTool(server: McpServer): void;
3
+ //# sourceMappingURL=skill-permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-permissions.d.ts","sourceRoot":"","sources":["../../src/tools/skill-permissions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsMzE,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA2KpE"}
@@ -0,0 +1,311 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { z } from 'zod';
4
+ function parseSkillName(key) {
5
+ const lastAt = key.lastIndexOf('@');
6
+ if (lastAt > 0) {
7
+ return key.slice(0, lastAt);
8
+ }
9
+ return key;
10
+ }
11
+ function collectPermissions(lockfile) {
12
+ const networkMap = new Map();
13
+ const fsReadMap = new Map();
14
+ const fsWriteMap = new Map();
15
+ const subprocessSkills = [];
16
+ const envMap = new Map();
17
+ const execMap = new Map();
18
+ for (const [key, entry] of Object.entries(lockfile.skills)) {
19
+ const skillName = parseSkillName(key);
20
+ const perms = entry.permissions;
21
+ if (perms.network?.outbound) {
22
+ for (const domain of perms.network.outbound) {
23
+ const existing = networkMap.get(domain) ?? [];
24
+ existing.push(skillName);
25
+ networkMap.set(domain, existing);
26
+ }
27
+ }
28
+ if (perms.filesystem?.read) {
29
+ for (const p of perms.filesystem.read) {
30
+ const existing = fsReadMap.get(p) ?? [];
31
+ existing.push(skillName);
32
+ fsReadMap.set(p, existing);
33
+ }
34
+ }
35
+ if (perms.filesystem?.write) {
36
+ for (const p of perms.filesystem.write) {
37
+ const existing = fsWriteMap.get(p) ?? [];
38
+ existing.push(skillName);
39
+ fsWriteMap.set(p, existing);
40
+ }
41
+ }
42
+ if (perms.subprocess === true) {
43
+ subprocessSkills.push(skillName);
44
+ }
45
+ const rawPerms = perms;
46
+ if (Array.isArray(rawPerms.env)) {
47
+ for (const envVar of rawPerms.env) {
48
+ const existing = envMap.get(envVar) ?? [];
49
+ existing.push(skillName);
50
+ envMap.set(envVar, existing);
51
+ }
52
+ }
53
+ if (Array.isArray(rawPerms.exec)) {
54
+ for (const cmd of rawPerms.exec) {
55
+ const existing = execMap.get(cmd) ?? [];
56
+ existing.push(skillName);
57
+ execMap.set(cmd, existing);
58
+ }
59
+ }
60
+ }
61
+ const toEntries = (map) => Array.from(map.entries()).map(([value, skills]) => ({ value, skills }));
62
+ return {
63
+ networkOutbound: toEntries(networkMap),
64
+ filesystemRead: toEntries(fsReadMap),
65
+ filesystemWrite: toEntries(fsWriteMap),
66
+ subprocess: subprocessSkills,
67
+ env: toEntries(envMap),
68
+ exec: toEntries(execMap),
69
+ };
70
+ }
71
+ function formatAttribution(skills) {
72
+ return '<- ' + skills.join(', ');
73
+ }
74
+ function formatSection(title, entries) {
75
+ const lines = [];
76
+ lines.push(`${title}:`);
77
+ if (entries.length === 0) {
78
+ lines.push(' none');
79
+ }
80
+ else {
81
+ for (const entry of entries) {
82
+ lines.push(` ${entry.value} ${formatAttribution(entry.skills)}`);
83
+ }
84
+ }
85
+ return lines.join('\n');
86
+ }
87
+ // Wildcard matching: *.example.com matches sub.example.com, * matches all
88
+ function isDomainAllowed(domain, allowedDomains) {
89
+ for (const allowed of allowedDomains) {
90
+ if (allowed === '*')
91
+ return true;
92
+ if (allowed === domain)
93
+ return true;
94
+ if (allowed.startsWith('*.')) {
95
+ const suffix = allowed.slice(1);
96
+ if (domain.endsWith(suffix) || domain === allowed.slice(2)) {
97
+ return true;
98
+ }
99
+ if (domain === allowed)
100
+ return true;
101
+ }
102
+ }
103
+ return false;
104
+ }
105
+ // Glob matching: ./src/** matches ./src/foo/bar
106
+ function isPathAllowed(requestedPath, allowedPaths) {
107
+ for (const allowed of allowedPaths) {
108
+ if (allowed === requestedPath)
109
+ return true;
110
+ if (allowed.endsWith('/**')) {
111
+ const prefix = allowed.slice(0, -3);
112
+ if (requestedPath.startsWith(prefix))
113
+ return true;
114
+ }
115
+ }
116
+ return false;
117
+ }
118
+ function checkBudget(resolved, budget) {
119
+ const violations = [];
120
+ const budgetDomains = budget.network?.outbound ?? [];
121
+ for (const entry of resolved.networkOutbound) {
122
+ if (!isDomainAllowed(entry.value, budgetDomains)) {
123
+ violations.push({
124
+ category: 'network outbound',
125
+ value: entry.value,
126
+ skills: entry.skills,
127
+ });
128
+ }
129
+ }
130
+ const budgetReadPaths = budget.filesystem?.read ?? [];
131
+ for (const entry of resolved.filesystemRead) {
132
+ if (!isPathAllowed(entry.value, budgetReadPaths)) {
133
+ violations.push({
134
+ category: 'filesystem read',
135
+ value: entry.value,
136
+ skills: entry.skills,
137
+ });
138
+ }
139
+ }
140
+ const budgetWritePaths = budget.filesystem?.write ?? [];
141
+ for (const entry of resolved.filesystemWrite) {
142
+ if (!isPathAllowed(entry.value, budgetWritePaths)) {
143
+ violations.push({
144
+ category: 'filesystem write',
145
+ value: entry.value,
146
+ skills: entry.skills,
147
+ });
148
+ }
149
+ }
150
+ if (resolved.subprocess.length > 0 && budget.subprocess !== true) {
151
+ violations.push({
152
+ category: 'subprocess',
153
+ value: 'subprocess access',
154
+ skills: resolved.subprocess,
155
+ });
156
+ }
157
+ return violations;
158
+ }
159
+ export function registerSkillPermissionsTool(server) {
160
+ server.tool('skill-permissions', 'Display resolved permission summary for installed skills. Shows what capabilities each skill requires and checks against the project permission budget.', {
161
+ directory: z.string().optional().describe('Project directory path (defaults to current working directory)'),
162
+ }, async ({ directory }) => {
163
+ const dir = directory ? path.resolve(directory) : process.cwd();
164
+ if (!fs.existsSync(dir)) {
165
+ return {
166
+ content: [{
167
+ type: 'text',
168
+ text: `Directory does not exist: ${dir}`,
169
+ }],
170
+ isError: true,
171
+ };
172
+ }
173
+ const skillsJsonPath = path.join(dir, 'skills.json');
174
+ if (!fs.existsSync(skillsJsonPath)) {
175
+ return {
176
+ content: [{
177
+ type: 'text',
178
+ text: 'No skills.json found. Run "init-skill" to create one.',
179
+ }],
180
+ isError: true,
181
+ };
182
+ }
183
+ let skillsJson;
184
+ try {
185
+ const raw = fs.readFileSync(skillsJsonPath, 'utf-8');
186
+ skillsJson = JSON.parse(raw);
187
+ }
188
+ catch {
189
+ return {
190
+ content: [{
191
+ type: 'text',
192
+ text: 'Failed to parse skills.json. The file may be corrupted.',
193
+ }],
194
+ isError: true,
195
+ };
196
+ }
197
+ const skillDeps = skillsJson.skills ?? {};
198
+ if (Object.keys(skillDeps).length === 0) {
199
+ return {
200
+ content: [{
201
+ type: 'text',
202
+ text: 'No skills with permissions to display. The project has no skill dependencies.',
203
+ }],
204
+ };
205
+ }
206
+ const lockfilePath = path.join(dir, 'skills.lock');
207
+ if (!fs.existsSync(lockfilePath)) {
208
+ return {
209
+ content: [{
210
+ type: 'text',
211
+ text: 'No skills.lock found. Skills are declared but not installed. Run install to generate a lockfile.',
212
+ }],
213
+ };
214
+ }
215
+ let lockfile;
216
+ try {
217
+ const raw = fs.readFileSync(lockfilePath, 'utf-8');
218
+ lockfile = JSON.parse(raw);
219
+ }
220
+ catch {
221
+ return {
222
+ content: [{
223
+ type: 'text',
224
+ text: 'Failed to parse skills.lock. The file may be corrupted.',
225
+ }],
226
+ isError: true,
227
+ };
228
+ }
229
+ if (!lockfile.skills || Object.keys(lockfile.skills).length === 0) {
230
+ return {
231
+ content: [{
232
+ type: 'text',
233
+ text: 'No skills installed. The lockfile is empty.',
234
+ }],
235
+ };
236
+ }
237
+ const resolved = collectPermissions(lockfile);
238
+ const lines = [];
239
+ lines.push('Resolved permissions for this project:');
240
+ lines.push('');
241
+ lines.push(formatSection('Network (outbound)', resolved.networkOutbound));
242
+ lines.push(formatSection('Filesystem (read)', resolved.filesystemRead));
243
+ lines.push(formatSection('Filesystem (write)', resolved.filesystemWrite));
244
+ lines.push('Subprocess:');
245
+ if (resolved.subprocess.length === 0) {
246
+ lines.push(' none');
247
+ }
248
+ else {
249
+ lines.push(` allowed ${formatAttribution(resolved.subprocess)}`);
250
+ }
251
+ if (resolved.env.length > 0) {
252
+ lines.push(formatSection('Environment variables', resolved.env));
253
+ }
254
+ if (resolved.exec.length > 0) {
255
+ lines.push(formatSection('Exec', resolved.exec));
256
+ }
257
+ lines.push('');
258
+ lines.push('Per-skill breakdown:');
259
+ for (const [key, entry] of Object.entries(lockfile.skills)) {
260
+ const skillName = parseSkillName(key);
261
+ const perms = entry.permissions;
262
+ const permParts = [];
263
+ if (perms.network?.outbound && perms.network.outbound.length > 0) {
264
+ permParts.push(`network: ${perms.network.outbound.join(', ')}`);
265
+ }
266
+ if (perms.filesystem?.read && perms.filesystem.read.length > 0) {
267
+ permParts.push(`filesystem:read: ${perms.filesystem.read.join(', ')}`);
268
+ }
269
+ if (perms.filesystem?.write && perms.filesystem.write.length > 0) {
270
+ permParts.push(`filesystem:write: ${perms.filesystem.write.join(', ')}`);
271
+ }
272
+ if (perms.subprocess === true) {
273
+ permParts.push('subprocess: allowed');
274
+ }
275
+ const rawPerms = perms;
276
+ if (Array.isArray(rawPerms.env) && rawPerms.env.length > 0) {
277
+ permParts.push(`env: ${rawPerms.env.join(', ')}`);
278
+ }
279
+ if (Array.isArray(rawPerms.exec) && rawPerms.exec.length > 0) {
280
+ permParts.push(`exec: ${rawPerms.exec.join(', ')}`);
281
+ }
282
+ if (permParts.length === 0) {
283
+ lines.push(` ${skillName}: no special permissions`);
284
+ }
285
+ else {
286
+ lines.push(` ${skillName}: ${permParts.join('; ')}`);
287
+ }
288
+ }
289
+ const budget = skillsJson.permissions;
290
+ lines.push('');
291
+ if (!budget) {
292
+ lines.push('Budget status: No budget defined');
293
+ }
294
+ else {
295
+ const violations = checkBudget(resolved, budget);
296
+ if (violations.length === 0) {
297
+ lines.push('Budget status: PASS (all within budget)');
298
+ }
299
+ else {
300
+ lines.push('Budget status: FAIL');
301
+ for (const v of violations) {
302
+ lines.push(` - ${v.category}: "${v.value}" not in budget (requested by ${v.skills.join(', ')})`);
303
+ }
304
+ }
305
+ }
306
+ return {
307
+ content: [{ type: 'text', text: lines.join('\n') }],
308
+ };
309
+ });
310
+ }
311
+ //# sourceMappingURL=skill-permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-permissions.js","sourceRoot":"","sources":["../../src/tools/skill-permissions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerUnlinkSkillTool(server: McpServer): void;
3
+ //# sourceMappingURL=unlink-skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unlink-skill.d.ts","sourceRoot":"","sources":["../../src/tools/unlink-skill.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKzE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAqE/D"}
@@ -0,0 +1,72 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { z } from 'zod';
4
+ const SCOPED_NAME_PATTERN = /^@[a-z0-9-]+\/[a-z0-9][a-z0-9-]*$/;
5
+ export function registerUnlinkSkillTool(server) {
6
+ server.tool('unlink-skill', 'Unlink a skill from an agent workspace. Removes the symlink without deleting the installed skill files.', {
7
+ name: z.string().describe('Skill name in @org/name format'),
8
+ workspace: z.string().describe('Agent workspace directory path'),
9
+ directory: z.string().optional().describe('Project directory where skills are installed (defaults to current working directory)'),
10
+ }, async ({ name, workspace, directory }) => {
11
+ if (!SCOPED_NAME_PATTERN.test(name)) {
12
+ return {
13
+ content: [{
14
+ type: 'text',
15
+ text: `Validation error: Skill name "${name}" must use the @org/name format (e.g. @acme/my-skill).`,
16
+ }],
17
+ isError: true,
18
+ };
19
+ }
20
+ const projectDir = directory ? path.resolve(directory) : process.cwd();
21
+ const workspaceDir = path.resolve(workspace);
22
+ if (!fs.existsSync(workspaceDir)) {
23
+ return {
24
+ content: [{
25
+ type: 'text',
26
+ text: `Error: Workspace directory does not exist: ${workspaceDir}`,
27
+ }],
28
+ isError: true,
29
+ };
30
+ }
31
+ const skillDir = getSkillDir(projectDir, name);
32
+ if (!fs.existsSync(skillDir)) {
33
+ return {
34
+ content: [{
35
+ type: 'text',
36
+ text: `Skill "${name}" is not installed. It was not found in ${skillDir}.`,
37
+ }],
38
+ isError: true,
39
+ };
40
+ }
41
+ const [scope, skillName] = name.split('/');
42
+ const symlinkPath = path.join(workspaceDir, '.skills', scope, skillName);
43
+ try {
44
+ const stats = fs.lstatSync(symlinkPath);
45
+ if (stats.isSymbolicLink()) {
46
+ fs.unlinkSync(symlinkPath);
47
+ return {
48
+ content: [{
49
+ type: 'text',
50
+ text: `Successfully unlinked "${name}" from ${workspaceDir}.\nRemoved symlink: ${symlinkPath}`,
51
+ }],
52
+ };
53
+ }
54
+ }
55
+ catch {
56
+ }
57
+ return {
58
+ content: [{
59
+ type: 'text',
60
+ text: `No link exists for "${name}" in ${workspaceDir}.`,
61
+ }],
62
+ };
63
+ });
64
+ }
65
+ function getSkillDir(projectDir, skillName) {
66
+ if (skillName.startsWith('@')) {
67
+ const [scope, name] = skillName.split('/');
68
+ return path.join(projectDir, '.tank', 'skills', scope, name);
69
+ }
70
+ return path.join(projectDir, '.tank', 'skills', skillName);
71
+ }
72
+ //# sourceMappingURL=unlink-skill.js.map