Skip to content

Commit 3b40cd6

Browse files
iburelclaude
authored andcommitted
feat: add MCP (Model Context Protocol) server support
- Add MCP server implementation with stdio transport - Integrate MCP server option in CLI with --mcp-server flag - Add ingest_repository tool for MCP clients - Remove HTTP transport, keeping only stdio for simplicity - Add MCP dependencies and optional installation group - Include comprehensive documentation and client examples - Support GitHub token authentication through MCP 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent c3e3b26 commit 3b40cd6

File tree

8 files changed

+407
-3
lines changed

8 files changed

+407
-3
lines changed

docs/MCP_USAGE.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Gitingest MCP Server
2+
3+
Gitingest includes an MCP (Model Context Protocol) server that allows LLMs to directly access repository analysis capabilities through the MCP protocol.
4+
5+
## What is MCP?
6+
7+
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.
8+
9+
## Installation
10+
11+
To use the MCP server, install Gitingest with MCP dependencies:
12+
13+
```bash
14+
pip install gitingest[mcp]
15+
```
16+
17+
## Starting the MCP Server
18+
19+
### Stdio Transport (Default)
20+
21+
```bash
22+
gitingest --mcp-server
23+
```
24+
25+
The MCP server uses stdio for communication by default, making it compatible with all MCP clients.
26+
27+
28+
## Available Tools
29+
30+
### `ingest_repository`
31+
32+
Ingests a Git repository or local directory and returns a structured digest.
33+
34+
**Parameters:**
35+
- `source` (required): Git repository URL or local directory path
36+
- `max_file_size` (optional): Maximum file size in bytes (default: 10485760)
37+
- `include_patterns` (optional): Shell patterns to include files
38+
- `exclude_patterns` (optional): Shell patterns to exclude files
39+
- `branch` (optional): Git branch to clone and ingest
40+
- `include_gitignored` (optional): Include files ignored by .gitignore (default: false)
41+
- `include_submodules` (optional): Include Git submodules (default: false)
42+
- `token` (optional): GitHub personal access token for private repositories
43+
44+
**Usage example:**
45+
```json
46+
{
47+
"source": "https://github.com/coderamp-labs/gitingest",
48+
"max_file_size": 1048576,
49+
"include_patterns": ["*.py", "*.md"],
50+
"exclude_patterns": ["tests/*"]
51+
}
52+
```
53+
54+
## MCP Client Configuration
55+
56+
### Stdio Transport Configuration
57+
58+
Create a configuration file for your MCP client:
59+
60+
```json
61+
{
62+
"mcpServers": {
63+
"gitingest": {
64+
"command": "gitingest",
65+
"args": ["--mcp-server"],
66+
"env": {
67+
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
68+
}
69+
}
70+
}
71+
}
72+
```
73+
74+
75+
### Environment Variables
76+
77+
- `GITHUB_TOKEN`: GitHub personal access token for private repositories
78+
79+
## Integration Examples
80+
81+
### Python Client Examples
82+
83+
See the following examples for how to use the Gitingest MCP server:
84+
85+
- **`examples/mcp_client_example.py`** - Stdio transport example
86+
- **`examples/start_mcp_server.py`** - Startup script for stdio transport
87+
88+
### Integration with Claude Desktop
89+
90+
1. Install Gitingest with MCP dependencies
91+
2. Create an MCP configuration file in your Claude configuration directory
92+
3. Restart Claude Desktop
93+
4. Use Gitingest tools in your conversations
94+
95+
### Integration with Other MCP Clients
96+
97+
The Gitingest MCP server is compatible with all MCP-compliant clients. Consult your MCP client's documentation for specific integration instructions.
98+
99+
## Output Format
100+
101+
The MCP server returns structured content that includes:
102+
103+
1. **Summary**: General information about the repository
104+
2. **File Structure**: Tree structure of files and directories
105+
3. **Content**: Code file content with LLM-optimized formatting
106+
107+
## Error Handling
108+
109+
The MCP server handles errors gracefully and returns informative error messages. Common errors include:
110+
111+
- Private repositories without authentication token
112+
- Invalid repository URLs
113+
- Network issues during cloning
114+
- Files that are too large
115+
116+
## Limitations
117+
118+
- The MCP server does not maintain a cache of ingested repositories (future feature)
119+
- Persistent resources are not yet implemented
120+
- The server uses stdio transport for MCP communication
121+
122+
## Development
123+
124+
To contribute to the MCP server:
125+
126+
1. Consult the MCP specification: https://modelcontextprotocol.io/
127+
2. Tests are located in `tests/test_mcp_server.py`
128+
3. The client example is located in `examples/mcp_client_example.py`
129+
130+
## Support
131+
132+
For help with the MCP server:
133+
134+
- Consult the official MCP documentation
135+
- Open an issue on GitHub
136+
- Join the Discord community

examples/mcp-config.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"mcpServers": {
3+
"gitingest": {
4+
"command": "gitingest",
5+
"args": ["--mcp-server"],
6+
"env": {
7+
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
8+
}
9+
}
10+
}
11+
}

