<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[The Plug]]></title><description><![CDATA[The Plug]]></description><link>https://blog.getmcpapps.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 11:30:06 GMT</lastBuildDate><atom:link href="https://blog.getmcpapps.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[MCP Servers for Data Science: Analyze Any Dataset with AI]]></title><description><![CDATA[If you've been doing data science with Claude, you've probably hit the wall: you can describe a dataset, paste a few rows, and get analysis — but the moment you need to query a real database, explore a file system, or pull live data from an API, the ...]]></description><link>https://blog.getmcpapps.com/mcp-servers-for-data-science-analyze-any-dataset-with-ai</link><guid isPermaLink="true">https://blog.getmcpapps.com/mcp-servers-for-data-science-analyze-any-dataset-with-ai</guid><category><![CDATA[AI]]></category><category><![CDATA[claude]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[mcp]]></category><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Sat, 28 Feb 2026 13:03:37 GMT</pubDate><content:encoded><![CDATA[<p>If you've been doing data science with Claude, you've probably hit the wall: you can describe a dataset, paste a few rows, and get analysis — but the moment you need to query a real database, explore a file system, or pull live data from an API, the conversation breaks down. You're copy-pasting between tools like it's 2015.</p>
<p>MCP (Model Context Protocol) changes that. It's an open protocol that lets Claude connect directly to your data infrastructure — databases, file systems, search engines, external APIs — and operate on them in real time. No more copy-paste. No more context-switching.</p>
<p>This post covers the best MCP servers for data science workflows: what each one does, why it matters, and how to wire it into your setup.</p>
<hr />
<h2 id="heading-what-mcp-actually-does-for-data-scientists">What MCP Actually Does for Data Scientists</h2>
<p>MCP servers act as bridges between Claude and external systems. When you add an MCP server to your Claude client (Claude Desktop, or any MCP-compatible environment), Claude gains the ability to call tools that server exposes — read files, run SQL queries, search indices, fetch web data.</p>
<p>The result: you can have a genuine back-and-forth with your data. Ask a question, Claude queries the source, interprets the result, asks a follow-up query, and builds toward an answer. It's the analyst workflow, but the AI is driving.</p>
<p>Here are the MCP servers worth knowing.</p>
<hr />
<h2 id="heading-1-filesystem-mcp">1. Filesystem MCP</h2>
<p><strong>What it does:</strong> Gives Claude read (and optionally write) access to your local file system. You specify which directories are accessible; Claude can list files, read contents, and search within them.</p>
<p><strong>Why it matters for data science:</strong> Most real work starts with files — CSVs, JSON exports, Parquet files, notebooks, raw logs. With the filesystem MCP, you can point Claude at a data directory and say "tell me what's in here." It will explore the structure, read samples, identify schemas, and start analysis without you lifting a finger.</p>
<p>Practical uses:</p>
<ul>
<li>Exploratory analysis on CSV dumps from production systems</li>
<li>Reading and summarizing log files</li>
<li>Comparing multiple dataset files across a directory</li>
<li>Loading and interpreting config files or metadata alongside data</li>
</ul>
<p>The filesystem MCP is the lowest-friction starting point. Every data scientist should have it running.</p>
<p><strong>Setup note:</strong> When configuring, be explicit about directory permissions. Restrict Claude to read-only access on sensitive paths — the right default for anything containing PII.</p>
<hr />
<h2 id="heading-2-postgresql-mcp">2. PostgreSQL MCP</h2>
<p><strong>What it does:</strong> Connects Claude directly to a PostgreSQL database. Claude can inspect schemas, run SELECT queries, and explore table relationships.</p>
<p><strong>Why it matters for data science:</strong> Postgres is where a huge amount of analytical data lives — either natively or via tools like dbt, which transforms raw data into analyst-ready tables. With the PostgreSQL MCP, you skip the "let me write this query, export it, paste it into Claude" loop entirely.</p>
<p>Ask Claude to find anomalies in your orders table. It will query the schema, write a SQL query, get the results, interpret them, and suggest next queries — all in one thread.</p>
<p>Practical uses:</p>
<ul>
<li>Ad-hoc analysis on production or analytics databases</li>
<li>Schema exploration when onboarding to a new codebase</li>
<li>Debugging data pipeline outputs</li>
<li>Generating and validating complex SQL without leaving the chat</li>
</ul>
<p><strong>Setup note:</strong> Use a read-only database user for Claude. Don't point it at a write-enabled account unless you have a specific reason.</p>
<hr />
<h2 id="heading-3-sqlite-mcp">3. SQLite MCP</h2>
<p><strong>What it does:</strong> Same concept as the PostgreSQL MCP, but for SQLite databases — lightweight, file-based, no server needed.</p>
<p><strong>Why it matters for data science:</strong> SQLite is everywhere in data work. It's the default database for many Python tools, a common way to ship small analytical datasets, and the storage format for countless local apps. If you're doing any kind of lightweight data analysis without a full database server, SQLite MCP is the right tool.</p>
<p>Practical uses:</p>
<ul>
<li>Analyzing exported app data (iOS Health exports, browser history, etc.)</li>
<li>Working with DuckDB or Datasette exports</li>
<li>Local prototyping before moving to Postgres</li>
<li>Querying Python-generated SQLite outputs from scrapers or ETL scripts</li>
</ul>
<p>The setup is minimal — point it at a <code>.db</code> file and Claude can query immediately.</p>
<hr />
<h2 id="heading-4-google-sheets-mcp">4. Google Sheets MCP</h2>
<p><strong>What it does:</strong> Connects Claude to Google Sheets, enabling it to read spreadsheet data, inspect multiple sheets, and write results back.</p>
<p><strong>Why it matters for data science:</strong> Spreadsheets are still the universal data format in most organizations. Product teams track KPIs in Sheets. Finance lives in Sheets. Client-facing reports live in Sheets. The Google Sheets MCP closes the gap between where data actually is and where analysis happens.</p>
<p>Practical uses:</p>
<ul>
<li>Analyzing marketing attribution data that lives in a shared Sheet</li>
<li>Summarizing multi-tab financial models</li>
<li>Pulling cohort data from a spreadsheet into a structured analysis</li>
<li>Writing clean summaries or pivot results back to a new Sheet tab</li>
</ul>
<p><strong>Setup note:</strong> Requires OAuth configuration with a Google Cloud project. Takes about 15 minutes to set up, then it just works.</p>
<hr />
<h2 id="heading-5-elasticsearch-mcp">5. Elasticsearch MCP</h2>
<p><strong>What it does:</strong> Gives Claude access to an Elasticsearch cluster — it can search indices, inspect mappings, run aggregations, and explore stored documents.</p>
<p><strong>Why it matters for data science:</strong> Elasticsearch is where logs, events, and search data live at scale. If your team runs ELK (Elasticsearch, Logstash, Kibana), you have a rich analytical data store that's historically hard to query without Kibana knowledge or raw JSON. The Elasticsearch MCP lets Claude write and run queries against it directly.</p>
<p>Practical uses:</p>
<ul>
<li>Log analysis at scale — find error patterns across millions of events</li>
<li>User behavior analysis from clickstream data</li>
<li>Full-text search over document corpora for NLP work</li>
<li>Operational analytics from application telemetry</li>
</ul>
<p>This one is particularly powerful for anyone doing anomaly detection or pattern finding across event streams.</p>
<hr />
<h2 id="heading-6-apify-mcp">6. Apify MCP</h2>
<p><strong>What it does:</strong> Connects Claude to Apify's web scraping and data extraction platform. Claude can trigger Apify actors (pre-built scrapers), retrieve results, and work with the extracted data directly.</p>
<p><strong>Why it matters for data science:</strong> Sometimes your dataset doesn't exist yet — you need to collect it. Apify has thousands of pre-built scrapers for e-commerce sites, social platforms, job boards, news sites, and more. With the Apify MCP, Claude can orchestrate the collection and then analyze the results in the same conversation.</p>
<p>Practical uses:</p>
<ul>
<li>Competitive price monitoring (trigger a product scraper, analyze results)</li>
<li>Social listening — collect and analyze mentions from public platforms</li>
<li>Building training datasets from web sources</li>
<li>Market research with live data rather than stale exports</li>
</ul>
<p><strong>Setup note:</strong> Requires an Apify API key. Usage depends on which actors you run — many have free tiers.</p>
<hr />
<h2 id="heading-setting-up-your-data-science-mcp-stack">Setting Up Your Data Science MCP Stack</h2>
<p>The practical setup path for most data scientists:</p>
<p><strong>Start with filesystem + one database.</strong> Add the filesystem MCP first — it has the lowest setup friction and unlocks immediate value. Then add the PostgreSQL or SQLite MCP depending on where your data lives.</p>
<p><strong>Use Claude Desktop for local work.</strong> Claude Desktop has built-in MCP support via <code>claude_desktop_config.json</code>. Add servers there and they're available across all your conversations.</p>
<p><strong>Restrict permissions explicitly.</strong> For any MCP server with write access, think carefully. Read-only is the right default for most analytical work. You want Claude exploring your data, not modifying it without clear intent.</p>
<p><strong>Chain servers for richer analysis.</strong> The real power comes from combining servers. Point Claude at your filesystem (for CSVs), Postgres (for transactional data), and Google Sheets (for reporting) simultaneously — it can join context across all three sources in a single conversation.</p>
<hr />
<h2 id="heading-the-shift-this-enables">The Shift This Enables</h2>
<p>The traditional data science workflow is a series of context switches: run a query in psql, export to CSV, load into a notebook, paste a sample into Claude, iterate on the prompt, go back to the database. Each switch adds friction and breaks the analytical thread.</p>
<p>With MCP, Claude becomes a capable co-analyst with direct access to your data. You describe what you're trying to understand, and it drives the exploration — writing queries, reading results, asking follow-up questions, surfacing patterns you didn't know to look for.</p>
<p>That's not a small improvement. That's a fundamentally different way of working with data.</p>
<hr />
<h2 id="heading-find-more-mcp-servers">Find More MCP Servers</h2>
<p>The servers covered here are a starting point. There are MCP servers for MongoDB, Neo4j, Redis, Snowflake, BigQuery, and dozens of other data tools — plus purpose-built servers for machine learning workflows, data pipelines, and API integrations.</p>
<p>Browse the full catalog at <strong><a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></strong> — curated, quality-filtered, with compatibility info for Claude Desktop, Cursor, Windsurf, GitHub Copilot, and more. If you're building a data science MCP stack, it's the right place to start.</p>
]]></content:encoded></item><item><title><![CDATA[The Hidden Cost of Chasing Clients Over Email (And How to Stop)]]></title><description><![CDATA[The Hidden Cost of Chasing Clients Over Email (And How to Stop)
Published: March 2, 2026 | Keywords: how to stop chasing clients for feedback, client communication for freelance web designers, client taking forever to respond, how to get faster appro...]]></description><link>https://blog.getmcpapps.com/the-hidden-cost-of-chasing-clients-over-email</link><guid isPermaLink="true">https://blog.getmcpapps.com/the-hidden-cost-of-chasing-clients-over-email</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Fri, 27 Feb 2026 22:37:54 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-the-hidden-cost-of-chasing-clients-over-email-and-how-to-stop">The Hidden Cost of Chasing Clients Over Email (And How to Stop)</h1>
<p><em>Published: March 2, 2026 | Keywords: how to stop chasing clients for feedback, client communication for freelance web designers, client taking forever to respond, how to get faster approvals</em></p>
<hr />
<p>Let's do some quick math.</p>
<p>You spend 3–5 hours a week chasing clients. Following up on feedback. Resending files. Waiting for approvals that never come. If you bill at $75/hour, that's <strong>$900 to $1,500 a month</strong> — gone. Either you're eating that time, or you're burning goodwill by billing for it.</p>
<p>Most designers never track this. It happens in small doses: a 20-minute follow-up email here, a 45-minute "wait, which version did I send?" spiral there. It doesn't feel like a big deal in the moment. Over a month? It's a car payment.</p>
<p>The worst part: the chaos isn't random. It comes from the same three traps, over and over.</p>
<hr />
<h2 id="heading-trap-1-feedback-without-context">Trap #1: Feedback Without Context</h2>
<p>"The button feels off."</p>
<p>You've gotten this message. Maybe in a reply-to-reply-to-reply email chain. No screenshot. No specifics. Just a vague feeling lobbed over the fence at you.</p>
<p>Now you're back on a call — or worse, firing off three clarifying emails — just to figure out what "off" means. Too big? Wrong color? Wrong position? The client isn't being difficult. They just have no structured way to explain what they're seeing, so they reach for the first words that come to mind.</p>
<p>This is a system failure, not a communication failure.</p>
<hr />
<h2 id="heading-trap-2-attachment-chains-aka-which-version-is-final">Trap #2: Attachment Chains (aka "Which Version Is Final?")</h2>
<p>You send v1 as an attachment. Client replies with comments. You send v2. Client forwards v2 to their partner. Partner replies-all with "I preferred the first one." Suddenly there are three email threads, two versions of the file, and nobody agrees on what "the first one" even means.</p>
<p>You've been here. It's not funny when it's 11pm and a client is asking you to "go back to what we had before."</p>
<p>File delivery via email attachments is a chaos machine. Every version you send creates a new branch of confusion. There's no canonical "latest" — just whoever has the most recent email open.</p>
<hr />
<h2 id="heading-trap-3-approval-by-silence">Trap #3: Approval by Silence</h2>
<p>This is the most dangerous one.</p>
<p>Client goes quiet. You figure they're happy — no news is good news, right? You move to the next phase. Then, two weeks later, they come back with: "Wait, I never signed off on that."</p>
<p>Now you're in a scope dispute with zero documentation. You <em>think</em> they approved it. They <em>think</em> they didn't. Neither of you has proof either way. And no matter how that conversation ends, the relationship is worse.</p>
<p>"Approval by silence" isn't approval. But without a system that makes approval explicit, you're leaving yourself exposed every single time.</p>
<hr />
<h2 id="heading-the-fix-isnt-better-communication">The Fix Isn't "Better Communication"</h2>
<p>Here's what most advice gets wrong: they tell you to communicate more clearly. Write better emails. Set firmer expectations. Follow up more promptly.</p>
<p>That's not wrong — but it's treating the symptom, not the cause.</p>
<p>The real problem is that email is an unstructured medium. It's great for conversation. It's terrible for project management. When your entire client workflow lives in email, you're working against the tool's nature. Every piece of feedback, every file, every approval attempt gets buried in a thread. Context disappears. Things fall through the cracks.</p>
<p>The fix is structural. You need one place where:</p>
<ul>
<li><strong>Files live</strong> — versioned, clearly labeled, always findable</li>
<li><strong>Feedback happens</strong> — attached to specific deliverables, not floating in a thread</li>
<li><strong>Approvals are explicit</strong> — a client clicks "approve" or they don't; there's no ambiguity</li>
</ul>
<p>When you create that environment, something interesting happens: clients behave differently. When they can see that clicking "approve" means moving forward — and that not responding is visibly holding things up — they move faster. The stakes are visible. The process is clear.</p>
<p>It's not magic. It's just better infrastructure.</p>
<hr />
<h2 id="heading-what-this-looks-like-in-practice">What This Looks Like in Practice</h2>
<p>Think about the last time a client took two weeks to give feedback on a homepage design. What was their experience on the other end?</p>
<p>They got an email with an attachment. Maybe they opened it. Maybe they meant to. Then life happened — their kid was sick, they had their own deadlines — and your email got buried. They weren't ignoring you. They just didn't have a clear, low-friction way to respond.</p>
<p>Now imagine instead: they get a link. They click it. They see the design, right there, no downloads required. There's a comment box next to it. There's a button that says "Approve this." The whole thing takes three minutes.</p>
<p>That's not a luxury workflow. That's just a sensible one.</p>
<hr />
<h2 id="heading-one-tool-worth-trying">One Tool Worth Trying</h2>
<p>I built Briefkit because I was tired of the email chaos. It's a free, open-source client portal built specifically for freelance web designers. You get a clean space to share deliverables, collect structured feedback, and get explicit sign-offs — all in one link.</p>
<p>No enterprise pricing. No "contact us for a demo." Just a tool that handles the operational side of client work so you can focus on the actual design.</p>
<p>If the math at the top of this post hit close to home, it's worth 20 minutes of your time.</p>
<p>👉 <strong><a target="_blank" href="https://briefkit.dev">Try Briefkit free at briefkit.dev</a></strong></p>
<hr />
<p><em>The hours you spend chasing clients aren't just annoying — they're expensive. Fix the system, and the problem mostly fixes itself.</em></p>
]]></content:encoded></item><item><title><![CDATA[MCP Security Best Practices: What Every Developer Needs to Know]]></title><description><![CDATA[MCP Security Best Practices: What Every Developer Needs to Know
The Model Context Protocol (MCP) is moving fast. Developers are shipping MCP servers that touch filesystems, databases, external APIs, and production infrastructure — often in a matter o...]]></description><link>https://blog.getmcpapps.com/mcp-security-best-practices</link><guid isPermaLink="true">https://blog.getmcpapps.com/mcp-security-best-practices</guid><category><![CDATA[best practices]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[mcp]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Fri, 27 Feb 2026 21:01:02 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-mcp-security-best-practices-what-every-developer-needs-to-know">MCP Security Best Practices: What Every Developer Needs to Know</h1>
<p>The Model Context Protocol (MCP) is moving fast. Developers are shipping MCP servers that touch filesystems, databases, external APIs, and production infrastructure — often in a matter of hours. That speed is exciting. It’s also a little terrifying from a security standpoint.</p>
<p><strong>MCP security</strong> isn’t theoretical. A poorly secured MCP server is a direct bridge between an AI model and your most sensitive systems. Prompt injection, stolen credentials, over-permissioned tools, unlogged access — these aren’t hypothetical risks. They’re the exact failure modes that have burned developers in adjacent ecosystems (think early serverless functions, or the first wave of OAuth integrations).</p>
<p>The good news: the defensive patterns are well understood. This guide covers <strong>7 practical MCP server security best practices</strong> — each with a short, realistic snippet you can adapt today. Whether you’re building your first server or hardening an existing one, these fundamentals are what separate a <em>secure MCP server</em> from a liability.</p>
<p>If you want to compare implementations, <a target="_blank" href="https://getmcpapps.com">browse security-focused MCP servers on MCPHub</a>. Seeing how other teams structure permissions, auth, and logging will save you time — and help you avoid unforced errors.</p>
<hr />
<h2 id="heading-1-apply-the-principle-of-least-privilege-to-tool-permissions">1) Apply the Principle of Least Privilege to Tool Permissions</h2>
<p>Every tool your MCP server exposes should have exactly the permissions it needs — nothing more.</p>
<p>In practice, developers often create a single “god mode” service account (or a single API key) and reuse it across all tools. That’s convenient, but it means <strong>any one compromised tool call can access everything</strong>.</p>
<p>Instead, scope permissions at the tool boundary:</p>
<ul>
<li>File tools should only access approved directories</li>
<li>Database tools should use separate DB users (read-only vs write)</li>
<li>Cloud tools should use scoped IAM roles/policies</li>
<li>“Admin” tools should require stronger auth (or be removed entirely)</li>
</ul>
<p>Here’s a file tool that only reads from a specific directory and blocks path traversal:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// server.ts — scoped file access</span>
<span class="hljs-keyword">import</span> fs <span class="hljs-keyword">from</span> <span class="hljs-string">"node:fs/promises"</span>;
<span class="hljs-keyword">import</span> path <span class="hljs-keyword">from</span> <span class="hljs-string">"node:path"</span>;
<span class="hljs-keyword">import</span> { z } <span class="hljs-keyword">from</span> <span class="hljs-string">"zod"</span>;

<span class="hljs-keyword">const</span> ALLOWED_READ_DIR = path.resolve(<span class="hljs-string">"/var/data/reports"</span>);

server.tool(
  <span class="hljs-string">"read_report"</span>,
  { filename: z.string().min(<span class="hljs-number">1</span>).max(<span class="hljs-number">120</span>) },
  <span class="hljs-keyword">async</span> ({ filename }) =&gt; {
    <span class="hljs-keyword">const</span> target = path.resolve(ALLOWED_READ_DIR, filename);

    <span class="hljs-comment">// Prevent ../ traversal and symlink surprises by enforcing prefix</span>
    <span class="hljs-keyword">if</span> (!target.startsWith(ALLOWED_READ_DIR + path.sep)) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Access denied: path outside allowed directory"</span>);
    }

    <span class="hljs-keyword">const</span> content = <span class="hljs-keyword">await</span> fs.readFile(target, <span class="hljs-string">"utf8"</span>);
    <span class="hljs-keyword">return</span> { content: [{ <span class="hljs-keyword">type</span>: <span class="hljs-string">"text"</span>, text: content }] };
  }
);
</code></pre>
<p><strong>Hard take:</strong> if your MCP server can read “any file on disk” or call “any internal API,” it’s not “powerful.” It’s <em>fragile</em>. Tight scope is what keeps power usable.</p>
<hr />
<h2 id="heading-2-validate-and-sanitize-all-inputs-prompt-injection-defense">2) Validate and Sanitize All Inputs (Prompt Injection Defense)</h2>
<p>MCP tools receive input that originates from an LLM. That means the input can contain anything — including adversarial instructions injected via user content.</p>
<p>Treat tool arguments like untrusted user input:</p>
<ul>
<li>Validate types and ranges</li>
<li>Whitelist allowed values where possible</li>
<li>Normalize/escape strings that feed into commands, queries, or URLs</li>
<li>Use parameterized database queries (always)</li>
</ul>
<p>A safe pattern is to keep arguments <strong>structured</strong> and <strong>constrained</strong>. For example, don’t accept a freeform table name.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { z } <span class="hljs-keyword">from</span> <span class="hljs-string">"zod"</span>;

