Config tweaks for docker

- Remove `$` interpolation for env
- Allow puppeteer to work headless in docker, headful with npx
This commit is contained in:
colinmcneil 2024-12-18 11:00:11 -05:00 • committed by Jim Clark
commit c64f8de15f
No known key found for this signature in database
GPG key ID: 73305B2338AAA7BE
12 changed files with 72 additions and 59 deletions

View file

@ -34,7 +34,7 @@ Add this to your `claude_desktop_config.json`:
"mcpServers": { "mcpServers": {
"aws-kb-retrieval": { "aws-kb-retrieval": {
"command": "docker", "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": { "env": {
"AWS_ACCESS_KEY_ID": "YOUR_ACCESS_KEY_HERE", "AWS_ACCESS_KEY_ID": "YOUR_ACCESS_KEY_HERE",
"AWS_SECRET_ACCESS_KEY": "YOUR_SECRET_ACCESS_KEY_HERE", "AWS_SECRET_ACCESS_KEY": "YOUR_SECRET_ACCESS_KEY_HERE",

View file

@ -48,7 +48,7 @@ Add this to your `claude_desktop_config.json`:
"-i", "-i",
"--rm", "--rm",
"-e", "-e",
"BRAVE_API_KEY=$BRAVE_API_KEY", "BRAVE_API_KEY",
"ai/mcp-brave-search" "ai/mcp-brave-search"
], ],
"env": { "env": {

View file

@ -17,7 +17,7 @@ Add to Claude Desktop config:
"mcpServers": { "mcpServers": {
"everart": { "everart": {
"command": "docker", "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": { "env": {
"EVERART_API_KEY": "your_key_here" "EVERART_API_KEY": "your_key_here"
} }

View file

@ -22,4 +22,6 @@ ENV NODE_ENV=production
RUN npm ci --ignore-scripts --omit-dev RUN npm ci --ignore-scripts --omit-dev
ENTRYPOINT ["node", "dist/index.js"] WORKDIR /projects
ENTRYPOINT ["node", "/app/dist/index.js"]

View file

@ -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. 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 ### Docker
Note: all directories must be mounted to `/projects` by default.
```json ```json
{ {
@ -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=/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/other/allowed/dir,dst=/projects/other/allowed/dir,ro",
"--mount", "type=bind,src=/path/to/file.txt,dst=/projects/path/to/file.txt", "--mount", "type=bind,src=/path/to/file.txt,dst=/projects/path/to/file.txt",
"--env", "DOCKER_ROOT_WORKSPACE=/projects",
"ai/mcp-filesystem" "ai/mcp-filesystem"
] ]
} }

View file

@ -20,8 +20,15 @@ const args = process.argv.slice(2);
let allowedDirectories: string[] = []; let allowedDirectories: string[] = [];
if (process.env.DOCKER_ROOT_WORKSPACE) { let hasProjectsDirectory = false;
allowedDirectories = await fs.readdir(process.env.DOCKER_ROOT_WORKSPACE);
// 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 { else {
if (args.length === 0) { if (args.length === 0) {
@ -51,7 +58,7 @@ function expandHome(filepath: string): string {
await Promise.all(allowedDirectories.map(async (dir) => { await Promise.all(allowedDirectories.map(async (dir) => {
try { try {
const stats = await fs.stat(dir); const stats = await fs.stat(dir);
if (!stats.isDirectory()) { if (!stats.isDirectory() && !hasProjectsDirectory) {
console.error(`Error: ${dir} is not a directory`); console.error(`Error: ${dir} is not a directory`);
process.exit(1); process.exit(1);
} }
@ -614,9 +621,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
const validPath = await validatePath(parsed.data.path); const validPath = await validatePath(parsed.data.path);
const info = await getFileStats(validPath); const info = await getFileStats(validPath);
return { return {
content: [{ type: "text", text: Object.entries(info) content: [{
type: "text", text: Object.entries(info)
.map(([key, value]) => `${key}: ${value}`) .map(([key, value]) => `${key}: ${value}`)
.join("\n") }], .join("\n")
}],
}; };
} }

View file

@ -236,7 +236,7 @@ To use this with Claude Desktop, add the following to your `claude_desktop_confi
"-i", "-i",
"--rm", "--rm",
"-e", "-e",
"GITHUB_PERSONAL_ACCESS_TOKEN=$GITHUB_PERSONAL_ACCESS_TOKEN", "GITHUB_PERSONAL_ACCESS_TOKEN",
"ai/mcp-github" "ai/mcp-github"
], ],
"env": { "env": {

View file

@ -118,9 +118,9 @@ Add the following to your `claude_desktop_config.json`:
"args": [ "args": [
"run", "run",
"-e", "-e",
"GITLAB_PERSONAL_ACCESS_TOKEN=$GITLAB_PERSONAL_ACCESS_TOKEN", "GITLAB_PERSONAL_ACCESS_TOKEN",
"-e", "-e",
"GITLAB_API_URL=$GITLAB_API_URL", "GITLAB_API_URL",
"ai/mcp-gitlab" "ai/mcp-gitlab"
], ],
"env": { "env": {

View file

@ -71,7 +71,7 @@ Add the following to your `claude_desktop_config.json`:
"-i", "-i",
"--rm", "--rm",
"-e", "-e",
"GOOGLE_MAPS_API_KEY=$GOOGLE_MAPS_API_KEY", "GOOGLE_MAPS_API_KEY",
"ai/mcp-google-maps" "ai/mcp-google-maps"
], ],
"env": { "env": {

View file

@ -72,7 +72,7 @@ Here's the Claude Desktop configuration to use the Puppeter server:
"mcpServers": { "mcpServers": {
"puppeteer": { "puppeteer": {
"command": "docker", "command": "docker",
"args": ["run", "-i", "--rm", "--init", "ai/mcp-puppeteer"] "args": ["run", "-i", "--rm", "--init", "-e", "DOCKER_CONTAINER=true", "ai/mcp-puppeteer"]
} }
} }
} }

View file

@ -108,7 +108,9 @@ const screenshots = new Map<string, string>();
async function ensureBrowser() { async function ensureBrowser() {
if (!browser) { 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(); const pages = await browser.pages();
page = pages[0]; page = pages[0];

View file

@ -121,9 +121,9 @@ Add the following to your `claude_desktop_config.json`:
"-i", "-i",
"--rm", "--rm",
"-e", "-e",
"SLACK_BOT_TOKEN=$SLACK_BOT_TOKEN", "SLACK_BOT_TOKEN",
"-e", "-e",
"SLACK_TEAM_ID=$SLACK_TEAM_ID", "SLACK_TEAM_ID",
"ai/mcp-slack" "ai/mcp-slack"
], ],
"env": { "env": {