Model Context Protocol (MCP) is an open protocol that standardizes how applications provide context to LLMs. From the MCP documentation:

Think of MCP like a USB-C port for AI applications. Just as USB-C provides a standardized way to connect your devices to various peripherals and accessories, MCP provides a standardized way to connect AI models to different data sources and tools.

This article provides a hands-on, step-by-step walkthrough to build a simple example on your local development machine that integrates the Unstructured API with the Python SDK for Model Context Protocol. Specifically, this walkthrough demonstrates how to write and run Python code to create an MCP server (a lightweight program that exposes specific capabilities through MCP); this MCP server uses the Unstructured Workflow Endpoint to list all of your available source connectors and to get information about a specific source connector. The Workflow Endpoint offers a full range of partitioning, chunking, embedding, and enrichment options for your files and data.

For a hands-on walkthrough of the Unstructured Partition Endpoint instead, see the MCP Hands-On Walkthrough for the Unstructured Partition Endpoint, which is intended for rapid prototyping of Unstructured’s various partitioning strategies, with limited support for chunking, processing local files one file at a time.

You call this MCP server from an MCP client (an application that maintains a one-to-one connection with an MCP server), which in this walkthrough is Claude for Desktop, a chat-based interface, by asking it plain language questions. Other MCP clients are also available. Learn more.

At the end of this walkthrough, you can extend this example by using the Workflow Endpoint to perform other tasks, such as creating, listing, changing, and deleting various connectors, workflows, and jobs in your Unstructured account.

Requirements

To complete this walkthrough, you must first have an Unstructured account, an Unstructured API key for that account, the necessary Python toolchain and project setups, and Claude for Desktop, as follows.

Unstructured account and API key

Before you begin, you must have an Unstructured account and an Unstructured API key, as follows:

  1. Go to https://platform.unstructured.io and use your email address, Google account, or GitHub account to sign up for an Unstructured account (if you do not already have one) and sign into the account at the same time. The Unstructured user interface (UI) appears.

  2. Get your Unstructured API key:

    a. In the Unstructured UI, click API Keys on the sidebar.
    b. Click Generate API Key.
    c. Follow the on-screen instructions to finish generating the key.
    d. Click the Copy icon next to your new key to add the key to your system’s clipboard. If you lose this key, simply return and click the Copy icon again.

By following the preceding instructions, you are signed up for a Developer pay per page account by default.

To save money, consider switching to a Subscribe & Save account instead. To save even more money, consider switching to an Enterprise account instead.

Python toolchain and Claude for Desktop setup

Before you can start coding on your local machine, you must install the Python package and project manager uv, and install Claude for Desktop, as follows.

1

Install uv, as follows.

By using pip:

pip install uv

Or, by using the following script (be sure to restart your terminal or Command Prompt after running the script):

# For macOS and Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh

# For Windows:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

(To learn more about uv, see the uv documentation.)

You are now ready to start coding.

Step 1: Create the MCP server

If you are not interested in building an MCP server from the beginning and want to use a pre-built MCP server instead, skip ahead to Optional Step 4: Extend the MCP server.

1

From your current working directory, create a project directory and then initialize it. This example creates a project directory named mcp-unstructured-demo. Then go to the project directory:

uv init mcp-unstructured-demo
cd mcp-unstructured-demo
2

Create a virtual environment in the root of the project directory. Then activate the virtual environment:

# For macOS and Linux:
uv venv
source .venv/bin/activate

# For Windows:
uv venv
.venv\Scripts\activate

To deactivate and exit the virtual environment at any time, simply run the deactivate command:

deactivate
3

With the virtual environment activated, install the Python SDK for Model Context Protocol and additional code dependencies:

uv add "mcp[cli]" "unstructured-client>=0.30.6" dotenv
4

In the root of the project directory, create a new Python file. This example names the file workflow.py. Then add the following code to this new workflow.py file:

from typing import Any, AsyncIterator, Optional
from mcp.server.fastmcp import FastMCP, Context
from dotenv import load_dotenv
import os
from dataclasses import dataclass
from contextlib import asynccontextmanager
from unstructured_client import UnstructuredClient
from unstructured_client.models.operations import (
    ListSourcesRequest,
    GetSourceRequest
)
from unstructured_client.models.shared import SourceConnectorType

