PraisonAI is an open-source framework for building multi-agent AI systems in a few lines
of Python. Like other agent frameworks, it connects to the Transform MCP server from agent code: you declare the
server as an MCP client and hand its tools to an agent. Because Transform is a hosted remote MCP server, there is
nothing to install or run locally. You point the client at the server URL and authenticate with your Unstructured API
key.
PraisonAI’s MCP class connects to a remote server over streamable HTTP and carries your Unstructured API key as an
Authorization: Bearer header on every request, including the initial handshake.
Requirements
Before you begin, you must have the following:
- Python 3.10 or later on your local development machine. To check, in your terminal, run
python --version or python3 --version. Install Python.
praisonaiagents 1.6.154 or later. Two fixes matter here: 1.6.152 added the remote streamable-HTTP MCP fix, without which PraisonAI cannot connect to a remote MCP server at all, and 1.6.154 made the agent’s loop guard result-aware. Before 1.6.154, the loop guard counted status polls as “no progress” and halted a transform after eight tool calls, so a multi-minute job never reached an answer. See the PraisonAI releases.
- An Unstructured API key, which the Transform MCP server uses as a bearer token. Get an API key.
- An API key for the agent’s underlying model, for example an OpenAI API key.
Install the packages
In your terminal, install PraisonAI with the mcp extra:
Store your keys in environment variables rather than hard-coding them:
In your agent code, declare the Transform MCP server with the MCP class and hand it to an agent. The headers
setting attaches the Authorization: Bearer header to every request, so the handshake and the tool calls are both
authenticated.
Transforms run as asynchronous jobs that take from about 30 seconds to a few minutes, and two settings keep the agent
from giving up before a job finishes. Both are explained under Pace the polling loop below:
Use the server URL exactly as shown. Do not add /mcp or /sse to the end of the URL.
Pace the polling loop
The two additions above are what make a multi-minute transform complete. Without them the agent connects and calls
the tools, but never reaches an answer:
wait_seconds, passed alongside the MCP tools. PraisonAI has no built-in pacing, so an agent left to itself
polls check_job_status every couple of seconds and then concludes the job is taking too long and stops, while
the transform is still running. Unpacking the MCP tools with *transform_tools lets you add this local function
to the same list. The instruction to call it between status checks matters as much as the tool itself.
ExecutionConfig(max_tool_calls_per_turn=100). PraisonAI caps a turn at 10 tool calls by default, which a
paced polling loop passes well before a job finishes. The cap then ends the turn with “Tool call limit reached
(10 calls)” rather than an answer.
Run the agent
Ask the agent to parse a document and answer a question about it:
Transforming a document is asynchronous: the agent starts a job with start_transform_job, waits with
wait_seconds, polls check_job_status until it is complete, then retrieves the output with get_job_results.
Large or scanned documents can take a few minutes. The Transform tools the agent uses for this flow are
request_file_upload_url, start_transform_job, check_job_status, and get_job_results, alongside the local
wait_seconds function.
To pull specific fields out of a document rather than convert the whole document, ask the agent for an extraction:
The agent parses the file first, then extracts from the parsed element JSON using
suggest_extraction_schema_for_file (when you have not supplied a schema) and start_extraction_job, polling with the
same check_job_status and get_job_results tools. Extraction runs on the element JSON that a parse produces rather
than on the raw file, so it always follows a transform job, and chaining the two takes longer than a parse alone.
Results arrive as JSON matching the schema, wrapped with the source filename and the element JSON reference they were
taken from.
Extraction can only surface what the parse captured, so ask for a higher-fidelity parse if a first attempt comes back
sparse. For prompt patterns, see Structured data extraction.
Next steps
Questions? Need help?