@agent-lint/mcp 0.3.0 → 0.3.4

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.
@@ -17304,19 +17304,6 @@ var artifactTypeValues = [
17304
17304
  "plans"
17305
17305
  ];
17306
17306
  var artifactTypeSchema = external_exports.enum(artifactTypeValues);
17307
- var contextDocumentSchema = external_exports.object({
17308
- label: external_exports.string().min(1).max(120),
17309
- content: external_exports.string().min(1).max(2e5),
17310
- path: external_exports.string().min(1).max(512).optional(),
17311
- type: artifactTypeSchema.optional(),
17312
- priority: external_exports.number().int().min(0).max(10).optional()
17313
- });
17314
- var artifactSubmissionSchema = external_exports.object({
17315
- type: artifactTypeSchema,
17316
- content: external_exports.string().min(1).max(1e6),
17317
- contextDocuments: external_exports.array(contextDocumentSchema).max(20).optional(),
17318
- userId: external_exports.string().min(1).max(128).optional()
17319
- });
17320
17307
  var qualityMetricIds = [
17321
17308
  "clarity",
17322
17309
  "specificity",
@@ -17356,71 +17343,112 @@ var AGENT_HINTS = [
17356
17343
  ecosystem: "Root docs",
17357
17344
  patterns: ["AGENTS.md", "CLAUDE.md"],
17358
17345
  examples: ["AGENTS.md", "CLAUDE.md"],
17346
+ discoveryTier: "canonical",
17359
17347
  notes: "Prefer root-level files when available."
17360
17348
  },
17361
17349
  {
17362
17350
  ecosystem: "Nested policy docs",
17363
- patterns: ["**/.agents/**/*.md", "docs/**/agents*.md"],
17364
- examples: [".agents/AGENTS.md", "docs/agent_guide.md"]
17351
+ patterns: [
17352
+ ".agents/AGENTS.md",
17353
+ ".agents/**/AGENTS.md",
17354
+ ".agents/CLAUDE.md",
17355
+ ".agents/**/CLAUDE.md"
17356
+ ],
17357
+ examples: [".agents/AGENTS.md", ".agents/team/CLAUDE.md"],
17358
+ discoveryTier: "canonical"
17359
+ },
17360
+ {
17361
+ ecosystem: "Fallback docs",
17362
+ patterns: ["docs/**/agents*.md"],
17363
+ examples: ["docs/agent_guide.md"],
17364
+ discoveryTier: "fallback"
17365
17365
  }
17366
17366
  ];
17367
17367
  var SKILL_HINTS = [
17368
17368
  {
17369
17369
  ecosystem: "Windsurf",
17370
- patterns: [".windsurf/skills/**/SKILL.md", ".windsurf/skills/**/*.md"],
17371
- examples: [".windsurf/skills/frontend/SKILL.md"]
17370
+ patterns: [".windsurf/skills/**/SKILL.md"],
17371
+ examples: [".windsurf/skills/frontend/SKILL.md"],
17372
+ discoveryTier: "canonical"
17372
17373
  },
17373
17374
  {
17374
17375
  ecosystem: "Claude/Cline style",
17375
17376
  patterns: [".claude/skills/**/SKILL.md", ".skills/**/SKILL.md", "skills/**/SKILL.md"],
17376
- examples: ["skills/release/SKILL.md", ".claude/skills/testing/SKILL.md"]
17377
+ examples: ["skills/release/SKILL.md", ".claude/skills/testing/SKILL.md"],
17378
+ discoveryTier: "canonical"
17377
17379
  },
17378
17380
  {
17379
17381
  ecosystem: "Agent Skills standard",
17380
17382
  patterns: [".agents/skills/**/SKILL.md", ".github/skills/**/SKILL.md"],
17381
- examples: [".agents/skills/release/SKILL.md", ".github/skills/security-review/SKILL.md"]
17383
+ examples: [".agents/skills/release/SKILL.md", ".github/skills/security-review/SKILL.md"],
17384
+ discoveryTier: "canonical"
17382
17385
  },
17383
17386
  {
17384
17387
  ecosystem: "Generic",
17385
17388
  patterns: ["**/*skill*.md", "**/SKILL.md"],
17386
17389
  examples: ["docs/skills/code-review-skill.md"],
17390
+ discoveryTier: "fallback",
17387
17391
  notes: "Use content heuristics when naming is inconsistent."
17388
17392
  }
17389
17393
  ];
