#[cfg(feature = "mcp")]
use sdforge::forge;
#[cfg(feature = "mcp")]
mod mcp_tests {
use sdforge::mcp::build;
#[tokio::test]
async fn test_mcp_server_builds() {
let _server = build();
}
}
#[cfg(feature = "mcp")]
mod mcp_registration_tests {
use rmcp::model::{CallToolResult, ErrorData as McpError};
use sdforge::core::ApiMetadata;
use sdforge::mcp::{McpToolRegistration, SdForgeTool};
use std::sync::Arc;
struct TestTool;
impl SdForgeTool for TestTool {
fn name(&self) -> &str {
"test_tool"
}
fn description(&self) -> &str {
"A test tool"
}
fn input_schema(&self) -> serde_json::Value {
serde_json::json!({
"type": "object",
"properties": {
"input": { "type": "string" }
}
})
}
fn call(&self, _input: Option<serde_json::Value>) -> Result<CallToolResult, McpError> {
Ok({
let mut result = CallToolResult::success(vec![]);
result.is_error = None;
result
})
}
}
#[test]
fn test_mcp_tool_registration() {
fn create_tool() -> Arc<dyn SdForgeTool> {
Arc::new(TestTool)
}
fn create_metadata() -> ApiMetadata {
ApiMetadata::new(
"test_tool".to_string(),
"v1".to_string(),
"A test tool".to_string(),
None,
false,
)
}
let _registration =
McpToolRegistration::new("test_tool", "v1", create_tool, create_metadata);
let _ = &_registration;
}
#[test]
fn test_mcp_tool_creation() {
let tool = TestTool;
assert_eq!(tool.name(), "test_tool");
}
}
#[cfg(all(feature = "http", feature = "mcp"))]
mod dual_protocol_tests {
use sdforge::http::build as http_build;
use sdforge::mcp::build as mcp_build;
#[tokio::test]
async fn test_both_protocols_build() {
let _http_app = http_build();
let _mcp_server = mcp_build();
}
}
#[cfg(feature = "mcp")]
#[forge(
name = "vuln0002_echo",
version = "v1",
tool_name = "vuln0002_echo",
description = "vuln-0002 regression test echo tool"
)]
async fn vuln0002_echo(message: String) -> Result<String, sdforge::core::ApiError> {
Ok(message)
}
#[cfg(feature = "mcp")]
mod vuln0002_security_tests {
use sdforge::mcp::SdForgeMcpServer;
fn server_with_tool() -> SdForgeMcpServer {
let server = SdForgeMcpServer::new();
assert!(
server.find_tool("vuln0002_echo").is_some(),
"vuln0002_echo tool must be registered via #[forge]"
);
server
}
#[test]
fn test_vuln0002_valid_field_accepted() {
let server = server_with_tool();
let args = serde_json::json!({ "message": "hello" });
let result = server.call_tool_internal("vuln0002_echo", Some(args));
assert!(
result.is_ok(),
"valid arguments must be accepted, got: {:?}",
result.err()
);
}
#[test]
fn test_vuln0002_unknown_field_rejected() {
let server = server_with_tool();
let args = serde_json::json!({ "message": "hi", "malicious_extra": "boom" });
let result = server.call_tool_internal("vuln0002_echo", Some(args));
assert!(
result.is_err(),
"unknown fields must be rejected by deny_unknown_fields"
);
let err = result.unwrap_err();
let msg = err.to_string();
assert!(
msg.contains("Failed to parse") || msg.contains("unknown field"),
"error should mention parse failure / unknown field, got: {msg}"
);
}
#[test]
fn test_vuln0002_missing_required_field_rejected() {
let server = server_with_tool();
let args = serde_json::json!({ "different_field": "value" });
let result = server.call_tool_internal("vuln0002_echo", Some(args));
assert!(result.is_err(), "missing required field must be rejected");
}
}