Skip to content

feat: implement MCP server #505

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## [Unreleased]

### Features

* **mcp:** Add Model Context Protocol (MCP) server support
- New `--mcp-server` CLI option to start MCP server
- `ingest_repository` tool for LLM integration
- Full MCP protocol compliance with stdio transport
- Enhanced MCP client examples for stdio transport

## [0.3.1](https://github.com/coderamp-labs/gitingest/compare/v0.3.0...v0.3.1) (2025-07-31)


Expand Down
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ You can also replace `hub` with `ingest` in any GitHub URL to access the corresp
- Token count
- **CLI tool**: Run it as a shell command
- **Python package**: Import it in your code
- **MCP Server**: Model Context Protocol server for LLM integration

## 📚 Requirements

Expand All @@ -74,6 +75,12 @@ pip install gitingest[server]

to include server dependencies for self-hosting.

For MCP (Model Context Protocol) support:

```bash
pip install gitingest[mcp]
```

However, it might be a good idea to use `pipx` to install it.
You can install `pipx` using your preferred package manager.

Expand Down Expand Up @@ -150,6 +157,49 @@ See more options and usage details with:
gitingest --help
```

## 🤖 MCP (Model Context Protocol) Server

Gitingest includes an MCP server that allows LLMs to directly access repository analysis capabilities through the Model Context Protocol.

### Starting the MCP Server

```bash
# Start the MCP server with stdio transport
python -m mcp_server
```

### Available Tools

The MCP server provides the following tools:

- **`ingest_repository`**: Ingest a Git repository or local directory and return a structured digest

### Example MCP Client

See `examples/mcp_client_example.py` for a complete example of how to use the MCP server.

### Configuration

Use the provided `examples/mcp-config.json` to configure the MCP server in your MCP client:

#### Stdio Transport (Default)

```json
{
"mcpServers": {
"gitingest": {
"command": "python",
"args": ["-m", "mcp_server"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
```



## 🐍 Python package usage

```python
Expand Down
136 changes: 136 additions & 0 deletions docs/MCP_USAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Gitingest MCP Server

Gitingest includes an MCP (Model Context Protocol) server that allows LLMs to directly access repository analysis capabilities through the MCP protocol.

## What is MCP?

The Model Context Protocol (MCP) is a standardized protocol that enables language models to interact with external tools and resources in a structured manner. It facilitates the integration of specialized capabilities into LLM workflows.

## Installation

To use the MCP server, install Gitingest with MCP dependencies:

```bash
pip install gitingest[mcp]
```

## Starting the MCP Server

### Stdio Transport (Default)

```bash
gitingest --mcp-server
```

The MCP server uses stdio for communication by default, making it compatible with all MCP clients.


## Available Tools

### `ingest_repository`

Ingests a Git repository or local directory and returns a structured digest.

**Parameters:**
- `source` (required): Git repository URL or local directory path
- `max_file_size` (optional): Maximum file size in bytes (default: 10485760)
- `include_patterns` (optional): Shell patterns to include files
- `exclude_patterns` (optional): Shell patterns to exclude files
- `branch` (optional): Git branch to clone and ingest
- `include_gitignored` (optional): Include files ignored by .gitignore (default: false)
- `include_submodules` (optional): Include Git submodules (default: false)
- `token` (optional): GitHub personal access token for private repositories

**Usage example:**
```json
{
"source": "https://github.com/coderamp-labs/gitingest",
"max_file_size": 1048576,
"include_patterns": ["*.py", "*.md"],
"exclude_patterns": ["tests/*"]
}
```

## MCP Client Configuration

### Stdio Transport Configuration

Create a configuration file for your MCP client:

```json
{
"mcpServers": {
"gitingest": {
"command": "python",
"args": ["-m", "mcp_server"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
```


### Environment Variables

- `GITHUB_TOKEN`: GitHub personal access token for private repositories

## Integration Examples

### Python Client Examples

See the following examples for how to use the Gitingest MCP server:

- **`examples/mcp_client_example.py`** - Stdio transport example
- **`examples/start_mcp_server.py`** - Startup script for stdio transport

### Integration with Claude Desktop

1. Install Gitingest with MCP dependencies
2. Create an MCP configuration file in your Claude configuration directory
3. Restart Claude Desktop
4. Use Gitingest tools in your conversations

### Integration with Other MCP Clients

The Gitingest MCP server is compatible with all MCP-compliant clients. Consult your MCP client's documentation for specific integration instructions.

## Output Format

The MCP server returns structured content that includes:

1. **Summary**: General information about the repository
2. **File Structure**: Tree structure of files and directories
3. **Content**: Code file content with LLM-optimized formatting

## Error Handling

The MCP server handles errors gracefully and returns informative error messages. Common errors include:

- Private repositories without authentication token
- Invalid repository URLs
- Network issues during cloning
- Files that are too large

## Limitations

- The MCP server does not maintain a cache of ingested repositories (future feature)
- Persistent resources are not yet implemented
- The server uses stdio transport for MCP communication

## Development

To contribute to the MCP server:

1. Consult the MCP specification: https://modelcontextprotocol.io/
2. Tests are located in `tests/test_mcp_server.py`
3. The client example is located in `examples/mcp_client_example.py`

## Support

For help with the MCP server:

- Consult the official MCP documentation
- Open an issue on GitHub
- Join the Discord community
11 changes: 11 additions & 0 deletions examples/mcp-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"mcpServers": {
"gitingest": {
"command": "gitingest",
"args": ["--mcp-server"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
25 changes: 25 additions & 0 deletions examples/mcp_client_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import asyncio
from mcp.client.session import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client


async def main():
async with stdio_client(
StdioServerParameters(command="gitingest", args=["--mcp-server"])
) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()

# List available tools
tools = await session.list_tools()
print("🛠️ Outils disponibles:")
for tool in tools.tools:
print(f" - {tool.name}: {tool.description}")

# Call the ingest_repository tool
print("\n📞 Appel de l'outil ingest_repository...")
result = await session.call_tool("ingest_repository", {"source": "https://github.com/coderamp-labs/gitingest"})
print(result)


asyncio.run(main())
9 changes: 9 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ server = [
"uvicorn>=0.11.7", # Minimum safe release (https://osv.dev/vulnerability/PYSEC-2020-150)
]

mcp = [
"mcp>=1.0.0", # Model Context Protocol
"pydantic>=2.0.0",
]

[project.scripts]
gitingest = "gitingest.__main__:main"

Expand Down Expand Up @@ -131,3 +136,7 @@ asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
python_classes = "Test*"
python_functions = "test_*"
addopts = "--strict-markers"
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
]
17 changes: 17 additions & 0 deletions src/gitingest/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class _CLIArgs(TypedDict):
include_submodules: bool
token: str | None
output: str | None
mcp_server: bool


@click.command()
Expand Down Expand Up @@ -76,6 +77,12 @@ class _CLIArgs(TypedDict):
default=None,
help="Output file path (default: digest.txt in current directory). Use '-' for stdout.",
)
@click.option(
"--mcp-server",
is_flag=True,
default=False,
help="Start the MCP (Model Context Protocol) server for LLM integration",
)
def main(**cli_kwargs: Unpack[_CLIArgs]) -> None:
"""Run the CLI entry point to analyze a repo / directory and dump its contents.

Expand All @@ -99,6 +106,9 @@ def main(**cli_kwargs: Unpack[_CLIArgs]) -> None:
$ gitingest -o -
$ gitingest https://github.com/user/repo --output -

MCP server mode:
$ gitingest --mcp-server

With filtering:
$ gitingest -i "*.py" -e "*.log"
$ gitingest --include-pattern "*.js" --exclude-pattern "node_modules/*"
Expand All @@ -125,6 +135,7 @@ async def _async_main(
include_submodules: bool = False,
token: str | None = None,
output: str | None = None,
mcp_server: bool = False,
) -> None:
"""Analyze a directory or repository and create a text dump of its contents.

Expand Down Expand Up @@ -161,6 +172,12 @@ async def _async_main(
Raised if an error occurs during execution and the command must be aborted.

"""
# Check if MCP server mode is requested
if mcp_server:
from gitingest.mcp_server import start_mcp_server
await start_mcp_server()
return

try:
# Normalise pattern containers (the ingest layer expects sets)
exclude_patterns = set(exclude_pattern) if exclude_pattern else set()
Expand Down
2 changes: 1 addition & 1 deletion src/gitingest/clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from gitingest.config import DEFAULT_TIMEOUT
from gitingest.utils.git_utils import (
_add_token_to_url,
check_repo_exists,
checkout_partial_clone,
create_git_repo,
Expand Down Expand Up @@ -109,7 +110,6 @@ async def clone_repo(config: CloneConfig, *, token: str | None = None) -> None:
else:
# For non-authenticated repos, use the standard GitPython method
git.Repo.clone_from(url, local_path, **clone_kwargs)

logger.info("Git clone completed successfully")
except git.GitCommandError as exc:
msg = f"Git clone failed: {exc}"
Expand Down
3 changes: 0 additions & 3 deletions src/gitingest/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,11 @@ async def ingest_async(
logger.info("Starting local directory processing")

if not include_gitignored:
logger.debug("Applying gitignore patterns")
_apply_gitignores(query)

logger.info("Processing files and generating output")
summary, tree, content = ingest_query(query)

if output:
logger.debug("Writing output to file", extra={"output_path": output})
await _write_output(tree, content=content, target=output)

logger.info("Ingestion completed successfully")
Expand Down
Loading
Loading