Skip to content

Commit aee46fd

Browse files
committed
Bump versions and fix MCP compatability problems
1 parent fc6bd16 commit aee46fd

8 files changed

Lines changed: 84 additions & 59 deletions

File tree

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ jobs:
160160

161161
# Run Qodana inspections
162162
- name: Qodana - Code Inspection
163-
uses: JetBrains/qodana-action@v2025.1.1
163+
uses: JetBrains/qodana-action@v2025.3.2
164164
with:
165165
cache-default-branch-only: true
166166

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pluginVersion=0.0.4
1010
pluginSinceBuild = 252
1111

1212
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
13-
platformVersion = 2025.2
13+
platformVersion=2025.2.6.1
1414

1515
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
1616
# Example: platformPlugins = com.jetbrains.php:203.4449.22, org.intellij.scala:2023.3.27@EAP

gradle/libs.versions.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ kotlinxSerialization = "1.7.3"
66
opentest4j = "1.3.0"
77

88
# plugins
9-
changelog = "2.4.0"
9+
changelog = "2.5.0"
1010
intelliJPlatform = "2.13.1"
1111
kotlin = "2.3.20"
12-
kover = "0.9.1"
13-
qodana = "2025.1.1"
12+
kover = "0.9.7"
13+
qodana = "2025.3.2"
1414

1515
[libraries]
1616
freemarker = { group = "org.freemarker", name = "freemarker", version.ref = "freemarker" }

qodana.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# https://www.jetbrains.com/help/qodana/qodana-yaml.html
33

44
version: "1.0"
5-
linter: jetbrains/qodana-jvm-community:2024.3
5+
linter: jetbrains/qodana-jvm-community:2025.3
66
projectJDK: "21"
77
profile:
88
name: qodana.recommended
Lines changed: 42 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.github.nonoxys.kmpmodulegenerator.mcp
22

3+
import com.github.nonoxys.kmpmodulegenerator.mcp.models.GenerationResultDTO
4+
import com.github.nonoxys.kmpmodulegenerator.mcp.models.TemplateDTO
5+
import com.github.nonoxys.kmpmodulegenerator.mcp.models.TemplateVariableDTO
36
import com.github.nonoxys.kmpmodulegenerator.models.GenerationResult
47
import com.github.nonoxys.kmpmodulegenerator.models.VariableType
58
import com.github.nonoxys.kmpmodulegenerator.services.ModuleGeneratorService
@@ -8,31 +11,33 @@ import com.intellij.mcpserver.McpExpectedError
811
import com.intellij.mcpserver.McpToolset
912
import com.intellij.mcpserver.annotations.McpDescription
1013
import com.intellij.mcpserver.annotations.McpTool
11-
import com.intellij.mcpserver.project
12-
import com.intellij.openapi.application.ApplicationManager
14+
import com.intellij.mcpserver.mcpFail
15+
import com.intellij.openapi.application.writeAction
16+
import com.intellij.openapi.project.Project
1317
import kotlinx.coroutines.currentCoroutineContext
14-
import kotlinx.serialization.Serializable
1518
import kotlinx.serialization.json.Json
19+
import kotlin.coroutines.CoroutineContext
1620

