A1C Console docs
Sally Skills is a metered, agent-callable surface over Sally's metabolic-health stack. Plug it into any MCP- or REST-aware agent. Pay per call. No subscription.
These docs are a curated summary for users. The canonical reference — schemas,
protocols, response shapes, error codes — lives in the open-source repo at
a1c-ai-agent/sally-skills.
Treat anything you read here as a starting point; the repo is always current.
Quickstart #
Four steps from zero to a working integration.
Sign up on A1C Insights
Sally Skills uses your A1C account for identity. Install the A1C Insights iOS app and create an account if you haven't yet — sign-up is free. Open the app once so it syncs your wearables and CGM data before you mint a key.
Mint an API key
Sign in at console.a1c.io with the same email. Click + New key, give it a label (e.g. "Claude Code, laptop"), and copy the sk-sally-… value.
Top up the wallet (only for paid skills)
health_sync is free. Paid skills check the wallet first and reject with 402 payment_required if you're short. Top up via Stripe Checkout on the Billing page.
Connect your agent
Drop the key into your agent's MCP or REST config. Worked examples in Sally MCP.
Authentication #
The sk-sally-… key is the identity. The gateway resolves
every key to one A1C user and uses that user's UUID for every downstream query.
Skill inputs never take a user identifier — schemas are strict and reject unknown
fields with invalid_input.
How it works
- Multi-key per user — mint a key per device or per agent. Each key has its own audit trail in
usage_events. - Per-account wallet — top-ups are shared across every key. Revoking one key doesn't strand a balance.
- Instant revocation — revoke from the console; other keys keep working.
- Plaintext shown once — the platform stores a SHA-256 hash plus a 12-char prefix for lookup. The plaintext is never persisted server-side after creation.
Sending the key
Every billed request to sally.a1c.io needs the Authorization header:
Authorization: Bearer sk-sally-...
Two MCP discovery methods are intentionally public so any
scanner or directory (Smithery, awesome-mcp lists, an agent's first probe)
can read the tool catalog without a key: initialize and
tools/list. They return server info and skill schemas but never
invoke a skill, so nothing is charged. The moment a request becomes
tools/call, the bearer is required and the wallet is decremented
per skill price.
Skill catalog #
Six skills live today. Discover them programmatically via MCP tools/list
or REST GET /v1/skills — both return the same set with versions,
descriptions, JSON-Schema inputs, and prices.
health_sync
Wearables, CGM, sleep, vitals, activity, environment — daily series + opt-in minute-base CGM.
chat_with_sally
Conversational preventive-health + TCM knowledge with source citations.
analyze_lab_result
Lipid, HbA1c, CBC, thyroid, hormone, micronutrient panels via VLM OCR + clinical analysis.
food_journal
Assess meals via inline image — macros, smart/trap categorisation, dish naming.
health_insights
Daily readouts — morning, afternoon, evening, or auto.
metabolic_overview
CGM-powered snapshot — TIR, variability, postprandial spikes, with what-is-driving narrative.
Roadmap (coming soon)
These appear in tools/list as coming_soon so agents discover the roadmap; tools/call rejects them with not_found until live.
health_report— longitudinal biomarker trends + clinician-shareable summariesmetabolic_risk_score— 5- and 10-year T2D, metabolic syndrome, cardiovascular risksupplement_grading— interactions, evidence quality, biomarker gapspreventive_protocol— multi-week intervention plans with checkpoints
Sally MCP #
Sally Skills ships a Model Context Protocol server at
https://sally.a1c.io/mcp. Drop the universal config into any
MCP-aware client (Claude Code, Claude Desktop, Manus, Perplexity, Codex,
Windsurf, Google Antigravity, etc.) and the six skills appear as
callable tools automatically. The LLM picks which one to invoke based
on the user's request; you don't wire each skill manually.
Universal config
Transport is Streamable HTTP (JSON-RPC 2.0 over a single POST endpoint, no stdio subprocess). Every client uses the same JSON shape:
{
"mcpServers": {
"sally": {
"url": "https://sally.a1c.io/mcp",
"headers": {
"Authorization": "Bearer sk-sally-..."
}
}
}
}
Replace sk-sally-... with the key you minted at
console.a1c.io/keys. The only
difference between agents below is where this JSON lives on
disk (or which settings panel hosts it).
Available tools
After connecting, the agent sees six tools via tools/list
(each call is metered against the wallet on your A1C account):
health_sync— wearable + CGM + sleep + vitals + activity + environment (free)chat_with_sally— preventive-health + TCM Q&A with citations ($0.003)analyze_lab_result— VLM OCR + clinical reading of lab PDFs / images ($0.008)food_journal— meal photo to macros + smart/trap categorisation ($0.004)health_insights— morning / afternoon / evening readout ($0.003)metabolic_overview— CGM snapshot, TIR, variability ($0.005, CGM required)
Quick start by agent
Claude Code
Fastest path — register it from the CLI in one command:
claude mcp add --transport http sally https://sally.a1c.io/mcp \
--header "Authorization: Bearer sk-sally-..."
Or write the JSON yourself to ~/.claude/mcp.json (user-wide)
or .mcp.json at a project root. Claude Code speaks Streamable
HTTP natively, so mark the transport with "type": "http":
{
"mcpServers": {
"sally": {
"type": "http",
"url": "https://sally.a1c.io/mcp",
"headers": {
"Authorization": "Bearer sk-sally-..."
}
}
}
}
Restart the claude CLI and the sally server
appears in /mcp.
Claude Desktop
Claude Desktop's config file only accepts stdio servers,
so the remote endpoint is bridged with
mcp-remote
(it proxies the Streamable HTTP transport through a local subprocess).
Place this at:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"sally": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://sally.a1c.io/mcp",
"--header",
"Authorization:${AUTH_HEADER}"
],
"env": {
"AUTH_HEADER": "Bearer sk-sally-..."
}
}
}
}
The token lives in env and is referenced as
Authorization:${AUTH_HEADER} with no space after the colon —
mcp-remote mis-parses a --header value that
contains a space. Quit Claude Desktop fully and reopen; the tools appear
in the slash-command picker.
Manus
In the Manus workspace, open Settings → MCP servers → Add server.
Choose transport HTTP, paste https://sally.a1c.io/mcp
as the URL, and add the header Authorization: Bearer sk-sally-....
Save; the tools become available to any agent run in that workspace.
Perplexity
Under Settings → Tools / MCP (Perplexity Pro), click
Add MCP server. Server URL is
https://sally.a1c.io/mcp; add an Authorization header with
Bearer sk-sally-.... Sally's tools appear under the search-with-tools
toolbar in chat.
Codex (OpenAI CLI / app)
Edit ~/.codex/config.toml and add a Streamable-HTTP server.
Codex's header key is http_headers (not headers),
and it has no inline bearer-token field:
[mcp_servers.sally]
url = "https://sally.a1c.io/mcp"
http_headers = { Authorization = "Bearer sk-sally-..." }
To keep the key out of the file, point Codex at an env var instead — it
resolves the value at launch and sends
Authorization: Bearer <value>:
[mcp_servers.sally]
url = "https://sally.a1c.io/mcp"
bearer_token_env_var = "SALLY_API_KEY"
The env-var form needs SALLY_API_KEY exported in the
environment Codex runs in — a Dock-launched Codex app won't inherit
shell exports, so prefer http_headers there. The same fields
are available in the GUI via Connect to a custom MCP
(transport Streamable HTTP). Restart codex; tools
are listed under codex mcp list.
Windsurf (Codeium)
Save the universal JSON to
~/.codeium/windsurf/mcp_config.json (one server entry per
key under mcpServers). Reload Windsurf via
Cmd/Ctrl + Shift + P → Reload Window. The Cascade panel
picks up the new tools on next message.
Google Antigravity
Open Settings → Agent → MCP servers → Add. Set the URL
to https://sally.a1c.io/mcp and the Authorization header to
Bearer sk-sally-.... Save; the tools appear immediately in
the agent panel without needing a restart.
Verify your connection
Independent of any client, confirm the endpoint is reachable and your
key is accepted with a single tools/list call. Streamable
HTTP needs the Accept header to allow both JSON and SSE —
swap in your sk-sally-… key:
curl -sS https://sally.a1c.io/mcp \
-H "Authorization: Bearer sk-sally-..." \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
A healthy server returns the six live skills:
health_sync · chat_with_sally · analyze_lab_result
food_journal · health_insights · metabolic_overview
In Codex, confirm the server is registered and the bearer header is attached:
codex mcp list # sally_ai → enabled, Auth: Bearer token
codex mcp get sally_ai # transport: streamable_http, http_headers: Authorization=*****
Then ask any connected agent to run the free health_sync
tool — if it returns data, the full round-trip
(client → gateway → skill → wallet check) works.
Protocol details
Sally implements MCP 2024-11-05 over Streamable HTTP. The
three methods you'll see in the wild:
initialize (public)
Protocol handshake. No bearer required — any scanner can probe this.
POST /mcp
Content-Type: application/json
{ "jsonrpc": "2.0", "id": 1, "method": "initialize" }
tools/list (public)
Discover every available skill, including roadmap entries. No bearer required so MCP catalog registries (Smithery, awesome-mcp lists) can cache the tool list. Returns names + descriptions + input schemas only; no skill code runs and no wallet is touched.
{ "jsonrpc": "2.0", "id": 2, "method": "tools/list" }
tools/call
Invoke a skill by name with its input arguments.
{
"jsonrpc": "2.0", "id": 3,
"method": "tools/call",
"params": {
"name": "health_sync",
"arguments": { "aggregate": true }
}
}
The response wraps the skill output in MCP's
content: [{ type: "text", text: "..." }] envelope; the raw
REST envelope (usage + version) is mirrored under
result._meta for clients that look for it.
Don't see your agent above?
Any client that supports remote MCP servers (HTTP transport, bearer
auth) will work. Use the universal JSON, point it at
https://sally.a1c.io/mcp, restart. If your agent only
supports stdio MCP, run
npx mcp-remote https://sally.a1c.io/mcp --header "Authorization:Bearer
sk-sally-..." as the local stdio bridge.
REST protocol #
Dispatcher endpoint
Single entry point — pick the skill in the body.
POST https://sally.a1c.io/v1/call
{ "skill": "health_sync", "input": { ... } }
Per-skill endpoint
Same dispatcher, slightly cleaner URL — name in the path.
POST https://sally.a1c.io/v1/skills/health_sync
{ ... input ... }
List skills (no auth)
curl -sS https://sally.a1c.io/v1/skills | jq
Full REST reference →
Wallet #
One wallet per A1C account, keyed on your user UUID. Every sk-sally-… you mint draws from the same balance.
- Free skills work regardless of balance — pre-check is skipped.
- Paid skills deduct on success. Failures are logged but not billed.
- Insufficient balance →
402 payment_requiredbefore any upstream cost is incurred. - Per-key audit — every call records
api_key_idinusage_eventsso you can see which key spent what.
See your balance + recent calls on console.a1c.io/billing.
Top up with Stripe #
Card payments via Stripe Checkout. No subscriptions — one-time top-ups credit the wallet immediately.
- Sign in at console.a1c.io/billing
- Pick a preset ($5 / $10 / $20 / $50 / $100) or enter a custom amount ($5–$500)
- Stripe-hosted checkout → enter your card → submit
- You're redirected back to the console; balance updates within ~2s
Refunds & disputes
Email [email protected] with the Stripe payment ID. Refunds flow back through Stripe and automatically debit the wallet via the webhook.
Error codes #
Every error returns the same envelope with a stable code and a human message. The HTTP status mirrors the code semantically.
| Code | HTTP | When |
|---|---|---|
unauthorized | 401 | Missing, malformed, or revoked key |
payment_required | 402 | Wallet balance < skill price |
forbidden | 403 | Key valid but not allowed for this skill / user |
not_found | 404 | Unknown skill name, or coming_soon called via tools/call |
invalid_input | 422 | Zod input validation failed (check the details field) |
rate_limited | 429 | Per-key per-skill token bucket exhausted |
upstream_error | 502 | Upstream service (langchain / OCR) returned an error |
gateway_error | 500 | Bug in the gateway itself — please file an issue |
Response envelope #
Every response — REST or MCP — follows the same shape.
Success
{
"ok": true,
"skill": "health_sync",
"version": "1.0.0",
"data": { "...": "skill-specific payload" },
"usage": { "units": 1, "cost_usd": 0 }
}
Error
{
"ok": false,
"skill": "health_sync",
"error": {
"code": "invalid_input",
"message": "requested window is 120 days; max is 90",
"details": null
}
}
Source on GitHub #
Treat a1c-ai-agent/sally-skills as the single source of truth. These docs are a curated summary; the repo always reflects the latest live behavior. File issues for bugs, open PRs for fixes, or just star the repo to keep tabs.
- README.md — onboarding, agent setup snippets, curl examples
- SKILLS.md — full skill catalog, prices, error codes
- packages/ — per-skill READMEs (input/output schemas, pricing rationale)
- protocols/ — MCP and REST protocol guides
- agents/ — per-client setup guides (Claude Code, Desktop, Cursor, etc.)
Ready to plug in?
Sign in with your A1C account, mint your first key, and you're calling Sally from your agent in 90 seconds.
Get an API key →