Developer documentation

Meow Meow Scratch® developer documentation

Learn how APIs work, connect Raspberry Pi or microcontroller projects, and build IoT applications without creating or operating a backend. This reference covers the web app, REST API, Python SDK and CLI, MCP, the MicroPython SDK, and examples.

Learn the basics

Build your first API in 10 minutes

An API is a way for two programs to exchange data. One program sends an HTTP request to an endpoint; the endpoint returns a response. In this lesson, you will create a private temperature API, send it a reading, and retrieve that reading.

What you will build

A Weather Station app with a Readings collection. Each record contains a numeric temperature value, ready for a script, Raspberry Pi, or another application to use. You do not need any hardware for this lesson.

The request-response loop

1 · Request

Your browser, terminal, or device asks an endpoint to read or change data.

2 · Endpoint

The endpoint authenticates the request, validates the data, and performs the action.

3 · Response

The API returns a status code and usually a JSON body describing the result.

Five parts of an HTTP request

URL

Where to send it

Method

GET reads, POST creates, PATCH updates, DELETE removes

Headers

Context such as authentication and content type

Body

JSON—the text format of keys and values sent with a write

Status

The numeric result, such as 200 or 404

Before you start

You need a Meow Meow Scratch® account and a terminal withcurl. The commands use macOS, Linux, Git Bash, or WSL shell syntax. On Windows, Git Bash is the simplest way to run them exactly as written. PowerShell uses different environment-variable and line-continuation syntax.

1. Create the app and collection

Complete these steps in the web app. Slugs become parts of the API URL, so enter them exactly as shown.
  1. 1Open Apps → New App. Use name Weather Station and slug weather-station.
  2. 2Open the app and choose New Endpoint. Use name Readings, slug readings, and type Collection.
  3. 3Open the endpoint and choose Add Field. Use label Temperature, key temperature, type Number, and enable Required.

Private by default

New apps and endpoints start private. Keep this tutorial private; you will authenticate each request with an API key restricted to this app.

2. Create an app API key

Return to Weather Station → API Keys → New API Key. Name it API tutorial, enable both Read and Write, then copy the value immediately. The full key is shown once.
terminal · set your values
export MEOW_APP_API_KEY="YOUR_APP_API_KEY"
export MEOW_USERNAME="YOUR_USERNAME"
export MEOW_API="https://meowmeowscratch.com/api"

Replace both YOUR_APP_API_KEY andYOUR_USERNAME. Keep the quotation marks. Do not paste a real token into source code, chat, or a public repository.

3. Send your first POST request

POST creates data. This request sends one temperature record to the collection management endpoint.
terminal · create a record
curl -i -X POST "$MEOW_API/apps/weather-station/endpoints/readings/records/"   -H "Authorization: Bearer $MEOW_APP_API_KEY"   -H "Content-Type: application/json"   -d '{"data":{"temperature":22.5}}'
expected response shape
HTTP/... 201 Created


{
  "uuid": "…",
  "data": {"temperature": 22.5},
  "created_at": "…",
  "updated_at": "…"
}

201 Created means the API accepted the request and created a new resource. Your UUID identifies that record.

4. Read it back with GET

GET reads data without changing it. The consumer URL is the stable address a website, script, or device uses.
terminal · read the collection
curl -i "$MEOW_API/v1/$MEOW_USERNAME/weather-station/readings/"   -H "Authorization: Bearer $MEOW_APP_API_KEY"
expected response shape
HTTP/... 200 OK


{
  "count": 1,
  "fields": [
    {"name": "temperature", "label": "Temperature", "field_type": "number"}
  ],
  "records": [
    {"uuid": "…", "data": {"temperature": 22.5}, "created_at": "…"}
  ]
}

What the command means

curl

The command-line HTTP client sending the request.

-i

Show the response status and headers as well as the JSON body.

-X POST

Use the POST method. GET is curl's default, so the read command does not need -X GET.

-H

Add a header. The Bearer header proves who you are; Content-Type says the body is JSON.

-d

Send the following JSON as the request body.

5. Experiment

Learning APIs becomes much easier when you change one thing and observe the response.
  • Send a second POST with temperature set to 18.4, then GET the collection again.
  • Add ?temperature__gte=20 to the GET URL and predict which record remains.
  • Send temperature as "warm" and inspect the 400 validation response.
  • Open Request Logs in the endpoint and find the GET request's status and response time.

You have built an API

You created a schema, authenticated a write, sent JSON with POST, interpreted a 201 response, and retrieved data with GET. The rest of this page shows every supported way to build on that loop.

Core product concepts

A Meow Meow Scratch® app is a project containing endpoints. Each endpoint has a stable consumer URL and can be managed through the web app, REST API, Python SDK, CLI, or MCP. Running boards use the MicroPython SDK to read and write endpoint data.

Collection

Many typed records

Sensor readings, events, form submissions, inventories

Static payload

One JSON document

Device state, configuration, flags, status documents

Proxy / integration

A guarded upstream request

Weather, games, or a third-party JSON service

Quick glossary

API
A defined way for programs to request data or actions from one another.
Endpoint
A URL that accepts a particular kind of API request.
JSON
A text format that represents data as objects, arrays, keys, and values.
Schema
The rules describing which fields exist and what type of value each accepts.
Slug
A short URL-safe name, such as weather-station.
Token
A secret credential sent with a request to prove identity and permission.

