A fully functional Model Context Protocol (MCP) Server implemented in Kotlin that acts as a gateway to the GitFlic service. The server operates over HTTP (localhost) and provides tools to interact with the GitFlic REST API.
This project follows Clean Architecture principles with three main layers:
- Domain Layer: Core business models (
Project,Commit,Branch,Owner) and repository interfaces - Infrastructure Layer: HTTP client for GitFlic API, MCP protocol handler, and tool implementations
- Application Layer: Use cases that orchestrate business logic
The implementation adheres to SOLID principles and uses Test-Driven Development (TDD) practices.
- Language: Kotlin (JVM target: 17)
- Build System: Gradle (Kotlin DSL)
- HTTP Framework: http4k (Server: Jetty, Client: Apache)
- Serialization: Kotlinx.serialization
- Testing: JUnit 5, Mockk
- Logging: Logback
- JDK 17 or higher
- Gradle 7.0 or higher (or use Gradle Wrapper)
The server requires the following environment variables:
GITFLIC_ACCESS_TOKEN(required): Your GitFlic API access tokenMCP_SERVER_PORT(optional): Server port (default: 8080)MCP_SERVER_HOST(optional): Server host (default: localhost)GITFLIC_BASE_URL(optional): GitFlic API base URL (default: https://api.gitflic.ru)
Linux/macOS:
export GITFLIC_ACCESS_TOKEN="your-access-token-here"
export MCP_SERVER_PORT=8080Windows (PowerShell):
$env:GITFLIC_ACCESS_TOKEN="your-access-token-here"
$env:MCP_SERVER_PORT=8080Windows (CMD):
set GITFLIC_ACCESS_TOKEN=your-access-token-here
set MCP_SERVER_PORT=8080./gradlew buildgradle build./gradlew runAfter building, run the JAR file:
./gradlew build
java -jar build/libs/mcp-gitflic-server-1.0.0.jarThe server will start on http://localhost:8080 (or the port specified in MCP_SERVER_PORT).
To use this MCP server with Claude Code (or Cursor), you need to configure it in the MCP settings.
macOS/Linux:
~/.config/cursor/mcp.json
Windows:
%APPDATA%\Cursor\mcp.json
Add the following configuration to your mcp.json file:
{
"mcpServers": {
"gitflic": {
"command": "java",
"args": [
"-jar",
"/path/to/mcp-gitflic-server/build/libs/mcp-gitflic-server-1.0.0.jar"
],
"env": {
"GITFLIC_ACCESS_TOKEN": "your-access-token-here",
"MCP_SERVER_PORT": "8080",
"MCP_SERVER_HOST": "localhost"
}
}
}
}Alternative: Using HTTP Transport
If you prefer to run the server separately and connect via HTTP:
-
Start the server manually:
export GITFLIC_ACCESS_TOKEN="your-access-token-here" ./gradlew run
-
Configure in
mcp.json:{ "mcpServers": { "gitflic": { "url": "http://localhost:8080", "transport": "http" } } }Note: HTTP transport support may vary depending on your Claude Code/Cursor version. If HTTP transport is not supported, use the command-based configuration above.
-
Build the JAR file:
./gradlew build
-
Locate the JAR file:
- Path:
build/libs/mcp-gitflic-server-1.0.0.jar - Use the absolute path in your configuration
- Path:
-
Create or edit the MCP configuration file:
- Create
mcp.jsonin the appropriate location (see above) - Add the configuration as shown above
- Replace
/path/to/mcp-gitflic-serverwith your actual project path - Replace
your-access-token-herewith your GitFlic access token
- Create
-
Restart Claude Code / Cursor:
- Close and reopen the application to load the new MCP server configuration
-
Verify the connection:
- The MCP server should appear in the MCP servers list
- You should be able to use the tools:
get_my_projects,get_projects_by_owner,get_project_info,create_project,get_project_commits,get_project_branches
Once configured, you can use the MCP tools directly in your conversations:
- Get your projects: Use the
get_my_projectstool - Find projects by owner: Use
get_projects_by_ownerwith the owner alias - Get project details: Use
get_project_infowith owner and project aliases - Create a project: Use
create_projectwith project details - View commits: Use
get_project_commitsto see project commit history - List branches: Use
get_project_branchesto see all project branches
The server implements the following MCP tools:
get_my_projects: Get a list of projects for the currently authorized userget_projects_by_owner: Get a list of projects by a specific owner alias (username/organization)get_project_info: Get detailed information about a specific projectcreate_project: Create a new project (accepts name, visibility, etc.)get_project_commits: Get a list of commits for a specific projectget_project_branches: Get a list of branches for a specific projectget_project_issues: Get a list of issues for a specific projectget_issue_details: Get detailed information about a specific issuecreate_issue: Create a new issue in a projectedit_issue: Edit an existing issuedelete_issue: Delete an issue from a projectsave_file_to_project: Save text content to a file in the project root directory
curl http://localhost:8080/healthExpected response:
{"status":"ok"}All requests use JSON-RPC 2.0 format over HTTP POST.
curl -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "get_my_projects",
"params": {}
}'curl -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "2",
"method": "get_projects_by_owner",
"params": {
"ownerAlias": "username"
}
}'curl -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "3",
"method": "get_project_info",
"params": {
"ownerAlias": "username",
"projectAlias": "project-name"
}
}'curl -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "4",
"method": "create_project",
"params": {
"name": "My New Project",
"alias": "my-new-project",
"description": "Project description",
"visibility": "PUBLIC"
}
}'Note: visibility can be PUBLIC or PRIVATE. Default is PUBLIC.
curl -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "5",
"method": "get_project_commits",
"params": {
"ownerAlias": "username",
"projectAlias": "project-name"
}
}'curl -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "6",
"method": "get_project_branches",
"params": {
"ownerAlias": "username",
"projectAlias": "project-name"
}
}'{
"jsonrpc": "2.0",
"id": "1",
"result": "[{\"id\":1,\"alias\":\"project\",\"name\":\"Project Name\"}]",
"error": null
}{
"jsonrpc": "2.0",
"id": "1",
"result": null,
"error": {
"code": -32602,
"message": "Invalid params",
"data": null
}
}-32700: Parse error-32600: Invalid Request-32601: Method not found-32602: Invalid params-32603: Internal error-32000: Server error
./gradlew testTo see test output:
./gradlew test --infomcp-gitflic-server/
├── build.gradle.kts
├── settings.gradle.kts
├── gradle.properties
├── README.md
└── src/
├── main/
│ ├── kotlin/com/gitflic/mcp/
│ │ ├── domain/ # Domain models and interfaces
│ │ ├── infrastructure/ # HTTP client, MCP protocol, tools
│ │ └── application/ # Use cases and main entry point
│ └── resources/
│ └── application.conf
└── test/
└── kotlin/com/gitflic/mcp/ # Unit tests
The server handles various error scenarios:
- Invalid Access Token: Returns 401 Unauthorized
- Project/Owner Not Found: Returns 404 Not Found
- Rate Limiting: Returns appropriate error response
- Network Errors: Returns server error with details
- Invalid Parameters: Returns JSON-RPC invalid params error
The server uses Logback for logging. Logs are output to the console with the following levels:
- INFO: Server startup, request processing
- WARN: Invalid requests, parameter validation failures
- ERROR: Exceptions, API errors
This project is provided as-is for the MCP GitFlic Server implementation.
This is a reference implementation following Clean Architecture and SOLID principles. When extending:
- Add new tools by implementing the
ToolHandlerinterface - Create corresponding use cases in the application layer
- Add repository methods in the domain layer
- Implement HTTP client methods in the infrastructure layer
- Write comprehensive unit tests
curl -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "12",
"method": "save_file_to_project",
"params": {
"fileName": "notes.txt",
"content": "This is a sample file content.\nIt can contain multiple lines.\n\nCreated via MCP tool."
}
}'Note: The file will be saved in the project root directory. You can also specify subdirectories like "docs/readme.md". The tool automatically creates necessary parent directories and prevents path traversal attacks.
- Ensure
GITFLIC_ACCESS_TOKENis set - Check that port 8080 (or your configured port) is available
- Verify JDK 17+ is installed
- Verify your GitFlic access token is valid
- Check network connectivity to
https://api.gitflic.ru - Review server logs for detailed error messages
- Ensure all dependencies are downloaded:
./gradlew build --refresh-dependencies - Check that mockk and JUnit 5 are properly configured