| name | tines |
| description | Use when creating, modifying, or managing Tines stories, actions, workflows, or automations. Also use when the user mentions Tines, asks about building SOAR workflows, or wants to automate security operations. Triggers on keywords like tines, story, action, webhook, workflow automation, SOAR. |
Tines Workflow Automation
Build and manage Tines stories (automated workflows) using the Tines MCP server tools.
Setup Check
This skill requires the Tines MCP server to be connected. Check if the tines MCP server is available.
If NOT connected, guide the user through setup — see mcp-reference.md for the full deployment guide. Quick summary:
- Edit
TENANT_URL in generate_mcp.py to match their tenant
- Run
python3 generate_mcp.py to create story_export.json
- Import into Tines:
curl -X POST -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
"$TENANT_URL/api/v1/stories/import" \
-d '{"new_name":"claude-mcp","team_id":TEAM_ID,"data":'$(cat story_export.json)'}'
- Create a Tines Credential named
tines_api_key with the API key value, and add the tenant domain to allowed_hosts
- Add the MCP server to Claude Code:
claude mcp add -t http -s project tines \
-H "Authorization: Bearer MCP_SECRET" \
"TENANT_URL/mcp/MCP_PATH"
Core Concepts
- Story = A workflow (container for actions)
- Action = A step in the workflow (API type uses
Agents:: prefix)
- Link = Connection between actions (data flows source -> receiver)
- Event = Data payload that flows through actions
- Resource = Shared data store (JSON/text/file) accessible across stories
- Credential = Stored authentication (API keys, OAuth tokens, etc.)
- Value Pills =
<<action_slug.field.path>> syntax for referencing upstream data
- Formulas = Built-in functions like
DATE(), IF(), SHA256(), etc.
MCP Tools Reference
Story Management
| Tool | Description | Required Params | Optional Params |
|---|
list_stories | List all stories | — | per_page, page, team_id |
get_story | Get story details | story_id | — |
create_story | Create a story | name, team_id | description |
update_story | Update story properties | story_id | name, description, tags_json, disabled, locked, keep_events_for |
delete_story | Delete a story | story_id | — |
export_story | Export as full JSON | story_id | — |
import_story | Import from JSON | new_name, team_id, data_json | — |
Action Management
| Tool | Description | Required Params | Optional Params |
|---|
list_actions | List actions in a story | story_id | per_page |
get_action | Get action details | action_id | — |
create_action | Create an action | story_id, type, name, options_json | position_x, position_y, source_ids_json, links_to_sources_json, description |
update_action | Update an action | action_id | name, options_json, position_x, position_y, source_ids_json, receiver_ids_json, links_to_sources_json, links_to_receivers_json |
delete_action | Delete an action | action_id | — |
list_action_events | View execution history | action_id | per_page, page |
delete_links | Remove links between actions | links_json | — |
Resources (Data Stores)
| Tool | Description | Required Params | Optional Params |
|---|
list_resources | List resources | — | team_id, per_page, page |
get_resource | Get resource details | resource_id | — |
create_resource | Create a resource | name, team_id, value_json | — |
update_resource | Update resource value | resource_id, value_json | — |
delete_resource | Delete a resource | resource_id | — |
Story Notes
| Tool | Description | Required Params | Optional Params |
|---|
list_notes | List storyboard notes | story_id | per_page, page |
get_note | Get a specific note | note_id | — |
create_note | Create a storyboard note (markdown) | story_id, content | position_x, position_y |
update_note | Update note content or position | note_id | content, position_x, position_y |
delete_note | Delete a note | note_id | — |
Story Events
| Tool | Description | Required Params | Optional Params |
|---|
list_story_events | List events across all actions in a story | story_id | per_page, page |
get_event | Get a specific event by ID | event_id | — |
Discovery
| Tool | Description | Required Params | Optional Params |
|---|
list_teams | List teams (find team IDs) | — | per_page, page |
list_credentials | List credentials (find slugs) | team_id | per_page, page |
list_folders | List folders | — | team_id, content_type, per_page, page |
Workflow Testing
| Tool | Description | Required Params | Optional Params |
|---|
run_action | Run an executable action (Event Transform, HTTP Request, etc.) with test data. Does not work on Webhook or Trigger action types. | action_id | payload_json |
reemit_event | Re-emit an existing event | event_id | — |
Parameter Conventions
All MCP tool parameters are strings. For complex values:
options_json — Pass action options as a JSON string: "{\"mode\":\"message_only\",\"payload\":{\"key\":\"value\"}}"
source_ids_json — Pass as JSON array string: "[\"12345\"]" (DEFAULT links only)
links_to_sources_json / links_to_receivers_json — Pass as JSON array of objects: "[{\"source_id\":\"12345\",\"type\":\"NO_MATCH\"}]" (supports typed links)
tags_json — Pass as JSON array string: "[\"tag1\",\"tag2\"]"
value_json — Pass resource values as JSON string
data_json — Pass full story export as JSON string (for import_story)
Formula escaping: When options_json values contain Tines formula references (e.g., <<webhook.body.field>>), escape the angle brackets as JSON unicode: use \u003c\u003c instead of << and \u003e\u003e instead of >>. This prevents premature formula evaluation during action creation. The Tines API stores these as the correct <</>> characters.
Action Types
When using create_action, the type parameter must be one of:
| Type | API Value | Purpose |
|---|
| Webhook | Agents::WebhookAgent | Receive HTTP requests (story entry point) |
| HTTP Request | Agents::HTTPRequestAgent | Make outbound API calls |
| Event Transform | Agents::EventTransformationAgent | Reshape, split, merge, delay, deduplicate data |
| Condition | Agents::TriggerAgent | Route events based on rules |
| Send to Story | Agents::SendToStoryAgent | Call sub-workflows |
| Send Email | Agents::EmailAgent | Send emails |
| Receive Email | Agents::IMAPAgent | Monitor email inboxes |
| AI Agent | Agents::LLMAgent | Invoke LLMs with optional tools |
| Group | Agents::GroupAgent | Organize actions visually |
See action-types.md for detailed options_json schemas for each type.
Linking Actions
When creating actions, pass source_ids_json to link to upstream actions (creates DEFAULT links):
create_action(story_id="123", type="Agents::EventTransformationAgent",
name="Process", options_json="{...}",
position_y="150", source_ids_json="[\"456\"]")
Typed links (NO_MATCH, FAILURE) use links_to_sources_json or links_to_receivers_json instead:
create_action(story_id="123", type="Agents::EventTransformationAgent",
name="Handle No Match", options_json="{...}",
position_y="300", position_x="300",
links_to_sources_json="[{\"source_id\":\"<trigger_id>\",\"type\":\"NO_MATCH\"}]")
Link types: DEFAULT, NO_MATCH (TriggerAgent only), FAILURE (action errored).
source_ids_json and links_to_sources_json are mutually exclusive (same for receiver_ids_json / links_to_receivers_json).
To remove links, use the delete_links tool:
delete_links(links_json="[{\"source_id\":\"456\",\"receiver_id\":\"789\"}]")
Layout Positioning
Use position_x and position_y when creating actions:
- Vertical spacing: ~150px between sequential actions
- Horizontal spacing: ~300px for parallel branches
- Start at
(0, 0) for the first action
Value Pills & Formulas
Reference upstream data: <<action_slug.field.nested_field>>
Array access: <<action_slug.items[0].name>>
Formulas
Common: IF(), DEFAULT(), SIZE(), JSON_PARSE(), TO_JSON(), DATE(), REGEX_EXTRACT(), MAP(), WHERE(), MERGE()
See formulas.md for the full formula reference (logic, text, arrays, objects, dates, crypto, numbers).
Common Mistakes
| Mistake | Fix |
|---|
Using << / >> in options_json | Escape as \u003c\u003c / \u003e\u003e to prevent premature formula evaluation |
| Passing numbers/arrays as raw values | All MCP params are strings — wrap in quotes: "[\"123\"]" not [123] |
| Using wrong action type string | Must use Agents:: prefix: Agents::HTTPRequestAgent not HTTPRequestAgent |
Not linking actions via source_ids_json | Actions won't receive events without explicit links |
Setting must_match wrong on TriggerAgent | 1 = OR (any rule), omit = AND (all rules) |
Building a Story — Process
- Find your team:
list_teams to get the team_id
- Create or find the story:
create_story or list_stories + get_story
- Create actions top-to-bottom: Use
create_action for each, linking with source_ids_json
- Verify:
export_story to check the full structure
- Test:
run_action on the first executable action (Event Transform, HTTP Request, etc. — not Webhook or Trigger) with test data shaped like the upstream output, then list_action_events on downstream actions to verify events flowed correctly
- Document: Use
create_note to add storyboard notes explaining the story's purpose, key design decisions, and what each branch handles. Position notes near the relevant actions on the diagram using position_x/position_y
Common Patterns
Webhook -> Transform -> HTTP Request
1. create_action(type="Agents::WebhookAgent", options_json="{\"path\":\"my-webhook\",\"verbs\":\"post\"}")
2. create_action(type="Agents::EventTransformationAgent", options_json="{\"mode\":\"message_only\",\"payload\":{...}}", source_ids_json="[\"<webhook_id>\"]")
3. create_action(type="Agents::HTTPRequestAgent", options_json="{\"url\":\"...\",\"method\":\"post\"}", source_ids_json="[\"<transform_id>\"]")
Webhook -> Condition -> Branch
1. create_action(type="Agents::TriggerAgent", name="Is Critical?",
options_json="{\"rules\":[{\"type\":\"field==value\",\"path\":\"...\",\"value\":\"critical\"}]}",
source_ids_json="[\"<webhook_id>\"]")
2. create_action(type="Agents::EventTransformationAgent", name="On Match", ...,
source_ids_json="[\"<trigger_id>\"]")
3. create_action(type="Agents::EventTransformationAgent", name="On No Match", ...,
links_to_sources_json="[{\"source_id\":\"<trigger_id>\",\"type\":\"NO_MATCH\"}]")
Error Handling
- Set
emit_failure_event: "Always" on HTTP requests
- Use FAILURE link type to route errors to notification actions
- Use
retry_on_status: ["429", "500-599"] for transient failures
Testing a Story
run_action works on executable action types (Event Transform, HTTP Request, Send to Story, etc.) but returns "Action type cannot be run" for Webhook and Trigger actions. To test a full pipeline, run the first executable action after the webhook with the expected upstream payload shape:
1. run_action(action_id="<first_executable_action_id>", payload_json="{\"body\":{\"test_key\":\"test_value\"}}")
— use the first Event Transform, HTTP Request, or other executable action (not the Webhook/Trigger)
— shape the payload to match what the upstream action would normally emit
2. list_action_events(action_id="<downstream_action_id>") to verify events flowed correctly
3. If an event failed, fix the action, then reemit_event(event_id="<failed_event_id>")
API Fallback
For operations not covered by the 31 MCP tools (e.g., managing story drafts, owners, recipients, cases, records, or admin operations), fall back to direct API calls. See api-reference.md for the full endpoint catalog with authentication and pagination details.