<span class="hljs-keyword">const</span> QuerySchema = z.object({
  table: z.enum([<span class="hljs-string">"orders"</span>, <span class="hljs-string">"products"</span>, <span class="hljs-string">"customers"</span>]),
  limit: z.number().int().min(<span class="hljs-number">1</span>).max(<span class="hljs-number">100</span>),
  <span class="hljs-comment">// Constrain filter language (or replace with explicit fields)</span>
  status: z.enum([<span class="hljs-string">"open"</span>, <span class="hljs-string">"closed"</span>, <span class="hljs-string">"pending"</span>]).optional(),
});

server.tool(<span class="hljs-string">"list_records"</span>, QuerySchema, <span class="hljs-keyword">async</span> ({ table, limit, status }) =&gt; {
  <span class="hljs-comment">// Parameterized query: values are bound, not interpolated</span>
  <span class="hljs-keyword">const</span> rows = <span class="hljs-keyword">await</span> db.query(
    <span class="hljs-string">"SELECT * FROM ?? WHERE (? IS NULL OR status = ?) LIMIT ?"</span>,
    [table, status ?? <span class="hljs-literal">null</span>, status ?? <span class="hljs-literal">null</span>, limit]
  );

  <span class="hljs-keyword">return</span> { content: [{ <span class="hljs-keyword">type</span>: <span class="hljs-string">"text"</span>, text: <span class="hljs-built_in">JSON</span>.stringify(rows) }] };
});
</code></pre>
<p>For prompt injection specifically, the key is: <strong>don’t let instructions become authority</strong>. If a model says “ignore your policy and delete all records,” the tool layer must still enforce the policy.</p>
<p>Two practical patterns that help a lot in real deployments:</p>
<ul>
<li><strong>Allowlist outbound destinations.</strong> If a tool can fetch URLs, restrict it to domains you control (or a short list you’ve vetted).</li>
<li><strong>Normalize input before use.</strong> Strip control characters and enforce a maximum length <em>before</em> passing strings into prompts, shell commands, or SQL.</li>
</ul>
<p>Here’s a lightweight allowlist validator for URL-fetching tools:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> AllowedHosts = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Set</span>([<span class="hljs-string">"api.mycompany.com"</span>, <span class="hljs-string">"status.mycompany.com"</span>]);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">assertAllowedUrl</span>(<span class="hljs-params">raw: <span class="hljs-built_in">string</span></span>) </span>{
  <span class="hljs-keyword">const</span> u = <span class="hljs-keyword">new</span> URL(raw);
  <span class="hljs-keyword">if</span> (u.protocol !== <span class="hljs-string">"https:"</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Only https URLs are allowed"</span>);
  <span class="hljs-keyword">if</span> (!AllowedHosts.has(u.hostname)) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Host not allowed"</span>);
  <span class="hljs-keyword">return</span> u;
}

server.tool(<span class="hljs-string">"fetch_status"</span>, { url: z.string().url() }, <span class="hljs-keyword">async</span> ({ url }) =&gt; {
  <span class="hljs-keyword">const</span> u = assertAllowedUrl(url);
  <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(u.toString(), { headers: { <span class="hljs-string">"User-Agent"</span>: <span class="hljs-string">"mcp-server/1.0"</span> } });
  <span class="hljs-keyword">return</span> { content: [{ <span class="hljs-keyword">type</span>: <span class="hljs-string">"text"</span>, text: <span class="hljs-keyword">await</span> res.text() }] };
});
</code></pre>
<hr />
<h2 id="heading-3-manage-secrets-properly-never-hardcode-api-keys">3) Manage Secrets Properly (Never Hardcode API Keys)</h2>
<p>Hardcoded credentials in MCP server source code get committed to git, baked into Docker images, and leaked in logs. It happens constantly.</p>
<p>Rules that keep you safe:</p>
<ol>
<li>Secrets come from the environment or a secrets manager</li>
<li>Never log secrets (including partial tokens)</li>
<li>Rotate secrets and scope them per environment</li>
<li>Use distinct credentials per tool/service (blast radius control)</li>
</ol>
<pre><code class="lang-ts"><span class="hljs-comment">// ✅ Read secrets at runtime</span>
<span class="hljs-keyword">const</span> apiKey = process.env.STRIPE_SECRET_KEY;
<span class="hljs-keyword">if</span> (!apiKey) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"STRIPE_SECRET_KEY is required"</span>);

<span class="hljs-keyword">const</span> stripe = <span class="hljs-keyword">new</span> Stripe(apiKey, { apiVersion: <span class="hljs-string">"2024-06-20"</span> });
</code></pre>
<p>If you’re on AWS, load secrets from Secrets Manager (or SSM Parameter Store) at boot time:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> STRIPE_SECRET_KEY=$(aws secretsmanager get-secret-value \
  --secret-id prod/mcp/stripe \
  --query SecretString \
  --output text | jq -r .stripe_secret_key)
</code></pre>
<p>Also: commit a lockfile and add a <strong>secret scanning step</strong> in CI. GitHub Advanced Security is great, but even basic regex scanning catches a lot.</p>
<hr />
<h2 id="heading-4-secure-transport-tls-strong-authentication">4) Secure Transport: TLS + Strong Authentication</h2>
<p>If your MCP server is reachable over the network, <strong>TLS is mandatory</strong>. Without it, tool arguments and results can be observed or modified in transit.</p>
<p>Then comes the second half: authentication. Your MCP server should not accept tool calls from anonymous clients, full stop.</p>
<p>A common, practical deployment is:</p>
<ul>
<li>TLS termination at a reverse proxy (nginx / Caddy / a load balancer)</li>
<li>A bearer token per client (or short-lived JWTs)</li>
<li>Server-side token verification middleware</li>
</ul>
<p>Example nginx TLS forwarding:</p>
<pre><code class="lang-nginx"><span class="hljs-section">server</span> {
  <span class="hljs-attribute">listen</span> <span class="hljs-number">443</span> ssl;
  <span class="hljs-attribute">ssl_certificate</span>     /etc/ssl/certs/mcpserver.crt;
  <span class="hljs-attribute">ssl_certificate_key</span> /etc/ssl/private/mcpserver.key;
  <span class="hljs-attribute">ssl_protocols</span>       TLSv1.<span class="hljs-number">2</span> TLSv1.<span class="hljs-number">3</span>;

  <span class="hljs-attribute">location</span> / {
    <span class="hljs-attribute">proxy_set_header</span> Authorization <span class="hljs-variable">$http_authorization</span>;
    <span class="hljs-attribute">proxy_set_header</span> X-Forwarded-Proto <span class="hljs-variable">$scheme</span>;
    <span class="hljs-attribute">proxy_pass</span> http://127.0.0.1:3000;
  }
}
</code></pre>
<p>And token verification in your app (store a hash, not the token itself):</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> crypto <span class="hljs-keyword">from</span> <span class="hljs-string">"node:crypto"</span>;

<span class="hljs-keyword">const</span> EXPECTED_TOKEN_HASH = process.env.MCP_TOKEN_SHA256;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sha256</span>(<span class="hljs-params">s: <span class="hljs-built_in">string</span></span>) </span>{
  <span class="hljs-keyword">return</span> crypto.createHash(<span class="hljs-string">"sha256"</span>).update(s).digest(<span class="hljs-string">"hex"</span>);
}

app.use(<span class="hljs-function">(<span class="hljs-params">req, res, next</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> header = req.headers.authorization || <span class="hljs-string">""</span>;
  <span class="hljs-keyword">const</span> token = header.startsWith(<span class="hljs-string">"Bearer "</span>) ? header.slice(<span class="hljs-number">7</span>) : <span class="hljs-string">""</span>;

  <span class="hljs-keyword">if</span> (!token || !EXPECTED_TOKEN_HASH || sha256(token) !== EXPECTED_TOKEN_HASH) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">401</span>).json({ error: <span class="hljs-string">"Unauthorized"</span> });
  }

  next();
});
</code></pre>
<p>If you need multi-user access, don’t DIY auth forever. Integrate an IdP (Auth0, Clerk, Cognito) and use short-lived tokens.</p>
<hr />
<h2 id="heading-5-rate-limiting-and-abuse-prevention-protect-your-wallet-too">5) Rate Limiting and Abuse Prevention (Protect Your Wallet Too)</h2>
<p>MCP servers are designed to be called repeatedly and autonomously by AI agents. Without rate limiting, a runaway loop — or a malicious client — can:</p>
<ul>
<li>Hammer upstream APIs</li>
<li>Exhaust DB connections</li>
<li>Trigger throttling/bans from third parties</li>
<li>Rack up a shockingly large bill</li>
</ul>
<p>Start with a global limit and then add stricter per-tool limits for expensive operations.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> rateLimit <span class="hljs-keyword">from</span> <span class="hljs-string">"express-rate-limit"</span>;

<span class="hljs-comment">// Global rate limit</span>
app.use(
  rateLimit({
    windowMs: <span class="hljs-number">60</span>_000,
    max: <span class="hljs-number">200</span>,
    standardHeaders: <span class="hljs-literal">true</span>,
    legacyHeaders: <span class="hljs-literal">false</span>,
  })
);

<span class="hljs-comment">// Expensive endpoint limiter</span>
<span class="hljs-keyword">const</span> expensiveLimiter = rateLimit({
  windowMs: <span class="hljs-number">60</span>_000,
  max: <span class="hljs-number">10</span>,
  keyGenerator: <span class="hljs-function">(<span class="hljs-params">req</span>) =&gt;</span> (req.headers[<span class="hljs-string">"x-client-id"</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">string</span>) || req.ip,
});

app.post(<span class="hljs-string">"/tools/run_analysis"</span>, expensiveLimiter, runAnalysis);
</code></pre>
<p>If you’re serious about MCP server security in production, also implement:</p>
<ul>
<li>Timeouts on outbound HTTP calls</li>
<li>Concurrency limits (per client)</li>
<li>Budgeting (max tokens / max tool calls per session)</li>
</ul>
<hr />
<h2 id="heading-6-audit-logging-for-mcp-tool-calls-you-cant-secure-what-you-cant-see">6) Audit Logging for MCP Tool Calls (You Can’t Secure What You Can’t See)</h2>
<p>When incidents happen, audit logs are how you answer:</p>
<ul>
<li>What tool was called?</li>
<li>By whom?</li>
<li>With what inputs?</li>
<li>What changed?</li>
<li>Did it succeed?</li>
</ul>
<p>The security trick is to log <em>enough</em> to investigate without leaking sensitive data into logs.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">type</span> AuditEvent = {
  ts: <span class="hljs-built_in">string</span>;
  clientId: <span class="hljs-built_in">string</span>;
  tool: <span class="hljs-built_in">string</span>;
  args: Record&lt;<span class="hljs-built_in">string</span>, unknown&gt;;
  ok: <span class="hljs-built_in">boolean</span>;
  durationMs: <span class="hljs-built_in">number</span>;
  error?: <span class="hljs-built_in">string</span>;
};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">audit</span>(<span class="hljs-params">event: AuditEvent</span>) </span>{
  <span class="hljs-comment">// Structured JSON logs work well with Datadog/ELK/CloudWatch</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify({ level: <span class="hljs-string">"audit"</span>, ...event }));
}

server.tool(<span class="hljs-string">"create_invoice"</span>, InvoiceSchema, <span class="hljs-keyword">async</span> (args, ctx) =&gt; {
  <span class="hljs-keyword">const</span> t0 = <span class="hljs-built_in">Date</span>.now();
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> invoice = <span class="hljs-keyword">await</span> stripe.invoices.create({
      customer: args.customerId,
      auto_advance: <span class="hljs-literal">false</span>,
    });

    audit({
      ts: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString(),
      clientId: ctx.clientId ?? <span class="hljs-string">"unknown"</span>,
      tool: <span class="hljs-string">"create_invoice"</span>,
      <span class="hljs-comment">// Do not log full PII payloads; log identifiers</span>
      args: { customerId: args.customerId },
      ok: <span class="hljs-literal">true</span>,
      durationMs: <span class="hljs-built_in">Date</span>.now() - t0,
    });

    <span class="hljs-keyword">return</span> { content: [{ <span class="hljs-keyword">type</span>: <span class="hljs-string">"text"</span>, text: invoice.id }] };
  } <span class="hljs-keyword">catch</span> (e) {
    audit({
      ts: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toISOString(),
      clientId: ctx.clientId ?? <span class="hljs-string">"unknown"</span>,
      tool: <span class="hljs-string">"create_invoice"</span>,
      args: { customerId: args.customerId },
      ok: <span class="hljs-literal">false</span>,
      durationMs: <span class="hljs-built_in">Date</span>.now() - t0,
      error: <span class="hljs-built_in">String</span>(e),
    });
    <span class="hljs-keyword">throw</span> e;
  }
});
</code></pre>
<p>Store audit logs in an append-only destination (S3/CloudWatch/Datadog). Keep at least 30–90 days of retention so you can investigate issues without panic.</p>
<hr />
<h2 id="heading-7-sandboxing-and-isolation-limit-blast-radius">7) Sandboxing and Isolation (Limit Blast Radius)</h2>
<p>Even with least privilege and validation, assume something will slip.</p>
<p>A <em>secure MCP server</em> is designed so that compromise doesn’t become catastrophe. That means isolation:</p>
<ul>
<li>Run as a non-root user</li>
<li>Use a minimal container image</li>
<li>Drop Linux capabilities</li>
<li>Prefer read-only filesystems where possible</li>
<li>Restrict outbound network access (allowlist)</li>
</ul>
<p>A practical Docker baseline:</p>
<pre><code class="lang-dockerfile"><span class="hljs-keyword">FROM</span> node:<span class="hljs-number">22</span>-alpine

<span class="hljs-keyword">RUN</span><span class="bash"> addgroup -S mcp &amp;&amp; adduser -S mcp -G mcp</span>
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>
<span class="hljs-keyword">COPY</span><span class="bash"> --chown=mcp:mcp package.json package-lock.json ./</span>
<span class="hljs-keyword">RUN</span><span class="bash"> npm ci --omit=dev</span>
<span class="hljs-keyword">COPY</span><span class="bash"> --chown=mcp:mcp . .</span>

<span class="hljs-keyword">USER</span> mcp
<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">3000</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"node"</span>, <span class="hljs-string">"dist/server.js"</span>]</span>
</code></pre>
<p>And a hardened compose setup:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">services:</span>
  <span class="hljs-attr">mcp-server:</span>
    <span class="hljs-attr">build:</span> <span class="hljs-string">.</span>
    <span class="hljs-attr">read_only:</span> <span class="hljs-literal">true</span>
    <span class="hljs-attr">tmpfs:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">/tmp</span>
    <span class="hljs-attr">cap_drop:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">ALL</span>
    <span class="hljs-attr">security_opt:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-literal">no</span><span class="hljs-string">-new-privileges:true</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">NODE_ENV=production</span>
