MCP Server
Unstract hosts a Model Context Protocol (MCP) server alongside every API deployment, so coding agents and other MCP clients can run document extraction as tool calls instead of building HTTP requests by hand.
The server runs inside Unstract itself — there is nothing to install or host, and no new credential to create. An MCP session is scoped to exactly one API deployment and authenticates with the API key that deployment already uses.
The older stdio server distributed as the unstract/mcp-server Docker image is documented separately under Local MCP Server (stdio). The server described on this page needs no local process.
What you need
- An API deployment. See API Deployments if you have not created one yet.
- That deployment's API key, available from the API Deployment tab in the same place you manage keys for REST calls.
- An MCP client that connects over HTTP and can send an
Authorizationheader — Claude Code, for example.
Endpoint
The MCP endpoint sits directly alongside the deployment's REST endpoint, with /mcp appended:
POST /deployment/api/<org_name>/<api_name>/ # REST
POST /deployment/api/<org_name>/<api_name>/mcp # MCP
Both are the same deployment reached two ways. <org_name> and <api_name> are exactly the values already in your deployment's REST URL, so the simplest way to build the MCP URL is to copy the REST one and add mcp.
Authentication
Pass the deployment's existing API key as a bearer token:
Authorization: Bearer <api_key>
This is the same key used for REST execution, managed from the same screen. There is no separate MCP credential to create or revoke, and revoking the key closes both surfaces at once.
There is deliberately no endpoint that accepts the API key as part of the path. A key in a URL reaches web-server and application access logs, monitoring traces and any proxy in between — places a header never reaches — and the MCP specification requires the Authorization header on every authenticated request. If your client cannot set headers, it cannot connect to this server.
Every authentication failure answers 401 with no detail, whatever the cause, so the endpoint cannot be used to discover which deployment names exist.
Connecting
Claude Code
claude mcp add --transport http unstract \
https://us-central.unstract.com/deployment/api/<org_name>/<api_name>/mcp \
--header "Authorization: Bearer <api_key>"
Other clients
Point the client at the same URL over HTTP transport, with the Authorization header set. Many clients express this as JSON along these lines — check your client's own documentation for the exact key names it expects:
{
"mcpServers": {
"unstract": {
"type": "http",
"url": "https://us-central.unstract.com/deployment/api/<org_name>/<api_name>/mcp",
"headers": {
"Authorization": "Bearer <api_key>"
}
}
}
}
Replace the host with your own — for example https://eu-central.unstract.com on the EU region, or your own domain for an on-premise installation.
Tools
| Tool | Purpose |
|---|---|
readMeFirst | Orientation for the agent, built from the live deployment. Worth calling first. |
getApiInfo | Name, description, workflow and active state of the connected deployment. |
extractDocument | Run the deployment's extraction workflow over one or more documents. Consumes your extraction quota. |
getExecutionStatus | Fetch the result of an extraction started by extractDocument. |
The deployment fixes the prompts and the output schema, so an agent supplies documents rather than instructions. To change what is extracted, change the Prompt Studio project behind the deployment.
extractDocument arguments
| Argument | Type | Default | Description |
|---|---|---|---|
document_urls | array of strings | — | Required. HTTPS URLs of the documents to extract. At most 32 per call. See Supplying documents below. |
timeout | integer | 30 | Seconds to wait for extraction to finish before returning a pending result. Ranges from -1 to 300; use -1 to return immediately and poll. |
include_metadata | boolean | false | Include extraction metadata in the result. |
include_metrics | boolean | false | Include token and cost metrics in the result. |
include_extracted_text | boolean | false | Include the full raw text of each document alongside the structured output. This can be very large. |
tags | array of strings | — | Tags to record against the execution. Currently limited to 1 tag, which must start with a letter and contain only letters, numbers, underscores and hyphens. |
llm_profile_id | string | — | UUID of an LLM profile to override the deployment's default. |
The default timeout of 30 seconds is shorter than the REST API's, deliberately: holding an MCP call open for several minutes looks like a hang to an agent, so the server returns early and lets the agent poll instead.
getExecutionStatus arguments
| Argument | Type | Default | Description |
|---|---|---|---|
execution_id | string | — | Required. The execution_id returned by a previous extractDocument call. |
include_metadata | boolean | false | Include extraction metadata in the result. |
include_metrics | boolean | false | Include token and cost metrics in the result. |
include_extracted_text | boolean | false | Include the full raw text of each document. |
Supplying documents
Documents are not uploaded through the MCP call. You pass URLs, and Unstract fetches each document server-side — the same mechanism the REST API uses for presigned_urls:
- The URL must use HTTPS.
- The host must be an AWS S3 endpoint. Links to any other host are rejected, so upload the document to S3 first if it is not already there.
- For a private object, pass a pre-signed URL. This is the usual case. An object that is already publicly readable needs no signature.
The maximum file size per URL is configurable by your administrator. See API Execution for the full set of rules, which the MCP server shares with the REST surface.
How an extraction completes
Extraction is asynchronous. A typical exchange runs:
extractDocumentis called with one or more document URLs.- If extraction finishes within
timeout, the response carriesexecution_status: COMPLETEDand the result — nothing further is needed. - Otherwise the response carries
execution_status: PENDINGand anexecution_id. - The agent polls
getExecutionStatuswith thatexecution_id, pausing a few seconds between calls, until the status isCOMPLETEDorERROR.
An execution_id is always returned, so a pending extraction is never lost. Never retry an extractDocument call that already returned an execution_id — that starts a second extraction and consumes quota again. Poll instead.
Reading a COMPLETED execution acknowledges it, and the result is not retrievable afterwards. A second getExecutionStatus call for the same execution_id returns a message saying the result was already acknowledged, not the result. This is existing API deployment behaviour, which the REST surface reports as HTTP 406; it is not specific to MCP. If an agent needs the data again, it must run a new extraction.
Limits and errors
extractDocument consumes your organization's extraction quota and is subject to the same organization-level rate limit as REST execution. When that limit is reached, the tool reports how much is in use and asks the caller to retry once running extractions finish.
Problems an agent can act on — a bad argument, an inactive deployment, a rate limit — come back as readable tool errors that the agent can correct and retry. Unexpected failures are logged server-side and reported generically, without internal detail; if one persists, an administrator can correlate it by deployment name and timestamp. Free-form error text is passed through redaction before it leaves the server, so a failing connector cannot leak the connection string it tried.
If the deployment is inactive, extractDocument refuses with a message saying so. Activate it in Unstract and retry.
Protocol details
- Transport: Streamable HTTP. Every tool call is a request/response pair.
- Protocol revision:
2025-06-18. A client that asks for2024-11-05is also accepted — the parts of the protocol used here are identical across the two revisions. - Methods:
initialize,tools/list,tools/callandping. GETon the endpoint answers405 Method Not Allowed. Under Streamable HTTP aGETopens a server-to-client event stream, and this server has nothing to stream, so it declines. This is expected and is not a misconfiguration.
Troubleshooting
| What you see | Likely cause |
|---|---|
401 on connect | Wrong or revoked API key, wrong <org_name>/<api_name>, or the key belongs to a different deployment. All auth failures look identical by design. |
405 when testing in a browser | A browser issues GET. The endpoint accepts POST only; use an MCP client. |
| Client cannot connect at all | The client must support HTTP transport and custom headers. A stdio-only client cannot reach this server — see Local MCP Server (stdio). |
| A document URL is rejected | The URL is not HTTPS, or its host is not an AWS S3 endpoint. Upload to S3 and pass a pre-signed URL. |
| The deployment is reported as not active | Activate the deployment in the API Deployment tab. |
getExecutionStatus says the result was already acknowledged | The result was already read once and is gone. Run a new extraction. |