<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shada Daab</title>
    <description>The latest articles on DEV Community by Shada Daab (@shada_daab).</description>
    <link>https://dev.to/shada_daab</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3305368%2Fae58de1c-18a7-4057-9888-68b46751014d.png</url>
      <title>DEV Community: Shada Daab</title>
      <link>https://dev.to/shada_daab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shada_daab"/>
    <language>en</language>
    <item>
      <title>Browser Automation Workflows with Playwright MCP and JavaScript</title>
      <dc:creator>Shada Daab</dc:creator>
      <pubDate>Sat, 08 Nov 2025 14:38:34 +0000</pubDate>
      <link>https://dev.to/shada_daab/browser-automation-workflows-with-playwright-mcp-and-javascript-2n1o</link>
      <guid>https://dev.to/shada_daab/browser-automation-workflows-with-playwright-mcp-and-javascript-2n1o</guid>
      <description>&lt;p&gt;Browser automation just got smarter — and conversational. With the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; and &lt;strong&gt;Playwright MCP&lt;/strong&gt;, developers can now let &lt;strong&gt;AI agents control browsers&lt;/strong&gt;: navigating pages, clicking elements, capturing screenshots, and running end-to-end tests — all through natural language.&lt;/p&gt;

&lt;p&gt;This post will walk you through how to use the &lt;strong&gt;Playwright MCP&lt;/strong&gt; to set up an AI-driven browser automation workflow in JavaScript or TypeScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Playwright MCP?
&lt;/h2&gt;

&lt;p&gt;The Playwright MCP server wraps the full power of Playwright (Microsoft’s browser automation library) in the &lt;strong&gt;Model Context Protocol&lt;/strong&gt; — a universal API standard that lets AI systems safely interact with tools.&lt;/p&gt;

