From 368e3b23ca08c629a500c63e9bbe1233012a1f9a Mon Sep 17 00:00:00 2001 From: Jim Clark Date: Tue, 10 Dec 2024 11:56:46 -0800 Subject: [PATCH 01/21] Add Dockerfiles for the 17 sample MCP servers * add Dockerfiles and update README.md definitions --- package-lock.json | 22 +++++------ src/aws-kb-retrieval-server/Dockerfile | 18 +++++++++ src/aws-kb-retrieval-server/README.md | 26 ++++++++++++ src/aws-kb-retrieval-server/package.json | 4 +- src/brave-search/Dockerfile | 19 +++++++++ src/brave-search/README.md | 34 ++++++++++++++++ src/brave-search/package.json | 2 +- src/everart/Dockerfile | 18 +++++++++ src/everart/README.md | 25 ++++++++++++ src/everart/package.json | 2 +- src/everything/Dockerfile | 18 +++++++++ src/fetch/Dockerfile | 29 ++++++++++++++ src/filesystem/Dockerfile | 18 +++++++++ src/filesystem/README.md | 36 ++++++++++++++++- src/filesystem/package.json | 4 +- src/gdrive/Dockerfile | 18 +++++++++ src/gdrive/README.md | 15 +++++++ src/gdrive/package.json | 2 +- src/git/Dockerfile | 31 +++++++++++++++ src/git/README.md | 50 ++++++++++++++++++++---- src/github/Dockerfile | 19 +++++++++ src/github/README.md | 38 ++++++++++++++++-- src/github/package.json | 2 +- src/gitlab/Dockerfile | 18 +++++++++ src/gitlab/README.md | 50 +++++++++++++++++++++--- src/google-maps/Dockerfile | 19 +++++++++ src/google-maps/README.md | 33 ++++++++++++++++ src/memory/Dockerfile | 18 +++++++++ src/memory/README.md | 26 +++++++++++- src/memory/package.json | 2 +- src/postgres/Dockerfile | 18 +++++++++ src/postgres/README.md | 25 +++++++++++- src/puppeteer/Dockerfile | 27 +++++++++++++ src/puppeteer/README.md | 23 +++++++++++ src/puppeteer/index.ts | 2 +- src/sentry/Dockerfile | 29 ++++++++++++++ src/sequentialthinking/Dockerfile | 18 +++++++++ src/sequentialthinking/README.md | 28 +++++++++++++ src/sequentialthinking/package.json | 2 +- src/slack/Dockerfile | 19 +++++++++ src/slack/README.md | 36 +++++++++++++++++ src/slack/package.json | 2 +- src/sqlite/Dockerfile | 29 ++++++++++++++ src/sqlite/README.md | 31 +++++++++++++++ src/time/Dockerfile | 29 ++++++++++++++ src/time/README.md | 22 +++++++++++ 46 files changed, 913 insertions(+), 43 deletions(-) create mode 100644 src/aws-kb-retrieval-server/Dockerfile create mode 100644 src/brave-search/Dockerfile create mode 100644 src/everart/Dockerfile create mode 100644 src/everything/Dockerfile create mode 100644 src/fetch/Dockerfile create mode 100644 src/filesystem/Dockerfile create mode 100644 src/gdrive/Dockerfile create mode 100644 src/git/Dockerfile create mode 100644 src/github/Dockerfile create mode 100644 src/gitlab/Dockerfile create mode 100644 src/google-maps/Dockerfile create mode 100644 src/memory/Dockerfile create mode 100644 src/postgres/Dockerfile create mode 100644 src/puppeteer/Dockerfile create mode 100644 src/sentry/Dockerfile create mode 100644 src/sequentialthinking/Dockerfile create mode 100644 src/slack/Dockerfile create mode 100644 src/sqlite/Dockerfile create mode 100644 src/time/Dockerfile diff --git a/package-lock.json b/package-lock.json index 34253af3f5..140b5ca338 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5015,7 +5015,7 @@ "mcp-server-aws-kb-retrieval": "dist/index.js" }, "devDependencies": { - "@types/node": "^20.10.0", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } @@ -5040,7 +5040,7 @@ "mcp-server-brave-search": "dist/index.js" }, "devDependencies": { - "@types/node": "^20.10.0", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } @@ -5080,7 +5080,7 @@ }, "devDependencies": { "@types/jsdom": "^21.1.6", - "@types/node": "^20.10.0", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } @@ -5099,7 +5099,7 @@ "mcp-server-everart": "dist/index.js" }, "devDependencies": { - "@types/node": "^20.11.0", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.3.3" } @@ -5201,7 +5201,7 @@ "devDependencies": { "@types/diff": "^5.0.9", "@types/minimatch": "^5.1.2", - "@types/node": "^20.11.0", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.3.3" } @@ -5298,7 +5298,7 @@ "mcp-server-gdrive": "dist/index.js" }, "devDependencies": { - "@types/node": "^22.9.3", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } @@ -5328,7 +5328,7 @@ "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "1.0.1", - "@types/node": "^20.11.0", + "@types/node": "^22", "@types/node-fetch": "^2.6.12", "node-fetch": "^3.3.2", "zod": "^3.22.4", @@ -5501,7 +5501,7 @@ "mcp-server-memory": "dist/index.js" }, "devDependencies": { - "@types/node": "^22.9.3", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } @@ -5591,7 +5591,7 @@ "mcp-server-sequential-thinking": "dist/index.js" }, "devDependencies": { - "@types/node": "^20.11.0", + "@types/node": "^22", "@types/yargs": "^17.0.32", "shx": "^0.3.4", "typescript": "^5.3.3" @@ -5617,7 +5617,7 @@ "mcp-server-slack": "dist/index.js" }, "devDependencies": { - "@types/node": "^22.9.3", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } @@ -5642,4 +5642,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/aws-kb-retrieval-server/Dockerfile b/src/aws-kb-retrieval-server/Dockerfile new file mode 100644 index 0000000000..88f3906d1c --- /dev/null +++ b/src/aws-kb-retrieval-server/Dockerfile @@ -0,0 +1,18 @@ +FROM node:22.12-alpine as builder + +COPY src/aws-kb-retrieval-server /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/aws-kb-retrieval-server/README.md b/src/aws-kb-retrieval-server/README.md index ac2bdb435c..ed19f1ee21 100644 --- a/src/aws-kb-retrieval-server/README.md +++ b/src/aws-kb-retrieval-server/README.md @@ -27,6 +27,24 @@ An MCP server implementation for retrieving information from the AWS Knowledge B Add this to your `claude_desktop_config.json`: +#### Docker + +```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" ], + "env": { + "AWS_ACCESS_KEY_ID": "YOUR_ACCESS_KEY_HERE", + "AWS_SECRET_ACCESS_KEY": "YOUR_SECRET_ACCESS_KEY_HERE", + "AWS_REGION": "YOUR_AWS_REGION_HERE" + } + } + } +} +``` + ```json { "mcpServers": { @@ -46,6 +64,14 @@ Add this to your `claude_desktop_config.json`: } ``` +## Building + +Docker: + +```sh +docker build -t ai/mcp-aws-kb-retrieval -f src/aws-kb-retrieval-server/Dockerfile . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/aws-kb-retrieval-server/package.json b/src/aws-kb-retrieval-server/package.json index fdad1a69fc..072fee1196 100644 --- a/src/aws-kb-retrieval-server/package.json +++ b/src/aws-kb-retrieval-server/package.json @@ -23,8 +23,8 @@ "@aws-sdk/client-bedrock-agent-runtime": "^3.0.0" }, "devDependencies": { - "@types/node": "^20.10.0", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } -} +} \ No newline at end of file diff --git a/src/brave-search/Dockerfile b/src/brave-search/Dockerfile new file mode 100644 index 0000000000..ed12955179 --- /dev/null +++ b/src/brave-search/Dockerfile @@ -0,0 +1,19 @@ +FROM node:22.12-alpine as builder + +# Must be entire project because `prepare` script is run during `npm install` and requires all files. +COPY src/brave-search /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/brave-search/README.md b/src/brave-search/README.md index 2d5ae0df92..d94ecdf111 100644 --- a/src/brave-search/README.md +++ b/src/brave-search/README.md @@ -36,6 +36,31 @@ An MCP server implementation that integrates the Brave Search API, providing bot ### Usage with Claude Desktop Add this to your `claude_desktop_config.json`: +### Docker + +```json +{ + "mcpServers": { + "brave-search": { + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "-e", + "BRAVE_API_KEY=$BRAVE_API_KEY", + "ai/mcp-brave-search" + ], + "env": { + "BRAVE_API_KEY": "YOUR_API_KEY_HERE" + } + } + } +} +``` + +### NPX + ```json { "mcpServers": { @@ -53,6 +78,15 @@ Add this to your `claude_desktop_config.json`: } ``` + +## Build + +Docker build: + +```bash +docker build -t vonwig/brave-search:mcp -f src/brave-search/Dockerfile . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/brave-search/package.json b/src/brave-search/package.json index 70ce9d00bc..163e5afc90 100644 --- a/src/brave-search/package.json +++ b/src/brave-search/package.json @@ -22,7 +22,7 @@ "@modelcontextprotocol/sdk": "1.0.1" }, "devDependencies": { - "@types/node": "^20.10.0", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } diff --git a/src/everart/Dockerfile b/src/everart/Dockerfile new file mode 100644 index 0000000000..385c08dd64 --- /dev/null +++ b/src/everart/Dockerfile @@ -0,0 +1,18 @@ +FROM node:22.12-alpine as builder + +COPY src/everart /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/everart/README.md b/src/everart/README.md index 545f5dfa1b..04b0757895 100644 --- a/src/everart/README.md +++ b/src/everart/README.md @@ -10,6 +10,25 @@ export EVERART_API_KEY=your_key_here ## Config Add to Claude Desktop config: + +### Docker +```json +{ + "mcpServers": { + "everart": { + "command": "docker", + "args": ["run", "-i", "--rm", "-e", "EVERART_API_KEY=$EVERART_API_KEY", "ai/mcp-everart"], + "env": { + "EVERART_API_KEY": "your_key_here" + } + }, + + } +} +``` + +### NPX + ```json { "mcpServers": { @@ -71,3 +90,9 @@ Generation details: You can also click the URL above to view the image again. ``` + +## Building w/ Docker + +```sh +docker build -t ai/mcp-everart -f src/everart/Dockerfile . +``` diff --git a/src/everart/package.json b/src/everart/package.json index 189ca650ce..653c654b5c 100644 --- a/src/everart/package.json +++ b/src/everart/package.json @@ -25,7 +25,7 @@ "open": "^9.1.0" }, "devDependencies": { - "@types/node": "^20.11.0", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.3.3" } diff --git a/src/everything/Dockerfile b/src/everything/Dockerfile new file mode 100644 index 0000000000..7a6482c41b --- /dev/null +++ b/src/everything/Dockerfile @@ -0,0 +1,18 @@ +FROM node:22.12-alpine as builder + +COPY src/everything /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/fetch/Dockerfile b/src/fetch/Dockerfile new file mode 100644 index 0000000000..fae262d1bd --- /dev/null +++ b/src/fetch/Dockerfile @@ -0,0 +1,29 @@ +# Use a Python image with uv pre-installed +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim + +# Install the project into `/app` +WORKDIR /app + +# Enable bytecode compilation +ENV UV_COMPILE_BYTECODE=1 + +# Copy from the cache instead of linking since it's a mounted volume +ENV UV_LINK_MODE=copy + +# Install the project's dependencies using the lockfile and settings +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --frozen --no-install-project --no-dev + +# Then, add the rest of the project source code and install it +# Installing separately from its dependencies allows optimal layer caching +ADD . /app +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev + +# Place executables in the environment at the front of the path +ENV PATH="/app/.venv/bin:$PATH" + +# when running the container, add --db-path and a bind mount to the host's db file +ENTRYPOINT ["uvx" , "mcp-server-fetch"] diff --git a/src/filesystem/Dockerfile b/src/filesystem/Dockerfile new file mode 100644 index 0000000000..2addb6dbcf --- /dev/null +++ b/src/filesystem/Dockerfile @@ -0,0 +1,18 @@ +FROM node:22.12-alpine as builder + +WORKDIR /app + +COPY src/filesystem /app +COPY tsconfig.json /tsconfig.json + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/filesystem/README.md b/src/filesystem/README.md index 79c2b0f390..b9286511e3 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -105,6 +105,32 @@ Node.js server implementing Model Context Protocol (MCP) for filesystem operatio ## Usage with Claude Desktop 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 + +```json +{ + "mcpServers": { + "filesystem": { + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "--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", + "ai/mcp-filesystem" + ] + } + } +} +``` + +### NPX + ```json { "mcpServers": { @@ -121,6 +147,14 @@ Add this to your `claude_desktop_config.json`: } ``` +## Build + +Docker build: + +```bash +docker build -t ai/mcp-filesystem -f src/filesystem/Dockerfile . +``` + ## License -This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. \ No newline at end of file +This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/filesystem/package.json b/src/filesystem/package.json index 6f0b223da1..6aca648fa4 100644 --- a/src/filesystem/package.json +++ b/src/filesystem/package.json @@ -28,8 +28,8 @@ "devDependencies": { "@types/diff": "^5.0.9", "@types/minimatch": "^5.1.2", - "@types/node": "^20.11.0", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.3.3" } -} +} \ No newline at end of file diff --git a/src/gdrive/Dockerfile b/src/gdrive/Dockerfile new file mode 100644 index 0000000000..43840db728 --- /dev/null +++ b/src/gdrive/Dockerfile @@ -0,0 +1,18 @@ +FROM node:22.12-alpine as builder + +COPY src/gdrive /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/gdrive/README.md b/src/gdrive/README.md index 9a795f0caa..016b592ddb 100644 --- a/src/gdrive/README.md +++ b/src/gdrive/README.md @@ -49,6 +49,21 @@ To authenticate and save credentials: To integrate this server with the desktop app, add the following to your app's server configuration: +#### Docker + +```json +{ + "mcpServers": { + "gdrive": { + "command": "docker", + "args": ["run", "-i", "--rm", "ai/mcp-gdrive"] + } + } +} +``` + +#### NPX + ```json { "mcpServers": { diff --git a/src/gdrive/package.json b/src/gdrive/package.json index 26e2bfe582..a2d4be3773 100644 --- a/src/gdrive/package.json +++ b/src/gdrive/package.json @@ -24,7 +24,7 @@ "googleapis": "^144.0.0" }, "devDependencies": { - "@types/node": "^22.9.3", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } diff --git a/src/git/Dockerfile b/src/git/Dockerfile new file mode 100644 index 0000000000..264962edde --- /dev/null +++ b/src/git/Dockerfile @@ -0,0 +1,31 @@ +# Use a Python image with uv pre-installed +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim + +# Install the project into `/app` +WORKDIR /app + +# Enable bytecode compilation +ENV UV_COMPILE_BYTECODE=1 + +# Copy from the cache instead of linking since it's a mounted volume +ENV UV_LINK_MODE=copy + +RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* + +# Install the project's dependencies using the lockfile and settings +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --frozen --no-install-project --no-dev + +# Then, add the rest of the project source code and install it +# Installing separately from its dependencies allows optimal layer caching +ADD . /app +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev + +# Place executables in the environment at the front of the path +ENV PATH="/app/.venv/bin:$PATH" + +# when running the container, add --db-path and a bind mount to the host's db file +ENTRYPOINT ["uv" , "run" , "--directory", ".", "mcp-server-git"] diff --git a/src/git/README.md b/src/git/README.md index 8f3afdc741..d62ddd614e 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -193,18 +193,52 @@ If you are doing local development, there are two ways to test your changes: 2. Test using the Claude desktop app. Add the following to your `claude_desktop_config.json`: +### Docker + +```json +{ + "mcpServers": { + "brave-search": { + "command": "docker", + "args": [ + "run", + "--rm", + "-i", + "--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", + "ai/mcp-git" + ] + } + } +} +``` + +### UVX ```json -"git": { - "command": "uv", - "args": [ - "--directory", - "//mcp-servers/src/git", - "run", - "mcp-server-git" - ] +{ +"mcpServers": { + "git": { + "command": "uv", + "args": [ + "--directory", + "//mcp-servers/src/git", + "run", + "mcp-server-git" + ] + } } ``` +## Build + +Docker build: + +```bash +cd src/git +docker build -t ai/mcp-git . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/github/Dockerfile b/src/github/Dockerfile new file mode 100644 index 0000000000..a94abcccf7 --- /dev/null +++ b/src/github/Dockerfile @@ -0,0 +1,19 @@ +FROM node:22.12-alpine as builder + +# Must be entire project because `prepare` script is run during `npm install` and requires all files. +COPY src/github /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/github/README.md b/src/github/README.md index 1898f9e170..d20ba9cc6e 100644 --- a/src/github/README.md +++ b/src/github/README.md @@ -225,14 +225,19 @@ For detailed search syntax, see [GitHub's searching documentation](https://docs. ### Usage with Claude Desktop To use this with Claude Desktop, add the following to your `claude_desktop_config.json`: +#### Docker ```json { "mcpServers": { "github": { - "command": "npx", + "command": "docker", "args": [ - "-y", - "@modelcontextprotocol/server-github" + "run", + "-i", + "--rm", + "-e", + "GITHUB_PERSONAL_ACCESS_TOKEN=$GITHUB_PERSONAL_ACCESS_TOKEN", + "ai/mcp-github" ], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "" @@ -242,6 +247,33 @@ To use this with Claude Desktop, add the following to your `claude_desktop_confi } ``` +### NPX + +```json +{ + "mcpServers": { + "github": { + "command": "npx", + "args": [ + "-y", + "@modelcontextprotocol/server-github" + ] + }, + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "" + } + } +} +``` + +## Build + +Docker build: + +```bash +docker build -t ai/mcp-github -f src/github/Dockerfile . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/github/package.json b/src/github/package.json index 0fc2aaebed..46d24ccd6b 100644 --- a/src/github/package.json +++ b/src/github/package.json @@ -20,7 +20,7 @@ }, "dependencies": { "@modelcontextprotocol/sdk": "1.0.1", - "@types/node": "^20.11.0", + "@types/node": "^22", "@types/node-fetch": "^2.6.12", "node-fetch": "^3.3.2", "zod": "^3.22.4", diff --git a/src/gitlab/Dockerfile b/src/gitlab/Dockerfile new file mode 100644 index 0000000000..79caaef020 --- /dev/null +++ b/src/gitlab/Dockerfile @@ -0,0 +1,18 @@ +FROM node:22.12-alpine as builder + +COPY src/gitlab /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/gitlab/README.md b/src/gitlab/README.md index fdf8255265..7feb06b428 100644 --- a/src/gitlab/README.md +++ b/src/gitlab/README.md @@ -109,19 +109,57 @@ MCP Server for the GitLab API, enabling project management, file operations, and ### Usage with Claude Desktop Add the following to your `claude_desktop_config.json`: +#### Docker ```json { - "gitlab": { - "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-gitlab"], - "env": { - "GITLAB_PERSONAL_ACCESS_TOKEN": "", - "GITLAB_API_URL": "https://gitlab.com/api/v4" // Optional, for self-hosted instances + "mcpServers": { + "gitlab": { + "command": "docker", + "args": [ + "run", + "-e", + "GITLAB_PERSONAL_ACCESS_TOKEN=$GITLAB_PERSONAL_ACCESS_TOKEN", + "-e", + "GITLAB_API_URL=$GITLAB_API_URL", + "ai/mcp-gitlab" + ], + "env": { + "GITLAB_PERSONAL_ACCESS_TOKEN": "", + "GITLAB_API_URL": "https://gitlab.com/api/v4" // Optional, for self-hosted instances + } } } } ``` +### NPX + +```json +{ + "mcpServers": { + "gitlab": { + "command": "npx", + "args": [ + "-y", + "@modelcontextprotocol/server-gitlab" + ], + "env": { + "GITLAB_PERSONAL_ACCESS_TOKEN": "", + "GITLAB_API_URL": "https://gitlab.com/api/v4" // Optional, for self-hosted instances + } + } + } +} +``` + +## Build + +Docker build: + +```bash +docker build -t vonwig/gitlab:mcp -f src/gitlab/Dockerfile . +``` + ## Environment Variables - `GITLAB_PERSONAL_ACCESS_TOKEN`: Your GitLab personal access token (required) diff --git a/src/google-maps/Dockerfile b/src/google-maps/Dockerfile new file mode 100644 index 0000000000..ca8a7dd5bb --- /dev/null +++ b/src/google-maps/Dockerfile @@ -0,0 +1,19 @@ +FROM node:22.12-alpine as builder + +# Must be entire project because `prepare` script is run during `npm install` and requires all files. +COPY src/google-maps /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/google-maps/README.md b/src/google-maps/README.md index 51a1b9e5f6..46a55c7290 100644 --- a/src/google-maps/README.md +++ b/src/google-maps/README.md @@ -59,6 +59,31 @@ Get a Google Maps API key by following the instructions [here](https://developer Add the following to your `claude_desktop_config.json`: +#### Docker + +```json +{ + "mcpServers": { + "google-maps": { + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "-e", + "GOOGLE_MAPS_API_KEY=$GOOGLE_MAPS_API_KEY", + "ai/mcp-google-maps" + ], + "env": { + "GOOGLE_MAPS_API_KEY": "" + } + } + } +} +``` + +### NPX + ```json { "mcpServers": { @@ -76,6 +101,14 @@ Add the following to your `claude_desktop_config.json`: } ``` +## Build + +Docker build: + +```bash +docker build -t vonwig/google-maps:mcp -f src/google-maps/Dockerfile . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/memory/Dockerfile b/src/memory/Dockerfile new file mode 100644 index 0000000000..0bbfa8efb5 --- /dev/null +++ b/src/memory/Dockerfile @@ -0,0 +1,18 @@ +FROM node:22.12-alpine as builder + +COPY src/memory /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/memory/README.md b/src/memory/README.md index 66bdbb410c..37f47094e0 100644 --- a/src/memory/README.md +++ b/src/memory/README.md @@ -127,7 +127,23 @@ Example: # Usage with Claude Desktop ### Setup + Add this to your claude_desktop_config.json: + +#### Docker + +```json +{ + "mcpServers": { + "memory": { + "command": "docker", + "args": ["run", "-i", "--rm", "ai/mcp-memory"] + } + } +} +``` + +#### NPX ```json { "mcpServers": { @@ -174,6 +190,14 @@ Follow these steps for each interaction: b) Store facts about them as observations ``` +## Building + +Docker: + +```sh +docker build -t ai/mcp-memory -f src/memory/Dockerfile . +``` + ## License -This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. +This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. \ No newline at end of file diff --git a/src/memory/package.json b/src/memory/package.json index 49cbc92eab..741244b187 100644 --- a/src/memory/package.json +++ b/src/memory/package.json @@ -22,7 +22,7 @@ "@modelcontextprotocol/sdk": "1.0.1" }, "devDependencies": { - "@types/node": "^22.9.3", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } diff --git a/src/postgres/Dockerfile b/src/postgres/Dockerfile new file mode 100644 index 0000000000..70fec576f4 --- /dev/null +++ b/src/postgres/Dockerfile @@ -0,0 +1,18 @@ +FROM node:22.12-alpine as builder + +COPY src/postgres /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/postgres/README.md b/src/postgres/README.md index 9a16af7740..f5e7b3a1ab 100644 --- a/src/postgres/README.md +++ b/src/postgres/README.md @@ -24,6 +24,21 @@ The server provides schema information for each table in the database: To use this server with the Claude Desktop app, add the following configuration to the "mcpServers" section of your `claude_desktop_config.json`: +### Docker + +```json +{ + "mcpServers": { + "postgres": { + "command": "docker", + "args": ["run", "-i", "--rm", "ai/mcp-postgres", "host.docker.internal:5432/mydb"] + } + } +} +``` + +### NPX + ```json { "mcpServers": { @@ -41,6 +56,14 @@ To use this server with the Claude Desktop app, add the following configuration Replace `/mydb` with your database name. +## Building + +Docker: + +```sh +docker build -t ai/mcp-postgres -f src/postgres/Dockerfile . +``` + ## License -This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. +This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. \ No newline at end of file diff --git a/src/puppeteer/Dockerfile b/src/puppeteer/Dockerfile new file mode 100644 index 0000000000..d3b250b1c0 --- /dev/null +++ b/src/puppeteer/Dockerfile @@ -0,0 +1,27 @@ +FROM node:22-bullseye-slim + +ENV DEBIAN_FRONTEND noninteractive + +# for arm64 support we need to install chromium provided by debian +# npm ERR! The chromium binary is not available for arm64. +# https://github.com/puppeteer/puppeteer/issues/7740 + +ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true +ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium + +RUN apt-get update && \ + apt-get install -y wget gnupg && \ + apt-get install -y fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 \ + libgtk2.0-0 libnss3 libatk-bridge2.0-0 libdrm2 libxkbcommon0 libgbm1 libasound2 && \ + apt-get install -y chromium && \ + apt-get clean + +COPY src/puppeteer /project +COPY tsconfig.json /tsconfig.json + +WORKDIR /project + +RUN npm install + +CMD ["node", "dist/index.js"] + diff --git a/src/puppeteer/README.md b/src/puppeteer/README.md index a951a9a327..715f9d0a85 100644 --- a/src/puppeteer/README.md +++ b/src/puppeteer/README.md @@ -65,6 +65,21 @@ The server provides access to two types of resources: ## Configuration to use Puppeteer Server Here's the Claude Desktop configuration to use the Puppeter server: +### Docker + +```json +{ + "mcpServers": { + "puppeteer": { + "command": "docker", + "args": ["run", "-i", "--rm", "--init", "ai/mcp-puppeteer"] + } + } +} +``` + +### NPX + ```json { "mcpServers": { @@ -76,6 +91,14 @@ Here's the Claude Desktop configuration to use the Puppeter server: } ``` +## Build + +Docker build: + +```bash +docker build -t ai/mcp-puppeteer -f src/puppeteer/Dockerfile . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/puppeteer/index.ts b/src/puppeteer/index.ts index 5cae2eb016..2dc9837137 100644 --- a/src/puppeteer/index.ts +++ b/src/puppeteer/index.ts @@ -108,7 +108,7 @@ const screenshots = new Map(); async function ensureBrowser() { if (!browser) { - browser = await puppeteer.launch({ headless: false }); + browser = await puppeteer.launch({ headless: true, args: ["--no-sandbox"] }); const pages = await browser.pages(); page = pages[0]; diff --git a/src/sentry/Dockerfile b/src/sentry/Dockerfile new file mode 100644 index 0000000000..5cd6f22009 --- /dev/null +++ b/src/sentry/Dockerfile @@ -0,0 +1,29 @@ +# Use a Python image with uv pre-installed +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim + +# Install the project into `/app` +WORKDIR /app + +# Enable bytecode compilation +ENV UV_COMPILE_BYTECODE=1 + +# Copy from the cache instead of linking since it's a mounted volume +ENV UV_LINK_MODE=copy + +# Install the project's dependencies using the lockfile and settings +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --frozen --no-install-project --no-dev + +# Then, add the rest of the project source code and install it +# Installing separately from its dependencies allows optimal layer caching +ADD . /app +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev + +# Place executables in the environment at the front of the path +ENV PATH="/app/.venv/bin:$PATH" + +# when running the container, add --db-path and a bind mount to the host's db file +ENTRYPOINT ["uv" , "run" , "--directory", ".", "mcp-server-sentry"] diff --git a/src/sequentialthinking/Dockerfile b/src/sequentialthinking/Dockerfile new file mode 100644 index 0000000000..3f35b54319 --- /dev/null +++ b/src/sequentialthinking/Dockerfile @@ -0,0 +1,18 @@ +FROM node:22.12-alpine as builder + +COPY src/sequentialthinking /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] diff --git a/src/sequentialthinking/README.md b/src/sequentialthinking/README.md index 0b299c3f47..15586b3930 100644 --- a/src/sequentialthinking/README.md +++ b/src/sequentialthinking/README.md @@ -44,6 +44,8 @@ The Sequential Thinking tool is designed for: Add this to your `claude_desktop_config.json`: +#### npx + ```json { "mcpServers": { @@ -58,6 +60,32 @@ Add this to your `claude_desktop_config.json`: } ``` +#### docker + +```json +{ + "mcpServers": { + "sequentialthinking": { + "command": "docker", + "args": [ + "run", + "--rm", + "-i", + "ai/mcp-sequentialthinking" + ] + } + } +} +``` + +## Building + +Docker: + +```bash +docker build -t ai/mcp-sequentialthinking -f sequentialthinking/Dockerfile . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/sequentialthinking/package.json b/src/sequentialthinking/package.json index d696695efe..89205d3044 100644 --- a/src/sequentialthinking/package.json +++ b/src/sequentialthinking/package.json @@ -24,7 +24,7 @@ "yargs": "^17.7.2" }, "devDependencies": { - "@types/node": "^20.11.0", + "@types/node": "^22", "@types/yargs": "^17.0.32", "shx": "^0.3.4", "typescript": "^5.3.3" diff --git a/src/slack/Dockerfile b/src/slack/Dockerfile new file mode 100644 index 0000000000..aed894eff3 --- /dev/null +++ b/src/slack/Dockerfile @@ -0,0 +1,19 @@ +FROM node:22.12-alpine as builder + +# Must be entire project because `prepare` script is run during `npm install` and requires all files. +COPY src/slack /app +COPY tsconfig.json /tsconfig.json + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.npm npm install + +FROM node:22-alpine AS release + +COPY --from=builder /app/dist /app + +ENV NODE_ENV=production + +WORKDIR /app + +CMD ["node", "dist/index.js"] diff --git a/src/slack/README.md b/src/slack/README.md index b3d80a21f9..b0523ee382 100644 --- a/src/slack/README.md +++ b/src/slack/README.md @@ -89,6 +89,8 @@ MCP Server for the Slack API, enabling Claude to interact with Slack workspaces. Add the following to your `claude_desktop_config.json`: +#### npx + ```json { "mcpServers": { @@ -107,6 +109,32 @@ Add the following to your `claude_desktop_config.json`: } ``` +#### docker + +```json +{ + "mcpServers": { + "slack": { + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "-e", + "SLACK_BOT_TOKEN=$SLACK_BOT_TOKEN", + "-e", + "SLACK_TEAM_ID=$SLACK_TEAM_ID", + "ai/mcp-slack" + ], + "env": { + "SLACK_BOT_TOKEN": "xoxb-your-bot-token", + "SLACK_TEAM_ID": "T01234567" + } + } + } +} +``` + ### Troubleshooting If you encounter permission errors, verify that: @@ -115,6 +143,14 @@ If you encounter permission errors, verify that: 3. The tokens and workspace ID are correctly copied to your configuration 4. The app has been added to the channels it needs to access +## Build + +Docker build: + +```bash +docker build -t ai/mcp-slack -f src/slack/Dockerfile . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/slack/package.json b/src/slack/package.json index 10e18594cc..337b9db08c 100644 --- a/src/slack/package.json +++ b/src/slack/package.json @@ -22,7 +22,7 @@ "@modelcontextprotocol/sdk": "1.0.1" }, "devDependencies": { - "@types/node": "^22.9.3", + "@types/node": "^22", "shx": "^0.3.4", "typescript": "^5.6.2" } diff --git a/src/sqlite/Dockerfile b/src/sqlite/Dockerfile new file mode 100644 index 0000000000..8189a3d6a3 --- /dev/null +++ b/src/sqlite/Dockerfile @@ -0,0 +1,29 @@ +# Use a Python image with uv pre-installed +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim + +# Install the project into `/app` +WORKDIR /app + +# Enable bytecode compilation +ENV UV_COMPILE_BYTECODE=1 + +# Copy from the cache instead of linking since it's a mounted volume +ENV UV_LINK_MODE=copy + +# Install the project's dependencies using the lockfile and settings +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --frozen --no-install-project --no-dev + +# Then, add the rest of the project source code and install it +# Installing separately from its dependencies allows optimal layer caching +ADD . /app +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev + +# Place executables in the environment at the front of the path +ENV PATH="/app/.venv/bin:$PATH" + +# when running the container, add --db-path and a bind mount to the host's db file +ENTRYPOINT ["uv" , "run" , "--directory", ".", "mcp-server-sqlite"] diff --git a/src/sqlite/README.md b/src/sqlite/README.md index 2b2bea8056..517b6e4788 100644 --- a/src/sqlite/README.md +++ b/src/sqlite/README.md @@ -63,6 +63,8 @@ The server offers six core tools: ## Usage with Claude Desktop +### uv + ```bash # Add the server to your claude_desktop_config.json "mcpServers": { @@ -80,6 +82,35 @@ The server offers six core tools: } ``` +### Docker + +```json +# Add the server to your claude_desktop_config.json +"mcpServers": { + "sqlite": { + "command": "docker", + "args": [ + "run", + "--rm", + "-i", + "-v", + "mcp-test:/mcp", + "ai/mcp-sqlite", + "--db-path", + "/mcp/test.db" + ] + } +} +``` + +## Building + +Docker: + +```bash +docker build -t ai/mcp-sqlite . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/time/Dockerfile b/src/time/Dockerfile new file mode 100644 index 0000000000..b45b389dd0 --- /dev/null +++ b/src/time/Dockerfile @@ -0,0 +1,29 @@ +# Use a Python image with uv pre-installed +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim + +# Install the project into `/app` +WORKDIR /app + +# Enable bytecode compilation +ENV UV_COMPILE_BYTECODE=1 + +# Copy from the cache instead of linking since it's a mounted volume +ENV UV_LINK_MODE=copy + +# Install the project's dependencies using the lockfile and settings +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --frozen --no-install-project --no-dev + +# Then, add the rest of the project source code and install it +# Installing separately from its dependencies allows optimal layer caching +ADD . /app +RUN --mount=type=cache,target=/root/.cache/uv \ + uv sync --frozen --no-dev + +# Place executables in the environment at the front of the path +ENV PATH="/app/.venv/bin:$PATH" + +# when running the container, add --db-path and a bind mount to the host's db file +ENTRYPOINT ["uv" , "run" , "--directory", ".", "mcp-server-time"] diff --git a/src/time/README.md b/src/time/README.md index 8f80e415ce..f40dc19df7 100644 --- a/src/time/README.md +++ b/src/time/README.md @@ -54,6 +54,19 @@ Add to your Claude settings: ``` +
+Using docker + +```json +"mcpServers": { + "time": { + "command": "docker", + "args": ["run", "-i", "--rm", "ai/mcp-time"] + } +} +``` +
+
Using pip installation @@ -179,6 +192,15 @@ npx @modelcontextprotocol/inspector uv run mcp-server-time 3. "When it's 4 PM in New York, what time is it in London?" 4. "Convert 9:30 AM Tokyo time to New York time" +## Build + +Docker build: + +```bash +cd src/time +docker build -t ai/mcp-time . +``` + ## Contributing We encourage contributions to help expand and improve mcp-server-time. Whether you want to add new time-related tools, enhance existing functionality, or improve documentation, your input is valuable. From 9ff603aef587059aa1aca79f42b23f998b089279 Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Tue, 17 Dec 2024 13:15:58 -0500 Subject: [PATCH 02/21] Update dockerfiles for npx versions, gdrive env credential paths --- src/filesystem/Dockerfile | 7 +++++-- src/gdrive/Dockerfile | 9 ++++++--- src/gdrive/README.md | 2 +- src/gdrive/index.ts | 8 ++++---- src/github/Dockerfile | 3 +++ src/gitlab/Dockerfile | 3 +++ src/google-maps/Dockerfile | 3 +++ src/memory/Dockerfile | 3 +++ src/postgres/Dockerfile | 4 +++- src/sequentialthinking/Dockerfile | 3 +++ src/slack/Dockerfile | 3 +++ 11 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/filesystem/Dockerfile b/src/filesystem/Dockerfile index 2addb6dbcf..00b4cb49c9 100644 --- a/src/filesystem/Dockerfile +++ b/src/filesystem/Dockerfile @@ -6,11 +6,14 @@ COPY src/filesystem /app COPY tsconfig.json /tsconfig.json RUN --mount=type=cache,target=/root/.npm npm install - + +RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev + + FROM node:22-alpine AS release COPY --from=builder /app/dist /app - +COPY --from=builder /app/node_modules /app/node_modules ENV NODE_ENV=production WORKDIR /app diff --git a/src/gdrive/Dockerfile b/src/gdrive/Dockerfile index 43840db728..edc223c424 100644 --- a/src/gdrive/Dockerfile +++ b/src/gdrive/Dockerfile @@ -7,12 +7,15 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.npm npm install +RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev + FROM node:22-alpine AS release -COPY --from=builder /app/dist /app +WORKDIR /app -ENV NODE_ENV=production +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/node_modules /app/node_modules -WORKDIR /app +ENV NODE_ENV=production CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/gdrive/README.md b/src/gdrive/README.md index 016b592ddb..1ef88b671e 100644 --- a/src/gdrive/README.md +++ b/src/gdrive/README.md @@ -56,7 +56,7 @@ To integrate this server with the desktop app, add the following to your app's s "mcpServers": { "gdrive": { "command": "docker", - "args": ["run", "-i", "--rm", "ai/mcp-gdrive"] + "args": ["run", "-i", "--rm", "--mount", "type=bind,source=/Users/colinmcneil/Desktop/gcp-oauth.keys.json,target=/gcp-oauth.keys.json", "-v", "mcp-gdrive:/gdrive-server", "-e", "GDRIVE_OAUTH_PATH=/gcp-oauth.keys.json", "-e", "GDRIVE_CREDENTIALS_PATH=/gdrive-server/credentials.json", "ai/mcp-gdrive"] } } } diff --git a/src/gdrive/index.ts b/src/gdrive/index.ts index b9c6d910ca..deb8ec0688 100644 --- a/src/gdrive/index.ts +++ b/src/gdrive/index.ts @@ -152,13 +152,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { const userQuery = request.params.arguments?.query as string; const escapedQuery = userQuery.replace(/\\/g, "\\\\").replace(/'/g, "\\'"); const formattedQuery = `fullText contains '${escapedQuery}'`; - + const res = await drive.files.list({ q: formattedQuery, pageSize: 10, fields: "files(id, name, mimeType, modifiedTime, size)", }); - + const fileList = res.data.files ?.map((file: any) => `${file.name} (${file.mimeType})`) .join("\n"); @@ -175,7 +175,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { throw new Error("Tool not found"); }); -const credentialsPath = path.join( +const credentialsPath = process.env.GDRIVE_CREDENTIALS_PATH || path.join( path.dirname(new URL(import.meta.url).pathname), "../../../.gdrive-server-credentials.json", ); @@ -185,7 +185,7 @@ async function authenticateAndSaveCredentials() { const auth = await authenticate({ keyfilePath: path.join( path.dirname(new URL(import.meta.url).pathname), - "../../../gcp-oauth.keys.json", + process.env.GDRIVE_OAUTH_PATH || "../../../gcp-oauth.keys.json", ), scopes: ["https://www.googleapis.com/auth/drive.readonly"], }); diff --git a/src/github/Dockerfile b/src/github/Dockerfile index a94abcccf7..20f4ff387b 100644 --- a/src/github/Dockerfile +++ b/src/github/Dockerfile @@ -8,9 +8,12 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.npm npm install +RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev + FROM node:22-alpine AS release COPY --from=builder /app/dist /app +COPY --from=builder /app/node_modules /app/node_modules ENV NODE_ENV=production diff --git a/src/gitlab/Dockerfile b/src/gitlab/Dockerfile index 79caaef020..83e470b6ff 100644 --- a/src/gitlab/Dockerfile +++ b/src/gitlab/Dockerfile @@ -7,9 +7,12 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.npm npm install +RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev + FROM node:22-alpine AS release COPY --from=builder /app/dist /app +COPY --from=builder /app/node_modules /app/node_modules ENV NODE_ENV=production diff --git a/src/google-maps/Dockerfile b/src/google-maps/Dockerfile index ca8a7dd5bb..24598a6d83 100644 --- a/src/google-maps/Dockerfile +++ b/src/google-maps/Dockerfile @@ -8,9 +8,12 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.npm npm install +RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev + FROM node:22-alpine AS release COPY --from=builder /app/dist /app +COPY --from=builder /app/node_modules /app/node_modules ENV NODE_ENV=production diff --git a/src/memory/Dockerfile b/src/memory/Dockerfile index 0bbfa8efb5..23f9304d98 100644 --- a/src/memory/Dockerfile +++ b/src/memory/Dockerfile @@ -7,9 +7,12 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.npm npm install +RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev + FROM node:22-alpine AS release COPY --from=builder /app/dist /app +COPY --from=builder /app/node_modules /app/node_modules ENV NODE_ENV=production diff --git a/src/postgres/Dockerfile b/src/postgres/Dockerfile index 70fec576f4..d9f8d0c70c 100644 --- a/src/postgres/Dockerfile +++ b/src/postgres/Dockerfile @@ -7,10 +7,12 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.npm npm install +RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev + FROM node:22-alpine AS release COPY --from=builder /app/dist /app - +COPY --from=builder /app/node_modules /app/node_modules ENV NODE_ENV=production WORKDIR /app diff --git a/src/sequentialthinking/Dockerfile b/src/sequentialthinking/Dockerfile index 3f35b54319..38c742c119 100644 --- a/src/sequentialthinking/Dockerfile +++ b/src/sequentialthinking/Dockerfile @@ -7,9 +7,12 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.npm npm install +RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev + FROM node:22-alpine AS release COPY --from=builder /app/dist /app +COPY --from=builder /app/node_modules /app/node_modules ENV NODE_ENV=production diff --git a/src/slack/Dockerfile b/src/slack/Dockerfile index aed894eff3..103579f68c 100644 --- a/src/slack/Dockerfile +++ b/src/slack/Dockerfile @@ -8,9 +8,12 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.npm npm install +RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev + FROM node:22-alpine AS release COPY --from=builder /app/dist /app +COPY --from=builder /app/node_modules /app/node_modules ENV NODE_ENV=production From 4e8a8d270a980cd4de03fb49c9099f051fc26347 Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Tue, 17 Dec 2024 14:56:25 -0500 Subject: [PATCH 03/21] Split production node_modules --- src/aws-kb-retrieval-server/Dockerfile | 10 +++++++--- src/brave-search/Dockerfile | 10 +++++++--- src/everart/Dockerfile | 10 ++++++++-- src/everything/Dockerfile | 8 ++++++-- src/filesystem/Dockerfile | 12 ++++++++---- src/gdrive/Dockerfile | 7 +++++-- src/gdrive/index.ts | 4 ++-- src/github/Dockerfile | 13 +++++++------ src/gitlab/Dockerfile | 13 ++++++++----- src/google-maps/Dockerfile | 9 ++++++--- src/memory/Dockerfile | 9 ++++++--- src/postgres/Dockerfile | 10 +++++++--- src/sequentialthinking/Dockerfile | 9 ++++++--- src/slack/Dockerfile | 9 ++++++--- 14 files changed, 89 insertions(+), 44 deletions(-) diff --git a/src/aws-kb-retrieval-server/Dockerfile b/src/aws-kb-retrieval-server/Dockerfile index 88f3906d1c..a173a6060e 100644 --- a/src/aws-kb-retrieval-server/Dockerfile +++ b/src/aws-kb-retrieval-server/Dockerfile @@ -9,10 +9,14 @@ RUN --mount=type=cache,target=/root/.npm npm install FROM node:22-alpine AS release -COPY --from=builder /app/dist /app +WORKDIR /app + +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production -WORKDIR /app +RUN npm ci --ignore-scripts --omit-dev -CMD ["node", "dist/index.js"] \ No newline at end of file +ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/brave-search/Dockerfile b/src/brave-search/Dockerfile index ed12955179..fefeca68bb 100644 --- a/src/brave-search/Dockerfile +++ b/src/brave-search/Dockerfile @@ -10,10 +10,14 @@ RUN --mount=type=cache,target=/root/.npm npm install FROM node:22-alpine AS release -COPY --from=builder /app/dist /app +WORKDIR /app + +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production -WORKDIR /app +RUN npm ci --ignore-scripts --omit-dev -CMD ["node", "dist/index.js"] \ No newline at end of file +ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/everart/Dockerfile b/src/everart/Dockerfile index 385c08dd64..c27f954251 100644 --- a/src/everart/Dockerfile +++ b/src/everart/Dockerfile @@ -9,10 +9,16 @@ RUN --mount=type=cache,target=/root/.npm npm install FROM node:22-alpine AS release -COPY --from=builder /app/dist /app +WORKDIR /app + +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production -WORKDIR /app +RUN npm ci --ignore-scripts --omit-dev + +ENTRYPOINT ["node", "dist/index.js"] CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/everything/Dockerfile b/src/everything/Dockerfile index 7a6482c41b..562679377e 100644 --- a/src/everything/Dockerfile +++ b/src/everything/Dockerfile @@ -9,10 +9,14 @@ RUN --mount=type=cache,target=/root/.npm npm install FROM node:22-alpine AS release -COPY --from=builder /app/dist /app +WORKDIR /app + +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production -WORKDIR /app +RUN npm ci --ignore-scripts --omit-dev CMD ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/filesystem/Dockerfile b/src/filesystem/Dockerfile index 00b4cb49c9..d762d39ee3 100644 --- a/src/filesystem/Dockerfile +++ b/src/filesystem/Dockerfile @@ -12,10 +12,14 @@ RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --om FROM node:22-alpine AS release -COPY --from=builder /app/dist /app -COPY --from=builder /app/node_modules /app/node_modules +WORKDIR /app + +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json + ENV NODE_ENV=production -WORKDIR /app +RUN npm ci --ignore-scripts --omit-dev -CMD ["node", "dist/index.js"] \ No newline at end of file +ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/gdrive/Dockerfile b/src/gdrive/Dockerfile index edc223c424..b7bb2a7685 100644 --- a/src/gdrive/Dockerfile +++ b/src/gdrive/Dockerfile @@ -14,8 +14,11 @@ FROM node:22-alpine AS release WORKDIR /app COPY --from=builder /app/dist /app/dist -COPY --from=builder /app/node_modules /app/node_modules +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production -CMD ["node", "dist/index.js"] \ No newline at end of file +RUN npm ci --ignore-scripts --omit-dev + +ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/gdrive/index.ts b/src/gdrive/index.ts index deb8ec0688..4a8e954c05 100644 --- a/src/gdrive/index.ts +++ b/src/gdrive/index.ts @@ -183,9 +183,9 @@ const credentialsPath = process.env.GDRIVE_CREDENTIALS_PATH || path.join( async function authenticateAndSaveCredentials() { console.log("Launching auth flow…"); const auth = await authenticate({ - keyfilePath: path.join( + keyfilePath: process.env.GDRIVE_OAUTH_PATH || path.join( path.dirname(new URL(import.meta.url).pathname), - process.env.GDRIVE_OAUTH_PATH || "../../../gcp-oauth.keys.json", + "../../../gcp-oauth.keys.json", ), scopes: ["https://www.googleapis.com/auth/drive.readonly"], }); diff --git a/src/github/Dockerfile b/src/github/Dockerfile index 20f4ff387b..4a054d65bf 100644 --- a/src/github/Dockerfile +++ b/src/github/Dockerfile @@ -8,15 +8,16 @@ WORKDIR /app RUN --mount=type=cache,target=/root/.npm npm install -RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev +FROM node:22.12-alpine AS release -FROM node:22-alpine AS release - -COPY --from=builder /app/dist /app -COPY --from=builder /app/node_modules /app/node_modules +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production WORKDIR /app -CMD ["node", "dist/index.js"] \ No newline at end of file +RUN npm ci --ignore-scripts --omit-dev + +ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/gitlab/Dockerfile b/src/gitlab/Dockerfile index 83e470b6ff..ce8823ca49 100644 --- a/src/gitlab/Dockerfile +++ b/src/gitlab/Dockerfile @@ -9,13 +9,16 @@ RUN --mount=type=cache,target=/root/.npm npm install RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev -FROM node:22-alpine AS release +FROM node:22.12-alpine AS release -COPY --from=builder /app/dist /app -COPY --from=builder /app/node_modules /app/node_modules +WORKDIR /app + +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production -WORKDIR /app +RUN npm ci --ignore-scripts --omit-dev -CMD ["node", "dist/index.js"] \ No newline at end of file +ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/google-maps/Dockerfile b/src/google-maps/Dockerfile index 24598a6d83..629496805d 100644 --- a/src/google-maps/Dockerfile +++ b/src/google-maps/Dockerfile @@ -12,11 +12,14 @@ RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --om FROM node:22-alpine AS release -COPY --from=builder /app/dist /app -COPY --from=builder /app/node_modules /app/node_modules +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production WORKDIR /app -CMD ["node", "dist/index.js"] \ No newline at end of file +RUN npm ci --ignore-scripts --omit-dev + +ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/memory/Dockerfile b/src/memory/Dockerfile index 23f9304d98..d5af847105 100644 --- a/src/memory/Dockerfile +++ b/src/memory/Dockerfile @@ -11,11 +11,14 @@ RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --om FROM node:22-alpine AS release -COPY --from=builder /app/dist /app -COPY --from=builder /app/node_modules /app/node_modules +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production WORKDIR /app -CMD ["node", "dist/index.js"] \ No newline at end of file +RUN npm ci --ignore-scripts --omit-dev + +ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/postgres/Dockerfile b/src/postgres/Dockerfile index d9f8d0c70c..f390ec0e93 100644 --- a/src/postgres/Dockerfile +++ b/src/postgres/Dockerfile @@ -11,10 +11,14 @@ RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --om FROM node:22-alpine AS release -COPY --from=builder /app/dist /app -COPY --from=builder /app/node_modules /app/node_modules +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json + ENV NODE_ENV=production WORKDIR /app -CMD ["node", "dist/index.js"] \ No newline at end of file +RUN npm ci --ignore-scripts --omit-dev + +ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/sequentialthinking/Dockerfile b/src/sequentialthinking/Dockerfile index 38c742c119..08a4282a59 100644 --- a/src/sequentialthinking/Dockerfile +++ b/src/sequentialthinking/Dockerfile @@ -11,11 +11,14 @@ RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --om FROM node:22-alpine AS release -COPY --from=builder /app/dist /app -COPY --from=builder /app/node_modules /app/node_modules +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production WORKDIR /app -CMD ["node", "dist/index.js"] +RUN npm ci --ignore-scripts --omit-dev + +ENTRYPOINT ["node", "dist/index.js"] diff --git a/src/slack/Dockerfile b/src/slack/Dockerfile index 103579f68c..6df0be5200 100644 --- a/src/slack/Dockerfile +++ b/src/slack/Dockerfile @@ -12,11 +12,14 @@ RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --om FROM node:22-alpine AS release -COPY --from=builder /app/dist /app -COPY --from=builder /app/node_modules /app/node_modules +COPY --from=builder /app/dist /app/dist +COPY --from=builder /app/package.json /app/package.json +COPY --from=builder /app/package-lock.json /app/package-lock.json ENV NODE_ENV=production WORKDIR /app -CMD ["node", "dist/index.js"] +RUN npm ci --ignore-scripts --omit-dev + +ENTRYPOINT ["node", "dist/index.js"] From bb0adaafd8c3c5b93715709e3108a4b18f987886 Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Tue, 17 Dec 2024 15:20:48 -0500 Subject: [PATCH 04/21] Allow filesystem to accept `DOCKER_ROOT_WORKSPACE` --- src/filesystem/README.md | 1 + src/filesystem/index.ts | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/filesystem/README.md b/src/filesystem/README.md index b9286511e3..d7e1fdc967 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -122,6 +122,7 @@ 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" ] } diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index b4d5c419fc..e67887e7fc 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -17,9 +17,20 @@ import { minimatch } from 'minimatch'; // Command line argument parsing const args = process.argv.slice(2); -if (args.length === 0) { - console.error("Usage: mcp-server-filesystem [additional-directories...]"); - process.exit(1); + +let allowedDirectories: string[] = []; + +if (process.env.DOCKER_ROOT_WORKSPACE) { + allowedDirectories = await fs.readdir(process.env.DOCKER_ROOT_WORKSPACE); +} +else { + if (args.length === 0) { + console.error("Usage: mcp-server-filesystem [additional-directories...]"); + process.exit(1); + } + allowedDirectories = args.map(dir => + normalizePath(path.resolve(expandHome(dir))) + ); } // Normalize all paths consistently @@ -35,12 +46,9 @@ function expandHome(filepath: string): string { } // Store allowed directories in normalized form -const allowedDirectories = args.map(dir => - normalizePath(path.resolve(expandHome(dir))) -); // Validate that all directories exist and are accessible -await Promise.all(args.map(async (dir) => { +await Promise.all(allowedDirectories.map(async (dir) => { try { const stats = await fs.stat(dir); if (!stats.isDirectory()) { @@ -644,4 +652,4 @@ async function runServer() { runServer().catch((error) => { console.error("Fatal error running server:", error); process.exit(1); -}); +}); \ No newline at end of file From 308b71c698123c5c6684b9c79de04b20dd9fb422 Mon Sep 17 00:00:00 2001 From: Jim Clark Date: Tue, 17 Dec 2024 17:49:04 -0800 Subject: [PATCH 05/21] Remove env from postgres server * interpolation of env into command args is not supported --- src/postgres/README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/postgres/README.md b/src/postgres/README.md index f5e7b3a1ab..f5ace34c58 100644 --- a/src/postgres/README.md +++ b/src/postgres/README.md @@ -26,12 +26,20 @@ To use this server with the Claude Desktop app, add the following configuration ### Docker +* when running docker on macos, use host.docker.internal if the server is running on the host network (eg localhost) +* username/password can be added to the postgresql url with `postgresql://user:password@host:port/db-name` + ```json { "mcpServers": { "postgres": { "command": "docker", - "args": ["run", "-i", "--rm", "ai/mcp-postgres", "host.docker.internal:5432/mydb"] + "args": [ + "run", + "-i", + "--rm", + "ai/mcp-postgres", + "postgresql://host.docker.internal:5432/mydb"] } } } @@ -66,4 +74,4 @@ docker build -t ai/mcp-postgres -f src/postgres/Dockerfile . ## License -This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. \ No newline at end of file +This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. From c64f8de15f5c38a5c1eb5a4841397b2dfdafff09 Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Wed, 18 Dec 2024 11:00:11 -0500 Subject: [PATCH 06/21] Config tweaks for docker - Remove `$` interpolation for env - Allow puppeteer to work headless in docker, headful with npx --- src/aws-kb-retrieval-server/README.md | 2 +- src/brave-search/README.md | 2 +- src/everart/README.md | 2 +- src/filesystem/Dockerfile | 4 +- src/filesystem/README.md | 2 +- src/filesystem/index.ts | 101 ++++++++++++++------------ src/github/README.md | 2 +- src/gitlab/README.md | 4 +- src/google-maps/README.md | 2 +- src/puppeteer/README.md | 2 +- src/puppeteer/index.ts | 4 +- src/slack/README.md | 4 +- 12 files changed, 72 insertions(+), 59 deletions(-) diff --git a/src/aws-kb-retrieval-server/README.md b/src/aws-kb-retrieval-server/README.md index ed19f1ee21..84855568b7 100644 --- a/src/aws-kb-retrieval-server/README.md +++ b/src/aws-kb-retrieval-server/README.md @@ -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", diff --git a/src/brave-search/README.md b/src/brave-search/README.md index d94ecdf111..1907fc9c30 100644 --- a/src/brave-search/README.md +++ b/src/brave-search/README.md @@ -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": { diff --git a/src/everart/README.md b/src/everart/README.md index 04b0757895..94c0e33b4a 100644 --- a/src/everart/README.md +++ b/src/everart/README.md @@ -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" } diff --git a/src/filesystem/Dockerfile b/src/filesystem/Dockerfile index d762d39ee3..0cfa371849 100644 --- a/src/filesystem/Dockerfile +++ b/src/filesystem/Dockerfile @@ -22,4 +22,6 @@ ENV NODE_ENV=production RUN npm ci --ignore-scripts --omit-dev -ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file +WORKDIR /projects + +ENTRYPOINT ["node", "/app/dist/index.js"] \ No newline at end of file diff --git a/src/filesystem/README.md b/src/filesystem/README.md index d7e1fdc967..74b83593d6 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -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 { @@ -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" ] } diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index e67887e7fc..f073a83ec3 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -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) { @@ -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); } @@ -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 { // Read file content and normalize line endings @@ -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, }, { @@ -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 { - 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 { + 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) { @@ -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") + }], }; } diff --git a/src/github/README.md b/src/github/README.md index d20ba9cc6e..a63e803b61 100644 --- a/src/github/README.md +++ b/src/github/README.md @@ -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": { diff --git a/src/gitlab/README.md b/src/gitlab/README.md index 7feb06b428..d2dff0235a 100644 --- a/src/gitlab/README.md +++ b/src/gitlab/README.md @@ -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": { diff --git a/src/google-maps/README.md b/src/google-maps/README.md index 46a55c7290..867aa2f548 100644 --- a/src/google-maps/README.md +++ b/src/google-maps/README.md @@ -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": { diff --git a/src/puppeteer/README.md b/src/puppeteer/README.md index 715f9d0a85..d13ef2a52a 100644 --- a/src/puppeteer/README.md +++ b/src/puppeteer/README.md @@ -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"] } } } diff --git a/src/puppeteer/index.ts b/src/puppeteer/index.ts index 2dc9837137..b82c653afc 100644 --- a/src/puppeteer/index.ts +++ b/src/puppeteer/index.ts @@ -108,7 +108,9 @@ const screenshots = new Map(); 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]; diff --git a/src/slack/README.md b/src/slack/README.md index b0523ee382..74d3dada01 100644 --- a/src/slack/README.md +++ b/src/slack/README.md @@ -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": { From 5865afb07a83fe376144321bb518e4cc60e545a1 Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Thu, 19 Dec 2024 11:19:09 -0500 Subject: [PATCH 07/21] Fix puppeteer docker container hanging --- src/puppeteer/Dockerfile | 3 +-- src/puppeteer/index.ts | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/puppeteer/Dockerfile b/src/puppeteer/Dockerfile index d3b250b1c0..082b250d8f 100644 --- a/src/puppeteer/Dockerfile +++ b/src/puppeteer/Dockerfile @@ -23,5 +23,4 @@ WORKDIR /project RUN npm install -CMD ["node", "dist/index.js"] - +ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/puppeteer/index.ts b/src/puppeteer/index.ts index b82c653afc..713f7626bd 100644 --- a/src/puppeteer/index.ts +++ b/src/puppeteer/index.ts @@ -401,3 +401,8 @@ async function runServer() { } runServer().catch(console.error); + +process.stdin.on("close", () => { + console.error("Puppeteer MCP Server closed"); + process.exit(1); +}); From 4034df774ed6d59074a8edc9bb3e422947e30fdd Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Thu, 19 Dec 2024 13:05:15 -0500 Subject: [PATCH 08/21] Switch puppeteer stdin close from `process.exit` to `server.close` --- src/puppeteer/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppeteer/index.ts b/src/puppeteer/index.ts index 713f7626bd..fda97164d1 100644 --- a/src/puppeteer/index.ts +++ b/src/puppeteer/index.ts @@ -404,5 +404,5 @@ runServer().catch(console.error); process.stdin.on("close", () => { console.error("Puppeteer MCP Server closed"); - process.exit(1); + server.close(); }); From 0b36cb4b54852a06430d5d678a6095f790485425 Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Thu, 19 Dec 2024 13:19:08 -0500 Subject: [PATCH 09/21] Revert filesystem back to original cli arg sandboxing --- src/filesystem/index.ts | 121 +++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 69 deletions(-) diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index f073a83ec3..b4d5c419fc 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -17,27 +17,9 @@ import { minimatch } from 'minimatch'; // Command line argument parsing const args = process.argv.slice(2); - -let allowedDirectories: string[] = []; - -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) { - console.error("Usage: mcp-server-filesystem [additional-directories...]"); - process.exit(1); - } - allowedDirectories = args.map(dir => - normalizePath(path.resolve(expandHome(dir))) - ); +if (args.length === 0) { + console.error("Usage: mcp-server-filesystem [additional-directories...]"); + process.exit(1); } // Normalize all paths consistently @@ -53,12 +35,15 @@ function expandHome(filepath: string): string { } // Store allowed directories in normalized form +const allowedDirectories = args.map(dir => + normalizePath(path.resolve(expandHome(dir))) +); // Validate that all directories exist and are accessible -await Promise.all(allowedDirectories.map(async (dir) => { +await Promise.all(args.map(async (dir) => { try { const stats = await fs.stat(dir); - if (!stats.isDirectory() && !hasProjectsDirectory) { + if (!stats.isDirectory()) { console.error(`Error: ${dir} is not a directory`); process.exit(1); } @@ -269,7 +254,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 { // Read file content and normalize line endings @@ -405,10 +390,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, }, { @@ -545,48 +530,48 @@ 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}`); - } + 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[]; - } + interface TreeEntry { + name: string; + type: 'file' | 'directory'; + children?: TreeEntry[]; + } - async function buildTree(currentPath: string): Promise { - const validPath = await validatePath(currentPath); - const entries = await fs.readdir(validPath, { withFileTypes: true }); - const result: TreeEntry[] = []; + async function buildTree(currentPath: string): Promise { + const validPath = await validatePath(currentPath); + const entries = await fs.readdir(validPath, {withFileTypes: true}); + const result: TreeEntry[] = []; - for (const entry of entries) { - const entryData: TreeEntry = { - name: entry.name, - type: entry.isDirectory() ? 'directory' : 'file' - }; + for (const entry of entries) { + const entryData: TreeEntry = { + name: entry.name, + type: entry.isDirectory() ? 'directory' : 'file' + }; - if (entry.isDirectory()) { - const subPath = path.join(currentPath, entry.name); - entryData.children = await buildTree(subPath); - } + if (entry.isDirectory()) { + const subPath = path.join(currentPath, entry.name); + entryData.children = await buildTree(subPath); + } - result.push(entryData); - } + result.push(entryData); + } - return result; - } + return result; + } - const treeData = await buildTree(parsed.data.path); - return { - content: [{ - type: "text", - text: JSON.stringify(treeData, null, 2) - }], - }; - } + 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); @@ -621,11 +606,9 @@ 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") }], }; } @@ -661,4 +644,4 @@ async function runServer() { runServer().catch((error) => { console.error("Fatal error running server:", error); process.exit(1); -}); \ No newline at end of file +}); From 545103386f6fb284a217d2d7338cff1878e5c74e Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Thu, 19 Dec 2024 13:19:34 -0500 Subject: [PATCH 10/21] Update filesystem config for Docker --- src/filesystem/Dockerfile | 2 -- src/filesystem/README.md | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/filesystem/Dockerfile b/src/filesystem/Dockerfile index 0cfa371849..12e5bcf4bf 100644 --- a/src/filesystem/Dockerfile +++ b/src/filesystem/Dockerfile @@ -22,6 +22,4 @@ ENV NODE_ENV=production RUN npm ci --ignore-scripts --omit-dev -WORKDIR /projects - ENTRYPOINT ["node", "/app/dist/index.js"] \ No newline at end of file diff --git a/src/filesystem/README.md b/src/filesystem/README.md index 74b83593d6..50d8c34797 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -123,7 +123,8 @@ Note: all directories must be mounted to `/projects` by default. "--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", - "ai/mcp-filesystem" + "ai/mcp-filesystem", + "/projects", ] } } From 49044156e32f393e8f322314703f650d1f8ca734 Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Thu, 19 Dec 2024 15:56:30 -0500 Subject: [PATCH 11/21] Update readmes to use new `mcp` namespace --- README.md | 4 ++-- src/aws-kb-retrieval-server/README.md | 4 ++-- src/brave-search/README.md | 2 +- src/everart/README.md | 4 ++-- src/filesystem/README.md | 4 ++-- src/gdrive/README.md | 2 +- src/git/README.md | 4 ++-- src/github/README.md | 4 ++-- src/gitlab/README.md | 2 +- src/google-maps/README.md | 2 +- src/memory/README.md | 4 ++-- src/postgres/README.md | 4 ++-- src/puppeteer/README.md | 4 ++-- src/sequentialthinking/README.md | 4 ++-- src/slack/README.md | 4 ++-- src/sqlite/README.md | 4 ++-- src/time/README.md | 4 ++-- 17 files changed, 30 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 7d828c0600..2606a795c7 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ A growing set of community-developed and maintained servers demonstrates various - **[Pinecone](https://github.com/sirmews/mcp-pinecone)** - MCP server for searching and uploading records to Pinecone. Allows for simple RAG features, leveraging Pinecone's Inference API. - **[HuggingFace Spaces](https://github.com/evalstate/mcp-hfspace)** - Server for using HuggingFace Spaces, supporting Open Source Image, Audio, Text Models and more. Claude Desktop mode for easy integration. - **[ChatSum](https://github.com/chatmcp/mcp-server-chatsum)** - Query and Summarize chat messages with LLM. by [mcpso](https://mcp.so) -- **[Rememberizer AI](https://github.com/skydeckai/mcp-server-rememberizer)** - An MCP server designed for interacting with the Rememberizer data source, facilitating enhanced knowledge retrieval. +- **[Rememberizer AI](https://github.com/skydeckmcp/server-rememberizer)** - An MCP server designed for interacting with the Rememberizer data source, facilitating enhanced knowledge retrieval. - **[FlightRadar24](https://github.com/sunsetcoder/flightradar24-mcp-server)** - A Claude Desktop MCP server that helps you track flights in real-time using Flightradar24 data. - **[X (Twitter)](https://github.com/vidhupv/x-mcp)** (by vidhupv) - Create, manage and publish X/Twitter posts directly through Claude chat. - **[X (Twitter)](https://github.com/EnesCinr/twitter-mcp)** (by EnesCinr) - Interact with twitter API. Post tweets and search for tweets by query. @@ -119,7 +119,7 @@ Additional resources on MCP. - **[mcp-cli](https://github.com/wong2/mcp-cli)** - A CLI inspector for the Model Context Protocol by **[wong2](https://github.com/wong2)** - **[r/mcp](https://www.reddit.com/r/mcp)** – A Reddit community dedicated to MCP by **[Frank Fiegel](https://github.com/punkpeye)** - **[MCP X Community](https://x.com/i/communities/1861891349609603310)** – A X community for MCP by **[Xiaoyi](https://x.com/chxy)** -- **[mcp-manager](https://github.com/zueai/mcp-manager)** - Simple Web UI to install and manage MCP servers for Claude Desktop by **[Zue](https://github.com/zueai)** +- **[mcp-manager](https://github.com/zuemcp/manager)** - Simple Web UI to install and manage MCP servers for Claude Desktop by **[Zue](https://github.com/zueai)** - **[MCPHub](https://github.com/Jeamee/MCPHub-Desktop)** – An Open Source MacOS & Windows GUI Desktop app for discovering, installing and managing MCP servers by **[Jeamee](https://github.com/jeamee)** ## 🚀 Getting Started diff --git a/src/aws-kb-retrieval-server/README.md b/src/aws-kb-retrieval-server/README.md index 84855568b7..bcd9fc2f4d 100644 --- a/src/aws-kb-retrieval-server/README.md +++ b/src/aws-kb-retrieval-server/README.md @@ -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", "-e", "AWS_SECRET_ACCESS_KEY", "-e", "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", "mcp/aws-kb-retrieval-server" ], "env": { "AWS_ACCESS_KEY_ID": "YOUR_ACCESS_KEY_HERE", "AWS_SECRET_ACCESS_KEY": "YOUR_SECRET_ACCESS_KEY_HERE", @@ -69,7 +69,7 @@ Add this to your `claude_desktop_config.json`: Docker: ```sh -docker build -t ai/mcp-aws-kb-retrieval -f src/aws-kb-retrieval-server/Dockerfile . +docker build -t mcp/aws-kb-retrieval -f src/aws-kb-retrieval-server/Dockerfile . ``` ## License diff --git a/src/brave-search/README.md b/src/brave-search/README.md index 1907fc9c30..a7c1b47c45 100644 --- a/src/brave-search/README.md +++ b/src/brave-search/README.md @@ -49,7 +49,7 @@ Add this to your `claude_desktop_config.json`: "--rm", "-e", "BRAVE_API_KEY", - "ai/mcp-brave-search" + "mcp/brave-search" ], "env": { "BRAVE_API_KEY": "YOUR_API_KEY_HERE" diff --git a/src/everart/README.md b/src/everart/README.md index 94c0e33b4a..bccd594235 100644 --- a/src/everart/README.md +++ b/src/everart/README.md @@ -17,7 +17,7 @@ Add to Claude Desktop config: "mcpServers": { "everart": { "command": "docker", - "args": ["run", "-i", "--rm", "-e", "EVERART_API_KEY", "ai/mcp-everart"], + "args": ["run", "-i", "--rm", "-e", "EVERART_API_KEY", "mcp/everart"], "env": { "EVERART_API_KEY": "your_key_here" } @@ -94,5 +94,5 @@ You can also click the URL above to view the image again. ## Building w/ Docker ```sh -docker build -t ai/mcp-everart -f src/everart/Dockerfile . +docker build -t mcp/everart -f src/everart/Dockerfile . ``` diff --git a/src/filesystem/README.md b/src/filesystem/README.md index 50d8c34797..05c915ad0a 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -123,7 +123,7 @@ Note: all directories must be mounted to `/projects` by default. "--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", - "ai/mcp-filesystem", + "mcp/filesystem", "/projects", ] } @@ -154,7 +154,7 @@ Note: all directories must be mounted to `/projects` by default. Docker build: ```bash -docker build -t ai/mcp-filesystem -f src/filesystem/Dockerfile . +docker build -t mcp/filesystem -f src/filesystem/Dockerfile . ``` ## License diff --git a/src/gdrive/README.md b/src/gdrive/README.md index 1ef88b671e..56e8cfbebb 100644 --- a/src/gdrive/README.md +++ b/src/gdrive/README.md @@ -56,7 +56,7 @@ To integrate this server with the desktop app, add the following to your app's s "mcpServers": { "gdrive": { "command": "docker", - "args": ["run", "-i", "--rm", "--mount", "type=bind,source=/Users/colinmcneil/Desktop/gcp-oauth.keys.json,target=/gcp-oauth.keys.json", "-v", "mcp-gdrive:/gdrive-server", "-e", "GDRIVE_OAUTH_PATH=/gcp-oauth.keys.json", "-e", "GDRIVE_CREDENTIALS_PATH=/gdrive-server/credentials.json", "ai/mcp-gdrive"] + "args": ["run", "-i", "--rm", "--mount", "type=bind,source=/Users/colinmcneil/Desktop/gcp-oauth.keys.json,target=/gcp-oauth.keys.json", "-v", "mcp-gdrive:/gdrive-server", "-e", "GDRIVE_OAUTH_PATH=/gcp-oauth.keys.json", "-e", "GDRIVE_CREDENTIALS_PATH=/gdrive-server/credentials.json", "mcp/gdrive"] } } } diff --git a/src/git/README.md b/src/git/README.md index d62ddd614e..d838dd9c00 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -207,7 +207,7 @@ If you are doing local development, there are two ways to test your changes: "--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", - "ai/mcp-git" + "mcp/git" ] } } @@ -236,7 +236,7 @@ Docker build: ```bash cd src/git -docker build -t ai/mcp-git . +docker build -t mcp/git . ``` ## License diff --git a/src/github/README.md b/src/github/README.md index a63e803b61..14bab491e5 100644 --- a/src/github/README.md +++ b/src/github/README.md @@ -237,7 +237,7 @@ To use this with Claude Desktop, add the following to your `claude_desktop_confi "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", - "ai/mcp-github" + "mcp/github" ], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "" @@ -271,7 +271,7 @@ To use this with Claude Desktop, add the following to your `claude_desktop_confi Docker build: ```bash -docker build -t ai/mcp-github -f src/github/Dockerfile . +docker build -t mcp/github -f src/github/Dockerfile . ``` ## License diff --git a/src/gitlab/README.md b/src/gitlab/README.md index d2dff0235a..e2b16fe174 100644 --- a/src/gitlab/README.md +++ b/src/gitlab/README.md @@ -121,7 +121,7 @@ Add the following to your `claude_desktop_config.json`: "GITLAB_PERSONAL_ACCESS_TOKEN", "-e", "GITLAB_API_URL", - "ai/mcp-gitlab" + "mcp/gitlab" ], "env": { "GITLAB_PERSONAL_ACCESS_TOKEN": "", diff --git a/src/google-maps/README.md b/src/google-maps/README.md index 867aa2f548..c0fd576e7b 100644 --- a/src/google-maps/README.md +++ b/src/google-maps/README.md @@ -72,7 +72,7 @@ Add the following to your `claude_desktop_config.json`: "--rm", "-e", "GOOGLE_MAPS_API_KEY", - "ai/mcp-google-maps" + "mcp/google-maps" ], "env": { "GOOGLE_MAPS_API_KEY": "" diff --git a/src/memory/README.md b/src/memory/README.md index 37f47094e0..e405a0d493 100644 --- a/src/memory/README.md +++ b/src/memory/README.md @@ -137,7 +137,7 @@ Add this to your claude_desktop_config.json: "mcpServers": { "memory": { "command": "docker", - "args": ["run", "-i", "--rm", "ai/mcp-memory"] + "args": ["run", "-i", "--rm", "mcp/memory"] } } } @@ -195,7 +195,7 @@ Follow these steps for each interaction: Docker: ```sh -docker build -t ai/mcp-memory -f src/memory/Dockerfile . +docker build -t mcp/memory -f src/memory/Dockerfile . ``` ## License diff --git a/src/postgres/README.md b/src/postgres/README.md index f5ace34c58..aaace581cd 100644 --- a/src/postgres/README.md +++ b/src/postgres/README.md @@ -38,7 +38,7 @@ To use this server with the Claude Desktop app, add the following configuration "run", "-i", "--rm", - "ai/mcp-postgres", + "mcp/postgres", "postgresql://host.docker.internal:5432/mydb"] } } @@ -69,7 +69,7 @@ Replace `/mydb` with your database name. Docker: ```sh -docker build -t ai/mcp-postgres -f src/postgres/Dockerfile . +docker build -t mcp/postgres -f src/postgres/Dockerfile . ``` ## License diff --git a/src/puppeteer/README.md b/src/puppeteer/README.md index d13ef2a52a..375b27cd4a 100644 --- a/src/puppeteer/README.md +++ b/src/puppeteer/README.md @@ -72,7 +72,7 @@ Here's the Claude Desktop configuration to use the Puppeter server: "mcpServers": { "puppeteer": { "command": "docker", - "args": ["run", "-i", "--rm", "--init", "-e", "DOCKER_CONTAINER=true", "ai/mcp-puppeteer"] + "args": ["run", "-i", "--rm", "--init", "-e", "DOCKER_CONTAINER=true", "mcp/puppeteer"] } } } @@ -96,7 +96,7 @@ Here's the Claude Desktop configuration to use the Puppeter server: Docker build: ```bash -docker build -t ai/mcp-puppeteer -f src/puppeteer/Dockerfile . +docker build -t mcp/puppeteer -f src/puppeteer/Dockerfile . ``` ## License diff --git a/src/sequentialthinking/README.md b/src/sequentialthinking/README.md index 15586b3930..77ccb45438 100644 --- a/src/sequentialthinking/README.md +++ b/src/sequentialthinking/README.md @@ -71,7 +71,7 @@ Add this to your `claude_desktop_config.json`: "run", "--rm", "-i", - "ai/mcp-sequentialthinking" + "mcp/sequentialthinking" ] } } @@ -83,7 +83,7 @@ Add this to your `claude_desktop_config.json`: Docker: ```bash -docker build -t ai/mcp-sequentialthinking -f sequentialthinking/Dockerfile . +docker build -t mcp/sequentialthinking -f sequentialthinking/Dockerfile . ``` ## License diff --git a/src/slack/README.md b/src/slack/README.md index 74d3dada01..970cba6645 100644 --- a/src/slack/README.md +++ b/src/slack/README.md @@ -124,7 +124,7 @@ Add the following to your `claude_desktop_config.json`: "SLACK_BOT_TOKEN", "-e", "SLACK_TEAM_ID", - "ai/mcp-slack" + "mcp/slack" ], "env": { "SLACK_BOT_TOKEN": "xoxb-your-bot-token", @@ -148,7 +148,7 @@ If you encounter permission errors, verify that: Docker build: ```bash -docker build -t ai/mcp-slack -f src/slack/Dockerfile . +docker build -t mcp/slack -f src/slack/Dockerfile . ``` ## License diff --git a/src/sqlite/README.md b/src/sqlite/README.md index 517b6e4788..e194c6bf5b 100644 --- a/src/sqlite/README.md +++ b/src/sqlite/README.md @@ -95,7 +95,7 @@ The server offers six core tools: "-i", "-v", "mcp-test:/mcp", - "ai/mcp-sqlite", + "mcp/sqlite", "--db-path", "/mcp/test.db" ] @@ -108,7 +108,7 @@ The server offers six core tools: Docker: ```bash -docker build -t ai/mcp-sqlite . +docker build -t mcp/sqlite . ``` ## License diff --git a/src/time/README.md b/src/time/README.md index f40dc19df7..eed504bb30 100644 --- a/src/time/README.md +++ b/src/time/README.md @@ -61,7 +61,7 @@ Add to your Claude settings: "mcpServers": { "time": { "command": "docker", - "args": ["run", "-i", "--rm", "ai/mcp-time"] + "args": ["run", "-i", "--rm", "mcp/time"] } } ``` @@ -198,7 +198,7 @@ Docker build: ```bash cd src/time -docker build -t ai/mcp-time . +docker build -t mcp/time . ``` ## Contributing From 70e19c466d3b99c7505e43a485aa7dc22e1da838 Mon Sep 17 00:00:00 2001 From: Jim Clark Date: Thu, 19 Dec 2024 12:40:49 -0800 Subject: [PATCH 12/21] Migrate python servers to mcp namespace --- README.md | 4 ++-- src/fetch/README.md | 13 +++++++++++++ src/git/README.md | 13 +++++++++++++ src/sentry/README.md | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2606a795c7..7d828c0600 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ A growing set of community-developed and maintained servers demonstrates various - **[Pinecone](https://github.com/sirmews/mcp-pinecone)** - MCP server for searching and uploading records to Pinecone. Allows for simple RAG features, leveraging Pinecone's Inference API. - **[HuggingFace Spaces](https://github.com/evalstate/mcp-hfspace)** - Server for using HuggingFace Spaces, supporting Open Source Image, Audio, Text Models and more. Claude Desktop mode for easy integration. - **[ChatSum](https://github.com/chatmcp/mcp-server-chatsum)** - Query and Summarize chat messages with LLM. by [mcpso](https://mcp.so) -- **[Rememberizer AI](https://github.com/skydeckmcp/server-rememberizer)** - An MCP server designed for interacting with the Rememberizer data source, facilitating enhanced knowledge retrieval. +- **[Rememberizer AI](https://github.com/skydeckai/mcp-server-rememberizer)** - An MCP server designed for interacting with the Rememberizer data source, facilitating enhanced knowledge retrieval. - **[FlightRadar24](https://github.com/sunsetcoder/flightradar24-mcp-server)** - A Claude Desktop MCP server that helps you track flights in real-time using Flightradar24 data. - **[X (Twitter)](https://github.com/vidhupv/x-mcp)** (by vidhupv) - Create, manage and publish X/Twitter posts directly through Claude chat. - **[X (Twitter)](https://github.com/EnesCinr/twitter-mcp)** (by EnesCinr) - Interact with twitter API. Post tweets and search for tweets by query. @@ -119,7 +119,7 @@ Additional resources on MCP. - **[mcp-cli](https://github.com/wong2/mcp-cli)** - A CLI inspector for the Model Context Protocol by **[wong2](https://github.com/wong2)** - **[r/mcp](https://www.reddit.com/r/mcp)** – A Reddit community dedicated to MCP by **[Frank Fiegel](https://github.com/punkpeye)** - **[MCP X Community](https://x.com/i/communities/1861891349609603310)** – A X community for MCP by **[Xiaoyi](https://x.com/chxy)** -- **[mcp-manager](https://github.com/zuemcp/manager)** - Simple Web UI to install and manage MCP servers for Claude Desktop by **[Zue](https://github.com/zueai)** +- **[mcp-manager](https://github.com/zueai/mcp-manager)** - Simple Web UI to install and manage MCP servers for Claude Desktop by **[Zue](https://github.com/zueai)** - **[MCPHub](https://github.com/Jeamee/MCPHub-Desktop)** – An Open Source MacOS & Windows GUI Desktop app for discovering, installing and managing MCP servers by **[Jeamee](https://github.com/jeamee)** ## 🚀 Getting Started diff --git a/src/fetch/README.md b/src/fetch/README.md index bc8f0f6136..0e58b3de16 100644 --- a/src/fetch/README.md +++ b/src/fetch/README.md @@ -61,6 +61,19 @@ Add to your Claude settings: ```
+
+Using docker + +```json +"mcpServers": { + "fetch": { + "command": "docker", + "args": ["run", "-i", "--rm", "mcp/fetch"] + } +} +``` +
+
Using pip installation diff --git a/src/git/README.md b/src/git/README.md index d838dd9c00..6fc905f181 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -120,6 +120,19 @@ Add this to your `claude_desktop_config.json`: ```
+
+Using docker + +```json +"mcpServers": { + "git": { + "command": "docker", + "args": ["run", "--rm", "-i", "type=bind,src=/Users/slim,dst=/projects", "mcp/git"] + } +} +``` +
+
Using pip installation diff --git a/src/sentry/README.md b/src/sentry/README.md index aae4456876..4f02bb58c3 100644 --- a/src/sentry/README.md +++ b/src/sentry/README.md @@ -69,6 +69,22 @@ Add this to your `claude_desktop_config.json`:
+ +
+Using docker + +```json +"mcpServers": { + "sentry": { + "command": "docker", + "args": ["run", "-i", "--rm", "mcp/sentry", "--auth-token", "YOUR_SENTRY_TOKEN"] + } +} +``` +
+ +
+ Using pip installation ```json From 066426c3fdff00530b4ebbd2149cac9614f18bc4 Mon Sep 17 00:00:00 2001 From: Jim Clark Date: Thu, 19 Dec 2024 14:00:30 -0800 Subject: [PATCH 13/21] Fix git and brave-search typos in README.md --- src/brave-search/README.md | 2 +- src/git/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/brave-search/README.md b/src/brave-search/README.md index a7c1b47c45..39f735353c 100644 --- a/src/brave-search/README.md +++ b/src/brave-search/README.md @@ -84,7 +84,7 @@ Add this to your `claude_desktop_config.json`: Docker build: ```bash -docker build -t vonwig/brave-search:mcp -f src/brave-search/Dockerfile . +docker build -t mcp/brave-search:latest -f src/brave-search/Dockerfile . ``` ## License diff --git a/src/git/README.md b/src/git/README.md index 6fc905f181..5bd893ccbc 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -127,7 +127,7 @@ Add this to your `claude_desktop_config.json`: "mcpServers": { "git": { "command": "docker", - "args": ["run", "--rm", "-i", "type=bind,src=/Users/slim,dst=/projects", "mcp/git"] + "args": ["run", "--rm", "-i", "--mount", "type=bind,src=/Users/username,dst=/projects", "mcp/git"] } } ``` From e4ef637f954dba86f9b47ed83ede9e9eb6ed5567 Mon Sep 17 00:00:00 2001 From: Jim Clark Date: Thu, 19 Dec 2024 14:21:14 -0800 Subject: [PATCH 14/21] fix indentation --- src/everart/README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/everart/README.md b/src/everart/README.md index bccd594235..57dab4d0af 100644 --- a/src/everart/README.md +++ b/src/everart/README.md @@ -18,11 +18,10 @@ Add to Claude Desktop config: "everart": { "command": "docker", "args": ["run", "-i", "--rm", "-e", "EVERART_API_KEY", "mcp/everart"], - "env": { - "EVERART_API_KEY": "your_key_here" + "env": { + "EVERART_API_KEY": "your_key_here" + } } - }, - } } ``` From 2b0b8afa260c4f75241fed265f8a25aa49f5cb98 Mon Sep 17 00:00:00 2001 From: Jim Clark Date: Thu, 19 Dec 2024 14:34:05 -0800 Subject: [PATCH 15/21] Update src/puppeteer/README.md Co-authored-by: David Soria Parra <167242713+dsp-ant@users.noreply.github.com> --- src/puppeteer/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/puppeteer/README.md b/src/puppeteer/README.md index 375b27cd4a..7c7e81607f 100644 --- a/src/puppeteer/README.md +++ b/src/puppeteer/README.md @@ -67,6 +67,8 @@ Here's the Claude Desktop configuration to use the Puppeter server: ### Docker +**NOTE** The docker implementation will use headless chromium, where as the NPX version will open a browser window. + ```json { "mcpServers": { From 38c88d9ac35c1b2db51b9de98be124d0a0baedd1 Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Thu, 19 Dec 2024 17:54:38 -0500 Subject: [PATCH 16/21] Bump puppeteer bullseye to bookworm --- src/puppeteer/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puppeteer/Dockerfile b/src/puppeteer/Dockerfile index 082b250d8f..d0f58a3aad 100644 --- a/src/puppeteer/Dockerfile +++ b/src/puppeteer/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22-bullseye-slim +FROM node:22-bookworm-slim ENV DEBIAN_FRONTEND noninteractive From f63029468d8c14bb0272f37fa254c605edca15cd Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Thu, 19 Dec 2024 18:24:35 -0500 Subject: [PATCH 17/21] Get gdrive working in Docker --- src/gdrive/Dockerfile | 5 +++++ src/gdrive/README.md | 19 ++++++++++++++++--- src/gdrive/replace_open.sh | 5 +++++ 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 src/gdrive/replace_open.sh diff --git a/src/gdrive/Dockerfile b/src/gdrive/Dockerfile index b7bb2a7685..8a3458f419 100644 --- a/src/gdrive/Dockerfile +++ b/src/gdrive/Dockerfile @@ -16,9 +16,14 @@ WORKDIR /app COPY --from=builder /app/dist /app/dist COPY --from=builder /app/package.json /app/package.json COPY --from=builder /app/package-lock.json /app/package-lock.json +COPY src/gdrive/replace_open.sh /replace_open.sh ENV NODE_ENV=production RUN npm ci --ignore-scripts --omit-dev +RUN sh /replace_open.sh + +RUN rm /replace_open.sh + ENTRYPOINT ["node", "dist/index.js"] \ No newline at end of file diff --git a/src/gdrive/README.md b/src/gdrive/README.md index 56e8cfbebb..bb200dd4dd 100644 --- a/src/gdrive/README.md +++ b/src/gdrive/README.md @@ -31,8 +31,9 @@ The server provides access to Google Drive files: 3. [Configure an OAuth consent screen](https://console.cloud.google.com/apis/credentials/consent) ("internal" is fine for testing) 4. Add OAuth scope `https://www.googleapis.com/auth/drive.readonly` 5. [Create an OAuth Client ID](https://console.cloud.google.com/apis/credentials/oauthclient) for application type "Desktop App" -6. Download the JSON file of your client's OAuth keys -7. Rename the key file to `gcp-oauth.keys.json` and place into the root of this repo (i.e. `servers/gcp-oauth.keys.json`) +6. Add http://localhost:3000/oauth2callback as a redirect URI +7. Download the JSON file of your client's OAuth keys +8. Rename the key file to `gcp-oauth.keys.json` and place into the root of this repo (i.e. `servers/gcp-oauth.keys.json`) Make sure to build the server with either `npm run build` or `npm run watch`. @@ -51,12 +52,24 @@ To integrate this server with the desktop app, add the following to your app's s #### Docker +Authentication: + +Assuming you have completed setting up the OAuth application on Google Cloud, you can now auth the server with the following command, replacing `/path/to/gcp-oauth.keys.json` with the path to your OAuth keys file: + +```bash +docker run -i --rm --mount type=bind,source=/path/to/gcp-oauth.keys.json,target=/gcp-oauth.keys.json -v mcp-gdrive:/gdrive-server -e GDRIVE_OAUTH_PATH=/gcp-oauth.keys.json -e "GDRIVE_CREDENTIALS_PATH=/gdrive-server/credentials.json" -p 3000:3000 mcp/gdrive auth +``` + +The command will print the URL to open in your browser. Open this URL in your browser and complete the authentication process. The credentials will be saved in the `mcp-gdrive` volume. + +Once authenticated, you can use the server in your app's server configuration: + ```json { "mcpServers": { "gdrive": { "command": "docker", - "args": ["run", "-i", "--rm", "--mount", "type=bind,source=/Users/colinmcneil/Desktop/gcp-oauth.keys.json,target=/gcp-oauth.keys.json", "-v", "mcp-gdrive:/gdrive-server", "-e", "GDRIVE_OAUTH_PATH=/gcp-oauth.keys.json", "-e", "GDRIVE_CREDENTIALS_PATH=/gdrive-server/credentials.json", "mcp/gdrive"] + "args": ["run", "-i", "--rm", "-v", "mcp-gdrive:/gdrive-server", "-e", "GDRIVE_CREDENTIALS_PATH=/gdrive-server/credentials.json", "mcp/gdrive"] } } } diff --git a/src/gdrive/replace_open.sh b/src/gdrive/replace_open.sh new file mode 100644 index 0000000000..6727854b8b --- /dev/null +++ b/src/gdrive/replace_open.sh @@ -0,0 +1,5 @@ +#! /bin/bash + +# Basic script to replace opn(authorizeUrl, { wait: false }).then(cp => cp.unref()); with process.stdout.write(`Open this URL in your browser: ${authorizeUrl}`); + +sed -i 's/opn(authorizeUrl, { wait: false }).then(cp => cp.unref());/process.stderr.write(`Open this URL in your browser: ${authorizeUrl}\n`);/' node_modules/@google-cloud/local-auth/build/src/index.js From 4fa1c47b0a1c4435dc9a0800a87394e21f15b652 Mon Sep 17 00:00:00 2001 From: Jim Clark Date: Thu, 19 Dec 2024 16:04:57 -0800 Subject: [PATCH 18/21] Update fetch Docker to not have ux in final stage --- src/fetch/Dockerfile | 15 +++++++++++---- src/git/README.md | 4 +++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/fetch/Dockerfile b/src/fetch/Dockerfile index fae262d1bd..7e8824c471 100644 --- a/src/fetch/Dockerfile +++ b/src/fetch/Dockerfile @@ -1,5 +1,5 @@ # Use a Python image with uv pre-installed -FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS uv # Install the project into `/app` WORKDIR /app @@ -14,16 +14,23 @@ ENV UV_LINK_MODE=copy RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --frozen --no-install-project --no-dev + uv sync --frozen --no-install-project --no-dev --no-editable # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching ADD . /app RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev + uv sync --frozen --no-dev --no-editable + +FROM python:3.12-slim-bookworm + +WORKDIR /app + +COPY --from=uv /root/.local /root/.local +COPY --from=uv --chown=app:app /app/.venv /app/.venv # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" # when running the container, add --db-path and a bind mount to the host's db file -ENTRYPOINT ["uvx" , "mcp-server-fetch"] +ENTRYPOINT ["mcp-server-fetch"] diff --git a/src/git/README.md b/src/git/README.md index 5bd893ccbc..cb22629e1b 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -123,11 +123,13 @@ Add this to your `claude_desktop_config.json`:
Using docker +* Note: replace '/Users/username' with the a path that you want to be accessible by this tool + ```json "mcpServers": { "git": { "command": "docker", - "args": ["run", "--rm", "-i", "--mount", "type=bind,src=/Users/username,dst=/projects", "mcp/git"] + "args": ["run", "--rm", "-i", "--mount", "type=bind,src=/Users/username,dst=/Users/username", "mcp/git"] } } ``` From 621919a9548cab4a83436ccc25ed502bf780fcf8 Mon Sep 17 00:00:00 2001 From: Jim Clark Date: Thu, 19 Dec 2024 17:13:21 -0800 Subject: [PATCH 19/21] Switch to uv-less final stages --- src/git/Dockerfile | 19 +++++++++++++------ src/sentry/Dockerfile | 16 ++++++++++++---- src/sqlite/Dockerfile | 16 ++++++++++++---- src/time/Dockerfile | 15 +++++++++++---- 4 files changed, 48 insertions(+), 18 deletions(-) diff --git a/src/git/Dockerfile b/src/git/Dockerfile index 264962edde..2746d63419 100644 --- a/src/git/Dockerfile +++ b/src/git/Dockerfile @@ -1,5 +1,5 @@ # Use a Python image with uv pre-installed -FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS uv # Install the project into `/app` WORKDIR /app @@ -10,22 +10,29 @@ ENV UV_COMPILE_BYTECODE=1 # Copy from the cache instead of linking since it's a mounted volume ENV UV_LINK_MODE=copy -RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* - # Install the project's dependencies using the lockfile and settings RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --frozen --no-install-project --no-dev + uv sync --frozen --no-install-project --no-dev --no-editable # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching ADD . /app RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev + uv sync --frozen --no-dev --no-editable + +FROM python:3.12-slim-bookworm + +RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +COPY --from=uv /root/.local /root/.local +COPY --from=uv --chown=app:app /app/.venv /app/.venv # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" # when running the container, add --db-path and a bind mount to the host's db file -ENTRYPOINT ["uv" , "run" , "--directory", ".", "mcp-server-git"] +ENTRYPOINT ["mcp-server-git"] diff --git a/src/sentry/Dockerfile b/src/sentry/Dockerfile index 5cd6f22009..a706a15e75 100644 --- a/src/sentry/Dockerfile +++ b/src/sentry/Dockerfile @@ -1,5 +1,5 @@ # Use a Python image with uv pre-installed -FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS uv # Install the project into `/app` WORKDIR /app @@ -14,16 +14,24 @@ ENV UV_LINK_MODE=copy RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --frozen --no-install-project --no-dev + uv sync --frozen --no-install-project --no-dev --no-editable # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching ADD . /app RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev + uv sync --frozen --no-dev --no-editable + +FROM python:3.12-slim-bookworm + +WORKDIR /app + +COPY --from=uv /root/.local /root/.local +COPY --from=uv --chown=app:app /app/.venv /app/.venv # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" # when running the container, add --db-path and a bind mount to the host's db file -ENTRYPOINT ["uv" , "run" , "--directory", ".", "mcp-server-sentry"] +ENTRYPOINT ["mcp-server-sentry"] + diff --git a/src/sqlite/Dockerfile b/src/sqlite/Dockerfile index 8189a3d6a3..2edc34b0e1 100644 --- a/src/sqlite/Dockerfile +++ b/src/sqlite/Dockerfile @@ -1,5 +1,5 @@ # Use a Python image with uv pre-installed -FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS uv # Install the project into `/app` WORKDIR /app @@ -14,16 +14,24 @@ ENV UV_LINK_MODE=copy RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --frozen --no-install-project --no-dev + uv sync --frozen --no-install-project --no-dev --no-editable # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching ADD . /app RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev + uv sync --frozen --no-dev --no-editable + +FROM python:3.12-slim-bookworm + +WORKDIR /app + +COPY --from=uv /root/.local /root/.local +COPY --from=uv --chown=app:app /app/.venv /app/.venv # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" # when running the container, add --db-path and a bind mount to the host's db file -ENTRYPOINT ["uv" , "run" , "--directory", ".", "mcp-server-sqlite"] +ENTRYPOINT ["mcp-server-sqlite"] + diff --git a/src/time/Dockerfile b/src/time/Dockerfile index b45b389dd0..bd62ea84a4 100644 --- a/src/time/Dockerfile +++ b/src/time/Dockerfile @@ -1,5 +1,5 @@ # Use a Python image with uv pre-installed -FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS uv # Install the project into `/app` WORKDIR /app @@ -14,16 +14,23 @@ ENV UV_LINK_MODE=copy RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ - uv sync --frozen --no-install-project --no-dev + uv sync --frozen --no-install-project --no-dev --no-editable # Then, add the rest of the project source code and install it # Installing separately from its dependencies allows optimal layer caching ADD . /app RUN --mount=type=cache,target=/root/.cache/uv \ - uv sync --frozen --no-dev + uv sync --frozen --no-dev --no-editable + +FROM python:3.12-slim-bookworm + +WORKDIR /app + +COPY --from=uv /root/.local /root/.local +COPY --from=uv --chown=app:app /app/.venv /app/.venv # Place executables in the environment at the front of the path ENV PATH="/app/.venv/bin:$PATH" # when running the container, add --db-path and a bind mount to the host's db file -ENTRYPOINT ["uv" , "run" , "--directory", ".", "mcp-server-time"] +ENTRYPOINT ["mcp-server-time"] From 071f41df53b05de7c89d53719d474c8518e278dc Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Fri, 20 Dec 2024 11:58:39 -0500 Subject: [PATCH 20/21] Remove step 6 for gdrive --- src/gdrive/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gdrive/README.md b/src/gdrive/README.md index bb200dd4dd..2d153815f8 100644 --- a/src/gdrive/README.md +++ b/src/gdrive/README.md @@ -31,9 +31,8 @@ The server provides access to Google Drive files: 3. [Configure an OAuth consent screen](https://console.cloud.google.com/apis/credentials/consent) ("internal" is fine for testing) 4. Add OAuth scope `https://www.googleapis.com/auth/drive.readonly` 5. [Create an OAuth Client ID](https://console.cloud.google.com/apis/credentials/oauthclient) for application type "Desktop App" -6. Add http://localhost:3000/oauth2callback as a redirect URI -7. Download the JSON file of your client's OAuth keys -8. Rename the key file to `gcp-oauth.keys.json` and place into the root of this repo (i.e. `servers/gcp-oauth.keys.json`) +6. Download the JSON file of your client's OAuth keys +7. Rename the key file to `gcp-oauth.keys.json` and place into the root of this repo (i.e. `servers/gcp-oauth.keys.json`) Make sure to build the server with either `npm run build` or `npm run watch`. From ddd4860452a769e324c4c8e2ae853fc507045275 Mon Sep 17 00:00:00 2001 From: colinmcneil Date: Fri, 20 Dec 2024 12:27:42 -0500 Subject: [PATCH 21/21] Emit gdrive log on stderr to prevent rpc errors in claude desktop --- src/gdrive/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gdrive/index.ts b/src/gdrive/index.ts index 4a8e954c05..575c350c60 100644 --- a/src/gdrive/index.ts +++ b/src/gdrive/index.ts @@ -206,7 +206,7 @@ async function loadCredentialsAndRunServer() { auth.setCredentials(credentials); google.options({ auth }); - console.log("Credentials loaded. Starting server."); + console.error("Credentials loaded. Starting server."); const transport = new StdioServerTransport(); await server.connect(transport); }