<?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: Ivelin (Ivo)</title>
    <description>The latest articles on DEV Community by Ivelin (Ivo) (@ivolondon).</description>
    <link>https://dev.to/ivolondon</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%2F201972%2Ffd66041f-4454-42f6-a4a2-bf604eb5ba54.jpg</url>
      <title>DEV Community: Ivelin (Ivo)</title>
      <link>https://dev.to/ivolondon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ivolondon"/>
    <language>en</language>
    <item>
      <title>The Rise of the Fleet: Scaling My Engineering Workflow with Github Copilot Agents</title>
      <dc:creator>Ivelin (Ivo)</dc:creator>
      <pubDate>Mon, 06 Apr 2026 20:59:58 +0000</pubDate>
      <link>https://dev.to/ivolondon/the-rise-of-the-fleet-scaling-my-engineering-workflow-with-vscode-copilot-agents-3boe</link>
      <guid>https://dev.to/ivolondon/the-rise-of-the-fleet-scaling-my-engineering-workflow-with-vscode-copilot-agents-3boe</guid>
      <description>&lt;p&gt;In this post, I’ll walk you through how I use Copilot and my personal preferences for different approaches. For this demo, I’m using an Express server with two endpoints that find books by author or publisher. My goal is to build a simple UI for it.&lt;/p&gt;

&lt;p&gt;I should start by saying I’m no expert; I’m learning new things every day and constantly adapting my workflow. By sharing this, I hope to kick off some discussions in the comments and at the office so I can learn how you’re using the tool, too.&lt;/p&gt;

&lt;p&gt;I’m not going to dive into specific models here - just use whatever suits your needs. It’s worth trying different ones to see what you like best. Models change and improve faster than I can blink (at least it feels that way!).&lt;/p&gt;

&lt;p&gt;The below is a screenshot of the chat with with all the options expanded. Let’s explore some of them:&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%2Fo6n14ll8gajq5cjix5ff.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%2Fo6n14ll8gajq5cjix5ff.png" alt="VSCode CoPilot" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using ‘Local’ mode
&lt;/h3&gt;

&lt;p&gt;I use ‘Local’ for tasks that need less compute and a faster response. When I’m planning, brainstorming, or exploring parts of the codebase and want to talk through ideas, I’ll stick with Local. Let’s start by mapping out the UI concept:&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%2F00afk4737qyxtam6s2o0.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%2F00afk4737qyxtam6s2o0.png" alt=" " width="800" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Agent helpfully clarifies the process, catches edge cases, or flags anything it finds a bit ambiguous.&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%2Fvhl72r12f04zbh3s6dfk.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%2Fvhl72r12f04zbh3s6dfk.png" alt=" " width="800" height="591"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we’ve gone back and forth a few times and the plan feels solid, it’s time to implement the changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  CoPilot CLI
&lt;/h3&gt;

&lt;p&gt;Moving on to the Copilot CLI. I think of it as the ‘agent’ that takes the guesswork out of the equation. It’s perfect for those tougher tasks that require a bit more compute.&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%2Fd9y97j4wsbzvwcim211b.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%2Fd9y97j4wsbzvwcim211b.png" alt=" " width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the top right of the search bar, you can check your ‘sessions in progress’ or ‘unread sessions’ that are waiting for your input or permission to continue.&lt;/p&gt;

&lt;p&gt;In the screenshot below, I accidentally kicked off the implementation twice. I’m going to archive one of them so I can focus on the session that actually needs my attention.&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%2Ftg0yy5edrhj22vf9uogh.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%2Ftg0yy5edrhj22vf9uogh.png" alt=" " width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Agent starts by checking out the plan and executing the steps in order. It’ll ask for permission before running certain commands, giving you a few ways to handle the workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Manually approve&lt;/strong&gt; each prompt as it comes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Whitelist&lt;/strong&gt; specific commands to always be allowed in the session, workspace, or globally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go rogue&lt;/strong&gt; and allow all commands for the duration of this session.&lt;/li&gt;
&lt;/ul&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%2Ft1jrs63vv56h821c7c60.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%2Ft1jrs63vv56h821c7c60.png" alt=" " width="800" height="1513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While waiting for the plan to finish executing, I decided to kick off another session to update the documentation.&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%2Fz8iogeti02o9cxmia3hy.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%2Fz8iogeti02o9cxmia3hy.png" alt=" " width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few minutes later, the work is done. Before reviewing the code, I’ll QA the changes. The first thing I noticed is that the response isn’t rendering, so let’s get the agent to fix it.&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%2F5zsq2rylrtgmvefh7yu5.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%2F5zsq2rylrtgmvefh7yu5.png" alt=" " width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m going to enable the ‘debugger’ custom agent to help me fix the error. (I’ll dive deeper into custom agents a bit later in the post.)&lt;/p&gt;

