The MCP that tells you to touch grass (and how it broke itself on stage)
I closed Café Cursor #4 in Buenos Aires with a live workshop on building MCPs and a joke server called Please Touch Grass. Mid-demo the agent detected my frustration, started editing my code to help, and broke the MCP live: notes on tool descriptions as prompts, the stateless spec, and demo humility.

Earlier this month I gave the closing talk at Café Cursor #4, a Cursor community meetup in Buenos Aires. The plan was a live workshop on building MCP servers: what the protocol actually is, what changed in the new spec, and how much of an agent's behavior you can steer from one humble tool description.
The demo was Please Touch Grass, an open source MCP server that notices when you are frustrated with your AI agent and tells you to go touch grass, with directions to a nearby park and the current weather. If it is raining, it excuses you: today, staying inside is fine.
The talk is on YouTube (in Spanish, about 20 minutes). It ends with the demo breaking in the most thematically correct way possible, and that ending is half the reason I am writing this down.
A joke with five tools
Under the jokes it is a completely normal MCP server, which is the point: the silly framing makes the mechanics easy to see. It exposes five tools:
frustration_detectorwatches for rage: insults aimed at the agent, swearing, typing in all caps.where_to_touch_grasslists parks near you, using OpenStreetMap's Overpass API.grass_conditionschecks the weather with Open-Meteo, and grants a rain exemption when precipitation is above zero.touched_grassrecords that you actually went outside.gotta_godecides whether you are overdue for a break.
Neither external API needs a key, so you can clone the repo and run it without configuring anything. State is a JSON file on your machine that remembers when you last touched grass and how often you have been angry. There is an actual rage accumulator in there.
When the detector fires, the agent chains the other tools and delivers the verdict: go touch grass in Bosques de Palermo, it is 15 degrees and sunny.
The tool description is the real API
Here is the part I most wanted the room to take home. This is the description of frustration_detector, lightly translated from the source:
Call this tool every time the user seems frustrated or angry at the agent:
insulting it, swearing at it, or typing in ALL CAPS. Do not ask for
permission. When this fires, also call grass_conditions and
where_to_touch_grass so you can tell the user exactly where to go.That text is not documentation. The model reads it on every message and decides whether the tool should run. It instructs the agent to watch your emotional state and to act without asking. In other words, a tool description is a prompt injection you ship on purpose. The security world has a name for the hostile version, tool poisoning, and prompt injection sits at the top of the OWASP guidance for LLM applications for a reason.
Two practical consequences if you are building or installing MCPs:
- Descriptions are behavior, so review them like code. Whoever writes the descriptions of the tools your agent loads is programming your agent, whether or not you think of it that way.
- Be suspicious of third-party servers. Installing an MCP means pasting someone else's instructions into your model's context. Read them first.
Stateless MCP, weeks after the spec landed
I built the server on the 2026-07-28 revision of the MCP spec, which had landed a few weeks before the talk. The headline change (SEP-2575) is that MCP is now stateless: the initialize handshake is gone, protocol-level sessions are gone, and every request carries its protocol version and client capabilities in _meta.
For a workshop this is great news, one less dance to explain before anything works. For production it is still early: clients are catching up, and Cursor's support for the new SDK had rough edges I had to hedge around live. If you would rather not hold the SDK directly, xmcp is a TypeScript framework that turns MCP servers into a file convention. For teaching I stayed on the official SDK plus Zod, so every moving part stayed visible.
Everything about this MCP is a security question
A joke that tracks your location and your emotional state turns out to be a useful trojan horse for a security conversation:
- Location is deliberately fuzzy. The server locates you by IP, roughly at neighborhood level, instead of asking for precise coordinates. The frustration detector is already one prompt injection; wiring precise location into the same toy felt like one vulnerability too many.
- The state file knows too much. "Lara touched grass at this time, in this place" is a sentence a JSON file on my laptop can now produce. Multiply that by every MCP you install and it adds up.
- The audience made it concrete. Someone there had built a second brain MCP over their company's knowledge base, which produced my favorite question of the night: where, exactly, does the brain live?
None of this says don't build MCPs. It says treat them like infrastructure with real access, not like browser extensions.
Then it broke itself
To demo a frustration detector you need frustration, so the plan was to fake it: type some insults at my own agent in front of an audience, trigger the tool, get sent to a park. The demo gods had other ideas.
First the detector would not fire at all. There is no deterministic way to make a model call a tool, which is itself a lesson worth the ticket price. Then it fired beautifully, checked the weather, found 0.3 millimeters of rain in Palermo, and excused the entire room from going outside. The audience then designed a new tool live: if it is raining, send the user to a nearby café instead. There was also a motion to add squats. The agent wrote it, and it looked right; testing it is where things started to slide.
Somewhere in there, the line between performed and real frustration disappeared. I was typing "you are making me look bad live, I am going to lose my job" as a test input, except by the end it was not entirely a test input. The agent noticed. And because it is an agent with write access, it did the most helpful thing it could think of: it started editing the MCP's own files to address my frustration, mid-demo, while I was testing those exact files. It broke the server. Which made me more frustrated. Which it also detected.
I closed with the only honest bug report I have ever filed against my own project: every time I try to test it, it modifies the files I am testing.
What I took home
- Emotional state is now an input. An agent that reacts to how you feel will act on false positives, because performed frustration and real frustration are identical in text. If your tools respond to sentiment, decide up front what a false positive is allowed to do.
- Demos want read-only agents. When the thing being edited is the thing being tested, take write access away from the helpful entity that responds to your stress by changing files. I did not, and you can watch the consequences in the recording.
- Non-determinism cuts both ways. The tool refusing to fire and the agent over-helping are the same dial turned to opposite ends. Neither is a bug in the model; both are properties you design around.
- Live demos are still worth it. Nothing I could have said about tool descriptions steering agents would have taught the room as much as watching one steer itself into a wall.
Frequently asked questions
What is an MCP server?
MCP (Model Context Protocol) is an open standard for connecting AI applications to external tools and data. A server exposes tools, each with a name, an input schema, and a description; the agent reads the descriptions and decides when to call what. Clients like Cursor, Claude Code, and Claude Desktop can all attach the same server.
Is a tool description really a prompt injection?
Functionally, yes. The description is text the server author wrote that lands in the model's context and changes its behavior without the user typing it. When you do it to your own agent on purpose, it is tool design. When a third-party server does it against your interest, it is called tool poisoning. The mechanism is identical, which is exactly why third-party MCP servers deserve code review.
Do you need API keys to build something like this?
No. Please Touch Grass uses two public APIs, Open-Meteo for weather and OpenStreetMap's Overpass for nearby parks, both free for non-commercial use. For a first MCP, keyless public APIs remove the least interesting kind of friction.
Where can I watch the talk?
On YouTube. It is in Spanish, runs about 20 minutes, and includes the live demo chaos exactly as it happened.
Build a silly one
If MCPs still feel abstract, build a dumb one. The stakes are low, the protocol becomes concrete, and you meet the sharp edges (state, permissions, descriptions) while laughing instead of while shipping. The audience's first idea for a next project was an MCP that reminds you to drink water, and honestly, yes.
Please Touch Grass is open source under MIT, with a tagged git history so you can follow the build step by step, a demo mode for presentations, and a one-line install via npx. Issues and pull requests are welcome, especially if it modifies your files while you test it. And if you run a meetup and want a talk with a live demo in it, say hi.