@perstack/base 0.0.78 → 0.0.79
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/bin/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { F as name, I as version, P as description, r as createBaseServer } from "../server-
|
|
2
|
+
import { F as name, I as version, P as description, r as createBaseServer } from "../server-Bq9K_Ock.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
@@ -11,7 +11,7 @@ import { promisify } from "node:util";
|
|
|
11
11
|
|
|
12
12
|
//#region package.json
|
|
13
13
|
var name = "@perstack/base";
|
|
14
|
-
var version = "0.0.
|
|
14
|
+
var version = "0.0.79";
|
|
15
15
|
var description = "Perstack base skills for agents.";
|
|
16
16
|
|
|
17
17
|
//#endregion
|
|
@@ -102,8 +102,23 @@ function registerClearTodo(server) {
|
|
|
102
102
|
//#region src/tools/attempt-completion.ts
|
|
103
103
|
async function attemptCompletion() {
|
|
104
104
|
const remainingTodos = getRemainingTodos();
|
|
105
|
-
if (remainingTodos.length > 0) return {
|
|
106
|
-
|
|
105
|
+
if (remainingTodos.length > 0) return {
|
|
106
|
+
isError: true,
|
|
107
|
+
content: [{
|
|
108
|
+
type: "text",
|
|
109
|
+
text: [
|
|
110
|
+
"Cannot complete: there are incomplete todos remaining.",
|
|
111
|
+
"",
|
|
112
|
+
"Remaining todos:",
|
|
113
|
+
remainingTodos.map((t) => ` - [id=${t.id}] ${t.title}`).join("\n"),
|
|
114
|
+
"",
|
|
115
|
+
"You must either:",
|
|
116
|
+
"1. Complete the remaining work, then mark each todo as done using the todo tool (e.g., todo({ completedTodos: [id1, id2] }))",
|
|
117
|
+
"2. If the work for a todo is already done, mark it as completed using the todo tool before calling attemptCompletion again"
|
|
118
|
+
].join("\n")
|
|
119
|
+
}]
|
|
120
|
+
};
|
|
121
|
+
return successToolResult({});
|
|
107
122
|
}
|
|
108
123
|
function registerAttemptCompletion(server) {
|
|
109
124
|
server.registerTool("attemptCompletion", {
|
|
@@ -112,7 +127,7 @@ function registerAttemptCompletion(server) {
|
|
|
112
127
|
inputSchema: z.object({ result: z.string().optional() }).strict()
|
|
113
128
|
}, async () => {
|
|
114
129
|
try {
|
|
115
|
-
return
|
|
130
|
+
return await attemptCompletion();
|
|
116
131
|
} catch (e) {
|
|
117
132
|
if (e instanceof Error) return errorToolResult(e);
|
|
118
133
|
throw e;
|
|
@@ -604,4 +619,4 @@ function createBaseServer(options) {
|
|
|
604
619
|
|
|
605
620
|
//#endregion
|
|
606
621
|
export { registerTodo as A, registerEditTextFile as C, clearTodo as D, registerAttemptCompletion as E, name as F, version as I, errorToolResult as M, successToolResult as N, getRemainingTodos as O, description as P, editTextFile as S, attemptCompletion as T, registerReadPdfFile as _, registerWriteTextFile as a, exec as b, registerAddDelegateFromConfig as c, registerRemoveDelegate as d, registerRemoveSkill as f, readPdfFile as g, registerReadTextFile as h, registerAllTools as i, todo as j, registerClearTodo as k, registerAddSkill as l, readTextFile as m, BASE_SKILL_VERSION as n, writeTextFile as o, registerSkillManagementTools as p, createBaseServer as r, registerAddDelegate as s, BASE_SKILL_NAME as t, registerCreateExpert as u, readImageFile as v, validatePath as w, registerExec as x, registerReadImageFile as y };
|
|
607
|
-
//# sourceMappingURL=server-
|
|
622
|
+
//# sourceMappingURL=server-Bq9K_Ock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-Bq9K_Ock.js","names":["z","z","z","z","z","z","z","z","packageJson.name","packageJson.version"],"sources":["../package.json","../src/lib/tool-result.ts","../src/tools/todo.ts","../src/tools/attempt-completion.ts","../src/lib/path.ts","../src/lib/safe-file.ts","../src/tools/edit-text-file.ts","../src/tools/exec.ts","../src/lib/mime.ts","../src/tools/read-image-file.ts","../src/tools/read-pdf-file.ts","../src/tools/read-text-file.ts","../src/tools/skill-management.ts","../src/tools/write-text-file.ts","../src/server.ts"],"sourcesContent":["","import type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\"\n\nexport function successToolResult(result: unknown): CallToolResult {\n return { content: [{ type: \"text\", text: JSON.stringify(result) }] }\n}\n\nexport function errorToolResult(e: Error): CallToolResult {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ error: e.name, message: e.message }) }],\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod/v4\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nclass Todo {\n currentTodoId = 0\n todos: { id: number; title: string; completed: boolean }[] = []\n public processTodo(input: { newTodos?: string[]; completedTodos?: number[] }) {\n const { newTodos, completedTodos } = input\n if (newTodos) {\n this.todos.push(\n ...newTodos.map((title) => ({ id: this.currentTodoId++, title, completed: false })),\n )\n }\n if (completedTodos) {\n this.todos = this.todos.map((todo) => ({\n ...todo,\n completed: todo.completed || completedTodos.includes(todo.id),\n }))\n }\n return {\n todos: this.todos,\n }\n }\n public clearTodo() {\n this.todos = []\n this.currentTodoId = 0\n return {\n todos: this.todos,\n }\n }\n}\nconst todoSingleton = new Todo()\nexport async function todo(input: { newTodos?: string[]; completedTodos?: number[] }) {\n return todoSingleton.processTodo(input)\n}\nexport async function clearTodo() {\n return todoSingleton.clearTodo()\n}\nexport function getRemainingTodos() {\n return todoSingleton.todos.filter((t) => !t.completed)\n}\n\nexport function registerTodo(server: McpServer) {\n server.registerTool(\n \"todo\",\n {\n title: \"todo\",\n description: \"Manage a todo list: add tasks and mark them completed.\",\n inputSchema: {\n newTodos: z.array(z.string()).describe(\"New todos to add\").optional(),\n completedTodos: z.array(z.number()).describe(\"Todo ids that are completed\").optional(),\n },\n },\n async (input: { newTodos?: string[]; completedTodos?: number[] }) => {\n try {\n return successToolResult(await todo(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerClearTodo(server: McpServer) {\n server.registerTool(\n \"clearTodo\",\n {\n title: \"clearTodo\",\n description: \"Clear all todos.\",\n inputSchema: {},\n },\n async () => {\n try {\n return successToolResult(await clearTodo())\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\"\nimport { z } from \"zod\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\nimport { getRemainingTodos } from \"./todo.js\"\n\nexport type AttemptCompletionResult =\n | { remainingTodos: { id: number; title: string; completed: boolean }[] }\n | Record<string, never>\n\nexport async function attemptCompletion(): Promise<CallToolResult> {\n const remainingTodos = getRemainingTodos()\n if (remainingTodos.length > 0) {\n const todoList = remainingTodos.map((t) => ` - [id=${t.id}] ${t.title}`).join(\"\\n\")\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: [\n \"Cannot complete: there are incomplete todos remaining.\",\n \"\",\n \"Remaining todos:\",\n todoList,\n \"\",\n \"You must either:\",\n \"1. Complete the remaining work, then mark each todo as done using the todo tool (e.g., todo({ completedTodos: [id1, id2] }))\",\n \"2. If the work for a todo is already done, mark it as completed using the todo tool before calling attemptCompletion again\",\n ].join(\"\\n\"),\n },\n ],\n }\n }\n return successToolResult({})\n}\n\nexport function registerAttemptCompletion(server: McpServer) {\n server.registerTool(\n \"attemptCompletion\",\n {\n title: \"Attempt completion\",\n description:\n \"Signal task completion. Provide a result parameter with your final response text. Validates all todos are complete before ending.\",\n inputSchema: z.object({ result: z.string().optional() }).strict(),\n },\n async () => {\n try {\n return await attemptCompletion()\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import { realpathSync } from \"node:fs\"\nimport fs from \"node:fs/promises\"\nimport os from \"node:os\"\nimport path from \"node:path\"\n\nexport const workspacePath = realpathSync(expandHome(process.cwd()))\n\nfunction expandHome(filepath: string): string {\n if (filepath.startsWith(\"~/\") || filepath === \"~\") {\n return path.join(os.homedir(), filepath.slice(1))\n }\n return filepath\n}\n\nexport async function validatePath(requestedPath: string): Promise<string> {\n const expandedPath = expandHome(requestedPath)\n const absolute = path.isAbsolute(expandedPath)\n ? path.resolve(expandedPath)\n : path.resolve(process.cwd(), expandedPath)\n const perstackDir = `${workspacePath}/perstack`.toLowerCase()\n if (\n absolute.toLowerCase() === perstackDir ||\n absolute.toLowerCase().startsWith(`${perstackDir}/`)\n ) {\n throw new Error(\"Access denied - perstack directory is not allowed\")\n }\n try {\n const realAbsolute = await fs.realpath(absolute)\n if (!isWithinWorkspace(realAbsolute)) {\n throw new Error(\"Access denied - symlink target outside allowed directories\")\n }\n return realAbsolute\n } catch (_error) {\n const parentDir = path.dirname(absolute)\n try {\n const realParentPath = await fs.realpath(parentDir)\n if (!isWithinWorkspace(realParentPath)) {\n throw new Error(\"Access denied - parent directory outside allowed directories\")\n }\n return absolute\n } catch {\n if (!isWithinWorkspace(absolute)) {\n throw new Error(\n `Access denied - path outside allowed directories: ${absolute} not in ${workspacePath}`,\n )\n }\n throw new Error(`Parent directory does not exist: ${parentDir}`)\n }\n }\n}\n\nfunction isWithinWorkspace(absolutePath: string): boolean {\n return absolutePath === workspacePath || absolutePath.startsWith(`${workspacePath}/`)\n}\n","import type { FileHandle } from \"node:fs/promises\"\nimport { constants, lstat, open } from \"node:fs/promises\"\n\nconst O_NOFOLLOW = constants.O_NOFOLLOW ?? 0\nconst O_NOFOLLOW_SUPPORTED = typeof constants.O_NOFOLLOW === \"number\"\n\nasync function checkNotSymlink(path: string): Promise<void> {\n const stats = await lstat(path).catch(() => null)\n if (stats?.isSymbolicLink()) {\n throw new Error(\"Operation denied: target is a symbolic link\")\n }\n}\n\nexport function isSymlinkProtectionFullySupported(): boolean {\n return O_NOFOLLOW_SUPPORTED\n}\n\nexport async function safeWriteFile(path: string, data: string): Promise<void> {\n let handle: FileHandle | undefined\n try {\n await checkNotSymlink(path)\n const flags = constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | O_NOFOLLOW\n handle = await open(path, flags, 0o644)\n await handle.writeFile(data, \"utf-8\")\n } finally {\n await handle?.close()\n }\n}\n\nexport async function safeReadFile(path: string): Promise<string> {\n let handle: FileHandle | undefined\n try {\n await checkNotSymlink(path)\n const flags = constants.O_RDONLY | O_NOFOLLOW\n handle = await open(path, flags)\n const buffer = await handle.readFile(\"utf-8\")\n return buffer\n } finally {\n await handle?.close()\n }\n}\n","import { stat } from \"node:fs/promises\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { truncateText } from \"@perstack/core\"\nimport { z } from \"zod/v4\"\nimport { validatePath } from \"../lib/path.js\"\nimport { safeReadFile, safeWriteFile } from \"../lib/safe-file.js\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nexport async function editTextFile(input: { path: string; newText: string; oldText: string }) {\n const { path, newText, oldText } = input\n const validatedPath = await validatePath(path)\n const stats = await stat(validatedPath).catch(() => null)\n if (!stats) {\n throw new Error(`File ${path} does not exist.`)\n }\n if (!(stats.mode & 0o200)) {\n throw new Error(`File ${path} is not writable`)\n }\n await applyFileEdit(validatedPath, newText, oldText)\n return {\n path: validatedPath,\n newText: truncateText(newText),\n oldText: truncateText(oldText),\n }\n}\n\nfunction normalizeLineEndings(text: string): string {\n return text.replace(/\\r\\n/g, \"\\n\")\n}\n\nasync function applyFileEdit(filePath: string, newText: string, oldText: string) {\n const content = normalizeLineEndings(await safeReadFile(filePath))\n const normalizedOld = normalizeLineEndings(oldText)\n const normalizedNew = normalizeLineEndings(newText)\n if (!content.includes(normalizedOld)) {\n throw new Error(`Could not find exact match for oldText in file ${filePath}`)\n }\n const modifiedContent = content.replace(normalizedOld, normalizedNew)\n await safeWriteFile(filePath, modifiedContent)\n}\n\nexport function registerEditTextFile(server: McpServer) {\n server.registerTool(\n \"editTextFile\",\n {\n title: \"Edit text file\",\n description: \"Replace exact text in an existing file. Normalizes line endings (CRLF → LF).\",\n inputSchema: {\n path: z.string().describe(\"Target file path to edit.\"),\n newText: z.string().describe(\"Text to replace with.\"),\n oldText: z.string().describe(\"Exact text to find and replace.\"),\n },\n },\n async (input: { path: string; newText: string; oldText: string }) => {\n try {\n return successToolResult(await editTextFile(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import { type ExecException, execFile } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { getFilteredEnv, truncateText } from \"@perstack/core\"\nimport { z } from \"zod/v4\"\nimport { validatePath } from \"../lib/path.js\"\nimport { successToolResult } from \"../lib/tool-result.js\"\n\nconst execFileAsync = promisify(execFile)\ntype ExecError = ExecException & { stdout?: string; stderr?: string }\nfunction isExecError(error: unknown): error is ExecError {\n return error instanceof Error && \"code\" in error\n}\ntype ExecInput = {\n command: string\n args: string[]\n env: Record<string, string>\n cwd: string\n stdout: boolean\n stderr: boolean\n timeout?: number\n}\nexport async function exec(input: ExecInput) {\n const validatedCwd = await validatePath(input.cwd)\n const { stdout, stderr } = await execFileAsync(input.command, input.args, {\n cwd: validatedCwd,\n env: getFilteredEnv(input.env),\n timeout: input.timeout,\n maxBuffer: 10 * 1024 * 1024,\n })\n let output = \"\"\n if (input.stdout) {\n output += stdout\n }\n if (input.stderr) {\n output += stderr\n }\n if (!output.trim()) {\n output = \"Command executed successfully, but produced no output.\"\n }\n return { output: truncateText(output) }\n}\n\nexport function registerExec(server: McpServer) {\n server.registerTool(\n \"exec\",\n {\n title: \"Execute Command\",\n description: \"Execute a system command. Returns stdout/stderr.\",\n inputSchema: {\n command: z.string().describe(\"The command to execute\"),\n args: z.array(z.string()).describe(\"The arguments to pass to the command\"),\n env: z.record(z.string(), z.string()).describe(\"The environment variables to set\"),\n cwd: z.string().describe(\"The working directory to execute the command in\"),\n stdout: z.boolean().describe(\"Whether to capture the standard output\"),\n stderr: z.boolean().describe(\"Whether to capture the standard error\"),\n timeout: z\n .number()\n .optional()\n .default(60000)\n .describe(\"Timeout in milliseconds (default: 60000)\"),\n },\n },\n async (input: ExecInput) => {\n try {\n return successToolResult(await exec(input))\n } catch (error: unknown) {\n let message: string\n let stdout: string | undefined\n let stderr: string | undefined\n if (isExecError(error)) {\n if ((error.killed || error.signal === \"SIGTERM\") && typeof input.timeout === \"number\") {\n message = `Command timed out after ${input.timeout}ms.`\n } else if (error.message.includes(\"timeout\")) {\n message = `Command timed out after ${input.timeout}ms.`\n } else {\n message = error.message\n }\n stdout = error.stdout\n stderr = error.stderr\n } else if (error instanceof Error) {\n message = error.message\n } else {\n message = \"An unknown error occurred.\"\n }\n const result: { error: string; stdout?: string; stderr?: string } = { error: message }\n if (stdout && input.stdout) {\n result.stdout = truncateText(stdout)\n }\n if (stderr && input.stderr) {\n result.stderr = truncateText(stderr)\n }\n return { content: [{ type: \"text\", text: JSON.stringify(result) }] }\n }\n },\n )\n}\n","import { extname } from \"node:path\"\n\nconst MIME_TYPES: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".pdf\": \"application/pdf\",\n}\n\nexport function lookupMimeType(filePath: string): string | undefined {\n return MIME_TYPES[extname(filePath).toLowerCase()]\n}\n","import { existsSync } from \"node:fs\"\nimport { stat } from \"node:fs/promises\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod/v4\"\nimport { lookupMimeType } from \"../lib/mime.js\"\nimport { validatePath } from \"../lib/path.js\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nconst MAX_IMAGE_SIZE = 15 * 1024 * 1024\nexport async function readImageFile(input: { path: string }) {\n const { path } = input\n const validatedPath = await validatePath(path)\n const isFile = existsSync(validatedPath)\n if (!isFile) {\n throw new Error(`File ${path} does not exist.`)\n }\n const mimeType = lookupMimeType(validatedPath)\n if (!mimeType || ![\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"].includes(mimeType)) {\n throw new Error(`File ${path} is not supported.`)\n }\n const fileStats = await stat(validatedPath)\n const fileSizeMB = fileStats.size / (1024 * 1024)\n if (fileStats.size > MAX_IMAGE_SIZE) {\n throw new Error(\n `Image file too large (${fileSizeMB.toFixed(1)}MB). Maximum supported size is ${MAX_IMAGE_SIZE / (1024 * 1024)}MB. Please use a smaller image file.`,\n )\n }\n return {\n path: validatedPath,\n mimeType,\n size: fileStats.size,\n }\n}\n\nexport function registerReadImageFile(server: McpServer) {\n server.registerTool(\n \"readImageFile\",\n {\n title: \"Read image file\",\n description: \"Read an image file as base64. Supports PNG, JPEG, GIF, WebP. Max 15MB.\",\n inputSchema: {\n path: z.string(),\n },\n },\n async (input: { path: string }) => {\n try {\n return successToolResult(await readImageFile(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import { existsSync } from \"node:fs\"\nimport { stat } from \"node:fs/promises\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod/v4\"\nimport { lookupMimeType } from \"../lib/mime.js\"\nimport { validatePath } from \"../lib/path.js\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nconst MAX_PDF_SIZE = 30 * 1024 * 1024\nexport async function readPdfFile(input: { path: string }) {\n const { path } = input\n const validatedPath = await validatePath(path)\n const isFile = existsSync(validatedPath)\n if (!isFile) {\n throw new Error(`File ${path} does not exist.`)\n }\n const mimeType = lookupMimeType(validatedPath)\n if (mimeType !== \"application/pdf\") {\n throw new Error(`File ${path} is not a PDF file.`)\n }\n const fileStats = await stat(validatedPath)\n const fileSizeMB = fileStats.size / (1024 * 1024)\n if (fileStats.size > MAX_PDF_SIZE) {\n throw new Error(\n `PDF file too large (${fileSizeMB.toFixed(1)}MB). Maximum supported size is ${MAX_PDF_SIZE / (1024 * 1024)}MB. Please use a smaller PDF file.`,\n )\n }\n return {\n path: validatedPath,\n mimeType,\n size: fileStats.size,\n }\n}\n\nexport function registerReadPdfFile(server: McpServer) {\n server.registerTool(\n \"readPdfFile\",\n {\n title: \"Read PDF file\",\n description: \"Read a PDF file as base64. Max 30MB.\",\n inputSchema: {\n path: z.string(),\n },\n },\n async (input: { path: string }) => {\n try {\n return successToolResult(await readPdfFile(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import { stat } from \"node:fs/promises\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { truncateText } from \"@perstack/core\"\nimport { z } from \"zod/v4\"\nimport { validatePath } from \"../lib/path.js\"\nimport { safeReadFile } from \"../lib/safe-file.js\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nexport async function readTextFile(input: { path: string; from?: number; to?: number }) {\n const { path, from, to } = input\n const validatedPath = await validatePath(path)\n const stats = await stat(validatedPath).catch(() => null)\n if (!stats) {\n throw new Error(`File ${path} does not exist.`)\n }\n const fileContent = await safeReadFile(validatedPath)\n const lines = fileContent.split(\"\\n\")\n const fromLine = from ?? 0\n const toLine = to ?? lines.length\n const selectedLines = lines.slice(fromLine, toLine)\n const content = selectedLines.join(\"\\n\")\n return {\n path,\n content: truncateText(content),\n from: fromLine,\n to: toLine,\n }\n}\n\nexport function registerReadTextFile(server: McpServer) {\n server.registerTool(\n \"readTextFile\",\n {\n title: \"Read text file\",\n description: \"Read a UTF-8 text file. Supports partial reading via line ranges.\",\n inputSchema: {\n path: z.string(),\n from: z.number().optional().describe(\"The line number to start reading from.\"),\n to: z.number().optional().describe(\"The line number to stop reading at.\"),\n },\n },\n async (input: { path: string; from?: number; to?: number }) => {\n try {\n return successToolResult(await readTextFile(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod/v4\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nexport interface SkillManagementCallbacks {\n addSkill(input: {\n name: string\n type: \"mcpStdioSkill\" | \"mcpSseSkill\"\n command?: string\n packageName?: string\n args?: string[]\n requiredEnv?: string[]\n endpoint?: string\n description?: string\n rule?: string\n pick?: string[]\n omit?: string[]\n }): Promise<{ tools: string[] }>\n removeSkill(skillName: string): Promise<void>\n addDelegate(expertKey: string): Promise<{ delegateToolName: string }>\n removeDelegate(expertName: string): Promise<void>\n createExpert(input: {\n key: string\n instruction: string\n description?: string\n version?: string\n skills?: Record<\n string,\n {\n type: \"mcpStdioSkill\" | \"mcpSseSkill\"\n command?: string\n packageName?: string\n args?: string[]\n requiredEnv?: string[]\n endpoint?: string\n description?: string\n rule?: string\n pick?: string[]\n omit?: string[]\n lazyInit?: boolean\n }\n >\n delegates?: string[]\n tags?: string[]\n providerTools?: string[]\n }): Promise<{ expertKey: string }>\n addDelegateFromConfig(input: {\n configPath: string\n delegateExpertName: string\n }): Promise<{ delegateToolName: string }>\n}\n\nexport function registerAddSkill(server: McpServer, callbacks: SkillManagementCallbacks) {\n server.registerTool(\n \"addSkill\",\n {\n title: \"Add skill\",\n description:\n \"Dynamically add an MCP skill. Returns the list of tool names provided by the new skill.\",\n inputSchema: {\n name: z.string().describe(\"Unique skill name\"),\n type: z.enum([\"mcpStdioSkill\", \"mcpSseSkill\"]).describe(\"Skill transport type\"),\n command: z.string().optional().describe(\"Command to execute (for stdio skills)\"),\n packageName: z.string().optional().describe(\"Package name for npx/uvx (for stdio skills)\"),\n args: z.array(z.string()).optional().describe(\"Additional command arguments\"),\n requiredEnv: z.array(z.string()).optional().describe(\"Required environment variable names\"),\n endpoint: z.string().optional().describe(\"SSE endpoint URL (for SSE skills)\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n rule: z.string().optional().describe(\"Usage rules for the LLM\"),\n pick: z.array(z.string()).optional().describe(\"Tool names to include (whitelist)\"),\n omit: z.array(z.string()).optional().describe(\"Tool names to exclude (blacklist)\"),\n },\n },\n async (input: {\n name: string\n type: \"mcpStdioSkill\" | \"mcpSseSkill\"\n command?: string\n packageName?: string\n args?: string[]\n requiredEnv?: string[]\n endpoint?: string\n description?: string\n rule?: string\n pick?: string[]\n omit?: string[]\n }) => {\n try {\n return successToolResult(await callbacks.addSkill(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerRemoveSkill(server: McpServer, callbacks: SkillManagementCallbacks) {\n server.registerTool(\n \"removeSkill\",\n {\n title: \"Remove skill\",\n description: \"Dynamically remove an MCP skill by name. Disconnects and removes the skill.\",\n inputSchema: {\n skillName: z.string().describe(\"Name of the skill to remove\"),\n },\n },\n async (input: { skillName: string }) => {\n try {\n await callbacks.removeSkill(input.skillName)\n return successToolResult({ removed: input.skillName })\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerAddDelegate(server: McpServer, callbacks: SkillManagementCallbacks) {\n server.registerTool(\n \"addDelegate\",\n {\n title: \"Add delegate\",\n description:\n \"Dynamically add a delegate expert. Returns the delegate tool name so you know what to call.\",\n inputSchema: {\n expertKey: z.string().describe(\"Key of the expert to add as a delegate\"),\n },\n },\n async (input: { expertKey: string }) => {\n try {\n return successToolResult(await callbacks.addDelegate(input.expertKey))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerRemoveDelegate(server: McpServer, callbacks: SkillManagementCallbacks) {\n server.registerTool(\n \"removeDelegate\",\n {\n title: \"Remove delegate\",\n description: \"Dynamically remove a delegate expert by name.\",\n inputSchema: {\n expertName: z.string().describe(\"Name of the delegate expert to remove\"),\n },\n },\n async (input: { expertName: string }) => {\n try {\n await callbacks.removeDelegate(input.expertName)\n return successToolResult({ removed: input.expertName })\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerCreateExpert(server: McpServer, callbacks: SkillManagementCallbacks) {\n server.registerTool(\n \"createExpert\",\n {\n title: \"Create expert\",\n description:\n \"Dynamically create an expert definition in memory. Returns the expert key so you can add it as a delegate.\",\n inputSchema: {\n key: z.string().describe(\"Unique expert key (kebab-case)\"),\n instruction: z.string().describe(\"System instruction for the expert\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n version: z.string().optional().describe(\"Semantic version (defaults to 1.0.0)\"),\n skills: z\n .record(\n z.string(),\n z.object({\n type: z.enum([\"mcpStdioSkill\", \"mcpSseSkill\"]).describe(\"Skill transport type\"),\n command: z.string().optional().describe(\"Command to execute (for stdio skills)\"),\n packageName: z\n .string()\n .optional()\n .describe(\"Package name for npx/uvx (for stdio skills)\"),\n args: z.array(z.string()).optional().describe(\"Additional command arguments\"),\n requiredEnv: z\n .array(z.string())\n .optional()\n .describe(\"Required environment variable names\"),\n endpoint: z.string().optional().describe(\"SSE endpoint URL (for SSE skills)\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n rule: z.string().optional().describe(\"Usage rules for the LLM\"),\n pick: z.array(z.string()).optional().describe(\"Tool names to include (whitelist)\"),\n omit: z.array(z.string()).optional().describe(\"Tool names to exclude (blacklist)\"),\n lazyInit: z.boolean().optional().describe(\"Lazy initialization\"),\n }),\n )\n .optional()\n .describe(\"Skills map (defaults to @perstack/base)\"),\n delegates: z.array(z.string()).optional().describe(\"Expert keys to delegate to\"),\n tags: z.array(z.string()).optional().describe(\"Tags for categorization\"),\n providerTools: z.array(z.string()).optional().describe(\"Provider-specific tool names\"),\n },\n },\n async (input: {\n key: string\n instruction: string\n description?: string\n version?: string\n skills?: Record<\n string,\n {\n type: \"mcpStdioSkill\" | \"mcpSseSkill\"\n command?: string\n packageName?: string\n args?: string[]\n requiredEnv?: string[]\n endpoint?: string\n description?: string\n rule?: string\n pick?: string[]\n omit?: string[]\n lazyInit?: boolean\n }\n >\n delegates?: string[]\n tags?: string[]\n providerTools?: string[]\n }) => {\n try {\n return successToolResult(await callbacks.createExpert(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerAddDelegateFromConfig(\n server: McpServer,\n callbacks: SkillManagementCallbacks,\n) {\n server.registerTool(\n \"addDelegateFromConfig\",\n {\n title: \"Add delegate from config\",\n description:\n \"Load all experts from a perstack.toml config file and add the specified one as a delegate. This is a shortcut that combines reading the config, creating the expert, and adding it as a delegate in a single step.\",\n inputSchema: {\n configPath: z.string().describe(\"Path to the perstack.toml config file\"),\n delegateExpertName: z\n .string()\n .describe(\"Name of the expert in the config to add as a delegate\"),\n },\n },\n async (input: { configPath: string; delegateExpertName: string }) => {\n try {\n return successToolResult(await callbacks.addDelegateFromConfig(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerSkillManagementTools(\n server: McpServer,\n callbacks: SkillManagementCallbacks,\n): void {\n registerAddSkill(server, callbacks)\n registerRemoveSkill(server, callbacks)\n registerAddDelegate(server, callbacks)\n registerRemoveDelegate(server, callbacks)\n registerCreateExpert(server, callbacks)\n registerAddDelegateFromConfig(server, callbacks)\n}\n","import { mkdir, stat } from \"node:fs/promises\"\nimport { dirname } from \"node:path\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod/v4\"\nimport { validatePath } from \"../lib/path.js\"\nimport { safeWriteFile } from \"../lib/safe-file.js\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nexport async function writeTextFile(input: { path: string; text: string }) {\n const { path, text } = input\n const validatedPath = await validatePath(path)\n const stats = await stat(validatedPath).catch(() => null)\n if (stats && !(stats.mode & 0o200)) {\n throw new Error(`File ${path} is not writable`)\n }\n const dir = dirname(validatedPath)\n await mkdir(dir, { recursive: true })\n await safeWriteFile(validatedPath, text)\n return {\n path: validatedPath,\n bytesWritten: Buffer.byteLength(text, \"utf-8\"),\n }\n}\n\nexport function registerWriteTextFile(server: McpServer) {\n server.registerTool(\n \"writeTextFile\",\n {\n title: \"writeTextFile\",\n description: \"Create or overwrite a UTF-8 text file. Creates parent directories as needed.\",\n inputSchema: {\n path: z.string().describe(\"Target file path (relative or absolute).\"),\n text: z.string().describe(\"Text to write to the file.\"),\n },\n },\n async (input: { path: string; text: string }) => {\n try {\n return successToolResult(await writeTextFile(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport packageJson from \"../package.json\" with { type: \"json\" }\nimport { registerAttemptCompletion } from \"./tools/attempt-completion.js\"\nimport { registerEditTextFile } from \"./tools/edit-text-file.js\"\nimport { registerExec } from \"./tools/exec.js\"\nimport { registerReadImageFile } from \"./tools/read-image-file.js\"\nimport { registerReadPdfFile } from \"./tools/read-pdf-file.js\"\nimport { registerReadTextFile } from \"./tools/read-text-file.js\"\nimport type { SkillManagementCallbacks } from \"./tools/skill-management.js\"\nimport { registerSkillManagementTools } from \"./tools/skill-management.js\"\nimport { registerClearTodo, registerTodo } from \"./tools/todo.js\"\nimport { registerWriteTextFile } from \"./tools/write-text-file.js\"\n\n/** Base skill name */\nexport const BASE_SKILL_NAME = packageJson.name\n\n/** Base skill version */\nexport const BASE_SKILL_VERSION = packageJson.version\n\n/**\n * Register all base skill tools on an MCP server.\n * This is useful for both standalone and in-process server creation.\n */\nexport function registerAllTools(server: McpServer): void {\n registerAttemptCompletion(server)\n registerTodo(server)\n registerClearTodo(server)\n registerExec(server)\n registerReadTextFile(server)\n registerReadImageFile(server)\n registerReadPdfFile(server)\n registerWriteTextFile(server)\n registerEditTextFile(server)\n}\n\nexport interface CreateBaseServerOptions {\n skillManagement?: SkillManagementCallbacks\n}\n\n/**\n * Create a base skill MCP server with all tools registered.\n * Used by the runtime for in-process execution via InMemoryTransport.\n */\nexport function createBaseServer(options?: CreateBaseServerOptions): McpServer {\n const server = new McpServer(\n {\n name: BASE_SKILL_NAME,\n version: BASE_SKILL_VERSION,\n },\n {\n capabilities: {\n tools: {},\n },\n },\n )\n registerAllTools(server)\n if (options?.skillManagement) {\n registerSkillManagementTools(server, options.skillManagement)\n }\n return server\n}\n"],"mappings":"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"}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -96,7 +96,7 @@ type AttemptCompletionResult = {
|
|
|
96
96
|
completed: boolean;
|
|
97
97
|
}[];
|
|
98
98
|
} | Record<string, never>;
|
|
99
|
-
declare function attemptCompletion(): Promise<
|
|
99
|
+
declare function attemptCompletion(): Promise<CallToolResult>;
|
|
100
100
|
declare function registerAttemptCompletion(server: McpServer): void;
|
|
101
101
|
//#endregion
|
|
102
102
|
//#region src/tools/edit-text-file.d.ts
|
package/dist/src/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { A as registerTodo, C as registerEditTextFile, D as clearTodo, E as registerAttemptCompletion, M as errorToolResult, N as successToolResult, O as getRemainingTodos, S as editTextFile, T as attemptCompletion, _ as registerReadPdfFile, a as registerWriteTextFile, b as exec, c as registerAddDelegateFromConfig, d as registerRemoveDelegate, f as registerRemoveSkill, g as readPdfFile, h as registerReadTextFile, i as registerAllTools, j as todo, k as registerClearTodo, l as registerAddSkill, m as readTextFile, n as BASE_SKILL_VERSION, o as writeTextFile, p as registerSkillManagementTools, r as createBaseServer, s as registerAddDelegate, t as BASE_SKILL_NAME, u as registerCreateExpert, v as readImageFile, w as validatePath, x as registerExec, y as registerReadImageFile } from "../server-
|
|
1
|
+
import { A as registerTodo, C as registerEditTextFile, D as clearTodo, E as registerAttemptCompletion, M as errorToolResult, N as successToolResult, O as getRemainingTodos, S as editTextFile, T as attemptCompletion, _ as registerReadPdfFile, a as registerWriteTextFile, b as exec, c as registerAddDelegateFromConfig, d as registerRemoveDelegate, f as registerRemoveSkill, g as readPdfFile, h as registerReadTextFile, i as registerAllTools, j as todo, k as registerClearTodo, l as registerAddSkill, m as readTextFile, n as BASE_SKILL_VERSION, o as writeTextFile, p as registerSkillManagementTools, r as createBaseServer, s as registerAddDelegate, t as BASE_SKILL_NAME, u as registerCreateExpert, v as readImageFile, w as validatePath, x as registerExec, y as registerReadImageFile } from "../server-Bq9K_Ock.js";
|
|
2
2
|
|
|
3
3
|
export { BASE_SKILL_NAME, BASE_SKILL_VERSION, attemptCompletion, clearTodo, createBaseServer, editTextFile, errorToolResult, exec, getRemainingTodos, readImageFile, readPdfFile, readTextFile, registerAddDelegate, registerAddDelegateFromConfig, registerAddSkill, registerAllTools, registerAttemptCompletion, registerClearTodo, registerCreateExpert, registerEditTextFile, registerExec, registerReadImageFile, registerReadPdfFile, registerReadTextFile, registerRemoveDelegate, registerRemoveSkill, registerSkillManagementTools, registerTodo, registerWriteTextFile, successToolResult, todo, validatePath, writeTextFile };
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server-CmY4XKI3.js","names":["z","z","z","z","z","z","z","z","packageJson.name","packageJson.version"],"sources":["../package.json","../src/lib/tool-result.ts","../src/tools/todo.ts","../src/tools/attempt-completion.ts","../src/lib/path.ts","../src/lib/safe-file.ts","../src/tools/edit-text-file.ts","../src/tools/exec.ts","../src/lib/mime.ts","../src/tools/read-image-file.ts","../src/tools/read-pdf-file.ts","../src/tools/read-text-file.ts","../src/tools/skill-management.ts","../src/tools/write-text-file.ts","../src/server.ts"],"sourcesContent":["","import type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\"\n\nexport function successToolResult(result: unknown): CallToolResult {\n return { content: [{ type: \"text\", text: JSON.stringify(result) }] }\n}\n\nexport function errorToolResult(e: Error): CallToolResult {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ error: e.name, message: e.message }) }],\n }\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod/v4\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nclass Todo {\n currentTodoId = 0\n todos: { id: number; title: string; completed: boolean }[] = []\n public processTodo(input: { newTodos?: string[]; completedTodos?: number[] }) {\n const { newTodos, completedTodos } = input\n if (newTodos) {\n this.todos.push(\n ...newTodos.map((title) => ({ id: this.currentTodoId++, title, completed: false })),\n )\n }\n if (completedTodos) {\n this.todos = this.todos.map((todo) => ({\n ...todo,\n completed: todo.completed || completedTodos.includes(todo.id),\n }))\n }\n return {\n todos: this.todos,\n }\n }\n public clearTodo() {\n this.todos = []\n this.currentTodoId = 0\n return {\n todos: this.todos,\n }\n }\n}\nconst todoSingleton = new Todo()\nexport async function todo(input: { newTodos?: string[]; completedTodos?: number[] }) {\n return todoSingleton.processTodo(input)\n}\nexport async function clearTodo() {\n return todoSingleton.clearTodo()\n}\nexport function getRemainingTodos() {\n return todoSingleton.todos.filter((t) => !t.completed)\n}\n\nexport function registerTodo(server: McpServer) {\n server.registerTool(\n \"todo\",\n {\n title: \"todo\",\n description: \"Manage a todo list: add tasks and mark them completed.\",\n inputSchema: {\n newTodos: z.array(z.string()).describe(\"New todos to add\").optional(),\n completedTodos: z.array(z.number()).describe(\"Todo ids that are completed\").optional(),\n },\n },\n async (input: { newTodos?: string[]; completedTodos?: number[] }) => {\n try {\n return successToolResult(await todo(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerClearTodo(server: McpServer) {\n server.registerTool(\n \"clearTodo\",\n {\n title: \"clearTodo\",\n description: \"Clear all todos.\",\n inputSchema: {},\n },\n async () => {\n try {\n return successToolResult(await clearTodo())\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\nimport { getRemainingTodos } from \"./todo.js\"\n\nexport type AttemptCompletionResult =\n | { remainingTodos: { id: number; title: string; completed: boolean }[] }\n | Record<string, never>\n\nexport async function attemptCompletion(): Promise<AttemptCompletionResult> {\n const remainingTodos = getRemainingTodos()\n if (remainingTodos.length > 0) {\n return { remainingTodos }\n }\n return {}\n}\n\nexport function registerAttemptCompletion(server: McpServer) {\n server.registerTool(\n \"attemptCompletion\",\n {\n title: \"Attempt completion\",\n description:\n \"Signal task completion. Provide a result parameter with your final response text. Validates all todos are complete before ending.\",\n inputSchema: z.object({ result: z.string().optional() }).strict(),\n },\n async () => {\n try {\n return successToolResult(await attemptCompletion())\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import { realpathSync } from \"node:fs\"\nimport fs from \"node:fs/promises\"\nimport os from \"node:os\"\nimport path from \"node:path\"\n\nexport const workspacePath = realpathSync(expandHome(process.cwd()))\n\nfunction expandHome(filepath: string): string {\n if (filepath.startsWith(\"~/\") || filepath === \"~\") {\n return path.join(os.homedir(), filepath.slice(1))\n }\n return filepath\n}\n\nexport async function validatePath(requestedPath: string): Promise<string> {\n const expandedPath = expandHome(requestedPath)\n const absolute = path.isAbsolute(expandedPath)\n ? path.resolve(expandedPath)\n : path.resolve(process.cwd(), expandedPath)\n const perstackDir = `${workspacePath}/perstack`.toLowerCase()\n if (\n absolute.toLowerCase() === perstackDir ||\n absolute.toLowerCase().startsWith(`${perstackDir}/`)\n ) {\n throw new Error(\"Access denied - perstack directory is not allowed\")\n }\n try {\n const realAbsolute = await fs.realpath(absolute)\n if (!isWithinWorkspace(realAbsolute)) {\n throw new Error(\"Access denied - symlink target outside allowed directories\")\n }\n return realAbsolute\n } catch (_error) {\n const parentDir = path.dirname(absolute)\n try {\n const realParentPath = await fs.realpath(parentDir)\n if (!isWithinWorkspace(realParentPath)) {\n throw new Error(\"Access denied - parent directory outside allowed directories\")\n }\n return absolute\n } catch {\n if (!isWithinWorkspace(absolute)) {\n throw new Error(\n `Access denied - path outside allowed directories: ${absolute} not in ${workspacePath}`,\n )\n }\n throw new Error(`Parent directory does not exist: ${parentDir}`)\n }\n }\n}\n\nfunction isWithinWorkspace(absolutePath: string): boolean {\n return absolutePath === workspacePath || absolutePath.startsWith(`${workspacePath}/`)\n}\n","import type { FileHandle } from \"node:fs/promises\"\nimport { constants, lstat, open } from \"node:fs/promises\"\n\nconst O_NOFOLLOW = constants.O_NOFOLLOW ?? 0\nconst O_NOFOLLOW_SUPPORTED = typeof constants.O_NOFOLLOW === \"number\"\n\nasync function checkNotSymlink(path: string): Promise<void> {\n const stats = await lstat(path).catch(() => null)\n if (stats?.isSymbolicLink()) {\n throw new Error(\"Operation denied: target is a symbolic link\")\n }\n}\n\nexport function isSymlinkProtectionFullySupported(): boolean {\n return O_NOFOLLOW_SUPPORTED\n}\n\nexport async function safeWriteFile(path: string, data: string): Promise<void> {\n let handle: FileHandle | undefined\n try {\n await checkNotSymlink(path)\n const flags = constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | O_NOFOLLOW\n handle = await open(path, flags, 0o644)\n await handle.writeFile(data, \"utf-8\")\n } finally {\n await handle?.close()\n }\n}\n\nexport async function safeReadFile(path: string): Promise<string> {\n let handle: FileHandle | undefined\n try {\n await checkNotSymlink(path)\n const flags = constants.O_RDONLY | O_NOFOLLOW\n handle = await open(path, flags)\n const buffer = await handle.readFile(\"utf-8\")\n return buffer\n } finally {\n await handle?.close()\n }\n}\n","import { stat } from \"node:fs/promises\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { truncateText } from \"@perstack/core\"\nimport { z } from \"zod/v4\"\nimport { validatePath } from \"../lib/path.js\"\nimport { safeReadFile, safeWriteFile } from \"../lib/safe-file.js\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nexport async function editTextFile(input: { path: string; newText: string; oldText: string }) {\n const { path, newText, oldText } = input\n const validatedPath = await validatePath(path)\n const stats = await stat(validatedPath).catch(() => null)\n if (!stats) {\n throw new Error(`File ${path} does not exist.`)\n }\n if (!(stats.mode & 0o200)) {\n throw new Error(`File ${path} is not writable`)\n }\n await applyFileEdit(validatedPath, newText, oldText)\n return {\n path: validatedPath,\n newText: truncateText(newText),\n oldText: truncateText(oldText),\n }\n}\n\nfunction normalizeLineEndings(text: string): string {\n return text.replace(/\\r\\n/g, \"\\n\")\n}\n\nasync function applyFileEdit(filePath: string, newText: string, oldText: string) {\n const content = normalizeLineEndings(await safeReadFile(filePath))\n const normalizedOld = normalizeLineEndings(oldText)\n const normalizedNew = normalizeLineEndings(newText)\n if (!content.includes(normalizedOld)) {\n throw new Error(`Could not find exact match for oldText in file ${filePath}`)\n }\n const modifiedContent = content.replace(normalizedOld, normalizedNew)\n await safeWriteFile(filePath, modifiedContent)\n}\n\nexport function registerEditTextFile(server: McpServer) {\n server.registerTool(\n \"editTextFile\",\n {\n title: \"Edit text file\",\n description: \"Replace exact text in an existing file. Normalizes line endings (CRLF → LF).\",\n inputSchema: {\n path: z.string().describe(\"Target file path to edit.\"),\n newText: z.string().describe(\"Text to replace with.\"),\n oldText: z.string().describe(\"Exact text to find and replace.\"),\n },\n },\n async (input: { path: string; newText: string; oldText: string }) => {\n try {\n return successToolResult(await editTextFile(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import { type ExecException, execFile } from \"node:child_process\"\nimport { promisify } from \"node:util\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { getFilteredEnv, truncateText } from \"@perstack/core\"\nimport { z } from \"zod/v4\"\nimport { validatePath } from \"../lib/path.js\"\nimport { successToolResult } from \"../lib/tool-result.js\"\n\nconst execFileAsync = promisify(execFile)\ntype ExecError = ExecException & { stdout?: string; stderr?: string }\nfunction isExecError(error: unknown): error is ExecError {\n return error instanceof Error && \"code\" in error\n}\ntype ExecInput = {\n command: string\n args: string[]\n env: Record<string, string>\n cwd: string\n stdout: boolean\n stderr: boolean\n timeout?: number\n}\nexport async function exec(input: ExecInput) {\n const validatedCwd = await validatePath(input.cwd)\n const { stdout, stderr } = await execFileAsync(input.command, input.args, {\n cwd: validatedCwd,\n env: getFilteredEnv(input.env),\n timeout: input.timeout,\n maxBuffer: 10 * 1024 * 1024,\n })\n let output = \"\"\n if (input.stdout) {\n output += stdout\n }\n if (input.stderr) {\n output += stderr\n }\n if (!output.trim()) {\n output = \"Command executed successfully, but produced no output.\"\n }\n return { output: truncateText(output) }\n}\n\nexport function registerExec(server: McpServer) {\n server.registerTool(\n \"exec\",\n {\n title: \"Execute Command\",\n description: \"Execute a system command. Returns stdout/stderr.\",\n inputSchema: {\n command: z.string().describe(\"The command to execute\"),\n args: z.array(z.string()).describe(\"The arguments to pass to the command\"),\n env: z.record(z.string(), z.string()).describe(\"The environment variables to set\"),\n cwd: z.string().describe(\"The working directory to execute the command in\"),\n stdout: z.boolean().describe(\"Whether to capture the standard output\"),\n stderr: z.boolean().describe(\"Whether to capture the standard error\"),\n timeout: z\n .number()\n .optional()\n .default(60000)\n .describe(\"Timeout in milliseconds (default: 60000)\"),\n },\n },\n async (input: ExecInput) => {\n try {\n return successToolResult(await exec(input))\n } catch (error: unknown) {\n let message: string\n let stdout: string | undefined\n let stderr: string | undefined\n if (isExecError(error)) {\n if ((error.killed || error.signal === \"SIGTERM\") && typeof input.timeout === \"number\") {\n message = `Command timed out after ${input.timeout}ms.`\n } else if (error.message.includes(\"timeout\")) {\n message = `Command timed out after ${input.timeout}ms.`\n } else {\n message = error.message\n }\n stdout = error.stdout\n stderr = error.stderr\n } else if (error instanceof Error) {\n message = error.message\n } else {\n message = \"An unknown error occurred.\"\n }\n const result: { error: string; stdout?: string; stderr?: string } = { error: message }\n if (stdout && input.stdout) {\n result.stdout = truncateText(stdout)\n }\n if (stderr && input.stderr) {\n result.stderr = truncateText(stderr)\n }\n return { content: [{ type: \"text\", text: JSON.stringify(result) }] }\n }\n },\n )\n}\n","import { extname } from \"node:path\"\n\nconst MIME_TYPES: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".pdf\": \"application/pdf\",\n}\n\nexport function lookupMimeType(filePath: string): string | undefined {\n return MIME_TYPES[extname(filePath).toLowerCase()]\n}\n","import { existsSync } from \"node:fs\"\nimport { stat } from \"node:fs/promises\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod/v4\"\nimport { lookupMimeType } from \"../lib/mime.js\"\nimport { validatePath } from \"../lib/path.js\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nconst MAX_IMAGE_SIZE = 15 * 1024 * 1024\nexport async function readImageFile(input: { path: string }) {\n const { path } = input\n const validatedPath = await validatePath(path)\n const isFile = existsSync(validatedPath)\n if (!isFile) {\n throw new Error(`File ${path} does not exist.`)\n }\n const mimeType = lookupMimeType(validatedPath)\n if (!mimeType || ![\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"].includes(mimeType)) {\n throw new Error(`File ${path} is not supported.`)\n }\n const fileStats = await stat(validatedPath)\n const fileSizeMB = fileStats.size / (1024 * 1024)\n if (fileStats.size > MAX_IMAGE_SIZE) {\n throw new Error(\n `Image file too large (${fileSizeMB.toFixed(1)}MB). Maximum supported size is ${MAX_IMAGE_SIZE / (1024 * 1024)}MB. Please use a smaller image file.`,\n )\n }\n return {\n path: validatedPath,\n mimeType,\n size: fileStats.size,\n }\n}\n\nexport function registerReadImageFile(server: McpServer) {\n server.registerTool(\n \"readImageFile\",\n {\n title: \"Read image file\",\n description: \"Read an image file as base64. Supports PNG, JPEG, GIF, WebP. Max 15MB.\",\n inputSchema: {\n path: z.string(),\n },\n },\n async (input: { path: string }) => {\n try {\n return successToolResult(await readImageFile(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import { existsSync } from \"node:fs\"\nimport { stat } from \"node:fs/promises\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod/v4\"\nimport { lookupMimeType } from \"../lib/mime.js\"\nimport { validatePath } from \"../lib/path.js\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nconst MAX_PDF_SIZE = 30 * 1024 * 1024\nexport async function readPdfFile(input: { path: string }) {\n const { path } = input\n const validatedPath = await validatePath(path)\n const isFile = existsSync(validatedPath)\n if (!isFile) {\n throw new Error(`File ${path} does not exist.`)\n }\n const mimeType = lookupMimeType(validatedPath)\n if (mimeType !== \"application/pdf\") {\n throw new Error(`File ${path} is not a PDF file.`)\n }\n const fileStats = await stat(validatedPath)\n const fileSizeMB = fileStats.size / (1024 * 1024)\n if (fileStats.size > MAX_PDF_SIZE) {\n throw new Error(\n `PDF file too large (${fileSizeMB.toFixed(1)}MB). Maximum supported size is ${MAX_PDF_SIZE / (1024 * 1024)}MB. Please use a smaller PDF file.`,\n )\n }\n return {\n path: validatedPath,\n mimeType,\n size: fileStats.size,\n }\n}\n\nexport function registerReadPdfFile(server: McpServer) {\n server.registerTool(\n \"readPdfFile\",\n {\n title: \"Read PDF file\",\n description: \"Read a PDF file as base64. Max 30MB.\",\n inputSchema: {\n path: z.string(),\n },\n },\n async (input: { path: string }) => {\n try {\n return successToolResult(await readPdfFile(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import { stat } from \"node:fs/promises\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { truncateText } from \"@perstack/core\"\nimport { z } from \"zod/v4\"\nimport { validatePath } from \"../lib/path.js\"\nimport { safeReadFile } from \"../lib/safe-file.js\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nexport async function readTextFile(input: { path: string; from?: number; to?: number }) {\n const { path, from, to } = input\n const validatedPath = await validatePath(path)\n const stats = await stat(validatedPath).catch(() => null)\n if (!stats) {\n throw new Error(`File ${path} does not exist.`)\n }\n const fileContent = await safeReadFile(validatedPath)\n const lines = fileContent.split(\"\\n\")\n const fromLine = from ?? 0\n const toLine = to ?? lines.length\n const selectedLines = lines.slice(fromLine, toLine)\n const content = selectedLines.join(\"\\n\")\n return {\n path,\n content: truncateText(content),\n from: fromLine,\n to: toLine,\n }\n}\n\nexport function registerReadTextFile(server: McpServer) {\n server.registerTool(\n \"readTextFile\",\n {\n title: \"Read text file\",\n description: \"Read a UTF-8 text file. Supports partial reading via line ranges.\",\n inputSchema: {\n path: z.string(),\n from: z.number().optional().describe(\"The line number to start reading from.\"),\n to: z.number().optional().describe(\"The line number to stop reading at.\"),\n },\n },\n async (input: { path: string; from?: number; to?: number }) => {\n try {\n return successToolResult(await readTextFile(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod/v4\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nexport interface SkillManagementCallbacks {\n addSkill(input: {\n name: string\n type: \"mcpStdioSkill\" | \"mcpSseSkill\"\n command?: string\n packageName?: string\n args?: string[]\n requiredEnv?: string[]\n endpoint?: string\n description?: string\n rule?: string\n pick?: string[]\n omit?: string[]\n }): Promise<{ tools: string[] }>\n removeSkill(skillName: string): Promise<void>\n addDelegate(expertKey: string): Promise<{ delegateToolName: string }>\n removeDelegate(expertName: string): Promise<void>\n createExpert(input: {\n key: string\n instruction: string\n description?: string\n version?: string\n skills?: Record<\n string,\n {\n type: \"mcpStdioSkill\" | \"mcpSseSkill\"\n command?: string\n packageName?: string\n args?: string[]\n requiredEnv?: string[]\n endpoint?: string\n description?: string\n rule?: string\n pick?: string[]\n omit?: string[]\n lazyInit?: boolean\n }\n >\n delegates?: string[]\n tags?: string[]\n providerTools?: string[]\n }): Promise<{ expertKey: string }>\n addDelegateFromConfig(input: {\n configPath: string\n delegateExpertName: string\n }): Promise<{ delegateToolName: string }>\n}\n\nexport function registerAddSkill(server: McpServer, callbacks: SkillManagementCallbacks) {\n server.registerTool(\n \"addSkill\",\n {\n title: \"Add skill\",\n description:\n \"Dynamically add an MCP skill. Returns the list of tool names provided by the new skill.\",\n inputSchema: {\n name: z.string().describe(\"Unique skill name\"),\n type: z.enum([\"mcpStdioSkill\", \"mcpSseSkill\"]).describe(\"Skill transport type\"),\n command: z.string().optional().describe(\"Command to execute (for stdio skills)\"),\n packageName: z.string().optional().describe(\"Package name for npx/uvx (for stdio skills)\"),\n args: z.array(z.string()).optional().describe(\"Additional command arguments\"),\n requiredEnv: z.array(z.string()).optional().describe(\"Required environment variable names\"),\n endpoint: z.string().optional().describe(\"SSE endpoint URL (for SSE skills)\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n rule: z.string().optional().describe(\"Usage rules for the LLM\"),\n pick: z.array(z.string()).optional().describe(\"Tool names to include (whitelist)\"),\n omit: z.array(z.string()).optional().describe(\"Tool names to exclude (blacklist)\"),\n },\n },\n async (input: {\n name: string\n type: \"mcpStdioSkill\" | \"mcpSseSkill\"\n command?: string\n packageName?: string\n args?: string[]\n requiredEnv?: string[]\n endpoint?: string\n description?: string\n rule?: string\n pick?: string[]\n omit?: string[]\n }) => {\n try {\n return successToolResult(await callbacks.addSkill(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerRemoveSkill(server: McpServer, callbacks: SkillManagementCallbacks) {\n server.registerTool(\n \"removeSkill\",\n {\n title: \"Remove skill\",\n description: \"Dynamically remove an MCP skill by name. Disconnects and removes the skill.\",\n inputSchema: {\n skillName: z.string().describe(\"Name of the skill to remove\"),\n },\n },\n async (input: { skillName: string }) => {\n try {\n await callbacks.removeSkill(input.skillName)\n return successToolResult({ removed: input.skillName })\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerAddDelegate(server: McpServer, callbacks: SkillManagementCallbacks) {\n server.registerTool(\n \"addDelegate\",\n {\n title: \"Add delegate\",\n description:\n \"Dynamically add a delegate expert. Returns the delegate tool name so you know what to call.\",\n inputSchema: {\n expertKey: z.string().describe(\"Key of the expert to add as a delegate\"),\n },\n },\n async (input: { expertKey: string }) => {\n try {\n return successToolResult(await callbacks.addDelegate(input.expertKey))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerRemoveDelegate(server: McpServer, callbacks: SkillManagementCallbacks) {\n server.registerTool(\n \"removeDelegate\",\n {\n title: \"Remove delegate\",\n description: \"Dynamically remove a delegate expert by name.\",\n inputSchema: {\n expertName: z.string().describe(\"Name of the delegate expert to remove\"),\n },\n },\n async (input: { expertName: string }) => {\n try {\n await callbacks.removeDelegate(input.expertName)\n return successToolResult({ removed: input.expertName })\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerCreateExpert(server: McpServer, callbacks: SkillManagementCallbacks) {\n server.registerTool(\n \"createExpert\",\n {\n title: \"Create expert\",\n description:\n \"Dynamically create an expert definition in memory. Returns the expert key so you can add it as a delegate.\",\n inputSchema: {\n key: z.string().describe(\"Unique expert key (kebab-case)\"),\n instruction: z.string().describe(\"System instruction for the expert\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n version: z.string().optional().describe(\"Semantic version (defaults to 1.0.0)\"),\n skills: z\n .record(\n z.string(),\n z.object({\n type: z.enum([\"mcpStdioSkill\", \"mcpSseSkill\"]).describe(\"Skill transport type\"),\n command: z.string().optional().describe(\"Command to execute (for stdio skills)\"),\n packageName: z\n .string()\n .optional()\n .describe(\"Package name for npx/uvx (for stdio skills)\"),\n args: z.array(z.string()).optional().describe(\"Additional command arguments\"),\n requiredEnv: z\n .array(z.string())\n .optional()\n .describe(\"Required environment variable names\"),\n endpoint: z.string().optional().describe(\"SSE endpoint URL (for SSE skills)\"),\n description: z.string().optional().describe(\"Human-readable description\"),\n rule: z.string().optional().describe(\"Usage rules for the LLM\"),\n pick: z.array(z.string()).optional().describe(\"Tool names to include (whitelist)\"),\n omit: z.array(z.string()).optional().describe(\"Tool names to exclude (blacklist)\"),\n lazyInit: z.boolean().optional().describe(\"Lazy initialization\"),\n }),\n )\n .optional()\n .describe(\"Skills map (defaults to @perstack/base)\"),\n delegates: z.array(z.string()).optional().describe(\"Expert keys to delegate to\"),\n tags: z.array(z.string()).optional().describe(\"Tags for categorization\"),\n providerTools: z.array(z.string()).optional().describe(\"Provider-specific tool names\"),\n },\n },\n async (input: {\n key: string\n instruction: string\n description?: string\n version?: string\n skills?: Record<\n string,\n {\n type: \"mcpStdioSkill\" | \"mcpSseSkill\"\n command?: string\n packageName?: string\n args?: string[]\n requiredEnv?: string[]\n endpoint?: string\n description?: string\n rule?: string\n pick?: string[]\n omit?: string[]\n lazyInit?: boolean\n }\n >\n delegates?: string[]\n tags?: string[]\n providerTools?: string[]\n }) => {\n try {\n return successToolResult(await callbacks.createExpert(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerAddDelegateFromConfig(\n server: McpServer,\n callbacks: SkillManagementCallbacks,\n) {\n server.registerTool(\n \"addDelegateFromConfig\",\n {\n title: \"Add delegate from config\",\n description:\n \"Load all experts from a perstack.toml config file and add the specified one as a delegate. This is a shortcut that combines reading the config, creating the expert, and adding it as a delegate in a single step.\",\n inputSchema: {\n configPath: z.string().describe(\"Path to the perstack.toml config file\"),\n delegateExpertName: z\n .string()\n .describe(\"Name of the expert in the config to add as a delegate\"),\n },\n },\n async (input: { configPath: string; delegateExpertName: string }) => {\n try {\n return successToolResult(await callbacks.addDelegateFromConfig(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n\nexport function registerSkillManagementTools(\n server: McpServer,\n callbacks: SkillManagementCallbacks,\n): void {\n registerAddSkill(server, callbacks)\n registerRemoveSkill(server, callbacks)\n registerAddDelegate(server, callbacks)\n registerRemoveDelegate(server, callbacks)\n registerCreateExpert(server, callbacks)\n registerAddDelegateFromConfig(server, callbacks)\n}\n","import { mkdir, stat } from \"node:fs/promises\"\nimport { dirname } from \"node:path\"\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport { z } from \"zod/v4\"\nimport { validatePath } from \"../lib/path.js\"\nimport { safeWriteFile } from \"../lib/safe-file.js\"\nimport { errorToolResult, successToolResult } from \"../lib/tool-result.js\"\n\nexport async function writeTextFile(input: { path: string; text: string }) {\n const { path, text } = input\n const validatedPath = await validatePath(path)\n const stats = await stat(validatedPath).catch(() => null)\n if (stats && !(stats.mode & 0o200)) {\n throw new Error(`File ${path} is not writable`)\n }\n const dir = dirname(validatedPath)\n await mkdir(dir, { recursive: true })\n await safeWriteFile(validatedPath, text)\n return {\n path: validatedPath,\n bytesWritten: Buffer.byteLength(text, \"utf-8\"),\n }\n}\n\nexport function registerWriteTextFile(server: McpServer) {\n server.registerTool(\n \"writeTextFile\",\n {\n title: \"writeTextFile\",\n description: \"Create or overwrite a UTF-8 text file. Creates parent directories as needed.\",\n inputSchema: {\n path: z.string().describe(\"Target file path (relative or absolute).\"),\n text: z.string().describe(\"Text to write to the file.\"),\n },\n },\n async (input: { path: string; text: string }) => {\n try {\n return successToolResult(await writeTextFile(input))\n } catch (e) {\n if (e instanceof Error) return errorToolResult(e)\n throw e\n }\n },\n )\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\"\nimport packageJson from \"../package.json\" with { type: \"json\" }\nimport { registerAttemptCompletion } from \"./tools/attempt-completion.js\"\nimport { registerEditTextFile } from \"./tools/edit-text-file.js\"\nimport { registerExec } from \"./tools/exec.js\"\nimport { registerReadImageFile } from \"./tools/read-image-file.js\"\nimport { registerReadPdfFile } from \"./tools/read-pdf-file.js\"\nimport { registerReadTextFile } from \"./tools/read-text-file.js\"\nimport type { SkillManagementCallbacks } from \"./tools/skill-management.js\"\nimport { registerSkillManagementTools } from \"./tools/skill-management.js\"\nimport { registerClearTodo, registerTodo } from \"./tools/todo.js\"\nimport { registerWriteTextFile } from \"./tools/write-text-file.js\"\n\n/** Base skill name */\nexport const BASE_SKILL_NAME = packageJson.name\n\n/** Base skill version */\nexport const BASE_SKILL_VERSION = packageJson.version\n\n/**\n * Register all base skill tools on an MCP server.\n * This is useful for both standalone and in-process server creation.\n */\nexport function registerAllTools(server: McpServer): void {\n registerAttemptCompletion(server)\n registerTodo(server)\n registerClearTodo(server)\n registerExec(server)\n registerReadTextFile(server)\n registerReadImageFile(server)\n registerReadPdfFile(server)\n registerWriteTextFile(server)\n registerEditTextFile(server)\n}\n\nexport interface CreateBaseServerOptions {\n skillManagement?: SkillManagementCallbacks\n}\n\n/**\n * Create a base skill MCP server with all tools registered.\n * Used by the runtime for in-process execution via InMemoryTransport.\n */\nexport function createBaseServer(options?: CreateBaseServerOptions): McpServer {\n const server = new McpServer(\n {\n name: BASE_SKILL_NAME,\n version: BASE_SKILL_VERSION,\n },\n {\n capabilities: {\n tools: {},\n },\n },\n )\n registerAllTools(server)\n if (options?.skillManagement) {\n registerSkillManagementTools(server, options.skillManagement)\n }\n return server\n}\n"],"mappings":"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"}
|