Skip to content

adds support to run tool from docker #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Use a Python image with uv pre-installed
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS uv

# 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 --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 --no-editable

FROM python:3.13-slim-bookworm

WORKDIR /app

# COPY --from=uv /root/.local /root/.local
COPY --from=uv --chown=app:app /app/.venv /app/.venv

# Copy the source code
COPY --from=uv --chown=app:app /app/src /app/src

# Place executables in the environment at the front of the path
ENV PATH="/app/.venv/bin:$PATH"

# Run mcp server
ENTRYPOINT ["python", "src/mcp_text_editor/server.py"]
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ code ~/Library/Application\ Support/Claude/claude_desktop_config.json
}
```

or with docker:
```json
{
"mcpServers": {
"text-editor": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"--mount",
"type=bind,src=/some/path/src,dst=/some/path/dst",
"mcp/text-editor"
]
}
}
}
```

## Overview

MCP Text Editor Server is designed to facilitate safe and efficient line-based text file operations in a client-server architecture. It implements the Model Context Protocol, ensuring reliable file editing with robust conflict detection and resolution. The line-oriented approach makes it ideal for applications requiring synchronized file access, such as collaborative editing tools, automated text processing systems, or any scenario where multiple processes need to modify text files safely. The partial file access capability is particularly valuable for LLM-based tools, as it helps reduce token consumption by loading only the necessary portions of files.
Expand Down Expand Up @@ -98,6 +117,12 @@ npx -y @smithery/cli install mcp-text-editor --client claude
pip install -e .
```

### Docker Installation
```
docker build --network=host -t mcp/text-editor .
```


For development:

```bash
Expand All @@ -112,6 +137,18 @@ Start the server:
python -m mcp_text_editor
```

Start the server with docker:

```bash
docker run -i --rm --mount "type=bind,src=/some/path/src,dst=/some/path/dst" mcp/text-editor
```

with inspector:

```bash
npx @modelcontextprotocol/inspector docker run -i --rm --mount "type=bind,src=/some/path/src,dst=/some/path/dst" mcp/text-editor
```

### MCP Tools

The server provides two main tools:
Expand Down
2 changes: 1 addition & 1 deletion src/mcp_text_editor/handlers/append_text_file_contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from mcp.types import TextContent, Tool

from .base import BaseHandler
from mcp_text_editor.handlers.base import BaseHandler

logger = logging.getLogger("mcp-text-editor")

Expand Down
2 changes: 1 addition & 1 deletion src/mcp_text_editor/handlers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from mcp.types import TextContent, Tool

from ..text_editor import TextEditor
from mcp_text_editor.text_editor import TextEditor


class BaseHandler:
Expand Down
2 changes: 1 addition & 1 deletion src/mcp_text_editor/handlers/create_text_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from mcp.types import TextContent, Tool

from .base import BaseHandler
from mcp_text_editor.handlers.base import BaseHandler

logger = logging.getLogger("mcp-text-editor")

Expand Down
4 changes: 2 additions & 2 deletions src/mcp_text_editor/handlers/delete_text_file_contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

from mcp.types import TextContent, Tool

from ..models import DeleteTextFileContentsRequest, FileRange
from .base import BaseHandler
from mcp_text_editor.handlers.base import BaseHandler
from mcp_text_editor.models import DeleteTextFileContentsRequest, FileRange

logger = logging.getLogger("mcp-text-editor")

Expand Down
2 changes: 1 addition & 1 deletion src/mcp_text_editor/handlers/get_text_file_contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from mcp.types import TextContent, Tool

from .base import BaseHandler
from mcp_text_editor.handlers.base import BaseHandler


class GetTextFileContentsHandler(BaseHandler):
Expand Down
2 changes: 1 addition & 1 deletion src/mcp_text_editor/handlers/insert_text_file_contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from mcp.types import TextContent, Tool

from .base import BaseHandler
from mcp_text_editor.handlers.base import BaseHandler

logger = logging.getLogger("mcp-text-editor")

Expand Down
2 changes: 1 addition & 1 deletion src/mcp_text_editor/handlers/patch_text_file_contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from mcp.types import TextContent, Tool

from .base import BaseHandler
from mcp_text_editor.handlers.base import BaseHandler

logger = logging.getLogger("mcp-text-editor")

Expand Down
9 changes: 7 additions & 2 deletions src/mcp_text_editor/server.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""MCP Text Editor Server implementation."""

import asyncio
import logging
import traceback
from collections.abc import Sequence
Expand All @@ -8,15 +9,15 @@
from mcp.server import Server
from mcp.types import TextContent, Tool

from .handlers import (
from mcp_text_editor.handlers import (
AppendTextFileContentsHandler,
CreateTextFileHandler,
DeleteTextFileContentsHandler,
GetTextFileContentsHandler,
InsertTextFileContentsHandler,
PatchTextFileContentsHandler,
)
from .version import __version__
from mcp_text_editor.version import __version__

# Configure logging
logging.basicConfig(level=logging.INFO)
Expand Down Expand Up @@ -88,3 +89,7 @@ async def main() -> None:
except Exception as e:
logger.error(f"Server error: {str(e)}")
raise


if __name__ == "__main__":
asyncio.run(main())
2 changes: 1 addition & 1 deletion src/mcp_text_editor/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import hashlib
from typing import Dict, List, Optional, Tuple

from .models import (
from mcp_text_editor.models import (
DeleteTextFileContentsRequest,
EditFileOperation,
EditPatch,
Expand Down
4 changes: 2 additions & 2 deletions src/mcp_text_editor/text_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import os
from typing import Any, Dict, List, Optional, Tuple

from .models import DeleteTextFileContentsRequest, EditPatch, FileRanges
from .service import TextEditorService
from mcp_text_editor.models import DeleteTextFileContentsRequest, EditPatch, FileRanges
from mcp_text_editor.service import TextEditorService

logger = logging.getLogger(__name__)

Expand Down