staff-mcp 1.0.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 +89 -0
- package/README_zh.md +89 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.js +3 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/security.d.ts +16 -0
- package/dist/security.js +43 -0
- package/dist/security.js.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.js +25 -0
- package/dist/server.js.map +1 -0
- package/dist/src/constants.d.ts +2 -0
- package/dist/src/constants.js +3 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +29 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/security.d.ts +21 -0
- package/dist/src/security.js +51 -0
- package/dist/src/security.js.map +1 -0
- package/dist/src/server.d.ts +10 -0
- package/dist/src/server.js +34 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/tools/file-tools.d.ts +6 -0
- package/dist/src/tools/file-tools.js +230 -0
- package/dist/src/tools/file-tools.js.map +1 -0
- package/dist/src/tools/lsp-tools.d.ts +10 -0
- package/dist/src/tools/lsp-tools.js +124 -0
- package/dist/src/tools/lsp-tools.js.map +1 -0
- package/dist/src/tools/shell-tools.d.ts +6 -0
- package/dist/src/tools/shell-tools.js +138 -0
- package/dist/src/tools/shell-tools.js.map +1 -0
- package/dist/src/tools/skill-manager.d.ts +14 -0
- package/dist/src/tools/skill-manager.js +97 -0
- package/dist/src/tools/skill-manager.js.map +1 -0
- package/dist/src/tools/skill-tools.d.ts +3 -0
- package/dist/src/tools/skill-tools.js +117 -0
- package/dist/src/tools/skill-tools.js.map +1 -0
- package/dist/src/tools/system-tools.d.ts +6 -0
- package/dist/src/tools/system-tools.js +36 -0
- package/dist/src/tools/system-tools.js.map +1 -0
- package/dist/src/transports/http.d.ts +5 -0
- package/dist/src/transports/http.js +58 -0
- package/dist/src/transports/http.js.map +1 -0
- package/dist/src/transports/stdio.d.ts +2 -0
- package/dist/src/transports/stdio.js +18 -0
- package/dist/src/transports/stdio.js.map +1 -0
- package/dist/tests/security.test.d.ts +1 -0
- package/dist/tests/security.test.js +21 -0
- package/dist/tests/security.test.js.map +1 -0
- package/dist/tools/file-tools.d.ts +6 -0
- package/dist/tools/file-tools.js +102 -0
- package/dist/tools/file-tools.js.map +1 -0
- package/dist/tools/lsp-tools.d.ts +6 -0
- package/dist/tools/lsp-tools.js +70 -0
- package/dist/tools/lsp-tools.js.map +1 -0
- package/dist/tools/shell-tools.d.ts +6 -0
- package/dist/tools/shell-tools.js +39 -0
- package/dist/tools/shell-tools.js.map +1 -0
- package/dist/transports/http.d.ts +5 -0
- package/dist/transports/http.js +58 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/stdio.d.ts +2 -0
- package/dist/transports/stdio.js +18 -0
- package/dist/transports/stdio.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as os from "os";
|
|
4
|
+
export class SkillManager {
|
|
5
|
+
// 定义搜索的基准目录名(隐藏目录)
|
|
6
|
+
static SEARCH_DIRS = [".staff", ".claude", ".agents", ".opencode"];
|
|
7
|
+
// 定义技能子目录名
|
|
8
|
+
static SKILL_SUBDIRS = ["skills", "skill"];
|
|
9
|
+
static loadSkills(workingDir) {
|
|
10
|
+
const skills = {};
|
|
11
|
+
const searchPaths = [];
|
|
12
|
+
// 0. 直接检查工作目录下的 skills (兼容旧逻辑)
|
|
13
|
+
searchPaths.push(path.join(workingDir, "skills"));
|
|
14
|
+
searchPaths.push(path.join(workingDir, "skill"));
|
|
15
|
+
// 1. 添加当前工作区搜索路径
|
|
16
|
+
this.SEARCH_DIRS.forEach(dir => {
|
|
17
|
+
this.SKILL_SUBDIRS.forEach(sub => {
|
|
18
|
+
searchPaths.push(path.join(workingDir, dir, sub));
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
// 2. 添加全局搜索路径 (用户主目录)
|
|
22
|
+
const homeDir = os.homedir();
|
|
23
|
+
this.SEARCH_DIRS.forEach(dir => {
|
|
24
|
+
this.SKILL_SUBDIRS.forEach(sub => {
|
|
25
|
+
searchPaths.push(path.join(homeDir, dir, sub));
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
// 3. 扫描所有有效路径
|
|
29
|
+
for (const root of searchPaths) {
|
|
30
|
+
if (fs.existsSync(root) && fs.statSync(root).isDirectory()) {
|
|
31
|
+
this.scanDirSync(root, skills);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return skills;
|
|
35
|
+
}
|
|
36
|
+
static scanDirSync(dir, skills) {
|
|
37
|
+
try {
|
|
38
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
// 跳过常见的忽略目录
|
|
41
|
+
if (entry.name === "node_modules" || entry.name === ".git")
|
|
42
|
+
continue;
|
|
43
|
+
const fullPath = path.join(dir, entry.name);
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
// 递归搜索子目录
|
|
46
|
+
this.scanDirSync(fullPath, skills);
|
|
47
|
+
}
|
|
48
|
+
else if (entry.name === "SKILL.md") {
|
|
49
|
+
this.addSkillSync(fullPath, skills);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
// 忽略读取错误
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
static addSkillSync(filePath, skills) {
|
|
58
|
+
try {
|
|
59
|
+
const fileContent = fs.readFileSync(filePath, "utf-8");
|
|
60
|
+
const { data, content } = this.parseMarkdown(fileContent);
|
|
61
|
+
// 确保有必要的元数据
|
|
62
|
+
if (data.name && data.description) {
|
|
63
|
+
// 如果名称冲突,优先保留先扫描到的(项目本地优先于全局)
|
|
64
|
+
if (!skills[data.name]) {
|
|
65
|
+
skills[data.name] = {
|
|
66
|
+
name: data.name,
|
|
67
|
+
description: data.description,
|
|
68
|
+
location: filePath,
|
|
69
|
+
content: content.trim(),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
console.error(`[SkillManager] Failed to load skill from ${filePath}`, e);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
static parseMarkdown(content) {
|
|
79
|
+
// 匹配 Markdown Frontmatter (--- yaml --- content)
|
|
80
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
|
|
81
|
+
if (!match)
|
|
82
|
+
return { data: {}, content };
|
|
83
|
+
const yamlStr = match[1];
|
|
84
|
+
const body = match[2];
|
|
85
|
+
const data = {};
|
|
86
|
+
for (const line of yamlStr.split("\n")) {
|
|
87
|
+
const colonIndex = line.indexOf(":");
|
|
88
|
+
if (colonIndex > -1) {
|
|
89
|
+
const key = line.slice(0, colonIndex).trim();
|
|
90
|
+
const value = line.slice(colonIndex + 1).trim().replace(/^['"]|['"]$/g, "");
|
|
91
|
+
data[key] = value;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { data, content: body };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=skill-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-manager.js","sourceRoot":"","sources":["../../../src/tools/skill-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { SkillManager } from "./skill-manager.js";
|
|
3
|
+
import * as fs from "fs/promises";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
export function registerSkillTools(server, workingDir, security) {
|
|
6
|
+
const skillsMap = SkillManager.loadSkills(workingDir);
|
|
7
|
+
const list = Object.values(skillsMap);
|
|
8
|
+
// skill
|
|
9
|
+
const description = list.length === 0
|
|
10
|
+
? "Load a specialized skill that provides domain-specific instructions and workflows. No skills are currently available."
|
|
11
|
+
: [
|
|
12
|
+
"The following skills provide specialized sets of instructions for particular tasks",
|
|
13
|
+
"Invoke this tool to load a skill when a task matches one of the available skills listed below:",
|
|
14
|
+
"",
|
|
15
|
+
"<available_skills>",
|
|
16
|
+
...list.flatMap((skill) => [
|
|
17
|
+
` <skill>`,
|
|
18
|
+
` <name>${skill.name}</name>`,
|
|
19
|
+
` <description>${skill.description}</description>`,
|
|
20
|
+
` </skill>`,
|
|
21
|
+
]),
|
|
22
|
+
"</available_skills>",
|
|
23
|
+
].join("\n");
|
|
24
|
+
const examples = list.map((skill) => `'${skill.name}'`).slice(0, 3).join(", ");
|
|
25
|
+
const hint = examples.length > 0 ? ` (e.g., ${examples}, ...)` : "";
|
|
26
|
+
server.registerTool("skill", {
|
|
27
|
+
description: description,
|
|
28
|
+
inputSchema: z.object({
|
|
29
|
+
name: z.string().describe(`The name of the skill from available_skills${hint}`),
|
|
30
|
+
}).strict(),
|
|
31
|
+
}, async ({ name }) => {
|
|
32
|
+
const skill = skillsMap[name];
|
|
33
|
+
if (!skill) {
|
|
34
|
+
const available = list.map((s) => s.name).join(", ");
|
|
35
|
+
throw new Error(`Skill "${name}" not found. Available skills: ${available || "none"}`);
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
content: [{
|
|
39
|
+
type: "text",
|
|
40
|
+
text: buildSkillOutput(skill)
|
|
41
|
+
}]
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
// read_skill_file
|
|
45
|
+
server.registerTool("read_skill_file", {
|
|
46
|
+
description: "Read the contents of a file associated with a specific loaded skill.",
|
|
47
|
+
inputSchema: z.object({
|
|
48
|
+
skillName: z.string().describe('The name of the skill (e.g., "react-component")'),
|
|
49
|
+
relativePath: z.string().describe('The relative path of the file to read (e.g., "templates/Component.tsx")')
|
|
50
|
+
}).strict(),
|
|
51
|
+
}, async ({ skillName, relativePath }) => {
|
|
52
|
+
const skill = skillsMap[skillName];
|
|
53
|
+
if (!skill) {
|
|
54
|
+
return {
|
|
55
|
+
isError: true,
|
|
56
|
+
content: [{ type: "text", text: `Error: Skill "${skillName}" not found.` }]
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const baseDir = path.dirname(skill.location);
|
|
60
|
+
const targetPath = path.resolve(baseDir, relativePath);
|
|
61
|
+
// Security check: ensure targetPath is within baseDir
|
|
62
|
+
if (!targetPath.startsWith(baseDir)) {
|
|
63
|
+
return {
|
|
64
|
+
isError: true,
|
|
65
|
+
content: [{ type: "text", text: `Security Error: Access denied. Cannot read files outside skill directory.` }]
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const content = await fs.readFile(targetPath, "utf-8");
|
|
70
|
+
return {
|
|
71
|
+
content: [{
|
|
72
|
+
type: "text",
|
|
73
|
+
text: content
|
|
74
|
+
}]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
return {
|
|
79
|
+
isError: true,
|
|
80
|
+
content: [{ type: "text", text: `Failed to read skill file: ${e.message}` }]
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// Register Prompts
|
|
85
|
+
for (const skill of list) {
|
|
86
|
+
server.registerPrompt(skill.name, {
|
|
87
|
+
description: skill.description,
|
|
88
|
+
argsSchema: {}
|
|
89
|
+
}, () => {
|
|
90
|
+
return {
|
|
91
|
+
messages: [
|
|
92
|
+
{
|
|
93
|
+
role: "user",
|
|
94
|
+
content: {
|
|
95
|
+
type: "text",
|
|
96
|
+
text: buildSkillOutput(skill)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function buildSkillOutput(skill) {
|
|
105
|
+
const dir = path.dirname(skill.location);
|
|
106
|
+
return [
|
|
107
|
+
`<skill_content name="${skill.name}">`,
|
|
108
|
+
`# Skill: ${skill.name}`,
|
|
109
|
+
"",
|
|
110
|
+
skill.content.trim(),
|
|
111
|
+
"",
|
|
112
|
+
`Base directory: ${dir}`,
|
|
113
|
+
"Relative paths in this skill are relative to this base directory.",
|
|
114
|
+
"</skill_content>"
|
|
115
|
+
].join("\n");
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=skill-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-tools.js","sourceRoot":"","sources":["../../../src/tools/skill-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SecurityManager } from "../security.js";
|
|
2
|
+
/**
|
|
3
|
+
* Returns a concise instruction string for the MCP server to guide tool usage.
|
|
4
|
+
* Focuses on environment context and tool relationships rather than defining identity.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getMcpInstructions(workingDir: string, security: SecurityManager): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as os from "os";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Returns a concise instruction string for the MCP server to guide tool usage.
|
|
5
|
+
* Focuses on environment context and tool relationships rather than defining identity.
|
|
6
|
+
*/
|
|
7
|
+
export function getMcpInstructions(workingDir, security) {
|
|
8
|
+
const platform = os.platform();
|
|
9
|
+
const isWin = platform === "win32";
|
|
10
|
+
const shell = isWin ? "cmd.exe or PowerShell" : (process.env.SHELL || "/bin/sh");
|
|
11
|
+
const allowedDirs = security.getAllowedDirs();
|
|
12
|
+
return `
|
|
13
|
+
# MCP Context: staff-mcp
|
|
14
|
+
Environment:
|
|
15
|
+
- OS: ${platform}
|
|
16
|
+
- Default Shell: ${shell}
|
|
17
|
+
- Working Directory: ${workingDir}
|
|
18
|
+
- Access Constraints: Only paths within [${allowedDirs.join(", ")}] are accessible.
|
|
19
|
+
- Path Separator: '${path.sep}'
|
|
20
|
+
|
|
21
|
+
Tool Usage Guidance:
|
|
22
|
+
1. File Navigation: Always start by using 'list_dir' to understand the project structure before reading files.
|
|
23
|
+
2. Content Inspection:
|
|
24
|
+
- Use 'read_file' for specific files.
|
|
25
|
+
- Use 'search_file_content' (regex-backed grep) to find patterns or usage across the codebase.
|
|
26
|
+
- Use 'get_document_symbols' for a quick structural overview of a file.
|
|
27
|
+
3. Command Execution:
|
|
28
|
+
- For quick, non-interactive tasks, use 'execute_command'.
|
|
29
|
+
- For long-running processes (e.g., dev servers), use 'start_background_task' and follow up with 'get_background_task_logs'.
|
|
30
|
+
- ${isWin ? "Critical: Use Windows-compatible commands (e.g., 'dir', 'copy', 'del', 'type'). Use backslashes '\\' for paths in commands." : "Critical: Use POSIX-compatible commands (e.g., 'ls', 'cp', 'rm', 'cat'). Use forward slashes '/' for paths."}
|
|
31
|
+
4. Specialized Skills: If a '.staff/skills' or '.claude/skills' directory exists, use the 'skill' tool to load domain-specific workflows which will augment your current context.
|
|
32
|
+
5. Search & Replace: When refactoring, use 'search_file_content' to find all occurrences, then 'edit_file_by_replace' for precise, line-based replacements.
|
|
33
|
+
6. Verification: Use 'get_diagnostics' after editing code to ensure no errors were introduced.
|
|
34
|
+
`.trim();
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=system-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-tools.js","sourceRoot":"","sources":["../../../src/tools/system-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB,EAAE,QAAyB;IAC9E,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,QAAQ,KAAK,OAAO,CAAC;IACnC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC;IACjF,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,EAAE,CAAC;IAE9C,OAAO;;;QAGD,QAAQ;mBACG,KAAK;uBACD,UAAU;2CACU,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;qBAC5C,IAAI,CAAC,GAAG;;;;;;;;;;;OAWtB,KAAK,CAAC,CAAC,CAAC,6HAA6H,CAAC,CAAC,CAAC,6GAA6G;;;;CAI3P,CAAC,IAAI,EAAE,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import cors from "cors";
|
|
3
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
/**
|
|
6
|
+
* Starts an Express server that hosts the MCP server over Streamable HTTP.
|
|
7
|
+
*/
|
|
8
|
+
export async function startHttpServer(server, port, host = "0.0.0.0") {
|
|
9
|
+
const app = express();
|
|
10
|
+
// Enable CORS for all origins, including the MCP Inspector
|
|
11
|
+
app.use(cors());
|
|
12
|
+
// Necessary for processing JSON-RPC messages (POST)
|
|
13
|
+
// We use express.json() but also need to be careful not to consume the stream if transport needs it.
|
|
14
|
+
// However, StreamableHTTPServerTransport.handleRequest accepts parsedBody.
|
|
15
|
+
app.use(express.json());
|
|
16
|
+
// Use a single transport instance for the lifetime of the HTTP server.
|
|
17
|
+
const transport = new StreamableHTTPServerTransport({
|
|
18
|
+
sessionIdGenerator: () => randomUUID(),
|
|
19
|
+
// VERY IMPORTANT: Enable JSON responses for POST requests.
|
|
20
|
+
// This allows the client to receive tool lists and call results directly in the POST response,
|
|
21
|
+
// which is what the Anthropic Inspector and many other clients expect.
|
|
22
|
+
enableJsonResponse: true,
|
|
23
|
+
});
|
|
24
|
+
// Connect the MCP server instance to this transport.
|
|
25
|
+
await server.connect(transport);
|
|
26
|
+
/**
|
|
27
|
+
* Unified handler for MCP requests.
|
|
28
|
+
* Handles GET (SSE) and POST (JSON-RPC).
|
|
29
|
+
*/
|
|
30
|
+
const mcpHandler = async (req, res) => {
|
|
31
|
+
try {
|
|
32
|
+
// In Streamable HTTP, handleRequest handles the full lifecycle based on method.
|
|
33
|
+
await transport.handleRequest(req, res, req.body);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.error("[MCP HTTP Error]:", error);
|
|
37
|
+
if (!res.headersSent) {
|
|
38
|
+
res.status(500).json({
|
|
39
|
+
error: "Internal Server Error",
|
|
40
|
+
message: error instanceof Error ? error.message : String(error)
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
// Route for all MCP interactions.
|
|
46
|
+
app.all("/mcp", mcpHandler);
|
|
47
|
+
// Standard fallbacks
|
|
48
|
+
app.get("/sse", mcpHandler);
|
|
49
|
+
app.post("/messages", mcpHandler);
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
app.listen(port, host, () => {
|
|
52
|
+
console.error(`[MCP HTTP] Server listening on http://${host}:${port}/mcp`);
|
|
53
|
+
console.error(`[MCP HTTP] JSON Response enabled: true`);
|
|
54
|
+
resolve();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/transports/http.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAiB,EAAE,IAAY,EAAE,OAAe,SAAS;IAC7F,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IAEtB,2DAA2D;IAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAEhB,oDAAoD;IACpD,qGAAqG;IACrG,2EAA2E;IAC3E,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAExB,uEAAuE;IACvE,MAAM,SAAS,GAAG,IAAI,6BAA6B,CAAC;QAClD,kBAAkB,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE;QACtC,4DAA4D;QAC5D,+FAA+F;QAC/F,uEAAuE;QACvE,kBAAkB,EAAE,IAAI;KACzB,CAAC,CAAC;IAEH,qDAAqD;IACrD,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC;;;OAGG;IACH,MAAM,UAAU,GAAG,KAAK,EAAE,GAAoB,EAAE,GAAqB,EAAE,EAAE;QACvE,IAAI,CAAC;YACH,gFAAgF;YAChF,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;YAC1C,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,KAAK,EAAE,uBAAuB;oBAC9B,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;iBAChE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,kCAAkC;IAClC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAE5B,qBAAqB;IACrB,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC5B,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAElC,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACnC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE;YAC1B,OAAO,CAAC,KAAK,CAAC,yCAAyC,IAAI,IAAI,IAAI,MAAM,CAAC,CAAC;YAC3E,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YACxD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
|
+
export async function startStdioServer(server) {
|
|
3
|
+
const transport = new StdioServerTransport();
|
|
4
|
+
// Redirect stdout to stderr so console.log doesn't break protocol
|
|
5
|
+
const originalLog = console.log;
|
|
6
|
+
console.log = (...args) => {
|
|
7
|
+
console.error(...args);
|
|
8
|
+
};
|
|
9
|
+
try {
|
|
10
|
+
await server.connect(transport);
|
|
11
|
+
console.error("MCP Server (Stdio) is running.");
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
console.error("Stdio connection failed:", error);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../../src/transports/stdio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAiB;IACtD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,kEAAkE;IAClE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;IAChC,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE;QACxB,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAClD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { SecurityManager } from "../src/security.js";
|
|
5
|
+
test("SecurityManager - Should allow paths inside allowed directories", () => {
|
|
6
|
+
const security = new SecurityManager("/tmp/sandbox");
|
|
7
|
+
const validated = security.resolveAndValidatePath("test.txt", "/tmp/sandbox");
|
|
8
|
+
assert.strictEqual(validated, path.resolve("/tmp/sandbox/test.txt"));
|
|
9
|
+
});
|
|
10
|
+
test("SecurityManager - Should block paths outside allowed directories", () => {
|
|
11
|
+
const security = new SecurityManager("/tmp/sandbox");
|
|
12
|
+
assert.throws(() => {
|
|
13
|
+
security.resolveAndValidatePath("../outside.txt", "/tmp/sandbox");
|
|
14
|
+
}, /Security Error/);
|
|
15
|
+
});
|
|
16
|
+
test("SecurityManager - Should allow subdirectory access", () => {
|
|
17
|
+
const security = new SecurityManager("/tmp/sandbox");
|
|
18
|
+
const validated = security.resolveAndValidatePath("subdir/file.ts", "/tmp/sandbox");
|
|
19
|
+
assert.strictEqual(validated, path.resolve("/tmp/sandbox/subdir/file.ts"));
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=security.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.test.js","sourceRoot":"","sources":["../../tests/security.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,IAAI,CAAC,iEAAiE,EAAE,GAAG,EAAE;IAC3E,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,cAAc,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,QAAQ,CAAC,sBAAsB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAC9E,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kEAAkE,EAAE,GAAG,EAAE;IAC5E,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,cAAc,CAAC,CAAC;IACrD,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE;QACjB,QAAQ,CAAC,sBAAsB,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IACpE,CAAC,EAAE,gBAAgB,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,oDAAoD,EAAE,GAAG,EAAE;IAC9D,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,cAAc,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,QAAQ,CAAC,sBAAsB,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IACpF,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,CAAC;AAC7E,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { SecurityManager } from "../security.js";
|
|
3
|
+
/**
|
|
4
|
+
* Registers file-related tools using the latest registerTool API.
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerFileTools(server: McpServer, security: SecurityManager): void;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { CHARACTER_LIMIT } from "../constants.js";
|
|
5
|
+
/**
|
|
6
|
+
* Registers file-related tools using the latest registerTool API.
|
|
7
|
+
*/
|
|
8
|
+
export function registerFileTools(server, security) {
|
|
9
|
+
// read_file
|
|
10
|
+
server.registerTool("read_file", {
|
|
11
|
+
description: "Read the content of a file from the allowed workspace.",
|
|
12
|
+
inputSchema: z.object({
|
|
13
|
+
path: z.string().describe("Relative path from the workspace to the file to read."),
|
|
14
|
+
}).strict(),
|
|
15
|
+
}, async ({ path: filePath }) => {
|
|
16
|
+
try {
|
|
17
|
+
const validatedPath = security.resolveAndValidatePath(filePath);
|
|
18
|
+
let content = await fs.readFile(validatedPath, "utf-8");
|
|
19
|
+
if (content.length > CHARACTER_LIMIT) {
|
|
20
|
+
content = content.substring(0, CHARACTER_LIMIT) + "\n\n...[Content truncated for brevity]";
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
content: [{ type: "text", text: content }],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
return {
|
|
28
|
+
content: [{ type: "text", text: `Error reading file: ${error.message}` }],
|
|
29
|
+
isError: true,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
// write_file
|
|
34
|
+
server.registerTool("write_file", {
|
|
35
|
+
description: "Write or overwrite a file in the allowed workspace.",
|
|
36
|
+
inputSchema: z.object({
|
|
37
|
+
path: z.string().describe("Path to the file to write."),
|
|
38
|
+
content: z.string().describe("Content to write into the file."),
|
|
39
|
+
}).strict(),
|
|
40
|
+
}, async ({ path: filePath, content }) => {
|
|
41
|
+
try {
|
|
42
|
+
const validatedPath = security.resolveAndValidatePath(filePath);
|
|
43
|
+
await fs.mkdir(path.dirname(validatedPath), { recursive: true });
|
|
44
|
+
await fs.writeFile(validatedPath, content, "utf-8");
|
|
45
|
+
return {
|
|
46
|
+
content: [{ type: "text", text: `Successfully wrote file: ${filePath}` }],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return {
|
|
51
|
+
content: [{ type: "text", text: `Error writing file: ${error.message}` }],
|
|
52
|
+
isError: true,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
// delete_file
|
|
57
|
+
server.registerTool("delete_file", {
|
|
58
|
+
description: "Delete a file from the allowed workspace.",
|
|
59
|
+
inputSchema: z.object({
|
|
60
|
+
path: z.string().describe("Path to the file to delete."),
|
|
61
|
+
}).strict(),
|
|
62
|
+
}, async ({ path: filePath }) => {
|
|
63
|
+
try {
|
|
64
|
+
const validatedPath = security.resolveAndValidatePath(filePath);
|
|
65
|
+
await fs.unlink(validatedPath);
|
|
66
|
+
return {
|
|
67
|
+
content: [{ type: "text", text: `Successfully deleted file: ${filePath}` }],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
return {
|
|
72
|
+
content: [{ type: "text", text: `Error deleting file: ${error.message}` }],
|
|
73
|
+
isError: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
// list_dir
|
|
78
|
+
server.registerTool("list_dir", {
|
|
79
|
+
description: "List files and directories within a specific path.",
|
|
80
|
+
inputSchema: z.object({
|
|
81
|
+
path: z.string().default(".").describe("Path to list (defaults to workspace root)."),
|
|
82
|
+
}).strict(),
|
|
83
|
+
}, async ({ path: dirPath }) => {
|
|
84
|
+
try {
|
|
85
|
+
const validatedPath = security.resolveAndValidatePath(dirPath);
|
|
86
|
+
const entries = await fs.readdir(validatedPath, { withFileTypes: true });
|
|
87
|
+
const result = entries.map(entry => {
|
|
88
|
+
return `${entry.isDirectory() ? "[DIR]" : "[FILE]"} ${entry.name}`;
|
|
89
|
+
}).join("\n");
|
|
90
|
+
return {
|
|
91
|
+
content: [{ type: "text", text: result || "(Directory is empty)" }],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
return {
|
|
96
|
+
content: [{ type: "text", text: `Error listing directory: ${error.message}` }],
|
|
97
|
+
isError: true,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=file-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-tools.js","sourceRoot":"","sources":["../../src/tools/file-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { SecurityManager } from "../security.js";
|
|
3
|
+
/**
|
|
4
|
+
* Registers LSP-related tools using the latest registerTool API.
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerLspTools(server: McpServer, security: SecurityManager): void;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Project } from "ts-morph";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/**
|
|
4
|
+
* Registers LSP-related tools using the latest registerTool API.
|
|
5
|
+
*/
|
|
6
|
+
export function registerLspTools(server, security) {
|
|
7
|
+
// get_document_symbols
|
|
8
|
+
server.registerTool("get_document_symbols", {
|
|
9
|
+
description: "Extract high-level symbols (classes, functions, interfaces) from a TypeScript file.",
|
|
10
|
+
inputSchema: z.object({
|
|
11
|
+
path: z.string().describe("TypeScript/JavaScript file path to analyze."),
|
|
12
|
+
}).strict(),
|
|
13
|
+
}, async ({ path: filePath }) => {
|
|
14
|
+
try {
|
|
15
|
+
const validatedPath = security.resolveAndValidatePath(filePath);
|
|
16
|
+
const project = new Project();
|
|
17
|
+
const sourceFile = project.addSourceFileAtPath(validatedPath);
|
|
18
|
+
const symbols = [];
|
|
19
|
+
sourceFile.getClasses().forEach(c => symbols.push(`[Class] ${c.getName()} (Line ${c.getStartLineNumber()})`));
|
|
20
|
+
sourceFile.getInterfaces().forEach(i => symbols.push(`[Interface] ${i.getName()} (Line ${i.getStartLineNumber()})`));
|
|
21
|
+
sourceFile.getFunctions().forEach(f => symbols.push(`[Function] ${f.getName()} (Line ${f.getStartLineNumber()})`));
|
|
22
|
+
sourceFile.getEnums().forEach(e => symbols.push(`[Enum] ${e.getName()} (Line ${e.getStartLineNumber()})`));
|
|
23
|
+
sourceFile.getTypeAliases().forEach(t => symbols.push(`[TypeAlias] ${t.getName()} (Line ${t.getStartLineNumber()})`));
|
|
24
|
+
return {
|
|
25
|
+
content: [{ type: "text", text: symbols.join("\n") || "(No significant symbols found)" }],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return {
|
|
30
|
+
content: [{ type: "text", text: `LSP Error: ${error.message}` }],
|
|
31
|
+
isError: true,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
// get_diagnostics
|
|
36
|
+
server.registerTool("get_diagnostics", {
|
|
37
|
+
description: "Get TypeScript diagnostics/errors for a file or directory.",
|
|
38
|
+
inputSchema: z.object({
|
|
39
|
+
path: z.string().describe("File or directory path to check for TypeScript diagnostics."),
|
|
40
|
+
}).strict(),
|
|
41
|
+
}, async ({ path: checkPath }) => {
|
|
42
|
+
try {
|
|
43
|
+
const validatedPath = security.resolveAndValidatePath(checkPath);
|
|
44
|
+
const project = new Project();
|
|
45
|
+
project.addSourceFilesAtPaths([
|
|
46
|
+
validatedPath.endsWith(".ts") || validatedPath.endsWith(".js")
|
|
47
|
+
? validatedPath
|
|
48
|
+
: `${validatedPath}/**/*.{ts,js,tsx,jsx}`
|
|
49
|
+
]);
|
|
50
|
+
const diagnostics = project.getPreEmitDiagnostics();
|
|
51
|
+
const output = diagnostics.map(diag => {
|
|
52
|
+
const messageText = diag.getMessageText();
|
|
53
|
+
const line = diag.getLineNumber();
|
|
54
|
+
const file = diag.getSourceFile()?.getFilePath() || "Unknown file";
|
|
55
|
+
const formattedMessage = typeof messageText === "string" ? messageText : messageText.getMessageText();
|
|
56
|
+
return `[${file}:${line}] ${formattedMessage}`;
|
|
57
|
+
}).join("\n");
|
|
58
|
+
return {
|
|
59
|
+
content: [{ type: "text", text: output || "No TypeScript diagnostics found." }],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return {
|
|
64
|
+
content: [{ type: "text", text: `LSP Error: ${error.message}` }],
|
|
65
|
+
isError: true,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=lsp-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lsp-tools.js","sourceRoot":"","sources":["../../src/tools/lsp-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { SecurityManager } from "../security.js";
|
|
3
|
+
/**
|
|
4
|
+
* Registers shell-related tools using the latest registerTool API.
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerShellTools(server: McpServer, security: SecurityManager): void;
|