Showing posts with label Model. Show all posts
Showing posts with label Model. Show all posts

Friday, July 17, 2026

Coding with Microsoft Foundry Local

Coding with Microsoft Foundry Local

In this article we will explore the Microsoft Foundry Local CLI application. We will then write a simple C# program that interacts with a local model that is served by Foundry Local.

Copanion Video: https://youtu.be/YD5QKDcb8T8

What is Microsoft Foundry Local?

Foundry Local is an AI solution that runs entirely on the user's device. It also provides an SDK (C#, JavaScript, Rust, and Python) that helps you build apps that interact with Foundry Local.

Installation

To install Foundry Local, follow these steps:

Windows

winget install Microsoft.FoundryLocal


macOS (only on silicon chips)

brew tap microsoft/foundrylocal
brew trust microsoft/foundrylocal
brew install foundrylocal


Exporing CLI commands

Try the following Foundry Local CLI commands:

Detect the CLI version:

foundry --version

Expected output:

0.8.119

View the list of CLI commands:

foundry --help

Expected output:

Description:
Foundry Local CLI: Run AI models on your device.
 ðŸš€ Getting started:
 1. To view available models: foundry model list
 2. To run a model: foundry model run <model>

 EXAMPLES:
foundry model run phi-3-mini-4k

 Usage:
foundry [command] [options]

 Options:
-?, -h, --help Show help and usage information
--version Show version information
--license Display foundry license information

Commands:
model Discover, run and manage models
cache Manage the local cache
service Manage the local model inference service

Download a model into local cache:

foundry model download qwen2.5-0.5b

Expected output:

