Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
{
"$schema": "https://json.schemastore.org/claude-code-marketplace.json",
"name": "pipefy",
"owner": {
"name": "Gabriel Custodio",
"url": "https://github.com/gbrlcustodio"
"url": "https://github.com/pipefy/ai-toolkit"
},
"plugins": [
{
"name": "pipefy",
"source": "./",
"description": "Pipefy workflow integration for Claude Code.",
"version": "0.2.0-beta.1"
"version": "0.2.0-beta.1",
"homepage": "https://github.com/pipefy/ai-toolkit",
"repository": "https://github.com/pipefy/ai-toolkit"
}
]
}
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ Releases are versioned in lockstep across workspace members (`pipefy-sdk`, `pipe

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

### Added

- **SDK / MCP / CLI**: `create_card` accepts optional `phase_id` and passes `title` on GraphQL `CreateCardInput` (mutation `createCard(input: $input)`). MCP: `phase_id` skips start-form elicitation; non-empty `fields` are validated against `get_phase_fields(phase_id)`; agent seeding should set `skip_elicitation=true`. CLI: `pipefy card create <pipe_id> --phase-id <id>` (optional `--title`).
- **MCP / CLI**: `get_phase_allowed_move_targets` lists valid destination phases for `move_card_to_phase` (GraphQL `phase.cards_can_be_moved_to_phases`). MCP returns normalized `{phase_id, phase_name, allowed_phases}`; CLI: `pipefy phase allowed-moves <phase_id>`.
- **SDK / MCP / CLI**: `get_phase_cards_count` reads native `Phase.cards_count` (MCP/CLI return `{phase_id, phase_name, cards_count}`; documents start-form count quirk). `get_phase_cards` lists cards in a phase via `Phase.cards` pagination (`first` default 50, `after`, optional fields). CLI: `pipefy phase cards-count <phase_id>`, `pipefy phase cards <phase_id> --first --after`.
- **SDK / MCP / CLI**: `get_pipe` adds `start_form_phase` (`id`, `name`, `cards_count`) and `cards_count` on each workflow phase in `phases[]` (start form excluded from `phases`; same JSON shape on MCP and `pipefy pipe get --json`).
- **SDK / MCP / CLI**: `create_pipe_report` and `update_pipe_report` preflight `filter` as nested `ReportCardsFilter` (`operator` + `queries`); reject naive top-level keys such as `current_phase` before GraphQL.

### Changed

- **Docs / install**: canonical GitHub repository is [`pipefy/ai-toolkit`](https://github.com/pipefy/ai-toolkit). Install snippets, `install.sh`, MCP setup links, Claude plugin metadata, and `.mcp.json` now point at `github.com/pipefy/ai-toolkit` (GitHub may still redirect older URLs).
- **MCP / CLI (6.0 label color)**: `create_label` and `update_label` validate `color` as hex `#RRGGBB` before GraphQL (e.g. `red` is rejected with `expected #RRGGBB, received 'red'`).

## [0.2.0-beta.2] - 2026-06-02

### Added
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License" /></a>
</p>

# pipefy-labs
# Pipefy AI Toolkit

Open-source toolkit for **Pipefy** developers: a Model Context Protocol (MCP) server for AI agents, a **`pipefy`** CLI for terminals and automation, a shared GraphQL SDK, and a catalog of agent skill playbooks.

Expand All @@ -36,7 +36,7 @@ Open-source toolkit for **Pipefy** developers: a Model Context Protocol (MCP) se

| Component | Package / path | Purpose |
|-----------|----------------|---------|
| **MCP server** | `pipefy-mcp-server` | Exposes **149** tools to MCP clients (Cursor, Claude Desktop, Claude Code, and others). |
| **MCP server** | `pipefy-mcp-server` | Exposes **152** tools to MCP clients (Cursor, Claude Desktop, Claude Code, and others). |
| **CLI** | `pipefy-cli` | Terminal commands aligned with MCP capabilities; see [`docs/parity.md`](docs/parity.md). |
| **SDK** | `pipefy-sdk` | Vendor GraphQL client, services, and models shared by MCP and CLI. |
| **Skills** | [`skills/`](skills/) | Markdown playbooks (Anthropic Skills format) for common Pipefy workflows. |
Expand Down Expand Up @@ -148,15 +148,15 @@ Deprecation and semver (post-1.0): [`docs/DEPRECATION.md`](docs/DEPRECATION.md).

## MCP server

The server registers **149 tools** across ten domains. Canonical names: `PIPEFY_TOOL_NAMES` in [`packages/mcp/src/pipefy_mcp/tools/registry.py`](packages/mcp/src/pipefy_mcp/tools/registry.py).
The server registers **152 tools** across ten domains. Canonical names: `PIPEFY_TOOL_NAMES` in [`packages/mcp/src/pipefy_mcp/tools/registry.py`](packages/mcp/src/pipefy_mcp/tools/registry.py).

Tool descriptions and `Args:` blocks come from Python docstrings (what MCP clients show to models). Per-area reference docs cover parameters, edge cases, and cross-cutting behavior.

**Shared conventions** (pagination, IDs, permissions, error shape): [`docs/mcp/tools/cross-cutting.md`](docs/mcp/tools/cross-cutting.md).

| Domain | Tools | Summary | Reference |
|--------|:-----:|---------|-----------|
| **Pipes & cards** | 37 | Pipes, phases, fields, labels, cards, field conditions, attachments. | [docs](docs/mcp/tools/pipes-and-cards.md) |
| **Pipes & cards** | 37 | Pipes, phases, fields, labels, cards, field conditions, attachments. Phase inventory (`get_phase_cards`, `get_phase_cards_count`), move discovery (`get_phase_allowed_move_targets`), and `create_card(phase_id=…)` reduce raw GraphQL for agent seeding. | [docs](docs/mcp/tools/pipes-and-cards.md) |
| **Database tables** | 17 | Tables, records, schema, table-record attachments. | [docs](docs/mcp/tools/database-tables.md) |
| **Relations** | 8 | Pipe and card relations. | [docs](docs/mcp/tools/relations.md) |
| **Reports** | 17 | Pipe and organization reports, async exports. | [docs](docs/mcp/tools/reports.md) |
Expand Down Expand Up @@ -189,6 +189,8 @@ The [`skills/`](skills/) directory holds workflow playbooks: prerequisites, tool

Full catalog: [`skills/README.md`](skills/README.md). Authoring: [`skills/AGENTS.md`](skills/AGENTS.md). Contributions: [`CONTRIBUTING.md`](CONTRIBUTING.md).

**Card & phase agent ergonomics:** use [`skills/pipes-and-cards/pipefy-pipes-and-cards/SKILL.md`](skills/pipes-and-cards/pipefy-pipes-and-cards/SKILL.md) (workflow *Seed pipe across phases*; prefer dedicated tools over `execute_graphql`). Manual smoke logs and replay payloads: [`.cursor/qa-tests-and-smoke/`](.cursor/qa-tests-and-smoke/).

---

## Documentation
Expand Down
4 changes: 2 additions & 2 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ After tagging a release, run the following on macOS and a Linux machine (or CI r

```bash
# Install CLI from the tagged release
uvx --from "git+https://github.com/<owner>/pipefy-labs[email protected]" --refresh pipefy-cli --version
uvx --from "git+https://github.com/pipefy/ai-toolkit[email protected]" --refresh pipefy-cli --version
# Expected: X.Y.Z

# Verify MCP server starts
uvx --from "git+https://github.com/<owner>/pipefy-labs[email protected]" --refresh pipefy-mcp-server --help
uvx --from "git+https://github.com/pipefy/ai-toolkit[email protected]" --refresh pipefy-mcp-server --help
# Expected: help text (server may block in stdio mode — Ctrl-C after banner)
```

Expand Down
16 changes: 10 additions & 6 deletions docs/MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Existing users of `pipefy-mcp-server`: this guide covers what changed and what t
**Pre-launch (v0.1 → v0.5):** install from git to get the latest:

```sh
uvx --from git+https://github.com/<owner>/pipefy-labs --refresh pipefy-mcp-server
uvx --from git+https://github.com/pipefy/ai-toolkit@latest --refresh pipefy-mcp-server
```

---
Expand Down Expand Up @@ -43,12 +43,16 @@ All MCP tools keep the same names, parameters, and behavior as in the pre-monore

## Repo URL

The repository was renamed from `pipefy-mcp-server` to `pipefy-labs` on GitHub. GitHub preserves redirects — your existing `git remote` URLs for the old repo keep working for `git fetch`, `git pull`, and `git push`.
The toolkit lives in the **Pipefy org** at **[github.com/pipefy/ai-toolkit](https://github.com/pipefy/ai-toolkit)**. Earlier community forks (`pipefy-mcp-server`, `pipefy-labs`) may still redirect on GitHub; update remotes and install URLs when you can.

Update your remote at your convenience:
```sh
git remote set-url origin https://github.com/pipefy/ai-toolkit.git
```

Pre-1.0 installs from git:

```sh
git remote set-url origin https://github.com/<owner>/pipefy-labs.git
uvx --from git+https://github.com/pipefy/ai-toolkit@latest --refresh pipefy-mcp-server
```

---
Expand All @@ -60,7 +64,7 @@ These are new additions — all optional to adopt:
**`pipefy-cli`** — a terminal CLI with the same capabilities as the MCP server.

```sh
uvx --from git+https://github.com/<owner>/pipefy-labs --refresh pipefy-cli
uvx --from git+https://github.com/pipefy/ai-toolkit@latest --refresh pipefy-cli
pipefy card get 12345
```

Expand Down Expand Up @@ -152,4 +156,4 @@ The legacy `PIPEFY_OAUTH_*` env-var aliases and the deprecation warning live on

## Questions?

Open an issue at [github.com/<owner>/pipefy-labs/issues](https://github.com/<owner>/pipefy-labs/issues) or email **[email protected]**.
Open an issue at [github.com/pipefy/ai-toolkit/issues](https://github.com/pipefy/ai-toolkit/issues) or email **[email protected]**.
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Documentation index

Human-facing guides for the **pipefy-labs** monorepo (`pipefy-mcp-server` on GitHub). Use the sections below to load only the surface you need.
Human-facing guides for the **[pipefy/ai-toolkit](https://github.com/pipefy/ai-toolkit)** monorepo (packages: `pipefy-mcp-server`, `pipefy-cli`, `pipefy-sdk`). Use the sections below to load only the surface you need.

## By surface

Expand Down
62 changes: 60 additions & 2 deletions docs/mcp/tools/pipes-and-cards.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ Pipefy’s GraphQL API uses **string** IDs for pipes, phases, cards, and most ot

| Tool | Role |
|------|------|
| `get_pipe` | Load pipe metadata (phases, fields, settings). |
| `get_pipe` | Load pipe metadata (phases, fields, settings). Response includes `start_form_phase` (`id`, `name`, `cards_count`) and per-phase `cards_count` on workflow phases (start form is not duplicated in `phases[]`). |
| `get_start_form_fields` | Start-form fields for a pipe. |
| `get_phase_fields` | Fields for a phase — each includes `id`, `internal_id`, `uuid`. |
| `get_pipe_members` | List pipe members. |
| `get_labels` | List labels configured on the pipe (`id`, `name`). |
| `search_pipes` | Search pipes by name. |
| `get_phase_cards_count` | Native `Phase.cards_count` for one phase (fast scalar). Start-form count may be **0** while cards exist — pair with `get_phase_cards`. |
| `get_phase_cards` | Paginated cards in a phase (`Phase.cards`). Prefer over `get_cards` for phase-local inventory. |

## Card reads

Expand All @@ -46,14 +48,15 @@ Pipefy’s GraphQL API uses **string** IDs for pipes, phases, cards, and most ot
|-------|-------|-------|
| Pipe | `create_pipe`, `update_pipe`, `delete_pipe`, `clone_pipe` | `delete_pipe`: two-step — preview first, then `confirm=true`. |
| Phase | `create_phase`, `update_phase`, `delete_phase` | Destructive deletes: confirm with the user. |
| Phase transitions | `get_phase_allowed_move_targets` | Read-only; mirrors **Phase → Connections** (`cards_can_be_moved_to_phases`). Call before `move_card_to_phase`. Edges are configured in the Pipefy UI only. |
| Phase field | `create_phase_field`, `update_phase_field`, `delete_phase_field` | `field_type` maps to API `type`; `field_id` may be a slug or numeric ID. |
| Label | `create_label`, `update_label`, `delete_label` | `color` must be a hex string (e.g. `#FF0000`), not a name. |

## Cards (lifecycle & comments)

| Tool | Role |
|------|------|
| `create_card` | Create a card; may use elicitation to ask the user for required fields mid-call. |
| `create_card` | Create a card in the start form (default) or in a specific phase via optional `phase_id`; may use elicitation to ask the user for required fields mid-call. |
| `fill_card_phase_fields` | Fill phase-specific fields on a card; may use elicitation when available. |
| `add_card_comment` | Add a comment to a card. |
| `update_comment` | Update an existing comment. |
Expand All @@ -80,10 +83,65 @@ Because non-editable keys are dropped without warning, agents should discover fi
get_start_form_fields(pipe_id) → learn field IDs, types, required flag
create_card(pipe_id, fields={…}) → supply every required field ID

get_pipe(pipe_id) → start_form_phase + phases[].id / cards_count for inventory
→ phases[].id when seeding a non-start-form phase
create_card(
pipe_id,
phase_id="340012345",
skip_elicitation=true,
title="Seeded card",
fields={…},
) → card created in that phase (fields validated via get_phase_fields)

get_phase_fields(phase_id) → learn phase field IDs
fill_card_phase_fields(card_id, phase_id, fields={…}) → supply values
```

With `phase_id`, the start-form elicitation path is skipped. Use `skip_elicitation=true` for agent workflows. When `fields` is non-empty, keys are filtered against both `get_phase_fields(phase_id)` and `get_start_form_fields(pipe_id)` so pipes that still require start-form values on `CreateCardInput` receive them alongside phase fields. Optional `title` is sent on `CreateCardInput` (no separate `update_card` on the happy path).

### `get_pipe` inventory fields (additive)

MCP tool results use the standard envelope; inventory fields live under the `pipe` object:

| JSON path | Meaning |
|-----------|---------|
| `pipe.start_form_phase.id` | Start-form phase ID (same as `pipe.startFormPhaseId`) |
| `pipe.start_form_phase.name` | Start-form phase display name |
| `pipe.start_form_phase.cards_count` | Native `Phase.cards_count` for the start form (may be **0** while cards exist — use `get_phase_cards`) |
| `pipe.phases[].id` | Workflow phase IDs (start form excluded) |
| `pipe.phases[].name` | Phase display name |
| `pipe.phases[].cards_count` | Native card count for that workflow phase |

CLI `pipefy pipe get <pipe_id> --json` returns the same SDK-normalized shape.

### Phase inventory (`get_phase_cards_count` / `get_phase_cards`)

Use these when you need per-phase totals or card lists without pipe-wide `CardSearch`:

| Tool | CLI | When to use |
|------|-----|-------------|
| `get_phase_cards_count` | `pipefy phase cards-count <phase_id>` | Quick scalar; empty phases for seeding. |
| `get_phase_cards` | `pipefy phase cards <phase_id> --first 50 --after <cursor>` | Verify cards after create/move; paginate with `pageInfo.endCursor`. |

Discovery path: `get_pipe(pipe_id)` → `phases[].id` (workflow) or `start_form_phase.id` (start form).

```
get_phase_cards_count(phase_id="340012345")
get_phase_cards(phase_id="340012345", first=50, include_fields=true)
```

### Phase transitions (`get_phase_allowed_move_targets`)

Outbound moves are constrained by UI-configured connections — there is no API to add edges.

1. Resolve source phase: `get_card(card_id).current_phase.id` (or known `phase_id` before move).
2. `get_phase_allowed_move_targets(phase_id=<source>)` → `allowed_phases` (`{id, name}`).
3. `move_card_to_phase(card_id, destination_phase_id=<allowed id>)`.

CLI: `pipefy phase allowed-moves <phase_id> --json`.

Empty `allowed_phases` means no outbound transitions are configured in the UI.

## Field condition tools

Five tools read and configure conditional visibility on phase fields.
Expand Down
21 changes: 21 additions & 0 deletions docs/mcp/tools/reports.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ Pipe reports and organization reports: discovery, CRUD, single pipe report fetch
## Cross-cutting patterns

- Build `ReportCardsFilter` using `get_pipe_report_columns` and `get_pipe_report_filterable_fields`; use `introspect_type` for uncommon inputs.
- **Filter shape:** nested `operator` (`and` | `or`) plus `queries` (and optional `groups`). Do **not** pass a top-level `current_phase` array — that is not valid GraphQL input. `create_pipe_report` / `update_pipe_report` (MCP and CLI) validate structure before calling the API.

### Example phase filter (`create_pipe_report` / `update_pipe_report`)

Discover the exact `field` string for your pipe via `get_pipe_report_filterable_fields`, then:

```json
{
"operator": "and",
"queries": [
{
"field": "current_phase",
"operator": "eq",
"type": "select",
"value": "<phase_id>"
}
]
}
```

Replace `field` / `value` when filterable-field metadata uses different names or option ids.
- `get_pipe_reports` omits `cardCount` in the query (Pipefy can error when resolving it).
- `debug=true` on writes like other mutation tools.
- **Async export pattern:** trigger export -> poll the matching `get_*_report_export` until `state` is done -> use `fileURL`. `export_pipe_audit_logs` only returns `success` (no export ID to poll — the file is delivered to the requesting user).
Expand Down
Loading
Loading