hen 0.19.0

Run protocol-aware API request collections from the command line or through MCP.
Documentation
pub(super) fn normalize_legacy_collection_header(input: &str) -> String {
    let lines: Vec<&str> = input.lines().collect();
    let Some(section_index) = lines.iter().position(|line| line.trim() == "---") else {
        return input.to_string();
    };

    let mut header_indices = Vec::new();
    let mut syntax_start = None;

    for (index, line) in lines.iter().take(section_index).enumerate() {
        let trimmed = line.trim();
        if trimmed.is_empty() {
            continue;
        }

        if is_collection_preamble_line(trimmed) {
            syntax_start = Some(index);
            break;
        }

        if is_request_line(trimmed) {
            return input.to_string();
        }

        header_indices.push(index);
    }

    if header_indices.is_empty() {
        return input.to_string();
    }

    if lines
        .iter()
        .take(section_index)
        .enumerate()
        .filter(|(index, _)| Some(*index) >= syntax_start)
        .any(|(_, line)| {
            let trimmed = line.trim();
            !trimmed.is_empty() && !is_collection_preamble_line(trimmed)
        })
    {
        return input.to_string();
    }

    let mut rewritten: Vec<String> = lines.iter().map(|line| (*line).to_string()).collect();
    rewritten[header_indices[0]] = format!("name = {}", lines[header_indices[0]].trim());

    if header_indices.len() > 1 {
        let description = header_indices[1..]
            .iter()
            .map(|index| lines[*index].trim())
            .collect::<Vec<_>>()
            .join(" ");
        rewritten[header_indices[1]] = format!("description = {}", description);
        for index in &header_indices[2..] {
            rewritten[*index].clear();
        }
    }

    let mut output = rewritten.join("\n");
    if input.ends_with('\n') {
        output.push('\n');
    }
    output
}

fn is_collection_preamble_line(line: &str) -> bool {
    let trimmed = line.trim_start();
    trimmed.starts_with("name")
        || trimmed.starts_with("description")
        || trimmed.starts_with("env ")
        || trimmed.starts_with("timeout ")
        || trimmed.starts_with("poll_until ")
        || trimmed.starts_with("poll_every ")
        || trimmed.starts_with('$')
        || trimmed.starts_with('*')
        || trimmed.starts_with('?')
        || trimmed.starts_with('!')
        || trimmed.starts_with("scalar ")
        || trimmed.starts_with("schema ")
}

fn is_request_line(line: &str) -> bool {
    let trimmed = line.trim_start();
    trimmed.starts_with("GET ")
        || trimmed.starts_with("PUT ")
        || trimmed.starts_with("POST ")
        || trimmed.starts_with("PATCH ")
        || trimmed.starts_with("DELETE ")
        || trimmed.starts_with("OPTIONS ")
        || trimmed.starts_with("protocol ")
        || trimmed.starts_with("session ")
        || trimmed.starts_with("operation ")
        || trimmed.starts_with("variables ")
        || trimmed.starts_with("call ")
        || trimmed.starts_with("tool ")
        || trimmed.starts_with("arguments ")
        || trimmed == "receive"
        || trimmed.starts_with("within ")
        || trimmed.starts_with("timeout ")
        || trimmed.starts_with("poll_until ")
        || trimmed.starts_with("poll_every ")
        || trimmed.starts_with("protocol_version ")
        || trimmed.starts_with("client_name ")
        || trimmed.starts_with("client_version ")
        || trimmed.starts_with("capabilities ")
        || trimmed.starts_with('~')
        || trimmed.starts_with('&')
        || trimmed.starts_with('^')
        || trimmed.starts_with("<<")
        || trimmed.starts_with('>')
}