01 · Web app

Use the Meow Meow Scratch® web app

Use the dashboard to define schemas, edit data, configure integrations, inspect logs, manage credentials, and create control panels.

Create your first API

  1. 1

    Create an app

    Open Apps, choose New app, then set its display name, URL slug, and description. The app starts private.

  2. 2

    Add an endpoint

    Inside the app, choose Collection, Static Payload, or Proxy / Integration and give it a stable slug.

  3. 3

    Configure its data

    Add typed fields to a collection, edit the JSON payload for a static endpoint, or configure the upstream proxy.

  4. 4

    Test the consumer URL

    Open the endpoint page to copy its URL, inspect code snippets or QR code, and make a request.

Collection schemas

Collection fields drive validation, dashboard inputs, and public response metadata. Available types are text, long text, number, boolean, date, date-time, time, color, email, URL, select, rating, image URL, and JSON.

A field can be required, have a default, include help text, and carry type-specific options such as numeric bounds, select choices, rating maximums, or text placeholders. Records keep a UUID, timestamps, and the validated data object.

Endpoint behavior and operations

Chaos mode

Add a controlled delay or simulated error rate when testing clients.

Record expiry

Set a TTL so old collection records are automatically removed.

Transforms

Round or clamp numbers, normalize text case, or set missing defaults.

Webhooks

Deliver record and payload events to another HTTPS service.

Request logs

Inspect recent method, status, timing, client IP, and user-agent data.

Response encryption

Encrypt consumer responses and request plaintext with X-Encryption-Key.

Control panels

Controls expose endpoint values through a dashboard. Add toggle, color, slider, number, text, select, or display widgets and optionally share the panel by link.

Remote configuration without building a backend

Put device settings in one static endpoint, bind dashboard controls to keys such as camera.thresholds.confidence, and let the Raspberry Pi poll that document with an app API key. A dashboard change updates the same JSON the device reads. Collection widgets are display-only and show values from the latest record; proxy endpoints do not support widgets.

Credentials

Create platform tokens under Account for the SDK, CLI, MCP, and automation that works across apps. Create an app API key inside the relevant app for a Raspberry Pi, device, or integration that only needs that app. Give app keys only the Read and Write scopes they require. The full value is shown once.

02 · REST API

Call the REST API directly

The management API creates and updates resources. The consumer API reads endpoint data. Send Content-Type: application/json with JSON request bodies. If HTTP is new to you, complete the beginner tutorial before using this section as a reference.

Management API

Create and configure apps, endpoints, schemas, records, keys, webhooks, and control panels. Every request requires a Bearer token.

Consumer API

Read the stable URL used by websites, scripts, and devices. Private resources require a token; public resources allow anonymous reads.

Authentication

Authorization: Bearer YOUR_TOKEN

Keep the trailing slash

API routes are slash-terminated. Use /api/apps/, not /api/apps, to avoid an HTTP redirect—especially for POST, PATCH, and DELETE requests.

Choose the narrowest credential

App API key · one app

Recommended for Raspberry Pis, devices, and direct API integrations. The key can access only its app, and Read and Write scopes are enforced independently.

Platform token · all your apps

Recommended for the SDK, CLI, MCP, and account-wide resource automation. It can manage Meow resources across your account.

API credentials are accepted only by Meow resource routes, not authentication, profile, billing, chat, or CMS management. App keys also cannot create apps, manage credentials, or access account-wide control panels and provider configuration.

Use role-specific environment variables

Store account-wide tokens in MEOW_PLATFORM_API_KEY and app-scoped credentials in MEOW_APP_API_KEY. The SDK and tooling do not read the ambiguous legacy name MEOW_API_KEY.

Set reusable shell values

The examples below use these environment variables. Replace the placeholders with the app API key and username from the beginner tutorial.
terminal
export MEOW_API="https://meowmeowscratch.com/api"
export MEOW_APP_API_KEY="YOUR_APP_API_KEY"
export MEOW_USERNAME="YOUR_USERNAME"

Consumer API

Every endpoint is read from the same stable URL shape. Collection endpoints return paginated records, static endpoints return their JSON document, and proxy endpoints return the transformed upstream response.
http
GET /api/v1/{username}/{app}/{endpoint}/
GET /api/v1/{username}/{app}/{endpoint}/{record_uuid}/
GET /api/v2/dashboards/{share_token}/


# Public reads omit the header; replace these slugs with a public app and endpoint
curl "$MEOW_API/v1/$MEOW_USERNAME/YOUR_PUBLIC_APP/YOUR_PUBLIC_ENDPOINT/"


# Supply a token for a private consumer endpoint
curl "$MEOW_API/v1/$MEOW_USERNAME/weather-station/readings/" \
  -H "Authorization: Bearer $MEOW_APP_API_KEY"

Filter, aggregate, and export collections

Filters

Use a field name for equality. Number and rating fields also accept __gt, __gte, __lt, and __lte.

Aggregates

Pass aggregate=avg,min,max,sum,count and a numeric field. Count does not require a field.

CSV

Pass format=csv to export up to 500 records. CSV export is unavailable for encrypted endpoints.

terminal
BASE="$MEOW_API/v1/$MEOW_USERNAME/weather-station/readings/"