21+
@Suppress("UnstableApiUsage")
1722
class KmpMcpToolset : McpToolset {
1823

1924
@McpTool(name = "kmp_list_templates")
2025
@McpDescription("List all available KMP module templates with their variables. Use this before calling kmp_generate_module to discover templateId values and required variables.")
21-
suspend fun listTemplates(): List<TemplateDto> {
22-
val project = currentCoroutineContext().project
26+
suspend fun listTemplates(): List<TemplateDTO> {
27+
val project = resolveProject(context = currentCoroutineContext()) ?: mcpFail("No project found")
2328
val templates = TemplateService.getInstance(project).getAllTemplates()
2429

2530
if (templates.isEmpty()) {
2631
throw McpExpectedError("No templates found. Create templates in .idea/kmp-templates/ or configure a custom path in Settings > KMP Module Templates.")
2732
}
2833

2934
return templates.map { template ->
30-
TemplateDto(
35+
TemplateDTO(
3136
id = template.id,
3237
name = template.name,
3338
description = template.description,
3439
variables = template.variables.map { v ->
35-
TemplateVariableDto(
40+
TemplateVariableDTO(
3641
name = v.name,
3742
displayName = v.displayName,
3843
description = v.description,
@@ -52,16 +57,16 @@ class KmpMcpToolset : McpToolset {
5257
@McpDescription("Template ID from kmp_list_templates") templateId: String,
5358
@McpDescription("Absolute filesystem path where the module will be created") targetPath: String,
5459
@McpDescription("JSON object with variable values, e.g. {\"key\": \"value\"}") variables: String = "{}",
55-
): GenerationResultDto {
56-
val project = currentCoroutineContext().project
60+
): GenerationResultDTO {
61+
val project = resolveProject(context = currentCoroutineContext()) ?: mcpFail("No project found")
5762
val templateService = TemplateService.getInstance(project)
5863
val generatorService = ModuleGeneratorService.getInstance(project)
5964

6065
val template = templateService.getTemplate(templateId)
6166
?: throw McpExpectedError("Template '$templateId' not found. Use kmp_list_templates to see available templates.")
6267

6368
val variablesMap = try {
64-
if (variables.isBlank() || variables == "{}") emptyMap()
69+
if (variables.isBlank()) emptyMap()
6570
else Json.decodeFromString<Map<String, String>>(variables)
6671
} catch (e: Exception) {
6772
throw McpExpectedError("Invalid variables JSON: ${e.message}. Expected format: {\"key\": \"value\"}")
@@ -74,52 +79,36 @@ class KmpMcpToolset : McpToolset {
7479
throw McpExpectedError("Validation failed:\n${validationErrors.joinToString("\n") { "- $it" }}")
7580
}
7681

77-
var result: GenerationResult? = null
78-
ApplicationManager.getApplication().invokeAndWait {
79-
result = generatorService.generateModule(configuration)
80-
}
82+
val result = writeAction { generatorService.generateModule(configuration) }
8183

82-
return when (val r = result) {
83-
is GenerationResult.Success -> GenerationResultDto(
84-
moduleName = r.moduleName,
85-
location = r.moduleDirectory.path,
86-
files = r.generatedFiles.map { it.path },
84+
return when (result) {
85+
is GenerationResult.Success -> GenerationResultDTO(
86+
moduleName = result.moduleName,
87+
location = result.moduleDirectory.path,
88+
files = result.generatedFiles.map { it.path },
8789
)
88-
is GenerationResult.Warning -> GenerationResultDto(
89-
moduleName = r.moduleName,
90-
location = r.moduleDirectory.path,
91-
files = r.generatedFiles.map { it.path },
92-
warnings = r.warnings,
90+
91+
is GenerationResult.Warning -> GenerationResultDTO(
92+
moduleName = result.moduleName,
93+
location = result.moduleDirectory.path,
94+
files = result.generatedFiles.map { it.path },
95+
warnings = result.warnings,
9396
)
94-
is GenerationResult.Failure -> throw McpExpectedError(r.error)
95-
null -> throw McpExpectedError("Generation produced no result (unexpected internal error)")
97+
98+
is GenerationResult.Failure -> throw McpExpectedError(result.error)
9699
}
97100
}
98-
}
99-
100-
@Serializable
101-
data class TemplateDto(
102-
val id: String,
103-
val name: String,
104-
val description: String,
105-
val variables: List<TemplateVariableDto>,
106-
)
107101

108-
@Serializable
109-
data class TemplateVariableDto(
110-
val name: String,
111-
val displayName: String,
112-
val description: String,
113-
val type: String,
114-
val required: Boolean,
115-
val defaultValue: String,
116-
val options: List<String>? = null,
117-
)
118-
119-
@Serializable
120-
data class GenerationResultDto(
121-
val moduleName: String,
122-
val location: String,
123-
val files: List<String>,
124-
val warnings: List<String> = emptyList(),
125-
)
102+
private fun resolveProject(context: CoroutineContext): Project? {
103+
return try {
104+
val helperClass = Class.forName("com.intellij.mcpserver.McpCallInfoKt")
105+
val helperMethod = helperClass.getMethod(
106+
"getProjectOrNull",
107+
CoroutineContext::class.java
108+
)
109+
helperMethod.invoke(null, context) as? Project
110+
} catch (_: ReflectiveOperationException) {
111+
null
112+
}
113+
}
114+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.github.nonoxys.kmpmodulegenerator.mcp.models
2+
3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
6+
data class GenerationResultDTO(
7+
val moduleName: String,
8+
val location: String,
9+
val files: List<String>,
10+
val warnings: List<String> = emptyList(),
11+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.github.nonoxys.kmpmodulegenerator.mcp.models
2+
3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
6+
data class TemplateDTO(
7+
val id: String,
8+
val name: String,
9+
val description: String,
10+
val variables: List<TemplateVariableDTO>,
11+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.github.nonoxys.kmpmodulegenerator.mcp.models
2+
3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
6+
data class TemplateVariableDTO(
7+
val name: String,
8+
val displayName: String,
9+
val description: String,
10+
val type: String,
11+
val required: Boolean,
12+
val defaultValue: String,
13+
val options: List<String>? = null,
14+
)

0 commit comments

Comments
 (0)