Week thirteen · August 6, 2026

A Third Prediction Market

This week I added a Gemini prediction markets toolkit. It joins Polymarket and Kalshi, which means three venues now answer the same questions, and the newest one answers them very quietly.

I didn’t have much time to devote to Toolforest this week, but in the spirit of trying to ship new functionality on a weekly cadence, I went looking for something small but still meaningful.

I found that in my inbox. Gemini has been sending me a steady stream of promotional emails about its prediction markets, offering fee credits and bonuses to come try it out. I already had a Gemini account, two prediction market toolkits, and a market data service running behind them. The path was already worn. Somewhere between the fourth and fifth email it stopped being an advertisement and started being an idea, which I believe is the entire point of the fourth and fifth email.

So I built it, eleven tools in all.

I neglected to look at Gemini volumes

At no stage of deciding to do this did I check how much anyone was trading on Gemini. Here are four markets that all three venues list, which is rarer than it sounds.

Log-scale bar chart comparing 24-hour contract volume on Kalshi and Gemini across four shared markets
Contracts traded in 24 hours. Log scale, so each gridline is ten times the one below it.

As the chart shows, Kalshi runs roughly a thousand times Gemini’s volume across the major markets. The exception is the AI question, where the gap is a factor of twelve.

Then there is the US House. Gemini’s deepest book of all time, 227,116 contracts since it opened, traded just six contracts yesterday.

Polymarket would rival Kalshi’s numbers, but it’s omitted here because it reports dollar volume instead of contracts. There’s no exact comparison without tracking VWAP to convert between them, which I may build out in the future. In the meantime, I’ve updated the toolkits so every volume field declares its units, ensuring nothing quietly adds dollars to contracts.

It is also mostly a sportsbook. Of roughly 4,600 markets I have stored, 3,533 are sports. Politics gets 490, crypto 176, economics 101.

Eight months old

In fairness to Gemini, and to my inbox, this is a very new venue. Prediction markets opened there on December 15, 2025, four days after the CFTC granted its subsidiary a Designated Contract Market licence. Since then it reports more than 100 million contracts traded across upwards of 20,000 traders, and prediction markets revenue of $0.4 million in its first full quarter. Kalshi did $4.54 billion of volume in November alone.

Eight months is not very long to build a book. And I still think a third quote is worth having, for two reasons that survive the volume numbers.

The first is that a third opinion is useful even when it is a thin one, and sometimes especially then. The second is distribution. Gemini has an existing exchange full of people, some of whom are never going to open a Polymarket account, and if event contracts become a normal thing that normal people trade, it will be because they appeared inside an app somebody already had.

Where do the three actually meet?

Not in many places. Polymarket is where long-horizon geopolitics gets priced, with $39.7 million sitting on whether China invades Taiwan by the end of 2026. Kalshi is the regulated one. Gemini is mostly sports. The September Fed decision is one of the few questions all three carry in the same five buckets.

Grouped bar chart of the September Fed decision priced on Polymarket, Kalshi and Gemini
September FOMC decision, midpoint on each venue.

They agree almost exactly on the two outcomes that matter and part company in the tails, which is where thin books usually give themselves away. The missing Kalshi bars are neither zeros nor errors. Kalshi’s books on the two extreme outcomes have an ask and no bid, so there is no midpoint to plot. A bar chart cannot say that out loud, which is why I am saying it here.

The better comparison turned out to be which lab has the best AI model at the end of 2026, which Gemini and Polymarket both run. Gemini prices Claude at 0.675. Polymarket prices Anthropic at 0.665. One cent apart.

Sum each venue’s outcomes, though, and Polymarket’s book adds to 1.047 while Gemini’s adds to 1.025. The small venue looks tighter.

A spread that means nothing, until it does

Every contract in that market came back with a spread of exactly one cent. The 0.675 favourite and the 0.015 no-hoper, same spread. So did every contract in the Fed market. That is not a book responding to liquidity. That is a market maker sitting on every line at one tick, and the tight sum is a quoting convention rather than a verdict.

I wrote this down as a tick floor, which was wrong. Gemini’s golf markets have spreads of one, two, three and four cents, with Scheffler quoted 0.62 bid against 0.66 ask in the FedEx St. Jude top ten. The field does respond to liquidity. It happens that a maker was quoting every line in both markets I picked. The golf markets were live, with play underway, and a maker facing people who could see the broadcast quoted wider or not at all. That is where the real book shows through.

The correct version is duller and more useful. A one-cent spread on Gemini tells you a maker is present. It does not tell you the market is liquid.

The last trade is not the price

On thin contracts, the last executed trade can sit a long way from the live book. Hideki Matsuyama’s last trade in the golf outright was 0.01 against a 0.06 bid and a 0.07 ask. On the Fed event, a 25 basis point hike last traded at 0.24 while the book stood 0.27 to 0.28.

Charting last trade on this venue produces noise with a plausible shape, which is the worst kind. The toolkit now leads with midpoint wherever a book exists and demotes last trade to a secondary field. On Polymarket and Kalshi that distinction was academic. Here it is the whole ballgame.