curl "$BASE?temperature__gte=20&limit=50"   -H "Authorization: Bearer $MEOW_APP_API_KEY"
curl "$BASE?aggregate=avg,max&field=temperature"   -H "Authorization: Bearer $MEOW_APP_API_KEY"
curl "$BASE?format=csv" -H "Authorization: Bearer $MEOW_APP_API_KEY" -o readings.csv

Consumer response shape

A collection response includes schema metadata alongside the data, so clients can render useful controls without a separate schema request.
json
{
  "count": 1,
  "limit": 100,
  "offset": 0,
  "fields": [
    {"name": "temperature", "label": "Temperature", "field_type": "number"}
  ],
  "records": [
    {"uuid": "…", "data": {"temperature": 22.5}, "created_at": "…"}
  ]
}

Update and delete a record

Use the UUID returned when the record was created. A successful PATCH returns the updated record; a successful DELETE returns204 No Content with no JSON body.
terminal
export RECORD_UUID="UUID_FROM_THE_POST_RESPONSE"


curl -i -X PATCH "$MEOW_API/apps/weather-station/endpoints/readings/records/$RECORD_UUID/"   -H "Authorization: Bearer $MEOW_APP_API_KEY"   -H "Content-Type: application/json"   -d '{"data":{"temperature":23.0}}'


curl -i -X DELETE "$MEOW_API/apps/weather-station/endpoints/readings/records/$RECORD_UUID/"   -H "Authorization: Bearer $MEOW_APP_API_KEY"

Successful status codes

200 OK

A read or update succeeded and returned a body.

201 Created

A POST created a new resource.

204 No Content

A delete succeeded and returned no body.

Management route reference

Path placeholders use the app, endpoint, or dashboard slug unless the placeholder is explicitly a UUID. List endpoints return JSON; record lists use limit/offset pagination with a default of 25 and maximum of 100. Account-wide app creation, dashboards, and key management require a platform token or web session; an app key can use the routes bound to its own app and permitted scopes.

Apps and endpoints

GET, POST/api/apps/List or create apps
GET, PATCH, DELETE/api/apps/{app}/Read, update, or delete an app
GET, POST/api/apps/{app}/endpoints/List or create endpoints
GET, PATCH, DELETE/api/apps/{app}/endpoints/{endpoint}/Manage one endpoint

Collection data

GET, POST/api/apps/{app}/endpoints/{endpoint}/fields/List or add schema fields
PATCH, DELETE/api/apps/{app}/endpoints/{endpoint}/fields/{uuid}/Update or remove a field
GET, POST/api/apps/{app}/endpoints/{endpoint}/records/List or create records
POST/api/apps/{app}/endpoints/{endpoint}/records/batch/Atomically create up to 100 records
GET, PATCH, DELETE/api/apps/{app}/endpoints/{endpoint}/records/{uuid}/Manage one record

Endpoint configuration

GET, PUT/api/apps/{app}/endpoints/{endpoint}/payload/Read or replace a static payload
GET, PUT/api/apps/{app}/endpoints/{endpoint}/proxy/Read or replace proxy configuration
GET, POST, DELETE/api/apps/{app}/endpoints/{endpoint}/encryption/Inspect, enable, or disable encryption
GET/api/apps/{app}/endpoints/{endpoint}/logs/Read the latest 50 request logs
GET, POST/api/apps/{app}/endpoints/{endpoint}/webhooks/List or create webhooks
GET, PATCH, DELETE/api/apps/{app}/endpoints/{endpoint}/webhooks/{uuid}/Manage one webhook
GET, POST/api/apps/{app}/keys/List or create app-associated keys
DELETE/api/apps/{app}/keys/{uuid}/Revoke an app-associated key

Control panels

GET, POST/api/dashboards/List or create control panels
GET, PATCH, DELETE/api/dashboards/{dashboard}/Manage a control panel
GET/api/dashboards/{dashboard}/widgets/List widgets
POST/api/dashboards/{dashboard}/widgets/{app}/{endpoint}/Create a widget with a slug-based binding
PATCH, DELETE/api/dashboards/{dashboard}/widgets/{uuid}/Update or remove a widget
GET/api/dashboards/{dashboard}/state/Read configured widget values
PATCH/api/dashboards/{dashboard}/widgets/{uuid}/value/Write through an interactive widget

Capacity and credentials

GET/api/billing/plans/Read public pricing, features, limits, and retention
GET/api/limits/Read enforced plan limits and remaining capacity
GET/api/auth/context/Inspect the non-secret credential context

Check pricing and capacity before provisioning

GET /api/billing/plans/ is public and returns the Free and Pro prices, features, limits, and record retention policies. Price amounts use integer minor units inamount_cents. A platform token can call GET /api/limits/. The response names the current plan, every enforced limit, and remaining global app and dashboard capacity. App, endpoint, and dashboard detail responses also include scoped capacity. Successful creation responses include X-Meow-Quota-* headers. The X-Meow-Quota-Policy header distinguishes hard limits from rolling record history.
LimitFreePro
Apps350
Endpoints per app325
Records retained per endpointLatest 1,000Latest 10,000
Fields per endpoint1050
Dashboards315
Widgets per dashboard1250
Webhooks per endpoint320
App API keys220
Maximum record payload64 KB512 KB
Maximum static payload256 KB1 MB

