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
26 changes: 26 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"permissions": {
"allow": [
"Bash(git add:*)",
"Bash(gh run list:*)",
"Bash(gh run view:*)",
"Bash(cargo fmt:*)",
"mcp__fetch__imageFetch",
"mcp__sequential-thinking__sequentialthinking",
"Bash(gh project view:*)",
"Bash(gh issue create:*)",
"Bash(gh project item-add:*)",
"Bash(gh project item-list:*)",
"Bash(cargo clippy:*)",
"WebFetch(domain:modelcontextprotocol.io)",
"Bash(cargo test:*)",
"Bash(gh issue view:*)",
"Bash(cargo check:*)",
"Bash(gh project item-edit:*)",
"WebFetch(domain:app.codecov.io)",
"Bash(grep:*)",
"Bash(gh pr checks:*)"
],
"deny": []
}
}
34 changes: 10 additions & 24 deletions .github/workflows/code-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,35 +86,26 @@ jobs:
> coverage-summary.txt
cat coverage-summary.txt

# Extract coverage percentage (use tail -1 to get TOTAL line, not first file)
# Extract coverage percentage for PR comment (use tail -1 to get TOTAL line, not first file)
COVERAGE=$(grep -oP '\d+\.\d+(?=%)' coverage-summary.txt | tail -1)
echo "COVERAGE_PERCENT=$COVERAGE" >> $GITHUB_ENV

# Check if coverage meets the 20% requirement (temporarily lowered)
if (( $(echo "$COVERAGE < 20" | bc -l) )); then
echo "❌ Coverage is below 20% threshold: $COVERAGE%"
echo "COVERAGE_PASSED=false" >> $GITHUB_ENV
else
echo "βœ… Coverage meets 20% threshold: $COVERAGE%"
echo "COVERAGE_PASSED=true" >> $GITHUB_ENV
fi
# Note: Coverage validation is now handled by Codecov, not locally
echo "ℹ️ Coverage validation delegated to Codecov - see https://codecov.io/gh/${{ github.repository }}"

- name: Post coverage comment
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const coverage = process.env.COVERAGE_PERCENT;
const passed = process.env.COVERAGE_PASSED === 'true';

