Thank you for your interest in contributing to MCP Azure DevOps Server!
This project provides a Model Context Protocol (MCP) server that exposes tools for interacting with Azure DevOps Work Items, Git Repositories, Pull Requests, and Pipelines. Contributions of all kinds are welcome, including bug fixes, documentation improvements, new tools, refactors, and tests.
- Code of Conduct
- Project Goals
- Ways to Contribute
- Development Setup
- Branching & Workflow
- Commit & PR Guidelines
- Coding Standards
- Testing
- Adding a New MCP Tool
- Architecture Overview
- Security
- Getting Help
Be respectful, constructive, and collaborative.
Harassment, discrimination, or abusive behavior will not be tolerated. All contributors are expected to interact professionally and respectfully. See CODE_OF_CONDUCT.md for details.
- Provide a reliable MCP server for Azure DevOps integration
- Offer useful, composable tools for Work Items, Git Repositories, Pull Requests, and Pipelines
- Keep the server safe-by-default (minimal permissions, no secret leakage)
- Maintain a clean and extensible architecture for future domains (Boards, Wikis, etc.)
You can contribute by:
- Reporting bugs with clear reproduction steps
- Improving documentation (README, examples, guides)
- Adding new MCP tools or extending existing ones
- Improving logging, error handling, and observability
- Writing or improving tests
- Refactoring code for clarity and maintainability
| Requirement | Version | Purpose |
|---|---|---|
| .NET SDK | 10.0+ | Build and run |
| Docker | Latest | Container deployment (optional) |
| Azure DevOps PAT | - | API authentication |
PAT Required Scopes:
- Work Items: Read & Write
- Code: Read
- Build: Read
# 1. Clone the repository
git clone https://github.com/viamus/mcp-azure-devops.git
cd mcp-azure-devops
# 2. Create environment file
cp .env.example .env
# 3. Edit .env with your credentialsWarning: Never commit
.envfiles or hardcode credentials!
# Using .NET CLI
dotnet run --project src/Viamus.Azure.Devops.Mcp.Server
# Using Docker
docker compose up -d# .NET CLI (port 5000)
curl http://localhost:5000/health
# Docker (port 8080)
curl http://localhost:8080/healthThe main branch must remain stable. Create feature branches using these patterns:
| Prefix | Purpose | Example |
|---|---|---|
feat/ |
New features | feat/add-wiki-tools |
fix/ |
Bug fixes | fix/wiql-query-error |
docs/ |
Documentation | docs/improve-readme |
chore/ |
Maintenance | chore/update-deps |
test/ |
Test additions | test/pipeline-tools |
- Create a branch from
main - Make your changes
- Add or update tests
- Run tests locally:
dotnet test - Open a Pull Request targeting
main
Use Conventional Commits style:
feat: add get_work_items_by_area_path tool
fix: handle WIQL errors gracefully
docs: clarify PAT permissions
test: add unit tests for pipeline tools
chore: bump dependencies
A good PR includes:
- What changed and why
- Link to related issue (if applicable)
- Notes about breaking changes (avoid if possible)
- Confirmation that no secrets were introduced
- Logs or screenshots when helpful
- Prefer clarity over cleverness
- Keep MCP tools focused (single responsibility)
- Avoid leaking secrets via logs or exceptions
- Validate inputs and return consistent outputs
- Errors should be actionable and safe
- Use
async/awaitconsistently for I/O operations - Favor dependency injection
- Keep handlers/controllers thin
- Put business logic in services
- Keep models and DTOs explicit and simple
- Use
sealed recordfor DTOs (immutability)
When behavior changes, tests should be added or updated.
# All tests
dotnet test
# Specific test class
dotnet test --filter "FullyQualifiedName~WorkItemToolsTests"
dotnet test --filter "FullyQualifiedName~GitToolsTests"
dotnet test --filter "FullyQualifiedName~PullRequestToolsTests"
dotnet test --filter "FullyQualifiedName~PipelineToolsTests"
# With coverage
dotnet test --collect:"XPlat Code Coverage"tests/Viamus.Azure.Devops.Mcp.Server.Tests/
├── Models/ # DTO serialization and equality tests
└── Tools/ # Tool behavior tests with mocked services
- Unit tests: Services and mapping logic
- Contract tests: MCP tool outputs
- Integration tests: HTTP endpoints (optional but encouraged)
Before creating a new tool, ensure it has:
- Clear and descriptive name (snake_case)
- Single responsibility
- Stable inputs and outputs
- Parameter validation
- Safe and consistent error handling
- Unit tests
- Documentation in README.md
- Add tool implementation in
src/.../Tools/
[McpServerToolType]
public sealed class MyTools
{
private readonly IAzureDevOpsService _service;
private static readonly JsonSerializerOptions JsonOptions = new()
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
public MyTools(IAzureDevOpsService service) => _service = service;
[McpServerTool(Name = "my_tool")]
[Description("Description of what this tool does")]
public async Task<string> MyTool(
[Description("Parameter description")] string param,
CancellationToken cancellationToken = default)
{
var result = await _service.MyMethodAsync(param, cancellationToken);
return JsonSerializer.Serialize(result, JsonOptions);
}
}-
Add service method in
src/.../Services/- Add signature to
IAzureDevOpsService.cs - Implement in
AzureDevOpsService.cs
- Add signature to
-
Add DTOs if needed in
src/.../Models/- Use
sealed recordfor immutability - Include XML documentation
- Use
-
Add tests in
tests/.../Tools/ -
Update README.md with the new tool
Tools are auto-registered via
.WithToolsFromAssembly()
src/Viamus.Azure.Devops.Mcp.Server/
├── Configuration/
│ └── AzureDevOpsOptions.cs # Configuration binding
├── Models/
│ ├── WorkItemDto.cs # Work item details
│ ├── WorkItemSummaryDto.cs # Work item list view
│ ├── WorkItemCommentDto.cs # Work item comment
│ ├── RepositoryDto.cs # Git repository
│ ├── BranchDto.cs # Git branch
│ ├── GitItemDto.cs # Git file/folder
│ ├── GitFileContentDto.cs # File content
│ ├── PullRequestDto.cs # Pull request details
│ ├── PullRequestReviewerDto.cs # PR reviewer
│ ├── PullRequestThreadDto.cs # PR comment thread
│ ├── PullRequestCommentDto.cs # PR comment
│ ├── PipelineDto.cs # Pipeline definition
│ ├── BuildDto.cs # Build details
│ ├── BuildLogDto.cs # Build log metadata
│ ├── BuildTimelineRecordDto.cs # Build timeline
│ ├── PipelineRunDto.cs # Pipeline run
│ └── PaginatedResult.cs # Generic pagination
├── Services/
│ ├── IAzureDevOpsService.cs # Service interface
│ └── AzureDevOpsService.cs # Implementation
├── Tools/
│ ├── WorkItemTools.cs # Work Item tools (11)
│ ├── GitTools.cs # Git Repository tools (6)
│ ├── PullRequestTools.cs # Pull Request tools (5)
│ └── PipelineTools.cs # Pipeline/Build tools (9)
└── Program.cs # Entry point & DI
| Pattern | Description |
|---|---|
| Dependency Injection | Services registered as singletons |
| Interface-based design | Enables testing with mocks |
| DTOs as sealed records | Immutability and value equality |
| JSON serialization | CamelCase, indented output |
| Error handling | JSON error responses, no exceptions to client |
| Client | Used For |
|---|---|
WorkItemTrackingHttpClient |
Work Items, WIQL queries, comments |
GitHttpClient |
Repositories, branches, items, file content, PRs |
BuildHttpClient |
Pipelines, builds, logs, timelines |
- Never commit secrets (PATs, tokens, credentials)
- Avoid logging sensitive data
- Validate all external inputs
- Sanitize user inputs in WIQL queries (escape single quotes)
If you discover a security vulnerability:
- Do NOT open a public issue
- Contact the maintainers privately (see SECURITY.md)
If you need help:
- Check the README first
- Search existing issues
- Open a new issue with:
- Expected behavior
- Actual behavior
- Reproduction steps
- Logs (with secrets removed)
- Environment details (OS, .NET version, Docker version)
Thank you for contributing to MCP Azure DevOps Server!
Your help makes this project better for everyone.