@thantos66/claude-context-mcp 0.1.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.
- package/LICENSE +21 -0
- package/README.md +171 -0
- package/dist/constants.d.ts +33 -0
- package/dist/constants.js +59 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/agent-frontmatter.d.ts +55 -0
- package/dist/schemas/agent-frontmatter.js +43 -0
- package/dist/schemas/agent-frontmatter.js.map +1 -0
- package/dist/schemas/mcp-config.d.ts +177 -0
- package/dist/schemas/mcp-config.js +38 -0
- package/dist/schemas/mcp-config.js.map +1 -0
- package/dist/schemas/settings.d.ts +70 -0
- package/dist/schemas/settings.js +28 -0
- package/dist/schemas/settings.js.map +1 -0
- package/dist/schemas/skill-frontmatter.d.ts +42 -0
- package/dist/schemas/skill-frontmatter.js +27 -0
- package/dist/schemas/skill-frontmatter.js.map +1 -0
- package/dist/services/agents.d.ts +56 -0
- package/dist/services/agents.js +155 -0
- package/dist/services/agents.js.map +1 -0
- package/dist/services/atomic-write.d.ts +10 -0
- package/dist/services/atomic-write.js +46 -0
- package/dist/services/atomic-write.js.map +1 -0
- package/dist/services/backup.d.ts +13 -0
- package/dist/services/backup.js +52 -0
- package/dist/services/backup.js.map +1 -0
- package/dist/services/mcp-config.d.ts +72 -0
- package/dist/services/mcp-config.js +163 -0
- package/dist/services/mcp-config.js.map +1 -0
- package/dist/services/paths.d.ts +42 -0
- package/dist/services/paths.js +91 -0
- package/dist/services/paths.js.map +1 -0
- package/dist/services/permissions.d.ts +38 -0
- package/dist/services/permissions.js +104 -0
- package/dist/services/permissions.js.map +1 -0
- package/dist/services/skills.d.ts +62 -0
- package/dist/services/skills.js +181 -0
- package/dist/services/skills.js.map +1 -0
- package/dist/tools/agents.d.ts +2 -0
- package/dist/tools/agents.js +134 -0
- package/dist/tools/agents.js.map +1 -0
- package/dist/tools/helpers.d.ts +25 -0
- package/dist/tools/helpers.js +36 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/mcp.d.ts +2 -0
- package/dist/tools/mcp.js +257 -0
- package/dist/tools/mcp.js.map +1 -0
- package/dist/tools/meta.d.ts +2 -0
- package/dist/tools/meta.js +79 -0
- package/dist/tools/meta.js.map +1 -0
- package/dist/tools/permissions.d.ts +2 -0
- package/dist/tools/permissions.js +144 -0
- package/dist/tools/permissions.js.map +1 -0
- package/dist/tools/skills.d.ts +2 -0
- package/dist/tools/skills.js +160 -0
- package/dist/tools/skills.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { McpConfigFileSchema, McpServerEntrySchema, isStdioServer, } from "../schemas/mcp-config.js";
|
|
3
|
+
import { atomicWriteFile, stringifyJson } from "./atomic-write.js";
|
|
4
|
+
import { backupFile } from "./backup.js";
|
|
5
|
+
import { mcpConfigPathFor } from "./paths.js";
|
|
6
|
+
const SECRET_KEY_RX = /(key|token|secret|password|apikey)/i;
|
|
7
|
+
/** Load an MCP config file, returning `{ mcpServers: {} }` if absent. */
|
|
8
|
+
export async function loadMcpConfig(path) {
|
|
9
|
+
let raw;
|
|
10
|
+
try {
|
|
11
|
+
raw = await fs.readFile(path, "utf8");
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
if (err.code === "ENOENT") {
|
|
15
|
+
return { mcpServers: {} };
|
|
16
|
+
}
|
|
17
|
+
throw err;
|
|
18
|
+
}
|
|
19
|
+
let parsed;
|
|
20
|
+
try {
|
|
21
|
+
parsed = JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
throw new Error(`Invalid JSON in ${path}: ${err.message}`);
|
|
25
|
+
}
|
|
26
|
+
return McpConfigFileSchema.parse(parsed);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Write an MCP config file: backup → atomic write.
|
|
30
|
+
* When `dryRun: true`, returns a diff and leaves disk untouched.
|
|
31
|
+
*/
|
|
32
|
+
export async function saveMcpConfig(path, next, { dryRun = false } = {}) {
|
|
33
|
+
const validated = McpConfigFileSchema.parse(next);
|
|
34
|
+
const nextText = stringifyJson(validated);
|
|
35
|
+
if (dryRun) {
|
|
36
|
+
let prevText = "";
|
|
37
|
+
try {
|
|
38
|
+
prevText = await fs.readFile(path, "utf8");
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err.code !== "ENOENT")
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
path,
|
|
46
|
+
backup: null,
|
|
47
|
+
dryRun: true,
|
|
48
|
+
diff: makeUnifiedDiff(prevText, nextText, path),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const backup = await backupFile(path);
|
|
52
|
+
await atomicWriteFile(path, nextText);
|
|
53
|
+
return { path, backup, dryRun: false };
|
|
54
|
+
}
|
|
55
|
+
/** List servers across one scope. Redacts secrets by default. */
|
|
56
|
+
export async function listServers(scope, opts = {}) {
|
|
57
|
+
const path = mcpConfigPathFor(scope, opts.projectPath);
|
|
58
|
+
const cfg = await loadMcpConfig(path);
|
|
59
|
+
const entries = Object.entries(cfg.mcpServers ?? {});
|
|
60
|
+
return entries.map(([name, entry]) => ({
|
|
61
|
+
scope,
|
|
62
|
+
name,
|
|
63
|
+
path,
|
|
64
|
+
entry: opts.revealSecrets ? entry : redactSecrets(entry),
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
/** Add or replace a server entry in a scope. */
|
|
68
|
+
export async function addServer(params) {
|
|
69
|
+
const { scope, name, entry, projectPath, dryRun, overwrite } = params;
|
|
70
|
+
const validatedEntry = McpServerEntrySchema.parse(entry);
|
|
71
|
+
const path = mcpConfigPathFor(scope, projectPath);
|
|
72
|
+
const cfg = await loadMcpConfig(path);
|
|
73
|
+
cfg.mcpServers ??= {};
|
|
74
|
+
if (!overwrite && cfg.mcpServers[name] !== undefined) {
|
|
75
|
+
throw new Error(`MCP server "${name}" already exists in ${path}. Pass overwrite: true to replace.`);
|
|
76
|
+
}
|
|
77
|
+
cfg.mcpServers[name] = validatedEntry;
|
|
78
|
+
return saveMcpConfig(path, cfg, { dryRun });
|
|
79
|
+
}
|
|
80
|
+
/** Patch individual fields of an existing server entry. */
|
|
81
|
+
export async function updateServer(params) {
|
|
82
|
+
const { scope, name, patch, projectPath, dryRun } = params;
|
|
83
|
+
const path = mcpConfigPathFor(scope, projectPath);
|
|
84
|
+
const cfg = await loadMcpConfig(path);
|
|
85
|
+
const current = cfg.mcpServers?.[name];
|
|
86
|
+
if (!current) {
|
|
87
|
+
throw new Error(`MCP server "${name}" not found in ${path}.`);
|
|
88
|
+
}
|
|
89
|
+
const merged = { ...current, ...patch };
|
|
90
|
+
cfg.mcpServers[name] = McpServerEntrySchema.parse(merged);
|
|
91
|
+
return saveMcpConfig(path, cfg, { dryRun });
|
|
92
|
+
}
|
|
93
|
+
/** Remove a server by name. */
|
|
94
|
+
export async function removeServer(params) {
|
|
95
|
+
const { scope, name, projectPath, dryRun } = params;
|
|
96
|
+
const path = mcpConfigPathFor(scope, projectPath);
|
|
97
|
+
const cfg = await loadMcpConfig(path);
|
|
98
|
+
if (!cfg.mcpServers?.[name]) {
|
|
99
|
+
throw new Error(`MCP server "${name}" not found in ${path}.`);
|
|
100
|
+
}
|
|
101
|
+
delete cfg.mcpServers[name];
|
|
102
|
+
return saveMcpConfig(path, cfg, { dryRun });
|
|
103
|
+
}
|
|
104
|
+
/** Toggle the `disabled` flag on an existing server entry. */
|
|
105
|
+
export async function setServerDisabled(params) {
|
|
106
|
+
return updateServer({
|
|
107
|
+
scope: params.scope,
|
|
108
|
+
name: params.name,
|
|
109
|
+
patch: { disabled: params.disabled },
|
|
110
|
+
projectPath: params.projectPath,
|
|
111
|
+
dryRun: params.dryRun,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/** Get a single server entry. */
|
|
115
|
+
export async function getServer(params) {
|
|
116
|
+
const { scope, name, projectPath, revealSecrets } = params;
|
|
117
|
+
const path = mcpConfigPathFor(scope, projectPath);
|
|
118
|
+
const cfg = await loadMcpConfig(path);
|
|
119
|
+
const entry = cfg.mcpServers?.[name];
|
|
120
|
+
if (!entry)
|
|
121
|
+
return null;
|
|
122
|
+
return {
|
|
123
|
+
scope,
|
|
124
|
+
name,
|
|
125
|
+
path,
|
|
126
|
+
entry: revealSecrets ? entry : redactSecrets(entry),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** Replace env-value secrets with "[REDACTED]" unless explicitly opted in. */
|
|
130
|
+
function redactSecrets(entry) {
|
|
131
|
+
if (!isStdioServer(entry) || !entry.env)
|
|
132
|
+
return entry;
|
|
133
|
+
const redactedEnv = {};
|
|
134
|
+
for (const [k, v] of Object.entries(entry.env)) {
|
|
135
|
+
redactedEnv[k] = SECRET_KEY_RX.test(k) ? "[REDACTED]" : v;
|
|
136
|
+
}
|
|
137
|
+
return { ...entry, env: redactedEnv };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Minimal unified diff for dry-run output. Not a full diff engine — just
|
|
141
|
+
* enough to read at a glance in tool responses.
|
|
142
|
+
*/
|
|
143
|
+
export function makeUnifiedDiff(a, b, label) {
|
|
144
|
+
if (a === b)
|
|
145
|
+
return `# no changes to ${label}\n`;
|
|
146
|
+
const aLines = a.split("\n");
|
|
147
|
+
const bLines = b.split("\n");
|
|
148
|
+
const header = `--- ${label} (current)\n+++ ${label} (proposed)\n`;
|
|
149
|
+
const body = [];
|
|
150
|
+
const max = Math.max(aLines.length, bLines.length);
|
|
151
|
+
for (let i = 0; i < max; i++) {
|
|
152
|
+
const aL = aLines[i];
|
|
153
|
+
const bL = bLines[i];
|
|
154
|
+
if (aL === bL)
|
|
155
|
+
continue;
|
|
156
|
+
if (aL !== undefined)
|
|
157
|
+
body.push(`- ${aL}`);
|
|
158
|
+
if (bL !== undefined)
|
|
159
|
+
body.push(`+ ${bL}`);
|
|
160
|
+
}
|
|
161
|
+
return header + body.join("\n") + "\n";
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=mcp-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-config.js","sourceRoot":"","sources":["../../src/services/mcp-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EAGpB,aAAa,GACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG9C,MAAM,aAAa,GAAG,qCAAqC,CAAC;AAS5D,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;QAC5B,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,IAAmB,EACnB,EAAE,MAAM,GAAG,KAAK,KAA2B,EAAE;IAE7C,MAAM,SAAS,GAAG,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IAE1C,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,GAAG,CAAC;QAClE,CAAC;QACD,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,IAAI;YACZ,IAAI,EAAE,eAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC;SAChD,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACtC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACzC,CAAC;AASD,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAY,EACZ,OAA0D,EAAE;IAE5D,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;IACrD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACrC,KAAK;QACL,IAAI;QACJ,IAAI;QACJ,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC;KACzD,CAAC,CAAC,CAAC;AACN,CAAC;AAED,gDAAgD;AAChD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAO/B;IACC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IACtE,MAAM,cAAc,GAAG,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IACtC,GAAG,CAAC,UAAU,KAAK,EAAE,CAAC;IACtB,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CACb,eAAe,IAAI,uBAAuB,IAAI,oCAAoC,CACnF,CAAC;IACJ,CAAC;IACD,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC;IACtC,OAAO,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,2DAA2D;AAC3D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAMlC;IACC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC3D,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,kBAAkB,IAAI,GAAG,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,MAAM,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,EAAoB,CAAC;IAC1D,GAAG,CAAC,UAAW,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3D,OAAO,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,+BAA+B;AAC/B,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAKlC;IACC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IACpD,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,kBAAkB,IAAI,GAAG,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAMvC;IACC,OAAO,YAAY,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAA6B;QAC/D,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,CAAC;AACL,CAAC;AAED,iCAAiC;AACjC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAK/B;IACC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,MAAM,CAAC;IAC3D,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO;QACL,KAAK;QACL,IAAI;QACJ,IAAI;QACJ,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,SAAS,aAAa,CAAC,KAAqB;IAC1C,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,WAAW,GAA2B,EAAE,CAAC;IAC/C,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,WAAW,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,CAAS,EACT,CAAS,EACT,KAAa;IAEb,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,mBAAmB,KAAK,IAAI,CAAC;IACjD,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,OAAO,KAAK,mBAAmB,KAAK,eAAe,CAAC;IACnE,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,EAAE,KAAK,EAAE;YAAE,SAAS;QACxB,IAAI,EAAE,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC3C,IAAI,EAAE,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type Scope } from "../constants.js";
|
|
2
|
+
/**
|
|
3
|
+
* Throws if `projectPath` is not a usable absolute path.
|
|
4
|
+
*
|
|
5
|
+
* Guards against two footguns:
|
|
6
|
+
* 1. Relative paths (ambiguous — we can't know what they're relative to).
|
|
7
|
+
* 2. Paths outside the user's home directory (likely a typo or attack).
|
|
8
|
+
* Opt-out with `allowOutsideHome: true` on the per-call basis.
|
|
9
|
+
*/
|
|
10
|
+
export declare function assertValidProjectPath(projectPath: string, { allowOutsideHome }?: {
|
|
11
|
+
allowOutsideHome?: boolean;
|
|
12
|
+
}): void;
|
|
13
|
+
/** Resolve the MCP servers config file for a given scope. */
|
|
14
|
+
export declare function mcpConfigPathFor(scope: Scope, projectPath?: string): string;
|
|
15
|
+
/** Resolve the settings.json file for a given Claude Code scope. */
|
|
16
|
+
export declare function settingsPathFor(scope: "user" | "project", projectPath?: string): string;
|
|
17
|
+
/** Resolve the agents directory for a given Claude Code scope. */
|
|
18
|
+
export declare function agentsDirFor(scope: "user" | "project", projectPath?: string): string;
|
|
19
|
+
/** Resolve the skills directory for a given Claude Code scope. */
|
|
20
|
+
export declare function skillsDirFor(scope: "user" | "project", projectPath?: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Summary of every config path the tool knows about for the current OS.
|
|
23
|
+
* Returned from the `meta_platform_paths` tool for discovery/debugging.
|
|
24
|
+
*/
|
|
25
|
+
export declare function allPlatformPaths(projectPath?: string): {
|
|
26
|
+
platform: NodeJS.Platform;
|
|
27
|
+
desktop: {
|
|
28
|
+
mcpServers: string;
|
|
29
|
+
};
|
|
30
|
+
user: {
|
|
31
|
+
mcpServers: string;
|
|
32
|
+
settings: string;
|
|
33
|
+
agents: string;
|
|
34
|
+
skills: string;
|
|
35
|
+
};
|
|
36
|
+
project: {
|
|
37
|
+
mcpServers: string;
|
|
38
|
+
settings: string;
|
|
39
|
+
agents: string;
|
|
40
|
+
skills: string;
|
|
41
|
+
} | null;
|
|
42
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import { claudeDesktopConfigPath, claudeCodeUserJsonPath, claudeCodeUserSettingsPath, claudeCodeUserAgentsDir, claudeCodeUserSkillsDir, projectMcpJsonPath, projectSettingsPath, projectAgentsDir, projectSkillsDir, } from "../constants.js";
|
|
4
|
+
/**
|
|
5
|
+
* Throws if `projectPath` is not a usable absolute path.
|
|
6
|
+
*
|
|
7
|
+
* Guards against two footguns:
|
|
8
|
+
* 1. Relative paths (ambiguous — we can't know what they're relative to).
|
|
9
|
+
* 2. Paths outside the user's home directory (likely a typo or attack).
|
|
10
|
+
* Opt-out with `allowOutsideHome: true` on the per-call basis.
|
|
11
|
+
*/
|
|
12
|
+
export function assertValidProjectPath(projectPath, { allowOutsideHome = false } = {}) {
|
|
13
|
+
if (!path.isAbsolute(projectPath)) {
|
|
14
|
+
throw new Error(`projectPath must be absolute, got ${JSON.stringify(projectPath)}`);
|
|
15
|
+
}
|
|
16
|
+
if (!allowOutsideHome) {
|
|
17
|
+
const home = os.homedir();
|
|
18
|
+
const rel = path.relative(home, projectPath);
|
|
19
|
+
if (rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
20
|
+
throw new Error(`projectPath ${JSON.stringify(projectPath)} is outside $HOME (${home}). ` +
|
|
21
|
+
`Pass allowOutsideHome: true to override.`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Resolve the MCP servers config file for a given scope. */
|
|
26
|
+
export function mcpConfigPathFor(scope, projectPath) {
|
|
27
|
+
switch (scope) {
|
|
28
|
+
case "desktop":
|
|
29
|
+
return claudeDesktopConfigPath();
|
|
30
|
+
case "user":
|
|
31
|
+
return claudeCodeUserJsonPath();
|
|
32
|
+
case "project": {
|
|
33
|
+
if (!projectPath)
|
|
34
|
+
throw new Error("projectPath required for scope=project");
|
|
35
|
+
assertValidProjectPath(projectPath);
|
|
36
|
+
return projectMcpJsonPath(projectPath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Resolve the settings.json file for a given Claude Code scope. */
|
|
41
|
+
export function settingsPathFor(scope, projectPath) {
|
|
42
|
+
if (scope === "user")
|
|
43
|
+
return claudeCodeUserSettingsPath();
|
|
44
|
+
if (!projectPath)
|
|
45
|
+
throw new Error("projectPath required for scope=project");
|
|
46
|
+
assertValidProjectPath(projectPath);
|
|
47
|
+
return projectSettingsPath(projectPath);
|
|
48
|
+
}
|
|
49
|
+
/** Resolve the agents directory for a given Claude Code scope. */
|
|
50
|
+
export function agentsDirFor(scope, projectPath) {
|
|
51
|
+
if (scope === "user")
|
|
52
|
+
return claudeCodeUserAgentsDir();
|
|
53
|
+
if (!projectPath)
|
|
54
|
+
throw new Error("projectPath required for scope=project");
|
|
55
|
+
assertValidProjectPath(projectPath);
|
|
56
|
+
return projectAgentsDir(projectPath);
|
|
57
|
+
}
|
|
58
|
+
/** Resolve the skills directory for a given Claude Code scope. */
|
|
59
|
+
export function skillsDirFor(scope, projectPath) {
|
|
60
|
+
if (scope === "user")
|
|
61
|
+
return claudeCodeUserSkillsDir();
|
|
62
|
+
if (!projectPath)
|
|
63
|
+
throw new Error("projectPath required for scope=project");
|
|
64
|
+
assertValidProjectPath(projectPath);
|
|
65
|
+
return projectSkillsDir(projectPath);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Summary of every config path the tool knows about for the current OS.
|
|
69
|
+
* Returned from the `meta_platform_paths` tool for discovery/debugging.
|
|
70
|
+
*/
|
|
71
|
+
export function allPlatformPaths(projectPath) {
|
|
72
|
+
return {
|
|
73
|
+
platform: process.platform,
|
|
74
|
+
desktop: { mcpServers: claudeDesktopConfigPath() },
|
|
75
|
+
user: {
|
|
76
|
+
mcpServers: claudeCodeUserJsonPath(),
|
|
77
|
+
settings: claudeCodeUserSettingsPath(),
|
|
78
|
+
agents: claudeCodeUserAgentsDir(),
|
|
79
|
+
skills: claudeCodeUserSkillsDir(),
|
|
80
|
+
},
|
|
81
|
+
project: projectPath
|
|
82
|
+
? {
|
|
83
|
+
mcpServers: projectMcpJsonPath(projectPath),
|
|
84
|
+
settings: projectSettingsPath(projectPath),
|
|
85
|
+
agents: projectAgentsDir(projectPath),
|
|
86
|
+
skills: projectSkillsDir(projectPath),
|
|
87
|
+
}
|
|
88
|
+
: null,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/services/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type SettingsFile, type PermissionsBlock, type DefaultMode, type PermissionListName } from "../schemas/settings.js";
|
|
2
|
+
import { type WriteResult } from "./mcp-config.js";
|
|
3
|
+
/** Load settings.json, returning an empty object if absent. */
|
|
4
|
+
export declare function loadSettings(path: string): Promise<SettingsFile>;
|
|
5
|
+
/** Return the permissions block for a scope, merging empty lists as needed. */
|
|
6
|
+
export declare function listPermissions(scope: "user" | "project", projectPath?: string): Promise<{
|
|
7
|
+
path: string;
|
|
8
|
+
permissions: Required<PermissionsBlock>;
|
|
9
|
+
defaultMode?: DefaultMode;
|
|
10
|
+
}>;
|
|
11
|
+
/** Add rule(s) to one of allow|deny|ask. Idempotent: duplicates are skipped. */
|
|
12
|
+
export declare function addRules(params: {
|
|
13
|
+
scope: "user" | "project";
|
|
14
|
+
list: PermissionListName;
|
|
15
|
+
rules: string[];
|
|
16
|
+
projectPath?: string;
|
|
17
|
+
dryRun?: boolean;
|
|
18
|
+
}): Promise<WriteResult & {
|
|
19
|
+
added: string[];
|
|
20
|
+
alreadyPresent: string[];
|
|
21
|
+
}>;
|
|
22
|
+
/** Remove one rule (by exact string) from allow|deny|ask. */
|
|
23
|
+
export declare function removeRule(params: {
|
|
24
|
+
scope: "user" | "project";
|
|
25
|
+
list: PermissionListName;
|
|
26
|
+
rule: string;
|
|
27
|
+
projectPath?: string;
|
|
28
|
+
dryRun?: boolean;
|
|
29
|
+
}): Promise<WriteResult & {
|
|
30
|
+
removed: boolean;
|
|
31
|
+
}>;
|
|
32
|
+
/** Set the `defaultMode` field on settings.json. */
|
|
33
|
+
export declare function setDefaultMode(params: {
|
|
34
|
+
scope: "user" | "project";
|
|
35
|
+
mode: DefaultMode;
|
|
36
|
+
projectPath?: string;
|
|
37
|
+
dryRun?: boolean;
|
|
38
|
+
}): Promise<WriteResult>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { SettingsFileSchema, } from "../schemas/settings.js";
|
|
3
|
+
import { atomicWriteFile, stringifyJson } from "./atomic-write.js";
|
|
4
|
+
import { backupFile } from "./backup.js";
|
|
5
|
+
import { settingsPathFor } from "./paths.js";
|
|
6
|
+
import { makeUnifiedDiff } from "./mcp-config.js";
|
|
7
|
+
/** Load settings.json, returning an empty object if absent. */
|
|
8
|
+
export async function loadSettings(path) {
|
|
9
|
+
try {
|
|
10
|
+
const raw = await fs.readFile(path, "utf8");
|
|
11
|
+
const parsed = JSON.parse(raw);
|
|
12
|
+
return SettingsFileSchema.parse(parsed);
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
if (err.code === "ENOENT")
|
|
16
|
+
return {};
|
|
17
|
+
throw err;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function saveSettings(path, next, { dryRun = false } = {}) {
|
|
21
|
+
const validated = SettingsFileSchema.parse(next);
|
|
22
|
+
const nextText = stringifyJson(validated);
|
|
23
|
+
if (dryRun) {
|
|
24
|
+
let prevText = "";
|
|
25
|
+
try {
|
|
26
|
+
prevText = await fs.readFile(path, "utf8");
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (err.code !== "ENOENT")
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
path,
|
|
34
|
+
backup: null,
|
|
35
|
+
dryRun: true,
|
|
36
|
+
diff: makeUnifiedDiff(prevText, nextText, path),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const backup = await backupFile(path);
|
|
40
|
+
await atomicWriteFile(path, nextText);
|
|
41
|
+
return { path, backup, dryRun: false };
|
|
42
|
+
}
|
|
43
|
+
/** Return the permissions block for a scope, merging empty lists as needed. */
|
|
44
|
+
export async function listPermissions(scope, projectPath) {
|
|
45
|
+
const path = settingsPathFor(scope, projectPath);
|
|
46
|
+
const settings = await loadSettings(path);
|
|
47
|
+
const p = settings.permissions ?? {};
|
|
48
|
+
return {
|
|
49
|
+
path,
|
|
50
|
+
permissions: {
|
|
51
|
+
allow: p.allow ?? [],
|
|
52
|
+
deny: p.deny ?? [],
|
|
53
|
+
ask: p.ask ?? [],
|
|
54
|
+
},
|
|
55
|
+
defaultMode: settings.defaultMode,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** Add rule(s) to one of allow|deny|ask. Idempotent: duplicates are skipped. */
|
|
59
|
+
export async function addRules(params) {
|
|
60
|
+
const { scope, list, rules, projectPath, dryRun } = params;
|
|
61
|
+
const path = settingsPathFor(scope, projectPath);
|
|
62
|
+
const settings = await loadSettings(path);
|
|
63
|
+
settings.permissions ??= {};
|
|
64
|
+
const current = (settings.permissions[list] ??= []);
|
|
65
|
+
const added = [];
|
|
66
|
+
const alreadyPresent = [];
|
|
67
|
+
for (const rule of rules) {
|
|
68
|
+
if (current.includes(rule)) {
|
|
69
|
+
alreadyPresent.push(rule);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
current.push(rule);
|
|
73
|
+
added.push(rule);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const result = await saveSettings(path, settings, { dryRun });
|
|
77
|
+
return { ...result, added, alreadyPresent };
|
|
78
|
+
}
|
|
79
|
+
/** Remove one rule (by exact string) from allow|deny|ask. */
|
|
80
|
+
export async function removeRule(params) {
|
|
81
|
+
const { scope, list, rule, projectPath, dryRun } = params;
|
|
82
|
+
const path = settingsPathFor(scope, projectPath);
|
|
83
|
+
const settings = await loadSettings(path);
|
|
84
|
+
const arr = settings.permissions?.[list];
|
|
85
|
+
if (!arr) {
|
|
86
|
+
return { path, backup: null, dryRun: dryRun ?? false, removed: false };
|
|
87
|
+
}
|
|
88
|
+
const idx = arr.indexOf(rule);
|
|
89
|
+
if (idx === -1) {
|
|
90
|
+
return { path, backup: null, dryRun: dryRun ?? false, removed: false };
|
|
91
|
+
}
|
|
92
|
+
arr.splice(idx, 1);
|
|
93
|
+
const result = await saveSettings(path, settings, { dryRun });
|
|
94
|
+
return { ...result, removed: true };
|
|
95
|
+
}
|
|
96
|
+
/** Set the `defaultMode` field on settings.json. */
|
|
97
|
+
export async function setDefaultMode(params) {
|
|
98
|
+
const { scope, mode, projectPath, dryRun } = params;
|
|
99
|
+
const path = settingsPathFor(scope, projectPath);
|
|
100
|
+
const settings = await loadSettings(path);
|
|
101
|
+
settings.defaultMode = mode;
|
|
102
|
+
return saveSettings(path, settings, { dryRun });
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/services/permissions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type SkillFrontmatter } from "../schemas/skill-frontmatter.js";
|
|
2
|
+
export interface SkillRecord {
|
|
3
|
+
scope: "user" | "project";
|
|
4
|
+
name: string;
|
|
5
|
+
dir: string;
|
|
6
|
+
skillMdPath: string;
|
|
7
|
+
frontmatter: SkillFrontmatter;
|
|
8
|
+
body: string;
|
|
9
|
+
}
|
|
10
|
+
export interface SkillWriteResult {
|
|
11
|
+
path: string;
|
|
12
|
+
backup: string | null;
|
|
13
|
+
dryRun: boolean;
|
|
14
|
+
preview?: string;
|
|
15
|
+
}
|
|
16
|
+
/** List all skill folders under the scope's skills dir. */
|
|
17
|
+
export declare function listSkills(scope: "user" | "project", projectPath?: string): Promise<SkillRecord[]>;
|
|
18
|
+
export declare function getSkill(params: {
|
|
19
|
+
scope: "user" | "project";
|
|
20
|
+
name: string;
|
|
21
|
+
projectPath?: string;
|
|
22
|
+
}): Promise<SkillRecord | null>;
|
|
23
|
+
/** Serialize a skill record to SKILL.md contents. */
|
|
24
|
+
export declare function serializeSkill(frontmatter: SkillFrontmatter, body: string): string;
|
|
25
|
+
/** Scaffold a new skill folder with a SKILL.md. */
|
|
26
|
+
export declare function createSkill(params: {
|
|
27
|
+
scope: "user" | "project";
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
|
+
allowedTools?: string;
|
|
31
|
+
model?: string;
|
|
32
|
+
body?: string;
|
|
33
|
+
projectPath?: string;
|
|
34
|
+
overwrite?: boolean;
|
|
35
|
+
dryRun?: boolean;
|
|
36
|
+
}): Promise<SkillWriteResult>;
|
|
37
|
+
/** Patch frontmatter fields or replace the SKILL.md body. */
|
|
38
|
+
export declare function updateSkill(params: {
|
|
39
|
+
scope: "user" | "project";
|
|
40
|
+
name: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
allowedTools?: string;
|
|
43
|
+
model?: string;
|
|
44
|
+
body?: string;
|
|
45
|
+
projectPath?: string;
|
|
46
|
+
dryRun?: boolean;
|
|
47
|
+
}): Promise<SkillWriteResult>;
|
|
48
|
+
/** Toggle `disable-model-invocation` flag while preserving files. */
|
|
49
|
+
export declare function setSkillEnabled(params: {
|
|
50
|
+
scope: "user" | "project";
|
|
51
|
+
name: string;
|
|
52
|
+
enabled: boolean;
|
|
53
|
+
projectPath?: string;
|
|
54
|
+
dryRun?: boolean;
|
|
55
|
+
}): Promise<SkillWriteResult>;
|
|
56
|
+
/** Remove a skill folder entirely. Backs up the full directory first. */
|
|
57
|
+
export declare function deleteSkill(params: {
|
|
58
|
+
scope: "user" | "project";
|
|
59
|
+
name: string;
|
|
60
|
+
projectPath?: string;
|
|
61
|
+
dryRun?: boolean;
|
|
62
|
+
}): Promise<SkillWriteResult>;
|