There is a second case that looks identical and is not. Some contracts have no bid at all, so spread and midpoint are correctly null while a buy and sell value still appear, both equal to the last trade. The temptation is to fill the nulls from those numbers. The right move is the opposite: mark the buy and sell values as indicative and leave the null alone. A null meaning “no two-sided market exists” is doing more work than a number that looks like a quote and is not.

Charts that escape the chat window

I built the image widget last month for satellite imagery, but it also works well for charts.

Line chart of the Gemini Fed maintains rate contract from August 3 to 7
Gemini’s “Fed maintains rate” contract, executed prices. Nothing traded on the 6th. The step on the 7th is a single hour: 1,939 contracts, and the price went from 0.52 to 0.67.

Prediction market data goes into Google Sheets, Sheets builds the chart, another tool exports it as a hosted image, and the widget renders it in the conversation. Four toolkits, none of which know the others exist, with a spreadsheet ID and an image URL passing between them.

Exported chart URLs also expire after a day, which is fine in a conversation and useless in a blog post, so the images here are static copies. The pipeline is live. These particular pictures are taxidermy.

Three venues now, and they still disagree. That is rather the point of asking three.

As always, ideas and suggestions are welcome at gerrit@toolforest.io.

Week twelve · July 30, 2026

Three Toolkits, One Planet

This week I released a Google Earth Engine toolkit. It joins Geo and EO in the Planet Earth tab, and the three are meant to be used together, so here is how they divide the work.

GeoEOEarth Engine
AnswersWhere is it?How is it now?How was it before?
SourceOpenStreetMapCopernicusEarth Engine
HistoryToday only2015 onward1950 onward
ResolutionVector10 m10 m to 11 km
DrawsOutline mapsImageryImagery, terrain
MeasuresDistance, areaIndices, changeRain, heat, people
compare, overlays and aoi_ref mean the same thing in all three

The bottom row of the table matters most. compare makes a before and after in all three. overlays draws a boundary in all three. aoi_ref is a shared region handle, so a boundary made in Geo renders in the others without the geometry ever passing through the conversation. Use the wipe slider in EO and you already know it in Earth Engine.

Forty years in one call

Sentinel-2, which EO uses, has been flying since 2015. Landsat has been up since 1972, with a usable archive from 1982. Most changes people ask about took longer than ten years to happen, and now they are in reach.

No single satellite covers forty years. Landsat 5 lasted until 2011, Landsat 7 broke in 2003, Landsat 8 arrived in 2013. The toolkit hides the roster behind one alias, landsat-all, which spans the whole record and picks the right instrument for each date. One call, two dates, forty years apart.

Toshka, Egypt's Western Desert, in 2025, with lakes and circular irrigated fields
The same stretch of desert in 1985, empty of lakes and fields

