Back/Engineering/Goose
AdvancedEngineering

How to Build a Custom AI Email Tool for Goose Using 'Vibe Coding'

Build a narrow email MCP by proving the provider call in a small script, wrapping it in a validated tool contract, and testing the enabled tool with safe recipients before connecting it to a larger agent workflow.

How to Build a Custom AI Email Tool for Goose Using 'Vibe Coding'

Brad first asks Goose to write and test a small Python script that sends an email, then provides MCP Python SDK reference code, converts the working function into a send email tool, fixes setup errors, enables it in Goose, and uses it to email the Square payment link.

Before you start

What you need

  • A permitted email provider and test account or sandbox
  • A scoped API key stored outside source code and agent context
  • A verified sender, allowlisted recipients, and nonproduction message templates
  • The current MCP Python SDK reference and a scaffolded Python package
  • Tool input schema, size and rate limits, idempotency, audit logging, and an emergency disable path

What you’ll make

A minimal send email MCP that validates recipient, subject, body, and idempotency key, protects credentials, reports provider status accurately, and can be disabled without changing the agent.

Tools used

  • Goose

    Open-source AI agent by Block for automating tasks

Step by step

The workflow

Follow the sequence once, then adapt the prompts, checks, and handoffs to your own setup.

5 steps

Step01

Scaffold the Core Functionality

Create a small Python package and implement one provider call that sends a fixed test message to an allowlisted address. Load the API key from the runtime environment, validate inputs, and keep secrets out of prompts and output.

Example prompt
In this scaffolded Python package, implement a send_test_email function using [provider]. Read only the named environment variables [names] at runtime without printing them. Restrict recipients to [allowlist], add idempotency, return provider message ID and acceptance state, and include a test with a mocked provider.
Step02

Convert the Script into an MCP

Use the current MCP Python SDK reference to wrap the proven function as a narrow send email tool. Define required fields, maximum sizes, allowlist behavior, idempotency, structured errors, and a description that does not overstate delivery guarantees.

Example prompt
Using this MCP Python SDK reference: [reference], expose the tested function as send_email. Schema: recipient, subject, text body, optional permitted link, and idempotency key. Enforce allowlist and size limits server side. Return accepted, provider message ID, and error category. Do not expose secrets or add unrelated tools.
Step03

Debug with AI Assistance

Run unit and integration tests, start the MCP server, and paste only sanitized errors back to Goose. Fix one cause at a time, rerun from a clean process, and verify that failure paths do not send mail.

Example prompt
That code produced this error: [paste full error message from terminal]. Can you fix it?
Step04

Integrate the New Custom Tool

Register the server in Goose with an explicit executable and safe environment mapping. Inspect the discovered tool name and schema, keep the recipient allowlist in force, and send a unique test message.

Step05

Use the New Tool to Close the Loop

Connect the email tool to the catalog flow only after both pieces work independently. Pass the verified payment link, recipient, template, and idempotency key explicitly, then reconcile the provider status and recipient inbox.

Example prompt
Send the verified payment link [URL] to the allowlisted test recipient [address] using template [template]. Subject: [subject]. Idempotency key: [stable key]. Echo recipient and link host before calling the tool. Do not change the recipient, amount, item, or link.

What good looks like

  • Secrets never appear in prompts, logs, source control, tool output, or exception messages.
  • The standalone function and MCP tool deliver only to approved test recipients before broader use.
  • Duplicate calls do not send duplicate messages, and provider failures return a truthful retryable or terminal state.
  • The enabled tool has a narrow description and schema, and the agent cannot silently choose arbitrary recipients or content.

Build your next product with ChatPRD

Turn an idea into a PRD, user stories, and a plan.

Try ChatPRD free

After the steps

Runbook notes

How to recover when the loop fails and where human judgment helps.

Recover

If it goes sideways

Goose attempts to read or print the environment file
Deny the read, expose only named runtime variables to the process, redact errors, and rotate any credential that was revealed.
A broad tool lets the agent contact arbitrary people or send unreviewed content
Start with recipient allowlists, templates, quotas, test mode, and explicit workflow rules for external sends.
A retry sends the same payment link or notification several times
Require an idempotency key, persist provider message IDs, and check prior status before sending.
The tool reports success before the provider accepts or delivers the message
Return provider acceptance and delivery states separately, handle callbacks, and expose failures to the calling workflow.

Start shipping
better products.

Join 100,000+ product managers who use ChatPRD to write better docs, align teams faster, and build products users love.

Free to start
No credit card
SOC 2 certified
Enterprise ready