mcp-text-editor 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,69 @@
1
+ name: Publish
2
+ on:
3
+ push:
4
+ tags:
5
+ - "v*"
6
+ strategy:
7
+ matrix:
8
+ python-version: ["3.11"]
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Set up Python ${{ matrix.python-version }}
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+
21
+ - name: Install uv
22
+ run: |
23
+ python -m pip install --upgrade pip
24
+ pip install uv
25
+
26
+ - name: Install dev/test dependencies
27
+ run: |
28
+ pip install -e ".[dev]"
29
+ pip install -e ".[test]"
30
+
31
+ - name: Run tests
32
+ run: |
33
+ make check
34
+
35
+ publish:
36
+ needs: test
37
+ runs-on: ubuntu-latest
38
+ environment: release
39
+ permissions:
40
+ id-token: write
41
+
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+
45
+ - name: Update version from tag
46
+ run: |
47
+ # Strip 'v' prefix from tag and update version.py
48
+ VERSION=${GITHUB_REF#refs/tags/v}
49
+ echo "__version__ = \"${VERSION}\"" > src/mcp_text_editor/version.py
50
+
51
+ - name: Set up Python ${{ matrix.python-version }}
52
+ uses: actions/setup-python@v5
53
+ with:
54
+ python-version: ${{ matrix.python-version }}
55
+
56
+ - name: Install uv
57
+ run: |
58
+ python -m pip install --upgrade pip
59
+ pip install uv
60
+
61
+ - name: Build package
62
+ run: |
63
+ uv build
64
+
65
+ - name: Publish to PyPI
66
+ env:
67
+ PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
68
+ run: |
69
+ uv publish --token $PYPI_TOKEN
@@ -0,0 +1,45 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches: [main, develop]
6
+ pull_request:
7
+ branches: [main, develop]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.11"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install uv
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install uv
28
+
29
+ - name: Install dev/test dependencies
30
+ run: |
31
+ pip install -e ".[dev]"
32
+ pip install -e ".[test]"
33
+
34
+ - name: Run lint and typecheck
35
+ run: |
36
+ make lint typecheck
37
+
38
+ - name: Run tests with coverage
39
+ run: |
40
+ pytest --cov --cov-report=xml
41
+
42
+ - name: Upload coverage to Codecov
43
+ uses: codecov/codecov-action@v5
44
+ with:
45
+ token: ${{ secrets.CODECOV_TOKEN }}
@@ -0,0 +1,48 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+ MANIFEST
23
+
24
+ # Virtual Environment
25
+ .env
26
+ .venv
27
+ env/
28
+ venv/
29
+ ENV/
30
+
31
+ # IDE
32
+ .idea/
33
+ .vscode/
34
+ *.swp
35
+ *.swo
36
+
37
+ # Testing
38
+ .coverage
39
+ .coverage.*
40
+ .pytest_cache/
41
+ htmlcov/
42
+
43
+ # Distribution
44
+ *.tar.gz
45
+
46
+ # Logs
47
+ *.log
48
+ prompt.md
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,27 @@
1
+ .PHONY: test format lint typecheck check coverage
2
+ .DEFAULT_GOAL := all
3
+
4
+ test:
5
+ pytest
6
+
7
+ coverage:
8
+ pytest --cov=mcp_text_editor --cov-report=term-missing
9
+
10
+ format:
11
+ black src tests
12
+ isort src tests
13
+ ruff check --fix src tests
14
+
15
+
16
+ lint:
17
+ black --check src tests
18
+ isort --check src tests
19
+ ruff check src tests
20
+
21
+ typecheck:
22
+ mypy src tests
23
+
24
+ # Run all checks required before pushing
25
+ check: lint typecheck test
26
+ fix: check format
27
+ all: format check
@@ -0,0 +1,434 @@
1
+ Metadata-Version: 2.3
2
+ Name: mcp-text-editor
3
+ Version: 1.0.0
4
+ Summary: MCP Text Editor Server - Edit text files via MCP protocol
5
+ Author: tumf
6
+ License: MIT
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: asyncio>=3.4.3
9
+ Requires-Dist: mcp>=1.1.0
10
+ Provides-Extra: dev
11
+ Requires-Dist: black>=23.3.0; extra == 'dev'
12
+ Requires-Dist: isort>=5.12.0; extra == 'dev'
13
+ Requires-Dist: mypy>=1.2.0; extra == 'dev'
14
+ Requires-Dist: pre-commit>=3.2.2; extra == 'dev'
15
+ Requires-Dist: ruff>=0.0.262; extra == 'dev'
16
+ Provides-Extra: test
17
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'test'
18
+ Requires-Dist: pytest-cov>=6.0.0; extra == 'test'
19
+ Requires-Dist: pytest-env>=1.1.0; extra == 'test'
20
+ Requires-Dist: pytest-mock>=3.12.0; extra == 'test'
21
+ Requires-Dist: pytest>=8.3.4; extra == 'test'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # MCP Text Editor Server
25
+
26
+ [![codecov](https://codecov.io/gh/tumf/mcp-text-editor/graph/badge.svg?token=52D51U0ZUR)](https://codecov.io/gh/tumf/mcp-text-editor)
27
+
28
+ A Model Context Protocol (MCP) server that provides text file editing capabilities through a standardized API.
29
+
30
+ ## Overview
31
+
32
+ MCP Text Editor Server is designed to facilitate safe and efficient text file operations in a client-server architecture. It implements the Model Context Protocol, ensuring reliable file editing with robust conflict detection and resolution. This 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.
33
+
34
+ ### Key Benefits
35
+
36
+ - Safe concurrent editing with hash-based validation
37
+ - Efficient partial file access with line-range specifications
38
+ - Atomic multi-file operations
39
+ - Robust error handling and recovery mechanisms
40
+
41
+
42
+ ## Features
43
+
44
+ - Get text file contents with line range specification
45
+ - Read multiple ranges from multiple files in a single operation
46
+ - Edit text file contents with conflict detection
47
+ - Support for multiple file operations
48
+ - Proper handling of concurrent edits with hash-based validation
49
+ - Line-based patch application with correct handling of line number shifts
50
+ - Robust error handling and validation
51
+ - Memory-efficient processing of large files
52
+
53
+
54
+ ## Requirements
55
+
56
+ - Python 3.11 or higher
57
+ - POSIX-compliant operating system (Linux, macOS, etc.) or Windows
58
+ - Sufficient disk space for text file operations
59
+ - File system permissions for read/write operations
60
+
61
+
62
+ 1. Install Python 3.11+
63
+
64
+ ```bash
65
+ pyenv install 3.11.6
66
+ pyenv local 3.11.6
67
+ ```
68
+
69
+ 2. Install uv (recommended) or pip
70
+
71
+ ```bash
72
+ curl -LsSf https://astral.sh/uv/install.sh | sh
73
+ ```
74
+
75
+ 3. Create virtual environment and install dependencies
76
+
77
+ ```bash
78
+ uv venv
79
+ source .venv/bin/activate # On Windows: .venv\Scripts\activate
80
+ uv pip install -e ".[dev]"
81
+ ```
82
+
83
+ ## Installation
84
+
85
+ ```bash
86
+ pip install -e .
87
+ ```
88
+
89
+ For development:
90
+
91
+ ```bash
92
+ pip install -e ".[dev]"
93
+ ```
94
+
95
+ ## Usage
96
+
97
+ Start the server:
98
+
99
+ ```bash
100
+ python -m mcp_text_editor
101
+ ```
102
+
103
+ ### MCP Tools
104
+
105
+ The server provides two main tools:
106
+
107
+ #### get_text_file_contents
108
+
109
+ Get the contents of one or more text files with line range specification.
110
+
111
+ **Single Range Request:**
112
+
113
+ ```json
114
+ {
115
+ "file_path": "path/to/file.txt",
116
+ "line_start": 1,
117
+ "line_end": 10
118
+ }
119
+ ```
120
+
121
+ **Multiple Ranges Request:**
122
+
123
+ ```json
124
+ {
125
+ "files": [
126
+ {
127
+ "file_path": "file1.txt",
128
+ "ranges": [
129
+ {"start": 1, "end": 10},
130
+ {"start": 20, "end": 30}
131
+ ]
132
+ },
133
+ {
134
+ "file_path": "file2.txt",
135
+ "ranges": [
136
+ {"start": 5, "end": 15}
137
+ ]
138
+ }
139
+ ]
140
+ }
141
+ ```
142
+
143
+ Parameters:
144
+ - `file_path`: Path to the text file
145
+ - `line_start`/`start`: Line number to start from (1-based)
146
+ - `line_end`/`end`: Line number to end at (inclusive, null for end of file)
147
+
148
+ **Single Range Response:**
149
+
150
+ ```json
151
+ {
152
+ "contents": "File contents",
153
+ "line_start": 1,
154
+ "line_end": 10,
155
+ "hash": "sha256-hash-of-contents",
156
+ "file_lines": 50,
157
+ "file_size": 1024
158
+ }
159
+ ```
160
+
161
+ **Multiple Ranges Response:**
162
+
163
+ ```json
164
+ {
165
+ "file1.txt": [
166
+ {
167
+ "content": "Lines 1-10 content",
168
+ "start_line": 1,
169
+ "end_line": 10,
170
+ "hash": "sha256-hash-1",
171
+ "total_lines": 50,
172
+ "content_size": 512
173
+ },
174
+ {
175
+ "content": "Lines 20-30 content",
176
+ "start_line": 20,
177
+ "end_line": 30,
178
+ "hash": "sha256-hash-2",
179
+ "total_lines": 50,
180
+ "content_size": 512
181
+ }
182
+ ],
183
+ "file2.txt": [
184
+ {
185
+ "content": "Lines 5-15 content",
186
+ "start_line": 5,
187
+ "end_line": 15,
188
+ "hash": "sha256-hash-3",
189
+ "total_lines": 30,
190
+ "content_size": 256
191
+ }
192
+ ]
193
+ }
194
+ ```
195
+
196
+ #### edit_text_file_contents
197
+
198
+ Edit text file contents with conflict detection. Supports editing multiple files in a single operation.
199
+
200
+ **Request Format:**
201
+
202
+ ```json
203
+ {
204
+ "files": [
205
+ {
206
+ "path": "file1.txt",
207
+ "hash": "sha256-hash-from-get-contents",
208
+ "patches": [
209
+ {
210
+ "line_start": 5,
211
+ "line_end": 8,
212
+ "contents": "New content for lines 5-8\n"
213
+ },
214
+ {
215
+ "line_start": 15,
216
+ "line_end": 15,
217
+ "contents": "Single line replacement\n"
218
+ }
219
+ ]
220
+ },
221
+ {
222
+ "path": "file2.txt",
223
+ "hash": "sha256-hash-from-get-contents",
224
+ "patches": [
225
+ {
226
+ "line_start": 1,
227
+ "line_end": 3,
228
+ "contents": "Replace first three lines\n"
229
+ }
230
+ ]
231
+ }
232
+ ]
233
+ }
234
+ ```
235
+
236
+ Important Notes:
237
+ 1. Always get the current hash using get_text_file_contents before editing
238
+ 2. Patches are applied from bottom to top to handle line number shifts correctly
239
+ 3. Patches must not overlap within the same file
240
+ 4. Line numbers are 1-based
241
+ 5. If original content ends with newline, ensure patch content also ends with newline
242
+
243
+ **Success Response:**
244
+
245
+ ```json
246
+ {
247
+ "file1.txt": {
248
+ "result": "ok",
249
+ "hash": "sha256-hash-of-new-contents"
250
+ },
251
+ "file2.txt": {
252
+ "result": "ok",
253
+ "hash": "sha256-hash-of-new-contents"
254
+ }
255
+ }
256
+ ```
257
+
258
+ **Error Response:**
259
+
260
+ ```json
261
+ {
262
+ "file1.txt": {
263
+ "result": "error",
264
+ "reason": "File not found",
265
+ "hash": null
266
+ },
267
+ "file2.txt": {
268
+ "result": "error",
269
+ "reason": "Content hash mismatch - file was modified",
270
+ "hash": "current-hash",
271
+ "content": "Current file content"
272
+ }
273
+ }
274
+ ```
275
+
276
+ ### Common Usage Pattern
277
+
278
+ 1. Get current content and hash:
279
+
280
+ ```python
281
+ contents = await get_text_file_contents({
282
+ "files": [
283
+ {
284
+ "file_path": "file.txt",
285
+ "ranges": [{"start": 1, "end": null}] # Read entire file
286
+ }
287
+ ]
288
+ })
289
+ ```
290
+
291
+ 2. Edit file content:
292
+
293
+ ```python
294
+ result = await edit_text_file_contents({
295
+ "files": [
296
+ {
297
+ "path": "file.txt",
298
+ "hash": contents["file.txt"][0]["hash"],
299
+ "patches": [
300
+ {
301
+ "line_start": 5,
302
+ "line_end": 8,
303
+ "contents": "New content\n"
304
+ }
305
+ ]
306
+ }
307
+ ]
308
+ })
309
+ ```
310
+
311
+ 3. Handle conflicts:
312
+
313
+ ```python
314
+ if result["file.txt"]["result"] == "error":
315
+ if "hash mismatch" in result["file.txt"]["reason"]:
316
+ # File was modified by another process
317
+ # Get new content and retry
318
+ pass
319
+ ```
320
+
321
+ ### Error Handling
322
+
323
+ The server handles various error cases:
324
+ - File not found
325
+ - Permission errors
326
+ - Hash mismatches (concurrent edit detection)
327
+ - Invalid patch ranges
328
+ - Overlapping patches
329
+ - Line number out of bounds
330
+
331
+ ## Security Considerations
332
+
333
+ - File Path Validation: The server validates all file paths to prevent directory traversal attacks
334
+ - Access Control: Proper file system permissions should be set to restrict access to authorized directories
335
+ - Hash Validation: All file modifications are validated using SHA-256 hashes to prevent race conditions
336
+ - Input Sanitization: All user inputs are properly sanitized and validated
337
+ - Error Handling: Sensitive information is not exposed in error messages
338
+
339
+ ## Troubleshooting
340
+
341
+ ### Common Issues
342
+
343
+ 1. Permission Denied
344
+ - Check file and directory permissions
345
+ - Ensure the server process has necessary read/write access
346
+
347
+ 2. Hash Mismatch Errors
348
+ - The file was modified by another process
349
+ - Fetch latest content and retry the operation
350
+
351
+ 3. Connection Issues
352
+ - Verify the server is running and accessible
353
+ - Check network configuration and firewall settings
354
+
355
+ 4. Performance Issues
356
+ - Consider using smaller line ranges for large files
357
+ - Monitor system resources (memory, disk space)
358
+
359
+ ## Development
360
+
361
+ ### Setup
362
+
363
+ 1. Clone the repository
364
+ 2. Create and activate a Python virtual environment
365
+ 3. Install development dependencies: `pip install -e ".[dev]"`
366
+ 4. Run tests: `pytest`
367
+
368
+ ### Code Quality Tools
369
+
370
+ - Ruff for linting
371
+ - Black for code formatting
372
+ - isort for import sorting
373
+ - mypy for type checking
374
+ - pytest-cov for test coverage
375
+
376
+ ### Testing
377
+
378
+ Tests are located in the `tests` directory and can be run with pytest:
379
+
380
+ ```bash
381
+ # Run all tests
382
+ pytest
383
+
384
+ # Run tests with coverage report
385
+ pytest --cov=mcp_text_editor --cov-report=term-missing
386
+
387
+ # Run specific test file
388
+ pytest tests/test_text_editor.py -v
389
+ ```
390
+
391
+ Current test coverage: 90%
392
+
393
+ ### Project Structure
394
+
395
+ ```
396
+ mcp-text-editor/
397
+ ├── mcp_text_editor/
398
+ │ ├── __init__.py
399
+ │ ├── __main__.py # Entry point
400
+ │ ├── models.py # Data models
401
+ │ ├── server.py # MCP Server implementation
402
+ │ ├── service.py # Core service logic
403
+ │ └── text_editor.py # Text editor functionality
404
+ ├── tests/ # Test files
405
+ └── pyproject.toml # Project configuration
406
+ ```
407
+
408
+ ## License
409
+
410
+ MIT
411
+
412
+ ## Contributing
413
+
414
+ 1. Fork the repository
415
+ 2. Create a feature branch
416
+ 3. Make your changes
417
+ 4. Run tests and code quality checks
418
+ 5. Submit a pull request
419
+
420
+ ### Type Hints
421
+
422
+ This project uses Python type hints throughout the codebase. Please ensure any contributions maintain this.
423
+
424
+ ### Error Handling
425
+
426
+ All error cases should be handled appropriately and return meaningful error messages. The server should never crash due to invalid input or file operations.
427
+
428
+ ### Testing
429
+
430
+ New features should include appropriate tests. Try to maintain or improve the current test coverage.
431
+
432
+ ### Code Style
433
+
434
+ All code should be formatted with Black and pass Ruff linting. Import sorting should be handled by isort.