(Toshka, in Egypt's Western Desert. 1985 left of the handle, 2025 right. Landsat 4/5 and Landsat 8/9, USGS.)

In 1985 there is nothing there. The lakes did not exist until 1998, when Egypt diverted Lake Nasser's overflow into the Toshka Depression during a flood year. They peaked around 2001, evaporated through the 2000s to almost nothing, and refilled after 2019 when the reservoir rose again. The circular fields are newer still.

One practical note. This toolkit needs no account. No Google sign-in, no cloud project, no Earth Engine registration. Connect it in the portal and it works. The other Earth Engine MCP servers I have seen require you to self-host and bring your own Google project.

The questions imagery cannot answer

Pictures tell you what the ground looks like. Earth Engine also carries data that is not a picture: rainfall since 1981, temperature since 1950, population counts, land cover classified by a model. Different questions, and the good ones come from combining two.

Here is northern Kenya, a 300 km box of arid rangeland, in two different years.

Bar chart of monthly rainfall in northern Kenya for 2019 and 2022
Monthly rainfall, CHIRPS.
Line chart of the monthly vegetation index in northern Kenya for 2019 and 2022
Monthly vegetation index, Sentinel-2. Contains modified Copernicus Sentinel data.

The rainfall estimate is a satellite product at 5.5 km resolution. The vegetation index is a different satellite at 10 m. Neither knows the other exists. Put the charts together and vegetation follows rainfall by about a month, in both years.

Now look at the end of each year. In 2019 the short rains delivered 104 mm in October, 96 in November, 62 in December, and the vegetation index tripled, 0.11 to 0.35. In 2022 the same months delivered 27 mm each and the index did nothing. It ended December lower than it started October. That flat line is the Horn of Africa drought, the fifth failed rainy season in a row.

One thing in the numbers surprised me. April 2022 got 87 mm in a single month and produced the year's only green pulse. October through December 2022 got 81 mm between them, nearly the same water, and produced nothing. In arid country the question is not how much rain falls but how hard. Light rain on hot ground evaporates before roots reach it.

I did not ask either dataset that question. It fell out of putting the two series side by side.

Saying what it could not do

The vegetation series above arrived with a warning. Earth Engine gives each request sixty seconds; one of my calls ran out after eleven of twelve months, and the response said so: eleven processed, one missing. So I fetched the missing month with a second call, and that month, December, turned out to be the peak of the entire series. A quieter API would have handed me eleven rows, the chart above would be missing its highest point, and I would not know.

The rest of the toolkit behaves the same way. Renders name the satellite era they came from. Landsat 7's scan line corrector failed in May 2003 and every scene since has diagonal gaps, so the toolkit avoids that satellite where it can. There is an eighteen month stretch, after Landsat 5 retired and before Landsat 8 arrived, where the broken satellite was the only one flying, and a render from that window tells you so. Land cover fractions report the resolution they were computed at, which for a whole country is about a kilometre and a half, coarse enough that small towns dissolve into the fields around them.

Temperature gave me the sharpest version. I asked for Egypt's average in 1955 and again in 2025: 21.90 °C and 22.97 °C. A degree of warming in seventy years, ready for a headline. Except February 2025 came out 2.2 °C cooler than February 1955, and August 2.7 °C warmer. Two single years measure weather, not climate. The toolkit answered exactly the question I asked. The question was the problem.

The border you draw is a claim

Ask for Egypt and the toolkit clips the image at Egypt's border. To do that it has to know where the border is, and it uses the US State Department's LSIB dataset, public domain and published in Earth Engine's catalogue.

So when you draw Egypt you are publishing the United States government's opinion of where Egypt ends. For Egypt that is not hypothetical. Halayib on the Red Sea coast and Bir Tawil south of it are disputed with Sudan, and LSIB picks a side. Kashmir, Crimea and Western Sahara raise the same problem.

There is no neutral file. OpenStreetMap encodes who controls the ground. Natural Earth makes its own editorial calls. Every boundary dataset is an opinion drawn as a polygon, and a tool that draws borders is choosing one. The toolkit names its source in every response, which is as much as a tool can do: not pretend the choice was never made.

Lights

One more dataset, for a different question again. Not plants, people.

Cairo's night lights in 2014 and 2025, side by side, with a new bright patch east of the city in 2025
Cairo at night, 2014 and 2025. VIIRS, NOAA and NASA.

The bright ribbon is the Nile, same as it ever was. The patch to the east is Egypt's New Administrative Capital, built on empty desert since 2016. Night lights track human activity, and a new city is about the easiest thing they catch.

The other two

Geo and EO got updates this week too.

Geo can draw now. render_outline produces hosted maps from OpenStreetMap geometry, with outlines, markers, labels and spotlights, so the toolkit went from answering questions about places to showing them. It also gained aoi_ref, the region handle from the top of this post, which exists because a state boundary with 139,000 vertices once had to travel between two toolkits and could not. Now it never has to.

EO gained five indices, burn severity and moisture among them, and a per-pixel change tool called temporal_map that answers not just what changed but when every pixel changed. That one gets its own post.

Say where, say when, and drag the handle.

As always, ideas and suggestions are welcome at gerrit@toolforest.io.

Earlier entries

Week eleven · July 23, 2026

An Earth Observation Toolkit & MCP GUI Widgets

This week I released the Earth observation toolkit I mentioned last week. Your assistant can now render satellite imagery, measure vegetation and water inside any boundary, and track how a location changes over time.

It also comes with Toolforest's first interactive MCP GUI widget. Drag the slider below.

Stargate 1 data center campus, Abilene, Texas, June 2026
The same land in April 2024, before construction

These interactive components only work on platforms that support MCP widgets, like Claude, ChatGPT, and Grok. Now that the foundation is built, I see a great opportunity to go back and add widget-leveraging tools to my existing toolkits.

Getting the widget to actually render in Claude took some effort. I noticed a lot of other developers in the community were hitting the same walls, so I built a simple, Claude-friendly reference implementation to make it easier. You can find it here: https://github.com/primevalsoup/mcp-apps-claude-demo.

Where the handle can't go

The slider is the fun answer, which naturally means it is the fragile one. Step outside a perfectly configured chat window into a markdown document, a saved history, or an older model that looks at interactive widgets the way a dog looks at a ceiling fan, and you suddenly need a regular, unglamorous image.

So EO builds the lowest common denominator first. Every panel starts with identical constraints: area, collection, settings, pixels. EO decodes each one and checks the math, mostly because APIs are perfectly happy to hand you half a picture and pretend it’s a whole one. If a panel is partial or misaligned, the comparison stubbornly refuses to proceed. Only when everything actually lines up does EO label the pieces, stitch them into a single PNG, and mint a short URL. That static image is the universal fallback.

Alongside it, EO sends a polite little dossier of the panels: their display order, image URLs, and titles. Then it washes its hands of the matter. The Toolforest layer takes over from there. Two panels become a wipe slider; three or four become a swipeable strip. A client that has no idea what an MCP widget is remains blissfully ignorant and just gets the labeled PNG.

EO’s job is to ensure the comparison is rooted in reality. Toolforest decides how to dress it up.

There is one ironclad rule: no blank panels. My first attempt at writing this post asked for a year the archive didn't actually cover at that site. Instead of cheerfully serving me a dramatic before-and-after of a Texas ranch and a dark void, EO just said no.

The picture came second

A before-and-after slider is a great trick provided you actually know the dates for the before and the after. The Stargate campus was easy since the construction schedule made the news. The real test is when nobody has any idea when to look. Here is a stretch of the Cascades near Skykomish, Washington, about two hours from my house.

The same forest in July 2023, one summer after the Bolt Creek Fire
Cascade forest near Skykomish in August 2022, before the fire

(August 2022 left of the handle, July 2023 right: the same forest one summer after the Bolt Creek Fire. The burn is the brown-grey ground where green used to be.)

Nobody gave the assistant those dates. I just vaguely asked if anything had happened to this particular patch of trees in the last few years. The assistant made one statistics call and dragged back a monthly vegetation index covering ninety months. Every summer the line dutifully climbed to about 0.8. Then between August and September of 2022, the math fell completely off a cliff.

The comparison pictures were pulled only after the data spotted the drop. That statistical cliff had a real-world name: the Bolt Creek Fire, which closed Highway 2 that September.

The wrong number looks right

The Sentinel-2 API is always thrilled to hand you a number. The actual challenge is figuring out if that number has any relationship to reality.

The standard defense is a maximum cloud cover setting. But that measures the entire scene, not the specific place you care about. An image can pass the test with flying colors while a giant cloud parks itself directly over your lake.

During testing, Lake Shasta was full. For the exact same month, one cloud threshold produced a water index of −0.120 and another yielded +0.417. Both requests succeeded perfectly. Both numbers looked entirely professional. One of them was just a cloud.

So EO ignores the scene and looks at the pixels instead. It uses Sentinel-2's own classification to mask the clouds, then reports exactly what share of the month's pixels actually survived the purge. A month scraped together from ten percent of its pixels is no longer allowed to masquerade as a month computed from ninety.

When a month is completely clouded over, the Sentinel-2 API does not do the polite thing and return an empty row. The month simply ceases to exist. Read the results as a standard list, and every value after the missing month quietly slides into the wrong spot on the calendar. EO has to manually rebuild the expected timeline, put every value back where it belongs, and formally declare the gaps.

The physical burn scar is easy enough to see. The severity is harder to measure, mostly because the untouched forest still gets a vote in the average. Zoomed in on the burn, the average vegetation index the following summer was down a mere 0.09. That sounds like a mild dry spell. But the tenth percentile was down 0.25. The surviving trees soften the average, while the bottom tenth shows where the fire actually did its work. Getting that darker, more accurate view just takes one extra parameter.

Composability, again

Just like last week, when I showed how your assistant could bolt the Geo toolkit to Anki to build spatial flashcards, getting independent tools to cooperate isn't a trick. It’s just the natural result of pointing increasingly smarter LLMs at an expanding library of toolkits. The real objective here is getting the output to actually escape the chat window.

In this case, the objective was to write a short report on the Bolt Creek Fire, tracking the initial damage and measuring the forest's slow recovery over the last few years. To get there, the pieces assemble into a finished document, with each toolkit doing its specific job and passing the data cleanly to the next.

The Geo toolkit resolves the boundary into a short reference string. The heavy geometry stays safely on the server, and EO accepts the reference directly. This means a complex forest perimeter with twenty thousand vertices never has to cross the conversation and completely blow out the context window.

Once EO turns that reference into imagery and a clean time series, it hands off the baton. The Google Sheets toolkit takes the time series, builds a spreadsheet, generates a chart, and spits out an image of it. Finally, the Google Docs toolkit sweeps up the imagery, the chart, and the written analysis, and binds it all into a proper report.

(A satellite site report on the Bolt Creek Fire, assembled by the assistant in fourteen tool calls: seven years of monthly vegetation statistics, a chart built in Google Sheets, four summers of imagery, and the written analysis. Read the report.)

Boundaries on the imagery

The two toolkits also meet directly inside a single image. Boundaries supplied by Geo can be drawn straight onto satellite renders: an outline, a label, or a spotlight effect that dims everything outside the chosen polygon. Because the boundary arrives as a reference and resolves on the server, the exact same overlay gets applied to every panel of a temporal comparison. A highlighted parcel stays perfectly locked in place while the years shift beneath it. The county flashcards from last week can now show the county directly from space.

The point

Sentinel Hub, which serves the imagery under all of this, is a remarkably powerful API. It will search catalogs, process pixels, and calculate statistics all day long. What it will not do is stop you from asking a subtly wrong question. In fact, it will cheerfully return a successful, highly plausible, and entirely useless answer to one.

The toolkit's actual job is everything that happens between the raw endpoint and a trustworthy answer. It remembers which bands mean what on which sensor. It knows the difference between a cloudy scene and a cloudy pixel. It patches the calendar back together when months go missing, forces sampling scales to be explicitly reported instead of vaguely implied, and has the decency to explain a blank image rather than just shipping a void.

And now, it delivers a result that knows how to dress itself for the occasion: as a slick interactive slider where the client allows, and as a stubbornly reliable labeled image everywhere else.

The Geo post ended by promising that toolkit would get more useful this week. This is what I meant. Say where, say when, and drag the handle.

As always, ideas and suggestions are welcome at gerrit@toolforest.io.

Week ten · July 16, 2026

A Geo Toolkit

This week I added a Geo toolkit built on OpenStreetMap. Your assistant can now geocode addresses, search for places and features in the real world, do geometry work on the server, and produce clean outline maps and highlight graphics. I also need it for the Earth observation toolkit I'll be releasing next week.

I've wanted my assistant to understand geography for a while. Not geography in the capitals-and-rivers sense, but the geography of actual questions: Where are the tennis courts near me? What's the largest park in town? Can you show me every county in a state on one map?

The data to answer all of these questions exists in OpenStreetMap, and it's open. The problem is that the raw APIs around that data are a poor fit for an LLM. They use a specialized vocabulary, return large and sometimes messy geometries, and can quickly bloat the model's context window by passing thousands of coordinates back and forth. This post is a little longer than usual because Geo turned out to be a particularly good example of the difference between wrapping an API and building a toolkit.

OpenStreetMap doesn't call a tennis court a tennis court

OpenStreetMap is an open tagging system, with a perfectly logical vocabulary that almost nobody actually speaks. In OpenStreetMap, a tennis court is leisure=pitch plus sport=tennis. A gas station is amenity=fuel. A drugstore is amenity=pharmacy. A model that queries for leisure=tennis_court has produced perfectly plausible English, but also an invalid query that returns nothing.

So the toolkit translates the request before it queries OpenStreetMap. It includes close to 4,500 natural-language aliases generated from OpenStreetMap's own tagging schema, validates values for the most commonly used tag keys, and expands interchangeable terms such as field, court, pitch, and diamond when they refer to the same kind of sports facility.

If you enter sport=tenis, it suggests tennis, table_tennis, and paddle_tennis rather than sending a typo off into the network and waiting politely for nothing to come back. It also handles multi-use facilities, so a court tagged sport=tennis;basketball appears when you ask for either sport.

When the toolkit rewrites a query, it tells you exactly what changed. The correction is visible, not silent.

Shapes you can trust

The second problem is what to do with the geometry once you have it. A lake or city boundary can contain thousands of coordinate pairs. You don't want to hand all of those coordinates to an LLM, so the toolkit simplifies shapes before returning them.

But simplification is also where the map can begin lying to you. Early on, I forced the Lake Washington shoreline down to 80 points and, in the process, apparently created 42.6 percent more lake.

The toolkit now projects the geometry locally and applies topology-preserving Douglas–Peucker simplification in metres. The algorithm removes points while retaining the overall outline, rather than forcing every boundary down to an arbitrary vertex count. It does not guarantee that area will remain unchanged, so area and other measurements still come from the original geometry. The toolkit also compares the simplified area with the original and warns you if it changes by more than 5 percent.

A simplified outline is fine for looking at. Just don't ask the sketch to do the measuring.

The toolkit also handles the geometry work LLMs are not particularly good at: merging all the parks in a city, buffering a boundary by 100 metres, intersecting two areas, measuring perimeter, or testing whether one shape contains another. The operation happens on the server, so the model gets the result rather than a pile of coordinates.

Keeping 21,000 coordinates out of the context window

The context-window problem became obvious in practice. I was passing the Shasta Lake shoreline between tools, and even after simplifying it to 586 vertices, the geometry was copied into the model's context three times, at several thousand tokens each time.

The full boundary has 21,512 vertices and would not fit at all. Simplifying it until it did fit solved the context problem by creating a geography problem: the lake's area shifted by 7.9 percent.

The fix was simple in principle: stop passing the shape around. When a tool produces a complex boundary, it stores the full geometry privately and returns a short reference such as aoi_7b8....

Every other Geo tool accepts that reference in place of the geometry itself. Derived operations return new references, so merge, buffer, and intersect can proceed without the shoreline ever taking a tour through the context window.

The model still gets the metadata it needs, including bounds, area, and vertex count, but never sees the coordinates themselves. References expire after about 48 hours. Identical geometry produces the same reference, so retries do not create duplicate lakes.

Rendering geography

Sometimes, after all that geometry, what you need is simply to see it. The new render_outline tool accepts boundaries by name, OpenStreetMap ID, or Geo reference and returns a hosted image.

It handles the mechanical parts of turning geography into an image: choosing a projection, fitting the canvas, assigning a colorblind-safe palette, and adding attribution. It also refuses to render an administrative boundary if it could assemble only part of it. A map can be wrong very convincingly.

Labels are harder. A cartographer can move them off-centre, add leader lines, abbreviate names, or split them across two lines. render_outline places one label per shape at a representative point. When two labels would collide, it drops one rather than overlapping them, and tells you which one it dropped.

That makes the tool better suited to outlines, highlighted regions, and other visual assets than to densely labelled reference maps. The resulting images can be used directly in a presentation or flashcard, or passed into another toolkit.

Here are Tokyo's 23 special wards, with Setagaya-ku highlighted. It took a single request, and none of the underlying geometry entered the model's context window.

Outline of Tokyo's 23 special wards, with Setagaya-ku highlighted
Boundary data © OpenStreetMap contributors (ODbL).

Flashcards, because why not

Composability is where toolkits start to get more interesting. Since adding the Anki toolkit last month, I've been thinking of ways to connect it to something else, and geography supplied one almost immediately.

Learning where things are is a classic flashcard subject, but most existing geography decks are built from static image packs assembled by hand.

With Geo and Anki connected, my assistant generated a South Dakota county deck in one conversation. For each card, Geo renders the whole state with one county highlighted and the other 65 dimmed. The Anki toolkit then pulls the image into the deck by URL and creates the card. The front asks which county is highlighted; the back gives its name and county seat.

No image bytes enter the model's context window, and there is no static image pack to prepare in advance. The same process works for states, countries, city districts, or neighborhoods.

Anki displaying a geography flashcard with one South Dakota county highlighted
One of the generated cards in Anki. The Geo toolkit produced the image; the Anki toolkit assembled the deck. Boundary data © OpenStreetMap contributors (ODbL).

What's coming next week

Geo is useful on its own, but the reason I built it now is that I need it for the Earth observation toolkit I'm releasing next week. It will provide satellite imagery and vegetation and water statistics for any area you can describe in words, for individual dates or across a date range.

The two toolkits are designed for composability. A Geo reference for a merged set of parks, a buffered lakeshore, or a town boundary can pass directly into the Earth observation tools.

You'll be able to say, "Merge every park in my city and tell me how green they stayed between June and August," and the geometry will pass from one toolkit to the other without ever entering the model's context window.

The Geo toolkit is useful on its own. It gets a lot more useful next week.

As always, ideas and suggestions are welcome at gerrit@toolforest.io.

Week eight · July 2, 2026

A Mochi Toolkit

This week I added a toolkit for Mochi, so you can now build and organize Mochi decks using your AI assistant, with nothing to install and nothing to run locally.

Last week was quiet. I was traveling with family, so I didn't release any new toolkits.

When I added the Anki toolkit, it inspired me to add support for similar learning apps. Mochi jumped to the front of the queue because of my nephew. He's studying medical French this summer, and when I suggested Anki for the vocabulary grind, he told me he was already using Mochi. He prefers Mochi because it natively supports multi-sided cards. By adding markdown dividers, he can break complex concepts down into sequential steps.

Since I knew he already used Grok, getting him to be a guinea pig was easy. The problem with existing Mochi (and many other) MCP servers is that they run locally. Connecting a local server to a cloud-based chat client like Grok is a bit of a lift, requiring the user to set up and maintain a network tunnel for the connection. If I had asked my nephew to do that, he probably would not have bothered.

Toolforest's cloud architecture bypasses this completely, and since Mochi has an API, users don't even need to run a bridge like they do with Anki. They can just load their Mochi API key into Toolforest, where it's stored encrypted, and authenticate with their AI assistant.

As always, ideas and suggestions are welcome at gerrit@toolforest.io.

Week six · June 18, 2026

An Anki Toolkit

This week I added a toolkit for Anki. You can now build and organize Anki decks using your AI assistant, with a bridge add-on that connects the desktop app to Toolforest.

This week I added a toolkit for Anki.

Anki is the flashcard app a lot of people rely on for spaced repetition, and now you can build and organize Anki decks using your AI assistant. Describe what you're trying to learn, and the cards land in your library ready to review.

This toolkit was different to build. Every other Toolforest toolkit so far connected to a cloud API. Anki runs on your desktop and has rich plugin support. So I built two pieces: a cloud gateway, and a bridge add-on that runs inside Anki and connects to it. The bridge is self-contained. It signs in with Toolforest using a device-code flow, then authenticates to the gateway with a scoped bridge token for the Anki capability.

The gateway provides a generic way for desktop and other local software to reach into Toolforest. That opens up a whole category of toolkits that weren't possible when everything had to be a cloud API.

The Anki toolkit has also inspired me to add support for similar learning apps, which are coming soon.

As always, ideas and suggestions are welcome at gerrit@toolforest.io.

Week five · June 11, 2026

A Google Health Toolkit

A new Google Health toolkit reads activity, sleep, and heart data from the Pixel Watch and other Google wearables, the eventual successor to the Fitbit toolkit. And the homepage now groups the growing list of toolkits into tabs.

It was a busy week elsewhere, so this one is light. Just two updates: a toolkit I'd been meaning to build, and a small bit of tidying on the homepage.

A Google Health toolkit

Toolforest already has a Fitbit toolkit, and it isn't going anywhere yet. But Google has said it will eventually retire the current Fitbit Web API, so I wanted a replacement ready before that day arrives. The new Google Health toolkit reads the same kind of data: activity, sleep, heart rate, and the rest. It also isn't limited to Fitbit hardware, so it can read from other Google wearables like the Pixel Watch.

Like Gmail and the other sensitive Google APIs, health data sits behind a verification process that Google requires before an application can offer it to everyone. I'm going through the process now, which from past experience will take several weeks. Until it's approved, access is limited to whitelisted users, so the toolkit has a register button that lets you request access in the meantime.

Tabs for the toolkits

The other change is smaller. As the number of toolkits has grown, having them all on one screen had started to feel crowded. The homepage now groups them into tabs, so the music toolkits sit together, the Google toolkits sit together, and so on. A small thing, but it should keep the set easy to scan as it keeps growing.

As always, ideas and suggestions are welcome at gerrit@toolforest.io.

Week four · June 4, 2026

Redaction for Gmail and a MusicBrainz Toolkit

The Gmail toolkit now redacts the login codes and reset links in your mail by default, before your assistant ever sees them. And there's a new MusicBrainz toolkit that reads the credits behind a record: who produced it, who engineered and mixed it, and who played what.

Connecting your mail to an assistant means the model sees whatever is in those messages. Login and verification emails are a good example.

A one-time code is meant for you, once, for a minute, and then never again. Nobody sets out to hand a bank's verification code to an LLM. You just ask it to check your mail, and in comes the code, riding the same wave as the receipts and the reminders and the promotional clutter, perfectly ordinary and entirely exposed.

Redaction for Gmail

So this week I added security-code handling to the Gmail toolkit, and it's on by default. When the toolkit reads a message, it detects login codes, one-time passwords, password reset URLs, and magic links, and replaces them with a [REDACTED] placeholder before the content is returned to your assistant. The rest of the message comes through as normal.

It works off a dynamic list of known security-code senders combined with text patterns for the codes and links themselves. The point is to protect you if an assistant, a local agent, or some connected app is ever compromised, and to stop a malicious email from using prompt injection to talk your assistant into handing over a code.

If you want something other than the default, the toolkit's settings let you switch from redacting just the codes to withholding any message that looks like it contains one, or turn the handling off entirely. The setting applies across all of your sessions. I'd leave it on.

You can read more in the Gmail section of the docs.

A MusicBrainz toolkit

The music side of Toolforest already had ListenBrainz, Last.fm, and Apple Music. This week I added a MusicBrainz toolkit to sit alongside them. Toolforest has kept a replicated MusicBrainz database for a while to back the ListenBrainz toolkit, and the new toolkit puts that data directly in your assistant's hands.

The toolkit resolves any artist, recording, or release to its canonical MusicBrainz identifier and reads the credits behind a track: who produced it, who engineered and mixed it, and who played what. Credits in MusicBrainz are sometimes attached to the album rather than the individual song, so the toolkit also checks the release level. A question like "who produced this track" still gets an answer even when the credit lives one level up.

There are also relationship tools, so you can start from a band and branch outward to its members and the other projects they belong to. Put together with ListenBrainz, that means your assistant can take your most-played tracks and tell you the recurring producers behind them, or map the collaboration web around a band you like. There are now cookbook examples showing both.

As always, ideas and suggestions are welcome at gerrit@toolforest.io.

Week three · May 28, 2026

One assistant, every account

Every Google Workspace toolkit now works across all of your connected accounts at once. Your assistant can search mail, calendars, and tasks everywhere you have a login, not just in one inbox.

A user wrote in to say that there was no reason to use Toolforest for Gmail, because his AI assistant already came with a Gmail connector.

The catch was that it only supported one Gmail account at a time, and he had several that he used regularly. He said that if I could support multiple accounts, he would switch. So this week I added multi-account support for all of the Google toolkits: Gmail, Calendar, Tasks, Docs, Sheets, and Slides.

Toolforest now supports the concept of a primary account, which is the default and which you don't need to refer to by name, and any number of secondary accounts, which you do need to refer to by name.

Of course you can also say things like "summarize my recent mail for all my Gmail accounts" or "summarize events from all my calendars for today."

I hope users find this helpful, and I welcome your continued suggestions. You can reach me at gerrit@toolforest.io.

Week two · May 21, 2026

Good feedback from users

Grok support is live, Last.fm is now part of the toolkit set, and the next useful layer might come from MusicBrainz and ListenBrainz enrichment.

A week after introducing toolforest.io on the ListenBrainz forum, I got a couple of good suggestions: add support for Grok, since they'd just introduced support for third-party MCP connectors, and take a look at Last.fm.

Grok now works too

This one was just a matter of configuration. That leaves Gemini as really the last major holdout among the major AI assistants. I'm hoping they come around soon.

Last.fm

After spending some time on the Last.fm subreddit, I noticed an active subset of the community that's specifically looking to connect with "compatible" users, people whose listening overlaps with theirs. There's even a recognized kind of post for it, where someone shares their username and invites others to check compatibility.

That struck me as a great use case for a toolkit. By giving an LLM access to any two users' top artists and listening summaries, the toolkit lets it produce a rich compatibility analysis: finding the bridge artists between two libraries, telling a casual shared play apart from a real favorite, and pointing out where two tastes meet and where they diverge. There's an example of this generated by Grok in the cookbook.

There's also room to make the Last.fm toolkit even richer. Because toolforest.io already maintains a replicated MusicBrainz and ListenBrainz database for the ListenBrainz toolkit, I can lean on that same data to resolve artists to canonical identifiers, round out the metadata, and answer relationship questions across libraries. I haven't built that layer yet. I'll wait and see what the Last.fm community comes back with first and build it if there's sufficient interest.

If you have ideas for toolkits or enhancements, you can reach me at gerrit@toolforest.io or through the request form on the homepage. Thanks to the folks on the ListenBrainz forum who took the time to write back.

Day one · May 14, 2026

Why toolforest.io

A small framework for one toolkit turned into something bigger. Here's what it is, why it exists, and why the launch starts with the ListenBrainz community.

This project started as something much smaller than it became.

A few months ago I wanted a clean way to give Claude access to Google Sheets and Google Docs. That was it. I use those tools every day, and the existing options either didn't work the way I wanted or mapped so directly to the underlying API that the LLM ended up doing all the heavy lifting itself. Fighting font metrics, retrying calls, hallucinating field names.

Once I had a working framework for one toolkit, I realized adding another wasn't much work. Then a third. I started thinking less about individual integrations and more about what an aggregator could look like if it were built specifically for the things consumers actually use (fitness data, listening history, prediction markets, calendars), rather than the developer and enterprise APIs that everyone else has already covered well.

That's toolforest.io. As of today it's in open beta.

What's different

There are excellent sites out there, like Zapier and Composio, that connect AI assistants to hundreds of APIs. For a lot of use cases they're a perfect fit. The thing I kept running into, though, was that many of these integrations are essentially thin wrappers. The LLM gets handed the same surface the API exposes, with all of its quirks intact.

I think there's real value in adding an intermediate layer between the toolkit and the underlying API. A few examples of what I mean:

  • Google Slides. The raw API has no concept of font metrics, which means LLMs routinely generate slides where text overflows its text box. Toolforest's Google Slides toolkit measures fonts properly and gives the model the tools it needs to lay things out correctly.
  • Google Sheets. The default auto-resize-column behavior doesn't measure fonts accurately. We compute widths properly so the output actually looks right.
  • Polymarket and Kalshi. The raw APIs expose markets, events, prices, and order books, but they don't have a built-in concept of "what's moving." The toolkits add that layer by continuously snapshotting markets, computing price and volume changes over multiple windows, filtering out low-volume noise, and normalizing the quirks between venues. The model can ask for meaningful movers directly instead of trying to assemble that analysis from a pile of raw API calls.
  • ListenBrainz. Toolforest maintains a replicated MusicBrainz and ListenBrainz database, so the toolkit can do more than proxy the public API. It resolves missing MBIDs, normalizes time ranges, paginates large histories, explains empty or truncated results, cleans playlist metadata, and supports database-backed questions the public API doesn't expose directly. The result is that an assistant can answer questions like "which Pink Floyd tracks has this user listened to most over time?" or "which similar artists should I explore?" without stitching together brittle raw API calls.

The LLM just gets the right answer faster, and the user never sees the plumbing.

Why I'm announcing this to ListenBrainz first

The toolkits across the site are all live, but I wanted to introduce toolforest somewhere specific rather than everywhere at once. ListenBrainz felt like the obvious place.

I've spent time on the community forums recently, and what struck me was how much of what people want to build is exactly the kind of thing an LLM with structured access to listening data is good at. Taste twins. Year-end summaries that are actually personalized. Reconstructing the shape of a specific day, a year ago. Connecting dots across years of scrobbles.

The dataset is open, the community is generous, and the use cases are genuinely fun. It felt like the right room to walk into first.

If you want to try it, the easiest path is to connect your ListenBrainz account to Toolforest and ask Claude (or whichever assistant you use) something like "According to my ListenBrainz data, who are my three closest taste twins?" The examples in the Cookbook section will give you a few more ideas.

Where this goes

This is a personal project. I have no plans to commercialize it. I'll support the infrastructure myself for as long as that's reasonable; if usage ever gets to the point where the costs become a problem, I'll figure something out then.

What I'm most interested in, though, is closing the loop on toolkit development itself. The same LLMs that use these toolkits are pretty good at evaluating them: finding rough edges, suggesting better tool shapes, inventing use cases I wouldn't have thought of. I've been building a pipeline where models do exactly that. Pick a toolkit, invent a use case, execute it, evaluate the result, and write the findings back as structured feedback. The end state is something close to LLM-guided toolkit development, where agents propose new toolkits, build intermediate layers, and roll them out with minimal hand-holding from me. I'll write more about that in a future post.

If you have ideas for toolkits or enhancements you'd like to see, you can reach me at gerrit@toolforest.io or through the request form on the homepage. And if you're a ListenBrainz user, thanks for taking a look. Hoping this is useful.