This codelab will walk you through integrating Zoom workplace data into an MCP server and building an MCP client using the Anthropic Python Model Context Protocol SDK.

What You'll Learn

Project Setup

Creating a Zoom Workplace Contextual data reader tool

The first tool reads oom Workplace Contextual data by resource and ID.

@mcp.tool(
    "read_zoom_resource",
    description="Read a Zoom Workplace item (meeting, chat message, email, or calendar event) by type and ID."
)

def read_zoom_resource(
    resource_type: ResourceType = Field(
        description="The Zoom dataset to read from. One of: 'meetings', 'team_chat', 'mail', 'calendar'."
    ),
    resource_id: str = Field(
        description="The ID of the item to read (e.g., meetingId, messageId, emailId, eventId)."
    ),
):
    """
    Returns the stored dict for the requested Zoom Workplace item.
    """
    _, item = _ensure_resource(resource_type, resource_id)
    return item

Building a Document Editor Tool

The second tool performs simple find-and-replace operations on requested Zoom Workplace item:

@mcp.tool(
    name="edit_document",
    description="Edit a document by replacing a string in the documents content with a new string."
)

def edit_zoom_resource(
    resource_type: ResourceType = Field(
        description="The Zoom dataset to write to. One of: 'meetings', 'team_chat', 'mail', 'calendar'."
    ),
    resource_id: str = Field(
        description="The ID of the item to edit or create (e.g., meetingId, messageId, emailId, eventId)."
    ),
    new_content: dict = Field(
        description="The replacement content for this item. Entire object is replaced."
    ),
):
    """
    Replaces the entire item content. For partial updates, add another tool that merges dicts.
    """
    if resource_type not in zoom_data:
        raise ValueError(f"Unknown resource_type '{resource_type}'. "
                         f"Use one of: meetings, team_chat, mail, calendar.")

    collection = zoom_data[resource_type]


    collection[resource_id] = new_content
    return collection[resource_id]

Run the following command to lauch the Python MCP SDK includes a built-in browser-based inspector that lets you debug and test your server in real-time.

mcp dev server.py

This starts a development server and gives you a local URL, typically something like http://127.0.0.1:6274. Open this URL in your browser to access the MCP Inspector.

Using the Your Tools

Navigate to the Tools section and click "List Tools" to see all available tools from your server. When you select a tool, the right panel shows its details and input fields.

alt-text-here

The inspector shows both the success status and the actual returned data, making it easy to verify your tool works correctly.

Add details on connecting with MCP clients overview

    # TODO: Return a list of tools defined by the MCP server
    async def list_tools(self) -> list[types.Tool]:
        result= await self.session().list_tools()
        return result.tools

    # TODO: Call a particular tool and return the result
    async def call_tool(
        self, tool_name: str, tool_input: dict
    ) -> types.CallToolResult | None:
        return await self.session().call_tool(tool_name, tool_input)

  1. Testing
# For testing
async def main():
    async with MCPClient(
        # If using Python without UV, update command to 'python' and remove "run" from args.
        command="python3",
        args=[ "mcp_server.py"],
    ) as _client:
        result = await _client.list_tools()
        print("Tools:", result)

List Tool Definations Start Client

python3 mcp_client.py 

You should see the out of the read and edit tools created earlier. Each tool includes a description and input schema as well. This defination will be passed off to Claude.

Call Tool with Claude

 python3 main.py      

Ask Claude the following:

What is the agenda for meeting ID "987654321" ?

When we run this, Claude will:

@mcp.resource("res://resources", mime_type="application/json")
def list_zoom_resources():
    """
    List all Zoom Workplace resource IDs by type.
    Returns:
    {
      "meetings": ["123456789", "987654321"],
      "team_chat": ["msg_1001", "msg_1002"],
      "mail": ["email_2001"],
      "calendar": ["event_3001"]
    }
    """
    return {
        rtype: sorted(items.keys(), key=str)
        for rtype, items in zoom_data.items()
    }



SINGLE RESOURCE (GET)

@mcp.resource("res://resources/{resource_type}/{resource_id}")
def get_zoom_resource(
    resource_type: ResourceType,
    resource_id: str,
):
    """
    Get a specific Zoom Workplace item by type and ID.
    Example paths:
      res://resources/meetings/987654321
      res://resources/team_chat/msg_1001
      res://resources/mail/email_2001
      res://resources/calendar/event_3001
    """
    if resource_type not in zoom_data:
        raise ValueError(f"Unknown resource_type '{resource_type}'. "
                         f"Use one of: meetings, team_chat, mail, calendar.")
    _, item = _ensure_resource(resource_type, resource_id)
    return item

You build MCP server that can access Zoom Workplace contextual data using the PYTHON SDK.