|
| 1 | +<!doctype html> |
| 2 | +<html lang="en"> |
| 3 | +<head> |
| 4 | + <meta charset="utf-8"> |
| 5 | + <meta http-equiv="x-ua-compatible" content="ie=edge"> |
| 6 | + <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 7 | + <link rel="icon" type="image/x-icon" href="../images/favicon.ico"> |
| 8 | + <title>Welcome - MCP Server for Project Development</title> |
| 9 | + <!-- Pure CSS CDN --> |
| 10 | + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/purecss@3.0.0/build/pure-min.css"> |
| 11 | + <!-- Google Fonts --> |
| 12 | + <link href="https://fonts.googleapis.com/css2?family=Tangerine:wght@700&display=swap" rel="stylesheet"> |
| 13 | + <link href="https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@400;600&display=swap" rel="stylesheet"> |
| 14 | + <!-- Font Awesome --> |
| 15 | + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> |
| 16 | + <!-- Syntax Highlighting --> |
| 17 | + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/night-owl.min.css"> |
| 18 | + <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> |
| 19 | + <script>hljs.highlightAll();</script> |
| 20 | + <!-- Pure CSS Grids Responsive CDN --> |
| 21 | + <link rel="stylesheet" href="../css/default.css" /> |
| 22 | +</head> |
| 23 | +<body> |
| 24 | + |
| 25 | +<div id="layout"> |
| 26 | + <!-- menu toggle --> |
| 27 | + <a href="#menu" id="menuLink" class="menu-link"> |
| 28 | + <!-- Hamburger icon --> |
| 29 | + <span></span> |
| 30 | + </a> |
| 31 | + |
| 32 | + <div id="menu"> |
| 33 | + <div class="pure-menu"> |
| 34 | + <a href="../" class="menu-logo-link"> |
| 35 | + <div class="logo-container"> |
| 36 | + <img src="../images/logo.svg?height=120&width=120" alt="Logo" class="logo"> |
| 37 | + <div class="logo-text">Brothel <br /> for Slaking <br /> Intellectual Lusts</div> |
| 38 | + </div> |
| 39 | + </a> |
| 40 | + |
| 41 | + <div class="social-links"> |
| 42 | + <a href="https://github.com/ardfard" class="social-link" target="_blank" rel="noopener"> |
| 43 | + <i class="fa-brands fa-github"></i> |
| 44 | + </a> |
| 45 | + <a href="https://linkedin.com/in/ardin-fardiansyah-74500a56/" class="social-link" target="_blank" rel="noopener"> |
| 46 | + <i class="fa-brands fa-linkedin"></i> |
| 47 | + </a> |
| 48 | + <a href="https://twitter.com/ardfard101" class="social-link" target="_blank" rel="noopener"> |
| 49 | + <i class="fa-brands fa-x-twitter"></i> |
| 50 | + </a> |
| 51 | + <a href="https://bsky.app/profile/ardfard.bsky.social" class="social-link" target="_blank" rel="noopener"> |
| 52 | + <i class="fa-solid fa-feather"></i> |
| 53 | + </a> |
| 54 | + </div> |
| 55 | + |
| 56 | + <ul class="pure-menu-list"> |
| 57 | + <li class="pure-menu-item"><a href="../" class="pure-menu-link">Home</a> </li> |
| 58 | + <li class="pure-menu-item"><a href="../about.html" class="pure-menu-link">About</a> </li> |
| 59 | + <li class="pure-menu-item"><a href="../posts.html" class="pure-menu-link">Posts</a> </li> |
| 60 | + </ul> |
| 61 | + </div> |
| 62 | + </div> |
| 63 | + |
| 64 | + <div id="main"> |
| 65 | + <div class="header"> |
| 66 | + <h1>MCP Server for Project Development</h1> |
| 67 | + </div> |
| 68 | + <div class="content"> |
| 69 | + <div class="subheader"> |
| 70 | + <small> |
| 71 | + <i> |
| 72 | + Posted on April 14, 2025 |
| 73 | + |
| 74 | + </i> |
| 75 | + </small> |
| 76 | +</div> |
| 77 | +<article> |
| 78 | + |
| 79 | + <section> |
| 80 | + <p>Leveraging the new AI hype, I’ve been thinking about how to use it to help with my project development. |
| 81 | +One of such case is to understand a new code base by not also summarizing the code but also read the actual schema on the database and understand the relations between tables. |
| 82 | +IDEs like Cursor and Copilot already capabel to read the code base but it can’t read the database and the data in it. |
| 83 | +So here comes the MCP server that make it possible for the AI model to interface with the database and answer the questions about the schema and the data in it.</p> |
| 84 | +<h2 id="mcp-server">MCP Server</h2> |
| 85 | +<p>MCP stands for “Model Context Protocol”. It’s a protocol that let an AI model to interact with external tools or data sources in a standardized way. |
| 86 | +There are many development in MCP servers including MCP servers for databases like PostgreSQL and MySQL. In here I will talk about my experience in setting up a MCP server for MySQL.</p> |
| 87 | +<p>My development environment is in Cursor IDE that connect to WSL2 Ubuntu 22.04 where it hosts the code and the database. |
| 88 | +One of the MCP Server that I’ve found is <a href="https://github.com/benborla/mcp-server-mysql">mcp-server-mysql</a> that can be used to connect to the MySQLdatabase. |
| 89 | +For cursor you need to add an <code>mcp.json</code> file to the project for the Cursor to recognize and use the MCP server. There are two modes of using the MCP server: the global mode and the project mode. |
| 90 | +For the <code>mcp-server-mysql</code> I use project mode because the database I want to connect is spesific to the project.</p> |
| 91 | +<p>For the project mode, you need to add the <code>mcp.json</code> in the path <code>.cursor/mcp.json</code> relative to the project root. |
| 92 | +Here is the content of my <code>mcp.json</code> file:</p> |
| 93 | +<div class="sourceCode" id="cb1"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span> |
| 94 | +<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="er">`</span><span class="dt">"mcpServers"</span><span class="fu">:</span> <span class="fu">{</span></span> |
| 95 | +<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">"MySQL"</span><span class="fu">:</span> <span class="fu">{</span></span> |
| 96 | +<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">"command"</span><span class="fu">:</span> <span class="st">"npx"</span><span class="fu">,</span></span> |
| 97 | +<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">"args"</span><span class="fu">:</span> <span class="ot">[</span></span> |
| 98 | +<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> <span class="st">"mcprunner"</span><span class="ot">,</span></span> |
| 99 | +<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> <span class="st">"MYSQL_HOST=127.0.0.1"</span><span class="ot">,</span></span> |
| 100 | +<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> <span class="st">"MYSQL_PORT=3333"</span><span class="ot">,</span></span> |
| 101 | +<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="st">"MYSQL_USER=<user>"</span><span class="ot">,</span></span> |
| 102 | +<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> <span class="st">"MYSQL_PASS=<password>"</span><span class="ot">,</span></span> |
| 103 | +<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> <span class="st">"MYSQL_DB=my_database"</span><span class="ot">,</span></span> |
| 104 | +<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> <span class="st">"ALLOW_INSERT_OPERATION=true"</span><span class="ot">,</span></span> |
| 105 | +<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> <span class="st">"ALLOW_UPDATE_OPERATION=true"</span><span class="ot">,</span></span> |
| 106 | +<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> <span class="st">"ALLOW_DELETE_OPERATION=true"</span><span class="ot">,</span></span> |
| 107 | +<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> <span class="st">"--"</span><span class="ot">,</span></span> |
| 108 | +<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> <span class="st">"npx"</span><span class="ot">,</span></span> |
| 109 | +<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> <span class="st">"@benborla29/mcp-server-mysql"</span></span> |
| 110 | +<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> <span class="ot">]</span></span> |
| 111 | +<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> <span class="fu">}</span></span> |
| 112 | +<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> <span class="fu">}</span></span> |
| 113 | +<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div> |
| 114 | +<p>After adding the <code>mcp.json</code> file, the Cursor will be able to recognize the MCP server and ask you to enable it. After enabling it, the Cursor then trying to connect to the database. |
| 115 | +But here is the problem, when I try to connect to the database, it failed. The status is always <code>Client closed</code>. So I look at the MCP server output on the Cursor output panel, and it shows the error:</p> |
| 116 | +<pre><code>2025-04-11 09:26:31.249 [info] ySQL: getOrCreateClient for stdio server. process.platform: win32 isElectron: true |
| 117 | +2025-04-11 09:26:31.249 [info] ySQL: Starting new stdio process with command: npx mcprunner MYSQL_HOST=127.0.0.1 MYSQL_PORT=3333 MYSQL_USER=<user> MYSQL_PASS=<password> MYSQL_DB=my_database ALLOW_INSERT_OPERATION=true ALLOW_UPDATE_OPERATION=true ALLOW_DELETE_OPERATION=true -- npx @benborla29/mcp-server-mysql |
| 118 | +2025-04-11 09:26:31.277 [error] ySQL: Client error for command spawn npx ENOENT |
| 119 | +2025-04-11 09:26:31.277 [error] ySQL: Error in MCP: spawn npx ENOENT |
| 120 | +2025-04-11 09:26:31.277 [info] ySQL: Client closed for command |
| 121 | +2025-04-11 09:26:31.277 [error] ySQL: Error in MCP: Client closed |
| 122 | +2025-04-11 09:26:31.277 [error] ySQL: Failed to reload client: MCP error -32000: Connection closed |
| 123 | +2025-04-11 09:26:31.281 [info] ySQL: Handling ListOfferings action |
| 124 | +2025-04-11 09:26:31.281 [error] ySQL: No server info found</code></pre> |
| 125 | +<p>This line is the key:</p> |
| 126 | +<pre><code>spawn npx ENOENT</code></pre> |
| 127 | +<p>ENOENT means “Error NO ENTity”, i.e., the command npx was not found. |
| 128 | +Since I am using WSL, but Cursor runs on Windows (Electron, win32), it’s trying to spawn npx on the Windows side, not in my WSL shell. |
| 129 | +So Cursor is looking for npx in my Windows environment, but it doesn’t exist since I installed my development tools in WSL.</p> |
| 130 | +<p>To fix this, I need to install npx in my Windows environment. I can do this by installing Node.js in my Windows environment. |
| 131 | +So I just need to install Node.js from the official website and add it to my PATH on Windows environment.</p> |
| 132 | +<p>After adding Node.js to my PATH, I need to restart the Cursor IDE. |
| 133 | +After restarting the Cursor IDE, I try to connect to the database again. This time it works. Now I can use the MCP server to interact with the database.</p> |
| 134 | +<figure> |
| 135 | +<img src="../images/cursor-mcp-server.png" alt="Cursor MCP Server" /> |
| 136 | +<figcaption aria-hidden="true">Cursor MCP Server</figcaption> |
| 137 | +</figure> |
| 138 | +<p>You can try a more complex prompt like: |
| 139 | +- “What is the relation between the table <code>users</code> and <code>posts</code>?” |
| 140 | +- “Explain the flow of <some function> in <some file> with the changes in the table <some table>.”</p> |
| 141 | + </section> |
| 142 | +</article> |
| 143 | + |
| 144 | + </div> |
| 145 | + <div id="footer"> |
| 146 | + <p>Powered by <a href="http://jaspervdj.be/hakyll">Hakyll</a></p> |
| 147 | + </div> |
| 148 | + </div> |
| 149 | +</div> |
| 150 | + |
| 151 | +<script src="../js/ui.js"></script> |
| 152 | +</body> |
| 153 | +</html> |
0 commit comments