Collection history rolls automatically on both plans: the oldest record is removed when a new record arrives beyond the retained count. Automated retention pruning does not emit arecord.deleted webhook. Endpoint TTL can remove records sooner. View pricing or upgrade to Pro.

Atomic batch ingestion

Send one to 100 records in a request. The API applies transforms, size limits and schema validation to the whole batch before writing. If one item fails, none are created and the error identifies its array index. After a successful write, any records beyond the rolling history window are pruned oldest-first. The HTTP request must remain under 1 MB.
terminal
curl -X POST "$MEOW_API/apps/weather-station/endpoints/readings/records/batch/" \
  -H "Authorization: Bearer $MEOW_APP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"records":[
    {"data":{"temperature":21.8}},
    {"data":{"temperature":21.9}}
  ]}'

Static payload envelope and nested key paths

The HTTP management endpoint reads and writes an envelope withdata and read-only updated_at. Dashboard bindings use dot notation. Missing objects are created for static writes, but a non-object intermediate value is rejected.
json
{
  "data": {
    "camera": {
      "thresholds": {"confidence": 0.65}
    }
  },
  "updated_at": "2026-07-25T10:00:00Z"
}

Schema changes after data exists

Labels, required state, defaults, help text, options, and ordering remain editable. A field's machine name and type become immutable after the endpoint has records. Create a replacement field and migrate deliberately instead of changing how stored values are interpreted.

Encryption and errors

Encrypted consumer responses

Without a decryption header, an encrypted endpoint returns a Fernet envelope containing encrypted, algorithm, fingerprint, and data. Send the one-time key as X-Encryption-Key to request a plaintext response. A wrong key returns 403.
400

Invalid input

401

Bad or missing auth

403

Not permitted

404

Resource not found

429

Rate limited

Writes are strict

