mcp-code-context 2.1.3

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.
Files changed (112) hide show
  1. package/AGENT_INSTRUCTIONS.md +135 -0
  2. package/CHANGELOG.md +84 -0
  3. package/DEPLOYMENT_INSTRUCTIONS.md +110 -0
  4. package/LICENSE +21 -0
  5. package/README.md +247 -0
  6. package/RELEASE_NOTES_v2.1.3.md +78 -0
  7. package/TROUBLESHOOTING.md +38 -0
  8. package/dist/src/ast/dartCompressor.d.ts +27 -0
  9. package/dist/src/ast/dartCompressor.js +859 -0
  10. package/dist/src/ast/dartCompressor.js.map +1 -0
  11. package/dist/src/ast/phpCompressor.d.ts +24 -0
  12. package/dist/src/ast/phpCompressor.js +634 -0
  13. package/dist/src/ast/phpCompressor.js.map +1 -0
  14. package/dist/src/ast/semanticCompressor.d.ts +22 -0
  15. package/dist/src/ast/semanticCompressor.js +677 -0
  16. package/dist/src/ast/semanticCompressor.js.map +1 -0
  17. package/dist/src/ast/writers/dartWriter.d.ts +37 -0
  18. package/dist/src/ast/writers/dartWriter.js +544 -0
  19. package/dist/src/ast/writers/dartWriter.js.map +1 -0
  20. package/dist/src/ast/writers/phpWriter.d.ts +37 -0
  21. package/dist/src/ast/writers/phpWriter.js +411 -0
  22. package/dist/src/ast/writers/phpWriter.js.map +1 -0
  23. package/dist/src/ast/writers/pyWriter.d.ts +37 -0
  24. package/dist/src/ast/writers/pyWriter.js +355 -0
  25. package/dist/src/ast/writers/pyWriter.js.map +1 -0
  26. package/dist/src/ast/writers/symbolWriter.d.ts +62 -0
  27. package/dist/src/ast/writers/symbolWriter.js +179 -0
  28. package/dist/src/ast/writers/symbolWriter.js.map +1 -0
  29. package/dist/src/ast/writers/tsWriter.d.ts +38 -0
  30. package/dist/src/ast/writers/tsWriter.js +344 -0
  31. package/dist/src/ast/writers/tsWriter.js.map +1 -0
  32. package/dist/src/index.d.ts +117 -0
  33. package/dist/src/index.js +1289 -0
  34. package/dist/src/index.js.map +1 -0
  35. package/dist/src/tests/test-confirmation-flow.d.ts +1 -0
  36. package/dist/src/tests/test-confirmation-flow.js +43 -0
  37. package/dist/src/tests/test-confirmation-flow.js.map +1 -0
  38. package/dist/src/utils/backupManager.d.ts +24 -0
  39. package/dist/src/utils/backupManager.js +59 -0
  40. package/dist/src/utils/backupManager.js.map +1 -0
  41. package/dist/src/utils/confirmationCache.d.ts +16 -0
  42. package/dist/src/utils/confirmationCache.js +40 -0
  43. package/dist/src/utils/confirmationCache.js.map +1 -0
  44. package/dist/src/utils/diffEngine.d.ts +21 -0
  45. package/dist/src/utils/diffEngine.js +163 -0
  46. package/dist/src/utils/diffEngine.js.map +1 -0
  47. package/dist/src/utils/fuzzyMatch.d.ts +8 -0
  48. package/dist/src/utils/fuzzyMatch.js +69 -0
  49. package/dist/src/utils/fuzzyMatch.js.map +1 -0
  50. package/dist/src/utils/ignoreManager.d.ts +22 -0
  51. package/dist/src/utils/ignoreManager.js +135 -0
  52. package/dist/src/utils/ignoreManager.js.map +1 -0
  53. package/dist/tests/debug-replace.d.ts +1 -0
  54. package/dist/tests/debug-replace.js +17 -0
  55. package/dist/tests/debug-replace.js.map +1 -0
  56. package/dist/tests/test-confirmation-flow.d.ts +1 -0
  57. package/dist/tests/test-confirmation-flow.js +43 -0
  58. package/dist/tests/test-confirmation-flow.js.map +1 -0
  59. package/dist/tests/test-dart.d.ts +1 -0
  60. package/dist/tests/test-dart.js +242 -0
  61. package/dist/tests/test-dart.js.map +1 -0
  62. package/dist/tests/test-php-ast.d.ts +1 -0
  63. package/dist/tests/test-php-ast.js +152 -0
  64. package/dist/tests/test-php-ast.js.map +1 -0
  65. package/dist/tests/test-php.d.ts +1 -0
  66. package/dist/tests/test-php.js +234 -0
  67. package/dist/tests/test-php.js.map +1 -0
  68. package/dist/tests/test-smoke.d.ts +5 -0
  69. package/dist/tests/test-smoke.js +83 -0
  70. package/dist/tests/test-smoke.js.map +1 -0
  71. package/dist/tests/writers/test-crlf-handling.d.ts +4 -0
  72. package/dist/tests/writers/test-crlf-handling.js +73 -0
  73. package/dist/tests/writers/test-crlf-handling.js.map +1 -0
  74. package/dist/tests/writers/test-write-smoke.d.ts +9 -0
  75. package/dist/tests/writers/test-write-smoke.js +346 -0
  76. package/dist/tests/writers/test-write-smoke.js.map +1 -0
  77. package/llms.txt +164 -0
  78. package/package.json +57 -0
  79. package/src/ast/dartCompressor.ts +1013 -0
  80. package/src/ast/phpCompressor.ts +814 -0
  81. package/src/ast/semanticCompressor.ts +808 -0
  82. package/src/ast/writers/dartWriter.ts +648 -0
  83. package/src/ast/writers/phpWriter.ts +508 -0
  84. package/src/ast/writers/pyWriter.ts +446 -0
  85. package/src/ast/writers/symbolWriter.ts +277 -0
  86. package/src/ast/writers/tsWriter.ts +418 -0
  87. package/src/index.ts +1553 -0
  88. package/src/utils/backupManager.ts +66 -0
  89. package/src/utils/confirmationCache.ts +61 -0
  90. package/src/utils/diffEngine.ts +223 -0
  91. package/src/utils/fuzzyMatch.ts +86 -0
  92. package/src/utils/ignoreManager.ts +144 -0
  93. package/tests/test-confirmation-flow.ts +49 -0
  94. package/tests/test-dart.d.ts +1 -0
  95. package/tests/test-dart.js +209 -0
  96. package/tests/test-dart.js.map +1 -0
  97. package/tests/test-dart.ts +265 -0
  98. package/tests/test-php-ast.d.ts +1 -0
  99. package/tests/test-php-ast.js +152 -0
  100. package/tests/test-php-ast.js.map +1 -0
  101. package/tests/test-php-ast.ts +155 -0
  102. package/tests/test-php.d.ts +1 -0
  103. package/tests/test-php.js +234 -0
  104. package/tests/test-php.js.map +1 -0
  105. package/tests/test-php.ts +261 -0
  106. package/tests/test-smoke.d.ts +5 -0
  107. package/tests/test-smoke.js +83 -0
  108. package/tests/test-smoke.js.map +1 -0
  109. package/tests/test-smoke.ts +93 -0
  110. package/tests/writers/test-crlf-handling.ts +100 -0
  111. package/tests/writers/test-write-smoke.ts +568 -0
  112. package/tsconfig.json +19 -0
