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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 staff-mcp
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# staff-mcp
|
|
2
|
+
|
|
3
|
+
[English](./README.md) | [简体中文](./README_zh.md)
|
|
4
|
+
|
|
5
|
+
A powerful Model Context Protocol (MCP) server providing file management, shell execution, and LSP capabilities. Built for seamless integration with AI assistants like Claude Desktop, IDE plugins, and custom agents.
|
|
6
|
+
|
|
7
|
+
## 🚀 Quick Start
|
|
8
|
+
|
|
9
|
+
### Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install
|
|
13
|
+
npm run build
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Running the Server
|
|
17
|
+
|
|
18
|
+
**Using npx (Quickest)**
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# From local directory
|
|
22
|
+
npx . --working-dir /path/to/your/project
|
|
23
|
+
|
|
24
|
+
# If published to npm (e.g., @your-org/staff-mcp)
|
|
25
|
+
# npx -y @your-org/staff-mcp --working-dir /path/to/your/project
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Stdio Mode (Recommended for Claude Desktop)**
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Using npm (Recommended)
|
|
32
|
+
npm start -- --working-dir /path/to/your/project
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**HTTP Mode**
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Using npm
|
|
39
|
+
npm start -- --transport http --port 3000
|
|
40
|
+
|
|
41
|
+
# Using node directly
|
|
42
|
+
node dist/src/index.js --transport http --port 3000
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### CLI Arguments
|
|
46
|
+
|
|
47
|
+
| Option | Description | Default |
|
|
48
|
+
| :--- | :--- | :--- |
|
|
49
|
+
| `--working-dir` | Root directory for the sandbox | `process.cwd()` |
|
|
50
|
+
| `--allowed-dir` | Extra directories allowed for access | `[]` |
|
|
51
|
+
| `--transport` | Transport type (`stdio` or `http`) | `stdio` |
|
|
52
|
+
| `--port` | Port for HTTP server | `3000` |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 🛠️ Supported MCP Features
|
|
57
|
+
|
|
58
|
+
- **Tools**: Comprehensive file operations, shell execution, and LSP support.
|
|
59
|
+
- **Skills & Prompts**: Compatible with the `SKILL.md` format. Automatically detects skills in `.staff/skills/`, `.claude/skills/`, etc.
|
|
60
|
+
- **MCP Native Support**: Implements the `instructions` mechanism to provide model context for environment awareness (OS, shell, etc.) and tool relationships.
|
|
61
|
+
|
|
62
|
+
### Skill File Format (`SKILL.md`)
|
|
63
|
+
|
|
64
|
+
```markdown
|
|
65
|
+
---
|
|
66
|
+
name: my-skill
|
|
67
|
+
description: Skill description
|
|
68
|
+
---
|
|
69
|
+
Skill instructions here...
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 💻 Cross-Platform Compatibility
|
|
75
|
+
|
|
76
|
+
`staff-mcp` handles environment differences automatically:
|
|
77
|
+
- **Paths**: Resolves `\` (Windows) and `/` (Unix) based on host OS.
|
|
78
|
+
- **Shell**: Uses `cmd.exe` on Windows and `sh` on Linux/macOS.
|
|
79
|
+
- **Line Endings**: Supports both `CRLF` and `LF` for file operations.
|
|
80
|
+
|
|
81
|
+
## 🧪 Development
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm run dev -- --working-dir ./test-workspace
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 📄 License
|
|
88
|
+
|
|
89
|
+
MIT
|
package/README_zh.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# staff-mcp
|
|
2
|
+
|
|
3
|
+
[English](./README.md) | [简体中文](./README_zh.md)
|
|
4
|
+
|
|
5
|
+
一个功能强大的 Model Context Protocol (MCP) 服务端,提供文件管理、Shell 执行和 LSP 能力。专为 AI 助手(如 Claude Desktop、IDE 插件和自定义 Agent)的无缝集成而设计。
|
|
6
|
+
|
|
7
|
+
## 🚀 快速开始
|
|
8
|
+
|
|
9
|
+
### 安装
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install
|
|
13
|
+
npm run build
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### 运行服务
|
|
17
|
+
|
|
18
|
+
**使用 npx (最快方式)**
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# 在项目本地运行
|
|
22
|
+
npx . --working-dir /你的项目/路径
|
|
23
|
+
|
|
24
|
+
# 如果已发布到 npm (例如 @your-org/staff-mcp)
|
|
25
|
+
# npx -y @your-org/staff-mcp --working-dir /你的项目/路径
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Stdio 模式 (Claude Desktop 推荐方式)**
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# 使用 npm (推荐)
|
|
32
|
+
npm start -- --working-dir /你的项目/路径
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**HTTP 模式**
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# 使用 npm
|
|
39
|
+
npm start -- --transport http --port 3000
|
|
40
|
+
|
|
41
|
+
# 使用 node 直接启动
|
|
42
|
+
node dist/src/index.js --transport http --port 3000
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 命令行参数
|
|
46
|
+
|
|
47
|
+
| 参数 | 说明 | 默认值 |
|
|
48
|
+
| :--- | :--- | :--- |
|
|
49
|
+
| `--working-dir` | 沙箱根目录 | `process.cwd()` |
|
|
50
|
+
| `--allowed-dir` | 额外允许访问的目录 | `[]` |
|
|
51
|
+
| `--transport` | 传输方式 (`stdio` 或 `http`) | `stdio` |
|
|
52
|
+
| `--port` | HTTP 服务端口 | `3000` |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 🛠️ 支持的 MCP 特性
|
|
57
|
+
|
|
58
|
+
- **Tools (工具)**: 提供完整的文件操作、Shell 执行和 LSP(符号/诊断)支持。
|
|
59
|
+
- **Skills (技能)**: 兼容 `SKILL.md` 格式。自动检测并注册 `.staff/skills/`、`.claude/skills/` 等目录下的技能及 Prompts。
|
|
60
|
+
- **MCP 原生支持**: 实现了 `instructions` 机制,为模型自动提供环境感知(OS、Shell、路径规则)及工具调用建议。
|
|
61
|
+
|
|
62
|
+
### Skill 文件格式 (`SKILL.md`)
|
|
63
|
+
|
|
64
|
+
```markdown
|
|
65
|
+
---
|
|
66
|
+
name: my-skill
|
|
67
|
+
description: 技能描述
|
|
68
|
+
---
|
|
69
|
+
这里是技能的具体指令...
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 💻 跨平台兼容性
|
|
75
|
+
|
|
76
|
+
`staff-mcp` 自动处理环境差异:
|
|
77
|
+
- **路径**: 根据宿主系统解析 `\` (Windows) 或 `/` (Unix)。
|
|
78
|
+
- **Shell**: Windows 使用 `cmd.exe`,Linux/macOS 使用 `sh`。
|
|
79
|
+
- **换行符**: 文件操作支持 `CRLF` 和 `LF`。
|
|
80
|
+
|
|
81
|
+
## 🧪 开发
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm run dev -- --working-dir ./test-workspace
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 📄 开源协议
|
|
88
|
+
|
|
89
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { createServer } from "./server.js";
|
|
4
|
+
import { startStdioServer } from "./transports/stdio.js";
|
|
5
|
+
import { startHttpServer } from "./transports/http.js";
|
|
6
|
+
const program = new Command();
|
|
7
|
+
program
|
|
8
|
+
.name("dev-env-mcp-server")
|
|
9
|
+
.description("MCP Server with file, shell, and LSP capabilities.")
|
|
10
|
+
.version("1.0.0")
|
|
11
|
+
.option("-t, --transport <type>", "Transport type (stdio or http)", "stdio")
|
|
12
|
+
.option("-p, --port <number>", "Port for HTTP server", "3000")
|
|
13
|
+
.option("-h, --host <address>", "Host for HTTP server", "127.0.0.1")
|
|
14
|
+
.option("-d, --allowed-dir <paths...>", "Directories allowed for sandbox", [process.cwd()])
|
|
15
|
+
.action(async (options) => {
|
|
16
|
+
const allowedDirs = options.allowedDir.map((d) => path.resolve(d));
|
|
17
|
+
const server = createServer("dev-env-mcp-server", "1.0.0", allowedDirs);
|
|
18
|
+
if (options.transport === "http") {
|
|
19
|
+
await startHttpServer(server, parseInt(options.port, 10), options.host);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
await startStdioServer(server);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
program.parse(process.argv);
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,oBAAoB,CAAC;KAC1B,WAAW,CAAC,oDAAoD,CAAC;KACjE,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,wBAAwB,EAAE,gCAAgC,EAAE,OAAO,CAAC;KAC3E,MAAM,CAAC,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,CAAC;KAC7D,MAAM,CAAC,sBAAsB,EAAE,sBAAsB,EAAE,WAAW,CAAC;KACnE,MAAM,CAAC,8BAA8B,EAAE,iCAAiC,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;KAC1F,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,YAAY,CAAC,oBAAoB,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IAExE,IAAI,OAAO,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QACjC,MAAM,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,CAAC;SAAM,CAAC;QACN,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class SecurityManager {
|
|
2
|
+
private allowedDirs;
|
|
3
|
+
constructor(allowedDirs: string[]);
|
|
4
|
+
/**
|
|
5
|
+
* Resolves a target path and ensures it lies within one of the allowed directories.
|
|
6
|
+
* @param targetPath The relative or absolute path requested.
|
|
7
|
+
* @param cwd Optional base directory for resolution (must also be validated if provided).
|
|
8
|
+
* @returns The absolute, validated path.
|
|
9
|
+
* @throws Error if the path is outside the allowed sandbox.
|
|
10
|
+
*/
|
|
11
|
+
resolveAndValidatePath(targetPath: string, cwd?: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Validates if a specific directory is allowed.
|
|
14
|
+
*/
|
|
15
|
+
validateDirectory(dirPath: string): string;
|
|
16
|
+
}
|
package/dist/security.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
export class SecurityManager {
|
|
3
|
+
allowedDirs;
|
|
4
|
+
constructor(allowedDirs) {
|
|
5
|
+
this.allowedDirs = allowedDirs.map(dir => path.resolve(dir));
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolves a target path and ensures it lies within one of the allowed directories.
|
|
9
|
+
* @param targetPath The relative or absolute path requested.
|
|
10
|
+
* @param cwd Optional base directory for resolution (must also be validated if provided).
|
|
11
|
+
* @returns The absolute, validated path.
|
|
12
|
+
* @throws Error if the path is outside the allowed sandbox.
|
|
13
|
+
*/
|
|
14
|
+
resolveAndValidatePath(targetPath, cwd) {
|
|
15
|
+
const base = cwd ? path.resolve(cwd) : process.cwd();
|
|
16
|
+
// If cwd is provided, we should probably ensure it's within allowedDirs as well
|
|
17
|
+
// but typically we resolve target relative to base.
|
|
18
|
+
const resolvedPath = path.resolve(base, targetPath);
|
|
19
|
+
const isAllowed = this.allowedDirs.some(allowedDir => {
|
|
20
|
+
const relative = path.relative(allowedDir, resolvedPath);
|
|
21
|
+
return !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
22
|
+
});
|
|
23
|
+
if (!isAllowed) {
|
|
24
|
+
throw new Error(`Security Error: Path "${resolvedPath}" is outside the allowed directories.`);
|
|
25
|
+
}
|
|
26
|
+
return resolvedPath;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validates if a specific directory is allowed.
|
|
30
|
+
*/
|
|
31
|
+
validateDirectory(dirPath) {
|
|
32
|
+
const resolved = path.resolve(dirPath);
|
|
33
|
+
const isAllowed = this.allowedDirs.some(allowedDir => {
|
|
34
|
+
const relative = path.relative(allowedDir, resolved);
|
|
35
|
+
return !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
36
|
+
});
|
|
37
|
+
if (!isAllowed) {
|
|
38
|
+
throw new Error(`Security Error: Directory "${resolved}" is not in the allowed list.`);
|
|
39
|
+
}
|
|
40
|
+
return resolved;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,OAAO,eAAe;IAClB,WAAW,CAAW;IAE9B,YAAY,WAAqB;QAC/B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED;;;;;;OAMG;IACI,sBAAsB,CAAC,UAAkB,EAAE,GAAY;QAC5D,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAErD,gFAAgF;QAChF,oDAAoD;QACpD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEpD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;YACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;YACzD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,yBAAyB,YAAY,uCAAuC,CAAC,CAAC;QAChG,CAAC;QAED,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;OAEG;IACI,iBAAiB,CAAC,OAAe;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;YACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACrD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,+BAA+B,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates and initializes a new McpServer with all tools.
|
|
4
|
+
* @param name The server's identification name.
|
|
5
|
+
* @param version The server's version.
|
|
6
|
+
* @param allowedDirs Directories for the SecurityManager.
|
|
7
|
+
* @returns An initialized McpServer instance.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createServer(name: string, version: string, allowedDirs: string[]): McpServer;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { SecurityManager } from "./security.js";
|
|
3
|
+
import { registerFileTools } from "./tools/file-tools.js";
|
|
4
|
+
import { registerShellTools } from "./tools/shell-tools.js";
|
|
5
|
+
import { registerLspTools } from "./tools/lsp-tools.js";
|
|
6
|
+
/**
|
|
7
|
+
* Creates and initializes a new McpServer with all tools.
|
|
8
|
+
* @param name The server's identification name.
|
|
9
|
+
* @param version The server's version.
|
|
10
|
+
* @param allowedDirs Directories for the SecurityManager.
|
|
11
|
+
* @returns An initialized McpServer instance.
|
|
12
|
+
*/
|
|
13
|
+
export function createServer(name, version, allowedDirs) {
|
|
14
|
+
const server = new McpServer({
|
|
15
|
+
name,
|
|
16
|
+
version,
|
|
17
|
+
});
|
|
18
|
+
const security = new SecurityManager(allowedDirs);
|
|
19
|
+
// Register all tool modules
|
|
20
|
+
registerFileTools(server, security);
|
|
21
|
+
registerShellTools(server, security);
|
|
22
|
+
registerLspTools(server, security);
|
|
23
|
+
return server;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAe,EAAE,WAAqB;IAC/E,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI;QACJ,OAAO;KACR,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC;IAElD,4BAA4B;IAC5B,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACpC,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACrC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEnC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { createServer } from "./server.js";
|
|
5
|
+
import { startStdioServer } from "./transports/stdio.js";
|
|
6
|
+
import { startHttpServer } from "./transports/http.js";
|
|
7
|
+
const program = new Command();
|
|
8
|
+
program
|
|
9
|
+
.name("staff-mcp")
|
|
10
|
+
.description("MCP Server with file, shell, and LSP capabilities.")
|
|
11
|
+
.version("1.0.0")
|
|
12
|
+
.option("-t, --transport <type>", "Transport type (stdio or http)", "stdio")
|
|
13
|
+
.option("-p, --port <number>", "Port for HTTP server", "3000")
|
|
14
|
+
.option("-h, --host <address>", "Host for HTTP server", "127.0.0.1")
|
|
15
|
+
.option("-w, --working-dir <path>", "Working directory for the server (defaults to current execution path)", process.cwd())
|
|
16
|
+
.option("-d, --allowed-dir <paths...>", "Additional directories allowed for sandbox", [])
|
|
17
|
+
.action(async (options) => {
|
|
18
|
+
const workingDir = path.resolve(options.workingDir);
|
|
19
|
+
const allowedDirs = options.allowedDir.map((d) => path.resolve(d));
|
|
20
|
+
const server = createServer("staff-mcp", "1.0.0", workingDir, allowedDirs);
|
|
21
|
+
if (options.transport === "http") {
|
|
22
|
+
await startHttpServer(server, parseInt(options.port, 10), options.host);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
await startStdioServer(server);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
program.parse(process.argv);
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,oDAAoD,CAAC;KACjE,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,wBAAwB,EAAE,gCAAgC,EAAE,OAAO,CAAC;KAC3E,MAAM,CAAC,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,CAAC;KAC7D,MAAM,CAAC,sBAAsB,EAAE,sBAAsB,EAAE,WAAW,CAAC;KACnE,MAAM,CAAC,0BAA0B,EAAE,uEAAuE,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KAC1H,MAAM,CAAC,8BAA8B,EAAE,4CAA4C,EAAE,EAAE,CAAC;KACxF,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACpD,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAE3E,IAAI,OAAO,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QACjC,MAAM,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,CAAC;SAAM,CAAC;QACN,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class SecurityManager {
|
|
2
|
+
private allowedDirs;
|
|
3
|
+
private workingDir;
|
|
4
|
+
constructor(workingDir: string, allowedDirs?: string[]);
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a target path and ensures it lies within one of the allowed directories.
|
|
7
|
+
* @param targetPath The relative or absolute path requested.
|
|
8
|
+
* @param cwd Optional base directory for resolution (must also be validated if provided).
|
|
9
|
+
* @returns The absolute, validated path.
|
|
10
|
+
* @throws Error if the path is outside the allowed sandbox.
|
|
11
|
+
*/
|
|
12
|
+
resolveAndValidatePath(targetPath: string, cwd?: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Validates if a specific directory is allowed.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Validates if a specific directory is allowed.
|
|
18
|
+
*/
|
|
19
|
+
validateDirectory(dirPath: string): string;
|
|
20
|
+
getAllowedDirs(): string[];
|
|
21
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
export class SecurityManager {
|
|
3
|
+
allowedDirs;
|
|
4
|
+
workingDir;
|
|
5
|
+
constructor(workingDir, allowedDirs = []) {
|
|
6
|
+
this.workingDir = path.resolve(workingDir);
|
|
7
|
+
// Working directory is always allowed
|
|
8
|
+
const resolvedAllowedDirs = allowedDirs.map(dir => path.resolve(dir));
|
|
9
|
+
this.allowedDirs = Array.from(new Set([this.workingDir, ...resolvedAllowedDirs]));
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolves a target path and ensures it lies within one of the allowed directories.
|
|
13
|
+
* @param targetPath The relative or absolute path requested.
|
|
14
|
+
* @param cwd Optional base directory for resolution (must also be validated if provided).
|
|
15
|
+
* @returns The absolute, validated path.
|
|
16
|
+
* @throws Error if the path is outside the allowed sandbox.
|
|
17
|
+
*/
|
|
18
|
+
resolveAndValidatePath(targetPath, cwd) {
|
|
19
|
+
const base = cwd ? path.resolve(cwd) : this.workingDir;
|
|
20
|
+
const resolvedPath = path.resolve(base, targetPath);
|
|
21
|
+
const isAllowed = this.allowedDirs.some(allowedDir => {
|
|
22
|
+
const relative = path.relative(allowedDir, resolvedPath);
|
|
23
|
+
return !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
24
|
+
});
|
|
25
|
+
if (!isAllowed) {
|
|
26
|
+
throw new Error(`Security Error: Path "${resolvedPath}" is outside the allowed directories.`);
|
|
27
|
+
}
|
|
28
|
+
return resolvedPath;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Validates if a specific directory is allowed.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Validates if a specific directory is allowed.
|
|
35
|
+
*/
|
|
36
|
+
validateDirectory(dirPath) {
|
|
37
|
+
const resolved = path.resolve(this.workingDir, dirPath);
|
|
38
|
+
const isAllowed = this.allowedDirs.some(allowedDir => {
|
|
39
|
+
const relative = path.relative(allowedDir, resolved);
|
|
40
|
+
return !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
41
|
+
});
|
|
42
|
+
if (!isAllowed) {
|
|
43
|
+
throw new Error(`Security Error: Directory "${resolved}" is not in the allowed list.`);
|
|
44
|
+
}
|
|
45
|
+
return resolved;
|
|
46
|
+
}
|
|
47
|
+
getAllowedDirs() {
|
|
48
|
+
return [...this.allowedDirs];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/security.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,OAAO,eAAe;IAClB,WAAW,CAAW;IACtB,UAAU,CAAS;IAE3B,YAAY,UAAkB,EAAE,cAAwB,EAAE;QACxD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3C,sCAAsC;QACtC,MAAM,mBAAmB,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC;IAED;;;;;;OAMG;IACI,sBAAsB,CAAC,UAAkB,EAAE,GAAY;QAC5D,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QAEvD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAEpD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;YACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;YACzD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,yBAAyB,YAAY,uCAAuC,CAAC,CAAC;QAChG,CAAC;QAED,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;OAEG;IACH;;OAEG;IACI,iBAAiB,CAAC,OAAe;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;YACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACrD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,+BAA+B,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEM,cAAc;QACnB,OAAO,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates and initializes a new McpServer with all functional tools.
|
|
4
|
+
* @param name The server's identification name.
|
|
5
|
+
* @param version The server's version.
|
|
6
|
+
* @param workingDir The working directory for the server.
|
|
7
|
+
* @param allowedDirs Additional directories for the SecurityManager.
|
|
8
|
+
* @returns An initialized McpServer instance.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createServer(name: string, version: string, workingDir: string, allowedDirs: string[]): McpServer;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { SecurityManager } from "./security.js";
|
|
3
|
+
import { registerFileTools } from "./tools/file-tools.js";
|
|
4
|
+
import { registerShellTools } from "./tools/shell-tools.js";
|
|
5
|
+
import { registerLspTools } from "./tools/lsp-tools.js";
|
|
6
|
+
import { registerSkillTools } from "./tools/skill-tools.js";
|
|
7
|
+
import { getMcpInstructions } from "./tools/system-tools.js";
|
|
8
|
+
/**
|
|
9
|
+
* Creates and initializes a new McpServer with all functional tools.
|
|
10
|
+
* @param name The server's identification name.
|
|
11
|
+
* @param version The server's version.
|
|
12
|
+
* @param workingDir The working directory for the server.
|
|
13
|
+
* @param allowedDirs Additional directories for the SecurityManager.
|
|
14
|
+
* @returns An initialized McpServer instance.
|
|
15
|
+
*/
|
|
16
|
+
export function createServer(name, version, workingDir, allowedDirs) {
|
|
17
|
+
const security = new SecurityManager(workingDir, allowedDirs);
|
|
18
|
+
// Generate instructions with system-specific details (OS, shell, etc.)
|
|
19
|
+
const instructions = getMcpInstructions(workingDir, security);
|
|
20
|
+
const server = new McpServer({
|
|
21
|
+
name,
|
|
22
|
+
version,
|
|
23
|
+
}, {
|
|
24
|
+
// Pass the instruction string to the initialize response
|
|
25
|
+
instructions,
|
|
26
|
+
});
|
|
27
|
+
// Register all functional tool modules
|
|
28
|
+
registerFileTools(server, security);
|
|
29
|
+
registerShellTools(server, security);
|
|
30
|
+
registerLspTools(server, security);
|
|
31
|
+
registerSkillTools(server, workingDir, security);
|
|
32
|
+
return server;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAe,EAAE,UAAkB,EAAE,WAAqB;IACnG,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAE9D,uEAAuE;IACvE,MAAM,YAAY,GAAG,kBAAkB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAE9D,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI;QACJ,OAAO;KACR,EACD;QACE,yDAAyD;QACzD,YAAY;KACb,CACF,CAAC;IAEF,uCAAuC;IACvC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACpC,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACrC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IAEjD,OAAO,MAAM,CAAC;AAChB,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;
|