Odobook
Enables Amazon Alexa+ voice interactions for a car logbook, including starting and ending trips, logging past trips, checking logbook status, listing trips, closing a logbook, and exporting records for ATO or IRS mileage tracking.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OdobookStart a work trip to Geelong."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Odobook
A voice car logbook. Odobook keeps the ATO 12-week logbook (Australia, km) or an IRS mileage log (US, miles) while you drive. It's an MCP server built to the published Alexa+ MCP add-on requirements, made for the Amazon "Build, Ship, Shape" hackathon (Alexa+ track).
Live server: https://odobook-alexa.odobook-alexa.workers.dev
MCP endpoint:
https://odobook-alexa.odobook-alexa.workers.dev/mcp
Try it
"Start a work trip to Geelong." "End trip, odometer 52,394. It was a quote for a bathroom reno." "How's my logbook going?"
Odobook replies in one or two short spoken sentences, for example: "Logged 84 km to Geelong for quote for a bathroom reno. Business use is 88% so far."
Related MCP server: time-tracker-ai-mcp
Contents
Alexa+ add-on requirements
Amazon's Alexa+ add-on toolkit (the alexa-ai CLI) is open to select partners only, which Amazon staff confirmed on the hackathon Discord. So Odobook is built to the published requirements and demoed with a stand-in simulator (see friction-log.md).
Requirement | How Odobook meets it | Where |
Streamable HTTP transport, MCP 2025-11-25 | Stateless Streamable HTTP: a fresh server and transport per POST, JSON responses, no sessions. Negotiates protocol |
|
OAuth 2.1 authorization code + PKCE (S256) |
|
|
RFC 8707 resource indicators | Clients send |
|
RFC 9728 protected resource metadata | Served at |
|
RFC 8414 authorization server metadata | Served at |
|
Pre-registered clients, no Dynamic Client Registration | No registration endpoint. Clients are created by an admin with |
|
Unauthenticated requests get a bare 401, no | The OAuth library adds |
|
Round trips under 500 ms | Stateless JSON replies, few D1 queries per tool, smart placement next to the database. Measured live from Australia: about 65 to 360 ms per call. Locally: 8 to 25 ms. |
|
| Locales (en-US, en-AU), descriptions, example phrases, privacy and terms URLs, MCP endpoint, auth type and PRM URL. |
|
Privacy policy and terms pages |
|
|
Account linking UI | Sign in or create an account, then allow, on one page. Same-origin form posts only; strict CSP. |
|
Architecture
One Cloudflare Worker is both the OAuth 2.1 authorization server and the protected MCP resource.
flowchart LR
V["Voice assistant<br/>(Alexa+, or the simulator)"] -->|"OAuth 2.1 + PKCE<br/>/authorize, /oauth/token"| W
V -->|"POST /mcp<br/>Bearer token"| W
subgraph W["Cloudflare Worker (smart placement)"]
P["OAuthProvider<br/>src/index.ts"] --> A["Sign-in, consent, admin,<br/>privacy, terms<br/>src/auth.ts"]
P --> M["MCP server, 11 tools<br/>src/mcp.ts"]
M --> L["Logbook rules<br/>src/logbook.ts"]
end
P <--> KV[("KV: OAUTH_KV<br/>clients, grants, tokens")]
A --> D1[("D1: odobook<br/>users, logbooks, trips")]
M --> D1src/index.ts: wires upOAuthProvider, serves PRM at both well-known paths, stripsWWW-Authenticatefrom/mcp401s.src/auth.ts: the/authorizepage (sign-in or sign-up and consent), PBKDF2 password hashing,POST /admin/clients, landing, privacy and terms pages.src/mcp.ts: the 11 tools and the/mcphandler. Replies are written to be read aloud; details go instructuredContentfor screens.src/logbook.ts: pure logbook rules (periods, vague purposes, late entries, totals, business %, CSV). No Workers or database code, so it's unit tested on its own.schema.sql: D1 tablesusers,logbooks,trips,amendments.Storage: D1 holds accounts and logbooks. KV holds OAuth clients, grants and tokens (managed by the library).
Smart placement: a tool call makes several D1 queries, so the Worker runs near the database and each call costs one long-haul round trip, wherever the caller is.
Tools
Tool | What it does |
| Starts a logbook for a car (make, model, rego, odometer). AU runs 12 weeks; US runs to 31 December. Warns if an AU logbook crosses 30 June, and asks for engine size if missing. |
| Fixes car details (engine cc, rego, make, model). The starting odometer can only change before any trip is logged. |
| Deletes the running logbook, only while it has no completed trips (for example, set up with the wrong car). |
| Starts timing a trip now. Odometer defaults to the last known reading and can't go backwards. Purpose and destination are optional until the end. |
| Ends the running trip from an odometer reading or a distance. Refuses a business trip with a vague or missing purpose. Replies with the business-use % so far. |
| Records a past trip by date, from odometer readings or a distance. Marks it late if entered more than a day after the trip. |
| Throws away the running trip. Completed trips are kept. |
| Days elapsed and left, trips, business and total distance, business-use %, any running trip, and the first warning. |
| Recent completed trips, newest first (default 5, max 50). |
| Closes the period with a final odometer reading and freezes the business-use %. Warns if an AU logbook ran under 12 weeks. |
| Returns the logbook as CSV (date, times, odometer, distance, kind, purpose, destination, late flag) as an embedded resource. |
Every tool carries MCP annotations (readOnlyHint, destructiveHint, idempotentHint). The tool descriptions for cancel_trip, discard_logbook and close_logbook tell the assistant to confirm with the driver first. Scopes are enforced: a token without logbook:write can only call the read-only tools.
Logbook rules
Odobook keeps records. It isn't tax advice and never works out a dollar deduction.
ATO logbook (AU, km): a period of 12 continuous weeks (84 days, start day included). Records make, model, rego and engine size, and for each journey the date, start and end odometer, distance and purpose. Warns when a first-year logbook would run past 30 June (it must fit inside one income year), and when a closed logbook ran under 12 weeks. Flags business trips without odometer readings.
IRS mileage log (US, miles): date, miles, destination and business purpose for each trip, kept to the end of the tax year (31 December).
Purpose specificity: "business", "work", "work trip" and similar aren't a purpose.
end_tripandlog_triprefuse them for business trips and ask what the trip was for. A trip ended with neither a kind nor a purpose isn't guessed: Odobook asks whether it was work or private.Late entries: a past trip entered more than 24 hours after it happened is stored with
late = 1, shown in status warnings and in the CSV.Odometer chain:
start_tripdefaults to the latest reading and refuses a lower one;end_triprefuses a reading below the trip's start;close_logbookrefuses a reading below the last one; the starting odometer is locked once trips exist. A single trip over 3,000 units is queried as a likely misreading.Business % from the odometer: total distance is the latest odometer reading minus the start, because private driving often isn't logged trip by trip. If logged trips add up to more (trips entered by distance only), that sum is used instead. Business % = business distance / total distance, frozen when the logbook closes.
Testing
Suite | Command | Needs |
Unit tests (10, logbook rules) |
| Node 22.6+ (uses |
Typecheck |
| |
End-to-end: OAuth, all 11 tools, latency |
| A running server |
Browser account linking (headless Chromium) |
|
|
ADMIN_TOKEN comes from .dev.vars (not committed). For the live server use the deployed secret's value.
scripts/e2e.mjs walks the Alexa+ path: bare 401, PRM and AS metadata, a pre-registered confidential client, PKCE + resource, sign-up, token exchange, initialize on 2025-11-25, every tool (including refusals for vague purposes and locked odometers), code replay, the simulator's public-client flow on a random loopback port, and a check that every round trip is under 500 ms. scripts/browser-e2e.mjs does sign-up, sign-in and a wrong password in a real browser and checks for console or CSP errors.
Both e2e scripts create a test client and a test account (e2e-…@example.com, browser-…@example.com) on the server they run against.
Local run:
npm install
printf 'PUBLIC_URL=http://localhost:8787\nADMIN_TOKEN=%s\n' "$(openssl rand -hex 24)" > .dev.vars
npm run db:local
npm run dev # http://localhost:8787
BASE=http://localhost:8787 ADMIN_TOKEN=<from .dev.vars> npm run test:e2eDeploy your own
npm install
npx wrangler login
npx wrangler kv namespace create OAUTH_KV # copy the id into wrangler.jsonc kv_namespaces
npx wrangler d1 create odobook # copy the database_id into wrangler.jsonc d1_databases
npm run db:remote # apply schema.sql to the remote D1
npx wrangler secret put ADMIN_TOKEN # a long random string
npm run deploySet PUBLIC_URL in wrangler.jsonc to your Worker's URL (the MCP resource is PUBLIC_URL + "/mcp") and deploy again if it changed.
Register a client (the voice assistant or simulator) ahead of time:
curl -X POST https://<your-worker>/admin/clients \
-H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \
-d '{"name":"Voice simulator","redirectUris":["http://127.0.0.1/callback"],"public":true}'It returns clientId (and clientSecret for confidential clients; omit "public": true for those). A loopback redirect without a port accepts any port, which suits desktop simulators.
Demo with the voice simulator
The demo uses the community mcp-voice-simulator as an Alexa+ stand-in. The brain that picks tools is Amazon Nova 2 Lite on Amazon Bedrock (see simulator/README.md); the simulator's built-in Claude brain also works.
Register a public client as above and note its
clientId.Point the simulator at
https://<your-worker>/mcpwith that client ID. For the Bedrock brain, setSIM_BRAIN=bedrockand an AWS profile; for the Claude brain, putANTHROPIC_API_KEYin its.env(never committed).Start the simulator, link the account in the browser window it opens (create an account or sign in), then talk to it.
A Bedrock-based brain for the simulator lives under simulator/, with its own setup steps.
Agent Skill
skills/odobook-car-logbook/SKILL.md is an Agent Skill that teaches an assistant how to drive the tools: which tool fits which phrase, asking for a specific purpose, one question at a time while driving, confirming destructive actions, and never estimating a deduction.
Limitations and honest notes
Not tested against real Alexa+. The Alexa+ add-on toolkit is partner-gated, so Odobook has only been run against the stand-in simulator and its own e2e tests.
addon.jsonis unvalidated. It follows the field list in Amazon's docs but hasn't been throughalexa-aivalidation or deploy; the nesting may need changes. Its icon and carousel image URLs (/assets/...) aren't served yet.Past-trip odometer readings aren't checked against the chain.
log_tripchecks start against end, but not against other trips.No voice editing of completed trips. The
amendmentstable exists for an audit trail but nothing writes to it yet.One open logbook per account, and one running trip at a time.
Hackathon prototype, not tax advice. Check ato.gov.au or irs.gov, or ask a registered tax agent. Don't rely on Odobook as your only tax record yet.
More docs
docs/: demo script, Devpost write-up and product feedback.friction-log.md: what went wrong with the Alexa+ tooling and what we did instead.simulator/README.md: the Bedrock brain for the voice simulator.scripts/seed-demo.mjs: seeds a demo logbook through the MCP tools (three weeks of a Geelong plumber's trips). Because every trip is entered on seeding day, Odobook correctly flags them all as late.scripts/demo-ontime.sql(run withwrangler d1 execute --remote --file) then gives the demo account's trips realistic end times and marks them as logged live, except one (the Lara callout), so the demo shows the late-entry flag once. This is made-up demo data; real accounts are never edited this way.
License
MIT © 2026 Jayden Tebble
This server cannot be deployed
Maintenance
Related MCP Connectors
Mileage log for deductible driving: trips, effective-dated rates, summaries and CSV export.
Track Australian work-related tax deductions: expenses, assets, car trips and work-from-home days.
Czech mileage logbook (kniha jizd): AI journey drafts, statutory reimbursement, XLSX export
Log expenses, receipts and mileage from chat: auto-categorise, split VAT, summarise, export, rebill.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables users to track and manage personal expenses through natural language, including adding entries, filtering by date/category, viewing statistics, and exporting data in JSON or CSV format.3-
- AlicenseAqualityBmaintenanceEnables tracking work time with start/stop timers, logging entries, and generating reports.42 npm55 PyPIMIT
- AlicenseNot gradedqualityDmaintenanceEnables managing personal vehicle history including mileage, maintenance, expenses, reminders, and document references through MCP tools and resources, all stored locally in SQLite.1MIT
- AlicenseAqualityBmaintenanceLogs deductible driving trips, manages effective-dated mileage rates, computes per-category summaries, and exports CSV for accountants, all locally with no network calls.9MIT