const emoji = passed ? 'βœ…' : '❌';
const status = passed ? 'PASSED' : 'FAILED';
const comment = `## Code Coverage Report πŸ“Š

const comment = `## Code Coverage Report ${emoji}
**Local Coverage**: ${coverage}%
**Validation**: Handled by [Codecov](https://codecov.io/gh/${{ github.repository }})

**Coverage**: ${coverage}%
**Required**: 20%
**Status**: ${status}
> **Note**: Coverage validation is now performed by Codecov to ensure consistency across all platforms.

<details>
<summary>Coverage Details</summary>
Expand All @@ -125,7 +116,8 @@ jobs:

</details>

View full report on [Codecov](https://codecov.io/gh/${{ github.repository }})`;

**πŸ“‹ Full Report**: [View on Codecov](https://codecov.io/gh/${{ github.repository }})`;

// Find existing coverage comment
const { data: comments } = await github.rest.issues.listComments({
Expand Down Expand Up @@ -160,10 +152,4 @@ jobs:
name: coverage-report
path: |
lcov-merged.info
coverage-summary.txt

- name: Fail if coverage is below threshold
if: env.COVERAGE_PASSED == 'false'
run: |
echo "Coverage is below the required 20% threshold"
exit 1
coverage-summary.txt
23 changes: 12 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 11 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ members = [
resolver = "2"

[workspace.package]
version = "0.4.4"
version = "0.5.0"
rust-version = "1.79"
edition = "2021"
license = "MIT OR Apache-2.0"
Expand Down Expand Up @@ -96,16 +96,16 @@ assert_matches = "1.5"
serde_yaml = "0.9"

# Framework internal dependencies (published versions)
pulseengine-mcp-protocol = { version = "0.4.0", path = "mcp-protocol" }
pulseengine-mcp-logging = { version = "0.4.0", path = "mcp-logging" }
pulseengine-mcp-auth = { version = "0.4.0", path = "mcp-auth" }
pulseengine-mcp-security = { version = "0.4.0", path = "mcp-security" }
pulseengine-mcp-monitoring = { version = "0.4.0", path = "mcp-monitoring" }
pulseengine-mcp-transport = { version = "0.4.0", path = "mcp-transport" }
pulseengine-mcp-cli = { version = "0.4.0", path = "mcp-cli" }
pulseengine-mcp-cli-derive = { version = "0.4.0", path = "mcp-cli-derive" }
pulseengine-mcp-server = { version = "0.4.0", path = "mcp-server" }
pulseengine-mcp-external-validation = { version = "0.4.0", path = "mcp-external-validation" }
pulseengine-mcp-protocol = { version = "0.5.0", path = "mcp-protocol" }
pulseengine-mcp-logging = { version = "0.5.0", path = "mcp-logging" }
pulseengine-mcp-auth = { version = "0.5.0", path = "mcp-auth" }
pulseengine-mcp-security = { version = "0.5.0", path = "mcp-security" }
pulseengine-mcp-monitoring = { version = "0.5.0", path = "mcp-monitoring" }
pulseengine-mcp-transport = { version = "0.5.0", path = "mcp-transport" }
pulseengine-mcp-cli = { version = "0.5.0", path = "mcp-cli" }
pulseengine-mcp-cli-derive = { version = "0.5.0", path = "mcp-cli-derive" }
pulseengine-mcp-server = { version = "0.5.0", path = "mcp-server" }
pulseengine-mcp-external-validation = { version = "0.5.0", path = "mcp-external-validation" }

[profile.release]
opt-level = "s"
Expand Down
13 changes: 9 additions & 4 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# Codecov Configuration
# This is the authoritative source for coverage validation in the MCP project.
# Local coverage scripts are for development only - all official validation
# is performed by Codecov to ensure consistency across platforms.

codecov:
# Require the Codecov token for uploads
require_ci_to_pass: true
Expand All @@ -6,19 +11,19 @@ codecov:
wait_for_ci: true

coverage:
# Set the coverage requirements
# Coverage requirements - these are the official thresholds
status:
project:
default:
# Overall project coverage must be at least 80%
# Overall project coverage target
target: 80%
# Allow 1% drop in coverage
# Allow small drops in coverage
threshold: 1%
# Fail the status if coverage drops below threshold
if_ci_failed: error
patch:
default:
# New code must have at least 80% coverage
# New code must have high coverage
target: 80%
# Be strict about new code coverage
threshold: 0%
Expand Down
18 changes: 13 additions & 5 deletions docs/COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@

This project uses comprehensive code coverage tracking to ensure high-quality, well-tested code.

## Coverage Requirements
## Official Coverage Source

**🎯 Codecov is the authoritative source for all coverage validation in this project.**

- **View Coverage**: https://codecov.io/gh/pulseengine/mcp
- **Minimum Coverage**: 80%
- **New Code Coverage**: 80%
- **Coverage Drop Tolerance**: 1%

> **Important**: Local coverage scripts are for development debugging only.
> All official coverage validation is performed by Codecov to ensure consistency across platforms.

## Running Coverage Locally

### Quick Start
### Quick Start (Development Only)

Run the coverage script:
Run the coverage script for local development:

```bash
./scripts/coverage.sh
Expand All @@ -22,9 +28,11 @@ This will:
1. Install `cargo-llvm-cov` if not already installed
2. Run all tests with coverage instrumentation
3. Generate coverage reports in multiple formats
4. Check if coverage meets the 80% threshold
4. Display local coverage percentage (for reference only)
5. Generate an HTML report for detailed analysis

> **Note**: Local coverage is for debugging purposes only. Official validation happens via Codecov.

### Manual Coverage Commands

```bash
Expand Down Expand Up @@ -56,7 +64,7 @@ The workflow:
1. Runs all tests with coverage instrumentation
2. Uploads results to Codecov
3. Posts coverage summary as PR comment
4. Fails if coverage drops below 80%
4. Codecov validates coverage against thresholds

### Codecov Integration

Expand Down
5 changes: 5 additions & 0 deletions examples/hello-world/examples/hello-world-streamable-http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl McpBackend for HelloWorldBackend {
prompts: None,
logging: None,
sampling: None,
..Default::default()
},
server_info: Implementation {
name: "Hello World MCP Server (Streamable HTTP)".to_string(),
Expand Down Expand Up @@ -118,6 +119,7 @@ impl McpBackend for HelloWorldBackend {
},
"required": ["name"]
}),
output_schema: None,
},
Tool {
name: "count_greetings".to_string(),
Expand All @@ -126,6 +128,7 @@ impl McpBackend for HelloWorldBackend {
"type": "object",
"properties": {}
}),
output_schema: None,
},
];

Expand Down Expand Up @@ -170,6 +173,7 @@ impl McpBackend for HelloWorldBackend {
Ok(CallToolResult {
content: vec![Content::text(message)],
is_error: Some(false),
structured_content: None,
})
}

Expand All @@ -187,6 +191,7 @@ impl McpBackend for HelloWorldBackend {
Ok(CallToolResult {
content: vec![Content::text(format!("Total greetings sent: {count}"))],
is_error: Some(false),
structured_content: None,
})
}

Expand Down
5 changes: 5 additions & 0 deletions examples/hello-world/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl McpBackend for HelloWorldBackend {
prompts: None,
logging: None,
sampling: None,
..Default::default()
},
server_info: Implementation {
name: "Hello World MCP Server".to_string(),
Expand Down Expand Up @@ -118,6 +119,7 @@ impl McpBackend for HelloWorldBackend {
},
"required": ["name"]
}),
output_schema: None,
},
Tool {
name: "count_greetings".to_string(),
Expand All @@ -126,6 +128,7 @@ impl McpBackend for HelloWorldBackend {
"type": "object",
"properties": {}
}),
output_schema: None,
},
];

Expand Down Expand Up @@ -170,6 +173,7 @@ impl McpBackend for HelloWorldBackend {
Ok(CallToolResult {
content: vec![Content::text(message)],
is_error: Some(false),
structured_content: None,
})
}

Expand All @@ -187,6 +191,7 @@ impl McpBackend for HelloWorldBackend {
Ok(CallToolResult {
content: vec![Content::text(format!("Total greetings sent: {count}"))],
is_error: Some(false),
structured_content: None,
})
}

Expand Down
Loading
Loading