Skip to content

Commit 4750aac

Browse files
Merge pull request #57 from wisedev-code/feat/mcp-integration
Feat/mcp integration
2 parents bbf23e6 + c03a999 commit 4750aac

File tree

28 files changed

+434
-59
lines changed

28 files changed

+434
-59
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Examples.Utils;
2+
using MaIN.Core.Hub;
3+
using MaIN.Core.Hub.Utils;
4+
using MaIN.Domain.Configuration;
5+
using MaIN.Domain.Entities;
6+
7+
namespace Examples;
8+
9+
public class McpAgentsExample : IExample
10+
{
11+
public async Task Start()
12+
{
13+
Console.WriteLine("McpClientExample is running!");
14+
15+
AIHub.Extensions.DisableLLamaLogs();
16+
var contextSecond = await AIHub.Agent()
17+
.WithModel("qwq:7b")
18+
.WithInitialPrompt("Your main role is to provide opinions about facts that you are given in a conversation.")
19+
.CreateAsync(interactiveResponse: true);
20+
21+
var context = await AIHub.Agent()
22+
.WithBackend(BackendType.OpenAi)
23+
.WithMcpConfig(new Mcp
24+
{
25+
Name = "GitHub",
26+
Arguments = ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"],
27+
EnvironmentVariables = new Dictionary<string, string>()
28+
{
29+
{"GITHUB_PERSONAL_ACCESS_TOKEN", "<YOUR_GITHUB_TOKEN>"}
30+
},
31+
Command = "docker",
32+
Model = "gpt-4o-mini"
33+
})
34+
.WithModel("gpt-4o-mini")
35+
.WithSteps(StepBuilder.Instance
36+
.Mcp()
37+
.Redirect(agentId: contextSecond.GetAgentId())
38+
.Build())
39+
.CreateAsync();
40+
41+
await context.ProcessAsync("What are recently added features in https://github.com/wisedev-code/MaIN.NET (based on recently closed issues)", translate: true);
42+
}
43+
}

Examples/Examples/Mcp/McpExample.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Examples.Utils;
2+
using MaIN.Core.Hub;
3+
using MaIN.Domain.Configuration;
4+
using MaIN.Domain.Entities;
5+
6+
namespace Examples;
7+
8+
public class McpExample : IExample
9+
{
10+
public async Task Start()
11+
{
12+
Console.WriteLine("McpClientExample is running!");
13+
OpenAiExample.Setup();
14+
15+
var result = await AIHub.Mcp()
16+
.WithBackend(BackendType.OpenAi)
17+
.WithConfig(
18+
new Mcp
19+
{
20+
Name = "McpEverythingDemo",
21+
Arguments = ["-y", "@modelcontextprotocol/server-everything"],
22+
Command = "npx",
23+
Model = "gpt-4o-mini"
24+
})
25+
.PromptAsync("Provide me information about resource 21 and 37. Also explain how you get this data");
26+
27+
Console.WriteLine(result.Message.Content);
28+
}
29+
}

