- The
McpToolsetclass, which connects to a remote MCP server and exposes its tools to an agent. - The
StreamableHTTPConnectionParamsconnection settings, which carry your Unstructured API key as anAuthorization: Bearerheader on every request, including the initialinitializehandshake.
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 --versionorpython3 --version. Install Python. - An Unstructured API key, which the Transform MCP server uses as a bearer token. Get an API key.
- A Gemini API key for the agent’s underlying model. Get an API key.
Install the packages
In your terminal, install ADK with themcp extra:
ADK is in active development and its APIs change between releases. This guide was verified against version
2.4.0. If you install a different version, check the
ADK release notes for changes.
Connect to the Transform MCP server
Store your API keys in environment variables rather than hard-coding them:McpToolset. The headers setting attaches the
Authorization: Bearer header to every request, so the handshake and the tool calls are both authenticated:
tool_filter list are the ones the transform job lifecycle uses, plus the two structured data
extraction tools covered in Extract structured data below. The filter exposes only
these tools to the agent and ignores any others the server advertises, so a tool that is missing from this list is
unreachable: add an entry whenever you want the agent to use another of the server’s tools.
Understand the transform job lifecycle
Transforming a document is an asynchronous, multi-step flow. Four of the steps are MCP tool calls, and two are plain HTTP transfers that are not MCP calls:request_file_upload_url: Returns a pre-signedupload_urland afile_reffor a local file.- An HTTP
PUTof the raw file bytes to the pre-signedupload_url. This is not an MCP call. start_transform_job: Starts a transform job for one or morefile_refvalues (or public HTTP(S) URLs) and returns ajob_id.check_job_status: Reports whether the job isSCHEDULED,IN_PROGRESS, orCOMPLETED.get_job_results: Returns a pre-signeddownload_urlfor the Markdown output of each transformed file.- An HTTP
GETof the Markdown from the pre-signeddownload_url. This is not an MCP call.
output_ref that get_job_results returns for each file:
suggest_extraction_schema_for_file: Drafts a JSON Schema from one parsed document. Use this only when you do not already have a schema.start_extraction_job: Starts an extraction for up to 10output_refvalues against a single JSON Schema, and returns ajob_id.
check_job_status and read with get_job_results, exactly as a transform job is.
Its results come back inline rather than behind a download_url, so there is no equivalent of the final HTTP GET.
Each result is wrapped with the source filename, file type, timestamp, and the element JSON reference it was taken
from. For prompt patterns, see Structured data extraction.
An agent cannot perform the two raw HTTP transfers through MCP tools alone, and an unpaced polling loop wastes model
calls. Give the agent two small helper functions alongside the toolset: one that performs the PUT upload, and one
that waits between status checks. Both helpers must be async: ADK runs tools on its event loop, so a helper that
blocks (for example, with time.sleep or a synchronous HTTP call) freezes every other session the agent is serving,
such as concurrent sessions under adk web.
The pre-signed
upload_url and download_url carry their own credentials in the URL itself. The PUT and GET
must not send the Authorization header, or the storage service rejects them.Build the agent
Create an agent package with the standard ADK layout:__init__.py:
agent.py (the httpx library it imports is installed with ADK):
On the Gemini API free tier, some models allow as few as 5 requests per minute, and an agent spends one model
request per step of the workflow. The
wait_seconds(30) pacing in the instruction keeps a polling loop from
hitting that limit; if you still see 429 RESOURCE_EXHAUSTED errors, increase the wait or switch to a model with a
higher quota. Also, some older model IDs are not available to newly created API keys. If a model returns a
404 NOT_FOUND error, choose a current one from the
Gemini model list.Run the agent
From the directory that contains thetransform_agent package, start the agent:
adk run console prints the
same activity with more verbose formatting:
If you do not use Google Cloud, ADK prints a warning at startup that it “Failed to configure mTLS” because default
credentials were not found. The warning is harmless: the Transform MCP server authenticates with your Unstructured
API key, not with Google Cloud credentials.
Extract structured data
The same agent returns named fields as JSON when you ask for specific values rather than the whole document. Two tools cover this, and both are already in thetool_filter and the agent instruction above:
Ask the running agent for an extraction:
output_ref from the completed parse, drafts a schema, and runs the
extraction as a second job:
output_ref; the agent does not
need to download the parsed output first. And extraction results are returned inline rather than behind a
pre-signed download_url, each wrapped with the source filename, file type, timestamp, and the element JSON
reference they came from.
Next steps
- Control Transform file parsing output: Control how the Unstructured Transform MCP server instructs Transform to partition, enrich, chunk, and embed the data based on your files.
- Control Transform structured data extraction: Control how the Unstructured Transform MCP server extracts and formats structured data from your files.
- Control Transform generated sample code: Control how the Unstructured Transform MCP server generates sample curl or Python code that demonstrates how to use Transform to partition, enrich, chunk, and embed the data based on your files.
Questions? Need help?
- For technical support, request support.

