Skip to main content
Glama

login

Authenticate with the eClass platform using stored credentials from your .env file to access course information and perform operations through UoA's SSO system.

Instructions

Log in to eClass using username/password from your .env file through UoA's SSO. Configure ECLASS_USERNAME and ECLASS_PASSWORD in your .env file.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
random_stringYesDummy parameter for no-parameter tools

Implementation Reference

  • Handler function for the 'login' MCP tool. Orchestrates login by checking current state, loading credentials from .env, calling core authentication logic, and formatting response.
    async def handle_login() -> List[types.TextContent]:
        """Handle login to eClass."""
        if session_state.logged_in and session_state.is_session_valid():
            return [
                types.TextContent(
                    type="text",
                    text=f"Already logged in as {session_state.username}",
                )
            ]
        
        if session_state.logged_in and not session_state.is_session_valid():
            session_state.reset()
        
        username = os.getenv('ECLASS_USERNAME')
        password = os.getenv('ECLASS_PASSWORD')
        
        if not username or not password:
            return [
                types.TextContent(
                    type="text",
                    text="Error: Username and password must be provided in the .env file. Please set ECLASS_USERNAME and ECLASS_PASSWORD in your .env file.",
                )
            ]
        
        logger.info(f"Attempting to log in as {username}")
        success, message = authentication.attempt_login(session_state, username, password)
        return [authentication.format_login_response(success, message, username if success else None)]
  • Core handler implementing the full SSO login flow: fetches login page, extracts SSO/CAS parameters using html_parsing helpers, submits credentials, verifies success by checking portfolio access.
    def attempt_login(
        session_state: SessionState, username: str, password: str
    ) -> Tuple[bool, Optional[str]]:
        """
        Attempt to log in to eClass using the SSO authentication flow.
        
        Returns:
            Tuple of (success, error_message). On success, error_message is None.
        """
        try:
            # Step 1: Visit the eClass login form page
            response = session_state.session.get(session_state.login_form_url)
            response.raise_for_status()
            
            # Step 2: Find and follow the SSO login link
            sso_link = html_parsing.extract_sso_link(response.text, session_state.base_url)
            if not sso_link:
                return False, "Could not find SSO login link on the login page"
            
            response = session_state.session.get(sso_link)
            response.raise_for_status()
            
            # Step 3: Validate SSO redirect and extract CAS form data
            if not _is_valid_sso_redirect(response.url, session_state):
                return False, f"Unexpected redirect to {response.url}"
            
            execution, action, error_text = html_parsing.extract_cas_form_data(
                response.text, response.url, session_state.sso_base_url
            )
            
            if error_text and ('authenticate' in error_text.lower() or 'credentials' in error_text.lower()):
                return False, f"Authentication error: {error_text}"
            if not execution:
                return False, "Could not find execution parameter on SSO page"
            if not action:
                return False, "Could not find login form on SSO page"
            
            # Step 4: Submit credentials to CAS
            login_data = {
                'username': username,
                'password': password,
                'execution': execution,
                '_eventId': 'submit',
                'geolocation': ''
            }
            
            response = session_state.session.post(action, data=login_data)
            response.raise_for_status()
            
            # Check for authentication errors in response
            if 'Πόροι Πληροφορικής ΕΚΠΑ' in response.text or \
               'The credentials you provided cannot be determined to be authentic' in response.text:
                _, _, error_text = html_parsing.extract_cas_form_data(response.text, response.url)
                if error_text:
                    return False, f"Authentication error: {error_text}"
                return False, "Authentication failed: Invalid credentials"
            
            logger.info("Successfully authenticated with SSO")
            
            # Step 5: Verify login by accessing portfolio page
            if session_state.eclass_domain not in response.url:
                return False, f"Unexpected redirect after login: {response.url}"
            
            response = session_state.session.get(session_state.portfolio_url)
            response.raise_for_status()
            
            if not html_parsing.verify_login_success(response.text):
                return False, "Could not access portfolio page after login"
            
            session_state.logged_in = True
            session_state.username = username
            logger.info("Login successful, redirected to eClass portfolio")
            return True, None
        
        except requests.RequestException as e:
            logger.error(f"Request error during login: {e}")
            return False, f"Network error during login process: {e}"
        except Exception as e:
            logger.error(f"Login error: {e}")
            return False, f"Error during login process: {e}"
  • Schema and metadata registration for the 'login' tool in the MCP list_tools() response, defining a dummy input parameter since credentials are from env.
    types.Tool(
        name="login",
        description="Log in to eClass using username/password from your .env file through UoA's SSO. Configure ECLASS_USERNAME and ECLASS_PASSWORD in your .env file.",
        inputSchema={
            "type": "object",
            "properties": {
                "random_string": {
                    "type": "string",
                    "description": "Dummy parameter for no-parameter tools"
                },
            },
            "required": ["random_string"],
        },
    ),
  • MCP server.call_tool() decorator and dispatcher function that routes 'login' calls to the specific handle_login handler.
    @server.call_tool()
    async def handle_call_tool(
        name: str, arguments: Dict[str, Any] | None
    ) -> List[types.TextContent | types.ImageContent | types.EmbeddedResource]:
        """Handle eClass tool execution requests."""
        if name == "login":
            return await handle_login()
        elif name == "get_courses":
            return await handle_get_courses()
        elif name == "logout":
            return await handle_logout()
        elif name == "authstatus":
            return await handle_authstatus()
        else:
            raise ValueError(f"Unknown tool: {name}")
  • Utility function to format TextContent response for successful or failed login attempts.
    def format_login_response(
        success: bool, message: Optional[str], username: Optional[str] = None
    ) -> types.TextContent:
        """Format login response for MCP."""
        if success:
            return types.TextContent(
                type="text",
                text=f"Login successful! You are now logged in as {username}.",
            )
        return types.TextContent(
            type="text",
            text=f"Error: {message}",
        )
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions authentication via SSO and .env file usage, but lacks details on what the tool actually does (e.g., establishes a session, returns tokens, handles errors) or behavioral traits like rate limits, side effects, or response format. For a login tool with zero annotation coverage, this is a significant gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences that efficiently convey the core functionality and configuration requirement. It's front-loaded with the main action and wastes no words, making it easy to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of a login operation (authentication, session management) with no annotations and no output schema, the description is incomplete. It doesn't explain what happens after login (e.g., session persistence, return values, error handling), leaving gaps in understanding the tool's behavior and outcomes.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 1 parameter with 100% coverage, describing it as a 'Dummy parameter for no-parameter tools.' The description doesn't add any parameter-specific information, which is appropriate since the tool likely doesn't require user-provided inputs. With high schema coverage and no meaningful parameters, a baseline of 4 is justified as the description doesn't need to compensate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Log in to eClass using username/password from your .env file through UoA's SSO.' It specifies the action (log in), target system (eClass), and authentication method (SSO with .env credentials). However, it doesn't explicitly differentiate from sibling tools like 'authstatus' or 'logout' beyond the obvious login/logout distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context: it should be used to authenticate with eClass via SSO when credentials are stored in .env. However, it doesn't provide explicit guidance on when to use this vs. alternatives like 'authstatus' (which might check login state) or prerequisites beyond .env configuration. The guidance is somewhat implied but not comprehensive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sdi2200262/eclass-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server