&lt;p&gt;It’s often a good idea to spin up a separate session for debugging, so your agent starts from a fresh session, but you can definitely keep it within the same session if you prefer.&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%2Fi37clsl7k09tj1mkqm56.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%2Fi37clsl7k09tj1mkqm56.png" alt=" " width="800" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This agent has access to the Simple Browser in VSCode, so it can check the error directly, but I usually include the details in my request anyway just to be sure.&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%2Fsftiqypqoqy77qtjiia0.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%2Fsftiqypqoqy77qtjiia0.png" alt=" " width="800" height="745"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, I’d totally forgotten to start the server in the background (a classic "face-palm" moment). Second, the returned price was occasionally &lt;code&gt;undefined&lt;/code&gt;, so calling &lt;code&gt;.toFixed()&lt;/code&gt; was breaking the app. Thankfully, the Debugger agent caught both.&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%2Fpi8upz04ztv8cg7hmujp.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%2Fpi8upz04ztv8cg7hmujp.png" alt=" " width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, I’ll review the code to make sure it matches what I had in mind. Once I’m happy, I’ll ask it to create a PR - this automatically runs some checks and raises the request against my main branch.&lt;/p&gt;

&lt;p&gt;In this example, I kept all my prompts in one session, but if you like to keep things tidy, you can easily do the PR part in a fresh session instead.&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%2Fu6ch1582inlh7z24tu3n.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%2Fu6ch1582inlh7z24tu3n.png" alt=" " width="800" height="1592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Copilot CLI options
&lt;/h3&gt;

&lt;p&gt;If you type &lt;code&gt;/&lt;/code&gt;, Copilot brings up a list of available commands with a brief description for each. Let’s break down the main ones and what they’re used for:&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%2Fw30o11bdlbdqy7hchdx1.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%2Fw30o11bdlbdqy7hchdx1.png" alt=" " width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To keep this brief, I’ll give you a quick overview of what’s what and how I use each, but I’d love for you to share your favourite prompt or agent that’s been game-changing for your workflow.&lt;/p&gt;

&lt;p&gt;I also recommend checking out the community-created collections of custom agents, skills, and workflows to supercharge your experience. One big tip: &lt;strong&gt;ALWAYS READ THE RAW FILES&lt;/strong&gt; before you copy them. Make sure no prompt injection commands are hidden in the comments, which are easy to miss in preview mode.&lt;/p&gt;

&lt;p&gt;Awesome-copilot collection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/github/awesome-copilot" rel="noopener noreferrer"&gt;https://github.com/github/awesome-copilot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And Anthropic’s collection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/anthropics/skills" rel="noopener noreferrer"&gt;https://github.com/anthropics/skills&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d also recommend Matt Pocock’s collection:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/mattpocock/skills" rel="noopener noreferrer"&gt;https://github.com/mattpocock/skills&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;/create-prompt&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;If you find yourself repeating the same prompts, save some time by creating a workspace-specific prompt. You can also save them globally to use across all your repos.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;/create-instructions&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Instructions are the guidelines for how an Agent should behave in a repository. Think of them as the ‘onboarding docs’ for the AI.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;/create-skill&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;I think of Skills as the ‘playbook’ you hand to your agents. They bundle together high-level instructions, strict context constraints, and technical tool definitions. This helps agents tackle complex workflows with much higher precision and consistency.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;/create-agent&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Think of Agents as personas with different skills. You can create one to help you brainstorm, another to turn those ideas into action, and a third to actually build them out - essentially a different persona for every stage of your development.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;/create-hook&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Think of these like Git hooks, but for AI agents—instructions that trigger during specific events like &lt;code&gt;sessionStart&lt;/code&gt;, &lt;code&gt;sessionEnd&lt;/code&gt;, &lt;code&gt;userPromptSubmitted&lt;/code&gt;, &lt;code&gt;preToolUse&lt;/code&gt;, &lt;code&gt;postToolUse&lt;/code&gt;, or &lt;code&gt;errorOccurred&lt;/code&gt;. I’d definitely suggest checking out the &lt;code&gt;secrets-scanner&lt;/code&gt; hook as a solid example.&lt;/p&gt;