def load_environment_variables() -> None:
    """
    Loads environment variables from a .env file and checks for required variables. 
    Raises an error if any required variable is missing.

    Args:
        None

    Returns:
        None
    """
    load_dotenv()
    required_vars = [
        "UNSTRUCTURED_API_KEY"
    ]

    for var in required_vars:
        if not os.getenv(var):
            raise ValueError(f"Missing required environment variable: {var}")

@dataclass
class AppContext:
    client: UnstructuredClient

@asynccontextmanager
async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]:
    """
    Manages application lifecycle with type-safe context
    for the FastMCP server. Initializes the UnstructuredClient.
    
    Args:
        server (FastMCP): The FastMCP server instance.
    
    Returns:
        AsyncIterator[AppContext]: An asynchronous context manager providing the 
        application context.
    """
    api_key = os.getenv("UNSTRUCTURED_API_KEY")
    if not api_key:
        raise ValueError("UNSTRUCTURED_API_KEY environment variable is required")
    client = UnstructuredClient(api_key_auth=api_key)
    try:
        yield AppContext(client=client)
    finally:
        pass

# Initialize the FastMCP server.
mcp = FastMCP("workflow", lifespan=app_lifespan)

@mcp.tool()
async def list_sources(ctx: Context, source_type: Optional[str] = None) -> str:
    """
    Lists available source connectors. Optionally filters by source type.
    
    Args:
        ctx (Context): The context for the request.
        source_type (Optional[str]): The type of source connector to filter by. 
            If None, all sources are listed.
    
    Returns:
        str: A formatted string listing available source connector names and IDs.
    """
    client = ctx.request_context.lifespan_context.client
    request = ListSourcesRequest()

    if source_type:
        try:
            request.source_type = SourceConnectorType[source_type]
        except KeyError:
            return f"Invalid source type: {source_type}"

    response = await client.sources.list_sources_async(
        request=request
    )
    sorted_sources = sorted(
        response.response_list_sources, 
        key=lambda source: source.name.lower()
    )
    result = ["Available source connectors:"]

    for source in sorted_sources:
        result.append(f"- {source.name} (ID: {source.id})")

    return "\n".join(result)

@mcp.tool()
async def get_source(ctx: Context, source_id: str) -> str:
    """
    Gets detailed information about a specific source connector by its ID.
    
    Args:
        ctx (Context): The context for the request.
        source_id (str): The ID of the source connector to retrieve.
        
    Returns: 
        str: A formatted string containing information about the source connector.
    """
    client = ctx.request_context.lifespan_context.client
    
    response = await client.sources.get_source_async(
        request=GetSourceRequest(source_id=source_id)
    )
    info = response.source_connector_information

    result = ["Source connector information:"]
    result.append(f"- name: {info.name}")
    
    for key, value in info.config:
        result.append(f"{key}: {value}")

    return "\n".join(result)
    
if __name__ == "__main__":
    load_environment_variables()
    # Initialize and run the MCP server.
    mcp.run(transport='stdio')
5

In the root of the project directory, create a new file named .env. Then add the following code to this new .env file, replacing <your-unstructured-api-key> with your Unstructured API key:

UNSTRUCTURED_API_KEY="<your-unstructured-api-key>"

Step 2: Configure Claude for Desktop to use the MCP server

1

Open the Claude for Desktop App configuration file from the following location, for example by using Visual Studio Code:

# For macOS or Linux:
code ~/Library/Application\ Support/Claude/claude_desktop_config.json

# For Windows:
code $env:AppData\Claude\claude_desktop_config.json
2

Add the following code to the claude_desktop_config.json file, and then save the file.