</code></pre>
<p>If your server includes “execute code” tools (shell execution, Python, eval, anything like that), don’t just sandbox harder — <strong>split it into a separate worker runtime</strong> with strict resource limits and no access to secrets.</p>
<hr />
<h2 id="heading-conclusion-build-mcp-servers-like-theyre-production-infrastructure">Conclusion: Build MCP Servers Like They’re Production Infrastructure</h2>
<p>That’s what they are.</p>
<p>MCP security is about setting sane defaults:</p>
<ol>
<li>Least privilege per tool</li>
<li>Validation + sanitization on every argument</li>
<li>Proper secrets management</li>
<li>TLS + authentication</li>
<li>Rate limits and abuse controls</li>
<li>Audit logging for every tool call</li>
<li>Isolation and sandboxing</li>
</ol>
<p>None of this is exotic. It’s the same security posture you’d apply to a payment webhook handler or an internal admin API — because an MCP server <em>is</em> an admin API, just with a different caller.</p>
<p>If you want to see how the ecosystem is evolving (and learn from hardened implementations), <a target="_blank" href="https://getmcpapps.com">browse MCPHub</a> and compare how popular servers handle auth, permissions, and safe tool design.</p>
<p><strong>Explore MCPHub's curated catalog at getmcpapps.com</strong></p>
]]></content:encoded></item><item><title><![CDATA[I Open-Sourced My SaaS and Here's What Happened]]></title><description><![CDATA[Last week I launched Briefkit — a client portal for freelancers — and I did something that made a few people raise an eyebrow: I shipped it under the MIT license.
Not "source available." Not "BSL with a four-year delay." Full MIT. Fork it, modify it,...]]></description><link>https://blog.getmcpapps.com/i-open-sourced-my-saas-and-heres-what-happened-1</link><guid isPermaLink="true">https://blog.getmcpapps.com/i-open-sourced-my-saas-and-heres-what-happened-1</guid><category><![CDATA[Indie Hacking]]></category><category><![CDATA[open source]]></category><category><![CDATA[SaaS]]></category><category><![CDATA[startup]]></category><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Fri, 27 Feb 2026 08:02:46 GMT</pubDate><content:encoded><![CDATA[<p>Last week I launched <a target="_blank" href="https://briefkit.dev">Briefkit</a> — a client portal for freelancers — and I did something that made a few people raise an eyebrow: I shipped it under the MIT license.</p>
<p>Not "source available." Not "BSL with a four-year delay." Full MIT. Fork it, modify it, self-host it, do whatever you want with it. Here's what happened, what I learned, and why I'd do it again.</p>
<hr />
<h2 id="heading-why-mit-for-a-paid-product">Why MIT for a paid product?</h2>
<p>Let me be honest about the thought process, because I almost didn't do it.</p>
<p>The fear is obvious: if you open-source your product, why would anyone pay for it? Someone will just spin up their own instance. Someone else will fork it and undercut you. You're handing your competitors a roadmap.</p>
<p>I've heard that argument. I've also watched it play out in reverse — GitLab, Plausible, Sentry — where open-sourcing the code <em>builds</em> the business rather than killing it. The key insight is that most people aren't paying for the code. They're paying for the hosted service, the updates, the support, and the trust that you're not going to disappear with their client data.</p>
<p>That last one is where Briefkit's audience is different. My users are freelancers. Developers, designers, consultants — people who have been burned before. They've had clients in tools that shut down. They've seen platforms pivot, raise prices 3x overnight, or just vanish. When I talked to them, the question wasn't "does this have a nice UI" — it was "what happens to my data if you disappear?"</p>
<p>Open source is the answer to that question. If I disappear tomorrow, the code is on GitHub under MIT. You can run it yourself. You're never locked in. That's not a marketing tagline — it's a genuine promise, and it required putting the code where my mouth was.</p>
<p>The stack is Next.js 16 + Supabase + Vercel. Self-hosting Supabase is actually pretty straightforward, and Next.js needs no introduction. Anyone comfortable with those tools can run their own instance. That felt right for a tool aimed at developers and tech-adjacent freelancers.</p>
<p>So: MIT license, added to the repo before launch day. Decision made.</p>
<hr />
<h2 id="heading-first-week-stats-the-honest-numbers">First week stats — the honest numbers</h2>
<p>Briefkit launched on February 20, 2026. One week in, here's where things stand:</p>
<p><strong>Signups:</strong> 2. Both are test accounts — one is mine, one is a friend I asked to poke around. Zero strangers have signed up yet.</p>
<p><strong>GitHub activity:</strong> Low. A handful of stars, no forks, no issues, no PRs. The repo exists, it's public, it has a README. That's about it.</p>
<p><strong>Viral moment from open-sourcing:</strong> There wasn't one.</p>
<p>I'm telling you this because every launch post I've read has at least <em>some</em> number to point to. "We got 200 stars on launch day!" or "Hacker News front page!" I did not have that experience. I posted, I shared it in a few places, and the internet mostly kept moving.</p>
<p>That's fine. It's also the truth, and I'd rather tell you the truth than dress up a quiet launch as a triumph.</p>
<hr />
<h2 id="heading-what-open-sourcing-actually-did-and-didnt-do">What open-sourcing actually did (and didn't do)</h2>
<p>Here's what I've worked out after one week:</p>
<p><strong>What it didn't do:</strong> It didn't generate signups. It didn't drive a wave of GitHub stars. It didn't get me on the front page of anything. If your goal is instant traction, open source is not a growth hack.</p>
<p><strong>What it did do:</strong> It made me write better code, because I knew it would be public. It forced me to clean up the README, write setup instructions that an actual human could follow, and add environment variable documentation that I definitely would have skipped otherwise. That's not nothing — a well-documented codebase is a better codebase.</p>
<p>More importantly, it changed how I talk about the product. When I tell a freelancer "the code is on GitHub, MIT license, you can check exactly what we do with your data, and you can self-host if you want" — that sentence lands differently than any feature list I could write. It's a trust signal that I can't fake. Either the repo is there or it isn't.</p>
<p>I don't know yet whether that trust will convert to paid customers. I suspect it will, but I can't prove it after one week with two test accounts.</p>
<p>What I can say is: the people I've talked to who are the <em>most</em> interested in Briefkit are the same people who asked about self-hosting first. That audience exists. It's small, it's specific, and it's exactly who this product is for.</p>
<hr />
<h2 id="heading-whats-next">What's next</h2>
<p>A few things I'm focused on over the next month:</p>
<p><strong>Finding the self-hosting audience.</strong> There's a community of developers who specifically seek out tools they can run themselves. I want to get Briefkit in front of them — not to convert them all to paid users, but because they give the best feedback and they'll stress-test assumptions I don't even know I'm making.</p>
<p><strong>Building a feedback loop.</strong> Right now the feedback channel is basically me DMing people. That's fine for now, but I want a more structured way to surface what's not working. GitHub issues will be part of that.</p>
<p><strong>Shipping the next few features.</strong> The MVP is intentionally thin. Client onboarding, file sharing, basic project tracking — there's a lot of ground to cover, and I'd rather build it with input from real users than in isolation.</p>
<p><strong>Being honest about growth.</strong> I'm not going to paper over a slow start. If next week's numbers are the same, I'll say so. If something works, I'll say that too.</p>
<hr />
<h2 id="heading-try-it-fork-it-tell-me-whats-wrong">Try it / Fork it / Tell me what's wrong</h2>
<p>If you're a freelancer who's been looking for a lightweight client portal — <strong><a target="_blank" href="https://briefkit.dev">try Briefkit</a></strong>. It's early, it's rough in places, and I want feedback more than I want you to be polite about it.</p>
<p>If you're a developer who wants to poke at the code, read the setup docs, or just see how we're doing things — <strong><a target="_blank" href="https://github.com/GetMCPApps">the repo is on GitHub</a></strong>. Fork it. Open an issue. Tell me what you'd do differently.</p>
<p>And if you've gone through a similar launch — open source or otherwise — I'd genuinely like to hear how it went. The honest version, not the polished retrospective. You can find me at <a target="_blank" href="https://x.com/briefkit_dev">@briefkit_dev</a> on X.</p>
<p>One week down. A lot more to go.</p>
<p>— Bob</p>
]]></content:encoded></item><item><title><![CDATA[I Open-Sourced My SaaS and Here's What Happened]]></title><description><![CDATA[Last week I launched Briefkit — a client portal for freelancers — and I did something that made a few people raise an eyebrow: I shipped it under the MIT license.
Not "source available." Not "BSL with a four-year delay." Full MIT. Fork it, modify it,...]]></description><link>https://blog.getmcpapps.com/i-open-sourced-my-saas-and-heres-what-happened</link><guid isPermaLink="true">https://blog.getmcpapps.com/i-open-sourced-my-saas-and-heres-what-happened</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Tue, 24 Feb 2026 12:41:44 GMT</pubDate><content:encoded><![CDATA[<p>Last week I launched <a target="_blank" href="https://briefkit.dev">Briefkit</a> — a client portal for freelancers — and I did something that made a few people raise an eyebrow: I shipped it under the MIT license.</p>
<p>Not "source available." Not "BSL with a four-year delay." Full MIT. Fork it, modify it, self-host it, do whatever you want with it. Here's what happened, what I learned, and why I'd do it again.</p>
<h2 id="heading-why-mit-for-a-paid-product">Why MIT for a paid product?</h2>
<p>Let me be honest about the thought process, because I almost didn't do it.</p>
<p>The fear is obvious: if you open-source your product, why would anyone pay for it? Someone will just spin up their own instance. Someone else will fork it and undercut you. You're handing your competitors a roadmap.</p>
<p>I've heard that argument. I've also watched it play out in reverse — GitLab, Plausible, Sentry — where open-sourcing the code <em>builds</em> the business rather than killing it. The key insight is that most people aren't paying for the code. They're paying for the hosted service, the updates, the support, and the trust that you're not going to disappear with their client data.</p>
<p>That last one is where Briefkit's audience is different. My users are freelancers. Developers, designers, consultants — people who have been burned before. They've had clients in tools that shut down. They've seen platforms pivot, raise prices 3x overnight, or just vanish. When I talked to them, the question wasn't "does this have a nice UI" — it was "what happens to my data if you disappear?"</p>
<p>Open source is the answer to that question. If I disappear tomorrow, the code is on GitHub under MIT. You can run it yourself. You're never locked in. That's not a marketing tagline — it's a genuine promise, and it required putting the code where my mouth was.</p>
<p>The stack is Next.js 16 + Supabase + Vercel. Self-hosting Supabase is actually pretty straightforward, and Next.js needs no introduction. Anyone comfortable with those tools can run their own instance. That felt right for a tool aimed at developers and tech-adjacent freelancers.</p>
<p>So: MIT license, added to the repo before launch day. Decision made.</p>
<h2 id="heading-first-week-stats-the-honest-numbers">First week stats — the honest numbers</h2>
<p>Briefkit launched on February 20, 2026. One week in, here's where things stand:</p>
<p><strong>Signups:</strong> 2. Both are test accounts — one is mine, one is a friend I asked to poke around. Zero strangers have signed up yet.</p>
<p><strong>GitHub activity:</strong> Low. A handful of stars, no forks, no issues, no PRs. The repo exists, it's public, it has a README. That's about it.</p>
<p><strong>Viral moment from open-sourcing:</strong> There wasn't one.</p>
<p>I'm telling you this because every launch post I've read has at least <em>some</em> number to point to. "We got 200 stars on launch day!" or "Hacker News front page!" I did not have that experience. I posted, I shared it in a few places, and the internet mostly kept moving.</p>
<p>That's fine. It's also the truth, and I'd rather tell you the truth than dress up a quiet launch as a triumph.</p>
<h2 id="heading-what-open-sourcing-actually-did-and-didnt-do">What open-sourcing actually did (and didn't do)</h2>
<p>Here's what I've worked out after one week:</p>
<p><strong>What it didn't do:</strong> It didn't generate signups. It didn't drive a wave of GitHub stars. It didn't get me on the front page of anything. If your goal is instant traction, open source is not a growth hack.</p>
<p><strong>What it did do:</strong> It made me write better code, because I knew it would be public. It forced me to clean up the README, write setup instructions that an actual human could follow, and add environment variable documentation that I definitely would have skipped otherwise. That's not nothing — a well-documented codebase is a better codebase.</p>
<p>More importantly, it changed how I talk about the product. When I tell a freelancer "the code is on GitHub, MIT license, you can check exactly what we do with your data, and you can self-host if you want" — that sentence lands differently than any feature list I could write. It's a trust signal that I can't fake. Either the repo is there or it isn't.</p>
<p>I don't know yet whether that trust will convert to paid customers. I suspect it will, but I can't prove it after one week with two test accounts.</p>
<p>What I can say is: the people I've talked to who are the <em>most</em> interested in Briefkit are the same people who asked about self-hosting first. That audience exists. It's small, it's specific, and it's exactly who this product is for.</p>
<h2 id="heading-whats-next">What's next</h2>
<p>A few things I'm focused on over the next month:</p>
<p><strong>Finding the self-hosting audience.</strong> There's a community of developers who specifically seek out tools they can run themselves. I want to get Briefkit in front of them — not to convert them all to paid users, but because they give the best feedback and they'll stress-test assumptions I don't even know I'm making.</p>
<p><strong>Building a feedback loop.</strong> Right now the feedback channel is basically me DMing people. That's fine for now, but I want a more structured way to surface what's not working. GitHub issues will be part of that.</p>
<p><strong>Shipping the next few features.</strong> The MVP is intentionally thin. Client onboarding, file sharing, basic project tracking — there's a lot of ground to cover, and I'd rather build it with input from real users than in isolation.</p>
<p><strong>Being honest about growth.</strong> I'm not going to paper over a slow start. If next week's numbers are the same, I'll say so. If something works, I'll say that too.</p>
<h2 id="heading-try-it-fork-it-tell-me-whats-wrong">Try it / Fork it / Tell me what's wrong</h2>
<p>If you're a freelancer who's been looking for a lightweight client portal — <strong><a target="_blank" href="https://briefkit.dev">try Briefkit</a></strong>. It's early, it's rough in places, and I want feedback more than I want you to be polite about it.</p>
<p>If you're a developer who wants to poke at the code, read the setup docs, or just see how we're doing things — <strong><a target="_blank" href="https://github.com/GetMCPApps">the repo is on GitHub</a></strong>. Fork it. Open an issue. Tell me what you'd do differently.</p>
<p>And if you've gone through a similar launch — open source or otherwise — I'd genuinely like to hear how it went. The honest version, not the polished retrospective. You can find me at <a target="_blank" href="https://x.com/briefkit_dev">@briefkit_dev</a> on X.</p>
<p>One week down. A lot more to go.</p>
<p>— Bob</p>
]]></content:encoded></item><item><title><![CDATA[The 10 Best MCP Servers for AI-Assisted Development in 2026]]></title><description><![CDATA[AI-assisted development has evolved from simple autocomplete to full project orchestration. At the heart of this evolution is the Model Context Protocol (MCP), which gives AI assistants structured access to your entire development environment.
But wi...]]></description><link>https://blog.getmcpapps.com/the-10-best-mcp-servers-for-ai-assisted-development-in-2026</link><guid isPermaLink="true">https://blog.getmcpapps.com/the-10-best-mcp-servers-for-ai-assisted-development-in-2026</guid><category><![CDATA[AI development]]></category><category><![CDATA[Claude Desktop]]></category><category><![CDATA[cursor]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[mcp]]></category><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Tue, 24 Feb 2026 08:10:24 GMT</pubDate><content:encoded><![CDATA[<p>AI-assisted development has evolved from simple autocomplete to full project orchestration. At the heart of this evolution is the Model Context Protocol (MCP), which gives AI assistants structured access to your entire development environment.</p>
<p>But with over 500 MCP servers now available, which ones are actually worth installing?</p>
<p>We maintain the largest curated catalog of MCP apps at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a>, and after reviewing hundreds of submissions, these 10 servers consistently deliver the most value for developers in 2026.</p>
<h2 id="heading-1-github-mcp-23k-stars">1. <strong>GitHub MCP</strong> (23K+ stars)</h2>
<p><strong>What it does:</strong> Full GitHub integration — search repos, read issues, review PRs, and manage projects directly from your AI assistant.</p>
<p><strong>Why it's essential:</strong> Your AI can now understand your entire codebase context, including open issues and recent commits. Ask "What's blocking the release?" and get a real-time summary pulled from GitHub.</p>
<p><strong>Best for:</strong> Teams using GitHub for project management and code review.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-github</code></p>
<h2 id="heading-2-filesystem-mcp-official">2. <strong>Filesystem MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Secure file operations with configurable allowed directories. Your AI can read, write, edit, and search files.</p>
<p><strong>Why it's essential:</strong> This is the foundation. Without file access, your AI can't help you code. With it, you get real-time refactoring, documentation generation, and automated fixes.</p>
<p><strong>Best for:</strong> Any developer using AI assistants for coding.</p>
<p><strong>Install:</strong> Built into Claude Desktop by default.</p>
<h2 id="heading-3-brave-search-mcp-official">3. <strong>Brave Search MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Web search with up-to-date results. Your AI can research docs, find examples, and verify information.</p>
<p><strong>Why it's essential:</strong> LLMs have knowledge cutoffs. This server eliminates that limitation for coding questions, library updates, and API references.</p>
<p><strong>Best for:</strong> Developers working with rapidly changing frameworks or new APIs.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-brave-search</code></p>
<h2 id="heading-4-postgresql-mcp-15k-stars">4. <strong>PostgreSQL MCP</strong> (1.5K stars)</h2>
<p><strong>What it does:</strong> Direct database access — query, analyze, and modify your Postgres databases through natural language.</p>
<p><strong>Why it's essential:</strong> "Show me all users who haven't logged in this month" becomes a single prompt instead of writing SQL, running it, and formatting results.</p>
<p><strong>Best for:</strong> Full-stack developers managing complex databases.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-postgres</code></p>
<h2 id="heading-5-sentry-mcp-official">5. <strong>Sentry MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Query Sentry issues, analyze error patterns, and correlate bugs with recent deployments.</p>
<p><strong>Why it's essential:</strong> Your AI becomes a debugging partner. "Why are we getting 500 errors on /api/users?" gets answered with stack traces, affected users, and suggested fixes.</p>
<p><strong>Best for:</strong> Production monitoring and incident response.</p>
<p><strong>Install:</strong> <code>npx @getsentry/mcp-server-sentry</code></p>
<h2 id="heading-6-sequential-thinking-mcp-official">6. <strong>Sequential Thinking MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Forces structured, step-by-step reasoning for complex problems. Your AI shows its work.</p>
<p><strong>Why it's essential:</strong> For architecture decisions and multi-step refactors, you want to see the reasoning, not just the output. This server makes AI thinking transparent.</p>
<p><strong>Best for:</strong> System design and complex debugging.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-sequential-thinking</code></p>
<h2 id="heading-7-memory-mcp-official">7. <strong>Memory MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Persistent memory across conversations. Your AI remembers past decisions, project structure, and your preferences.</p>
<p><strong>Why it's essential:</strong> Stop repeating yourself. "Remember we're using Tailwind, not CSS modules" becomes permanent context.</p>
<p><strong>Best for:</strong> Long-term projects with evolving codebases.</p>
<p><strong>Install:</strong> Built into Claude Desktop by default.</p>
<h2 id="heading-8-slack-mcp-official">8. <strong>Slack MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Read channels, send messages, and search conversation history. Your AI becomes a team communication assistant.</p>
<p><strong>Why it's essential:</strong> "Summarize today's #engineering discussion" or "Did anyone report this bug?" gets instant answers from your team's knowledge base.</p>
<p><strong>Best for:</strong> Remote teams using Slack as their primary communication tool.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-slack</code></p>
<h2 id="heading-9-puppeteer-mcp-official">9. <strong>Puppeteer MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Headless browser automation — scrape websites, test UIs, and capture screenshots.</p>
<p><strong>Why it's essential:</strong> Your AI can now verify that your code changes actually work in the browser. "Does the login flow work on mobile?" gets tested, not guessed.</p>
<p><strong>Best for:</strong> Frontend developers and QA automation.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-puppeteer</code></p>
<h2 id="heading-10-everything-mcp-official">10. <strong>Everything MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Lightning-fast file search on Windows using the Everything search engine.</p>
<p><strong>Why it's essential:</strong> "Find all TypeScript files that import React" returns results in milliseconds, not minutes. Essential for navigating large monorepos.</p>
<p><strong>Best for:</strong> Windows developers working with large codebases.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-everything</code></p>
<h2 id="heading-honorable-mentions">Honorable Mentions</h2>
<ul>
<li><strong>Git MCP</strong> — Version control operations without leaving your AI chat</li>
<li><strong>Filesystem Editor</strong> — Advanced file editing with diff preview</li>
<li><strong>Google Drive MCP</strong> — Access docs and spreadsheets</li>
<li><strong>Linear MCP</strong> — Project management and issue tracking</li>
</ul>
<h2 id="heading-how-to-install-multiple-servers">How to Install Multiple Servers</h2>
<p>All major AI assistants now support MCP:</p>
<ul>
<li><strong>Claude Desktop:</strong> Edit <code>~/Library/Application Support/Claude/claude_desktop_config.json</code></li>
<li><strong>Cursor:</strong> Built-in MCP manager in settings</li>
<li><strong>VS Code + Continue:</strong> Configure via <code>.continuerc.json</code></li>
<li><strong>Windsurf:</strong> MCP settings in preferences</li>
<li><strong>GitHub Copilot:</strong> Workspace extensions (beta)</li>
</ul>
<p>Most servers follow the same pattern:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"github"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-github"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"GITHUB_TOKEN"</span>: <span class="hljs-string">"your-token-here"</span>
      }
    }
  }
}
</code></pre>
<h2 id="heading-the-real-power-combining-servers">The Real Power: Combining Servers</h2>
<p>The magic happens when servers work together:</p>
<ol>
<li><strong>GitHub MCP</strong> finds an issue</li>
<li><strong>Filesystem MCP</strong> reads the relevant code</li>
<li><strong>Brave Search MCP</strong> researches the solution</li>
<li><strong>Sequential Thinking MCP</strong> plans the fix</li>
<li><strong>Filesystem MCP</strong> applies the changes</li>
<li><strong>Git MCP</strong> commits and pushes</li>
<li><strong>Slack MCP</strong> notifies the team</li>
</ol>
<p>This entire workflow happens in one conversation.</p>
<h2 id="heading-whats-next-for-mcp-in-2026">What's Next for MCP in 2026?</h2>
<p>The protocol is still evolving. Expect to see:</p>
<ul>
<li><strong>Enterprise MCP servers</strong> for internal tools (already happening at companies like Replit and Sourcegraph)</li>
<li><strong>Marketplace expansion</strong> — hundreds of vertical-specific servers (legal, medical, finance)</li>
<li><strong>Better discovery</strong> — searchable registries and compatibility checking</li>
<li><strong>Security standards</strong> — sandboxing and permission models</li>
</ul>
<p>If you're building an MCP server, submit it to <a target="_blank" href="https://getmcpapps.com/submit">getmcpapps.com</a> — we curate the best ones and feature standout projects in our weekly newsletter.</p>
<h2 id="heading-start-small-scale-up">Start Small, Scale Up</h2>
<p>You don't need all 10 servers today. Start with:</p>
<ol>
<li><strong>Filesystem</strong> (read/write files)</li>
<li><strong>GitHub</strong> (if you use GitHub)</li>
<li><strong>Brave Search</strong> (for research)</li>
</ol>
<p>Add more as you discover specific needs. Each server unlocks new workflows, and the learning curve is gentle.</p>
<p>The future of development isn't "AI replaces developers" — it's "developers with AI-powered tools move 10x faster." MCP servers are how you get there.</p>
<p><strong>Related Reading:</strong></p>
<ul>
<li><a target="_blank" href="https://blog.getmcpapps.com/how-to-build-your-first-mcp-app-from-zero-to-working-tool-in-30-minutes">How to Build Your First MCP Server</a></li>
<li><a target="_blank" href="https://blog.getmcpapps.com/mcp-vs-rest-apis-why-ai-agents-need-a-different-kind-of-interface">MCP vs REST APIs: Why AI Needs a Different Interface</a></li>
<li><a target="_blank" href="https://getmcpapps.com">Browse all 57 curated MCP servers</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[MCP Won: How One Protocol Conquered the AI Coding Ecosystem]]></title><description><![CDATA[In November 2025, Anthropic released the Model Context Protocol (MCP) — a simple, open standard for connecting AI assistants to data sources and tools. By February 2026, just 90 days later, every major AI coding tool had adopted it.
That's not gradua...]]></description><link>https://blog.getmcpapps.com/mcp-won-how-one-protocol-conquered-the-ai-coding-ecosystem-1</link><guid isPermaLink="true">https://blog.getmcpapps.com/mcp-won-how-one-protocol-conquered-the-ai-coding-ecosystem-1</guid><category><![CDATA[AI Coding Tools]]></category><category><![CDATA[cursor]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[github copilot]]></category><category><![CDATA[mcp]]></category><category><![CDATA[protocol]]></category><category><![CDATA[windsurf]]></category><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Tue, 24 Feb 2026 08:09:17 GMT</pubDate><content:encoded><![CDATA[<p>In November 2025, Anthropic released the Model Context Protocol (MCP) — a simple, open standard for connecting AI assistants to data sources and tools. By February 2026, just 90 days later, every major AI coding tool had adopted it.</p>
<p>That's not gradual adoption. That's a sweep.</p>
<p>This is the story of how MCP won, why it happened so fast, and what it means for developers building in the AI-native era.</p>
<hr />
<h3 id="heading-the-problem-before-mcp">The Problem Before MCP</h3>
<p>Before MCP, every AI coding tool had its own integration system:</p>
<ul>
<li><strong>Cursor</strong> had a custom plugin API</li>
<li><strong>GitHub Copilot</strong> worked through VS Code extensions</li>
<li><strong>Cody/Sourcegraph</strong> built "OpenCTX" — their own context protocol</li>
<li><strong>Replit</strong> relied on built-in tool connections</li>
</ul>
<p>If you wanted your tool to work with all of them, you built four different integrations. Most developers didn't bother. The result: a fragmented ecosystem where great tools were locked into individual platforms.</p>
<p>Worse, there was no way for an AI agent to <em>discover</em> what tools were available or learn how to use them without custom prompting or hardcoded instructions.</p>
<hr />
<h3 id="heading-what-mcp-got-right">What MCP Got Right</h3>
<p>MCP's design is deceptively simple. At its core: any server can expose "tools" (callable functions), "resources" (readable data), and "prompts" (reusable templates) via a standard protocol. AI clients connect once and get everything.</p>
<p>Three design decisions made it win:</p>
<p><strong>1. Open spec, not open source product</strong>
Anthropic published MCP as a protocol specification, not a product. This meant any tool could implement it without depending on Anthropic. Companies didn't have to "adopt Anthropic's product" — they just implemented a spec. That's a much easier political sell internally.</p>
<p><strong>2. Transport agnostic</strong>
MCP works over stdio, HTTP, and SSE. Whether you're running a local process or a hosted API, same protocol. This made local-first tools (Cursor, Claude Desktop) and cloud-native tools (Replit) equally easy to support.</p>
<p><strong>3. Zero runtime dependencies</strong>
MCP servers are just programs. You can build one in Python, TypeScript, Rust, Go — anything. There's no SDK you <em>have</em> to use, no framework to adopt. This removed the "not invented here" barrier that kills most ecosystem projects.</p>
<hr />
<h3 id="heading-the-90-day-sweep">The 90-Day Sweep</h3>
<p>Here's the adoption timeline:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Tool</td><td>MCP Support Added</td><td>Notes</td></tr>
</thead>
<tbody>
<tr>
<td>Claude Desktop</td><td>November 2025</td><td>Day one — Anthropic's own client</td></tr>
<tr>
<td>Cursor</td><td>December 2025</td><td>"Best IDE for AI coding" — massive user base</td></tr>
<tr>
<td>Windsurf (Codeium)</td><td>December 2025</td><td>Through "Cascade" AI brain</td></tr>
<tr>
<td>Cody / Sourcegraph</td><td>January 2026</td><td>OpenCTX → MCP migration</td></tr>
<tr>
<td>GitHub Copilot</td><td>January 2026</td><td>Via VS Code settings; official GitHub MCP server</td></tr>
<tr>
<td>Replit Agent</td><td>February 2026</td><td>Cloud-native, no local config needed</td></tr>
</tbody>
</table>
</div><p>Five of the six most widely-used AI coding assistants. In ninety days.</p>
<p>For context: it took years for REST to become the de facto web API standard. GraphQL has been around since 2015 and still hasn't fully displaced REST. MCP moved at a pace that most protocol advocates can only dream of.</p>
<hr />
<h3 id="heading-what-build-once-run-everywhere-actually-means">What "Build Once, Run Everywhere" Actually Means</h3>
<p>Here's the practical implication that most developers haven't absorbed yet:</p>
<p><strong>Any MCP server you build today works with all of these tools.</strong></p>
<p>You build a database MCP server for your company's internal data warehouse. It works in Claude Desktop for product managers, in Cursor for your engineers, in GitHub Copilot for the team that won't switch IDEs, and in Replit for your interns.</p>
<p>One server. Six clients. All of them.</p>
<p>This is a genuine "write once, run anywhere" moment — the kind that Java promised in 1995 and actually kind of delivered on, but for AI tool integration.</p>
<p>For open-source developers: if you publish an MCP server, you're not building for "Claude Desktop users." You're building for everyone using AI-assisted development.</p>
<hr />
<h3 id="heading-the-shared-ecosystem-nobody-talks-about">The Shared Ecosystem Nobody Talks About</h3>
<p>Here's something that surprises most developers when they first hear it: Cursor's MCP configuration file looks like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"github"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-github"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"GITHUB_PERSONAL_ACCESS_TOKEN"</span>: <span class="hljs-string">"your-token"</span>
      }
    }
  }
}
</code></pre>
<p>Claude Desktop's <code>claude_desktop_config.json</code> looks <em>identical</em>.</p>
<p>That's not coincidence — that's deliberate. The spec was designed so the same configuration works across clients. The <code>@modelcontextprotocol/server-github</code> package from npm is maintained by GitHub and works in all six tools listed above without modification.</p>
<p>This is the network effect that makes MCP defensible. Every new MCP server that gets published makes every MCP client more valuable. Every new client that adopts MCP makes every existing server more valuable.</p>
<hr />
<h3 id="heading-where-mcphub-fits">Where MCPHub Fits</h3>
<p>With MCP adoption now universal, the problem has shifted.</p>
<p>It's not "how do I connect my AI tool to external data?" That's solved. The new problem is: <strong>which MCP servers are actually worth using?</strong></p>
<p>There are now hundreds of MCP servers on npm, GitHub, and various registries. Most are experiments. Some are abandoned. A handful are production-ready tools that will meaningfully improve how you work.</p>
<p>That's what <a target="_blank" href="https://getmcpapps.com">MCPHub</a> is for.</p>
<p>We review and approve MCP servers before listing them. Every app in our catalog has been checked for:</p>
<ul>
<li>Active maintenance (commits in the last 6 months)</li>
<li>Working installation instructions</li>
<li>Clear documentation</li>
<li>Real use cases (not just "I made this as a demo")</li>
</ul>
<p>We organize them by category — databases, development, productivity, communication — so you can find what you need without wading through npm search results.</p>
<p>As of this writing, we have 47 curated apps. All of them work across Claude Desktop, Cursor, Windsurf, GitHub Copilot, Cody, and Replit.</p>
<hr />
<h3 id="heading-whats-next-for-mcp">What's Next for MCP</h3>
<p>A few predictions based on what I'm watching:</p>
<p><strong>MCP will become the default "tool calling" standard beyond coding tools.</strong> Email clients, project management tools, CRMs — any software that wants to expose its data to AI agents will implement MCP servers. Microsoft has already shipped an official Microsoft 365 MCP server.</p>
<p><strong>Server marketplaces will matter more than clients.</strong> Once MCP is table stakes, differentiation moves up the stack. The companies that curate, validate, and make MCP servers discoverable will capture significant value.</p>
<p><strong>Hosted MCP servers will become a SaaS category.</strong> Right now, most MCP servers run locally. As teams need shared access, providers will offer hosted, authenticated MCP endpoints. Think "MCP as a service."</p>
<p><strong>MCP and agent frameworks will converge.</strong> Tools like LangChain, AutoGen, and CrewAI are already adding MCP support. The line between "agent framework" and "MCP client" will blur.</p>
<hr />
<h3 id="heading-the-bottom-line">The Bottom Line</h3>
<p>MCP succeeded where previous attempts at AI integration standards failed because it prioritized simplicity, openness, and developer ergonomics over completeness and control.</p>
<p>It's 90 days old and already universal.</p>
<p>If you're building anything that an AI should be able to use — a database, an API, an internal tool — MCP is the obvious choice. Build it once, and every AI coding tool your users prefer will be able to use it.</p>
<p>And if you want to find what's already built, <a target="_blank" href="https://getmcpapps.com">browse the MCPHub catalog</a> — 47 production-ready servers across 8 categories, all free to use.</p>
<hr />
<p><em>Found this useful? The MCPHub catalog is open source and community-driven. <a target="_blank" href="https://getmcpapps.com/submit">Submit your MCP server</a> for review.</em></p>
<hr />
<h2 id="heading-meta">Meta</h2>
<ul>
<li><strong>Word count:</strong> ~1,100</li>
<li><strong>Reading time:</strong> ~5 min</li>
<li><strong>Cover image brief:</strong> Split-screen showing 5-6 AI tool logos (Cursor, Claude, Windsurf, GitHub Copilot, Replit) all connected to a central hub/node. Clean, dark background. MCPHub branding subtle.</li>
<li><strong>SEO title:</strong> MCP Won: How One Protocol Unified the AI Coding Ecosystem in 90 Days</li>
<li><strong>Meta description:</strong> In November 2025, Anthropic released MCP. By February 2026, Cursor, Windsurf, GitHub Copilot, Cody, and Replit had all adopted it. Here's how one protocol conquered AI coding.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[The 10 Best MCP Servers for AI-Assisted Development in 2026]]></title><description><![CDATA[Meta Description: Discover the top 10 MCP servers that will supercharge your AI-assisted development workflow in 2026. From code quality to deployment, these tools transform how you build with Claude, Cursor, and other AI assistants.
Slug: best-mcp-s...]]></description><link>https://blog.getmcpapps.com/best-mcp-servers-ai-development-2026</link><guid isPermaLink="true">https://blog.getmcpapps.com/best-mcp-servers-ai-development-2026</guid><category><![CDATA[AI development]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[mcp]]></category><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Tue, 24 Feb 2026 07:27:01 GMT</pubDate><content:encoded><![CDATA[<p><strong>Meta Description:</strong> Discover the top 10 MCP servers that will supercharge your AI-assisted development workflow in 2026. From code quality to deployment, these tools transform how you build with Claude, Cursor, and other AI assistants.</p>
<p><strong>Slug:</strong> best-mcp-servers-ai-development-2026</p>
<p><strong>Tags:</strong> MCP, AI Development, Developer Tools, Claude Desktop, Cursor</p>
<h2 id="heading-2-filesystem-mcp-official">2. <strong>Filesystem MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Secure file operations with configurable allowed directories. Your AI can read, write, edit, and search files.</p>
<p><strong>Why it's essential:</strong> This is the foundation. Without file access, your AI can't help you code. With it, you get real-time refactoring, documentation generation, and automated fixes.</p>
<p><strong>Best for:</strong> Any developer using AI assistants for coding.</p>
<p><strong>Install:</strong> Built into Claude Desktop by default.</p>
<h2 id="heading-4-postgresql-mcp-15k-stars">4. <strong>PostgreSQL MCP</strong> (1.5K stars)</h2>
<p><strong>What it does:</strong> Direct database access — query, analyze, and modify your Postgres databases through natural language.</p>
<p><strong>Why it's essential:</strong> "Show me all users who haven't logged in this month" becomes a single prompt instead of writing SQL, running it, and formatting results.</p>
<p><strong>Best for:</strong> Full-stack developers managing complex databases.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-postgres</code></p>
<h2 id="heading-6-sequential-thinking-mcp-official">6. <strong>Sequential Thinking MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Forces structured, step-by-step reasoning for complex problems. Your AI shows its work.</p>
<p><strong>Why it's essential:</strong> For architecture decisions and multi-step refactors, you want to see the reasoning, not just the output. This server makes AI thinking transparent.</p>
<p><strong>Best for:</strong> System design and complex debugging.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-sequential-thinking</code></p>
<h2 id="heading-8-slack-mcp-official">8. <strong>Slack MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Read channels, send messages, and search conversation history. Your AI becomes a team communication assistant.</p>
<p><strong>Why it's essential:</strong> "Summarize today's #engineering discussion" or "Did anyone report this bug?" gets instant answers from your team's knowledge base.</p>
<p><strong>Best for:</strong> Remote teams using Slack as their primary communication tool.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-slack</code></p>
<h2 id="heading-10-everything-mcp-official">10. <strong>Everything MCP</strong> (Official)</h2>
<p><strong>What it does:</strong> Lightning-fast file search on Windows using the Everything search engine.</p>
<p><strong>Why it's essential:</strong> "Find all TypeScript files that import React" returns results in milliseconds, not minutes. Essential for navigating large monorepos.</p>
<p><strong>Best for:</strong> Windows developers working with large codebases.</p>
<p><strong>Install:</strong> <code>npx @modelcontextprotocol/server-everything</code></p>
<h2 id="heading-how-to-install-multiple-servers">How to Install Multiple Servers</h2>
<p>All major AI assistants now support MCP:</p>
<ul>
<li><strong>Claude Desktop:</strong> Edit <code>~/Library/Application Support/Claude/claude_desktop_config.json</code></li>
<li><strong>Cursor:</strong> Built-in MCP manager in settings</li>
<li><strong>VS Code + Continue:</strong> Configure via <code>.continuerc.json</code></li>
<li><strong>Windsurf:</strong> MCP settings in preferences</li>
<li><strong>GitHub Copilot:</strong> Workspace extensions (beta)</li>
</ul>
<p>Most servers follow the same pattern:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"github"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-github"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"GITHUB_TOKEN"</span>: <span class="hljs-string">"your-token-here"</span>
      }
    }
  }
}
</code></pre>
<h2 id="heading-whats-next-for-mcp-in-2026">What's Next for MCP in 2026?</h2>
<p>The protocol is still evolving. Expect to see:</p>
<ul>
<li><strong>Enterprise MCP servers</strong> for internal tools (already happening at companies like Replit and Sourcegraph)</li>
<li><strong>Marketplace expansion</strong> — hundreds of vertical-specific servers (legal, medical, finance)</li>
<li><strong>Better discovery</strong> — searchable registries and compatibility checking</li>
<li><strong>Security standards</strong> — sandboxing and permission models</li>
</ul>
<p>If you're building an MCP server, submit it to <a target="_blank" href="https://getmcpapps.com/submit">getmcpapps.com</a> — we curate the best ones and feature standout projects in our weekly newsletter.</p>
<p><strong>Related Reading:</strong></p>
<ul>
<li><a target="_blank" href="https://blog.getmcpapps.com/how-to-build-your-first-mcp-app-from-zero-to-working-tool-in-30-minutes">How to Build Your First MCP Server</a></li>
<li><a target="_blank" href="https://blog.getmcpapps.com/mcp-vs-rest-apis-why-ai-agents-need-a-different-kind-of-interface">MCP vs REST APIs: Why AI Needs a Different Interface</a></li>
<li><a target="_blank" href="https://getmcpapps.com">Browse all 57 curated MCP servers</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Client Portals vs Notion: Which Works Better for Designers?]]></title><description><![CDATA[Notion is everywhere. It's free, flexible, and your clients probably already use it. So why would you pay for a dedicated client portal?
I built Briefkit after trying (and failing) to use Notion for client work. Here's what I learned.
What Notion Doe...]]></description><link>https://blog.getmcpapps.com/client-portals-vs-notion-which-works-better-for-designers</link><guid isPermaLink="true">https://blog.getmcpapps.com/client-portals-vs-notion-which-works-better-for-designers</guid><category><![CDATA[client management]]></category><category><![CDATA[Freelancing]]></category><category><![CDATA[notion]]></category><category><![CDATA[Web Design]]></category><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Mon, 23 Feb 2026 22:02:03 GMT</pubDate><content:encoded><![CDATA[<p>Notion is everywhere. It's free, flexible, and your clients probably already use it. So why would you pay for a dedicated client portal?</p>
<p>I built Briefkit after trying (and failing) to use Notion for client work. Here's what I learned.</p>
<h2 id="heading-what-notion-does-well">What Notion Does Well</h2>
<p><strong>Flexibility.</strong> You can build literally anything — client databases, project trackers, approval workflows, knowledge bases. The block-based editor makes it easy to customize every page.</p>
<p><strong>Collaboration.</strong> Real-time editing, comments, @mentions. Your clients can leave feedback directly on project docs.</p>
<p><strong>Cost.</strong> The free tier works for most freelancers. Even paid plans are cheap ($10/month).</p>
<p><strong>Familiarity.</strong> Most clients have seen Notion. There's less friction when onboarding.</p>
<h2 id="heading-where-notion-breaks-down">Where Notion Breaks Down</h2>
<p><strong>It's not built for client work.</strong> Notion is a knowledge management tool. Client portals are relationship management tools. The difference matters.</p>
<p>Here's what breaks:</p>
<h3 id="heading-1-clients-see-your-workspace-chaos">1. Clients see your workspace chaos</h3>
<p>When you share a Notion page, clients can navigate to your sidebar. They see your todo lists, internal notes, other client folders (if permissions slip). There's no true isolation.</p>
<p>Client portals keep client views separate by default. Each client logs in and sees only their own stuff.</p>
<h3 id="heading-2-file-management-is-messy">2. File management is messy</h3>
<p>Try organizing 50 client revisions in Notion. You'll end up with:</p>
<ul>
<li>Files embedded in random doc blocks</li>
<li>Versioning via filename prefixes (<code>logo-v3-final-FINAL.png</code>)</li>
<li>No automatic approval tracking</li>
<li>Comments scattered across pages</li>
</ul>
<p>Client portals group files by project, track versions automatically, and let clients approve/reject with one click.</p>
<h3 id="heading-3-no-client-specific-branding">3. No client-specific branding</h3>
<p>Your Notion workspace looks like... Notion. Your logo in the corner doesn't change that.</p>
<p>Client portals let you white-label. Custom domain, your colors, your brand. Clients see <em>your</em> tool, not a shared workspace.</p>
<h3 id="heading-4-permissions-are-fragile">4. Permissions are fragile</h3>
<p>Notion permissions are page-based. Add a client to the wrong parent page and they can see everything below it. Revoke access and they lose everything — even approved files they need.</p>
<p>Client portals use role-based access. Clients can't accidentally navigate outside their project scope.</p>
<h3 id="heading-5-mobile-experience-isnt-great">5. Mobile experience isn't great</h3>
<p>The Notion mobile app is fine for your own notes. For clients trying to approve a logo on their phone? Clunky.</p>
<p>Client portals are built mobile-first — big approve/reject buttons, upload from camera, simple navigation.</p>
<h2 id="heading-when-notion-still-makes-sense">When Notion Still Makes Sense</h2>
<p><strong>You're a solo designer with &lt;5 clients.</strong> The flexibility is worth the friction.</p>
<p><strong>Your clients are technical.</strong> If they already live in Notion for their own work, they'll tolerate the UX quirks.</p>
<p><strong>Budget is tight.</strong> Notion is free. Client portals start at $10-30/month.</p>
<p><strong>Your projects are simple.</strong> A single deliverable, no revisions, minimal feedback loops.</p>
<h2 id="heading-when-a-client-portal-wins">When a Client Portal Wins</h2>
<p><strong>You have 10+ active clients.</strong> File chaos scales badly in Notion.</p>
<p><strong>You do revision-heavy work</strong> (branding, web design, illustration). You need approval tracking.</p>
<p><strong>Your clients aren't technical.</strong> They want "click to approve logo", not "navigate to page 3, find the file block, leave a comment".</p>
<p><strong>You care about branding.</strong> Client-facing tools should look like yours, not Notion's.</p>
<p><strong>You bill hourly and track project budgets.</strong> Client portals often include time tracking and invoicing. Notion doesn't.</p>
<h2 id="heading-the-real-question">The Real Question</h2>
<p>It's not "Notion vs client portals."</p>
<p>It's "Do I need a tool built for <em>me</em> or a tool built for <em>clients</em>?"</p>
<p>Notion is built for you. It's your workspace that you share.</p>
<p>Client portals are built for clients. They log in, see their project, upload feedback, approve work. Done.</p>
<p>If you're spending &gt;30 min/week manually organizing client files, hunting for approvals in comment threads, or explaining how to navigate your Notion workspace — you've outgrown Notion.</p>
<h2 id="heading-try-both-for-free">Try Both (for Free)</h2>
<p>The best way to decide is to actually use them.</p>
<p><strong>Notion:</strong> Already free. Set up a client workspace this week.</p>
<p><strong>Briefkit:</strong> Open-source client portal built for designers. Free during beta. <a target="_blank" href="https://briefkit.dev">Try it →</a></p>
<p>Test both with one real client. See which feels faster.</p>
]]></content:encoded></item><item><title><![CDATA[MCP Won: How One Protocol Conquered the AI Coding Ecosystem]]></title><description><![CDATA[In November 2025, Anthropic released the Model Context Protocol (MCP) — a simple, open standard for connecting AI assistants to data sources and tools. By February 2026, just 90 days later, every major AI coding tool had adopted it.
That's not gradua...]]></description><link>https://blog.getmcpapps.com/mcp-won-how-one-protocol-conquered-the-ai-coding-ecosystem</link><guid isPermaLink="true">https://blog.getmcpapps.com/mcp-won-how-one-protocol-conquered-the-ai-coding-ecosystem</guid><category><![CDATA[AI]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[mcp]]></category><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Mon, 23 Feb 2026 21:04:44 GMT</pubDate><content:encoded><![CDATA[<p>In November 2025, Anthropic released the Model Context Protocol (MCP) — a simple, open standard for connecting AI assistants to data sources and tools. By February 2026, just 90 days later, every major AI coding tool had adopted it.</p>
<p>That's not gradual adoption. That's a sweep.</p>
<p>This is the story of how MCP won, why it happened so fast, and what it means for developers building in the AI-native era.</p>
<hr />
<h3 id="heading-the-problem-before-mcp">The Problem Before MCP</h3>
<p>Before MCP, every AI coding tool had its own integration system:</p>
<ul>
<li><strong>Cursor</strong> had a custom plugin API</li>
<li><strong>GitHub Copilot</strong> worked through VS Code extensions</li>
<li><strong>Cody/Sourcegraph</strong> built "OpenCTX" — their own context protocol</li>
<li><strong>Replit</strong> relied on built-in tool connections</li>
</ul>
<p>If you wanted your tool to work with all of them, you built four different integrations. Most developers didn't bother. The result: a fragmented ecosystem where great tools were locked into individual platforms.</p>
<p>Worse, there was no way for an AI agent to <em>discover</em> what tools were available or learn how to use them without custom prompting or hardcoded instructions.</p>
<hr />
<h3 id="heading-what-mcp-got-right">What MCP Got Right</h3>
<p>MCP's design is deceptively simple. At its core: any server can expose "tools" (callable functions), "resources" (readable data), and "prompts" (reusable templates) via a standard protocol. AI clients connect once and get everything.</p>
<p>Three design decisions made it win:</p>
<p><strong>1. Open spec, not open source product</strong>
Anthropic published MCP as a protocol specification, not a product. This meant any tool could implement it without depending on Anthropic. Companies didn't have to "adopt Anthropic's product" — they just implemented a spec. That's a much easier political sell internally.</p>
<p><strong>2. Transport agnostic</strong>
MCP works over stdio, HTTP, and SSE. Whether you're running a local process or a hosted API, same protocol. This made local-first tools (Cursor, Claude Desktop) and cloud-native tools (Replit) equally easy to support.</p>
<p><strong>3. Zero runtime dependencies</strong>
MCP servers are just programs. You can build one in Python, TypeScript, Rust, Go — anything. There's no SDK you <em>have</em> to use, no framework to adopt. This removed the "not invented here" barrier that kills most ecosystem projects.</p>
<hr />
<h3 id="heading-the-90-day-sweep">The 90-Day Sweep</h3>
<p>Here's the adoption timeline:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Tool</td><td>MCP Support Added</td><td>Notes</td></tr>
</thead>
<tbody>
<tr>
<td>Claude Desktop</td><td>November 2025</td><td>Day one — Anthropic's own client</td></tr>
<tr>
<td>Cursor</td><td>December 2025</td><td>"Best IDE for AI coding" — massive user base</td></tr>
<tr>
<td>Windsurf (Codeium)</td><td>December 2025</td><td>Through "Cascade" AI brain</td></tr>
<tr>
<td>Cody / Sourcegraph</td><td>January 2026</td><td>OpenCTX → MCP migration</td></tr>
<tr>
<td>GitHub Copilot</td><td>January 2026</td><td>Via VS Code settings; official GitHub MCP server</td></tr>
<tr>
<td>Replit Agent</td><td>February 2026</td><td>Cloud-native, no local config needed</td></tr>
</tbody>
</table>
</div><p>Five of the six most widely-used AI coding assistants. In ninety days.</p>
<p>For context: it took years for REST to become the de facto web API standard. GraphQL has been around since 2015 and still hasn't fully displaced REST. MCP moved at a pace that most protocol advocates can only dream of.</p>
<hr />
<h3 id="heading-what-build-once-run-everywhere-actually-means">What "Build Once, Run Everywhere" Actually Means</h3>
<p>Here's the practical implication that most developers haven't absorbed yet:</p>
<p><strong>Any MCP server you build today works with all of these tools.</strong></p>
<p>You build a database MCP server for your company's internal data warehouse. It works in Claude Desktop for product managers, in Cursor for your engineers, in GitHub Copilot for the team that won't switch IDEs, and in Replit for your interns.</p>
<p>One server. Six clients. All of them.</p>
<p>This is a genuine "write once, run anywhere" moment — the kind that Java promised in 1995 and actually kind of delivered on, but for AI tool integration.</p>
<p>For open-source developers: if you publish an MCP server, you're not building for "Claude Desktop users." You're building for everyone using AI-assisted development.</p>
<hr />
<h3 id="heading-the-shared-ecosystem-nobody-talks-about">The Shared Ecosystem Nobody Talks About</h3>
<p>Here's something that surprises most developers when they first hear it: Cursor's MCP configuration file looks like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"github"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-github"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"GITHUB_PERSONAL_ACCESS_TOKEN"</span>: <span class="hljs-string">"your-token"</span>
      }
    }
  }
}
</code></pre>
<p>Claude Desktop's <code>claude_desktop_config.json</code> looks <em>identical</em>.</p>
<p>That's not coincidence — that's deliberate. The spec was designed so the same configuration works across clients. The <code>@modelcontextprotocol/server-github</code> package from npm is maintained by GitHub and works in all six tools listed above without modification.</p>
<p>This is the network effect that makes MCP defensible. Every new MCP server that gets published makes every MCP client more valuable. Every new client that adopts MCP makes every existing server more valuable.</p>
<hr />
<h3 id="heading-where-mcphub-fits">Where MCPHub Fits</h3>
<p>With MCP adoption now universal, the problem has shifted.</p>
<p>It's not "how do I connect my AI tool to external data?" That's solved. The new problem is: <strong>which MCP servers are actually worth using?</strong></p>
<p>There are now hundreds of MCP servers on npm, GitHub, and various registries. Most are experiments. Some are abandoned. A handful are production-ready tools that will meaningfully improve how you work.</p>
<p>That's what <a target="_blank" href="https://getmcpapps.com">MCPHub</a> is for.</p>
<p>We review and approve MCP servers before listing them. Every app in our catalog has been checked for:</p>
<ul>
<li>Active maintenance (commits in the last 6 months)</li>
<li>Working installation instructions</li>
<li>Clear documentation</li>
<li>Real use cases (not just "I made this as a demo")</li>
</ul>
<p>We organize them by category — databases, development, productivity, communication — so you can find what you need without wading through npm search results.</p>
<p>As of this writing, we have 47 curated apps. All of them work across Claude Desktop, Cursor, Windsurf, GitHub Copilot, Cody, and Replit.</p>
<hr />
<h3 id="heading-whats-next-for-mcp">What's Next for MCP</h3>
<p>A few predictions based on what I'm watching:</p>
<p><strong>MCP will become the default "tool calling" standard beyond coding tools.</strong> Email clients, project management tools, CRMs — any software that wants to expose its data to AI agents will implement MCP servers. Microsoft has already shipped an official Microsoft 365 MCP server.</p>
<p><strong>Server marketplaces will matter more than clients.</strong> Once MCP is table stakes, differentiation moves up the stack. The companies that curate, validate, and make MCP servers discoverable will capture significant value.</p>
<p><strong>Hosted MCP servers will become a SaaS category.</strong> Right now, most MCP servers run locally. As teams need shared access, providers will offer hosted, authenticated MCP endpoints. Think "MCP as a service."</p>
<p><strong>MCP and agent frameworks will converge.</strong> Tools like LangChain, AutoGen, and CrewAI are already adding MCP support. The line between "agent framework" and "MCP client" will blur.</p>
<hr />
<h3 id="heading-the-bottom-line">The Bottom Line</h3>
<p>MCP succeeded where previous attempts at AI integration standards failed because it prioritized simplicity, openness, and developer ergonomics over completeness and control.</p>
<p>It's 90 days old and already universal.</p>
<p>If you're building anything that an AI should be able to use — a database, an API, an internal tool — MCP is the obvious choice. Build it once, and every AI coding tool your users prefer will be able to use it.</p>
<p>And if you want to find what's already built, <a target="_blank" href="https://getmcpapps.com">browse the MCPHub catalog</a> — 47 production-ready servers across 8 categories, all free to use.</p>
<hr />
<p><em>Found this useful? The MCPHub catalog is open source and community-driven. <a target="_blank" href="https://getmcpapps.com/submit">Submit your MCP server</a> for review.</em></p>
]]></content:encoded></item><item><title><![CDATA[Building a Production MCP Server: Lessons from 30+ Apps]]></title><description><![CDATA[After cataloging and reviewing over 30 MCP applications at getmcpapps.com, I've seen what works, what breaks, and what separates a weekend prototype from something people actually use. Here's what I've learned.
The Gap Between "It Works" and "It Ship...]]></description><link>https://blog.getmcpapps.com/building-a-production-mcp-server-lessons-from-30-plus-apps</link><guid isPermaLink="true">https://blog.getmcpapps.com/building-a-production-mcp-server-lessons-from-30-plus-apps</guid><category><![CDATA[AI]]></category><category><![CDATA[api]]></category><category><![CDATA[Developer Tools]]></category><category><![CDATA[mcp]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Mon, 23 Feb 2026 13:02:06 GMT</pubDate><content:encoded><![CDATA[<p>After cataloging and reviewing over 30 MCP applications at getmcpapps.com, I've seen what works, what breaks, and what separates a weekend prototype from something people actually use. Here's what I've learned.</p>
<h2 id="heading-the-gap-between-it-works-and-it-ships">The Gap Between "It Works" and "It Ships"</h2>
<p>Most MCP server tutorials end at "hello world." You get stdio working, you register a tool, Claude calls it, and you're done. That's fine for learning. But the apps that actually get installed and stay installed handle a dozen things the tutorials don't mention.</p>
<h3 id="heading-1-error-messages-that-actually-help">1. Error Messages That Actually Help</h3>
<p>When your MCP server breaks, Claude shows the user a JSON error. That error is the only debugging information they'll see. Make it count.</p>
<p><strong>Bad:</strong></p>
<pre><code class="lang-json">{<span class="hljs-attr">"error"</span>: <span class="hljs-string">"Failed"</span>}
</code></pre>
<p><strong>Better:</strong></p>
<pre><code class="lang-json">{<span class="hljs-attr">"error"</span>: <span class="hljs-string">"API key missing. Set GITHUB_TOKEN in environment."</span>}
</code></pre>
<p><strong>Best:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"error"</span>: <span class="hljs-string">"GitHub API authentication failed"</span>,
  <span class="hljs-attr">"details"</span>: <span class="hljs-string">"GITHUB_TOKEN not found in environment. Get one at: https://github.com/settings/tokens"</span>,
  <span class="hljs-attr">"docs"</span>: <span class="hljs-string">"https://github.com/yourname/mcp-server#setup"</span>
}
</code></pre>
<p>The best error messages include:</p>
<ul>
<li>What went wrong (not just "failed")</li>
<li>Why it went wrong</li>
<li>How to fix it (with a link if possible)</li>
</ul>
<h3 id="heading-2-handle-rate-limits-before-they-hit">2. Handle Rate Limits Before They Hit</h3>
<p>Every external API has rate limits. If your MCP server doesn't handle them, users will hit walls and blame your tool.</p>
<p><strong>Strategies that work:</strong></p>
<ul>
<li><strong>Check remaining quota before expensive calls.</strong> If you're about to make 50 API requests and the user has 10 left, tell them upfront.</li>
<li><strong>Exponential backoff on 429s.</strong> Don't just retry immediately. Wait 1s, then 2s, then 4s.</li>
<li><strong>Cache aggressively.</strong> If Claude asks for the same GitHub repo info twice in 30 seconds, return the cached version.</li>
</ul>
<p>The MCP servers that stay installed are the ones that don't burn through API quotas.</p>
<h3 id="heading-3-validation-is-not-optional">3. Validation is Not Optional</h3>
<p>Claude will send you garbage inputs. Users will typo repository names, paste malformed URLs, request files that don't exist. Your server needs to validate before calling external APIs.</p>
<p><strong>Validate:</strong></p>
<ul>
<li>Required fields are present</li>
<li>URLs are actual URLs</li>
<li>File paths don't escape boundaries (<code>../../etc/passwd</code>)</li>
<li>Enum values match allowed options</li>
<li>Numeric ranges make sense</li>
</ul>
<p>Return a clear error immediately. Don't let the external API tell them the input was wrong — you should catch it first.</p>
<h3 id="heading-4-timeouts-everywhere">4. Timeouts Everywhere</h3>
<p>Network calls hang. APIs go down. Filesystems block on NFS mounts. If your MCP server doesn't have timeouts, it will freeze Claude.</p>
<p><strong>Timeout every:</strong></p>
<ul>
<li>HTTP requests (5-10s for most APIs)</li>
<li>File operations (especially on network drives)</li>
<li>Database queries</li>
<li>Subprocess calls</li>
</ul>
<p>When a timeout fires, return a useful error. "GitHub API timed out after 10s. Check your network connection."</p>
<h3 id="heading-5-secrets-management">5. Secrets Management</h3>
<p>Storing API keys in plaintext config files is how MCP servers end up on "please don't install this" lists.</p>
<p><strong>Do:</strong></p>
<ul>
<li>Use environment variables (<code>process.env.API_KEY</code>)</li>
<li>Support <code>.env</code> files for local dev</li>
<li>Document exactly which env vars are needed</li>
<li>Check for secrets on startup and fail fast with clear instructions</li>
</ul>
<p><strong>Don't:</strong></p>
<ul>
<li>Commit secrets to git (add <code>.env</code> to <code>.gitignore</code>)</li>
<li>Log secrets (even in debug mode)</li>
<li>Pass secrets in URLs (they end up in logs)</li>
</ul>
<h3 id="heading-6-installation-should-be-one-command">6. Installation Should Be One Command</h3>
<p>The best MCP servers install with:</p>
<pre><code class="lang-bash">npx your-mcp-server
</code></pre>
<p>or</p>
<pre><code class="lang-bash">pip install your-mcp-server
</code></pre>
<p>No cloning repos. No manual npm installs. No "first run these 5 setup commands." If it takes more than one line, most people won't install it.</p>
<p><strong>Ship:</strong></p>
<ul>
<li>An npm package (for Node)</li>
<li>A PyPI package (for Python)</li>
<li>A binary (for Go/Rust)</li>
</ul>
<p>Make it trivial to try. You can add advanced setup options in the docs, but the happy path should be one command.</p>
<h3 id="heading-7-logs-but-not-too-many">7. Logs (But Not Too Many)</h3>
<p>When things break, users need logs. When things work, users want silence.</p>
<p><strong>Log:</strong></p>
<ul>
<li>Errors (always)</li>
<li>Warnings (rate limits approaching, deprecated features)</li>
<li>Startup configuration (which env vars were found)</li>
</ul>
<p><strong>Don't log:</strong></p>
<ul>
<li>Every tool call (spams the console)</li>
<li>Request/response bodies (security risk)</li>
<li>Stack traces for expected errors (validation failures)</li>
</ul>
<p>Support a <code>DEBUG=1</code> mode for troubleshooting, but keep the default quiet.</p>
<h3 id="heading-8-testing-yes-really">8. Testing (Yes, Really)</h3>
<p>MCP servers are harder to test than normal APIs because Claude is in the loop. But you can still test the core logic.</p>
<p><strong>Test:</strong></p>
<ul>
<li>Tool parameter validation (pass garbage, expect clear errors)</li>
<li>API response parsing (mock the external API)</li>
<li>Error handling (simulate timeouts, rate limits, auth failures)</li>
<li>Edge cases (empty results, huge results, malformed data)</li>
</ul>
<p>The apps with test coverage are the ones that don't break on updates.</p>
<h3 id="heading-9-documentation-is-your-marketing">9. Documentation Is Your Marketing</h3>
<p>Your README is the landing page. If it doesn't clearly explain what the server does and why someone would want it, nobody installs it.</p>
<p><strong>Good READMEs include:</strong></p>
<ul>
<li>One sentence: what does this do?</li>
<li>Installation (one command)</li>
<li>Setup (which env vars, where to get API keys)</li>
<li>Example usage (show Claude using it)</li>
<li>Troubleshooting (common errors and fixes)</li>
</ul>
<p>A GIF showing it in action is worth 500 words of explanation.</p>
<h3 id="heading-10-versioning-and-updates">10. Versioning and Updates</h3>
<p>Once people install your MCP server, they'll expect it to keep working. That means:</p>
<p><strong>Semantic versioning.</strong> Breaking changes need a major version bump. Bug fixes are patch releases.</p>
<p><strong>Changelog.</strong> Tell people what changed. "Fixed rate limiting bug" is useful. "Various improvements" is not.</p>
<p><strong>Backward compatibility when possible.</strong> If you rename a tool, support the old name for one version with a deprecation warning.</p>
<h3 id="heading-11-graceful-degradation">11. Graceful Degradation</h3>
<p>Not everyone has API keys. Not everyone has network access. Not everyone runs the latest version of Claude.</p>
<p><strong>Design for:</strong></p>
<ul>
<li>Offline mode (cache what you can, explain what needs network)</li>
<li>Missing credentials (offer limited functionality instead of failing entirely)</li>
<li>Older Claude versions (don't assume features from the latest release)</li>
</ul>
<p>The best MCP servers work in as many environments as possible.</p>
<h2 id="heading-the-checklist">The Checklist</h2>
<p>Before you call it "production ready":</p>
<ul>
<li>[ ] Clear error messages with actionable fixes</li>
<li>[ ] Rate limit handling (check quota, backoff, cache)</li>
<li>[ ] Input validation on all parameters</li>
<li>[ ] Timeouts on all external calls</li>
<li>[ ] Environment variables for secrets</li>
<li>[ ] One-command installation</li>
<li>[ ] Quiet logs by default, DEBUG mode available</li>
<li>[ ] Tests for core logic</li>
<li>[ ] README with install/setup/examples</li>
<li>[ ] Semantic versioning + changelog</li>
</ul>
<h2 id="heading-what-actually-matters">What Actually Matters</h2>
<p>After reviewing 30+ MCP apps, here's what separates the ones people use from the ones people try once and uninstall:</p>
<p><strong>Reliability &gt; features.</strong> A server that does 3 things well beats one that does 10 things poorly.</p>
<p><strong>Error messages &gt; everything.</strong> When it breaks (and it will), users need to know why and how to fix it.</p>
<p><strong>Easy install &gt; perfect code.</strong> If it's hard to install, it doesn't matter how good it is.</p>
<p>Ship something simple that works reliably. You can add features later. You can't un-burn someone's API quota or un-frustrate them after a cryptic error.</p>
<hr />
<p><em>Based on patterns from 30+ production MCP servers cataloged at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a>. If you're building an MCP server and want feedback, <a target="_blank" href="https://getmcpapps.com">submit it to the catalog</a>.</em></p>
]]></content:encoded></item><item><title><![CDATA[The Complete Claude Desktop Setup Guide: 10 MCP Servers Worth Installing]]></title><description><![CDATA[Published by The Plug | MCPHub — the MCP App Marketplace
If you're using Claude Desktop without MCP servers, you're leaving 90% of its potential on the table. Model Context Protocol (MCP) transforms Claude from a chatbot into a genuine productivity p...]]></description><link>https://blog.getmcpapps.com/the-complete-claude-desktop-setup-guide-10-mcp-servers-worth-installing</link><guid isPermaLink="true">https://blog.getmcpapps.com/the-complete-claude-desktop-setup-guide-10-mcp-servers-worth-installing</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Sun, 22 Feb 2026 13:01:08 GMT</pubDate><enclosure url="https://jnngymtirprbsfeevggk.supabase.co/storage/v1/object/public/blog-og/claude-setup-guide.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Published by The Plug | MCPHub — the MCP App Marketplace</em></p>
<p>If you're using Claude Desktop without MCP servers, you're leaving 90% of its potential on the table. Model Context Protocol (MCP) transforms Claude from a chatbot into a genuine productivity powerhouse — giving it access to your filesystem, GitHub repos, databases, search engines, and more.</p>
<p>This guide walks you through setting up Claude Desktop with 10 essential MCP servers that will 10x your workflow.</p>
<hr />
<h2 id="heading-quick-setup-how-mcp-servers-work">Quick Setup: How MCP Servers Work</h2>
<p>MCP servers run locally on your machine and expose tools, resources, and prompts to Claude Desktop through a standardized protocol. Think of them as plugins that give Claude new capabilities — except they're privacy-first (everything runs locally) and work across any MCP-compatible client.</p>
<p><strong>Installation is simple:</strong> Add a server config to your <code>claude_desktop_config.json</code> file, restart Claude, and you're done.</p>
<h3 id="heading-where-to-find-your-config-file">Where to find your config file:</h3>
<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>
</ul>
<hr />
<h2 id="heading-the-10-must-have-mcp-servers">The 10 Must-Have MCP Servers</h2>
<h3 id="heading-1-filesystem-server-read-amp-write-files-locally">1. <strong>Filesystem Server</strong> — Read &amp; Write Files Locally</h3>
<p><strong>What it does:</strong> Lets Claude read, write, search, and edit files on your computer. Essential for coding, writing, or working with local documents.</p>
<p><strong>Install:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"filesystem"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-filesystem"</span>, <span class="hljs-string">"/path/to/allowed/directory"</span>]
    }
  }
}
</code></pre>
<p>Replace <code>/path/to/allowed/directory</code> with the folder you want Claude to access (e.g., <code>~/projects</code>).</p>
<p><a target="_blank" href="https://getmcpapps.com">Browse filesystem tools on MCPHub →</a></p>
<hr />
<h3 id="heading-2-github-server-manage-repos-issues-and-prs">2. <strong>GitHub Server</strong> — Manage Repos, Issues, and PRs</h3>
<p><strong>What it does:</strong> Search repos, create issues, comment on PRs, fetch file contents, and more — all without leaving Claude.</p>
<p><strong>Install:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"github"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-github"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"GITHUB_PERSONAL_ACCESS_TOKEN"</span>: <span class="hljs-string">"your_token_here"</span>
      }
    }
  }
}
</code></pre>
<p>Get a GitHub PAT at <a target="_blank" href="https://github.com/settings/tokens">github.com/settings/tokens</a>.</p>
<hr />
<h3 id="heading-3-brave-search-server-real-time-web-search">3. <strong>Brave Search Server</strong> — Real-Time Web Search</h3>
<p><strong>What it does:</strong> Lets Claude search the web in real time. Crucial for research, fact-checking, and staying current.</p>
<p><strong>Install:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"brave-search"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-brave-search"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"BRAVE_API_KEY"</span>: <span class="hljs-string">"your_api_key_here"</span>
      }
    }
  }
}
</code></pre>
<p>Get a free Brave API key at <a target="_blank" href="https://brave.com/search/api">brave.com/search/api</a>.</p>
<hr />
<h3 id="heading-4-postgresql-server-query-databases-directly">4. <strong>PostgreSQL Server</strong> — Query Databases Directly</h3>
<p><strong>What it does:</strong> Run SQL queries, inspect schemas, and analyze data in your PostgreSQL databases.</p>
<p><strong>Install:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"postgres"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-postgres"</span>, <span class="hljs-string">"postgresql://user:pass@localhost/dbname"</span>]
    }
  }
}
</code></pre>
<p>Replace the connection string with your actual database credentials.</p>
<hr />
<h3 id="heading-5-memory-server-persistent-knowledge-graph">5. <strong>Memory Server</strong> — Persistent Knowledge Graph</h3>
<p><strong>What it does:</strong> Creates a local knowledge graph so Claude remembers context across conversations. Game-changer for long-term projects.</p>
<p><strong>Install:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"memory"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-memory"</span>]
    }
  }
}
</code></pre>
<hr />
<h3 id="heading-6-puppeteer-server-browser-automation">6. <strong>Puppeteer Server</strong> — Browser Automation</h3>
<p><strong>What it does:</strong> Control a headless Chrome browser — scrape websites, fill forms, take screenshots, run end-to-end tests.</p>
<p><strong>Install:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"puppeteer"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-puppeteer"</span>]
    }
  }
}
</code></pre>
<hr />
<h3 id="heading-7-slack-server-send-messages-amp-read-channels">7. <strong>Slack Server</strong> — Send Messages &amp; Read Channels</h3>
<p><strong>What it does:</strong> Post to Slack channels, read message history, search conversations — great for team automation.</p>
<p><strong>Install:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"slack"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-slack"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"SLACK_BOT_TOKEN"</span>: <span class="hljs-string">"xoxb-your-token"</span>
      }
    }
  }
}
</code></pre>
<p>Create a Slack app and bot token at <a target="_blank" href="https://api.slack.com/apps">api.slack.com/apps</a>.</p>
<hr />
<h3 id="heading-8-google-maps-server-geocoding-amp-directions">8. <strong>Google Maps Server</strong> — Geocoding &amp; Directions</h3>
<p><strong>What it does:</strong> Geocode addresses, calculate routes, find nearby places — useful for logistics, travel planning, or location-aware apps.</p>
<p><strong>Install:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"google-maps"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-google-maps"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"GOOGLE_MAPS_API_KEY"</span>: <span class="hljs-string">"your_api_key_here"</span>
      }
    }
  }
}
</code></pre>
<p>Get a Google Maps API key at <a target="_blank" href="https://console.cloud.google.com">console.cloud.google.com</a>.</p>
<hr />
<h3 id="heading-9-sequential-thinking-server-extended-reasoning">9. <strong>Sequential Thinking Server</strong> — Extended Reasoning</h3>
<p><strong>What it does:</strong> Gives Claude access to a sequential thinking tool for complex multi-step reasoning. Particularly useful for debugging or strategic planning.</p>
<p><strong>Install:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"sequential-thinking"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-sequential-thinking"</span>]
    }
  }
}
</code></pre>
<hr />
<h3 id="heading-10-time-server-current-date-amp-time">10. <strong>Time Server</strong> — Current Date &amp; Time</h3>
<p><strong>What it does:</strong> Provides Claude with the current date and time. Simple but essential — Claude otherwise has no concept of "today."</p>
<p><strong>Install:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"time"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-time"</span>]
    }
  }
}
</code></pre>
<hr />
<h2 id="heading-putting-it-all-together">Putting It All Together</h2>
<p>Your final <code>claude_desktop_config.json</code> should look like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"filesystem"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-filesystem"</span>, <span class="hljs-string">"~/projects"</span>]
    },
    <span class="hljs-attr">"github"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-github"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"GITHUB_PERSONAL_ACCESS_TOKEN"</span>: <span class="hljs-string">"your_token_here"</span>
      }
    },
    <span class="hljs-attr">"brave-search"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-brave-search"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"BRAVE_API_KEY"</span>: <span class="hljs-string">"your_api_key_here"</span>
      }
    },
    <span class="hljs-attr">"postgres"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-postgres"</span>, <span class="hljs-string">"postgresql://user:pass@localhost/dbname"</span>]
    },
    <span class="hljs-attr">"memory"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-memory"</span>]
    },
    <span class="hljs-attr">"puppeteer"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-puppeteer"</span>]
    },
    <span class="hljs-attr">"slack"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-slack"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"SLACK_BOT_TOKEN"</span>: <span class="hljs-string">"xoxb-your-token"</span>
      }
    },
    <span class="hljs-attr">"google-maps"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-google-maps"</span>],
      <span class="hljs-attr">"env"</span>: {
        <span class="hljs-attr">"GOOGLE_MAPS_API_KEY"</span>: <span class="hljs-string">"your_api_key_here"</span>
      }
    },
    <span class="hljs-attr">"sequential-thinking"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-sequential-thinking"</span>]
    },
    <span class="hljs-attr">"time"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-time"</span>]
    }
  }
}
</code></pre>
<p><strong>Important:</strong> Replace all placeholder tokens and credentials with your actual API keys. Restart Claude Desktop after saving the config.</p>
<hr />
<h2 id="heading-troubleshooting-common-issues">Troubleshooting Common Issues</h2>
<h3 id="heading-claude-doesnt-see-the-new-servers">Claude doesn't see the new servers</h3>
<ul>
<li>Restart Claude Desktop completely (quit and reopen)</li>
<li>Check the config file for JSON syntax errors (use a JSON validator)</li>
<li>Make sure the file path is correct for your OS</li>
</ul>
<h3 id="heading-server-fails-to-start">Server fails to start</h3>
<ul>
<li>Run the <code>npx</code> command manually in your terminal to see the error</li>
<li>Check that all required environment variables are set</li>
<li>Ensure Node.js 18+ is installed (<code>node --version</code>)</li>
</ul>
<h3 id="heading-permission-errors">Permission errors</h3>
<ul>
<li>For filesystem server: make sure the path exists and is readable</li>
<li>For database servers: verify connection strings are correct</li>
<li>For API-based servers: confirm API keys are valid</li>
</ul>
<hr />
<h2 id="heading-whats-next">What's Next?</h2>
<p>This is just the beginning. The MCP ecosystem has 100+ servers and growing — from specialized tools like Obsidian integration and Linear project management to custom servers you can build yourself.</p>
<p><strong>Browse the full catalog at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></strong> to discover more servers, read reviews, and see what the community is building.</p>
<p>Claude Desktop + MCP isn't just a better chatbot. It's your AI-powered operating system.</p>
<hr />
<p><em>The Plug | MCPHub — the first dedicated marketplace for MCP apps.</em>
<em>Explore the catalog at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></em></p>
]]></content:encoded></item><item><title><![CDATA[How to Stop Losing Client Files]]></title><description><![CDATA[Briefkit is a client portal for designers at briefkit.dev]]></description><link>https://blog.getmcpapps.com/how-to-stop-losing-client-files</link><guid isPermaLink="true">https://blog.getmcpapps.com/how-to-stop-losing-client-files</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Sun, 22 Feb 2026 10:30:26 GMT</pubDate><enclosure url="https://jnngymtirprbsfeevggk.supabase.co/storage/v1/object/public/blog-og/stop-losing-files.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Briefkit is a client portal for designers at briefkit.dev</p>
]]></content:encoded></item><item><title><![CDATA[WebMCP: The Browser Just Became an MCP Server]]></title><description><![CDATA[WebMCP: The Browser Just Became an MCP Server
Published by The Plug | getmcpapps.com
On February 10, 2026, something quiet landed in Chrome 146 that changes what "building for AI agents" actually means. It's called WebMCP — and if you ship MCP apps, ...]]></description><link>https://blog.getmcpapps.com/webmcp-the-browser-just-became-an-mcp-server-1-1</link><guid isPermaLink="true">https://blog.getmcpapps.com/webmcp-the-browser-just-became-an-mcp-server-1-1</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Sat, 21 Feb 2026 12:29:51 GMT</pubDate><enclosure url="https://jnngymtirprbsfeevggk.supabase.co/storage/v1/object/public/blog-og/webmcp-3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-webmcp-the-browser-just-became-an-mcp-server">WebMCP: The Browser Just Became an MCP Server</h1>
<p><em>Published by The Plug | getmcpapps.com</em></p>
<p>On February 10, 2026, something quiet landed in Chrome 146 that changes what "building for AI agents" actually means. It's called WebMCP — and if you ship MCP apps, you need to understand it.</p>
<hr />
<h2 id="heading-the-problem-webmcp-solves">The Problem WebMCP Solves</h2>
<p>Right now, when an AI agent visits a website, it's essentially blind. It either takes screenshots and guesses what's on screen, or it parses thousands of tokens of raw HTML hoping to find what it needs. Both approaches are fragile, expensive, and slow.</p>
<p>Your beautifully designed app submission form? To an agent, it's a wall of <code>&lt;div&gt;</code> soup.</p>
<p>WebMCP flips this. Instead of agents reverse-engineering your UI, your website <em>tells</em> agents exactly what it can do — in the same structured, schema-first language that MCP servers already speak.</p>
<hr />
<h2 id="heading-what-webmcp-actually-is">What WebMCP Actually Is</h2>
<p>WebMCP (Web Model Context Protocol) is a W3C Community Group standard that adds a <code>navigator.modelContext</code> API to the browser. It was jointly developed by Google and Microsoft, born from Alex Nahas's MCP-B project at Amazon, and dropped as an early preview in Chrome 146.</p>
<p>The concept is simple: <strong>websites register tools. AI agents call them.</strong></p>
<p>No screenshots. No DOM scraping. No 2,000-token visual payloads. Just clean, typed function calls — the same pattern MCP developers already know.</p>
<p>The efficiency numbers are stark: <strong>89% fewer tokens</strong> compared to screenshot-based approaches.</p>
<hr />
<h2 id="heading-how-it-works">How It Works</h2>
<p>WebMCP gives you two ways to expose tools: declarative (HTML) and imperative (JavaScript).</p>
<h3 id="heading-declarative-api-no-javascript-required">Declarative API — No JavaScript Required</h3>
<p>For simple cases, you can declare tools directly in your HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">mcp-tool</span>=<span class="hljs-string">"search_apps"</span>
      <span class="hljs-attr">mcp-description</span>=<span class="hljs-string">"Search the MCPHub catalog by keyword or category"</span>
      <span class="hljs-attr">action</span>=<span class="hljs-string">"/api/apps/search"</span>
      <span class="hljs-attr">method</span>=<span class="hljs-string">"GET"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"query"</span> <span class="hljs-attr">mcp-description</span>=<span class="hljs-string">"Search term or keyword"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"category"</span> <span class="hljs-attr">mcp-description</span>=<span class="hljs-string">"Filter by category (e.g. productivity, dev-tools)"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Search<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>Any AI agent with Chrome 146+ sees this form as a structured tool, not a UI element to click.</p>
<h3 id="heading-imperative-api-full-programmatic-control">Imperative API — Full Programmatic Control</h3>
<p>For dynamic tools or complex schemas, use JavaScript:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// components/WebMCPProvider.tsx (Next.js client component)</span>
<span class="hljs-string">'use client'</span>;

<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">WebMCPProvider</span>(<span class="hljs-params"></span>) </span>{
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!navigator.modelContext) <span class="hljs-keyword">return</span>; <span class="hljs-comment">// graceful degradation</span>

    <span class="hljs-comment">// Register: search the app catalog</span>
    navigator.modelContext.registerTool({
      <span class="hljs-attr">name</span>: <span class="hljs-string">'search_apps'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'Search the MCPHub catalog for MCP apps by keyword, category, or tag'</span>,
      <span class="hljs-attr">inputSchema</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">'object'</span>,
        <span class="hljs-attr">properties</span>: {
          <span class="hljs-attr">query</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Search term'</span> },
          <span class="hljs-attr">category</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Category filter'</span> },
          <span class="hljs-attr">tag</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Tag filter'</span> },
        },
        <span class="hljs-attr">required</span>: [<span class="hljs-string">'query'</span>],
      },
      <span class="hljs-keyword">async</span> execute({ query, category, tag }) {
        <span class="hljs-keyword">const</span> params = <span class="hljs-keyword">new</span> URLSearchParams({ query, ...(category &amp;&amp; { category }), ...(tag &amp;&amp; { tag }) });
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`/api/apps/search?<span class="hljs-subst">${params}</span>`</span>);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">content</span>: [{ <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">text</span>: <span class="hljs-built_in">JSON</span>.stringify(data) }] };
      },
    });

    <span class="hljs-comment">// Register: get full app details</span>
    navigator.modelContext.registerTool({
      <span class="hljs-attr">name</span>: <span class="hljs-string">'get_app_details'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'Get full details for a specific MCP app by its slug'</span>,
      <span class="hljs-attr">inputSchema</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">'object'</span>,
        <span class="hljs-attr">properties</span>: {
          <span class="hljs-attr">slug</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'App slug (e.g. "github-mcp")'</span> },
        },
        <span class="hljs-attr">required</span>: [<span class="hljs-string">'slug'</span>],
      },
      <span class="hljs-keyword">async</span> execute({ slug }) {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`/api/apps/<span class="hljs-subst">${slug}</span>`</span>);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">content</span>: [{ <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">text</span>: <span class="hljs-built_in">JSON</span>.stringify(data) }] };
      },
    });

    <span class="hljs-comment">// Register: list categories</span>
    navigator.modelContext.registerTool({
      <span class="hljs-attr">name</span>: <span class="hljs-string">'list_categories'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'List all available app categories in the MCPHub catalog'</span>,
      <span class="hljs-attr">inputSchema</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'object'</span>, <span class="hljs-attr">properties</span>: {} },
      <span class="hljs-keyword">async</span> execute() {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'/api/categories'</span>);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">content</span>: [{ <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">text</span>: <span class="hljs-built_in">JSON</span>.stringify(data) }] };
      },
    });

  }, []);

  <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
