
    ~hW'                    :   d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ dd	lmZmZ dd
lmZ ddlmZ  ee      Z	 	 	 d!	 	 	 	 	 	 	 	 	 d"dZe G d d             Z	 	 	 d#	 	 	 	 	 	 	 	 	 d$dZedk(  r	 ddlZddlZ e       Z ed        ed        ede d        ede d        ede d        ed        e         eed      Z ej<                  de d        ej>                  ej@                  jB                  dedd        yy)%z
OAuth callback server for handling authorization code flows.

This module provides a reusable callback server that can handle OAuth redirects
and display styled responses to users.
    )annotationsN)	dataclass)	Starlette)Request)HTMLResponse)Route)ConfigServer)find_available_port)
get_loggerc                d    |rdnd}|rdnd}d}|r|rd| d}d| d	| d
|rdnd d| d|  d| dS )z2Create a styled HTML response for OAuth callbacks.u   ✅u   ❌z#10b981z#ef4444 zM
            <div class="server-info">
                Connected to: <strong>z%</strong>
            </div>
        z
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>a	  </title>
        <style>
            body {
                font-family: 'SF Mono', 'Monaco', 'Consolas', 'Roboto Mono', monospace;
                margin: 0;
                padding: 0;
                min-height: 100vh;
                display: flex;
                align-items: center;
                justify-content: center;
                background: linear-gradient(135deg, #0f0f23 0%, #1a1a2e 25%, #16213e 50%, #0f0f23 100%);
                color: #e2e8f0;
                overflow: hidden;
            }
            
            body::before {
                content: '';
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: 
                    radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.1) 0%, transparent 50%),
                    radial-gradient(circle at 80% 20%, rgba(16, 185, 129, 0.1) 0%, transparent 50%),
                    radial-gradient(circle at 40% 40%, rgba(14, 165, 233, 0.1) 0%, transparent 50%);
                pointer-events: none;
                z-index: -1;
            }
            
            .container {
                background: rgba(30, 41, 59, 0.9);
                backdrop-filter: blur(10px);
                border: 1px solid rgba(71, 85, 105, 0.3);
                padding: 3rem 2rem;
                border-radius: 1rem;
                box-shadow: 
                    0 25px 50px -12px rgba(0, 0, 0, 0.7),
                    0 0 0 1px rgba(255, 255, 255, 0.05),
                    inset 0 1px 0 0 rgba(255, 255, 255, 0.1);
                text-align: center;
                max-width: 500px;
                margin: 1rem;
                position: relative;
            }
            
            .container::before {
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                height: 1px;
                background: linear-gradient(90deg, transparent, rgba(16, 185, 129, 0.5), transparent);
            }
            
            .status-icon {
                font-size: 4rem;
                margin-bottom: 1rem;
                display: block;
                filter: drop-shadow(0 0 20px currentColor);
            }
            
            .message {
                font-size: 1.25rem;
                line-height: 1.6;
                color: zv;
                margin-bottom: 1.5rem;
                font-weight: 600;
                text-shadow: 0 0 10px rgba(z16, 185, 129z239, 68, 68a%  , 0.3);
            }
            
            .server-info {
                background: rgba(6, 182, 212, 0.1);
                border: 1px solid rgba(6, 182, 212, 0.3);
                border-radius: 0.75rem;
                padding: 1rem;
                margin: 1rem 0;
                font-size: 0.9rem;
                color: #67e8f9;
                font-family: 'SF Mono', 'Monaco', 'Consolas', 'Roboto Mono', monospace;
                text-shadow: 0 0 10px rgba(103, 232, 249, 0.3);
            }
            
            .server-info strong {
                color: #22d3ee;
                font-weight: 700;
            }
            
            .subtitle {
                font-size: 1rem;
                color: #94a3b8;
                margin-top: 1rem;
            }
            
            .close-instruction {
                background: rgba(51, 65, 85, 0.8);
                border: 1px solid rgba(71, 85, 105, 0.4);
                border-radius: 0.75rem;
                padding: 1rem;
                margin-top: 1.5rem;
                font-size: 0.9rem;
                color: #cbd5e1;
                font-family: 'SF Mono', 'Monaco', 'Consolas', 'Roboto Mono', monospace;
            }
            
            @keyframes glow {
                0%, 100% { opacity: 1; }
                50% { opacity: 0.7; }
            }
            
            .status-icon {
                animation: glow 2s ease-in-out infinite;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <span class="status-icon">z)</span>
            <div class="message">z</div>
            z
            <div class="close-instruction">
                You can safely close this tab now.
            </div>
        </div>
    </body>
    </html>
     )message
