MCP
ScriptHaul has two deliberately different Streamable HTTP MCP endpoints.
| Endpoint | Authentication | Intended use |
|---|---|---|
https://scripthaul.com/mcp | None | A small keyless taste: 20 cold fetches per address per UTC day; bulk links back to the free site. |
https://api.scripthaul.com/mcp | Authorization: Bearer | The account's REST limits, balance, metering, and keyed bulk jobs. |
The keyless server is unchanged and never accepts an API key. The keyed server is registered as com.scripthaul/api and exposes five tools: get_transcript, list_videos, get_bulk_download_link, create_bulk_job, and get_job. The download-link tool only returns a prefilled link to the free bulk site; it does not create a keyed job. Transcript and listing behavior matches REST: cache hits, metadata, and enumeration cost zero; one successfully delivered cold transcript costs one credit. A keyed bulk call creates the same durable job as POST /v1/jobs, including reservations and account-scoped idempotency. create_bulk_job and get_job return the job envelope without per-video rows; page GET /v1/jobs/{id}/videos (with status=error for failures) when an agent needs them.
Never put a key in the MCP URL or client arguments that may be logged. Use an HTTP header supplied from the client's secret or environment configuration. The server rejects query-string credentials.
{
"mcpServers": {
"scripthaul": {
"type": "http",
"url": "https://api.scripthaul.com/mcp",
"headers": { "Authorization": "Bearer ${SCRIPTHAUL_API_KEY}" }
}
}
}
Machine discovery
Agents can discover the narrow ScriptHaul transcript skill at /.well-known/agent-skills/index.json. Its SHA-256 digest pins the exact SKILL.md bytes. The skill says when to choose keyless MCP, keyed MCP, or REST and explicitly excludes video and audio download.
The keyed remote publishes an experimental MCP server card at /mcp/server-card with the same Bearer-header template as the client configuration above. The card format is an experimental MCP extension and may change.
List keyed tools in four languages
Maintained runnable versions are in the examples directory.
curl https://api.scripthaul.com/mcp -X POST -H "Authorization: Bearer $SCRIPTHAUL_API_KEY" -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
import json, os, urllib.request
body = json.dumps({"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}).encode()
request = urllib.request.Request("https://api.scripthaul.com/mcp", data=body, method="POST")
request.add_header("Authorization", f"Bearer {os.environ['SCRIPTHAUL_API_KEY']}")
request.add_header("Content-Type", "application/json")
print(urllib.request.urlopen(request).read().decode())
const response = await fetch("https://api.scripthaul.com/mcp", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SCRIPTHAUL_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "tools/list", params: {} }),
});
console.log(await response.json());
body := strings.NewReader(`{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}`)
req, _ := http.NewRequest("POST", "https://api.scripthaul.com/mcp", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("SCRIPTHAUL_API_KEY"))
req.Header.Set("Content-Type", "application/json")
response, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer response.Body.Close()
io.Copy(os.Stdout, response.Body)