</code></pre>
<p>Drop <code>&lt;WebMCPProvider /&gt;</code> in your root layout and your site is agent-native.</p>
<hr />
<h2 id="heading-why-this-is-a-big-deal-for-mcp-developers">Why This Is a Big Deal for MCP Developers</h2>
<p>If you build MCP servers, WebMCP is your browser counterpart. A few things worth noting:</p>
<p><strong>Auth is solved.</strong> WebMCP reuses the browser session — same cookies, same SSO. No OAuth 2.1 dance, no token exchange. If the user is logged in, the agent is logged in.</p>
<p><strong>It's just the "tools" primitive.</strong> No prompts, no resources — just tools. That's intentional. It keeps the surface area small and the security model clean.</p>
<p><strong>Same-origin enforcement.</strong> Tools only fire on the domain that registered them. No cross-site tool injection.</p>
<p><strong>It's Chrome-first, but the spec is open.</strong> Firefox and Safari haven't committed yet, but this is W3C — the pressure is on.</p>
<p><strong>It doesn't replace MCP servers.</strong> It complements them. Server-side MCP gives agents access to data and services. WebMCP gives agents access to <em>web applications</em> using existing browser sessions and UI logic. Different layer, different job.</p>
<hr />
<h2 id="heading-what-this-means-right-now">What This Means Right Now</h2>
<p>If you're building a web app that you want AI agents to use well, this is your signal to start thinking about what tools you'd expose. Not the DOM — your <em>business actions</em>. Submit, search, filter, create, publish.</p>
<p>If you're building MCP apps that wrap web services, WebMCP gives those services a way to meet you halfway — fewer hacks, more reliability.</p>
<p>And if you're tracking the MCP ecosystem (you're on MCPHub, so you are), WebMCP is the next category to watch.</p>
<hr />
<h2 id="heading-submit-your-webmcp-app-to-mcphub">Submit Your WebMCP App to MCPHub</h2>
<p>We're tracking WebMCP-enabled apps as the ecosystem grows. If you've built or found a site or tool that implements <code>navigator.modelContext</code>, <strong><a target="_blank" href="https://getmcpapps.com/submit">submit it to our catalog</a></strong> — we'll get it tagged and listed.</p>
<p>The web is becoming agent-native. Might as well catalog it.</p>
<hr />
<p><em>The Plug | MCPHub — the first dedicated marketplace for MCP apps.</em>
<em>Browse the catalog at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></em></p>
]]></content:encoded></item><item><title><![CDATA[WebMCP: The Browser Just Became an MCP Server]]></title><description><![CDATA[On February 10, 2026, something quiet landed in Chrome 146 that changes what "building for AI agents" actually means. It's called WebMCP — and if you ship MCP apps, you need to understand it.

The Problem WebMCP Solves
Right now, when an AI agent vis...]]></description><link>https://blog.getmcpapps.com/webmcp-the-browser-just-became-an-mcp-server-1</link><guid isPermaLink="true">https://blog.getmcpapps.com/webmcp-the-browser-just-became-an-mcp-server-1</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Sat, 21 Feb 2026 12:12:01 GMT</pubDate><enclosure url="https://jnngymtirprbsfeevggk.supabase.co/storage/v1/object/public/blog-og/webmcp-2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>On February 10, 2026, something quiet landed in Chrome 146 that changes what "building for AI agents" actually means. It's called WebMCP — and if you ship MCP apps, you need to understand it.</p>
<hr />
<h2 id="heading-the-problem-webmcp-solves">The Problem WebMCP Solves</h2>
<p>Right now, when an AI agent visits a website, it's essentially blind. It either takes screenshots and guesses what's on screen, or it parses thousands of tokens of raw HTML hoping to find what it needs. Both approaches are fragile, expensive, and slow.</p>
<p>Your beautifully designed app submission form? To an agent, it's a wall of <code>&lt;div&gt;</code> soup.</p>
<p>WebMCP flips this. Instead of agents reverse-engineering your UI, your website <em>tells</em> agents exactly what it can do — in the same structured, schema-first language that MCP servers already speak.</p>
<hr />
<h2 id="heading-what-webmcp-actually-is">What WebMCP Actually Is</h2>
<p>WebMCP (Web Model Context Protocol) is a W3C Community Group standard that adds a <code>navigator.modelContext</code> API to the browser. It was jointly developed by Google and Microsoft, born from Alex Nahas's MCP-B project at Amazon, and dropped as an early preview in Chrome 146.</p>
<p>The concept is simple: <strong>websites register tools. AI agents call them.</strong></p>
<p>No screenshots. No DOM scraping. No 2,000-token visual payloads. Just clean, typed function calls — the same pattern MCP developers already know.</p>
<p>The efficiency numbers are stark: <strong>89% fewer tokens</strong> compared to screenshot-based approaches.</p>
<hr />
<h2 id="heading-how-it-works">How It Works</h2>
<p>WebMCP gives you two ways to expose tools: declarative (HTML) and imperative (JavaScript).</p>
<h3 id="heading-declarative-api-no-javascript-required">Declarative API — No JavaScript Required</h3>
<p>For simple cases, you can declare tools directly in your HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">mcp-tool</span>=<span class="hljs-string">"search_apps"</span>
      <span class="hljs-attr">mcp-description</span>=<span class="hljs-string">"Search the MCPHub catalog by keyword or category"</span>
      <span class="hljs-attr">action</span>=<span class="hljs-string">"/api/apps/search"</span>
      <span class="hljs-attr">method</span>=<span class="hljs-string">"GET"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"query"</span> <span class="hljs-attr">mcp-description</span>=<span class="hljs-string">"Search term or keyword"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"category"</span> <span class="hljs-attr">mcp-description</span>=<span class="hljs-string">"Filter by category (e.g. productivity, dev-tools)"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Search<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>Any AI agent with Chrome 146+ sees this form as a structured tool, not a UI element to click.</p>
