@veracity/codeguardian-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +141 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/ado.d.ts +2 -0
- package/dist/tools/ado.d.ts.map +1 -0
- package/dist/tools/ado.js +291 -0
- package/dist/tools/ado.js.map +1 -0
- package/dist/tools/basic.d.ts +9 -0
- package/dist/tools/basic.d.ts.map +1 -0
- package/dist/tools/basic.js +68 -0
- package/dist/tools/basic.js.map +1 -0
- package/dist/tools.d.ts +3 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +6 -0
- package/dist/tools.js.map +1 -0
- package/package.json +66 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 DNV
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# CodeGuardian MCP Server
|
|
2
|
+
|
|
3
|
+
A Model Context Protocol (MCP) server implementation with Azure DevOps integration.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
This MCP server provides the following tools:
|
|
8
|
+
|
|
9
|
+
### Azure DevOps Tools
|
|
10
|
+
|
|
11
|
+
1. **ado_get_pull_request_changes** - Get detailed file changes for an Azure DevOps pull request
|
|
12
|
+
- Parameters:
|
|
13
|
+
- `organization` (required): Azure DevOps organization name (e.g., "myorg")
|
|
14
|
+
- `project` (required): Azure DevOps project name (e.g., "myproject")
|
|
15
|
+
- `repositoryId` (required): Repository identifier (can be name or GUID)
|
|
16
|
+
- `pullRequestId` (required): Pull request ID number
|
|
17
|
+
- Returns: Detailed pull request information including file changes, diffs, and source content
|
|
18
|
+
- **Authentication Required**: Azure CLI login or Azure credentials must be configured
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
- Node.js 18 or higher
|
|
23
|
+
- npm or yarn package manager
|
|
24
|
+
- **For Azure DevOps tools**: Azure CLI logged in or Azure credentials configured
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
1. Install dependencies:
|
|
29
|
+
```powershell
|
|
30
|
+
npm install
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
2. Build the project:
|
|
34
|
+
```powershell
|
|
35
|
+
npm run build
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
3. Run the server:
|
|
39
|
+
```powershell
|
|
40
|
+
npm start
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Development
|
|
44
|
+
|
|
45
|
+
1. Start development mode with auto-rebuild:
|
|
46
|
+
```powershell
|
|
47
|
+
npm run dev
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
2. Run tests:
|
|
51
|
+
```powershell
|
|
52
|
+
npm test
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
3. Lint code:
|
|
56
|
+
```powershell
|
|
57
|
+
npm run lint
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Usage with VS Code
|
|
61
|
+
|
|
62
|
+
To use this MCP server with VS Code, create a `.vscode/mcp.json` file in your project:
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{
|
|
66
|
+
"servers": {
|
|
67
|
+
"codeguardian": {
|
|
68
|
+
"type": "stdio",
|
|
69
|
+
"command": "node",
|
|
70
|
+
"args": ["path/to/CodeGuardian-mcp/dist/index.js"]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Or if you have it installed globally:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"servers": {
|
|
81
|
+
"codeguardian": {
|
|
82
|
+
"type": "stdio",
|
|
83
|
+
"command": "codeguardian-mcp"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Project Structure
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
src/
|
|
93
|
+
├── index.ts # Main entry point
|
|
94
|
+
├── tools.ts # Tool configuration orchestrator
|
|
95
|
+
└── tools/
|
|
96
|
+
└── basic.ts # Basic tools including helloworld
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Adding New Tools
|
|
100
|
+
|
|
101
|
+
To add new tools:
|
|
102
|
+
|
|
103
|
+
1. Create a new file in `src/tools/` (e.g., `custom.ts`)
|
|
104
|
+
2. Define your tools using the same pattern as in `basic.ts`
|
|
105
|
+
3. Import and configure them in `src/tools.ts`
|
|
106
|
+
|
|
107
|
+
Example tool structure:
|
|
108
|
+
```typescript
|
|
109
|
+
server.tool(
|
|
110
|
+
"tool_name",
|
|
111
|
+
"Tool description",
|
|
112
|
+
{
|
|
113
|
+
param1: z.string().describe("Parameter description"),
|
|
114
|
+
param2: z.number().optional().describe("Optional parameter"),
|
|
115
|
+
},
|
|
116
|
+
async ({ param1, param2 }) => {
|
|
117
|
+
// Tool implementation
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
{
|
|
121
|
+
type: "text",
|
|
122
|
+
text: "Tool response",
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Contributing
|
|
131
|
+
|
|
132
|
+
1. Fork the repository
|
|
133
|
+
2. Create a feature branch
|
|
134
|
+
3. Make your changes
|
|
135
|
+
4. Add tests if applicable
|
|
136
|
+
5. Run `npm run lint` and `npm test`
|
|
137
|
+
6. Submit a pull request
|
|
138
|
+
|
|
139
|
+
## License
|
|
140
|
+
|
|
141
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { configureAllTools } from "./tools.js";
|
|
5
|
+
const packageVersion = "1.0.0";
|
|
6
|
+
async function main() {
|
|
7
|
+
const server = new McpServer({
|
|
8
|
+
name: "CodeGuardian MCP Server",
|
|
9
|
+
version: packageVersion,
|
|
10
|
+
});
|
|
11
|
+
// Configure all tools
|
|
12
|
+
configureAllTools(server);
|
|
13
|
+
// Connect using stdio transport
|
|
14
|
+
const transport = new StdioServerTransport();
|
|
15
|
+
await server.connect(transport);
|
|
16
|
+
console.error("CodeGuardian MCP Server running on stdio");
|
|
17
|
+
}
|
|
18
|
+
main().catch((error) => {
|
|
19
|
+
console.error("Fatal error in main():", error);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,cAAc;KACxB,CAAC,CAAC;IAEH,sBAAsB;IACtB,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE1B,gCAAgC;IAChC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;AAC5D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ado.d.ts","sourceRoot":"","sources":["../../src/tools/ado.ts"],"names":[],"mappings":"AA8QA,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,GAAG,QAwG5C"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import * as azdev from 'azure-devops-node-api';
|
|
2
|
+
import { DefaultAzureCredential } from '@azure/identity';
|
|
3
|
+
import * as diff from 'diff';
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
// Helper function to create Azure DevOps connection
|
|
6
|
+
async function getAzureDevOpsConnection(organization) {
|
|
7
|
+
// Use DefaultAzureCredential to get a token
|
|
8
|
+
const credential = new DefaultAzureCredential();
|
|
9
|
+
const token = await credential.getToken('499b84ac-1321-427f-aa17-267ca6975798/.default');
|
|
10
|
+
if (!token) {
|
|
11
|
+
throw new Error('Failed to obtain Azure DevOps token. Ensure you have Azure CLI logged in or another token source setup correctly.');
|
|
12
|
+
}
|
|
13
|
+
const authHandler = azdev.getBearerHandler(token.token);
|
|
14
|
+
const orgUrl = `https://dev.azure.com/${organization}`;
|
|
15
|
+
return new azdev.WebApi(orgUrl, authHandler);
|
|
16
|
+
}
|
|
17
|
+
// Shared utility functions
|
|
18
|
+
function isValidFilePath(filePath) {
|
|
19
|
+
if (!filePath) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
// Filter out common binary files and problematic paths
|
|
23
|
+
const lowercasePath = filePath.toLowerCase();
|
|
24
|
+
// Skip binary files
|
|
25
|
+
const binaryExtensions = ['.exe', '.dll', '.bin', '.zip', '.tar', '.gz', '.7z', '.rar',
|
|
26
|
+
'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.ico', '.pdf', '.doc', '.docx'];
|
|
27
|
+
if (binaryExtensions.some(ext => lowercasePath.endsWith(ext))) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
// Skip very long paths (might cause issues)
|
|
31
|
+
if (filePath.length > 260) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// Skip paths with special characters that might cause issues
|
|
35
|
+
if (filePath.includes('..') || filePath.includes('//')) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
async function checkItemExists(gitApi, project, repositoryId, filePath, versionDescriptor) {
|
|
41
|
+
try {
|
|
42
|
+
const result = await gitApi.getItem(repositoryId, filePath, project, undefined, // scopePath
|
|
43
|
+
undefined, // recursionLevel
|
|
44
|
+
false, // includeContentMetadata
|
|
45
|
+
false, // latestProcessedChange
|
|
46
|
+
false, // download
|
|
47
|
+
versionDescriptor);
|
|
48
|
+
// Extra safety: check if result exists and has expected properties
|
|
49
|
+
return !!result?.path;
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
53
|
+
console.debug(`Item check failed for ${filePath}: ${errorMessage}`);
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function streamToString(stream) {
|
|
58
|
+
const chunks = [];
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
|
|
61
|
+
stream.on('error', (err) => reject(new Error(`Stream error: ${err}`)));
|
|
62
|
+
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Clean file content to handle special characters that can affect line counting and processing
|
|
67
|
+
* @param content Raw file content
|
|
68
|
+
* @returns Cleaned content
|
|
69
|
+
*/
|
|
70
|
+
function cleanFileContent(content) {
|
|
71
|
+
if (!content) {
|
|
72
|
+
return '';
|
|
73
|
+
}
|
|
74
|
+
return content
|
|
75
|
+
// Remove UTF-8 BOM if present at the beginning
|
|
76
|
+
.replace(/^\uFEFF/, '')
|
|
77
|
+
// Remove UTF-16 BE BOM
|
|
78
|
+
.replace(/^\uFFFE/, '')
|
|
79
|
+
// Remove Zero Width No-Break Space (can appear as BOM in some cases)
|
|
80
|
+
.replace(/^\u2FEFF/, '');
|
|
81
|
+
}
|
|
82
|
+
async function getFileContentAtCommit(gitApi, project, repositoryId, filePath, commitId) {
|
|
83
|
+
if (!filePath) {
|
|
84
|
+
return '';
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const versionDescriptor = {
|
|
88
|
+
version: commitId,
|
|
89
|
+
versionType: 2 // GitVersionType.Commit
|
|
90
|
+
};
|
|
91
|
+
// Check if item exists first
|
|
92
|
+
const itemExists = await checkItemExists(gitApi, project, repositoryId, filePath, versionDescriptor);
|
|
93
|
+
if (!itemExists) {
|
|
94
|
+
console.warn(`File ${filePath} does not exist at commit ${commitId}`);
|
|
95
|
+
return '';
|
|
96
|
+
}
|
|
97
|
+
const stream = await gitApi.getItemContent(repositoryId, filePath, project, undefined, // scopePath
|
|
98
|
+
undefined, // recursionLevel
|
|
99
|
+
false, // includeContentMetadata
|
|
100
|
+
false, // latestProcessedChange
|
|
101
|
+
false, // download
|
|
102
|
+
versionDescriptor);
|
|
103
|
+
if (stream) {
|
|
104
|
+
const content = await streamToString(stream);
|
|
105
|
+
// Clean up content to handle special characters that affect line counting
|
|
106
|
+
return cleanFileContent(content);
|
|
107
|
+
}
|
|
108
|
+
return '';
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
// Handle specific Azure DevOps error codes
|
|
112
|
+
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
113
|
+
if (errorMessage.includes('VS403420') || errorMessage.includes('does not exist at the specified version')) {
|
|
114
|
+
console.warn(`File ${filePath} does not exist at commit ${commitId} or access denied`);
|
|
115
|
+
return '';
|
|
116
|
+
}
|
|
117
|
+
else if (errorMessage.includes('VS403404') || errorMessage.includes('not found')) {
|
|
118
|
+
console.warn(`File ${filePath} not found at commit ${commitId}`);
|
|
119
|
+
return '';
|
|
120
|
+
}
|
|
121
|
+
else if (errorMessage.includes('VS401401') || errorMessage.includes('Unauthorized')) {
|
|
122
|
+
console.warn(`Unauthorized access to file ${filePath} at commit ${commitId}`);
|
|
123
|
+
return '';
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
console.warn(`Could not get content for ${filePath} at commit ${commitId}:`, errorMessage);
|
|
127
|
+
return '';
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async function getPullRequestFileChanges(gitApi, project, repositoryId, targetBranchCommit, sourceBranchCommit, commits) {
|
|
132
|
+
try {
|
|
133
|
+
// Step 1: Iterate through all commits in the PR to get all changed files
|
|
134
|
+
const allChangedFiles = new Set();
|
|
135
|
+
console.log(`Processing ${commits.length} commits in the pull request`);
|
|
136
|
+
for (const commit of commits) {
|
|
137
|
+
try {
|
|
138
|
+
const commitChanges = await gitApi.getChanges(commit.commitId, repositoryId, project, 50);
|
|
139
|
+
commitChanges?.changes?.forEach((change) => {
|
|
140
|
+
// Only add files that exist (not deleted), skip folders and other git objects
|
|
141
|
+
// GitObjectType: 1=Tree(folder), 2=Commit, 3=Blob(file), 4=Tag
|
|
142
|
+
// ChangeType: 1=Add, 2=Edit, 16=Delete, 32=Undelete, 64=Branch, 128=Merge, 256=Edit+Rename, etc.
|
|
143
|
+
if (change.item?.path && change.item?.gitObjectType === "blob" && change.changeType !== 128 && isValidFilePath(change.item.path)) {
|
|
144
|
+
if (change.changeType === 16) {
|
|
145
|
+
// Remove deleted files from allChangedFiles
|
|
146
|
+
if (allChangedFiles.has(change.item.path)) {
|
|
147
|
+
allChangedFiles.delete(change.item.path);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// Add non-deleted files
|
|
152
|
+
allChangedFiles.add(change.item.path);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
console.warn(`Failed to get changes for commit ${commit.commitId}:`, error);
|
|
159
|
+
// Continue with other commits even if one fails
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (allChangedFiles.size === 0) {
|
|
163
|
+
return {
|
|
164
|
+
filesChanged: 0,
|
|
165
|
+
files: [],
|
|
166
|
+
message: "No valid files found to be changed in the pull request commits."
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
console.log(`Found ${allChangedFiles.size} unique files changed across all commits`);
|
|
170
|
+
// Step 2: Limit to 10 files for API constraints
|
|
171
|
+
const filePaths = Array.from(allChangedFiles).slice(0, 50);
|
|
172
|
+
// Step 3: For each file, get content from source and target branches and generate diff
|
|
173
|
+
const filesWithContent = await Promise.all(filePaths.map(async (filePath) => {
|
|
174
|
+
try {
|
|
175
|
+
// Get file content from target branch (usually main/master)
|
|
176
|
+
const targetBranchContent = await getFileContentAtCommit(gitApi, project, repositoryId, filePath, targetBranchCommit);
|
|
177
|
+
// Get file content from source branch (the feature branch)
|
|
178
|
+
const sourceBranchContent = await getFileContentAtCommit(gitApi, project, repositoryId, filePath, sourceBranchCommit);
|
|
179
|
+
// Generate unified diff using the diff npm package
|
|
180
|
+
const diffPatches = diff.createPatch(filePath, targetBranchContent || '', sourceBranchContent || '', 'a/' + filePath, 'b/' + filePath);
|
|
181
|
+
const diffContent = diffPatches;
|
|
182
|
+
return {
|
|
183
|
+
file: filePath,
|
|
184
|
+
// targetBranchContent: targetBranchContent,
|
|
185
|
+
source: sourceBranchContent,
|
|
186
|
+
diff: diffContent,
|
|
187
|
+
// hasChanges: targetBranchContent !== sourceBranchContent,
|
|
188
|
+
// changeType: this.determineChangeType(targetBranchContent, sourceBranchContent)
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
193
|
+
console.warn(`Error processing file ${filePath}:`, errorMessage);
|
|
194
|
+
return {
|
|
195
|
+
filePath: filePath,
|
|
196
|
+
error: `Failed to get content: ${errorMessage}`,
|
|
197
|
+
note: errorMessage.includes('VS403420') ?
|
|
198
|
+
'File may not exist at the specified commit version or access denied' :
|
|
199
|
+
'Unknown error occurred while retrieving file content'
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}));
|
|
203
|
+
return {
|
|
204
|
+
filesChanged: filePaths.length,
|
|
205
|
+
totalFilesFound: allChangedFiles.size,
|
|
206
|
+
commitsProcessed: commits.length,
|
|
207
|
+
files: filesWithContent.filter(f => f !== null)
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
throw new Error(`Failed to get pull request file changes: ${error instanceof Error ? error.message : String(error)}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// MCP server tool configuration
|
|
215
|
+
export function configureAdoTools(server) {
|
|
216
|
+
server.tool("repo_get_pullrequest_changes_by_id", "Retrieve all file changes and diffs from a pull request by iterating through all commits in the PR", {
|
|
217
|
+
organization: z.string().describe("Azure DevOps organization name (e.g., 'myorg')"),
|
|
218
|
+
project: z.string().describe("The name or ID of the Azure DevOps project."),
|
|
219
|
+
repositoryId: z.string().describe("The ID of the repository where the pull requests are located."),
|
|
220
|
+
pullRequestId: z.string().describe("Pull request ID number")
|
|
221
|
+
}, async (args) => {
|
|
222
|
+
try {
|
|
223
|
+
const { organization, project, repositoryId, pullRequestId } = args;
|
|
224
|
+
// Validate required parameters
|
|
225
|
+
if (!organization || !project || !repositoryId || !pullRequestId) {
|
|
226
|
+
throw new Error('Missing required parameters. Please provide organization, project, repositoryId, and pullRequestId.');
|
|
227
|
+
}
|
|
228
|
+
// Get Azure DevOps connection
|
|
229
|
+
const connection = await getAzureDevOpsConnection(organization);
|
|
230
|
+
const gitApi = await connection.getGitApi();
|
|
231
|
+
// Get pull request details
|
|
232
|
+
const pullRequest = await gitApi.getPullRequest(repositoryId, pullRequestId, project);
|
|
233
|
+
if (!pullRequest) {
|
|
234
|
+
throw new Error(`Pull request ${pullRequestId} not found in repository ${repositoryId}`);
|
|
235
|
+
}
|
|
236
|
+
// Get all commits in the pull request
|
|
237
|
+
const commits = await gitApi.getPullRequestCommits(repositoryId, pullRequestId, project);
|
|
238
|
+
if (!commits || commits.length === 0) {
|
|
239
|
+
return {
|
|
240
|
+
content: [{
|
|
241
|
+
type: "text",
|
|
242
|
+
text: `No commits found in pull request ${pullRequestId}`
|
|
243
|
+
}]
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
// Sort commits by committer date in ascending order (oldest first)
|
|
247
|
+
commits.sort((a, b) => {
|
|
248
|
+
const dateA = new Date(a.committer?.date || a.author?.date || 0);
|
|
249
|
+
const dateB = new Date(b.committer?.date || b.author?.date || 0);
|
|
250
|
+
return dateA.getTime() - dateB.getTime();
|
|
251
|
+
});
|
|
252
|
+
// Get the source and target branch commit IDs
|
|
253
|
+
const sourceBranchCommit = pullRequest.lastMergeSourceCommit?.commitId;
|
|
254
|
+
const targetBranchCommit = pullRequest.lastMergeTargetCommit?.commitId;
|
|
255
|
+
if (!sourceBranchCommit || !targetBranchCommit) {
|
|
256
|
+
throw new Error(`Could not determine source or target commit for pull request ${pullRequestId}`);
|
|
257
|
+
}
|
|
258
|
+
// Get file changes between source and target branches
|
|
259
|
+
const fileChanges = await getPullRequestFileChanges(gitApi, project, repositoryId, targetBranchCommit, sourceBranchCommit, commits);
|
|
260
|
+
const response = {
|
|
261
|
+
type: 'pullRequestChanges',
|
|
262
|
+
pullRequestId: pullRequest.pullRequestId,
|
|
263
|
+
organization: organization,
|
|
264
|
+
project: project,
|
|
265
|
+
repositoryId: repositoryId,
|
|
266
|
+
summary: {
|
|
267
|
+
filesChanged: fileChanges.filesChanged,
|
|
268
|
+
totalFilesFound: fileChanges.totalFilesFound,
|
|
269
|
+
commitsProcessed: fileChanges.commitsProcessed
|
|
270
|
+
},
|
|
271
|
+
files: fileChanges.files
|
|
272
|
+
};
|
|
273
|
+
return {
|
|
274
|
+
content: [{
|
|
275
|
+
type: "text",
|
|
276
|
+
text: JSON.stringify(response, null, 2)
|
|
277
|
+
}]
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
282
|
+
return {
|
|
283
|
+
content: [{
|
|
284
|
+
type: "text",
|
|
285
|
+
text: `Error getting pull request changes: ${errorMessage}`
|
|
286
|
+
}]
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=ado.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ado.js","sourceRoot":"","sources":["../../src/tools/ado.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
declare const BASIC_TOOLS: {
|
|
3
|
+
helloworld: string;
|
|
4
|
+
echo: string;
|
|
5
|
+
get_current_time: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function configureBasicTools(server: McpServer): void;
|
|
8
|
+
export { BASIC_TOOLS };
|
|
9
|
+
//# sourceMappingURL=basic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basic.d.ts","sourceRoot":"","sources":["../../src/tools/basic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,QAAA,MAAM,WAAW;;;;CAIhB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgF3D;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const BASIC_TOOLS = {
|
|
3
|
+
helloworld: "basic_helloworld",
|
|
4
|
+
echo: "basic_echo",
|
|
5
|
+
get_current_time: "basic_get_current_time",
|
|
6
|
+
};
|
|
7
|
+
export function configureBasicTools(server) {
|
|
8
|
+
// Helloworld tool - returns a simple greeting message
|
|
9
|
+
server.tool(BASIC_TOOLS.helloworld, "Returns a friendly greeting message with optional name parameter", {
|
|
10
|
+
name: z.string().optional().describe("Optional name to include in the greeting"),
|
|
11
|
+
}, async ({ name }) => {
|
|
12
|
+
const greeting = name ? `Hello, ${name}!` : "Hello, World!";
|
|
13
|
+
const message = `${greeting} Welcome to the CodeGuardian MCP Server. This is a simple demonstration tool.`;
|
|
14
|
+
return {
|
|
15
|
+
content: [
|
|
16
|
+
{
|
|
17
|
+
type: "text",
|
|
18
|
+
text: message,
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
// Echo tool - echoes back the input text
|
|
24
|
+
server.tool(BASIC_TOOLS.echo, "Echoes back the provided text", {
|
|
25
|
+
text: z.string().describe("The text to echo back"),
|
|
26
|
+
uppercase: z.boolean().optional().default(false).describe("Whether to return the text in uppercase"),
|
|
27
|
+
}, async ({ text, uppercase }) => {
|
|
28
|
+
const result = uppercase ? text.toUpperCase() : text;
|
|
29
|
+
return {
|
|
30
|
+
content: [
|
|
31
|
+
{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: `Echo: ${result}`,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
// Get current time tool
|
|
39
|
+
server.tool(BASIC_TOOLS.get_current_time, "Returns the current date and time", {
|
|
40
|
+
format: z.enum(["iso", "locale", "timestamp"]).optional().default("iso").describe("The format for the returned time"),
|
|
41
|
+
}, async ({ format }) => {
|
|
42
|
+
const now = new Date();
|
|
43
|
+
let timeString;
|
|
44
|
+
switch (format) {
|
|
45
|
+
case "iso":
|
|
46
|
+
timeString = now.toISOString();
|
|
47
|
+
break;
|
|
48
|
+
case "locale":
|
|
49
|
+
timeString = now.toLocaleString();
|
|
50
|
+
break;
|
|
51
|
+
case "timestamp":
|
|
52
|
+
timeString = now.getTime().toString();
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
timeString = now.toISOString();
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
content: [
|
|
59
|
+
{
|
|
60
|
+
type: "text",
|
|
61
|
+
text: `Current time (${format}): ${timeString}`,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
export { BASIC_TOOLS };
|
|
68
|
+
//# sourceMappingURL=basic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basic.js","sourceRoot":"","sources":["../../src/tools/basic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,WAAW,GAAG;IAClB,UAAU,EAAE,kBAAkB;IAC9B,IAAI,EAAE,YAAY;IAClB,gBAAgB,EAAE,wBAAwB;CAC3C,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,sDAAsD;IACtD,MAAM,CAAC,IAAI,CACT,WAAW,CAAC,UAAU,EACtB,kEAAkE,EAClE;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;KACjF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC;QAC5D,MAAM,OAAO,GAAG,GAAG,QAAQ,+EAA+E,CAAC;QAE3G,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,OAAO;iBACd;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,yCAAyC;IACzC,MAAM,CAAC,IAAI,CACT,WAAW,CAAC,IAAI,EAChB,+BAA+B,EAC/B;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QAClD,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,yCAAyC,CAAC;KACrG,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE;QAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAErD,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,SAAS,MAAM,EAAE;iBACxB;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,wBAAwB;IACxB,MAAM,CAAC,IAAI,CACT,WAAW,CAAC,gBAAgB,EAC5B,mCAAmC,EACnC;QACE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,kCAAkC,CAAC;KACtH,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QACnB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,UAAkB,CAAC;QAEvB,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,KAAK;gBACR,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;gBAC/B,MAAM;YACR,KAAK,QAAQ;gBACX,UAAU,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;gBAClC,MAAM;YACR,KAAK,WAAW;gBACd,UAAU,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC;gBACtC,MAAM;YACR;gBACE,UAAU,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QACnC,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,iBAAiB,MAAM,MAAM,UAAU,EAAE;iBAChD;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAGzD"}
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,+BAA+B;IAC/B,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@veracity/codeguardian-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A Model Context Protocol (MCP) server for CodeGuardian",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"codeguardian-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"test": "jest",
|
|
15
|
+
"lint": "eslint src/**/*.ts",
|
|
16
|
+
"lint:fix": "eslint src/**/*.ts --fix",
|
|
17
|
+
"clean": "rimraf dist"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"model-context-protocol",
|
|
22
|
+
"ai",
|
|
23
|
+
"typescript",
|
|
24
|
+
"codeguardian"
|
|
25
|
+
],
|
|
26
|
+
"author": "Veracity",
|
|
27
|
+
"homepage": "https://github.com/dnvgl/CodeGuardian",
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/dnvgl/CodeGuardian/issues"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@azure/identity": "^4.12.0",
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.17.5",
|
|
38
|
+
"azure-devops-extension-api": "^4.259.0",
|
|
39
|
+
"azure-devops-extension-sdk": "^4.1.0",
|
|
40
|
+
"azure-devops-node-api": "^15.1.1",
|
|
41
|
+
"diff": "^8.0.2",
|
|
42
|
+
"zod": "^3.22.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/jest": "^29.0.0",
|
|
46
|
+
"@types/node": "^20.0.0",
|
|
47
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
48
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
49
|
+
"eslint": "^8.0.0",
|
|
50
|
+
"jest": "^29.0.0",
|
|
51
|
+
"rimraf": "^5.0.0",
|
|
52
|
+
"ts-jest": "^29.0.0",
|
|
53
|
+
"typescript": "^5.0.0"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=18"
|
|
57
|
+
},
|
|
58
|
+
"files": [
|
|
59
|
+
"dist/**/*"
|
|
60
|
+
],
|
|
61
|
+
"repository": {
|
|
62
|
+
"type": "git",
|
|
63
|
+
"url": "git+https://github.com/dnvgl/CodeGuardian.git"
|
|
64
|
+
},
|
|
65
|
+
"types": "./dist/index.d.ts"
|
|
66
|
+
}
|