Unknown top-level fields return 400 and are never discarded. Errors include a stable code, message, details, and request ID. Quota errors also include the resource, plan, limit, usage, remaining capacity, and a remediation hint. API routing and proxy errors under /api/* are JSON.

03 · Python SDK & CLI

Python SDK and CLI

meow-sdk wraps the REST API and installs the meow CLI. It supports Python 3.8 and newer and uses the same resource names as the web app.

Recommended credential: platform token

The SDK and CLI can discover and manage multiple apps, so configure them with a platform token from Account → Platform Tokens. Use an app API key instead only when a client must be confined to one app.

Installation details, complete examples, releases, and package metadata.

Read the meow-sdk docs on PyPI ↗

Install and configure

terminal
pip install meow-sdk


export MEOW_PLATFORM_API_KEY="YOUR_PLATFORM_TOKEN"
export MEOW_APP_API_KEY="YOUR_APP_API_KEY"
export MEOW_USERNAME="YOUR_USERNAME"
# Optional for a self-hosted or local backend:
export MEOW_URL="https://meowmeowscratch.com"
python
import os
from meow_sdk import Meow


api = Meow(
    base_url=os.getenv("MEOW_URL", "https://meowmeowscratch.com"),
    username=os.getenv("MEOW_USERNAME"),
    api_key=os.environ["MEOW_PLATFORM_API_KEY"],
    timeout=30,
)


# Check enforced capacity before provisioning a schema or dashboard.
print(api.limits())

Collection workflow

This reference example explicitly publishes harmless sample data so the following anonymous-read example works. Omitis_public=True to keep both resources private.
weather_station.py
from meow_sdk import Meow
import os


api = Meow(api_key=os.environ["MEOW_PLATFORM_API_KEY"])


api.create_app("Weather Station", "weather-station", is_public=True)
api.create_endpoint(
    "weather-station",
    "Readings",
    "readings",
    endpoint_type="collection",
    is_public=True,
)
api.create_field(
    "weather-station",
    "readings",
    "temperature",
    "Temperature",
    "number",
    required=True,
    options={"min": -50, "max": 80, "step": 0.1},
)


created = api.send(
    "weather-station",
    "readings",
    {"temperature": 22.5},
)
api.send_many(
    "weather-station",
    "readings",
    [{"temperature": 22.6}, {"temperature": 22.7}],
)


page = api.records("weather-station", "readings", limit=25)
api.update(
    "weather-station",
    "readings",
    created["uuid"],
    {"temperature": 23.0},
)
print(page["results"])

Static settings and a remote control

The SDK returns the bare static document, so an empty endpoint is simply {}. Use get_payload_state() when the update timestamp matters. A widget binding names the app and endpoint once; later value changes target only the widget UUID.
device_settings.py
api.create_endpoint(
    "weather-station", "Device Settings", "settings", endpoint_type="static"
)
api.set_payload("weather-station", "settings", {
    "camera": {"thresholds": {"confidence": 0.65}}
})
settings = api.get_payload("weather-station", "settings")


api.create_dashboard("Camera Controls", "camera-controls")
widget = api.create_dashboard_widget(
    "camera-controls",
    "weather-station",
    "settings",
    "camera.thresholds.confidence",
    "slider",
    "Tracking confidence",
    config={"min": 0, "max": 1, "step": 0.05},
)
api.set_dashboard_widget_value("camera-controls", widget["uuid"], 0.7)

Public reads do not need a token

Public reads use the owner username to build the consumer URL. Keep an API key on the client only if the same process also writes, manages resources, or reads a private endpoint.
python
from meow_sdk import Meow


public = Meow(username="YOUR_USERNAME")


readings = public.get(
    "weather-station",
    "readings",
    temperature__gte=20,
    limit=25,
)
stats = public.aggregate(
    "weather-station",
    "readings",
    ["avg", "max"],
    field="temperature",
)
csv_text = public.export_csv("weather-station", "readings")

Client method reference

These method names match the published client. Ellipses omit arguments shown in the examples above.

Public reads

  • get(app, endpoint, **filters)
  • get_record(app, endpoint, record_id)
  • aggregate(app, endpoint, aggregates, field=None)
  • export_csv(app, endpoint, **filters)
  • public_dashboard(share_token)

Apps and endpoints

  • apps() / get_app(slug)
  • create_app(...) / update_app(...) / delete_app(...)
  • endpoints(app) / get_endpoint(app, endpoint)
  • create_endpoint(...) / update_endpoint(...) / delete_endpoint(...)

Collection data

  • records(app, endpoint, limit=25, offset=0)
  • all_records(app, endpoint)
  • send(app, endpoint, data)
  • send_many(app, endpoint, records)
  • update(app, endpoint, record_id, data)
  • delete_record(app, endpoint, record_id)
  • fields(...) / create_field(...) / update_field(...) / delete_field(...)
  • field_types()

Payloads and integrations

  • get_payload(...) / get_payload_state(...) / set_payload(...)
  • get_proxy(...) / set_proxy(...)
  • webhooks(...) / get_webhook(...)
  • create_webhook(...) / update_webhook(...) / delete_webhook(...)
  • get_encryption(...) / enable_encryption(...) / disable_encryption(...)
  • request_logs(app, endpoint)

Control panels

  • dashboards() / get_dashboard(slug)
  • create_dashboard(...) / update_dashboard(...) / delete_dashboard(...)
  • dashboard_widgets(dashboard)
  • create_dashboard_widget(...) / update_dashboard_widget(...) / delete_dashboard_widget(...)
  • dashboard_state(dashboard)
  • set_dashboard_widget_value(dashboard, widget_uuid, value)

Keys and capacity

  • app_keys(app) / create_app_key(app) / delete_app_key(app, uuid)
  • platform_tokens() / create_platform_token(name) / revoke_platform_token(uuid)
  • limits() / auth_context()

Limits are token-safe; billing is session-only

API credentials cannot access authentication, account, or billing subscription endpoints. Use limits() for provisioning and manage checkout or the customer portal in the web app. billing_status() is deprecated.

Exceptions

All SDK exceptions inherit from MeowError and include the HTTP status and response when available. Structured failures also expose code, field, hint, and details without string matching.
python
from meow_sdk.exceptions import (
    AuthError,
    MeowError,
    NotFoundError,
    RateLimitError,
    ValidationError,
)


try:
    api.send("weather-station", "readings", {"temperature": "hot"})
except ValidationError as exc:  # HTTP 400
    print(exc.code, exc.field, exc.hint)
except AuthError:               # HTTP 401 or 403
    print("Check the token and resource access")
except NotFoundError:           # HTTP 404
    print("Check the app and endpoint slugs")
except RateLimitError:          # HTTP 429
    print("Retry with backoff")
except MeowError as exc:
    print(f"Request failed: {exc}")

CLI quick reference

Management commands read MEOW_PLATFORM_API_KEY. Data-plane commands read MEOW_APP_API_KEY. The CLI also reads MEOW_USERNAME and optional MEOW_URL. Commands return JSON.
terminal
meow apps
meow endpoints weather-station
meow fields weather-station readings
meow limits
meow send weather-station readings temperature=22.5
meow send-batch weather-station readings @records.json
meow records weather-station readings --limit 25
meow get weather-station readings temperature__gte=20
meow payload-get weather-station status
meow payload-get weather-station status --metadata
meow logs weather-station readings
meow webhooks weather-station readings
meow dashboards
meow widget-create camera-controls weather-station settings \
  camera.thresholds.confidence slider "Tracking confidence" \
  --config '{"min":0,"max":1,"step":0.05}'
meow widget-set camera-controls WIDGET_UUID 0.7
meow --help

Package documentation

The PyPI project page includes installation, quickstarts, Raspberry Pi examples, CLI usage, error handling, and the method map.

View meow-sdk on PyPI ↗

04 · MCP server

Connect an AI agent with MCP

The MCP server exposes your resources as schema-defined tools for compatible agents, including Codex and Claude Code.

Transport

Streamable HTTP · stateless

Remote endpoint

https://meowmeowscratch.com/mcp/

Authentication

Open Account → Platform tokens, create a token, and store the value. Export it in the shell that launches the MCP client. MCP needs account-wide discovery, so use a platform token rather than an app API key.
terminal
export MEOW_PLATFORM_API_KEY="YOUR_PLATFORM_TOKEN"

Install Meow Agent Tools

The official Agent Tools repository packages the shareduse-meow skill and the hosted MCP connection for Codex and Claude Code. The skill teaches the agent how to choose between the web app, REST API, SDK, CLI, and MCP; design endpoints; work safely with credentials; and build Raspberry Pi or IoT projects.

meowmeowscratch/meow-agent-tools

One shared skill with native plugin and MCP packaging for both supported agent clients. Review the source and release notes before installing updates.

View Agent Tools on GitHub ↗

Codex

terminal
codex plugin marketplace add meowmeowscratch/meow-agent-tools
codex plugin add meow-meow-scratch@meow-agent-tools

Start a new Codex thread after installation. Ask for a Meow Meow Scratch® task naturally, or inspect /mcp if the tools are not available.

Claude Code

terminal
claude plugin marketplace add meowmeowscratch/meow-agent-tools
claude plugin install meow-meow-scratch@meow-agent-tools

Start a new session or run /reload-plugins. Claude Code can select the skill automatically, or you can invoke/meow-meow-scratch:use-meow directly.

The plugin does not contain your token

Both packages read MEOW_PLATFORM_API_KEY from the environment of the process that launches the agent. Keep the token out of repositories, project configuration, prompts, and logs. Agent Tools supports Codex and Claude Code; it is not a Claude.ai or Claude Desktop connector.

Configure Codex manually

Use this setup when you want the MCP tools without installing the Agent Tools skill. Codex CLI and the Codex IDE extension share MCP configuration on the same host. This command stores the environment-variable name rather than the token.
terminal
codex mcp add meow \
  --url https://meowmeowscratch.com/mcp/ \
  --bearer-token-env-var MEOW_PLATFORM_API_KEY


codex mcp list

The equivalent user configuration is:

~/.codex/config.toml
[mcp_servers.meow]
url = "https://meowmeowscratch.com/mcp/"
bearer_token_env_var = "MEOW_PLATFORM_API_KEY"

Restart Codex or the IDE extension after editing the file. Run/mcp to verify the connection. For a project-specific setup, put the same table in .codex/config.toml; Codex loads it only for trusted projects. See the official Codex MCP guide ↗.

Configure Claude Code manually

Use this setup when you want the MCP tools without installing the Agent Tools skill. Put the server in the project's .mcp.json. Claude Code expands MEOW_PLATFORM_API_KEY from the local environment, so the configuration can be committed safely.
.mcp.json
{
  "mcpServers": {
    "meow": {
      "type": "http",
      "url": "https://meowmeowscratch.com/mcp/",
      "headers": {
        "Authorization": "Bearer ${MEOW_PLATFORM_API_KEY}"
      }
    }
  }
}
terminal
export MEOW_PLATFORM_API_KEY="YOUR_PLATFORM_TOKEN"
claude mcp list
claude

The type field is required and may behttp or streamable-http. Approve the server when Claude Code first opens the project, then run /mcp to verify the connection. See the official Claude Code MCP guide ↗.

Claude web and Desktop connectors

The MCP server uses a Bearer header. Claude's account-level connector flow documents OAuth but not fixed custom headers, so use Claude Code for this integration. Do not include the token in the URL.

Connection checks

Missing authentication returns 401. Keep the trailing slash on/mcp/ to avoid a redirect. If tools are unavailable, verify MEOW_PLATFORM_API_KEY, restart the client, and inspect /mcp. Once tools load, call connection_status to confirm that the MCP Authorization header contains a platform token and to inspect its scopes without exposing the token.

Available tool families

Agents should discover before acting: list apps and endpoints, inspect schemas and capacity, then use returned slugs. Widget creation binds by app and endpoint slug; value updates use the widget UUID and do not repeat an endpoint identifier or key path.

Structure

Discover, create, update, and delete apps and endpoints.

Collections

Define fields and create, batch, update, or delete validated records.

Endpoint behavior

Configure static payloads, proxies, encryption, webhooks, and inspect request logs.

Control panels

Create slug-bound widgets, read only configured state, and write through widget UUIDs.

Consumer reads

Read public endpoints and records, aggregate values, export CSV, and open shared dashboards.

Discovery

Check the connection, enforced limits, field types, and resources before making changes.

Recommended tool workflow

  1. 01Call connection_status, then get_limits before provisioning.
  2. 02List apps and endpoints before making changes.
  3. 03Inspect the endpoint and field schema before writing data.
  4. 04Require confirmation before destructive operations.
  5. 05Call the narrowest applicable tool and read the resource back to verify the result.
  6. 06Return the consumer URL and relevant resource identifiers.

Limits and safety

60 tool calls per minute

The MCP service allows 60 tool calls per token each minute. Avoid polling unchanged resources.

Destructive calls need an approval policy

MCP does not enforce a server-side human approval gate. Require client approval for deletes, key revocation, encryption changes, and other sensitive writes.

Account routes stay out of scope

API credentials cannot access authentication, profile, or billing subscription routes. The dedicated get_limits tool is safe for platform-token provisioning; manage checkout and the billing portal in the web app. Do not expose tokens in prompts, repositories, browser bundles, or logs.

05 · MicroPython SDK

Send data from ESP32 and Pico W boards

meow-micropython is a small client with no external Python dependencies. It talks HTTPS directly over usocket/ussl. The package includes the client and the CA certificate used to verify the production API. Manage apps, schemas, dashboards, and account limits from the web app, CLI, MCP, or full Python SDK.

Full install options, board wiring examples, and the complete method reference.

View meow-micropython on GitHub ↗

Install on a board

terminal · MicroPython 1.24+
mpremote mip install github:meowmeowscratch/meow-micropython

Or install with mip once the board is connected to Wi-Fi:

python · on-device
import mip
mip.install("github:meowmeowscratch/meow-micropython")

Connect securely

Connect to Wi-Fi and set the board clock before the first HTTPS call. Correct time is required for certificate validation.
python · MicroPython
import network
import ntptime
import time


wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("YOUR_WIFI", "YOUR_PASSWORD")
while not wlan.isconnected():
    time.sleep_ms(250)
ntptime.settime()

Send sensor data

python · MicroPython
from meow import Meow


api = Meow(api_key="YOUR_APP_API_KEY")
api.send("weather-station", "readings", {
    "temperature": 22.5,
    "humidity": 65,
})

Use an app-scoped device key

Create a read/write API key inside the app used by this board. Never copy an account-wide platform token onto a device.

Drive hardware from dashboard state

Bind a dashboard toggle to a private static endpoint. The board reads that endpoint by app and endpoint slug—no UUIDs are needed.
python · MicroPython
from machine import Pin
from meow import Meow


api = Meow(api_key="YOUR_APP_API_KEY")
led = Pin("LED", Pin.OUT)


data = api.get_payload("my-pi", "controls")
led.value(1 if data.get("lights_on") else 0)

Desktop testing before flashing

pip install meow-micropython gives the same from meow import Meow import for testing on a computer before flashing to a board. It has no effect on-device — MicroPython's mip never talks to PyPI, so a board still needs one of the install methods above.

What's included

Reading & writing data

send, send_many, update, delete_record, get, get_record, aggregate, records, all_records

Device state & diagnostics

get_payload, get_payload_state, set_payload, public_dashboard, auth_context

Same errors as the Python SDK

MeowError and its subclasses (AuthError, NotFoundError, ValidationError, RateLimitError) carry the same status_code, code, field, and hint attributes.

06 · Open source

Example projects

These projects demonstrate API concepts, Raspberry Pi hardware, IoT data collection, and control panels using the Python SDK.

GitHub

meowmeowscratch

SDK source, Raspberry Pi projects, classroom examples, issues, and releases.

View all projects ↗

Open-source projects

56 repositories
pi-neuromorphic-cameraAn open-source project from Meow Meow Scratch®.Pythonmeow-agent-toolsCodex and Claude Code agent tools, skills, plugins and MCP integration for Meow Meow Scratch.Pythonpi-meowagotchi-controlsAn ESP32-S3 round touchscreen remote for meowagotchi. Six radial buttons queue care actions in a Meow Meow Scratch collection; the Pi owns the pet and applies them.Pythonpi-meowagotchi A virtual cat that lives on a Waveshare e-Paper HAT. It paces, sleeps, gets hungry, makes a mess, and dies if you ignore it — a Raspberry Pi systemd service with an SSH-friendly CLI.Pythonmeow-micropythonMicroPython SDK for building APIs, dashboards and IoT projects with Meow Meow Scratch on ESP32 and Raspberry Pi Pico W boards.Pythonpi-ir-remoteTurn your TV on from anywhere. Reads your remote's infrared codes, then replays them from a web dashboard on your phone. Decodes the NEC protocol from scratch.Pythonpi-lcd-screenSee your data on a cheap 128x64 LCD. Point it at any endpoint for a live heads-up display — and learn bit-banging, driving a screen with no I2C or SPI hardware.Pythonpi-servo-gaugePut your data on a real needle and dial. A physical instrument for any endpoint, plus how to power a servo without killing your Pi.Pythonpi-rgb-notifierA status light for any project. Green, amber, red at a glance — and a separate colour for "I don't know".Pythonpi-gps-trackerLog where you have been. GPS position, trip distance, and why haversine beats Pythagoras on a curved Earth.Pythonpi-smart-scaleA kitchen scale that logs what it weighs. Talks to the HX711 directly, so you can see how the protocol actually works.Pythonpi-energy-clampMeasure household electricity without touching a wire. Clip-on current sensing, with the safety guidance it deserves.Pythonpi-power-monitorFind out what a device really costs to run. Volts, amps and watts made concrete with an INA219 sensor.Pythonpi-qr-scannerScan QR codes and barcodes with a Pi camera. The gentlest possible introduction to computer vision.Pythonpi-timelapseWatch a plant grow or a sunset happen in ten seconds. Includes the arithmetic that stops you shooting for three days for nothing.Pythonpi-security-camTake a photo whenever something moves. Your images stay on your Pi; only the alert goes to the cloud.Pythonpi-slider-mixerPhysical faders that set values in the cloud. A mixing desk for your projects, with settings you can read across the room.Pythonpi-fingerprint-lockRecognise people by fingerprint. Learn why the sensor never actually stores your fingerprint, only a template.Pythonpi-touch-keypadA 12-key touch pad with no moving parts. Works through paper, foil or drawing pins — and explains why gloves do not.Pythonpi-rfid-attendanceTap a card to sign in. A classroom register or workshop board — and an honest look at what RFID cannot secure.Pythonpi-gesture-controlWave your hand to control things. Four infrared detectors, and the order they see your hand is the gesture.Pythonpi-knob-controllerA physical dial that sets a value in the cloud. Learn quadrature encoding — how two switches reveal which way you turned.Pythonpi-earthquake-detectorMeasure how hard the ground shakes. Learns your building's normal background, then reports anything unusual.Pythonpi-step-counterBuild your own pedometer. Smoothing, thresholds and refractory periods — the three techniques inside every fitness tracker.Pythonpi-tilt-alarmGuard something by watching its angle. Uses gravity as a permanent reference to detect tilting or tampering.Pythonpi-joystickRead a game controller thumbstick with a Pi. Teaches dead zones — the trick that stops your robot drifting across the room.Pythonpi-flex-sensorMeasure how far something bends, as a clean 0-100%. Calibrates itself at startup instead of asking you for numbers.Pythonpi-chair-sensorKnow when someone is sitting down. A force sensor under a cushion, with a calibration mode to find your own thresholds.Pythonpi-battery-monitorWatch a battery drain in real time. Teaches the voltage divider — the circuit standing between you and a fried ADC.Pythonpi-noise-monitorChart how loud your room gets across the day. Settle the argument about the street outside, and learn what decibels really are.Pythonpi-vibration-loggerGet told when the washing machine finishes. Turns a messy vibration signal into a reliable start and stop.Pythonpi-temp-probeWaterproof temperature probes for ponds, aquariums and brewing. Add ten sensors without adding a single wire.Pythonpi-rain-gaugeMeasure real rainfall in millimetres with a tipping-bucket gauge, the mechanism weather stations have used for a century.Pythonpi-presence-radarDetect someone sitting perfectly still — the thing a motion sensor famously cannot do. mmWave radar presence detection.Pythonpi-people-counterCount people in and out of a room. Two light beams, and the order they break tells you which way someone walked.Pythonpi-water-tankKnow how full your rainwater tank is without climbing up. Turns an ultrasonic reading into depth, litres and percentage.Pythonpi-parking-sensorThe thing that beeps in your car. Ultrasonic distance sensing that beeps faster as you get closer.Pythonpi-compassA working compass from a magnetometer. Learn why every compass needs calibrating, and what hard-iron distortion means.Pythonpi-oled-statsPut your data on a tiny screen. Displays live values from any of your endpoints on a 128x64 OLED.Pythonpi-laser-tapeA digital tape measure. Fires an invisible laser and times the bounce — millimetre accuracy up to four metres.Pythonpi-colour-sensorHold something up and your Pi names its colour. Sort Lego or read coloured cards with a VEML6040 sensor.Pythonpi-light-meterFind the sunniest windowsill. Measures room brightness in lux and charts how daylight moves through your day.Pythonpi-precision-tempCatch the fridge door left open. Tenth-of-a-degree accuracy with a TMP117, and alerts that ignore someone grabbing the milk.Pythonpi-co2-monitorKnow when to open a window. Measures real CO2 with an SCD-30 laser sensor — the reason meeting rooms make you drowsy.Pythonpi-atmosphericA weather station that predicts rather than just reports. Reads pressure trends with a BME280 to tell you what's coming.Pythonpi-air-qualitySee what's actually in the air you're breathing. Reads VOCs and estimated CO2 with an ENS160 sensor and charts your room's air quality over the day.Pythonpi-doorbellPress a button, hear a chime, and see every ring logged to your own cloud dashboard. The simplest Raspberry Pi starter kit — no soldering, no breadboard.Pythonpi-xmas-lightsPhone-controlled Raspberry Pi Christmas light show with eight NeoPixel animations.Pythonpi-weather-stationRaspberry Pi weather station that publishes DHT22 temperature and humidity readings online.Pythonpi-thermal-cameraRaspberry Pi thermal camera with an AMG8833 sensor, LED heat map and cloud streaming.Pythonpi-reaction-timerRaspberry Pi reaction-time game with an LED, button and online leaderboard.Pythonpi-plant-monitorRaspberry Pi soil moisture and light monitor using an MCP3008 ADC and cloud dashboard.Pythonpi-motion-loggerRaspberry Pi PIR motion detector that records timestamped movement events online.Pythonpi-door-monitorRaspberry Pi door sensor that publishes live open and closed status using a magnetic reed switch.Pythonpi-led-dashboardControl a Raspberry Pi NeoPixel LED strip remotely through an online colour dashboard.Pythonmeow-sdkPython SDK and CLI for building APIs, dashboards and IoT projects with Meow Meow Scratch.Python

Ship safely

Production checklist

Verify credentials, visibility, retries, and agent approval policy before exposing an endpoint to production traffic.
  • Keep platform tokens and app API keys in a secret manager or environment variable and rotate them after suspected exposure.
  • Prefer an app API key with the minimum Read and Write scopes for each device or single-app integration.
  • Use public visibility only for data that is genuinely safe for anonymous internet access.
  • Preserve trailing slashes on REST and MCP URLs to avoid redirects during writes and protocol negotiation.
  • Apply timeouts and exponential backoff for 429 and transient 5xx responses; do not retry validation failures.
  • Store API and encryption keys when they are created; full values are shown once.
  • Treat shared control-panel links as bearer secrets and expire or disable sharing when it is no longer needed.
  • Verify proxy targets and transformations with non-sensitive data before enabling a public integration.
  • Require explicit human confirmation before an agent deletes apps, endpoints, records, keys, or dashboards.