<h3 id="heading-imperative-api-full-programmatic-control">Imperative API — Full Programmatic Control</h3>
<p>For dynamic tools or complex schemas, use JavaScript:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// components/WebMCPProvider.tsx (Next.js client component)</span>
<span class="hljs-string">'use client'</span>;

<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">WebMCPProvider</span>(<span class="hljs-params"></span>) </span>{
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!navigator.modelContext) <span class="hljs-keyword">return</span>; <span class="hljs-comment">// graceful degradation</span>

    <span class="hljs-comment">// Register: search the app catalog</span>
    navigator.modelContext.registerTool({
      <span class="hljs-attr">name</span>: <span class="hljs-string">'search_apps'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'Search the MCPHub catalog for MCP apps by keyword, category, or tag'</span>,
      <span class="hljs-attr">inputSchema</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">'object'</span>,
        <span class="hljs-attr">properties</span>: {
          <span class="hljs-attr">query</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Search term'</span> },
          <span class="hljs-attr">category</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Category filter'</span> },
          <span class="hljs-attr">tag</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Tag filter'</span> },
        },
        <span class="hljs-attr">required</span>: [<span class="hljs-string">'query'</span>],
      },
      <span class="hljs-keyword">async</span> execute({ query, category, tag }) {
        <span class="hljs-keyword">const</span> params = <span class="hljs-keyword">new</span> URLSearchParams({ query, ...(category &amp;&amp; { category }), ...(tag &amp;&amp; { tag }) });
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`/api/apps/search?<span class="hljs-subst">${params}</span>`</span>);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">content</span>: [{ <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">text</span>: <span class="hljs-built_in">JSON</span>.stringify(data) }] };
      },
    });

    <span class="hljs-comment">// Register: get full app details</span>
    navigator.modelContext.registerTool({
      <span class="hljs-attr">name</span>: <span class="hljs-string">'get_app_details'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'Get full details for a specific MCP app by its slug'</span>,
      <span class="hljs-attr">inputSchema</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">'object'</span>,
        <span class="hljs-attr">properties</span>: {
          <span class="hljs-attr">slug</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'App slug (e.g. "github-mcp")'</span> },
        },
        <span class="hljs-attr">required</span>: [<span class="hljs-string">'slug'</span>],
      },
      <span class="hljs-keyword">async</span> execute({ slug }) {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`/api/apps/<span class="hljs-subst">${slug}</span>`</span>);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">content</span>: [{ <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">text</span>: <span class="hljs-built_in">JSON</span>.stringify(data) }] };
      },
    });

    <span class="hljs-comment">// Register: list categories</span>
    navigator.modelContext.registerTool({
      <span class="hljs-attr">name</span>: <span class="hljs-string">'list_categories'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'List all available app categories in the MCPHub catalog'</span>,
      <span class="hljs-attr">inputSchema</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'object'</span>, <span class="hljs-attr">properties</span>: {} },
      <span class="hljs-keyword">async</span> execute() {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'/api/categories'</span>);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">content</span>: [{ <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">text</span>: <span class="hljs-built_in">JSON</span>.stringify(data) }] };
      },
    });

  }, []);

  <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
