Skip to content

Commit 2bb73b9

Browse files
authored
Merge pull request #961 from Chris0Jeky/fix/debt-05-mcp-di-deduplication
Deduplicate MCP mode DI registration in Program.cs
2 parents 95e43d4 + 14c54cd commit 2bb73b9

3 files changed

Lines changed: 77 additions & 60 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Taskdeck.Application.Interfaces;
2+
using Taskdeck.Application.Services;
3+
4+
namespace Taskdeck.Api.Extensions;
5+
6+
/// <summary>
7+
/// Registers the minimal subset of Application services required by MCP
8+
/// resources and tools. Both MCP stdio and MCP HTTP standalone modes call
9+
/// this instead of the full <see cref="ApplicationServiceRegistration.AddApplicationServices"/>
10+
/// which includes web-only services (SignalR notifiers, workers, LLM providers, etc.).
11+
/// </summary>
12+
public static class McpApplicationServiceRegistration
13+
{
14+
/// <summary>
15+
/// Register the Application services that MCP resources and tools depend on.
16+
/// Deliberately skips web-only services (SignalR notifiers, workers,
17+
/// LLM providers, rate limiting, etc.) to keep the MCP host minimal.
18+
/// </summary>
19+
public static IServiceCollection AddMcpApplicationServices(this IServiceCollection services)
20+
{
21+
services.AddScoped<AuthorizationService>();
22+
services.AddScoped<IAuthorizationService>(
23+
sp => sp.GetRequiredService<AuthorizationService>());
24+
services.AddScoped<BoardService>(sp =>
25+
new BoardService(
26+
sp.GetRequiredService<IUnitOfWork>(),
27+
sp.GetRequiredService<IAuthorizationService>()));
28+
services.AddScoped<ColumnService>();
29+
services.AddScoped<CardService>();
30+
services.AddScoped<LabelService>();
31+
services.AddScoped<AutomationProposalService>();
32+
services.AddScoped<IAutomationProposalService>(
33+
sp => sp.GetRequiredService<AutomationProposalService>());
34+
services.AddScoped<CaptureService>();
35+
services.AddScoped<ICaptureService>(
36+
sp => sp.GetRequiredService<CaptureService>());
37+
services.AddScoped<NotificationService>();
38+
services.AddScoped<INotificationService>(
39+
sp => sp.GetRequiredService<NotificationService>());
40+
41+
return services;
42+
}
43+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using ModelContextProtocol.AspNetCore;
2+
using ModelContextProtocol.Server;
3+
using Taskdeck.Api.Mcp;
4+
5+
namespace Taskdeck.Api.Extensions;
6+
7+
/// <summary>
8+
/// Registers the shared set of MCP resources and tools used by all three
9+
/// hosting modes (co-hosted web, standalone HTTP, and stdio).
10+
/// </summary>
11+
public static class McpResourcesAndToolsRegistration
12+
{
13+
/// <summary>
14+
/// Add MCP resources (Board, Capture, Proposal) and tools (Read, Write, Proposal)
15+
/// to the given MCP server builder.
16+
/// </summary>
17+
public static IMcpServerBuilder AddMcpResourcesAndTools(this IMcpServerBuilder builder)
18+
{
19+
return builder
20+
.WithResources<BoardResources>()
21+
.WithResources<CaptureResources>()
22+
.WithResources<ProposalResources>()
23+
.WithTools<ReadTools>()
24+
.WithTools<WriteTools>()
25+
.WithTools<ProposalTools>();
26+
}
27+
}

backend/src/Taskdeck.Api/Program.cs

Lines changed: 7 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -69,26 +69,8 @@
6969
// Infrastructure (DbContext, Repositories, UoW)
7070
mcpHttpBuilder.Services.AddInfrastructure(mcpHttpBuilder.Configuration);
7171

72-
// Register Application services needed by MCP resources and tools.
73-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.AuthorizationService>();
74-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.IAuthorizationService>(
75-
sp => sp.GetRequiredService<Taskdeck.Application.Services.AuthorizationService>());
76-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.BoardService>(sp =>
77-
new Taskdeck.Application.Services.BoardService(
78-
sp.GetRequiredService<IUnitOfWork>(),
79-
sp.GetRequiredService<Taskdeck.Application.Services.IAuthorizationService>()));
80-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.ColumnService>();
81-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.CardService>();
82-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.LabelService>();
83-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.AutomationProposalService>();
84-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.IAutomationProposalService>(
85-
sp => sp.GetRequiredService<Taskdeck.Application.Services.AutomationProposalService>());
86-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.CaptureService>();
87-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.ICaptureService>(
88-
sp => sp.GetRequiredService<Taskdeck.Application.Services.CaptureService>());
89-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.NotificationService>();
90-
mcpHttpBuilder.Services.AddScoped<Taskdeck.Application.Services.INotificationService>(
91-
sp => sp.GetRequiredService<Taskdeck.Application.Services.NotificationService>());
72+
// Application services needed by MCP resources and tools (shared with stdio mode).
73+
mcpHttpBuilder.Services.AddMcpApplicationServices();
9274

9375
// HTTP identity: maps API key to user via HttpUserContextProvider.
9476
mcpHttpBuilder.Services.AddHttpContextAccessor();
@@ -119,12 +101,7 @@
119101
// MCP server: HTTP transport + all resources and tools.
120102
mcpHttpBuilder.Services.AddMcpServer()
121103
.WithHttpTransport()
122-
.WithResources<BoardResources>()
123-
.WithResources<CaptureResources>()
124-
.WithResources<ProposalResources>()
125-
.WithTools<ReadTools>()
126-
.WithTools<WriteTools>()
127-
.WithTools<ProposalTools>();
104+
.AddMcpResourcesAndTools();
128105

129106
var mcpHttpApp = mcpHttpBuilder.Build();
130107

@@ -189,28 +166,8 @@
189166
// Infrastructure (DbContext, Repositories, UoW)
190167
services.AddInfrastructure(ctx.Configuration);
191168

192-
// Register Application services needed by MCP resources and tools.
193-
// We deliberately skip web-only services (SignalR notifiers, workers,
194-
// LLM providers, rate limiting, etc.) to keep the MCP host minimal.
195-
services.AddScoped<Taskdeck.Application.Services.AuthorizationService>();
196-
services.AddScoped<Taskdeck.Application.Services.IAuthorizationService>(
197-
sp => sp.GetRequiredService<Taskdeck.Application.Services.AuthorizationService>());
198-
services.AddScoped<Taskdeck.Application.Services.BoardService>(sp =>
199-
new Taskdeck.Application.Services.BoardService(
200-
sp.GetRequiredService<IUnitOfWork>(),
201-
sp.GetRequiredService<Taskdeck.Application.Services.IAuthorizationService>()));
202-
services.AddScoped<Taskdeck.Application.Services.ColumnService>();
203-
services.AddScoped<Taskdeck.Application.Services.CardService>();
204-
services.AddScoped<Taskdeck.Application.Services.LabelService>();
205-
services.AddScoped<Taskdeck.Application.Services.AutomationProposalService>();
206-
services.AddScoped<Taskdeck.Application.Services.IAutomationProposalService>(
207-
sp => sp.GetRequiredService<Taskdeck.Application.Services.AutomationProposalService>());
208-
services.AddScoped<Taskdeck.Application.Services.CaptureService>();
209-
services.AddScoped<Taskdeck.Application.Services.ICaptureService>(
210-
sp => sp.GetRequiredService<Taskdeck.Application.Services.CaptureService>());
211-
services.AddScoped<Taskdeck.Application.Services.NotificationService>();
212-
services.AddScoped<Taskdeck.Application.Services.INotificationService>(
213-
sp => sp.GetRequiredService<Taskdeck.Application.Services.NotificationService>());
169+
// Application services needed by MCP resources and tools (shared with HTTP mode).
170+
services.AddMcpApplicationServices();
214171

215172
// Stdio identity: maps the OS process owner to the local default user.
216173
services.AddScoped<IUserContextProvider, StdioUserContextProvider>();
@@ -221,12 +178,7 @@
221178
// MCP server: stdio transport + all resources and tools.
222179
services.AddMcpServer()
223180
.WithStdioServerTransport()
224-
.WithResources<BoardResources>()
225-
.WithResources<CaptureResources>()
226-
.WithResources<ProposalResources>()
227-
.WithTools<ReadTools>()
228-
.WithTools<WriteTools>()
229-
.WithTools<ProposalTools>();
181+
.AddMcpResourcesAndTools();
230182
})
231183
.Build();
232184

@@ -357,12 +309,7 @@
357309
builder.Services.AddMcpTelemetry();
358310
builder.Services.AddMcpServer()
359311
.WithHttpTransport()
360-
.WithResources<BoardResources>()
361-
.WithResources<CaptureResources>()
362-
.WithResources<ProposalResources>()
363-
.WithTools<ReadTools>()
364-
.WithTools<WriteTools>()
365-
.WithTools<ProposalTools>();
312+
.AddMcpResourcesAndTools();
366313

367314
// Add JWT Authentication (with optional GitHub OAuth and OIDC providers, circuit-breaker-protected backchannel)
368315
// CircuitBreakerStateTracker is already registered as a singleton by AddLlmProviders above.

0 commit comments

Comments
 (0)