This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Build all modules
./gradlew buildAll
# Build specific module
./gradlew :dmtools-core:shadowJar # Core library (creates fatJAR)
./gradlew :dmtools-server:bootJar # Spring Boot server
./gradlew :dmtools-automation:shadowJar # Automation module
# Clean all
./gradlew cleanAll# Build and install to ~/.dmtools/dmtools.jar in one command
./buildInstallLocal.sh
# This script does:
# 1. Builds the fat JAR (./gradlew :dmtools-core:shadowJar)
# 2. Reads version from gradle.properties
# 3. Copies build/libs/dmtools-v{version}-all.jar to ~/.dmtools/dmtools.jar
# 4. After this, ./dmtools.sh will use your locally built version
# Manual alternative:
./gradlew :dmtools-core:shadowJar
cp build/libs/dmtools-v*-all.jar ~/.dmtools/dmtools.jar# RECOMMENDED: Run unit tests only (fast, no external API calls)
./gradlew :dmtools-core:test
# Run all unit tests across modules
./gradlew testAll
# Run specific test
./gradlew :dmtools-core:test --tests "ClassName.methodName"
# ⚠️ AVOID: Integration tests (make real API calls, require credentials)
# ./gradlew :dmtools-core:integrationTest
# Only run integration tests when explicitly needed for API validationImportant: Integration tests are intentionally excluded from normal builds and CI:
- They make real API calls to Jira, Confluence, GitHub, etc.
- They require valid credentials in environment variables
- They are slow and can hit API rate limits
- Use unit tests for development and regular testing
# CLI (after building or installing)
./dmtools.sh <command> [args]
./dmtools.sh list # List all MCP tools
./dmtools.sh jira_get_ticket KEY-123 # Execute MCP tool
./dmtools.sh --help # Show help
# With debug output
./dmtools.sh --debug <command> [args]
# Server (Spring Boot)
./gradlew :dmtools-server:bootRun
# Or after building:
java -jar dmtools-appengine.jar- dmtools-core: Core library with Job system, MCP tools, integrations, AI providers
- dmtools-server: Spring Boot REST API with OAuth2, JPA persistence, multi-tenancy
- dmtools-automation: Browser/mobile test automation (Selenium, Playwright, Appium)
- dmtools-mcp-annotations: SOURCE retention annotations for MCP tool generation
- dmtools-annotation-processor: Compile-time code generator for MCP infrastructure
- CLI (Jobs):
JobRunner.main()- Execute 20+ jobs from command line - MCP CLI:
McpCliHandler.processMcpCommand()- Execute 67 MCP tools - REST API:
DmToolsServerApplication.main()- Web service with OAuth2 - Job Factory:
JobRunner.createJobInstance()- Thread-safe job instantiation
- Interface:
Job<Params, Result>- Generic job contract - Base:
AbstractJob<Params, Result>- Thread-local context support - Runner:
JobRunner- Factory-based instantiation, prevents race conditions - Context:
JobContext- Thread-local configuration and attributes - 20+ specialized jobs: BA (RequirementsCollector, UserStoryGenerator), Dev (CodeGenerator compatibility shim, UnitTestsGenerator), QA (TestCasesGenerator), Reporting (DevProductivityReport)
Three-component architecture:
- Annotations (
dmtools-mcp-annotations):@MCPTool,@MCPParamwith SOURCE retention - Annotation Processor (
dmtools-annotation-processor): GeneratesMCPToolRegistry,MCPSchemaGenerator,MCPToolExecutorat compile time intobuild/generated/sources/ - CLI Handler (
McpCliHandler): Executes tools viamcp <tool_name> [args]
67+ Built-in MCP Tools: Jira (35+), Confluence (13+), ADO (23+), Figma (12+), Teams (29+), AI (10+), File (4), CLI (1)
Tool invocation supports: JSON via --data, stdin via --stdin-data, positional args, key=value pairs
JavaScript Access: All MCP tools are available as direct function calls in JS agents (via GraalJS)
Complete reference: docs/README-MCP.md
- Interface:
AI.java-chat(model, message), supports multi-turn conversations - Providers: OpenAI, Gemini, Claude, DIAL, Bedrock (AWS), Anthropic, Ollama
- Configuration: Runtime provider selection via env vars (OPENAI_API_KEY, GEMINI_API_KEY, DIAL_API_KEY, ANTHROPIC_API_KEY)
- Observer:
ConversationObserverpattern for monitoring - Token Counter:
Claude35TokenCounterfor context management
- Interface:
TrackerClient<T extends ITicket>- Generic abstraction for issue tracking - Implementations: Jira (
BasicJiraClient), Confluence, GitHub, GitLab, Bitbucket, Figma, Teams, SharePoint - Factory pattern for client instantiation
- Framework: Dagger 2
- 46+ Components:
AIComponentsModule,ConfigurationModule,TrackerModule,SourceCodeModule, agent-specific components - Scopes: Singleton for most clients
- Configuration-driven provider selection
Jobs use JobContext with thread-local storage for isolated configuration:
JobContext.withContext(context, () -> {
// Job execution with isolated config
});This enables parallel execution with different configurations without cross-thread contamination.
com.github.istin.dmtools/
├── ai/ # AI integrations (AI interface, providers, JAssistant)
├── mcp/ # Model Context Protocol (CLI handler, generated code)
├── job/ # Job execution system (Job, AbstractJob, JobRunner)
├── common/ # Core abstractions (TrackerClient, config, utils)
├── atlassian/ # Jira, Confluence, Bitbucket
├── github/ # GitHub integration
├── gitlab/ # GitLab integration
├── figma/ # Figma design system
├── microsoft/ # Teams, SharePoint
├── di/ # Dagger dependency injection (46+ components)
├── ba/ # Business Analysis jobs
├── qa/ # QA jobs (TestCasesGenerator)
├── dev/ # Development jobs (CodeGenerator compatibility shim, UnitTestsGenerator)
├── report/ # Productivity reporting
├── documentation/ # Documentation generation
├── diagram/ # Mermaid diagram generation
├── sync/ # Source code sync jobs
├── context/ # Context management
├── kb/ # Knowledge base processing
├── js/ # JavaScript execution (GraalVM)
└── teammate/ # AI teammate workflows
Configuration sources (precedence order):
- Environment variables
dmtools.envfile (current directory or script directory)dmtools-local.envfileapplication.properties(server)
Key variables:
# Jira
JIRA_BASE_PATH=https://your-company.atlassian.net
JIRA_LOGIN_PASS_TOKEN=base64(email:token)
JIRA_AUTH_TYPE=Bearer
# AI Providers
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4-turbo
OPENAI_BASE_PATH=https://api.openai.com/v1/chat/completions # Optional
OPENAI_MAX_TOKENS=4096 # Optional, default: 4096
OPENAI_TEMPERATURE=0.7 # Optional, default: -1 (don't send, use model default)
# Set to -1 or negative to skip sending temperature parameter
# Some models (o1, o3) don't support custom temperature
OPENAI_MAX_TOKENS_PARAM_NAME=max_completion_tokens # Optional, default: "max_completion_tokens"
# Use "max_tokens" for older models (gpt-3.5-turbo)
# Use empty string to skip sending this parameter
# Gemini - API Key Mode (Public API)
GEMINI_API_KEY=...
GEMINI_MODEL=gemini-2.0-flash-exp # Optional, can also use GEMINI_DEFAULT_MODEL
# Gemini - Vertex AI Mode (Google Cloud Service Account)
GEMINI_VERTEX_ENABLED=true
GEMINI_VERTEX_PROJECT_ID=my-gcp-project
GEMINI_VERTEX_LOCATION=europe-west4 # or us-central1, asia-northeast1, global, etc.
GEMINI_VERTEX_API_VERSION=v1beta1 # Optional: "v1" (default) or "v1beta1" (required for global location)
GEMINI_VERTEX_CREDENTIALS_PATH=/path/to/service-account.json # OR use inline JSON
GEMINI_VERTEX_CREDENTIALS_JSON={"type":"service_account",...} # Alternative to file path
GEMINI_MODEL=gemini-2.5-flash-lite # Model to use
DIAL_API_KEY=...
DIAL_MODEL=gpt-4
ANTHROPIC_API_KEY=...
ANTHROPIC_MODEL=claude-3-5-sonnet-20241022
# GitHub/GitLab
SOURCE_GITHUB_TOKEN=...
GITLAB_TOKEN=...
# TestRail
TESTRAIL_BASE_PATH=https://your-company.testrail.com
TESTRAIL_USERNAME=your-email@example.com
TESTRAIL_API_KEY=your_api_key_from_my_settings
TESTRAIL_PROJECT=My Project # Default project name (optional)
TESTRAIL_LOGGING_ENABLED=true # Enable debug logging (optional, default: false)
# Context Limits
PROMPT_CHUNK_TOKEN_LIMIT=4000
PROMPT_CHUNK_MAX_SINGLE_FILE_SIZE_MB=4- Always use package imports instead of fully qualified class names
- Never write full package paths unless there's a naming conflict
- Use import statements at the top of the file
- Examples:
- ✅ Good:
import com.github.istin.dmtools.ai.ollama.OllamaAIClient;then useOllamaAIClient - ❌ Bad:
new com.github.istin.dmtools.ai.ollama.OllamaAIClient(...) - ✅ Good (when conflict exists):
new java.util.Date()vsnew java.sql.Date()
- ✅ Good:
- Always respond in English. No comments in code in Russian.
- Don't write documentation unless it's asked for.
- Prefer clean, readable code with proper imports over verbose fully qualified names.
CRITICAL: All code MUST be testable and tested before completing work.
- Use Dependency Injection: Constructor injection (Dagger 2) for all external dependencies
- Avoid static methods: Use instance methods to enable mocking
- Separate concerns: Business logic should be independent of framework code
- Interface over implementation: Program to interfaces for easy mocking
Example - Testable Design:
// ✅ GOOD: Testable with dependency injection
public class TestCaseProcessor {
private final TrackerClient jiraClient;
private final AI aiClient;
@Inject
public TestCaseProcessor(TrackerClient jiraClient, AI aiClient) {
this.jiraClient = jiraClient;
this.aiClient = aiClient;
}
public List<TestCase> processTicket(String ticketKey) {
// Can be easily tested with mocks
}
}
// ❌ BAD: Hard to test
public class TestCaseProcessor {
public List<TestCase> processTicket(String ticketKey) {
BasicJiraClient client = new BasicJiraClient(); // Hard-coded dependency
// Cannot mock external calls
}
}Always mock:
- API clients (Jira, Confluence, GitHub, AI providers)
- File system operations
- Database connections
- Network calls
- Time-dependent operations
Mocking Framework: Mockito (already configured)
Example - Mocking in Tests:
import static org.mockito.Mockito.*;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class TestCaseProcessorTest {
@Mock
private TrackerClient mockJiraClient;
@Mock
private AI mockAiClient;
private TestCaseProcessor processor;
@BeforeEach
void setUp() {
processor = new TestCaseProcessor(mockJiraClient, mockAiClient);
}
@Test
void shouldProcessTicketSuccessfully() {
// Given
String ticketKey = "PROJ-123";
when(mockJiraClient.performTicket(ticketKey))
.thenReturn(createMockTicket());
// When
List<TestCase> result = processor.processTicket(ticketKey);
// Then
assertNotNull(result);
assertEquals(3, result.size());
verify(mockJiraClient).performTicket(ticketKey);
}
}Before finishing any development work, you MUST:
- Write unit tests for new functionality
- Run tests locally:
./gradlew :dmtools-core:test - Verify all tests pass: Check test output for failures
- Achieve meaningful coverage: Test happy path + error cases
- Do NOT use integration tests for regular development (they hit real APIs)
Test Coverage Guidelines:
- ✅ Test: Business logic, data transformations, validation rules
- ✅ Test: Edge cases, null handling, error conditions
- ✅ Mock: External API calls, file I/O, network operations
- ❌ Don't test: Simple getters/setters, framework code
Example Development Flow:
# 1. Write code
# 2. Write unit tests
# 3. Run tests
./gradlew :dmtools-core:test --tests "TestCaseProcessorTest"
# 4. Check results
# BUILD SUCCESSFUL means tests passed
# 5. Only then complete the taskIf tests fail: Fix the code or tests, never skip this step.
The generated MCPToolExecutor can only convert CLI String input to a limited set of types. Only use these parameter types in @MCPTool-annotated methods:
| ✅ Allowed | ❌ Not Allowed |
|---|---|
String |
boolean / Boolean |
Integer / int |
Calendar / Date |
Long / long |
Complex objects |
String[] |
Enums |
If the underlying method uses incompatible types (e.g., boolean checkAllRequests, Calendar startDate), create a simple MCP-specific wrapper method:
// ❌ BAD: boolean and Calendar cannot be converted from CLI String
@MCPTool(name = "my_tool", ...)
public List<Item> complexMethod(String workspace, boolean paginate, Calendar since) { ... }
// ✅ GOOD: Create a wrapper with String-only params, call the real method with defaults
@MCPTool(name = "my_tool", ...)
public List<Item> myToolMCP(
@MCPParam(name = "workspace", ...) String workspace) throws IOException {
return complexMethod(workspace, false, null); // Apply sensible defaults
}- Create method in appropriate client class (e.g.,
BasicJiraClient,BasicConfluence) - Annotate with
@MCPTool(name, description, integration, category) - Annotate parameters with
@MCPParam(name, description, required, example) - Ensure all parameters are String/Integer/Long/String[] only (see type rules above)
- Build project to trigger annotation processor:
./gradlew :dmtools-core:compileJava - Generated code appears in
dmtools-core/build/generated/sources/annotationProcessor/java/main - Write unit tests for the new tool with mocks (MANDATORY)
- Update documentation in
docs/README-MCP.md:- Add tool to the appropriate category table (Jira, Confluence, etc.)
- Include tool name, parameters, and clear description
- Follow existing format in the file
- Update tool count if adding to new category
- Verify tool is available:
- CLI:
./dmtools.sh list(should show new tool) - CLI execution:
./dmtools.sh <tool_name> <args> - JavaScript agents:
tool_name()function (via GraalJS)
- CLI:
Complete reference: docs/README-MCP.md
Example Documentation Entry:
| Tool | Parameters | Description |
|------|------------|-------------|
| `jira_update_labels` | `key`, `labels` | Update labels for a Jira ticket. Labels parameter is comma-separated string. |When exposing a new client class (e.g., GitHub, GitLab) as an MCP integration, follow ALL steps:
- Annotate methods with
@MCPTool/@MCPParam(follow parameter type rules above) - Register client in
McpCliHandler.createClientInstances():try { clients.put("myintegration", MyClient.getInstance()); } catch (IOException e) { logger.warn("Failed to create MyClient: {}", e.getMessage()); }
- Add to
getAvailableIntegrations()inMcpCliHandler:integrations.addAll(Arrays.asList( "jira", "github", "myintegration" // ← add here ));
- Add to
DMTOOLS_INTEGRATIONSindmtools.env:# ⚠️ CRITICAL: If DMTOOLS_INTEGRATIONS is set, it OVERRIDES getAvailableIntegrations() # Any integration NOT listed here will be INVISIBLE to `dmtools list` DMTOOLS_INTEGRATIONS=jira,cli,file,github,myintegration
- Build and install:
./buildInstallLocal.sh - Verify:
./dmtools.sh list myintegrationshould return the tools
- Create class extending
AbstractJob<Params, Result> - Implement
public Result runJob(Params params) - Use
JobContext.current()to access thread-local configuration - Register in
JobRunner.createJobInstance()andJobRunner.getStaticInstances() - Add Dagger component if needed in
com.github.istin.dmtools.di
- Access AI via
AIinterface from JobContext or dependency injection - Provider selected at runtime via configuration
- Use
AI.chat(model, message)orAI.chat(model, Message[])for multi-turn - Token counting via
Claude35TokenCounterfor context management
Important Architecture Principles:
- Jobs are orchestrators - coordinate multiple agents and manage workflow
- Agents are small and focused - each agent performs ONE specific task
- Agents are reusable - can be composed in different jobs
1. Extend AbstractSimpleAgent:
public class TestCaseGeneratorAgent extends AbstractSimpleAgent<TestCaseGeneratorAgent.Params, List<TestCase>> {
public TestCaseGeneratorAgent() {
super("agents/test_case_generator"); // References XML prompt file
DaggerTestCaseGeneratorAgentComponent.create().inject(this);
}
@Override
public List<TestCase> transformAIResponse(Params params, String response) throws Exception {
// Parse AI response and return typed result
JSONArray jsonArray = AIResponseParser.parseResponseAsJSONArray(response);
// ... transform to List<TestCase>
}
}2. Create XML Prompt in dmtools-core/src/main/resources/ftl/prompts/agents/<name>.xml:
<prompt>
<role>
You're a highly skilled software testing engineer specialising in designing tests.
</role>
<instructions>
Your task is to write test cases and follow these rules:
1. Each generated Test Case must include priority from the list: {priorities}
2. Don't create duplicates, check {existing_test_cases}
3. Return only valid JSON format without any additional text or formatting
</instructions>
<input_data>
<story_description>
${global.storyDescription}
</story_description>
<priorities>
${global.priorities}
</priorities>
</input_data>
<formatting>
<rules>
Return results as a JSON array with JSON objects inside.
Each JSON object must include 'priority', 'summary', and 'description'.
</rules>
</formatting>
</prompt>Key Points:
- Prompts MUST be in XML format with clear structure:
<role>,<instructions>,<input_data>,<formatting> - Use FreeMarker templates for dynamic content:
${global.paramName} - Agent prompt path:
agents/<name>maps toftl/prompts/agents/<name>.xml - Keep agents focused - ONE responsibility per agent
3. Create Dagger Component (if needed):
@Component(modules = {ConfigurationModule.class, AIComponentsModule.class})
public interface TestCaseGeneratorAgentComponent {
void inject(TestCaseGeneratorAgent agent);
}JS agents run via GraalJS (polyglot JavaScript execution in JVM) and are used for:
- Preprocessing: Data validation, transformation before AI calls
- Postprocessing: Handling temporary IDs, creating related tickets
- Light orchestration: Coordinating simple workflows
Location: agents/js/*.js
🔌 Full Access to MCP Tools: JavaScript agents have direct access to 67+ MCP tools as functions:
| Category | Example Functions | Total Tools |
|---|---|---|
| Jira | jira_get_ticket(), jira_search_by_jql(), jira_post_comment(), jira_create_ticket_basic() |
35+ |
| Jira Xray | jira_xray_add_test_step(), jira_xray_create_precondition(), jira_xray_get_test_details() |
10+ |
| Confluence | confluence_content_by_title(), confluence_search_content_by_text(), confluence_create_page() |
13+ |
| ADO | ado_get_work_item(), ado_move_to_state(), ado_assign_work_item(), ado_add_comment() |
23+ |
| Figma | figma_get_layers(), figma_get_icons(), figma_download_image_as_file() |
12+ |
| Teams | teams_send_message(), teams_get_messages(), teams_download_file() |
29+ |
| AI | gemini_ai_chat(), anthropic_ai_chat(), ollama_ai_chat(), bedrock_ai_chat() |
10+ |
| File | file_read(), file_write(), file_validate_json() |
4 |
| CLI | cli_execute_command() |
1 |
Complete reference: See docs/README-MCP.md for all 67+ tools with parameters and descriptions.
Example with MCP Tools (agents/js/preprocessXrayTestCases.js):
/**
* Preprocess Xray Test Cases - Handle Preconditions with Temporary IDs
* Uses MCP tools: jira_xray_create_precondition, jira_xray_add_preconditions_to_test
*/
function action(params) {
const newTestCases = params.newTestCases;
const ticket = params.ticket;
const projectCode = ticket.key.split("-")[0];
// Use MCP tool to create precondition
for (const testCase of newTestCases) {
if (testCase.customFields?.preconditions) {
// Create actual precondition in Jira using MCP tool
const precondition = jira_xray_create_precondition(
projectCode,
"Setup database",
"Database must be populated with test data"
);
// Replace temporary ID with real precondition key
testCase.customFields.preconditions = [precondition.key];
}
}
return modifiedTestCases;
}Execution via Job Config (agents/*.json):
{
"name": "TestCasesGenerator",
"params": {
"inputJql": "key in (TP-1309)",
"preprocessJSAction": "agents/js/preprocessXrayTestCases.js"
}
}Run with: ./dmtools.sh run agents/xray_test_cases_generator.json
| Aspect | Agent | Job |
|---|---|---|
| Purpose | Single focused task | Orchestrates multiple agents |
| Size | Small (~100-200 lines) | Can be larger |
| AI Interaction | One prompt, one call | Multiple agent calls |
| Reusability | High - used by multiple jobs | Lower - specific workflow |
| Examples | TestCaseGeneratorAgent, RequestDecompositionAgent | TestCasesGenerator, CodeGenerator compatibility shim |
Example Flow:
Job: TestCasesGenerator
├─ Load story from Jira
├─ Agent: TestCaseGeneratorAgent → Generate test cases
├─ JS: preprocessXrayTestCases.js → Handle preconditions
├─ Create test tickets in Jira
└─ Return result
- Unit tests:
dmtools-core/src/test/java- USE THESE for development - Integration tests:
dmtools-core/src/integrationTest/java- AVOID in normal development - Test framework: JUnit 5 (Jupiter)
- Mocking: Mockito 5.18.0
MANDATORY: Test Before Completing Work:
# Write unit tests for new code
# Run tests to verify functionality
./gradlew :dmtools-core:test
# Or run specific test class
./gradlew :dmtools-core:test --tests "YourTestClass"
# ✅ All tests must pass before completing task
# ❌ Never skip testing - it's a required stepWhat to Test:
- ✅ Business logic: Calculations, transformations, validation
- ✅ Edge cases: Null values, empty collections, boundary conditions
- ✅ Error handling: Exception scenarios, validation failures
- ✅ Mock external calls: Jira, Confluence, AI, file I/O, network
What NOT to Test:
- ❌ Simple getters/setters
- ❌ Framework code (Spring, Dagger)
- ❌ External services (use mocks instead)
Integration Test Warning:
- Integration tests make real API calls to external services (Jira, Confluence, GitHub, etc.)
- They require valid credentials configured in environment variables
- They are intentionally excluded from normal build and CI pipeline
- Only run explicitly when validating actual API integration:
./gradlew :dmtools-core:integrationTest - For regular development, rely on unit tests only
- Core CLI:
build/libs/dmtools-v{version}-all.jar(Main-Class:JobRunner) - Server:
dmtools-appengine.jar(Spring Boot executable) - Automation:
dmtools-automation-v{version}-all.jar - Installation:
curl -fsSL https://github.com/epam/dm.ai/releases/latest/download/install.sh | bash
The dmtools-ai-docs/ directory is the Claude Code skill folder for this project. It contains ALL end-user documentation on how to use DMtools. When adding new integrations, features, or jobs — the corresponding usage documentation MUST be added here.
dmtools-ai-docs/
├── SKILL.md # Main skill entry point for Claude Code
├── references/
│ ├── configuration/
│ │ ├── integrations/ # Per-integration setup guides
│ │ │ ├── jira.md # Jira setup, env vars, examples
│ │ │ ├── ado.md # Azure DevOps setup
│ │ │ └── testrail.md # TestRail setup, env vars, examples
│ │ └── ai-providers/ # AI provider setup guides
│ ├── mcp-tools/ # MCP tool references (one file per integration)
│ │ ├── jira-tools.md # All Jira MCP tools with parameters
│ │ ├── testrail-tools.md # All TestRail MCP tools with parameters
│ │ └── ...
│ ├── test-generation/ # Test case generation guides
│ │ ├── xray-manual.md # Xray integration guide
│ │ └── testrail-manual.md # TestRail integration guide
│ ├── jobs/README.md # Job system reference
│ └── agents/ # Agent development guides
- New integration added? → Add
references/configuration/integrations/<name>.md+references/mcp-tools/<name>-tools.md - New job or generation feature? → Add or update the relevant guide under
references/ - All URLs in docs must be generic — use
yourcompany.atlassian.net,YOUR_SPACE,PAGE_IDplaceholders, never real internal URLs or IDs - Keep docs in sync with code — when MCP tools are added/removed, update the corresponding
*-tools.md
- Job Factory Pattern: Fresh job instances per execution for thread safety
- Thread-Local Context: Isolated configuration per thread/job
- Annotation-Driven Generation: Zero-runtime overhead (SOURCE retention)
- Tracker Abstraction: Generic
TrackerClient<T>for multiple platforms - Multi-Model AI: Runtime provider selection via configuration
- Dagger DI: Modular components with singleton scope
- Agent Architecture: Jobs orchestrate, agents execute (small, focused, reusable)
- XML-Based Prompts: All AI agent prompts in XML format with FreeMarker templates
- GraalJS Integration: JavaScript agents for preprocessing/postprocessing via polyglot execution
Use MCP Tools - Remember that you have a rich set of MCP tools and use them.
MANDATORY: Use Serena MCP for all code analysis and editing operations to achieve maximum token efficiency and precision.
Serena MCP provides symbol-level analysis and editing capabilities that drastically reduce token consumption compared to reading entire files.
Before reading any code file, use get_symbols_overview to understand structure, then find_symbol with targeted queries to read only necessary code sections. Use replace_symbol_body, insert_after_symbol, and insert_before_symbol for precise modifications instead of broad file rewrites. This approach can reduce token usage by 70-90% while improving accuracy and maintaining architectural compliance. Token economy is critical for complex projects - every unnecessary token spent on redundant file reads limits our ability to perform deep analysis and implement comprehensive solutions. NOTE: before using any serena tool you MUST activate it first with serena_activate_project.