use crate::{
config::McpOAuthConfig,
mcp::{McpError, McpResult},
};
use base64::Engine;
use chrono::Utc;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use sha2::{Digest, Sha256};
use std::{
collections::BTreeMap,
fmt, fs, io,
io::{Read, Write},
net::{TcpListener, TcpStream},
path::{Path, PathBuf},
sync::{
Arc, Mutex,
atomic::{AtomicBool, Ordering},
mpsc::Receiver,
},
time::{Duration, Instant},
};
const TOKEN_FILE_MODE: u32 = 0o600;
const HTTP_CLIENT_NAME: &str = "magi-code";
const REFRESH_SKEW_SECONDS: i64 = 60;
pub(crate) const CALLBACK_PATH: &str = "/mcp/oauth/callback";
pub(crate) const LOGIN_WAIT_TIMEOUT: Duration = Duration::from_secs(300);
const CALLBACK_STREAM_TIMEOUT: Duration = Duration::from_secs(5);
mod discovery;
mod login;
mod storage;
mod tokens;
pub(crate) use discovery::{AuthorizationServerMetadata, parse_www_authenticate_resource_metadata};
pub(crate) use login::{bind_callback_listener, capture_loopback_or_manual_code, prepare_login};
pub(crate) use storage::{StoredToken, delete_token, write_token};
pub(crate) use tokens::{TokenProvider, auth_status, exchange_code, stored_token_from_response};
use discovery::{
discover_authorization_server, discover_protected_resource, register_client,
select_authorization_server,
};
use storage::read_token;
use discovery::{sanitize_url, validate_oauth_endpoint};
use storage::{read_token_locked, validate_token_url, write_token_if_unchanged};
use tokens::read_oauth_success_text;