<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>mcp &#8211; iAIFeed</title>
	<atom:link href="https://www.iaifeed.com/tag/mcp/feed" rel="self" type="application/rss+xml" />
	<link>https://www.iaifeed.com</link>
	<description>iAIFeed</description>
	<lastBuildDate>Tue, 20 Oct 2026 12:52:12 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>

<image>
	<url>https://www.iaifeed.com/wp-content/uploads/2026/07/cropped-iaifeed1-80x80.png</url>
	<title>mcp &#8211; iAIFeed</title>
	<link>https://www.iaifeed.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How to Add a Custom MCP Server to Cursor and Test It Safely</title>
		<link>https://www.iaifeed.com/how-to-add-custom-mcp-server-to-cursor</link>
					<comments>https://www.iaifeed.com/how-to-add-custom-mcp-server-to-cursor#respond</comments>
		
		<dc:creator><![CDATA[iamltlb]]></dc:creator>
		<pubDate>Tue, 20 Oct 2026 12:49:23 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[mcp]]></category>
		<guid isPermaLink="false">https://www.iaifeed.com/how-to-add-custom-mcp-server-to-cursor</guid>

					<description><![CDATA[Cursor reads MCP config from two places depending on scope, and the Tools list only appears after a restart. Per-project setup, env vars and permission scope.]]></description>
										<content:encoded><![CDATA[<p>Cursor reads <a href="https://www.iaifeed.com/ai-tool/mcp">MCP</a> servers from <code>.cursor/mcp.json</code> in the project root for project-scoped servers, or from <code>~/.cursor/mcp.json</code> for global ones. Add the server block, restart Cursor, then approve the tools in the Tools panel — the editor won&#8217;t expose them until you explicitly toggle them on.</p>
<p>That approval step is where most setups appear broken. The config is right, the server runs, and no tools show because nobody clicked.</p>
<h2 id="where-does-cursor-look-for-mcp-config">Where does Cursor look for MCP config?</h2>
<p>Two files, two scopes:</p>
<table>
<thead>
<tr>
<th>File</th>
<th>Scope</th>
<th>Use for</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>.cursor/mcp.json</code></td>
<td>This project only</td>
<td>Project-specific APIs, committing to the repo</td>
</tr>
<tr>
<td><code>~/.cursor/mcp.json</code></td>
<td>All projects</td>
<td>Personal tools, filesystem access, Git</td>
</tr>
</tbody>
</table>
<p>If both exist, project-level entries merge with global ones and project takes precedence on name collisions. Name servers distinctly — a global <code>postgres</code> and a project <code>postgres</code> with different connection strings is a debugging afternoon you don&#8217;t want.</p>
<h2 id="step-1-add-the-server-block">Step 1: Add the server block</h2>
<p>Here is a minimal per-project config with an API key passed as an environment variable:</p>
<pre><code>{
  &quot;mcpServers&quot;: {
    &quot;filesystem&quot;: {
      &quot;command&quot;: &quot;npx&quot;,
      &quot;args&quot;: [&quot;-y&quot;, &quot;@modelcontextprotocol/server-filesystem&quot;, &quot;.&quot;],
      &quot;env&quot;: {}
    },
    &quot;internal-api&quot;: {
      &quot;command&quot;: &quot;node&quot;,
      &quot;args&quot;: [&quot;./mcp-server/dist/index.js&quot;],
      &quot;env&quot;: { &quot;API_TOKEN&quot;: &quot;paste-token-here&quot; }
    }
  }
}
</code></pre>
<p>The <code>.</code> in the filesystem args means &#8220;current working directory&#8221; — scoped to the project, which is what you want. Never point it at <code>~</code>.</p>
<h2 id="step-2-restart-then-enable-the-tools">Step 2: Restart, then enable the tools</h2>
<p>Completely quit Cursor and reopen the project. Open the agent panel and look at the tool list — there&#8217;s an MCP section where each server shows its tools with individual toggles.</p>
<p>Enable the ones you need. Cursor keeps them disabled by default for a reason: a filesystem server with 11 tools adds 11 function definitions to every request, which costs tokens and dilutes tool selection. Enable three tools and the model picks correctly more often than when all 11 are on.</p>
<h2 id="step-3-watch-the-output-for-startup-errors">Step 3: Watch the output for startup errors</h2>
<p>Cursor surfaces MCP stderr in the Output pane under the MCP channel. Two errors that come up constantly:</p>
<ul>
<li><strong>Server exited before handshake</strong> — usually a missing dependency. Run the exact command in your terminal; the real error appears there.</li>
<li><strong>Tool call failed with 401</strong> — the env var didn&#8217;t reach the subprocess. Cursor passes <code>env</code> verbatim; if your server reads a config file instead, that file may be in the wrong working directory.</li>
</ul>
<p>Relative paths in <code>args</code> resolve from the workspace root, not from the config file&#8217;s folder. That trips people up in monorepos.</p>
<h2 id="step-4-decide-what-the-agent-is-allowed-to-touch">Step 4: Decide what the agent is allowed to touch</h2>
<p>MCP changes what the agent can do without approval. A Postgres server with write access in an agent that also runs terminal commands is a bad combination — one hallucinated query and a table is gone.</p>
<p>Practical rules that have served me well:</p>
<ul>
<li>Read-only database credentials for any MCP server in a coding agent</li>
<li>Filesystem scope limited to the project folder</li>
<li>No server with production credentials in a config file that lives in a repo you might push publicly</li>
<li><code>.cursor/mcp.json</code> in <code>.gitignore</code> if it contains tokens</li>
</ul>
<h2 id="step-5-write-your-own-and-test-it-as-a-project-server">Step 5: Write your own and test it as a project server</h2>
<p>If you build a server, develop it inside the project and point Cursor at <code>./mcp-server/dist/index.js</code>. Rebuild and restart Cursor to pick up changes — Cursor doesn&#8217;t hot reload MCP servers, which surprises people mid-session.</p>
<p>For quick iteration, run it in a terminal first and use the MCP Inspector to confirm it lists tools before wiring it into Cursor. Debugging through the editor&#8217;s output pane is slower.</p>
<h2 id="why-do-tools-disappear-after-a-cursor-update">Why do tools disappear after a Cursor update?</h2>
<p>Because the tool approval state is tied to the server&#8217;s reported tool list. If your server changes its tools — added a parameter, renamed something — Cursor treats them as new and leaves them disabled. Re-enable them after any server update. This is also why version-pinning your MCP server package is worth the small hassle.</p>
<h2 id="should-mcp-servers-be-per-project-or-global">Should MCP servers be per-project or global?</h2>
<p>The filesystem and shell-adjacent ones per-project, always. A global filesystem server pointed at your home directory means every project you open can read every other project. Database and API servers where the credentials differ per project belong in the project config; ones like a documentation search or a personal notes server work fine globally.</p>
<h2 id="quick-summary">Quick Summary</h2>
<ul>
<li>Project config lives at <code>.cursor/mcp.json</code>; global at <code>~/.cursor/mcp.json</code>.</li>
<li>Restart Cursor fully and enable each tool manually in the MCP panel.</li>
<li>Give filesystem servers the project folder (<code>.</code>), never your home directory.</li>
<li>Use read-only DB credentials; keep tokens out of committed config files.</li>
<li>Tools reset to disabled when a server changes its tool list — re-enable after updates.</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.iaifeed.com/how-to-add-custom-mcp-server-to-cursor/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Build a Custom MCP Server for Your Own API</title>
		<link>https://www.iaifeed.com/how-to-build-custom-mcp-server-for-your-own-api</link>
					<comments>https://www.iaifeed.com/how-to-build-custom-mcp-server-for-your-own-api#respond</comments>
		
		<dc:creator><![CDATA[iamltlb]]></dc:creator>
		<pubDate>Tue, 20 Oct 2026 12:43:00 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[mcp]]></category>
		<guid isPermaLink="false">https://www.iaifeed.com/how-to-build-custom-mcp-server-for-your-own-api</guid>

					<description><![CDATA[Writing your own MCP server takes about 80 lines of TypeScript. Tool schemas, stdio transport, error handling, and the design mistakes that make tools useless.]]></description>
										<content:encoded><![CDATA[<p>A working <a href="https://www.iaifeed.com/ai-tool/mcp">MCP</a> server for your own API is roughly 80 lines of TypeScript using the official SDK, a handful of tool definitions, and a stdio transport. You export a <code>main()</code> that registers tools with JSON Schema inputs, and the client discovers them on connect. No hosted infrastructure required.</p>
<p>The hard part isn&#8217;t the code. It&#8217;s deciding how granular your tools should be.</p>
<h2 id="what-does-a-minimal-mcp-server-contain">What does a minimal MCP server contain?</h2>
<p>Three things: a server instance with a name and version, one or more registered tools, and a transport to talk to the client. The <code>@modelcontextprotocol/sdk</code> package gives you all three. Python has an equivalent with <code>mcp</code> on PyPI and the <code>FastMCP</code> helper.</p>
<p>Nothing here requires Anthropic&#8217;s blessing or a manifest upload. The protocol is open and the client just spawns your process.</p>
<h2 id="step-1-scaffold-and-install">Step 1: Scaffold and install</h2>
<pre><code>mkdir my-mcp &amp;&amp; cd my-mcp
npm init -y
npm i @modelcontextprotocol/sdk zod
</code></pre>
<p>Add <code>"type": "module"</code> to package.json and set a <code>bin</code> entry if you want to run it after <code>npm link</code>. You&#8217;ll be writing ESM whether you like it or not — the SDK ships ESM-only now, so CommonJS <code>require</code> will fail.</p>
<h2 id="step-2-define-tools-by-user-intent-not-by-endpoint">Step 2: Define tools by user intent, not by endpoint</h2>
<p>The most common mistake is one tool per REST endpoint. Give a model 40 endpoints and it picks wrong constantly. Give it four tools that match how a person would ask, and accuracy climbs sharply.</p>
<p>Compare these two designs for an invoicing API:</p>
<table>
<thead>
<tr>
<th>Design</th>
<th>Tools</th>
<th>Typical result</th>
</tr>
</thead>
<tbody>
<tr>
<td>Endpoint mirroring</td>
<td>list_invoices, get_invoice, list_customers, get_customer, create_invoice_line, finalize_invoice (and 30 more)</td>
<td>4-6 round trips, wrong tool chosen</td>
</tr>
<tr>
<td>Task oriented</td>
<td>find_invoices(query, customer, date_range), get_invoice_detail(id), draft_invoice(customer, items)</td>
<td>1-2 round trips</td>
</tr>
</tbody>
</table>
<p>Task-oriented tools need server-side logic. That&#8217;s fine — it&#8217;s your server.</p>
<h2 id="step-3-write-schemas-the-model-can-read">Step 3: Write schemas the model can read</h2>
<p>Every tool needs a <code>name</code>, a <code>description</code> that reads like an instruction, and an <code>inputSchema</code> in JSON Schema. Descriptions carry more weight than you&#8217;d expect: the model selects tools by matching the user&#8217;s words against them.</p>
<p>Write descriptions that include the trigger conditions. &#8220;Search invoices. Use when the user asks about billing history, overdue amounts, or a specific invoice number&#8221; beats &#8220;Search invoices&#8221; by a wide margin in my testing. Avoid clever names — <code>find_invoices</code> is better than <code>invQ</code>.</p>
<p>Use <code>zod</code> for validation. Mark required fields as required; models do respect <code>required</code> arrays, but only if you also reject bad input rather than coercing it.</p>
<h2 id="step-4-handle-errors-as-tool-results-not-exceptions">Step 4: Handle errors as tool results, not exceptions</h2>
<p>This is the item that separates a toy server from a usable one. If your handler throws, the client sees a transport error and the conversation stalls. Instead, return a result with <code>isError: true</code> and a message the model can act on.</p>
<p>Say the API returns 429. Return something like &#8220;Rate limited, retry after 30 seconds&#8221; rather than a stack trace. The model will wait or tell the user. A raw exception gets you a broken turn.</p>
<p>Also: never return a whole JSON blob if a short summary works. Token cost is real, and dumping 400 invoice rows fills the context window in one call. Paginate with a default page size of 20.</p>
<h2 id="step-5-wire-up-stdio-then-add-to-the-client">Step 5: Wire up stdio, then add to the client</h2>
<pre><code>const transport = new StdioServerTransport();
await server.connect(transport);
</code></pre>
<p>Stdio means the client launches your process and speaks over stdin/stdout. Two rules follow: <strong>never write logs to stdout</strong> (it corrupts the protocol — use stderr), and keep startup under a few seconds, because clients time out fast.</p>
<p>For local development, test in the MCP Inspector before wiring it into Claude Desktop. Build the config entry with <code>command: "node"</code> and <code>args: ["/absolute/path/to/build/index.js"]</code>.</p>
<h2 id="should-you-use-stdio-or-http-transport">Should you use stdio or HTTP transport?</h2>
<p>Stdio for anything local: it&#8217;s simpler, needs no auth, and dies when the client closes. HTTP with the streamable transport for anything shared across machines or served to a team. Multi-user HTTP needs real auth — an unauthenticated MCP endpoint exposed to the internet is an open door to whatever API keys you hold.</p>
<h2 id="when-is-a-custom-server-overkill">When is a custom server overkill?</h2>
<p>If your need is one or two read-only calls, a script plus a paste beats a protocol. If you&#8217;re the only user and you never change editors, a shell alias works. Build a server when you want the same capability available in several MCP clients, or when teammates should reuse it without copying configs.</p>
<h2 id="quick-summary">Quick Summary</h2>
<ul>
<li>The official SDK scaffolds an MCP server in under 100 lines with stdio transport.</li>
<li>Design 3-6 tools around user tasks, not one per API endpoint.</li>
<li>Tool descriptions are prompts: include when to use the tool.</li>
<li>Return errors as <code>isError</code> results with actionable text, never as thrown exceptions.</li>
<li>Log to stderr only; anything on stdout breaks the protocol.</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.iaifeed.com/how-to-build-custom-mcp-server-for-your-own-api/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Connect an MCP Server to Claude Desktop in 10 Minutes</title>
		<link>https://www.iaifeed.com/how-to-connect-mcp-server-to-claude-desktop</link>
					<comments>https://www.iaifeed.com/how-to-connect-mcp-server-to-claude-desktop#respond</comments>
		
		<dc:creator><![CDATA[iamltlb]]></dc:creator>
		<pubDate>Tue, 20 Oct 2026 12:42:33 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[mcp]]></category>
		<guid isPermaLink="false">https://www.iaifeed.com/how-to-connect-mcp-server-to-claude-desktop</guid>

					<description><![CDATA[MCP is an open protocol that lets Claude Desktop call local tools. Config file location, a working filesystem server, and the two errors everyone hits first.]]></description>
										<content:encoded><![CDATA[<p><a href="https://www.iaifeed.com/ai-tool/mcp">MCP</a> (Model Context Protocol) is an open standard, published by Anthropic in late 2024, that lets a chat client call external tools through a small JSON config file. To connect a server to Claude Desktop you edit <code>claude_desktop_config.json</code>, add a <code>command</code> and <code>args</code> entry, restart the app, and the tools appear in the input box.</p>
<p>That&#8217;s the whole loop. The friction is entirely in the paths and the JSON.</p>
<h2 id="what-is-mcp-and-why-should-you-care">What is MCP and why should you care?</h2>
<p>MCP is a protocol that defines how an AI client asks a server what it can do, then calls those capabilities. Think of it as a USB port for AI: one server for your filesystem, one for Postgres, one for GitHub, and any MCP-speaking client can use all of them without custom code per app.</p>
<p>Claude Desktop, Cursor, and a growing list of editors speak MCP natively. Servers exist in Node and Python, and the reference ones live under <code>modelcontextprotocol/servers</code> on GitHub.</p>
<p>You need this if you keep copying data into chat windows by hand. You don&#8217;t need it if a plain API key plus a script already solves your problem.</p>
<h2 id="step-1-find-the-config-file-the-part-people-get-wrong">Step 1: Find the config file (the part people get wrong)</h2>
<p>The file is not inside the app bundle. It lives in your user profile:</p>
<ul>
<li><strong>macOS:</strong> <code>~/Library/Application Support/Claude/claude_desktop_config.json</code></li>
<li><strong>Windows:</strong> <code>%APPDATA%\Claude\claude_desktop_config.json</code></li>
<li><strong>Linux:</strong> <code>~/.config/Claude/claude_desktop_config.json</code></li>
</ul>
<p>If the file doesn&#8217;t exist, create it. Claude Desktop will not generate it for you, and it silently ignores a file saved with a <code>.txt</code> extension — a surprisingly common cause of &#8220;nothing happened&#8221;.</p>
<h2 id="step-2-install-node-18-or-newer-first">Step 2: Install Node 18 or newer first</h2>
<p>Most reference servers are npm packages run through <code>npx</code>. Check with <code>node -v</code>. Anything below 18 fails on modern syntax, and on Windows you&#8217;ll want the plain <code>node</code> install rather than a version manager shim, because Claude Desktop launches the process without your shell&#8217;s PATH.</p>
<p>That PATH detail explains half of all broken setups: the app can find <code>node</code> interactively but not when it spawns the server. If <code>npx</code> isn&#8217;t on the system path, use an absolute path like <code>/usr/local/bin/npx</code> or <code>C:\\Program Files\\nodejs\\npx.cmd</code>.</p>
<h2 id="step-3-add-your-first-server">Step 3: Add your first server</h2>
<p>Open the config and paste this, adjusting the folder to one you actually want readable:</p>
<pre><code>{
  &quot;mcpServers&quot;: {
    &quot;filesystem&quot;: {
      &quot;command&quot;: &quot;npx&quot;,
      &quot;args&quot;: [
        &quot;-y&quot;,
        &quot;@modelcontextprotocol/server-filesystem&quot;,
        &quot;/Users/you/Projects&quot;
      ]
    }
  }
}
</code></pre>
<p>Three rules: the top key must be <code>mcpServers</code>, every entry needs <code>command</code>, and on Windows <code>command</code> must be <code>npx.cmd</code> not <code>npx</code>. Save as UTF-8 with no BOM.</p>
<h2 id="step-4-restart-completely-not-just-the-window">Step 4: Restart completely, not just the window</h2>
<p>Quit Claude Desktop from the menu — on macOS <code>Cmd+Q</code>, not the red close button. The app only reads the config file at process start. After relaunch, look for a small plug icon or a tools badge in the message input; hovering shows which server it is and how many tools it exposes. The filesystem server typically reports 11 tools.</p>
<p>If the icon is missing entirely, the config didn&#8217;t parse. Validate it with <code>python3 -m json.tool claude_desktop_config.json</code> before doing anything else.</p>
<h2 id="step-5-test-with-a-request-that-proves-file-access">Step 5: Test with a request that proves file access</h2>
<p>Ask: &#8220;List the files in my Projects folder and summarise any README.&#8221; Claude will request permission the first time — approval is per-client, not per-session. Deny it and the tool stays unavailable until you flip it back in settings.</p>
<p>Good first tests are cheap and verifiable. &#8220;What&#8217;s in package.json?&#8221; beats &#8220;organise my whole drive&#8221;, which burns context and usually disappoints.</p>
<h2 id="how-do-you-debug-a-server-that-wont-start">How do you debug a server that won&#8217;t start?</h2>
<p>Enable the log file and read it. On macOS, tail <code>~/Library/Logs/Claude/</code> and open the file named for your server (logs are written per server). On Windows it&#8217;s under <code>%APPDATA%\Claude\logs</code>. You want the last error, not the whole file.</p>
<p>The two failures I see most:</p>
<ul>
<li><code>spawn npx ENOENT</code> — the PATH problem above. Use an absolute command path.</li>
<li><code>Server disconnected</code> after a few seconds — usually a crashed package. Run the exact <code>command</code> + <code>args</code> in your terminal and watch the error appear immediately.</li>
</ul>
<h2 id="is-running-mcp-servers-risky">Is running MCP servers risky?</h2>
<p>Yes, in a specific way: the filesystem server can read whatever path you give it, and some community servers accept arbitrary shell commands. Scope directories narrowly. Give the filesystem server your <code>Projects</code> folder, never your home directory. Review any third-party server&#8217;s source before pointing it at credentials — you&#8217;re handing a model the keys.</p>
<h2 id="quick-summary">Quick Summary</h2>
<ul>
<li>MCP connects Claude Desktop to local tools through <code>claude_desktop_config.json</code>.</li>
<li>The file lives in the user profile, not the app folder, and must be UTF-8 JSON.</li>
<li>Node 18+ is required; use absolute paths to <code>npx</code> to avoid the PATH error.</li>
<li>Fully quit and relaunch the app — the config is read at startup only.</li>
<li>Scope filesystem servers to specific folders, not your whole home directory.</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.iaifeed.com/how-to-connect-mcp-server-to-claude-desktop/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
