Skip to content

Commit 3d90ae9

Browse files
authored
Adding Model Ccntrol Protocol (MCP) sample (#424)
1 parent 3acea9c commit 3d90ae9

File tree

11 files changed

+464
-2
lines changed

11 files changed

+464
-2
lines changed

device-listing/Configuration.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
"Name": "device",
99
"Description": "Gpio, I2C, I2S, Spi, Pwm, Adc, Dac, 1-Wire, Serial"
1010
},
11-
1211
{
1312
"Name": "amqp",
1413
"Description": "AMQP"
@@ -57,6 +56,10 @@
5756
"Name": "json",
5857
"Description": "Json"
5958
},
59+
{
60+
"Name": "mcp",
61+
"Description": "Model Context Protocol (MCP)"
62+
},
6063
{
6164
"Name": "mqtt",
6265
"Description": "MQTT"

samples/MQTT/category.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
mqtt
2-
networking
2+
networking

samples/McpAi/Light.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Device.Gpio;
6+
using System.Diagnostics;
7+
using nanoFramework.WebServer.Mcp;
8+
9+
namespace McpAi
10+
{
11+
public static class Light
12+
{
13+
private static GpioPin _lightPin;
14+
private static string _location = "kitchen";
15+
16+
public static void Initialize()
17+
{
18+
_lightPin = new GpioController().OpenPin(8, PinMode.Output);
19+
// Ensure the light is off initially
20+
_lightPin.Write(PinValue.High);
21+
}
22+
23+
[McpServerTool("turn_on", "Turn on the light. Check the location to make sure it's the proper location first. Do not change location of this light to turn it on.")]
24+
public static void TurnOn()
25+
{
26+
if (_lightPin == null)
27+
{
28+
Initialize();
29+
}
30+
31+
Debug.WriteLine($"Turning on the light at location: {_location}");
32+
_lightPin.Write(PinValue.Low);
33+
}
34+
35+
[McpServerTool("turn_off", "Turn off the light. Check the location to make sure it's the proper location first. Do not change location of this light to turn it off.")]
36+
public static void TurnOff()
37+
{
38+
if (_lightPin == null)
39+
{
40+
Initialize();
41+
}
42+
43+
Debug.WriteLine($"Turning off the light at location: {_location}");
44+
_lightPin.Write(PinValue.High);
45+
}
46+
47+
[McpServerTool("get_location", "Get the location of the light. Check this before switching a light on or off.")]
48+
public static string GetLocation()
49+
{
50+
Debug.WriteLine($"Getting the location of the light: {_location}");
51+
return _location;
52+
}
53+
54+
[McpServerTool("set_location", "Change the location of the light. Do not change the location of the light unless the user ask you to change the location.")]
55+
public static void SetLocation(string location)
56+
{
57+
if (string.IsNullOrEmpty(location))
58+
{
59+
throw new ArgumentException("Location cannot be null or empty.", nameof(location));
60+
}
61+
62+
Debug.WriteLine($"Setting the location of the light to: {location}");
63+
_location = location;
64+
}
65+
}
66+
}

samples/McpAi/McpAi.nfproj

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup Label="Globals">
4+
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
5+
</PropertyGroup>
6+
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
7+
<PropertyGroup>
8+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
9+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
10+
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
11+
<ProjectGuid>75022ce1-3597-477c-a4a0-cdcd06ec5e54</ProjectGuid>
12+
<OutputType>Exe</OutputType>
13+
<AppDesignerFolder>Properties</AppDesignerFolder>
14+
<FileAlignment>512</FileAlignment>
15+
<RootNamespace>McpAi</RootNamespace>
16+
<AssemblyName>McpAi</AssemblyName>
17+
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
18+
</PropertyGroup>
19+
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
20+
<ItemGroup>
21+
<Compile Include="Light.cs" />
22+
<Compile Include="Program.cs" />
23+
<Compile Include="Properties\AssemblyInfo.cs" />
24+
<Compile Include="WiFi.cs" />
25+
</ItemGroup>
26+
<ItemGroup>
27+
<Reference Include="mscorlib">
28+
<HintPath>packages\nanoFramework.CoreLibrary.1.17.11\lib\mscorlib.dll</HintPath>
29+
</Reference>
30+
<Reference Include="nanoFramework.Json">
31+
<HintPath>packages\nanoFramework.Json.2.2.199\lib\nanoFramework.Json.dll</HintPath>
32+
</Reference>
33+
<Reference Include="nanoFramework.Runtime.Events">
34+
<HintPath>packages\nanoFramework.Runtime.Events.1.11.32\lib\nanoFramework.Runtime.Events.dll</HintPath>
35+
</Reference>
36+
<Reference Include="nanoFramework.System.Collections">
37+
<HintPath>packages\nanoFramework.System.Collections.1.5.67\lib\nanoFramework.System.Collections.dll</HintPath>
38+
</Reference>
39+
<Reference Include="nanoFramework.System.Text">
40+
<HintPath>packages\nanoFramework.System.Text.1.3.42\lib\nanoFramework.System.Text.dll</HintPath>
41+
</Reference>
42+
<Reference Include="nanoFramework.WebServer">
43+
<HintPath>packages\nanoFramework.WebServer.Mcp.1.2.123\lib\nanoFramework.WebServer.dll</HintPath>
44+
</Reference>
45+
<Reference Include="nanoFramework.WebServer.Mcp">
46+
<HintPath>packages\nanoFramework.WebServer.Mcp.1.2.123\lib\nanoFramework.WebServer.Mcp.dll</HintPath>
47+
</Reference>
48+
<Reference Include="System.Device.Gpio">
49+
<HintPath>packages\nanoFramework.System.Device.Gpio.1.1.57\lib\System.Device.Gpio.dll</HintPath>
50+
</Reference>
51+
<Reference Include="System.Device.Wifi">
52+
<HintPath>packages\nanoFramework.System.Device.Wifi.1.5.133\lib\System.Device.Wifi.dll</HintPath>
53+
</Reference>
54+
<Reference Include="System.IO.Streams">
55+
<HintPath>packages\nanoFramework.System.IO.Streams.1.1.96\lib\System.IO.Streams.dll</HintPath>
56+
</Reference>
57+
<Reference Include="System.Net">
58+
<HintPath>packages\nanoFramework.System.Net.1.11.43\lib\System.Net.dll</HintPath>
59+
</Reference>
60+
<Reference Include="System.Net.Http">
61+
<HintPath>packages\nanoFramework.System.Net.Http.Server.1.5.196\lib\System.Net.Http.dll</HintPath>
62+
</Reference>
63+
<Reference Include="System.Threading">
64+
<HintPath>packages\nanoFramework.System.Threading.1.1.52\lib\System.Threading.dll</HintPath>
65+
</Reference>
66+
</ItemGroup>
67+
<ItemGroup>
68+
<None Include="packages.config" />
69+
</ItemGroup>
70+
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
71+
<ProjectExtensions>
72+
<ProjectCapabilities>
73+
<ProjectConfigurationsDeclaredAsItems />
74+
</ProjectCapabilities>
75+
</ProjectExtensions>
76+
</Project>

samples/McpAi/McpAi.sln

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.14.36212.18 d17.14
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "McpAi", "McpAi.nfproj", "{75022CE1-3597-477C-A4A0-CDCD06EC5E54}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{75022CE1-3597-477C-A4A0-CDCD06EC5E54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{75022CE1-3597-477C-A4A0-CDCD06EC5E54}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{75022CE1-3597-477C-A4A0-CDCD06EC5E54}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
17+
{75022CE1-3597-477C-A4A0-CDCD06EC5E54}.Release|Any CPU.ActiveCfg = Release|Any CPU
18+
{75022CE1-3597-477C-A4A0-CDCD06EC5E54}.Release|Any CPU.Build.0 = Release|Any CPU
19+
{75022CE1-3597-477C-A4A0-CDCD06EC5E54}.Release|Any CPU.Deploy.0 = Release|Any CPU
20+
EndGlobalSection
21+
GlobalSection(SolutionProperties) = preSolution
22+
HideSolutionNode = FALSE
23+
EndGlobalSection
24+
GlobalSection(ExtensibilityGlobals) = postSolution
25+
SolutionGuid = {BFF956C2-216C-479F-B12A-1C423A0B080B}
26+
EndGlobalSection
27+
EndGlobal

samples/McpAi/Program.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.Threading;
7+
using McpAi;
8+
using nanoFramework.Networking;
9+
using nanoFramework.WebServer;
10+
using nanoFramework.WebServer.Mcp;
11+
12+
13+
// Connect to WiFi (device-specific code)
14+
var connected = WifiNetworkHelper.ConnectDhcp(WiFi.Ssid, WiFi.Password, requiresDateTime: true, token: new CancellationTokenSource(60_000).Token);
15+
if (!connected)
16+
{
17+
Debug.WriteLine("Failed to connect to WiFi");
18+
return;
19+
}
20+
21+
// Step 1: Discover and register MCP tools
22+
McpToolRegistry.DiscoverTools(new Type[] { typeof(Light) });
23+
Debug.WriteLine("MCP Tools discovered and registered.");
24+
25+
// Step 2: Start WebServer with MCP controller
26+
// You can add more types if you also want to use it as a Web Server
27+
// Note: HTTPS and certs are also supported, see the pervious sections
28+
using (var server = new WebServer(80, HttpProtocol.Http, new Type[] { typeof(McpServerController) }))
29+
{ // Optional: Customize MCP server information and instructions
30+
// This will override the default server name "nanoFramework" and version "1.0.0"
31+
McpServerController.ServerName = "MyIoTDevice";
32+
McpServerController.ServerVersion = "2.1.0";
33+
34+
// Optional: Customize instructions sent to AI agents
35+
// This will override the default instruction about single request limitation
36+
McpServerController.Instructions = "This is my custom IoT device. Please send requests one at a time and wait for responses. Supports GPIO control and sensor readings.";
37+
38+
server.Start();
39+
Thread.Sleep(Timeout.Infinite);
40+
}
41+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Reflection;
5+
using System.Runtime.CompilerServices;
6+
using System.Runtime.InteropServices;
7+
8+
// General Information about an assembly is controlled through the following
9+
// set of attributes. Change these attribute values to modify the information
10+
// associated with an assembly.
11+
[assembly: AssemblyTitle("MCP AI Sample Application")]
12+
[assembly: AssemblyDescription("")]
13+
[assembly: AssemblyConfiguration("")]
14+
[assembly: AssemblyCompany("")]
15+
[assembly: AssemblyProduct("McpAiSample")]
16+
[assembly: AssemblyCopyright("Copyright © 2025")]
17+
[assembly: AssemblyTrademark("")]
18+
[assembly: AssemblyCulture("")]
19+
20+
// Setting ComVisible to false makes the types in this assembly not visible
21+
// to COM components. If you need to access a type in this assembly from
22+
// COM, set the ComVisible attribute to true on that type.
23+
[assembly: ComVisible(false)]

0 commit comments

Comments
 (0)