{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# MCP Server Toolset Implementation\n",
    "\n",
    "This notebook creates a custom **Model Context Protocol (MCP) toolset** that exposes a `shakeIde` command to MCP clients.\n",
    "\n",
    "The command shakes your JetBrains IDE window using IntelliJ Platform SDK."
   ]
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-10T11:19:03.720646Z",
     "start_time": "2025-07-10T11:19:03.563158Z"
    }
   },
   "cell_type": "code",
   "source": "%use intellij-platform",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IntelliJ Platform integration is loaded"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "Load the MCP Server bundled plugin using its `com.intellij.mcpServer` ID."
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-10T11:19:03.765860Z",
     "start_time": "2025-07-10T11:19:03.728673Z"
    }
   },
   "cell_type": "code",
   "source": "loadPlugins(\"com.intellij.mcpServer\")",
   "outputs": [],
   "execution_count": 2
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "Implement the `McpToolset` extension with an example code that shakes the current IDE using a built-it `DialogEarthquakeShaker` utility class.\n",
    "Using the `registerExtension` helper, register the implemented extension as `com.intellij.mcpServer.mcpToolset`."
   ]
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-10T11:19:03.855623Z",
     "start_time": "2025-07-10T11:19:03.769942Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import com.intellij.openapi.application.ApplicationManager\n",
    "import com.intellij.openapi.ui.DialogEarthquakeShaker\n",
    "import com.intellij.openapi.wm.WindowManager\n",
    "import com.intellij.mcpserver.McpToolset\n",
    "import com.intellij.mcpserver.annotations.McpDescription\n",
    "import com.intellij.mcpserver.annotations.McpTool\n",
    "import com.intellij.mcpserver.project\n",
    "import kotlinx.coroutines.delay\n",
    "import kotlin.coroutines.coroutineContext\n",
    "\n",
    "class ShakeMcpToolset : McpToolset {\n",
    "\n",
    "    @McpTool\n",
    "    @McpDescription(\"Shakes your JetBrains IDE 😵‍💫\")\n",
    "    suspend fun shakeIde(\n",
    "        @McpDescription(\"How many times to shake your IDE?\")\n",
    "        times: Int = 1\n",
    "    ) {\n",
    "        val project = coroutineContext.project\n",
    "        val window = WindowManager.getInstance().getFrame(project)\n",
    "\n",
    "        repeat(times) {\n",
    "            DialogEarthquakeShaker.shake(window)\n",
    "            delay(500)\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "registerExtension(McpToolset.EP, ShakeMcpToolset())"
   ],
   "outputs": [],
   "execution_count": 3
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## Testing\n",
    "\n",
    "Make sure that the JetBrains MCP Server is enabled in [⚙️ Settings | Tools | MCP Server](jetbrains://idea/settings?name=Tools--MCP+Server) and copy its URL, like `http://127.0.0.1:64342/sse`\n",
    "\n",
    "As soon as the extension is registered, you can test it using the [MCP Inspector tool](https://modelcontextprotocol.io/docs/tools/inspector):\n",
    "\n",
    "```shell\n",
    "npx @modelcontextprotocol/inspector\n",
    "```\n",
    "\n",
    "When running, _🔗 Open inspector with token pre-filled:_ `http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=foo`\n",
    "\n",
    "Configure the connection and set the _Transport Type_ to `SSE`, the MCP Server URL, and establish the connection.\n",
    "\n",
    "Find the `shakeIde` entry in the tool list, set the `times` parameter to any number, and click the _Run tool_ button."
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## Integration with standalone plugins\n",
    "\n",
    "To register the extension within a standalone plugin, use:\n",
    "```xml\n",
    "<idea-plugin>\n",
    "  ...\n",
    "  <extensions defaultExtensionNs=\"com.intellij\">\n",
    "    <mcpServer.mcpToolset implementation=\"com.example.ShakeMcpToolset\"/>\n",
    "  </extensions>\n",
    "</idea-plugin>\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Kotlin",
   "language": "kotlin",
   "name": "kotlin"
  },
  "language_info": {
   "name": "kotlin",
   "version": "1.9.23",
   "mimetype": "text/x-kotlin",
   "file_extension": ".kt",
   "pygments_lexer": "kotlin",
   "codemirror_mode": "text/x-kotlin",
   "nbconvert_exporter": ""
  },
  "ktnbPluginMetadata": {
   "sessionRunMode": "IDE_PROCESS"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
