Skip to content

Commit 0909c88

Browse files
ctothclaude
andcommitted
feat: Integrate new core library into main MCP server
- Replace old tree-sitter extraction with new core library calls - Maintain FastMCP interface for compatibility with Claude Code - Methods now correctly classified as 'method' with parent relationships - Functions properly classified as 'function' without parents - Verified working: methods show parent=Calculator, functions show parent=None Breaking changes resolved: - Core problem solved: method vs function classification working - MCP server entrypoint: mcp_server_code_extractor.py - Usage: uv run /path/to/mcp_server_code_extractor.py 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
1 parent ffb582c commit 0909c88

File tree

1 file changed

+27
-139
lines changed

1 file changed

+27
-139
lines changed

mcp_server_code_extractor.py

Lines changed: 27 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,20 @@
4444
"""
4545

4646
import os
47+
import sys
4748
from pathlib import Path
4849

50+
# Add current directory to path for local imports
51+
sys.path.insert(0, os.path.dirname(__file__))
52+
53+
try:
54+
from code_extractor import CodeExtractor, create_extractor
55+
from code_extractor.models import SymbolKind
56+
except ImportError as e:
57+
print(f"Error: Code extractor library not found: {e}")
58+
print("Make sure it's installed or run from the correct directory.")
59+
exit(1)
60+
4961
try:
5062
from tree_sitter_languages import get_language, get_parser
5163
except ImportError:
@@ -366,147 +378,23 @@ def get_symbols(file_path: str) -> list:
366378
if not os.path.exists(file_path):
367379
return [{"error": f"File not found: {file_path}"}]
368380

369-
lang_name = get_language_for_file(file_path)
370-
if lang_name == 'text':
371-
return [] # Just return empty for unsupported files
372-
373381
try:
374-
parser = get_parser(lang_name)
375-
376-
with open(file_path, 'rb') as f:
377-
source = f.read()
378-
379-
tree = parser.parse(source)
380-
symbols = []
381-
382-
# Combined function and class types for each language
383-
symbol_types = {
384-
'python': {
385-
'function_definition': 'function',
386-
'async_function_definition': 'function',
387-
'class_definition': 'class',
388-
},
389-
'javascript': {
390-
'function_declaration': 'function',
391-
'function_expression': 'function',
392-
'arrow_function': 'function',
393-
'class_declaration': 'class',
394-
},
395-
'typescript': {
396-
'function_declaration': 'function',
397-
'function_expression': 'function',
398-
'arrow_function': 'function',
399-
'method_definition': 'method',
400-
'class_declaration': 'class',
401-
'interface_declaration': 'interface',
402-
},
403-
'tsx': {
404-
'function_declaration': 'function',
405-
'function_expression': 'function',
406-
'arrow_function': 'function',
407-
'method_definition': 'method',
408-
'class_declaration': 'class',
409-
'interface_declaration': 'interface',
410-
},
411-
'go': {
412-
'function_declaration': 'function',
413-
'method_declaration': 'method',
414-
'type_declaration': 'type',
415-
},
416-
'rust': {
417-
'function_item': 'function',
418-
'struct_item': 'struct',
419-
'enum_item': 'enum',
420-
},
421-
'java': {
422-
'method_declaration': 'method',
423-
'constructor_declaration': 'constructor',
424-
'class_declaration': 'class',
425-
},
426-
'c': {
427-
'function_definition': 'function',
428-
},
429-
'cpp': {
430-
'function_definition': 'function',
431-
'class_specifier': 'class',
432-
},
433-
'c_sharp': {
434-
'method_declaration': 'method',
435-
'constructor_declaration': 'constructor',
436-
'class_declaration': 'class',
437-
},
438-
'ruby': {
439-
'method': 'method',
440-
'singleton_method': 'method',
441-
'class': 'class',
442-
},
443-
'php': {
444-
'function_definition': 'function',
445-
'method_declaration': 'method',
446-
'class_declaration': 'class',
447-
},
448-
'swift': {
449-
'function_declaration': 'function',
450-
'class_declaration': 'class',
451-
},
452-
'kotlin': {
453-
'function_declaration': 'function',
454-
'class_declaration': 'class',
455-
},
456-
'scala': {
457-
'function_definition': 'function',
458-
'class_definition': 'class',
459-
},
460-
}
461-
462-
lang_symbols = symbol_types.get(lang_name, {})
463-
464-
def extract_symbols(node, depth=0):
465-
if node.type in lang_symbols:
466-
# Extract name
467-
name = None
468-
for child in node.children:
469-
if child.type in ['identifier', 'type_identifier', 'property_identifier', 'field_identifier']:
470-
name = source[child.start_byte:child.end_byte].decode(
471-
'utf-8')
472-
break
473-
474-
# Try field-based access as fallback
475-
if not name and hasattr(node, 'child_by_field_name'):
476-
name_node = node.child_by_field_name('name')
477-
if name_node:
478-
name = source[name_node.start_byte:name_node.end_byte].decode(
479-
'utf-8')
480-
481-
if name:
482-
start_line = source[:node.start_byte].count(b'\n') + 1
483-
end_line = source[:node.end_byte].count(b'\n') + 1
484-
485-
# Get first line as preview
486-
first_line = source[node.start_byte:node.end_byte].decode(
487-
'utf-8').split('\n')[0]
488-
if len(first_line) > 80:
489-
first_line = first_line[:77] + "..."
490-
491-
symbols.append({
492-
'name': name,
493-
'type': lang_symbols[node.type],
494-
'start_line': start_line,
495-
'end_line': end_line,
496-
'lines': f"{start_line}-{end_line}",
497-
'preview': first_line
498-
})
499-
500-
# Recurse
501-
for child in node.children:
502-
extract_symbols(child, depth + 1)
503-
504-
extract_symbols(tree.root_node)
505-
return symbols
506-
382+
extractor = create_extractor(file_path)
383+
384+
with open(file_path, 'r', encoding='utf-8') as f:
385+
source_code = f.read()
386+
387+
symbols = extractor.extract_symbols(source_code)
388+
389+
# Convert to dict format for MCP compatibility
390+
result = []
391+
for symbol in symbols:
392+
result.append(symbol.to_dict())
393+
394+
return result
395+
507396
except Exception as e:
508-
import traceback
509-
return [{"error": f"Failed to parse '{file_path}': {e.__class__.__name__}: {e}", "traceback": traceback.format_exc()}]
397+
return [{"error": f"Failed to parse '{file_path}': {str(e)}"}]
510398

511399

512400
@mcp.tool()

0 commit comments

Comments
 (0)