Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1ac3c1d
feat(mcp_server_git): Add support for configurable GIT_DIFF_CONTEXT_L…
mceachen Apr 8, 2025
4c77b64
refactor(mcp-server-git): Change from environment variable to proper …
mceachen Apr 9, 2025
6475a75
Merge branch 'main' into main
mceachen Apr 13, 2025
ba54c9d
fix(server.py): remove unused import 'os'
mceachen Apr 29, 2025
c6eb49b
Merge branch 'main' into main
mceachen May 12, 2025
1e7d4bc
fix: replace deprecated pydantic function
May 13, 2025
c53b530
fix: fix mypy warning about representation of bytes
May 13, 2025
abd24f6
fix: use 'references' instead of 'refs' for pylance even though it's…
May 13, 2025
0ffd701
fix: fix f-strings
May 13, 2025
7c5dcaf
chore: add py.typed
May 13, 2025
8e86d49
fix: pyproject
May 13, 2025
cd88954
fix: resolve ZoneInfo error by using IANA-compliant local timezone
sleeper May 13, 2025
2ee38d3
Merge branch 'main' into hesreallyhim/git-small-fixes-with-typing-and…
hesreallyhim May 14, 2025
bd295ba
Merge branch 'main' into hesreallyhim/git-small-fixes-with-typing-and…
hesreallyhim May 15, 2025
c430ac9
Merge branch 'main' into hesreallyhim/git-small-fixes-with-typing-and…
hesreallyhim May 18, 2025
5e5819a
Merge branch 'main' into hesreallyhim/git-small-fixes-with-typing-and…
hesreallyhim May 19, 2025
7e1b629
feat: add conductor mcp server
AWOrpington May 20, 2025
dcbd53c
Merge branch 'main' into main
AWOrpington May 22, 2025
069d503
Merge branch 'main' into hesreallyhim/git-small-fixes-with-typing-and…
hesreallyhim May 22, 2025
70f5f07
Merge branch 'main' into main
AWOrpington May 23, 2025
2581ba1
Merge branch 'main' into main
AWOrpington May 26, 2025
7c9cb06
Merge branch 'main' into hesreallyhim/git-small-fixes-with-typing-and…
hesreallyhim May 30, 2025
446ff66
Merge branch 'main' into main
AWOrpington May 30, 2025
5dd895b
Merge branch 'main' into main
AWOrpington Jun 2, 2025
fa2d358
Merge branch 'main' into main
AWOrpington Jun 3, 2025
a59717e
Merge branch 'main' into main
AWOrpington Jun 4, 2025
22fdd78
Merge branch 'main' into main
AWOrpington Jun 9, 2025
0a628be
Merge branch 'main' into main
AWOrpington Jun 10, 2025
cb9229d
Merge branch 'main' into main
AWOrpington Jun 12, 2025
5c6963f
Update README.md with alt tags
AWOrpington Jun 12, 2025
ab43a7b
Merge branch 'main' into main
AWOrpington Jun 13, 2025
11d0ed0
Merge branch 'main' into main
AWOrpington Jun 17, 2025
0d03dc7
Merge branch 'main' into main
AWOrpington Jun 20, 2025
f64f8c0
Merge branch 'main' into main
AWOrpington Jun 24, 2025
02be9bc
Merge pull request #1855 from AWOrpington/main
olaservo Jun 25, 2025
fb9bb0b
Merge branch 'main' into hesreallyhim/git-small-fixes-with-typing-and…
olaservo Jun 25, 2025
9898e5a
Merge pull request #1753 from hesreallyhim/hesreallyhim/git-small-fix…
olaservo Jun 25, 2025
1252f48
Merge pull request #1326 from mceachen/main
olaservo Jun 25, 2025
531c1fe
Merge pull request #1761 from sleeper/fix_local_time
olaservo Jun 25, 2025
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ Official integrations are maintained by companies building production ready MCP
- <img height="12" width="12" src="https://codelogic.com/wp-content/themes/codelogic/assets/img/favicon.png" alt="CodeLogic Logo" /> **[CodeLogic](https://github.com/CodeLogicIncEngineering/codelogic-mcp-server)** - Interact with [CodeLogic](https://codelogic.com), a Software Intelligence platform that graphs complex code and data architecture dependencies, to boost AI accuracy and insight.
- <img height="12" width="12" src="https://static.coingecko.com/s/coingecko-logo-white-750bdea438e850281f784dffc8f4fd498415754f088d655a1140849745cb66ac.svg" alt="CoinGecko Logo" /> **[CoinGecko](https://github.com/coingecko/coingecko-typescript/tree/main/packages/mcp-server)** - Official [CoinGecko API](https://www.coingecko.com/en/api) MCP Server for Crypto Price & Market Data, across 200+ Blockchain Networks and 8M+ Tokens.
- <img height="12" width="12" src="https://www.comet.com/favicon.ico" alt="Comet Logo" /> **[Comet Opik](https://github.com/comet-ml/opik-mcp)** - Query and analyze your [Opik](https://github.com/comet-ml/opik) logs, traces, prompts and all other telemtry data from your LLMs in natural language.
- <img height="12" width="12" src="https://cdn.prod.website-files.com/6572bd8c27ee5db3eb91f4b3/6572bd8d27ee5db3eb91f55e_favicon-dashflow-webflow-template.svg" alt="OSS Conductor Logo" /> <img height="12" width="12" src="https://orkes.io/icons/icon-48x48.png" alt="Orkes Conductor Logo" />**[Conductor](https://github.com/conductor-oss/conductor-mcp)** - Interact with Conductor (OSS and Orkes) REST APIs.
- <img height="12" width="12" src="https://www.confluent.io/favicon.ico" alt="Confluent Logo" /> **[Confluent](https://github.com/confluentinc/mcp-confluent)** - Interact with Confluent Kafka and Confluent Cloud REST APIs.
- <img src="https://contrastsecurity.com/favicon.ico" alt="Contrast Security" width="12" height="12"> **[Contrast Security](https://github.com/Contrast-Security-OSS/mcp-contrast)** - Brings Contrast's vulnerability and SCA data into your coding agent to quickly remediate vulnerabilities.
- <img height="12" width="12" src="https://www.convex.dev/favicon.ico" alt="Convex Logo" /> **[Convex](https://stack.convex.dev/convex-mcp-server)** - Introspect and query your apps deployed to Convex.
Expand Down
7 changes: 5 additions & 2 deletions src/git/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,24 @@ Please note that mcp-server-git is currently in early development. The functiona

2. `git_diff_unstaged`
- Shows changes in working directory not yet staged
- Input:
- Inputs:
- `repo_path` (string): Path to Git repository
- `context_lines` (number, optional): Number of context lines to show (default: 3)
- Returns: Diff output of unstaged changes

3. `git_diff_staged`
- Shows changes that are staged for commit
- Input:
- Inputs:
- `repo_path` (string): Path to Git repository
- `context_lines` (number, optional): Number of context lines to show (default: 3)
- Returns: Diff output of staged changes

4. `git_diff`
- Shows differences between branches or commits
- Inputs:
- `repo_path` (string): Path to Git repository
- `target` (string): Target branch or commit to compare with
- `context_lines` (number, optional): Number of context lines to show (default: 3)
- Returns: Diff output comparing current state with target

5. `git_commit`
Expand Down
2 changes: 1 addition & 1 deletion src/git/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ dev-dependencies = ["pyright>=1.1.389", "ruff>=0.7.3", "pytest>=8.0.0"]
testpaths = ["tests"]
python_files = "test_*.py"
python_classes = "Test*"
python_functions = "test_*"
python_functions = "test_*"
Empty file.
64 changes: 35 additions & 29 deletions src/git/src/mcp_server_git/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,24 @@
import git
from pydantic import BaseModel

# Default number of context lines to show in diff output
DEFAULT_CONTEXT_LINES = 3

class GitStatus(BaseModel):
repo_path: str

class GitDiffUnstaged(BaseModel):
repo_path: str
context_lines: int = DEFAULT_CONTEXT_LINES

class GitDiffStaged(BaseModel):
repo_path: str
context_lines: int = DEFAULT_CONTEXT_LINES

class GitDiff(BaseModel):
repo_path: str
target: str
context_lines: int = DEFAULT_CONTEXT_LINES

class GitCommit(BaseModel):
repo_path: str
Expand Down Expand Up @@ -76,14 +82,14 @@ class GitTools(str, Enum):
def git_status(repo: git.Repo) -> str:
return repo.git.status()

def git_diff_unstaged(repo: git.Repo) -> str:
return repo.git.diff()
def git_diff_unstaged(repo: git.Repo, context_lines: int = DEFAULT_CONTEXT_LINES) -> str:
return repo.git.diff(f"--unified={context_lines}")

def git_diff_staged(repo: git.Repo) -> str:
return repo.git.diff("--cached")
def git_diff_staged(repo: git.Repo, context_lines: int = DEFAULT_CONTEXT_LINES) -> str:
return repo.git.diff(f"--unified={context_lines}", "--cached")

def git_diff(repo: git.Repo, target: str) -> str:
return repo.git.diff(target)
def git_diff(repo: git.Repo, target: str, context_lines: int = DEFAULT_CONTEXT_LINES) -> str:
return repo.git.diff(f"--unified={context_lines}", target)

def git_commit(repo: git.Repo, message: str) -> str:
commit = repo.index.commit(message)
Expand All @@ -102,16 +108,16 @@ def git_log(repo: git.Repo, max_count: int = 10) -> list[str]:
log = []
for commit in commits:
log.append(
f"Commit: {commit.hexsha}\n"
f"Author: {commit.author}\n"
f"Commit: {commit.hexsha!r}\n"
f"Author: {commit.author!r}\n"
f"Date: {commit.authored_datetime}\n"
f"Message: {commit.message}\n"
f"Message: {commit.message!r}\n"
)
return log

def git_create_branch(repo: git.Repo, branch_name: str, base_branch: str | None = None) -> str:
if base_branch:
base = repo.refs[base_branch]
base = repo.references[base_branch]
else:
base = repo.active_branch

Expand All @@ -132,10 +138,10 @@ def git_init(repo_path: str) -> str:
def git_show(repo: git.Repo, revision: str) -> str:
commit = repo.commit(revision)
output = [
f"Commit: {commit.hexsha}\n"
f"Author: {commit.author}\n"
f"Date: {commit.authored_datetime}\n"
f"Message: {commit.message}\n"
f"Commit: {commit.hexsha!r}\n"
f"Author: {commit.author!r}\n"
f"Date: {commit.authored_datetime!r}\n"
f"Message: {commit.message!r}\n"
]
if commit.parents:
parent = commit.parents[0]
Expand Down Expand Up @@ -166,62 +172,62 @@ async def list_tools() -> list[Tool]:
Tool(
name=GitTools.STATUS,
description="Shows the working tree status",
inputSchema=GitStatus.schema(),
inputSchema=GitStatus.model_json_schema(),
),
Tool(
name=GitTools.DIFF_UNSTAGED,
description="Shows changes in the working directory that are not yet staged",
inputSchema=GitDiffUnstaged.schema(),
inputSchema=GitDiffUnstaged.model_json_schema(),
),
Tool(
name=GitTools.DIFF_STAGED,
description="Shows changes that are staged for commit",
inputSchema=GitDiffStaged.schema(),
inputSchema=GitDiffStaged.model_json_schema(),
),
Tool(
name=GitTools.DIFF,
description="Shows differences between branches or commits",
inputSchema=GitDiff.schema(),
inputSchema=GitDiff.model_json_schema(),
),
Tool(
name=GitTools.COMMIT,
description="Records changes to the repository",
inputSchema=GitCommit.schema(),
inputSchema=GitCommit.model_json_schema(),
),
Tool(
name=GitTools.ADD,
description="Adds file contents to the staging area",
inputSchema=GitAdd.schema(),
inputSchema=GitAdd.model_json_schema(),
),
Tool(
name=GitTools.RESET,
description="Unstages all staged changes",
inputSchema=GitReset.schema(),
inputSchema=GitReset.model_json_schema(),
),
Tool(
name=GitTools.LOG,
description="Shows the commit logs",
inputSchema=GitLog.schema(),
inputSchema=GitLog.model_json_schema(),
),
Tool(
name=GitTools.CREATE_BRANCH,
description="Creates a new branch from an optional base branch",
inputSchema=GitCreateBranch.schema(),
inputSchema=GitCreateBranch.model_json_schema(),
),
Tool(
name=GitTools.CHECKOUT,
description="Switches branches",
inputSchema=GitCheckout.schema(),
inputSchema=GitCheckout.model_json_schema(),
),
Tool(
name=GitTools.SHOW,
description="Shows the contents of a commit",
inputSchema=GitShow.schema(),
inputSchema=GitShow.model_json_schema(),
),
Tool(
name=GitTools.INIT,
description="Initialize a new Git repository",
inputSchema=GitInit.schema(),
inputSchema=GitInit.model_json_schema(),
)
]

Expand Down Expand Up @@ -278,21 +284,21 @@ async def call_tool(name: str, arguments: dict) -> list[TextContent]:
)]

case GitTools.DIFF_UNSTAGED:
diff = git_diff_unstaged(repo)
diff = git_diff_unstaged(repo, arguments.get("context_lines", DEFAULT_CONTEXT_LINES))
return [TextContent(
type="text",
text=f"Unstaged changes:\n{diff}"
)]

case GitTools.DIFF_STAGED:
diff = git_diff_staged(repo)
diff = git_diff_staged(repo, arguments.get("context_lines", DEFAULT_CONTEXT_LINES))
return [TextContent(
type="text",
text=f"Staged changes:\n{diff}"
)]

case GitTools.DIFF:
diff = git_diff(repo, arguments["target"])
diff = git_diff(repo, arguments["target"], arguments.get("context_lines", DEFAULT_CONTEXT_LINES))
return [TextContent(
type="text",
text=f"Diff with {arguments['target']}:\n{diff}"
Expand Down
1 change: 1 addition & 0 deletions src/time/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies = [
"mcp>=1.0.0",
"pydantic>=2.0.0",
"tzdata>=2024.2",
"tzlocal>=5.3.1"
]

[project.scripts]
Expand Down
8 changes: 5 additions & 3 deletions src/time/src/mcp_server_time/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from typing import Sequence

from zoneinfo import ZoneInfo
from tzlocal import get_localzone_name # ← returns "Europe/Paris", etc.

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
Expand Down Expand Up @@ -40,9 +42,9 @@ def get_local_tz(local_tz_override: str | None = None) -> ZoneInfo:
return ZoneInfo(local_tz_override)

# Get local timezone from datetime.now()
tzinfo = datetime.now().astimezone(tz=None).tzinfo
if tzinfo is not None:
return ZoneInfo(str(tzinfo))
local_tzname = get_localzone_name()
if local_tzname is not None:
return ZoneInfo(local_tzname)
raise McpError("Could not determine local timezone - tzinfo is None")


Expand Down
Loading
Loading