Skip to content

Commit

Permalink
Config tweaks for docker
Browse files Browse the repository at this point in the history
- Remove `$` interpolation for env
- Allow puppeteer to work headless in docker, headful with npx
  • Loading branch information
ColinMcNeil committed Dec 18, 2024
1 parent 9ac1fff commit 2e55e9d
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 61 deletions.
2 changes: 1 addition & 1 deletion src/aws-kb-retrieval-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Add this to your `claude_desktop_config.json`:
"mcpServers": {
"aws-kb-retrieval": {
"command": "docker",
"args": [ "run", "-i", "--rm", "-e", "AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID", "-e", "AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY", "-e", "AWS_REGION=$AWS_REGION", "ai/mcp-aws-kb-retrieval-server" ],
"args": [ "run", "-i", "--rm", "-e", "AWS_ACCESS_KEY_ID", "-e", "AWS_SECRET_ACCESS_KEY", "-e", "AWS_REGION", "ai/mcp-aws-kb-retrieval-server" ],
"env": {
"AWS_ACCESS_KEY_ID": "YOUR_ACCESS_KEY_HERE",
"AWS_SECRET_ACCESS_KEY": "YOUR_SECRET_ACCESS_KEY_HERE",
Expand Down
2 changes: 1 addition & 1 deletion src/brave-search/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Add this to your `claude_desktop_config.json`:
"-i",
"--rm",
"-e",
"BRAVE_API_KEY=$BRAVE_API_KEY",
"BRAVE_API_KEY",
"ai/mcp-brave-search"
],
"env": {
Expand Down
2 changes: 1 addition & 1 deletion src/everart/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Add to Claude Desktop config:
"mcpServers": {
"everart": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "EVERART_API_KEY=$EVERART_API_KEY", "ai/mcp-everart"],
"args": ["run", "-i", "--rm", "-e", "EVERART_API_KEY", "ai/mcp-everart"],
"env": {
"EVERART_API_KEY": "your_key_here"
}
Expand Down
4 changes: 3 additions & 1 deletion src/filesystem/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ ENV NODE_ENV=production

RUN npm ci --ignore-scripts --omit-dev

ENTRYPOINT ["node", "dist/index.js"]
WORKDIR /projects

ENTRYPOINT ["node", "/app/dist/index.js"]
2 changes: 1 addition & 1 deletion src/filesystem/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ Add this to your `claude_desktop_config.json`:
Note: you can provide sandboxed directories to the server by mounting them to `/projects`. Adding the `ro` flag will make the directory readonly by the server.

### Docker
Note: all directories must be mounted to `/projects` by default.

```json
{
Expand All @@ -122,7 +123,6 @@ Note: you can provide sandboxed directories to the server by mounting them to `/
"--mount", "type=bind,src=/Users/username/Desktop,dst=/projects/Desktop",
"--mount", "type=bind,src=/path/to/other/allowed/dir,dst=/projects/other/allowed/dir,ro",
"--mount", "type=bind,src=/path/to/file.txt,dst=/projects/path/to/file.txt",
"--env", "DOCKER_ROOT_WORKSPACE=/projects",
"ai/mcp-filesystem"
]
}
Expand Down
101 changes: 55 additions & 46 deletions src/filesystem/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,15 @@ const args = process.argv.slice(2);

let allowedDirectories: string[] = [];

if (process.env.DOCKER_ROOT_WORKSPACE) {
allowedDirectories = await fs.readdir(process.env.DOCKER_ROOT_WORKSPACE);
let hasProjectsDirectory = false;

// If the projects directory has contents, use it as the root workspace
const projectsContents = await fs.readdir('/projects');
if (projectsContents.length > 0) {
hasProjectsDirectory = true;
allowedDirectories = projectsContents.map(dir =>
normalizePath(path.resolve(expandHome(dir)))
);
}
else {
if (args.length === 0) {
Expand Down Expand Up @@ -51,7 +58,7 @@ function expandHome(filepath: string): string {
await Promise.all(allowedDirectories.map(async (dir) => {
try {
const stats = await fs.stat(dir);
if (!stats.isDirectory()) {
if (!stats.isDirectory() && !hasProjectsDirectory) {
console.error(`Error: ${dir} is not a directory`);
process.exit(1);
}
Expand Down Expand Up @@ -262,7 +269,7 @@ function createUnifiedDiff(originalContent: string, newContent: string, filepath

async function applyFileEdits(
filePath: string,
edits: Array<{oldText: string, newText: string}>,
edits: Array<{ oldText: string, newText: string }>,
dryRun = false
): Promise<string> {
// Read file content and normalize line endings
Expand Down Expand Up @@ -398,10 +405,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
{
name: "directory_tree",
description:
"Get a recursive tree view of files and directories as a JSON structure. " +
"Each entry includes 'name', 'type' (file/directory), and 'children' for directories. " +
"Files have no children array, while directories always have a children array (which may be empty). " +
"The output is formatted with 2-space indentation for readability. Only works within allowed directories.",
"Get a recursive tree view of files and directories as a JSON structure. " +
"Each entry includes 'name', 'type' (file/directory), and 'children' for directories. " +
"Files have no children array, while directories always have a children array (which may be empty). " +
"The output is formatted with 2-space indentation for readability. Only works within allowed directories.",
inputSchema: zodToJsonSchema(DirectoryTreeArgsSchema) as ToolInput,
},
{
Expand Down Expand Up @@ -538,49 +545,49 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
};
}

case "directory_tree": {
const parsed = DirectoryTreeArgsSchema.safeParse(args);
if (!parsed.success) {
throw new Error(`Invalid arguments for directory_tree: ${parsed.error}`);
}

interface TreeEntry {
name: string;
type: 'file' | 'directory';
children?: TreeEntry[];
}

async function buildTree(currentPath: string): Promise<TreeEntry[]> {
const validPath = await validatePath(currentPath);
const entries = await fs.readdir(validPath, {withFileTypes: true});
const result: TreeEntry[] = [];
case "directory_tree": {
const parsed = DirectoryTreeArgsSchema.safeParse(args);
if (!parsed.success) {
throw new Error(`Invalid arguments for directory_tree: ${parsed.error}`);
}

for (const entry of entries) {
const entryData: TreeEntry = {
name: entry.name,
type: entry.isDirectory() ? 'directory' : 'file'
};
interface TreeEntry {
name: string;
type: 'file' | 'directory';
children?: TreeEntry[];
}

if (entry.isDirectory()) {
const subPath = path.join(currentPath, entry.name);
entryData.children = await buildTree(subPath);
}
async function buildTree(currentPath: string): Promise<TreeEntry[]> {
const validPath = await validatePath(currentPath);
const entries = await fs.readdir(validPath, { withFileTypes: true });
const result: TreeEntry[] = [];

result.push(entryData);
}
for (const entry of entries) {
const entryData: TreeEntry = {
name: entry.name,
type: entry.isDirectory() ? 'directory' : 'file'
};

return result;
if (entry.isDirectory()) {
const subPath = path.join(currentPath, entry.name);
entryData.children = await buildTree(subPath);
}

const treeData = await buildTree(parsed.data.path);
return {
content: [{
type: "text",
text: JSON.stringify(treeData, null, 2)
}],
};
result.push(entryData);
}

return result;
}

const treeData = await buildTree(parsed.data.path);
return {
content: [{
type: "text",
text: JSON.stringify(treeData, null, 2)
}],
};
}

case "move_file": {
const parsed = MoveFileArgsSchema.safeParse(args);
if (!parsed.success) {
Expand Down Expand Up @@ -614,9 +621,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
const validPath = await validatePath(parsed.data.path);
const info = await getFileStats(validPath);
return {
content: [{ type: "text", text: Object.entries(info)
.map(([key, value]) => `${key}: ${value}`)
.join("\n") }],
content: [{
type: "text", text: Object.entries(info)
.map(([key, value]) => `${key}: ${value}`)
.join("\n")
}],
};
}

Expand Down
2 changes: 1 addition & 1 deletion src/github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ To use this with Claude Desktop, add the following to your `claude_desktop_confi
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN=$GITHUB_PERSONAL_ACCESS_TOKEN",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ai/mcp-github"
],
"env": {
Expand Down
4 changes: 2 additions & 2 deletions src/gitlab/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ Add the following to your `claude_desktop_config.json`:
"args": [
"run",
"-e",
"GITLAB_PERSONAL_ACCESS_TOKEN=$GITLAB_PERSONAL_ACCESS_TOKEN",
"GITLAB_PERSONAL_ACCESS_TOKEN",
"-e",
"GITLAB_API_URL=$GITLAB_API_URL",
"GITLAB_API_URL",
"ai/mcp-gitlab"
],
"env": {
Expand Down
2 changes: 1 addition & 1 deletion src/google-maps/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Add the following to your `claude_desktop_config.json`:
"-i",
"--rm",
"-e",
"GOOGLE_MAPS_API_KEY=$GOOGLE_MAPS_API_KEY",
"GOOGLE_MAPS_API_KEY",
"ai/mcp-google-maps"
],
"env": {
Expand Down
2 changes: 1 addition & 1 deletion src/puppeteer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Here's the Claude Desktop configuration to use the Puppeter server:
"mcpServers": {
"puppeteer": {
"command": "docker",
"args": ["run", "-i", "--rm", "--init", "ai/mcp-puppeteer"]
"args": ["run", "-i", "--rm", "--init", "-e", "DOCKER_CONTAINER=true", "ai/mcp-puppeteer"]
}
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/puppeteer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ const screenshots = new Map<string, string>();

async function ensureBrowser() {
if (!browser) {
browser = await puppeteer.launch({ headless: true, args: ["--no-sandbox"] });
const npx_args = { headless: false }
const docker_args = { headless: true, args: ["--no-sandbox", "--single-process", "--no-zygote"] }
browser = await puppeteer.launch(process.env.DOCKER_CONTAINER ? docker_args : npx_args);
const pages = await browser.pages();
page = pages[0];

Expand Down Expand Up @@ -283,8 +285,8 @@ async function handleToolCall(name: string, args: any): Promise<CallToolResult>
window.mcpHelper.logs.push(`[${method}] ${args.join(' ')}`);
(window.mcpHelper.originalConsole as any)[method](...args);
};
} );
} );
});
});

const result = await page.evaluate( args.script );

Expand Down
4 changes: 2 additions & 2 deletions src/slack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ Add the following to your `claude_desktop_config.json`:
"-i",
"--rm",
"-e",
"SLACK_BOT_TOKEN=$SLACK_BOT_TOKEN",
"SLACK_BOT_TOKEN",
"-e",
"SLACK_TEAM_ID=$SLACK_TEAM_ID",
"SLACK_TEAM_ID",
"ai/mcp-slack"
],
"env": {
Expand Down

0 comments on commit 2e55e9d

Please sign in to comment.