Local API and MCP

Giggle Pig Pro can be controlled by other programs on your PC: a Stream Deck plugin, a chat bot, your own script, or an AI assistant through MCP. Everything stays on your computer.

Turn it on

In Giggle Pig, open Settings → Local API & AI assistants and switch on Local API. It listens on ws://127.0.0.1:17572 (you can change the port there). It is off until you turn it on, only accepts connections from this PC, and turns itself off if your plan no longer includes it.

Pairing and scopes

The first time an app connects it asks to pair, with a name and the scopes it wants. Giggle Pig shows you the request; you can untick scopes or deny it. An approved app receives a client id and a random token; Giggle Pig only keeps a hash of the token. Remove an app in Settings at any time, and it is cut off immediately.

Web pages can't use the API: browsers always send an Origin header, and those connections are refused.

Messages

JSON text messages over one WebSocket connection:

→ {"type": "hello"}
← {"type": "hello", "api": 1, "app": "Giggle Pig", "actions": [...], "scopes": {...}}

→ {"type": "pair", "name": "My bot", "scopes": ["read", "clips"]}
← {"type": "pairing", "message": "Approve this app in Giggle Pig."}
← {"type": "paired", "client_id": "c_…", "token": "…", "scopes": ["clips", "read"]}

→ {"type": "auth", "client_id": "c_…", "token": "…"}
← {"type": "authed", "client_id": "c_…", "name": "My bot", "scopes": ["clips", "read"]}

→ {"type": "request", "id": "1", "action": "play_clip", "args": {"clip_id": "air-horn"}, "idempotency_key": "k-17"}
← {"type": "response", "id": "1", "ok": true, "result": {...}}
← {"type": "response", "id": "2", "ok": false, "error": {"code": "forbidden", "message": "…"}}

→ {"type": "subscribe", "events": ["state"]}
← {"type": "event", "event": "state", "data": {"active_voice": "robot", "muted": false, ...}}

Every request carries an id, echoed in its response. A mutating request may carry an idempotency_key: repeating it within 120 seconds returns the first result instead of acting twice.

Actions

ActionScopeArgumentsWhat it does
get_statusreadnoneReport the actual current state: active and previous voice, mute, normal-voice bypass, any pending voice switch, routing and conversion worker health.
list_clipsreadnoneList your sound clips (songs, effects) with ids, names and aliases.
list_voicesreadnoneList the installed, usable voice presets with their ids, names and spoken aliases.
restore_previous_voicevoicenoneSwitch back to the previous successfully active voice preset.
set_bypassvoiceenabled (boolean)true: send your normal voice to the game. false: return to the selected converted voice.
set_mutedvoicemuted (boolean)Mute (true) or unmute (false) the voice sent to the game. Voice commands keep working while muted.
set_voicevoicevoice_id (string)Activate an installed voice preset by its id (from list_voices) and leave normal-voice bypass. Returns the verified resulting state; status 'pending' means the voice is still loading and get_status must be checked before announcing success.
play_clipclipsclip_id (string)Play a sound clip by its id (from list_clips) into the game voice chat. Replaces any clip already playing. Requested names are often inexact; pick the clip that clearly matches.
stop_clipclipsnoneStop the sound clip that is currently playing.
save_replayreplaynoneSave the last seconds of what teammates heard (instant replay must be on; Pro). Also saves OBS's video replay when that is set up. Returns the saved length in seconds.
obs_save_replayobsnoneSave OBS Studio's video replay buffer. Succeeds only when OBS confirms the file was saved.
obs_set_sceneobsscene (string)Switch OBS Studio's program scene to an existing scene by its exact name (OBS must be connected in Giggle Pig; Pro).

The API never exposes audio, files, your account, purchases, training or deletion.

Errors and limits

Error codes are stable: unauthorized, forbidden, unknown_action, missing_parameter, unexpected_parameter, invalid_type, invalid_value, rate_limited, busy, unavailable, plus action results such as unknown_clip, obs_not_connected or plan_required.

Limits: 8 connections, 64 KB per message, 20 requests per second per connection.

Example (Python)

import json
from websockets.sync.client import connect

with connect("ws://127.0.0.1:17572") as ws:
    ws.send(json.dumps({"type": "pair", "name": "My script", "scopes": ["read", "voice"]}))
    while (reply := json.loads(ws.recv()))["type"] == "pairing":
        pass                     # approve it in Giggle Pig
    creds = reply                # keep client_id and token somewhere safe
    ws.send(json.dumps({"type": "auth", "client_id": creds["client_id"], "token": creds["token"]}))
    ws.recv()
    ws.send(json.dumps({"type": "request", "id": "1", "action": "set_voice", "args": {"voice_id": "robot"}}))
    print(ws.recv())

AI assistants (MCP)

Giggle Pig includes an MCP server that AI assistants such as Claude Desktop and Claude Code can start. In Settings → Local API & AI assistants, click Set up for AI assistants: Giggle Pig pairs its MCP bridge with the scopes you choose and can add it to Claude Desktop for you (your other settings are kept, with a backup). For Claude Code it shows the claude mcp add command; for other clients, the JSON to paste.

The bridge is just another paired app: it can only do what its scopes allow, only while Giggle Pig is running with the local API on, and the assistant can't give itself more. Clip and voice names it reads back are your data, not instructions.

Try: “switch my voice to Robot”, “play the air horn”, “save a replay”, or “switch OBS to the BRB scene”.