Downloading qwen2.5-0.5b-instruct-generic-gpu:4... 
 . . . T R U N C A T E D . . . 
 [################################## ] 94.85 % [Time remaining: about 1s]
[################################## ] 95.22 % [Time remaining: about 1s]
[################################## ] 95.59 % [Time remaining: about 1s]
[################################## ] 95.96 % [Time remaining: about 1s]
[################################## ] 96.33 % [Time remaining: about 1s]
[################################## ] 96.69 % [Time remaining: about 1s]
[################################## ] 97.06 % [Time remaining: about 1s]
[################################### ] 97.43 % [Time remaining: about 1s]
[################################### ] 97.79 % [Time remaining: about 1s]
[################################### ] 98.16 % [Time remaining: about 1s]
[################################### ] 98.53 % [Time remaining: about 1s]
[################################### ] 98.90 % [Time remaining: about 1s]
[################################### ] 99.27 % [Time remaining: about 1s]
[################################### ] 99.63 % [Time remaining: about 1s]
[####################################] 100.00 % [Time remaining: about 0s]
[####################################] 100.00 % [Time remaining: about 0s] 85.9 MB/s

Tips:
- To find model cache location use: foundry cache location
- To find models already downloaded use: foundry cache ls

List models in local cache:

foundry cache list

Expected output:

💾 qwen2.5-0.5b              qwen2.5-0.5b-instruct-generic-gpu:4

Remove a model from local cache:

foundry cache remove qwen2.5-0.5b

Expected output:

⚠️ This will delete model 'qwen2.5-0.5b (qwen2.5-0.5b-instruct-generic-gpu:4)' from cache.
⚠️ Are you sure you want to delete this model from the local cache? (y/n)
y
Deleted model qwen2.5-0.5b-instruct-generic-gpu:4 from the cache.

Download and run a model:

foundry model run qwen2.5-0.5b

Expected output:

Downloading qwen2.5-0.5b-instruct-generic-gpu:4...
[####################################] 100.00 % [Time remaining: about 0s]  105.2 MB/s
🕛 Loading model...
🟢 Model qwen2.5-0.5b-instruct-generic-gpu:4 loaded successfully

Interactive Chat. Enter /? or /help for help.
Press Ctrl+C to cancel generation. Type /exit to leave the chat.

Interactive mode, please enter your prompt
>

💡 TIP

If you get an error when running a model, it may mean that your hardware is incompatible with the specific model that was downloaded. You can try looking ar variants of that model for different processor configurations. To view the variants for a model (Example: qwen2.5-0.5b), type the following command: 

foundry model info qwen2.5-0.5b

You can then try one of the variants like qwen2.5-0.5b-instruct-generic-cpu with: 
foundry model run qwen2.5-0.5b-instruct-generic-cpu

The above puts the user in a CLI interactive mode. You can then send prompt to the model. Let's ask the model to create for us a C# program that does temperature conversion. Type in the following prompt:

Write a C# console app that converts temperature from C to F and also from F to C.

Expected output:

🧠 Thinking...
🤖 Certainly! Below is a simple console application written in C# that takes user input for Celsius temperature and converts it to either Fahrenheit or vice versa.


using System;
using System.Windows.Forms;

namespace TemperatureConverterApp
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Enter the Temperature (in Celcius): ");
                int celsius = Convert.ToInt32(Console.ReadLine());

                bool convertToFahrenheit = false;
                string result;

                if (Convert.ToBoolean(calculateCtoF(celsius)) == true)
                    result = "Celsius to Fahrenheit: ";
                else
                    result = "Temperature not converted";

                result += $"Celsius {result}";

                if (convertToFahrenheit) 
                {
                    Console.WriteLine($"Result: Fahrenheits");
                    return;
                }

                Console.WriteLine(result);
            }
            catch
            {
                Console.WriteLine("Invalid Input");
            }
        }

        public static bool calculateCtoF(int celsius)
        {
            double fahrenheit = 9/5 * celsius + 32;
            double result = Math.Round(fahrenheit, 1);

            // Round down to the nearest integer since temperatures must be whole numbers
            if (fahrenheit.ToString() != "0")
                return true;
            else
                return false;
        }

        public static bool calculateFtoc(double fahrenheit)
        {
            double celsius = fahrenheit - 32 * 5 / 9;
            double result = Math.Round(celsius, 1);

            // Round down to the nearest integer since temperatures must be whole numbers
            if (celsius.ToString() != "0")
                return true;
            else
                return false;
        }
    }
}

Explanation: 

1. Imports: The code starts with importing necessary namespaces (System and System.Windows.Forms). It's assumed you have this namespace available. 

2. Program Class
    - This contains the main program logic. 

3. calculateCtoF Function
    - Calculates the temperature in Fahrenheit given Celsius temperature. 
    - If successful, calculates the equivalent number of degrees Celsius based on the provided value and rounds it to the closest integer.  
    - Outputs the result along with any additional information like "Celsius" or "Temperature not converted". 

4. calculateFtoc Function
    - Calculates the equivalent temperature in Celcius given the equivalent degrees Fahrenheit. 
    - Same as calculateCtoF, but used for converting degrees Fahrenheit back to Celsius. 

Example Usage: 

If you run the program, pressing the keyboard will take an input to calculate the correct conversion type and output results accordingly. 

Example Input: 25 
    - If calculated using Celsius, it will print: "Celsius", then "25". 
    - If converted to Fahrenheit, it will print: "Temperature not converted", then "25". 

This example only demonstrates basic conversions between the two temperature scales and does not handle invalid inputs like non-numerical characters which would throw exceptions during parsing.

Exit CLI mode, type:

/exit

Stop the Foundry service:

foundry service stop

Expected output:

🔴 Service is stopped.

Start the Foundry service:

foundry service start

Expected output:

🟢 Service is Started on http://127.0.0.1:64398/, PID 9459!

Develop a C# app using Foundry Local SDK

The Foundry Local SDK enables you to ship AI features in your applications that are capable of using local AI models through a simple and intuitive API. The SDK abstracts away the complexities of managing AI models and provides a seamless experience for integrating local AI capabilities into your applications.

dotnet new console -o FoundryLocalConsoleApp
cd FoundryLocalConsoleApp
dotnet add package Microsoft.AI.Foundry.Local
dotnet add package Microsoft.Extensions.Logging
dotnet add package Betalgo.Ranul.OpenAI -v  9.1.0

Add this to the .csproj file right above </PropertyGroup>:

<RuntimeIdentifiers>osx-arm64;osx-x64;win-x64;linux-x64</RuntimeIdentifiers>

Replace Program.cs with this code that asks the qwen2.5-0.5b local AI model the question: Where did coffee come from?:

using Betalgo.Ranul.OpenAI.ObjectModels.RequestModels;
using Microsoft.AI.Foundry.Local;
using Microsoft.Extensions.Logging;

CancellationToken ct = new();

var config = new Configuration {
    AppName = "foundry_local_samples",
    LogLevel = Microsoft.AI.Foundry.Local.LogLevel.Information
};

using var loggerFactory = LoggerFactory.Create(builder => {
    // Intentionally no providers configured; this still yields a valid ILogger instance.
});
ILogger logger = loggerFactory.CreateLogger("FoundryLocalConsoleApp");

// Initialize the singleton instance.
await FoundryLocalManager.CreateAsync(config, logger);
var mgr = FoundryLocalManager.Instance;


// Discover available execution providers and their registration status.
var eps = mgr.DiscoverEps();
int maxNameLen = 30;
Console.WriteLine("Available execution providers:");
Console.WriteLine($"  {"Name".PadRight(maxNameLen)}  Registered");
Console.WriteLine($"  {new string('─', maxNameLen)}  {"──────────"}");
foreach (var ep in eps) {
    Console.WriteLine($"  {ep.Name.PadRight(maxNameLen)}  {ep.IsRegistered}");
}

// Download and register all execution providers with per-EP progress.
// EP packages include dependencies and may be large.
// Download is only required again if a new version of the EP is released.
// For cross platform builds there is no dynamic EP download and this will return immediately.
Console.WriteLine("\nDownloading execution providers:");
if (eps.Length > 0) {
    string currentEp = "";
    await mgr.DownloadAndRegisterEpsAsync((epName, percent) => {
        if (epName != currentEp) {
            if (currentEp != "") {
                Console.WriteLine();
            }
            currentEp = epName;
        }
        Console.Write($"\r  {epName.PadRight(maxNameLen)}  {percent,6:F1}%");
    });
    Console.WriteLine();
} else {
    Console.WriteLine("No execution providers to download.");
}


// Get the model catalog
var catalog = await mgr.GetCatalogAsync();


// Get a model using an alias.
var model = await catalog.GetModelAsync("qwen2.5-0.5b") ?? throw new Exception("Model not found");

// Download the model (the method skips download if already cached)
await model.DownloadAsync(progress =>{
    Console.Write($"\rDownloading model: {progress:F2}%");
    if (progress >= 100f)
    {
        Console.WriteLine();
    }
});

// Load the model
Console.Write($"Loading model {model.Id}...");
await model.LoadAsync();
Console.WriteLine("done.");

// Get a chat client
var chatClient = await model.GetChatClientAsync();

// Create a chat message
List<ChatMessage> messages = new() {
    new ChatMessage { Role = "user", Content = "Where did coffee come from?" }
};

// Get a streaming chat completion response
Console.WriteLine("Chat completion response:");
var streamingResponse = chatClient.CompleteChatStreamingAsync(messages, ct);
await foreach (var chunk in streamingResponse) {
    Console.Write(chunk.Choices[0].Message.Content);
    Console.Out.Flush();
}
Console.WriteLine();

// Tidy up - unload the model
await model.UnloadAsync();

ℹ️ NOTE - Notice model qwen2.5-0.5b in the above code (around line 59). Change this to any other model or variant of your choice.

Expected output:


  Available execution providers:
  Name                            Registered
  ──────────────────────────────  ──────────
  WebGpuExecutionProvider         False

Downloading execution providers:
  WebGpuExecutionProvider          100.0%
Loading model qwen2.5-0.5b-instruct-generic-gpu:4...done.
Chat completion response:
Coffee originated in the Ethiopian Highlands and later spread to other regions due to various factors such as trade, migration, and disease. It''s believed that people first brought coffee from Ethiopia with them when they migrated to other parts of the world. The earliest known records suggest that the first drink made from coffee was consumed by the Shas people in West Africa.

As the demand for coffee grew, more people began to experiment with making their own beverages. By 1750, coffee had been developed into its current form in the Middle East and Asia. It wasn''t until 1826 that an American named Robert Brown invented espresso, which has since become one of the most popular beverages worldwide.

The history of coffee is a story of innovation, trade, and cultural exchange over centuries. Coffee has played a significant role in many societies around the world and continues to be enjoyed today through different methods and traditions.
 

For more information, see the Foundry Local SDK reference.

Sunday, October 19, 2025

Small Language Models with AI Toolkit Extension in VS Code

In this article, we will see how we can work with small language models (SLM) from the AI Toolkit extension in VS Code. Though the toolkit can do other things, our focus is to consume an ONNX SLM hosted on Visual Studio Code from a C# application. We will first look at an example that is based on OpenAI packages. We will later use a similar example based on the Sematic Kernal approach.

Companion Video: https://youtu.be/V_eWAM2fxJg

Prerequisites

You will need:

  • The latest version of VS Code
  • .NET version 9.0 or higher

What are small language models (SLMs)?

Small Language Models (SLMs) are compact versions of large language models (LLMs), designed to deliver strong performance in natural language tasks while using significantly fewer computational resources.

What is the AI Toolkit Extension in VS Code?

The AI Toolkit Extension for Visual Studio Code is a powerful, all-in-one environment for building, testing, and deploying generative AI applications—especially useful for developers working with small language models (SLMs).

Getting Started

Install the following Visual Studio Code extension:


Click on the three dots (...) in the left navigation of VS Code, and choose "AI Toolkit".

Click on "Model Catalog".

Scroll down down the list until you find “Local Models” >> ONNX >> Minstral 7B – (CPU – Small, Standard) >> + Add Model.

Once the model is fully downloaded, it will appear under Models >> ONNX.

Right-click on the model and select “Copy Model Name”.

I copied the following name for the "Minstral 7B" model: 

mistral-7b-v02-int4-cpu

Using OpenAI packages

Create a C# console application named AIToolkitOpenAI and add to it required packages with the following terminal window commands:

dotnet new console -n AIToolkitOpenAI
cd AIToolkitOpenAI
dotnet add package OpenAI

Start VS Code with:

code .

Click on the "AI Toolkit" tab in VS Code and make sure that the "Minstral 7B" model is running.

Replace content of Program.cs with this code:

using OpenAI;
using OpenAI.Chat;
using System.ClientModel;
using System.Text;

var model = "mistral-7b-v02-int4-cpu";
var baseUrl = "http://localhost:5272/v1/"; // root URL for local OpenAI-like server
var apikey = "unused";

OpenAIClientOptions options = new OpenAIClientOptions();
options.Endpoint = new Uri(baseUrl);
ApiKeyCredential credential = new ApiKeyCredential(apikey);
ChatClient client = new OpenAIClient(credential, options).GetChatClient(model);

// Build the prompt
StringBuilder prompt = new StringBuilder();
prompt.AppendLine("You will analyze the sentiment of the following product reviews.");
prompt.AppendLine("Each line is its own review. Output the sentiment of each review in");
prompt.AppendLine("a bulleted list and then provide a general sentiment of all reviews.");
prompt.AppendLine();
prompt.AppendLine("I bought this product and it's amazing. I love it!");
prompt.AppendLine("This product is terrible. I hate it.");
prompt.AppendLine("I'm not sure about this product. It's okay.");
prompt.AppendLine("I found this product based on the other reviews. It worked");

// send the prompt to the model and wait for the text completion
var response = await client.CompleteChatAsync(prompt.ToString());
// display the response
Console.WriteLine(response.Value.Content[0].Text);

Run the application with:

dotnet run

The application does sentiment analysis on what customers think of the product.

This is a sample of the output:

* I bought this product and it's amazing. I love it!: Positive sentiment
* This product is terrible. I hate it.: Negative sentiment
* I'm not sure about this product. It's okay.: Neutral sentiment
* I found this product based on the other reviews. It worked for me.: Positive sentiment

General sentiment: The reviews contain both positive and negative sentiments. Some customers expressed their love for the product, while others expressed their dislike. Neutral sentiment was also expressed by one customer. Overall, the reviews suggest that the product has the potential to elicit strong feelings from customers, both positive and negative.

Sematic Kernel packages

Create a C# console application named AIToolkitSK and add to it required packages with the following terminal window commands:

dotnet new console -n AIToolkitSK
cd AIToolkitSK
dotnet add package Microsoft.SemanticKernel

Start VS Code with:

code .

Click on the "AI Toolkit" tab in VS Code and make sure that the "Minstral 7B" model is running.

Replace content of Program.cs with this code:

using System.Text;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;

var model = "mistral-7b-v02-int4-cpu";
var baseUrl = "http://localhost:5272/v1/";
var apikey = "unused";

// Create a chat completion service
var kernel = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion(modelId: model, apiKey: apikey, endpoint: new Uri(baseUrl))
    .Build();
var chat = kernel.GetRequiredService<IChatCompletionService>();
var history = new ChatHistory();
history.AddSystemMessage("You are a useful chatbot. Always reply in a funny way with short answers.");
var settings = new OpenAIPromptExecutionSettings
{
    MaxTokens = 500,
    Temperature = 1,
};

while (true)
{
    Console.Write("\nUser: ");
    var userInput = Console.ReadLine();
    if (string.IsNullOrWhiteSpace(userInput)) break;

    history.AddUserMessage(userInput);

    var responseBuilder = new StringBuilder();
    Console.Write("\nAI: ");
    await foreach (var message in chat.GetStreamingChatMessageContentsAsync(userInput, settings, kernel))
    {
        responseBuilder.Append(message);
        Console.Write(message);
    }
}

This is a simple chat completion app.

Run the application with:

dotnet run

My prompt was:

Red or white wine with beef steak?

The response was:

AI:  Both red and white wines can pair well with beef steak, but a red wine is generally the more traditional choice. Red wines, such as Cabernet Sauvignon, Merlot, or Pinot Noir, have flavors that complement the rich and savory flavors of beef. However, if you prefer a lighter taste, a white wine such as Pinot Noir or Chardonnay can also work well with beef steak. Ultimately, it comes down to personal preference.

Conclusion

We have seen how to use SLMs hosted by VS Code through the AI Toolkit extension. We were able to communicate with the model from these two C# applications: (1) a app the uses OpenAI packages, and (2) an app that uses Sematic Kernel.

Friday, August 15, 2025

Using the timer MCP Server in Visual Studio Code

In a previous article, I discussed “Getting started with MCP Server in Visual Studio Code”. I decided to update this article because the process has become much easier with the latest version of VS Code.

In this tutorial, you will learn how to enable and use MCP servers in Visual Studio Code. The simple example we will use is the Timer MCP Server.

Companion Video: https://youtu.be/H14yMdHuyM4

What is MCP?

Model Context Protocol (MCP) is an open standard developed by Anthropic, the company behind Claude models. 

MCP is an open protocol that enables seamless integration between AI apps & agents and your tools & data sources.

Prerequisites

  • Visual Studio Code
  • GitHub account
  • Github Copilot Chat extension
  • Docker Desktop

NOTE:  This article uses Visual Studio Code version 1.103.1 as shown below:

Later versions of Visual Studio Code will likely have minor UI changes that may look different from the screen captures in this article.

Getting Started

We will setup an MCP Server that provides current time information. This will be done in a local workspace, as opposed to making it globally available in VS Code. Also, the MCP server will run in Docker.

Start Docker Desktop.

Create a working directory named time-mcp-server and open VS Code in that directory with:

mkdir time-mcp-server
cd time-mcp-server
code .

In VS Code, click on the GitHub Copilot Chat icon and select “Open Chat”.

In the chat window that opens, choose Agent mode and the latest Claude model. A tools button appears.

When you click on the tools button, a pop-up window will display the tools used by VS-Code GitHub Copilot Chat.

Click on OK to close the pop-up window.

In Visual Studio Code, click on the gear in the bottom-left, then choose settings:

In the filter field, type MCP.

Note that Discovery is enabled. These are early days, so some Mcp features are in Experimental mode.

Click on 'Edit in settings.json'. 

The file will open in the editor. Note that chat.mcp.discovery.enabled is set to true.

You can close the settings.json file in the editor.

Find a suitable MCP Server

Go to https://github.com/modelcontextprotocol/servers. Search for Time under Reference Servers.

Click on the Time link. Then fing Configuration >> Configure for Claude App >> Unsing docker.

Take note of the name of the docker image mcp/time.

Setup a timer MCP Server

In Visual Studio Code, click on View >> Command Palette….

Choose “MCP: Add Server…”.

Choose “Docker Image Install from a Docker image”.

For "Docker Image Name", enter “mcp/time”.

Next, choose Allow.

Accept the default Server ID.

Choose “Workspace Available in this workspace, runs locally”.

When prompted to trust and run the MCP server time, click on Trust.

A file named mcp.json gets created in a folder named .vscode inside your workspace with content:

{
"servers": {
"time": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"mcp/time"
],
"type": "stdio"
}
},
"inputs": []
}

If the MCP server is not yet started, click on Start.

This will start the mcp/time server in Docker.

In the GitHub Copilot Chat window, enter: What is the current time?

 VS Code detects the running MCP server which knows how to handle requests for current time:

Click on Continue and you will get a response like this:

You can ask it to convert the time to another time zone with: What is that in pacific time zone?

Again, it should resort to the time MCP server for assistance.

Click on Continue to get your answer.

You can even ask the time in another country. Example: What time is it in Cairo, Egypt?

Again, it uses our MCP time server:

Click on Continue.

Finally, let us ask it to refresh the current time, with: Refresh the time in Egypt.

Conclusion

The ecosystem for MCP servers is growing rapidly. There are already many servers that you can explore at https://github.com/modelcontextprotocol/servers. 

Wednesday, June 11, 2025

Getting started with MCP Server in Visual Studio Code

In this tutorial, you will learn how to enable and use MCP servers in Visual Studio Code. The simple example we will use is the Timer MCP Server.

What is MCP?

Model Context Protocol (MCP) is an open standard developed by Anthropic, the company behind Claude. 

MCP is an open protocol that enables seamless integration between AI apps & agents and your tools & data sources.

Prerequisites

  • Visual Studio Code
  • GitHub account
  • Github Copilot Chat extension
  • Docker Desktop

Getting Started

Start VS Code and click on the GitHub Copilot Chat icon.


Choose any Claude model and Agent mode. A tools button appears.


When you click on the tools button, you will see the tools that VS-Code GitHub Copilot Chat is using:

In Visual Studio Code, click on the gear in the bottom-left, then choose settings:

In the filter field, type MCP.


Note that Discovery is enabled and 'Chat' > 'Mcp' is also enabled. These are early days so Mcp is in preview.

Click on 'Mcp' >> 'Edit in settings.json'. The file will open in the editor. Note the mcp section with a sample mcp-server-time server:


"mcp": {   
  "inputs": [],
  "servers": {
    "mcp-server-time": {
      "command": "python",
      "args": [
        "-m",
        "mcp_server_time",
        "--local-timezone=America/Los_Angeles"
      ],
      "env": {}
    }
  }
}

In the chat window, click on the blue refresh tool.


If you do not have Python installed on your computer, you will get an error in the chat window:


Tap on the red error icon and choose “Show Output”.

The error is because python is not installed on the computer and, therefore, the MCP server cannot start.

Let us fix that by using an alternative way to run the MCP server without the need for Python. We will use Docker instead. Therefore, start your Docker Desktop.

Go to https://github.com/modelcontextprotocol/servers. Search for Time and click on it.

Find “Configure for Claude.app” >> “Using Docker”.


Copy the JSON code under mcpServers:

"mcpServers": {
 
  "time": {
    "command": "docker",
    "args": ["run", "-i", "--rm", "mcp/time"]
  }  
}

Back in settings.json, comment out (or delete) previous MCP servers under “mcp >> servers”. Paste the JSON code under mcp >> servers in settings.json. This is what the section will look like:

Click on the blue refresh tool again in the chat box, if it is there. This time you should not experience any errors.


The time server now shows up among the available mcp servers when you click on tools.


Inside settings.json, start the server if it is not already started.

This will start the mcp/time server in Docker.

In the GitHub Copilot Chat window, enter: What is the current time?

It detects the running MCP server that knows how to handle requests for current time:


Click on Continue and you will get a response like this:

You can ask it to convert the time to another time zone with: What is that in pacific time zone?

Again, it may resort to our Time MCP server for assistance.

Click on Continue to get your answer.

You can even ask the time in another country. Example: What time is it in Cairo, Egypt?

Again, it uses our MCP Time server:


Click on Continue.

Finally, let us ask it to refresh the current time, with: Refresh the time in Egypt.


Conclusion

The ecosystem for MCP servers is growing rapidly. There are already many servers that you can explore at https://github.com/modelcontextprotocol/servers. In another article, I will show you how you can integrate the GitHub MCP server into VS Code.