Token Offset for developers
Token Offset runs a hosted MCP server, so Claude, ChatGPT, Cursor and other assistants can read and run a Token Offset account for the person who signs in. Agents that sign people up or report usage on their behalf use the agent protocol, which is plain HTTP with an agent key. Both are below.
https://mcp.tokenoffset.com/mcpStreamable HTTP
Overview
The server speaks Streamable HTTP and is stateless. There is nothing to install or run. A client connects to the address above, the server answers 401 with a pointer to its sign-in, and the client opens a Token Offset page where the person signs in with their email and approves the app.
| MCP server | Agent protocol | |
|---|---|---|
| For | A person using their own assistant | An agent product acting for many people |
| Address | https://mcp.tokenoffset.com/mcp | https://api.tokenoffset.com/api/agents/* |
| Sign-in | OAuth 2.1, the person's own account | Agent API key, plus the person's approval per link |
| Reach | 24 tools over one account | Accounts that approved the agent |
| Spec | Tool reference | /agents |
Things an assistant can do once connected: check the monthly estimate and where it comes from, move to a different usage band or a custom amount, cancel or resume, change the monthly support add-on, read billing, page through or export offset history as CSV, log tokens an agent used, refresh or remove an estimate source, and revoke agents and other connected apps. Adding a card and pasting a provider admin key stay in the browser, so tools that need them return a link to the right Settings page.
Quickstart
You need a Token Offset account. If you don't have one, the sign-in page creates it from your email. Every client below ends with the same Token Offset approval page.
Claude
- 1In Claude, open Settings, then Connectors, and choose Add custom connector.
- 2Name it Token Offset and paste
https://mcp.tokenoffset.com/mcp. - 3Choose Connect. Claude opens Token Offset, where you sign in and approve it.
Custom connectors work in Claude on the web, desktop and mobile once added. On Team and Enterprise plans an owner may need to add the connector first.
ChatGPT
- 1In ChatGPT settings, open Apps and Connectors, then Advanced settings, and turn on Developer mode.
- 2Back in Apps and Connectors, choose Create. Name it Token Offset, paste
https://mcp.tokenoffset.com/mcpand pick OAuth. - 3Save, then sign in and approve on the Token Offset page that opens.
Developer mode is available on paid ChatGPT plans. ChatGPT asks before it runs a tool that makes changes.
Cursor
Add it to ~/.cursor/mcp.json, or to .cursor/mcp.json in a project. Cursor asks you to sign in the first time it connects.
{
"mcpServers": {
"tokenoffset": {
"url": "https://mcp.tokenoffset.com/mcp"
}
}
}VS Code
Add it to .vscode/mcp.json in a workspace, or run MCP: Add Server from the command palette and pick HTTP. VS Code shows a sign-in prompt on first use.
{
"servers": {
"tokenoffset": {
"type": "http",
"url": "https://mcp.tokenoffset.com/mcp"
}
}
}Windsurf
Open the MCP settings from the Cascade panel, choose View raw config, and add the server. Refresh the MCP list, then sign in when Windsurf asks.
{
"mcpServers": {
"tokenoffset": {
"serverUrl": "https://mcp.tokenoffset.com/mcp"
}
}
}Claude Code
claude mcp add --transport http tokenoffset https://mcp.tokenoffset.com/mcpThen run /mcp inside a session and pick tokenoffset to sign in.
Gemini CLI
{
"mcpServers": {
"tokenoffset": {
"httpUrl": "https://mcp.tokenoffset.com/mcp"
}
}
}Then run /mcp auth tokenoffset inside Gemini CLI to sign in.
Other clients
Any client that supports remote Streamable HTTP servers and the MCP authorization spec finds the sign-in on its own: add the address and connect. For a client that only runs local stdio servers, bridge it with mcp-remote, which handles the sign-in in your browser.
{
"mcpServers": {
"tokenoffset": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp.tokenoffset.com/mcp"
]
}
}
}To try the server without an assistant, run npx @modelcontextprotocol/inspector, choose Streamable HTTP, paste the address and connect.
Sign-in and OAuth
Token Offset is its own OAuth 2.1 authorization server for public clients. A client registers itself, sends the person to the consent page, and swaps the code for tokens. You never paste a key into the assistant.
- 1The client calls
https://mcp.tokenoffset.com/mcpand gets401with aWWW-Authenticateheader naming the protected resource metadata. - 2It reads the metadata and registers through dynamic client registration (RFC 7591) at
/oauth/register. - 3It opens
/oauth/authorizewith a PKCE challenge (S256). The person signs in with an emailed link if needed, sees who is asking, and approves. - 4The client exchanges the code at
/oauth/tokenand calls the server with the access token as a bearer.
- Protected resource metadata
- https://mcp.tokenoffset.com/.well-known/oauth-protected-resource/mcp
- Authorization server metadata
- https://mcp.tokenoffset.com/.well-known/oauth-authorization-server
- Issuer
- https://mcp.tokenoffset.com
- Resource
- https://mcp.tokenoffset.com/mcp
- Endpoints
- /oauth/authorize, /oauth/token, /oauth/register, /oauth/revoke
- Grant types
- authorization_code with PKCE S256, refresh_token
- Client auth
- none (public clients, no client secret)
- Access token
- 1 hour
- Refresh token
- 60 days, rotates on every use. Reusing an old one ends the connection.
- Authorization code
- 5 minutes, single use
- Redirect URIs
- https, or http on localhost and 127.0.0.1 (any port)
Scopes
read covers the 13 tools that only look. write adds the 11 that change something, and includes read. The consent page always grants read and lets the person untick write, so a client can end up with less than it asked for. The server lists only the tools the granted scope allows, and a write tool called on a read-only connection returns a plain error.
What a connection can reach
One connection is one person's account and nothing more. Every tool looks up records through the signed-in account, so an id from another account reads as not found. Connections can't add a card, see a full card number, paste provider admin keys or rotate agent keys.
Revoking
Every connected app is listed in Settings, Agents with when it connected and when it was last used. Disconnecting one deletes the grant, and its tokens stop working on the next request. Clients can also revoke their own tokens at /oauth/revoke (RFC 7009).
Tool reference
24 tools in 5 groups. Each one carries a title and read-only or destructive hints, so clients can ask before running anything that changes your account. Amounts are in US cents, dates are YYYY-MM-DD, and band prices come from list_usage_bands.
Account
get_accountread-onlyGet my account
The signed-in person's Token Offset account: email, name, member since, plan status, and how many estimate sources, agents and connected apps it has.
update_profileneeds writeUpdate my name
Change the display name on the account. An empty name clears it. The email can only be changed by contacting support.
namestring, requiredNew display name, up to 80 characters. Empty clears it.
send_feedbackneeds writeSend feedback to Token Offset
Send a bug report, feature request or other note to the Token Offset team from the signed-in account.
kindbug | feature | other, requiredWhat sort of feedback it is.messagestring, requiredThe feedback, in the person's words.
Plan and billing
list_usage_bandsread-onlyList usage bands
The preset monthly usage bands (Casual, Worker, Agentic, Extreme) with the tokens each assumes and the suggested monthly amount.
get_planread-onlyGet my monthly plan
The monthly offset plan: amount, status, next billing date, whether card billing is on, monthly support, and lifetime totals.
set_planneeds writedestructiveSet my monthly offset
Set the monthly offset amount from a usage band or a custom amount in cents ($4.99 to $10,000). Creates the plan if there is none. When card billing is on, the new amount is charged from the next invoice. 90% of each offset payment goes to Token Offset's climate partner and Token Offset keeps 10%; Token Offset is a for-profit company and payments aren't tax-deductible. Confirm the amount with the person first.
bandcasual | worker | agentic | extremeUsage band to size the plan from. Use this or amountCents.amountCentsintegerCustom monthly amount in US cents, e.g. 500 for $5.00.
cancel_planneeds writedestructiveCancel my monthly plan
Cancel the monthly offset plan. Card billing stops at the end of the period already paid for. Confirm with the person first.
resume_planneeds writedestructiveResume my monthly plan
Turn a cancelled plan back on. If the paid period hasn't ended, the existing card billing simply continues.
get_billingread-onlyGet my billing details
Card on file (brand, last four digits, expiry) and whether the subscription is set to end. Card changes happen on the billing page, linked in the result.
set_monthly_supportneeds writedestructiveSet my monthly support
Set the optional monthly amount that supports Token Offset itself, separate from the offset. 0 removes it. Needs card billing to be on. Applies from the next invoice. Confirm with the person first.
amountCentsinteger, requiredMonthly support in US cents. 0 removes the support line.
get_offset_historyread-onlyGet my offset history
Monthly offsets and support payments, newest first, one page at a time: amount, status, dates, the tokens each period covered, and a summary of everything that matches. Simulated rows are periods before card billing was on; no money moved for them. Paid offset rows show the 90% that goes to the climate partner and the 10% Token Offset keeps. These are payments to a for-profit company and are not charitable donations.
fromstring (date)First charge date to include, YYYY-MM-DD.tostring (date)Last charge date to include, YYYY-MM-DD.kindoffset | supportOnly offsets or only support payments.statuspaid | simulated | failed | refundedOnly rows with this status.limitintegerRows per page. Default 50.cursorstringcontinueCursor from the previous page.
export_offset_historyread-onlyExport my offset history as CSV
The same history as two CSV files (payments, and the usage behind them) plus receipt links, for a spreadsheet or bookkeeping. Narrow the dates if the export comes back truncated.
fromstring (date)First charge date to include, YYYY-MM-DD.tostring (date)Last charge date to include, YYYY-MM-DD.kindoffset | supportOnly offsets or only support payments.statuspaid | simulated | failed | refundedOnly rows with this status.
Usage
get_usage_summaryread-onlySummarize my AI usage
Tokens reported by connected assistants today, this week and in the last 30 days, the usage synced from estimate sources, and the current plan.
get_usage_estimateread-onlyEstimate my monthly usage
Projected monthly tokens from the connected estimate sources, with the suggested monthly offset. Without a source it returns the usage bands instead.
get_daily_usageread-onlyGet my daily usage
Daily token totals per provider from the estimate sources, split into input, output and cache tokens with a per-model breakdown. Up to 93 days per call.
startDatestring (date), requiredFirst day, YYYY-MM-DD (UTC).endDatestring (date), requiredLast day, YYYY-MM-DD (UTC).provideranthropic | openai | cursor | openrouter | xaiOnly this provider.
get_usage_logread-onlyGet my reported usage log
Recent token reports from assistants and agents, newest first, optionally for one session.
sessionIdstringOnly reports with this session id.limitintegerHow many reports. Default 50.
report_usageneeds writeReport token usage
Add a conversation turn's token counts to the person's usage. Use it when the person wants this conversation counted toward their offset. Only counts and an optional model and session id are stored, never message content.
inputTokensinteger, requiredUncached input (prompt) tokens for the turn.outputTokensinteger, requiredOutput (completion) tokens for the turn.cacheReadTokensintegerPrompt-cache reads, when the provider reports them. Weighted at 2% of an output token.cacheWriteTokensintegerPrompt-cache writes, when the provider reports them.modelstringModel id, e.g. claude-sonnet-5-5.sessionIdstringStable id for the conversation, to keep a running total.
Estimate sources
list_estimate_sourcesread-onlyList my estimate sources
Connected read-only usage keys (Anthropic, OpenAI, Cursor, OpenRouter, Grok API) that feed the usage estimate, with sync status. Adding one happens in the browser, linked in the result.
refresh_estimate_sourceneeds writeRe-sync an estimate source
Pull the latest usage from one estimate source now.
sourceIdstring, requiredSource id from list_estimate_sources.
disconnect_estimate_sourceneeds writedestructiveRemove an estimate source
Remove an estimate source and delete the usage it synced. The stored key is deleted. Confirm with the person first.
sourceIdstring, requiredSource id from list_estimate_sources.
Agents and apps
list_agentsread-onlyList agents on my account
Agent integrations that asked to act on the account through the agent protocol, with their approval status.
revoke_agentneeds writedestructiveRevoke an agent
Remove an agent's access to the account. Confirm with the person first.
linkIdstring, requiredLink id from list_agents.
list_connected_appsread-onlyList my connected apps
Assistants and apps signed in to the account through MCP, with access level, connected date and last use. The current one is marked.
disconnect_appneeds writedestructiveDisconnect an app
Sign an assistant or app out of the account. Disconnecting the current app ends this session. Confirm with the person first.
appIdstring, requiredApp id from list_connected_apps.
Agent protocol
Agent products that act for many people register once, get an agent API key, and ask each person to approve a link by email. The full HTTP spec, with request and response bodies, is at /agents and in plain text at /agents-protocol.txt.
The same protocol is available as MCP tools. Send your agent key as Authorization: Bearer to_agent_… to https://mcp.tokenoffset.com/mcp and the server lists the agent tools below in place of the account tools. Integrations set up before OAuth keep working at https://mcp.tokenoffset.com/agent/mcp.
Agents are registered over HTTP at https://api.tokenoffset.com/api/agents/register. The owner can see and rotate the key in Settings, Agents when signed in with the email the agent was registered under.
tokenoffset_get_protocolread-onlyRead the agent protocol
The plain-text Token Offset agent integration protocol.
tokenoffset_list_usage_bandsread-onlyList usage bands
Preset monthly usage bands (Casual, Worker, Agentic, Extreme) with suggested offset amounts.
tokenoffset_quick_signupRequest an account for a person
Create a Token Offset account for a person and email them a link to approve this agent. No agent key needed. One email per address per hour.
userEmailstring (email), requiredThe person's email address.userNamestringThe person's name.agentNamestring, requiredProduct name shown in the approval email, e.g. Cursor.agentDescriptionstringOne line on what the agent does.agentWebsiteUrlstring (url)Agent homepage.
tokenoffset_signup_userSign a person up
Create an account for a person under this agent and email them an approval link. Needs an agent API key.
userEmailstring (email), requiredThe person's email address.userNamestringThe person's name.exclusiveAgentbooleanTrue when this agent is the only intended actor on the account.
tokenoffset_check_link_statusread-onlyCheck approval status
Whether the person has approved this agent (pending, approved or revoked).
linkIdstring, requiredlinkId returned by signup_user or quick_signup.
tokenoffset_report_usageReport token usage
Add a turn's token counts to an approved person's usage. Reuse sessionId to keep a running total.
linkIdstring, requiredlinkId returned by signup_user or quick_signup.sessionIdstringStable id for the conversation.inputTokensinteger, requiredUncached input tokens.outputTokensinteger, requiredOutput tokens.cacheReadTokensintegerPrompt-cache reads, weighted at 2% of an output token.cacheWriteTokensintegerPrompt-cache writes.modelstringModel id.
tokenoffset_get_usage_logread-onlyGet the usage log
Token reports this agent sent for a person, optionally for one session.
linkIdstring, requiredlinkId returned by signup_user or quick_signup.sessionIdstringOnly this session.limitintegerHow many. Default 50.
tokenoffset_get_usage_summaryread-onlySummarize a person's usage
Tokens this agent reported, usage from the person's estimate sources, and their active plan.
linkIdstring, requiredlinkId returned by signup_user or quick_signup.
tokenoffset_set_plandestructiveSet a person's monthly offset
Set an approved person's monthly offset from a usage band or a custom amount. Changes what their card is charged from the next invoice.
linkIdstring, requiredlinkId returned by signup_user or quick_signup.bandcasual | worker | agentic | extremeUsage band.amountCentsintegerCustom monthly amount in cents.sourceusage_estimate | preset_casual | preset_worker | preset_agentic | preset_extreme | customWhere a custom amount came from. Required with amountCents.sizedForMonthlyTokensintegerMonthly tokens the amount was sized for.
tokenoffset_connect_providerConnect a provider usage key
Store a read-only usage key (Anthropic, OpenAI, Cursor, OpenRouter or Grok API) for an approved person so their usage can be estimated.
linkIdstring, requiredlinkId returned by signup_user or quick_signup.provideranthropic | openai | cursor | openrouter | xai, requiredWhich provider the key is for.apiKeystring, requiredanthropic: Admin key (sk-ant-admin…) or Claude Enterprise Analytics key; openai: Admin key (sk-admin-…); cursor: team Admin API key; openrouter: management key; xai: Grok API management key.
Rate limits
- Tool calls
- 60 per minute for each connected app
- Client registration
- 60 new clients every 10 minutes across the server
- Quick signup emails
- 1 per email address per hour
- get_daily_usage
- Up to 93 days per call
- report_usage
- Up to 50 million tokens per call
- get_usage_log
- Up to 200 rows per call
- get_offset_history
- Up to 200 rows per page, with a cursor for the next
- export_offset_history
- Each CSV up to about 200 KB; narrow the dates past that
Over a limit, the server answers 429 with how long to wait. Retrying straight away counts against the same window.
FAQ
Does the assistant see my prompts?
report_usage, it sends numbers, a model name and an optional session id. The server has no field for prompt or reply text.Can an assistant charge my card?
How do I connect a read-only assistant?
My client says it can't sign in.
mcp-remote bridge under Other clients. If the approval page says the link doesn't work, start the connection again from the client; codes last five minutes.What happens to a connection when I close my account?
Where is the server listed?
io.github.jakehandy/tokenoffset. Read how we handle data in the Privacy Policy and the rules for connected apps in the Terms.