Skip to content

Commit 82b113c

Browse files
committed
Filtering repos by name substring
Also improving code formatting
1 parent f38b1c5 commit 82b113c

2 files changed

Lines changed: 39 additions & 17 deletions

File tree

src/tools/core.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,24 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
66
import { WebApi } from "azure-devops-node-api";
77
import { z } from "zod";
88

9+
import type { ProjectInfo } from "azure-devops-node-api/interfaces/CoreInterfaces.js";
10+
911
const CORE_TOOLS = {
1012
list_project_teams: "core_list_project_teams",
1113
list_projects: "core_list_projects",
1214
};
1315

16+
function filterProjectsByName(
17+
projects: ProjectInfo[],
18+
projectNameFilter: string
19+
): ProjectInfo[]
20+
{
21+
const lowerCaseFilter = projectNameFilter.toLowerCase();
22+
return projects.filter((project) =>
23+
project.name?.toLowerCase().includes(lowerCaseFilter)
24+
);
25+
}
26+
1427
function configureCoreTools(
1528
server: McpServer,
1629
tokenProvider: () => Promise<AccessToken>,
@@ -82,21 +95,12 @@ function configureCoreTools(
8295
return { content: [{ type: "text", text: "No projects found" }], isError: true };
8396
}
8497

85-
// If projectNameFilter is provided, filter the projects
86-
if (projectNameFilter) {
87-
const filteredProjects = projects.filter(project =>
88-
project.name?.toLowerCase().includes(projectNameFilter.toLowerCase())
89-
);
90-
if (filteredProjects.length === 0) {
91-
return { content: [{ type: "text", text: "No projects found matching the filter" }], isError: true };
92-
}
93-
return {
94-
content: [{ type: "text", text: JSON.stringify(filteredProjects, null, 2) }],
95-
};
96-
}
98+
const filteredProject = projectNameFilter
99+
? filterProjectsByName(projects, projectNameFilter)
100+
: projects;
97101

98102
return {
99-
content: [{ type: "text", text: JSON.stringify(projects, null, 2) }],
103+
content: [{ type: "text", text: JSON.stringify(filteredProject, null, 2) }],
100104
};
101105
} catch (error) {
102106
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';

src/tools/repos.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { WebApi } from "azure-devops-node-api";
77
import { GitRef, PullRequestStatus } from "azure-devops-node-api/interfaces/GitInterfaces.js";
88
import { z } from "zod";
99
import { getCurrentUserDetails } from "./auth.js";
10+
import { GitRepository } from "azure-devops-node-api/interfaces/TfvcInterfaces.js";
1011

1112
const REPO_TOOLS = {
1213
list_repos_by_project: "repo_list_repos_by_project",
@@ -55,6 +56,18 @@ function pullRequestStatusStringToInt(
5556
}
5657
}
5758

59+
function filterReposByName(
60+
repositories: GitRepository[],
61+
repoNameFilter: string
62+
): GitRepository[] {
63+
const lowerCaseFilter = repoNameFilter.toLowerCase();
64+
const filteredByName = repositories?.filter((repo) =>
65+
repo.name?.toLowerCase().includes(lowerCaseFilter)
66+
);
67+
68+
return filteredByName;
69+
}
70+
5871
function configureRepoTools(
5972
server: McpServer,
6073
tokenProvider: () => Promise<AccessToken>,
@@ -137,9 +150,10 @@ function configureRepoTools(
137150
REPO_TOOLS.list_repos_by_project,
138151
"Retrieve a list of repositories for a given project",
139152
{
140-
project: z.string().describe("The name or ID of the Azure DevOps project."),
153+
project: z.string().describe("The name or ID of the Azure DevOps project."),
154+
repoNameFilter: z.string().optional().describe("Optional filter to search for repositories by name. If provided, only repositories with names containing this string will be returned."),
141155
},
142-
async ({ project }) => {
156+
async ({ project, repoNameFilter }) => {
143157
const connection = await connectionProvider();
144158
const gitApi = await connection.getGitApi();
145159
const repositories = await gitApi.getRepositories(
@@ -149,8 +163,12 @@ function configureRepoTools(
149163
false
150164
);
151165

166+
const filteredRepositories = repoNameFilter
167+
? filterReposByName(repositories, repoNameFilter)
168+
: repositories;
169+
152170
// Filter out the irrelevant properties
153-
const filteredRepositories = repositories?.map((repo) => ({
171+
const trimmedRepositories = filteredRepositories?.map((repo) => ({
154172
id: repo.id,
155173
name: repo.name,
156174
isDisabled: repo.isDisabled,
@@ -162,7 +180,7 @@ function configureRepoTools(
162180

163181
return {
164182
content: [
165-
{ type: "text", text: JSON.stringify(filteredRepositories, null, 2) },
183+
{ type: "text", text: JSON.stringify(trimmedRepositories, null, 2) },
166184
],
167185
};
168186
}

0 commit comments

Comments
 (0)