ソースを参照

fix(mcp): cap codegraph_context output to prevent context bloat (#296)

Route handleContext's output through the shared truncateOutput cap
(MAX_OUTPUT_LENGTH) so codegraph_context can no longer blow past the context
budget — every sibling MCP tool already truncates; this was the one uncapped
output path.

Closes #296

Co-authored-by: Baijack-star <71923891+Baijack-star@users.noreply.github.com>
Baijack-star 1 ヶ月 前
コミット
23ad4ea923
2 ファイル変更16 行追加2 行削除
  1. 14 0
      __tests__/security.test.ts
  2. 2 2
      src/mcp/tools.ts

+ 14 - 0
__tests__/security.test.ts

@@ -239,6 +239,20 @@ describe('MCP Input Validation', () => {
     expect(result.content[0].text).toContain('non-empty string');
   });
 
+  it('should truncate oversized codegraph_context output', async () => {
+    const oversizedContext = Array.from({ length: 400 }, (_, i) => `line-${i} ${'x'.repeat(80)}`).join('\n');
+    const fakeCg = {
+      buildContext: async () => oversizedContext,
+    };
+    const fakeHandler = new ToolHandler(fakeCg as unknown as CodeGraph);
+
+    const result = await fakeHandler.execute('codegraph_context', { task: 'find example' });
+
+    expect(result.isError).toBeFalsy();
+    expect(result.content[0].text.length).toBeLessThan(oversizedContext.length);
+    expect(result.content[0].text).toContain('... (output truncated)');
+  });
+
   it('should reject non-string symbol in codegraph_impact', async () => {
     const result = await handler.execute('codegraph_impact', { symbol: [] });
     expect(result.isError).toBe(true);

+ 2 - 2
src/mcp/tools.ts

@@ -775,11 +775,11 @@ export class ToolHandler {
 
     // buildContext returns string when format is 'markdown'
     if (typeof context === 'string') {
-      return this.textResult(context + reminder);
+      return this.textResult(this.truncateOutput(context + reminder));
     }
 
     // If it returns TaskContext, format it
-    return this.textResult(this.formatTaskContext(context) + reminder);
+    return this.textResult(this.truncateOutput(this.formatTaskContext(context) + reminder));
   }
 
   /**