# PO派 MCP — ops skill (token-efficient)

Use when the user wants you to run Instagram / Threads / LINE ops via PO派,
or to design & maintain their automation workflows by conversation.

**MCP:** `https://popai.bot/mcp`  
**Auth:** `Authorization: Bearer popai_sk_…` (ask user; never invent; never echo full key later)  
**Params:** trust `tools/list` schemas — do not re-list tools here.

## Setup (once)

1. Ask for `popai_sk_…` from PO派 → Integrations.
2. Connect MCP to `https://popai.bot/mcp` with that Bearer token.
3. Call `list_accounts` once. If a platform says 未連結, stop and tell user to OAuth under Account.

## Hard limits

- One IG (or Threads) account ↔ one PO派 user.
- Cold DMs to strangers: **not supported**. `send_dm` needs a recipient id from prior interaction / tools.
- `list_dm_threads` only covers people who already messaged (local inbox mirror).
- `list_mentions` has no pre-feature history.
- No MCP tools for: review queue UI, broadcasts, patrol/海巡, LINE rich-menu editing, IG/Threads posting on LINE. If asked, say so — don't invent tools.
- Workflow tools cover ig / threads / line. The posting & engagement tools above are ig / threads only.
- Write tools need write scope. 401 → bad/revoked key. Empty lists → reconnect IG/Threads or wrong platform.
- Publish / bulk DMs: confirm with user first. Some AI content may land in human review — if a tool says 待審, tell user to check console review.

## Token rules

- `list_accounts` at most once per session (unless user reconnects).
- Prefer small limits; never re-list after you already have `media_id` / `comment_id` / recipient id.
- Workflows have their own budget rules — see **Workflow token budget** below. Read them before the first `get_workflow_node_types` call.
- Read → write. One write per confirmed intent; no speculative publish.
- Batch replies: sequential tool calls; don't parallel-spam Meta.
- Short user messages; don't paste this skill back.

## Playbooks (shortest path)

**A. Morning / shift scan**  
`list_accounts` → `list_ig_media` (recent) → for top posts: `list_comments` → `list_dm_threads` → optional `list_mentions` → report counts + draft actions; wait for user green light before writes.

**B. Reply IG comment**  
Have media_id? else `list_ig_media`. → `list_comments` → `reply_to_comment`. Optional `send_dm` only if recipient known and user wants private follow-up.

**C. Reply IG DM**  
`list_dm_threads` → `get_dm_thread` → `send_dm` with that recipient. No cold outreach.

**D. Publish now**  
Confirm platform + caption (+ image URLs if required by schema) → `publish_post` → report returned post id.

**E. Schedule**  
Confirm platform, caption, images, `scheduled_at` RFC3339 with timezone → `schedule_post`.

**F. Threads engagement**  
`list_threads_media` → `list_thread_replies` → `reply_to_thread` / `quote_thread` / `repost_thread` as requested.

## Workflows (自動化)

A workflow = one trigger + a graph of action/logic nodes, scoped to one platform
(`ig` / `threads` / `line`). Same objects the console's 自動化 canvas edits.

**Graph DSL** — you never write UUIDs or coordinates:

```json
nodes: [{"key":"t","type":"trigger.line_message","config":{"keywords":["價格"],"match_mode":"contains"}},
        {"key":"reply","type":"action.send_line_text","config":{"message":"單堂 $1200"}}]
edges: [{"from":"t","to":"reply"}]
```

- `key` = any short string for new nodes. **When editing, reuse the UUID keys
  `get_workflow` returned** — that preserves the node's stats and canvas position.
  A key you invent = a brand-new node; the old one is deleted.
- `source_handle` omitted = `default`. Branch nodes (quick replies, condition,
  A/B) expose one handle per option — use that option's `key`.
- Positions are auto-laid-out. Don't send them.
- `save_workflow_graph` **replaces the whole graph**. Send every node you want
  to keep, not a diff.

**Rules the server enforces** (it rejects the save, listing every problem at once):
one trigger per workflow · one outgoing edge per handle · node must support the
workflow's platform · required config fields filled · IG `action.publish_post`
needs an `action.generate_images` node · nodes whose trigger can't supply what
they need (e.g. `send_dm` under `trigger.cron`) are rejected.

**Workflow token budget** — measured response sizes, cheapest path first:

| Call | ≈tokens | Rule |
|---|---|---|
| `list_workflow_templates {platform}` | 0.5–1.0k | Cheapest thing here. Check it first. |
| `get_workflow_node_types {platform}` | 2.7–3.4k | **Always pass `platform`.** |
| `get_workflow_node_types` no filter | 5.6k | Never — you always know the platform. |
| `get_workflow_node_types {types:[…]}` | 0.4–1.0k **each** | Ask for every type you need in **one** call, and only those. |
| `list_workflow_templates` no filter | 2.3k | Wasteful — 3–4× the filtered call. |
| `get_workflow` | grows with the graph | Full configs of every node. |
| `get_workflow_runs` | grows fast (step traces) | Keep the default `limit`; raise only while diagnosing. |

- The index (2.7–3.4k) already carries `type`, `label`, `description`,
  `required_config_keys`, handles, `coming_soon`, and the `{{variable}}` list —
  enough to **choose** nodes and sketch the flow. Pull `types:[…]` only for the
  handful you will actually configure. All ~48 full schemas would be ~19k tokens;
  never go near that.
- Fetch each of these **once per session** and reuse from context. The catalog,
  templates and variables are static — re-fetching is pure waste.
- Cheapest route for a common ask is a template: filtered `list_workflow_templates`
  → `create_workflow {template_id}` → `get_workflow`, and skip the index and
  schemas entirely. Reach for hand-authoring only when no template fits.
- Author the whole graph in **one** `create_workflow` call. Create-then-save is
  two round-trips for the same result.
- A rejected save costs a full retry — so read the schema before writing config,
  and fix **every** listed issue in one resend. Two failed guesses cost more than
  one schema fetch.
- Don't echo graphs back to the user as JSON. Describe the flow in a line or two
  ("有人留言『價格』→ 公開回覆 → 私訊價目表"); they have the canvas for the rest.

**Order of operations**

1. `get_workflow_node_types {platform}` → pick node types from the index.
2. `get_workflow_node_types {types:[…]}` — one call listing every type you chose
   → **read the real `config_schema` before writing any config.** Do not guess
   field names or enum values.
3. `list_workflow_resources` only if the flow touches tags / custom fields /
   personas / LINE rich menus — configs reference their ids. Missing ones:
   `create_subscriber_tag` (color ∈ red/yellow/green/navy/sky/ink) or
   `create_subscriber_field`.
4. `create_workflow` — whole graph in one call, or `template_id` to copy a built-in.
5. `simulate_workflow` → dry run, no messages sent, no run log written.
6. Describe what it does in a sentence, get approval, then `update_workflow enabled:true`.

**Safety**: agent-created workflows always land **disabled**. Enabling puts live
automation in front of real subscribers — never enable without the user saying so
in this turn. Deleting is irreversible: confirm first.

## Workflow playbooks

**G. Design a new automation** (~5k tokens hand-authored, ~1k from a template)  
Ask platform + trigger + what it should send. → check templates first → else
index `{platform}` → schemas `{types:[…]}` in one call → resources only if needed
→ `create_workflow` → `simulate_workflow` → describe the flow → user approves →
enable. If validation fails, fix everything it listed and resend once.

**H. Edit an existing one**  
`list_workflows` → `get_workflow` (gives nodes + current `issues` + `version`) →
send back the **full** node list with the UUID keys kept, plus `version` for
optimistic locking. Version conflict = someone edited it; re-`get_workflow`,
merge, retry. You already have the node types from `get_workflow` — only fetch a
schema for a node type you're **adding**, not for ones you're editing in place.

**I. "My automation isn't working"**  
`get_workflow` → read `issues` (unfilled required fields are the usual cause) and
`enabled`. Then `get_workflow_runs` → failed/skipped runs carry the reason.
`pending_review_node_types` non-empty = blocked on Meta App Review, can't enable.

**J. Templates**  
`list_workflow_templates` → `create_workflow` with `template_id` → `get_workflow`
and fill the fields templates deliberately leave blank (e.g. IG `media_ids`).

## Fail map

| Result | You do |
|--------|--------|
| 401 / unauthorized | Ask for a new key from Integrations |
| 未連結 / empty media | User reconnects platform in Account |
| 權限不足 | New key with write access |
| 待審 / review | Point user to console review queue |
| Unknown id | Re-list; never invent ids |
| 工作流設定有誤 | Fix every listed issue in one retry; re-read the node's `config_schema` first |
| version 不是最新 | `get_workflow`, merge your edits onto it, save again |
| 尚待 Meta 平台審核 | That node type can't be enabled yet — swap it out or leave the workflow off |
