use rmcp::{ServiceExt, handler::server::wrapper::Parameters, tool_router, tool, schemars};
use serde::Deserialize;
use shohei::api::*;
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckDnsParams {
domain: String,
#[serde(default)]
record_types: Option<Vec<String>>,
#[serde(default)]
transport: Option<String>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckHttpParams {
url: String,
#[serde(default = "default_true")]
follow_redirects: bool,
}
fn default_true() -> bool { true }
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckTlsChainParams {
hostname: String,
#[serde(default)]
port: Option<u16>,
#[serde(default)]
check_dane: Option<bool>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckEmailSecurityParams {
domain: String,
#[serde(default)]
dkim_selectors: Option<Vec<String>>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckMtaStsParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckPropagationGlobalParams {
domain: String,
#[serde(default = "default_record_type")]
record_type: String,
}
fn default_record_type() -> String { "A".to_string() }
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckPropagationParams {
domain: String,
#[serde(default = "default_record_type")]
record_type: String,
#[serde(default)]
resolvers: Option<String>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckDnssecParams {
domain: String,
#[serde(default = "default_record_type")]
record_type: String,
#[serde(default)]
resolver_ip: Option<String>,
#[serde(default)]
verbose: bool,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct TraceResolutionParams {
domain: String,
#[serde(default = "default_record_type")]
record_type: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckOcspParams {
hostname: String,
#[serde(default = "default_port")]
port: u16,
}
fn default_port() -> u16 { 443 }
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckStartTlsParams {
hostname: String,
port: u16,
protocol: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckDomainHealthParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckCaaParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckBimiParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckCtParams {
hostname: String,
#[serde(default = "default_port")]
port: u16,
#[serde(default)]
expected_cas: Option<Vec<String>>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct BenchmarkLatencyParams {
domain: String,
#[serde(default)]
transports: Option<String>,
#[serde(default)]
record_type: Option<String>,
#[serde(default)]
rounds: Option<u32>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckWhoisParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckSubdomainsParams {
domain: String,
#[serde(default)]
extra_subdomains: Option<Vec<String>>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckPortsParams {
host: String,
#[serde(default)]
ports: Option<String>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckRdnsParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckDnsblParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DetectCdnParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckDelegationParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckIpInfoParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckTlsVulnsParams {
hostname: String,
#[serde(default)]
port: Option<u16>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckTlsRptParams {
domain: String,
#[serde(default)]
dnssec: Option<bool>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckIpv6Params {
domain: String,
#[serde(default)]
port: Option<u16>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckArcParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckCipherSuitesParams {
hostname: String,
#[serde(default = "default_port")]
port: u16,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckRpkiParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckDnsAmplificationParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckTracerouteParams {
host: String,
#[serde(default)]
max_hops: Option<u32>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckWildcardDnsParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckZoneTransferParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckIpNoiseParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckDomainRiskParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckTechStackParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckCveParams {
keyword: String,
#[serde(default)]
max_results: Option<u32>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckTyposquattingParams {
domain: String,
#[serde(default)]
max_mutations: Option<u32>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckRedirectChainParams {
url: String,
#[serde(default)]
max_hops: Option<u32>,
#[serde(default)]
check_domain_age: Option<bool>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckParkedDomainParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckBrandImpersonationParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckUrlReputationParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckUrlAnalysisParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckShodanIpParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckSshFingerprintParams {
host: String,
#[serde(default)]
port: Option<u16>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckComplianceParams {
domain: String,
#[serde(default)]
url: Option<String>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckBgpRouteParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckDnsHijackingParams {
domain: String,
#[serde(default)]
record_type: Option<String>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckSpfDeepParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CheckThreatIntelParams {
target: String,
#[serde(default)]
include_sources: Option<Vec<String>>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ThreatIntelRiskScoreParams {
target: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PhishingDetectionParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct MalwareSourcesParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DomainTrustScoreParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct IpTrustScoreParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct SubdomainEnumerationParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct WhoisEnrichmentParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DnsThreatMappingParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DnsTakeoverRiskParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct SubdomainBruteforceParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct TyposquatDetectionParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct IpWhoisEnrichmentParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DomainAgeTimelineParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CertificateHistoryParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ThreatActorInfraParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DnsHistoryParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct IpGeolocationParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct AsnLookupParams {
ip: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct WhoisPrivacyDetectionParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct EmailSpoofingRiskParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct TlsCertValidationParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct InfrastructureOverlapParams {
domains: Vec<String>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct TechStackFingerprintingParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DomainReputationAnalysisParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PolicyDefinitionParams {
policy_name: String,
policy_type: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DomainBlocklistParams {
domains: Vec<String>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct IpBlocklistParams {
ips: Vec<String>,
threat_level: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct AllowlistParams {
domains: Vec<String>,
reason: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct RateLimitPolicyParams {
user_id: String,
requests_per_minute: u32,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ApprovalGateParams {
operation: String,
requester: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct AuditLogQueryParams {
#[serde(default = "default_audit_days")]
days: u32,
}
fn default_audit_days() -> u32 { 30 }
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ComplianceReportParams {
framework: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ToolCallControlParams {
tool_name: String,
#[serde(default)]
allowed_users: Option<String>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct RiskClassificationParams {
target: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct QuarantineParams {
targets: Vec<String>,
reason: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PolicyViolationAlertParams {
domain: String,
violation_type: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DataResidencyComplianceParams {
domain: String,
required_region: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct EncryptionStatusParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PolicyExceptionParams {
target: String,
exception_type: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct AuditTrailVerificationParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PolicyEffectivenessParams {
#[serde(default = "default_effectiveness_days")]
days: u32,
}
fn default_effectiveness_days() -> u32 { 30 }
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct IncidentResponsePlaybookParams {
incident_type: String,
#[serde(default = "default_severity")]
severity: String,
}
fn default_severity() -> String { "high".to_string() }
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct SecurityPostureAssessmentParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct BreachSimulationParams {
simulation_type: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PiiDetectionParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PiiAnonymizationParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DataRetentionPolicyParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct GdprComplianceParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct HipaaComplianceParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PciDssComplianceParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DataClassificationParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DataMaskingParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DataDeletionParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DataSubjectAccessParams {
domain: String,
subject_identifier: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ConsentManagementParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CryptographicSignatureParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct AuditTrailImmutabilityParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PrivacyImpactAssessmentParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PrivacyBreachNotificationParams {
domain: String,
breach_scope: u32,
breach_type: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct Rfc3161TimestampParams {
document_hash: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct TimestampValidationParams {
timestamp_token: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct SignstoreRekorParams {
artifact_hash: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct RekorVerificationParams {
entry_uuid: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ZkProofGenerationParams {
circuit_type: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ZkProofVerificationParams {
proof: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct EscrowAgreementParams {
payer: String,
payee: String,
amount: u64,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct EscrowReleaseParams {
escrow_id: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DigitalNotarizationParams {
document_hash: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct NotarizationVerificationParams {
notarization_id: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct KeyManagementParams {
key_type: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct KeyRotationParams {
key_id: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct AuditTrailBindingParams {
audit_entries: usize,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct HsmIntegrationParams {
operation: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CryptographicComplianceParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct UrlUnshortenParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct Ja4hFingerprintParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct UrlSafetyMultiParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct UrlRedirectThreatParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct S3BucketExposureParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CloudProviderParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ServerHardeningParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DanglingDnsParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct UsernameOsintParams {
username: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct EmailIntelParams {
email: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct OrganizationIntelParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct SocialMediaPresenceParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct AsnReputationParams {
asn: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct BgpHijackHistoryParams {
prefix: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct NetworkExposureScoreParams {
target: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CloudMetadataExposureParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct AzureBlobExposureParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct GcsBucketExposureParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CorsPolicyParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct SecurityTxtParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct JwtSecurityParams {
token: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CookieSecurityParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CspAdvancedParams {
url: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ExposedFilesParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct NpmPackageSecurityParams {
package: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PypiPackageSecurityParams {
package: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DependencyConfusionParams {
internal_package: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct SbomDisclosureParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct RobotsTxtParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct WellKnownParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct OauthOidcParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct CertPinningParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ApiExposureParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ExposedDatabasesParams {
host: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ContainerExposureParams {
host: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct ServiceFingerprintParams {
host: String,
#[serde(default)]
ports: Option<Vec<u16>>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DgaRiskParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct SubdomainTakeoverParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct PassiveDnsParams {
query: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct AzureAdExposureParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct DkimKeyStrengthParams {
domain: String,
#[serde(default)]
selectors: Option<Vec<String>>,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct MxSecurityParams {
domain: String,
}
#[derive(Deserialize, schemars::JsonSchema, Clone)]
struct AttackSurfaceParams {
domain: String,
}
#[derive(Clone)]
struct ShoheiServer;
#[tool_router(server_handler)]
impl ShoheiServer {
#[tool(description = "Check DNS records for a domain")]
async fn check_dns(
&self,
Parameters(CheckDnsParams { domain, record_types, transport }): Parameters<CheckDnsParams>,
) -> String {
let transport_enum = match transport.as_deref() {
Some("doh") | Some("doh-cloudflare") => Transport::Doh("https://1.1.1.1/dns-query".to_string()),
Some("dot") | Some("dot-cloudflare") => Transport::Dot("1.1.1.1:853".to_string()),
Some("doq") | Some("doq-cloudflare") => Transport::Doq("1.1.1.1:853".to_string()),
Some(addr) => Transport::Server(addr.to_string()),
None => Transport::System,
};
let req = DnsCheckRequest {
domain,
record_types: record_types.unwrap_or_else(|| vec!["A".to_string()]),
transport: transport_enum,
..Default::default()
};
match shohei::api::check_dns(&req).await {
Ok(results) => serde_json::to_string_pretty(&results).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check HTTP(S) endpoint reachability and headers")]
async fn check_http(
&self,
Parameters(CheckHttpParams { url, follow_redirects }): Parameters<CheckHttpParams>,
) -> String {
let req = HttpCheckRequest {
url,
follow_redirects,
timeout_secs: 10,
};
match shohei::api::check_http(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Inspect TLS certificate chain for a hostname")]
async fn check_tls_chain(
&self,
Parameters(CheckTlsChainParams {
hostname,
port,
check_dane,
}): Parameters<CheckTlsChainParams>,
) -> String {
let req = TlsCheckRequest {
hostname,
port: port.unwrap_or(443),
check_dane: check_dane.unwrap_or(false),
timeout_secs: 10,
};
match shohei::api::check_tls_chain(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check email security (MX, SPF, DKIM, DMARC)")]
async fn check_email_security(
&self,
Parameters(CheckEmailSecurityParams { domain, dkim_selectors }): Parameters<CheckEmailSecurityParams>,
) -> String {
let req = EmailSecurityRequest {
domain,
timeout_secs: 5,
dkim_selectors: dkim_selectors.unwrap_or_else(|| vec![
"default".to_string(),
"google".to_string(),
"selector1".to_string(),
"selector2".to_string(),
]),
};
match shohei::api::check_email_security(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check MTA-STS policy for SMTP TLS enforcement")]
async fn check_mta_sts(
&self,
Parameters(CheckMtaStsParams { domain }): Parameters<CheckMtaStsParams>,
) -> String {
let req = MtaStsRequest {
domain,
timeout_secs: 5,
};
match shohei::api::check_mta_sts(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check OCSP revocation status for a certificate")]
async fn check_ocsp(
&self,
Parameters(CheckOcspParams { hostname, port }): Parameters<CheckOcspParams>,
) -> String {
let req = OcspCheckRequest {
hostname,
port,
ocsp_responder_url: None,
timeout_secs: 10,
};
match shohei::api::check_ocsp(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check STARTTLS capability for SMTP/IMAP/POP3")]
async fn check_starttls(
&self,
Parameters(CheckStartTlsParams { hostname, port, protocol }): Parameters<CheckStartTlsParams>,
) -> String {
let proto = match protocol.to_lowercase().as_str() {
"smtp" => StartTlsProtocol::Smtp,
"imap" => StartTlsProtocol::Imap,
"pop3" => StartTlsProtocol::Pop3,
_ => return serde_json::json!({"error": format!("unknown protocol {}", protocol)}).to_string(),
};
let req = StartTlsCheckRequest {
hostname,
port,
protocol: proto,
timeout_secs: 10,
};
match shohei::api::check_starttls(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Comprehensive domain health assessment")]
async fn check_domain_health(
&self,
Parameters(CheckDomainHealthParams { domain }): Parameters<CheckDomainHealthParams>,
) -> String {
let req = DomainHealthRequest {
domain,
timeout_secs: 10,
};
match shohei::api::check_domain_health(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check CAA records for certificate issuance authorization")]
async fn check_caa(
&self,
Parameters(CheckCaaParams { domain }): Parameters<CheckCaaParams>,
) -> String {
let req = CaaCheckRequest {
domain,
issued_by_ca: None,
timeout_secs: 5,
};
match shohei::api::check_caa(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check BIMI configuration for brand protection")]
async fn check_bimi(
&self,
Parameters(CheckBimiParams { domain }): Parameters<CheckBimiParams>,
) -> String {
let req = BimiCheckRequest {
domain,
timeout_secs: 5,
};
match shohei::api::check_bimi(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check Certificate Transparency logs")]
async fn check_ct(
&self,
Parameters(CheckCtParams { hostname, port, expected_cas }): Parameters<CheckCtParams>,
) -> String {
let req = CtCheckRequest {
hostname,
port,
timeout_secs: 10,
expected_cas,
};
match shohei::api::check_ct(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check DNS propagation across 6 global resolvers")]
async fn check_propagation_global(
&self,
Parameters(CheckPropagationGlobalParams { domain, record_type }): Parameters<
CheckPropagationGlobalParams,
>,
) -> String {
let req = PropagationRequest {
domain: domain.clone(),
record_type,
resolvers: vec![
PropagationResolver { name: "Google".to_string(), address: "8.8.8.8".to_string(), region: None },
PropagationResolver { name: "Cloudflare".to_string(), address: "1.1.1.1".to_string(), region: None },
PropagationResolver { name: "Quad9".to_string(), address: "9.9.9.9".to_string(), region: None },
PropagationResolver { name: "OpenDNS".to_string(), address: "208.67.222.222".to_string(), region: None },
PropagationResolver { name: "CleanBrowsing".to_string(), address: "185.228.168.168".to_string(), region: None },
PropagationResolver { name: "Comodo".to_string(), address: "8.26.56.26".to_string(), region: None },
],
timeout_secs: 5,
};
match shohei::api::check_propagation(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check DNS propagation across custom resolvers (default: 6 global resolvers)")]
async fn check_propagation(
&self,
Parameters(CheckPropagationParams { domain, record_type, resolvers }): Parameters<
CheckPropagationParams,
>,
) -> String {
let resolver_list = if let Some(resolver_str) = resolvers {
let mut list = Vec::new();
for (idx, addr) in resolver_str.split(',').enumerate() {
let addr = addr.trim().to_string();
list.push(PropagationResolver {
name: format!("Resolver{}", idx + 1),
address: addr,
region: None,
});
}
list
} else {
vec![
PropagationResolver { name: "Google".to_string(), address: "8.8.8.8".to_string(), region: None },
PropagationResolver { name: "Cloudflare".to_string(), address: "1.1.1.1".to_string(), region: None },
PropagationResolver { name: "Quad9".to_string(), address: "9.9.9.9".to_string(), region: None },
PropagationResolver { name: "OpenDNS".to_string(), address: "208.67.222.222".to_string(), region: None },
PropagationResolver { name: "CleanBrowsing".to_string(), address: "185.228.168.168".to_string(), region: None },
PropagationResolver { name: "Comodo".to_string(), address: "8.26.56.26".to_string(), region: None },
]
};
let req = PropagationRequest {
domain,
record_type,
resolvers: resolver_list,
timeout_secs: 5,
};
match shohei::api::check_propagation(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Validate DNSSEC chain of trust")]
async fn check_dnssec(
&self,
Parameters(CheckDnssecParams { domain, record_type, resolver_ip, verbose }): Parameters<
CheckDnssecParams,
>,
) -> String {
let req = DnssecCheckRequest {
domain,
record_type,
resolver_ip,
verbose,
};
match shohei::api::check_dnssec(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Trace DNS resolution path from root to authoritative")]
async fn trace_resolution(
&self,
Parameters(TraceResolutionParams { domain, record_type }): Parameters<
TraceResolutionParams,
>,
) -> String {
match shohei::api::trace_resolution(&domain, &record_type).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Benchmark DNS latency across transports")]
async fn benchmark_latency(
&self,
Parameters(BenchmarkLatencyParams { domain, transports, record_type, rounds }): Parameters<
BenchmarkLatencyParams,
>,
) -> String {
let mut bench_transports = vec![
BenchTransport {
transport: Transport::System,
label: "System".to_string(),
},
BenchTransport {
transport: Transport::Doh("https://1.1.1.1/dns-query".to_string()),
label: "DoH-Cloudflare".to_string(),
},
];
if let Some(transport_str) = transports {
bench_transports.clear();
for (idx, t) in transport_str.split(',').enumerate() {
let t = t.trim();
let (transport, label) = match t.to_lowercase().as_str() {
"system" => (Transport::System, "System".to_string()),
"doh" | "doh-cloudflare" => (
Transport::Doh("https://1.1.1.1/dns-query".to_string()),
"DoH-Cloudflare".to_string(),
),
"dot" | "dot-cloudflare" => (
Transport::Dot("1.1.1.1:853".to_string()),
"DoT-Cloudflare".to_string(),
),
"doq" | "doq-cloudflare" => (
Transport::Doq("1.1.1.1:853".to_string()),
"DoQ-Cloudflare".to_string(),
),
addr => {
(Transport::Server(addr.to_string()), format!("Server{}", idx + 1))
}
};
bench_transports.push(BenchTransport { transport, label });
}
}
let req = LatencyBenchRequest {
domain,
record_type: record_type.unwrap_or_else(|| "A".to_string()),
transports: bench_transports,
rounds: rounds.unwrap_or(3),
timeout_secs: 5,
};
match shohei::api::benchmark_latency(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check domain registration details and expiration")]
async fn check_whois(
&self,
Parameters(CheckWhoisParams { domain }): Parameters<CheckWhoisParams>,
) -> String {
let req = WhoisCheckRequest {
domain,
timeout_secs: 10,
};
match shohei::api::check_whois(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check common subdomains for DNS/HTTP/TLS validity")]
async fn check_subdomains(
&self,
Parameters(CheckSubdomainsParams { domain, extra_subdomains }): Parameters<CheckSubdomainsParams>,
) -> String {
let req = SubdomainCheckRequest {
domain,
timeout_secs: 10,
extra_subdomains,
};
match shohei::api::check_common_subdomains(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check port reachability and service detection")]
async fn check_ports(
&self,
Parameters(CheckPortsParams { host, ports }): Parameters<CheckPortsParams>,
) -> String {
let port_list = ports.as_ref().and_then(|p| {
let parsed: Result<Vec<u16>, _> = p.split(',')
.map(|s| s.trim().parse::<u16>())
.collect();
parsed.ok()
});
let req = PortCheckRequest {
host,
ports: port_list,
timeout_secs: 5,
};
match shohei::api::check_ports(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check reverse DNS and forward-confirmed reverse DNS (FCrDNS)")]
async fn check_rdns(
&self,
Parameters(CheckRdnsParams { ip }): Parameters<CheckRdnsParams>,
) -> String {
let req = RdnsCheckRequest {
ip,
timeout_secs: 10,
};
match shohei::api::check_rdns(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check IP reputation against DNSBL services")]
async fn check_dnsbl(
&self,
Parameters(CheckDnsblParams { ip }): Parameters<CheckDnsblParams>,
) -> String {
let req = DnsblCheckRequest {
ip,
timeout_secs: 10,
};
match shohei::api::check_dnsbl(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect CDN and WAF providers via HTTP headers")]
async fn detect_cdn(
&self,
Parameters(DetectCdnParams { url }): Parameters<DetectCdnParams>,
) -> String {
let req = CdnDetectRequest {
url,
timeout_secs: 10,
};
match shohei::api::detect_cdn(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check DNS delegation consistency (SOA serials, NS reachability)")]
async fn check_delegation(
&self,
Parameters(CheckDelegationParams { domain }): Parameters<CheckDelegationParams>,
) -> String {
let req = DelegationCheckRequest {
domain,
timeout_secs: 10,
};
match shohei::api::check_delegation(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check IP information (ASN, geolocation, organization)")]
async fn check_ip_info(
&self,
Parameters(CheckIpInfoParams { ip }): Parameters<CheckIpInfoParams>,
) -> String {
let req = IpInfoCheckRequest {
ip,
timeout_secs: 10,
};
match shohei::api::check_ip_info(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check TLS protocol vulnerabilities (TLS 1.0/1.1/1.2/1.3 support, forward secrecy)")]
async fn check_tls_vulns(
&self,
Parameters(CheckTlsVulnsParams { hostname, port }): Parameters<CheckTlsVulnsParams>,
) -> String {
let req = TlsVulnCheckRequest {
hostname,
port: port.unwrap_or(443),
timeout_secs: 10,
};
match shohei::api::check_tls_vulns(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check TLS-RPT (SMTP TLS Reporting Policy) record")]
async fn check_tls_rpt(
&self,
Parameters(CheckTlsRptParams { domain, dnssec }): Parameters<CheckTlsRptParams>,
) -> String {
let req = TlsRptRequest {
domain,
dnssec: dnssec.unwrap_or(false),
timeout_secs: 10,
};
match shohei::api::check_tls_rpt(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check IPv6 dual-stack support (DNS AAAA, TCP, TLS, HTTP)")]
async fn check_ipv6(
&self,
Parameters(CheckIpv6Params { domain, port }): Parameters<CheckIpv6Params>,
) -> String {
let req = Ipv6CheckRequest {
domain,
port: port.unwrap_or(443),
timeout_secs: 10,
};
match shohei::api::check_ipv6(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check ARC (Authenticated Received Chain) records for a domain")]
async fn check_arc(
&self,
Parameters(CheckArcParams { domain }): Parameters<CheckArcParams>,
) -> String {
let req = ArcCheckRequest {
domain,
timeout_secs: 10,
};
match shohei::api::check_arc(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check supported TLS cipher suites for a hostname")]
async fn check_cipher_suites(
&self,
Parameters(CheckCipherSuitesParams { hostname, port }): Parameters<CheckCipherSuitesParams>,
) -> String {
let req = CipherSuitesRequest {
hostname,
port,
timeout_secs: 10,
probe_weak: false,
};
match shohei::api::check_cipher_suites(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check RPKI (Resource Public Key Infrastructure) validity for an IP prefix")]
async fn check_rpki(
&self,
Parameters(CheckRpkiParams { ip }): Parameters<CheckRpkiParams>,
) -> String {
let req = RpkiCheckRequest { ip };
match shohei::api::check_rpki(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check DNS amplification risk (query/response size ratio)")]
async fn check_dns_amplification(
&self,
Parameters(CheckDnsAmplificationParams { domain }): Parameters<CheckDnsAmplificationParams>,
) -> String {
let req = DnsAmplificationRequest {
nameserver: "8.8.8.8".to_string(),
port: 53,
domain,
timeout_secs: 10,
};
match shohei::api::check_dns_amplification(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Trace route to a host using ICMP echo requests")]
async fn check_traceroute(
&self,
Parameters(CheckTracerouteParams { host, max_hops }): Parameters<CheckTracerouteParams>,
) -> String {
let req = TracerouteRequest {
hostname: host,
max_hops: max_hops.unwrap_or(30),
timeout_secs: 30,
};
match shohei::api::check_traceroute(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check for wildcard DNS records that could mask domain enumeration")]
async fn check_wildcard_dns(
&self,
Parameters(CheckWildcardDnsParams { domain }): Parameters<CheckWildcardDnsParams>,
) -> String {
let req = WildcardDnsRequest {
domain,
timeout_secs: 10,
};
match shohei::api::check_wildcard_dns(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Attempt DNS zone transfer (AXFR) against authoritative nameservers")]
async fn check_zone_transfer(
&self,
Parameters(CheckZoneTransferParams { domain }): Parameters<CheckZoneTransferParams>,
) -> String {
let req = shohei::api::zone_transfer::ZoneTransferRequest {
domain,
timeout_secs: 10,
};
match shohei::api::zone_transfer::check_zone_transfer(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Classify IP address using GreyNoise community API (no API key required)")]
async fn check_ip_noise(
&self,
Parameters(CheckIpNoiseParams { ip }): Parameters<CheckIpNoiseParams>,
) -> String {
let req = shohei::api::greynoise::GreyNoiseRequest {
ip,
timeout_secs: 10,
};
match shohei::api::greynoise::check_ip_noise(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Evaluate domain registration risk for phishing and squatting")]
async fn check_domain_risk(
&self,
Parameters(CheckDomainRiskParams { domain }): Parameters<CheckDomainRiskParams>,
) -> String {
let req = shohei::api::domain_risk::DomainRiskRequest {
domain,
timeout_secs: 10,
};
match shohei::api::domain_risk::check_domain_risk(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Identify web technologies (web server, language, CMS, frameworks)")]
async fn check_tech_stack(
&self,
Parameters(CheckTechStackParams { url }): Parameters<CheckTechStackParams>,
) -> String {
let req = shohei::api::TechFingerprintRequest {
url,
timeout_secs: 10,
};
match shohei::api::check_tech_stack(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Search for known CVEs in the NVD database (no API key required)")]
async fn check_cve(
&self,
Parameters(CheckCveParams { keyword, max_results }): Parameters<CheckCveParams>,
) -> String {
let req = shohei::api::CveLookupRequest {
keyword,
max_results: max_results.unwrap_or(10),
timeout_secs: 10,
};
match shohei::api::check_cve(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect typosquatting variants of a domain")]
async fn check_typosquatting(
&self,
Parameters(CheckTyposquattingParams { domain, max_mutations }): Parameters<CheckTyposquattingParams>,
) -> String {
let req = shohei::api::TyposquatRequest {
domain,
timeout_secs: 10,
max_mutations: max_mutations.unwrap_or(200),
};
match shohei::api::check_typosquatting(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Trace HTTP redirect chain from a URL")]
async fn check_redirect_chain(
&self,
Parameters(CheckRedirectChainParams { url, max_hops, check_domain_age }): Parameters<CheckRedirectChainParams>,
) -> String {
let req = shohei::api::RedirectChainRequest {
url,
timeout_secs: 10,
max_hops: max_hops.unwrap_or(20),
check_domain_age: check_domain_age.unwrap_or(false),
};
match shohei::api::check_redirect_chain(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check if a domain is parked for sale")]
async fn check_parked_domain(
&self,
Parameters(CheckParkedDomainParams { domain }): Parameters<CheckParkedDomainParams>,
) -> String {
let req = shohei::api::ParkedDomainRequest {
domain,
timeout_secs: 10,
};
match shohei::api::check_parked_domain(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check if a domain impersonates known brands")]
async fn check_brand_impersonation(
&self,
Parameters(CheckBrandImpersonationParams { domain }): Parameters<CheckBrandImpersonationParams>,
) -> String {
let req = shohei::api::BrandImpersonationRequest {
domain,
timeout_secs: 10,
};
match shohei::api::check_brand_impersonation(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check URL against URLhaus malware/phishing database (no API key required)")]
async fn check_url_reputation(
&self,
Parameters(CheckUrlReputationParams { url }): Parameters<CheckUrlReputationParams>,
) -> String {
let req = shohei::api::UrlhausRequest {
url,
timeout_secs: 10,
};
match shohei::api::check_url_reputation(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Analyze URL structure for phishing and brand impersonation signals")]
async fn check_url_analysis(
&self,
Parameters(CheckUrlAnalysisParams { url }): Parameters<CheckUrlAnalysisParams>,
) -> String {
let req = shohei::api::UrlAnalysisRequest { url };
match shohei::api::check_url_analysis(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Query Shodan InternetDB for open ports, CPEs, tags, and CVE associations (no API key required)")]
async fn check_shodan_ip(
&self,
Parameters(CheckShodanIpParams { ip }): Parameters<CheckShodanIpParams>,
) -> String {
let req = shohei::api::ShodanInternetDbRequest {
ip,
timeout_secs: 10,
};
match shohei::api::check_shodan_ip(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Compute HASSH SSH fingerprint from server KEXINIT packet")]
async fn check_ssh_fingerprint(
&self,
Parameters(CheckSshFingerprintParams { host, port }): Parameters<CheckSshFingerprintParams>,
) -> String {
let req = shohei::api::SshFingerprintRequest {
host,
port: port.unwrap_or(22),
timeout_secs: 10,
};
match shohei::api::check_ssh_fingerprint(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Assess domain compliance against CIS, PCI-DSS, HIPAA, and OWASP controls")]
async fn check_compliance(
&self,
Parameters(CheckComplianceParams { domain, url }): Parameters<CheckComplianceParams>,
) -> String {
let req = shohei::api::ComplianceRequest {
domain,
url,
timeout_secs: 15,
};
match shohei::api::check_compliance(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Query RIPE STAT for BGP route, AS name, prefix visibility, and routing status (no API key required)")]
async fn check_bgp_route(
&self,
Parameters(CheckBgpRouteParams { ip }): Parameters<CheckBgpRouteParams>,
) -> String {
let req = shohei::api::BgpRouteRequest {
ip,
timeout_secs: 10,
};
match shohei::api::check_bgp_route(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Compare authoritative DNS answers vs public resolvers to detect DNS hijacking, cache poisoning, or split-horizon configuration")]
async fn check_dns_hijacking(
&self,
Parameters(CheckDnsHijackingParams { domain, record_type }): Parameters<CheckDnsHijackingParams>,
) -> String {
let req = shohei::api::DnsHijackingRequest {
domain,
record_type: record_type.unwrap_or_else(|| "A".to_string()),
timeout_secs: 10,
};
match shohei::api::check_dns_hijacking(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Recursively resolve SPF include chains and count total DNS lookups against RFC 7208 limit of 10 (no API key required)")]
async fn check_spf_deep(
&self,
Parameters(CheckSpfDeepParams { domain }): Parameters<CheckSpfDeepParams>,
) -> String {
let req = shohei::api::SpfAnalysisRequest {
domain,
timeout_secs: 10,
};
match shohei::api::check_spf_deep(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Aggregate threat intelligence from 5+ sources (GreyNoise, Shodan, URLhaus, Brand Impersonation, CT) with unified risk scoring")]
async fn check_threat_intel_aggregate(
&self,
Parameters(CheckThreatIntelParams { target, include_sources }): Parameters<CheckThreatIntelParams>,
) -> String {
let req = shohei::api::ThreatIntelRequest {
target,
include_sources,
timeout_secs: 30,
};
match shohei::api::check_threat_intel_aggregate(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Get detailed risk score breakdown (0-100) with per-source confidence and actionable recommendation")]
async fn threat_intel_risk_score(
&self,
Parameters(ThreatIntelRiskScoreParams { target }): Parameters<ThreatIntelRiskScoreParams>,
) -> String {
match shohei::api::threat_intel_risk_score(&target).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect phishing indicators (brand impersonation, suspicious URLs, new domain registration) with phishing score")]
async fn phishing_detection_aggregate(
&self,
Parameters(PhishingDetectionParams { domain }): Parameters<PhishingDetectionParams>,
) -> String {
match shohei::api::phishing_detection_aggregate(&domain, 30).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "List all threat intelligence sources that flagged an IP as malicious with confidence levels")]
async fn malware_detected_sources(
&self,
Parameters(MalwareSourcesParams { ip }): Parameters<MalwareSourcesParams>,
) -> String {
match shohei::api::malware_detected_sources(&ip, 30).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Calculate 5-dimensional domain trust score (0-100): DNS consistency, TLS validity, threat reputation, registration age, infrastructure maturity")]
async fn check_domain_trust_score(
&self,
Parameters(DomainTrustScoreParams { domain }): Parameters<DomainTrustScoreParams>,
) -> String {
let req = shohei::api::DomainTrustScoreRequest {
domain,
timeout_secs: 30,
};
match shohei::api::check_domain_trust_score(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Calculate 5-dimensional IP trust score (0-100): reverse DNS, TLS presence, threat reputation, BGP status, RPKI validity")]
async fn check_ip_trust_score(
&self,
Parameters(IpTrustScoreParams { ip }): Parameters<IpTrustScoreParams>,
) -> String {
let req = shohei::api::IpTrustScoreRequest {
ip,
timeout_secs: 30,
};
match shohei::api::check_ip_trust_score(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Enumerate subdomains via Certificate Transparency, WHOIS nameservers, and DNS resolution")]
async fn enumerate_subdomains(
&self,
Parameters(SubdomainEnumerationParams { domain }): Parameters<SubdomainEnumerationParams>,
) -> String {
let req = shohei::api::SubdomainEnumerationRequest {
domain,
timeout_secs: 30,
};
match shohei::api::enumerate_subdomains(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Enrich WHOIS data with registration details, nameservers, and DNSSEC status")]
async fn enrich_whois(
&self,
Parameters(WhoisEnrichmentParams { domain }): Parameters<WhoisEnrichmentParams>,
) -> String {
let req = shohei::api::WhoisEnrichmentRequest {
domain,
timeout_secs: 30,
};
match shohei::api::enrich_whois(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Map DNS domain to threat sources (GreyNoise, Shodan, URLhaus, etc.) with risk scoring")]
async fn map_dns_threats(
&self,
Parameters(DnsThreatMappingParams { domain }): Parameters<DnsThreatMappingParams>,
) -> String {
let req = shohei::api::DnsThreatMappingRequest {
domain,
timeout_secs: 30,
};
match shohei::api::map_dns_threats(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Assess DNS takeover risk by checking nameserver redundancy, responsiveness, and dangling records")]
async fn assess_dns_takeover_risk(
&self,
Parameters(DnsTakeoverRiskParams { domain }): Parameters<DnsTakeoverRiskParams>,
) -> String {
let req = shohei::api::DnsTakeoverRiskRequest {
domain,
timeout_secs: 30,
};
match shohei::api::assess_dns_takeover_risk(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Brute-force common subdomain prefixes (www, mail, api, admin, staging, etc.)")]
async fn bruteforce_subdomains(
&self,
Parameters(SubdomainBruteforceParams { domain }): Parameters<SubdomainBruteforceParams>,
) -> String {
let req = shohei::api::SubdomainBruteforceRequest {
domain,
timeout_secs: 30,
};
match shohei::api::bruteforce_subdomains(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect typosquat domain variants (character omission, swaps, vowel substitution)")]
async fn detect_typosquats(
&self,
Parameters(TyposquatDetectionParams { domain }): Parameters<TyposquatDetectionParams>,
) -> String {
let req = shohei::api::TyposquatDetectionRequest {
domain,
timeout_secs: 30,
};
match shohei::api::detect_typosquats(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Enrich IP address with WHOIS, BGP, and ASN information")]
async fn enrich_ip_whois(
&self,
Parameters(IpWhoisEnrichmentParams { ip }): Parameters<IpWhoisEnrichmentParams>,
) -> String {
let req = shohei::api::IpWhoisEnrichmentRequest {
ip,
timeout_secs: 30,
};
match shohei::api::enrich_ip_whois(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Analyze domain age and registration timeline (new/young/established/legacy)")]
async fn analyze_domain_age(
&self,
Parameters(DomainAgeTimelineParams { domain }): Parameters<DomainAgeTimelineParams>,
) -> String {
let req = shohei::api::DomainAgeTimelineRequest {
domain,
timeout_secs: 30,
};
match shohei::api::analyze_domain_age(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Retrieve domain certificate history from Certificate Transparency logs")]
async fn get_certificate_history(
&self,
Parameters(CertificateHistoryParams { domain }): Parameters<CertificateHistoryParams>,
) -> String {
let req = shohei::api::CertificateHistoryRequest {
domain,
timeout_secs: 30,
};
match shohei::api::get_certificate_history(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Map threat actor infrastructure (IPs, nameservers, ASNs) and threat scoring")]
async fn map_threat_actor_infra(
&self,
Parameters(ThreatActorInfraParams { domain }): Parameters<ThreatActorInfraParams>,
) -> String {
let req = shohei::api::ThreatActorInfraRequest {
domain,
timeout_secs: 30,
};
match shohei::api::map_threat_actor_infra(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Analyze current DNS configuration as historical snapshot for forensics")]
async fn analyze_dns_history(
&self,
Parameters(DnsHistoryParams { domain }): Parameters<DnsHistoryParams>,
) -> String {
let req = shohei::api::DnsHistoryRequest {
domain,
timeout_secs: 30,
};
match shohei::api::analyze_dns_history(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Get IP geolocation: country, region, city, coordinates, timezone, ISP")]
async fn get_ip_geolocation(
&self,
Parameters(IpGeolocationParams { ip }): Parameters<IpGeolocationParams>,
) -> String {
let req = shohei::api::IpGeolocationRequest {
ip,
timeout_secs: 30,
};
match shohei::api::get_ip_geolocation(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Look up ASN (Autonomous System Number) and organization for IP address")]
async fn lookup_asn(
&self,
Parameters(AsnLookupParams { ip }): Parameters<AsnLookupParams>,
) -> String {
let req = shohei::api::AsnLookupRequest {
ip,
timeout_secs: 30,
};
match shohei::api::lookup_asn(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect WHOIS privacy protection (redacted/anonymized registrant information)")]
async fn detect_whois_privacy(
&self,
Parameters(WhoisPrivacyDetectionParams { domain }): Parameters<WhoisPrivacyDetectionParams>,
) -> String {
let req = shohei::api::WhoisPrivacyDetectionRequest {
domain,
timeout_secs: 30,
};
match shohei::api::detect_whois_privacy(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Assess email spoofing risk (SPF/DKIM/DMARC configuration analysis)")]
async fn assess_email_spoofing_risk(
&self,
Parameters(EmailSpoofingRiskParams { domain }): Parameters<EmailSpoofingRiskParams>,
) -> String {
let req = shohei::api::EmailSpoofingRiskRequest {
domain,
timeout_secs: 30,
};
match shohei::api::assess_email_spoofing_risk(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Validate TLS certificate: issuer, signature algorithm, expiry, trust level")]
async fn validate_tls_cert(
&self,
Parameters(TlsCertValidationParams { domain }): Parameters<TlsCertValidationParams>,
) -> String {
let req = shohei::api::TlsCertValidationRequest {
domain,
timeout_secs: 30,
};
match shohei::api::validate_tls_cert(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect infrastructure overlap between multiple domains (shared IPs, nameservers, ASNs)")]
async fn detect_infrastructure_overlap(
&self,
Parameters(InfrastructureOverlapParams { domains }): Parameters<InfrastructureOverlapParams>,
) -> String {
let req = shohei::api::InfrastructureOverlapRequest {
domains,
timeout_secs: 30,
};
match shohei::api::detect_infrastructure_overlap(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Fingerprint domain technology stack (web servers, frameworks, languages, tools)")]
async fn fingerprint_tech_stack(
&self,
Parameters(TechStackFingerprintingParams { domain }): Parameters<TechStackFingerprintingParams>,
) -> String {
let req = shohei::api::TechStackFingerprintingRequest {
domain,
timeout_secs: 30,
};
match shohei::api::fingerprint_tech_stack(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Analyze domain reputation: trust score, health, threats, age, email security")]
async fn analyze_domain_reputation(
&self,
Parameters(DomainReputationAnalysisParams { domain }): Parameters<DomainReputationAnalysisParams>,
) -> String {
let req = shohei::api::DomainReputationAnalysisRequest {
domain,
timeout_secs: 30,
};
match shohei::api::analyze_domain_reputation(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Define governance policy (blocklist, allowlist, rate limit, approval gate)")]
async fn define_policy(
&self,
Parameters(PolicyDefinitionParams { policy_name, policy_type }): Parameters<PolicyDefinitionParams>,
) -> String {
let req = shohei::api::PolicyDefinitionRequest {
policy_name,
policy_type,
rules: Vec::new(),
enabled: true,
};
match shohei::api::define_policy(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Add domains to blocklist (malicious, phishing, spam, malware)")]
async fn add_domain_blocklist(
&self,
Parameters(DomainBlocklistParams { domains }): Parameters<DomainBlocklistParams>,
) -> String {
let req = shohei::api::DomainBlocklistRequest {
domains,
reason: None,
expires_at: None,
};
match shohei::api::add_domain_blocklist(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Add IPs to reputation blocklist with threat level classification")]
async fn add_ip_blocklist(
&self,
Parameters(IpBlocklistParams { ips, threat_level }): Parameters<IpBlocklistParams>,
) -> String {
let req = shohei::api::IpReputationBlocklistRequest {
ips,
threat_level,
reason: None,
};
match shohei::api::add_ip_blocklist(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Add domains to allowlist (trusted, verified partners)")]
async fn add_allowlist(
&self,
Parameters(AllowlistParams { domains, reason }): Parameters<AllowlistParams>,
) -> String {
let req = shohei::api::AllowlistRequest {
domains,
reason,
trusted_until: None,
};
match shohei::api::add_allowlist(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Set rate limit policy for user (requests per minute/hour/day)")]
async fn set_rate_limit_policy(
&self,
Parameters(RateLimitPolicyParams { user_id, requests_per_minute }): Parameters<RateLimitPolicyParams>,
) -> String {
let req = shohei::api::RateLimitPolicyRequest {
user_id,
requests_per_minute,
requests_per_hour: requests_per_minute.saturating_mul(60),
requests_per_day: requests_per_minute.saturating_mul(1440),
};
match shohei::api::set_rate_limit_policy(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Create approval gate for sensitive operations (requires 2+ approvals)")]
async fn create_approval_gate(
&self,
Parameters(ApprovalGateParams { operation, requester }): Parameters<ApprovalGateParams>,
) -> String {
let req = shohei::api::ApprovalGateRequest {
operation,
requester,
justification: "Governance operation".to_string(),
urgency: "medium".to_string(),
};
match shohei::api::create_approval_gate(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Query audit logs for user actions and system events")]
async fn query_audit_logs(
&self,
Parameters(AuditLogQueryParams { days }): Parameters<AuditLogQueryParams>,
) -> String {
let req = shohei::api::AuditLogQueryRequest {
user: None,
action: None,
days,
};
match shohei::api::query_audit_logs(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Generate compliance report (SOC2, ISO27001, HIPAA, GDPR, PCI-DSS)")]
async fn generate_compliance_report(
&self,
Parameters(ComplianceReportParams { framework }): Parameters<ComplianceReportParams>,
) -> String {
let req = shohei::api::ComplianceReportRequest {
framework,
period: "monthly".to_string(),
};
match shohei::api::generate_compliance_report(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Set tool call access control (restrict by user, domain, or rate limit)")]
async fn set_tool_call_control(
&self,
Parameters(ToolCallControlParams { tool_name, allowed_users }): Parameters<ToolCallControlParams>,
) -> String {
let users: Vec<String> = allowed_users
.map(|u| u.split(',').map(|s| s.trim().to_string()).collect())
.unwrap_or_default();
let req = shohei::api::ToolCallControlRequest {
tool_name,
allowed_users: users,
allowed_domains: None,
max_calls_per_day: None,
};
match shohei::api::set_tool_call_control(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Classify domain/IP by risk level (critical, high, medium, low, unknown)")]
async fn classify_risk(
&self,
Parameters(RiskClassificationParams { target }): Parameters<RiskClassificationParams>,
) -> String {
let req = shohei::api::RiskClassificationRequest {
target,
historical_data: true,
};
match shohei::api::classify_risk(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Quarantine suspicious domains/IPs pending review")]
async fn quarantine_targets(
&self,
Parameters(QuarantineParams { targets, reason }): Parameters<QuarantineParams>,
) -> String {
let req = shohei::api::QuarantineRequest {
targets,
reason,
duration_hours: 72,
};
match shohei::api::quarantine_targets(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Alert on policy violations (blocklist match, rate limit, unauthorized access)")]
async fn alert_policy_violation(
&self,
Parameters(PolicyViolationAlertParams { domain, violation_type }): Parameters<PolicyViolationAlertParams>,
) -> String {
let req = shohei::api::PolicyViolationAlertRequest {
domain,
violation_type,
};
match shohei::api::alert_policy_violation(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check data residency compliance (EU, US, APAC, CA)")]
async fn check_data_residency(
&self,
Parameters(DataResidencyComplianceParams { domain, required_region }): Parameters<DataResidencyComplianceParams>,
) -> String {
let req = shohei::api::DataResidencyComplianceRequest {
domain,
required_region,
};
match shohei::api::check_data_residency(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Verify encryption status (TLS version, cipher strength, compliance)")]
async fn verify_encryption_status(
&self,
Parameters(EncryptionStatusParams { domain }): Parameters<EncryptionStatusParams>,
) -> String {
let req = shohei::api::EncryptionStatusRequest {
domain,
};
match shohei::api::verify_encryption_status(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Create policy exception (temporary or permanent)")]
async fn create_policy_exception(
&self,
Parameters(PolicyExceptionParams { target, exception_type }): Parameters<PolicyExceptionParams>,
) -> String {
let req = shohei::api::PolicyExceptionRequest {
target,
exception_type,
duration_days: Some(30),
justification: "Governance exception".to_string(),
};
match shohei::api::create_policy_exception(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Verify audit trail integrity and completeness")]
async fn verify_audit_trail(
&self,
Parameters(AuditTrailVerificationParams { domain }): Parameters<AuditTrailVerificationParams>,
) -> String {
let req = shohei::api::AuditTrailVerificationRequest {
domain,
days: 30,
};
match shohei::api::verify_audit_trail(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Measure governance policy effectiveness and ROI")]
async fn measure_policy_effectiveness(
&self,
Parameters(PolicyEffectivenessParams { days }): Parameters<PolicyEffectivenessParams>,
) -> String {
let req = shohei::api::PolicyEffectivenessRequest {
days,
};
match shohei::api::measure_policy_effectiveness(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Get incident response playbook with escalation procedures")]
async fn get_incident_response_playbook(
&self,
Parameters(IncidentResponsePlaybookParams { incident_type, severity }): Parameters<IncidentResponsePlaybookParams>,
) -> String {
let req = shohei::api::IncidentResponsePlaybookRequest {
incident_type,
severity,
};
match shohei::api::get_incident_response_playbook(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Assess security posture maturity level and improvement areas")]
async fn assess_security_posture(
&self,
Parameters(SecurityPostureAssessmentParams { domain }): Parameters<SecurityPostureAssessmentParams>,
) -> String {
let req = shohei::api::SecurityPostureAssessmentRequest {
domain,
};
match shohei::api::assess_security_posture(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Run breach simulation / tabletop exercise (phishing, credential theft, data exfil, lateral movement)")]
async fn run_breach_simulation(
&self,
Parameters(BreachSimulationParams { simulation_type }): Parameters<BreachSimulationParams>,
) -> String {
let req = shohei::api::BreachSimulationRequest {
simulation_type,
scope: "organization_wide".to_string(),
};
match shohei::api::run_breach_simulation(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect personally identifiable information (PII) in domain/system")]
async fn detect_pii(
&self,
Parameters(PiiDetectionParams { domain }): Parameters<PiiDetectionParams>,
) -> String {
let req = shohei::api::PiiDetectionRequest {
domain,
scan_depth: "deep".to_string(),
};
match shohei::api::detect_pii(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Anonymize PII (redaction, pseudonymization, generalization)")]
async fn anonymize_pii(
&self,
Parameters(PiiAnonymizationParams { domain }): Parameters<PiiAnonymizationParams>,
) -> String {
let req = shohei::api::PiiAnonymizationRequest {
domain,
pii_types: vec!["email".to_string(), "phone".to_string(), "ssn".to_string()],
retention_days: None,
};
match shohei::api::anonymize_pii(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Define data retention policy and auto-purge schedule")]
async fn define_retention_policy(
&self,
Parameters(DataRetentionPolicyParams { domain }): Parameters<DataRetentionPolicyParams>,
) -> String {
let req = shohei::api::DataRetentionPolicyRequest {
domain,
data_type: "customer_data".to_string(),
retention_days: 365,
};
match shohei::api::define_retention_policy(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Assess GDPR compliance (processing, consent, DPIA, documentation)")]
async fn assess_gdpr_compliance(
&self,
Parameters(GdprComplianceParams { domain }): Parameters<GdprComplianceParams>,
) -> String {
let req = shohei::api::GdprComplianceRequest {
domain,
assessment_scope: "processing".to_string(),
};
match shohei::api::assess_gdpr_compliance(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Assess HIPAA compliance (technical, administrative, physical controls)")]
async fn assess_hipaa_compliance(
&self,
Parameters(HipaaComplianceParams { domain }): Parameters<HipaaComplianceParams>,
) -> String {
let req = shohei::api::HipaaComplianceRequest {
domain,
check_type: "technical".to_string(),
};
match shohei::api::assess_hipaa_compliance(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Assess PCI-DSS compliance for payment systems")]
async fn assess_pci_dss_compliance(
&self,
Parameters(PciDssComplianceParams { domain }): Parameters<PciDssComplianceParams>,
) -> String {
let req = shohei::api::PciDssComplianceRequest {
domain,
requirement: None,
};
match shohei::api::assess_pci_dss_compliance(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Classify data by sensitivity level (public, internal, confidential, restricted)")]
async fn classify_data(
&self,
Parameters(DataClassificationParams { domain }): Parameters<DataClassificationParams>,
) -> String {
let req = shohei::api::DataClassificationRequest {
domain,
data_inventory_provided: true,
};
match shohei::api::classify_data(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Apply data masking rules to sensitive fields")]
async fn apply_data_masking(
&self,
Parameters(DataMaskingParams { domain }): Parameters<DataMaskingParams>,
) -> String {
let req = shohei::api::DataMaskingRequest {
domain,
masking_rules: vec!["email_mask".to_string(), "phone_mask".to_string()],
};
match shohei::api::apply_data_masking(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Delete expired data according to retention policies")]
async fn delete_expired_data(
&self,
Parameters(DataDeletionParams { domain }): Parameters<DataDeletionParams>,
) -> String {
let req = shohei::api::DataDeletionRequest {
domain,
data_types: vec!["logs".to_string(), "backups".to_string()],
reason: "retention_expired".to_string(),
};
match shohei::api::delete_expired_data(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Process data subject access request (DSAR / subject access rights)")]
async fn process_data_subject_access(
&self,
Parameters(DataSubjectAccessParams { domain, subject_identifier }): Parameters<DataSubjectAccessParams>,
) -> String {
let req = shohei::api::DataSubjectAccessRequest {
domain,
subject_identifier,
data_types: None,
};
match shohei::api::process_data_subject_access(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Manage user consent preferences (marketing, analytics, processing)")]
async fn manage_consent(
&self,
Parameters(ConsentManagementParams { domain }): Parameters<ConsentManagementParams>,
) -> String {
let req = shohei::api::ConsentManagementRequest {
domain,
consent_type: "processing".to_string(),
};
match shohei::api::manage_consent(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Create cryptographic signature for audit trail (RSA, ECDSA, EdDSA)")]
async fn sign_audit_trail(
&self,
Parameters(CryptographicSignatureParams { domain }): Parameters<CryptographicSignatureParams>,
) -> String {
let req = shohei::api::CryptographicSignatureRequest {
domain,
algorithm: "ECDSA".to_string(),
document_hash: "sha256".to_string(),
};
match shohei::api::sign_audit_trail(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Verify audit trail immutability (hash chain, blockchain, HSM)")]
async fn verify_audit_immutability(
&self,
Parameters(AuditTrailImmutabilityParams { domain }): Parameters<AuditTrailImmutabilityParams>,
) -> String {
let req = shohei::api::AuditTrailImmutabilityRequest {
domain,
days: 90,
};
match shohei::api::verify_audit_immutability(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Conduct privacy impact assessment (DPIA/PIA)")]
async fn conduct_privacy_assessment(
&self,
Parameters(PrivacyImpactAssessmentParams { domain }): Parameters<PrivacyImpactAssessmentParams>,
) -> String {
let req = shohei::api::PrivacyImpactAssessmentRequest {
domain,
processing_activity: "Data processing".to_string(),
};
match shohei::api::conduct_privacy_assessment(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Notify affected individuals of privacy breach (GDPR 72-hour requirement)")]
async fn notify_privacy_breach(
&self,
Parameters(PrivacyBreachNotificationParams { domain, breach_scope, breach_type }): Parameters<PrivacyBreachNotificationParams>,
) -> String {
let req = shohei::api::PrivacyBreachNotificationRequest {
domain,
breach_scope,
breach_type,
};
match shohei::api::notify_privacy_breach(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Request RFC 3161 timestamp from TSA (timestamp authority)")]
async fn request_rfc3161_timestamp(
&self,
Parameters(Rfc3161TimestampParams { document_hash }): Parameters<Rfc3161TimestampParams>,
) -> String {
let req = shohei::api::Rfc3161TimestampRequest {
document_hash,
hash_algorithm: "SHA256".to_string(),
tsa_url: None,
};
match shohei::api::request_rfc3161_timestamp(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Validate RFC 3161 timestamp token and TSA signature")]
async fn validate_timestamp(
&self,
Parameters(TimestampValidationParams { timestamp_token }): Parameters<TimestampValidationParams>,
) -> String {
let req = shohei::api::TimestampValidationRequest {
timestamp_token,
document_hash: "".to_string(),
};
match shohei::api::validate_timestamp(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Add entry to Sigstore Rekor transparency log (immutable audit trail)")]
async fn add_sigstore_rekor_entry(
&self,
Parameters(SignstoreRekorParams { artifact_hash }): Parameters<SignstoreRekorParams>,
) -> String {
let req = shohei::api::SignstoreRekorEntryRequest {
artifact_hash,
signature: "".to_string(),
certificate: "".to_string(),
};
match shohei::api::add_sigstore_rekor_entry(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Verify Sigstore Rekor entry consistency and inclusion proofs")]
async fn verify_rekor_entry(
&self,
Parameters(RekorVerificationParams { entry_uuid }): Parameters<RekorVerificationParams>,
) -> String {
let req = shohei::api::RekorEntryVerificationRequest {
entry_uuid,
merkle_tree_leaf_hash: "".to_string(),
};
match shohei::api::verify_rekor_entry(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Generate zero-knowledge proof (merkle, range, authentication proofs)")]
async fn generate_zk_proof(
&self,
Parameters(ZkProofGenerationParams { circuit_type }): Parameters<ZkProofGenerationParams>,
) -> String {
let req = shohei::api::ZkProofGenerationRequest {
statement: "".to_string(),
witness: "".to_string(),
circuit_type,
};
match shohei::api::generate_zk_proof(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Verify zero-knowledge proof (correctness and security)")]
async fn verify_zk_proof(
&self,
Parameters(ZkProofVerificationParams { proof }): Parameters<ZkProofVerificationParams>,
) -> String {
let req = shohei::api::ZkProofVerificationRequest {
proof,
verification_key: "".to_string(),
statement: "".to_string(),
};
match shohei::api::verify_zk_proof(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Create escrow agreement with release conditions")]
async fn create_escrow_agreement(
&self,
Parameters(EscrowAgreementParams { payer, payee, amount }): Parameters<EscrowAgreementParams>,
) -> String {
let req = shohei::api::EscrowAgreementRequest {
payer,
payee,
amount,
release_conditions: Vec::new(),
};
match shohei::api::create_escrow_agreement(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Release funds from escrow upon condition satisfaction")]
async fn release_escrow(
&self,
Parameters(EscrowReleaseParams { escrow_id }): Parameters<EscrowReleaseParams>,
) -> String {
let req = shohei::api::EscrowReleaseRequest {
escrow_id,
release_reason: "Conditions satisfied".to_string(),
};
match shohei::api::release_escrow(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Notarize document digitally (blockchain, TSA, or ledger)")]
async fn notarize_document(
&self,
Parameters(DigitalNotarizationParams { document_hash }): Parameters<DigitalNotarizationParams>,
) -> String {
let req = shohei::api::DigitalNotarizationRequest {
document_hash,
document_type: "".to_string(),
notary_type: "public_blockchain".to_string(),
};
match shohei::api::notarize_document(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Verify digital notarization (integrity and authenticity)")]
async fn verify_notarization(
&self,
Parameters(NotarizationVerificationParams { notarization_id }): Parameters<NotarizationVerificationParams>,
) -> String {
let req = shohei::api::NotarizationVerificationRequest {
notarization_id,
document_hash: "".to_string(),
};
match shohei::api::verify_notarization(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Generate and manage cryptographic keys (RSA, ECDSA, EdDSA)")]
async fn manage_cryptographic_key(
&self,
Parameters(KeyManagementParams { key_type }): Parameters<KeyManagementParams>,
) -> String {
let req = shohei::api::KeyManagementRequest {
key_type,
key_size: 2048,
usage: "signing".to_string(),
};
match shohei::api::manage_cryptographic_key(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Rotate cryptographic key with transition period")]
async fn rotate_key(
&self,
Parameters(KeyRotationParams { key_id }): Parameters<KeyRotationParams>,
) -> String {
let req = shohei::api::KeyRotationRequest {
key_id,
new_key_size: None,
};
match shohei::api::rotate_key(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Bind audit trail entries cryptographically (hash chain, merkle tree)")]
async fn bind_audit_trail(
&self,
Parameters(AuditTrailBindingParams { audit_entries }): Parameters<AuditTrailBindingParams>,
) -> String {
let req = shohei::api::AuditTrailBindingRequest {
audit_entries,
binding_type: "hash_chain".to_string(),
};
match shohei::api::bind_audit_trail(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Perform cryptographic operations via Hardware Security Module (HSM)")]
async fn integrate_hsm(
&self,
Parameters(HsmIntegrationParams { operation }): Parameters<HsmIntegrationParams>,
) -> String {
let req = shohei::api::HsmIntegrationRequest {
operation,
hsm_slot: 0,
};
match shohei::api::integrate_hsm(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Verify cryptographic compliance (FIPS140-2/3, Common Criteria)")]
async fn verify_crypto_compliance(
&self,
Parameters(CryptographicComplianceParams { domain }): Parameters<CryptographicComplianceParams>,
) -> String {
let req = shohei::api::CryptographicComplianceRequest {
domain,
standard: "FIPS140-3".to_string(),
};
match shohei::api::verify_crypto_compliance(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Resolve shortened URLs (bit.ly, t.co, etc.) through full redirect chain")]
async fn check_url_unshorten(
&self,
Parameters(UrlUnshortenParams { url }): Parameters<UrlUnshortenParams>,
) -> String {
let req = shohei::api::UrlUnshortenRequest { url, timeout_secs: 10 };
match shohei::api::check_url_unshorten(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "JA4H HTTP client fingerprinting — analyze request headers to identify client type")]
async fn check_ja4h_fingerprint(
&self,
Parameters(Ja4hFingerprintParams { url }): Parameters<Ja4hFingerprintParams>,
) -> String {
let req = shohei::api::Ja4hFingerprintRequest { url, timeout_secs: 10 };
match shohei::api::check_ja4h_fingerprint(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Multi-source URL threat check combining URLhaus + phishing + domain age")]
async fn check_url_safety_multi(
&self,
Parameters(UrlSafetyMultiParams { url }): Parameters<UrlSafetyMultiParams>,
) -> String {
let req = shohei::api::UrlSafetyMultiRequest { url, timeout_secs: 10 };
match shohei::api::check_url_safety_multi(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect open redirect vulnerabilities in URL redirect chains")]
async fn check_url_redirect_threat(
&self,
Parameters(UrlRedirectThreatParams { url }): Parameters<UrlRedirectThreatParams>,
) -> String {
let req = shohei::api::UrlRedirectThreatRequest { url, timeout_secs: 10 };
match shohei::api::check_url_redirect_threat(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check if domain maps to publicly accessible AWS S3 bucket")]
async fn check_s3_bucket_exposure(
&self,
Parameters(S3BucketExposureParams { domain }): Parameters<S3BucketExposureParams>,
) -> String {
let req = shohei::api::S3BucketExposureRequest { domain, timeout_secs: 10 };
match shohei::api::check_s3_bucket_exposure(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect cloud provider (AWS/GCP/Azure/Cloudflare) via CNAME and IP patterns")]
async fn check_cloud_provider(
&self,
Parameters(CloudProviderParams { domain }): Parameters<CloudProviderParams>,
) -> String {
let req = shohei::api::CloudProviderRequest { domain, timeout_secs: 10 };
match shohei::api::check_cloud_provider(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "CIS-lite benchmark: check HTTP security headers, server disclosure, directory listing")]
async fn check_server_hardening(
&self,
Parameters(ServerHardeningParams { url }): Parameters<ServerHardeningParams>,
) -> String {
let req = shohei::api::ServerHardeningRequest { url, timeout_secs: 10 };
match shohei::api::check_server_hardening(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect dangling DNS records pointing to deleted cloud resources")]
async fn check_dangling_dns(
&self,
Parameters(DanglingDnsParams { domain }): Parameters<DanglingDnsParams>,
) -> String {
let req = shohei::api::DanglingDnsRequest { domain, timeout_secs: 10 };
match shohei::api::check_dangling_dns(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check username availability on GitHub, Twitter, LinkedIn, Reddit, HackerNews")]
async fn check_username_osint(
&self,
Parameters(UsernameOsintParams { username }): Parameters<UsernameOsintParams>,
) -> String {
let req = shohei::api::UsernameOsintRequest { username, timeout_secs: 10 };
match shohei::api::check_username_osint(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Email intelligence: SMTP validation + breach check + SPF/DKIM assessment")]
async fn check_email_intel(
&self,
Parameters(EmailIntelParams { email }): Parameters<EmailIntelParams>,
) -> String {
let req = shohei::api::EmailIntelRequest { email, timeout_secs: 10 };
match shohei::api::check_email_intel(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Organization footprinting: WHOIS, tech stack, social media profiles")]
async fn check_organization_intel(
&self,
Parameters(OrganizationIntelParams { domain }): Parameters<OrganizationIntelParams>,
) -> String {
let req = shohei::api::OrganizationIntelRequest { domain, timeout_secs: 10 };
match shohei::api::check_organization_intel(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Map social media handles linked to a domain/brand")]
async fn check_social_media_presence(
&self,
Parameters(SocialMediaPresenceParams { domain }): Parameters<SocialMediaPresenceParams>,
) -> String {
let req = shohei::api::SocialMediaPresenceRequest { domain, timeout_secs: 10 };
match shohei::api::check_social_media_presence(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "ASN reputation scoring: combine DNSBL + BGP visibility + threat intel")]
async fn check_asn_reputation(
&self,
Parameters(AsnReputationParams { asn }): Parameters<AsnReputationParams>,
) -> String {
let req = shohei::api::AsnReputationRequest { asn, timeout_secs: 10 };
match shohei::api::check_asn_reputation(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Historical BGP route changes via RIPE STAT")]
async fn check_bgp_hijack_history(
&self,
Parameters(BgpHijackHistoryParams { prefix }): Parameters<BgpHijackHistoryParams>,
) -> String {
let req = shohei::api::BgpHijackHistoryRequest { prefix, timeout_secs: 10 };
match shohei::api::check_bgp_hijack_history(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Comprehensive attack surface score: open ports + CVEs + BGP + RPKI + threat intel")]
async fn check_network_exposure_score(
&self,
Parameters(NetworkExposureScoreParams { target }): Parameters<NetworkExposureScoreParams>,
) -> String {
let req = shohei::api::NetworkExposureScoreRequest { target, timeout_secs: 10 };
match shohei::api::check_network_exposure_score(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check if 169.254.169.254 IMDS endpoint is accessible")]
async fn check_cloud_metadata_exposure(
&self,
Parameters(CloudMetadataExposureParams { domain }): Parameters<CloudMetadataExposureParams>,
) -> String {
let req = shohei::api::CloudMetadataExposureRequest { domain, timeout_secs: 10 };
match shohei::api::check_cloud_metadata_exposure(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect Azure Blob Storage CNAME exposure")]
async fn check_azure_blob_exposure(
&self,
Parameters(AzureBlobExposureParams { domain }): Parameters<AzureBlobExposureParams>,
) -> String {
let req = shohei::api::AzureBlobExposureRequest { domain, timeout_secs: 10 };
match shohei::api::check_azure_blob_exposure(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect Google Cloud Storage CNAME exposure")]
async fn check_gcs_bucket_exposure(
&self,
Parameters(GcsBucketExposureParams { domain }): Parameters<GcsBucketExposureParams>,
) -> String {
let req = shohei::api::GcsBucketExposureRequest { domain, timeout_secs: 10 };
match shohei::api::check_gcs_bucket_exposure(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Analyze CORS policy from HTTP response headers")]
async fn check_cors_policy(
&self,
Parameters(CorsPolicyParams { url }): Parameters<CorsPolicyParams>,
) -> String {
let req = shohei::api::CorsPolicyRequest { url, timeout_secs: 10 };
match shohei::api::check_cors_policy(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Fetch and parse .well-known/security.txt (RFC 9116)")]
async fn check_security_txt(
&self,
Parameters(SecurityTxtParams { domain }): Parameters<SecurityTxtParams>,
) -> String {
let req = shohei::api::SecurityTxtRequest { domain, timeout_secs: 10 };
match shohei::api::check_security_txt(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Parse and analyze JWT token security (alg, exp, none attack)")]
async fn check_jwt_security(
&self,
Parameters(JwtSecurityParams { token }): Parameters<JwtSecurityParams>,
) -> String {
let req = shohei::api::JwtSecurityRequest { token };
match shohei::api::check_jwt_security(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Inspect HTTP Set-Cookie headers for Secure, HttpOnly, SameSite flags")]
async fn check_cookie_security(
&self,
Parameters(CookieSecurityParams { url }): Parameters<CookieSecurityParams>,
) -> String {
let req = shohei::api::CookieSecurityRequest { url, timeout_secs: 10 };
match shohei::api::check_cookie_security(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Deep CSP analysis: unsafe-inline, unsafe-eval, wildcard sources")]
async fn check_csp_advanced(
&self,
Parameters(CspAdvancedParams { url }): Parameters<CspAdvancedParams>,
) -> String {
let req = shohei::api::CspAdvancedRequest { url, timeout_secs: 10 };
match shohei::api::check_csp_advanced(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Probe common sensitive paths (.env, package.json, .git/config, etc.)")]
async fn check_exposed_files(
&self,
Parameters(ExposedFilesParams { domain }): Parameters<ExposedFilesParams>,
) -> String {
let req = shohei::api::ExposedFilesRequest { domain, timeout_secs: 10 };
match shohei::api::check_exposed_files(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Query npm registry for package metadata, version, maintainers, typosquatting")]
async fn check_npm_package_security(
&self,
Parameters(NpmPackageSecurityParams { package }): Parameters<NpmPackageSecurityParams>,
) -> String {
let req = shohei::api::NpmPackageSecurityRequest { package, timeout_secs: 10 };
match shohei::api::check_npm_package_security(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Query PyPI for package metadata, maintainers, security indicators")]
async fn check_pypi_package_security(
&self,
Parameters(PypiPackageSecurityParams { package }): Parameters<PypiPackageSecurityParams>,
) -> String {
let req = shohei::api::PypiPackageSecurityRequest { package, timeout_secs: 10 };
match shohei::api::check_pypi_package_security(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check if internal package name exists on public registries (npm, PyPI, crates.io)")]
async fn check_dependency_confusion(
&self,
Parameters(DependencyConfusionParams { internal_package }): Parameters<DependencyConfusionParams>,
) -> String {
let req = shohei::api::DependencyConfusionRequest { internal_package, timeout_secs: 10 };
match shohei::api::check_dependency_confusion(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect accidentally exposed SBOM files (/sbom.json, /bom.xml, /.well-known/sbom)")]
async fn check_sbom_disclosure(
&self,
Parameters(SbomDisclosureParams { domain }): Parameters<SbomDisclosureParams>,
) -> String {
let req = shohei::api::SbomDisclosureRequest { domain, timeout_secs: 10 };
match shohei::api::check_sbom_disclosure(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Fetch and analyze robots.txt — discover sensitive disallowed paths (admin, backup, config, api), sitemap URLs, and crawl-delay settings")]
async fn check_robots_txt(
&self,
Parameters(RobotsTxtParams { domain }): Parameters<RobotsTxtParams>,
) -> String {
let req = shohei::api::RobotsTxtRequest { domain, timeout_secs: 10 };
match shohei::api::check_robots_txt(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Discover all accessible .well-known/ endpoints on a domain — OIDC, security.txt, MTA-STS, JWKS, ai-plugin.json, assetlinks, SBOM, and more")]
async fn check_well_known(
&self,
Parameters(WellKnownParams { domain }): Parameters<WellKnownParams>,
) -> String {
let req = shohei::api::WellKnownRequest { domain, timeout_secs: 10 };
match shohei::api::check_well_known(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Audit OAuth 2.0 / OIDC configuration — check for implicit flow, PKCE support, grant types, and response types from .well-known/openid-configuration")]
async fn check_oauth_oidc(
&self,
Parameters(OauthOidcParams { domain }): Parameters<OauthOidcParams>,
) -> String {
let req = shohei::api::OauthOidcRequest { domain, timeout_secs: 10 };
match shohei::api::check_oauth_oidc(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check certificate pinning configuration — Expect-CT enforce mode, HPKP (deprecated), CAA iodef reporting")]
async fn check_cert_pinning(
&self,
Parameters(CertPinningParams { domain }): Parameters<CertPinningParams>,
) -> String {
let req = shohei::api::CertPinningRequest { domain, timeout_secs: 10 };
match shohei::api::check_cert_pinning(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Probe for exposed API/debug endpoints — Spring Actuator, Swagger UI, GraphQL, phpinfo, server-status, and version disclosure headers")]
async fn check_api_exposure(
&self,
Parameters(ApiExposureParams { domain }): Parameters<ApiExposureParams>,
) -> String {
let req = shohei::api::ApiExposureRequest { domain, timeout_secs: 10 };
match shohei::api::check_api_exposure(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Probe for unauthenticated database access — Redis (6379), MongoDB (27017), Elasticsearch (9200), Memcached (11211), CouchDB (5984)")]
async fn check_exposed_databases(
&self,
Parameters(ExposedDatabasesParams { host }): Parameters<ExposedDatabasesParams>,
) -> String {
let req = shohei::api::ExposedDatabasesRequest { host, timeout_secs: 10 };
match shohei::api::check_exposed_databases(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect exposed container orchestration APIs — Docker API (2375/2376), Kubernetes API (6443), etcd (2379)")]
async fn check_container_exposure(
&self,
Parameters(ContainerExposureParams { host }): Parameters<ContainerExposureParams>,
) -> String {
let req = shohei::api::ContainerExposureRequest { host, timeout_secs: 10 };
match shohei::api::check_container_exposure(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Fingerprint running services via banner grabbing — SSH version, FTP, SMTP, MySQL, PostgreSQL, Redis with security notes")]
async fn check_service_fingerprint(
&self,
Parameters(ServiceFingerprintParams { host, ports }): Parameters<ServiceFingerprintParams>,
) -> String {
let req = shohei::api::ServiceFingerprintRequest { host, ports, timeout_secs: 10 };
match shohei::api::check_service_fingerprint(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Score a domain name for DGA (Domain Generation Algorithm) risk using entropy, vowel ratio, digit ratio, and consonant cluster analysis")]
async fn check_dga_risk(
&self,
Parameters(DgaRiskParams { domain }): Parameters<DgaRiskParams>,
) -> String {
let req = shohei::api::DgaRiskRequest { domain };
match shohei::api::check_dga_risk(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Detect subdomain takeover vulnerabilities across 30+ cloud services — GitHub Pages, Heroku, Netlify, Vercel, Azure, AWS, Shopify, Fastly, and more")]
async fn check_subdomain_takeover(
&self,
Parameters(SubdomainTakeoverParams { domain }): Parameters<SubdomainTakeoverParams>,
) -> String {
let req = shohei::api::SubdomainTakeoverRequest { domain, timeout_secs: 15 };
match shohei::api::check_subdomain_takeover(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Query RIPE Stat passive DNS for historical DNS records — IP changes, old nameservers, past A/CNAME records (no API key required)")]
async fn check_passive_dns(
&self,
Parameters(PassiveDnsParams { query }): Parameters<PassiveDnsParams>,
) -> String {
let req = shohei::api::PassiveDnsRequest { query, timeout_secs: 15 };
match shohei::api::check_passive_dns(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Discover Azure AD / Entra ID tenant information — tenant ID, federation type (ADFS/Managed), OIDC metadata via public Microsoft Graph endpoints")]
async fn check_azure_ad_exposure(
&self,
Parameters(AzureAdExposureParams { domain }): Parameters<AzureAdExposureParams>,
) -> String {
let req = shohei::api::AzureAdExposureRequest { domain, timeout_secs: 10 };
match shohei::api::check_azure_ad_exposure(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Check DKIM key strength — detect weak 1024-bit RSA keys, validate 2048-bit and Ed25519 keys across common selectors (default, google, selector1/2, etc.)")]
async fn check_dkim_key_strength(
&self,
Parameters(DkimKeyStrengthParams { domain, selectors }): Parameters<DkimKeyStrengthParams>,
) -> String {
let req = shohei::api::DkimKeyStrengthRequest { domain, selectors, timeout_secs: 15 };
match shohei::api::check_dkim_key_strength(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Deep MX server security audit — STARTTLS support, banner leak, ESMTP features for each MX server via live SMTP connection")]
async fn check_mx_security(
&self,
Parameters(MxSecurityParams { domain }): Parameters<MxSecurityParams>,
) -> String {
let req = shohei::api::MxSecurityRequest { domain, timeout_secs: 15 };
match shohei::api::check_mx_security(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
#[tool(description = "Comprehensive attack surface score (0-100) — aggregates TLS, web security headers, email security, and network exposure into a CVSS-like composite score")]
async fn check_attack_surface(
&self,
Parameters(AttackSurfaceParams { domain }): Parameters<AttackSurfaceParams>,
) -> String {
let req = shohei::api::AttackSurfaceRequest { domain, timeout_secs: 20 };
match shohei::api::check_attack_surface(&req).await {
Ok(result) => serde_json::to_string_pretty(&result).unwrap_or_default(),
Err(e) => serde_json::json!({"error": e.to_string()}).to_string(),
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
eprintln!("[shohei-mcp] Server started");
ShoheiServer
.serve(rmcp::transport::stdio())
.await?
.waiting()
.await?;
eprintln!("[shohei-mcp] Server exiting");
Ok(())
}