Skip to content

Commit 0c94b37

Browse files
committed
chore: mcps list update
1 parent aad86ee commit 0c94b37

2 files changed

Lines changed: 80 additions & 3 deletions

File tree

src/everything/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ This MCP server attempts to exercise all the features of the MCP protocol. It is
8989
- `structuredContent` field conformant to the output schema
9090
- A backward compatible Text Content field, a SHOULD advisory in the specification
9191

92+
11. `writeFile`
93+
- Writes text content to a file on disk within a safe base directory
94+
- Base directory: `MCP_WRITE_BASE_DIR` env var if set, otherwise the server's current working directory
95+
- Inputs:
96+
- `path` (string): Relative path under the base directory
97+
- `content` (string, default ""): Text to write
98+
- `append` (boolean, default false): Append instead of overwrite
99+
- `ensureDir` (boolean, default true): Create parent directories as needed
100+
- Safety: rejects paths that escape the base directory
101+
92102
### Resources
93103

94104
The server provides 100 test resources in two formats:

src/everything/everything.ts

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ import {
2020
} from "@modelcontextprotocol/sdk/types.js";
2121
import { z } from "zod";
2222
import { zodToJsonSchema } from "zod-to-json-schema";
23-
import { readFileSync } from "fs";
23+
import { readFileSync, writeFileSync, appendFileSync, mkdirSync } from "fs";
2424
import { fileURLToPath } from "url";
25-
import { dirname, join } from "path";
25+
import { dirname, join, resolve, relative, isAbsolute } from "path";
2626

2727
const __filename = fileURLToPath(import.meta.url);
2828
const __dirname = dirname(__filename);
@@ -118,6 +118,21 @@ const StructuredContentSchema = {
118118
})
119119
};
120120

121+
const WriteFileSchema = z.object({
122+
path: z
123+
.string()
124+
.min(1)
125+
.describe(
126+
"Relative file path to write under the base directory (defaults to process.cwd or MCP_WRITE_BASE_DIR)"
127+
),
128+
content: z.string().default("").describe("Text content to write"),
129+
append: z.boolean().default(false).describe("Append to file if true"),
130+
ensureDir: z
131+
.boolean()
132+
.default(true)
133+
.describe("Create parent directories if they do not exist"),
134+
});
135+
121136
enum ToolName {
122137
ECHO = "echo",
123138
ADD = "add",
@@ -129,7 +144,9 @@ enum ToolName {
129144
GET_RESOURCE_REFERENCE = "getResourceReference",
130145
ELICITATION = "startElicitation",
131146
GET_RESOURCE_LINKS = "getResourceLinks",
132-
STRUCTURED_CONTENT = "structuredContent"
147+
STRUCTURED_CONTENT = "structuredContent",
148+
WRITE_FILE = "writeFile",
149+
WRITE_FILE_SNAKE = "write_file",
133150
}
134151

135152
enum PromptName {
@@ -524,6 +541,18 @@ export const createServer = () => {
524541
inputSchema: zodToJsonSchema(StructuredContentSchema.input) as ToolInput,
525542
outputSchema: zodToJsonSchema(StructuredContentSchema.output) as ToolOutput,
526543
},
544+
{
545+
name: ToolName.WRITE_FILE,
546+
description:
547+
"Writes text content to a file under a safe base directory (defaults to process.cwd or MCP_WRITE_BASE_DIR)",
548+
inputSchema: zodToJsonSchema(WriteFileSchema) as ToolInput,
549+
},
550+
{
551+
name: ToolName.WRITE_FILE_SNAKE,
552+
description:
553+
"Alias of writeFile. Writes text content to a file under a safe base directory (defaults to process.cwd or MCP_WRITE_BASE_DIR)",
554+
inputSchema: zodToJsonSchema(WriteFileSchema) as ToolInput,
555+
},
527556
];
528557

529558
return { tools };
@@ -819,6 +848,44 @@ export const createServer = () => {
819848
};
820849
}
821850

851+
if (name === ToolName.WRITE_FILE || name === ToolName.WRITE_FILE_SNAKE) {
852+
const argsValidated = WriteFileSchema.parse(args);
853+
const baseDirEnv = process.env.MCP_WRITE_BASE_DIR;
854+
const resolvedBaseDir = resolve(baseDirEnv ? baseDirEnv : process.cwd());
855+
const resolvedTargetPath = resolve(resolvedBaseDir, argsValidated.path);
856+
const rel = relative(resolvedBaseDir, resolvedTargetPath);
857+
858+
// Prevent path traversal outside base directory
859+
if (rel.startsWith("..") || isAbsolute(rel)) {
860+
throw new Error(
861+
`Invalid path: ${argsValidated.path}. Path must stay within base directory: ${resolvedBaseDir}`
862+
);
863+
}
864+
865+
if (argsValidated.ensureDir) {
866+
mkdirSync(dirname(resolvedTargetPath), { recursive: true });
867+
}
868+
869+
if (argsValidated.append) {
870+
appendFileSync(resolvedTargetPath, argsValidated.content, {
871+
encoding: "utf-8",
872+
});
873+
} else {
874+
writeFileSync(resolvedTargetPath, argsValidated.content, {
875+
encoding: "utf-8",
876+
});
877+
}
878+
879+
return {
880+
content: [
881+
{
882+
type: "text",
883+
text: `Wrote ${argsValidated.append ? "(appended) " : ""}${argsValidated.content.length} bytes to ${resolvedTargetPath}`,
884+
},
885+
],
886+
};
887+
}
888+
822889
throw new Error(`Unknown tool: ${name}`);
823890
});
824891

0 commit comments

Comments
 (0)