Release

Baton 1.0: one open spec, three SDKs

Ujwal Chinthala, Good Timing  ·  November 6, 2026

Baton helps the people who use your MCP server get a great experience from their agent. Today the Baton wire spec and our Python, TypeScript and Go SDKs reach 1.0.

Baton records what happens when an AI agent calls your MCP server: which tool it called, what it sent, what came back, and what the agent was trying to do. The SDKs send those events to a collector. That can be our hosted Console, or any HTTPS endpoint that speaks the spec.

Here is what is supported, how fast it is, and what comes next.

The spec is open

The spec lives in its own repo, under Apache 2.0: github.com/good-timing/baton-spec.

It holds:

All three SDKs test against these files in CI. If you want to write an SDK in another language, or your own collector, start here.

What's supported

PythonTypeScriptGo
Packagebaton-sdk@goodtiming/baton-sdkgithub.com/good-timing/baton-go
RuntimePython 3.11–3.14Node 20+Go 1.25+
MCP librariesmcp 1.21.1+ and 2.x; fastmcp 2.14 to 4.x@modelcontextprotocol/sdk 1.30+; @modelcontextprotocol/server 2.xmodelcontextprotocol/go-sdk 1.6.1+
Tested in CIPython 3.11, 3.12, 3.13, 3.14; mcp 1.21.1, 1.25.0, 1.27.2, 2.0.0; fastmcp 2.14.7, 3.4.2, 4.0.2, 4.1.5Node 20 and 22; SDK 1.x and 2.xgo-sdk 1.6.1, 1.7.0, 1.8.0 and the latest release
MCP serversyesyesyes
Library API (no MCP)yesyesnot yet

Go 1.0 covers MCP servers only. The library API comes in a later 1.x release, and it only adds things.

The READMEs stay current; this table is as of today. Python · TypeScript · Go

Getting started

One call wraps your server. In Python:

from mcp.server.mcpserver import MCPServer
from baton import install_baton

mcp = MCPServer("echo-server")
install_baton(mcp, dsn="https://baton_pk_...@baton.goodtiming.ai/ten_.../echo-server")

TypeScript is withBaton(server, { dsn }). Go is baton.Install(server, impl, nil, baton.Config{...}). Each README has the full example.

Without a DSN, the SDK installs nothing and your server starts as usual.

How fast it is

Our first rule is that Baton never slows down or breaks your server. On a small tool call, Baton adds under 1 ms at the median in all three SDKs.

Every release runs the same benchmark, defined in the spec repo (bench/bench.json). It runs on GitHub's standard ubuntu-latest runner, which has 2 shared CPUs. It also runs the calls against a collector that never answers and against an address where nothing listens. Calls were no slower in either case. Baton drops and counts those events instead of making your server wait.

Your numbers in production will differ. The raw results for 1.0.0 are on each SDK's bench-results branch: Python · TypeScript · Go.

What leaves your server

Only what crosses the MCP call: the tool name, its arguments, the result, the error, timing, and what the client says about itself. Baton never reads your logs, your database or anything else in your process.

You can turn off results (result_capture_mode="off" in Python). Arguments are always sent, so a scrubber runs on them by default. It matches patterns like emails, keys, tokens and card numbers. It is pattern matching, so it does not catch everything; a plain name or address passes through. You can replace it with your own.

What you can set. All three SDKs have these settings in 1.0. The names below are Python's. TypeScript uses the same names in camelCase, and Go uses Config fields.

SettingWhat it controlsDefault
result_capture_modeWhether tool results are sent"full"
intent_param_modeWhether the agent must say what it is trying to do (user_goal) on each call"required"
report_modeWhether the agent gets a tool to report problems with your server"off"
scrubberWhat is removed from arguments and results before they leavebuilt-in patterns
settings="console" (experimental)Reads the settings above from the Console instead of your code, so they can differ by labeloff

Some of these change what the agent spends on each call, in tokens and time. Next week's post measures that.

What's next

All of this is additive and keeps the 1.0 promise:

Experimental. A few fields and options are marked experimental and may change in a minor release. The spec lists them in SPEC §13, and each SDK's README lists its own.

Tell us what you want next. If you want Baton in another language, such as C#, the spec repo has what you need to build an SDK, and we would like to hear about it. Open an issue there and tell us what you are building.

Python · TypeScript · Go · Spec · Docs