What is MCP?
My short definition is: A protocol that lets LLMs talk to your code.
For example, if you have an API that returns a list of warehouses, how could you get Copilot to call your API and return a list of those warehouses? Or use the list internally to answer your questions about your warehouses?
The answer is MCP. These clients can use it https://modelcontextprotocol.io/clients
VSCode is in that list. They have added support for MCP https://code.visualstudio.com/docs/copilot/chat/mcp-servers
What can I write my MCP server in?
- Python SDK
 - TypeScript SDK
 - Java SDK
 - Kotlin SDK
 - C# SDK
 
Using CSharp
I followed this tutorial, I will simplify here and adapt for my Smart Home
https://devblogs.microsoft.com/dotnet/build-a-model-context-protocol-mcp-server-in-csharp/
Create a .NET app:
dotnet new console -n SmartHomeMCPServerdotnet add package ModelContextProtocoldotnet add package Microsoft.Extensions.Logging.Consoledotnet add package Microsoft.Extensions.Hosting- 
dotnet add package RestEase(http client helper https://github.com/canton7/RestEase) 
I am using a Hubitat with an API plugin https://hubitat.com/.
This is what the API plugin shows me:
I used Copilot edit mode to generate my app after feeding in the API spec above. I also fed it the RestEase docs which is just the entire README.md. This is the HTTP client it generated with RestEase:
public interface IHubitatApi
{
    [Get("apps/api/60/devices/all")]
    Task<List<Device>> GetAllDevicesAsync([Query("access_token")] string accessToken);
    [Get("apps/api/60/devices/{deviceId}/{command}/{secondaryValue}")]
    Task SendDeviceCommandAsync(
        [Path("deviceId")] string deviceId,
        [Path("command")] string command,
        [Path("secondaryValue")] string secondaryValue,
        [Query("access_token")] string accessToken
    );
    [Get("apps/api/60/devices/{deviceId}/{command}")]
    Task SendDeviceCommandAsync(
        [Path("deviceId")] string deviceId,
        [Path("command")] string command,
        [Query("access_token")] string accessToken
    );
}
public class Device
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Label { get; set; }
    public string Type { get; set; }
    public string Room { get; set; }
    public string Date { get; set; }
    public string Model { get; set; }
    public string Manufacturer { get; set; }
    public List<string> Capabilities { get; set; }
    public Attributes Attributes { get; set; }
    public List<Command> Commands { get; set; }
}
// ...
After that, I wrapped the client around an MCP server:
[McpServerToolType]
public static class HubitatTool
{
    [McpServerTool, Description("Fetches all devices from the Hubitat API.")]
    public static async Task<List<Device>> GetAllDevices()
    {
        const string baseUrl = "http://192.168.1.120";
        const string accessToken = "YOUR-TOKEN";
        var api = RestClient.For<IHubitatApi>(baseUrl);
        return await api.GetAllDevicesAsync(accessToken);
    }
    [McpServerTool, Description("Send a command to a specific device.")]
    public static async Task SendDeviceCommand(string deviceId, string command, string secondaryValue = null)
    {
        const string baseUrl = "http://192.168.1.120";
        const string accessToken = "YOUR-TOKEN";
        var api = RestClient.For<IHubitatApi>(baseUrl);
        // Ensure secondaryValue is handled properly
        if (string.IsNullOrWhiteSpace(secondaryValue))
        {
            await api.SendDeviceCommandAsync(deviceId, command, accessToken);
        }
        else
        {
            await api.SendDeviceCommandAsync(deviceId, command, secondaryValue.Trim(), accessToken);
        }
    }
}
I "vibe coded" the above, in a real world scenario id have a .env file for tokens and URLs.
Finally, you can ask the LLM to list your devices!
              

    
Top comments (0)