&lt;h3&gt;
  
  
  Using a Fleet (multiple agents)
&lt;/h3&gt;

&lt;p&gt;Let’s tackle that same task again, but this time using a Skill to generate a Product Requirements Document (PRD) and then kicking off a fleet of agents to execute the work in parallel.&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%2F1465cltco5czlgbyg9le.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%2F1465cltco5czlgbyg9le.png" alt=" " width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It then follows up with a bunch of questions about any criteria I might have missed.&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%2F5ss06bbsi9f1sdhzxvku.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%2F5ss06bbsi9f1sdhzxvku.png" alt=" " width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Skill I used splits tasks into GitHub issues, but you can easily set it up to create them locally instead.&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%2Fpu9c1a8n97bfdd1n1a9v.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%2Fpu9c1a8n97bfdd1n1a9v.png" alt=" " width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Done! Let’s check and see if those issues were actually created.&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%2Fc0ot26wjl8kgyo1xda6d.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%2Fc0ot26wjl8kgyo1xda6d.png" alt=" " width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And in Github:&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%2Fnf4d7ekdst4zj54p0z8p.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%2Fnf4d7ekdst4zj54p0z8p.png" alt=" " width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, I’ll use the &lt;code&gt;/fleet&lt;/code&gt; command to kick off multiple agents. Each one will grab an issue and execute the task independently.&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%2Ff2fci2av4br2kxrfyfry.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%2Ff2fci2av4br2kxrfyfry.png" alt=" " width="800" height="892"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once it’s finished, it’ll let me know in the chat and provide the files for review. I’ll usually run a quick test to make sure everything works as expected before I dive into the code review.&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%2F853x4qdw7qi190jci010.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%2F853x4qdw7qi190jci010.png" alt=" " width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The UI looks okay - I didn’t give it much detail on the styling, so I’m pretty happy with the result. If anything feels off, I’ll just keep iterating until it’s exactly where I want it.&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%2Frnajzrr2dkxvgpbjzbfd.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%2Frnajzrr2dkxvgpbjzbfd.png" alt=" " width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my experience, deploying a fleet can be a bit slower-this specific task took about 15 minutes. But as models improve, this is only going to get faster.&lt;/p&gt;

&lt;p&gt;It’s more cost-effective since you end up using fewer tokens. Because each agent has its own context and focuses on its own task, you get much less context drift. You can even assign specific personalities to different tasks.&lt;/p&gt;

&lt;p&gt;One thing to watch out for: agents share the same file system, which can lead to conflicts. It’s a "last write wins" scenario, so if multiple agents hit the same file, they might overwrite each other. Ideally, you want them working on separate areas.&lt;/p&gt;

&lt;p&gt;The best part is that you can "set and forget" them. Once they’re finished, you just review all the changes in one go.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Orchestrating agents and agentic development is only going to get faster and more effective-and hopefully cheaper, too. We’re still in the early days, so experiment and see what fits your needs. Just be mindful of what you copy from the web and the permissions you grant your agents. If you have any tips, share them-we’re all in this together. Embrace the learning and enjoy the process. Happy coding (or maybe I should say Happy prompting)!&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>productivity</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Getting Started with the Model Context Protocol (MCP): Build and Connect Your First MCP Server</title>
      <dc:creator>Ivelin (Ivo)</dc:creator>
      <pubDate>Mon, 04 Aug 2025 10:57:51 +0000</pubDate>
      <link>https://dev.to/ivolondon/getting-started-with-the-model-context-protocol-mcp-build-and-connect-your-first-mcp-server-f2</link>
      <guid>https://dev.to/ivolondon/getting-started-with-the-model-context-protocol-mcp-build-and-connect-your-first-mcp-server-f2</guid>
      <description>&lt;ol&gt;
&lt;li&gt;What is MCP&lt;/li&gt;
&lt;li&gt;Demo 1 - Using a pre-build MCP - sharing my local filesystem&lt;/li&gt;
&lt;li&gt;Demo 2 - Creating MCP server from the ground up (using Typescript SDK)&lt;/li&gt;
&lt;li&gt;MCP Server Inspector&lt;/li&gt;
&lt;li&gt;Connecting MCP Client with our MCP Server&lt;/li&gt;
&lt;li&gt;(Optional) Extend the custom MCP Server with dynamic data&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What is MCP?
&lt;/h3&gt;

