mcp-server-code-assist 0.1.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. mcp_server_code_assist-0.1.0/.gitignore +3 -0
  2. mcp_server_code_assist-0.1.0/Dockerfile +27 -0
  3. mcp_server_code_assist-0.1.0/License +7 -0
  4. mcp_server_code_assist-0.1.0/PKG-INFO +11 -0
  5. mcp_server_code_assist-0.1.0/README.md +125 -0
  6. mcp_server_code_assist-0.1.0/calude_prompt.txt +8 -0
  7. mcp_server_code_assist-0.1.0/plan.md +88 -0
  8. mcp_server_code_assist-0.1.0/pyproject.toml +25 -0
  9. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/__init__.py +24 -0
  10. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/__main__.py +3 -0
  11. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/schema.xsd +28 -0
  12. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/server.py +240 -0
  13. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/tools/__init__.py +0 -0
  14. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/tools/file_tools.py +220 -0
  15. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/tools/git_functions.py +25 -0
  16. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/tools/invoke.py +7 -0
  17. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/tools/models.py +48 -0
  18. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/tools/repository_tools.py +76 -0
  19. mcp_server_code_assist-0.1.0/src/mcp_server_code_assist/xml_parser.py +48 -0
  20. mcp_server_code_assist-0.1.0/tests/__init__.py +0 -0
  21. mcp_server_code_assist-0.1.0/tests/test_file_operations.py +150 -0
  22. mcp_server_code_assist-0.1.0/tests/test_repository_tools.py +68 -0
  23. mcp_server_code_assist-0.1.0/tests/test_server.py +79 -0
  24. mcp_server_code_assist-0.1.0/tests/test_tools.py +86 -0
  25. mcp_server_code_assist-0.1.0/tests/test_xml_parser.py +40 -0
  26. mcp_server_code_assist-0.1.0/uv.lock +217 -0
