Skip to content

Commit 8145db8

Browse files
committed
feat(mcp): add MCP client and configuration support #330
- Introduce `McpClient` with `McpConfig` and `McpServer` data classes. - Add `mcpServices` property to `AutoDevCustomizeSettings`. - Include `CustomMCPServersSchemaFileProvider` for MCP schema validation. - Update UI to support MCP services configuration.
1 parent afc9840 commit 8145db8

File tree

8 files changed

+132
-1
lines changed

8 files changed

+132
-1
lines changed

core/src/main/kotlin/cc/unitmesh/devti/custom/schema/AutoDevJsonSchemaProviderFactory.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ class AutoDevJsonSchemaProviderFactory : JsonSchemaProviderFactory {
99
return mutableListOf(
1010
CustomAgentSchemaFileProvider(project),
1111
CustomLlmSchemaFileProvider(project),
12-
CustomPromptsSchemaFileProvider(project)
12+
CustomPromptsSchemaFileProvider(project),
13+
CustomMCPServersSchemaFileProvider(project)
1314
)
1415
}
1516
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package cc.unitmesh.devti.custom.schema
2+
3+
import com.intellij.openapi.application.runReadAction
4+
import com.intellij.openapi.project.Project
5+
import com.intellij.openapi.vfs.VirtualFile
6+
import com.jetbrains.jsonSchema.extension.JsonSchemaFileProvider
7+
import com.jetbrains.jsonSchema.extension.JsonSchemaProviderFactory
8+
import com.jetbrains.jsonSchema.extension.SchemaType
9+
10+
const val MCP_SERVERS_FILE_NAME = "AutoDevMCPServersFile.json"
11+
12+
class CustomMCPServersSchemaFileProvider(project: Project) : JsonSchemaFileProvider {
13+
override fun isAvailable(file: VirtualFile): Boolean {
14+
return runReadAction { isAutoDevCustomAgentFile(file) }
15+
}
16+
17+
private fun isAutoDevCustomAgentFile(file: VirtualFile): Boolean {
18+
if (!file.isValid) {
19+
return false
20+
}
21+
22+
return file.name == MCP_SERVERS_FILE_NAME
23+
}
24+
25+
override fun getName(): String = "AutoDevMCPServersFile"
26+
27+
override fun getSchemaFile(): VirtualFile? {
28+
return JsonSchemaProviderFactory.getResourceFile(this::class.java, customMcpServerSchemaFile)
29+
}
30+
31+
override fun getSchemaType(): SchemaType {
32+
return SchemaType.schema
33+
}
34+
35+
companion object {
36+
private const val customMcpServerSchemaFile = "autodev-mcp-server-schema.json"
37+
}
38+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package cc.unitmesh.devti.mcp
2+
3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
6+
data class McpConfig(
7+
val mcpServers: Map<String, McpServer>
8+
)
9+
10+
@Serializable
11+
data class McpServer(
12+
val command: String,
13+
val args: List<String>,
14+
val disabled: Boolean? = null,
15+
val autoApprove: List<String>? = null,
16+
val env: Map<String, String>? = null,
17+
val requiresConfirmation: List<String>? = null
18+
)

core/src/main/kotlin/cc/unitmesh/devti/settings/customize/AutoDevCustomizeSettings.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class AutoDevCustomizeSettings(
1313
) : SimplePersistentStateComponent<AutoDevCustomizeSettings.CustomizeProjectSettings>(CustomizeProjectSettings()) {
1414
val enableCustomRag: Boolean get() = state.enableCustomRag
1515
val customPrompts: String get() = state.customPrompts
16+
val mcpServer: String get() = state.mcpServices
1617

1718
/**
1819
* Use [cc.unitmesh.devti.agent.model.CustomAgentConfig.loadFromProject]
@@ -31,6 +32,7 @@ class AutoDevCustomizeSettings(
3132
var enableCustomRag by property(false)
3233
var agentJsonConfig by property("") { it.isEmpty() }
3334
var customPrompts by property("") { it.isEmpty() }
35+
var mcpServices by property("") { it.isEmpty() }
3436

3537
override fun copy(): CustomizeProjectSettings {
3638
val state = CustomizeProjectSettings()

core/src/main/kotlin/cc/unitmesh/devti/settings/customize/CustomizeConfigurable.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cc.unitmesh.devti.settings.customize
33
import cc.unitmesh.devti.AutoDevBundle
44
import cc.unitmesh.devti.custom.schema.CUSTOM_AGENT_FILE_NAME
55
import cc.unitmesh.devti.custom.schema.CUSTOM_PROMPTS_FILE_NAME
6+
import cc.unitmesh.devti.custom.schema.MCP_SERVERS_FILE_NAME
67
import cc.unitmesh.devti.fullHeight
78
import cc.unitmesh.devti.fullWidthCell
89
import cc.unitmesh.devti.gui.component.JsonLanguageField
@@ -82,12 +83,34 @@ class CustomizeConfigurable(val project: Project) : BoundConfigurable(AutoDevBun
8283
prop = state::agentJsonConfig.toMutableProperty()
8384
)
8485
}
86+
row {
87+
cell(jBLabel("counit.mcp.services.placeholder", 1))
88+
}
89+
90+
row {
91+
val mcpServices = JsonLanguageField(
92+
project,
93+
state::mcpServices.toString(),
94+
AutoDevBundle.messageWithLanguageFromLLMSetting("counit.mcp.services.placeholder"),
95+
MCP_SERVERS_FILE_NAME
96+
).apply {
97+
placeholder("counit.mcp.services.placeholder", this)
98+
}
99+
fullWidthCell(mcpServices)
100+
.fullHeight()
101+
.bind(
102+
componentGet = { it.text },
103+
componentSet = { component, value -> component.text = value },
104+
prop = state::mcpServices.toMutableProperty()
105+
)
106+
}
85107

86108
onApply {
87109
settings.modify {
88110
it.enableCustomRag = state.enableCustomRag
89111
it.agentJsonConfig = state.agentJsonConfig
90112
it.customPrompts = state.customPrompts
113+
it.mcpServices = state.mcpServices
91114
}
92115
}
93116
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"type": "object",
4+
"properties": {
5+
"mcpServers": {
6+
"type": "object",
7+
"additionalProperties": {
8+
"type": "object",
9+
"properties": {
10+
"command": {
11+
"type": "string"
12+
},
13+
"args": {
14+
"type": "array",
15+
"items": {
16+
"type": "string"
17+
}
18+
},
19+
"disabled": {
20+
"type": "boolean"
21+
},
22+
"autoApprove": {
23+
"type": "array",
24+
"items": {
25+
"type": "string"
26+
}
27+
},
28+
"env": {
29+
"type": "object",
30+
"additionalProperties": {
31+
"type": "string"
32+
}
33+
},
34+
"requires_confirmation": {
35+
"type": "array",
36+
"items": {
37+
"type": "string"
38+
}
39+
}
40+
},
41+
"required": ["command", "args"],
42+
"additionalProperties": false
43+
}
44+
}
45+
},
46+
"required": ["mcpServers"]
47+
}

core/src/main/resources/messages/AutoDevBundle_en.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,4 @@ sketch.compile.devins=Collect context (aka. transpile AutoDev DevIns)
224224
autodev.run.action=Run this file
225225
#llm.error.url.scheme=请配置好您的模型,参考文档:https://ide.unitmesh.cc/quick-start
226226
llm.error.url.scheme=Please, Please, Please configure your model, refer to the document: https://ide.unitmesh.cc/quick-start
227+
counit.mcp.services.placeholder=MCP Servers

core/src/main/resources/messages/AutoDevBundle_zh.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,4 @@ settings.autodev.coder.customLlms=自定义不同模型: Plan/ACT/Completion/Emb
227227
sketch.compile.devins=收集上下文中(即转译 AutoDev DevIns 指令)
228228
autodev.run.action=Run this file
229229
llm.error.url.scheme=请请请先配置好您的模型,参考文档:https://ide.unitmesh.cc/quick-start
230+
counit.mcp.services.placeholder=MCP Servers

0 commit comments

Comments
 (0)