&lt;p&gt;The Model Context Protocol acts as a bridge between AI models and external services in a standardised way. On their own, LLMs are limited in usefulness - while ChatGPT 3.5 was good at generating text and making jokes, it couldn’t access real-time data or connect to your email inbox by itself.&lt;/p&gt;

&lt;p&gt;This is where “tool augmentation” became important - we were able to link LLMs to various services, but each service used a different API. Managing and scaling applications with this approach could quickly become very challenging.&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%2F2zrvggrf1vm945c4y2mz.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%2F2zrvggrf1vm945c4y2mz.png" alt="basic llm architecture" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MCP Server addresses this issue by providing a unified communication method with the LLM (MCP Client). This means users no longer need to worry about individual service APIs, making it much easier to implement and scale different services.&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%2F051glc9gtf828z1iaoha.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%2F051glc9gtf828z1iaoha.png" alt="mcp server layer" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In fact, it's even more convenient - typically, service providers are responsible for creating and maintaining the MCP server. This means that any changes to their API are handled by them, so users don't need to worry about ongoing maintenance.&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%2Fp8gxhrsi4va08bngo49i.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%2Fp8gxhrsi4va08bngo49i.png" alt="mcp client connected to mcp servers" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are countless ways to use MCP servers. Common examples include connecting an LLM to your browser so the AI can browse for you, granting access to your email, linking to Github to allow the AI access to your repositories, or integrating with tools like Figma or Blender for 3D design tasks. &lt;a href="https://github.com/modelcontextprotocol/servers?tab=readme-ov-file" rel="noopener noreferrer"&gt;Many many more.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To show how this works, we'll start by using an existing community built MCP server before creating our own. To connect to an MCP server, we need an MCP Client. Some available options are VSCode, Claude Desktop, Cursor and many others. Since I'll be coding in VSCode, that's the client we'll use.&lt;/p&gt;

&lt;h3&gt;
  
  
  (Part 1) Connecting to a pre-built MCP Server
&lt;/h3&gt;

&lt;p&gt;After reviewing the available options on &lt;a href="http://mcpservers.org/" rel="noopener noreferrer"&gt;mcpservers.org&lt;/a&gt;, I’ve chosen to use the &lt;a href="https://mcpservers.org/servers/modelcontextprotocol/filesystem" rel="noopener noreferrer"&gt;Filesystem MCP&lt;/a&gt;. This MCP includes built-in tools for managing a selected directory. Once access is granted, the AI will be able to perform the following tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read/write files&lt;/li&gt;
&lt;li&gt;Create/list/delete directories&lt;/li&gt;
&lt;li&gt;Move files/directories&lt;/li&gt;
&lt;li&gt;Search files&lt;/li&gt;
&lt;li&gt;Get file metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To add The Filesystem MCP in VSCode, we'll connect by using the following commands&lt;/p&gt;

&lt;p&gt;🔸 &lt;code&gt;Cmd/Ctrl + Shift + P&lt;/code&gt; and select &lt;code&gt;MCP: Add Server&lt;/code&gt;&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%2Fhr53wuwhx5p4ntwe72ng.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%2Fhr53wuwhx5p4ntwe72ng.png" alt="mcp add server screen" width="624" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔸 Enter the NPM Package name and allow access&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%2Ffaxso1gjtjwd571qe46y.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%2Ffaxso1gjtjwd571qe46y.png" alt="enter npm package screen" width="625" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔸 I will add a directory containing various files that require sorting (uhh you should see my desktop). If you're following along, select an existing directory from your file system.&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%2Fcv0egoo1pl0xo94bgl3u.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%2Fcv0egoo1pl0xo94bgl3u.png" alt="selecting custom directory" width="719" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔸 Enter system ID - you can leave that as filesystem.&lt;/p&gt;

