superkit-mcp-server 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/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Super-Kit MCP Server
2
+
3
+ This is a Model Context Protocol (MCP) server that exposes the agents, skills, and workflows of **Super-Kit** to any compatible AI assistant (Cline, Cursor, Gemini, etc.).
4
+
5
+ By installing this MCP server, your AI agent can dynamically list, read, and load the specific operational contexts it needs on the fly, without needing massive system prompts.
6
+
7
+ ## Available Tools
8
+
9
+ - **`list_superkit_assets`**: Lists all available agents, skills (tech/meta), and workflows in the Super-Kit repository.
10
+ - **`load_superkit_agent`**: Loads the system instructions and guidelines for a specific specialist agent (e.g., `data-engineer`).
11
+ - **`load_superkit_skill`**: Loads the skill instructions (`SKILL.md`) for a specific category and skill (e.g., category: `tech`, name: `react-best-practices`).
12
+ - **`load_superkit_workflow`**: Loads the instructions for a specific slash-command workflow (e.g., `work`, `explore`).
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ cd super-kit/mcp-server
18
+ npm install
19
+ npm run build
20
+ ```
21
+
22
+ ## Configuring in AI Platforms
23
+
24
+ ### Cline (VS Code)
25
+ Add the following to your `cline_mcp_settings.json`:
26
+ ```json
27
+ {
28
+ "mcpServers": {
29
+ "superkit": {
30
+ "command": "node",
31
+ "args": ["/absolute/path/to/super-kit/mcp-server/build/index.js"]
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ ### Cursor / Windsurf
38
+ Go to Settings -> Features -> MCP Servers.
39
+ Add a new stdio server:
40
+ - Name: `superkit`
41
+ - Command: `node /absolute/path/to/super-kit/mcp-server/build/index.js`
42
+
43
+ ## How it works
44
+ The server reads directly from the parent `super-kit` directory, resolving paths safely to prevent traversal attacks. It automatically parses and returns the Markdown contents of the structural elements.
package/build/index.js ADDED
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import * as path from "path";
6
+ import * as fs from "fs/promises";
7
+ import { fileURLToPath } from "url";
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ // Assuming __dirname is super-kit/mcp-server/build
11
+ const IS_BUILD = __dirname.endsWith("build");
12
+ const superKitRoot = IS_BUILD ? path.resolve(__dirname, "../../") : path.resolve(__dirname, "../");
13
+ const server = new Server({
14
+ name: "superkit-mcp-server",
15
+ version: "1.0.0",
16
+ }, {
17
+ capabilities: {
18
+ tools: {},
19
+ },
20
+ });
21
+ // Helper function to read directory contents, tracking if they are directories or files
22
+ async function listDirectorySafe(dirPath) {
23
+ try {
24
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
25
+ return entries.map((entry) => (entry.isDirectory() ? `${entry.name}/` : entry.name));
26
+ }
27
+ catch (err) {
28
+ return [];
29
+ }
30
+ }
31
+ // Ensure safe path resolution to prevent traversal
32
+ function getSafePath(basePath, relativePath) {
33
+ // Normalize and resolve
34
+ const resolvedPath = path.resolve(basePath, relativePath);
35
+ // Check if it starts with the basePath
36
+ if (!resolvedPath.startsWith(basePath)) {
37
+ return null; // Path traversal detected
38
+ }
39
+ return resolvedPath;
40
+ }
41
+ const TOOLS = [
42
+ {
43
+ name: "list_superkit_assets",
44
+ description: "Lists all available agents, skills, and workflows in the Super-Kit repository.",
45
+ inputSchema: {
46
+ type: "object",
47
+ properties: {},
48
+ required: [],
49
+ },
50
+ },
51
+ {
52
+ name: "load_superkit_agent",
53
+ description: "Loads the instruction markdown for a specific specialist agent.",
54
+ inputSchema: {
55
+ type: "object",
56
+ properties: {
57
+ agentName: {
58
+ type: "string",
59
+ description: "The name of the agent to load (e.g., 'data-engineer'). Do not include .md.",
60
+ },
61
+ },
62
+ required: ["agentName"],
63
+ },
64
+ },
65
+ {
66
+ name: "load_superkit_skill",
67
+ description: "Loads the skill index (SKILL.md) or specific reference file for a skill.",
68
+ inputSchema: {
69
+ type: "object",
70
+ properties: {
71
+ category: {
72
+ type: "string",
73
+ description: "The category of the skill (e.g., 'tech', 'meta', 'workflows').",
74
+ },
75
+ skillName: {
76
+ type: "string",
77
+ description: "The name of the skill directory (e.g., 'react-best-practices').",
78
+ },
79
+ },
80
+ required: ["category", "skillName"],
81
+ },
82
+ },
83
+ {
84
+ name: "load_superkit_workflow",
85
+ description: "Loads the instructions for a specific workflow.",
86
+ inputSchema: {
87
+ type: "object",
88
+ properties: {
89
+ workflowName: {
90
+ type: "string",
91
+ description: "The name of the workflow (e.g., 'plan', 'explore'). Do not include .md.",
92
+ },
93
+ },
94
+ required: ["workflowName"],
95
+ },
96
+ },
97
+ ];
98
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
99
+ return { tools: TOOLS };
100
+ });
101
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
102
+ try {
103
+ if (request.params.name === "list_superkit_assets") {
104
+ const agentsPath = path.join(superKitRoot, "agents");
105
+ const skillsTechPath = path.join(superKitRoot, "skills", "tech");
106
+ const skillsMetaPath = path.join(superKitRoot, "skills", "meta");
107
+ const workflowsPath = path.join(superKitRoot, "workflows");
108
+ const agents = await listDirectorySafe(agentsPath);
109
+ const techSkills = await listDirectorySafe(skillsTechPath);
110
+ const metaSkills = await listDirectorySafe(skillsMetaPath);
111
+ const workflows = await listDirectorySafe(workflowsPath);
112
+ return {
113
+ content: [
114
+ {
115
+ type: "text",
116
+ text: JSON.stringify({
117
+ agents: agents.map((a) => a.replace(".md", "")),
118
+ skills: {
119
+ tech: techSkills.map((s) => s.replace("/", "")),
120
+ meta: metaSkills.map((s) => s.replace("/", "")),
121
+ },
122
+ workflows: workflows.map((w) => w.replace(".md", "")),
123
+ }, null, 2),
124
+ },
125
+ ],
126
+ };
127
+ }
128
+ if (request.params.name === "load_superkit_agent") {
129
+ const args = request.params.arguments;
130
+ if (!args.agentName)
131
+ throw new Error("Missing agentName");
132
+ const agentFile = `${args.agentName}.md`;
133
+ const baseDir = path.join(superKitRoot, "agents");
134
+ const safePath = getSafePath(baseDir, agentFile);
135
+ if (!safePath)
136
+ throw new Error("Invalid agent path");
137
+ const content = await fs.readFile(safePath, "utf-8");
138
+ return { content: [{ type: "text", text: content }] };
139
+ }
140
+ if (request.params.name === "load_superkit_skill") {
141
+ const args = request.params.arguments;
142
+ if (!args.category || !args.skillName)
143
+ throw new Error("Missing category or skillName");
144
+ const baseDir = path.join(superKitRoot, "skills", args.category, args.skillName);
145
+ const safePath = getSafePath(path.join(superKitRoot, "skills"), path.join(args.category, args.skillName, "SKILL.md"));
146
+ if (!safePath)
147
+ throw new Error("Invalid skill path");
148
+ try {
149
+ const content = await fs.readFile(safePath, "utf-8");
150
+ return { content: [{ type: "text", text: content }] };
151
+ }
152
+ catch (e) {
153
+ // If SKILL.md isn't there, just return the directory context if we can.
154
+ const fallbackSafePath = getSafePath(path.join(superKitRoot, "skills"), path.join(args.category, args.skillName));
155
+ if (fallbackSafePath) {
156
+ const items = await listDirectorySafe(fallbackSafePath);
157
+ return { content: [{ type: "text", text: `SKILL.md not found. Directory contains: ${items.join(', ')}` }] };
158
+ }
159
+ throw e;
160
+ }
161
+ }
162
+ if (request.params.name === "load_superkit_workflow") {
163
+ const args = request.params.arguments;
164
+ if (!args.workflowName)
165
+ throw new Error("Missing workflowName");
166
+ const workflowFile = `${args.workflowName}.md`;
167
+ const baseDir = path.join(superKitRoot, "workflows");
168
+ const safePath = getSafePath(baseDir, workflowFile);
169
+ if (!safePath)
170
+ throw new Error("Invalid workflow path");
171
+ const content = await fs.readFile(safePath, "utf-8");
172
+ return { content: [{ type: "text", text: content }] };
173
+ }
174
+ throw new Error(`Unknown tool: ${request.params.name}`);
175
+ }
176
+ catch (error) {
177
+ return {
178
+ content: [{ type: "text", text: `Error executing tool: ${error.message}` }],
179
+ isError: true,
180
+ };
181
+ }
182
+ });
183
+ async function main() {
184
+ const transport = new StdioServerTransport();
185
+ await server.connect(transport);
186
+ console.error("Super-Kit MCP Server running on stdio");
187
+ }
188
+ main().catch((error) => {
189
+ console.error("Server error:", error);
190
+ process.exit(1);
191
+ });
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "superkit-mcp-server",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "An MCP server for exploring and loading Super-Kit AI agent resources.",
6
+ "main": "build/index.js",
7
+ "bin": {
8
+ "superkit-mcp-server": "./build/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node build/index.js",
13
+ "dev": "tsc --watch"
14
+ },
15
+ "dependencies": {
16
+ "@modelcontextprotocol/sdk": "^1.4.1",
17
+ "zod": "^3.23.8"
18
+ },
19
+ "devDependencies": {
20
+ "@types/node": "^22.10.1",
21
+ "typescript": "^5.7.2"
22
+ }
23
+ }
package/src/index.ts ADDED
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import {
6
+ CallToolRequestSchema,
7
+ ListToolsRequestSchema,
8
+ Tool,
9
+ } from "@modelcontextprotocol/sdk/types.js";
10
+ import * as path from "path";
11
+ import * as fs from "fs/promises";
12
+ import { fileURLToPath } from "url";
13
+ import { z } from "zod";
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = path.dirname(__filename);
17
+ // Assuming __dirname is super-kit/mcp-server/build
18
+ const IS_BUILD = __dirname.endsWith("build");
19
+ const superKitRoot = IS_BUILD ? path.resolve(__dirname, "../../") : path.resolve(__dirname, "../");
20
+
21
+ const server = new Server(
22
+ {
23
+ name: "superkit-mcp-server",
24
+ version: "1.0.0",
25
+ },
26
+ {
27
+ capabilities: {
28
+ tools: {},
29
+ },
30
+ }
31
+ );
32
+
33
+ // Helper function to read directory contents, tracking if they are directories or files
34
+ async function listDirectorySafe(dirPath: string): Promise<string[]> {
35
+ try {
36
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
37
+ return entries.map((entry) => (entry.isDirectory() ? `${entry.name}/` : entry.name));
38
+ } catch (err) {
39
+ return [];
40
+ }
41
+ }
42
+
43
+ // Ensure safe path resolution to prevent traversal
44
+ function getSafePath(basePath: string, relativePath: string): string | null {
45
+ // Normalize and resolve
46
+ const resolvedPath = path.resolve(basePath, relativePath);
47
+ // Check if it starts with the basePath
48
+ if (!resolvedPath.startsWith(basePath)) {
49
+ return null; // Path traversal detected
50
+ }
51
+ return resolvedPath;
52
+ }
53
+
54
+ const TOOLS: Tool[] = [
55
+ {
56
+ name: "list_superkit_assets",
57
+ description: "Lists all available agents, skills, and workflows in the Super-Kit repository.",
58
+ inputSchema: {
59
+ type: "object",
60
+ properties: {},
61
+ required: [],
62
+ },
63
+ },
64
+ {
65
+ name: "load_superkit_agent",
66
+ description: "Loads the instruction markdown for a specific specialist agent.",
67
+ inputSchema: {
68
+ type: "object",
69
+ properties: {
70
+ agentName: {
71
+ type: "string",
72
+ description: "The name of the agent to load (e.g., 'data-engineer'). Do not include .md.",
73
+ },
74
+ },
75
+ required: ["agentName"],
76
+ },
77
+ },
78
+ {
79
+ name: "load_superkit_skill",
80
+ description: "Loads the skill index (SKILL.md) or specific reference file for a skill.",
81
+ inputSchema: {
82
+ type: "object",
83
+ properties: {
84
+ category: {
85
+ type: "string",
86
+ description: "The category of the skill (e.g., 'tech', 'meta', 'workflows').",
87
+ },
88
+ skillName: {
89
+ type: "string",
90
+ description: "The name of the skill directory (e.g., 'react-best-practices').",
91
+ },
92
+ },
93
+ required: ["category", "skillName"],
94
+ },
95
+ },
96
+ {
97
+ name: "load_superkit_workflow",
98
+ description: "Loads the instructions for a specific workflow.",
99
+ inputSchema: {
100
+ type: "object",
101
+ properties: {
102
+ workflowName: {
103
+ type: "string",
104
+ description: "The name of the workflow (e.g., 'plan', 'explore'). Do not include .md.",
105
+ },
106
+ },
107
+ required: ["workflowName"],
108
+ },
109
+ },
110
+ ];
111
+
112
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
113
+ return { tools: TOOLS };
114
+ });
115
+
116
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
117
+ try {
118
+ if (request.params.name === "list_superkit_assets") {
119
+ const agentsPath = path.join(superKitRoot, "agents");
120
+ const skillsTechPath = path.join(superKitRoot, "skills", "tech");
121
+ const skillsMetaPath = path.join(superKitRoot, "skills", "meta");
122
+ const workflowsPath = path.join(superKitRoot, "workflows");
123
+
124
+ const agents = await listDirectorySafe(agentsPath);
125
+ const techSkills = await listDirectorySafe(skillsTechPath);
126
+ const metaSkills = await listDirectorySafe(skillsMetaPath);
127
+ const workflows = await listDirectorySafe(workflowsPath);
128
+
129
+ return {
130
+ content: [
131
+ {
132
+ type: "text",
133
+ text: JSON.stringify(
134
+ {
135
+ agents: agents.map((a) => a.replace(".md", "")),
136
+ skills: {
137
+ tech: techSkills.map((s) => s.replace("/", "")),
138
+ meta: metaSkills.map((s) => s.replace("/", "")),
139
+ },
140
+ workflows: workflows.map((w) => w.replace(".md", "")),
141
+ },
142
+ null,
143
+ 2
144
+ ),
145
+ },
146
+ ],
147
+ };
148
+ }
149
+
150
+ if (request.params.name === "load_superkit_agent") {
151
+ const args = request.params.arguments as { agentName: string };
152
+ if (!args.agentName) throw new Error("Missing agentName");
153
+
154
+ const agentFile = `${args.agentName}.md`;
155
+ const baseDir = path.join(superKitRoot, "agents");
156
+ const safePath = getSafePath(baseDir, agentFile);
157
+
158
+ if (!safePath) throw new Error("Invalid agent path");
159
+
160
+ const content = await fs.readFile(safePath, "utf-8");
161
+ return { content: [{ type: "text", text: content }] };
162
+ }
163
+
164
+ if (request.params.name === "load_superkit_skill") {
165
+ const args = request.params.arguments as { category: string; skillName: string };
166
+ if (!args.category || !args.skillName) throw new Error("Missing category or skillName");
167
+
168
+ const baseDir = path.join(superKitRoot, "skills", args.category, args.skillName);
169
+ const safePath = getSafePath(path.join(superKitRoot, "skills"), path.join(args.category, args.skillName, "SKILL.md"));
170
+
171
+ if (!safePath) throw new Error("Invalid skill path");
172
+
173
+ try {
174
+ const content = await fs.readFile(safePath, "utf-8");
175
+ return { content: [{ type: "text", text: content }] };
176
+ } catch (e) {
177
+ // If SKILL.md isn't there, just return the directory context if we can.
178
+ const fallbackSafePath = getSafePath(path.join(superKitRoot, "skills"), path.join(args.category, args.skillName));
179
+ if (fallbackSafePath) {
180
+ const items = await listDirectorySafe(fallbackSafePath);
181
+ return { content: [{ type: "text", text: `SKILL.md not found. Directory contains: ${items.join(', ')}` }] };
182
+ }
183
+ throw e;
184
+ }
185
+ }
186
+
187
+ if (request.params.name === "load_superkit_workflow") {
188
+ const args = request.params.arguments as { workflowName: string };
189
+ if (!args.workflowName) throw new Error("Missing workflowName");
190
+
191
+ const workflowFile = `${args.workflowName}.md`;
192
+ const baseDir = path.join(superKitRoot, "workflows");
193
+ const safePath = getSafePath(baseDir, workflowFile);
194
+
195
+ if (!safePath) throw new Error("Invalid workflow path");
196
+
197
+ const content = await fs.readFile(safePath, "utf-8");
198
+ return { content: [{ type: "text", text: content }] };
199
+ }
200
+
201
+ throw new Error(`Unknown tool: ${request.params.name}`);
202
+ } catch (error: any) {
203
+ return {
204
+ content: [{ type: "text", text: `Error executing tool: ${error.message}` }],
205
+ isError: true,
206
+ };
207
+ }
208
+ });
209
+
210
+ async function main() {
211
+ const transport = new StdioServerTransport();
212
+ await server.connect(transport);
213
+ console.error("Super-Kit MCP Server running on stdio");
214
+ }
215
+
216
+ main().catch((error) => {
217
+ console.error("Server error:", error);
218
+ process.exit(1);
219
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "./build",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true
12
+ },
13
+ "include": [
14
+ "src/**/*"
15
+ ]
16
+ }