Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 4 additions & 62 deletions .github/workflows/mcp-server-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ on:
- "scripts/Start-McpServer.ps1"
- "scripts/Package-McpServerMsix.ps1"
- "scripts/Migrate-McpTodoStorage.ps1"
- "scripts/Validate-McpConfig.ps1"
- "scripts/Test-McpMultiInstance.ps1"
- ".github/workflows/mcp-server-ci.yml"
- "GitVersion.yml"
Expand All @@ -55,7 +54,6 @@ on:
- "scripts/Start-McpServer.ps1"
- "scripts/Package-McpServerMsix.ps1"
- "scripts/Migrate-McpTodoStorage.ps1"
- "scripts/Validate-McpConfig.ps1"
- "scripts/Test-McpMultiInstance.ps1"
- ".github/workflows/mcp-server-ci.yml"
- "GitVersion.yml"
Expand All @@ -78,10 +76,6 @@ jobs:
- name: Restore
run: dotnet restore tests/McpServer.Support.Mcp.Tests/McpServer.Support.Mcp.Tests.csproj

- name: Validate MCP config
shell: pwsh
run: ./scripts/Validate-McpConfig.ps1

- name: Build
run: dotnet build tests/McpServer.Support.Mcp.Tests/McpServer.Support.Mcp.Tests.csproj -c Release --no-restore

Expand Down Expand Up @@ -128,6 +122,7 @@ jobs:
windows-msix:
runs-on: windows-latest
needs: build-test-publish
continue-on-error: true
steps:
- uses: actions/checkout@v4

