@codemcp/skills 1.7.1 → 1.8.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.
- package/dist/cli.mjs +53 -18
- package/dist/cli.mjs.map +1 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -549,13 +549,17 @@ async function parseSkillMd(skillMdPath, options) {
|
|
|
549
549
|
if (typeof data.name !== "string" || typeof data.description !== "string") return null;
|
|
550
550
|
if (data.metadata?.internal === true && !shouldInstallInternalSkills() && !options?.includeInternal) return null;
|
|
551
551
|
const rawMcpDeps = data["requires-mcp-servers"];
|
|
552
|
+
const rawAllowedTools = data["allowed-tools"];
|
|
553
|
+
let allowedTools;
|
|
554
|
+
if (typeof rawAllowedTools === "string") allowedTools = rawAllowedTools.split(/\s+/).filter(Boolean);
|
|
552
555
|
return {
|
|
553
556
|
name: data.name,
|
|
554
557
|
description: data.description,
|
|
555
558
|
path: dirname(skillMdPath),
|
|
556
559
|
rawContent: content,
|
|
557
560
|
metadata: data.metadata,
|
|
558
|
-
requiresMcpServers: Array.isArray(rawMcpDeps) ? rawMcpDeps : void 0
|
|
561
|
+
requiresMcpServers: Array.isArray(rawMcpDeps) ? rawMcpDeps : void 0,
|
|
562
|
+
allowedTools
|
|
559
563
|
};
|
|
560
564
|
} catch {
|
|
561
565
|
return null;
|
|
@@ -2352,7 +2356,7 @@ function createEmptyLocalLock() {
|
|
|
2352
2356
|
skills: {}
|
|
2353
2357
|
};
|
|
2354
2358
|
}
|
|
2355
|
-
var version$1 = "1.
|
|
2359
|
+
var version$1 = "1.8.1";
|
|
2356
2360
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
2357
2361
|
/**
|
|
2358
2362
|
* Check if a source identifier (owner/repo format) represents a private GitHub repo.
|
|
@@ -4837,17 +4841,39 @@ async function generateSkillsMcpAgent(agentType, cwd, scope = "local", extraServ
|
|
|
4837
4841
|
*/
|
|
4838
4842
|
/**
|
|
4839
4843
|
* Load all installed skills for the given scope and return the unique set of
|
|
4840
|
-
* MCP server dependencies declared across them
|
|
4844
|
+
* MCP server dependencies declared across them, along with per-server allowed
|
|
4845
|
+
* tool restrictions derived from skill `allowed-tools` frontmatter.
|
|
4841
4846
|
*/
|
|
4842
4847
|
async function loadInstalledSkillMcpDeps(cwd, scope) {
|
|
4843
4848
|
const isGlobal = scope === "global";
|
|
4844
4849
|
const searchDirs = [getCanonicalSkillsDir(isGlobal, cwd), getMCPCanonicalSkillsDir(isGlobal, cwd)];
|
|
4845
4850
|
const seen = /* @__PURE__ */ new Map();
|
|
4851
|
+
const serverToolSets = /* @__PURE__ */ new Map();
|
|
4846
4852
|
for (const dir of searchDirs) try {
|
|
4847
4853
|
const skills = await discoverSkills(dir, void 0, { fullDepth: true });
|
|
4848
|
-
for (const skill of skills) for (const dep of skill.requiresMcpServers ?? [])
|
|
4854
|
+
for (const skill of skills) for (const dep of skill.requiresMcpServers ?? []) {
|
|
4855
|
+
if (!seen.has(dep.name)) seen.set(dep.name, dep);
|
|
4856
|
+
const skillAllowedTools = skill.allowedTools;
|
|
4857
|
+
const serverName = dep.name;
|
|
4858
|
+
if (!skillAllowedTools || skillAllowedTools.length === 0) serverToolSets.set(serverName, "wildcard");
|
|
4859
|
+
else if (serverToolSets.get(serverName) !== "wildcard") {
|
|
4860
|
+
const prefix = `@${serverName}/`;
|
|
4861
|
+
const serverTools = skillAllowedTools.filter((t) => t.startsWith(prefix)).map((t) => t.slice(prefix.length));
|
|
4862
|
+
if (serverTools.length === 0) serverToolSets.set(serverName, "wildcard");
|
|
4863
|
+
else {
|
|
4864
|
+
const existing = serverToolSets.get(serverName);
|
|
4865
|
+
if (existing instanceof Set) for (const t of serverTools) existing.add(t);
|
|
4866
|
+
else serverToolSets.set(serverName, new Set(serverTools));
|
|
4867
|
+
}
|
|
4868
|
+
}
|
|
4869
|
+
}
|
|
4849
4870
|
} catch {}
|
|
4850
|
-
|
|
4871
|
+
const allowedToolsByServer = {};
|
|
4872
|
+
for (const [serverName, toolsOrWildcard] of serverToolSets.entries()) if (toolsOrWildcard instanceof Set) allowedToolsByServer[serverName] = [...toolsOrWildcard];
|
|
4873
|
+
return {
|
|
4874
|
+
deps: [...seen.values()],
|
|
4875
|
+
allowedToolsByServer
|
|
4876
|
+
};
|
|
4851
4877
|
}
|
|
4852
4878
|
/** Replace `{{PARAM_NAME}}` placeholders with resolved values. */
|
|
4853
4879
|
function substituteParam(value, params) {
|
|
@@ -4896,13 +4922,17 @@ async function resolveParameters(dep) {
|
|
|
4896
4922
|
* In all cases the diff rule is: only check presence of the server key —
|
|
4897
4923
|
* never modify an existing server's configuration.
|
|
4898
4924
|
*
|
|
4899
|
-
* @param deps
|
|
4900
|
-
* @param agentTypes
|
|
4901
|
-
* @param configCwd
|
|
4902
|
-
* @param scope
|
|
4903
|
-
* @param configMode
|
|
4925
|
+
* @param deps MCP server dependencies collected from installed skills.
|
|
4926
|
+
* @param agentTypes Agents that were just configured by `mcp setup`.
|
|
4927
|
+
* @param configCwd Base directory for agent config files.
|
|
4928
|
+
* @param scope 'local' or 'global'.
|
|
4929
|
+
* @param configMode Whether generator-backed agents use agent-config or mcp-json.
|
|
4930
|
+
* @param allowedToolsByServer Per-server tool restrictions derived from skill allowedTools.
|
|
4931
|
+
* When provided and a server has an entry, only those specific
|
|
4932
|
+
* tools are whitelisted in the generated agent config instead of
|
|
4933
|
+
* the default wildcard.
|
|
4904
4934
|
*/
|
|
4905
|
-
async function configureSkillMcpDepsForAgents(deps, agentTypes, configCwd, scope, configMode = "agent-config") {
|
|
4935
|
+
async function configureSkillMcpDepsForAgents(deps, agentTypes, configCwd, scope, configMode = "agent-config", allowedToolsByServer = {}) {
|
|
4906
4936
|
if (deps.length === 0 || agentTypes.length === 0) return;
|
|
4907
4937
|
const resolvedConfigs = /* @__PURE__ */ new Map();
|
|
4908
4938
|
for (const dep of deps) {
|
|
@@ -4915,11 +4945,13 @@ async function configureSkillMcpDepsForAgents(deps, agentTypes, configCwd, scope
|
|
|
4915
4945
|
const missingServers = {};
|
|
4916
4946
|
for (const dep of deps) {
|
|
4917
4947
|
const resolved = resolvedConfigs.get(dep.name);
|
|
4948
|
+
const restrictedTools = allowedToolsByServer[dep.name];
|
|
4918
4949
|
missingServers[dep.name] = {
|
|
4919
4950
|
command: resolved.command,
|
|
4920
4951
|
args: resolved.args,
|
|
4921
4952
|
env: resolved.env,
|
|
4922
|
-
...resolved.cwd ? { cwd: resolved.cwd } : {}
|
|
4953
|
+
...resolved.cwd ? { cwd: resolved.cwd } : {},
|
|
4954
|
+
...restrictedTools ? { tools: restrictedTools } : {}
|
|
4923
4955
|
};
|
|
4924
4956
|
}
|
|
4925
4957
|
try {
|
|
@@ -5106,7 +5138,10 @@ async function setupTuiMode(cwd, scope = "local", forcedConfigMode) {
|
|
|
5106
5138
|
console.log("");
|
|
5107
5139
|
const configuredAgents = [];
|
|
5108
5140
|
for (const agentType of selectedAgents) if (await configureOneAgent(agentType, configCwd, scope, configMode) !== null) configuredAgents.push(agentType);
|
|
5109
|
-
if (configuredAgents.length > 0)
|
|
5141
|
+
if (configuredAgents.length > 0) {
|
|
5142
|
+
const { deps: skillDeps, allowedToolsByServer } = await loadInstalledSkillMcpDeps(cwd, scope);
|
|
5143
|
+
await configureSkillMcpDepsForAgents(skillDeps, configuredAgents, configCwd, scope, configMode, allowedToolsByServer);
|
|
5144
|
+
}
|
|
5110
5145
|
const scopeLabel = scope === "global" ? "global (home directory)" : "local (project directory)";
|
|
5111
5146
|
const failCount = selectedAgents.length - configuredAgents.length;
|
|
5112
5147
|
console.log("");
|
|
@@ -5124,17 +5159,17 @@ async function setupCliMode(agentTypes, cwd, scope = "local", forcedConfigMode)
|
|
|
5124
5159
|
const configuredAgents = [];
|
|
5125
5160
|
for (const agentType of agentTypes) if (await configureOneAgent(agentType, cwd, scope, forcedConfigMode ?? (isGeneratorBacked(agentType) ? "agent-config" : "mcp-json")) !== null) configuredAgents.push(agentType);
|
|
5126
5161
|
if (configuredAgents.length > 0) {
|
|
5127
|
-
const skillDeps = await loadInstalledSkillMcpDeps(cwd, scope);
|
|
5162
|
+
const { deps: skillDeps, allowedToolsByServer } = await loadInstalledSkillMcpDeps(cwd, scope);
|
|
5128
5163
|
if (forcedConfigMode) {
|
|
5129
5164
|
const generatorBacked = configuredAgents.filter((a) => isGeneratorBacked(a));
|
|
5130
5165
|
const rawMcp = configuredAgents.filter((a) => !isGeneratorBacked(a));
|
|
5131
|
-
if (generatorBacked.length > 0) await configureSkillMcpDepsForAgents(skillDeps, generatorBacked, cwd, scope, forcedConfigMode);
|
|
5132
|
-
if (rawMcp.length > 0) await configureSkillMcpDepsForAgents(skillDeps, rawMcp, cwd, scope, "mcp-json");
|
|
5166
|
+
if (generatorBacked.length > 0) await configureSkillMcpDepsForAgents(skillDeps, generatorBacked, cwd, scope, forcedConfigMode, allowedToolsByServer);
|
|
5167
|
+
if (rawMcp.length > 0) await configureSkillMcpDepsForAgents(skillDeps, rawMcp, cwd, scope, "mcp-json", allowedToolsByServer);
|
|
5133
5168
|
} else {
|
|
5134
5169
|
const generatorBacked = configuredAgents.filter((a) => isGeneratorBacked(a));
|
|
5135
5170
|
const rawMcp = configuredAgents.filter((a) => !isGeneratorBacked(a));
|
|
5136
|
-
if (generatorBacked.length > 0) await configureSkillMcpDepsForAgents(skillDeps, generatorBacked, cwd, scope, "agent-config");
|
|
5137
|
-
if (rawMcp.length > 0) await configureSkillMcpDepsForAgents(skillDeps, rawMcp, cwd, scope, "mcp-json");
|
|
5171
|
+
if (generatorBacked.length > 0) await configureSkillMcpDepsForAgents(skillDeps, generatorBacked, cwd, scope, "agent-config", allowedToolsByServer);
|
|
5172
|
+
if (rawMcp.length > 0) await configureSkillMcpDepsForAgents(skillDeps, rawMcp, cwd, scope, "mcp-json", allowedToolsByServer);
|
|
5138
5173
|
}
|
|
5139
5174
|
}
|
|
5140
5175
|
const failCount = agentTypes.length - configuredAgents.length;
|