&lt;p&gt;A mcp.json file has now been created in .vscode directory, containing the following information:&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;servers&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;filesystem&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;command&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="s2"&gt;npx&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="s2"&gt;args&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="s2"&gt;@modelcontextprotocol/server-filesystem&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="s2"&gt;/Users/{{username}}/Downloads/TheJunkDrawer&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="s2"&gt;type&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="s2"&gt;stdio&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inputs&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="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can also confirm that the Filesystem MCP has been added by checking the Extensions tab in the sidebar. (Yes my sidebar is on the right and it’s just awesome, don’t judge me!).&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%2Fdge13oiw8mpooq31eiky.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%2Fdge13oiw8mpooq31eiky.png" alt="vscode sidebar" width="465" height="892"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I noticed that although the server was installed, it didn't start automatically for me. If you encounter the same issue, you can start it by pressing &lt;code&gt;Cmd/Ctrl + Shift + P&lt;/code&gt;, then select &lt;code&gt;MCP List Servers&lt;/code&gt; &amp;gt; Select &lt;code&gt;Filesystem&lt;/code&gt; &amp;gt; &lt;code&gt;Start Server&lt;/code&gt;. &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%2Fnyq1ndmghmy2e6myymw4.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%2Fnyq1ndmghmy2e6myymw4.png" alt="vscode output log" width="800" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To check if it's functioning properly, let's ask the AI to organise the files into folders based on their file types. Here’s the current state of the folder:&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%2F1z7hfxqbmrwdy9yc97vg.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%2F1z7hfxqbmrwdy9yc97vg.png" alt="folder with random files in it" width="778" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The query I ran: (without saying “please.” The guilt is real)&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%2Fdrd7lzk32bhb815k7o1f.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%2Fdrd7lzk32bhb815k7o1f.png" alt="vscode copilot" width="358" height="940"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This MCP server includes 12 tools, each functioning like a separate action. It can independently determine the next steps to take, but before carrying out any action, it will either request your approval or you can choose to let it operate automatically and go wild. Here’s the result after it finished:&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%2Fgw5qocuk0np1sti6esdy.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%2Fgw5qocuk0np1sti6esdy.png" alt="folder with structured files" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Aaaaaaa!!! This is crazy!! Honestly, my Desktop and Downloads need this more than anywhere else).&lt;/p&gt;




&lt;h3&gt;
  
  
  (Part 2) Creating MCP server from the ground up
&lt;/h3&gt;

&lt;p&gt;Now that we've worked with a pre-built MCP, let's create a server from scratch to connect our app with AI models. To keep it straightforward, we'll build a weather tool using TypeScript. Let's begin by setting up a new project:&lt;/p&gt;

&lt;h4&gt;
  
  
  Setup a new project
&lt;/h4&gt;

&lt;p&gt;🔸 Create a directory and cd into it. In your terminal, type:&lt;br&gt;
&lt;code&gt;mkdir mcp-weather-server &amp;amp;&amp;amp; cd $_&lt;/code&gt; &lt;br&gt;
🔸 Initiate a new project &lt;code&gt;yarn init -y&lt;/code&gt; or use your preferred package manager (I knooow, I should really start using pnpm)&lt;br&gt;
🔸 In the newly created files, open &lt;code&gt;package.json&lt;/code&gt; and add &lt;code&gt;"type": "module"&lt;/code&gt; below &lt;code&gt;version&lt;/code&gt; to enable ES Modules (required for MCP SDK)&lt;br&gt;
🔸 Create index file with &lt;code&gt;touch index.ts&lt;/code&gt; &lt;br&gt;
🔸 Install the SDK&lt;br&gt;
&lt;code&gt;yarn add @modelcontextprotocol/sdk&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's everything for now. Here is how the directory currently appears:&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%2F3ygsywuj26rdncl5vzay.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%2F3ygsywuj26rdncl5vzay.png" alt="folder structure" width="422" height="146"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Building the server
&lt;/h4&gt;

&lt;p&gt;Open &lt;code&gt;index.ts&lt;/code&gt; and copy the code provided below. Be sure to follow the comments that explain each step.&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;// Import necessary modules from the MCP SDK&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;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="s2"&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StdioServerTransport&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="s2"&gt;@modelcontextprotocol/sdk/server/stdio.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;z&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="s2"&gt;zod&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 a new MCP server instance with a name and version, required for the MCP protocol&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="s2"&gt;MCP Weather 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="s2"&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="p"&gt;});&lt;/span&gt;