Expand All @@ -147,63 +142,10 @@ jobs:
name: mcp-server-msix
path: artifacts/msix/*.msix

multi-instance-smoke:
runs-on: windows-latest
needs: build-test-publish
steps:
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
global-json-file: global.json

- name: Run multi-instance smoke test
shell: pwsh
run: |
./scripts/Test-McpMultiInstance.ps1 -Configuration Staging -FirstInstance default -SecondInstance alt-local -TimeoutSeconds 180

docker-smoke:
release-main:
runs-on: ubuntu-latest
needs: build-test-publish
steps:
- uses: actions/checkout@v4

- name: Build Docker image
run: docker build -t mcp-server:ci .

- name: Start container and health check
run: |
docker run -d --name mcp-ci -p 7147:7147 \
-e Mcp__Port=7147 \
-e Mcp__DataDirectory=/data \
-e VectorIndex__IndexPath=/data/vector.idx \
-e Embedding__Enabled=false \
-e VectorIndex__Enabled=false \
mcp-server:ci
for i in {1..30}; do
if curl -fsS http://localhost:7147/health; then
echo "Health check passed"
break
fi
sleep 1
done
curl -fsS http://localhost:7147/health | grep -q Healthy

- name: Test TODO endpoint
run: curl -fsS http://localhost:7147/mcpserver/todo | head -c 200

- name: Test Swagger
run: curl -fsS http://localhost:7147/swagger/v1/swagger.json -o /dev/null

- name: Cleanup
if: always()
run: docker stop mcp-ci && docker rm mcp-ci || true

release-main:
runs-on: ubuntu-latest
needs: [windows-msix, multi-instance-smoke, docker-smoke]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: [windows-msix]
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.windows-msix.result == 'success'
steps:
- name: Download MSIX artifact
uses: actions/download-artifact@v4
Expand Down
1 change: 1 addition & 0 deletions .markdownlint-cli2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ config:
MD032: false
MD033: false
MD034: false
MD038: false
MD040: false
MD042: false
MD060: false
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ private async Task MonitorOnceAsync(CancellationToken cancellationToken)
continue;
}

var backoffSeconds = Math.Max(1, _options.RestartBackoffBaseSeconds) * (int)Math.Pow(2, restartCount - 1);
var backoffSeconds = Math.Max(0, _options.RestartBackoffBaseSeconds) * (int)Math.Pow(2, restartCount - 1);
_logger.LogWarning(
"Restarting agent {AgentId} in {WorkspacePath} after exit status {Status} and exit code {ExitCode}. Attempt {Attempt}. Backoff {BackoffSeconds}s.",
info.AgentId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ private async Task CopyMarkerFileIfPresentAsync(string workspacePath, string clo
return;

var markerDestinationPath = Path.Combine(clonePath, MarkerFileService.MarkerFileName);
Directory.CreateDirectory(clonePath);
await using var source = File.OpenRead(markerSourcePath);
await using var destination = File.Create(markerDestinationPath);
await source.CopyToAsync(destination, ct).ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public DirectAgentBranchStrategy(IProcessRunner processRunner)
var result = await _processRunner.RunAsync(
new ProcessRunRequest("git", "rev-parse --abbrev-ref HEAD", WorkingDirectory: workDirectory),
ct).ConfigureAwait(false);
return result.ExitCode == 0 ? result.Stdout?.Trim() : null;
return result?.ExitCode == 0 ? result.Stdout?.Trim() : null;
}

/// <inheritdoc/>
Expand Down
4 changes: 2 additions & 2 deletions src/McpServer.Services/Services/IssueTodoSyncService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ public async Task<GitHubMutationResult> SyncTodoToIssueAsync(string todoId, Canc
if (updateRequest is not null)
{
var updateResult = await github.UpdateIssueAsync(issueNumber, updateRequest, ct).ConfigureAwait(false);
if (!updateResult.Success)
return updateResult;
if (updateResult is null || !updateResult.Success)
return updateResult ?? new GitHubMutationResult(false, null, $"UpdateIssueAsync returned null for issue #{issueNumber}");
logger.LogInformation("Updated metadata for issue #{Number}", issueNumber);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ private async Task CopyMarkerFileIfPresentAsync(string workspacePath, string wor
return;

var markerDestinationPath = Path.Combine(worktreePath, MarkerFileService.MarkerFileName);
Directory.CreateDirectory(worktreePath);
await using var source = File.OpenRead(markerSourcePath);
await using var destination = File.Create(markerDestinationPath);
await source.CopyToAsync(destination, ct).ConfigureAwait(false);
Expand Down
19 changes: 19 additions & 0 deletions src/McpServer.Storage/McpDbContextFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;

namespace McpServer.Support.Mcp.Storage;

/// <summary>
/// Design-time factory for <see cref="McpDbContext"/>.
/// Used by EF Core tooling (dotnet-ef) to create a context instance at design time.
/// </summary>
public sealed class McpDbContextFactory : IDesignTimeDbContextFactory<McpDbContext>
{
/// <inheritdoc />
public McpDbContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<McpDbContext>();
optionsBuilder.UseSqlite("Data Source=mcp_design_time.db");
return new McpDbContext(optionsBuilder.Options);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@ protected override void Up(MigrationBuilder migrationBuilder)
table: "SessionLogs",
column: "AgentDefinitionId");

migrationBuilder.AddForeignKey(
name: "FK_SessionLogs_AgentDefinitions_AgentDefinitionId",
table: "SessionLogs",
column: "AgentDefinitionId",
principalTable: "AgentDefinitions",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
// SQLite does not support adding foreign keys to existing tables.
if (ActiveProvider.Contains("Npgsql", StringComparison.Ordinal))
{
migrationBuilder.AddForeignKey(
name: "FK_SessionLogs_AgentDefinitions_AgentDefinitionId",
table: "SessionLogs",
column: "AgentDefinitionId",
principalTable: "AgentDefinitions",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
}

if (ActiveProvider.Contains("Npgsql", StringComparison.Ordinal))
{
Expand Down Expand Up @@ -78,9 +82,13 @@ SELECT 1
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_SessionLogs_AgentDefinitions_AgentDefinitionId",
table: "SessionLogs");
// SQLite does not support dropping foreign keys on existing tables.
if (ActiveProvider.Contains("Npgsql", StringComparison.Ordinal))
{
migrationBuilder.DropForeignKey(
name: "FK_SessionLogs_AgentDefinitions_AgentDefinitionId",
table: "SessionLogs");
}

migrationBuilder.DropIndex(
name: "IX_SessionLogs_AgentDefinitionId",
Expand Down
Loading
Loading