Skip to main content
Glama
joaofilhosm

Unstract MCP Server

by joaofilhosm

Unstract MCP Server

A public remote Model Context Protocol server that exposes an Unstract API Deployment to AI agents.

It runs on Vercel as a stateless Streamable HTTP endpoint and is compatible with OpenAI and Claude (and any other MCP client that speaks Streamable HTTP).


How it works

The Unstract platform already ships a native MCP server (backend/mcp_server/). This project is a thin, stateless proxy in front of it:

Claude / OpenAI  ──Bearer <MCP_PUBLIC_KEY>──▶  this server (Vercel)
                                                     │
                                                     │ Authorization: Bearer <UNSTRACT_API_KEY>
                                                     ▼
                                    Unstract MCP endpoint
                          /deployment/api/<org>/<api_name>/mcp

The Unstract API key lives only in the server's environment variables. Clients never see it — they authenticate with a separate public key you issue. The proxy forwards JSON-RPC envelopes verbatim and returns the upstream response untouched, so none of Unstract's business rules are reimplemented here:

  • S3 pre-signed URL validation

  • quota / rate-limit accounting

  • input schemas and their validation errors

  • the one-shot semantics of a completed extraction result


Related MCP server: AgentHansa HTTP MCP

Tools

Tool

Purpose

readMeFirst

Instructions and context about the connected deployment.

getApiInfo

Deployment metadata: display name, API name, workflow, active state.

extractDocument

Run LLM-driven extraction over document URLs. Consumes quota.

getExecutionStatus

Poll for the result of a pending extraction.

extractDocument arguments

Argument

Type

Default

Notes

document_urls

string[]

required

HTTPS URLs on an AWS S3 host. Use a pre-signed URL for private objects. Max 32 URLs.

timeout

integer

30

-1 to return immediately and poll. Range -1–300 seconds.

include_metadata

boolean

false

Include extraction metadata.

include_metrics

boolean

false

Include token and cost metrics.

include_extracted_text

boolean

false

Include the full raw text (can be very large).

tags

string[]

–

At most 1 tag.

llm_profile_id

string

–

UUID of an LLM profile overriding the deployment default.

getExecutionStatus arguments

Argument

Type

Default

execution_id

string

required

include_metadata

boolean

false

include_metrics

boolean

false

include_extracted_text

boolean

false


⚠️ Critical behaviour to respect

  1. extractDocument always returns an execution_id. Never re-run it after receiving one — every retry consumes quota a second time. Poll with getExecutionStatus instead.

  2. A completed result can only be read once. The first COMPLETED poll consumes it; a second poll returns "This result was already acknowledged and is no longer retrievable."

  3. Documents must already be on S3 and referenced by an HTTPS URL whose host ends in amazonaws.com. Any other host is rejected. For private objects, generate a pre-signed URL.

  4. timeout: -1 runs asynchronously — use it when you intend to poll.


Configuration

Set these environment variables in your Vercel project:

Variable

Required

Description

UNSTRACT_API_KEY

✅

Your Unstract API key (a UUID). Never exposed to clients.

UNSTRACT_ORG_NAME

✅

The <org> segment of your deployment REST URL.

UNSTRACT_API_NAME

✅

The <api_name> segment of your deployment REST URL.

MCP_PUBLIC_KEY

✅

Bearer token your clients must send to use this server.

UNSTRACT_BASE_URL

–

Defaults to https://us-central.unstract.com. Use https://eu-central.unstract.com for EU.

ALLOWED_ORIGINS

–

Comma-separated CORS origins. Defaults to *.

UPSTREAM_TIMEOUT_MS

–

Upstream request timeout in ms. Defaults to 55000.


Client configuration

Claude Desktop / Claude Code

claude mcp add --transport http unstract \
  https://<your-deployment>.vercel.app/mcp \
  --header "Authorization: Bearer <MCP_PUBLIC_KEY>"

Claude Desktop (claude_desktop_config.json)

{
  "mcpServers": {
    "unstract": {
      "type": "http",
      "url": "https://<your-deployment>.vercel.app/mcp",
      "headers": {
        "Authorization": "Bearer <MCP_PUBLIC_KEY>"
      }
    }
  }
}

OpenAI

OpenAI's MCP connector expects an HTTP endpoint with bearer auth:

{
  "mcpServers": {
    "unstract": {
      "type": "http",
      "url": "https://<your-deployment>.vercel.app/mcp",
      "authorization": "Bearer <MCP_PUBLIC_KEY>"
    }
  }
}

Endpoints

Path

Method

Auth

Description

/mcp

POST

Bearer

The MCP endpoint (Streamable HTTP, request/response).

/

GET

–

Service identity and protocol information.

/health

GET

–

Health check used by the platform.


Development with a local mock

A mock of the Unstract MCP endpoint ships with this repo. It reproduces the real backend's contract (validation rules, the execution_id contract, the one-shot completed-result behaviour) so you can exercise the whole path without credentials.

npm install
npm run build
npm run dev:mock

It prints the MCP endpoint and a ready-to-use bearer token:

MCP endpoint : http://localhost:3000/mcp
Bearer token : mock-client-key

Then:

curl -s http://localhost:3000/mcp \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer mock-client-key' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

The mock returns synthetic extraction results. It exists to validate the proxy, not to replace the real platform.


Local development

npm install
npm test          # 37 unit + integration tests
npm run typecheck
npm run dev

To run against the real Unstract backend, export the env vars and start the server:

export UNSTRACT_API_KEY=<your uuid>
export UNSTRACT_ORG_NAME=<org>
export UNSTRACT_API_NAME=<api name>
export MCP_PUBLIC_KEY=<any secret>
npm run dev

Then:

curl -s http://localhost:3000/mcp \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <MCP_PUBLIC_KEY>' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}'

Protocol details

  • Transport: Streamable HTTP, request/response (no SSE).

  • JSON-RPC: 2.0. Batch requests are rejected with -32600.

  • Protocol revisions: 2025-06-18 (preferred) and 2024-11-05 (accepted).

  • Methods: initialize, ping, tools/list, tools/call.

  • Errors: JSON-RPC errors are returned with HTTP 200, except authentication which returns a real HTTP 401 with a WWW-Authenticate header.

  • Tool errors that the agent can fix are returned as result.isError = true (HTTP 200).

  • Unexpected tool errors use JSON-RPC code -32002.


Deployment

This project deploys to Vercel with zero configuration:

  • api/index.ts is the serverless function entry point.

  • vercel.json pins maxDuration: 60 and rewrites /mcp → /api/index.

  • The function is fully stateless — no filesystem, no shared state, so it scales horizontally.

vercel --prod

License

MIT — see LICENSE.

This project is an independent client of the Unstract API. It is not affiliated with or endorsed by Zipstack. Unstract itself is licensed under AGPL-3.0.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Lifts local stdio MCP servers into remote Streamable HTTP endpoints for cloud-hosted AI clients, with bearer-token auth and tool policy filtering.
    15 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Exposes AgentHansa's MCP tools to remote clients over Streamable HTTP, enabling ChatGPT and desktop agents to use the AgentHansa service through a secure authenticated endpoint.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables secure exposure of internal tools to LLM clients with API-key authentication, tenant isolation, per-tool guardrails, PII scrubbing, rate limiting, audit logging, and telemetry over stdio and HTTP/SSE.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to read tenants, computers, inventory, deployments, compliance, maintenance sessions, scripts and software catalogs from an ImmyBot instance, and, with explicit confirmation, start maintenance, install software, run deployments or run scripts on machines. Credentials are supplied per request via headers and never stored, so one stateless deployment can serve multiple instances.
    Apache 2.0