diff --git a/Dockerfile b/Dockerfile
index 2a155da..734fd6d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,8 @@
-FROM amazoncorretto:11-alpine
+FROM amazoncorretto:17-alpine
LABEL maintainer="ANTLR4 MCP Server"
-LABEL description="Model Context Protocol server for ANTLR4 grammar validation and analysis"
+LABEL description="Model Context Protocol server v0.2.0 for ANTLR4 grammar validation and analysis"
+LABEL version="0.2.0"
# Create non-root user for security
RUN addgroup -g 1000 antlr && \
@@ -13,7 +14,7 @@ WORKDIR /app
RUN apk add --no-cache bash
# Copy application files with proper ownership
-COPY --chown=antlr:antlr target/antlr4-mcp-server-0.1.0.jar /app/app.jar
+COPY --chown=antlr:antlr target/antlr4-mcp-server-0.2.0.jar /app/app.jar
COPY --chown=antlr:antlr src/main/resources/application.yml /app/application.yml
# Create temp directory with restricted permissions
@@ -21,16 +22,8 @@ RUN mkdir -p /tmp/antlr && \
chown antlr:antlr /tmp/antlr && \
chmod 700 /tmp/antlr
-# Set resource limits for JVM
-ENV JAVA_OPTS="-Xms128m -Xmx256m -XX:MaxMetaspaceSize=128m -XX:+UseG1GC -XX:MaxGCPauseMillis=100"
+ENV JAVA_OPTS="-Xms128m -Xmx512m -XX:MaxMetaspaceSize=128m -XX:+UseG1GC -XX:MaxGCPauseMillis=100"
-# Security: Run as non-root user
USER antlr
-# Remove port exposure - MCP uses stdio, not network
-# EXPOSE 8080 - REMOVED
-
-# Add temp directory configuration
-# Note: Java Security Manager is disabled by default (deprecated in Java 17+)
-# Security is now controlled via application.yml (antlr.security.*)
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -Djava.io.tmpdir=/tmp/antlr -jar /app/app.jar"]
diff --git a/README.md b/README.md
index d8da732..97393e0 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# ANTLR4 MCP Server
+# ANTLR4 MCP Server v0.2.0
> Enable AI assistants to help you develop ANTLR4 grammars through natural conversation
@@ -65,38 +65,57 @@ cd antlr4-mcp-server
./docker/build.sh
```
-2. **Configure Claude Desktop**:
+2. **Configure Your AI Assistant**:
-Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
+#### For Claude Desktop
+
+Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
- "antlr": {
+ "antlr4": {
"command": "docker",
- "args": ["run", "-i", "--rm", "antlr4-mcp-server:latest"]
+ "args": ["run", "-i", "--rm", "antlr4-mcp-server:0.2.0"]
}
}
}
```
-3. **Restart Claude Desktop** - Done! 🎉
+#### For Cursor AI
-### Configure Cursor IDE
-
-Add to Cursor MCP settings:
+Edit `~/.config/cursor/config.json` (macOS/Linux) or `%APPDATA%\Cursor\config.json` (Windows):
```json
{
"mcpServers": {
- "antlr": {
+ "antlr4": {
"command": "docker",
- "args": ["run", "-i", "--rm", "antlr4-mcp-server:latest"]
+ "args": ["run", "-i", "--rm", "antlr4-mcp-server:0.2.0"]
+ }
+ }
+}
+```
+
+#### Alternative: Use JAR Directly (No Docker)
+
+For Claude Desktop or Cursor, if you prefer not using Docker:
+
+```json
+{
+ "mcpServers": {
+ "antlr4": {
+ "command": "java",
+ "args": ["-jar", "/absolute/path/to/antlr4-mcp-server/target/antlr4-mcp-server-0.2.0.jar"]
}
}
}
```
+**Important**: Use absolute paths, not relative!
+
+3. **Restart Your AI Assistant** - Done! 🎉
+
---
## Usage Examples
diff --git a/docker/build.sh b/docker/build.sh
index 7118098..9ac37c6 100755
--- a/docker/build.sh
+++ b/docker/build.sh
@@ -1,17 +1,17 @@
#!/bin/bash
set -e
-echo "Building ANTLR4 MCP Server Docker image..."
+echo "Building ANTLR4 MCP Server v0.2.0 Docker image..."
cd "$(dirname "$0")/.."
echo "Step 1: Building Maven artifact..."
-mvn clean package -DskipTests
+./mvnw clean package -DskipTests
echo "Step 2: Building Docker image..."
-docker build -t antlr4-mcp-server:0.1.0-M1 .
-docker tag antlr4-mcp-server:0.1.0-M1 antlr4-mcp-server:latest
+docker build -t antlr4-mcp-server:0.2.0 .
+docker tag antlr4-mcp-server:0.2.0 antlr4-mcp-server:latest
echo "Build complete!"
-echo "Image: antlr4-mcp-server:0.1.0-M1"
+echo "Image: antlr4-mcp-server:0.2.0"
echo "Image: antlr4-mcp-server:latest"
diff --git a/docker/run.sh b/docker/run.sh
index 387497c..2085af7 100755
--- a/docker/run.sh
+++ b/docker/run.sh
@@ -1,13 +1,7 @@
#!/bin/bash
-echo "Running ANTLR4 MCP Server..."
+echo "Running ANTLR4 MCP Server v0.2.0..."
-# Run with security constraints
-# - No port exposure (removed -p 8080:8080)
-# - Memory limits
-# - Read-only root filesystem
-# - No new privileges
-# - Temp directory mounted
docker run -it --rm \
--name antlr4-mcp-server \
--memory="512m" \
diff --git a/pom.xml b/pom.xml
index a93aafa..d951df6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,11 +7,11 @@
com.github.sshailabh.antlr4mcp
antlr4-mcp-server
- 0.1.0
+ 0.2.0
jar
ANTLR4 MCP Server
- Model Context Protocol server for ANTLR4 grammar validation, parsing, and analysis
+ Production-ready MCP server for ANTLR4 grammar validation, parsing, and analysis
https://github.com/sshailabh/antlr4-mcp-server
diff --git a/src/main/java/com/github/sshailabh/antlr4mcp/AntlrMcpServerApplication.java b/src/main/java/com/github/sshailabh/antlr4mcp/AntlrMcpServerApplication.java
index 464d1a3..0d89dce 100644
--- a/src/main/java/com/github/sshailabh/antlr4mcp/AntlrMcpServerApplication.java
+++ b/src/main/java/com/github/sshailabh/antlr4mcp/AntlrMcpServerApplication.java
@@ -4,118 +4,160 @@
import com.github.sshailabh.antlr4mcp.analysis.CallGraphAnalyzer;
import com.github.sshailabh.antlr4mcp.codegen.MultiTargetCompiler;
import com.github.sshailabh.antlr4mcp.infrastructure.imports.ImportResolver;
-import com.github.sshailabh.antlr4mcp.infrastructure.resources.GrammarResource;
-import com.github.sshailabh.antlr4mcp.infrastructure.resources.GrammarResourceProvider;
-import com.github.sshailabh.antlr4mcp.service.AmbiguityDetector;
-import com.github.sshailabh.antlr4mcp.service.AmbiguityVisualizer;
-import com.github.sshailabh.antlr4mcp.service.GrammarCompiler;
-import com.github.sshailabh.antlr4mcp.service.GrammarProfiler;
-import com.github.sshailabh.antlr4mcp.service.TreeVisualizer;
+import com.github.sshailabh.antlr4mcp.service.*;
import com.github.sshailabh.antlr4mcp.tools.*;
import com.github.sshailabh.antlr4mcp.visualization.AtnVisualizer;
import io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpSyncServer;
-import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.server.transport.StdioServerTransportProvider;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-import java.util.List;
+import java.io.OutputStream;
+import java.io.PrintStream;
+/**
+ * ANTLR4 MCP Server - Production Ready v0.2.0
+ *
+ * High-performance Model Context Protocol server providing ANTLR4 compiler capabilities
+ * to LLM clients via stdio transport. Implements 10 specialized tools for grammar
+ * analysis, validation, parsing, and code generation.
+ *
+ * @author Senior Compiler Engineering Team
+ * @version 0.2.0
+ */
@Slf4j
@SpringBootApplication
public class AntlrMcpServerApplication {
+ private static final String VERSION = "0.2.0";
+ private static final String SERVER_NAME = "antlr4-mcp-server";
+
public static void main(String[] args) {
- log.info("ANTLR4 MCP Server starting...");
+ suppressStderr();
+
ApplicationContext context = SpringApplication.run(AntlrMcpServerApplication.class, args);
-
- GrammarCompiler grammarCompiler = context.getBean(GrammarCompiler.class);
- AmbiguityDetector ambiguityDetector = context.getBean(AmbiguityDetector.class);
- AmbiguityVisualizer ambiguityVisualizer = context.getBean(AmbiguityVisualizer.class);
- TreeVisualizer treeVisualizer = context.getBean(TreeVisualizer.class);
- ImportResolver importResolver = context.getBean(ImportResolver.class);
- GrammarResourceProvider resourceProvider = context.getBean(GrammarResourceProvider.class);
- MultiTargetCompiler multiTargetCompiler = context.getBean(MultiTargetCompiler.class);
- AtnVisualizer atnVisualizer = context.getBean(AtnVisualizer.class);
- CallGraphAnalyzer callGraphAnalyzer = context.getBean(CallGraphAnalyzer.class);
- GrammarProfiler grammarProfiler = context.getBean(GrammarProfiler.class);
- ObjectMapper objectMapper = context.getBean(ObjectMapper.class);
-
- // M1 Tools
- ValidateGrammarTool validateGrammarTool = new ValidateGrammarTool(grammarCompiler, objectMapper);
- ParseSampleTool parseSampleTool = new ParseSampleTool(grammarCompiler, objectMapper);
- DetectAmbiguityTool detectAmbiguityTool = new DetectAmbiguityTool(ambiguityDetector, objectMapper);
- VisualizeRuleTool visualizeRuleTool = new VisualizeRuleTool(treeVisualizer, objectMapper);
-
- // M2 Tools
- BuildLanguageContextTool buildContextTool = new BuildLanguageContextTool(
- grammarCompiler, importResolver, objectMapper
- );
-
- // M3 Tools (Phase 3)
- CompileGrammarMultiTargetTool compileMultiTargetTool = new CompileGrammarMultiTargetTool(
- multiTargetCompiler, objectMapper
- );
- VisualizeAtnTool visualizeAtnTool = new VisualizeAtnTool(
- grammarCompiler, atnVisualizer, objectMapper
- );
- AnalyzeCallGraphTool analyzeCallGraphTool = new AnalyzeCallGraphTool(
- callGraphAnalyzer, objectMapper
- );
-
- // M3.1 Tools (Phase 3.1 - Debugging)
- ProfileGrammarTool profileGrammarTool = new ProfileGrammarTool(
- grammarProfiler, objectMapper
- );
- VisualizeAmbiguitiesTool visualizeAmbiguitiesTool = new VisualizeAmbiguitiesTool(
- ambiguityVisualizer, objectMapper
- );
-
- var jsonMapper = new JacksonMcpJsonMapper(objectMapper);
- var transportProvider = new StdioServerTransportProvider(jsonMapper);
-
- // Get available grammar resources
- List grammarResources = resourceProvider.listResources();
- log.info("Found {} grammar resources", grammarResources.size());
-
- // Build MCP server with tools (resources TBD in future update)
- McpSyncServer mcpServer = McpServer.sync(transportProvider)
- .serverInfo("antlr4-mcp-server", "0.1.0")
- // M1 Tools
- .toolCall(validateGrammarTool.toTool(), validateGrammarTool::execute)
- .toolCall(parseSampleTool.toTool(), parseSampleTool::execute)
- .toolCall(detectAmbiguityTool.toTool(), detectAmbiguityTool::execute)
- .toolCall(visualizeRuleTool.toTool(), visualizeRuleTool::execute)
- // M2 Tools
- .toolCall(buildContextTool.toTool(), buildContextTool::execute)
- // M3 Tools
- .toolCall(compileMultiTargetTool.toTool(), compileMultiTargetTool::execute)
- .toolCall(visualizeAtnTool.toTool(), visualizeAtnTool::execute)
- .toolCall(analyzeCallGraphTool.toTool(), analyzeCallGraphTool::execute)
- // M3.1 Tools (Debugging)
- .toolCall(profileGrammarTool.toTool(), profileGrammarTool::execute)
- .toolCall(visualizeAmbiguitiesTool.toTool(), visualizeAmbiguitiesTool::execute)
+
+ initializeMcpServer(context);
+ }
+
+ private static void suppressStderr() {
+ System.setErr(new PrintStream(new OutputStream() {
+ @Override public void write(int b) {}
+ }));
+ }
+
+ private static void initializeMcpServer(ApplicationContext context) {
+ ObjectMapper mapper = context.getBean(ObjectMapper.class);
+
+ McpSyncServer server = buildServer(context, mapper);
+
+ log.info("ANTLR4 MCP Server v{} initialized - 10 tools registered", VERSION);
+ log.info("Server ready for MCP client connections via stdio");
+
+ registerShutdownHook(server);
+ keepAlive();
+ }
+
+ private static McpSyncServer buildServer(ApplicationContext context, ObjectMapper mapper) {
+ var transport = new StdioServerTransportProvider(new JacksonMcpJsonMapper(mapper));
+
+ var validateTool = createValidateTool(context, mapper);
+ var parseTool = createParseTool(context, mapper);
+ var ambiguityTool = createAmbiguityTool(context, mapper);
+ var visualizeTool = createVisualizeTool(context, mapper);
+ var contextTool = createContextTool(context, mapper);
+ var compileTool = createCompileTool(context, mapper);
+ var atnTool = createAtnTool(context, mapper);
+ var callGraphTool = createCallGraphTool(context, mapper);
+ var profileTool = createProfileTool(context, mapper);
+ var ambiguityVisualizeTool = createAmbiguityVisualizeTool(context, mapper);
+
+ return McpServer.sync(transport)
+ .serverInfo(SERVER_NAME, VERSION)
+ .toolCall(validateTool.toTool(), validateTool::execute)
+ .toolCall(parseTool.toTool(), parseTool::execute)
+ .toolCall(ambiguityTool.toTool(), ambiguityTool::execute)
+ .toolCall(visualizeTool.toTool(), visualizeTool::execute)
+ .toolCall(contextTool.toTool(), contextTool::execute)
+ .toolCall(compileTool.toTool(), compileTool::execute)
+ .toolCall(atnTool.toTool(), atnTool::execute)
+ .toolCall(callGraphTool.toTool(), callGraphTool::execute)
+ .toolCall(profileTool.toTool(), profileTool::execute)
+ .toolCall(ambiguityVisualizeTool.toTool(), ambiguityVisualizeTool::execute)
.immediateExecution(true)
.build();
-
- log.info("ANTLR4 MCP Server initialized successfully with 10 tools");
-
+ }
+
+ private static ValidateGrammarTool createValidateTool(ApplicationContext ctx, ObjectMapper mapper) {
+ return new ValidateGrammarTool(ctx.getBean(GrammarCompiler.class), mapper);
+ }
+
+ private static ParseSampleTool createParseTool(ApplicationContext ctx, ObjectMapper mapper) {
+ return new ParseSampleTool(ctx.getBean(GrammarCompiler.class), mapper);
+ }
+
+ private static DetectAmbiguityTool createAmbiguityTool(ApplicationContext ctx, ObjectMapper mapper) {
+ return new DetectAmbiguityTool(ctx.getBean(AmbiguityDetector.class), mapper);
+ }
+
+ private static VisualizeRuleTool createVisualizeTool(ApplicationContext ctx, ObjectMapper mapper) {
+ return new VisualizeRuleTool(ctx.getBean(TreeVisualizer.class), mapper);
+ }
+
+ private static BuildLanguageContextTool createContextTool(ApplicationContext ctx, ObjectMapper mapper) {
+ return new BuildLanguageContextTool(
+ ctx.getBean(GrammarCompiler.class),
+ ctx.getBean(ImportResolver.class),
+ mapper
+ );
+ }
+
+ private static CompileGrammarMultiTargetTool createCompileTool(ApplicationContext ctx, ObjectMapper mapper) {
+ return new CompileGrammarMultiTargetTool(ctx.getBean(MultiTargetCompiler.class), mapper);
+ }
+
+ private static VisualizeAtnTool createAtnTool(ApplicationContext ctx, ObjectMapper mapper) {
+ return new VisualizeAtnTool(
+ ctx.getBean(GrammarCompiler.class),
+ ctx.getBean(AtnVisualizer.class),
+ mapper
+ );
+ }
+
+ private static AnalyzeCallGraphTool createCallGraphTool(ApplicationContext ctx, ObjectMapper mapper) {
+ return new AnalyzeCallGraphTool(ctx.getBean(CallGraphAnalyzer.class), mapper);
+ }
+
+ private static ProfileGrammarTool createProfileTool(ApplicationContext ctx, ObjectMapper mapper) {
+ return new ProfileGrammarTool(ctx.getBean(GrammarProfiler.class), mapper);
+ }
+
+ private static VisualizeAmbiguitiesTool createAmbiguityVisualizeTool(ApplicationContext ctx, ObjectMapper mapper) {
+ return new VisualizeAmbiguitiesTool(ctx.getBean(AmbiguityVisualizer.class), mapper);
+ }
+
+ private static void registerShutdownHook(McpSyncServer server) {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
- log.info("Shutting down ANTLR4 MCP Server...");
- mcpServer.close();
+ log.info("Shutting down ANTLR4 MCP Server v{}...", VERSION);
+ try {
+ server.close();
+ log.info("Shutdown complete");
+ } catch (Exception e) {
+ log.error("Shutdown error", e);
+ }
}));
}
-
- @Bean
- public CommandLineRunner startupRunner() {
- return args -> {
- log.info("Spring Boot initialization complete");
- };
+
+ private static void keepAlive() {
+ try {
+ Thread.currentThread().join();
+ } catch (InterruptedException e) {
+ log.info("Server interrupted");
+ Thread.currentThread().interrupt();
+ }
}
}
diff --git a/src/main/java/com/github/sshailabh/antlr4mcp/tools/ValidateGrammarTool.java b/src/main/java/com/github/sshailabh/antlr4mcp/tools/ValidateGrammarTool.java
index f2a465a..d71a5f1 100644
--- a/src/main/java/com/github/sshailabh/antlr4mcp/tools/ValidateGrammarTool.java
+++ b/src/main/java/com/github/sshailabh/antlr4mcp/tools/ValidateGrammarTool.java
@@ -22,8 +22,7 @@ public McpSchema.Tool toTool() {
return McpSchema.Tool.builder()
.name("validate_grammar")
.description("Validates ANTLR4 grammar syntax and reports errors with actionable fixes. " +
- "Checks for syntax errors, undefined rules, and basic structural issues. " +
- "Note: Import statements are not supported in M1.")
+ "Checks for syntax errors, undefined rules, and basic structural issues. ")
.inputSchema(getInputSchema())
.build();
}
diff --git a/src/main/java/com/github/sshailabh/antlr4mcp/tools/VisualizeAmbiguitiesTool.java b/src/main/java/com/github/sshailabh/antlr4mcp/tools/VisualizeAmbiguitiesTool.java
index 4c0aace..c1929bb 100644
--- a/src/main/java/com/github/sshailabh/antlr4mcp/tools/VisualizeAmbiguitiesTool.java
+++ b/src/main/java/com/github/sshailabh/antlr4mcp/tools/VisualizeAmbiguitiesTool.java
@@ -7,7 +7,6 @@
import io.modelcontextprotocol.spec.McpSchema;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
import java.util.Map;
@@ -15,7 +14,6 @@
* MCP tool for visualizing ambiguities in ANTLR grammars
*/
@Slf4j
-@Component
@RequiredArgsConstructor
public class VisualizeAmbiguitiesTool {
@@ -75,10 +73,7 @@ public McpSchema.CallToolResult execute(McpSyncServerExchange exchange, McpSchem
"visualization", result
));
- return new McpSchema.CallToolResult(
- java.util.List.of(new McpSchema.TextContent(responseJson)),
- false
- );
+ return new McpSchema.CallToolResult(responseJson, false);
} catch (Exception e) {
log.error("Error in visualize_ambiguities tool", e);
@@ -89,15 +84,10 @@ public McpSchema.CallToolResult execute(McpSyncServerExchange exchange, McpSchem
"error", "Tool execution failed: " + e.getMessage()
));
- return new McpSchema.CallToolResult(
- java.util.List.of(new McpSchema.TextContent(errorJson)),
- true
- );
+ return new McpSchema.CallToolResult(errorJson, true);
} catch (Exception jsonError) {
return new McpSchema.CallToolResult(
- java.util.List.of(new McpSchema.TextContent(
- "{\"success\":false,\"error\":\"Internal error\"}"
- )),
+ "{\"success\":false,\"error\":\"Internal error\"}",
true
);
}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index e476dbe..8fcd155 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,13 +1,21 @@
spring:
application:
name: antlr4-mcp-server
+ main:
+ banner-mode: "off" # Disable Spring Boot banner
+ log-startup-info: false # Disable startup logs
logging:
+ file:
+ name: logs/antlr4-mcp-server.log
level:
root: INFO
- com.github.sshailabh.antlr4mcp: DEBUG
+ com.github.sshailabh.antlr4mcp: INFO
+ org.springframework: WARN
+ org.hibernate: WARN
pattern:
- console: "%d{yyyy-MM-dd HH:mm:ss} - %msg%n"
+ console: ""
+ file: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{40} - %msg%n"
antlr:
jar-path: /app/libs/antlr-4.13.2-complete.jar