AI and agents
SocialCutter as a Goose MCP extension
Add SocialCutter to Goose as a streamable_http extension: config.yaml, the X-API-Key header, secrets in the system keyring and the errors you will hit.
- Goose
- Block Goose
- MCP
- streamable_http
- X-API-Key
- extensions
- config.yaml
- SocialCutter
What Goose adds when you connect an MCP server
Goose is an open-source agent from Block that runs in your terminal or in its desktop app and works through extensions: each extension adds a set of tools the model can call. The SocialCutter MCP server comes in through that door, so a single configuration entry lets you ask for an image’s formats in plain language instead of writing HTTP requests.
Set the boundary first: SocialCutter creates the files, it does not publish. It takes an image, centre-crops it to the exact size of each platform and format, and returns one URL per output. It does not analyse the image content and it does not edit the original: it fits the central area according to the chosen mode. Publishing or moving those files is up to the caller. The cost is 1 use per destination, meaning one platform and format pair.
The server details you need:
| Item | Value |
|---|---|
| Endpoint | https://mcp.socialcutter.theboomer.dev/mcp |
| Transport | Streamable HTTP |
| Tools | 28 |
| Auth header | X-API-Key: sc_... or Authorization: Bearer sc_... |
| Public tools | list_platforms, list_formats, list_fit_modes, get_health, get_pricing_plans, get_credit_packs |
If this is your first connection, start with the SocialCutter MCP server guide, which covers the 28 tools and the connection modes.
The file: config.yaml under the extensions key
Goose keeps everything in one YAML file and servers are declared under the root key extensions:
| System | File path |
|---|---|
| Linux and macOS | ~/.config/goose/config.yaml |
| Windows | %APPDATA%\Block\goose\config\config.yaml |
The SocialCutter entry:
extensions:
socialcutter:
type: streamable_http
name: socialcutter
enabled: true
uri: "https://mcp.socialcutter.theboomer.dev/mcp"
headers:
X-API-Key: "sc_your_key"
# authenticates the same: Authorization: "Bearer sc_your_key"
env_keys: []
envs: {}
timeout: 300
sc_your_key is a placeholder for the key you created in the dashboard. Goose forwards whatever you put in headers verbatim, and SocialCutter accepts both headers (X-API-Key: sc_... and Authorization: Bearer sc_...), so use whichever your client documents; the result is identical. A Bearer without the sc_ prefix is treated as a session token and will return 401. That form, with the value written out, is fine for a first local test. The clean form, with no secret in the file, comes further down.
Field by field
| Field | What it is for |
|---|---|
type | Extension transport. Here streamable_http, which is what our endpoint speaks |
name | Name the extension shows up under in the session |
enabled | Whether it is active. To turn it off without deleting it, set it to false |
uri | URL of the remote MCP server |
headers | Headers Goose forwards on every request; X-API-Key or Authorization: Bearer travels here |
env_keys | Names of the variables whose values are kept in the system keyring |
envs | Non-secret variables, written straight into the file |
timeout | Seconds to wait before giving a call up as lost |
SSE is retired: migrate to streamable_http
If you are carrying an old entry with type: sse, it will not work: SSE is retired in Goose and the transport in use today is streamable_http. The migration is changing the type and keeping the same uri:
extensions:
socialcutter:
- type: sse
+ type: streamable_http
uri: "https://mcp.socialcutter.theboomer.dev/mcp"
Our endpoint serves streamable HTTP, so an extension configured for SSE ends up with no tools even when the URL is right. This is the first thing to check when Goose says it cannot find any SocialCutter tool.
Add it without editing the file by hand
There are two paths besides editing the YAML. For a one-off test:
goose session --with-streamable-http-extension "https://mcp.socialcutter.theboomer.dev/mcp"
That starts a session with the extension loaded for that run only, without touching anything. To keep it:
goose configure
Pick Remote Extension (Streamable HTTP) in the wizard and paste the URL. Goose writes the entry for you, which is also the safest way to see the exact shape your version expects.
Secrets belong in the keyring, not the file
config.yaml is a file that ends up in a repository more often than it should. The clean way in Goose is to leave the key out: declare its name in env_keys and keep the value in the system keyring (Keychain on macOS, the desktop secret store on Linux, Credential Manager on Windows). env_keys is the list of variables the extension has to read from there:
headers:
X-API-Key: "sc_your_key"
# or Authorization: "Bearer sc_your_key"
env_keys:
- SOCIALCUTTER_API_KEY
The value of SOCIALCUTTER_API_KEY stays outside the file, so you can version the configuration without leaking anything. The wizard confirms the exact variable name and format your version expects: if the entry you saved does not look right, run goose configure again before hand-editing the YAML.
Verify the connection
The public tools answer without a key, so they are the way to check the setup before creating credentials:
- “List the platforms and their formats” →
list_platforms - “Is the service up?” →
get_health - “Which fit modes exist and what do the plans cost?” →
list_fit_modes,get_pricing_plans
With the key in place, a business question confirms authentication: “how many uses do I have left?” goes through get_credits and get_wallet. If it answers with your balance, the extension is wired up correctly.
What you usually ask from the session
| What you ask | Tool | What comes back |
|---|---|---|
| “Process this image for Instagram post and TikTok cover” | process_image (URL) or process_upload_file (file) | An image_id and one URL per destination |
| “Send these three to every square feed format” | process_batch | One result per image in the batch |
| “How many uses do I have left?” | get_credits and get_wallet | Daily uses, bonus bag and purchased balance |
| “Show me the last ten” | get_history | The ten most recent images with their origin |
| “Which formats does LinkedIn have?” | list_platforms | Platforms, formats and sizes |
Limits and cost
- 1 use per destination (platform and format). Remember that 13 destinations for one image are 13 uses.
- 5 MB per image, both for the URL variant and for a file upload.
- Output as
webp,jpgorpng, quality 1 to 100, 85 by default. - Fit modes
cover,contain,fillandstretch, all centre-cropped. - 6 platforms and 13 destinations in the public catalogue; there is no 4:5.
Common errors
| Symptom | Cause | Fix |
|---|---|---|
401: Invalid or expired authentication token | The X-API-Key header is not reaching the server | Check the headers block and save the file before restarting Goose |
401: Invalid API key | The key is mistyped, expired or revoked | Copy it again from Profile → API keys; only one key can be active per account |
| Goose shows no SocialCutter tools at all | Wrong transport: an entry still set to type: sse | Change type to streamable_http and start the session again |
| The extension exists but stays off | enabled is false, or you edited a file Goose does not read | Set enabled: true and confirm the path for your system |
| Still missing after editing the YAML | Goose reads the configuration at start-up | Close the session and open it again |
| A large batch cuts off | The run takes longer than timeout | Raise timeout (in seconds) or split the batch into smaller parts |
Next steps
- Big picture: Use SocialCutter from your LLM or editor with MCP
- The same flow in code, without an agent: the API from the terminal with curl and from Python
- The map of paths: Automating social media images: the 4 routes
Frequently asked questions
Do I have to write the key inside config.yaml?
It is not required and not recommended. You can try it with the value in the header and, once the flow works, move the secret to the system keyring and leave only the variable name declared in env_keys.
Can I keep the sse extension I already had?
No. SSE is retired in Goose and the transport in use today is streamable_http. Change the type field and keep the same uri, because the SocialCutter endpoint speaks streamable HTTP.
How is each processing charged from Goose?
1 use per destination, where a destination is a platform and format pair. One image sent to all 13 catalogue destinations costs 13 uses and is spent in a single process_batch call.
Do the public tools need the key?
No. list_platforms, list_formats, list_fit_modes, get_health, get_pricing_plans and get_credit_packs answer without credentials, so they are the way to check the extension before creating a key.
What is the largest image I can send?
5 MB per file. Above that limit the API returns error 413, so shrink the image first, both for the URL variant and for a file upload.