azure-devops-mcp

by RyanCardin15
Verified
  • src
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { getAzureDevOpsConfig } from './config'; import { WorkItemTools } from './Tools/WorkItemTools'; import { BoardsSprintsTools } from './Tools/BoardsSprintsTools'; import { ProjectTools } from './Tools/ProjectTools'; import { GitTools } from './Tools/GitTools'; import { TestingCapabilitiesTools } from './Tools/TestingCapabilitiesTools'; import { DevSecOpsTools } from './Tools/DevSecOpsTools'; import { ArtifactManagementTools } from './Tools/ArtifactManagementTools'; import { AIAssistedDevelopmentTools } from './Tools/AIAssistedDevelopmentTools'; import { z } from 'zod'; async function main() { try { // Log startup info console.log('Starting MCP server for Azure DevOps...'); // Load configuration const azureDevOpsConfig = getAzureDevOpsConfig(); console.log('Successfully loaded Azure DevOps configuration'); // Initialize tools const workItemTools = new WorkItemTools(azureDevOpsConfig); const boardsSprintsTools = new BoardsSprintsTools(azureDevOpsConfig); const projectTools = new ProjectTools(azureDevOpsConfig); const gitTools = new GitTools(azureDevOpsConfig); const testingCapabilitiesTools = new TestingCapabilitiesTools(azureDevOpsConfig); const devSecOpsTools = new DevSecOpsTools(azureDevOpsConfig); const artifactManagementTools = new ArtifactManagementTools(azureDevOpsConfig); const aiAssistedDevelopmentTools = new AIAssistedDevelopmentTools(azureDevOpsConfig); console.log('Initialized tools'); // Create MCP server const server = new McpServer({ name: 'azure-devops-mcp', version: '1.0.0', description: 'MCP server for Azure DevOps integration', }); // Register Work Item Tools server.tool("listWorkItems", "List work items based on a WIQL query", { query: z.string().describe("WIQL query to get work items") }, async (params, extra) => { const result = await workItemTools.listWorkItems({ query: params.query }); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getWorkItemById", "Get a specific work item by ID", { id: z.number().describe("Work item ID") }, async (params, extra) => { const result = await workItemTools.getWorkItemById({ id: params.id }); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("searchWorkItems", "Search for work items by text", { searchText: z.string().describe("Text to search for in work items"), top: z.number().optional().describe("Maximum number of work items to return") }, async (params, extra) => { const result = await workItemTools.searchWorkItems(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getRecentlyUpdatedWorkItems", "Get recently updated work items", { top: z.number().optional().describe("Maximum number of work items to return"), skip: z.number().optional().describe("Number of work items to skip") }, async (params, extra) => { const result = await workItemTools.getRecentlyUpdatedWorkItems(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getMyWorkItems", "Get work items assigned to you", { state: z.string().optional().describe("Filter by work item state"), top: z.number().optional().describe("Maximum number of work items to return") }, async (params, extra) => { const result = await workItemTools.getMyWorkItems(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createWorkItem", "Create a new work item", { workItemType: z.string().describe("Type of work item to create"), title: z.string().describe("Title of the work item"), description: z.string().optional().describe("Description of the work item"), assignedTo: z.string().optional().describe("User to assign the work item to"), state: z.string().optional().describe("Initial state of the work item"), areaPath: z.string().optional().describe("Area path for the work item"), iterationPath: z.string().optional().describe("Iteration path for the work item"), additionalFields: z.record(z.any()).optional().describe("Additional fields to set on the work item") }, async (params, extra) => { const result = await workItemTools.createWorkItem(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("updateWorkItem", "Update an existing work item", { id: z.number().describe("ID of the work item to update"), fields: z.record(z.any()).describe("Fields to update on the work item") }, async (params, extra) => { const result = await workItemTools.updateWorkItem(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("addWorkItemComment", "Add a comment to a work item", { id: z.number().describe("ID of the work item"), text: z.string().describe("Comment text") }, async (params, extra) => { const result = await workItemTools.addWorkItemComment(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("updateWorkItemState", "Update the state of a work item", { id: z.number().describe("ID of the work item"), state: z.string().describe("New state for the work item"), comment: z.string().optional().describe("Comment explaining the state change") }, async (params, extra) => { const result = await workItemTools.updateWorkItemState(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("assignWorkItem", "Assign a work item to a user", { id: z.number().describe("ID of the work item"), assignedTo: z.string().describe("User to assign the work item to") }, async (params, extra) => { const result = await workItemTools.assignWorkItem(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createLink", "Create a link between work items", { sourceId: z.number().describe("ID of the source work item"), targetId: z.number().describe("ID of the target work item"), linkType: z.string().describe("Type of link to create"), comment: z.string().optional().describe("Comment explaining the link") }, async (params, extra) => { const result = await workItemTools.createLink(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("bulkCreateWorkItems", "Create or update multiple work items in a single operation", { workItems: z.array(z.any()).describe("Array of work items to create or update") }, async (params, extra) => { const result = await workItemTools.bulkCreateWorkItems(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); // Register Boards & Sprints Tools server.tool("getBoards", "Get all boards for a team", { teamId: z.string().optional().describe("Team ID (uses default team if not specified)") }, async (params, extra) => { const result = await boardsSprintsTools.getBoards(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getBoardColumns", "Get columns for a specific board", { teamId: z.string().optional().describe("Team ID (uses default team if not specified)"), boardId: z.string().describe("ID of the board") }, async (params, extra) => { const result = await boardsSprintsTools.getBoardColumns(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getBoardItems", "Get items on a specific board", { teamId: z.string().optional().describe("Team ID (uses default team if not specified)"), boardId: z.string().describe("ID of the board") }, async (params, extra) => { const result = await boardsSprintsTools.getBoardItems(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("moveCardOnBoard", "Move a card on a board", { teamId: z.string().optional().describe("Team ID (uses default team if not specified)"), boardId: z.string().describe("ID of the board"), workItemId: z.number().describe("ID of the work item to move"), columnId: z.string().describe("ID of the column to move to"), position: z.number().optional().describe("Position within the column") }, async (params, extra) => { const result = await boardsSprintsTools.moveCardOnBoard(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getSprints", "Get all sprints for a team", { teamId: z.string().optional().describe("Team ID (uses default team if not specified)") }, async (params, extra) => { const result = await boardsSprintsTools.getSprints(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getCurrentSprint", "Get the current sprint", { teamId: z.string().optional().describe("Team ID (uses default team if not specified)") }, async (params, extra) => { const result = await boardsSprintsTools.getCurrentSprint(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getSprintWorkItems", "Get work items in a specific sprint", { teamId: z.string().optional().describe("Team ID (uses default team if not specified)"), sprintId: z.string().describe("ID of the sprint") }, async (params, extra) => { const result = await boardsSprintsTools.getSprintWorkItems(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getSprintCapacity", "Get capacity for a specific sprint", { teamId: z.string().optional().describe("Team ID (uses default team if not specified)"), sprintId: z.string().describe("ID of the sprint") }, async (params, extra) => { const result = await boardsSprintsTools.getSprintCapacity(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getTeamMembers", "Get members of a team", { teamId: z.string().optional().describe("Team ID (uses default team if not specified)") }, async (params, extra) => { const result = await boardsSprintsTools.getTeamMembers(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); // Register Project Tools server.tool("listProjects", "List all projects", { stateFilter: z.enum(['all', 'createPending', 'deleted', 'deleting', 'new', 'unchanged', 'wellFormed']).optional().describe("Filter by project state"), top: z.number().optional().describe("Maximum number of projects to return"), skip: z.number().optional().describe("Number of projects to skip") }, async (params, extra) => { const result = await projectTools.listProjects(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getProjectDetails", "Get details of a specific project", { projectId: z.string().describe("ID of the project"), includeCapabilities: z.boolean().optional().describe("Include project capabilities"), includeHistory: z.boolean().optional().describe("Include project history") }, async (params, extra) => { const result = await projectTools.getProjectDetails(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createProject", "Create a new project", { name: z.string().describe("Name of the project"), description: z.string().optional().describe("Description of the project"), visibility: z.enum(['private', 'public']).optional().describe("Visibility of the project"), capabilities: z.record(z.any()).optional().describe("Project capabilities"), processTemplateId: z.string().optional().describe("Process template ID") }, async (params, extra) => { const result = await projectTools.createProject(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getAreas", "Get areas for a project", { projectId: z.string().describe("ID of the project"), depth: z.number().optional().describe("Maximum depth of the area hierarchy") }, async (params, extra) => { const result = await projectTools.getAreas(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getIterations", "Get iterations for a project", { projectId: z.string().describe("ID of the project"), includeDeleted: z.boolean().optional().describe("Include deleted iterations") }, async (params, extra) => { const result = await projectTools.getIterations(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createArea", "Create a new area in a project", { projectId: z.string().describe("ID of the project"), name: z.string().describe("Name of the area"), parentPath: z.string().optional().describe("Path of the parent area") }, async (params, extra) => { const result = await projectTools.createArea(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createIteration", "Create a new iteration in a project", { projectId: z.string().describe("ID of the project"), name: z.string().describe("Name of the iteration"), parentPath: z.string().optional().describe("Path of the parent iteration"), startDate: z.string().optional().describe("Start date of the iteration"), finishDate: z.string().optional().describe("End date of the iteration") }, async (params, extra) => { const result = await projectTools.createIteration(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getProcesses", "Get all processes", { expandIcon: z.boolean().optional().describe("Include process icons") }, async (params, extra) => { const result = await projectTools.getProcesses(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getWorkItemTypes", "Get work item types for a process", { processId: z.string().describe("ID of the process") }, async (params, extra) => { const result = await projectTools.getWorkItemTypes(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getWorkItemTypeFields", "Get fields for a work item type", { processId: z.string().describe("ID of the process"), witRefName: z.string().describe("Reference name of the work item type") }, async (params, extra) => { const result = await projectTools.getWorkItemTypeFields(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); // Register Git Tools server.tool("listRepositories", "List all repositories", { projectId: z.string().optional().describe("Filter by project"), includeHidden: z.boolean().optional().describe("Include hidden repositories"), includeAllUrls: z.boolean().optional().describe("Include all URLs") }, async (params, extra) => { const result = await gitTools.listRepositories(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getRepository", "Get details of a specific repository", { projectId: z.string().describe("ID of the project"), repositoryId: z.string().describe("ID of the repository") }, async (params, extra) => { const result = await gitTools.getRepository(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createRepository", "Create a new repository", { name: z.string().describe("Name of the repository"), projectId: z.string().describe("ID of the project") }, async (params, extra) => { const result = await gitTools.createRepository(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("listBranches", "List branches in a repository", { repositoryId: z.string().describe("ID of the repository"), filter: z.string().optional().describe("Filter branches by name"), top: z.number().optional().describe("Maximum number of branches to return") }, async (params, extra) => { const result = await gitTools.listBranches(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("searchCode", "Search for code in repositories", { searchText: z.string().describe("Text to search for"), projectId: z.string().optional().describe("ID of the project"), repositoryId: z.string().optional().describe("ID of the repository"), fileExtension: z.string().optional().describe("File extension to filter by"), top: z.number().optional().describe("Maximum number of results to return") }, async (params, extra) => { const result = await gitTools.searchCode(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("browseRepository", "Browse the contents of a repository", { repositoryId: z.string().describe("ID of the repository"), path: z.string().optional().describe("Path within the repository"), versionDescriptor: z.object({ version: z.string().optional().describe("Version (branch, tag, or commit)"), versionOptions: z.string().optional().describe("Version options"), versionType: z.string().optional().describe("Version type") }).optional().describe("Version descriptor") }, async (params, extra) => { const result = await gitTools.browseRepository(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getFileContent", "Get the content of a file", { repositoryId: z.string().describe("ID of the repository"), path: z.string().describe("Path to the file"), versionDescriptor: z.object({ version: z.string().optional().describe("Version (branch, tag, or commit)"), versionOptions: z.string().optional().describe("Version options"), versionType: z.string().optional().describe("Version type") }).optional().describe("Version descriptor") }, async (params, extra) => { const result = await gitTools.getFileContent(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getCommitHistory", "Get commit history for a repository", { repositoryId: z.string().describe("ID of the repository"), itemPath: z.string().optional().describe("Path to filter commits by"), top: z.number().optional().describe("Maximum number of commits to return"), skip: z.number().optional().describe("Number of commits to skip") }, async (params, extra) => { const result = await gitTools.getCommitHistory(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("listPullRequests", "List pull requests", { repositoryId: z.string().describe("ID of the repository"), status: z.enum(['abandoned', 'active', 'all', 'completed', 'notSet']).optional().describe("Filter by status"), creatorId: z.string().optional().describe("Filter by creator"), reviewerId: z.string().optional().describe("Filter by reviewer"), top: z.number().optional().describe("Maximum number of pull requests to return"), skip: z.number().optional().describe("Number of pull requests to skip") }, async (params, extra) => { const result = await gitTools.listPullRequests(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createPullRequest", "Create a new pull request", { repositoryId: z.string().describe("ID of the repository"), sourceRefName: z.string().describe("Source branch"), targetRefName: z.string().describe("Target branch"), title: z.string().describe("Title of the pull request"), description: z.string().optional().describe("Description of the pull request"), reviewers: z.array(z.string()).optional().describe("List of reviewers") }, async (params, extra) => { const result = await gitTools.createPullRequest(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getPullRequest", "Get details of a specific pull request", { repositoryId: z.string().describe("ID of the repository"), pullRequestId: z.number().describe("ID of the pull request") }, async (params, extra) => { const result = await gitTools.getPullRequest(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getPullRequestComments", "Get comments on a pull request", { repositoryId: z.string().describe("ID of the repository"), pullRequestId: z.number().describe("ID of the pull request"), threadId: z.number().optional().describe("ID of a specific thread"), top: z.number().optional().describe("Maximum number of comments to return"), skip: z.number().optional().describe("Number of comments to skip") }, async (params, extra) => { const result = await gitTools.getPullRequestComments(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("approvePullRequest", "Approve a pull request", { repositoryId: z.string().describe("ID of the repository"), pullRequestId: z.number().describe("ID of the pull request") }, async (params, extra) => { const result = await gitTools.approvePullRequest(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("mergePullRequest", "Merge a pull request", { repositoryId: z.string().describe("ID of the repository"), pullRequestId: z.number().describe("ID of the pull request"), mergeStrategy: z.enum(['noFastForward', 'rebase', 'rebaseMerge', 'squash']).optional().describe("Merge strategy"), comment: z.string().optional().describe("Comment for the merge commit") }, async (params, extra) => { const result = await gitTools.mergePullRequest(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); // Register Testing Capabilities Tools server.tool("runAutomatedTests", "Execute automated test suites", { testSuiteId: z.number().optional().describe("ID of the test suite to run"), testPlanId: z.number().optional().describe("ID of the test plan to run"), testEnvironment: z.string().optional().describe("Environment to run tests in"), parallelExecution: z.boolean().optional().describe("Whether to run tests in parallel") }, async (params, extra) => { const result = await testingCapabilitiesTools.runAutomatedTests(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getTestAutomationStatus", "Check status of automated test execution", { testRunId: z.number().describe("ID of the test run to check status for") }, async (params, extra) => { const result = await testingCapabilitiesTools.getTestAutomationStatus(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("configureTestAgents", "Configure and manage test agents", { agentName: z.string().describe("Name of the test agent to configure"), capabilities: z.record(z.any()).optional().describe("Capabilities to set for the agent"), enabled: z.boolean().optional().describe("Whether the agent should be enabled") }, async (params, extra) => { const result = await testingCapabilitiesTools.configureTestAgents(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createTestDataGenerator", "Generate test data for automated tests", { name: z.string().describe("Name of the test data generator"), dataSchema: z.record(z.any()).describe("Schema for the test data to generate"), recordCount: z.number().optional().describe("Number of records to generate") }, async (params, extra) => { const result = await testingCapabilitiesTools.createTestDataGenerator(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("manageTestEnvironments", "Manage test environments for different test types", { environmentName: z.string().describe("Name of the test environment"), action: z.enum(['create', 'update', 'delete']).describe("Action to perform"), properties: z.record(z.any()).optional().describe("Properties for the environment") }, async (params, extra) => { const result = await testingCapabilitiesTools.manageTestEnvironments(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getTestFlakiness", "Analyze and report on test flakiness", { testId: z.number().optional().describe("ID of a specific test to analyze"), testRunIds: z.array(z.number()).optional().describe("Specific test runs to analyze"), timeRange: z.string().optional().describe("Time range for analysis (e.g., '30d')") }, async (params, extra) => { const result = await testingCapabilitiesTools.getTestFlakiness(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getTestGapAnalysis", "Identify gaps in test coverage", { areaPath: z.string().optional().describe("Area path to analyze"), codeChangesOnly: z.boolean().optional().describe("Only analyze recent code changes") }, async (params, extra) => { const result = await testingCapabilitiesTools.getTestGapAnalysis(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("runTestImpactAnalysis", "Determine which tests to run based on code changes", { buildId: z.number().describe("ID of the build to analyze"), changedFiles: z.array(z.string()).optional().describe("List of changed files") }, async (params, extra) => { const result = await testingCapabilitiesTools.runTestImpactAnalysis(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getTestHealthDashboard", "View overall test health metrics", { timeRange: z.string().optional().describe("Time range for metrics (e.g., '90d')"), includeTrends: z.boolean().optional().describe("Include trend data") }, async (params, extra) => { const result = await testingCapabilitiesTools.getTestHealthDashboard(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("runTestOptimization", "Optimize test suite execution for faster feedback", { testPlanId: z.number().describe("ID of the test plan to optimize"), optimizationGoal: z.enum(['time', 'coverage', 'reliability']).describe("Optimization goal") }, async (params, extra) => { const result = await testingCapabilitiesTools.runTestOptimization(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createExploratorySessions", "Create new exploratory testing sessions", { title: z.string().describe("Title of the exploratory session"), description: z.string().optional().describe("Description of the session"), areaPath: z.string().optional().describe("Area path for the session") }, async (params, extra) => { const result = await testingCapabilitiesTools.createExploratorySessions(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("recordExploratoryTestResults", "Record findings during exploratory testing", { sessionId: z.number().describe("ID of the exploratory session"), findings: z.array(z.string()).describe("List of findings to record"), attachments: z.array(z.any()).optional().describe("Attachments for the findings") }, async (params, extra) => { const result = await testingCapabilitiesTools.recordExploratoryTestResults(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("convertFindingsToWorkItems", "Convert exploratory test findings to work items", { sessionId: z.number().describe("ID of the exploratory session"), findingIds: z.array(z.number()).describe("IDs of findings to convert"), workItemType: z.string().optional().describe("Type of work item to create") }, async (params, extra) => { const result = await testingCapabilitiesTools.convertFindingsToWorkItems(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getExploratoryTestStatistics", "Get statistics on exploratory testing activities", { timeRange: z.string().optional().describe("Time range for statistics (e.g., '90d')"), userId: z.string().optional().describe("Filter by specific user") }, async (params, extra) => { const result = await testingCapabilitiesTools.getExploratoryTestStatistics(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); // Register DevSecOps Tools server.tool("runSecurityScan", "Run security scans on repositories", { repositoryId: z.string().describe("ID of the repository to scan"), branch: z.string().optional().describe("Branch to scan"), scanType: z.enum(['static', 'dynamic', 'container', 'dependency', 'all']).optional().describe("Type of security scan to run") }, async (params, extra) => { const result = await devSecOpsTools.runSecurityScan(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getSecurityScanResults", "Get results from security scans", { scanId: z.string().describe("ID of the scan to get results for"), severity: z.enum(['critical', 'high', 'medium', 'low', 'all']).optional().describe("Filter results by severity") }, async (params, extra) => { const result = await devSecOpsTools.getSecurityScanResults(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("trackSecurityVulnerabilities", "Track and manage security vulnerabilities", { vulnerabilityId: z.string().optional().describe("ID of a specific vulnerability to track"), status: z.enum(['open', 'in-progress', 'mitigated', 'resolved', 'false-positive']).optional().describe("Filter by vulnerability status"), timeRange: z.string().optional().describe("Time range for tracking (e.g., '90d')") }, async (params, extra) => { const result = await devSecOpsTools.trackSecurityVulnerabilities(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("generateSecurityCompliance", "Generate security compliance reports", { standardType: z.enum(['owasp', 'pci-dss', 'hipaa', 'gdpr', 'iso27001', 'custom']).optional().describe("Compliance standard to report on"), includeEvidence: z.boolean().optional().describe("Include evidence in the report") }, async (params, extra) => { const result = await devSecOpsTools.generateSecurityCompliance(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("integrateSarifResults", "Import and process SARIF format security results", { sarifFilePath: z.string().describe("Path to the SARIF file to import"), createWorkItems: z.boolean().optional().describe("Create work items from findings") }, async (params, extra) => { const result = await devSecOpsTools.integrateSarifResults(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("runComplianceChecks", "Run compliance checks against standards", { complianceStandard: z.string().describe("Compliance standard to check against"), scopeId: z.string().optional().describe("Scope of the compliance check") }, async (params, extra) => { const result = await devSecOpsTools.runComplianceChecks(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getComplianceStatus", "Get current compliance status", { standardId: z.string().optional().describe("ID of the compliance standard"), includeHistory: z.boolean().optional().describe("Include historical compliance data") }, async (params, extra) => { const result = await devSecOpsTools.getComplianceStatus(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createComplianceReport", "Create compliance reports for auditing", { standardId: z.string().describe("ID of the compliance standard"), format: z.enum(['pdf', 'html', 'json']).optional().describe("Format of the report") }, async (params, extra) => { const result = await devSecOpsTools.createComplianceReport(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("manageSecurityPolicies", "Manage security policies", { policyName: z.string().describe("Name of the security policy"), action: z.enum(['create', 'update', 'delete', 'get']).describe("Action to perform on the policy"), policyDefinition: z.record(z.any()).optional().describe("Definition of the policy") }, async (params, extra) => { const result = await devSecOpsTools.manageSecurityPolicies(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("trackSecurityAwareness", "Track security awareness and training", { teamId: z.string().optional().describe("ID of the team to track"), trainingId: z.string().optional().describe("ID of specific training to track"), timeRange: z.string().optional().describe("Time range for tracking (e.g., '90d')") }, async (params, extra) => { const result = await devSecOpsTools.trackSecurityAwareness(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("rotateSecrets", "Rotate secrets and credentials", { secretName: z.string().optional().describe("Name of the secret to rotate"), secretType: z.enum(['password', 'token', 'certificate', 'key']).optional().describe("Type of secret to rotate"), force: z.boolean().optional().describe("Force rotation even if not expired") }, async (params, extra) => { const result = await devSecOpsTools.rotateSecrets(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("auditSecretUsage", "Audit usage of secrets across services", { secretName: z.string().optional().describe("Name of the secret to audit"), timeRange: z.string().optional().describe("Time range for the audit (e.g., '30d')") }, async (params, extra) => { const result = await devSecOpsTools.auditSecretUsage(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("vaultIntegration", "Integrate with secret vaults", { vaultUrl: z.string().describe("URL of the vault to integrate with"), secretPath: z.string().optional().describe("Path to the secret in the vault"), action: z.enum(['get', 'list', 'set', 'delete']).describe("Action to perform"), secretValue: z.string().optional().describe("Value to set (for 'set' action)") }, async (params, extra) => { const result = await devSecOpsTools.vaultIntegration(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); // Register ArtifactManagement Tools server.tool("listArtifactFeeds", "List artifact feeds in the organization", { feedType: z.enum(['npm', 'nuget', 'maven', 'python', 'universal', 'all']).optional().describe("Type of feeds to list"), includeDeleted: z.boolean().optional().describe("Include deleted feeds") }, async (params, extra) => { const result = await artifactManagementTools.listArtifactFeeds(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getPackageVersions", "Get versions of a package in a feed", { feedId: z.string().describe("ID of the feed"), packageName: z.string().describe("Name of the package"), top: z.number().optional().describe("Maximum number of versions to return") }, async (params, extra) => { const result = await artifactManagementTools.getPackageVersions(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("publishPackage", "Publish a package to a feed", { feedId: z.string().describe("ID of the feed to publish to"), packageType: z.enum(['npm', 'nuget', 'maven', 'python', 'universal']).describe("Type of package"), packagePath: z.string().describe("Path to the package file"), packageVersion: z.string().optional().describe("Version of the package") }, async (params, extra) => { const result = await artifactManagementTools.publishPackage(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("promotePackage", "Promote a package version between views", { feedId: z.string().describe("ID of the feed"), packageName: z.string().describe("Name of the package"), packageVersion: z.string().describe("Version of the package"), sourceView: z.string().describe("Source view (e.g., 'prerelease')"), targetView: z.string().describe("Target view (e.g., 'release')") }, async (params, extra) => { const result = await artifactManagementTools.promotePackage(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("deletePackageVersion", "Delete a version of a package", { feedId: z.string().describe("ID of the feed"), packageName: z.string().describe("Name of the package"), packageVersion: z.string().describe("Version of the package to delete"), permanent: z.boolean().optional().describe("Permanently delete the package version") }, async (params, extra) => { const result = await artifactManagementTools.deletePackageVersion(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("listContainerImages", "List container images in a repository", { repositoryName: z.string().optional().describe("Name of the container repository"), includeManifests: z.boolean().optional().describe("Include image manifests"), includeDeleted: z.boolean().optional().describe("Include deleted images") }, async (params, extra) => { const result = await artifactManagementTools.listContainerImages(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("getContainerImageTags", "Get tags for a container image", { repositoryName: z.string().describe("Name of the container repository"), imageName: z.string().describe("Name of the container image"), top: z.number().optional().describe("Maximum number of tags to return") }, async (params, extra) => { const result = await artifactManagementTools.getContainerImageTags(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("scanContainerImage", "Scan a container image for vulnerabilities and compliance issues", { repositoryName: z.string().describe("Name of the container repository"), imageTag: z.string().describe("Tag of the container image to scan"), scanType: z.enum(['vulnerability', 'compliance', 'both']).optional().describe("Type of scan to perform") }, async (params, extra) => { const result = await artifactManagementTools.scanContainerImage(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("manageContainerPolicies", "Manage policies for container repositories", { repositoryName: z.string().describe("Name of the container repository"), policyType: z.enum(['retention', 'security', 'access']).describe("Type of policy to manage"), action: z.enum(['get', 'set', 'delete']).describe("Action to perform on the policy"), policySettings: z.record(z.any()).optional().describe("Settings for the policy when setting") }, async (params, extra) => { const result = await artifactManagementTools.manageContainerPolicies(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("manageUniversalPackages", "Manage universal packages", { packageName: z.string().describe("Name of the universal package"), action: z.enum(['download', 'upload', 'delete']).describe("Action to perform"), packagePath: z.string().optional().describe("Path for package upload or download"), packageVersion: z.string().optional().describe("Version of the package") }, async (params, extra) => { const result = await artifactManagementTools.manageUniversalPackages(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("createPackageDownloadReport", "Create reports on package downloads", { feedId: z.string().optional().describe("ID of the feed"), packageName: z.string().optional().describe("Name of the package"), timeRange: z.string().optional().describe("Time range for the report (e.g., '30d')"), format: z.enum(['csv', 'json']).optional().describe("Format of the report") }, async (params, extra) => { const result = await artifactManagementTools.createPackageDownloadReport(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); server.tool("checkPackageDependencies", "Check package dependencies and vulnerabilities", { packageName: z.string().describe("Name of the package to check"), packageVersion: z.string().optional().describe("Version of the package"), includeTransitive: z.boolean().optional().describe("Include transitive dependencies"), checkVulnerabilities: z.boolean().optional().describe("Check for known vulnerabilities") }, async (params, extra) => { const result = await artifactManagementTools.checkPackageDependencies(params); return { content: result.content, rawData: result.rawData, isError: result.isError }; } ); // AI Assisted Development Tools server.tool("getAICodeReview", "Get AI-based code review suggestions", { pullRequestId: z.number().optional().describe("ID of the pull request to review"), repositoryId: z.string().optional().describe("ID of the repository"), commitId: z.string().optional().describe("ID of the commit to review"), filePath: z.string().optional().describe("Path to the file to review") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.getAICodeReview(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("suggestCodeOptimization", "Suggest code optimizations using AI", { repositoryId: z.string().describe("ID of the repository"), filePath: z.string().describe("Path to the file to optimize"), lineStart: z.number().optional().describe("Starting line number"), lineEnd: z.number().optional().describe("Ending line number"), optimizationType: z.enum(['performance', 'memory', 'readability', 'all']).optional().describe("Type of optimization to focus on") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.suggestCodeOptimization(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("identifyCodeSmells", "Identify potential code smells and anti-patterns", { repositoryId: z.string().describe("ID of the repository"), branch: z.string().optional().describe("Branch to analyze"), filePath: z.string().optional().describe("Path to the file to analyze"), severity: z.enum(['high', 'medium', 'low', 'all']).optional().describe("Severity level to filter by") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.identifyCodeSmells(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("getPredictiveBugAnalysis", "Predict potential bugs in code changes", { repositoryId: z.string().describe("ID of the repository"), pullRequestId: z.number().optional().describe("ID of the pull request"), branch: z.string().optional().describe("Branch to analyze"), filePath: z.string().optional().describe("Path to the file to analyze") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.getPredictiveBugAnalysis(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("getDeveloperProductivity", "Measure developer productivity metrics", { userId: z.string().optional().describe("ID of the user"), teamId: z.string().optional().describe("ID of the team"), timeRange: z.string().optional().describe("Time range for analysis (e.g., '30d', '3m')"), includeMetrics: z.array(z.string()).optional().describe("Specific metrics to include") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.getDeveloperProductivity(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("getPredictiveEffortEstimation", "AI-based effort estimation for work items", { workItemIds: z.array(z.number()).optional().describe("IDs of work items to estimate"), workItemType: z.string().optional().describe("Type of work items to estimate"), areaPath: z.string().optional().describe("Area path to filter work items") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.getPredictiveEffortEstimation(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("getCodeQualityTrends", "Track code quality trends over time", { repositoryId: z.string().optional().describe("ID of the repository"), branch: z.string().optional().describe("Branch to analyze"), timeRange: z.string().optional().describe("Time range for analysis (e.g., '90d', '6m')"), metrics: z.array(z.string()).optional().describe("Specific metrics to include") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.getCodeQualityTrends(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("suggestWorkItemRefinements", "Get AI suggestions for work item refinements", { workItemId: z.number().optional().describe("ID of the work item to refine"), workItemType: z.string().optional().describe("Type of work item"), areaPath: z.string().optional().describe("Area path to filter work items") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.suggestWorkItemRefinements(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("suggestAutomationOpportunities", "Identify opportunities for automation", { projectId: z.string().optional().describe("ID of the project"), scopeType: z.enum(['builds', 'releases', 'tests', 'workitems', 'all']).optional().describe("Type of scope to analyze") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.suggestAutomationOpportunities(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("createIntelligentAlerts", "Set up intelligent alerts based on patterns", { alertName: z.string().describe("Name of the alert"), alertType: z.enum(['build', 'release', 'test', 'workitem', 'code']).describe("Type of alert to create"), conditions: z.record(z.any()).describe("Conditions for the alert"), actions: z.record(z.any()).optional().describe("Actions to take when the alert triggers") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.createIntelligentAlerts(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("predictBuildFailures", "Predict potential build failures before they occur", { buildDefinitionId: z.number().describe("ID of the build definition"), lookbackPeriod: z.string().optional().describe("Period to analyze for patterns (e.g., '30d')") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.predictBuildFailures(params); return { content: result.content, rawData: result.rawData, }; } ); server.tool("optimizeTestSelection", "Intelligently select tests to run based on changes", { buildId: z.number().describe("ID of the build"), changedFiles: z.array(z.string()).optional().describe("List of changed files"), maxTestCount: z.number().optional().describe("Maximum number of tests to select") }, async (params, extra) => { const result = await aiAssistedDevelopmentTools.optimizeTestSelection(params); return { content: result.content, rawData: result.rawData, }; } ); console.log(`Registered tools`); // Create a transport (use stdio for simplicity) console.log('Creating StdioServerTransport'); const transport = new StdioServerTransport(); // Connect to the transport and start listening console.log('Connecting to transport...'); await server.connect(transport); console.log('Connected to transport'); } catch (error) { console.error('Error starting MCP server:', error); if (error instanceof Error) { console.error('Stack trace:', error.stack); } process.exit(1); } } // Set an environment variable to indicate we're in MCP mode // This helps prevent console.log from interfering with stdio communication process.env.MCP_MODE = 'true'; // Run the server main();