</code></pre>
<p>Drop <code>&lt;WebMCPProvider /&gt;</code> in your root layout and your site is agent-native.</p>
<hr />
<h2 id="heading-why-this-is-a-big-deal-for-mcp-developers">Why This Is a Big Deal for MCP Developers</h2>
<p>If you build MCP servers, WebMCP is your browser counterpart. A few things worth noting:</p>
<p><strong>Auth is solved.</strong> WebMCP reuses the browser session — same cookies, same SSO. No OAuth 2.1 dance, no token exchange. If the user is logged in, the agent is logged in.</p>
<p><strong>It's just the "tools" primitive.</strong> No prompts, no resources — just tools. That's intentional. It keeps the surface area small and the security model clean.</p>
<p><strong>Same-origin enforcement.</strong> Tools only fire on the domain that registered them. No cross-site tool injection.</p>
<p><strong>It's Chrome-first, but the spec is open.</strong> Firefox and Safari haven't committed yet, but this is W3C — the pressure is on.</p>
<p><strong>It doesn't replace MCP servers.</strong> It complements them. Server-side MCP gives agents access to data and services. WebMCP gives agents access to <em>web applications</em> using existing browser sessions and UI logic. Different layer, different job.</p>
<hr />
<h2 id="heading-what-this-means-right-now">What This Means Right Now</h2>
<p>If you're building a web app that you want AI agents to use well, this is your signal to start thinking about what tools you'd expose. Not the DOM — your <em>business actions</em>. Submit, search, filter, create, publish.</p>
<p>If you're building MCP apps that wrap web services, WebMCP gives those services a way to meet you halfway — fewer hacks, more reliability.</p>
<p>And if you're tracking the MCP ecosystem (you're on MCPHub, so you are), WebMCP is the next category to watch.</p>
<hr />
<h2 id="heading-submit-your-webmcp-app-to-mcphub">Submit Your WebMCP App to MCPHub</h2>
<p>We're tracking WebMCP-enabled apps as the ecosystem grows. If you've built or found a site or tool that implements <code>navigator.modelContext</code>, <strong><a target="_blank" href="https://getmcpapps.com/submit">submit it to our catalog</a></strong> — we'll get it tagged and listed.</p>
<p>The web is becoming agent-native. Might as well catalog it.</p>
<hr />
<p><em>The Plug | MCPHub — the first dedicated marketplace for MCP apps.</em>
<em>Browse the catalog at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></em></p>
]]></content:encoded></item><item><title><![CDATA[WebMCP: The Browser Just Became an MCP Server]]></title><description><![CDATA[WebMCP: The Browser Just Became an MCP Server
Published by The Plug | getmcpapps.com
On February 10, 2026, something quiet landed in Chrome 146 that changes what "building for AI agents" actually means. It's called WebMCP — and if you ship MCP apps, ...]]></description><link>https://blog.getmcpapps.com/webmcp-the-browser-just-became-an-mcp-server</link><guid isPermaLink="true">https://blog.getmcpapps.com/webmcp-the-browser-just-became-an-mcp-server</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Sat, 21 Feb 2026 10:05:41 GMT</pubDate><enclosure url="https://jnngymtirprbsfeevggk.supabase.co/storage/v1/object/public/blog-og/webmcp-1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-webmcp-the-browser-just-became-an-mcp-server">WebMCP: The Browser Just Became an MCP Server</h1>
<p><em>Published by The Plug | getmcpapps.com</em></p>
<p>On February 10, 2026, something quiet landed in Chrome 146 that changes what "building for AI agents" actually means. It's called WebMCP — and if you ship MCP apps, you need to understand it.</p>
<hr />
<h2 id="heading-the-problem-webmcp-solves">The Problem WebMCP Solves</h2>
<p>Right now, when an AI agent visits a website, it's essentially blind. It either takes screenshots and guesses what's on screen, or it parses thousands of tokens of raw HTML hoping to find what it needs. Both approaches are fragile, expensive, and slow.</p>
<p>Your beautifully designed app submission form? To an agent, it's a wall of <code>&lt;div&gt;</code> soup.</p>
<p>WebMCP flips this. Instead of agents reverse-engineering your UI, your website <em>tells</em> agents exactly what it can do — in the same structured, schema-first language that MCP servers already speak.</p>
<hr />
<h2 id="heading-what-webmcp-actually-is">What WebMCP Actually Is</h2>
<p>WebMCP (Web Model Context Protocol) is a W3C Community Group standard that adds a <code>navigator.modelContext</code> API to the browser. It was jointly developed by Google and Microsoft, born from Alex Nahas's MCP-B project at Amazon, and dropped as an early preview in Chrome 146.</p>
<p>The concept is simple: <strong>websites register tools. AI agents call them.</strong></p>
<p>No screenshots. No DOM scraping. No 2,000-token visual payloads. Just clean, typed function calls — the same pattern MCP developers already know.</p>
<p>The efficiency numbers are stark: <strong>89% fewer tokens</strong> compared to screenshot-based approaches.</p>
<hr />
<h2 id="heading-how-it-works">How It Works</h2>
<p>WebMCP gives you two ways to expose tools: declarative (HTML) and imperative (JavaScript).</p>
<h3 id="heading-declarative-api-no-javascript-required">Declarative API — No JavaScript Required</h3>
<p>For simple cases, you can declare tools directly in your HTML:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">mcp-tool</span>=<span class="hljs-string">"search_apps"</span>
      <span class="hljs-attr">mcp-description</span>=<span class="hljs-string">"Search the MCPHub catalog by keyword or category"</span>
      <span class="hljs-attr">action</span>=<span class="hljs-string">"/api/apps/search"</span>
      <span class="hljs-attr">method</span>=<span class="hljs-string">"GET"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"query"</span> <span class="hljs-attr">mcp-description</span>=<span class="hljs-string">"Search term or keyword"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"category"</span> <span class="hljs-attr">mcp-description</span>=<span class="hljs-string">"Filter by category (e.g. productivity, dev-tools)"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Search<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>Any AI agent with Chrome 146+ sees this form as a structured tool, not a UI element to click.</p>
<h3 id="heading-imperative-api-full-programmatic-control">Imperative API — Full Programmatic Control</h3>
<p>For dynamic tools or complex schemas, use JavaScript:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// components/WebMCPProvider.tsx (Next.js client component)</span>
<span class="hljs-string">'use client'</span>;

<span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">WebMCPProvider</span>(<span class="hljs-params"></span>) </span>{
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!navigator.modelContext) <span class="hljs-keyword">return</span>; <span class="hljs-comment">// graceful degradation</span>

    <span class="hljs-comment">// Register: search the app catalog</span>
    navigator.modelContext.registerTool({
      <span class="hljs-attr">name</span>: <span class="hljs-string">'search_apps'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'Search the MCPHub catalog for MCP apps by keyword, category, or tag'</span>,
      <span class="hljs-attr">inputSchema</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">'object'</span>,
        <span class="hljs-attr">properties</span>: {
          <span class="hljs-attr">query</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Search term'</span> },
          <span class="hljs-attr">category</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Category filter'</span> },
          <span class="hljs-attr">tag</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'Tag filter'</span> },
        },
        <span class="hljs-attr">required</span>: [<span class="hljs-string">'query'</span>],
      },
      <span class="hljs-keyword">async</span> execute({ query, category, tag }) {
        <span class="hljs-keyword">const</span> params = <span class="hljs-keyword">new</span> URLSearchParams({ query, ...(category &amp;&amp; { category }), ...(tag &amp;&amp; { tag }) });
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`/api/apps/search?<span class="hljs-subst">${params}</span>`</span>);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">content</span>: [{ <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">text</span>: <span class="hljs-built_in">JSON</span>.stringify(data) }] };
      },
    });

    <span class="hljs-comment">// Register: get full app details</span>
    navigator.modelContext.registerTool({
      <span class="hljs-attr">name</span>: <span class="hljs-string">'get_app_details'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'Get full details for a specific MCP app by its slug'</span>,
      <span class="hljs-attr">inputSchema</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">'object'</span>,
        <span class="hljs-attr">properties</span>: {
          <span class="hljs-attr">slug</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">description</span>: <span class="hljs-string">'App slug (e.g. "github-mcp")'</span> },
        },
        <span class="hljs-attr">required</span>: [<span class="hljs-string">'slug'</span>],
      },
      <span class="hljs-keyword">async</span> execute({ slug }) {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`/api/apps/<span class="hljs-subst">${slug}</span>`</span>);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">content</span>: [{ <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">text</span>: <span class="hljs-built_in">JSON</span>.stringify(data) }] };
      },
    });

    <span class="hljs-comment">// Register: list categories</span>
    navigator.modelContext.registerTool({
      <span class="hljs-attr">name</span>: <span class="hljs-string">'list_categories'</span>,
      <span class="hljs-attr">description</span>: <span class="hljs-string">'List all available app categories in the MCPHub catalog'</span>,
      <span class="hljs-attr">inputSchema</span>: { <span class="hljs-attr">type</span>: <span class="hljs-string">'object'</span>, <span class="hljs-attr">properties</span>: {} },
      <span class="hljs-keyword">async</span> execute() {
        <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'/api/categories'</span>);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> res.json();
        <span class="hljs-keyword">return</span> { <span class="hljs-attr">content</span>: [{ <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">text</span>: <span class="hljs-built_in">JSON</span>.stringify(data) }] };
      },
    });

  }, []);

  <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