is_successtitle
server_urlstatus_emojistatus_colorserver_infos          Y/opt/mcp/mcp-sentiment/venv/lib/python3.12/site-packages/fastmcp/client/oauth_callback.pycreate_callback_htmlr      s     '5EL *9	L Kj''1l 3	 w BD %~ &, %-,1'b (4n 5"") +M AG G    c                  `    e Zd ZU dZded<   dZded<   dZded<   dZded<   ed	d       Z	d
dZ
y)CallbackResponseN
str | Nonecodestateerrorerror_descriptionc           
          | di |j                         D ci c]  \  }}|| j                  v s|| c}}S c c}}w )Nr   )items__annotations__)clsdatakvs       r   	from_dictzCallbackResponse.from_dict   s9    Qtzz|Ptq!qC<O<O7OadPQQPs   ::c                p    | j                   j                         D ci c]  \  }}|	|| c}}S c c}}w )N)__dict__r"   )selfr&   r'   s      r   to_dictzCallbackResponse.to_dict   s/    !%!4!4!6HA!-1HHHs   
22)r%   dict[str, str]returnr   )r.   r-   )__name__
__module____qualname__r   r#   r   r   r    classmethodr(   r,   r   r   r   r   r      sE    D*E:E:$(z(R RIr   r   	/callbackc           	     t    dfd}t        t        ||      g      }t        t        |d| dd            S )a  
    Create an OAuth callback server.

    Args:
        port: The port to run the server on
        callback_path: The path to listen for OAuth redirects on
        server_url: Optional server URL to display in success messages
        response_future: Optional future to resolve when OAuth callback is received

    Returns:
        Configured uvicorn Server instance (not yet running)
    c                  K   t        | j                        }t        j                  |      }|j                  rt|j
                  xs d}r:j                         s*j                  t        d|j                   d|              t        t        d|j                   d| d      d	      S |j                  sDr*j                         sj                  t        d
             t        t        dd      d	      S r7j                         s'j                  |j                  |j                  f       t        t        d            S w)z:Handle OAuth callback requests with proper HTML responses.zUnknown errorzOAuth error: z - zFastMCP OAuth Error: z<br>F)r   i  )status_codez)OAuth callback missing authorization codez3FastMCP OAuth Error: No authorization code receivedzFastMCP OAuth login complete!)r   )dictquery_paramsr   r(   r   r    doneset_exceptionRuntimeErrorr   r   r   
set_resultr   )requestr8   callback_response
error_descresponse_futurer   s       r   callback_handlerz6create_oauth_callback_server.<locals>.callback_handler   sU    G001,66|D""*<<OJ ';';'=-- '(9(?(?'@J<P  $+,=,C,C+DDU$    !%%';';'=-- !LM  $I$    ?#7#7#9&&"''):)@)@A  !@ZX
 	
s   E
E)routes	127.0.0.1offwarning)apphostportlifespan	log_level)r=   r   )r   r   r
   r	   )rH   callback_pathr   r@   rA   rF   s     ``  r   create_oauth_callback_serverrL      sD    &/
b E-1ABC
DC	
 r   __main__u   🎭 OAuth Callback Test Serveru   📍 Test URLs:z  Success: http://localhost:z /callback?code=test123&state=xyzz  Error:   http://localhost:z=/callback?error=access_denied&error_description=User%20deniedz  Missing: http://localhost:u   🛑 Press Ctrl+C to stopz'https://fastmcp-test-server.example.com)rH   r   zhttp://localhost:rC   rE   F)rG   rH   rJ   
access_log)TzFastMCP OAuthN)
r   strr   boolr   rO   r   r   r.   rO   )r3   NN)
rH   intrK   rO   r   r   r@   zasyncio.Future | Noner.   r
   )"__doc__
__future__r   asynciodataclassesr   starlette.applicationsr   starlette.requestsr   starlette.responsesr   starlette.routingr   uvicornr	   r
   fastmcp.utilities.httpr   fastmcp.utilities.loggingr   r/   loggerr   r   rL   
webbrowserrH   printserveropenrunconfigrF   r   r   r   <module>rd      s   #  ! , & , # " 6 0	H	
  !	ZZZ Z 	Z
 	Zz I I I  %!-1	N
NN N +	N
 Nb z3 D	
+,	
	(.N
OP	
&tf,ij 
(i
89	
%&	G *GF
 JOO'v-MNO GKK5 r   