&lt;span class="cm"&gt;/* Register a tool with the server.
   Tools allow the AI to perform specific actions or retrieve information */&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="c1"&gt;// Unique identifier for the tool&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;get-weather&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// Tool metadata&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="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Get Weather&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="c1"&gt;// Descrtion helps AI understand what the tool does&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="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Tool to get the weather of my location&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="c1"&gt;// Input schema to define the expected input&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;location&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;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The location to get the weather for&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="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// Function to execute when the tool is called&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;location&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="cm"&gt;/* For demonstration purposes we will return static data,
         but in a later step we will make this dynamic */&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&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="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="s2"&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;`The weather in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is sunny with a temperature of 28°C.`&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;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* StdioServerTransport uses the terminal for input/output
   This is useful for local development and testing
   In production, you might use a different transport like HTTP or WebSocket */&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;StdioServerTransport&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! This was a straightforward example, but it gives you an idea of how it works. Now, let's test it out using the inspector.&lt;/p&gt;




&lt;h3&gt;
  
  
  MCP Server Inspector
&lt;/h3&gt;

&lt;p&gt;The MCP Inspector is a handy GUI tool used for testing MCP Servers. Let's launch it and connect our server by running the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx -y @modelcontextprotocol/inspector npx -y tsx index.ts&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;You should see the following output in the console. Open the provided URL, which will already have the token filled in:&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%2F7tvxc5xai07sq55j2chx.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%2F7tvxc5xai07sq55j2chx.png" alt="running MCP server inspector" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how Inspector version v0.15.0 appears on my system with the dark theme enabled, so your view might look slightly different. On the loaded screen, select the bottom left button ‘Connect’,  then click on ‘List Tools’ and select the ID of the tool (get-weather).&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%2Fqi9htbxkure5cddphf5x.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%2Fqi9htbxkure5cddphf5x.png" alt="mcp inspector v0.15.0" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Type the location and you should receive a result.&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%2Fsozg34g2gru4wa9gods9.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%2Fsozg34g2gru4wa9gods9.png" alt="query mcp inspector" width="615" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that, ladies and gentlemen, is how you get endless 28°C sunny days in London. You’re welcome! For you rain lovers (I am secretly one too, but shhh), we will work on this later. &lt;/p&gt;

&lt;p&gt;The MCP Inspector is useful for testing each tool you’ve created, but it’s probably not the main way you’d want to interact with your server. Let’s integrate this with the tools you use every day - specifically, back to VSCode.&lt;/p&gt;




&lt;h3&gt;
  
  
  Connecting MCP Client with our MCP Server
&lt;/h3&gt;

&lt;p&gt;🔸 In VSCode, open the command palette by pressing &lt;code&gt;Cmd/Ctrl + Shift + P&lt;/code&gt;.&lt;br&gt;
🔸 Type &lt;code&gt;MCP: Add Server&lt;/code&gt;&lt;br&gt;
🔸 Choose &lt;code&gt;Command (stdio)&lt;/code&gt;&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%2Fx52ych0ikd1e1bs8epku.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%2Fx52ych0ikd1e1bs8epku.png" alt="vscode selecting cmp server command" width="633" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔸 Enter command &lt;code&gt;npx -y tsx index.ts&lt;/code&gt; &lt;br&gt;
🔸 Enter your server name (or leave default)&lt;br&gt;
🔸 Choose where to install it - I have selected &lt;code&gt;Workspace&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;This should open your &lt;code&gt;mcp.json&lt;/code&gt; file with your configurations in place and the server running. If it hasn't started automatically, click Start to launch it.&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%2F4j56luw1tqoq61zzgzvv.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%2F4j56luw1tqoq61zzgzvv.png" alt="vscode local mcp" width="800" height="789"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔸 Let's ask Copilot for the current weather in London (as if I can’t see out of the window that it isn’t sunny)&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%2Fzvwxtq4chut1r7se4vh0.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%2Fzvwxtq4chut1r7se4vh0.png" alt="prompting copilot" width="428" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and the result, as expected - Sunny 28C (Before I move on, I will hit refresh on this a few more times to see if the clouds will get the hint and clear as I have plans for this weekend).&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%2Fsy6yudfzmpy481iqeb7k.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%2Fsy6yudfzmpy481iqeb7k.png" alt="mcp server response with static data" width="423" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You’ve set up your first MCP Server. While this example is quite simple and the use case may seem limited for now, the main goal was to help you understand the concept. Feel free to experiment with your own ideas. If you have any questions, you can reach out to me on &lt;a href="https://www.linkedin.com/in/ivelin-iliev-16272baa/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next step, we’ll make a request to fetch actual weather data and update the static response to return real-time information.&lt;/p&gt;