@@ -0,0 +1,3 @@
1
+ __pycache__
2
+ .venv/
3
+ venv/
@@ -0,0 +1,27 @@
1
+ # Use a Python image with uv pre-installed
2
+ FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS uv
3
+
4
+ WORKDIR /app
5
+
6
+ ENV UV_COMPILE_BYTECODE=1
7
+ ENV UV_LINK_MODE=copy
8
+
9
+ RUN --mount=type=cache,target=/root/.cache/uv \
10
+ --mount=type=bind,source=uv.lock,target=uv.lock \
11
+ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
12
+ uv sync --frozen --no-install-project --no-dev --no-editable
13
+
14
+ ADD . /app
15
+ RUN --mount=type=cache,target=/root/.cache/uv \
16
+ uv sync --frozen --no-dev --no-editable
17
+
18
+ FROM python:3.12-slim-bookworm
19
+
20
+ WORKDIR /app
21
+
22
+ COPY --from=uv /root/.local /root/.local
23
+ COPY --from=uv --chown=app:app /app/.venv /app/.venv
24
+
25
+ ENV PATH="/app/.venv/bin:$PATH"
26
+
27
+ ENTRYPOINT ["mcp-server-code-assist"]
@@ -0,0 +1,7 @@
1
+ Copyright 2025 Abhishek Bhakat
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-server-code-assist
3
+ Version: 0.1.0
4
+ Summary: MCP Code Assist Server
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: aiofiles>=24.0.0
7
+ Requires-Dist: gitpython>=3.1.40
8
+ Requires-Dist: pydantic>=2.0.0
9
+ Provides-Extra: test
10
+ Requires-Dist: pytest-asyncio>=0.25.0; extra == 'test'
11
+ Requires-Dist: pytest>=8.0.0; extra == 'test'
@@ -0,0 +1,125 @@
1
+ # mcp-server-code-assist: A Code Assistant MCP Server
2
+
3
+ ## Overview
4
+
5
+ A Model Context Protocol server for code modification and generation. This server provides tools to create, modify, and delete code via Large Language Models.
6
+
7
+ ### Tools
8
+
9
+ 1. `create`
10
+ - Creates new files
11
+ - Input: XML instruction with path and content
12
+ - Returns: Confirmation of file creation
13
+
14
+ 2. `modify`
15
+ - Modifies existing files with search/replace
16
+ - Input: XML instruction with path, search pattern, and new content
17
+ - Returns: Diff of changes
18
+
19
+ 3. `rewrite`
20
+ - Completely rewrites a file
21
+ - Input: XML instruction with path and new content
22
+ - Returns: Confirmation of rewrite
23
+
24
+ 4. `delete`
25
+ - Removes files
26
+ - Input: XML instruction with path
27
+ - Returns: Confirmation of deletion
28
+
29
+ ### XML Format
30
+
31
+ ```xml
32
+ <Plan>
33
+ Describe approach and reasoning
34
+ </Plan>
35
+
36
+ <file path="/path/to/file" action="create|modify|rewrite|delete">
37
+ <change>
38
+ <description>What this change does</description>
39
+ <search>
40
+ ===
41
+ Original code for modification
42
+ ===
43
+ </search>
44
+ <content>
45
+ ===
46
+ New or modified code
47
+ ===
48
+ </content>
49
+ </change>
50
+ </file>
51
+ ```
52
+
53
+ ## Installation
54
+
55
+ ### Using uv (recommended)
56
+
57
+ ```bash
58
+ uvx mcp-server-code-assist
59
+ ```
60
+
61
+ ### Using pip
62
+
63
+ ```bash
64
+ pip install mcp-server-code-assist
65
+ python -m mcp_server_code_assist
66
+ ```
67
+
68
+ ## Configuration
69
+
70
+ ### Usage with Claude Desktop
71
+
72
+ <details>
73
+ <summary>Using uvx</summary>
74
+
75
+ ```json
76
+ "mcpServers": {
77
+ "code-assist": {
78
+ "command": "uvx",
79
+ "args": ["mcp-server-code-assist"]
80
+ }
81
+ }
82
+ ```
83
+ </details>
84
+
85
+ <details>
86
+ <summary>Using docker</summary>
87
+
88
+ ```json
89
+ "mcpServers": {
90
+ "code-assist": {
91
+ "command": "docker",
92
+ "args": ["run", "--rm", "-i", "--mount", "type=bind,src=/Users/username,dst=/Users/username", "mcp/code-assist"]
93
+ }
94
+ }
95
+ ```
96
+ </details>
97
+
98
+ ### Usage with Zed
99
+
100
+ Add to settings.json:
101
+
102
+ ```json
103
+ "context_servers": {
104
+ "mcp-server-code-assist": {
105
+ "command": {
106
+ "path": "uvx",
107
+ "args": ["mcp-server-code-assist"]
108
+ }
109
+ }
110
+ },
111
+ ```
112
+
113
+ ## Development
114
+
115
+ ```bash
116
+ cd src/code-assist
117
+ uvx mcp-server-code-assist
118
+
119
+ # For docker:
120
+ docker build -t mcp/code-assist .
121
+ ```
122
+
123
+ ## License
124
+
125
+ MIT License. See LICENSE file for details.
@@ -0,0 +1,8 @@
1
+ Project: MCP Code Assist Server
2
+ Location: /Volumes/Passport616/AI/MCP/src/code-assist
3
+ Branch: code-assist
4
+
5
+ Claude, let's continue working on our MCP Code Assist Server. Please:
6
+ 1. Read /Volumes/Passport616/AI/MCP/src/code-assist/plan.md
7
+ 2. Show me what's done and what's next
8
+ 3. Let's complete phase 1 properly
@@ -0,0 +1,88 @@
1
+ # Code Assist MCP Server Implementation Plan
2
+
3
+ ## Project Setup
4
+ - [x] Basic file structure
5
+ - [x] pyproject.toml with dependencies
6
+ - [x] Dockerfile with UV support
7
+ - [x] README.md with usage instructions
8
+ - [x] LICENSE file (MIT)
9
+ - [x] Source package structure
10
+ - [x] __main__.py and __init__.py
11
+ - [x] Tools module structure
12
+
13
+ ## Core Components Implementation
14
+ - [x] XML Parser
15
+ - [x] Add XML schema validation
16
+ - [x] Implement parse/generate methods
17
+ - [x] Add tests
18
+
19
+ - [x] File Tools
20
+ - [x] create function
21
+ - [x] delete function
22
+ - [x] modify with search/replace
23
+ - [x] rewrite function
24
+ - [x] diff generation
25
+ - [x] directory tree with gitignore
26
+ - [x] file search
27
+ - [x] file operations tests
28
+
29
+ - [x] Git Operations
30
+ - [x] Repository tools implementation
31
+ - [x] GitPython integration
32
+ - [x] Status/Diff/Log operations
33
+ - [x] Add/Commit operations
34
+ - [x] Branch operations
35
+ - [x] Tests for git operations
36
+
37
+ - [ ] Server
38
+ - [ ] OpenRouter integration
39
+ - [ ] Command line interface
40
+ - [ ] XML instruction processing
41
+ - [x] Basic request handlers
42
+ - [x] Error handling
43
+ - [x] Request validation
44
+ - [x] Tests for file operations
45
+
46
+ ## Testing Infrastructure
47
+ - [x] Unit test suite setup
48
+ - [x] Integration test cases
49
+ - [x] Fixtures and test data
50
+ - [x] GitPython test fixtures
51
+
52
+ ## Documentation
53
+ - [ ] API documentation
54
+ - [ ] Example XML files
55
+ - [ ] Configuration examples
56
+ - [x] Git operations guide
57
+
58
+ ## System Design Challenges
59
+
60
+ ### Context Length Limitation
61
+ Problem: LLMs have limited context length ("memory"). Multiple file changes or complex refactoring can exceed this limit.
62
+
63
+ Proposed Solutions:
64
+ - Make operations idempotent (retryable without side effects)
65
+ - Break large changes into atomic, self-contained operations
66
+ - Use git commits as checkpoints
67
+ - Store intermediate state in temporary files
68
+ - Design instruction format to be resumable
69
+
70
+ ## Current Task
71
+ Phase 1: Read-only operations
72
+ - File read operations complete
73
+ - Git read operations complete
74
+ - File write operations to be implemented directly
75
+
76
+ Phase 2:
77
+ - OpenRouter integration
78
+
79
+ Phase 3: Write operations
80
+ - For git write operations (add, commit, reset, branch, checkout), Claude provides commands to user by making an API call to openrouter.
81
+
82
+
83
+ ## Notes
84
+ - XML format for instructions defined and documented
85
+ - Using Python 3.12 with UV package manager
86
+ - Following MCP server patterns from git implementation
87
+ - Local development setup complete with tests
88
+ - GitPython used for repository operations
@@ -0,0 +1,25 @@
1
+ [project]
2
+ name = "mcp-server-code-assist"
3
+ version = "0.1.0"
4
+ description = "MCP Code Assist Server"
5
+ requires-python = ">=3.11"
6
+ dependencies = [
7
+ "aiofiles>=24.0.0",
8
+ "gitpython>=3.1.40",
9
+ "pydantic>=2.0.0"
10
+ ]
11
+
12
+ [project.optional-dependencies]
13
+ test = [
14
+ "pytest>=8.0.0",
15
+ "pytest-asyncio>=0.25.0"
16
+ ]
17
+
18
+ [build-system]
19
+ requires = ["hatchling"]
20
+ build-backend = "hatchling.build"
21
+
22
+ [tool.pytest.ini_options]
23
+ pythonpath = ["src"]
24
+ asyncio_mode = "strict"
25
+ testpaths = ["tests"]
@@ -0,0 +1,24 @@
1
+ import click
2
+ from pathlib import Path
3
+ import logging
4
+ import sys
5
+ from .server import serve
6
+
7
+ @click.command()
8
+ @click.option("--working-dir", "-w", type=Path, help="Working directory path")
9
+ @click.option("-v", "--verbose", count=True)
10
+ def main(working_dir: Path | None, verbose: bool) -> None:
11
+ """MCP Code Assist Server - Code operations for MCP"""
12
+ import asyncio
13
+
14
+ logging_level = logging.WARN
15
+ if verbose == 1:
16
+ logging_level = logging.INFO
17
+ elif verbose >= 2:
18
+ logging_level = logging.DEBUG
19
+
20
+ logging.basicConfig(level=logging_level, stream=sys.stderr)
21
+ asyncio.run(serve(working_dir))
22
+
23
+ if __name__ == "__main__":
24
+ main()
@@ -0,0 +1,3 @@
1
+ from mcp_server_code_assist import main
2
+
3
+ main()
@@ -0,0 +1,28 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3
+ <xs:element name="instruction">
4
+ <xs:complexType>
5
+ <xs:sequence>
6
+ <xs:element name="function">
7
+ <xs:simpleType>
8
+ <xs:restriction base="xs:string">
9
+ <xs:enumeration value="create"/>
10
+ <xs:enumeration value="delete"/>
11
+ <xs:enumeration value="modify"/>
12
+ <xs:enumeration value="rewrite"/>
13
+ </xs:restriction>
14
+ </xs:simpleType>
15
+ </xs:element>
16
+ <xs:element name="path" type="xs:string"/>
17
+ <xs:element name="content" type="xs:string" minOccurs="0"/>
18
+ <xs:element name="replacements" minOccurs="0">
19
+ <xs:complexType>
20
+ <xs:sequence>
21
+ <xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
22
+ </xs:sequence>
23
+ </xs:complexType>
24
+ </xs:element>
25
+ </xs:sequence>
26
+ </xs:complexType>
27
+ </xs:element>
28
+ </xs:schema>
@@ -0,0 +1,240 @@
1
+ import logging
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Any
5
+ from enum import Enum
6
+ from mcp.server import Server
7
+ from mcp.server.session import ServerSession
8
+ from mcp.server.stdio import stdio_server
9
+ from mcp.types import ClientCapabilities, TextContent, Tool, ListRootsResult, RootsCapability
10
+ import git
11
+ from mcp_server_code_assist.tools.models import (
12
+ FileCreate, FileDelete, FileModify, FileRewrite,
13
+ GitBase, GitAdd, GitCommit, GitDiff, GitCreateBranch,
14
+ GitCheckout, GitShow, GitLog
15
+ )
16
+ from mcp_server_code_assist.tools.file_tools import FileTools
17
+ from mcp_server_code_assist.tools.git_functions import git_status, git_diff_unstaged, git_diff_staged, git_diff, git_log, git_show
18
+
19
+ class CodeAssistTools(str, Enum):
20
+ FILE_CREATE = "file_create"
21
+ FILE_DELETE = "file_delete"
22
+ FILE_MODIFY = "file_modify"
23
+ FILE_REWRITE = "file_rewrite"
24
+ GIT_STATUS = "git_status"
25
+ GIT_DIFF_UNSTAGED = "git_diff_unstaged"
26
+ GIT_DIFF_STAGED = "git_diff_staged"
27
+ GIT_DIFF = "git_diff"
28
+ GIT_COMMIT = "git_commit"
29
+ GIT_ADD = "git_add"
30
+ GIT_RESET = "git_reset"
31
+ GIT_LOG = "git_log"
32
+ GIT_CREATE_BRANCH = "git_create_branch"
33
+ GIT_CHECKOUT = "git_checkout"
34
+ GIT_SHOW = "git_show"
35
+
36
+ async def process_instruction(instruction: dict[str, Any], repo_path: Path) -> dict[str, Any]:
37
+ FileTools.init_allowed_paths([str(repo_path)])
38
+ try:
39
+ match instruction['type']:
40
+ case 'read_file':
41
+ path = str(repo_path / instruction['path'])
42
+ content = await FileTools.read_file(path)
43
+ return {'content': content}
44
+
45
+ case 'read_multiple':
46
+ paths = [str(repo_path / p) for p in instruction['paths']]
47
+ contents = await FileTools.read_multiple_files(paths)
48
+ contents_dict = {os.path.basename(k): v for k,v in contents.items()}
49
+ return {'contents': contents_dict}
50
+
51
+ case 'create_file':
52
+ path = str(repo_path / instruction['path'])
53
+ result = await FileTools.create_file(path, instruction.get('content', ''))
54
+ return {'result': result}
55
+
56
+ case 'modify_file':
57
+ path = str(repo_path / instruction['path'])
58
+ result = await FileTools.modify_file(path, instruction['replacements'])
59
+ return {'result': result}
60
+
61
+ case 'rewrite_file':
62
+ path = str(repo_path / instruction['path'])
63
+ result = await FileTools.rewrite_file(path, instruction['content'])
64
+ return {'result': result}
65
+
66
+ case 'delete_file':
67
+ path = str(repo_path / instruction['path'])
68
+ result = await FileTools.delete_file(path)
69
+ return {'result': result}
70
+
71
+ case _:
72
+ return {'error': 'Invalid instruction type'}
73
+
74
+ except Exception as e:
75
+ return {'error': str(e)}
76
+
77
+ async def serve(working_dir: Path | None) -> None:
78
+ logger = logging.getLogger(__name__)
79
+ server = Server("mcp-code-assist")
80
+
81
+ @server.list_tools()
82
+ async def list_tools() -> list[Tool]:
83
+ return [
84
+ Tool(
85
+ name=CodeAssistTools.FILE_CREATE,
86
+ description="Creates a new file with content",
87
+ inputSchema=FileCreate.schema(),
88
+ ),
89
+ Tool(
90
+ name=CodeAssistTools.FILE_DELETE,
91
+ description="Deletes a file",
92
+ inputSchema=FileDelete.schema(),
93
+ ),
94
+ Tool(
95
+ name=CodeAssistTools.FILE_MODIFY,
96
+ description="Modifies file content using search/replace",
97
+ inputSchema=FileModify.schema(),
98
+ ),
99
+ Tool(
100
+ name=CodeAssistTools.FILE_REWRITE,
101
+ description="Rewrites entire file content",
102
+ inputSchema=FileRewrite.schema(),
103
+ ),
104
+ Tool(
105
+ name=CodeAssistTools.GIT_STATUS,
106
+ description="Shows the working tree status",
107
+ inputSchema=GitBase.schema(),
108
+ ),
109
+ Tool(
110
+ name=CodeAssistTools.GIT_DIFF_UNSTAGED,
111
+ description="Shows changes in the working directory that are not yet staged",
112
+ inputSchema=GitBase.schema(),
113
+ ),
114
+ Tool(
115
+ name=CodeAssistTools.GIT_DIFF_STAGED,
116
+ description="Shows changes that are staged for commit",
117
+ inputSchema=GitBase.schema(),
118
+ ),
119
+ Tool(
120
+ name=CodeAssistTools.GIT_DIFF,
121
+ description="Shows differences between branches or commits",
122
+ inputSchema=GitDiff.schema(),
123
+ ),
124
+ Tool(
125
+ name=CodeAssistTools.GIT_COMMIT,
126
+ description="Records changes to the repository",
127
+ inputSchema=GitCommit.schema(),
128
+ ),
129
+ Tool(
130
+ name=CodeAssistTools.GIT_ADD,
131
+ description="Adds file contents to the staging area",
132
+ inputSchema=GitAdd.schema(),
133
+ ),
134
+ Tool(
135
+ name=CodeAssistTools.GIT_RESET,
136
+ description="Unstages all staged changes",
137
+ inputSchema=GitBase.schema(),
138
+ ),
139
+ Tool(
140
+ name=CodeAssistTools.GIT_LOG,
141
+ description="Shows the commit logs",
142
+ inputSchema=GitLog.schema(),
143
+ ),
144
+ Tool(
145
+ name=CodeAssistTools.GIT_CREATE_BRANCH,
146
+ description="Creates a new branch from an optional base branch",
147
+ inputSchema=GitCreateBranch.schema(),
148
+ ),
149
+ Tool(
150
+ name=CodeAssistTools.GIT_CHECKOUT,
151
+ description="Switches branches",
152
+ inputSchema=GitCheckout.schema(),
153
+ ),
154
+ Tool(
155
+ name=CodeAssistTools.GIT_SHOW,
156
+ description="Shows the contents of a commit",
157
+ inputSchema=GitShow.schema(),
158
+ ),
159
+ ]
160
+
161
+ @server.call_tool()
162
+ async def call_tool(name: str, arguments: dict) -> list[TextContent]:
163
+ match name:
164
+ case CodeAssistTools.FILE_CREATE:
165
+ result = await FileTools.create_file(arguments["path"], arguments.get("content", ""))
166
+ return [TextContent(type="text", text=result)]
167
+
168
+ case CodeAssistTools.FILE_DELETE:
169
+ result = await FileTools.delete_file(arguments["path"])
170
+ return [TextContent(type="text", text=result)]
171
+
172
+ case CodeAssistTools.FILE_MODIFY:
173
+ result = await FileTools.modify_file(arguments["path"], arguments["replacements"])
174
+ return [TextContent(type="text", text=result)]
175
+
176
+ case CodeAssistTools.FILE_REWRITE:
177
+ result = await FileTools.rewrite_file(arguments["path"], arguments["content"])
178
+ return [TextContent(type="text", text=result)]
179
+
180
+ case CodeAssistTools.GIT_STATUS:
181
+ repo = git.Repo(arguments["repo_path"])
182
+ status = git_status(repo)
183
+ return [TextContent(type="text", text=f"Repository status:\n{status}")]
184
+
185
+ case CodeAssistTools.GIT_DIFF_UNSTAGED:
186
+ repo = git.Repo(arguments["repo_path"])
187
+ diff = git_diff_unstaged(repo)
188
+ return [TextContent(type="text", text=f"Unstaged changes:\n{diff}")]
189
+
190
+ case CodeAssistTools.GIT_DIFF_STAGED:
191
+ repo = git.Repo(arguments["repo_path"])
192
+ diff = git_diff_staged(repo)
193
+ return [TextContent(type="text", text=f"Staged changes:\n{diff}")]
194
+
195
+ case CodeAssistTools.GIT_DIFF:
196
+ repo = git.Repo(arguments["repo_path"])
197
+ diff = git_diff(repo, arguments["target"])
198
+ return [TextContent(type="text", text=f"Diff with {arguments['target']}:\n{diff}")]
199
+
200
+ case CodeAssistTools.GIT_COMMIT:
201
+ repo = git.Repo(arguments["repo_path"])
202
+ result = git_commit(repo, arguments["message"])
203
+ return [TextContent(type="text", text=result)]
204
+
205
+ case CodeAssistTools.GIT_ADD:
206
+ repo = git.Repo(arguments["repo_path"])
207
+ result = git_add(repo, arguments["files"])
208
+ return [TextContent(type="text", text=result)]
209
+
210
+ case CodeAssistTools.GIT_RESET:
211
+ repo = git.Repo(arguments["repo_path"])
212
+ result = git_reset(repo)
213
+ return [TextContent(type="text", text=result)]
214
+
215
+ case CodeAssistTools.GIT_LOG:
216
+ repo = git.Repo(arguments["repo_path"])
217
+ log = git_log(repo, arguments.get("max_count", 10))
218
+ return [TextContent(type="text", text="Commit history:\n" + "\n".join(log))]
219
+
220
+ case CodeAssistTools.GIT_CREATE_BRANCH:
221
+ repo = git.Repo(arguments["repo_path"])
222
+ result = git_create_branch(repo, arguments["branch_name"], arguments.get("base_branch"))
223
+ return [TextContent(type="text", text=result)]
224
+
225
+ case CodeAssistTools.GIT_CHECKOUT:
226
+ repo = git.Repo(arguments["repo_path"])
227
+ result = git_checkout(repo, arguments["branch_name"])
228
+ return [TextContent(type="text", text=result)]
229
+
230
+ case CodeAssistTools.GIT_SHOW:
231
+ repo = git.Repo(arguments["repo_path"])
232
+ result = git_show(repo, arguments["revision"])
233
+ return [TextContent(type="text", text=result)]
234
+
235
+ case _:
236
+ raise ValueError(f"Unknown tool: {name}")
237
+
238
+ options = server.create_initialization_options()
239
+ async with stdio_server() as (read_stream, write_stream):
240
+ await server.run(read_stream, write_stream, options, raise_exceptions=True)