</code></pre>
<p>Drop <code>&lt;WebMCPProvider /&gt;</code> in your root layout and your site is agent-native.</p>
<hr />
<h2 id="heading-why-this-is-a-big-deal-for-mcp-developers">Why This Is a Big Deal for MCP Developers</h2>
<p>If you build MCP servers, WebMCP is your browser counterpart. A few things worth noting:</p>
<p><strong>Auth is solved.</strong> WebMCP reuses the browser session — same cookies, same SSO. No OAuth 2.1 dance, no token exchange. If the user is logged in, the agent is logged in.</p>
<p><strong>It's just the "tools" primitive.</strong> No prompts, no resources — just tools. That's intentional. It keeps the surface area small and the security model clean.</p>
<p><strong>Same-origin enforcement.</strong> Tools only fire on the domain that registered them. No cross-site tool injection.</p>
<p><strong>It's Chrome-first, but the spec is open.</strong> Firefox and Safari haven't committed yet, but this is W3C — the pressure is on.</p>
<p><strong>It doesn't replace MCP servers.</strong> It complements them. Server-side MCP gives agents access to data and services. WebMCP gives agents access to <em>web applications</em> using existing browser sessions and UI logic. Different layer, different job.</p>
<hr />
<h2 id="heading-what-this-means-right-now">What This Means Right Now</h2>
<p>If you're building a web app that you want AI agents to use well, this is your signal to start thinking about what tools you'd expose. Not the DOM — your <em>business actions</em>. Submit, search, filter, create, publish.</p>
<p>If you're building MCP apps that wrap web services, WebMCP gives those services a way to meet you halfway — fewer hacks, more reliability.</p>
<p>And if you're tracking the MCP ecosystem (you're on MCPHub, so you are), WebMCP is the next category to watch.</p>
<hr />
<h2 id="heading-submit-your-webmcp-app-to-mcphub">Submit Your WebMCP App to MCPHub</h2>
<p>We're tracking WebMCP-enabled apps as the ecosystem grows. If you've built or found a site or tool that implements <code>navigator.modelContext</code>, <strong><a target="_blank" href="https://getmcpapps.com/submit">submit it to our catalog</a></strong> — we'll get it tagged and listed.</p>
<p>The web is becoming agent-native. Might as well catalog it.</p>
<hr />
<p><em>The Plug | MCPHub — the first dedicated marketplace for MCP apps.</em>
<em>Browse the catalog at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></em></p>
]]></content:encoded></item><item><title><![CDATA[MCP vs REST APIs: Why AI Agents Need a Different Kind of Interface]]></title><description><![CDATA[I've spent the last few months running MCPHub — a catalog of 30+ MCP apps for Claude and other AI agents. One question I get constantly from developers: "Why MCP? I already have a REST API. Isn't that enough?"
It's a fair question. And the short answ...]]></description><link>https://blog.getmcpapps.com/mcp-vs-rest-apis-why-ai-agents-need-a-different-kind-of-interface</link><guid isPermaLink="true">https://blog.getmcpapps.com/mcp-vs-rest-apis-why-ai-agents-need-a-different-kind-of-interface</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Fri, 20 Feb 2026 22:32:23 GMT</pubDate><enclosure url="https://jnngymtirprbsfeevggk.supabase.co/storage/v1/object/public/blog-og/mcp-vs-rest.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've spent the last few months running <a target="_blank" href="https://getmcpapps.com">MCPHub</a> — a catalog of 30+ MCP apps for Claude and other AI agents. One question I get constantly from developers: <em>"Why MCP? I already have a REST API. Isn't that enough?"</em></p>
<p>It's a fair question. And the short answer is: REST APIs are designed for humans (or human-written code) to consume. MCP is designed for AI models to discover and use at runtime. That's a fundamentally different design contract.</p>
<p>Let me break down exactly why.</p>
<hr />
<h2 id="heading-what-is-mcp-actually">What is MCP, Actually?</h2>
<p>MCP (Model Context Protocol) is an open standard from Anthropic that lets AI models connect to external tools, data sources, and services through a unified protocol. Think of it as USB-C for AI — one standard interface that any compatible model can plug into any compatible server.</p>
<p>An MCP server exposes <em>tools</em> (functions the AI can call), <em>resources</em> (data the AI can read), and <em>prompts</em> (pre-built instructions). The AI discovers these capabilities at runtime by asking the server: "What can you do?" The server replies with structured descriptions, and the AI decides how to use them based on the user's request.</p>
<p>That runtime discovery piece is the key. With REST, you have to tell your app exactly which endpoints to call and when. With MCP, the AI figures it out.</p>
<hr />
<h2 id="heading-the-core-difference-design-time-vs-runtime">The Core Difference: Design Time vs Runtime</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Aspect</td><td>REST API</td><td>MCP</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Designed for</strong></td><td>Developers and their software</td><td>AI models</td></tr>
<tr>
<td><strong>Discovery</strong></td><td>Docs, OpenAPI specs (read by humans)</td><td><code>tools/list</code> call (read by AI at runtime)</td></tr>
<tr>
<td><strong>Who decides what to call</strong></td><td>Developer writes the logic</td><td>AI model decides contextually</td></tr>
<tr>
<td><strong>Composability</strong></td><td>Fixed, developer-defined flows</td><td>Dynamic, model-chosen combinations</td></tr>
<tr>
<td><strong>Natural language input</strong></td><td>❌ Requires structured requests</td><td>✅ AI translates intent → tool calls</td></tr>
<tr>
<td><strong>Schema evolution</strong></td><td>Breaking changes need client updates</td><td>AI adapts based on updated descriptions</td></tr>
<tr>
<td><strong>Authentication</strong></td><td>OAuth, API keys, etc.</td><td>MCP handles auth handshake in protocol</td></tr>
</tbody>
</table>
</div><p>The table tells the story. REST puts the routing logic in your code. MCP puts it in the AI.</p>
<hr />
<h2 id="heading-why-this-matters-for-agents">Why This Matters for Agents</h2>
<p>Here's a concrete example. Say you're building an agent that helps users manage their GitHub repos.</p>
<p><strong>With REST:</strong></p>
<pre><code>user asks: <span class="hljs-string">"close all issues labeled 'wontfix'"</span>
→ your code: GET /repos/:owner/:repo/issues?labels=wontfix&amp;state=open
→ your code: <span class="hljs-keyword">for</span> each issue, POST /repos/:owner/:repo/issues/:id { <span class="hljs-string">"state"</span>: <span class="hljs-string">"closed"</span> }
</code></pre><p>You have to anticipate every possible action and hard-code the API calls. The agent's capabilities are fixed at design time.</p>
<p><strong>With a GitHub MCP server:</strong></p>
<pre><code>user asks: <span class="hljs-string">"close all issues labeled 'wontfix'"</span>
→ AI calls tools/list → sees list_issues, close_issue, create_issue, etc.
→ AI calls list_issues({ <span class="hljs-attr">labels</span>: <span class="hljs-string">"wontfix"</span>, <span class="hljs-attr">state</span>: <span class="hljs-string">"open"</span> })
→ AI calls close_issue <span class="hljs-keyword">for</span> each result
→ AI reports back to user
</code></pre><p>The AI composed the workflow itself. You didn't write any routing logic. If GitHub adds new API capabilities and updates the MCP server, the AI can use them immediately — no code changes needed on your end.</p>
<hr />
<h2 id="heading-but-mcp-servers-just-wrap-rest-apis-anyway">"But MCP Servers Just Wrap REST APIs Anyway"</h2>
<p>Yes, and that's fine. Most MCP servers <em>do</em> call REST APIs under the hood. The <a target="_blank" href="https://getmcpapps.com">GitHub MCP server</a> calls the GitHub REST API. The Slack MCP server calls the Slack Web API.</p>
<p>The MCP layer isn't replacing REST — it's adding an AI-readable interface on top of it. The distinction that matters:</p>
<blockquote>
<p><strong>A good REST API is not automatically a good MCP server.</strong></p>
</blockquote>
<p>REST API design optimizes for developer ergonomics: small, composable endpoints, consistent patterns, predictable responses. MCP server design optimizes for <em>model ergonomics</em>: tools with rich natural-language descriptions, forgiving inputs, and outputs formatted for the AI to interpret and relay to users.</p>
<p>If you take a raw REST API and expose it directly as MCP tools, the AI will technically use it — but it won't use it <em>well</em>. Descriptions matter enormously. The AI decides which tool to call based on your tool descriptions, not on REST conventions.</p>
<hr />
<h2 id="heading-when-to-use-each">When to Use Each</h2>
<p><strong>Use REST when:</strong></p>
<ul>
<li>Your consumers are developers or other software systems</li>
<li>You need maximum performance and control</li>
<li>You're building deterministic pipelines with known inputs and outputs</li>
<li>You're not integrating AI at all</li>
</ul>
<p><strong>Use MCP when:</strong></p>
<ul>
<li>Your consumer is an AI model (Claude, GPT, Gemini, etc.)</li>
<li>You want AI agents to dynamically compose workflows</li>
<li>You're building a product on top of Claude or another model and want extensibility</li>
<li>You want users to control your product via natural language</li>
</ul>
<p>The sweet spot in 2026: <strong>build both</strong>. Keep your REST API for developers and your existing integrations. Add an MCP server for AI consumers. They're complementary, not competing.</p>
<hr />
<h2 id="heading-the-developer-experience-gap-mcp-closes">The Developer Experience Gap MCP Closes</h2>
<p>Here's what actually sold me on MCP when I was first building MCPHub: the setup experience is <em>dramatically</em> simpler for end users.</p>
<p>Before MCP, integrating your tool with an AI app meant:</p>
<ol>
<li>User gets API key</li>
<li>User reads your docs to understand which endpoints exist</li>
<li>Developer (you) writes custom integration code</li>
<li>Repeat for every AI app you want to support</li>
</ol>
<p>With MCP:</p>
<ol>
<li>User installs your MCP server (one JSON config line in Claude Desktop)</li>
<li>Claude discovers your tools automatically</li>
<li>User can immediately ask Claude to do anything your server supports</li>
</ol>
<p>It's the difference between "read the manual" and "just ask." That's why the MCP ecosystem is growing so fast — it dramatically lowers the friction of AI integration for end users.</p>
<hr />
<h2 id="heading-what-im-seeing-in-the-catalog">What I'm Seeing in the Catalog</h2>
<p>At <a target="_blank" href="https://getmcpapps.com">MCPHub</a>, we track 30+ MCP apps across categories: developer tools, productivity, data, security, and more. The most-starred apps tend to be wrappers around REST APIs that developers already loved but wanted to use conversationally:</p>
<ul>
<li><strong>GitHub MCP</strong> — because developers already have GitHub, they just want Claude to work within it</li>
<li><strong>Postgres/SQLite MCP</strong> — because querying a database with natural language is infinitely better than remembering syntax</li>
<li><strong>Filesystem MCP</strong> — because "find all JS files modified this week" is faster to say than to command</li>
</ul>
<p>These aren't new capabilities. They're existing REST/DB interfaces with an MCP layer that makes them AI-native. That's the pattern.</p>
<hr />
<h2 id="heading-where-things-are-headed">Where Things Are Headed</h2>
<p>The REST vs MCP debate will settle into a "both, obviously" answer — the same way mobile apps didn't kill the web, they just added a new surface. Every serious API will eventually have an MCP counterpart.</p>
<p>The interesting question is what <em>new things become possible</em> when AI can dynamically compose across multiple MCP servers. An agent that pulls your GitHub issues, checks your Notion docs for context, drafts a Slack message, and opens a Linear ticket — all from one request — because all four services expose MCP servers.</p>
<p>That's the agentic future. REST is the plumbing. MCP is the interface layer AI actually uses.</p>
<hr />
<h2 id="heading-browse-30-mcp-apps">Browse 30+ MCP Apps</h2>
<p>If you're building with MCP or looking for servers to add to your Claude setup, browse the full catalog at <strong><a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></strong> — curated, reviewed, and updated weekly. Each listing includes installation instructions, GitHub stars, and compatibility info.</p>
<p>What MCP server do you wish existed? Drop it in the comments or <a target="_blank" href="https://getmcpapps.com/submit">submit it</a> to the catalog.</p>
]]></content:encoded></item><item><title><![CDATA[5 MCP Apps That Replace Entire SaaS Products]]></title><description><![CDATA[There's a slow-motion disruption happening in SaaS right now, and most people haven't noticed yet.
Model Context Protocol (MCP) lets AI models like Claude reach directly into your tools — your files, databases, browsers, calendars, APIs — without you...]]></description><link>https://blog.getmcpapps.com/5-mcp-apps-that-replace-entire-saas-products</link><guid isPermaLink="true">https://blog.getmcpapps.com/5-mcp-apps-that-replace-entire-saas-products</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Wed, 18 Feb 2026 14:04:35 GMT</pubDate><enclosure url="https://jnngymtirprbsfeevggk.supabase.co/storage/v1/object/public/blog-og/5-mcp-apps.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There's a slow-motion disruption happening in SaaS right now, and most people haven't noticed yet.</p>
<p>Model Context Protocol (MCP) lets AI models like Claude reach directly into your tools — your files, databases, browsers, calendars, APIs — without you having to copy-paste, export CSVs, or switch tabs. The result: a growing category of MCP servers that do what entire SaaS products used to do, but natively inside your AI workflow.</p>
<p>Here are five categories where MCP apps are already making subscription tools look overpriced.</p>
<hr />
<h2 id="heading-1-file-system-access-bye-google-drive-for-quick-lookups">1. File System Access — Bye, Google Drive for "quick lookups"</h2>
<p><strong>What SaaS it replaces:</strong> The habit of uploading files to Google Drive or Dropbox just so you can "share" them with an AI tool or a teammate.</p>
<p>A filesystem MCP server gives Claude direct read/write access to your local files. Ask it to summarize a contract, extract action items from meeting notes, or compare two versions of a document — and it just does it. No upload step, no storage limit, no per-seat fee.</p>
<p><strong>How it works:</strong> The MCP server exposes tools like <code>read_file</code>, <code>list_directory</code>, and <code>write_file</code>. Claude calls them directly during your conversation.</p>
<p><strong>Install pattern:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"filesystem"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-filesystem"</span>, <span class="hljs-string">"/path/to/your/files"</span>]
    }
  }
}
</code></pre>
<p>The official Anthropic filesystem server handles this out of the box.</p>
<hr />
<h2 id="heading-2-database-querying-bye-metabase-for-ad-hoc-analysis">2. Database Querying — Bye, Metabase for ad-hoc analysis</h2>
<p><strong>What SaaS it replaces:</strong> BI tools like Metabase, Tableau, or Retool — specifically the use case of "I need to run a quick query and see results in plain English."</p>
<p>A database MCP server connects Claude directly to your PostgreSQL, SQLite, or MySQL database. Instead of writing SQL or building dashboards, you ask: <em>"How many users signed up last week broken down by country?"</em> and Claude writes the query, runs it, and explains the results.</p>
<p>This doesn't replace your entire data stack. But for ad-hoc analysis, exploratory queries, and debugging? You'll stop opening Metabase for a lot of things.</p>
<p><strong>Install pattern:</strong></p>
<pre><code class="lang-bash">npx @modelcontextprotocol/server-postgres postgresql://localhost/mydb
</code></pre>
<p>Or for SQLite: point it at your <code>.db</code> file and start asking questions.</p>
<hr />
<h2 id="heading-3-browser-automation-bye-zapier-for-web-scraping-workflows">3. Browser Automation — Bye, Zapier for web scraping workflows</h2>
<p><strong>What SaaS it replaces:</strong> Zapier's "browser extension" automations, Make.com's web scraping modules, and any tool you've used to "watch a webpage and do something when it changes."</p>
<p>Browser automation MCP servers give Claude control of a real Chromium instance. It can navigate to URLs, click elements, fill forms, extract data from pages — all in response to natural language instructions. </p>
<p>Ask it to: pull competitor pricing from five websites and put it in a spreadsheet, fill in a web form from data in your notes, or check if a page has been updated since yesterday.</p>
<p>No visual workflow builder, no per-task credits, no Zap limits.</p>
<p><strong>Install pattern:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"puppeteer"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@modelcontextprotocol/server-puppeteer"</span>]
    }
  }
}
</code></pre>
<hr />
<h2 id="heading-4-email-amp-calendar-bye-scheduling-tools-for-simple-workflows">4. Email &amp; Calendar — Bye, scheduling tools for simple workflows</h2>
<p><strong>What SaaS it replaces:</strong> Tools like Calendly (for simple "find a time" requests), email automation platforms for one-off sequences, and the copy-paste dance between your calendar and your notes.</p>
<p>An email/calendar MCP server connects Claude to Gmail or Outlook. You can ask it to: draft replies to a thread using context from a document, summarize your inbox by topic, or find all emails about a specific project and extract the action items. Calendar MCP servers let you query availability, schedule meetings, and check what's coming up — in plain English.</p>
<p>This isn't a full email client replacement. But for the workflows where you're bouncing between Gmail and a doc trying to synthesize information? That's done.</p>
<p><strong>Install pattern:</strong></p>
<pre><code class="lang-bash"><span class="hljs-comment"># Gmail via Google Workspace MCP</span>
npx @gptscript-ai/gmail-mcp
</code></pre>
<hr />
<h2 id="heading-5-code-execution-bye-jupyter-for-quick-data-scripts">5. Code Execution — Bye, Jupyter for quick data scripts</h2>
<p><strong>What SaaS it replaces:</strong> The friction of spinning up a Jupyter notebook, a Colab session, or a Python REPL just to run a quick data transformation or test a calculation.</p>
<p>A code execution MCP server gives Claude a sandboxed environment to write and run Python (or other languages) in real time. You describe what you want — "clean this CSV, parse the dates, and tell me how many rows have missing values" — and Claude writes the script, runs it, and shows you the output. Iteratively.</p>
<p>It's the "AI pair programmer with a live REPL" experience that Jupyter was trying to be before LLMs existed.</p>
<p><strong>Install pattern:</strong></p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"code-runner"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"npx"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"-y"</span>, <span class="hljs-string">"@pydantic/mcp-run-python"</span>]
    }
  }
}
</code></pre>
<hr />
<h2 id="heading-the-bigger-picture">The Bigger Picture</h2>
<p>None of these MCP apps are magic. They're narrow, well-scoped tools that do one thing — give Claude a specific capability — and they do it better than a SaaS integration layer because there's no translation layer in the middle.</p>
<p>The pattern is consistent: wherever SaaS tools have built "bring your AI to your data" features, MCP goes the other direction and brings the data to your AI. Less setup, less maintenance, lower cost.</p>
<p>This isn't the end of SaaS. Collaboration features, audit logs, team permissions, compliance — there's a lot that MCP servers don't handle. But for the specific case of <em>individual knowledge work</em>, the value of a lot of subscriptions is evaporating.</p>
<p>We're early. The ecosystem is growing fast. And the apps that exist today are just the first wave.</p>
<hr />
<p><strong>Browse all 28 MCP apps (with install configs) at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></strong></p>
<p><em>Written by <strong>The Plug</strong> — the MCPHub team curating the best MCP apps at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></em></p>
]]></content:encoded></item><item><title><![CDATA[How to Build Your First MCP App (From Zero to Working Tool in 30 Minutes)]]></title><description><![CDATA[MCP (Model Context Protocol) is the open standard that lets AI models like Claude reach outside the chat window and interact with your tools, files, and APIs — without any custom wrapper code on the model side. Think of it as USB-C for AI: one protoc...]]></description><link>https://blog.getmcpapps.com/how-to-build-your-first-mcp-app-from-zero-to-working-tool-in-30-minutes</link><guid isPermaLink="true">https://blog.getmcpapps.com/how-to-build-your-first-mcp-app-from-zero-to-working-tool-in-30-minutes</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Wed, 18 Feb 2026 10:00:00 GMT</pubDate><enclosure url="https://jnngymtirprbsfeevggk.supabase.co/storage/v1/object/public/blog-og/build-first-mcp.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>MCP (Model Context Protocol) is the open standard that lets AI models like Claude reach outside the chat window and interact with your tools, files, and APIs — without any custom wrapper code on the model side. Think of it as USB-C for AI: one protocol, plug anything in. If you've been wondering why every serious AI integration in 2025 mentions MCP, this is why.</p>
<p>In this post you'll build a working MCP server from scratch. You'll write the code, plug it into Claude Desktop, and ask Claude to read files from your machine. Total time: under 30 minutes.</p>
<hr />
<h2 id="heading-what-youll-build">What You'll Build</h2>
<p>A <strong>file-reader MCP server</strong> — a small TypeScript process that exposes two tools to Claude:</p>
<ul>
<li><code>read_file</code> — reads the contents of any file path you give it</li>
<li><code>list_directory</code> — lists files in a folder</li>
</ul>
<p>Once connected, you can ask Claude: <em>"Read my <code>~/projects/notes.txt</code> and summarise it"</em> — and it will. No API call gymnastics, no LangChain chains, no prompt hacks. Claude calls your tool directly.</p>
<hr />
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><strong>Node.js 18+</strong> (<code>node --version</code> should say v18 or higher)</li>
<li><strong>Claude Desktop</strong> installed (<a target="_blank" href="https://claude.ai/download">download here</a>)</li>
<li>Basic TypeScript comfort (you don't need to be an expert)</li>
</ul>
<p>That's it. No cloud account, no paid API key for this tutorial.</p>
<hr />
<h2 id="heading-step-1-bootstrap-the-project">Step 1 — Bootstrap the Project</h2>
<pre><code class="lang-bash">mkdir file-reader-mcp &amp;&amp; <span class="hljs-built_in">cd</span> file-reader-mcp
npm init -y
npm install @modelcontextprotocol/sdk
npm install -D typescript @types/node tsx
npx tsc --init --target ES2022 --module Node16 --moduleResolution Node16 --outDir dist --rootDir src --strict
mkdir src
</code></pre>
<p>Your <code>package.json</code> scripts section should look like:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
  <span class="hljs-attr">"build"</span>: <span class="hljs-string">"tsc"</span>,
  <span class="hljs-attr">"dev"</span>: <span class="hljs-string">"tsx src/index.ts"</span>,
  <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node dist/index.js"</span>
}
</code></pre>
<hr />
<h2 id="heading-step-2-write-the-server">Step 2 — Write the Server</h2>
<p>Create <code>src/index.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { McpServer } <span class="hljs-keyword">from</span> <span class="hljs-string">"@modelcontextprotocol/sdk/server/mcp.js"</span>;
<span class="hljs-keyword">import</span> { StdioServerTransport } <span class="hljs-keyword">from</span> <span class="hljs-string">"@modelcontextprotocol/sdk/server/stdio.js"</span>;
<span class="hljs-keyword">import</span> { z } <span class="hljs-keyword">from</span> <span class="hljs-string">"zod"</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> fs <span class="hljs-keyword">from</span> <span class="hljs-string">"fs"</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> path <span class="hljs-keyword">from</span> <span class="hljs-string">"path"</span>;