examples/mcp_client_example.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import asyncio
2+
from mcp.client.session import ClientSession
3+
from mcp.client.stdio import StdioServerParameters, stdio_client
4+
5+
6+
async def main():
7+
async with stdio_client(
8+
StdioServerParameters(command="gitingest", args=["--mcp-server"])
9+
) as (read, write):
10+
async with ClientSession(read, write) as session:
11+
await session.initialize()
12+
13+
# List available tools
14+
tools = await session.list_tools()
15+
print("🛠️ Outils disponibles:")
16+
for tool in tools.tools:
17+
print(f" - {tool.name}: {tool.description}")
18+
19+
# Call the ingest_repository tool
20+
print("\n📞 Appel de l'outil ingest_repository...")
21+
result = await session.call_tool("ingest_repository", {"source": "https://github.com/coderamp-labs/gitingest"})
22+
print(result)
23+
24+
25+
asyncio.run(main())

examples/start_mcp_server.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Startup script for the Gitingest MCP server.
4+
5+
This script starts the MCP server with stdio transport.
6+
7+
Usage:
8+
python examples/start_mcp_server.py
9+
"""
10+
11+
import sys
12+
import asyncio
13+
from pathlib import Path
14+
15+
# Add the src directory to the Python path
16+
src_path = Path(__file__).parent.parent / "src"
17+
sys.path.insert(0, str(src_path))
18+
19+
from gitingest.mcp_server import start_mcp_server
20+
21+
22+
async def main_wrapper():
23+
"""Start the MCP server with stdio transport."""
24+
print("Starting Gitingest MCP Server")
25+
print(" Transport: stdio")
26+
print(" Mode: stdio (for MCP clients that support stdio transport)")
27+
28+
print("\nServer Configuration:")
29+
print(" - Repository analysis and text digest generation")
30+
print(" - Token counting and file structure analysis")
31+
print(" - Support for both local directories and Git repositories")
32+
print()
33+
34+
try:
35+
await start_mcp_server()
36+
except KeyboardInterrupt:
37+
print("\nServer stopped by user")
38+
except Exception as e:
39+
print(f"\nError starting server: {e}")
40+
import traceback
41+
traceback.print_exc()
42+
sys.exit(1)
43+
44+
45+
if __name__ == "__main__":
46+
asyncio.run(main_wrapper())

pyproject.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ server = [
5353
"uvicorn>=0.11.7", # Minimum safe release (https://osv.dev/vulnerability/PYSEC-2020-150)
5454
]
5555

56+
mcp = [
57+
"mcp>=1.0.0", # Model Context Protocol
58+
"pydantic>=2.0.0",
59+
]
60+
5661
[project.scripts]
5762
gitingest = "gitingest.__main__:main"
5863

@@ -131,3 +136,7 @@ asyncio_mode = "auto"
131136
asyncio_default_fixture_loop_scope = "function"
132137
python_classes = "Test*"
133138
python_functions = "test_*"
139+
addopts = "--strict-markers"
140+
markers = [
141+
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
142+
]

src/gitingest/__main__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class _CLIArgs(TypedDict):
2929
include_submodules: bool
3030
token: str | None
3131
output: str | None
32+
mcp_server: bool
3233

3334

3435
@click.command()
@@ -76,6 +77,12 @@ class _CLIArgs(TypedDict):
7677
default=None,
7778
help="Output file path (default: digest.txt in current directory). Use '-' for stdout.",
7879
)
80+
@click.option(
81+
"--mcp-server",
82+
is_flag=True,
83+
default=False,
84+
help="Start the MCP (Model Context Protocol) server for LLM integration",
85+
)
7986
def main(**cli_kwargs: Unpack[_CLIArgs]) -> None:
8087
"""Run the CLI entry point to analyze a repo / directory and dump its contents.
8188
@@ -99,6 +106,9 @@ def main(**cli_kwargs: Unpack[_CLIArgs]) -> None:
99106
$ gitingest -o -
100107
$ gitingest https://github.com/user/repo --output -
101108
109+
MCP server mode:
110+
$ gitingest --mcp-server
111+
102112
With filtering:
103113
$ gitingest -i "*.py" -e "*.log"
104114
$ gitingest --include-pattern "*.js" --exclude-pattern "node_modules/*"
@@ -125,6 +135,7 @@ async def _async_main(
125135
include_submodules: bool = False,
126136
token: str | None = None,
127137
output: str | None = None,
138+
mcp_server: bool = False,
128139
) -> None:
129140
"""Analyze a directory or repository and create a text dump of its contents.
130141
@@ -161,6 +172,12 @@ async def _async_main(
161172
Raised if an error occurs during execution and the command must be aborted.
162173
163174
"""
175+
# Check if MCP server mode is requested
176+
if mcp_server:
177+
from gitingest.mcp_server import start_mcp_server
178+
await start_mcp_server()
179+
return
180+
164181
try:
165182
# Normalise pattern containers (the ingest layer expects sets)
166183
exclude_patterns = set(exclude_pattern) if exclude_pattern else set()

src/gitingest/entrypoint.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,11 @@ async def ingest_async(
134134
logger.info("Starting local directory processing")
135135

136136
if not include_gitignored:
137-
logger.debug("Applying gitignore patterns")
138137
_apply_gitignores(query)
139138

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

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

147144
logger.info("Ingestion completed successfully")

0 commit comments

Comments
 (0)