17390
17394
  var RULE_HINTS = [
17391
17395
  {
17392
17396
  ecosystem: "Root/docs",
17393
- patterns: ["rules.md", "docs/rules.md", "docs/**/*rule*.md"],
17394
- examples: ["docs/rules.md", "rules.md"]
17397
+ patterns: ["rules.md", "docs/rules.md"],
17398
+ examples: ["docs/rules.md", "rules.md"],
17399
+ discoveryTier: "canonical"
17395
17400
  },
17396
17401
  {
17397
17402
  ecosystem: "Editor-specific",
17398
17403
  patterns: [".cursor/rules/**/*.md", ".cursor/rules/**/*.mdc", ".windsurf/rules/**/*.md"],
17399
- examples: [".cursor/rules/typescript.mdc"]
17404
+ examples: [".cursor/rules/typescript.mdc"],
17405
+ discoveryTier: "canonical"
17406
+ },
17407
+ {
17408
+ ecosystem: "Fallback docs",
17409
+ patterns: ["docs/**/*rule*.md"],
17410
+ examples: ["docs/backend-rule-overrides.md"],
17411
+ discoveryTier: "fallback"
17400
17412
  }
17401
17413
  ];
17402
17414
  var WORKFLOW_HINTS = [
17403
17415
  {
17404
17416
  ecosystem: "Slash-command docs",
17405
- patterns: ["docs/workflows/**/*.md", "docs/commands/**/*.md", "**/*workflow*.md"],
17406
- examples: ["docs/workflows/release.md", "docs/commands/fix.md"]
17417
+ patterns: ["docs/workflows/**/*.md", "docs/commands/**/*.md"],
17418
+ examples: ["docs/workflows/release.md", "docs/commands/fix.md"],
17419
+ discoveryTier: "canonical"
17407
17420
  },
17408
17421
  {
17409
17422
  ecosystem: "Client command folders",
17410
17423
  patterns: [".claude/commands/**/*.md", ".windsurf/workflows/**/*.md"],
17411
- examples: [".claude/commands/review.md"]
17424
+ examples: [".claude/commands/review.md"],
17425
+ discoveryTier: "canonical"
17426
+ },
17427
+ {
17428
+ ecosystem: "Fallback docs",
17429
+ patterns: ["**/*workflow*.md"],
17430
+ examples: ["docs/deploy-workflow.md"],
17431
+ discoveryTier: "fallback"
17412
17432
  }
17413
17433
  ];
17414
17434
  var PLAN_HINTS = [
17415
17435
  {
17416
17436
  ecosystem: "Roadmap/plan docs",
17417
- patterns: ["docs/**/*plan*.md", "docs/**/*roadmap*.md", "docs/**/*backlog*.md"],
17418
- examples: ["docs/phased_implementation_plan.md", "docs/roadmap_master.md"]
17437
+ patterns: ["docs/plans/**/*.md", "docs/backlog/**/*.md"],
17438
+ examples: ["docs/plans/auth-and-billing-rollout.md", "docs/backlog/q2.md"],
17439
+ discoveryTier: "canonical"
17419
17440
  },
17420
17441
  {
17421
17442
  ecosystem: "Top-level planning",
17422
17443
  patterns: ["PLAN.md", "great_plan.md", "PRD.md"],
17423
- examples: ["docs/great_plan.md", "docs/PRD.md"]
17444
+ examples: ["PLAN.md", "PRD.md"],
17445
+ discoveryTier: "canonical"
17446
+ },
17447
+ {
17448
+ ecosystem: "Fallback docs",
17449
+ patterns: ["docs/**/*plan*.md", "docs/**/*roadmap*.md", "docs/**/*backlog*.md"],
17450
+ examples: ["docs/phased_implementation_plan.md", "docs/roadmap_master.md"],
17451
+ discoveryTier: "fallback"
17424
17452
  }
17425
17453
  ];
17426
17454
  function getArtifactPathHints(type) {
@@ -17438,6 +17466,9 @@ function getArtifactPathHints(type) {
17438
17466
  }
17439
17467
  return PLAN_HINTS;
17440
17468
  }