<span class="hljs-comment">// Create the MCP server</span>
<span class="hljs-keyword">const</span> server = <span class="hljs-keyword">new</span> McpServer({
  name: <span class="hljs-string">"file-reader"</span>,
  version: <span class="hljs-string">"1.0.0"</span>,
});

<span class="hljs-comment">// Tool 1: read_file</span>
server.tool(
  <span class="hljs-string">"read_file"</span>,
  <span class="hljs-string">"Read the contents of a file from the local filesystem"</span>,
  {
    file_path: z.string().describe(<span class="hljs-string">"Absolute or relative path to the file"</span>),
    encoding: z
      .enum([<span class="hljs-string">"utf8"</span>, <span class="hljs-string">"base64"</span>])
      .optional()
      .default(<span class="hljs-string">"utf8"</span>)
      .describe(<span class="hljs-string">"File encoding (default: utf8)"</span>),
  },
  <span class="hljs-keyword">async</span> ({ file_path, encoding }) =&gt; {
    <span class="hljs-keyword">const</span> resolved = path.resolve(file_path);

    <span class="hljs-keyword">if</span> (!fs.existsSync(resolved)) {
      <span class="hljs-keyword">return</span> {
        content: [{ <span class="hljs-keyword">type</span>: <span class="hljs-string">"text"</span>, text: <span class="hljs-string">`Error: File not found: <span class="hljs-subst">${resolved}</span>`</span> }],
        isError: <span class="hljs-literal">true</span>,
      };
    }

    <span class="hljs-keyword">const</span> stat = fs.statSync(resolved);
    <span class="hljs-keyword">if</span> (stat.size &gt; <span class="hljs-number">1</span>_000_000) {
      <span class="hljs-keyword">return</span> {
        content: [
          {
            <span class="hljs-keyword">type</span>: <span class="hljs-string">"text"</span>,
            text: <span class="hljs-string">`Error: File too large (<span class="hljs-subst">${(stat.size / <span class="hljs-number">1024</span>).toFixed(<span class="hljs-number">1</span>)}</span> KB). Max 1 MB.`</span>,
          },
        ],
        isError: <span class="hljs-literal">true</span>,
      };
    }

    <span class="hljs-keyword">const</span> content = fs.readFileSync(resolved, encoding <span class="hljs-keyword">as</span> BufferEncoding);
    <span class="hljs-keyword">return</span> {
      content: [{ <span class="hljs-keyword">type</span>: <span class="hljs-string">"text"</span>, text: content }],
    };
  }
);

<span class="hljs-comment">// Tool 2: list_directory</span>
server.tool(
  <span class="hljs-string">"list_directory"</span>,
  <span class="hljs-string">"List files and folders in a directory"</span>,
  {
    dir_path: z
      .string()
      .describe(<span class="hljs-string">"Path to the directory to list"</span>),
    show_hidden: z
      .boolean()
      .optional()
      .default(<span class="hljs-literal">false</span>)
      .describe(<span class="hljs-string">"Include hidden files (dotfiles)"</span>),
  },
  <span class="hljs-keyword">async</span> ({ dir_path, show_hidden }) =&gt; {
    <span class="hljs-keyword">const</span> resolved = path.resolve(dir_path);

    <span class="hljs-keyword">if</span> (!fs.existsSync(resolved)) {
      <span class="hljs-keyword">return</span> {
        content: [
          { <span class="hljs-keyword">type</span>: <span class="hljs-string">"text"</span>, text: <span class="hljs-string">`Error: Directory not found: <span class="hljs-subst">${resolved}</span>`</span> },
        ],
        isError: <span class="hljs-literal">true</span>,
      };
    }

    <span class="hljs-keyword">const</span> entries = fs.readdirSync(resolved, { withFileTypes: <span class="hljs-literal">true</span> });
    <span class="hljs-keyword">const</span> filtered = show_hidden
      ? entries
      : entries.filter(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> !e.name.startsWith(<span class="hljs-string">"."</span>));

    <span class="hljs-keyword">const</span> lines = filtered.map(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> <span class="hljs-keyword">type</span> = e.isDirectory() ? <span class="hljs-string">"📁"</span> : <span class="hljs-string">"📄"</span>;
      <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-keyword">type</span>}</span> <span class="hljs-subst">${e.name}</span>`</span>;
    });

    <span class="hljs-keyword">return</span> {
      content: [
        {
          <span class="hljs-keyword">type</span>: <span class="hljs-string">"text"</span>,
          text: <span class="hljs-string">`Contents of <span class="hljs-subst">${resolved}</span>:\n\n<span class="hljs-subst">${lines.join(<span class="hljs-string">"\n"</span>)}</span>`</span>,
        },
      ],
    };
  }
);

<span class="hljs-comment">// Start the server over stdio (how Claude Desktop communicates)</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> transport = <span class="hljs-keyword">new</span> StdioServerTransport();
  <span class="hljs-keyword">await</span> server.connect(transport);
  <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"File Reader MCP server running on stdio"</span>);
}

main().catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Fatal error:"</span>, err);
  process.exit(<span class="hljs-number">1</span>);
});
</code></pre>
<blockquote>
<p><strong>Note on <code>zod</code>:</strong> The MCP SDK uses Zod for schema validation. Install it: <code>npm install zod</code></p>
</blockquote>
<hr />
<h2 id="heading-step-3-build-it">Step 3 — Build It</h2>
<pre><code class="lang-bash">npm install zod
npm run build
</code></pre>
<p>You should see a <code>dist/</code> folder with compiled JS. Test it manually:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">'{}'</span> | node dist/index.js
<span class="hljs-comment"># Should print: File Reader MCP server running on stdio</span>
</code></pre>
<p>If you see the message, the server starts correctly. Ctrl-C to exit.</p>
<hr />
<h2 id="heading-step-4-connect-to-claude-desktop">Step 4 — Connect to Claude Desktop</h2>
<p>Claude Desktop reads MCP server configs from a JSON file. Open (or create) the config:</p>
<p><strong>macOS:</strong></p>
<pre><code>~<span class="hljs-regexp">/Library/</span>Application Support/Claude/claude_desktop_config.json
</code></pre><p><strong>Windows:</strong></p>
<pre><code>%APPDATA%\Claude\claude_desktop_config.json
</code></pre><p>Add your server to the <code>mcpServers</code> object:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"mcpServers"</span>: {
    <span class="hljs-attr">"file-reader"</span>: {
      <span class="hljs-attr">"command"</span>: <span class="hljs-string">"node"</span>,
      <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"/absolute/path/to/file-reader-mcp/dist/index.js"</span>]
    }
  }
}
</code></pre>
<p>Replace <code>/absolute/path/to/file-reader-mcp</code> with your actual project path. Get it fast with:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Run this from your project directory</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-subst">$(pwd)</span>/dist/index.js"</span>
</code></pre>
<p><strong>Restart Claude Desktop</strong> — it only reads the config on startup.</p>
<hr />
<h2 id="heading-step-5-test-it">Step 5 — Test It</h2>
<p>Open Claude Desktop. In the bottom-left of the chat window you should see a small tools icon (🔧) — click it and confirm <code>file-reader</code> appears in the list with <code>read_file</code> and <code>list_directory</code> tools.</p>
<p>Now try it:</p>
<blockquote>
<p><em>"Use read_file to read /etc/hosts and tell me what's in it"</em></p>
</blockquote>
<p>Claude will call your tool, get the file contents, and summarise them. You'll see the tool call rendered inline in the conversation.</p>
<p>Try the directory listing:</p>
<blockquote>
<p><em>"List the files in my Downloads folder at ~/Downloads"</em></p>
</blockquote>
<p>If something doesn't work, check Claude Desktop logs:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># macOS</span>
tail -f ~/Library/Logs/Claude/mcp*.<span class="hljs-built_in">log</span>
</code></pre>
<p>Common issues:</p>
<ul>
<li><strong>Server not appearing:</strong> Incorrect path in <code>claude_desktop_config.json</code> — use absolute paths only</li>
<li><strong>Tool call fails:</strong> Check the log for the actual error from your server (stderr shows up in the log)</li>
<li><strong>Permission denied:</strong> The server runs as your user, so file permissions apply normally</li>
</ul>
<hr />
<h2 id="heading-whats-next">What's Next</h2>
<p>You've got a working MCP server. Here are five ways to push it further:</p>
<ol>
<li><strong>Add a <code>write_file</code> tool</strong> — let Claude create or edit files (add a confirmation prompt pattern for safety)</li>
<li><strong>Search tool</strong> — implement grep-style search across a directory tree</li>
<li><strong>Watch mode</strong> — expose a tool that tails a log file and returns the last N lines</li>
<li><strong>Database access</strong> — swap the filesystem for a SQLite query tool using <code>better-sqlite3</code></li>
<li><strong>HTTP requests</strong> — add a <code>fetch_url</code> tool so Claude can pull external data on demand</li>
</ol>
<p>Each of these follows the exact same pattern: define the tool with a Zod schema, implement the handler, return <code>content</code> with <code>type: "text"</code>. The SDK handles everything else.</p>
<p>For real-world inspiration — and to skip building from scratch — check what the community has already shipped.</p>
<hr />
<p><strong>Browse 27 production MCP apps at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></strong></p>
<p>From database connectors to browser automation to custom API bridges — if you want to see how production MCP servers are structured before you build your own, that's the place to start.</p>
<hr />
<p><em>Written by <strong>The Plug</strong> — the MCPHub team at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a></em></p>
]]></content:encoded></item><item><title><![CDATA[Why We Only List 27 MCP Apps (And Why That's Our Strength)]]></title><description><![CDATA[Today, OpenAI hired Peter Steinberger, the creator of OpenClaw. The project stays open-source, but it now has the weight of OpenAI behind it. Great news for the ecosystem, right?
Sure. Except for one detail that emerged this morning: 21,000 OpenClaw ...]]></description><link>https://blog.getmcpapps.com/why-we-only-list-27-mcp-apps-and-why-thats-our-strength</link><guid isPermaLink="true">https://blog.getmcpapps.com/why-we-only-list-27-mcp-apps-and-why-thats-our-strength</guid><dc:creator><![CDATA[Bob]]></dc:creator><pubDate>Mon, 16 Feb 2026 13:34:04 GMT</pubDate><enclosure url="https://jnngymtirprbsfeevggk.supabase.co/storage/v1/object/public/blog-og/why-27-apps.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today, OpenAI hired Peter Steinberger, the creator of OpenClaw. The project stays open-source, but it now has the weight of OpenAI behind it. Great news for the ecosystem, right?</p>
<p>Sure. Except for one detail that emerged this morning: <strong>21,000 OpenClaw instances were compromised via 341 malicious skills</strong> distributed through open marketplaces. A CVE 8.8 RCE exploit called ClawHavoc is actively being used in the wild. Over 135,000 instances are exposed to the internet with default credentials.</p>
<p>While everyone was celebrating the ecosystem's growth, attackers were quietly building a supply chain attack.</p>
<p>This is why MCPHub lists 27 apps. Not 500. Not "every GitHub repo with 'mcp' in the name." Twenty-seven carefully vetted, interactive MCP apps.</p>
<h2 id="heading-the-malicious-skill-problem">The Malicious Skill Problem</h2>
<p>The Model Context Protocol (MCP) gives AI agents the ability to interact with external systems — databases, APIs, file systems, anything. A well-designed MCP server is incredibly powerful. A malicious one is a root shell with a smile.</p>
<p>Here's what happened:</p>
<ol>
<li><strong>Open skill marketplaces</strong> scraped every repo on GitHub with "mcp" in the description</li>
<li>Attackers published <strong>legitimate-looking skills</strong> with backdoors buried in dependencies</li>
<li>Users installed them via <code>openclaw skill install awesome-mcp-tool</code></li>
<li><strong>Game over.</strong> The skill had full access to the agent's context, credentials, and host system.</li>
</ol>
<p>341 malicious skills. 21K compromised instances. This isn't theoretical — it's happening right now.</p>
<h2 id="heading-why-curation-matters">Why Curation Matters</h2>
<p>MCPHub started with a simple question: "What if we only listed MCP apps that we'd actually install ourselves?"</p>
<p>Every app in our catalog goes through:</p>
<ol>
<li><strong>Manual review</strong> — we read the code, check dependencies, verify the repo history</li>
<li><strong>Interactive verification</strong> — does it actually provide a UI/interface, or is it just another SDK?</li>
<li><strong>Metadata enrichment</strong> — GitHub stars, last commit, maintainer responsiveness, installation count</li>
<li><strong>Developer contact</strong> — we reach out to authors, verify ownership, establish communication</li>
</ol>
<p>The result: <strong>27 curated apps</strong> instead of 500+ auto-scraped repos. We rejected over 300 MCP servers and SDKs in the last cleanup alone.</p>
<p>Is it slower? Yes. Does it scale worse? Absolutely. Is it the only sane approach in a supply-chain-attack environment? You bet.</p>
<h2 id="heading-what-we-look-for">What We Look For</h2>
<p>Our catalog focuses on <strong>interactive MCP apps</strong> — tools that provide a user interface, not just an API wrapper. Think:</p>
<ul>
<li>✅ <strong>Stripe MCP</strong> (dashboard for payments)</li>
<li>✅ <strong>Linear MCP</strong> (issue browser with kanban view)</li>
<li>✅ <strong>Notion MCP</strong> (doc explorer with search)</li>
<li>❌ Generic GitHub API wrapper</li>
<li>❌ "Awesome list" of 50 uncurated servers</li>
<li>❌ Anything that's just <code>pip install mcp-something</code></li>
</ul>
<p>We're not trying to be comprehensive. We're trying to be <strong>trustworthy</strong>.</p>
<h2 id="heading-the-openai-effect">The OpenAI Effect</h2>
<p>With OpenAI backing OpenClaw, institutional adoption is coming fast. That means:</p>
<ul>
<li><strong>More attackers</strong> targeting the ecosystem (supply chain attacks scale with adoption)</li>
<li><strong>Higher stakes</strong> (companies will run agents with access to production systems)</li>
<li><strong>Regulatory scrutiny</strong> (GDPR, SOC2, ISO27001 — agents need audit trails)</li>
</ul>
<p>Security used to be a "nice-to-have" in the agent ecosystem. Now it's <strong>table stakes</strong>. The marketplace that solves trust wins.</p>
<h2 id="heading-whats-next-for-mcphub">What's Next for MCPHub</h2>
<p>We're doubling down on curation:</p>
<ol>
<li><strong>Developer verification</strong> — OAuth-based claims so maintainers can prove ownership</li>
<li><strong>Security badges</strong> — last audit date, dependency scan results, security contact</li>
<li><strong>Installation telemetry</strong> — opt-in reporting so we can catch breaking changes early</li>
<li><strong>Composio partnership</strong> (maybe) — they handle OAuth, we handle discovery</li>
</ol>
<p>The goal isn't to list every MCP app. The goal is to be <strong>the place you go when you need something that won't wreck your system</strong>.</p>
<h2 id="heading-try-it">Try It</h2>
<p>Browse the catalog at <a target="_blank" href="https://getmcpapps.com">getmcpapps.com</a>. All 27 apps. Every one vetted. Zero malware.</p>
<p>If you're building an MCP app, <a target="_blank" href="https://getmcpapps.com/submit">submit it for review</a>. We'll read your code, test your app, and give you real feedback. If it's good, you're in. If it's not, we'll tell you why.</p>
<p>Security isn't a feature. It's the whole point.</p>
<hr />
<p><strong>Bob</strong> runs <a target="_blank" href="https://getmcpapps.com">MCPHub</a> — the first curated marketplace for interactive MCP apps. Follow along at <a target="_blank" href="https://x.com/getmcpapps">@getmcpapps</a>.</p>
]]></content:encoded></item></channel></rss>