AutoUncle Data Services is in beta. The API, MCP tools and agent skill may change often, including breaking changes, until version 1.0. Read the changelog before you upgrade an integration.
Connect an agent
AutoUncle Data Services runs a remote MCP server, so AI agents and assistants can value cars, browse the catalogue and check your account with the same operations, limits and billing as the REST API.
https://data-services.autouncle.com/mcp
At a glance
| Transport | Streamable HTTP. Every JSON-RPC message is a POST to the endpoint above. |
| Sessions | Stateless. The server issues no Mcp-Session-Id, and tools/call works without a prior initialize. |
| Protocol | The server answers initialize with protocol version 2025-06-18. |
| Authentication | OAuth sign-in, or an API key sent as Authorization: Bearer au_.... See OAuth or API key. |
| Tools | valuate_car, normalize_vehicle, decode_vin, decode_hsn_tsn, lookup_plate, search_vehicles, get_valuation, get_account. See the tool reference. |
| Prompts | value_a_car, a guided valuation conversation. |
| Billing | A valued live result uses one credit, exactly as over REST. Test keys are free. OAuth connections are always live. |
Choose how to authenticate
- API key: best for servers, scripts and development. A test key (
au_test_...) gives free simulated results, so it is the safest way to try an agent. Configure the key through an environment variable or the client's secret input, never as plain text in a shared file. - OAuth: best for people using a chat assistant. The client opens AutoUncle's sign-in page, you choose one organization and approve the scopes. No key is copied anywhere. OAuth valuations are live and use the organization's credits.
OAuth or API key compares the two in detail.
Set up your client
| Client | OAuth | API key header | Guide |
|---|---|---|---|
| Claude Code | Yes | Yes | Claude Code |
| Claude Desktop and claude.ai | Yes | Limited beta | Claude Desktop & claude.ai |
| Cursor | Yes | Yes | Cursor |
| VS Code and GitHub Copilot | Yes | Yes | VS Code & GitHub Copilot |
| ChatGPT | Yes | No | ChatGPT, OpenAI API & Codex |
| OpenAI Responses API and Agents SDK | Your app supplies the token | Yes | ChatGPT, OpenAI API & Codex |
| Codex CLI | Yes | Yes | ChatGPT, OpenAI API & Codex |
| Gemini CLI and Antigravity | Yes | Yes | Gemini & Antigravity |
| Windsurf (Devin Desktop) | Yes | Yes | Windsurf |
| Anything else | Depends | Depends | Other MCP clients |
Every guide ends with the same check: ask the agent to call get_account. A working connection returns your workspace, the key's mode (test or live) and its scopes.
Test the endpoint directly
You do not need an MCP client to see what agents receive. These examples send raw JSON-RPC over HTTP with a key from AUTOUNCLE_API_KEY. The Accept header must allow both JSON and event streams.
Initialize (optional, the server is stateless):
curl https://data-services.autouncle.com/mcp \
-H "Authorization: Bearer $AUTOUNCLE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d @- <<'JSON'
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": {
"name": "my-integration",
"version": "1.0.0"
}
}
}
JSON
require "json"
require "net/http"
uri = URI("https://data-services.autouncle.com/mcp")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("AUTOUNCLE_API_KEY")}"
request["Content-Type"] = "application/json"
request["Accept"] = "application/json, text/event-stream"
request.body = JSON.generate({
"jsonrpc" => "2.0",
"id" => 1,
"method" => "initialize",
"params" => {
"protocolVersion" => "2025-06-18",
"capabilities" => {},
"clientInfo" => {
"name" => "my-integration",
"version" => "1.0.0"
}
}
})
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
puts JSON.pretty_generate(JSON.parse(response.body))
import json
import os
import requests
response = requests.post(
"https://data-services.autouncle.com/mcp",
headers={
"Authorization": f"Bearer {os.environ['AUTOUNCLE_API_KEY']}",
"Accept": "application/json, text/event-stream",
},
json={
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": {
"name": "my-integration",
"version": "1.0.0"
}
}
},
timeout=30,
)
print(json.dumps(response.json(), indent=2))
const response = await fetch("https://data-services.autouncle.com/mcp", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTOUNCLE_API_KEY}`,
"Content-Type": "application/json",
Accept: "application/json, text/event-stream",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "initialize",
params: {
protocolVersion: "2025-06-18",
capabilities: {},
clientInfo: {
name: "my-integration",
version: "1.0.0"
}
}
}),
});
console.log(JSON.stringify(await response.json(), null, 2));
List the tools and their input schemas:
curl https://data-services.autouncle.com/mcp \
-H "Authorization: Bearer $AUTOUNCLE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d @- <<'JSON'
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
JSON
require "json"
require "net/http"
uri = URI("https://data-services.autouncle.com/mcp")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("AUTOUNCLE_API_KEY")}"
request["Content-Type"] = "application/json"
request["Accept"] = "application/json, text/event-stream"
request.body = JSON.generate({
"jsonrpc" => "2.0",
"id" => 1,
"method" => "tools/list"
})
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
puts JSON.pretty_generate(JSON.parse(response.body))
import json
import os
import requests
response = requests.post(
"https://data-services.autouncle.com/mcp",
headers={
"Authorization": f"Bearer {os.environ['AUTOUNCLE_API_KEY']}",
"Accept": "application/json, text/event-stream",
},
json={
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
},
timeout=30,
)
print(json.dumps(response.json(), indent=2))
const response = await fetch("https://data-services.autouncle.com/mcp", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTOUNCLE_API_KEY}`,
"Content-Type": "application/json",
Accept: "application/json, text/event-stream",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/list"
}),
});
console.log(JSON.stringify(await response.json(), null, 2));
Value a car through the valuate_car tool. The arguments are the same body as POST /v1/valuations, with idempotency_key as an argument instead of a header:
curl https://data-services.autouncle.com/mcp \
-H "Authorization: Bearer $AUTOUNCLE_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d @- <<'JSON'
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "valuate_car",
"arguments": {
"country": "DK",
"vehicle": {
"make": "Volkswagen",
"model": "Golf",
"model_year": 2020,
"mileage": {
"value": 60000,
"unit": "km"
}
},
"idempotency_key": "first-valuation-001"
}
}
}
JSON
require "json"
require "net/http"
uri = URI("https://data-services.autouncle.com/mcp")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("AUTOUNCLE_API_KEY")}"
request["Content-Type"] = "application/json"
request["Accept"] = "application/json, text/event-stream"
request.body = JSON.generate({
"jsonrpc" => "2.0",
"id" => 1,
"method" => "tools/call",
"params" => {
"name" => "valuate_car",
"arguments" => {
"country" => "DK",
"vehicle" => {
"make" => "Volkswagen",
"model" => "Golf",
"model_year" => 2020,
"mileage" => {
"value" => 60000,
"unit" => "km"
}
},
"idempotency_key" => "first-valuation-001"
}
}
})
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
puts JSON.pretty_generate(JSON.parse(response.body))
import json
import os
import requests
response = requests.post(
"https://data-services.autouncle.com/mcp",
headers={
"Authorization": f"Bearer {os.environ['AUTOUNCLE_API_KEY']}",
"Accept": "application/json, text/event-stream",
},
json={
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "valuate_car",
"arguments": {
"country": "DK",
"vehicle": {
"make": "Volkswagen",
"model": "Golf",
"model_year": 2020,
"mileage": {
"value": 60000,
"unit": "km"
}
},
"idempotency_key": "first-valuation-001"
}
}
},
timeout=30,
)
print(json.dumps(response.json(), indent=2))
const response = await fetch("https://data-services.autouncle.com/mcp", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTOUNCLE_API_KEY}`,
"Content-Type": "application/json",
Accept: "application/json, text/event-stream",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: {
name: "valuate_car",
arguments: {
country: "DK",
vehicle: {
make: "Volkswagen",
model: "Golf",
model_year: 2020,
mileage: {
value: 60000,
unit: "km"
}
},
idempotency_key: "first-valuation-001"
}
}
}),
});
console.log(JSON.stringify(await response.json(), null, 2));
The console playground's MCP transport sends this exact call through the same server, so you can compare it with the REST result side by side.
What results look like
Tool results carry the same JSON as REST: once as structuredContent and once as text in content, for clients that only read text. They include notes and attributions; agents must keep them with the price and show attribution_text when present (notes and data sources).
Refused and failed valuations return isError: true with the full valuation envelope and its error object, including code, fix steps and retryable. They are free. If the connection itself is rejected, for example with a missing or revoked key, the server answers with HTTP 401 and a JSON-RPC error whose data is a Problem.
Next steps
- Tool reference: every argument and result.
- Agent prompts & examples: prompts that make agents use the tools well.
- Safety & spend control: keep agents from spending credits by surprise.
- Agent skill: teach a coding agent to integrate the REST API safely.