17469
+ function getArtifactDiscoveryPatterns(type, tier = "canonical") {
17470
+ return getArtifactPathHints(type).filter((hint) => hint.discoveryTier === tier).flatMap((hint) => hint.patterns);
17471
+ }
17441
17472
  function buildArtifactPathHintsMarkdown(type) {
17442
17473
  const hints = getArtifactPathHints(type);
17443
17474
  const lines = [
@@ -17450,6 +17481,8 @@ function buildArtifactPathHintsMarkdown(type) {
17450
17481
  for (const hint of hints) {
17451
17482
  lines.push(`## ${hint.ecosystem}`);
17452
17483
  lines.push("");
17484
+ lines.push(`Discovery tier: ${hint.discoveryTier}`);
17485
+ lines.push("");
17453
17486
  lines.push("Patterns:");
17454
17487
  for (const pattern of hint.patterns) {
17455
17488
  lines.push(`- ${pattern}`);
@@ -18197,11 +18230,17 @@ function buildTemplateMarkdown(type) {
18197
18230
  "```"
18198
18231
  ].join("\n");
18199
18232
  }
18233
+ function normalizePath(filePath) {
18234
+ return filePath.replace(/\\/g, "/");
18235
+ }
18200
18236
  var SKIP_DIRS = /* @__PURE__ */ new Set([
18201
18237
  "node_modules",
18202
18238
  ".git",
18203
18239
  ".next",
18204
18240
  ".nuxt",
18241
+ ".turbo",
18242
+ ".idea",
18243
+ ".vscode",
18205
18244
  "dist",
18206
18245
  "build",
18207
18246
  "out",
@@ -18212,51 +18251,18 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([
18212
18251
  "vendor",
18213
18252
  "target"
18214
18253
  ]);
18254
+ var ALLOWED_HIDDEN_DIRS = /* @__PURE__ */ new Set([
18255
+ ".agents",
18256
+ ".claude",
18257
+ ".cursor",
18258
+ ".github",
18259
+ ".skills",
18260
+ ".windsurf"
18261
+ ]);
18215
18262
  var ARTIFACT_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".mdc", ".yaml", ".yml", ".txt"]);
18216
18263
  var MAX_FILES = 200;
18217
18264
  var MAX_DEPTH = 6;
18218
18265
  var MAX_FILE_SIZE = 5e5;
18219
- function shouldSkipDir(name) {
18220
- return SKIP_DIRS.has(name) || name.startsWith(".");
18221
- }
18222
- function isArtifactExtension(filePath) {
18223
- return ARTIFACT_EXTENSIONS.has(path.extname(filePath).toLowerCase());
18224
- }
18225
- function inferArtifactType(filePath, content) {
18226
- const normalized = filePath.replace(/\\/g, "/").toLowerCase();
18227
- const lowerContent = content.substring(0, 2e3).toLowerCase();
18228
- if (/agents\.md$/i.test(normalized) || /claude\.md$/i.test(normalized)) {
18229
- return "agents";
18230
- }
18231
- if (normalized.includes("skill")) {
18232
- return "skills";
18233
- }
18234
- if (normalized.includes("rule")) {
18235
- return "rules";
18236
- }
18237
- if (normalized.includes("workflow") || normalized.includes("command")) {
18238
- return "workflows";
18239
- }
18240
- if (normalized.includes("plan") || normalized.includes("roadmap") || normalized.includes("backlog")) {
18241
- return "plans";
18242
- }
18243
- if (lowerContent.includes("agents.md") || lowerContent.includes("claude.md")) {
18244
- return "agents";
18245
- }
18246
- if (lowerContent.includes("disable-model-invocation") || lowerContent.includes("required frontmatter")) {
18247
- return "skills";
18248
- }
18249
- if (lowerContent.includes("activation mode") || lowerContent.includes("do block")) {
18250
- return "rules";
18251
- }
18252
- if (lowerContent.includes("ordered steps") || lowerContent.includes("preconditions")) {
18253
- return "workflows";
18254
- }
18255
- if (lowerContent.includes("acceptance criteria") || lowerContent.includes("## phases")) {
18256
- return "plans";
18257
- }
18258
- return null;
18259
- }
18260
18266
  var REQUIRED_SECTIONS = {
18261
18267
  agents: [
18262
18268
  "quick commands",
@@ -18298,70 +18304,143 @@ var REQUIRED_SECTIONS = {
18298
18304
  "evidence"
18299
18305
  ]
18300
18306
  };
18307
+ var CANONICAL_MATCHERS = artifactTypeValues.flatMap(
18308
+ (type) => getArtifactDiscoveryPatterns(type, "canonical").map((pattern) => ({
18309
+ type,
18310
+ regex: globToRegExp(pattern)
18311
+ }))
18312
+ );
18313
+ function escapeRegExp(value) {
18314
+ return value.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
18315
+ }
18316
+ function globToRegExp(pattern) {
18317
+ const normalizedPattern = normalizePath(pattern);
18318
+ let source = "^";
18319
+ for (let i = 0; i < normalizedPattern.length; i++) {
18320
+ const char = normalizedPattern[i];
18321
+ if (char === "*") {
18322
+ const next = normalizedPattern[i + 1];
18323
+ const afterNext = normalizedPattern[i + 2];
18324
+ if (next === "*" && afterNext === "/") {
18325
+ source += "(?:.*/)?";
18326
+ i += 2;
18327
+ continue;
18328
+ }
18329
+ if (next === "*") {
18330
+ source += ".*";
18331
+ i += 1;
18332
+ continue;
18333
+ }
18334
+ source += "[^/]*";
18335
+ continue;
18336
+ }
18337
+ if (char === "?") {
18338
+ source += "[^/]";
18339
+ continue;
18340
+ }
18341
+ source += escapeRegExp(char);
18342
+ }
18343
+ source += "$";
18344
+ return new RegExp(source, "i");
18345
+ }
18346
+ function shouldSkipDir(name) {
18347
+ return SKIP_DIRS.has(name) || name.startsWith(".") && !ALLOWED_HIDDEN_DIRS.has(name);
18348
+ }
18349
+ function isArtifactExtension(filePath) {
18350
+ return ARTIFACT_EXTENSIONS.has(path.extname(filePath).toLowerCase());
18351
+ }
18352
+ function matchArtifactType(relativePath) {
18353
+ for (const matcher of CANONICAL_MATCHERS) {
18354
+ if (matcher.regex.test(relativePath)) {
18355
+ return matcher.type;
18356
+ }
18357
+ }
18358
+ return null;
18359
+ }
18301
18360
  function findMissingSections(content, type) {
18302
18361
  const lowerContent = content.toLowerCase();
18303
18362
  const required2 = REQUIRED_SECTIONS[type];
18304
18363
  return required2.filter((section) => !lowerContent.includes(section));
18305
18364
  }
18306
- function collectCandidateFiles(rootPath, currentDepth, results) {
18365
+ function collectCandidateFiles(rootPath, currentPath, currentDepth, results) {
18307
18366
  if (currentDepth > MAX_DEPTH || results.length >= MAX_FILES) {
18308
18367
  return;
18309
18368
  }
18310
18369
  let entries;
18311
18370
  try {
18312
- entries = fs.readdirSync(rootPath, { withFileTypes: true });
18371
+ entries = fs.readdirSync(currentPath, { withFileTypes: true });
18313
18372
  } catch {
18314
18373
  return;
18315
18374
  }
18375
+ entries.sort((a, b) => a.name.localeCompare(b.name));
18316
18376
  for (const entry of entries) {
18317
18377
  if (results.length >= MAX_FILES) {
18318
18378
  break;
18319
18379
  }
18320
- const fullPath = path.join(rootPath, entry.name);
18380
+ const fullPath = path.join(currentPath, entry.name);
18321
18381
  if (entry.isDirectory()) {
18322
- if (!shouldSkipDir(entry.name) || entry.name === ".cursor" || entry.name === ".windsurf" || entry.name === ".claude" || entry.name === ".agents") {
18323
- collectCandidateFiles(fullPath, currentDepth + 1, results);
18382
+ if (!shouldSkipDir(entry.name)) {
18383
+ collectCandidateFiles(rootPath, fullPath, currentDepth + 1, results);
18324
18384
  }
18325
- } else if (entry.isFile() && isArtifactExtension(entry.name)) {
18326
- results.push(fullPath);
18385
+ continue;
18386
+ }
18387
+ if (!entry.isFile() || !isArtifactExtension(entry.name)) {
18388
+ continue;
18327
18389
  }
18390
+ const relativePath = normalizePath(path.relative(rootPath, fullPath));
18391
+ const type = matchArtifactType(relativePath);
18392
+ if (!type) {
18393
+ continue;
18394
+ }
18395
+ results.push({
18396
+ filePath: fullPath,
18397
+ relativePath,
18398
+ type
18399
+ });
18328
18400
  }
18329
18401
  }
18330
18402
  function findSuggestedPath(type, rootPath) {
18331
- const hints = getArtifactPathHints(type);
18332
- if (hints.length > 0 && hints[0].examples.length > 0) {
18333
- return path.join(rootPath, hints[0].examples[0]);
18403
+ const canonicalHints = getArtifactPathHints(type).filter(
18404
+ (hint) => hint.discoveryTier === "canonical"
18405
+ );
18406
+ for (const hint of canonicalHints) {
18407
+ if (hint.examples.length > 0) {
18408
+ return path.join(rootPath, hint.examples[0]);
18409
+ }
18410
+ }
18411
+ const allHints = getArtifactPathHints(type);
18412
+ for (const hint of allHints) {
18413
+ if (hint.examples.length > 0) {
18414
+ return path.join(rootPath, hint.examples[0]);
18415
+ }
18334
18416
  }
18335
18417
  return path.join(rootPath, `${type.toUpperCase()}.md`);
18336
18418
  }
18337
18419
  function discoverWorkspaceArtifacts(rootPath) {
18338
18420
  const resolvedRoot = path.resolve(rootPath);
18339
- const candidatePaths = [];
18340
- collectCandidateFiles(resolvedRoot, 0, candidatePaths);
18421
+ const candidateFiles = [];
18422
+ collectCandidateFiles(resolvedRoot, resolvedRoot, 0, candidateFiles);
18423
+ candidateFiles.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
18341
18424
  const discovered = [];
18342
18425
  const foundTypes = /* @__PURE__ */ new Set();
18343
- for (const filePath of candidatePaths) {
18426
+ for (const candidate of candidateFiles) {
18344
18427
  let content;
18345
18428
  let stats;
18346
18429
  try {
18347
- stats = fs.statSync(filePath);
18430
+ stats = fs.statSync(candidate.filePath);
18348
18431
  if (stats.size > MAX_FILE_SIZE) {
18349
18432
  continue;
18350
18433
  }
18351
- content = fs.readFileSync(filePath, "utf-8");
18434
+ content = fs.readFileSync(candidate.filePath, "utf-8");
18352
18435
  } catch {
18353
18436
  continue;
18354
18437
  }
18355
- const type = inferArtifactType(filePath, content);
18356
- if (!type) {
18357
- continue;
18358
- }
18359
- foundTypes.add(type);
18360
- const missingSections = findMissingSections(content, type);
18438
+ foundTypes.add(candidate.type);
18439
+ const missingSections = findMissingSections(content, candidate.type);
18361
18440
  discovered.push({
18362
- filePath,
18363
- relativePath: path.relative(resolvedRoot, filePath),
18364
- type,
18441
+ filePath: candidate.filePath,
18442
+ relativePath: candidate.relativePath,
18443
+ type: candidate.type,
18365
18444
  exists: true,
18366
18445
  sizeBytes: stats.size,
18367
18446
  isEmpty: content.trim().length === 0,
@@ -18374,7 +18453,7 @@ function discoverWorkspaceArtifacts(rootPath) {
18374
18453
  missing.push({
18375
18454
  type,
18376
18455
  suggestedPath: findSuggestedPath(type, resolvedRoot),
18377
- reason: `No ${type} artifact found in the workspace.`
18456
+ reason: `No canonical ${type} artifact found in the workspace.`
18378
18457
  });
18379
18458
  }
18380
18459
  }
@@ -18915,6 +18994,115 @@ function registerAgentLintResources(server) {
18915
18994
  );
18916
18995
  }
18917
18996
 
18997
+ // src/logger.ts
18998
+ function logMcp(level, event, fields = {}) {
18999
+ const payload = {
19000
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
19001
+ level,
19002
+ event,
19003
+ ...fields
19004
+ };
19005
+ console.error(JSON.stringify(payload));
19006
+ }
19007
+
19008
+ // src/catalog.ts
19009
+ var CURRENT_TOOL_TIMEOUTS = {
19010
+ agentlint_get_guidelines: 3e4,
19011
+ agentlint_plan_workspace_autofix: 6e4,
19012
+ agentlint_quick_check: 3e4,
19013
+ agentlint_emit_maintenance_snippet: 1e4
19014
+ };
19015
+ var LEGACY_TOOL_TIMEOUT_ALIASES = {
19016
+ analyze_artifact: 3e4,
19017
+ analyze_workspace_artifacts: 6e4,
19018
+ analyze_context_bundle: 3e4,
19019
+ prepare_artifact_fix_context: 3e4,
19020
+ submit_client_assessment: 3e4,
19021
+ suggest_patch: 3e4,
19022
+ quality_gate_artifact: 3e4,
19023
+ apply_patches: 15e3,
19024
+ validate_export: 1e4
19025
+ };
19026
+
19027
+ // src/transport-security.ts
19028
+ var MAX_JSONRPC_MESSAGE_BYTES = 10 * 1024 * 1024;
19029
+ var TOOL_TIMEOUTS = {
19030
+ ...CURRENT_TOOL_TIMEOUTS,
19031
+ ...LEGACY_TOOL_TIMEOUT_ALIASES
19032
+ };
19033
+ var DEFAULT_TOOL_TIMEOUT_MS = 3e4;
19034
+ function applyMessageSizeGuard(transport, maxBytes = MAX_JSONRPC_MESSAGE_BYTES) {
19035
+ const originalStart = transport.start.bind(transport);
19036
+ transport.start = async function() {
19037
+ await originalStart();
19038
+ const downstream = transport.onmessage;
19039
+ if (!downstream) {
19040
+ return;
19041
+ }
19042
+ transport.onmessage = (message, extra) => {
19043
+ const serialized = JSON.stringify(message);
19044
+ const byteLength = Buffer.byteLength(serialized, "utf8");
19045
+ if (byteLength > maxBytes) {
19046
+ logMcp("warn", "transport.message_too_large", {
19047
+ byteLength,
19048
+ maxBytes,
19049
+ preview: serialized.slice(0, 200)
19050
+ });
19051
+ if (transport.onerror) {
19052
+ transport.onerror(
19053
+ new Error(`JSON-RPC message too large: ${byteLength} bytes (limit: ${maxBytes} bytes)`)
19054
+ );
19055
+ }
19056
+ return;
19057
+ }
19058
+ downstream(message, extra);
19059
+ };
19060
+ };
19061
+ return transport;
19062
+ }
19063
+ var ToolTimeoutError = class extends Error {
19064
+ toolName;
19065
+ timeoutMs;
19066
+ constructor(toolName, timeoutMs) {
19067
+ super(`Tool "${toolName}" timed out after ${timeoutMs}ms`);
19068
+ this.name = "ToolTimeoutError";
19069
+ this.toolName = toolName;
19070
+ this.timeoutMs = timeoutMs;
19071
+ }
19072
+ };
19073
+ function getToolTimeout(toolName) {
19074
+ return TOOL_TIMEOUTS[toolName] ?? DEFAULT_TOOL_TIMEOUT_MS;
19075
+ }
19076
+ async function withToolTimeout(toolName, fn, timeoutMs) {
19077
+ const ms = timeoutMs ?? getToolTimeout(toolName);
19078
+ return new Promise((resolve, reject) => {
19079
+ let settled = false;
19080
+ const timer = setTimeout(() => {
19081
+ if (!settled) {
19082
+ settled = true;
19083
+ logMcp("warn", "tool.timeout", { toolName, timeoutMs: ms });
19084
+ reject(new ToolTimeoutError(toolName, ms));
19085
+ }
19086
+ }, ms);
19087
+ fn().then(
19088
+ (result) => {
19089
+ if (!settled) {
19090
+ settled = true;
19091
+ clearTimeout(timer);
19092
+ resolve(result);
19093
+ }
19094
+ },
19095
+ (error48) => {
19096
+ if (!settled) {
19097
+ settled = true;
19098
+ clearTimeout(timer);
19099
+ reject(error48);
19100
+ }
19101
+ }
19102
+ );
19103
+ });
19104
+ }
19105
+
18918
19106
  // src/tools/schema-compat.ts
18919
19107
  function asInputSchema(schema) {
18920
19108
  return schema;
@@ -18948,8 +19136,9 @@ function toErrorResult(message) {
18948
19136
 
18949
19137
  // src/tools/get-guidelines.ts
18950
19138
  function registerGetGuidelinesTool(server) {
19139
+ const toolName = "agentlint_get_guidelines";
18951
19140
  server.registerTool(
18952
- "agentlint_get_guidelines",
19141
+ toolName,
18953
19142
  {
18954
19143
  title: "Get Guidelines",
18955
19144
  description: "Returns comprehensive Markdown guidelines for creating or updating a context artifact (AGENTS.md, skills, rules, workflows, plans). Includes mandatory sections, do/don't lists, anti-patterns, quality checklist, template skeleton, and client-specific hints. Call this tool before creating or editing any AI agent context artifact file.",
@@ -18962,11 +19151,11 @@ function registerGetGuidelinesTool(server) {
18962
19151
  },
18963
19152
  asToolHandler(async (args) => {
18964
19153
  try {
18965
- const markdown = buildGuidelines(args.type, args.client ?? "generic");
19154
+ const markdown = await withToolTimeout(toolName, async () => buildGuidelines(args.type, args.client ?? "generic"));
18966
19155
  return toMarkdownResult(markdown);
18967
19156
  } catch (error48) {
18968
19157
  const message = error48 instanceof Error ? error48.message : "Unknown error";
18969
- return toErrorResult(`agentlint_get_guidelines failed: ${message}`);
19158
+ return toErrorResult(`${toolName} failed: ${message}`);
18970
19159
  }
18971
19160
  })
18972
19161
  );
@@ -18974,11 +19163,12 @@ function registerGetGuidelinesTool(server) {
18974
19163
 
18975
19164
  // src/tools/plan-workspace-autofix.ts
18976
19165
  function registerPlanWorkspaceAutofixTool(server, options2) {
19166
+ const toolName = "agentlint_plan_workspace_autofix";
18977
19167
  if (!options2.enabled) {
18978
19168
  return;
18979
19169
  }
18980
19170
  server.registerTool(
18981
- "agentlint_plan_workspace_autofix",
19171
+ toolName,
18982
19172
  {
18983
19173
  title: "Plan Workspace Autofix",
18984
19174
  description: "Scans the workspace for all AI agent context artifact files (AGENTS.md, CLAUDE.md, skills, rules, workflows, plans), identifies missing files and incomplete sections, and returns a step-by-step Markdown action plan. The LLM should execute the plan using its file reading and editing capabilities. Call this when the user asks to review, fix, or improve all context artifacts in a project.",
@@ -18992,11 +19182,11 @@ function registerPlanWorkspaceAutofixTool(server, options2) {
18992
19182
  asToolHandler(async (args) => {
18993
19183
  try {
18994
19184
  const rootPath = args.rootPath ?? process.cwd();
18995
- const plan = buildWorkspaceAutofixPlan(rootPath);
19185
+ const plan = await withToolTimeout(toolName, async () => buildWorkspaceAutofixPlan(rootPath));
18996
19186
  return toMarkdownResult(plan.markdown);
18997
19187
  } catch (error48) {
18998
19188
  const message = error48 instanceof Error ? error48.message : "Unknown error";
18999
- return toErrorResult(`agentlint_plan_workspace_autofix failed: ${message}`);
19189
+ return toErrorResult(`${toolName} failed: ${message}`);
19000
19190
  }
19001
19191
  })
19002
19192
  );
@@ -19004,8 +19194,9 @@ function registerPlanWorkspaceAutofixTool(server, options2) {
19004
19194
 
19005
19195
  // src/tools/quick-check.ts
19006
19196
  function registerQuickCheckTool(server) {
19197
+ const toolName = "agentlint_quick_check";
19007
19198
  server.registerTool(
19008
- "agentlint_quick_check",
19199
+ toolName,
19009
19200
  {
19010
19201
  title: "Quick Check",
19011
19202
  description: "Checks whether recent code changes require updates to AI agent context artifacts. Provide changed file paths and/or a description of what changed. Returns signals indicating which artifacts (AGENTS.md, rules, workflows, etc.) may need updating and what action to take. Call this after structural changes like adding modules, changing configs, or modifying dependencies.",
@@ -19018,11 +19209,11 @@ function registerQuickCheckTool(server) {
19018
19209
  },
19019
19210
  asToolHandler(async (args) => {
19020
19211
  try {
19021
- const result = runQuickCheck(args.changedPaths, args.changeDescription);
19212
+ const result = await withToolTimeout(toolName, async () => runQuickCheck(args.changedPaths, args.changeDescription));
19022
19213
  return toMarkdownResult(result.markdown);
19023
19214
  } catch (error48) {
19024
19215
  const message = error48 instanceof Error ? error48.message : "Unknown error";
19025
- return toErrorResult(`agentlint_quick_check failed: ${message}`);
19216
+ return toErrorResult(`${toolName} failed: ${message}`);
19026
19217
  }
19027
19218
  })
19028
19219
  );
@@ -19030,8 +19221,9 @@ function registerQuickCheckTool(server) {
19030
19221
 
19031
19222
  // src/tools/emit-maintenance-snippet.ts
19032
19223
  function registerEmitMaintenanceSnippetTool(server) {
19224
+ const toolName = "agentlint_emit_maintenance_snippet";
19033
19225
  server.registerTool(
19034
- "agentlint_emit_maintenance_snippet",
19226
+ toolName,
19035
19227
  {
19036
19228
  title: "Emit Maintenance Snippet",
19037
19229
  description: "Returns a persistent rule snippet that you should add to the user's IDE rules file. Once added, these rules ensure the LLM agent automatically maintains context artifacts (AGENTS.md, skills, rules, workflows, plans) whenever structural changes happen. Supports Cursor, Windsurf, VS Code, Claude Code, and generic formats. Call this when the user asks to set up automatic context maintenance.",
@@ -19044,11 +19236,11 @@ function registerEmitMaintenanceSnippetTool(server) {
19044
19236
  },
19045
19237
  asToolHandler(async (args) => {
19046
19238
  try {
19047
- const result = buildMaintenanceSnippet(args.client ?? "generic");
19239
+ const result = await withToolTimeout(toolName, async () => buildMaintenanceSnippet(args.client ?? "generic"));
19048
19240
  return toMarkdownResult(result.markdown);
19049
19241
  } catch (error48) {
19050
19242
  const message = error48 instanceof Error ? error48.message : "Unknown error";
19051
- return toErrorResult(`agentlint_emit_maintenance_snippet failed: ${message}`);
19243
+ return toErrorResult(`${toolName} failed: ${message}`);
19052
19244
  }
19053
19245
  })
19054
19246
  );
@@ -19063,6 +19255,7 @@ function registerAgentLintTools(server, options2) {
19063
19255
  }
19064
19256
 
19065
19257
  // src/server.ts
19258
+ import { readFileSync } from "fs";
19066
19259
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
19067
19260
  var DEFAULT_MCP_SERVER_NAME = "agentlint";
19068
19261
  var DEFAULT_MCP_INSTRUCTIONS = [
@@ -19075,7 +19268,22 @@ var DEFAULT_MCP_INSTRUCTIONS = [
19075
19268
  "Apply recommended changes directly using your file editing capabilities."
19076
19269
  ].join(" ");
19077
19270
  function resolveServerVersion() {
19078
- return process.env.npm_package_version ?? "0.2.0";
19271
+ if (process.env.npm_package_name === "@agent-lint/mcp" && process.env.npm_package_version) {
19272
+ return process.env.npm_package_version;
19273
+ }
19274
+ if ("0.3.4".length > 0) {
19275
+ return "0.3.4";
19276
+ }
19277
+ try {
19278
+ const pkg = JSON.parse(
19279
+ readFileSync(new URL("../package.json", import.meta.url), "utf-8")
19280
+ );
19281
+ if (typeof pkg.version === "string" && pkg.version.length > 0) {
19282
+ return pkg.version;
19283
+ }
19284
+ } catch {
19285
+ }
19286
+ return "0.0.0-dev";
19079
19287
  }
19080
19288
  function resolveWorkspaceScanEnabled(options2) {
19081
19289
  if (typeof options2.enableWorkspaceScan === "boolean") {
@@ -19087,7 +19295,7 @@ function resolveWorkspaceScanEnabled(options2) {
19087
19295
  if (options2.transportMode === "http") {
19088
19296
  return process.env.MCP_ENABLE_WORKSPACE_SCAN === "true";
19089
19297
  }
19090
- return process.env.MCP_ENABLE_WORKSPACE_SCAN === "true";
19298
+ return process.env.MCP_ENABLE_WORKSPACE_SCAN !== "false";
19091
19299
  }
19092
19300
  function resolveInstructions(options2, workspaceScanEnabled) {
19093
19301
  if (options2.instructions) {
@@ -19125,103 +19333,6 @@ function createAgentLintMcpServer(options2 = {}) {
19125
19333
  return server;
19126
19334
  }
19127
19335
 
19128
- // src/logger.ts
19129
- function logMcp(level, event, fields = {}) {
19130
- const payload = {
19131
- ts: (/* @__PURE__ */ new Date()).toISOString(),
19132
- level,
19133
- event,
19134
- ...fields
19135
- };
19136
- console.error(JSON.stringify(payload));
19137
- }
19138
-
19139
- // src/transport-security.ts
19140
- var MAX_JSONRPC_MESSAGE_BYTES = 10 * 1024 * 1024;
19141
- var TOOL_TIMEOUTS = {
19142
- analyze_artifact: 3e4,
19143
- analyze_workspace_artifacts: 6e4,
19144
- analyze_context_bundle: 3e4,
19145
- prepare_artifact_fix_context: 3e4,
19146
- submit_client_assessment: 3e4,
19147
- suggest_patch: 3e4,
19148
- quality_gate_artifact: 3e4,
19149
- apply_patches: 15e3,
19150
- validate_export: 1e4
19151
- };
19152
- var DEFAULT_TOOL_TIMEOUT_MS = 3e4;
19153
- function applyMessageSizeGuard(transport, maxBytes = MAX_JSONRPC_MESSAGE_BYTES) {
19154
- const originalStart = transport.start.bind(transport);
19155
- transport.start = async function() {
19156
- await originalStart();
19157
- const downstream = transport.onmessage;
19158
- if (!downstream) {
19159
- return;
19160
- }
19161
- transport.onmessage = (message, extra) => {
19162
- const serialized = JSON.stringify(message);
19163
- const byteLength = Buffer.byteLength(serialized, "utf8");
19164
- if (byteLength > maxBytes) {
19165
- logMcp("warn", "transport.message_too_large", {
19166
- byteLength,
19167
- maxBytes,
19168
- preview: serialized.slice(0, 200)
19169
- });
19170
- if (transport.onerror) {
19171
- transport.onerror(
19172
- new Error(`JSON-RPC message too large: ${byteLength} bytes (limit: ${maxBytes} bytes)`)
19173
- );
19174
- }
19175
- return;
19176
- }
19177
- downstream(message, extra);
19178
- };
19179
- };
19180
- return transport;
19181
- }
19182
- var ToolTimeoutError = class extends Error {
19183
- toolName;
19184
- timeoutMs;
19185
- constructor(toolName, timeoutMs) {
19186
- super(`Tool "${toolName}" timed out after ${timeoutMs}ms`);
19187
- this.name = "ToolTimeoutError";
19188
- this.toolName = toolName;
19189
- this.timeoutMs = timeoutMs;
19190
- }
19191
- };
19192
- function getToolTimeout(toolName) {
19193
- return TOOL_TIMEOUTS[toolName] ?? DEFAULT_TOOL_TIMEOUT_MS;
19194
- }
19195
- async function withToolTimeout(toolName, fn, timeoutMs) {
19196
- const ms = timeoutMs ?? getToolTimeout(toolName);
19197
- return new Promise((resolve, reject) => {
19198
- let settled = false;
19199
- const timer = setTimeout(() => {
19200
- if (!settled) {
19201
- settled = true;
19202
- logMcp("warn", "tool.timeout", { toolName, timeoutMs: ms });
19203
- reject(new ToolTimeoutError(toolName, ms));
19204
- }
19205
- }, ms);
19206
- fn().then(
19207
- (result) => {
19208
- if (!settled) {
19209
- settled = true;
19210
- clearTimeout(timer);
19211
- resolve(result);
19212
- }
19213
- },
19214
- (error48) => {
19215
- if (!settled) {
19216
- settled = true;
19217
- clearTimeout(timer);
19218
- reject(error48);
19219
- }
19220
- }
19221
- );
19222
- });
19223
- }
19224
-
19225
19336
  // src/stdio.ts
19226
19337
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
19227
19338
  async function runStdioServer() {
@@ -19601,9 +19712,6 @@ async function runHttpServer(options2 = {}) {
19601
19712
  export {
19602
19713
  registerAgentLintPrompts,
19603
19714
  registerAgentLintResources,
19604
- registerAgentLintTools,
19605
- DEFAULT_MCP_SERVER_NAME,
19606
- createAgentLintMcpServer,
19607
19715
  logMcp,
19608
19716
  MAX_JSONRPC_MESSAGE_BYTES,
19609
19717
  TOOL_TIMEOUTS,
@@ -19612,6 +19720,9 @@ export {
19612
19720
  ToolTimeoutError,
19613
19721
  getToolTimeout,
19614
19722
  withToolTimeout,
19723
+ registerAgentLintTools,
19724
+ DEFAULT_MCP_SERVER_NAME,
19725
+ createAgentLintMcpServer,
19615
19726
  runStdioServer,
19616
19727
  startRateLimitCleanup,
19617
19728
  stopRateLimitCleanup,
@@ -19641,4 +19752,4 @@ strip-bom-string/index.js:
19641
19752
  * Released under the MIT License.
19642
19753
  *)
19643
19754
  */
19644
- //# sourceMappingURL=chunk-ZYDIOQXE.js.map
19755
+ //# sourceMappingURL=chunk-GNY7X6J5.js.map