just what i find

just what i find

Responsible disclosure: TRMNL MCP server leaks password fields to AI agents

TRMNL is an awesome open-source ePaper display that lets users show almost anything they want. Launched on Kickstarter, it’s now got thousands of plugins and users. I’ve published a few plugins, including a realtime TfL bus stop arrival time board.

A few weeks ago, TRMNL added an MCP server. This lets you use a local coding agent to do most of the grunt work. I wrote about how to set that up in another post.

Using multiple TRMNL MCP API keys in a single plugin repo

TRMNL is an awesome open-source ePaper display that lets users show almost anything they want. Launched on Kickstarter, it’s now got thousands of plugins and users. I’ve published a few plugins, including a realtime TfL bus stop arrival time board.

A few weeks ago, TRMNL added an MCP server. This lets you use a local coding agent to do most of the grunt work.

Install the MCP server through .mcp.json

Using Claude Code, i created a simple .mcp.json file which references the API key by environment variable. Place this in the root of your repo. As it contains no secrets, this is safe to commit:

Fix: Claude Code with op run responds "No deferred tool marker found in the resumed session"

To stop my API keys being sucked up by some random malware, I keep secrets in 1Password and inject them into commands at runtime with op run. That works for almost everything, but when using Claude Code, i started getting a confusing error message.

Injecting MCP API keys to Claude Code

Claude Code reads MCP server config from .mcp.json and expands ${VAR} references from the environment.

{
  "mcpServers": {
    "trmnl": {
      "type": "http",
      "url": "https://mcp-server.com/mcp?api_key=${MY_SECRET_MCP_API_KEY}"
    }
  }
}

The API key is in a file. .env.tpl:

Recipe: Veggie smoked beans

Ingredients

  • 1 tin baked beans
  • 1 small white onion
  • 1 clove garlic
  • 1 tbsp Hendersons Relish
  • splash of vegetable oil

Method

  1. finely chop the onion
  2. grate the garlic
  3. gently (low temperature) fry onion in the vegetable oil for 5-6 mins over a medium heat in the small (metal?) roasting tin you’ll use in the smoker
  4. Take off the heat and add the grated garlic
  5. Add the beans and hendersons
  6. Stir and put in the smoker (110-120c) for 60-90 minutes. Check after 60 mins to make sure not dried out. If it starts to get dry, add a splash of water. Stir.

Recipe: Spicy cheese quesadillas

ingredients

  • 20g cheddar
  • 20g light cream cheese
  • 1 tsp paprika
  • 1/2 tsp chilli flakes
  • 30g tinned sweetcorn, drained well
  • One of:
    • 1/2 tsp miso paste
    • 1 tsp soy sauce
    • 1 tsp Hendersons relish
  • 1/4 tsp garlic powder
  • 1/4 tsp onion powder
  • pinch white pepper
  • 1 small tortilla

Method

  1. Mix cream cheese & miso/soy/Henderson’s + spices into a paste
  2. Fold in sweetcorn and cheddar
  3. Spread in tortilla and fold in half
  4. Cook in pan, place baking parchment on top and plate on that to squash slightly

Recipe: Smoked Tempeh

Smoked tempeh is excellent for smoking as the dense, porous structure absorbs smoke like few other proteins.

Ingredients

  • 30ml soy sauce
  • 3 grams (about 1-2 cloves) minced garlic
  • 15 g sesame oil
  • 15ml rice vinegar - needed to penetrate
  • pinch of salt

Method

  1. Slice into planks or thick strips rather than cubes — more surface area, better bark formation, less risk of drying out.
  2. Steam or simmer the tempeh for 10-15 minutes first. This removes bitterness and opens the pores for better smoke and marinade absorption.
  3. Marinate for at least 30 minutes. This gives time for the marinade to to infuse.
  4. Smoke at 110-130°C for 45-60 minutes.
  5. Baste or re-glaze halfway through (or more often if you like) if using a sticky marinade.

Recipe: Smoked Roast Potatoes

Ingredients

  • as many New Potatoes as you think you’ll need
  • Vegetable oil
  • salt, pepper
  • and a smoker

Method

  1. Boil new potatoes until fork-tender (15-20 min) then drain
  2. smash them on a sheet tray to break them slightly. The fluffy bits go crispy.
  3. Coat them in oil/fat (e.g. drizzle in vegetable oil) and seasoning (salt, pepper)
  4. roast in the oven at 220°C for 20-25 minutes until the edges are crispy and golden.
  5. Transfer to the smoker at 110-130°C for 20-30 minutes to pick up smoke flavour. The already-crisped surfaces absorb smoke well. Going longer than 30 minutes risks drying them out or making the smoke flavour acrid.

Updated: using 1Password and direnv to store developer secrets

I previously wrote about how i’d implemented a combination of 1Password’s CLI and direnv to avoid storing passwords on disk. This works great, most of the time. The problem comes when i want to add a secret and i’m in the middle of a complex multi-agent task - because the environment is loaded once before Claude or Codex or whatever starts, adding or rotating credentials during a build (e.g. if the agent needs an API key to a new service, or accidentally exposes a secret to its context) is tricky. So i’ve evolved the system slightly.

Recpie: Miso BBQ Aubergine

glaze

  • 30g white or red miso (white = sweeter/milder, red = deeper/saltier)
  • 15ml soy sauce
  • 15ml mirin (or 10ml rice vinegar + small pinch sugar)
  • 10g grated garlic
  • 10g sesame oil
  • 15ml honey
  • optional: 5g grated ginger

Method

  1. Halve aubergines lengthways. Score the cut face in a crosshatch ~1cm deep without piercing the skin. This speeds cooking and lets glaze penetrate.
  2. Lightly oil the cut face only. Do not soak it — aubergine absorbs oil indefinitely. Use high temperature oil (vegegable or avocado oil, not olive)
  3. Grill cut-side down over medium heat 6-8 minutes until charred and the flesh is collapsing soft. Flip to skin-side down for another 4-6 minutes.
  4. Test doneness: the flesh should be fully translucent and yielding throughout, no white spongy core.
  5. Brush glaze onto the cut face. Return cut-side down over medium-low heat 2-3 minutes to caramelise. Watch closely — it scorches quickly.
  6. Re-glaze and finish skin-side down 1-2 minutes to set the lacquer without burning.

Minimum Viable Solution Architecture

Recently at work, someone asked me why my team wasn’t creating detailed logical data models as part of their solution design. It seems quite simple to me – they don’t do it because nobody reads it. Most solution architecture documentation is out of date before it even gets logged in the architecture repository.

Why do we even write documentation?

I think we create documentation for one of two reasons:

  1. Collaborate now: as soon as there is a second person in a team, they need to start talking so that they can work together. The more people, the harder this is (which is why we try to limit teams to half a dozen people or so). Documentation is a great way for people to collaborate. When things are written down, everyone can see it, and by adding comments or questions we get to a resolved version.
  2. Communicate with the future: We make decisions today which are the best available given the information we have at the time. Sometimes we forget what we decided, or why, and documentation gives us that. It’s not about proving whether a decision was right or wrong – that’s largely irrelevant – it’s about understanding what led us to that decision in the first place. Perhaps the reasons are still valid and we just forgot what they were. Or perhaps information we have now changes things.

So really, design documentation is about ensuring that everyone’s on the same page, both now and in the future. Some designs are ephemeral – just to help us get our heads around what we want to do, and some is persistent – giving us a framework on which to hang our future plans.

All posts