@adrata/adrata-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +548 -0
- package/access/auth.js +289 -0
- package/access/oauth.js +1059 -0
- package/access/resource-metadata.js +167 -0
- package/access/tiers.js +422 -0
- package/analytics.js +634 -0
- package/api-bridge.js +499 -0
- package/governance/money.js +141 -0
- package/output-formatter.js +589 -0
- package/package.json +68 -0
- package/resources.js +246 -0
- package/security.js +690 -0
- package/server.js +2139 -0
- package/server.json +55 -0
- package/skills/backlog-triage/SKILL.md +115 -0
- package/skills/board-review/SKILL.md +96 -0
- package/skills/incident-to-card/SKILL.md +126 -0
- package/skills/log-outreach.md +62 -0
- package/skills/ship-the-card/SKILL.md +155 -0
- package/tool-annotations.js +269 -0
- package/tools/billing.js +149 -0
- package/tools/email-tools.js +652 -0
- package/tools/enterprise-tools.js +651 -0
- package/tools/free-search.js +160 -0
- package/tools/memory.js +440 -0
- package/tools/morning-brief.js +551 -0
- package/tools/paper-tools.js +563 -0
- package/tools/scheduling.js +322 -0
- package/tools/work-board-tools.js +758 -0
- package/toolsets/communications.js +276 -0
- package/toolsets/crm.js +495 -0
- package/toolsets/extensibility.js +1131 -0
- package/toolsets/infrastructure.js +757 -0
- package/toolsets/intelligence.js +232 -0
- package/toolsets/knowledge.js +154 -0
- package/toolsets/matrix.js +217 -0
- package/toolsets/outreach.js +432 -0
- package/toolsets/prospecting.js +314 -0
- package/toolsets/revenue/always-loaded.js +341 -0
- package/toolsets/revenue/sloan-tools.js +81 -0
- package/transport-http.js +505 -0
package/server.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
|
|
3
|
+
"name": "com.adrata/adrata-mcp",
|
|
4
|
+
"description": "Adrata revenue-intelligence MCP server: companies, people, opportunities, actions, buyer groups, enrichment, email, and workspace operations for AI agents.",
|
|
5
|
+
"status": "active",
|
|
6
|
+
"version": "1.0.0",
|
|
7
|
+
"websiteUrl": "https://adrata.com/developers",
|
|
8
|
+
"repository": {
|
|
9
|
+
"url": "https://github.com/adrata/adrata",
|
|
10
|
+
"source": "github",
|
|
11
|
+
"subfolder": "code/mcp"
|
|
12
|
+
},
|
|
13
|
+
"packages": [
|
|
14
|
+
{
|
|
15
|
+
"registryType": "npm",
|
|
16
|
+
"registryBaseUrl": "https://registry.npmjs.org",
|
|
17
|
+
"identifier": "@adrata/adrata-mcp",
|
|
18
|
+
"version": "1.0.0",
|
|
19
|
+
"transport": {
|
|
20
|
+
"type": "stdio"
|
|
21
|
+
},
|
|
22
|
+
"environmentVariables": [
|
|
23
|
+
{
|
|
24
|
+
"name": "ADRATA_API_KEY",
|
|
25
|
+
"description": "Pro-tier API key. Omit for free tier; use OAuth (connect_workspace) for enterprise.",
|
|
26
|
+
"isRequired": false,
|
|
27
|
+
"isSecret": true
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "ADRATA_OAUTH_TOKEN",
|
|
31
|
+
"description": "Enterprise OAuth 2.1 access token, audience-bound to the Adrata MCP resource (RFC 8707).",
|
|
32
|
+
"isRequired": false,
|
|
33
|
+
"isSecret": true
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"remotes": [
|
|
39
|
+
{
|
|
40
|
+
"type": "streamable-http",
|
|
41
|
+
"url": "https://mcp.adrata.com/mcp"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"_meta": {
|
|
45
|
+
"com.adrata": {
|
|
46
|
+
"authorization": {
|
|
47
|
+
"spec": "MCP 2025-06-18",
|
|
48
|
+
"oauth": "2.1 + PKCE (S256)",
|
|
49
|
+
"resourceIndicators": "RFC 8707",
|
|
50
|
+
"protectedResourceMetadata": "RFC 9728 at /.well-known/oauth-protected-resource",
|
|
51
|
+
"tokenPassthrough": "rejected (audience-bound)"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backlog-triage
|
|
3
|
+
description: Triage a Starfield backlog board — work the Triage column down, deduplicate against what is already there, tag by the board's own scheme, and route each card. Use when asked to triage, groom, sort, or "clean up" a backlog, or when someone asks what they should work on next.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Backlog triage
|
|
7
|
+
|
|
8
|
+
You are working someone's real backlog. Every move you make shows up on their
|
|
9
|
+
board on Monday morning, and a card you mis-tag is a card they stop trusting the
|
|
10
|
+
tag on. Be conservative and leave a trail.
|
|
11
|
+
|
|
12
|
+
## Before you touch anything
|
|
13
|
+
|
|
14
|
+
1. `list_work_boards` — get the board id. If there is more than one, ask which,
|
|
15
|
+
unless the request already names a company or product that identifies it.
|
|
16
|
+
2. `get_work_board` — read the columns AND their staleness policies, and the
|
|
17
|
+
cards. Note the board's `tagScheme`: it decides the vocabulary you are
|
|
18
|
+
allowed to tag in.
|
|
19
|
+
|
|
20
|
+
**Read the whole board before changing one card.** Triage is a comparison
|
|
21
|
+
between cards, not a judgement on each in isolation — you cannot know a card is
|
|
22
|
+
a duplicate, or that it is the fifth report of one bug, without the rest.
|
|
23
|
+
|
|
24
|
+
## The order of work
|
|
25
|
+
|
|
26
|
+
Work the board's FIRST column (usually Triage). Do not touch cards further
|
|
27
|
+
along: a card in In review has been looked at by someone who knew more than you
|
|
28
|
+
do about it.
|
|
29
|
+
|
|
30
|
+
For each card, in this order:
|
|
31
|
+
|
|
32
|
+
### 1. Is it a duplicate?
|
|
33
|
+
|
|
34
|
+
Compare against every other card on the board, not just the same column. Two
|
|
35
|
+
cards are duplicates when fixing one closes the other — not merely when they use
|
|
36
|
+
similar words. "Export is slow" and "Export times out at 10k rows" may be one
|
|
37
|
+
bug or two; if you cannot tell, they are two.
|
|
38
|
+
|
|
39
|
+
Do NOT delete or merge duplicates on your own judgement. Say which cards you
|
|
40
|
+
believe are duplicates and why, and let a human collapse them. A wrongly merged
|
|
41
|
+
card loses its reporter and its evidence, and nobody ever notices.
|
|
42
|
+
|
|
43
|
+
### 2. Is it actually a card?
|
|
44
|
+
|
|
45
|
+
Some Triage entries are questions, notifications, or half a thought. A card that
|
|
46
|
+
does not describe a change to make is not ready to be worked. Flag it, propose
|
|
47
|
+
a one-line rewrite that names the change, and leave it in Triage.
|
|
48
|
+
|
|
49
|
+
### 3. Tag it
|
|
50
|
+
|
|
51
|
+
Use `set_work_item_tag` with the board's own `tagScheme`. Source is **`model`**
|
|
52
|
+
and you must give a `confidence` — you are a classifier here, not the person
|
|
53
|
+
whose call it is. Claiming `human` would launder your guess as their judgement.
|
|
54
|
+
|
|
55
|
+
Be conservative upward. The severity scheme's `critical` means *someone is
|
|
56
|
+
broken right now*: an outage, data loss, a security issue, or every customer
|
|
57
|
+
affected. A slow report is not critical. A backlog that cries wolf gets ignored,
|
|
58
|
+
and then the one real critical is missed.
|
|
59
|
+
|
|
60
|
+
If the card gives you no signal at all, leave it untagged rather than tagging it
|
|
61
|
+
low-confidence — the board falls back to its own deterministic rules, which is
|
|
62
|
+
more honest than a guess with a number on it.
|
|
63
|
+
|
|
64
|
+
### 4. Route it
|
|
65
|
+
|
|
66
|
+
Move a card out of Triage only when you can say which column it belongs in and
|
|
67
|
+
why. `move_work_item`, with a `reason` that would satisfy the person who wrote
|
|
68
|
+
the card: "Reproduced on staging, needs a fix" beats "triaged".
|
|
69
|
+
|
|
70
|
+
The tool refuses a placeholder `reason` — "triaged", "moved", "update" — so the
|
|
71
|
+
line above is a rule the board now enforces rather than advice.
|
|
72
|
+
|
|
73
|
+
A card you could not tag confidently stays in Triage. That is the correct
|
|
74
|
+
outcome, not a failure.
|
|
75
|
+
|
|
76
|
+
### 5. Leave the owner alone
|
|
77
|
+
|
|
78
|
+
Routing a card is not picking it up. Do **not** pass `claim` on these moves, and
|
|
79
|
+
never `force`: an assignee is how two people stay off one card, and triage
|
|
80
|
+
reassigning it is exactly the surprise that makes a board stop being trusted. A
|
|
81
|
+
card that already has an assignee is that person's — route it if it is in the
|
|
82
|
+
wrong column, and say so, but it stays theirs.
|
|
83
|
+
|
|
84
|
+
Picking work up is a different skill: `ship-the-card`.
|
|
85
|
+
|
|
86
|
+
## What the ages mean
|
|
87
|
+
|
|
88
|
+
Every card carries `enteredColumnAt`. Compare it against **its own column's**
|
|
89
|
+
`agingAfterHours` / `staleAfterHours` — a missing bound means the column never
|
|
90
|
+
ages, which is what a Done column wants. Three days in Triage is alarming; three
|
|
91
|
+
days in In review is a Tuesday. Applying one threshold across the board will
|
|
92
|
+
make you report finished work as stale.
|
|
93
|
+
|
|
94
|
+
Stale cards in Triage are the ones to surface first: they have been waiting for
|
|
95
|
+
a decision nobody made.
|
|
96
|
+
|
|
97
|
+
## Writes
|
|
98
|
+
|
|
99
|
+
Every move and tag change is a governed write. Preview first (the tools default
|
|
100
|
+
to `dryRun: true`), show the human the full list of what you intend to do, and
|
|
101
|
+
only then run with `dryRun: false`, `approved: true`, a `reason`, and an
|
|
102
|
+
`idempotencyKey`. Reuse the same key if you retry — a duplicate move makes the
|
|
103
|
+
card read as having bounced between columns, and the board's stage timer is
|
|
104
|
+
derived from exactly those rows.
|
|
105
|
+
|
|
106
|
+
## What to report
|
|
107
|
+
|
|
108
|
+
A short list, in this shape:
|
|
109
|
+
|
|
110
|
+
- **Moved** — card, from → to, why.
|
|
111
|
+
- **Tagged** — card, tag, confidence, the signal you read it from.
|
|
112
|
+
- **Left in Triage** — card, and the specific question that would unblock it.
|
|
113
|
+
- **Possible duplicates** — the pairs, and what would confirm it.
|
|
114
|
+
|
|
115
|
+
No summary paragraph. The person reading this is about to act on it.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: board-review
|
|
3
|
+
description: Review a Starfield board or roll-up and report what is actually stuck — what has gone stale, what is unowned, where work is piling up, and which decisions are overdue. Use for a standup, a weekly review, a "how are we doing", or when someone asks what is blocked across their clients.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Board review
|
|
7
|
+
|
|
8
|
+
The question behind every board review is *what needs a decision that nobody is
|
|
9
|
+
making*. Card counts do not answer it. Time does.
|
|
10
|
+
|
|
11
|
+
## Scope
|
|
12
|
+
|
|
13
|
+
- One team's board → `get_work_board`.
|
|
14
|
+
- Everything, across every client → `get_work_board_rollup` with `rollupId:
|
|
15
|
+
"all"`. This one has no membership rows, so it always includes a board created
|
|
16
|
+
five minutes ago.
|
|
17
|
+
- A curated view → `list_work_board_rollups`, then `get_work_board_rollup`.
|
|
18
|
+
|
|
19
|
+
A roll-up keeps provenance: every card still names its board and its company.
|
|
20
|
+
Use it. "Three cards are stale" is useless; "Acme has three stale cards, all in
|
|
21
|
+
Triage" is a conversation.
|
|
22
|
+
|
|
23
|
+
## Read the time, not the count
|
|
24
|
+
|
|
25
|
+
Every card carries `enteredColumnAt`. Compare it against **its own column's**
|
|
26
|
+
policy — `agingAfterHours` and `staleAfterHours` live on the column, and a
|
|
27
|
+
missing bound means that column never ages.
|
|
28
|
+
|
|
29
|
+
This is the mistake to avoid: applying one threshold to a whole board. Three
|
|
30
|
+
days in Triage means nobody has decided. Three days in In review means it is
|
|
31
|
+
Tuesday. Three days in Done means nothing at all. A review that calls finished
|
|
32
|
+
work stale destroys its own credibility in one line.
|
|
33
|
+
|
|
34
|
+
On a roll-up, each slice carries the member board's own policy — use the slice's
|
|
35
|
+
policy for its own cards.
|
|
36
|
+
|
|
37
|
+
## What to look for, in priority order
|
|
38
|
+
|
|
39
|
+
1. **Stale in an early column.** A card sitting in Triage past its threshold is
|
|
40
|
+
a decision nobody made. This is the highest-value thing a review surfaces,
|
|
41
|
+
because it is pure latency — no work is happening and none is blocked on
|
|
42
|
+
anything real.
|
|
43
|
+
|
|
44
|
+
2. **Work in progress with no assignee.** `assigneeUserId` absent on a card in
|
|
45
|
+
an active column means it is nobody's. Cards do not move themselves.
|
|
46
|
+
`list_my_work_items` with `includeUnassigned: true` returns the unowned pool
|
|
47
|
+
across every board directly, which is faster than scanning each board — but
|
|
48
|
+
its `assignedToMe` half answers only for YOU, so it is not a way to report on
|
|
49
|
+
anybody else's load. For that, read the boards and group by assignee.
|
|
50
|
+
|
|
51
|
+
3. **A column piling up.** Compare column depths against the board's own
|
|
52
|
+
history, not against each other — some columns are meant to be deep. A
|
|
53
|
+
suddenly-deep In review means the reviewers are the bottleneck, not the
|
|
54
|
+
builders.
|
|
55
|
+
|
|
56
|
+
4. **Critical cards that are not moving.** Cross the tag against the age. A card
|
|
57
|
+
tagged `critical` (or `p0`) that has been in one column for days is either
|
|
58
|
+
mis-tagged or genuinely on fire, and both are worth saying out loud. Use
|
|
59
|
+
`get_work_item_history` to see whether it has moved at all or has been
|
|
60
|
+
bouncing.
|
|
61
|
+
|
|
62
|
+
5. **Cards that have bounced.** `get_work_item_history` shows every transition.
|
|
63
|
+
A card that has crossed the same boundary three times is not making progress;
|
|
64
|
+
it is missing information, and the history's `reason` fields usually say
|
|
65
|
+
which.
|
|
66
|
+
|
|
67
|
+
## Do not equate tag schemes
|
|
68
|
+
|
|
69
|
+
Boards can use different vocabularies — severity, priority, kind, impact. A P1
|
|
70
|
+
is not a Critical, and nothing in this product will translate one into the
|
|
71
|
+
other. Rank within each board's own scheme and report them as they are. If you
|
|
72
|
+
need a single ordering across boards, say what you ordered by and that it is
|
|
73
|
+
your own reading, not the boards'.
|
|
74
|
+
|
|
75
|
+
## This is a read-only skill
|
|
76
|
+
|
|
77
|
+
A review reports; it does not reorganise. If the review surfaces cards that
|
|
78
|
+
should move, say so and stop — moving them is `backlog-triage`, and it is a
|
|
79
|
+
separate decision the person may not want made for them. Do not call
|
|
80
|
+
`move_work_item` or `set_work_item_tag` here — and in particular do not claim a
|
|
81
|
+
card you noticed is unowned. Reviewing work and taking it are different acts, and
|
|
82
|
+
doing the second while asked for the first is how a review stops being safe to
|
|
83
|
+
ask for.
|
|
84
|
+
|
|
85
|
+
## What to report
|
|
86
|
+
|
|
87
|
+
Lead with what is stuck, not with totals:
|
|
88
|
+
|
|
89
|
+
- **Overdue decisions** — card, board/company, how long it has waited, and the
|
|
90
|
+
specific question that would unstick it.
|
|
91
|
+
- **Unowned in-flight work** — card, board, column.
|
|
92
|
+
- **Bottleneck** — the column that is piling up, and against what.
|
|
93
|
+
- **Critical and not moving** — card, tag, days in column, whether it has moved.
|
|
94
|
+
|
|
95
|
+
Then, and only then, one line of totals. If nothing is stuck, say that plainly —
|
|
96
|
+
a clean board is a real result, and padding it with numbers hides it.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: incident-to-card
|
|
3
|
+
description: Turn a live problem — an alert, a failing build, a stack trace, a customer saying "it's down" — into a Starfield card that someone can actually pick up. Use when reporting a bug, filing an incident, or capturing something broken you found while working.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Incident to card
|
|
7
|
+
|
|
8
|
+
The gap between "I found a bug" and "someone fixed it" is almost always the
|
|
9
|
+
card. A card that says *Export broken* costs the next person an hour of
|
|
10
|
+
rediscovery. This skill is about spending two minutes now instead.
|
|
11
|
+
|
|
12
|
+
## What makes a card workable
|
|
13
|
+
|
|
14
|
+
Five things, and a card missing any of them will bounce:
|
|
15
|
+
|
|
16
|
+
1. **What you did** — the smallest sequence that shows the problem.
|
|
17
|
+
2. **What happened** — the actual output. Paste the error, the status code, the
|
|
18
|
+
stack trace. Not your summary of it.
|
|
19
|
+
3. **What you expected** — obvious to you, not to the person picking it up.
|
|
20
|
+
4. **Where** — environment, build SHA or version, workspace/account if it is
|
|
21
|
+
scoped to one.
|
|
22
|
+
5. **Acceptance criteria** — what would prove this fixed, as outcomes somebody
|
|
23
|
+
can check. See below; this is the one people leave off.
|
|
24
|
+
|
|
25
|
+
If you are filing from a conversation or a log you are looking at right now,
|
|
26
|
+
extract these from it. **Do not invent any of them.** A plausible repro that
|
|
27
|
+
does not reproduce is worse than no repro: it sends someone down a path you
|
|
28
|
+
never actually walked. If you do not know the expected behaviour, say "expected
|
|
29
|
+
unknown — reporter did not state it" in the body.
|
|
30
|
+
|
|
31
|
+
## Acceptance criteria, and where they live
|
|
32
|
+
|
|
33
|
+
A card is the unit of QA sign-off: it is one judgement, made in one pass against
|
|
34
|
+
a written list. So every card carries that list, and post-AI it has **two**
|
|
35
|
+
readers — it is the build spec the agent works from and the test plan QA
|
|
36
|
+
validates against. The same sentences, doing both jobs. A card without them
|
|
37
|
+
makes the agent guess and gives QA nothing to check, which is how a card gets
|
|
38
|
+
signed off on the wrong thing.
|
|
39
|
+
|
|
40
|
+
**There is no acceptance-criteria field.** They live in the card's `body`, under
|
|
41
|
+
an `Acceptance criteria` heading, one checkable outcome per line:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
Acceptance criteria
|
|
45
|
+
- Exporting 10,000 rows completes without a 504.
|
|
46
|
+
- The export button is disabled until the download starts.
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Two rules that decide whether you have written them correctly:
|
|
50
|
+
|
|
51
|
+
- **One card is one QA judgement.** If your list needs QA to make more than one
|
|
52
|
+
call — "follows the OS theme" AND "the toggle persists" AND "every surface is
|
|
53
|
+
restyled" — that is several cards. A bounce from a multi-outcome card names
|
|
54
|
+
nothing actionable, which is what makes the second QA pass worthless. The
|
|
55
|
+
count is also the honest size signal: one line is a small card, five is a big
|
|
56
|
+
one, ten means you should have filed two.
|
|
57
|
+
- **Do not invent them**, on exactly the terms you do not invent a repro. If the
|
|
58
|
+
reporter never said what "fixed" looks like, write "acceptance criteria
|
|
59
|
+
unknown — reporter did not state what fixed looks like" and file it. That is a
|
|
60
|
+
triage problem for a human, and naming it is what gets it triaged; a made-up
|
|
61
|
+
criterion is worse, because QA will sign the card off against it.
|
|
62
|
+
|
|
63
|
+
Implementation steps are **not** criteria and never become their own cards:
|
|
64
|
+
"create a React hook", "rename the CSS variables" are lines in this body, in a
|
|
65
|
+
checklist under the criteria. There are deliberately no sub-tasks on this board.
|
|
66
|
+
|
|
67
|
+
## Writing it
|
|
68
|
+
|
|
69
|
+
**Title**: the failure, not the area. `Checkout returns 500 for all customers
|
|
70
|
+
since the 14:02 deploy` — not `Checkout issue`. Someone scanning the board must
|
|
71
|
+
be able to tell whether this is theirs without opening it.
|
|
72
|
+
|
|
73
|
+
**Body**: the five things above, in that order, under plain headings. Keep the
|
|
74
|
+
raw error verbatim in a code block — the exact string is what someone will
|
|
75
|
+
grep for.
|
|
76
|
+
|
|
77
|
+
## Filing it
|
|
78
|
+
|
|
79
|
+
1. `list_work_boards` → pick the board. If the problem is scoped to a company
|
|
80
|
+
the workspace serves, use that company's board.
|
|
81
|
+
2. `get_work_board` → find the Triage column (the first one) and read the
|
|
82
|
+
board's `tagScheme`.
|
|
83
|
+
3. `create_work_item` with the title, the body, and `product` if you can tell
|
|
84
|
+
which one it belongs to.
|
|
85
|
+
|
|
86
|
+
**Leave `assigneeUserId` empty.** Filing a card is not picking it up, and an
|
|
87
|
+
assignee put on at filing time is a name nobody agreed to. An unowned card in the
|
|
88
|
+
first column is the honest state: it shows up in everybody's
|
|
89
|
+
`list_my_work_items` unassigned pool, which is where someone chooses to take it.
|
|
90
|
+
If you are going to work it yourself, file it unassigned and then claim it
|
|
91
|
+
properly — `ship-the-card`, one `move_work_item` with `claim: true`.
|
|
92
|
+
|
|
93
|
+
Filing it unassigned loses nothing, because **the card records who created it**
|
|
94
|
+
either way: the server stamps the creator from your authenticated session, so
|
|
95
|
+
the card can always be traced back to the person whose terminal it came from.
|
|
96
|
+
You cannot set it, and a body naming a creator is refused rather than ignored —
|
|
97
|
+
an author a tool could name would be a record of what the tool said, not of who
|
|
98
|
+
filed the card. Say "created by" and "assigned to" separately when you report
|
|
99
|
+
back; they are different people and the board keeps them apart.
|
|
100
|
+
|
|
101
|
+
Then tag it with `set_work_item_tag`, source `model` plus a `confidence`.
|
|
102
|
+
|
|
103
|
+
**The severity bar, if the board uses the severity scheme:** `critical` means
|
|
104
|
+
someone is broken right now — an outage, data loss, a security issue, or every
|
|
105
|
+
customer affected. A workaround existing usually means it is not critical. Be
|
|
106
|
+
honest about this even when the person reporting it is upset; the board's
|
|
107
|
+
credibility is what makes the next real critical get picked up fast.
|
|
108
|
+
|
|
109
|
+
If you are filing several cards from one incident, file the *symptom* people
|
|
110
|
+
hit, not one card per log line. Five cards for one root cause is five triage
|
|
111
|
+
decisions someone has to make.
|
|
112
|
+
|
|
113
|
+
## Writes
|
|
114
|
+
|
|
115
|
+
`create_work_item` and `set_work_item_tag` are governed writes: they preview by
|
|
116
|
+
default. Show the human the card you are about to file — title, body, tag — and
|
|
117
|
+
file it only after they say yes, with `dryRun: false`, `approved: true`, a
|
|
118
|
+
`reason`, and an `idempotencyKey`. Reuse the same key on retry so a flaky
|
|
119
|
+
connection does not file the same incident twice.
|
|
120
|
+
|
|
121
|
+
## After filing
|
|
122
|
+
|
|
123
|
+
Report the card id and its column. If you found something while filing that
|
|
124
|
+
suggests the cause — a recent deploy, a related card already on the board — say
|
|
125
|
+
so as a separate line, clearly marked as your inference rather than as evidence
|
|
126
|
+
from the report.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Log Outreach Skill
|
|
2
|
+
|
|
3
|
+
Use the Adrata MCP to log sales outreach interactions. This skill replaces manual Airtable logging.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
When the user says things like:
|
|
8
|
+
- "Log my LinkedIn outreach from today"
|
|
9
|
+
- "I sent a connection request to John Smith at Acme"
|
|
10
|
+
- "Log that I messaged these 5 people on LinkedIn"
|
|
11
|
+
- "Update my CRM with today's outreach"
|
|
12
|
+
|
|
13
|
+
## How it works
|
|
14
|
+
|
|
15
|
+
Use the `log_interaction` tool for each interaction. It handles everything in one call:
|
|
16
|
+
1. Finds the person by email or name (or creates them if new)
|
|
17
|
+
2. Finds the company (or creates it if new)
|
|
18
|
+
3. Creates an action with the interaction details and metadata
|
|
19
|
+
4. Optionally updates the person's custom fields
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
### Single interaction
|
|
24
|
+
```
|
|
25
|
+
User: "I sent a LinkedIn connection request to Sarah Chen, VP Engineering at Dataflow Labs. Here's the message I sent: 'Hi Sarah, I noticed Dataflow is scaling their sales team...'"
|
|
26
|
+
|
|
27
|
+
→ Call log_interaction with:
|
|
28
|
+
personName: "Sarah Chen"
|
|
29
|
+
companyName: "Dataflow Labs"
|
|
30
|
+
type: "linkedin_connection_request"
|
|
31
|
+
title: "Sent LinkedIn connection request to Sarah Chen"
|
|
32
|
+
message: "Hi Sarah, I noticed Dataflow is scaling their sales team..."
|
|
33
|
+
outcome: "pending"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Batch logging
|
|
37
|
+
```
|
|
38
|
+
User: "Log these LinkedIn messages I sent today:
|
|
39
|
+
1. John Smith at Acme - connection request - 'Hi John...'
|
|
40
|
+
2. Lisa Park at TechCorp - follow-up message - 'Thanks for connecting...'
|
|
41
|
+
3. Mike Johnson at StartupXYZ - connection request - 'Hi Mike...'"
|
|
42
|
+
|
|
43
|
+
→ Call log_interaction 3 times, once per person
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Connection accepted + meeting booked
|
|
47
|
+
```
|
|
48
|
+
User: "Sarah Chen accepted my connection and we booked a meeting for Friday"
|
|
49
|
+
|
|
50
|
+
→ Call log_interaction with:
|
|
51
|
+
personName: "Sarah Chen"
|
|
52
|
+
type: "meeting"
|
|
53
|
+
title: "Meeting booked with Sarah Chen"
|
|
54
|
+
outcome: "meeting_booked"
|
|
55
|
+
customFields: { "outreach_status": "meeting_scheduled" }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Tips
|
|
59
|
+
- Always use `log_interaction` — it's the single tool that does find-or-create + action logging in one call
|
|
60
|
+
- For checking past outreach, use `list_actions` with type and person filters
|
|
61
|
+
- For "what did I do this week?", use `get_activity_summary`
|
|
62
|
+
- For finding specific people, use `search_people`
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ship-the-card
|
|
3
|
+
description: Take a Starfield card from its column through to a change that is ready for review — read the card and its history, do the work, and move it with a reason a human can audit. Use when asked to pick up a card, work the backlog, or "do the next thing" on a board.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Ship the card
|
|
7
|
+
|
|
8
|
+
This is the loop a coding agent actually runs: read a card, do the work, move
|
|
9
|
+
the card. The part people get wrong is the last step — work that lands with the
|
|
10
|
+
board untouched is work nobody can see.
|
|
11
|
+
|
|
12
|
+
## Pick up
|
|
13
|
+
|
|
14
|
+
1. `list_my_work_items` — **start here.** It answers "what is mine", across every
|
|
15
|
+
board, already ordered the way you would pick: escalated first, then the
|
|
16
|
+
board's own left-to-right flow, then longest-waiting. You do not have to pull
|
|
17
|
+
a board and eyeball it, and you cannot accidentally read somebody else's
|
|
18
|
+
queue — "me" comes from the token, and the tool has no parameter that could
|
|
19
|
+
name anyone else.
|
|
20
|
+
2. If your queue is empty, call it again with `includeUnassigned: true`. Those
|
|
21
|
+
are the cards nobody owns, and they are the ones you may take. **A card
|
|
22
|
+
assigned to someone else is theirs** — do not work it, do not claim it. Say
|
|
23
|
+
you saw it if it is on fire, and leave it alone.
|
|
24
|
+
3. `get_work_board` for the card's board when you need the target column id —
|
|
25
|
+
`move_work_item` moves to a column id, and only `get_work_board` has them.
|
|
26
|
+
4. `get_work_item` for the full body, `get_work_item_history` for how it got
|
|
27
|
+
here, and `get_work_item_comments` for what people have SAID about it.
|
|
28
|
+
**Read both before starting.** A card that has bounced out of a review column
|
|
29
|
+
twice was rejected for a reason: the history says WHEN it bounced, the
|
|
30
|
+
comments say WHY. Repeating a rejected approach is the most expensive mistake
|
|
31
|
+
available here, and the reviewer's comment is usually the one thing that
|
|
32
|
+
would have stopped you.
|
|
33
|
+
|
|
34
|
+
**A card carrying a `flag` is not workable.** The flag means somebody has already
|
|
35
|
+
found a problem with the card ITSELF — unclear scope, no repro, a blocked
|
|
36
|
+
dependency, a question waiting on an answer — and its `reason` says which. It is
|
|
37
|
+
a different claim from the tag, which is only about urgency: a flagged Critical
|
|
38
|
+
card is still not something to start on. Read the comments for the surrounding
|
|
39
|
+
argument and pick a different card, unless you are the person who can answer it.
|
|
40
|
+
If you resolve it, clear the flag with `flag_work_item` (`flagged: false`) and
|
|
41
|
+
say what resolved it. Anyone may clear one, which is exactly why every clear is
|
|
42
|
+
recorded as a comment.
|
|
43
|
+
|
|
44
|
+
If the card is not workable — no repro, no expected behaviour, ambiguous scope —
|
|
45
|
+
**flag it** with `flag_work_item` and the one question that would unblock it,
|
|
46
|
+
then stop. Do not invent the missing half. Flagging is what turns "I could not
|
|
47
|
+
work this" into something the next person sees before they pick it up, rather
|
|
48
|
+
than a sentence in your report that nobody reads. An unworkable card is a triage
|
|
49
|
+
problem, not a coding problem.
|
|
50
|
+
|
|
51
|
+
## Claim it, in the same move, FIRST
|
|
52
|
+
|
|
53
|
+
Before you write code, move the card to the board's active column **with
|
|
54
|
+
`claim: true`**. One call, not two:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
move_work_item(itemId, toColumnId: <the active column>, claim: true,
|
|
58
|
+
dryRun: false, approved: true,
|
|
59
|
+
reason: "Picked up — reproducing against staging first",
|
|
60
|
+
idempotencyKey: "claim-<itemId>")
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Three reasons, and the third is the real one:
|
|
64
|
+
|
|
65
|
+
- claiming stops someone else picking up the same card;
|
|
66
|
+
- moving it now starts the stage timer honestly. Moving it at the end backdates
|
|
67
|
+
the work to zero and quietly corrupts the board's cycle-time history;
|
|
68
|
+
- doing both in ONE call is what makes it true. A separate "assign" step is the
|
|
69
|
+
step that gets skipped, and a card sitting in an active column with nobody's
|
|
70
|
+
name on it is exactly what the board's unassigned glyph exists to shout about.
|
|
71
|
+
|
|
72
|
+
Reuse the same `idempotencyKey` if the call fails and you retry. The server
|
|
73
|
+
replays rather than appending a second transition.
|
|
74
|
+
|
|
75
|
+
**If the claim is refused**, the card already belongs to somebody: pick a
|
|
76
|
+
different one. `force: true` exists — it takes the card over and demands a reason
|
|
77
|
+
saying why — but it is for a card whose owner is genuinely gone, not for working
|
|
78
|
+
around a refusal. Taking someone's card because it was convenient is the one move
|
|
79
|
+
on this board that costs trust permanently. If you use it, say so in your report,
|
|
80
|
+
not only in the reason field.
|
|
81
|
+
|
|
82
|
+
## Do the work
|
|
83
|
+
|
|
84
|
+
Ordinary engineering. Follow the repository's own conventions and its
|
|
85
|
+
`CLAUDE.md` / `AGENTS.md`. Nothing about this skill overrides the project's
|
|
86
|
+
rules — it only governs the board.
|
|
87
|
+
|
|
88
|
+
Two things to carry back to the card:
|
|
89
|
+
|
|
90
|
+
- if what you find contradicts the card, say so on the card rather than silently
|
|
91
|
+
fixing something else — `comment_on_work_item` is where that goes. A card that
|
|
92
|
+
says "export is slow" and turns out to be an auth timeout is a different card.
|
|
93
|
+
**Do not edit the card's body to make the point:** the body is the original
|
|
94
|
+
request, and overwriting it destroys the evidence of what was actually asked
|
|
95
|
+
for. A comment sits beside it and keeps both.
|
|
96
|
+
- if the comment needs a specific person's attention, @-mention them by writing
|
|
97
|
+
`<@userId>` in the body — the id comes from the card's assignee, its history,
|
|
98
|
+
or `list_my_work_items`. Writing `@noah` mentions nobody; that is deliberate,
|
|
99
|
+
so nothing you merely type can notify somebody by accident. Mention the person
|
|
100
|
+
who can answer, not everyone who might care: a mention means "see this" and
|
|
101
|
+
nothing else, and a thread that pings four people to reach one is how a team
|
|
102
|
+
learns to ignore them.
|
|
103
|
+
- if the fix is bigger than the card, do not quietly expand scope. Finish what
|
|
104
|
+
the card asked for and report the rest as a card that should exist. If you
|
|
105
|
+
file it yourself, file it the way `incident-to-card` says: a title, a body
|
|
106
|
+
carrying **acceptance criteria** — what would prove it done, one checkable
|
|
107
|
+
outcome per line — and no assignee. A card you file from here arrives
|
|
108
|
+
attributed to you automatically (the server stamps the creator from your
|
|
109
|
+
session), so the next person at aligning can ask you what you meant; what it
|
|
110
|
+
must not arrive with is a list of outcomes nobody can check.
|
|
111
|
+
|
|
112
|
+
## Submit it
|
|
113
|
+
|
|
114
|
+
When the change is ready for review, `move_work_item` it onward — no `claim`
|
|
115
|
+
this time, you already own it — with a `reason` that carries something a human
|
|
116
|
+
can audit:
|
|
117
|
+
|
|
118
|
+
- a branch name, or
|
|
119
|
+
- a PR link, or
|
|
120
|
+
- one line naming what changed and how it was verified.
|
|
121
|
+
|
|
122
|
+
> "Fixed the N+1 in the export query on `fix/export-n1`; added a test at 10k
|
|
123
|
+
> rows, full suite green."
|
|
124
|
+
|
|
125
|
+
That reason is the whole audit trail. Someone will read it in three weeks when
|
|
126
|
+
they are asking why this card took a week, and the card id will not tell them.
|
|
127
|
+
The tool refuses placeholder reasons — "moved", "update", "Moved to another
|
|
128
|
+
column" — on purpose: a history full of those looks like an audit trail, so
|
|
129
|
+
nobody goes looking for the real answer, which is worse than no history at all.
|
|
130
|
+
|
|
131
|
+
**Do not move a card into the terminal column** — `Production` on a default
|
|
132
|
+
board, or whatever the last column is called on this one. That is a human's call:
|
|
133
|
+
the person who reported it, or the reviewer. An agent marking its own work
|
|
134
|
+
complete is the one move on this board that nobody can trust. Stop at the review
|
|
135
|
+
or QA column and say it is ready.
|
|
136
|
+
|
|
137
|
+
## Writes
|
|
138
|
+
|
|
139
|
+
Comments and flags are governed writes too, on the same contract as a move, and
|
|
140
|
+
the idempotency key matters there for a quieter reason: a replayed comment posts
|
|
141
|
+
the same paragraph twice, which reads as you being emphatic rather than as a
|
|
142
|
+
retry.
|
|
143
|
+
|
|
144
|
+
Every move is governed: preview first, then `dryRun: false`, `approved: true`, a
|
|
145
|
+
`reason`, and an `idempotencyKey`. Reuse the same key on retry. A duplicate
|
|
146
|
+
transition makes the card read as having bounced, and the stage timer is derived
|
|
147
|
+
from exactly those rows — so a retry without a key does not just add noise, it
|
|
148
|
+
rewrites how long the work appears to have taken.
|
|
149
|
+
|
|
150
|
+
## What to report
|
|
151
|
+
|
|
152
|
+
- the card, where it is now, and whether you left it flagged;
|
|
153
|
+
- what changed, and how it was verified;
|
|
154
|
+
- anything you found that should be its own card, stated as a title someone
|
|
155
|
+
could file as-is.
|