&lt;p&gt;That means an LLM can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to URLs (&lt;code&gt;goto&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Click and type on elements&lt;/li&gt;
&lt;li&gt;Capture screenshots or full-page renders&lt;/li&gt;
&lt;li&gt;Extract data or verify page content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All without writing traditional test code — but still fully inspectable and structured.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Install Playwright MCP
&lt;/h2&gt;

&lt;p&gt;If you already have Node.js (v18+), installation is one command away:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @playwright/mcp init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This installs and configures the &lt;strong&gt;Playwright MCP server&lt;/strong&gt;, exposing endpoints defined by the protocol (such as &lt;code&gt;open_page&lt;/code&gt;, &lt;code&gt;click_element&lt;/code&gt;, &lt;code&gt;fill_field&lt;/code&gt;, and &lt;code&gt;screenshot&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;You can also run it manually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @playwright/mcp serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, it runs on &lt;code&gt;http://localhost:4000/mcp&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Explore Available Tools
&lt;/h2&gt;

&lt;p&gt;Once the server is live, it exposes MCP tools like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;open_page&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opens a given URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;click_element&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Clicks a DOM element by selector&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fill_field&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Types text into input fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;get_content&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieves visible text or HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;screenshot&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Takes a screenshot of the current page&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These structured tool calls allow an AI assistant (like Claude or GPT-5) to reason about page layouts, element trees, and accessibility data rather than raw pixels.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Connect from a JavaScript Client
&lt;/h2&gt;

&lt;p&gt;Let’s write a small Node.js client that interacts with the Playwright MCP server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @modelcontextprotocol/sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create a file called &lt;code&gt;browserClient.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@modelcontextprotocol/sdk/client/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StreamableHTTPClientTransport&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@modelcontextprotocol/sdk/client/streamableHttp.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;playwright-demo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StreamableHTTPClientTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:4000/mcp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Open GitHub login page&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open_page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://github.com/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Fill in username &amp;amp; password fields&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fill_field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#login_field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;demo_user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fill_field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secret_pass&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Click the login button&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click_element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input[type="submit"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 4. Capture a screenshot after login&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;screenshot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Screenshot saved:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;structuredContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script effectively lets an AI-driven process control your Playwright browser — structured, auditable, and automatable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Natural Language Control with VS Code or Claude
&lt;/h2&gt;

&lt;p&gt;If you use &lt;strong&gt;Claude Desktop&lt;/strong&gt; or the &lt;strong&gt;VS Code MCP extension&lt;/strong&gt;, you can link your Playwright MCP server so that your AI assistant can perform automation via conversation.&lt;/p&gt;

&lt;p&gt;Try prompting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Open my dashboard at &lt;a href="https://example.com/dashboard" rel="noopener noreferrer"&gt;https://example.com/dashboard&lt;/a&gt; and tell me how many new messages I have.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Navigate to the contact form and fill out the name and email fields.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The AI uses MCP tools like &lt;code&gt;open_page&lt;/code&gt;, &lt;code&gt;get_content&lt;/code&gt;, and &lt;code&gt;fill_field&lt;/code&gt; to execute these steps — safely and reproducibly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Example — AI-Powered Website Testing
&lt;/h2&gt;

&lt;p&gt;You can use the same setup to perform automated end-to-end (E2E) tests. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open_page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fill_field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fill_field&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mypassword&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click_element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button[type="submit"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get_content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Page heading after login:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;structuredContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can even let the AI &lt;strong&gt;generate&lt;/strong&gt; these steps itself — by describing the goal instead of coding it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Accessibility Snapshots for Safer Automation
&lt;/h2&gt;

&lt;p&gt;Unlike brittle pixel-based automation, MCP’s structured data layer uses &lt;strong&gt;accessibility snapshots&lt;/strong&gt; and &lt;strong&gt;semantic element trees&lt;/strong&gt;. That means commands like “click the ‘Submit’ button” map to actual labeled UI elements — improving reliability and safety.&lt;/p&gt;

&lt;p&gt;This approach is crucial for integrating AI into production-grade testing environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Playwright MCP transforms the way developers and AI systems interact with the web. By exposing structured browser-control tools, it bridges the gap between &lt;strong&gt;conversational AI&lt;/strong&gt; and &lt;strong&gt;real-world automation&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 Key Benefits:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Seamless LLM integration with browser automation.&lt;/li&gt;
&lt;li&gt;Declarative and safe access to page content.&lt;/li&gt;
&lt;li&gt;Perfect for automated QA, scraping, or RAG data pipelines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve ever wished your AI assistant could &lt;em&gt;click that button for you&lt;/em&gt; — now it can.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/playwright" rel="noopener noreferrer"&gt;Playwright MCP on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/modelcontextprotocol/typescript-sdk" rel="noopener noreferrer"&gt;MCP SDK for JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://claude.ai" rel="noopener noreferrer"&gt;Claude + MCP integration guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>ai</category>
      <category>automation</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Setting Up an MCP Server</title>
      <dc:creator>Shada Daab</dc:creator>
      <pubDate>Sat, 08 Nov 2025 14:18:22 +0000</pubDate>
      <link>https://dev.to/shada_daab/setting-up-an-mcp-server-jj3</link>
      <guid>https://dev.to/shada_daab/setting-up-an-mcp-server-jj3</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;1. Choose Your Environment (Local vs. Cloud)&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local (developer machine):&lt;/strong&gt; For testing or desktop apps, you can run an MCP server as a local process. Any machine with Node.js installed can host an MCP server. Many reference servers are available as npm packages – for example, the &lt;strong&gt;filesystem server&lt;/strong&gt; (which exposes files as tools) is published as &lt;strong&gt;&lt;code&gt;@modelcontextprotocol/server-filesystem&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud (remote):&lt;/strong&gt; For production or web-based use, host the MCP server on a cloud platform. You can use services like &lt;strong&gt;Cloudflare Workers&lt;/strong&gt;, &lt;strong&gt;Azure Functions&lt;/strong&gt;, &lt;strong&gt;AWS Lambda&lt;/strong&gt;, or any Node-friendly web host. Cloudflare even provides boilerplate and OAuth handling for remote MCP servers. The key is that the server must have an HTTPS endpoint that supports the MCP transport (Streamable HTTP + optional Server-Sent Events).
## &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Install Dependencies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Make sure you have &lt;strong&gt;Node.js&lt;/strong&gt; (latest LTS) installed. Then initialize a project and install the MCP SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @modelcontextprotocol/sdk express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;&lt;code&gt;@modelcontextprotocol/sdk&lt;/code&gt;&lt;/strong&gt; package contains the TypeScript/JavaScript SDK for building MCP servers and clients.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Create Your MCP Server (Example)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Using the TypeScript/JS SDK, you define an &lt;strong&gt;&lt;code&gt;McpServer&lt;/code&gt;&lt;/strong&gt;, register tools, and run an HTTP or stdio transport. For example, to make a simple “addition” tool in a Node.js server (&lt;strong&gt;&lt;code&gt;server.ts&lt;/code&gt;&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;McpServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@modelcontextprotocol/sdk/server/mcp.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create an MCP server instance&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;McpServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;demo-server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Register a simple addition tool&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Addition Tool&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Add two numbers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;         &lt;span class="c1"&gt;// e.g. use zod for schemas&lt;/span&gt;
    &lt;span class="na"&gt;outputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This function runs when the AI calls the 'add' tool&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// The AI receives the text and structured output&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Result: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
      &lt;span class="na"&gt;structuredContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example shows the core of an MCP server: you create an &lt;strong&gt;&lt;code&gt;McpServer&lt;/code&gt;&lt;/strong&gt;, then use &lt;strong&gt;&lt;code&gt;registerTool(toolName, metadata, handler)&lt;/code&gt;&lt;/strong&gt; to expose a function. In this case, an AI can call the “add” tool with &lt;strong&gt;&lt;code&gt;{a:1, b:2}&lt;/code&gt;&lt;/strong&gt; to get &lt;strong&gt;&lt;code&gt;{result:3}&lt;/code&gt;&lt;/strong&gt;. The full SDK README provides this example in context.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Expose the Server over a Transport&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Next, tie the MCP server into an HTTP endpoint so clients can connect. A common pattern with Express is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StreamableHTTPServerTransport&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@modelcontextprotocol/sdk/server/streamableHttp.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// HTTP endpoint for MCP (Streamable HTTP transport)&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/mcp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create a new transport for each request&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StreamableHTTPServerTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;enableJsonResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// Clean up on close&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

  &lt;span class="c1"&gt;// Connect transport to our server and handle the incoming JSON-RPC&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Start listening&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`MCP server running at http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/mcp`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This skeleton (adapted from the MCP SDK docs) spins up an HTTP POST route at &lt;strong&gt;&lt;code&gt;/mcp&lt;/code&gt;&lt;/strong&gt;. MCP clients can then send JSON requests or open an SSE stream here. The key is to call &lt;strong&gt;&lt;code&gt;server.connect(transport)&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;transport.handleRequest(req, res, req.body)&lt;/code&gt;&lt;/strong&gt; for each request. (The SDK docs show this complete example.)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Quick-start with Reference Servers (no coding)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For common tasks, you don’t even have to write code. The community maintains ready-to-run MCP server packages. For example, the &lt;strong&gt;Filesystem Server&lt;/strong&gt; (providing file-read/write tools) can be launched with one command. In a terminal, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @modelcontextprotocol/server-filesystem /path/to/dir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts an MCP server that grants access to the specified folder. You’ll then configure your AI client (or Claude Desktop, VS Code, etc.) to connect to this local server. Anthropic’s official docs show exactly this command for testing. In the same way, there are packages for other servers (e.g. &lt;strong&gt;&lt;code&gt;server-git&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;server-google-drive&lt;/code&gt;&lt;/strong&gt;, etc.) listed in the MCP GitHub repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;6. Deploying to the Cloud&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you want your MCP server accessible on the internet, deploy it like any web service. Some options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare Workers:&lt;/strong&gt; Cloudflare provides a streamlined flow. Their blog explains how a Worker can handle MCP (with built-in OAuth support) in minutes. You can bundle your TypeScript server code into a Worker and use Cloudflare’s &lt;strong&gt;&lt;code&gt;workers-oauth-provider&lt;/code&gt;&lt;/strong&gt; library to handle authentication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure Functions / AWS Lambda / Containers:&lt;/strong&gt; You can host the above Express code in Azure Functions (they even have a sample project) or any Node.js server environment. The only requirement is an HTTPS endpoint for the MCP transport (HTTP+SSE). For example, an Azure Functions template shows how to expose an &lt;strong&gt;&lt;code&gt;/mcp&lt;/code&gt;&lt;/strong&gt; SSE endpoint secured with function keys (see MS sample).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generic Server:&lt;/strong&gt; Any cloud VM or container works. Just ensure the host has Node, and forward port 3000 (or your port). Configure SSL for production (HTTPS is required for SSE). Once deployed, remote clients will point to your server’s URL instead of localhost.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Integrating MCP into JavaScript Apps&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Once your MCP server is running, you can write a JavaScript &lt;em&gt;client&lt;/em&gt; to use it. The MCP TypeScript SDK provides &lt;strong&gt;&lt;code&gt;Client&lt;/code&gt;&lt;/strong&gt; classes and transports. The common transports for JS are &lt;strong&gt;stdio&lt;/strong&gt; (for local subprocess servers) and &lt;strong&gt;SSE/HTTP&lt;/strong&gt; (for remote servers).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Using the MCP Client SDK&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Install the same SDK in your JS project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @modelcontextprotocol/sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can create a client and connect. For a &lt;strong&gt;local subprocess&lt;/strong&gt; server (stdin/stdout transport), use &lt;strong&gt;&lt;code&gt;StdioClientTransport&lt;/code&gt;&lt;/strong&gt;. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@modelcontextprotocol/sdk/client/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StdioClientTransport&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@modelcontextprotocol/sdk/client/stdio.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StdioClientTransport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;npx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-y&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-mcp-server@latest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;// e.g. launch a server via npx&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This spawns the server (via &lt;strong&gt;&lt;code&gt;npx&lt;/code&gt;&lt;/strong&gt;) as a subprocess and communicates with it over stdio. The code snippet above is adapted from LangChain’s tutorial for MCP. After &lt;strong&gt;&lt;code&gt;connect()&lt;/code&gt;&lt;/strong&gt;, the client is linked to the server and ready to call tools.&lt;/p&gt;

&lt;p&gt;For a &lt;strong&gt;remote (HTTP+SSE) server&lt;/strong&gt;, use &lt;strong&gt;&lt;code&gt;SSEClientTransport&lt;/code&gt;&lt;/strong&gt; or the newer &lt;strong&gt;&lt;code&gt;StreamableHTTPClientTransport&lt;/code&gt;&lt;/strong&gt;. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@modelcontextprotocol/sdk/client/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SSEClientTransport&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@modelcontextprotocol/sdk/client/sse.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SSEClientTransport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://myserver.com/mcp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This opens a long-lived Server-Sent Events connection to the &lt;strong&gt;&lt;code&gt;/mcp&lt;/code&gt;&lt;/strong&gt; endpoint of your server. Once connected, the client and server exchange JSON-RPC messages over this channel.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Calling Tools from JavaScript&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With the client connected, you can invoke any registered tool on the server. The SDK provides a simple method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;structuredContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { result: 12 }&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sends a tool-invocation request to the server’s &lt;strong&gt;&lt;code&gt;add&lt;/code&gt;&lt;/strong&gt; tool, and awaits the response. The example above (from the SDK docs) shows calling a tool named “example-tool”. The &lt;strong&gt;&lt;code&gt;result&lt;/code&gt;&lt;/strong&gt; includes both textual content and structured output as defined by the server.&lt;/p&gt;

&lt;p&gt;You can also read resources (if the server provides any) via &lt;strong&gt;&lt;code&gt;client.readResource({...})&lt;/code&gt;&lt;/strong&gt; or listen to server notifications. In practice, many JS developers use higher-level libraries (e.g. LangChain/MCP adapters) to wrap these calls in agent patterns, but the raw &lt;strong&gt;&lt;code&gt;callTool&lt;/code&gt;&lt;/strong&gt; method is there if you need low-level control.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Example: Integrating in an App&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Suppose you have a Node app that needs to list files via an MCP filesystem server. You might write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// (After connecting client as above...)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;list-files&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/project&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JS files:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;structuredContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Behind the scenes, the MCP server’s “list-files” tool runs and returns the list of files (in both text and JSON). Your app need not know &lt;em&gt;how&lt;/em&gt; the server implemented it. The protocol ensures a clean handoff.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Best Practices and Pitfalls&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Least Privilege Access.&lt;/strong&gt; Only expose the tools and data the AI truly needs. For a filesystem server, explicitly list the directories it may touch. Never mount root or sensitive paths. By default, grant as narrow permissions as possible (e.g. read-only vs. write). Remember that a server runs with the user’s privileges, so be careful – the user approving is effectively giving full access of those resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate Inputs/Outputs.&lt;/strong&gt; Define clear schemas for tool arguments and return values (the MCP SDK supports JSON schemas or libraries like Zod as shown). This prevents the AI from sending malformed data. It also keeps logs clean if something goes wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security (Prompt Injection &amp;amp; Malicious Tools).&lt;/strong&gt; MCP is powerful, but be cautious. Treat tools as potentially dangerous operations. For example, an LLM might try to combine multiple tool calls in a way that exfiltrates data. Always review which tools an AI can invoke and under what context. Research has shown that MCP can be vulnerable to prompt-injection or sneaky tool replacement attacks, so monitor usage carefully. If you’re connecting to third-party APIs, ensure you’re not leaking tokens or sensitive info.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use HTTPS and Authentication for Remote.&lt;/strong&gt; When running servers on the internet, always use SSL/TLS. Implement standard OAuth or API key authentication for your endpoints. (For example, Cloudflare Workers provide a turnkey OAuth handler for you.) MCP itself assumes you’ll use OAuth-like flows to let users sign in and grant permissions, so leverage those rather than writing your own ad-hoc token system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle Errors and Reconnection.&lt;/strong&gt; Network glitches happen. The MCP SDK transports have retry modes, but design your client to handle disconnects or server timeouts gracefully. Log errors on both sides. The Claude Desktop guide recommends tailing the MCP logs if tools fail – you should similarly monitor your server’s output and the client’s logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep Spec Versions and SDKs Updated.&lt;/strong&gt; MCP is evolving rapidly. For example, the older SSE transport is being phased out in favor of the Streamable HTTP transport. Make sure you use the latest SDK releases and check the MCP spec updates. Also pay attention to versioning fields (&lt;strong&gt;&lt;code&gt;name&lt;/code&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;version&lt;/code&gt;&lt;/strong&gt;) in &lt;strong&gt;&lt;code&gt;Client&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;McpServer&lt;/code&gt;&lt;/strong&gt; for compatibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing.&lt;/strong&gt; Before connecting a powerful LLM (like GPT-4) to your server, test tools with simple inputs and offline prompts. Tools should fail safely. Use the &lt;strong&gt;MCP Inspector&lt;/strong&gt; tool (&lt;strong&gt;&lt;code&gt;npx @modelcontextprotocol/inspector&lt;/code&gt;&lt;/strong&gt;) to list and test tools manually over HTTP.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Useful References and Next Steps&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Official Docs:&lt;/strong&gt; The Model Context Protocol documentation covers the spec and has tutorials (including local vs. remote server setup). Anthropic’s README lists many reference servers and usage tips.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP GitHub:&lt;/strong&gt; The &lt;strong&gt;&lt;code&gt;typescript-sdk&lt;/code&gt;&lt;/strong&gt; repo has examples and detailed API info; we cited its Quick Start above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Articles &amp;amp; Blogs:&lt;/strong&gt; The Cloudflare MCP blog walks through deploying to Workers. Marc Nuri’s JavaScript tutorial shows client-side code and LangChain integration. Microsoft’s DevBlogs and Azure samples illustrate MCP in C# and TS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community Servers:&lt;/strong&gt; Check out the mcp-servers repo for ready-made servers (Filesystem, GitHub, SQL, etc.) you can adapt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following these guidelines and examples, you can bring the power of MCP to your JavaScript projects. MCP servers let your AI assistants &lt;em&gt;do&lt;/em&gt; things in your apps and data environments in a secure, standardized way, moving from mere chatbots to truly helpful agents.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>node</category>
      <category>tutorial</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Understanding Model Context Protocol (MCP) Servers</title>
      <dc:creator>Shada Daab</dc:creator>
      <pubDate>Sat, 08 Nov 2025 14:11:58 +0000</pubDate>
      <link>https://dev.to/shada_daab/understanding-model-context-protocol-mcpservers-4md</link>
      <guid>https://dev.to/shada_daab/understanding-model-context-protocol-mcpservers-4md</guid>
      <description>&lt;p&gt;Model Context Protocol (MCP) is a new open standard (introduced by Anthropic in late 2024) that unifies how AI systems like large language models (LLMs) connect to external tools, data, and services. &lt;br&gt;
In MCP’s client-server architecture, an AI host (for example, a chat app or IDE) runs one or more MCP clients, each of which connects to an MCP server that provides specific functionality. An MCP server is simply a program (often a Node/TypeScript/Express service for JS developers) that registers “tools” and “resources” that the AI can invoke . These tools might let the AI read files, query a database, call an API, or perform any domain-specific action. Each action is mediated by the MCP protocol (a JSON-RPC 2.0–based interface over stdio or HTTP/SSE) so that the AI and server communicate in a standardized way .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswu9ml7eoseatub8dtyu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswu9ml7eoseatub8dtyu.png" alt="MCP server" width="688" height="286"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;MCP Architecture – an AI host on the user’s device runs one or more MCP clients, each connected to an MCP server. The server implements tools (functions) or data queries, often calling external APIs, and responds over the MCP protocol&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This model solves the “N×M” connector problem: before MCP, developers had to write custom bridge code for each AI-tool pair, leading to many one-off integrations. MCP provides a universal interface for the AI to&lt;br&gt;
discover and use tools . In practice, popular AI platforms (ChatGPT, Claude, etc.) and agent frameworks create an MCP client under the hood, so your JavaScript code can focus on exposing tools or&lt;br&gt;
calling them without worrying about AI prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Use MCP Servers? (Benefits &amp;amp; Use Cases)&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Standardized integrations.&lt;/strong&gt; MCP is an open, vendor-neutral protocol (similar in spirit to OpenAPI but for AI tools.). It lets any AI client talk to any MCP server with no proprietary plumbing. Anthropic’s docs note that MCP ships with SDKs in many languages (TypeScript, Python, C#, Java, etc.) and reference implementations for GitHub, Slack, Google Drive, databases, browser automation, and more. This ecosystem means you can often reuse or adapt an existing MCP server rather than reinvent one from scratch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure, user-mediated access.&lt;/strong&gt; By design, MCP interactions require explicit user approval. For local servers, the AI must ask the user before performing any action, ensuring you stay in control. For remote servers, MCP supports standard OAuth flows so end users can grant limited access tokens without sharing credentials. This combination of explicit approval and scoped tokens helps mitigate risks – for example, Cloudflare’s blog notes that MCP “uses OAuth” under the hood so users grant access safely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Immediate new capabilities for AI.&lt;/strong&gt; Connecting an MCP server can dramatically boost an AI’s abilities. For instance, an MCP server exposing your database enables natural-language queries to that database (use cases like “AI2SQL”). In software development, MCP is already powering code-assistant tools: IDEs like VS Code, GitHub Copilot, and platforms like Replit or Sourcegraph connect MCP servers that let the AI read your codebase, search your repo, or manipulate files in real-time. In short, you can turn your AI assistant into an &lt;em&gt;agent&lt;/em&gt; that takes actions (sending emails, updating spreadsheets, deploying code, etc.) instead of just answering questions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wide adoption and momentum.&lt;/strong&gt; Major AI providers (OpenAI, Google DeepMind, Microsoft) have embraced MCP. For example, in 2025 OpenAI announced MCP support in ChatGPT and their Agents SDK, and Google confirmed MCP support in its Gemini models. This broad industry adoption means MCP is likely to be supported everywhere agents run, so building on it is future-friendly. (One reporter even called MCP the “USB-C for AI” uniting rivals.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable to your needs.&lt;/strong&gt; Because the protocol is open-source and extensible, you can write your own MCP server in JavaScript to connect any data source or tool to AI. This is huge for specialized domains: for example, you could build an MCP server that interfaces with your company’s ERP system or a proprietary API, without having to wait for a vendor plugin.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
