A backend system to power conversational, AI-augmented workflows in Azure DevOps. This project provides REST and WebSocket APIs for integrating with Azure DevOps Boards using user-supplied Personal Access Tokens (PAT). AI features can be enabled using LLM providers like OpenRouter.ai or OpenAI.
- Architecture
- Features
- Getting Started
- Environment Variables
- API Reference
- WebSocket Events
- Security
- Deployment
- License
Frontend (Chat UI)
|
v
Backend API <-----> Azure DevOps (PAT)
|
v
AI/LLM Service (OpenRouter, OpenAI, etc.)
- Express/Node.js API server: Exposes REST and Socket.IO endpoints
- Azure DevOps Integration: Uses user-supplied Personal Access Token (PAT) per session/request
- AI Services (Optional): Connects to LLM providers for natural language queries and workflow recommendations
- Stateless Backend: No persistent storage of tokens; all auth handled per request
- Create, update, reassign, and describe user stories, issues, and tasks
- Move work items between sprints
- View work item details by ID
- Get current sprint status
- Overview of all recent sprints
- List and filter items by sprint, type, and state
- Search work items by keyword
- Filter by type, state, and sprint
- Find unassigned items, child tasks, and linked bugs
- Ask natural language questions about sprints and backlog
- AI-generated summaries of sprints and boards
- Risk and blocker identification
- Planning focus recommendations
- Node.js v14 or higher (for local development)
- npm or yarn
- Docker and Docker Compose (for Docker deployment)
- Azure DevOps organization and project
- Azure DevOps Personal Access Token (PAT) with Work Items read/write permissions
- (Optional) OpenRouter/OpenAI API key for AI features
git clone https://github.com/your-username/azure-devops-chatbot-backend.git
cd azure-devops-chatbot-backendnpm installCopy the example environment file and configure it:
cp .env.example .envEdit .env file with your configuration:
# Server Configuration
PORT=3001
NODE_ENV=development
LOG_LEVEL=info
# CORS Configuration (optional)
CORS_ORIGIN=*
# Azure DevOps Configuration (Optional - can be provided per request via headers)
AZURE_ORG_URL=https://dev.azure.com/your-org
AZURE_PROJECT=your-project-name
# Azure DevOps PAT for MCP Server (Required for MCP server only)
AZURE_DEVOPS_PAT=your-azure-devops-personal-access-token
# AI Service Configuration (Optional)
OPENROUTER_API_KEY=your-openrouter-api-key
OPENAI_API_KEY=your-openai-api-key
# Application URL
APP_URL=http://localhost:3001Important Notes:
- For REST API: Azure DevOps PAT is provided per request via
Authorization: Bearer <pat>header- For MCP Server:
AZURE_DEVOPS_PATmust be set in.envfileAZURE_ORG_URLandAZURE_PROJECTare optional if provided via request headers
Start the main API server:
npm startThe server will run at http://localhost:3001 by default.
Development mode with auto-reload:
npm run devStart the MCP server (separate process):
npm run mcpMCP server in development mode:
npm run mcp:devCheck if the server is running:
curl http://localhost:3001/api/healthExpected response:
{
"status": "healthy",
"timestamp": "2024-01-15T10:30:00.000Z",
"service": "azure-devops-chatbot-backend"
}git clone https://github.com/your-username/azure-devops-chatbot-backend.git
cd azure-devops-chatbot-backendCreate a .env file in the project root:
cp .env.example .envEdit .env with your configuration (see environment variables section below).
Option A: Using Docker Compose (Recommended)
# Build and start the container
docker-compose up -d
# View logs
docker-compose logs -f
# Stop the container
docker-compose downOption B: Using Docker directly
# Build the Docker image
docker build -t azure-devops-backend .
# Run the container
docker run -d \
--name azure-devops-backend \
-p 3001:3001 \
--env-file .env \
-v $(pwd)/logs:/app/logs \
azure-devops-backend
# View logs
docker logs -f azure-devops-backend
# Stop the container
docker stop azure-devops-backend
docker rm azure-devops-backendcurl http://localhost:3001/api/healthCreate a .env file in the root of your project. You can copy from .env.example:
cp .env.example .env| Variable | Required | Default | Description |
|---|---|---|---|
PORT |
No | 3001 |
Port on which the server will run |
NODE_ENV |
No | development |
Environment mode (development, production) |
LOG_LEVEL |
No | info |
Logging level (error, warn, info, debug) |
CORS_ORIGIN |
No | * |
CORS allowed origins (use * for all, or specific domain) |
APP_URL |
No | http://localhost:3001 |
Application URL (used for OpenRouter API) |
| Variable | Required | Description |
|---|---|---|
AZURE_ORG_URL |
Optional* | Azure DevOps organization URL (e.g., https://dev.azure.com/your-org) |
AZURE_PROJECT |
Optional* | Azure DevOps project name |
AZURE_DEVOPS_PAT |
Required for MCP | Azure DevOps Personal Access Token (required for MCP server) |
Note:
- For REST API:
AZURE_ORG_URLandAZURE_PROJECTcan be provided via request headers (x-org-url,x-project) or environment variables- For REST API: PAT is provided per request via
Authorization: Bearer <pat>header- For MCP Server:
AZURE_DEVOPS_PAT,AZURE_ORG_URL, andAZURE_PROJECTmust be set in environment variables
| Variable | Required | Description |
|---|---|---|
OPENROUTER_API_KEY |
Optional | OpenRouter API key for AI features |
OPENAI_API_KEY |
Optional | OpenAI API key for AI features |
Note: AI API keys can also be provided per request in the request body for REST API endpoints.
PORT=3001
NODE_ENV=development
LOG_LEVEL=info
# Optional: Default values (can be overridden via headers)
AZURE_ORG_URL=https://dev.azure.com/your-org
AZURE_PROJECT=your-project-name
# Optional: AI features
OPENROUTER_API_KEY=your-key
OPENAI_API_KEY=your-keyNote: PAT is provided per request via Authorization header.
PORT=3001
NODE_ENV=development
# Required for MCP Server
AZURE_DEVOPS_PAT=your-azure-devops-pat
AZURE_ORG_URL=https://dev.azure.com/your-org
AZURE_PROJECT=your-project-name
# Optional: AI features
OPENROUTER_API_KEY=your-key
OPENAI_API_KEY=your-keyPORT=3001
NODE_ENV=development
LOG_LEVEL=info
CORS_ORIGIN=*
APP_URL=http://localhost:3001
# Required for MCP Server, optional defaults for REST API
AZURE_DEVOPS_PAT=your-azure-devops-pat
AZURE_ORG_URL=https://dev.azure.com/your-org
AZURE_PROJECT=your-project-name
# Optional: AI features
OPENROUTER_API_KEY=your-key
OPENAI_API_KEY=your-key- Go to Azure DevOps:
https://dev.azure.com/{your-org} - Click on your profile picture → Security
- Click Personal access tokens → + New Token
- Configure the token:
- Name:
Azure DevOps Assistant - Organization: Select your organization
- Expiration: Set appropriate expiration
- Scopes: Select Work Items (Read & Write)
- Name:
- Click Create and copy the token (you won't see it again)
The main API server provides REST endpoints and WebSocket support.
Start:
npm startDevelopment mode:
npm run devWith Docker:
docker-compose up -dThe MCP server runs as a separate process for integration with AI assistants.
Start:
npm run mcpDevelopment mode:
npm run mcp:devNote: The MCP server communicates via stdio and is typically launched by MCP-compatible clients (Claude Desktop, Cursor, etc.) rather than run directly. See docs.md for client integration instructions.
# 1. Clone and install
git clone <repository-url>
cd azure-devops-chatbot-backend
npm install
# 2. Configure environment
cp .env.example .env
# Edit .env with your values
# 3. Start the server
npm run dev
# 4. Test the API
curl http://localhost:3001/api/health# 1. Clone repository
git clone <repository-url>
cd azure-devops-chatbot-backend
# 2. Configure environment
cp .env.example .env
# Edit .env with your values
# 3. Start with Docker Compose
docker-compose up -d
# 4. Check logs
docker-compose logs -f
# 5. Test the API
curl http://localhost:3001/api/health# Health check (no auth required)
curl http://localhost:3001/api/health
# Get work item (requires PAT in header)
curl http://localhost:3001/api/workitems/12345 \
-H "Authorization: Bearer <your-pat>" \
-H "x-org-url: https://dev.azure.com/your-org" \
-H "x-project: your-project"All endpoints require Authorization: Bearer <azure-pat> in headers unless otherwise stated.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/health |
Check API health |
| Method | Endpoint | Description | Parameters |
|---|---|---|---|
| POST | /api/workitems |
Create a new work item | type, title, description, sprint |
| GET | /api/workitems/:id |
Get details of a work item by ID | id |
| PATCH | /api/workitems/:id/state |
Update the state of a work item | id, newState |
| PATCH | /api/workitems/:id/sprint |
Move work item to another sprint | id, sprintId |
| GET | /api/workitems |
List/filter/search all work items | type, sprint, state, keywords |
| GET | /api/workitems/:id/children |
List child tasks for a work item | id |
| GET | /api/workitems/:id/linked-bugs |
List bugs linked to a work item | id |
| Method | Endpoint | Description | Parameters |
|---|---|---|---|
| GET | /api/sprints/current |
Get a summary of the current sprint | - |
| GET | /api/sprints |
View an overview of all sprints | - |
| GET | /api/sprints/:sprintId/items |
List items in a specific sprint | sprintId, type |
| Method | Endpoint | Description | Parameters |
|---|---|---|---|
| GET | /api/search |
Search work items using keywords | query, type, state, sprint |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/workitems/unassigned/todo |
List unassigned items in "To Do" state |
| Method | Endpoint | Description | Body Parameters |
|---|---|---|---|
| POST | /api/ai/query |
NLP/Natural language queries | question, context, openrouter_api_key (optional) |
| POST | /api/ai/summarize |
AI-powered Sprint/Board summary | scope, id, openrouter_api_key (optional) |
| POST | /api/ai/suggestions/risks |
AI-generated risk identification | sprintId (optional), openrouter_api_key (optional) |
| POST | /api/ai/suggestions/focus |
AI recommendations for planning/focus | context, openrouter_api_key (optional) |
Note: For AI endpoints, you may include an
openrouter_api_keyin the POST body for per-user/provider LLM selection.
The backend provides real-time communication via Socket.IO at /socket.io.
authenticate– Send PAT and optional AI key for sessionchat_message– Send chat messagesdevops_action– Trigger work item/sprint actionsai_query– Send natural language/AI queries
response– Response to actions/queries in real timeerror– Error/event reportingstatus_update– Progress updates for long-running operations
- No persistent storage of PATs or AI keys; all tokens are in-memory/stateless per session
- All operations are performed using the user's supplied PAT (principle of least privilege)
- PAT should be scoped to Work Items (read/write only)
- Use HTTPS/TLS for production deployments
- Validate and sanitize all user inputs
- Rate limiting recommended for production
- Azure App Service
- AWS EC2 / Elastic Beanstalk
- Google Cloud Platform
- Vercel
- Heroku
- Docker
- Any Node.js-compatible platform
See Installation & Setup section above for detailed Docker instructions.
Quick Docker commands:
# Using Docker Compose (recommended)
docker-compose up -d
# Using Docker directly
docker build -t azure-devops-backend .
docker run -d -p 3001:3001 --env-file .env --name azure-devops-backend azure-devops-backendAll configuration should use environment variables. Never hardcode secrets. See Environment Variables section for complete reference.
azure-devops-chatbot-backend/
├── src/
│ ├── routes/
│ │ ├── workitems.js
│ │ ├── sprints.js
│ │ ├── search.js
│ │ └── ai.js
│ ├── services/
│ │ ├── azureDevOps.js
│ │ └── aiService.js
│ ├── middleware/
│ │ ├── auth.js
│ │ └── errorHandler.js
│ ├── mcp/
│ │ └── server.js
│ ├── utils/
│ │ ├── logger.js
│ │ └── helpers.js
│ └── index.js
├── .env
├── .gitignore
├── package.json
├── docs.md
└── README.md
MIT License
Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.
For issues or questions, please open a GitHub issue or contact the maintainers.
- This backend is designed for a chat-based frontend UI where users input their PAT directly
- APIs and sockets are stateless and secure
- To enable AI features, supply an OpenRouter/OpenAI API key via frontend or environment
- The backend does not store any user credentials or tokens persistently