This document describes the internal architecture of RagCode MCP Server after the multi-language restructuring.
RagCode MCP is structured to support multiple programming languages through a pluggable analyzer architecture. The codebase is organized to separate language-agnostic components from language-specific analyzers.
internal/
├── codetypes/ # Universal types and interfaces (language-agnostic)
│ ├── types.go # CodeChunk (canonical), PathAnalyzer (legacy APIChunk/APIAnalyzer kept only for compatibility)
│ └── symbol_schema.go # Symbol schema definitions
│
├── ragcode/ # Core indexing and language management
│ ├── indexer.go # Indexing logic using PathAnalyzer (CodeChunk-only)
│ ├── language_manager.go # Factory for selecting language analyzers (by project type)
│ ├── ragcode_test.go # Integration tests
│ ├── laravel_integration_test.go # Laravel integration tests
│ └── analyzers/ # Language-specific analyzers
│ ├── golang/ # Go language analyzer (fully implemented)
│ │ ├── analyzer.go # PathAnalyzer implementation → CodeChunk
│ │ ├── api_analyzer.go # API documentation analyzer
│ │ ├── types.go # Go-specific types (FunctionInfo, TypeInfo, etc.)
│ │ └── analyzer_test.go # Unit tests
│ ├── php/ # PHP analyzer (including Laravel support)
│ │ ├── analyzer.go # Main PHP analyzer
│ │ ├── api_analyzer.go # PHP API analyzer
│ │ ├── phpdoc.go # PHPDoc parsing
│ │ ├── types.go # PHP-specific types
│ │ └── laravel/ # Laravel-specific analyzers
│ │ ├── analyzer.go # Laravel analyzer coordinator
│ │ ├── eloquent.go # Eloquent model analyzer
│ │ ├── controller.go # Controller analyzer
│ │ ├── routes.go # Route analyzer
│ │ ├── adapter.go # Adapter for integration
│ │ └── ast_helper.go # AST utilities
│ ├── html/ # HTML analyzer
│ │ └── analyzer.go
│ └── python/ # Python analyzer (full implementation)
│ ├── analyzer.go
│ ├── analyzer_test.go
│ ├── api_analyzer.go
│ ├── types.go
│ └── README.md
│
├── workspace/ # Multi-workspace detection and management
│ ├── manager.go # Workspace manager (per-language collections)
│ ├── detector.go # Workspace root detection
│ ├── language_detection.go # Language detection from markers
│ ├── multi_search.go # Cross-workspace search logic
│ ├── cache.go # Workspace cache
│ ├── types.go # Workspace types and structs
│ ├── README.md # Workspace documentation
│ └── *_test.go # Comprehensive test suite (manager_multilang_test.go, etc.)
│
├── tools/ # MCP tool implementations (9 tools)
│ ├── search_local_index.go
│ ├── hybrid_search.go
│ ├── get_function_details.go
│ ├── find_type_definition.go
│ ├── get_code_context.go
│ ├── list_package_exports.go
│ ├── find_implementations.go
│ ├── search_docs.go
│ ├── index_workspace.go # Manual indexing tool
│ ├── workspace_helpers.go # Helper functions for tools
│ ├── utils.go
│ └── *_test.go # Tool tests
│
├── storage/ # Vector database (Qdrant) integration
│ ├── qdrant.go # Qdrant client wrapper
│ ├── qdrant_memory.go # LongTermMemory implementation
│ ├── qdrant_memory_test.go
│ └── (Redis, SQLite configs - optional backends)
│
├── memory/ # Memory management (short-term, long-term)
│ ├── state.go # Memory state interface
│ ├── shortterm.go # Short-term memory implementation
│ ├── longterm.go # Long-term memory interface
│ └── (Storage implementations)
│
├── llm/ # LLM provider (Ollama, HuggingFace, etc.)
│ ├── provider.go # LLM provider interface
│ ├── ollama.go # Ollama implementation
│ └── provider_test.go # Tests
│
├── config/ # Configuration management
│ ├── config.go # Config structs (8 sections: LLM, Storage, etc.)
│ ├── loader.go # YAML + ENV parsing
│ └── config_test.go # Tests
│
├── healthcheck/ # Health check utilities
│ └── healthcheck.go # Dependency checks (Ollama, Qdrant, etc.)
│
├── utils/ # Utility functions
│ └── retry.go # Retry logic
│
└── codetypes/ # (See above)
RagCode MCP supports polyglot workspaces (containing multiple programming languages) by creating separate Qdrant collections per language per workspace. This ensures clean separation of code by language, better search quality, and improved scalability.
Format:
{prefix}-{workspaceID}-{language}
Examples:
ragcode-a1b2c3d4e5f6-go
ragcode-a1b2c3d4e5f6-python
ragcode-a1b2c3d4e5f6-javascript
ragcode-a1b2c3d4e5f6-php
Default Prefix: ragcode (configurable via workspace.collection_prefix in config.yaml)
Language detection uses file markers to identify programming languages present in a workspace:
| Marker File | Detected Language |
|---|---|
go.mod |
go |
package.json |
javascript |
pyproject.toml |
python |
setup.py |
python |
requirements.txt |
python |
composer.json |
php |
Cargo.toml |
rust |
pom.xml |
java |
build.gradle |
java |
Gemfile |
ruby |
Package.swift |
swift |
.git |
workspace root |
Consider a monorepo with multiple languages:
myproject/
├── .git
├── go.mod # Triggers Go detection
├── main.go # → Indexed into ragcode-xxx-go
├── api_server.go
├── scripts/
│ ├── pyproject.toml # Triggers Python detection
│ ├── train.py # → Indexed into ragcode-xxx-python
│ └── ml_utils.py
└── web/
├── package.json # Triggers JavaScript detection
├── app.js # → Indexed into ragcode-xxx-javascript
└── utils.ts
Results in 3 collections:
ragcode-{workspaceID}-go - Contains all Go coderagcode-{workspaceID}-python - Contains all Python coderagcode-{workspaceID}-javascript - Contains all JavaScript/TypeScript codeWhen indexing a workspace:
{prefix}-{workspaceID}-{language}**/*.go, **/*.py, etc.)Language field set to the language identifierFile Filtering Examples:
| Language | Include Patterns | Exclude Patterns |
|---|---|---|
| Go | **/*.go |
**/*_test.go, vendor/ |
| Python | **/*.py |
**/__pycache__/, **/.venv/ |
| JavaScript | **/*.js, **/*.ts |
**/node_modules/, **/dist/ |
| PHP | **/*.php |
**/vendor/, **/cache/ |
When a query is received via MCP tools with file context:
file_path){prefix}-{workspaceID}-{language}Example: Query with Go file context
{
"file_path": "/workspace/main.go",
"query": "handler function"
}
→ Automatically searches in ragcode-{workspaceID}-go
For semantic searches across all code:
Example: Semantic search without file context
{
"query": "authentication middleware",
"workspace_id": "backend"
}
→ Searches in:
ragcode-backend-goragcode-backend-pythonragcode-backend-javascript
→ Returns combined results with language labelsThe Workspace.Info struct tracks detected languages:
type Info struct {
Root string `json:"root"`
ID string `json:"id"`
ProjectType string `json:"project_type,omitempty"`
Languages []string `json:"languages,omitempty"` // Detected languages
Markers []string `json:"markers,omitempty"` // Detection markers found
DetectedAt time.Time `json:"detected_at,omitempty"`
CollectionPrefix string `json:"collection_prefix,omitempty"`
}
// CollectionNameForLanguage returns the collection name for a specific language
func (w *Info) CollectionNameForLanguage(language string) string {
return w.CollectionPrefix + "-" + w.ID + "-" + language
}
Legacy Format (Deprecated):
ragcode-{workspaceID} → [Mixed Go + Python + JavaScript code]
New Format:
ragcode-{workspaceID}-go → [Go code only]
ragcode-{workspaceID}-python → [Python code only]
ragcode-{workspaceID}-javascript → [JavaScript code only]
To migrate:
ragcode-{workspaceID}CollectionNameForLanguage(language) instead of single collectioninternal/codetypes)Purpose: Define language-agnostic types and interfaces used across all analyzers.
Key Types:
CodeChunk - Represents a code symbol (function, method, type, etc.)APIChunk - Represents API documentation for a symbolPathAnalyzer - Interface for code analysisAPIAnalyzer - Interface for API documentation extractionDesign Principle: These types are enhanced with LSP-inspired fields (Language, URI, SelectionRange, Detail, AccessModifier, Tags, Children) to support rich code navigation.
internal/ragcode/language_manager.go)Purpose: Factory pattern for selecting the appropriate analyzer based on project type or language.
Key Functions:
func (m *AnalyzerManager) CodeAnalyzerForProjectType(projectType string) codetypes.PathAnalyzer
func (m *AnalyzerManager) APIAnalyzerForProjectType(projectType string) codetypes.APIAnalyzer
Supported Languages:
LanguageGo (Go) - fully implementedLanguagePHP (PHP) - fully implemented with Laravel supportLanguagePython (Python) - fully implemented with classes, decorators, type hints, mixins, metaclassesLanguageHTML (HTML) - basic supportinternal/workspace/manager.go)Purpose: Core component for multi-workspace and multi-language support. Manages automatic workspace detection, per-language collections, and multi-workspace indexing.
Key Capabilities:
.git, go.mod, package.json, etc.){prefix}-{workspaceID}-{language}Key Methods:
func (m *Manager) GetMemoryForWorkspaceLanguage(workspaceID, language string) (memory.LongTermMemory, error)
func (m *Manager) DetectWorkspace(params map[string]interface{}) (*Info, error)
func (m *Manager) GetAllWorkspaces() []Info
Example: For a monorepo with Go + Python code:
├── backend/ → workspace "backend"
│ ├── .git/
│ ├── go.mod → language: "go"
│ └── Collections: ragcode-backend-go
├── frontend/ → workspace "frontend"
│ ├── package.json → language: "javascript"
│ └── Collections: ragcode-frontend-javascript
└── scripts/ → workspace "scripts"
├── requirements.txt → language: "python"
└── Collections: ragcode-scripts-python
internal/workspace/detector.go)Purpose: Detects workspace roots from file paths and manages workspace information caching.
Key Features:
internal/workspace/language_detection.go)Purpose: Identifies programming language from workspace detection markers.
Supported Languages (11+):
go.modpackage.jsonpyproject.toml, setup.py, requirements.txtCargo.tomlcomposer.jsonpom.xml, build.gradleGemfilePackage.swift*.csproj.git alone indicates workspace rootinternal/ragcode/indexer.go)Purpose: Indexes code chunks into vector database using embeddings.
Dependencies:
codetypes.PathAnalyzer or codetypes.APIAnalyzerllm.Provider for embeddingsmemory.LongTermMemory (Qdrant)Workflow:
paths → analyzer.AnalyzePaths() → []CodeChunk → embeddings → Qdrant
internal/ragcode/analyzers/golang)Purpose: Implements PathAnalyzer and APIAnalyzer for Go language using go/ast, go/doc, and go/parser.
Components:
analyzer.go - Implements AnalyzePaths() for code chunk extractionapi_analyzer.go - Implements AnalyzeAPIPaths() for API documentationtypes.go - Go-specific internal types (PackageInfo, FunctionInfo, TypeInfo, etc.)Key Features:
Language: "go" for all chunksTest Coverage: 82.1% (13 unit tests)
internal/storage)Purpose: Vector database integration for storing and retrieving embeddings.
Components:
qdrant.go - Qdrant client wrapper with collection managementqdrant_memory.go - LongTermMemory implementation using QdrantFeatures:
internal/tools)Purpose: Implements semantic code navigation and search tools for IDE integration.
Tools:
search_local_index.go - Semantic search across indexed codebasehybrid_search.go - Combined semantic + lexical searchget_function_details.go - Retrieve function signatures and documentationfind_type_definition.go - Locate type and interface definitionsget_code_context.go - Direct file access without indexinglist_package_exports.go - List exported symbolsfind_implementations.go - Find interface implementationssearch_docs.go - Search markdown documentationAll tools support:
To add support for a new language (e.g., PHP, Python):
mkdir -p internal/ragcode/analyzers/<language>
Create analyzer.go:
package <language>
import "github.com/doITmagic/rag-code-mcp/internal/codetypes"
type CodeAnalyzer struct {
// language-specific fields
}
func NewCodeAnalyzer() *CodeAnalyzer {
return &CodeAnalyzer{}
}
func (ca *CodeAnalyzer) AnalyzePaths(paths []string) ([]codetypes.CodeChunk, error) {
// Parse files and extract symbols
// Set Language field to appropriate value (e.g., "php", "python")
// Return chunks
}
Create api_analyzer.go:
package <language>
import "github.com/doITmagic/rag-code-mcp/internal/codetypes"
type APIAnalyzerImpl struct {
analyzer *CodeAnalyzer
}
func NewAPIAnalyzer(analyzer *CodeAnalyzer) *APIAnalyzerImpl {
return &APIAnalyzerImpl{analyzer: analyzer}
}
func (a *APIAnalyzerImpl) AnalyzeAPIPaths(paths []string) ([]codetypes.APIChunk, error) {
// Extract API documentation
// Set Language field
// Return API chunks
}
Update internal/ragcode/language_manager.go:
import "github.com/doITmagic/rag-code-mcp/internal/ragcode/analyzers/<language>"
const (
Language<Name> Language = "<language>"
)
func (m *AnalyzerManager) CodeAnalyzerForProjectType(projectType string) codetypes.PathAnalyzer {
lang := normalizeProjectType(projectType)
switch lang {
case Language<Name>:
return <language>.NewCodeAnalyzer()
// ...
}
}
Create analyzer_test.go and api_analyzer_test.go following the pattern in golang/ tests.
Update this file and main README.md to list the new language as supported.
codetypes PackageRationale: Prevents import cycles. Analyzers import codetypes, not ragcode.
Benefits:
golang → codetypes, ragcode → codetypes, ragcode → golangRationale: Support multi-language workspaces and language-specific queries.
Implementation: Each analyzer must set Language field (e.g., “go”, “php”, “python”) in all returned chunks.
Rationale: Enable rich IDE-like features (navigation, hover, completion).
Fields Added:
URI - Full document URI for protocol complianceSelectionRange - Precise symbol name location for “Go to Definition”Detail - Short description for hover tooltipsAccessModifier - public/private/protected for filteringTags - deprecated/experimental/internal for UI badgesChildren - Nested symbols for hierarchy displayRationale: Single point of entry for analyzer selection, easy to extend.
Benefits:
workspace:
enabled: true # Enable multi-workspace mode
auto_index: true # Auto-index detected workspaces
collection_prefix: ragcode # Collection naming prefix
# Language detection markers - file presence indicates language
detection_markers:
- .git # Generic workspace root
- go.mod # Go projects
- package.json # JavaScript/Node.js
- pyproject.toml # Python (modern)
- setup.py # Python (legacy)
- requirements.txt # Python (pip)
- composer.json # PHP
- Cargo.toml # Rust
- pom.xml # Java (Maven)
- build.gradle # Java (Gradle)
- Gemfile # Ruby
- Package.swift # Swift
For advanced users (not recommended for typical use):
WORKSPACE_ENABLED - Enable/disable multi-workspace mode (default: true)WORKSPACE_AUTO_INDEX - Auto-index detected workspaces (default: true)WORKSPACE_COLLECTION_PREFIX - Collection naming prefix (default: “ragcode”)WORKSPACE_MAX_WORKSPACES - Maximum concurrent workspaces to index (default: 10)Note: These variables are auto-managed by the system. Use defaults unless you have specific requirements.
Multi-Language Support: ✅ Fully implemented architecture
Multi-Workspace Support: ✅ Fully implemented
MCP Tools: ✅ 8 tools fully implemented
The PHP analyzer provides comprehensive support for PHP 8.0+ codebases with advanced Laravel framework integration.
php/)Features:
Test Coverage: 83.6% (19 unit tests)
php/laravel/)Architecture:
php/laravel/
├── types.go # Laravel-specific types
├── analyzer.go # Main coordinator
├── eloquent.go # Eloquent model analyzer
├── controller.go # Controller analyzer
├── ast_helper.go # AST extraction utilities
├── *_test.go # Comprehensive test suite
└── README.md # Documentation
Features:
1. Eloquent Model Analysis:
Illuminate\Database\Eloquent\Model)$table, $primaryKey, $fillable, $guarded, $casts, $hidden, $visible, $appendsSoftDeletes, HasFactory, custom traitshasMany, hasOne, belongsTo, belongsToMany, morphMany, etc.scopeActive, scopePublished, etc.getFullNameAttribute, setPasswordAttributePost::class syntax)2. Controller Analysis:
App\Http\Controllers\Api)$ prefix normalization)3. AST Helpers:
$ prefix trimmingClass::class constant fetch supportLaravel Detection: The system automatically detects Laravel projects by checking for:
App\Models, App\Http\ControllersModel, ControllerIlluminate\ framework classesTest Coverage:
Example Output:
// EloquentModel
{
ClassName: "User",
Namespace: "App\\Models",
Table: "users",
Fillable: ["name", "email", "password"],
SoftDeletes: true,
Relations: [
{Name: "posts", Type: "hasMany", RelatedModel: "Post"},
{Name: "profile", Type: "hasOne", RelatedModel: "Profile"}
],
Scopes: [{Name: "active", MethodName: "scopeActive"}],
Attributes: [{Name: "full_name", MethodName: "getFullNameAttribute"}]
}
// Controller
{
ClassName: "PostController",
Namespace: "App\\Http\\Controllers",
IsResource: true,
IsApi: false,
Actions: [
{Name: "index", HttpMethods: ["GET"]},
{Name: "store", HttpMethods: ["POST"], Parameters: ["request"]},
{Name: "destroy", HttpMethods: ["DELETE"], Parameters: ["post"]}
]
}
Usage:
// Detect Laravel project
analyzer := php.NewCodeAnalyzer()
analyzer.AnalyzeFile("app/Models/User.php")
if analyzer.IsLaravelProject() {
// Get packages and analyze with Laravel
packages := analyzer.GetPackages()
laravelAnalyzer := laravel.NewAnalyzer(packages[0])
info := laravelAnalyzer.Analyze()
// info.Models contains Eloquent models
// info.Controllers contains controllers
}
When contributing code:
PathAnalyzer and APIAnalyzer for new languagesLanguage field correctly in all chunkscodetypes for shared types, not package-local definitions