&lt;h3&gt;
  
  
  Connect the server to a weather API provider
&lt;/h3&gt;

&lt;p&gt;We are going to use Open-Meteo, as it’s free and does not need API key.&lt;/p&gt;

&lt;p&gt;🔸 In your &lt;code&gt;index.ts&lt;/code&gt;, replace the body of the callback function with the following. Be sure to follow the comments that explain each step.&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="cm"&gt;/* We first need to fetch latitude and longitude coordinates for the given location using
    the Geocoding API Notice that I am using countryCode=GB to limit results to Great Britain,
    you can change this to any country code or remove it for global results.
  */&lt;/span&gt;
  &lt;span class="k"&gt;try&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`https://geocoding-api.open-meteo.com/v1/search?name=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;count=1&amp;amp;countryCode=GB`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&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="s2"&gt;Content-Type&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="s2"&gt;application/json&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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Parse the response as JSON&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;coordinatesJson&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;result&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;// Extract latitude and longitude from the response&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;longitude&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;coordinatesJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Fetch weather data using the obtained coordinates&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weatherResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`https://api.open-meteo.com/v1/forecast?latitude=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;longitude=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;hourly=temperature_2m,precipitation_probability,rain`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&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="s2"&gt;Content-Type&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="s2"&gt;application/json&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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Parse the weather data response as JSON&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weatherJson&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;weatherResult&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;// Return the weather data in a structured format&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&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="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="s2"&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="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;weatherJson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&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;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Handle any errors&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error fetching weather data:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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="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="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="s2"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to fetch weather data. Please try again later.&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="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;We can view the result in the inspector. Next, we'll run it in our MCP Client.&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%2Fr8x2nebd7c7534sjcrdg.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%2Fr8x2nebd7c7534sjcrdg.png" alt="mcp inspector result" width="800" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔸 In VSCode, restart your MCP Server by opening the Command Palette &lt;code&gt;Cmd/ctrl + Shift + P&lt;/code&gt;&lt;br&gt;
🔸 Select &lt;code&gt;MCP: List Servers&lt;/code&gt; and select the weather-server&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%2Fb8aj7r3psonnehqucq7g.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%2Fb8aj7r3psonnehqucq7g.png" alt="mcp server list servers" width="630" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔸 Select &lt;code&gt;Restart server&lt;/code&gt; . You will then notice in the Output that the MCP server has been stopped and restarted.&lt;br&gt;
🔸 Try again with the same prompt:&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%2Fabwe1ozjufr4qclkhu0r.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%2Fabwe1ozjufr4qclkhu0r.png" alt="copilot response" width="800" height="1093"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How awesomeeee!!! The LLM takes the raw data and gives you a friendly message, with the accurate data, with no formatting needed! &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Connecting an LLM to various services, data sources, and applications in a standardised way significantly enhances its usefulness. MCP, an open-source solution from Anthropic, has rapidly gained popularity. Like any emerging technology, developers may eventually encounter edge cases that require further development or even replacement of the solution, but for now, it shows great promise and is becoming the standard.&lt;/p&gt;

&lt;p&gt;If you'd like to talk more about any of the topics above, I’d be happy to connect on &lt;a href="https://www.linkedin.com/in/ivelin-iliev-16272baa/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;. I’m happy hear your feedback or answer any questions. All the best and happy coding!&lt;/p&gt;

&lt;h4&gt;
  
  
  Useful Links:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.anthropic.com/news/model-context-protocol" rel="noopener noreferrer"&gt;Introducing the Model Context Protocol by Anthropic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/modelcontextprotocol" rel="noopener noreferrer"&gt;Model Context Protocol Github Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://modelcontextprotocol.io/docs/learn/architecture" rel="noopener noreferrer"&gt;Architecture Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mcpcat.io/blog/mcp-server-client-host/" rel="noopener noreferrer"&gt;What is an MCP Server, MCP Client, and MCP Host?&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>First steps in initialising Webpack and Typescript</title>
      <dc:creator>Ivelin (Ivo)</dc:creator>
      <pubDate>Tue, 15 Mar 2022 23:29:34 +0000</pubDate>
      <link>https://dev.to/ivolondon/first-steps-in-initialising-webpack-and-typescript-57gj</link>
      <guid>https://dev.to/ivolondon/first-steps-in-initialising-webpack-and-typescript-57gj</guid>
      <description>&lt;h2&gt;
  
  
  Part 1 - Very basic setup