Examples/Examples/Program.cs

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
static void RegisterExamples(IServiceCollection services)
4141
{
4242
services.AddTransient<ExampleRegistry>();
43+
services.AddTransient<McpExample>();
4344
services.AddTransient<ChatExample>();
4445
services.AddTransient<ChatWithFilesExample>();
4546
services.AddTransient<ChatWithFilesFromStreamExample>();
@@ -51,6 +52,7 @@ static void RegisterExamples(IServiceCollection services)
5152
services.AddTransient<AgentConversationExample>();
5253
services.AddTransient<AgentWithRedirectExample>();
5354
services.AddTransient<MultiBackendAgentWithRedirectExample>();
55+
services.AddTransient<McpAgentsExample>();
5456
services.AddTransient<AgentWithRedirectImageExample>();
5557
services.AddTransient<AgentWithBecomeExample>();
5658
services.AddTransient<AgentWithApiDataSourceExample>();
@@ -120,35 +122,36 @@ async Task RunSelectedExample(IServiceProvider serviceProvider)
120122

121123
public class ExampleRegistry(IServiceProvider serviceProvider)
122124
{
123-
private readonly IServiceProvider _serviceProvider = serviceProvider;
124-
125125
public List<(string Name, IExample Instance)> GetAvailableExamples()
126126
{
127127
return new List<(string, IExample)>
128128
{
129-
("\u25a0 Basic Chat", _serviceProvider.GetRequiredService<ChatExample>()),
130-
("\u25a0 Chat with Files", _serviceProvider.GetRequiredService<ChatWithFilesExample>()),
131-
("\u25a0 Chat with Files from stream", _serviceProvider.GetRequiredService<ChatWithFilesFromStreamExample>()),
132-
("\u25a0 Chat with Vision", _serviceProvider.GetRequiredService<ChatWithVisionExample>()),
133-
("\u25a0 Chat with Image Generation", _serviceProvider.GetRequiredService<ChatWithImageGenExample>()),
134-
("\u25a0 Chat from Existing", _serviceProvider.GetRequiredService<ChatFromExistingExample>()),
135-
("\u25a0 Chat with reasoning", _serviceProvider.GetRequiredService<ChatWithReasoningExample>()),
136-
("\u25a0 Basic Agent", _serviceProvider.GetRequiredService<AgentExample>()),
137-
("\u25a0 Conversation Agent", _serviceProvider.GetRequiredService<AgentConversationExample>()),
138-
("\u25a0 Agent with Redirect", _serviceProvider.GetRequiredService<AgentWithRedirectExample>()),
139-
("\u25a0 Agent with Redirect (Multi backends)", _serviceProvider.GetRequiredService<MultiBackendAgentWithRedirectExample>()),
140-
("\u25a0 Agent with Redirect Image", _serviceProvider.GetRequiredService<AgentWithRedirectImageExample>()),
141-
("\u25a0 Agent with Become", _serviceProvider.GetRequiredService<AgentWithBecomeExample>()),
142-
("\u25a0 Agent with API Data Source", _serviceProvider.GetRequiredService<AgentWithApiDataSourceExample>()),
143-
("\u25a0 Agents Talking to Each Other", _serviceProvider.GetRequiredService<AgentTalkingToEachOtherExample>()),
144-
("\u25a0 Agents Composed as Flow", _serviceProvider.GetRequiredService<AgentsComposedAsFlowExample>()),
145-
("\u25a0 Agents Flow Loaded", _serviceProvider.GetRequiredService<AgentsFlowLoadedExample>()),
146-
("\u25a0 OpenAi Chat", _serviceProvider.GetRequiredService<ChatExampleOpenAi>()),
147-
("\u25a0 OpenAi Chat with image", _serviceProvider.GetRequiredService<ChatWithImageGenOpenAiExample>()),
148-
("\u25a0 OpenAi Agent with Web Data Source", _serviceProvider.GetRequiredService<AgentWithWebDataSourceOpenAiExample>()),
149-
("\u25a0 Gemini Chat", _serviceProvider.GetRequiredService<ChatExampleGemini>()),
150-
("\u25a0 Gemini Chat with image", _serviceProvider.GetRequiredService<ChatWithImageGenGeminiExample>()),
151-
("\u25a0 Gemini Chat with files", _serviceProvider.GetRequiredService<ChatWithFilesExampleGemini>()),
129+
("\u25a0 Basic Chat", serviceProvider.GetRequiredService<ChatExample>()),
130+
("\u25a0 Chat with Files", serviceProvider.GetRequiredService<ChatWithFilesExample>()),
131+
("\u25a0 Chat with Files from stream", serviceProvider.GetRequiredService<ChatWithFilesFromStreamExample>()),
132+
("\u25a0 Chat with Vision", serviceProvider.GetRequiredService<ChatWithVisionExample>()),
133+
("\u25a0 Chat with Image Generation", serviceProvider.GetRequiredService<ChatWithImageGenExample>()),
134+
("\u25a0 Chat from Existing", serviceProvider.GetRequiredService<ChatFromExistingExample>()),
135+
("\u25a0 Chat with reasoning", serviceProvider.GetRequiredService<ChatWithReasoningExample>()),
136+
("\u25a0 Basic Agent", serviceProvider.GetRequiredService<AgentExample>()),
137+
("\u25a0 Conversation Agent", serviceProvider.GetRequiredService<AgentConversationExample>()),
138+
("\u25a0 Agent with Redirect", serviceProvider.GetRequiredService<AgentWithRedirectExample>()),
139+
("\u25a0 Agent with Redirect (Multi backends)", serviceProvider.GetRequiredService<MultiBackendAgentWithRedirectExample>()),
140+
("\u25a0 Agent with Redirect Image", serviceProvider.GetRequiredService<AgentWithRedirectImageExample>()),
141+
("\u25a0 Agent with Become", serviceProvider.GetRequiredService<AgentWithBecomeExample>()),
142+
("\u25a0 Agent with API Data Source", serviceProvider.GetRequiredService<AgentWithApiDataSourceExample>()),
143+
("\u25a0 Agents Talking to Each Other", serviceProvider.GetRequiredService<AgentTalkingToEachOtherExample>()),
144+
("\u25a0 Agents Composed as Flow", serviceProvider.GetRequiredService<AgentsComposedAsFlowExample>()),
145+
("\u25a0 Agents Flow Loaded", serviceProvider.GetRequiredService<AgentsFlowLoadedExample>()),
146+
("\u25a0 OpenAi Chat", serviceProvider.GetRequiredService<ChatExampleOpenAi>()),
147+
("\u25a0 OpenAi Chat with image", serviceProvider.GetRequiredService<ChatWithImageGenOpenAiExample>()),
148+
("\u25a0 OpenAi Agent with Web Data Source", serviceProvider.GetRequiredService<AgentWithWebDataSourceOpenAiExample>()),
149+
("\u25a0 Gemini Chat", serviceProvider.GetRequiredService<ChatExampleGemini>()),
150+
("\u25a0 Gemini Chat with image", serviceProvider.GetRequiredService<ChatWithImageGenGeminiExample>()),
151+
("\u25a0 Gemini Chat with files", serviceProvider.GetRequiredService<ChatWithFilesExampleGemini>()),
152+
("\u25a0 McpClient example", serviceProvider.GetRequiredService<McpExample>()),
153+
("\u25a0 McpAgent example", serviceProvider.GetRequiredService<McpAgentsExample>())
154+
152155
};
153156
}
154157
}

Releases/0.2.3.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# 0.2.3 release
2+
3+
- Added Mcp integration
4+
- Include examples and documentation
5+
- McpContext for simple integration
6+
- MCP as AgentStep to allow advanced workflows

src/MaIN.Core/.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>MaIN.NET</id>
5-
<version>0.2.2</version>
5+
<version>0.2.3</version>
66
<authors>Wisedev</authors>
77
<owners>Wisedev</owners>
88
<icon>favicon.png</icon>

src/MaIN.Core/Bootstrapper.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,16 @@ public static IServiceCollection AddAIHub(this IServiceCollection services)
3434
services.AddSingleton<IChatService, ChatService>();
3535
services.AddSingleton<IAgentService, AgentService>();
3636
services.AddSingleton<IAgentFlowService, AgentFlowService>();
37-
37+
services.AddSingleton<IMcpService, McpService>();
38+
3839
// Register service provider for AIHub
3940
services.AddSingleton<IAIHubServices>(sp =>
4041
{
4142
var aiServices = new AIHubServices(
4243
sp.GetRequiredService<IChatService>(),
4344
sp.GetRequiredService<IAgentService>(),
44-
sp.GetRequiredService<IAgentFlowService>()
45+
sp.GetRequiredService<IAgentFlowService>(),
46+
sp.GetRequiredService<IMcpService>()
4547
);
4648

4749
// Initialize AIHub with the services

src/MaIN.Core/Hub/AiHub.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ internal static void Initialize(IAIHubServices services)
2222
public static ChatContext Chat() => new(Services.ChatService);
2323
public static AgentContext Agent() => new(Services.AgentService);
2424
public static FlowContext Flow() => new(Services.FlowService, Services.AgentService);
25+
public static McpContext Mcp() => new(Services.McpService);
2526

2627
public abstract class Extensions
2728
{

src/MaIN.Core/Hub/Contexts/AgentContext.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ public AgentContext WithModel(string model)
9292
return this;
9393
}
9494

95+
public AgentContext WithMcpConfig(Mcp mcpConfig)
96+
{
97+
if (_agent.Backend != null)
98+
{
99+
mcpConfig.Backend = _agent.Backend;
100+
}
101+
_agent.Context.McpConfig = mcpConfig;
102+
return this;
103+
}
104+
95105
public AgentContext WithInferenceParams(InferenceParams inferenceParams)
96106
{
97107
_inferenceParams = inferenceParams;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
using MaIN.Domain.Configuration;
3+
using MaIN.Domain.Entities;
4+
using MaIN.Services.Services;
5+
using MaIN.Services.Services.Abstract;
6+
using MaIN.Services.Services.Models;
7+
8+
namespace MaIN.Core.Hub.Contexts;
9+
10+
public class McpContext
11+
{
12+
private readonly IMcpService _mcpService;
13+
private Mcp? _mcpConfig;
14+
15+
internal McpContext(IMcpService mcpService)
16+
{
17+
_mcpService = mcpService;
18+
_mcpConfig = Mcp.NotSet;
19+
}
20+
21+
public McpContext WithConfig(Mcp mcpConfig)
22+
{
23+
_mcpConfig = mcpConfig;
24+
return this;
25+
}
26+
27+
public McpContext WithBackend(BackendType backendType)
28+
{
29+
_mcpConfig!.Backend = backendType;
30+
return this;
31+
}
32+
33+
public async Task<McpResult> PromptAsync(string prompt)
34+
{
35+
if (_mcpConfig == null)
36+
{
37+
throw new InvalidOperationException("MCP config not found");
38+
}
39+
40+
return await _mcpService.Prompt(_mcpConfig!, prompt);
41+
}
42+
}

src/MaIN.Core/Hub/Utils/StepBuilder.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ public StepBuilder FetchData(FetchResponseType fetchResponseType = FetchResponse
3131
Steps.Add(stepToAdd);
3232
return this;
3333
}
34+
35+
public StepBuilder Mcp()
36+
{
37+
var stepToAdd = "MCP";
38+
Steps.Add(stepToAdd);
39+
return this;
40+
}
3441

3542
public StepBuilder Redirect(string agentId, string output = "AS_Output", string mode = "REPLACE")
3643
{

src/MaIN.Core/Interfaces/IAIHubService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using MaIN.Services.Services;
12
using MaIN.Services.Services.Abstract;
23

34
namespace MaIN.Core.Interfaces;
@@ -7,4 +8,5 @@ public interface IAIHubServices
78
IChatService ChatService { get; }
89
IAgentService AgentService { get; }
910
IAgentFlowService FlowService { get; }
11+
IMcpService McpService { get; }
1012
}
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
using MaIN.Core.Interfaces;
2+
using MaIN.Services.Services;
23
using MaIN.Services.Services.Abstract;
34

45
namespace MaIN.Core.Services;
56

67
public class AIHubServices(
78
IChatService chatService,
89
IAgentService agentService,
9-
IAgentFlowService flowService)
10+
IAgentFlowService flowService,
11+
IMcpService mcpService)
1012
: IAIHubServices
1113
{
1214
public IChatService ChatService { get; } = chatService;
1315
public IAgentService AgentService { get; } = agentService;
1416
public IAgentFlowService FlowService { get; } = flowService;
17+
18+
public IMcpService McpService { get; } = mcpService;
1519
}

src/MaIN.Domain/Entities/Agents/AgentData.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ public class AgentData
44
{
55
public string? Instruction { get; set; }
66
public AgentSource.AgentSource? Source { get; set; }
7+
public Mcp? McpConfig { get; set; }
78
public List<string>? Steps { get; set; }
89
public List<string>? Relations { get; set; }
910

src/MaIN.Domain/Entities/Mcp.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using MaIN.Domain.Configuration;
2+
3+
namespace MaIN.Domain.Entities;
4+
5+
public class Mcp
6+
{
7+
public required string Name { get; init; }
8+
public required List<string> Arguments { get; init; }
9+
public required string Command { get; init; }
10+
public required string Model { get; init; }
11+
public Dictionary<string, string> Properties { get; set; } = [];
12+
public BackendType? Backend { get; set; }
13+
public Dictionary<string, string> EnvironmentVariables { get; set; } = [];
14+
15+
public static Mcp NotSet => new Mcp()
16+
{
17+
Arguments = [],
18+
Command = string.Empty,
19+
Model = string.Empty,
20+
Properties = new Dictionary<string, string>(),
21+
Name = string.Empty,
22+
Backend = BackendType.Self
23+
};
24+
}

src/MaIN.Infrastructure/Models/AgentContextDocument.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using MaIN.Domain.Entities;
12
using MaIN.Models.Rag;
23

34
namespace MaIN.Infrastructure.Models;
@@ -8,4 +9,5 @@ public class AgentContextDocument
89
public AgentSourceDocument? Source { get; init; }
910
public List<string>? Steps { get; init; }
1011
public List<string>? Relations { get; init; }
12+
public Mcp? McpConfig { get; set; }
1113
}

src/MaIN.Services/Bootstrapper.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public static IServiceCollection ConfigureMaIN(
4848
serviceCollection.AddSingleton<IStepHandler, RedirectStepHandler>();
4949
serviceCollection.AddSingleton<IStepHandler, FetchDataStepHandler>();
5050
serviceCollection.AddSingleton<IStepHandler, AnswerStepHandler>();
51+
serviceCollection.AddSingleton<IStepHandler, McpStepHandler>();
5152
serviceCollection.AddSingleton<IStepHandler, BecomeStepHandler>();
5253
serviceCollection.AddSingleton<IStepHandler, CleanupStepHandler>();
5354
serviceCollection.AddCommandHandlers();
@@ -72,11 +73,13 @@ private static IServiceCollection AddCommandHandlers(this IServiceCollection ser
7273
services.AddSingleton<ICommandHandler<RedirectCommand, Message?>, RedirectCommandHandler>();
7374
services.AddSingleton<ICommandHandler<FetchCommand, Message?>, FetchCommandHandler>();
7475
services.AddSingleton<ICommandHandler<AnswerCommand, Message?>, AnswerCommandHandler>();
76+
services.AddSingleton<ICommandHandler<McpCommand, Message?>, McpCommandHandler>();
7577

7678
services.AddSingleton<ICommandDispatcher, CommandDispatcher>(provider =>
7779
{
7880
var dispatcher = new CommandDispatcher(provider);
7981

82+
dispatcher.RegisterNamedHandler<McpCommand, Message?, McpCommandHandler>("MCP");
8083
dispatcher.RegisterNamedHandler<StartCommand, Message?, StartCommandHandler>("START");
8184
dispatcher.RegisterNamedHandler<RedirectCommand, Message?, RedirectCommandHandler>("REDIRECT");
8285
dispatcher.RegisterNamedHandler<FetchCommand, Message?, FetchCommandHandler>("FETCH_DATA");
@@ -90,6 +93,7 @@ private static IServiceCollection AddCommandHandlers(this IServiceCollection ser
9093
services.AddSingleton<RedirectCommandHandler>();
9194
services.AddSingleton<FetchCommandHandler>();
9295
services.AddSingleton<AnswerCommandHandler>();
96+
services.AddSingleton<McpCommandHandler>();
9397

9498
return services;
9599
}

src/MaIN.Services/MaIN.Services.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.3" />
2222
<PackageReference Include="Microsoft.KernelMemory" Version="0.98.250324.1" />
2323
<PackageReference Include="Microsoft.SemanticKernel" Version="1.49.0" />
24-
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Google" Version="1.48.0-alpha" />
24+
<PackageReference Include="Microsoft.SemanticKernel.Connectors.Google" Version="1.33.0-alpha" />
25+
<PackageReference Include="ModelContextProtocol.AspNetCore" Version="0.2.0-preview.1" />
2526
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
2627
<PackageReference Include="Tesseract" Version="5.2.0" />
2728
<PackageReference Include="Tesseract.Data.English" Version="4.0.0" />

0 commit comments

Comments
 (0)