oauth_cognito_dynamodb_mcp_server/
oauth_cognito_dynamodb_mcp_server.rs1use oauth_provider_rs::CognitoOAuthConfig;
52use remote_mcp_kernel::{
53 config::Config, error::AppResult, microkernel::create_full_cognito_microkernel_dynamodb,
54};
55use std::env;
56use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
57
58#[tokio::main]
59async fn main() -> AppResult<()> {
60 dotenv::dotenv().ok();
62
63 let config = Config::from_env()?;
65
66 init_tracing(&config)?;
68
69 tracing::info!("Starting MCP OAuth server with Cognito and DynamoDB storage...");
70
71 let cognito_config = CognitoOAuthConfig {
73 client_id: config.cognito.client_id.clone(),
74 client_secret: config.cognito.client_secret.clone().unwrap_or_default(),
75 redirect_uri: format!(
76 "http://{}:{}/oauth/callback",
77 config.server.host, config.server.port
78 ),
79 scope: config.cognito.scope.clone(),
80 provider_name: "cognito".to_string(),
81 };
82
83 let table_name =
85 env::var("DYNAMODB_TABLE_NAME").unwrap_or_else(|_| "oauth-storage".to_string());
86 let create_table = env::var("DYNAMODB_CREATE_TABLE")
87 .unwrap_or_else(|_| "true".to_string())
88 .parse::<bool>()
89 .unwrap_or(true);
90
91 log_startup_info(&config, &table_name, create_table);
93
94 let microkernel = create_full_cognito_microkernel_dynamodb(
96 cognito_config,
97 config.cognito.cognito_domain.clone(),
98 config.cognito.region.clone(),
99 config.cognito.user_pool_id.clone(),
100 table_name,
101 create_table,
102 )
103 .await
104 .map_err(|e| {
105 remote_mcp_kernel::error::AppError::Internal(format!("Failed to create microkernel: {}", e))
106 })?;
107
108 let bind_address = config.bind_socket_addr()?;
110 microkernel.serve(bind_address).await?;
111
112 Ok(())
113}
114
115fn init_tracing(config: &Config) -> AppResult<()> {
116 tracing_subscriber::registry()
117 .with(
118 tracing_subscriber::EnvFilter::try_from_default_env()
119 .unwrap_or_else(|_| config.logging.level.as_str().into()),
120 )
121 .with(tracing_subscriber::fmt::layer())
122 .init();
123
124 Ok(())
125}
126
127fn log_startup_info(config: &Config, table_name: &str, create_table: bool) {
128 println!("🚀 Starting MCP OAuth server with Cognito and DynamoDB storage...");
129 println!("📋 Configuration:");
130 println!(" - Architecture: Microkernel (independent handlers)");
131 println!(" - OAuth Provider: AWS Cognito");
132 println!(" - Storage Backend: DynamoDB");
133 println!(" - Server: {}:{}", config.server.host, config.server.port);
134 println!(" - Version: {}", config.server.version);
135 println!();
136
137 println!("🔐 AWS Cognito Configuration:");
138 println!(
139 " - Client ID: {}",
140 if config.cognito.client_id.is_empty() {
141 "Not configured"
142 } else {
143 "Configured"
144 }
145 );
146 println!(
147 " - Client Secret: {}",
148 match &config.cognito.client_secret {
149 Some(secret) if !secret.is_empty() => "Configured",
150 _ => "Not configured (Public Client)",
151 }
152 );
153 println!(
154 " - Domain: {}",
155 if config.cognito.cognito_domain.is_empty() {
156 "Not configured"
157 } else {
158 &config.cognito.cognito_domain
159 }
160 );
161 println!(
162 " - Region: {}",
163 if config.cognito.region.is_empty() {
164 "Not configured"
165 } else {
166 &config.cognito.region
167 }
168 );
169 println!(
170 " - User Pool ID: {}",
171 if config.cognito.user_pool_id.is_empty() {
172 "Not configured"
173 } else {
174 &config.cognito.user_pool_id
175 }
176 );
177 println!(" - Scopes: {}", config.cognito.scope);
178 println!();
179
180 println!("🗄️ DynamoDB Storage Configuration:");
181 println!(" - Table Name: {}", table_name);
182 println!(" - Auto-create Table: {}", create_table);
183 println!(" - TTL Attribute: expires_at");
184 println!();
185
186 println!("🔧 Handlers:");
187 println!(" - OAuth Provider (Cognito authentication & authorization)");
188 println!(" - Streamable HTTP Handler (MCP over HTTP)");
189 println!(" - SSE Handler (MCP over SSE)");
190 println!();
191
192 println!("🔐 Required Environment Variables:");
193 println!(" ## Cognito Configuration");
194 println!(" - COGNITO_CLIENT_ID: Your Cognito app client ID");
195 println!(
196 " - COGNITO_CLIENT_SECRET: Your Cognito app client secret (optional for public clients)"
197 );
198 println!(
199 " - COGNITO_DOMAIN: Your Cognito domain (e.g., mydomain.auth.us-east-1.amazoncognito.com)"
200 );
201 println!(" - COGNITO_REGION: AWS region (e.g., us-east-1)");
202 println!(" - COGNITO_USER_POOL_ID: Your Cognito user pool ID (e.g., us-east-1_XXXXXXXXX)");
203 println!(" - COGNITO_SCOPE: OAuth scopes (default: 'openid email profile phone')");
204 println!();
205 println!(" ## AWS Configuration (for DynamoDB)");
206 println!(" - AWS_ACCESS_KEY_ID: Your AWS access key ID");
207 println!(" - AWS_SECRET_ACCESS_KEY: Your AWS secret access key");
208 println!(" - AWS_REGION: AWS region (should match COGNITO_REGION)");
209 println!();
210 println!(" ## Server Configuration");
211 println!(" - MCP_HOST: Server host (default: localhost)");
212 println!(" - MCP_PORT: Server port (default: 8080)");
213 println!(" - DYNAMODB_TABLE_NAME: DynamoDB table name (default: oauth-storage)");
214 println!(" - DYNAMODB_CREATE_TABLE: Whether to auto-create table (default: true)");
215 println!();
216
217 println!("🌐 OAuth 2.0 Endpoints:");
218 println!(
219 " - Authorization: https://{}/oauth2/authorize",
220 config.cognito.cognito_domain
221 );
222 println!(
223 " - Token: https://{}/oauth2/token",
224 config.cognito.cognito_domain
225 );
226 println!(
227 " - JWKS: https://{}/oauth2/jwks",
228 config.cognito.cognito_domain
229 );
230 println!(
231 " - UserInfo: https://{}/oauth2/userInfo",
232 config.cognito.cognito_domain
233 );
234 println!();
235
236 println!("💾 DynamoDB Table Configuration:");
237 println!(" - Table Structure: Single table design with 'pk' primary key");
238 println!(" - TTL Support: Automatic cleanup using 'expires_at' attribute");
239 println!(" - Billing Mode: Pay-per-request (on-demand)");
240 println!(" - Encryption: Server-side encryption enabled");
241 println!();
242
243 println!("🏗️ Microkernel Architecture:");
244 println!(" - Independent handlers that can operate standalone");
245 println!(" - Runtime composition of services");
246 println!(" - Single responsibility per handler");
247 println!(" - Easy testing and maintenance");
248 println!();
249}