Skip to main content
Glama
hbd

MCP Chat

by hbd

join_room

Join a specific chat room to participate in conversations. Enter a room using its ID and your display name to start communicating with others in that space.

Instructions

Join a specific chat room directly.

Creates a new session with a unique client_id and adds the user to the specified room. Useful for rejoining a room or creating private rooms.

IMPORTANT: After joining a room, prompt the user to choose whether they want to:

  • Wait for messages (call wait_for_message) - if they expect to receive first

  • Send a message (call send_message) - if they want to initiate conversation

This gives users control over the conversation flow rather than automatically blocking.

Args: room_id: The ID of the room to join display_name: Display name for the user (required)

Returns: Success status with client_id or error information

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
room_idYes
display_nameYes

Implementation Reference

  • The complete implementation of the 'join_room' tool handler. This async function handles joining a chat room, creating it if it doesn't exist, managing user connections, checking room capacity, notifying existing users, and returning appropriate status and client_id.
    @mcp.tool()
    async def join_room(room_id: str, display_name: str) -> Dict[str, Any]:
        """Join a specific chat room directly.
    
        Creates a new session with a unique client_id and adds the user to the specified room.
        Useful for rejoining a room or creating private rooms.
    
        IMPORTANT: After joining a room, prompt the user to choose whether they want to:
        - Wait for messages (call wait_for_message) - if they expect to receive first
        - Send a message (call send_message) - if they want to initiate conversation
    
        This gives users control over the conversation flow rather than automatically blocking.
    
        Args:
            room_id: The ID of the room to join
            display_name: Display name for the user (required)
    
        Returns:
            Success status with client_id or error information
        """
        # Generate a unique client_id for this user
        connection_id = str(uuid.uuid4())
    
        # Create new user
        user = User(display_name=display_name, connection_id=connection_id)
        connections[connection_id] = user
    
        # Check if room exists
        room = await room_manager.get_room(room_id)
        if not room:
            # Create a new room with just this user
            room = await room_manager.create_room(user, user)  # Temporarily both users
            room.room_id = room_id  # Override the generated ID
            # Update the room in manager
            room_manager._rooms[room_id] = room
            room_manager._user_to_room[user.user_id] = room_id
    
            logger.info(f"Created new room {room_id} for {user.name}")
    
            return {
                "status": "room_created",
                "room_id": room_id,
                "client_id": connection_id,
                "message": "New room created, waiting for another user to join",
            }
    
        # Check if room is active
        if not room.active:
            return {
                "status": "error",
                "error": "Room is no longer active",
                "client_id": connection_id,
            }
    
        # Check if room has space (max 2 users)
        current_users = []
        active_user_ids = {u.user_id for u in connections.values()}
        if room.user1 and room.user1.user_id in active_user_ids:
            current_users.append(room.user1)
        if (
            room.user2
            and room.user2.user_id != room.user1.user_id
            and room.user2.user_id in active_user_ids
        ):
            current_users.append(room.user2)
    
        if len(current_users) >= 2:
            return {"status": "error", "error": "Room is full", "client_id": connection_id}
    
        # Add user to room
        if len(current_users) == 0:
            # First user in existing room
            room.user1 = user
        else:
            # Second user joining
            room.user2 = user
            # Notify the first user
            first_user = room.user1
            if first_user and first_user.user_id in connections:
                # Send notification about new user joining
                if (
                    room_id in message_queues
                    and first_user.user_id in message_queues[room_id]
                ):
                    join_msg = {
                        "content": f"[System] {user.name} has joined the chat.",
                        "sender_name": "System",
                        "sender_id": "system",
                        "timestamp": datetime.now().isoformat(),
                        "message_id": str(uuid.uuid4()),
                        "system": True,
                    }
                    try:
                        message_queues[room_id][first_user.user_id].put_nowait(join_msg)
                    except (asyncio.QueueFull, RuntimeError) as e:
                        # Queue might be full or closed
                        logger.debug(f"Could not send join notification: {e}")
    
        # Update user-to-room mapping
        room_manager._user_to_room[user.user_id] = room_id
    
        logger.info(f"User {user.name} joined room {room_id}")
    
        # Get partner info if exists
        partner = room.get_partner(user.user_id)
    
        return {
            "status": "joined",
            "room_id": room_id,
            "client_id": connection_id,
            "partner": {"display_name": partner.name} if partner else None,
            "message": "Successfully joined room"
            + (f" with {partner.name}" if partner else ", waiting for partner"),
        }
  • The @mcp.tool() decorator registers the join_room function as an MCP tool.
    @mcp.tool()
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behaviors: that joining creates a new session with a unique client_id, adds the user to the room, and doesn't automatically block (giving users control over flow). It mentions the tool returns success status with client_id or error information. However, it doesn't cover potential side effects like rate limits, authentication needs, or what happens if the room doesn't exist.

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

Conciseness4/5

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

The description is well-structured with clear sections: purpose statement, behavioral details, usage guidance, and parameter explanations. Every sentence earns its place, though the IMPORTANT section is somewhat lengthy. The information is front-loaded with the core purpose in the first sentence. Minor deduction for some redundancy in explaining the workflow.

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

Completeness4/5

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

Given the tool's moderate complexity (joining rooms with session creation), no annotations, no output schema, and 2 parameters, the description provides good coverage. It explains the purpose, usage context, parameters, and return values. However, it lacks details about error conditions, what 'success status' entails, and potential limitations or prerequisites for joining rooms.

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?

With 0% schema description coverage for 2 parameters, the description compensates well by explaining both parameters in the Args section. It clarifies that room_id is 'The ID of the room to join' and display_name is 'Display name for the user (required)'. This adds meaningful context beyond the bare schema, though it doesn't provide format examples or constraints for either parameter.

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

Purpose5/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 with specific verbs ('join', 'creates', 'adds') and resources ('chat room', 'session', 'user'). It distinguishes from siblings by explaining this is for joining rooms directly, while siblings like send_message and wait_for_message are for subsequent actions. The first sentence 'Join a specific chat room directly' is precise and unambiguous.

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

Usage Guidelines5/5

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

The description provides explicit guidance on when to use this tool vs alternatives. It states it's 'useful for rejoining a room or creating private rooms' and includes an IMPORTANT section that explains what to do after joining (call wait_for_message or send_message). This clearly distinguishes it from sibling tools and provides context for the workflow.

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/hbd/mcp-chat'

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