In this file:

  • "workflow" must match the value that you set in mcp = FastMCP("workflow" ... in the workflow.py file.
  • “Absolute path to” uv must be the absolute path to the uv executable on your local machine.
  • “Absolute path to project directory” must be the absolute path to the project directory.
  • mcp_unstructured-demo must match the name of the project directory that you created.
  • "workflow.py" must match the name of the Python file that you created for the MCP server.

For macOS or Linux:

{
    "mcpServers": {
        "workflow": {
            "command": "/ABSOLUTE/PATH/TO/uv",
            "args": [
                "--directory",
                "/ABSOLUTE/PATH/TO/PROJECT/DIRECTORY/mcp-unstructured-demo/",
                "run",
                "workflow.py"
            ]
        }
    }
}

For Windows:

{
    "mcpServers": {
        "workflow": {
            "command": "C:\\ABSOLUTE\\PATH\\TO\\uv",
            "args": [
                "--directory",
                "C:\\ABSOLUTE\\PATH\\TO\\PROJECT\\DIRECTORY\\mcp-unstructured-demo\\",
                "run",
                "workflow.py"
            ]
        }
    }
}

Step 3: Run the MCP server and call it from Claude for Desktop

1

Start Claude for Desktop. If it is already running, restart it.

2

Ask the following question in the chat window, replacing S3 with the type of source connector that you want to list. For a list of available source connector types, see the Workflow Endpoint Sources overview.

List all available source connectors of type S3.

Claude for Desktop responds with a list of all available source connectors for that source connector type.

3

Ask another question in the chat window, replacing <source-connector-id> with one of the source connector IDs that Claude for Desktop returned in the previous step. For example:

Provide information about the source connector with ID <source-connector-id>.

Claude for Desktop responds with information about that source connector.

Optional Step 4: Extend the MCP server

Unstructured offers an initial experimental MCP server implementation, with much more functionality then the MCP server that you just created previously in this walkthrough. This initial MCP server is intended only for experimentation purposes and is not recommended for production usage. A more complete, supported, production-level implementation is coming soon.

To use Unstructured’s initial experimental MCP server implementation, do the following:

1

From a different working directory than the one you used in previously in this walkthrough, use Git to clone the Unstructured API MCP Server repository in GitHub, and then switch to the cloned repository’s root directory:

git clone https://github.com/Unstructured-IO/UNS-MCP.git
cd UNS-MCP
2

In the cloned repository’s root directory, create a new file named .env. Then add the following code to this new .env file, replacing <your-unstructured-api-key> with your Unstructured API key:

UNSTRUCTURED_API_KEY="<your-unstructured-api-key>"
3

In the cloned repository’s root directory, create a virtual environment. Then activate the virtual environment:

# For macOS and Linux:
uv venv
source .venv/bin/activate

# For Windows:
uv venv
.venv\Scripts\activate

To deactivate and exit the virtual environment at any time, simply run the deactivate command:

deactivate
4

With the virtual environment activated, install the cloned repository’s code dependencies:

uv sync
5

Open the Claude for Desktop App configuration file from the following location, for example by using Visual Studio Code:

# For macOS or Linux:
code ~/Library/Application\ Support/Claude/claude_desktop_config.json

# For Windows:
code $env:AppData\Claude\claude_desktop_config.json
6

Overwrite the contents of the claude_desktop_config.json file with the following content, and then save the file.

For macOS or Linux:

{
    "mcpServers": {
        "UNS-MCP": {
            "command": "/ABSOLUTE/PATH/TO/uv",
            "args": [
                "--directory",
                "/ABSOLUTE/PATH/TO/PARENT/FOLDER/UNS-MCP",
                "run",
                "server.py"
            ]
        }
    }
}

For Windows:

{
    "mcpServers": {
        "workflow": {
            "command": "C:\\ABSOLUTE\\PATH\\TO\\uv",
            "args": [
                "--directory",
                "C:\\ABSOLUTE\\PATH\\TO\\PARENT\\FOLDER\\UNS-MCP",
                "run",
                "server.py"
            ]
        }
    }
}
7

Start Claude for Desktop. If it is already running, restart it.

8

Here are some questions that you can ask in the chat window to test the MCP server. Replace the placeholders with the appropriate values.

For a list of available source connector types, see the Workflow Endpoint Sources overview.

For a list of available destination connector types, see the Workflow Endpoint Destinations overview.

  • List all available source connectors of type <source-connector-type>.
  • Provide information about the source connector with ID <source-connector-id>.
  • List all available source connectors of type <destination-connector-type>.
  • Provide information about the source connector with ID <destination-connector-id>.
  • List all available destination connectors of type <destination-connector-type>.
  • Provide information about the destination connector with ID <destination-connector-id>.
  • Create a new workflow.
  • Provide information about the workflow with ID <workflow-id>.
  • Run the workflow with ID <workflow-id>.
  • Update the workflow with ID <workflow-id>.
  • List all available workflows.
  • Delete the worklow with ID <workflow-id>.