diff --git a/plugins/mcp-server/src/com/intellij/mcpserver/McpCallAdditionalData.kt b/plugins/mcp-server/src/com/intellij/mcpserver/McpCallInfo.kt similarity index 75% rename from plugins/mcp-server/src/com/intellij/mcpserver/McpCallAdditionalData.kt rename to plugins/mcp-server/src/com/intellij/mcpserver/McpCallInfo.kt index b04dafa67c03..efc170971286 100644 --- a/plugins/mcp-server/src/com/intellij/mcpserver/McpCallAdditionalData.kt +++ b/plugins/mcp-server/src/com/intellij/mcpserver/McpCallInfo.kt @@ -6,7 +6,7 @@ import org.jetbrains.ide.RestService.Companion.getLastFocusedOrOpenedProject import kotlin.coroutines.AbstractCoroutineContextElement import kotlin.coroutines.CoroutineContext -class McpCallAdditionalData( +class McpCallInfo( val callId: Int, val clientInfo: ClientInfo, val project: Project?, @@ -21,23 +21,23 @@ class McpCallAdditionalData( class ClientInfo(val name: String, val version: String) -class McpCallAdditionalDataElement(val additionalData: McpCallAdditionalData) : AbstractCoroutineContextElement(Key) { +class McpCallAdditionalDataElement(val additionalData: McpCallInfo) : AbstractCoroutineContextElement(Key) { companion object Key : CoroutineContext.Key } -val CoroutineContext.mcpCallAdditionalDataOrNull: McpCallAdditionalData? get() = get(McpCallAdditionalDataElement)?.additionalData -val CoroutineContext.mcpCallAdditionalData: McpCallAdditionalData get() = mcpCallAdditionalDataOrNull ?: error("mcpCallAdditionalData called outside of a MCP call") +val CoroutineContext.mcpCallInfoOrNull: McpCallInfo? get() = get(McpCallAdditionalDataElement)?.additionalData +val CoroutineContext.mcpCallInfo: McpCallInfo get() = mcpCallInfoOrNull ?: error("mcpCallAdditionalData called outside of a MCP call") /** * Returns information about the MCP client that is calling a tool. */ -val CoroutineContext.clientInfo: ClientInfo get() = mcpCallAdditionalData.clientInfo +val CoroutineContext.clientInfo: ClientInfo get() = mcpCallInfo.clientInfo /** * Returns information about the MCP tool that is called. */ -val CoroutineContext.currentToolDescriptor: McpToolDescriptor get() = mcpCallAdditionalData.mcpToolDescriptor +val CoroutineContext.currentToolDescriptor: McpToolDescriptor get() = mcpCallInfo.mcpToolDescriptor /** * MCP tool can resolve a project with this extension property. In the case of running some MCP clients (like Claude) by IJ infrastructure @@ -58,7 +58,7 @@ val CoroutineContext.project: Project * The same as [projectOrNull], but allows to specify whether to look for any/last focused project or take only the one from the context element */ fun CoroutineContext.getProjectOrNull(lookForAnyProject: Boolean): Project? { - val projectFromContext = mcpCallAdditionalData.project + val projectFromContext = mcpCallInfo.project if (projectFromContext != null) return projectFromContext if (!lookForAnyProject) return null return getLastFocusedOrOpenedProject() diff --git a/plugins/mcp-server/src/com/intellij/mcpserver/ToolCallListener.kt b/plugins/mcp-server/src/com/intellij/mcpserver/ToolCallListener.kt index 9b3ce9b271e0..db82c8949960 100644 --- a/plugins/mcp-server/src/com/intellij/mcpserver/ToolCallListener.kt +++ b/plugins/mcp-server/src/com/intellij/mcpserver/ToolCallListener.kt @@ -12,11 +12,11 @@ interface ToolCallListener { val TOPIC: Topic = Topic(ToolCallListener::class.java) } - fun beforeMcpToolCall(mcpToolDescriptor: McpToolDescriptor, additionalData: McpCallAdditionalData) {} + fun beforeMcpToolCall(mcpToolDescriptor: McpToolDescriptor, additionalData: McpCallInfo) {} - fun afterMcpToolCall(mcpToolDescriptor: McpToolDescriptor, events: List, error: Throwable?, additionalData: McpCallAdditionalData) {} + fun afterMcpToolCall(mcpToolDescriptor: McpToolDescriptor, events: List, error: Throwable?, callInfo: McpCallInfo) {} - fun toolActivity(mcpToolDescriptor: McpToolDescriptor, @NlsContexts.Label toolActivityDescription: String, additionalData: McpCallAdditionalData) {} + fun toolActivity(mcpToolDescriptor: McpToolDescriptor, @NlsContexts.Label toolActivityDescription: String, callInfo: McpCallInfo) {} } sealed interface McpToolSideEffectEvent @@ -29,5 +29,5 @@ class FileMovedEvent(val file: VirtualFile, val oldParent: VirtualFile, val newP class FileContentChangeEvent(val file: VirtualFile, val oldContent: String?, val newContent: String) : FileEvent fun CoroutineContext.reportToolActivity(@NlsContexts.Label toolDescription: String) { - application.messageBus.syncPublisher(ToolCallListener.TOPIC).toolActivity(this.currentToolDescriptor, toolDescription, this.mcpCallAdditionalData) + application.messageBus.syncPublisher(ToolCallListener.TOPIC).toolActivity(this.currentToolDescriptor, toolDescription, this.mcpCallInfo) } \ No newline at end of file diff --git a/plugins/mcp-server/src/com/intellij/mcpserver/impl/McpServerService.kt b/plugins/mcp-server/src/com/intellij/mcpserver/impl/McpServerService.kt index 7e56c251ce39..9e63c918f235 100644 --- a/plugins/mcp-server/src/com/intellij/mcpserver/impl/McpServerService.kt +++ b/plugins/mcp-server/src/com/intellij/mcpserver/impl/McpServerService.kt @@ -205,7 +205,7 @@ private fun McpTool.mcpToolToRegisteredTool(server: Server, projectPathFromIniti val initialDocumentContents = ConcurrentHashMap() val clientVersion = server.clientVersion ?: Implementation("Unknown MCP client", "Unknown version") - val additionalData = McpCallAdditionalData( + val additionalData = McpCallInfo( callId = callId.getAndAdd(1), clientInfo = ClientInfo(clientVersion.name, clientVersion.version), project = project, @@ -217,9 +217,9 @@ private fun McpTool.mcpToolToRegisteredTool(server: Server, projectPathFromIniti val callResult = coroutineScope { VirtualFileManager.getInstance().addAsyncFileListener(this, AsyncFileListener { events -> - val inHandlerData = currentThreadContext().mcpCallAdditionalDataOrNull - if (inHandlerData != null && inHandlerData.callId == additionalData.callId) { - logger.trace { "VFS changes detected for call: $inHandlerData" } + val inHandlerInfo = currentThreadContext().mcpCallInfoOrNull + if (inHandlerInfo != null && inHandlerInfo.callId == additionalData.callId) { + logger.trace { "VFS changes detected for call: $inHandlerInfo" } vfsEvent.addAll(events) } // probably we have to read initial contents here @@ -230,9 +230,9 @@ private fun McpTool.mcpToolToRegisteredTool(server: Server, projectPathFromIniti val documentListener = object : DocumentListener { // record content before any change override fun beforeDocumentChange(event: DocumentEvent) { - val inHandlerData = currentThreadContext().mcpCallAdditionalDataOrNull - if (inHandlerData != null && inHandlerData.callId == additionalData.callId) { - logger.trace { "Document changes detected for call: $inHandlerData" } + val inHandlerInfo = currentThreadContext().mcpCallInfoOrNull + if (inHandlerInfo != null && inHandlerInfo.callId == additionalData.callId) { + logger.trace { "Document changes detected for call: $inHandlerInfo" } initialDocumentContents.computeIfAbsent(event.document) { event.document.text } } }