&lt;/h2&gt;

&lt;p&gt;Build your own config for Webpack from the ground up. This post will hold your hand for the first 4 steps and you will see how to take it from there. As of Webpack 4, a config file is not needed so let's see how we can create a build.&lt;/p&gt;

&lt;p&gt;In your terminal, navigate to a folder you want to work in and type the following:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn init -y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add webpack webpack-cli --dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the root level create a folder &lt;code&gt;/dist&lt;/code&gt; with a file &lt;code&gt;index.html&lt;/code&gt; inside and another folder &lt;code&gt;/src&lt;/code&gt; in the root level and add a &lt;code&gt;index.js&lt;/code&gt; file inside it. Your file structure should look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|- package.json
|- package-lock.json
|- /dist
    |- index.html
|- /src
    |- index.js```




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

&lt;/div&gt;

&lt;p&gt;In your &lt;code&gt;package.json&lt;/code&gt;, replace &lt;code&gt;"main": "index.js",&lt;/code&gt; with &lt;code&gt;"private": true&lt;/code&gt; to prevent it from publishing your package.&lt;/p&gt;

&lt;p&gt;Add basic HTML5 boiler plate to your &lt;code&gt;dist/index.html&lt;/code&gt; file, it should look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8" /&amp;gt;
    &amp;lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&amp;gt;
    &amp;lt;title&amp;gt;Webpack&amp;lt;/title&amp;gt;
    &amp;lt;script src="main.js"&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;As an example, add a console log to your &lt;code&gt;./src/index.js&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

const greetings = "Hello World";
console.log(greetings);


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

&lt;/div&gt;

&lt;p&gt;This is all that is needed for a very basic build. Now run &lt;code&gt;yarn webpack&lt;/code&gt; and you can see a new, compiled file &lt;code&gt;main.js&lt;/code&gt; to appear in &lt;code&gt;./dist&lt;/code&gt;. The content of the compiled file should look like the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

console.log("Hello World");


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

&lt;/div&gt;




&lt;h2&gt;
  
  
  Part 2 - Adding a custom config file
&lt;/h2&gt;

&lt;p&gt;In the root level, add a file called &lt;code&gt;webpack-config.js&lt;/code&gt; and then add the following configs:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import path from "path";

export default {
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
  },
};


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Part 3 - Add script command
&lt;/h2&gt;

&lt;p&gt;In your &lt;code&gt;package.json&lt;/code&gt;, add the following command to the existing scripts (you should have &lt;code&gt;test&lt;/code&gt; by default)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

"build": "webpack --mode development"


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

&lt;/div&gt;

&lt;p&gt;Next time you need to run a build, you can use &lt;code&gt;yarn run build&lt;/code&gt; instead of typing it all in the terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 4 - Add TypeScript
&lt;/h2&gt;

&lt;p&gt;Install dependancies&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

yarn add typescript ts-loader ts-node --dev


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

&lt;/div&gt;

&lt;p&gt;Add a new file &lt;code&gt;tsconfig.json&lt;/code&gt; to the root level of the project and add the following configs:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
    "compilerOptions": {
      "target": "ESNEXT",
      "module": "commonjs",
      "strict": true,
      "esModuleInterop": true,
      "skipLibCheck": true,
      "forceConsistentCasingInFileNames": true,
      "resolveJsonModule": true
    }
  }


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

&lt;/div&gt;

&lt;p&gt;Then open your webpack-config and add the following below &lt;code&gt;output&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

module: {
  rules: [
    {
      test: /\.tsx?$/,
      use: "ts-loader",
      exclude: /node_modules/,
    },
  ],
},
resolve: {
  extensions: [".tsx", ".ts", ".js"],
},


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

&lt;/div&gt;

&lt;p&gt;Replace the entry file extension in your webpack-config to:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

entry: path.resolve(__dirname, "src/index.ts")


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

&lt;/div&gt;



&lt;p&gt;Add a new file to &lt;code&gt;./src&lt;/code&gt; named &lt;code&gt;index.ts&lt;/code&gt;. You can now start to use this instead.&lt;/p&gt;

&lt;p&gt;This is all that is needed to create an initial configs for webpack and add support for typescript. If you have any questions, please leave a comment and I will get back to you. All the best at initialising webpack!&lt;/p&gt;

</description>
      <category>webpack</category>
      <category>firstpost</category>
      <category>tutorial</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
