mobbdev 1.0.210 → 1.0.212

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/dist/index.mjs CHANGED
@@ -51,7 +51,7 @@ var init_configs = __esm({
51
51
  isAutoScan = process.env["AUTO_SCAN"] !== "false";
52
52
  MVS_AUTO_FIX_OVERRIDE = process.env["MVS_AUTO_FIX"];
53
53
  MCP_AUTO_FIX_DEBUG_MODE = true;
54
- MCP_PERIODIC_TRACK_INTERVAL = 60 * 60 * 1e3;
54
+ MCP_PERIODIC_TRACK_INTERVAL = 24 * 60 * 60 * 1e3;
55
55
  MCP_DEFAULT_REST_API_URL = "https://api.mobb.ai/api/rest/mcp/track";
56
56
  MCP_SYSTEM_FIND_TIMEOUT_MS = 15 * 60 * 1e3;
57
57
  }
@@ -6224,7 +6224,7 @@ async function getAdoSdk(params) {
6224
6224
  const url = new URL(repoUrl);
6225
6225
  const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
6226
6226
  const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
6227
- const path17 = [
6227
+ const path18 = [
6228
6228
  prefixPath,
6229
6229
  owner,
6230
6230
  projectName,
@@ -6235,7 +6235,7 @@ async function getAdoSdk(params) {
6235
6235
  "items",
6236
6236
  "items"
6237
6237
  ].filter(Boolean).join("/");
6238
- return new URL(`${path17}?${params2}`, origin2).toString();
6238
+ return new URL(`${path18}?${params2}`, origin2).toString();
6239
6239
  },
6240
6240
  async getAdoBranchList({ repoUrl }) {
6241
6241
  try {
@@ -6809,7 +6809,7 @@ function getBitbucketSdk(params) {
6809
6809
  return repoRes.map((repo) => ({
6810
6810
  repoIsPublic: !repo.is_private,
6811
6811
  repoName: repo.name || "unknown repo name",
6812
- repoOwner: repo.owner?.username || "unknown owner",
6812
+ repoOwner: repo.owner?.["username"] || "unknown owner",
6813
6813
  repoLanguages: repo.language ? [repo.language] : [],
6814
6814
  repoUpdatedAt: repo.updated_on ? repo.updated_on : (/* @__PURE__ */ new Date()).toISOString(),
6815
6815
  repoUrl: repo.links?.html?.href || ""
@@ -7209,10 +7209,10 @@ var BitbucketSCMLib = class extends SCMLib {
7209
7209
  async _getUsernameForAuthUrl() {
7210
7210
  this._validateAccessTokenAndUrl();
7211
7211
  const user = await this.bitbucketSdk.getUser();
7212
- if (!user.username) {
7212
+ if (!user["username"]) {
7213
7213
  throw new Error("no username found");
7214
7214
  }
7215
- return user.username;
7215
+ return user["username"];
7216
7216
  }
7217
7217
  async getIsRemoteBranch(branch) {
7218
7218
  this._validateAccessTokenAndUrl();
@@ -7233,7 +7233,7 @@ var BitbucketSCMLib = class extends SCMLib {
7233
7233
  async getUsername() {
7234
7234
  this._validateAccessToken();
7235
7235
  const res = await this.bitbucketSdk.getUser();
7236
- return z20.string().parse(res.username);
7236
+ return z20.string().parse(res["username"]);
7237
7237
  }
7238
7238
  async getSubmitRequestStatus(_scmSubmitRequestId) {
7239
7239
  this._validateAccessTokenAndUrl();
@@ -7564,13 +7564,33 @@ function getGithubSdk(params = {}) {
7564
7564
  const { username, repoUrl } = params2;
7565
7565
  try {
7566
7566
  const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
7567
- const res = await octokit.rest.repos.checkCollaborator({
7568
- owner,
7569
- repo,
7570
- username
7571
- });
7572
- if (res.status === 204) {
7573
- return true;
7567
+ try {
7568
+ const res = await octokit.rest.repos.checkCollaborator({
7569
+ owner,
7570
+ repo,
7571
+ username
7572
+ });
7573
+ if (res.status === 204) {
7574
+ return true;
7575
+ }
7576
+ } catch (collaboratorError) {
7577
+ try {
7578
+ const permissionRes = await octokit.rest.repos.getCollaboratorPermissionLevel({
7579
+ owner,
7580
+ repo,
7581
+ username
7582
+ });
7583
+ if (permissionRes.data.permission !== "none") {
7584
+ return true;
7585
+ }
7586
+ } catch (permissionError) {
7587
+ try {
7588
+ await octokit.rest.repos.get({ owner, repo });
7589
+ return true;
7590
+ } catch (repoError) {
7591
+ return false;
7592
+ }
7593
+ }
7574
7594
  }
7575
7595
  } catch (e) {
7576
7596
  return false;
@@ -7645,6 +7665,9 @@ function getGithubSdk(params = {}) {
7645
7665
  const repos = await octokit.rest.repos.get({ repo, owner });
7646
7666
  return repos.data.default_branch;
7647
7667
  },
7668
+ async getRepository({ owner, repo }) {
7669
+ return octokit.rest.repos.get({ repo, owner });
7670
+ },
7648
7671
  async getGithubReferenceData({
7649
7672
  ref,
7650
7673
  gitHubUrl
@@ -7759,14 +7782,14 @@ function getGithubSdk(params = {}) {
7759
7782
  };
7760
7783
  },
7761
7784
  async getGithubBlameRanges(params2) {
7762
- const { ref, gitHubUrl, path: path17 } = params2;
7785
+ const { ref, gitHubUrl, path: path18 } = params2;
7763
7786
  const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
7764
7787
  const res = await octokit.graphql(
7765
7788
  GET_BLAME_DOCUMENT,
7766
7789
  {
7767
7790
  owner,
7768
7791
  repo,
7769
- path: path17,
7792
+ path: path18,
7770
7793
  ref
7771
7794
  }
7772
7795
  );
@@ -7904,11 +7927,12 @@ function getGithubSdk(params = {}) {
7904
7927
  return octokit.request(GET_USER);
7905
7928
  },
7906
7929
  async getPrCommits(params2) {
7907
- return octokit.rest.pulls.listCommits({
7930
+ const data = await octokit.paginate(octokit.rest.pulls.listCommits, {
7908
7931
  owner: params2.owner,
7909
7932
  repo: params2.repo,
7910
7933
  pull_number: params2.pull_number
7911
7934
  });
7935
+ return { data };
7912
7936
  },
7913
7937
  async getUserRepos() {
7914
7938
  return octokit.rest.repos.listForAuthenticatedUser({
@@ -7929,12 +7953,12 @@ function getGithubSdk(params = {}) {
7929
7953
  });
7930
7954
  },
7931
7955
  async listPRFiles(params2) {
7932
- return octokit.rest.pulls.listFiles({
7956
+ const data = await octokit.paginate(octokit.rest.pulls.listFiles, {
7933
7957
  owner: params2.owner,
7934
7958
  repo: params2.repo,
7935
- pull_number: params2.pull_number,
7936
- per_page: 100
7959
+ pull_number: params2.pull_number
7937
7960
  });
7961
+ return { data };
7938
7962
  }
7939
7963
  };
7940
7964
  }
@@ -8107,11 +8131,11 @@ var GithubSCMLib = class extends SCMLib {
8107
8131
  markdownComment: comment
8108
8132
  });
8109
8133
  }
8110
- async getRepoBlameRanges(ref, path17) {
8134
+ async getRepoBlameRanges(ref, path18) {
8111
8135
  this._validateUrl();
8112
8136
  return await this.githubSdk.getGithubBlameRanges({
8113
8137
  ref,
8114
- path: path17,
8138
+ path: path18,
8115
8139
  gitHubUrl: this.url
8116
8140
  });
8117
8141
  }
@@ -8204,13 +8228,54 @@ var GithubSCMLib = class extends SCMLib {
8204
8228
  commitSha
8205
8229
  });
8206
8230
  const commitTimestamp = commit.commit.committer?.date ? new Date(commit.commit.committer.date) : new Date(commit.commit.author?.date || Date.now());
8231
+ let parentCommits;
8232
+ if (commit.parents && commit.parents.length > 0) {
8233
+ try {
8234
+ parentCommits = await Promise.all(
8235
+ commit.parents.map(async (parent) => {
8236
+ const parentCommit = await this.githubSdk.getCommit({
8237
+ owner,
8238
+ repo,
8239
+ commitSha: parent.sha
8240
+ });
8241
+ const parentTimestamp = parentCommit.data.committer?.date ? new Date(parentCommit.data.committer.date) : new Date(Date.now());
8242
+ return {
8243
+ sha: parent.sha,
8244
+ timestamp: parentTimestamp
8245
+ };
8246
+ })
8247
+ );
8248
+ } catch (error) {
8249
+ console.error("Failed to fetch parent commit timestamps", {
8250
+ error,
8251
+ commitSha,
8252
+ owner,
8253
+ repo
8254
+ });
8255
+ parentCommits = void 0;
8256
+ }
8257
+ }
8258
+ let repositoryCreatedAt;
8259
+ try {
8260
+ const repoData = await this.githubSdk.getRepository({ owner, repo });
8261
+ repositoryCreatedAt = repoData.data.created_at ? new Date(repoData.data.created_at) : void 0;
8262
+ } catch (error) {
8263
+ console.error("Failed to fetch repository creation date", {
8264
+ error,
8265
+ owner,
8266
+ repo
8267
+ });
8268
+ repositoryCreatedAt = void 0;
8269
+ }
8207
8270
  return {
8208
8271
  diff,
8209
8272
  commitTimestamp,
8210
8273
  commitSha: commit.sha,
8211
8274
  authorName: commit.commit.author?.name,
8212
8275
  authorEmail: commit.commit.author?.email,
8213
- message: commit.commit.message
8276
+ message: commit.commit.message,
8277
+ parentCommits,
8278
+ repositoryCreatedAt
8214
8279
  };
8215
8280
  }
8216
8281
  async getSubmitRequestDiff(submitRequestId) {
@@ -8750,13 +8815,13 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
8750
8815
  const { organization, repoName, projectPath } = parsingResult;
8751
8816
  return { owner: organization, repo: repoName, projectPath };
8752
8817
  }
8753
- async function getGitlabBlameRanges({ ref, gitlabUrl, path: path17 }, options) {
8818
+ async function getGitlabBlameRanges({ ref, gitlabUrl, path: path18 }, options) {
8754
8819
  const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
8755
8820
  const api2 = getGitBeaker({
8756
8821
  url: gitlabUrl,
8757
8822
  gitlabAuthToken: options?.gitlabAuthToken
8758
8823
  });
8759
- const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path17, ref);
8824
+ const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path18, ref);
8760
8825
  let lineNumber = 1;
8761
8826
  return resp.filter((range) => range.lines).map((range) => {
8762
8827
  const oldLineNumber = lineNumber;
@@ -8933,10 +8998,10 @@ var GitlabSCMLib = class extends SCMLib {
8933
8998
  markdownComment: comment
8934
8999
  });
8935
9000
  }
8936
- async getRepoBlameRanges(ref, path17) {
9001
+ async getRepoBlameRanges(ref, path18) {
8937
9002
  this._validateUrl();
8938
9003
  return await getGitlabBlameRanges(
8939
- { ref, path: path17, gitlabUrl: this.url },
9004
+ { ref, path: path18, gitlabUrl: this.url },
8940
9005
  {
8941
9006
  url: this.url,
8942
9007
  gitlabAuthToken: this.accessToken
@@ -10968,7 +11033,7 @@ async function postIssueComment(params) {
10968
11033
  fpDescription
10969
11034
  } = params;
10970
11035
  const {
10971
- path: path17,
11036
+ path: path18,
10972
11037
  startLine,
10973
11038
  vulnerabilityReportIssue: {
10974
11039
  vulnerabilityReportIssueTags,
@@ -10983,7 +11048,7 @@ async function postIssueComment(params) {
10983
11048
  Refresh the page in order to see the changes.`,
10984
11049
  pull_number: pullRequest,
10985
11050
  commit_id: commitSha,
10986
- path: path17,
11051
+ path: path18,
10987
11052
  line: startLine
10988
11053
  });
10989
11054
  const commentId = commentRes.data.id;
@@ -11017,7 +11082,7 @@ async function postFixComment(params) {
11017
11082
  scanner
11018
11083
  } = params;
11019
11084
  const {
11020
- path: path17,
11085
+ path: path18,
11021
11086
  startLine,
11022
11087
  vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
11023
11088
  vulnerabilityReportIssueId
@@ -11035,7 +11100,7 @@ async function postFixComment(params) {
11035
11100
  Refresh the page in order to see the changes.`,
11036
11101
  pull_number: pullRequest,
11037
11102
  commit_id: commitSha,
11038
- path: path17,
11103
+ path: path18,
11039
11104
  line: startLine
11040
11105
  });
11041
11106
  const commentId = commentRes.data.id;
@@ -12779,6 +12844,8 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
12779
12844
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12780
12845
  import {
12781
12846
  CallToolRequestSchema,
12847
+ GetPromptRequestSchema,
12848
+ ListPromptsRequestSchema,
12782
12849
  ListToolsRequestSchema
12783
12850
  } from "@modelcontextprotocol/sdk/types.js";
12784
12851
 
@@ -12791,8 +12858,8 @@ var WorkspaceService = class {
12791
12858
  * Sets a known workspace path that was discovered through successful validation
12792
12859
  * @param path The validated workspace path to store
12793
12860
  */
12794
- static setKnownWorkspacePath(path17) {
12795
- this.knownWorkspacePath = path17;
12861
+ static setKnownWorkspacePath(path18) {
12862
+ this.knownWorkspacePath = path18;
12796
12863
  }
12797
12864
  /**
12798
12865
  * Gets the known workspace path that was previously validated
@@ -14040,10 +14107,10 @@ var getHostInfo = (additionalMcpList) => {
14040
14107
  const ideConfigPaths = /* @__PURE__ */ new Set();
14041
14108
  for (const ide of IDEs) {
14042
14109
  const configPaths = getMCPConfigPaths(ide);
14043
- configPaths.forEach((path17) => ideConfigPaths.add(path17));
14110
+ configPaths.forEach((path18) => ideConfigPaths.add(path18));
14044
14111
  }
14045
14112
  const uniqueAdditionalPaths = additionalMcpList.filter(
14046
- (path17) => !ideConfigPaths.has(path17)
14113
+ (path18) => !ideConfigPaths.has(path18)
14047
14114
  );
14048
14115
  for (const ide of IDEs) {
14049
14116
  const cfg = readMCPConfig(ide);
@@ -14163,78 +14230,68 @@ init_configs();
14163
14230
 
14164
14231
  // src/mcp/services/McpUsageService/system.ts
14165
14232
  init_configs();
14166
- import { spawn } from "child_process";
14233
+ import fs12 from "fs";
14167
14234
  import os4 from "os";
14235
+ import path12 from "path";
14236
+ var MAX_DEPTH = 2;
14237
+ var patterns = ["mcp", "claude"];
14238
+ var isFileMatch = (fileName) => {
14239
+ const lowerName = fileName.toLowerCase();
14240
+ return lowerName.endsWith(".json") && patterns.some((p) => lowerName.includes(p.toLowerCase()));
14241
+ };
14242
+ var safeAccess = async (filePath) => {
14243
+ try {
14244
+ await fs12.promises.access(filePath, fs12.constants.R_OK);
14245
+ return true;
14246
+ } catch {
14247
+ return false;
14248
+ }
14249
+ };
14250
+ var searchDir = async (dir, depth = 0) => {
14251
+ const results = [];
14252
+ if (depth > MAX_DEPTH) return results;
14253
+ const entries = await fs12.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
14254
+ for (const entry of entries) {
14255
+ const fullPath = path12.join(dir, entry.name);
14256
+ if (entry.isFile() && isFileMatch(entry.name)) {
14257
+ results.push(fullPath);
14258
+ } else if (entry.isDirectory()) {
14259
+ if (await safeAccess(fullPath)) {
14260
+ const subResults = await searchDir(fullPath, depth + 1);
14261
+ results.push(...subResults);
14262
+ }
14263
+ }
14264
+ }
14265
+ return results;
14266
+ };
14168
14267
  var findSystemMCPConfigs = async () => {
14169
14268
  try {
14269
+ const home = os4.homedir();
14170
14270
  const platform = os4.platform();
14171
- let command;
14172
- let args;
14173
- if (platform === "win32") {
14174
- command = "powershell";
14175
- args = [
14176
- "-NoProfile",
14177
- "-Command",
14178
- "Get-ChildItem -Path $env:USERPROFILE -Recurse -Include *mcp*.json,*claude*.json -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName }"
14179
- ];
14180
- } else {
14181
- const home = os4.homedir();
14182
- command = "find";
14183
- args = [
14184
- home,
14185
- "-type",
14186
- "f",
14187
- "(",
14188
- "-iname",
14189
- "*mcp*.json",
14190
- "-o",
14191
- "-iname",
14192
- "*claude*.json",
14193
- ")"
14194
- ];
14195
- }
14196
- return await new Promise((resolve) => {
14197
- const child = spawn(command, args, {
14198
- stdio: ["ignore", "pipe", "pipe"],
14199
- shell: platform === "win32"
14200
- // needed for PowerShell
14201
- });
14202
- let output = "";
14203
- let errorOutput = "";
14204
- const timer = setTimeout(() => {
14205
- child.kill("SIGTERM");
14271
+ const knownDirs = platform === "win32" ? [
14272
+ path12.join(home, ".cursor"),
14273
+ path12.join(home, "Documents"),
14274
+ path12.join(home, "Downloads")
14275
+ ] : [
14276
+ path12.join(home, ".cursor"),
14277
+ process.env["XDG_CONFIG_HOME"] || path12.join(home, ".config"),
14278
+ path12.join(home, "Documents"),
14279
+ path12.join(home, "Downloads")
14280
+ ];
14281
+ const timeoutPromise = new Promise(
14282
+ (resolve) => setTimeout(() => {
14206
14283
  logWarn(
14207
14284
  `MCP config search timed out after ${MCP_SYSTEM_FIND_TIMEOUT_MS / 1e3}s`
14208
14285
  );
14209
14286
  resolve([]);
14210
- }, MCP_SYSTEM_FIND_TIMEOUT_MS);
14211
- child.stdout.on("data", (data) => {
14212
- output += data.toString();
14213
- });
14214
- child.stderr.on("data", (data) => {
14215
- const msg = data.toString();
14216
- if (!msg.includes("Operation not permitted") && !msg.includes("Permission denied") && !msg.includes("Access is denied")) {
14217
- errorOutput += msg;
14218
- }
14219
- });
14220
- child.on("error", (err) => {
14221
- clearTimeout(timer);
14222
- logWarn("MCP config search failed to start", { err });
14223
- resolve([]);
14224
- });
14225
- child.on("close", (code) => {
14226
- clearTimeout(timer);
14227
- if (code === 0 || output.trim().length > 0) {
14228
- const files = output.split(/\r?\n/).map((f) => f.trim()).filter(Boolean);
14229
- resolve(files);
14230
- } else {
14231
- if (errorOutput.trim().length > 0) {
14232
- logWarn("MCP config search finished with warnings", { errorOutput });
14233
- }
14234
- resolve([]);
14235
- }
14236
- });
14237
- });
14287
+ }, MCP_SYSTEM_FIND_TIMEOUT_MS)
14288
+ );
14289
+ const searchPromise = Promise.all(
14290
+ knownDirs.map(
14291
+ (dir) => fs12.existsSync(dir) ? searchDir(dir) : Promise.resolve([])
14292
+ )
14293
+ ).then((results) => results.flat());
14294
+ return await Promise.race([timeoutPromise, searchPromise]);
14238
14295
  } catch (err) {
14239
14296
  logWarn("MCP config search unexpected error", { err });
14240
14297
  return [];
@@ -14409,6 +14466,45 @@ var MCP_TOOL_CHECKER = "mcp_checker";
14409
14466
  // src/mcp/core/McpServer.ts
14410
14467
  init_configs();
14411
14468
 
14469
+ // src/mcp/core/PromptRegistry.ts
14470
+ var PromptRegistry = class {
14471
+ constructor() {
14472
+ __publicField(this, "prompts", /* @__PURE__ */ new Map());
14473
+ }
14474
+ registerPrompt(prompt) {
14475
+ if (this.prompts.has(prompt.name)) {
14476
+ logWarn(`Prompt ${prompt.name} is already registered, overwriting`, {
14477
+ promptName: prompt.name
14478
+ });
14479
+ }
14480
+ this.prompts.set(prompt.name, prompt);
14481
+ logDebug(`Prompt registered: ${prompt.name}`, {
14482
+ promptName: prompt.name,
14483
+ description: prompt.description
14484
+ });
14485
+ }
14486
+ getPrompt(name) {
14487
+ return this.prompts.get(name);
14488
+ }
14489
+ getPromptDefinition(name) {
14490
+ return this.prompts.get(name)?.getDefinition();
14491
+ }
14492
+ getAllPrompts() {
14493
+ return Array.from(this.prompts.values()).map(
14494
+ (prompt) => prompt.getDefinition()
14495
+ );
14496
+ }
14497
+ getPromptNames() {
14498
+ return Array.from(this.prompts.keys());
14499
+ }
14500
+ hasPrompt(name) {
14501
+ return this.prompts.has(name);
14502
+ }
14503
+ getPromptCount() {
14504
+ return this.prompts.size;
14505
+ }
14506
+ };
14507
+
14412
14508
  // src/mcp/core/ToolRegistry.ts
14413
14509
  var ToolRegistry = class {
14414
14510
  constructor() {
@@ -14451,6 +14547,7 @@ var McpServer = class {
14451
14547
  constructor(config6, govOrgId = "") {
14452
14548
  __publicField(this, "server");
14453
14549
  __publicField(this, "toolRegistry");
14550
+ __publicField(this, "promptRegistry");
14454
14551
  __publicField(this, "isEventHandlersSetup", false);
14455
14552
  __publicField(this, "eventHandlers", /* @__PURE__ */ new Map());
14456
14553
  __publicField(this, "parentProcessCheckInterval");
@@ -14466,11 +14563,13 @@ var McpServer = class {
14466
14563
  },
14467
14564
  {
14468
14565
  capabilities: {
14469
- tools: {}
14566
+ tools: {},
14567
+ prompts: {}
14470
14568
  }
14471
14569
  }
14472
14570
  );
14473
14571
  this.toolRegistry = new ToolRegistry();
14572
+ this.promptRegistry = new PromptRegistry();
14474
14573
  this.setupHandlers();
14475
14574
  this.setupProcessEventHandlers();
14476
14575
  this.setupParentProcessMonitoring();
@@ -14787,6 +14886,62 @@ var McpServer = class {
14787
14886
  throw error;
14788
14887
  }
14789
14888
  }
14889
+ async handleListPromptsRequest(request) {
14890
+ const mcpCheckerTool = this.toolRegistry.getToolDefinition(MCP_TOOL_CHECKER);
14891
+ if (mcpCheckerTool) {
14892
+ return {
14893
+ prompts: []
14894
+ };
14895
+ }
14896
+ logInfo("Received list_prompts request");
14897
+ logDebug("list_prompts request", {
14898
+ request: JSON.parse(JSON.stringify(request))
14899
+ });
14900
+ const promptDefinitions = this.promptRegistry.getAllPrompts();
14901
+ const response = {
14902
+ prompts: promptDefinitions.map((prompt) => ({
14903
+ name: prompt.name,
14904
+ description: prompt.description,
14905
+ arguments: prompt.arguments
14906
+ }))
14907
+ };
14908
+ logDebug("Returning list_prompts response", { response });
14909
+ return response;
14910
+ }
14911
+ async handleGetPromptRequest(request) {
14912
+ const { name, arguments: args } = request.params;
14913
+ logInfo(`Received get_prompt request for ${name}`);
14914
+ logDebug("get_prompt request", {
14915
+ request: JSON.parse(JSON.stringify(request))
14916
+ });
14917
+ try {
14918
+ const prompt = this.promptRegistry.getPrompt(name);
14919
+ if (!prompt) {
14920
+ const errorMsg = `Unknown prompt: ${name}`;
14921
+ logWarn(errorMsg, {
14922
+ name,
14923
+ availablePrompts: this.promptRegistry.getPromptNames()
14924
+ });
14925
+ throw new Error(errorMsg);
14926
+ }
14927
+ logInfo(`Generating prompt: ${name}`);
14928
+ const response = await prompt.getPrompt(args);
14929
+ logInfo(`Prompt ${name} generated successfully`);
14930
+ logDebug(`Prompt ${name} generated successfully`, {
14931
+ hasMessages: !!response.messages,
14932
+ messageCount: response.messages?.length
14933
+ });
14934
+ return response;
14935
+ } catch (error) {
14936
+ const errorMessage = error instanceof Error ? error.message : String(error);
14937
+ logError(`Error generating prompt ${name}: ${errorMessage}`, {
14938
+ error,
14939
+ promptName: name,
14940
+ args
14941
+ });
14942
+ throw error;
14943
+ }
14944
+ }
14790
14945
  setupHandlers() {
14791
14946
  this.server.setRequestHandler(
14792
14947
  ListToolsRequestSchema,
@@ -14796,12 +14951,24 @@ var McpServer = class {
14796
14951
  CallToolRequestSchema,
14797
14952
  (request) => this.handleCallToolRequest(request)
14798
14953
  );
14954
+ this.server.setRequestHandler(
14955
+ ListPromptsRequestSchema,
14956
+ (request) => this.handleListPromptsRequest(request)
14957
+ );
14958
+ this.server.setRequestHandler(
14959
+ GetPromptRequestSchema,
14960
+ (request) => this.handleGetPromptRequest(request)
14961
+ );
14799
14962
  logInfo("MCP server handlers registered");
14800
14963
  }
14801
14964
  registerTool(tool) {
14802
14965
  this.toolRegistry.registerTool(tool);
14803
14966
  logInfo(`Tool registered: ${tool.name}`);
14804
14967
  }
14968
+ registerPrompt(prompt) {
14969
+ this.promptRegistry.registerPrompt(prompt);
14970
+ logInfo(`Prompt registered: ${prompt.name}`);
14971
+ }
14805
14972
  getParentProcessId() {
14806
14973
  return this.parentPid;
14807
14974
  }
@@ -14865,117 +15032,43 @@ var McpServer = class {
14865
15032
  }
14866
15033
  };
14867
15034
 
14868
- // src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
14869
- import { z as z34 } from "zod";
14870
-
14871
- // src/mcp/services/PathValidation.ts
14872
- import fs12 from "fs";
14873
- import path12 from "path";
14874
- async function validatePath(inputPath) {
14875
- logDebug("Validating MCP path", { inputPath });
14876
- if (/^\/[a-zA-Z]:\//.test(inputPath)) {
14877
- inputPath = inputPath.slice(1);
14878
- }
14879
- if (inputPath === "." || inputPath === "./") {
14880
- const workspaceFolderPath = WorkspaceService.getWorkspaceFolderPath();
14881
- if (workspaceFolderPath) {
14882
- logDebug("Fallback to workspace folder path", {
14883
- inputPath,
14884
- workspaceFolderPaths: [workspaceFolderPath]
14885
- });
14886
- WorkspaceService.setKnownWorkspacePath(workspaceFolderPath);
14887
- logDebug("Stored workspace folder path as known path", {
14888
- workspaceFolderPath
14889
- });
14890
- return {
14891
- isValid: true,
14892
- path: workspaceFolderPath
14893
- };
14894
- } else {
14895
- const error = `"." is not a valid path, please provide a full localpath to the repository`;
14896
- logError(error);
14897
- return { isValid: false, error, path: inputPath };
14898
- }
14899
- }
14900
- if (inputPath.includes("..")) {
14901
- const error = `Path contains path traversal patterns: ${inputPath}`;
14902
- logError(error);
14903
- return { isValid: false, error, path: inputPath };
14904
- }
14905
- const normalizedPath = path12.normalize(inputPath);
14906
- if (normalizedPath.includes("..")) {
14907
- const error = `Normalized path contains path traversal patterns: ${inputPath}`;
14908
- logError(error);
14909
- return { isValid: false, error, path: inputPath };
14910
- }
14911
- let decodedPath;
14912
- try {
14913
- decodedPath = decodeURIComponent(inputPath);
14914
- } catch (err) {
14915
- const error = `Failed to decode path: ${inputPath}`;
14916
- logError(error, { err });
14917
- return { isValid: false, error, path: inputPath };
14918
- }
14919
- if (decodedPath.includes("..") || decodedPath !== inputPath) {
14920
- const error = `Path contains encoded traversal attempts: ${inputPath}`;
14921
- logError(error);
14922
- return { isValid: false, error, path: inputPath };
14923
- }
14924
- if (inputPath.includes("\0") || inputPath.includes("\0")) {
14925
- const error = `Path contains dangerous characters: ${inputPath}`;
14926
- logError(error);
14927
- return { isValid: false, error, path: inputPath };
14928
- }
14929
- logDebug("Path validation successful", { inputPath });
14930
- logDebug("Checking path existence", { inputPath });
14931
- try {
14932
- await fs12.promises.access(inputPath);
14933
- logDebug("Path exists and is accessible", { inputPath });
14934
- WorkspaceService.setKnownWorkspacePath(inputPath);
14935
- logDebug("Stored validated path in WorkspaceService", { inputPath });
14936
- return { isValid: true, path: inputPath };
14937
- } catch (error) {
14938
- const errorMessage = `Path does not exist or is not accessible: ${inputPath}`;
14939
- logError(errorMessage, { error });
14940
- return { isValid: false, error: errorMessage, path: inputPath };
14941
- }
14942
- }
15035
+ // src/mcp/prompts/CheckForNewVulnerabilitiesPrompt.ts
15036
+ import { z as z33 } from "zod";
14943
15037
 
14944
- // src/mcp/tools/base/BaseTool.ts
15038
+ // src/mcp/prompts/base/BasePrompt.ts
14945
15039
  import { z as z32 } from "zod";
14946
- var BaseTool = class {
15040
+ var BasePrompt = class {
14947
15041
  getDefinition() {
14948
15042
  return {
14949
15043
  name: this.name,
14950
- display_name: this.displayName,
14951
15044
  description: this.description,
14952
- inputSchema: this.inputSchema
15045
+ arguments: this.arguments
14953
15046
  };
14954
15047
  }
14955
- async execute(args) {
14956
- if (this.hasAuthentication) {
14957
- logDebug(`Authenticating tool: ${this.name}`, { args });
14958
- const mcpGqlClient = await createAuthenticatedMcpGQLClient();
14959
- const userInfo = await mcpGqlClient.getUserInfo();
14960
- logDebug("User authenticated successfully", { userInfo });
15048
+ async getPrompt(args) {
15049
+ let validatedArgs = args;
15050
+ if (this.argumentsValidationSchema) {
15051
+ validatedArgs = this.validateArguments(args);
15052
+ logDebug(`Prompt ${this.name} arguments validation successful`, {
15053
+ validatedArgs
15054
+ });
14961
15055
  }
14962
- const validatedArgs = this.validateInput(args);
14963
- logDebug(`Tool ${this.name} input validation successful`, {
14964
- validatedArgs
14965
- });
14966
- logInfo(`Executing tool: ${this.name}`);
14967
- const result = await this.executeInternal(validatedArgs);
14968
- logInfo(`Tool ${this.name} executed successfully`);
15056
+ const result = await this.generatePrompt(validatedArgs);
15057
+ logDebug(`Prompt ${this.name} generated successfully`);
14969
15058
  return result;
14970
15059
  }
14971
- validateInput(args) {
15060
+ validateArguments(args) {
15061
+ if (!this.argumentsValidationSchema) {
15062
+ return args;
15063
+ }
14972
15064
  try {
14973
- return this.inputValidationSchema.parse(args);
15065
+ const argsToValidate = args === void 0 ? {} : args;
15066
+ return this.argumentsValidationSchema.parse(argsToValidate);
14974
15067
  } catch (error) {
14975
15068
  if (error instanceof z32.ZodError) {
14976
15069
  const errorDetails = error.errors.map((e) => {
14977
15070
  const fieldPath = e.path.length > 0 ? e.path.join(".") : "root";
14978
- const message = e.message === "Required" ? `Missing required parameter '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
15071
+ const message = e.message === "Required" ? `Missing required argument '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
14979
15072
  return message;
14980
15073
  });
14981
15074
  const errorMessage = `Invalid arguments: ${errorDetails.join(", ")}`;
@@ -14984,53 +15077,1786 @@ var BaseTool = class {
14984
15077
  throw error;
14985
15078
  }
14986
15079
  }
14987
- createSuccessResponse(text) {
15080
+ createUserMessage(text) {
14988
15081
  return {
14989
- content: [
15082
+ description: this.description,
15083
+ messages: [
14990
15084
  {
14991
- type: "text",
14992
- text
15085
+ role: "user",
15086
+ content: {
15087
+ type: "text",
15088
+ text
15089
+ }
14993
15090
  }
14994
15091
  ]
14995
15092
  };
14996
15093
  }
14997
15094
  };
14998
15095
 
14999
- // src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesService.ts
15000
- init_configs();
15096
+ // src/mcp/prompts/CheckForNewVulnerabilitiesPrompt.ts
15097
+ var CheckForNewVulnerabilitiesArgsSchema = z33.object({
15098
+ path: z33.string().optional()
15099
+ });
15100
+ var CheckForNewVulnerabilitiesPrompt = class extends BasePrompt {
15101
+ constructor() {
15102
+ super(...arguments);
15103
+ __publicField(this, "name", "check-for-new-vulnerabilities");
15104
+ __publicField(this, "description", "Guide for enabling continuous security monitoring to detect new vulnerabilities");
15105
+ __publicField(this, "arguments", [
15106
+ {
15107
+ name: "path",
15108
+ description: "Optional: Full local path to the git repository to monitor",
15109
+ required: false
15110
+ }
15111
+ ]);
15112
+ __publicField(this, "argumentsValidationSchema", CheckForNewVulnerabilitiesArgsSchema);
15113
+ }
15114
+ async generatePrompt(validatedArgs) {
15115
+ const args = validatedArgs;
15116
+ const promptText = `# Continuous Security Monitoring Setup
15001
15117
 
15002
- // src/mcp/core/prompts.ts
15003
- init_configs();
15004
- function friendlyType(s) {
15005
- const withoutUnderscores = s.replace(/_/g, " ");
15006
- const result = withoutUnderscores.replace(/([a-z])([A-Z])/g, "$1 $2");
15007
- return result.charAt(0).toUpperCase() + result.slice(1);
15008
- }
15009
- var noFixesReturnedForParameters = `No fixes returned for the given offset and limit parameters.
15010
- `;
15011
- var noFixesReturnedForParametersWithGuidance = ({
15012
- offset,
15013
- limit,
15014
- totalCount,
15015
- currentTool
15016
- }) => `## No Fixes Returned for Current Parameters
15118
+ This workflow sets up ongoing security monitoring to detect new vulnerabilities as code changes.
15017
15119
 
15018
- **\u{1F4C4} Current Request:**
15019
- - **Page:** ${Math.floor(offset / limit) + 1}
15020
- - **Offset:** ${offset}
15021
- - **Limit:** ${limit}
15120
+ ## Purpose
15022
15121
 
15023
- **\u274C Result:** No fixes returned for the given offset and limit parameters.
15122
+ The \`check_for_new_available_fixes\` tool provides:
15123
+ - Lightweight background security monitoring
15124
+ - Detection of newly introduced vulnerabilities
15125
+ - Periodic checks without heavy scanning overhead
15126
+ - Notifications when new fixes become available
15024
15127
 
15025
- **\u2139\uFE0F Available Fixes:** ${totalCount} total fixes are available, but your current offset (${offset}) is beyond the available range.
15128
+ ## When to Use
15026
15129
 
15027
- **\u2705 How to Get the Fixes:**
15130
+ Call this tool:
15131
+ \u2713 At the end of a coding session
15132
+ \u2713 After completing a series of edits
15133
+ \u2713 After applying security fixes (to verify no new issues)
15134
+ \u2713 Before committing code changes
15135
+ \u2713 As part of a continuous security workflow
15136
+ \u2713 When setting up a project for security monitoring
15028
15137
 
15029
- To retrieve the available fixes, use one of these approaches:
15138
+ ## Workflow Steps
15030
15139
 
15031
- 1. **Start from the beginning:**
15032
- \`\`\`
15033
- offset: 0
15140
+ ### Step 1: Determine Repository Path
15141
+ ${args?.path ? `\u2713 Repository path provided: \`${args.path}\`` : `Get the full local path to the git repository to monitor.`}
15142
+
15143
+ ### Step 2: Call check_for_new_available_fixes
15144
+
15145
+ Use the tool with minimal parameters:
15146
+
15147
+ \`\`\`json
15148
+ {
15149
+ "path": "${args?.path || "<repository-path>"}"
15150
+ }
15151
+ \`\`\`
15152
+
15153
+ This tool is designed to be lightweight and non-intrusive.
15154
+
15155
+ ### Step 3: Interpret Results
15156
+
15157
+ The tool will return one of several possible outcomes:
15158
+
15159
+ #### New Vulnerabilities Detected
15160
+
15161
+ If new security issues are found:
15162
+
15163
+ 1. **Alert the user promptly:**
15164
+ "\u26A0\uFE0F New security vulnerabilities detected!"
15165
+
15166
+ 2. **Provide summary:**
15167
+ - Number of new vulnerabilities
15168
+ - Severity breakdown
15169
+ - Files affected
15170
+
15171
+ 3. **Recommend immediate action:**
15172
+ - For Critical/High: "I recommend reviewing these immediately"
15173
+ - For Medium/Low: "These should be addressed when convenient"
15174
+
15175
+ 4. **Offer next steps:**
15176
+ - "Would you like to scan and see the details?"
15177
+ - "Should I fetch the available fixes?"
15178
+ - Suggest calling \`scan_and_fix_vulnerabilities\` or \`fetch_available_fixes\`
15179
+
15180
+ #### No New Vulnerabilities
15181
+
15182
+ "\u2713 Monitoring active. No new security vulnerabilities detected."
15183
+
15184
+ Optional follow-up:
15185
+ - Confirm monitoring is now enabled
15186
+ - Mention that checks will continue periodically
15187
+ - Reassure the user their code remains secure
15188
+
15189
+ #### Monitoring Enabled
15190
+
15191
+ "\u2713 Continuous security monitoring has been enabled for this repository."
15192
+
15193
+ Explain what this means:
15194
+ - Periodic background checks will run
15195
+ - User will be notified of new vulnerabilities
15196
+ - No action required from user right now
15197
+
15198
+ ### Step 4: Handle User Response
15199
+
15200
+ **If new vulnerabilities were found:**
15201
+
15202
+ Guide the user to take appropriate action:
15203
+
15204
+ 1. **Immediate threats (Critical/High):**
15205
+ - Strongly recommend scanning now
15206
+ - Offer to fetch and display fixes
15207
+ - Suggest not committing until fixed
15208
+
15209
+ 2. **Medium priority:**
15210
+ - Add to todo list or backlog
15211
+ - Schedule time to address
15212
+ - Can proceed with current work
15213
+
15214
+ 3. **Low priority:**
15215
+ - Track for future maintenance
15216
+ - Can be addressed in next refactoring
15217
+ - No immediate action required
15218
+
15219
+ **If no issues found:**
15220
+
15221
+ - Congratulate the user on maintaining security
15222
+ - Remind them monitoring will continue
15223
+ - Suggest they can continue their work confidently
15224
+
15225
+ ### Step 5: Integration into Workflow
15226
+
15227
+ This tool should be called **automatically** in certain scenarios:
15228
+
15229
+ 1. **End-of-session cleanup:**
15230
+ After a user completes a significant amount of work
15231
+
15232
+ 2. **Post-fix verification:**
15233
+ After applying security fixes to ensure no new issues
15234
+
15235
+ 3. **Pre-commit hook simulation:**
15236
+ Before suggesting the user commit their changes
15237
+
15238
+ 4. **Periodic checks:**
15239
+ During long-running IDE sessions (every 15-30 minutes)
15240
+
15241
+ ## Best Practices
15242
+
15243
+ ### DO:
15244
+ \u2713 Call this tool frequently and automatically
15245
+ \u2713 Make it part of your regular workflow
15246
+ \u2713 Alert users immediately when issues are found
15247
+ \u2713 Provide clear severity context
15248
+ \u2713 Offer actionable next steps
15249
+ \u2713 Keep the messaging positive and non-alarming
15250
+
15251
+ ### DON'T:
15252
+ \u2717 Make this tool intrusive or annoying
15253
+ \u2717 Overwhelm users with constant notifications
15254
+ \u2717 Ignore Critical/High severity findings
15255
+ \u2717 Forget to explain what monitoring means
15256
+ \u2717 Skip this step at the end of sessions
15257
+
15258
+ ## Monitoring vs. Scanning
15259
+
15260
+ It's important to understand the difference:
15261
+
15262
+ | Feature | check_for_new_available_fixes | scan_and_fix_vulnerabilities |
15263
+ |---------|------------------------------|------------------------------|
15264
+ | Purpose | Continuous monitoring | Full security scan |
15265
+ | Speed | Very fast | Slower (minutes) |
15266
+ | Depth | Lightweight check | Comprehensive analysis |
15267
+ | When | Frequently, automatically | On-demand, deliberately |
15268
+ | Results | Binary (new issues yes/no) | Detailed vulnerability reports |
15269
+ | Resource usage | Minimal | Higher |
15270
+
15271
+ **Strategy:** Use monitoring frequently, trigger full scans only when needed.
15272
+
15273
+ ## Example Usage
15274
+
15275
+ ### Scenario 1: End of Coding Session
15276
+
15277
+ \`\`\`
15278
+ AI: "I'm running a final security check on your changes..."
15279
+
15280
+ [Calls check_for_new_available_fixes]
15281
+
15282
+ AI: "\u2713 All clear! No new security vulnerabilities detected. Your code is safe to commit."
15283
+ \`\`\`
15284
+
15285
+ ### Scenario 2: New Vulnerabilities Found
15286
+
15287
+ \`\`\`
15288
+ AI: "Running continuous security monitoring..."
15289
+
15290
+ [Calls check_for_new_available_fixes]
15291
+
15292
+ AI: "\u26A0\uFE0F I detected 2 new security vulnerabilities:
15293
+ - 1 High severity
15294
+ - 1 Medium severity
15295
+
15296
+ Would you like me to run a full scan to see the details and available fixes?"
15297
+
15298
+ User: "Yes, please"
15299
+
15300
+ [AI proceeds to call scan_and_fix_vulnerabilities]
15301
+ \`\`\`
15302
+
15303
+ ### Scenario 3: After Applying Fixes
15304
+
15305
+ \`\`\`
15306
+ AI: "I've applied the security fixes. Let me verify no new issues were introduced..."
15307
+
15308
+ [Calls check_for_new_available_fixes]
15309
+
15310
+ AI: "\u2713 Perfect! The fixes resolved the issues and no new vulnerabilities were introduced. Your code is now more secure."
15311
+ \`\`\`
15312
+
15313
+ ## Silent vs. Announced Monitoring
15314
+
15315
+ **Silent monitoring** (recommended for background checks):
15316
+ - Call the tool without announcing it
15317
+ - Only notify user if issues are found
15318
+ - Keeps the experience smooth and non-intrusive
15319
+
15320
+ **Announced monitoring** (use when setting up or after significant changes):
15321
+ - Tell the user monitoring is running
15322
+ - Confirm when monitoring is enabled
15323
+ - Provides transparency and confidence
15324
+
15325
+ ## Technical Details
15326
+
15327
+ The tool:
15328
+ - Connects to Mobb's backend API
15329
+ - Checks for new vulnerability data
15330
+ - Compares against last known state
15331
+ - Returns summary of new findings
15332
+ - Maintains minimal overhead
15333
+
15334
+ ## Ready to Monitor
15335
+
15336
+ Call the \`check_for_new_available_fixes\` tool now${args?.path ? ` for ${args.path}` : ""} to enable continuous security monitoring. This is a best practice that helps catch vulnerabilities early and maintain code security over time.
15337
+ `;
15338
+ return this.createUserMessage(promptText);
15339
+ }
15340
+ };
15341
+
15342
+ // src/mcp/prompts/FullSecurityAuditPrompt.ts
15343
+ import { z as z34 } from "zod";
15344
+ var FullSecurityAuditArgsSchema = z34.object({
15345
+ path: z34.string().optional()
15346
+ });
15347
+ var FullSecurityAuditPrompt = class extends BasePrompt {
15348
+ constructor() {
15349
+ super(...arguments);
15350
+ __publicField(this, "name", "full-security-audit");
15351
+ __publicField(this, "description", "Complete end-to-end security audit workflow: scan \u2192 review \u2192 fix \u2192 verify \u2192 monitor");
15352
+ __publicField(this, "arguments", [
15353
+ {
15354
+ name: "path",
15355
+ description: "Optional: Full local path to the git repository to audit",
15356
+ required: false
15357
+ }
15358
+ ]);
15359
+ __publicField(this, "argumentsValidationSchema", FullSecurityAuditArgsSchema);
15360
+ }
15361
+ async generatePrompt(validatedArgs) {
15362
+ const args = validatedArgs;
15363
+ const promptText = `# Complete Security Audit Workflow
15364
+
15365
+ This is a comprehensive, end-to-end security audit process that will scan, review, fix, verify, and set up monitoring for a repository.
15366
+
15367
+ ## Audit Overview
15368
+
15369
+ This workflow includes:
15370
+ 1. **Initial Assessment** - Understand the repository
15371
+ 2. **Comprehensive Scan** - Full security analysis
15372
+ 3. **Issue Review** - Categorize and prioritize vulnerabilities
15373
+ 4. **Fix Application** - Apply security patches systematically
15374
+ 5. **Verification** - Confirm fixes work correctly
15375
+ 6. **Continuous Monitoring** - Set up ongoing security checks
15376
+ 7. **Final Report** - Document all actions taken
15377
+
15378
+ **Estimated Time:** 10-30 minutes depending on repository size and issue count
15379
+
15380
+ ## Prerequisites
15381
+
15382
+ Before starting:
15383
+ - Repository should be in a clean git state (or user is aware of uncommitted changes)
15384
+ - Tests should be available and passing
15385
+ - User has time to review and address issues
15386
+ - Backup or branch created (recommended for first-time users)
15387
+
15388
+ ## Phase 1: Initial Assessment
15389
+
15390
+ ### Step 1.1: Gather Repository Information
15391
+ ${args?.path ? `\u2713 Repository path: \`${args.path}\`` : `- Request repository path from user
15392
+ - Ask: "What is the full path to the repository you want to audit?"`}
15393
+
15394
+ ### Step 1.2: Set Expectations
15395
+
15396
+ Inform the user:
15397
+
15398
+ \`\`\`
15399
+ "I'll perform a complete security audit of your repository. This will:
15400
+ - Scan all code for security vulnerabilities
15401
+ - Identify issues across all severity levels
15402
+ - Provide automatic fixes where possible
15403
+ - Set up continuous monitoring
15404
+
15405
+ This process will take a few minutes. I'll guide you through each step and explain my findings.
15406
+
15407
+ Ready to begin?"
15408
+ \`\`\`
15409
+
15410
+ ### Step 1.3: Check Repository Status
15411
+
15412
+ Recommend running git status:
15413
+ \`\`\`bash
15414
+ git status
15415
+ \`\`\`
15416
+
15417
+ If there are uncommitted changes, suggest:
15418
+ - "I see uncommitted changes. Would you like to commit or stash them first?"
15419
+ - "We can proceed, but I recommend committing current work first."
15420
+
15421
+ ## Phase 2: Comprehensive Scan
15422
+
15423
+ ### Step 2.1: Initial Full Scan
15424
+
15425
+ Call \`scan_and_fix_vulnerabilities\`:
15426
+
15427
+ \`\`\`json
15428
+ {
15429
+ "path": "${args?.path || "<repository-path>"}",
15430
+ "limit": 10,
15431
+ "maxFiles": 50
15432
+ }
15433
+ \`\`\`
15434
+
15435
+ Larger limits for comprehensive audit.
15436
+
15437
+ ### Step 2.2: Initial Results Analysis
15438
+
15439
+ When results arrive, analyze and present:
15440
+
15441
+ 1. **Executive Summary:**
15442
+ \`\`\`
15443
+ Security Scan Complete
15444
+ ----------------------
15445
+ Total Vulnerabilities Found: [N]
15446
+
15447
+ By Severity:
15448
+ - \u{1F534} Critical: [N] (immediate action required)
15449
+ - \u{1F7E0} High: [N] (urgent)
15450
+ - \u{1F7E1} Medium: [N] (important)
15451
+ - \u{1F535} Low: [N] (maintenance)
15452
+
15453
+ By Category:
15454
+ - [List top 3-5 vulnerability types found]
15455
+
15456
+ Fixable: [N] vulnerabilities have automatic fixes available
15457
+ \`\`\`
15458
+
15459
+ 2. **Initial Recommendation:**
15460
+ Based on findings, recommend:
15461
+ - If Critical exists: "Address critical issues immediately"
15462
+ - If mostly High/Medium: "Systematic fix approach recommended"
15463
+ - If only Low: "Good security posture, minor improvements available"
15464
+
15465
+ ## Phase 3: Issue Review & Prioritization
15466
+
15467
+ ### Step 3.1: Detailed Issue Presentation
15468
+
15469
+ Present issues in priority order:
15470
+
15471
+ **For each Critical vulnerability:**
15472
+ \`\`\`
15473
+ \u{1F534} CRITICAL: [Type]
15474
+ Location: [file:line]
15475
+ Risk Level: Severe Security Threat
15476
+
15477
+ Description: [What the vulnerability is]
15478
+ Attack Vector: [How it could be exploited]
15479
+ Impact: [What an attacker could do]
15480
+
15481
+ Proposed Fix: [Summary of the fix]
15482
+ [Show diff/patch preview]
15483
+
15484
+ Last modified by: [git blame]
15485
+ \`\`\`
15486
+
15487
+ Continue for High, Medium, Low...
15488
+
15489
+ ### Step 3.2: Create Fix Plan
15490
+
15491
+ Generate a structured fix plan:
15492
+
15493
+ \`\`\`markdown
15494
+ ## Security Fix Plan
15495
+
15496
+ ### Phase 1: Critical Fixes (Do First)
15497
+ 1. [Vulnerability type] in [file]
15498
+ 2. [Vulnerability type] in [file]
15499
+ ...
15500
+
15501
+ ### Phase 2: High Severity Fixes
15502
+ 1. [Vulnerability type] in [file]
15503
+ 2. [Vulnerability type] in [file]
15504
+ ...
15505
+
15506
+ ### Phase 3: Medium Severity Fixes
15507
+ [Can be done in follow-up session]
15508
+
15509
+ ### Phase 4: Low Severity Fixes
15510
+ [Add to maintenance backlog]
15511
+ \`\`\`
15512
+
15513
+ ### Step 3.3: Get User Approval
15514
+
15515
+ Ask user how they want to proceed:
15516
+
15517
+ "I've identified the security issues and created a fix plan. How would you like to proceed?
15518
+
15519
+ 1. **Comprehensive Fix** - Fix all Critical and High issues now (recommended)
15520
+ 2. **Critical Only** - Fix only Critical issues now
15521
+ 3. **Selective Fix** - Review and choose which fixes to apply
15522
+ 4. **Report Only** - Generate report without applying fixes (for review)
15523
+
15524
+ Recommendation: Option 1 for best security posture."
15525
+
15526
+ ## Phase 4: Fix Application
15527
+
15528
+ Based on user choice, systematically apply fixes:
15529
+
15530
+ ### Step 4.1: Apply Critical Fixes
15531
+
15532
+ For each Critical fix:
15533
+ 1. Show what will be fixed
15534
+ 2. Apply the patch
15535
+ 3. Confirm application: "\u2713 Fixed: [vulnerability] in [file]"
15536
+ 4. Track progress: "[N/Total] Critical fixes applied"
15537
+
15538
+ ### Step 4.2: Apply High Severity Fixes
15539
+
15540
+ Same process as Critical, but can be done in batches.
15541
+
15542
+ ### Step 4.3: Handle Fix Failures
15543
+
15544
+ If a fix fails to apply:
15545
+ 1. Note the failure
15546
+ 2. Show the conflict or error
15547
+ 3. Mark for manual review
15548
+ 4. Continue with remaining fixes
15549
+ 5. Summarize failed fixes at the end
15550
+
15551
+ ## Phase 5: Verification
15552
+
15553
+ ### Step 5.1: Verify Patches Applied
15554
+
15555
+ Check each modified file:
15556
+ \`\`\`bash
15557
+ git status
15558
+ git diff
15559
+ \`\`\`
15560
+
15561
+ Confirm:
15562
+ - Expected files were modified
15563
+ - No unexpected changes
15564
+ - No merge conflicts
15565
+
15566
+ ### Step 5.2: Run Test Suite
15567
+
15568
+ If tests exist:
15569
+
15570
+ \`\`\`bash
15571
+ # Run appropriate test command
15572
+ npm test
15573
+ # or
15574
+ pytest
15575
+ # or
15576
+ mvn test
15577
+ \`\`\`
15578
+
15579
+ **If tests pass:**
15580
+ "\u2705 All tests passed! Security fixes did not break functionality."
15581
+
15582
+ **If tests fail:**
15583
+ "\u26A0\uFE0F Some tests are failing after applying fixes:
15584
+ [List failing tests]
15585
+
15586
+ This could mean:
15587
+ 1. Tests need to be updated (common for security fixes)
15588
+ 2. A fix introduced an issue (less common)
15589
+
15590
+ Would you like me to:
15591
+ 1. Review the failing tests
15592
+ 2. Revert specific fixes
15593
+ 3. Continue anyway (tests may need updates)"
15594
+
15595
+ ### Step 5.3: Re-scan for Verification
15596
+
15597
+ Call \`scan_and_fix_vulnerabilities\` again with \`rescan: true\`:
15598
+
15599
+ \`\`\`json
15600
+ {
15601
+ "path": "${args?.path || "<repository-path>"}",
15602
+ "rescan": true,
15603
+ "limit": 10
15604
+ }
15605
+ \`\`\`
15606
+
15607
+ Compare before/after:
15608
+ - Confirm fixed vulnerabilities are gone
15609
+ - Check no new vulnerabilities were introduced
15610
+ - Verify severity counts decreased as expected
15611
+
15612
+ ## Phase 6: Continuous Monitoring Setup
15613
+
15614
+ ### Step 6.1: Enable Monitoring
15615
+
15616
+ Call \`check_for_new_available_fixes\`:
15617
+
15618
+ \`\`\`json
15619
+ {
15620
+ "path": "${args?.path || "<repository-path>"}"
15621
+ }
15622
+ \`\`\`
15623
+
15624
+ ### Step 6.2: Explain Monitoring
15625
+
15626
+ "\u2705 Continuous security monitoring is now enabled for this repository.
15627
+
15628
+ What this means:
15629
+ - Periodic background checks for new vulnerabilities
15630
+ - Notifications when security issues are detected
15631
+ - Ongoing protection as code evolves
15632
+
15633
+ This helps maintain the security improvements we just made."
15634
+
15635
+ ## Phase 7: Final Report
15636
+
15637
+ ### Step 7.1: Generate Comprehensive Report
15638
+
15639
+ Create a detailed report:
15640
+
15641
+ \`\`\`markdown
15642
+ # Security Audit Report
15643
+ Repository: [name/path]
15644
+ Date: [date]
15645
+ Audited by: Mobb AI Security Assistant
15646
+
15647
+ ## Executive Summary
15648
+ - Total vulnerabilities found: [N]
15649
+ - Vulnerabilities fixed: [N]
15650
+ - Files modified: [N]
15651
+ - Test status: [Pass/Fail/Not Run]
15652
+
15653
+ ## Vulnerabilities Fixed
15654
+
15655
+ ### Critical (\u{1F534})
15656
+ 1. [Type] in [file:line] - FIXED \u2705
15657
+ - Risk: [description]
15658
+ - Fix: [description]
15659
+
15660
+ 2. [Type] in [file:line] - FIXED \u2705
15661
+ ...
15662
+
15663
+ ### High (\u{1F7E0})
15664
+ [Similar format]
15665
+
15666
+ ### Medium (\u{1F7E1})
15667
+ [List - note which were fixed]
15668
+
15669
+ ### Low (\u{1F535})
15670
+ [List - note which were fixed]
15671
+
15672
+ ## Files Modified
15673
+ - [list all modified files with change descriptions]
15674
+
15675
+ ## Verification Results
15676
+ \u2705 All fixes applied successfully
15677
+ \u2705 Tests passing
15678
+ \u2705 Re-scan confirms vulnerabilities resolved
15679
+ \u2705 No new vulnerabilities introduced
15680
+
15681
+ ## Remaining Items
15682
+ - [N] Medium severity issues (recommended to fix soon)
15683
+ - [N] Low severity issues (maintenance backlog)
15684
+
15685
+ ## Recommendations
15686
+ 1. Commit these security improvements
15687
+ 2. Deploy to staging environment for testing
15688
+ 3. Schedule follow-up for remaining Medium issues
15689
+ 4. Review security practices to prevent future issues
15690
+ 5. Keep continuous monitoring enabled
15691
+
15692
+ ## Next Steps
15693
+ 1. Review the changes: git diff
15694
+ 2. Run additional tests if needed
15695
+ 3. Commit: git add . && git commit -m "Security fixes: addressed [N] critical and high severity vulnerabilities"
15696
+ 4. Push to remote repository
15697
+ 5. Deploy with confidence
15698
+
15699
+ ---
15700
+ \u{1F512} Security Level: [Excellent/Good/Fair] (based on remaining issues)
15701
+ \`\`\`
15702
+
15703
+ ### Step 7.2: Provide Next Steps
15704
+
15705
+ Give clear guidance:
15706
+
15707
+ "## What to do next:
15708
+
15709
+ **Immediate (Do now):**
15710
+ 1. Review the changes made (git diff)
15711
+ 2. Commit the security fixes
15712
+ 3. Push to your repository
15713
+
15714
+ **Soon (This week):**
15715
+ 1. Address remaining Medium severity issues ([N] items)
15716
+ 2. Review security best practices for your framework
15717
+ 3. Share this report with your team
15718
+
15719
+ **Ongoing:**
15720
+ 1. Continuous monitoring is active
15721
+ 2. Run security scans after major changes
15722
+ 3. Keep dependencies updated
15723
+
15724
+ **Questions?**
15725
+ - Need help with any specific fix?
15726
+ - Want to understand a vulnerability better?
15727
+ - Need guidance on preventing similar issues?
15728
+
15729
+ Ask me anything!"
15730
+
15731
+ ## Important Guidelines
15732
+
15733
+ ### Communication Throughout
15734
+
15735
+ **Be:**
15736
+ - Professional and clear
15737
+ - Patient and thorough
15738
+ - Encouraging and supportive
15739
+ - Transparent about what you're doing
15740
+
15741
+ **Tone:**
15742
+ - Security issues are serious but fixable
15743
+ - Congratulate progress
15744
+ - Celebrate improvements
15745
+ - Don't blame or shame
15746
+
15747
+ ### DO:
15748
+ \u2705 Follow all phases systematically
15749
+ \u2705 Explain each step clearly
15750
+ \u2705 Get user approval before major actions
15751
+ \u2705 Verify all changes
15752
+ \u2705 Provide comprehensive documentation
15753
+ \u2705 Enable monitoring
15754
+ \u2705 Give clear next steps
15755
+
15756
+ ### DON'T:
15757
+ \u274C Rush through the process
15758
+ \u274C Skip verification steps
15759
+ \u274C Apply fixes without explanation
15760
+ \u274C Forget to check for new issues
15761
+ \u274C Leave user without next steps
15762
+ \u274C Create alarm - be solution-focused
15763
+
15764
+ ## Time Management
15765
+
15766
+ For large repositories with many issues:
15767
+ - Take breaks between phases
15768
+ - Offer to pause and resume later
15769
+ - Batch fixes appropriately
15770
+ - Don't overwhelm the user
15771
+
15772
+ Suggest: "We've fixed [N] critical issues. Would you like to continue with High severity, or take a break and resume later?"
15773
+
15774
+ ## Success Criteria
15775
+
15776
+ Audit is successful when:
15777
+ \u2705 All Critical vulnerabilities are fixed
15778
+ \u2705 Most High severity issues addressed
15779
+ \u2705 All fixes verified and tested
15780
+ \u2705 No new vulnerabilities introduced
15781
+ \u2705 Continuous monitoring enabled
15782
+ \u2705 Comprehensive report provided
15783
+ \u2705 User understands next steps
15784
+
15785
+ ## Ready to Begin
15786
+
15787
+ This is a comprehensive security audit that will significantly improve the security posture of the repository. Follow each phase carefully, communicate clearly, and celebrate the improvements made.
15788
+
15789
+ Begin the audit now${args?.path ? ` for ${args.path}` : ""}.
15790
+ `;
15791
+ return this.createUserMessage(promptText);
15792
+ }
15793
+ };
15794
+
15795
+ // src/mcp/prompts/ReviewAndFixCriticalPrompt.ts
15796
+ import { z as z35 } from "zod";
15797
+ var ReviewAndFixCriticalArgsSchema = z35.object({
15798
+ path: z35.string().optional()
15799
+ });
15800
+ var ReviewAndFixCriticalPrompt = class extends BasePrompt {
15801
+ constructor() {
15802
+ super(...arguments);
15803
+ __publicField(this, "name", "review-and-fix-critical");
15804
+ __publicField(this, "description", "Focused workflow for identifying and fixing Critical and High severity security vulnerabilities");
15805
+ __publicField(this, "arguments", [
15806
+ {
15807
+ name: "path",
15808
+ description: "Optional: Full local path to the git repository to scan and fix",
15809
+ required: false
15810
+ }
15811
+ ]);
15812
+ __publicField(this, "argumentsValidationSchema", ReviewAndFixCriticalArgsSchema);
15813
+ }
15814
+ async generatePrompt(validatedArgs) {
15815
+ const args = validatedArgs;
15816
+ const promptText = `# Critical Security Vulnerabilities - Review and Fix
15817
+
15818
+ This is a focused workflow for identifying and addressing Critical and High severity security vulnerabilities that require immediate attention.
15819
+
15820
+ ## Workflow Purpose
15821
+
15822
+ Use this workflow when:
15823
+ - Security is a high priority
15824
+ - Preparing for production deployment
15825
+ - Security audit or compliance review is needed
15826
+ - You want to address the most severe issues first
15827
+ - Time is limited and you need to focus on critical threats
15828
+
15829
+ ## Severity Priority
15830
+
15831
+ **CRITICAL** \u{1F534}
15832
+ - Immediate security risk
15833
+ - Can lead to complete system compromise
15834
+ - Examples: Remote Code Execution, Authentication Bypass, SQL Injection with data exposure
15835
+ - **Action: FIX IMMEDIATELY**
15836
+
15837
+ **HIGH** \u{1F7E0}
15838
+ - Significant security vulnerability
15839
+ - Can lead to data breaches or unauthorized access
15840
+ - Examples: XSS attacks, Privilege Escalation, Exposed Sensitive Data
15841
+ - **Action: FIX URGENTLY**
15842
+
15843
+ Medium and Low severity issues will be noted but not prioritized in this workflow.
15844
+
15845
+ ## Workflow Steps
15846
+
15847
+ ### Step 1: Initial Scan
15848
+ ${args?.path ? `Scanning repository at: \`${args.path}\`` : `Obtain the repository path from the user.`}
15849
+
15850
+ Call \`scan_and_fix_vulnerabilities\`:
15851
+
15852
+ \`\`\`json
15853
+ {
15854
+ "path": "${args?.path || "<repository-path>"}",
15855
+ "limit": 10,
15856
+ "maxFiles": 20
15857
+ }
15858
+ \`\`\`
15859
+
15860
+ Higher limits to ensure we catch all critical issues.
15861
+
15862
+ ### Step 2: Filter and Present Critical Issues
15863
+
15864
+ When results arrive:
15865
+
15866
+ 1. **Count vulnerabilities by severity:**
15867
+ - Critical count
15868
+ - High count
15869
+ - Medium count (mention but don't focus)
15870
+ - Low count (mention but don't focus)
15871
+
15872
+ 2. **Present ONLY Critical and High severity issues:**
15873
+
15874
+ For each Critical/High vulnerability:
15875
+
15876
+ \`\`\`
15877
+ \u{1F534} CRITICAL: [Vulnerability Type]
15878
+
15879
+ File: [path/to/file.ext:line]
15880
+ Last modified by: [git blame user]
15881
+
15882
+ Risk: [Explain the security risk in simple terms]
15883
+
15884
+ Proposed Fix:
15885
+ [Show the diff/patch]
15886
+
15887
+ Impact: [What this fix does and why it's necessary]
15888
+ \`\`\`
15889
+
15890
+ 3. **Provide clear summary:**
15891
+ "Found X critical and Y high severity vulnerabilities that require immediate attention."
15892
+
15893
+ ### Step 3: Prioritize Fixes
15894
+
15895
+ Create a fix priority list:
15896
+
15897
+ **Phase 1 - Critical (DO FIRST):**
15898
+ - List all Critical issues
15899
+ - Sort by risk level
15900
+ - Recommend fixing ALL before any High issues
15901
+
15902
+ **Phase 2 - High (DO SECOND):**
15903
+ - List all High issues
15904
+ - Can be addressed after Critical are resolved
15905
+
15906
+ **Ask the user:**
15907
+ "I recommend we fix these in priority order. Would you like me to:
15908
+ 1. Apply ALL critical fixes automatically (recommended)
15909
+ 2. Review each critical fix individually
15910
+ 3. See the full details before proceeding"
15911
+
15912
+ ### Step 4: Apply Fixes
15913
+
15914
+ Based on user choice:
15915
+
15916
+ #### Option 1: Apply All Critical Automatically
15917
+
15918
+ \`\`\`
15919
+ "I'll apply all [N] critical fixes now. This will modify [X] files."
15920
+
15921
+ For each fix:
15922
+ 1. Apply the patch
15923
+ 2. Verify it applied successfully
15924
+ 3. Show brief confirmation: "\u2713 Fixed: [vulnerability type] in [file]"
15925
+
15926
+ "All critical fixes applied. Running verification..."
15927
+ [Call check_for_new_available_fixes to verify]
15928
+
15929
+ "Next, I can address the [N] high severity issues. Continue?"
15930
+ \`\`\`
15931
+
15932
+ #### Option 2: Review Each Fix Individually
15933
+
15934
+ For each Critical fix:
15935
+ 1. Show the vulnerability details
15936
+ 2. Show the exact code changes
15937
+ 3. Explain the security improvement
15938
+ 4. Ask: "Apply this fix? (yes/no/skip)"
15939
+ 5. Apply if approved
15940
+ 6. Move to next
15941
+
15942
+ #### Option 3: Provide Full Details First
15943
+
15944
+ - Show comprehensive analysis of each vulnerability
15945
+ - Include CVE references if available
15946
+ - Explain attack vectors
15947
+ - Demonstrate how the fix prevents the attack
15948
+ - Then proceed to fixing phase
15949
+
15950
+ ### Step 5: Verification
15951
+
15952
+ After applying fixes:
15953
+
15954
+ 1. **Verify fixes applied correctly:**
15955
+ - Check files were modified
15956
+ - No merge conflicts
15957
+ - Code syntax is valid
15958
+
15959
+ 2. **Run tests if available:**
15960
+ \`\`\`bash
15961
+ npm test
15962
+ # or
15963
+ pytest
15964
+ # or appropriate test command
15965
+ \`\`\`
15966
+
15967
+ 3. **Re-scan to confirm:**
15968
+ Call \`scan_and_fix_vulnerabilities\` again with \`rescan: true\`
15969
+
15970
+ Verify:
15971
+ - Critical issues are resolved
15972
+ - No new issues were introduced
15973
+ - High severity count decreased (if those were also fixed)
15974
+
15975
+ ### Step 6: Summary Report
15976
+
15977
+ Provide a comprehensive summary:
15978
+
15979
+ \`\`\`markdown
15980
+ ## Security Fix Summary
15981
+
15982
+ ### Fixed
15983
+ - \u2705 [N] Critical vulnerabilities resolved
15984
+ - \u2705 [N] High severity vulnerabilities resolved
15985
+
15986
+ ### Files Modified
15987
+ - [list of modified files]
15988
+
15989
+ ### Remaining Issues
15990
+ - \u26A0\uFE0F [N] Medium severity (can be addressed later)
15991
+ - \u2139\uFE0F [N] Low severity (maintenance backlog)
15992
+
15993
+ ### Recommendations
15994
+ 1. Run your test suite to ensure functionality
15995
+ 2. Review the changes before committing
15996
+ 3. Consider addressing remaining High severity issues
15997
+ 4. Schedule time for Medium/Low issues
15998
+ 5. Enable continuous monitoring
15999
+
16000
+ ### Next Steps
16001
+ - Commit these security fixes
16002
+ - Deploy to staging for testing
16003
+ - Schedule follow-up for remaining issues
16004
+ \`\`\`
16005
+
16006
+ ## Important Guidelines
16007
+
16008
+ ### Communication Style
16009
+
16010
+ **For Critical Issues:**
16011
+ - Use urgent but calm language
16012
+ - Clearly explain the risk
16013
+ - Don't create panic, but convey seriousness
16014
+ - Be direct about the need to fix immediately
16015
+
16016
+ **For High Issues:**
16017
+ - Emphasize importance but not emergency
16018
+ - Explain impact on security posture
16019
+ - Recommend fixing soon but not necessarily right now
16020
+
16021
+ ### DO:
16022
+ \u2705 Fix ALL Critical issues before moving to High
16023
+ \u2705 Explain each vulnerability clearly
16024
+ \u2705 Show exact code changes
16025
+ \u2705 Verify fixes were applied successfully
16026
+ \u2705 Run tests after applying fixes
16027
+ \u2705 Create a clear summary of actions taken
16028
+ \u2705 Recommend continuous monitoring
16029
+
16030
+ ### DON'T:
16031
+ \u274C Apply fixes without user approval (except if explicitly requested)
16032
+ \u274C Minimize the importance of Critical issues
16033
+ \u274C Get distracted by Medium/Low issues during this workflow
16034
+ \u274C Skip verification steps
16035
+ \u274C Forget to check for new issues after applying fixes
16036
+ \u274C Rush through explanations
16037
+
16038
+ ## Example Interaction
16039
+
16040
+ \`\`\`
16041
+ AI: "Scanning repository for critical security vulnerabilities..."
16042
+
16043
+ [Scans]
16044
+
16045
+ AI: "\u26A0\uFE0F **Security Alert: Critical Issues Found**
16046
+
16047
+ I found 3 critical and 5 high severity vulnerabilities:
16048
+
16049
+ \u{1F534} **CRITICAL ISSUES** (Must fix immediately):
16050
+
16051
+ 1. **SQL Injection** in src/api/users.ts:67
16052
+ - Risk: Attacker can access entire database
16053
+ - Last modified by: john@example.com
16054
+ - Fix: Use parameterized queries
16055
+
16056
+ 2. **Authentication Bypass** in src/auth/middleware.ts:23
16057
+ - Risk: Unauthorized access to admin functions
16058
+ - Last modified by: jane@example.com
16059
+ - Fix: Validate JWT signature properly
16060
+
16061
+ 3. **Remote Code Execution** in src/utils/processor.ts:45
16062
+ - Risk: Attacker can execute arbitrary code on server
16063
+ - Last modified by: bob@example.com
16064
+ - Fix: Sanitize eval() input
16065
+
16066
+ \u{1F7E0} **HIGH SEVERITY** (Fix urgently):
16067
+ [Lists 5 high issues...]
16068
+
16069
+ **Recommendation:** Fix all 3 critical issues immediately. Would you like me to:
16070
+ 1. Apply ALL critical fixes now (recommended) \u2190 [DEFAULT]
16071
+ 2. Review each fix individually
16072
+ 3. See detailed analysis first"
16073
+
16074
+ User: "Apply all critical fixes"
16075
+
16076
+ AI: "Applying all critical fixes...
16077
+
16078
+ \u2713 Fixed: SQL Injection in src/api/users.ts
16079
+ \u2713 Fixed: Authentication Bypass in src/auth/middleware.ts
16080
+ \u2713 Fixed: Remote Code Execution in src/utils/processor.ts
16081
+
16082
+ All critical vulnerabilities resolved! Running verification...
16083
+
16084
+ \u2713 Verification complete - no new issues introduced.
16085
+
16086
+ 3 files modified, 0 critical issues remaining.
16087
+
16088
+ Would you like to proceed with fixing the 5 high severity issues?"
16089
+ \`\`\`
16090
+
16091
+ ## Ready to Begin
16092
+
16093
+ This workflow focuses exclusively on the most dangerous vulnerabilities. Follow the steps above to systematically eliminate critical security threats from the codebase.
16094
+
16095
+ Start by scanning${args?.path ? ` ${args.path}` : " the repository"} and prioritizing Critical and High severity issues.
16096
+ `;
16097
+ return this.createUserMessage(promptText);
16098
+ }
16099
+ };
16100
+
16101
+ // src/mcp/prompts/ScanRecentChangesPrompt.ts
16102
+ import { z as z36 } from "zod";
16103
+ var ScanRecentChangesArgsSchema = z36.object({
16104
+ path: z36.string().optional()
16105
+ });
16106
+ var ScanRecentChangesPrompt = class extends BasePrompt {
16107
+ constructor() {
16108
+ super(...arguments);
16109
+ __publicField(this, "name", "scan-recent-changes");
16110
+ __publicField(this, "description", "Guide for scanning only recently modified files for new security vulnerabilities");
16111
+ __publicField(this, "arguments", [
16112
+ {
16113
+ name: "path",
16114
+ description: "Optional: Full local path to the git repository to scan",
16115
+ required: false
16116
+ }
16117
+ ]);
16118
+ __publicField(this, "argumentsValidationSchema", ScanRecentChangesArgsSchema);
16119
+ }
16120
+ async generatePrompt(validatedArgs) {
16121
+ const args = validatedArgs;
16122
+ const promptText = `# Scan Recent Changes for Security Issues
16123
+
16124
+ This workflow helps you quickly scan only the files that have been recently modified, making security checks fast and targeted.
16125
+
16126
+ ## When to Use This Workflow
16127
+
16128
+ Use this approach when:
16129
+ - You've just made code changes and want to check for new vulnerabilities
16130
+ - You want a quick security check without scanning the entire repository
16131
+ - You're working in a specific area of the codebase
16132
+ - You want faster scan results
16133
+ - You're doing iterative development and want continuous security feedback
16134
+
16135
+ ## Workflow Steps
16136
+
16137
+ ### Step 1: Determine Repository Path
16138
+ ${args?.path ? `\u2713 Repository path provided: \`${args.path}\`` : `Ask the user for the full local path to the git repository.`}
16139
+
16140
+ ### Step 2: Call scan_and_fix_vulnerabilities with Recent Changes Flag
16141
+
16142
+ Use the \`scan_and_fix_vulnerabilities\` tool with the \`scanRecentlyChangedFiles\` parameter:
16143
+
16144
+ \`\`\`json
16145
+ {
16146
+ "path": "${args?.path || "<repository-path>"}",
16147
+ "scanRecentlyChangedFiles": true,
16148
+ "limit": 5
16149
+ }
16150
+ \`\`\`
16151
+
16152
+ **Key parameters:**
16153
+ - \`scanRecentlyChangedFiles: true\` - Only scans files modified recently
16154
+ - \`limit: 5\` - Return up to 5 fixes (adjustable based on user needs)
16155
+
16156
+ ### Step 3: Present Results
16157
+
16158
+ When you receive results:
16159
+
16160
+ #### If new vulnerabilities found:
16161
+
16162
+ 1. **Alert the user:**
16163
+ "\u26A0\uFE0F Security issues detected in recently modified files!"
16164
+
16165
+ 2. **Provide context:**
16166
+ - Number of new vulnerabilities introduced
16167
+ - Which files are affected
16168
+ - Severity breakdown
16169
+ - Who made the changes (git blame)
16170
+
16171
+ 3. **Show each vulnerability:**
16172
+ - File and line number
16173
+ - Type of vulnerability
16174
+ - Severity level
16175
+ - Proposed fix with diff preview
16176
+
16177
+ 4. **Recommend immediate action:**
16178
+ For Critical/High severity:
16179
+ - "I strongly recommend addressing these issues before committing/merging"
16180
+ - "Would you like me to apply the fixes now?"
16181
+
16182
+ #### If no vulnerabilities found:
16183
+
16184
+ "\u2713 Great! No new security issues detected in your recent changes."
16185
+
16186
+ Optional suggestions:
16187
+ - Continue with your work
16188
+ - Commit your changes
16189
+ - Consider enabling continuous monitoring
16190
+
16191
+ #### If no recently changed files:
16192
+
16193
+ "No recently modified files detected. This could mean:
16194
+ - No uncommitted changes exist
16195
+ - No files were modified recently
16196
+ - The repository has no git history
16197
+
16198
+ Would you like to:
16199
+ 1. Perform a full repository scan instead?
16200
+ 2. Check the repository status?"
16201
+
16202
+ ### Step 4: Handle User Decisions
16203
+
16204
+ **If user wants to apply fixes:**
16205
+ - Confirm each fix before applying
16206
+ - Show the exact changes
16207
+ - Apply patches sequentially
16208
+ - Verify each application succeeded
16209
+ - Run tests if available
16210
+
16211
+ **If user wants to see more details:**
16212
+ - Explain the vulnerability type
16213
+ - Show the vulnerable code pattern
16214
+ - Explain how the fix improves security
16215
+ - Provide references or documentation links
16216
+
16217
+ **If user wants to continue without fixing:**
16218
+ - Warn about the risks (especially for Critical/High)
16219
+ - Suggest creating an issue to track the vulnerability
16220
+ - Remind them to fix before merging to production
16221
+
16222
+ ### Step 5: Post-Scan Recommendations
16223
+
16224
+ After handling vulnerabilities:
16225
+
16226
+ 1. **If fixes were applied:**
16227
+ - Verify the code still works (run tests)
16228
+ - Review the changes
16229
+ - Update commit message to mention security fixes
16230
+ - Consider running a full scan to check for other issues
16231
+
16232
+ 2. **If fixes were deferred:**
16233
+ - Create tracking issues for the vulnerabilities
16234
+ - Add TODO comments in the code
16235
+ - Schedule time to address them
16236
+
16237
+ 3. **Enable continuous monitoring:**
16238
+ Call \`check_for_new_available_fixes\`:
16239
+ \`\`\`json
16240
+ {
16241
+ "path": "${args?.path || "<repository-path>"}"
16242
+ }
16243
+ \`\`\`
16244
+
16245
+ ## Advantages of Scanning Recent Changes
16246
+
16247
+ \u2713 **Fast**: Only scans modified files
16248
+ \u2713 **Targeted**: Focuses on your current work
16249
+ \u2713 **Immediate feedback**: Catch issues before they're committed
16250
+ \u2713 **Less overwhelming**: Smaller result set
16251
+ \u2713 **Continuous security**: Integrates into development workflow
16252
+
16253
+ ## Important Notes
16254
+
16255
+ ### DO:
16256
+ \u2713 Run this scan after making changes but before committing
16257
+ \u2713 Address Critical/High severity issues immediately
16258
+ \u2713 Explain security risks clearly to the user
16259
+ \u2713 Offer to apply fixes automatically
16260
+ \u2713 Provide context about what changed and why it's vulnerable
16261
+
16262
+ ### DON'T:
16263
+ \u2717 Skip Critical/High severity warnings
16264
+ \u2717 Apply fixes without showing the user
16265
+ \u2717 Ignore the vulnerability just because the scan is quick
16266
+ \u2717 Forget to run tests after applying fixes
16267
+ \u2717 Assume all recent changes have vulnerabilities
16268
+
16269
+ ## Integration with Development Workflow
16270
+
16271
+ This scan type integrates well with:
16272
+ - **Pre-commit hooks**: Scan before each commit
16273
+ - **IDE integration**: Scan on file save or periodically
16274
+ - **CI/CD pipelines**: Fast security check in pull requests
16275
+ - **Iterative development**: Continuous security feedback
16276
+
16277
+ ## Example Usage
16278
+
16279
+ \`\`\`
16280
+ User: "I just added a new API endpoint for user data. Can you check if it's secure?"
16281
+
16282
+ AI: "I'll scan your recent changes for security vulnerabilities..."
16283
+
16284
+ [Calls scan_and_fix_vulnerabilities with scanRecentlyChangedFiles: true]
16285
+
16286
+ AI: "\u26A0\uFE0F Found 1 security issue in your recent changes:
16287
+
16288
+ **SQL Injection Vulnerability** (Critical)
16289
+ - File: src/api/user-data.ts:34
16290
+ - Your new endpoint is vulnerable to SQL injection
16291
+
16292
+ The issue is in this code:
16293
+ \`\`\`typescript
16294
+ const query = \`SELECT * FROM users WHERE id = \${req.params.id}\`
16295
+ \`\`\`
16296
+
16297
+ Recommended fix: Use parameterized queries
16298
+ \`\`\`typescript
16299
+ const query = 'SELECT * FROM users WHERE id = $1'
16300
+ const result = await db.query(query, [req.params.id])
16301
+ \`\`\`
16302
+
16303
+ This is a Critical severity issue. I strongly recommend fixing it before committing. Would you like me to apply this fix automatically?"
16304
+ \`\`\`
16305
+
16306
+ ## Ready to Scan
16307
+
16308
+ You now have the guidance needed to perform a fast, targeted security scan of recent changes. Follow the workflow above to help users catch security issues early in their development process.
16309
+ `;
16310
+ return this.createUserMessage(promptText);
16311
+ }
16312
+ };
16313
+
16314
+ // src/mcp/prompts/ScanRepositoryPrompt.ts
16315
+ import { z as z37 } from "zod";
16316
+ var ScanRepositoryArgsSchema = z37.object({
16317
+ path: z37.string().optional()
16318
+ });
16319
+ var ScanRepositoryPrompt = class extends BasePrompt {
16320
+ constructor() {
16321
+ super(...arguments);
16322
+ __publicField(this, "name", "scan-repository");
16323
+ __publicField(this, "description", "Guide for performing an initial security scan of a repository using Mobb tools");
16324
+ __publicField(this, "arguments", [
16325
+ {
16326
+ name: "path",
16327
+ description: "Optional: Full local path to the git repository to scan",
16328
+ required: false
16329
+ }
16330
+ ]);
16331
+ __publicField(this, "argumentsValidationSchema", ScanRepositoryArgsSchema);
16332
+ }
16333
+ async generatePrompt(validatedArgs) {
16334
+ const args = validatedArgs;
16335
+ const pathInfo = args?.path ? `for repository at: ${args.path}` : "for the current repository";
16336
+ const promptText = `# Security Repository Scan Workflow
16337
+
16338
+ You are about to perform a security scan ${pathInfo}. Follow this workflow to scan the repository for vulnerabilities and present the findings to the user.
16339
+
16340
+ ## Workflow Steps
16341
+
16342
+ ### Step 1: Determine Repository Path
16343
+ ${args?.path ? `\u2713 Repository path provided: \`${args.path}\`` : `- The user should provide the full local path to the git repository
16344
+ - Ask: "What is the full path to the repository you want to scan?"
16345
+ - Example: /Users/username/projects/my-app`}
16346
+
16347
+ ### Step 2: Call scan_and_fix_vulnerabilities Tool
16348
+
16349
+ Use the \`scan_and_fix_vulnerabilities\` tool with these parameters:
16350
+
16351
+ \`\`\`json
16352
+ {
16353
+ "path": "${args?.path || "<repository-path>"}",
16354
+ "limit": 3,
16355
+ "maxFiles": 10
16356
+ }
16357
+ \`\`\`
16358
+
16359
+ **Why these defaults?**
16360
+ - \`limit: 3\` - Start with top 3 most severe vulnerabilities
16361
+ - \`maxFiles: 10\` - Reasonable initial scan scope
16362
+
16363
+ **Optional parameters** (use if user specifies):
16364
+ - \`rescan: true\` - Force a fresh scan (if user wants to override cached results)
16365
+ - \`scanRecentlyChangedFiles: true\` - Only scan recently modified files (faster)
16366
+
16367
+ ### Step 3: Process and Present Results
16368
+
16369
+ When you receive the scan results:
16370
+
16371
+ #### If vulnerabilities are found:
16372
+
16373
+ 1. **Provide a summary:**
16374
+ - Total number of vulnerabilities found
16375
+ - Breakdown by severity (Critical, High, Medium, Low)
16376
+ - Number of fixes available
16377
+
16378
+ 2. **Present the top fixes:**
16379
+ - Show each fix with:
16380
+ * Severity level
16381
+ * Vulnerability type (e.g., "SQL Injection", "XSS", "Insecure Dependency")
16382
+ * Affected file(s)
16383
+ * Who last modified the vulnerable code (git blame)
16384
+ * Brief description from the fix
16385
+
16386
+ 3. **Show the fix preview:**
16387
+ - Display the git diff/patch for each fix
16388
+ - Explain what changes will be made
16389
+ - Highlight the security improvement
16390
+
16391
+ 4. **Ask for user preference:**
16392
+ - "Would you like to apply these fixes automatically?"
16393
+ - "Would you like to see more vulnerabilities?" (if more exist)
16394
+ - "Would you like to focus on a specific severity level?"
16395
+
16396
+ #### If no vulnerabilities are found:
16397
+
16398
+ Congratulate the user! Their repository appears to be secure. Suggest:
16399
+ - Running periodic scans as code changes
16400
+ - Enabling continuous monitoring with \`check_for_new_available_fixes\`
16401
+
16402
+ #### If report is expired:
16403
+
16404
+ Inform the user that a previous scan is too old. Ask:
16405
+ - "A previous scan exists but is outdated. Would you like to run a fresh scan?"
16406
+ - If yes, call \`scan_and_fix_vulnerabilities\` with \`rescan: true\`
16407
+
16408
+ ### Step 4: Handle User Actions
16409
+
16410
+ Based on user response:
16411
+
16412
+ **If user wants to apply fixes:**
16413
+ - Confirm which fixes to apply (all, or specific ones)
16414
+ - Apply each fix patch using standard git apply workflow
16415
+ - Verify the changes
16416
+ - Run tests if available
16417
+ - Create a commit with the fixes
16418
+
16419
+ **If user wants to see more:**
16420
+ - Call \`fetch_available_fixes\` with:
16421
+ \`\`\`json
16422
+ {
16423
+ "path": "${args?.path || "<repository-path>"}",
16424
+ "offset": 3,
16425
+ "limit": 5
16426
+ }
16427
+ \`\`\`
16428
+ - Present the additional fixes following the same format
16429
+
16430
+ **If user wants to filter by severity:**
16431
+ - The results are already sorted by severity (Critical \u2192 High \u2192 Medium \u2192 Low)
16432
+ - Explain the severity of issues found
16433
+ - Focus on the most critical issues first
16434
+
16435
+ ### Step 5: Post-Scan Actions
16436
+
16437
+ After completing the scan and any fixes:
16438
+
16439
+ 1. **Summary of actions taken:**
16440
+ - Number of fixes applied
16441
+ - Remaining vulnerabilities (if any)
16442
+ - Files modified
16443
+
16444
+ 2. **Recommendations:**
16445
+ - Run tests to ensure fixes don't break functionality
16446
+ - Review the changes before committing
16447
+ - Consider addressing remaining Medium/Low severity issues
16448
+ - Set up continuous monitoring
16449
+
16450
+ 3. **Call monitoring tool:**
16451
+ Call \`check_for_new_available_fixes\` to enable ongoing security monitoring:
16452
+ \`\`\`json
16453
+ {
16454
+ "path": "${args?.path || "<repository-path>"}"
16455
+ }
16456
+ \`\`\`
16457
+
16458
+ ## Important Reminders
16459
+
16460
+ ### DO:
16461
+ \u2713 Present vulnerabilities clearly with severity context
16462
+ \u2713 Ask for user confirmation before applying fixes
16463
+ \u2713 Explain what each fix does
16464
+ \u2713 Start with critical/high severity issues
16465
+ \u2713 Provide clear next steps
16466
+ \u2713 Mention git blame information (shows responsibility)
16467
+
16468
+ ### DON'T:
16469
+ \u2717 Apply fixes automatically without user approval
16470
+ \u2717 Overwhelm user with all vulnerabilities at once
16471
+ \u2717 Skip severity information
16472
+ \u2717 Forget to call monitoring tool at the end
16473
+ \u2717 Assume the user wants to fix everything immediately
16474
+
16475
+ ## Error Handling
16476
+
16477
+ - **Authentication error**: Guide user to authenticate with Mobb
16478
+ - **Path not found**: Verify the path is correct and is a git repository
16479
+ - **Scan timeout**: Suggest scanning fewer files or recent changes only
16480
+ - **No report found**: This is expected for first-time scans, proceed normally
16481
+
16482
+ ## Example Conversation Flow
16483
+
16484
+ \`\`\`
16485
+ AI: "I'll scan your repository for security vulnerabilities. This may take a moment..."
16486
+
16487
+ [Calls scan_and_fix_vulnerabilities]
16488
+
16489
+ AI: "Scan complete! I found 12 security vulnerabilities:
16490
+ - 2 Critical severity
16491
+ - 5 High severity
16492
+ - 4 Medium severity
16493
+ - 1 Low severity
16494
+
16495
+ Here are the top 3 most critical issues:
16496
+
16497
+ 1. **SQL Injection** (Critical)
16498
+ - File: src/database/users.ts:45
16499
+ - Last modified by: john@example.com
16500
+ - Fix: Parameterize SQL query to prevent injection
16501
+
16502
+ [Shows diff preview]
16503
+
16504
+ 2. **Cross-Site Scripting (XSS)** (Critical)
16505
+ - File: src/components/UserProfile.tsx:122
16506
+ - Last modified by: jane@example.com
16507
+ - Fix: Sanitize user input before rendering
16508
+
16509
+ [Shows diff preview]
16510
+
16511
+ 3. **Insecure Dependency** (High)
16512
+ - Package: lodash@4.17.15
16513
+ - Fix: Upgrade to lodash@4.17.21 (fixes CVE-2021-23337)
16514
+
16515
+ Would you like to:
16516
+ 1. Apply these fixes automatically
16517
+ 2. See more vulnerabilities
16518
+ 3. Focus on specific issues"
16519
+ \`\`\`
16520
+
16521
+ ## Ready to Begin
16522
+
16523
+ You now have all the information needed to perform a security scan. Follow the steps above, call the appropriate tools, and guide the user through the process professionally and clearly.
16524
+ `;
16525
+ return this.createUserMessage(promptText);
16526
+ }
16527
+ };
16528
+
16529
+ // src/mcp/prompts/SecurityToolsOverviewPrompt.ts
16530
+ var SecurityToolsOverviewPrompt = class extends BasePrompt {
16531
+ constructor() {
16532
+ super(...arguments);
16533
+ __publicField(this, "name", "security-tools-overview");
16534
+ __publicField(this, "description", "Provides an overview of available Mobb security tools and guidance on when to use each tool");
16535
+ __publicField(this, "arguments");
16536
+ __publicField(this, "argumentsValidationSchema");
16537
+ }
16538
+ async generatePrompt() {
16539
+ const promptText = `# Mobb Security Tools Overview
16540
+
16541
+ You have access to powerful security scanning and auto-fixing tools from Mobb. Here's a comprehensive guide to the available tools and when to use them:
16542
+
16543
+ ## Available Tools
16544
+
16545
+ ### 1. **scan_and_fix_vulnerabilities**
16546
+ **Purpose:** Scans a local repository for security vulnerabilities and returns automatically-generated fixes.
16547
+
16548
+ **When to use:**
16549
+ - First-time security scan of a repository
16550
+ - Comprehensive security audit needed
16551
+ - User explicitly requests a security scan
16552
+ - After major code changes or refactoring
16553
+
16554
+ **Key features:**
16555
+ - Scans the entire repository or specific files
16556
+ - Identifies vulnerabilities across multiple categories (XSS, SQL injection, insecure dependencies, etc.)
16557
+ - Provides detailed fix information including severity levels
16558
+ - Returns git-compatible patches that can be directly applied
16559
+ - Shows who last modified vulnerable code (git blame integration)
16560
+
16561
+ **Parameters:**
16562
+ - \`path\` (required): Full local path to the git repository
16563
+ - \`offset\`: Pagination offset for results (default: 0)
16564
+ - \`limit\`: Number of fixes to return (default: 3)
16565
+ - \`maxFiles\`: Maximum files to scan (default: 10)
16566
+ - \`rescan\`: Force a new scan even if recent report exists
16567
+ - \`scanRecentlyChangedFiles\`: Only scan recently modified files
16568
+
16569
+ **Important notes:**
16570
+ - This tool requires authentication
16571
+ - Scans may take time for large repositories
16572
+ - Results are cached - use \`rescan: true\` to force a fresh scan
16573
+ - The tool returns fixes in order of severity (Critical \u2192 High \u2192 Medium \u2192 Low)
16574
+
16575
+ ### 2. **fetch_available_fixes**
16576
+ **Purpose:** Retrieves pre-generated fixes from previous scans without triggering a new scan.
16577
+
16578
+ **When to use:**
16579
+ - Checking for existing fixes without scanning
16580
+ - Retrieving additional fixes from a paginated result set
16581
+ - User wants to see more fixes beyond the initial set
16582
+ - Fetching fixes for specific files
16583
+
16584
+ **Key features:**
16585
+ - Fast retrieval of existing fix data
16586
+ - No scanning overhead
16587
+ - Supports file filtering
16588
+ - Pagination for large result sets
16589
+
16590
+ **Parameters:**
16591
+ - \`path\` (required): Full local path to the git repository
16592
+ - \`offset\`: Pagination offset
16593
+ - \`limit\`: Number of fixes to return
16594
+ - \`fileFilter\`: Filter by specific file path
16595
+ - \`fetchFixesFromAnyFile\`: Fetch fixes across all files
16596
+
16597
+ **Important notes:**
16598
+ - Returns an error if no previous scan exists
16599
+ - Does NOT trigger a new scan
16600
+ - Use this when you want to avoid re-scanning
16601
+
16602
+ ### 3. **check_for_new_available_fixes**
16603
+ **Purpose:** Monitors code for new security vulnerabilities and notifies when fixes are available.
16604
+
16605
+ **When to use:**
16606
+ - Continuous security monitoring
16607
+ - After completing a series of edits
16608
+ - End of a coding session
16609
+ - User requests ongoing security checks
16610
+
16611
+ **Key features:**
16612
+ - Lightweight background checking
16613
+ - Detects new vulnerabilities introduced by code changes
16614
+ - Non-intrusive monitoring
16615
+
16616
+ **Parameters:**
16617
+ - \`path\` (required): Full local path to the git repository
16618
+
16619
+ **Important notes:**
16620
+ - This is typically called automatically at the end of operations
16621
+ - Much lighter weight than full scans
16622
+ - Part of Mobb's continuous monitoring workflow
16623
+
16624
+ ## Best Practices
16625
+
16626
+ ### Tool Selection Guidelines
16627
+
16628
+ 1. **Starting fresh?** \u2192 Use \`scan_and_fix_vulnerabilities\`
16629
+ 2. **Already scanned, need more results?** \u2192 Use \`fetch_available_fixes\`
16630
+ 3. **Continuous monitoring?** \u2192 Use \`check_for_new_available_fixes\`
16631
+
16632
+ ### User Interaction Patterns
16633
+
16634
+ **When to ask for user confirmation:**
16635
+ - Before applying fixes automatically
16636
+ - Before running a full repository scan (can be time-consuming)
16637
+ - Before re-scanning when a recent scan exists
16638
+ - When multiple high-severity issues are found
16639
+
16640
+ **When to proceed automatically:**
16641
+ - Fetching additional fixes from existing scans
16642
+ - Running background monitoring checks
16643
+ - Displaying vulnerability information
16644
+ - Showing fix previews
16645
+
16646
+ ### Severity Levels
16647
+
16648
+ Vulnerabilities are categorized by severity:
16649
+ - **CRITICAL**: Immediate action required - severe security risk
16650
+ - **HIGH**: Important security issue - should be fixed soon
16651
+ - **MEDIUM**: Moderate security concern - fix when feasible
16652
+ - **LOW**: Minor security issue - fix during regular maintenance
16653
+
16654
+ **Recommended approach:**
16655
+ 1. Address CRITICAL issues immediately
16656
+ 2. Review and fix HIGH severity issues
16657
+ 3. Plan fixes for MEDIUM issues
16658
+ 4. Address LOW issues during regular maintenance
16659
+
16660
+ ### Workflow Example
16661
+
16662
+ \`\`\`
16663
+ 1. User opens a repository
16664
+ 2. Call scan_and_fix_vulnerabilities with default parameters
16665
+ 3. Review the returned fixes (typically top 3 by severity)
16666
+ 4. Present fixes to user with severity breakdown
16667
+ 5. If user wants to see more: call fetch_available_fixes with appropriate offset
16668
+ 6. When user approves fixes: apply the patches using git apply
16669
+ 7. After session: call check_for_new_available_fixes for monitoring
16670
+ \`\`\`
16671
+
16672
+ ## Authentication
16673
+
16674
+ All tools require authentication via the Mobb API. The tools will handle authentication automatically and prompt if credentials are needed.
16675
+
16676
+ ## Error Handling
16677
+
16678
+ Common scenarios:
16679
+ - **No fixes found**: Repository has no vulnerabilities or they're not fixable
16680
+ - **Report expired**: Previous scan is too old, need to rescan
16681
+ - **No report found**: No previous scan exists, run scan_and_fix_vulnerabilities
16682
+ - **Authentication required**: User needs to authenticate with Mobb
16683
+
16684
+ ## Next Steps
16685
+
16686
+ To get started with scanning a repository, use the \`scan-repository\` prompt which will guide you through the scanning workflow.
16687
+
16688
+ For a complete security audit workflow, use the \`full-security-audit\` prompt.
16689
+ `;
16690
+ return this.createUserMessage(promptText);
16691
+ }
16692
+ };
16693
+
16694
+ // src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
16695
+ import { z as z40 } from "zod";
16696
+
16697
+ // src/mcp/services/PathValidation.ts
16698
+ import fs13 from "fs";
16699
+ import path13 from "path";
16700
+ async function validatePath(inputPath) {
16701
+ logDebug("Validating MCP path", { inputPath });
16702
+ if (/^\/[a-zA-Z]:\//.test(inputPath)) {
16703
+ inputPath = inputPath.slice(1);
16704
+ }
16705
+ if (inputPath === "." || inputPath === "./") {
16706
+ const workspaceFolderPath = WorkspaceService.getWorkspaceFolderPath();
16707
+ if (workspaceFolderPath) {
16708
+ logDebug("Fallback to workspace folder path", {
16709
+ inputPath,
16710
+ workspaceFolderPaths: [workspaceFolderPath]
16711
+ });
16712
+ WorkspaceService.setKnownWorkspacePath(workspaceFolderPath);
16713
+ logDebug("Stored workspace folder path as known path", {
16714
+ workspaceFolderPath
16715
+ });
16716
+ return {
16717
+ isValid: true,
16718
+ path: workspaceFolderPath
16719
+ };
16720
+ } else {
16721
+ const error = `"." is not a valid path, please provide a full localpath to the repository`;
16722
+ logError(error);
16723
+ return { isValid: false, error, path: inputPath };
16724
+ }
16725
+ }
16726
+ if (inputPath.includes("..")) {
16727
+ const error = `Path contains path traversal patterns: ${inputPath}`;
16728
+ logError(error);
16729
+ return { isValid: false, error, path: inputPath };
16730
+ }
16731
+ const normalizedPath = path13.normalize(inputPath);
16732
+ if (normalizedPath.includes("..")) {
16733
+ const error = `Normalized path contains path traversal patterns: ${inputPath}`;
16734
+ logError(error);
16735
+ return { isValid: false, error, path: inputPath };
16736
+ }
16737
+ let decodedPath;
16738
+ try {
16739
+ decodedPath = decodeURIComponent(inputPath);
16740
+ } catch (err) {
16741
+ const error = `Failed to decode path: ${inputPath}`;
16742
+ logError(error, { err });
16743
+ return { isValid: false, error, path: inputPath };
16744
+ }
16745
+ if (decodedPath.includes("..") || decodedPath !== inputPath) {
16746
+ const error = `Path contains encoded traversal attempts: ${inputPath}`;
16747
+ logError(error);
16748
+ return { isValid: false, error, path: inputPath };
16749
+ }
16750
+ if (inputPath.includes("\0") || inputPath.includes("\0")) {
16751
+ const error = `Path contains dangerous characters: ${inputPath}`;
16752
+ logError(error);
16753
+ return { isValid: false, error, path: inputPath };
16754
+ }
16755
+ logDebug("Path validation successful", { inputPath });
16756
+ logDebug("Checking path existence", { inputPath });
16757
+ try {
16758
+ await fs13.promises.access(inputPath);
16759
+ logDebug("Path exists and is accessible", { inputPath });
16760
+ WorkspaceService.setKnownWorkspacePath(inputPath);
16761
+ logDebug("Stored validated path in WorkspaceService", { inputPath });
16762
+ return { isValid: true, path: inputPath };
16763
+ } catch (error) {
16764
+ const errorMessage = `Path does not exist or is not accessible: ${inputPath}`;
16765
+ logError(errorMessage, { error });
16766
+ return { isValid: false, error: errorMessage, path: inputPath };
16767
+ }
16768
+ }
16769
+
16770
+ // src/mcp/tools/base/BaseTool.ts
16771
+ import { z as z38 } from "zod";
16772
+ var BaseTool = class {
16773
+ getDefinition() {
16774
+ return {
16775
+ name: this.name,
16776
+ display_name: this.displayName,
16777
+ description: this.description,
16778
+ inputSchema: this.inputSchema
16779
+ };
16780
+ }
16781
+ async execute(args) {
16782
+ if (this.hasAuthentication) {
16783
+ logDebug(`Authenticating tool: ${this.name}`, { args });
16784
+ const mcpGqlClient = await createAuthenticatedMcpGQLClient();
16785
+ const userInfo = await mcpGqlClient.getUserInfo();
16786
+ logDebug("User authenticated successfully", { userInfo });
16787
+ }
16788
+ const validatedArgs = this.validateInput(args);
16789
+ logDebug(`Tool ${this.name} input validation successful`, {
16790
+ validatedArgs
16791
+ });
16792
+ logInfo(`Executing tool: ${this.name}`);
16793
+ const result = await this.executeInternal(validatedArgs);
16794
+ logInfo(`Tool ${this.name} executed successfully`);
16795
+ return result;
16796
+ }
16797
+ validateInput(args) {
16798
+ try {
16799
+ return this.inputValidationSchema.parse(args);
16800
+ } catch (error) {
16801
+ if (error instanceof z38.ZodError) {
16802
+ const errorDetails = error.errors.map((e) => {
16803
+ const fieldPath = e.path.length > 0 ? e.path.join(".") : "root";
16804
+ const message = e.message === "Required" ? `Missing required parameter '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
16805
+ return message;
16806
+ });
16807
+ const errorMessage = `Invalid arguments: ${errorDetails.join(", ")}`;
16808
+ throw new Error(errorMessage);
16809
+ }
16810
+ throw error;
16811
+ }
16812
+ }
16813
+ createSuccessResponse(text) {
16814
+ return {
16815
+ content: [
16816
+ {
16817
+ type: "text",
16818
+ text
16819
+ }
16820
+ ]
16821
+ };
16822
+ }
16823
+ };
16824
+
16825
+ // src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesService.ts
16826
+ init_configs();
16827
+
16828
+ // src/mcp/core/prompts.ts
16829
+ init_configs();
16830
+ function friendlyType(s) {
16831
+ const withoutUnderscores = s.replace(/_/g, " ");
16832
+ const result = withoutUnderscores.replace(/([a-z])([A-Z])/g, "$1 $2");
16833
+ return result.charAt(0).toUpperCase() + result.slice(1);
16834
+ }
16835
+ var noFixesReturnedForParameters = `No fixes returned for the given offset and limit parameters.
16836
+ `;
16837
+ var noFixesReturnedForParametersWithGuidance = ({
16838
+ offset,
16839
+ limit,
16840
+ totalCount,
16841
+ currentTool
16842
+ }) => `## No Fixes Returned for Current Parameters
16843
+
16844
+ **\u{1F4C4} Current Request:**
16845
+ - **Page:** ${Math.floor(offset / limit) + 1}
16846
+ - **Offset:** ${offset}
16847
+ - **Limit:** ${limit}
16848
+
16849
+ **\u274C Result:** No fixes returned for the given offset and limit parameters.
16850
+
16851
+ **\u2139\uFE0F Available Fixes:** ${totalCount} total fixes are available, but your current offset (${offset}) is beyond the available range.
16852
+
16853
+ **\u2705 How to Get the Fixes:**
16854
+
16855
+ To retrieve the available fixes, use one of these approaches:
16856
+
16857
+ 1. **Start from the beginning:**
16858
+ \`\`\`
16859
+ offset: 0
15034
16860
  \`\`\`
15035
16861
 
15036
16862
  2. **Go to the first page:**
@@ -15553,10 +17379,10 @@ If you wish to scan files that were recently changed in your git history call th
15553
17379
  init_FileUtils();
15554
17380
  init_GitService();
15555
17381
  init_configs();
15556
- import fs13 from "fs/promises";
17382
+ import fs14 from "fs/promises";
15557
17383
  import nodePath from "path";
15558
17384
  var getLocalFiles = async ({
15559
- path: path17,
17385
+ path: path18,
15560
17386
  maxFileSize = MCP_MAX_FILE_SIZE,
15561
17387
  maxFiles,
15562
17388
  isAllFilesScan,
@@ -15564,17 +17390,17 @@ var getLocalFiles = async ({
15564
17390
  scanRecentlyChangedFiles
15565
17391
  }) => {
15566
17392
  logDebug(`[${scanContext}] Starting getLocalFiles`, {
15567
- path: path17,
17393
+ path: path18,
15568
17394
  maxFileSize,
15569
17395
  maxFiles,
15570
17396
  isAllFilesScan,
15571
17397
  scanRecentlyChangedFiles
15572
17398
  });
15573
17399
  try {
15574
- const resolvedRepoPath = await fs13.realpath(path17);
17400
+ const resolvedRepoPath = await fs14.realpath(path18);
15575
17401
  logDebug(`[${scanContext}] Resolved repository path`, {
15576
17402
  resolvedRepoPath,
15577
- originalPath: path17
17403
+ originalPath: path18
15578
17404
  });
15579
17405
  const gitService = new GitService(resolvedRepoPath, log);
15580
17406
  const gitValidation = await gitService.validateRepository();
@@ -15587,7 +17413,7 @@ var getLocalFiles = async ({
15587
17413
  if (!gitValidation.isValid || isAllFilesScan) {
15588
17414
  try {
15589
17415
  files = await FileUtils.getLastChangedFiles({
15590
- dir: path17,
17416
+ dir: path18,
15591
17417
  maxFileSize,
15592
17418
  maxFiles,
15593
17419
  isAllFilesScan
@@ -15651,7 +17477,7 @@ var getLocalFiles = async ({
15651
17477
  absoluteFilePath
15652
17478
  );
15653
17479
  try {
15654
- const fileStat = await fs13.stat(absoluteFilePath);
17480
+ const fileStat = await fs14.stat(absoluteFilePath);
15655
17481
  return {
15656
17482
  filename: nodePath.basename(absoluteFilePath),
15657
17483
  relativePath,
@@ -15679,23 +17505,23 @@ var getLocalFiles = async ({
15679
17505
  logError(`${scanContext}Unexpected error in getLocalFiles`, {
15680
17506
  error: error instanceof Error ? error.message : String(error),
15681
17507
  stack: error instanceof Error ? error.stack : void 0,
15682
- path: path17
17508
+ path: path18
15683
17509
  });
15684
17510
  throw error;
15685
17511
  }
15686
17512
  };
15687
17513
 
15688
17514
  // src/mcp/services/LocalMobbFolderService.ts
15689
- import fs14 from "fs";
15690
- import path13 from "path";
15691
- import { z as z33 } from "zod";
17515
+ import fs15 from "fs";
17516
+ import path14 from "path";
17517
+ import { z as z39 } from "zod";
15692
17518
  init_GitService();
15693
17519
  function extractPathFromPatch(patch) {
15694
17520
  const match = patch?.match(/diff --git a\/([^\s]+) b\//);
15695
17521
  return match?.[1] ?? null;
15696
17522
  }
15697
17523
  function parsedIssueTypeRes(issueType) {
15698
- return z33.nativeEnum(IssueType_Enum).safeParse(issueType);
17524
+ return z39.nativeEnum(IssueType_Enum).safeParse(issueType);
15699
17525
  }
15700
17526
  var LocalMobbFolderService = class {
15701
17527
  /**
@@ -15774,19 +17600,19 @@ var LocalMobbFolderService = class {
15774
17600
  "[LocalMobbFolderService] Non-git repository detected, skipping .gitignore operations"
15775
17601
  );
15776
17602
  }
15777
- const mobbFolderPath = path13.join(
17603
+ const mobbFolderPath = path14.join(
15778
17604
  this.repoPath,
15779
17605
  this.defaultMobbFolderName
15780
17606
  );
15781
- if (!fs14.existsSync(mobbFolderPath)) {
17607
+ if (!fs15.existsSync(mobbFolderPath)) {
15782
17608
  logInfo("[LocalMobbFolderService] Creating .mobb folder", {
15783
17609
  mobbFolderPath
15784
17610
  });
15785
- fs14.mkdirSync(mobbFolderPath, { recursive: true });
17611
+ fs15.mkdirSync(mobbFolderPath, { recursive: true });
15786
17612
  } else {
15787
17613
  logDebug("[LocalMobbFolderService] .mobb folder already exists");
15788
17614
  }
15789
- const stats = fs14.statSync(mobbFolderPath);
17615
+ const stats = fs15.statSync(mobbFolderPath);
15790
17616
  if (!stats.isDirectory()) {
15791
17617
  throw new Error(`Path exists but is not a directory: ${mobbFolderPath}`);
15792
17618
  }
@@ -15827,13 +17653,13 @@ var LocalMobbFolderService = class {
15827
17653
  logDebug("[LocalMobbFolderService] Git repository validated successfully");
15828
17654
  } else {
15829
17655
  try {
15830
- const stats = fs14.statSync(this.repoPath);
17656
+ const stats = fs15.statSync(this.repoPath);
15831
17657
  if (!stats.isDirectory()) {
15832
17658
  throw new Error(
15833
17659
  `Path exists but is not a directory: ${this.repoPath}`
15834
17660
  );
15835
17661
  }
15836
- fs14.accessSync(this.repoPath, fs14.constants.R_OK | fs14.constants.W_OK);
17662
+ fs15.accessSync(this.repoPath, fs15.constants.R_OK | fs15.constants.W_OK);
15837
17663
  logDebug(
15838
17664
  "[LocalMobbFolderService] Non-git directory validated successfully"
15839
17665
  );
@@ -15946,8 +17772,8 @@ var LocalMobbFolderService = class {
15946
17772
  mobbFolderPath,
15947
17773
  baseFileName
15948
17774
  );
15949
- const filePath = path13.join(mobbFolderPath, uniqueFileName);
15950
- await fs14.promises.writeFile(filePath, patch, "utf8");
17775
+ const filePath = path14.join(mobbFolderPath, uniqueFileName);
17776
+ await fs15.promises.writeFile(filePath, patch, "utf8");
15951
17777
  logInfo("[LocalMobbFolderService] Patch saved successfully", {
15952
17778
  filePath,
15953
17779
  fileName: uniqueFileName,
@@ -16004,11 +17830,11 @@ var LocalMobbFolderService = class {
16004
17830
  * @returns Unique filename that doesn't conflict with existing files
16005
17831
  */
16006
17832
  getUniqueFileName(folderPath, baseFileName) {
16007
- const baseName = path13.parse(baseFileName).name;
16008
- const extension = path13.parse(baseFileName).ext;
17833
+ const baseName = path14.parse(baseFileName).name;
17834
+ const extension = path14.parse(baseFileName).ext;
16009
17835
  let uniqueFileName = baseFileName;
16010
17836
  let index = 1;
16011
- while (fs14.existsSync(path13.join(folderPath, uniqueFileName))) {
17837
+ while (fs15.existsSync(path14.join(folderPath, uniqueFileName))) {
16012
17838
  uniqueFileName = `${baseName}-${index}${extension}`;
16013
17839
  index++;
16014
17840
  if (index > 1e3) {
@@ -16039,18 +17865,18 @@ var LocalMobbFolderService = class {
16039
17865
  logDebug("[LocalMobbFolderService] Logging patch info", { fixId: fix.id });
16040
17866
  try {
16041
17867
  const mobbFolderPath = await this.getFolder();
16042
- const patchInfoPath = path13.join(mobbFolderPath, "patchInfo.md");
17868
+ const patchInfoPath = path14.join(mobbFolderPath, "patchInfo.md");
16043
17869
  const markdownContent = this.generateFixMarkdown(fix, savedPatchFileName);
16044
17870
  let existingContent = "";
16045
- if (fs14.existsSync(patchInfoPath)) {
16046
- existingContent = await fs14.promises.readFile(patchInfoPath, "utf8");
17871
+ if (fs15.existsSync(patchInfoPath)) {
17872
+ existingContent = await fs15.promises.readFile(patchInfoPath, "utf8");
16047
17873
  logDebug("[LocalMobbFolderService] Existing patchInfo.md found");
16048
17874
  } else {
16049
17875
  logDebug("[LocalMobbFolderService] Creating new patchInfo.md file");
16050
17876
  }
16051
17877
  const separator = existingContent ? "\n\n================================================================================\n\n" : "";
16052
17878
  const updatedContent = `${markdownContent}${separator}${existingContent}`;
16053
- await fs14.promises.writeFile(patchInfoPath, updatedContent, "utf8");
17879
+ await fs15.promises.writeFile(patchInfoPath, updatedContent, "utf8");
16054
17880
  logInfo("[LocalMobbFolderService] Patch info logged successfully", {
16055
17881
  patchInfoPath,
16056
17882
  fixId: fix.id,
@@ -16081,7 +17907,7 @@ var LocalMobbFolderService = class {
16081
17907
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
16082
17908
  const patch = this.extractPatchFromFix(fix);
16083
17909
  const relativePatchedFilePath = patch ? extractPathFromPatch(patch) : null;
16084
- const patchedFilePath = relativePatchedFilePath ? path13.resolve(this.repoPath, relativePatchedFilePath) : null;
17910
+ const patchedFilePath = relativePatchedFilePath ? path14.resolve(this.repoPath, relativePatchedFilePath) : null;
16085
17911
  const fixIdentifier = savedPatchFileName ? savedPatchFileName.replace(".patch", "") : fix.id;
16086
17912
  let markdown = `# Fix ${fixIdentifier}
16087
17913
 
@@ -16423,16 +18249,16 @@ import {
16423
18249
  unlinkSync,
16424
18250
  writeFileSync
16425
18251
  } from "fs";
16426
- import fs15 from "fs/promises";
18252
+ import fs16 from "fs/promises";
16427
18253
  import parseDiff2 from "parse-diff";
16428
- import path14 from "path";
18254
+ import path15 from "path";
16429
18255
  var PatchApplicationService = class {
16430
18256
  /**
16431
18257
  * Gets the appropriate comment syntax for a file based on its extension
16432
18258
  */
16433
18259
  static getCommentSyntax(filePath) {
16434
- const ext = path14.extname(filePath).toLowerCase();
16435
- const basename2 = path14.basename(filePath);
18260
+ const ext = path15.extname(filePath).toLowerCase();
18261
+ const basename2 = path15.basename(filePath);
16436
18262
  const commentMap = {
16437
18263
  // C-style languages (single line comments)
16438
18264
  ".js": "//",
@@ -16635,7 +18461,7 @@ var PatchApplicationService = class {
16635
18461
  }
16636
18462
  );
16637
18463
  }
16638
- const dirPath = path14.dirname(filePath);
18464
+ const dirPath = path15.dirname(filePath);
16639
18465
  mkdirSync(dirPath, { recursive: true });
16640
18466
  writeFileSync(filePath, finalContent, "utf8");
16641
18467
  return filePath;
@@ -16919,9 +18745,9 @@ var PatchApplicationService = class {
16919
18745
  continue;
16920
18746
  }
16921
18747
  try {
16922
- const absolutePath = path14.resolve(repositoryPath, targetFile);
18748
+ const absolutePath = path15.resolve(repositoryPath, targetFile);
16923
18749
  if (existsSync2(absolutePath)) {
16924
- const stats = await fs15.stat(absolutePath);
18750
+ const stats = await fs16.stat(absolutePath);
16925
18751
  const fileModTime = stats.mtime.getTime();
16926
18752
  if (fileModTime > scanStartTime) {
16927
18753
  logError(
@@ -16962,7 +18788,7 @@ var PatchApplicationService = class {
16962
18788
  const appliedFixes = [];
16963
18789
  const failedFixes = [];
16964
18790
  const skippedFixes = [];
16965
- const resolvedRepoPath = await fs15.realpath(repositoryPath);
18791
+ const resolvedRepoPath = await fs16.realpath(repositoryPath);
16966
18792
  logInfo(
16967
18793
  `[${scanContext}] Starting patch application for ${fixes.length} fixes`,
16968
18794
  {
@@ -17110,11 +18936,11 @@ var PatchApplicationService = class {
17110
18936
  }) {
17111
18937
  const sanitizedRepoPath = String(repositoryPath || "").replace("\0", "").replace(/^(\.\.(\/|\\))+/, "");
17112
18938
  const sanitizedTargetFile = String(targetFile || "").replace("\0", "").replace(/^(\.\.(\/|\\))+/, "");
17113
- const absoluteFilePath = path14.resolve(
18939
+ const absoluteFilePath = path15.resolve(
17114
18940
  sanitizedRepoPath,
17115
18941
  sanitizedTargetFile
17116
18942
  );
17117
- const relativePath = path14.relative(sanitizedRepoPath, absoluteFilePath);
18943
+ const relativePath = path15.relative(sanitizedRepoPath, absoluteFilePath);
17118
18944
  if (relativePath.startsWith("..")) {
17119
18945
  throw new Error(
17120
18946
  `Security violation: target file ${targetFile} resolves outside repository`
@@ -17148,7 +18974,7 @@ var PatchApplicationService = class {
17148
18974
  fix,
17149
18975
  scanContext
17150
18976
  });
17151
- appliedFiles.push(path14.relative(repositoryPath, actualPath));
18977
+ appliedFiles.push(path15.relative(repositoryPath, actualPath));
17152
18978
  logDebug(`[${scanContext}] Created new file: ${relativePath}`);
17153
18979
  }
17154
18980
  /**
@@ -17196,7 +19022,7 @@ var PatchApplicationService = class {
17196
19022
  fix,
17197
19023
  scanContext
17198
19024
  });
17199
- appliedFiles.push(path14.relative(repositoryPath, actualPath));
19025
+ appliedFiles.push(path15.relative(repositoryPath, actualPath));
17200
19026
  logDebug(`[${scanContext}] Modified file: ${relativePath}`);
17201
19027
  }
17202
19028
  }
@@ -17391,8 +19217,8 @@ init_configs();
17391
19217
 
17392
19218
  // src/mcp/services/FileOperations.ts
17393
19219
  init_FileUtils();
17394
- import fs16 from "fs";
17395
- import path15 from "path";
19220
+ import fs17 from "fs";
19221
+ import path16 from "path";
17396
19222
  import AdmZip2 from "adm-zip";
17397
19223
  var FileOperations = class {
17398
19224
  /**
@@ -17412,10 +19238,10 @@ var FileOperations = class {
17412
19238
  let packedFilesCount = 0;
17413
19239
  const packedFiles = [];
17414
19240
  const excludedFiles = [];
17415
- const resolvedRepoPath = path15.resolve(repositoryPath);
19241
+ const resolvedRepoPath = path16.resolve(repositoryPath);
17416
19242
  for (const filepath of fileList) {
17417
- const absoluteFilepath = path15.join(repositoryPath, filepath);
17418
- const resolvedFilePath = path15.resolve(absoluteFilepath);
19243
+ const absoluteFilepath = path16.join(repositoryPath, filepath);
19244
+ const resolvedFilePath = path16.resolve(absoluteFilepath);
17419
19245
  if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
17420
19246
  const reason = "potential path traversal security risk";
17421
19247
  logDebug(`[FileOperations] Skipping ${filepath} due to ${reason}`);
@@ -17462,11 +19288,11 @@ var FileOperations = class {
17462
19288
  fileList,
17463
19289
  repositoryPath
17464
19290
  }) {
17465
- const resolvedRepoPath = path15.resolve(repositoryPath);
19291
+ const resolvedRepoPath = path16.resolve(repositoryPath);
17466
19292
  const validatedPaths = [];
17467
19293
  for (const filepath of fileList) {
17468
- const absoluteFilepath = path15.join(repositoryPath, filepath);
17469
- const resolvedFilePath = path15.resolve(absoluteFilepath);
19294
+ const absoluteFilepath = path16.join(repositoryPath, filepath);
19295
+ const resolvedFilePath = path16.resolve(absoluteFilepath);
17470
19296
  if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
17471
19297
  logDebug(
17472
19298
  `[FileOperations] Rejecting ${filepath} - path traversal attempt detected`
@@ -17474,7 +19300,7 @@ var FileOperations = class {
17474
19300
  continue;
17475
19301
  }
17476
19302
  try {
17477
- await fs16.promises.access(absoluteFilepath, fs16.constants.R_OK);
19303
+ await fs17.promises.access(absoluteFilepath, fs17.constants.R_OK);
17478
19304
  validatedPaths.push(filepath);
17479
19305
  } catch (error) {
17480
19306
  logDebug(
@@ -17493,8 +19319,8 @@ var FileOperations = class {
17493
19319
  const fileDataArray = [];
17494
19320
  for (const absolutePath of filePaths) {
17495
19321
  try {
17496
- const content = await fs16.promises.readFile(absolutePath);
17497
- const relativePath = path15.basename(absolutePath);
19322
+ const content = await fs17.promises.readFile(absolutePath);
19323
+ const relativePath = path16.basename(absolutePath);
17498
19324
  fileDataArray.push({
17499
19325
  relativePath,
17500
19326
  absolutePath,
@@ -17519,7 +19345,7 @@ var FileOperations = class {
17519
19345
  relativeFilepath
17520
19346
  }) {
17521
19347
  try {
17522
- return await fs16.promises.readFile(absoluteFilepath);
19348
+ return await fs17.promises.readFile(absoluteFilepath);
17523
19349
  } catch (fsError) {
17524
19350
  logError(
17525
19351
  `[FileOperations] Failed to read ${relativeFilepath} from filesystem: ${fsError}`
@@ -17806,14 +19632,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17806
19632
  * since the last scan.
17807
19633
  */
17808
19634
  async scanForSecurityVulnerabilities({
17809
- path: path17,
19635
+ path: path18,
17810
19636
  isAllDetectionRulesScan,
17811
19637
  isAllFilesScan,
17812
19638
  scanContext
17813
19639
  }) {
17814
19640
  this.hasAuthenticationFailed = false;
17815
19641
  logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
17816
- path: path17
19642
+ path: path18
17817
19643
  });
17818
19644
  if (!this.gqlClient) {
17819
19645
  logInfo(`[${scanContext}] No GQL client found, skipping scan`);
@@ -17829,11 +19655,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17829
19655
  }
17830
19656
  logDebug(
17831
19657
  `[${scanContext}] Connected to the API, assembling list of files to scan`,
17832
- { path: path17 }
19658
+ { path: path18 }
17833
19659
  );
17834
19660
  const isBackgroundScan = scanContext === ScanContext.BACKGROUND_INITIAL || scanContext === ScanContext.BACKGROUND_PERIODIC;
17835
19661
  const files = await getLocalFiles({
17836
- path: path17,
19662
+ path: path18,
17837
19663
  isAllFilesScan,
17838
19664
  scanContext,
17839
19665
  scanRecentlyChangedFiles: !isBackgroundScan
@@ -17859,13 +19685,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17859
19685
  });
17860
19686
  const { fixReportId, projectId } = await scanFiles({
17861
19687
  fileList: filesToScan.map((file) => file.relativePath),
17862
- repositoryPath: path17,
19688
+ repositoryPath: path18,
17863
19689
  gqlClient: this.gqlClient,
17864
19690
  isAllDetectionRulesScan,
17865
19691
  scanContext
17866
19692
  });
17867
19693
  logInfo(
17868
- `[${scanContext}] Security scan completed for ${path17} reportId: ${fixReportId} projectId: ${projectId}`
19694
+ `[${scanContext}] Security scan completed for ${path18} reportId: ${fixReportId} projectId: ${projectId}`
17869
19695
  );
17870
19696
  if (isAllFilesScan) {
17871
19697
  return;
@@ -18159,13 +19985,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
18159
19985
  });
18160
19986
  return scannedFiles.some((file) => file.relativePath === fixFile);
18161
19987
  }
18162
- async getFreshFixes({ path: path17 }) {
19988
+ async getFreshFixes({ path: path18 }) {
18163
19989
  const scanContext = ScanContext.USER_REQUEST;
18164
- logDebug(`[${scanContext}] Getting fresh fixes`, { path: path17 });
18165
- if (this.path !== path17) {
18166
- this.path = path17;
19990
+ logDebug(`[${scanContext}] Getting fresh fixes`, { path: path18 });
19991
+ if (this.path !== path18) {
19992
+ this.path = path18;
18167
19993
  this.reset();
18168
- logInfo(`[${scanContext}] Reset service state for new path`, { path: path17 });
19994
+ logInfo(`[${scanContext}] Reset service state for new path`, { path: path18 });
18169
19995
  }
18170
19996
  try {
18171
19997
  this.gqlClient = await createAuthenticatedMcpGQLClient();
@@ -18183,7 +20009,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
18183
20009
  }
18184
20010
  throw error;
18185
20011
  }
18186
- this.triggerScan({ path: path17, gqlClient: this.gqlClient });
20012
+ this.triggerScan({ path: path18, gqlClient: this.gqlClient });
18187
20013
  let isMvsAutoFixEnabled = null;
18188
20014
  try {
18189
20015
  isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
@@ -18217,33 +20043,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
18217
20043
  return noFreshFixesPrompt;
18218
20044
  }
18219
20045
  triggerScan({
18220
- path: path17,
20046
+ path: path18,
18221
20047
  gqlClient
18222
20048
  }) {
18223
- if (this.path !== path17) {
18224
- this.path = path17;
20049
+ if (this.path !== path18) {
20050
+ this.path = path18;
18225
20051
  this.reset();
18226
- logInfo(`Reset service state for new path in triggerScan`, { path: path17 });
20052
+ logInfo(`Reset service state for new path in triggerScan`, { path: path18 });
18227
20053
  }
18228
20054
  this.gqlClient = gqlClient;
18229
20055
  if (!this.intervalId) {
18230
- this.startPeriodicScanning(path17);
18231
- this.executeInitialScan(path17);
18232
- void this.executeInitialFullScan(path17);
20056
+ this.startPeriodicScanning(path18);
20057
+ this.executeInitialScan(path18);
20058
+ void this.executeInitialFullScan(path18);
18233
20059
  }
18234
20060
  }
18235
- startPeriodicScanning(path17) {
20061
+ startPeriodicScanning(path18) {
18236
20062
  const scanContext = ScanContext.BACKGROUND_PERIODIC;
18237
20063
  logDebug(
18238
20064
  `[${scanContext}] Starting periodic scan for new security vulnerabilities`,
18239
20065
  {
18240
- path: path17
20066
+ path: path18
18241
20067
  }
18242
20068
  );
18243
20069
  this.intervalId = setInterval(() => {
18244
- logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path17 });
20070
+ logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path18 });
18245
20071
  this.scanForSecurityVulnerabilities({
18246
- path: path17,
20072
+ path: path18,
18247
20073
  scanContext
18248
20074
  }).catch((error) => {
18249
20075
  logError(`[${scanContext}] Error during periodic security scan`, {
@@ -18252,45 +20078,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
18252
20078
  });
18253
20079
  }, MCP_PERIODIC_CHECK_INTERVAL);
18254
20080
  }
18255
- async executeInitialFullScan(path17) {
20081
+ async executeInitialFullScan(path18) {
18256
20082
  const scanContext = ScanContext.FULL_SCAN;
18257
- logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path17 });
20083
+ logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path18 });
18258
20084
  logDebug(`[${scanContext}] Full scan paths scanned`, {
18259
20085
  fullScanPathsScanned: this.fullScanPathsScanned
18260
20086
  });
18261
- if (this.fullScanPathsScanned.includes(path17)) {
20087
+ if (this.fullScanPathsScanned.includes(path18)) {
18262
20088
  logDebug(`[${scanContext}] Full scan already executed for this path`, {
18263
- path: path17
20089
+ path: path18
18264
20090
  });
18265
20091
  return;
18266
20092
  }
18267
20093
  configStore.set("fullScanPathsScanned", [
18268
20094
  ...this.fullScanPathsScanned,
18269
- path17
20095
+ path18
18270
20096
  ]);
18271
20097
  try {
18272
20098
  await this.scanForSecurityVulnerabilities({
18273
- path: path17,
20099
+ path: path18,
18274
20100
  isAllFilesScan: true,
18275
20101
  isAllDetectionRulesScan: true,
18276
20102
  scanContext: ScanContext.FULL_SCAN
18277
20103
  });
18278
- if (!this.fullScanPathsScanned.includes(path17)) {
18279
- this.fullScanPathsScanned.push(path17);
20104
+ if (!this.fullScanPathsScanned.includes(path18)) {
20105
+ this.fullScanPathsScanned.push(path18);
18280
20106
  configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
18281
20107
  }
18282
- logInfo(`[${scanContext}] Full scan completed`, { path: path17 });
20108
+ logInfo(`[${scanContext}] Full scan completed`, { path: path18 });
18283
20109
  } catch (error) {
18284
20110
  logError(`[${scanContext}] Error during initial full security scan`, {
18285
20111
  error
18286
20112
  });
18287
20113
  }
18288
20114
  }
18289
- executeInitialScan(path17) {
20115
+ executeInitialScan(path18) {
18290
20116
  const scanContext = ScanContext.BACKGROUND_INITIAL;
18291
- logDebug(`[${scanContext}] Triggering initial security scan`, { path: path17 });
20117
+ logDebug(`[${scanContext}] Triggering initial security scan`, { path: path18 });
18292
20118
  this.scanForSecurityVulnerabilities({
18293
- path: path17,
20119
+ path: path18,
18294
20120
  scanContext: ScanContext.BACKGROUND_INITIAL
18295
20121
  }).catch((error) => {
18296
20122
  logError(`[${scanContext}] Error during initial security scan`, { error });
@@ -18369,8 +20195,8 @@ Example payload:
18369
20195
  },
18370
20196
  required: ["path"]
18371
20197
  });
18372
- __publicField(this, "inputValidationSchema", z34.object({
18373
- path: z34.string().describe(
20198
+ __publicField(this, "inputValidationSchema", z40.object({
20199
+ path: z40.string().describe(
18374
20200
  "Full local path to the cloned git repository to check for new available fixes"
18375
20201
  )
18376
20202
  }));
@@ -18387,9 +20213,9 @@ Example payload:
18387
20213
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
18388
20214
  );
18389
20215
  }
18390
- const path17 = pathValidationResult.path;
20216
+ const path18 = pathValidationResult.path;
18391
20217
  const resultText = await this.newFixesService.getFreshFixes({
18392
- path: path17
20218
+ path: path18
18393
20219
  });
18394
20220
  logInfo("CheckForNewAvailableFixesTool execution completed", {
18395
20221
  resultText
@@ -18400,7 +20226,7 @@ Example payload:
18400
20226
 
18401
20227
  // src/mcp/tools/fetchAvailableFixes/FetchAvailableFixesTool.ts
18402
20228
  init_GitService();
18403
- import { z as z35 } from "zod";
20229
+ import { z as z41 } from "zod";
18404
20230
 
18405
20231
  // src/mcp/tools/fetchAvailableFixes/FetchAvailableFixesService.ts
18406
20232
  init_configs();
@@ -18542,16 +20368,16 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
18542
20368
  },
18543
20369
  required: ["path"]
18544
20370
  });
18545
- __publicField(this, "inputValidationSchema", z35.object({
18546
- path: z35.string().describe(
20371
+ __publicField(this, "inputValidationSchema", z41.object({
20372
+ path: z41.string().describe(
18547
20373
  "Full local path to the cloned git repository to check for available fixes"
18548
20374
  ),
18549
- offset: z35.number().optional().describe("Optional offset for pagination"),
18550
- limit: z35.number().optional().describe("Optional maximum number of fixes to return"),
18551
- fileFilter: z35.array(z35.string()).optional().describe(
20375
+ offset: z41.number().optional().describe("Optional offset for pagination"),
20376
+ limit: z41.number().optional().describe("Optional maximum number of fixes to return"),
20377
+ fileFilter: z41.array(z41.string()).optional().describe(
18552
20378
  "Optional list of file paths relative to the path parameter to filter fixes by. INCOMPATIBLE with fetchFixesFromAnyFile"
18553
20379
  ),
18554
- fetchFixesFromAnyFile: z35.boolean().optional().describe(
20380
+ fetchFixesFromAnyFile: z41.boolean().optional().describe(
18555
20381
  "Optional boolean to fetch fixes for all files. INCOMPATIBLE with fileFilter"
18556
20382
  )
18557
20383
  }));
@@ -18566,8 +20392,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
18566
20392
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
18567
20393
  );
18568
20394
  }
18569
- const path17 = pathValidationResult.path;
18570
- const gitService = new GitService(path17, log);
20395
+ const path18 = pathValidationResult.path;
20396
+ const gitService = new GitService(path18, log);
18571
20397
  const gitValidation = await gitService.validateRepository();
18572
20398
  if (!gitValidation.isValid) {
18573
20399
  throw new Error(`Invalid git repository: ${gitValidation.error}`);
@@ -18620,7 +20446,7 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
18620
20446
  };
18621
20447
 
18622
20448
  // src/mcp/tools/mcpChecker/mcpCheckerTool.ts
18623
- import z36 from "zod";
20449
+ import z42 from "zod";
18624
20450
 
18625
20451
  // src/mcp/tools/mcpChecker/mcpCheckerService.ts
18626
20452
  var _McpCheckerService = class _McpCheckerService {
@@ -18681,7 +20507,7 @@ var McpCheckerTool = class extends BaseTool {
18681
20507
  __publicField(this, "displayName", "MCP Checker");
18682
20508
  // A detailed description to guide the LLM on when and how to invoke this tool.
18683
20509
  __publicField(this, "description", "Check the MCP servers running on this IDE against organization policies.");
18684
- __publicField(this, "inputValidationSchema", z36.object({}));
20510
+ __publicField(this, "inputValidationSchema", z42.object({}));
18685
20511
  __publicField(this, "inputSchema", {
18686
20512
  type: "object",
18687
20513
  properties: {},
@@ -18707,7 +20533,7 @@ var McpCheckerTool = class extends BaseTool {
18707
20533
  };
18708
20534
 
18709
20535
  // src/mcp/tools/scanAndFixVulnerabilities/ScanAndFixVulnerabilitiesTool.ts
18710
- import z37 from "zod";
20536
+ import z43 from "zod";
18711
20537
  init_configs();
18712
20538
 
18713
20539
  // src/mcp/tools/scanAndFixVulnerabilities/ScanAndFixVulnerabilitiesService.ts
@@ -18894,17 +20720,17 @@ Example payload:
18894
20720
  "rescan": false
18895
20721
  }`);
18896
20722
  __publicField(this, "hasAuthentication", true);
18897
- __publicField(this, "inputValidationSchema", z37.object({
18898
- path: z37.string().describe(
20723
+ __publicField(this, "inputValidationSchema", z43.object({
20724
+ path: z43.string().describe(
18899
20725
  "Full local path to repository to scan and fix vulnerabilities"
18900
20726
  ),
18901
- offset: z37.number().optional().describe("Optional offset for pagination"),
18902
- limit: z37.number().optional().describe("Optional maximum number of results to return"),
18903
- maxFiles: z37.number().optional().describe(
20727
+ offset: z43.number().optional().describe("Optional offset for pagination"),
20728
+ limit: z43.number().optional().describe("Optional maximum number of results to return"),
20729
+ maxFiles: z43.number().optional().describe(
18904
20730
  `Optional maximum number of files to scan (default: ${MCP_DEFAULT_MAX_FILES_TO_SCAN}). Increase for comprehensive scans of larger codebases or decrease for faster focused scans.`
18905
20731
  ),
18906
- rescan: z37.boolean().optional().describe("Optional whether to rescan the repository"),
18907
- scanRecentlyChangedFiles: z37.boolean().optional().describe(
20732
+ rescan: z43.boolean().optional().describe("Optional whether to rescan the repository"),
20733
+ scanRecentlyChangedFiles: z43.boolean().optional().describe(
18908
20734
  "Optional whether to automatically scan recently changed files when no changed files are found in git status. If false, the tool will prompt the user instead."
18909
20735
  )
18910
20736
  }));
@@ -18955,9 +20781,9 @@ Example payload:
18955
20781
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
18956
20782
  );
18957
20783
  }
18958
- const path17 = pathValidationResult.path;
20784
+ const path18 = pathValidationResult.path;
18959
20785
  const files = await getLocalFiles({
18960
- path: path17,
20786
+ path: path18,
18961
20787
  maxFileSize: MCP_MAX_FILE_SIZE,
18962
20788
  maxFiles: args.maxFiles,
18963
20789
  scanContext: ScanContext.USER_REQUEST,
@@ -18977,7 +20803,7 @@ Example payload:
18977
20803
  try {
18978
20804
  const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
18979
20805
  fileList: files.map((file) => file.relativePath),
18980
- repositoryPath: path17,
20806
+ repositoryPath: path18,
18981
20807
  offset: args.offset,
18982
20808
  limit: args.limit,
18983
20809
  isRescan: args.rescan || !!args.maxFiles
@@ -19032,6 +20858,19 @@ function createMcpServer(govOrgId) {
19032
20858
  const mcpCheckerTool = new McpCheckerTool(govOrgId);
19033
20859
  registerIfEnabled(mcpCheckerTool);
19034
20860
  }
20861
+ logDebug("Registering MCP prompts");
20862
+ const prompts = [
20863
+ new SecurityToolsOverviewPrompt(),
20864
+ new ScanRepositoryPrompt(),
20865
+ new ScanRecentChangesPrompt(),
20866
+ new CheckForNewVulnerabilitiesPrompt(),
20867
+ new ReviewAndFixCriticalPrompt(),
20868
+ new FullSecurityAuditPrompt()
20869
+ ];
20870
+ prompts.forEach((prompt) => {
20871
+ server.registerPrompt(prompt);
20872
+ logDebug(`Registered prompt: ${prompt.name}`);
20873
+ });
19035
20874
  logInfo("MCP server created and configured");
19036
20875
  return server;
19037
20876
  }
@@ -19068,7 +20907,7 @@ var mcpHandler = async (_args) => {
19068
20907
  };
19069
20908
 
19070
20909
  // src/args/commands/review.ts
19071
- import fs17 from "fs";
20910
+ import fs18 from "fs";
19072
20911
  import chalk9 from "chalk";
19073
20912
  function reviewBuilder(yargs2) {
19074
20913
  return yargs2.option("f", {
@@ -19105,7 +20944,7 @@ function reviewBuilder(yargs2) {
19105
20944
  ).help();
19106
20945
  }
19107
20946
  function validateReviewOptions(argv) {
19108
- if (!fs17.existsSync(argv.f)) {
20947
+ if (!fs18.existsSync(argv.f)) {
19109
20948
  throw new CliError(`
19110
20949
  Can't access ${chalk9.bold(argv.f)}`);
19111
20950
  }
@@ -19179,34 +21018,34 @@ async function addScmTokenHandler(args) {
19179
21018
 
19180
21019
  // src/args/commands/upload_ai_blame.ts
19181
21020
  import fsPromises3 from "fs/promises";
19182
- import path16 from "path";
21021
+ import path17 from "path";
19183
21022
  import chalk10 from "chalk";
19184
21023
  import Configstore6 from "configstore";
19185
21024
  import { withFile } from "tmp-promise";
19186
- import z38 from "zod";
19187
- var PromptItemZ = z38.object({
19188
- type: z38.enum(["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING"]),
19189
- attachedFiles: z38.array(
19190
- z38.object({
19191
- relativePath: z38.string(),
19192
- startLine: z38.number().optional()
21025
+ import z44 from "zod";
21026
+ var PromptItemZ = z44.object({
21027
+ type: z44.enum(["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING"]),
21028
+ attachedFiles: z44.array(
21029
+ z44.object({
21030
+ relativePath: z44.string(),
21031
+ startLine: z44.number().optional()
19193
21032
  })
19194
21033
  ).optional(),
19195
- tokens: z38.object({
19196
- inputCount: z38.number(),
19197
- outputCount: z38.number()
21034
+ tokens: z44.object({
21035
+ inputCount: z44.number(),
21036
+ outputCount: z44.number()
19198
21037
  }).optional(),
19199
- text: z38.string().optional(),
19200
- date: z38.date().optional(),
19201
- tool: z38.object({
19202
- name: z38.string(),
19203
- parameters: z38.string(),
19204
- result: z38.string(),
19205
- rawArguments: z38.string().optional(),
19206
- accepted: z38.boolean().optional()
21038
+ text: z44.string().optional(),
21039
+ date: z44.date().optional(),
21040
+ tool: z44.object({
21041
+ name: z44.string(),
21042
+ parameters: z44.string(),
21043
+ result: z44.string(),
21044
+ rawArguments: z44.string().optional(),
21045
+ accepted: z44.boolean().optional()
19207
21046
  }).optional()
19208
21047
  });
19209
- var PromptItemArrayZ = z38.array(PromptItemZ);
21048
+ var PromptItemArrayZ = z44.array(PromptItemZ);
19210
21049
  function uploadAiBlameBuilder(args) {
19211
21050
  return args.option("prompt", {
19212
21051
  type: "string",
@@ -19281,8 +21120,8 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
19281
21120
  throw new Error(errorMsg);
19282
21121
  }
19283
21122
  sessions.push({
19284
- promptFileName: path16.basename(promptPath),
19285
- inferenceFileName: path16.basename(inferencePath),
21123
+ promptFileName: path17.basename(promptPath),
21124
+ inferenceFileName: path17.basename(inferencePath),
19286
21125
  aiResponseAt: responseTimes[i] || nowIso,
19287
21126
  model: models[i],
19288
21127
  toolName: tools[i]