You could integrate to the built-in MCP server MCP Server | IntelliJ IDEA Documentation
dependencies {
...
bundledPlugin("com.intellij.mcpServer")
}
plugin.xml
<depends>com.intellij.mcpServer</depends>
Implement com.intellij.mcpserver.McpToolset
<mcpServer.mcpToolset implementation="com.intellij.mcpserver.toolsets.general.FileToolset" />
Example:
class FileToolset : McpToolset {
@McpToolHints(readOnlyHint = TRUE, openWorldHint = FALSE)
@McpTool
@McpDescription("""
|Provides a tree representation of the specified directory in the pseudo graphic format like `tree` utility does.
|Use this tool to explore the contents of a directory or the whole project.
|You MUST prefer this tool over listing directories via command line utilities like `ls` or `dir`.
""")
suspend fun list_directory_tree(
@McpDescription(Constants.RELATIVE_PATH_IN_PROJECT_DESCRIPTION) directoryPath: String,
@McpDescription("Maximum recursion depth") maxDepth: Int = 5,
@McpDescription(Constants.TIMEOUT_MILLISECONDS_DESCRIPTION) timeout: Int = Constants.MEDIUM_TIMEOUT_MILLISECONDS_VALUE,
): DirectoryTreeInfo {
val project = currentCoroutineContext().project
val resolvedPath = project.resolveInProject(directoryPath)
if (!resolvedPath.exists()) mcpFail("No such directory: $resolvedPath")
if (!resolvedPath.isDirectory()) mcpFail("Not a directory: $resolvedPath")
val result = StringBuilder()
val errors = mutableListOf<String>()
val timedOut = withTimeoutOrNull(timeout.milliseconds) { renderDirectoryTree(resolvedPath.toFile(), result, errors, maxDepth = maxDepth) } == null
return DirectoryTreeInfo(directoryPath, result.toString(), errors, timedOut)
}
@Serializable
class DirectoryTreeInfo(
val traversedDirectory: String,
val tree: String,
val errors: List<String>,
@property:McpDescription(Constants.TIMED_OUT_DESCRIPTION)
@EncodeDefault(mode = EncodeDefault.Mode.NEVER)
val listingTimedOut: Boolean? = false,
)
You would need kotlinx-serialization applied in Gradle for @Serializable