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
12 changes: 10 additions & 2 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,16 @@
"Bash(gh issue list:*)",
"Bash(gh pr view:*)",
"WebSearch",
"Bash(git log:*)"
"Bash(git log:*)",
"Bash(awk:*)",
"Bash(xargs:*)",
"Read(//Users/r/git/**)",
"WebFetch(domain:docs.rs)",
"Bash(gh release list:*)",
"Bash(gh release view:*)",
"Bash(gh pr list:*)",
"Bash(pre-commit:*)"
],
"deny": []
}
}
}
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ repos:
- id: cargo-clippy-check
name: Cargo Clippy Check
description: Run clippy with warnings as errors (same as CI)
entry: cargo clippy --workspace --lib --all-features -- -D warnings
entry: cargo clippy --all-features --all-targets --release -- -D warnings
language: system
files: '\.rs$'
pass_filenames: false
Expand All @@ -105,7 +105,7 @@ repos:
- id: cargo-test-check
name: Cargo Test Check
description: Run quick tests to catch major issues before CI
entry: cargo test --workspace --lib
entry: cargo test --workspace --lib --all-features
language: system
files: '\.rs$'
pass_filenames: false
Expand Down
29 changes: 15 additions & 14 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ uuid = { version = "1.11", features = ["v4", "serde"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
anyhow = "1.0"
thiserror = "1.0"
thiserror = "2.0"

# Validation
validator = { version = "0.20", features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion examples/hello-world-with-auth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ tower = { workspace = true }
pulseengine-mcp-macros = { workspace = true }
pulseengine-mcp-server = { workspace = true }
pulseengine-mcp-security-middleware = { workspace = true }
pulseengine-mcp-protocol = { workspace = true }
pulseengine-mcp-protocol = { workspace = true }
39 changes: 23 additions & 16 deletions examples/hello-world-with-auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@ This example demonstrates how to add zero-configuration authentication to an MCP
## Key Features

### 🔐 Development Security Profile

- Authentication is **optional** but **logged** when present
- Auto-generates API keys for testing
- Permissive CORS settings
- Detailed logging for debugging

### 🎯 Zero Configuration

- No environment variables required
- No CLI tools to run
- No configuration files needed
- Works out of the box

### 📊 Security Logging

- All authentication attempts logged
- Request/response audit trail
- Security events tracking
Expand All @@ -37,6 +40,7 @@ cargo run --bin hello-world-with-auth
```

The server will display:

- Generated API key for testing
- Security configuration summary
- Available endpoints
Expand Down Expand Up @@ -64,18 +68,21 @@ curl -H "Authorization: ApiKey mcp_generated_key_here" \\
## Code Walkthrough

### 1. Security Configuration (3 lines)

```rust
let security_config = SecurityConfig::development();
let security_middleware = security_config.create_middleware().await?;
```

### 2. MCP Server Integration (1 line)

```rust
// Integrate with MCP server HTTP transport
.layer(from_fn(security_middleware))
```

### 3. Tool Implementation (unchanged)

```rust
#[mcp_tools]
impl HelloWorldAuth {
Expand All @@ -87,14 +94,14 @@ impl HelloWorldAuth {

## Security Features Demonstrated

| Feature | Development Mode | Notes |
|---------|------------------|--------|
| Authentication | Optional | Logged when present |
| Rate Limiting | Disabled | For development convenience |
| HTTPS | Optional | Localhost connections accepted |
| CORS | Permissive | Wildcard origins allowed |
| Audit Logging | Enabled | All requests logged |
| API Key Generation | Automatic | New key per restart |
| Feature | Development Mode | Notes |
| ------------------ | ---------------- | ------------------------------ |
| Authentication | Optional | Logged when present |
| Rate Limiting | Disabled | For development convenience |
| HTTPS | Optional | Localhost connections accepted |
| CORS | Permissive | Wildcard origins allowed |
| Audit Logging | Enabled | All requests logged |
| API Key Generation | Automatic | New key per restart |

## Environment Variables (Optional)

Expand All @@ -118,12 +125,12 @@ cargo run --bin hello-world-with-auth

## Comparison with Basic Hello World

| Aspect | hello-world | hello-world-with-auth |
|--------|-------------|----------------------|
| Lines of code | 25 | 35 (+authentication) |
| Setup complexity | None | None (zero-config) |
| Security features | None | Full middleware stack |
| Production ready | No | Development ready |
| Authentication | None | API key + JWT support |
| Aspect | hello-world | hello-world-with-auth |
| ----------------- | ----------- | --------------------- |
| Lines of code | 25 | 35 (+authentication) |
| Setup complexity | None | None (zero-config) |
| Security features | None | Full middleware stack |
| Production ready | No | Development ready |
| Authentication | None | API key + JWT support |

This demonstrates how the security middleware maintains simplicity while adding comprehensive security features.
This demonstrates how the security middleware maintains simplicity while adding comprehensive security features.
8 changes: 8 additions & 0 deletions examples/memory-only-auth/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ impl McpBackend for MemoryAuthBackend {
description: "List all API keys currently in memory".to_string(),
input_schema: json!({"type": "object", "properties": {}}),
output_schema: None,
title: None,
annotations: None,
icons: None,
},
Tool {
name: "add_temp_key".to_string(),
Expand All @@ -157,6 +160,9 @@ impl McpBackend for MemoryAuthBackend {
"required": ["name", "role"]
}),
output_schema: None,
title: None,
annotations: None,
icons: None,
},
],
next_cursor: None,
Expand Down Expand Up @@ -192,6 +198,7 @@ impl McpBackend for MemoryAuthBackend {
))],
is_error: Some(false),
structured_content: None,
_meta: None,
})
}
"add_temp_key" => {
Expand Down Expand Up @@ -231,6 +238,7 @@ impl McpBackend for MemoryAuthBackend {
))],
is_error: Some(false),
structured_content: None,
_meta: None,
})
}
_ => Err(ServerError::InvalidParameter(format!(
Expand Down
2 changes: 1 addition & 1 deletion examples/ultra-simple/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
schemars = { version = "1.0", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
anyhow = "1.0"
anyhow = "1.0"
4 changes: 2 additions & 2 deletions examples/ultra-simple/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ pub struct UltraSimple;

#[mcp_tools]
impl UltraSimple {
/// Say hello to someone with customizable greeting
/// Say hello to someone with customizable greeting
pub async fn say_hello(&self, params: SayHelloParams) -> anyhow::Result<String> {
let greeting = params.greeting.unwrap_or_else(|| "Hello".to_string());
Ok(format!("{greeting}, {}! 👋", params.name))
}

/// Add two numbers together
/// Add two numbers together
pub fn add(&self, params: AddParams) -> i32 {
params.a + params.b
}
Expand Down
Loading