@@ -0,0 +1,346 @@
1
+ /**
2
+ * test-write-smoke.ts — Smoke Tests for Surgical Writing Tools
3
+ *
4
+ * Tests all 4 write operations (replace, insert, rename, remove)
5
+ * across all 4 supported languages (TypeScript, PHP, Dart, Python).
6
+ *
7
+ * Run: npm run build && node dist/tests/writers/test-write-smoke.js
8
+ */
9
+ import { replaceSymbol, insertCode, renameInFile, removeSymbolFromFile, } from "../../src/ast/writers/symbolWriter.js";
10
+ import { generateDiff } from "../../src/utils/diffEngine.js";
11
+ // ─── Test Harness ───────────────────────────────────────────────────
12
+ let passed = 0;
13
+ let failed = 0;
14
+ function assert(condition, label, detail) {
15
+ if (condition) {
16
+ passed++;
17
+ console.log(` ✅ ${label}`);
18
+ }
19
+ else {
20
+ failed++;
21
+ console.error(` ❌ ${label}`);
22
+ if (detail)
23
+ console.error(` ${detail}`);
24
+ }
25
+ }
26
+ function section(title) {
27
+ console.log(`\n━━━ ${title} ━━━`);
28
+ }
29
+ // ─── Test Fixtures ──────────────────────────────────────────────────
30
+ const TS_FIXTURE = `
31
+ import { Something } from "./something.js";
32
+
33
+ const API_URL = "https://example.com";
34
+
35
+ export interface UserConfig {
36
+ name: string;
37
+ email: string;
38
+ }
39
+
40
+ export class UserService {
41
+ private users: Map<string, UserConfig> = new Map();
42
+
43
+ getUser(id: string): UserConfig | undefined {
44
+ return this.users.get(id);
45
+ }
46
+
47
+ addUser(id: string, config: UserConfig): void {
48
+ this.users.set(id, config);
49
+ }
50
+
51
+ deleteUser(id: string): boolean {
52
+ return this.users.delete(id);
53
+ }
54
+ }
55
+
56
+ export function formatUser(user: UserConfig): string {
57
+ return \`\${user.name} <\${user.email}>\`;
58
+ }
59
+ `.trim();
60
+ const PHP_FIXTURE = `<?php
61
+
62
+ namespace App\\Services;
63
+
64
+ use App\\Models\\User;
65
+ use App\\Contracts\\UserRepositoryInterface;
66
+
67
+ /**
68
+ * Manages user operations.
69
+ */
70
+ class UserService
71
+ {
72
+ private UserRepositoryInterface $repository;
73
+
74
+ public function __construct(UserRepositoryInterface $repository)
75
+ {
76
+ $this->repository = $repository;
77
+ }
78
+
79
+ /**
80
+ * Find a user by ID.
81
+ */
82
+ public function findUser(int $id): ?User
83
+ {
84
+ return $this->repository->find($id);
85
+ }
86
+
87
+ /**
88
+ * Create a new user.
89
+ */
90
+ public function createUser(array $data): User
91
+ {
92
+ return $this->repository->create($data);
93
+ }
94
+
95
+ public function deleteUser(int $id): bool
96
+ {
97
+ return $this->repository->delete($id);
98
+ }
99
+ }
100
+
101
+ function helperFunction(): string
102
+ {
103
+ return 'hello';
104
+ }
105
+ `;
106
+ const DART_FIXTURE = `
107
+ import 'package:flutter/material.dart';
108
+
109
+ /// A service for managing user data.
110
+ class UserService {
111
+ final Map<String, dynamic> _cache = {};
112
+
113
+ /// Gets a user by ID.
114
+ Future<Map<String, dynamic>?> getUser(String id) async {
115
+ if (_cache.containsKey(id)) {
116
+ return _cache[id];
117
+ }
118
+ return null;
119
+ }
120
+
121
+ /// Adds a user to the cache.
122
+ void addUser(String id, Map<String, dynamic> data) {
123
+ _cache[id] = data;
124
+ }
125
+
126
+ /// Removes a user from the cache.
127
+ bool removeUser(String id) {
128
+ return _cache.remove(id) != null;
129
+ }
130
+ }
131
+
132
+ /// Formats a user name for display.
133
+ String formatUserName(String first, String last) {
134
+ return '\$first \$last';
135
+ }
136
+ `.trim();
137
+ const PY_FIXTURE = `
138
+ from typing import Optional, Dict
139
+
140
+ class UserService:
141
+ """Manages user operations."""
142
+
143
+ def __init__(self):
144
+ self._users: Dict[str, dict] = {}
145
+
146
+ def get_user(self, user_id: str) -> Optional[dict]:
147
+ """Get a user by ID."""
148
+ return self._users.get(user_id)
149
+
150
+ def add_user(self, user_id: str, data: dict) -> None:
151
+ """Add a user."""
152
+ self._users[user_id] = data
153
+
154
+ def delete_user(self, user_id: str) -> bool:
155
+ """Delete a user."""
156
+ if user_id in self._users:
157
+ del self._users[user_id]
158
+ return True
159
+ return False
160
+
161
+
162
+ def format_user(user: dict) -> str:
163
+ """Format a user for display."""
164
+ return f"{user['name']} <{user['email']}>"
165
+ `.trim();
166
+ // ─── TypeScript Tests ───────────────────────────────────────────────
167
+ function testTypeScript() {
168
+ section("TypeScript / JavaScript");
169
+ // Replace
170
+ const replaceResult = replaceSymbol("test.ts", TS_FIXTURE, "formatUser", `export function formatUser(user: UserConfig): string {\n return \`User: \${user.name} (\${user.email})\`;\n}`);
171
+ assert(replaceResult.success, "Replace: formatUser");
172
+ assert(replaceResult.newContent.includes("User: ${user.name}"), "Replace: new content is present");
173
+ assert(replaceResult.newContent.includes("class UserService"), "Replace: other symbols preserved");
174
+ // Insert
175
+ const insertResult = insertCode("test.ts", TS_FIXTURE, `export function greetUser(user: UserConfig): string {\n return \`Hello, \${user.name}!\`;\n}`, "formatUser", "after");
176
+ assert(insertResult.success, "Insert: after formatUser");
177
+ assert(insertResult.newContent.includes("greetUser"), "Insert: new function is present");
178
+ // Insert inside class
179
+ const insertClassResult = insertCode("test.ts", TS_FIXTURE, `getUserCount(): number {\n return this.users.size;\n}`, "UserService", "inside_end");
180
+ assert(insertClassResult.success, "Insert: inside_end of UserService");
181
+ assert(insertClassResult.newContent.includes("getUserCount"), "Insert: method added to class");
182
+ // Rename
183
+ const renameResult = renameInFile("test.ts", TS_FIXTURE, "UserService", "AccountService");
184
+ assert(renameResult.success, "Rename: UserService → AccountService");
185
+ assert(renameResult.newContent.includes("class AccountService"), "Rename: class declaration updated");
186
+ assert(!renameResult.newContent.includes("class UserService"), "Rename: old name removed");
187
+ // Remove
188
+ const removeResult = removeSymbolFromFile("test.ts", TS_FIXTURE, "formatUser");
189
+ assert(removeResult.success, "Remove: formatUser");
190
+ assert(!removeResult.newContent.includes("function formatUser"), "Remove: function is gone");
191
+ assert(removeResult.newContent.includes("class UserService"), "Remove: other symbols still exist");
192
+ // Remove interface
193
+ const removeIfaceResult = removeSymbolFromFile("test.ts", TS_FIXTURE, "UserConfig");
194
+ assert(removeIfaceResult.success, "Remove: UserConfig interface");
195
+ assert(!removeIfaceResult.newContent.includes("interface UserConfig"), "Remove: interface is gone");
196
+ }
197
+ // ─── PHP Tests ──────────────────────────────────────────────────────
198
+ function testPHP() {
199
+ section("PHP");
200
+ // Replace
201
+ const replaceResult = replaceSymbol("test.php", PHP_FIXTURE, "findUser", ` public function findUser(int $id): ?User\n {\n $cached = $this->cache->get($id);\n return $cached ?? $this->repository->find($id);\n }`);
202
+ assert(replaceResult.success, "Replace: findUser method");
203
+ assert(replaceResult.newContent.includes("$cached"), "Replace: new content present");
204
+ // Insert
205
+ const insertResult = insertCode("test.php", PHP_FIXTURE, ` public function updateUser(int $id, array $data): User\n {\n return $this->repository->update($id, $data);\n }`, "createUser", "after");
206
+ assert(insertResult.success, "Insert: after createUser");
207
+ assert(insertResult.newContent.includes("updateUser"), "Insert: method present");
208
+ // Rename
209
+ const renameResult = renameInFile("test.php", PHP_FIXTURE, "UserService", "AccountService");
210
+ assert(renameResult.success, "Rename: UserService → AccountService");
211
+ assert(renameResult.newContent.includes("class AccountService"), "Rename: class updated");
212
+ // Remove
213
+ const removeResult = removeSymbolFromFile("test.php", PHP_FIXTURE, "helperFunction");
214
+ assert(removeResult.success, "Remove: helperFunction");
215
+ assert(!removeResult.newContent.includes("function helperFunction"), "Remove: function gone");
216
+ assert(removeResult.newContent.includes("class UserService"), "Remove: class preserved");
217
+ }
218
+ // ─── Dart Tests ─────────────────────────────────────────────────────
219
+ function testDart() {
220
+ section("Dart");
221
+ // Replace
222
+ const replaceResult = replaceSymbol("test.dart", DART_FIXTURE, "formatUserName", `String formatUserName(String first, String last) {\n return '\${last.toUpperCase()}, \$first';\n}`);
223
+ assert(replaceResult.success, "Replace: formatUserName");
224
+ assert(replaceResult.newContent.includes("toUpperCase"), "Replace: new content present");
225
+ // Insert
226
+ const insertResult = insertCode("test.dart", DART_FIXTURE, `/// Checks if a user exists.\nbool userExists(String id) {\n return false;\n}`, "formatUserName", "after");
227
+ assert(insertResult.success, "Insert: after formatUserName");
228
+ assert(insertResult.newContent.includes("userExists"), "Insert: function present");
229
+ // Insert inside class
230
+ const insertClassResult = insertCode("test.dart", DART_FIXTURE, ` /// Clears the entire cache.\n void clearCache() {\n _cache.clear();\n }`, "UserService", "inside_end");
231
+ assert(insertClassResult.success, "Insert: inside_end of UserService");
232
+ assert(insertClassResult.newContent.includes("clearCache"), "Insert: method in class");
233
+ // Rename
234
+ const renameResult = renameInFile("test.dart", DART_FIXTURE, "UserService", "ProfileService");
235
+ assert(renameResult.success, "Rename: UserService → ProfileService");
236
+ assert(renameResult.newContent.includes("class ProfileService"), "Rename: class updated");
237
+ // Remove
238
+ const removeResult = removeSymbolFromFile("test.dart", DART_FIXTURE, "formatUserName");
239
+ assert(removeResult.success, "Remove: formatUserName");
240
+ assert(!removeResult.newContent.includes("formatUserName"), "Remove: function gone");
241
+ assert(removeResult.newContent.includes("class UserService"), "Remove: class preserved");
242
+ }
243
+ // ─── Python Tests ───────────────────────────────────────────────────
244
+ function testPython() {
245
+ section("Python");
246
+ // Replace
247
+ const replaceResult = replaceSymbol("test.py", PY_FIXTURE, "format_user", `def format_user(user: dict) -> str:\n """Format a user for display with title."""\n name = user['name'].title()\n return f"{name} <{user['email']}>"`);
248
+ assert(replaceResult.success, "Replace: format_user");
249
+ assert(replaceResult.newContent.includes(".title()"), "Replace: new content present");
250
+ // Insert
251
+ const insertResult = insertCode("test.py", PY_FIXTURE, `def validate_email(email: str) -> bool:\n """Check if email is valid."""\n return "@" in email and "." in email`, "format_user", "after");
252
+ assert(insertResult.success, "Insert: after format_user");
253
+ assert(insertResult.newContent.includes("validate_email"), "Insert: function present");
254
+ // Rename
255
+ const renameResult = renameInFile("test.py", PY_FIXTURE, "UserService", "AccountService");
256
+ assert(renameResult.success, "Rename: UserService → AccountService");
257
+ assert(renameResult.newContent.includes("class AccountService"), "Rename: class updated");
258
+ // Remove
259
+ const removeResult = removeSymbolFromFile("test.py", PY_FIXTURE, "format_user");
260
+ assert(removeResult.success, "Remove: format_user");
261
+ assert(!removeResult.newContent.includes("def format_user"), "Remove: function gone");
262
+ assert(removeResult.newContent.includes("class UserService"), "Remove: class preserved");
263
+ }
264
+ // ─── Class Name Filtering Tests ───────────────────────────────────────
265
+ function testClassName() {
266
+ section("ClassName Disambiguation");
267
+ const DART_MULTI_CLASS = `
268
+ class ClassA {
269
+ void build() {
270
+ print('A');
271
+ }
272
+ }
273
+
274
+ class ClassB {
275
+ void build() {
276
+ print('B');
277
+ }
278
+ }
279
+ `;
280
+ // Try to remove "build" from ClassB
281
+ const removeResult = removeSymbolFromFile("test_multi.dart", DART_MULTI_CLASS, "build", "ClassB");
282
+ assert(removeResult.success, "ClassName Remove: build from ClassB");
283
+ assert(removeResult.newContent.includes("print('A');"), "ClassName Remove: ClassA build preserved");
284
+ assert(!removeResult.newContent.includes("print('B');"), "ClassName Remove: ClassB build removed");
285
+ const PY_MULTI_CLASS = `
286
+ class ClassA:
287
+ def execute(self):
288
+ return 'A'
289
+
290
+ class ClassB:
291
+ def execute(self):
292
+ return 'B'
293
+ `;
294
+ const replaceResult = replaceSymbol("test_multi.py", PY_MULTI_CLASS, "execute", " def execute(self):\n return 'C'", "ClassB");
295
+ assert(replaceResult.success, "ClassName Replace: execute in ClassB");
296
+ assert(replaceResult.newContent.includes("return 'A'"), "ClassName Replace: ClassA execute preserved");
297
+ assert(replaceResult.newContent.includes("return 'C'"), "ClassName Replace: ClassB execute updated");
298
+ assert(!replaceResult.newContent.includes("return 'B'"), "ClassName Replace: ClassB execute old content removed");
299
+ }
300
+ // ─── Diff Engine Tests ──────────────────────────────────────────────
301
+ function testDiffEngine() {
302
+ section("Diff Engine");
303
+ const oldContent = "line1\nline2\nline3\nline4\nline5";
304
+ const newContent = "line1\nline2_modified\nline3\nline4\nline5\nline6_added";
305
+ const diff = generateDiff(oldContent, newContent, "test.txt");
306
+ assert(diff.includes("---"), "Diff: has header");
307
+ assert(diff.includes("+++"), "Diff: has header (new)");
308
+ assert(diff.includes("-line2"), "Diff: shows removal");
309
+ assert(diff.includes("+line2_modified"), "Diff: shows addition");
310
+ assert(diff.includes("+line6_added"), "Diff: shows appended line");
311
+ // No-change diff
312
+ const noDiff = generateDiff("same", "same", "noop.txt");
313
+ assert(noDiff.includes("no changes"), "Diff: no-change case handled");
314
+ }
315
+ // ─── Unsupported Language Tests ─────────────────────────────────────
316
+ function testUnsupported() {
317
+ section("Unsupported Languages (Graceful Failures)");
318
+ const result = replaceSymbol("test.rs", "fn main() {}", "main", "fn main() { println!(\"hi\"); }");
319
+ assert(!result.success, "Unsupported: Rust returns failure");
320
+ assert(result.error?.includes("Unsupported") ?? false, "Unsupported: error message is descriptive");
321
+ }
322
+ // ─── Run All ────────────────────────────────────────────────────────
323
+ async function main() {
324
+ console.log("🔬 Surgical Writing Tools — Smoke Tests\n");
325
+ testTypeScript();
326
+ testPHP();
327
+ testDart();
328
+ testPython();
329
+ testClassName();
330
+ testDiffEngine();
331
+ testUnsupported();
332
+ console.log(`\n${"═".repeat(50)}`);
333
+ console.log(`📊 Results: ${passed} passed, ${failed} failed (${passed + failed} total)`);
334
+ if (failed > 0) {
335
+ console.error(`\n❌ ${failed} test(s) FAILED`);
336
+ process.exit(1);
337
+ }
338
+ else {
339
+ console.log(`\n✅ All tests passed!`);
340
+ }
341
+ }
342
+ main().catch((err) => {
343
+ console.error("Fatal error:", err);
344
+ process.exit(1);
345
+ });
346
+ //# sourceMappingURL=test-write-smoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-write-smoke.js","sourceRoot":"","sources":["../../../tests/writers/test-write-smoke.ts"],"names":[],"mappings":"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"}
package/llms.txt ADDED
@@ -0,0 +1,164 @@
1
+ # mcp-code-context
2
+
3
+ > A Model Context Protocol (MCP) server that compresses any code repository into LLM-ready semantic context and provides surgical code editing tools.
4
+
5
+ ## What This Tool Does
6
+
7
+ This MCP server solves two problems:
8
+ 1. **Token bloat on reads**: When an LLM needs to understand a large codebase, sending raw source files wastes most of the context window. This server extracts only structural signatures.
9
+ 2. **Imprecise writes**: When an LLM needs to edit code, rewriting entire files is error-prone and expensive. This server enables symbol-level surgical edits.
10
+
11
+ ## Available Tools
12
+
13
+ ### Read Tools
14
+
15
+ #### 1. `get_semantic_repo_map`
16
+ **Purpose:** Generate a compressed architectural map of an entire repository.
17
+
18
+ **Input:**
19
+ - `directoryPath` (required): Absolute path to the repository root.
20
+ - `format` (optional): `"xml"` (default) or `"markdown"`.
21
+
22
+ **What it does:**
23
+ - Walks the directory tree respecting `.gitignore` and `.repomixignore` rules.
24
+ - Always excludes `node_modules`, `dist`, `build`, `vendor`, `.git`.
25
+ - For TypeScript/JavaScript: Uses AST parsing (ts-morph) to extract only function signatures, class structures, interfaces, types, and enums.
26
+ - For PHP: Uses AST parsing (php-parser) to extract namespaces, classes, interfaces, traits, enums, methods, properties, and docblocks.
27
+ - For Dart: Uses brace-counting + regex engine to extract classes, mixins, extensions, enums, methods, and fields.
28
+ - For Python: Uses regex-based extraction to capture class/function signatures and docstrings.
29
+ - For other files: Returns content as-is if small, or a truncated preview if large.
30
+
31
+ **Best used when:** You need to understand the architecture of a project before diving into specific files.
32
+
33
+ #### 2. `read_file_surgical`
34
+ **Purpose:** Read a full file or extract only a specific named symbol.
35
+
36
+ **Input:**
37
+ - `filePath` (required): Absolute path to the source file.
38
+ - `symbolName` (optional): Name of a function, class, interface, method, or type to extract.
39
+
40
+ **What it does:**
41
+ - With `symbolName`: Parses the AST and returns only the full source code block for that symbol. Saves tokens when you only need one function from a large file.
42
+ - If missing: Returns structured JSON with `available_symbols` and `suggestions` (e.g., suggesting a `className` scope).
43
+
44
+ **Best used when:** You identified a symbol from the repo map and need to see its full implementation.
45
+
46
+ #### 3. `analyze_impact`
47
+ **Purpose:** Find all files that depend on a given file.
48
+
49
+ **Input:**
50
+ - `filePath` (required): Absolute path to the file being modified.
51
+ - `rootDir` (optional): Repository root. Auto-detected if omitted.
52
+
53
+ **What it does:**
54
+ - Scans all source files for `import`, `require()`, Python `from/import`, PHP `use`/`require_once`/`include`, and Dart `import` statements.
55
+ - Resolves relative paths to determine if they point to the target file.
56
+ - Returns a structured report listing every dependent file and the specific import statement.
57
+
58
+ **Best used when:** You're about to modify a file and need to understand the blast radius.
59
+
60
+ #### 4. `rollback_file`
61
+ **Purpose:** Restores a file to a previous state from the automated backup system.
62
+ **Input:**
63
+ - `filePath` (required): Absolute path.
64
+ - `steps` (optional): Number of versions to go back (1-5, default: 1).
65
+ **What it does:** Reverts the file to the state it was in before the last 1-5 modifications.
66
+
67
+ ### Write Tools (v2.1.3 Mandatory Workflow)
68
+
69
+ All write tools follow a **Two-Phase Workflow**:
70
+ 1. **Phase 1 (Preview)**: Call without a token to get a unified `diff` and a `confirmationToken`.
71
+ 2. **Phase 2 (Apply)**: Call with `confirmationToken` and `confirm: true` to apply the changes.
72
+
73
+ **Important Notes (v2.1.3):**
74
+ - ✅ **Windows CRLF Support**: Fully resolved. All operations work correctly on Windows files with CRLF line endings.
75
+ - ✅ **Parameter Brace Handling**: Methods with braces in parameters (e.g., `{int? cart}`) are now handled correctly.
76
+
77
+ #### 5. `write_file_surgical`
78
+ **Purpose:** Replace the full source code of a named symbol in a file.
79
+
80
+ **Input:**
81
+ - `filePath` (required): Absolute path to the file to modify.
82
+ - `symbolName` (required): Name of the symbol to replace.
83
+ - `newContent` (required): Complete replacement code (signature + body).
84
+ - `confirmationToken` (optional): Token from Phase 1.
85
+ - `confirm` (optional): Set to `true` to apply.
86
+ - `className` (optional): Scope the symbol to a specific class.
87
+
88
+ **What it does:**
89
+ - Locates the symbol via AST parsing (ts-morph, php-parser, brace-counting, or indentation detection).
90
+ - Replaces only that symbol's code, preserving all other file contents.
91
+ - Returns a unified diff showing exactly what changed.
92
+ - Validates the result is syntactically valid before writing.
93
+
94
+ **Best used when:** You need to modify a specific function or method without touching the rest of the file.
95
+
96
+ #### 5. `insert_symbol`
97
+ **Purpose:** Insert new code at a precise location relative to an existing symbol.
98
+
99
+ **Input:**
100
+ - `filePath` (required): Absolute path to the file.
101
+ - `code` (required): The new code to insert.
102
+ - `anchorSymbol` (optional): Symbol name to position relative to. If omitted, inserts at end of file.
103
+ - `position` (optional): `"before"`, `"after"`, `"inside_start"`, `"inside_end"`. Defaults to `"after"`.
104
+ - `confirmationToken`, `confirm` (optional): Standard Phase 2 parameters.
105
+
106
+ **What it does:**
107
+ - Finds the anchor symbol and inserts new code at the specified position.
108
+ - Automatically matches the surrounding indentation style.
109
+ - `inside_start` and `inside_end` insert as members inside a class or interface.
110
+
111
+ **Best used when:** Adding new methods to a class or new functions to a module.
112
+
113
+ #### 6. `rename_symbol`
114
+ **Purpose:** Rename a symbol across an entire repository.
115
+
116
+ **Input:**
117
+ - `filePath` (required): File where the symbol is defined.
118
+ - `oldName` (required): Current name.
119
+ - `newName` (required): New name.
120
+ - `rootDir` (optional): Repository root. Auto-detected if omitted.
121
+ - `confirmationToken`, `confirm` (optional): Standard Phase 2 parameters.
122
+
123
+ **What it does:**
124
+ - Renames the symbol definition in the source file.
125
+ - Finds all dependent files using import analysis.
126
+ - Renames all references in dependent files using whole-word replacement.
127
+ - Returns a multi-file diff showing all changes.
128
+ - Rolls back all changes if any file write fails.
129
+
130
+ **Best used when:** Refactoring a class, function, or method name that is used across multiple files.
131
+
132
+ #### 7. `remove_symbol`
133
+ **Purpose:** Safely remove a symbol from a file.
134
+
135
+ **Input:**
136
+ - `filePath` (required): Absolute path.
137
+ - `symbolName` (required): Symbol to remove.
138
+ - `force` (optional): If true, skip dependency check. Defaults to false.
139
+ - `confirmationToken`, `confirm` (optional): Standard Phase 2 parameters.
140
+
141
+ **What it does:**
142
+ - Checks if other files reference the symbol (unless `force: true`).
143
+ - If dependents exist, refuses to remove and reports which files use it.
144
+ - If safe, removes the symbol's code and cleans up whitespace.
145
+
146
+ **Best used when:** Cleaning up deprecated functions or unused code.
147
+
148
+ ## Recommended Workflow
149
+
150
+ 1. **Start with `get_semantic_repo_map`** to understand the project structure.
151
+ 2. **Use `read_file_surgical`** with a symbol name. Use suggestions if the symbol is missing.
152
+ 3. **Before modifying, run `analyze_impact`** to know the blast radius.
153
+ 4. **Phase 1: Preview Edit** → Call write tools to get a `diff` and `confirmationToken`.
154
+ 5. **Phase 2: Apply Edit** → Verify the diff, then call with the token and `confirm: true`.
155
+ 6. **Recovery** → Use `rollback_file` if needed.
156
+
157
+ ## Technical Details
158
+
159
+ - **Transport:** stdio (JSON-RPC over stdin/stdout)
160
+ - **Runtime:** Node.js >= 18
161
+ - **AST Engines:** ts-morph (TypeScript/JS), php-parser (PHP), brace-counting/regex (Dart, Python)
162
+ - **Ignore Engine:** `ignore` npm package (full .gitignore spec support)
163
+ - **Supported languages:** TypeScript, JavaScript (all variants), PHP, Dart, Python
164
+ - **Safety features:** Mandatory two-phase confirmation, rolling 5-version backups (`.mcp-backups/`), fuzzy symbol suggestions, dependency tracking, surgical restoration.
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "mcp-code-context",
3
+ "version": "2.1.3",
4
+ "description": "Powerful MCP server for LLM-ready semantic code context and surgical AST-aware editing. Supports TypeScript, JavaScript, PHP, Dart, and Python.",
5
+ "type": "module",
6
+ "main": "dist/src/index.js",
7
+ "bin": {
8
+ "mcp-code-context": "dist/src/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/src/index.js",
13
+ "dev": "tsc && node dist/src/index.js",
14
+ "test": "npm run build && node dist/tests/test-dart.js && node dist/tests/test-php.js && node dist/tests/writers/test-write-smoke.js",
15
+ "clean": "rimraf dist",
16
+ "rebuild": "npm run clean && npm run build"
17
+ },
18
+ "keywords": [
19
+ "mcp",
20
+ "model-context-protocol",
21
+ "semantic-compression",
22
+ "llm",
23
+ "code-analysis",
24
+ "ast",
25
+ "repository-map",
26
+ "claude",
27
+ "cursor",
28
+ "windsurf",
29
+ "copilot",
30
+ "amazon-q",
31
+ "code-context",
32
+ "typescript",
33
+ "php",
34
+ "dart",
35
+ "python"
36
+ ],
37
+ "author": "",
38
+ "license": "MIT",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://github.com/achatainga/mcp-code-context.git"
42
+ },
43
+ "dependencies": {
44
+ "@modelcontextprotocol/sdk": "^1.12.0",
45
+ "ignore": "^6.0.2",
46
+ "php-parser": "^3.5.1",
47
+ "ts-morph": "^24.0.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^22.10.0",
51
+ "rimraf": "^6.0.1",
52
+ "typescript": "^5.7.0"
53
+ },
54
+ "engines": {
55
+ "node": ">=18.0.0"
56
+ }
57
+ }