@glie/mcp-polaris 0.12.0 → 0.14.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/dist/index.js +112 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -95,6 +95,9 @@ var INSTRUCTIONS = [
|
|
|
95
95
|
`\u2022 "It's reviewed, ship it" \u2192 polaris.task.approve (human-only); ship several together via polaris.stack.* \u2192 stack.release`,
|
|
96
96
|
`\u2022 "My task is stuck in a blocked stack" \u2192 fix the conflict on YOUR branch (rebase agent/task-N onto dev, push) \u2014 the rc PR flips to ready automatically. A stacked task can't advance individually; never merge the rc PR by hand.`,
|
|
97
97
|
'\u2022 "Break a milestone into tasks" \u2192 polaris.milestone.qa_list / qa_answer (while in discovery)',
|
|
98
|
+
'\u2022 "Jot something down for later" \u2192 polaris.idea.create (a title is enough). NO dates: an idea is not a milestone.',
|
|
99
|
+
'\u2022 "What have we already thought of?" \u2192 polaris.idea.list \u2014 read it before proposing work; it also holds what was turned down',
|
|
100
|
+
'\u2022 "This idea is now real" \u2192 polaris.idea.promote (needs end_date + team) \u2014 the one door from the idea list to the timeline',
|
|
98
101
|
`\u2022 "Triage support / what's waiting?" \u2192 polaris.ticket.list (status, project_key) \u2014 P1 first`,
|
|
99
102
|
'\u2022 "Reply to a customer / hand off" \u2192 polaris.ticket.reply then polaris.ticket.pass(to)',
|
|
100
103
|
'\u2022 "Turn a report into work" \u2192 polaris.ticket.frame_issue \u2192 polaris.issue.add_task \xD7N (framing is HUMAN-only; the helpdesker proposes it)',
|
|
@@ -162,16 +165,114 @@ var TOOLS = [
|
|
|
162
165
|
},
|
|
163
166
|
{
|
|
164
167
|
name: "polaris.project.arm",
|
|
165
|
-
description: "Arm a project for auto-approval (human-only): while armed,
|
|
168
|
+
description: "Arm a project for auto-approval (human-only): while armed, a task an agent writes in `draft` (discovery's batch, a campaign's pieces) is approved into `backlog` on your behalf, with no per-task click. Tasks a person creates by hand and support work still wait in `draft`. `approval \u2192 release` is never automatic. Not retroactive: drafts already there stay. Idempotent.",
|
|
166
169
|
inputSchema: objSchema({ key: strSchema("project key (e.g. saasA)") }, ["key"]),
|
|
167
170
|
call: async (args) => (await apiCall("POST", `/api/projects/${args.key}/arm`)).body
|
|
168
171
|
},
|
|
169
172
|
{
|
|
170
173
|
name: "polaris.project.disarm",
|
|
171
|
-
description: "Disarm a project (human-only). Immediate effect: the next task
|
|
174
|
+
description: "Disarm a project (human-only). Immediate effect: the next task an agent writes in `draft` waits for a person again. Tasks already moved to `backlog` stay there. Idempotent.",
|
|
172
175
|
inputSchema: objSchema({ key: strSchema("project key (e.g. saasA)") }, ["key"]),
|
|
173
176
|
call: async (args) => (await apiCall("POST", `/api/projects/${args.key}/disarm`)).body
|
|
174
177
|
},
|
|
178
|
+
{
|
|
179
|
+
name: "polaris.idea.list",
|
|
180
|
+
description: "List a project's IDEAS \u2014 what might matter later, before it has a date. An idea is not a milestone: no dates, no tasks, never on the timeline. Read this before proposing new work: it is where the things already thought of (and the things already turned down) live. Optional status filter: open|promoted|dropped.",
|
|
181
|
+
inputSchema: objSchema({
|
|
182
|
+
project_key: strSchema("project key (e.g. saasA)"),
|
|
183
|
+
status: strSchema("open|promoted|dropped")
|
|
184
|
+
}, ["project_key"]),
|
|
185
|
+
call: async (args) => {
|
|
186
|
+
const qs = typeof args.status === "string" ? `?status=${args.status}` : "";
|
|
187
|
+
return (await apiCall("GET", `/api/projects/${args.project_key}/ideas${qs}`)).body;
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: "polaris.idea.create",
|
|
192
|
+
description: "Capture an idea in a project. The title is the only required field \u2014 capturing has to cost less than losing the idea. No dates: if it has a deadline it is a milestone, so use polaris.milestone.create instead. Needs a token.",
|
|
193
|
+
inputSchema: objSchema({
|
|
194
|
+
project_key: strSchema("project key (e.g. saasA)"),
|
|
195
|
+
title: strSchema("one line \u2014 what the idea is"),
|
|
196
|
+
note_md: strSchema("optional: what it is and why now; becomes the milestone's description on promotion"),
|
|
197
|
+
team: strSchema("optional: dev|mkt \u2014 leave empty if you don't know yet")
|
|
198
|
+
}, ["project_key", "title"]),
|
|
199
|
+
call: async (args) => {
|
|
200
|
+
const { project_key, ...body } = args;
|
|
201
|
+
return (await apiCall("POST", `/api/projects/${project_key}/ideas`, body)).body;
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: "polaris.idea.update",
|
|
206
|
+
description: "Refine an open idea \u2014 its title, note or team. A promoted idea is refused: it became a milestone, and the milestone is the truth from then on (use polaris.milestone.update). Needs a token.",
|
|
207
|
+
inputSchema: objSchema({
|
|
208
|
+
project_key: strSchema(),
|
|
209
|
+
id: intSchema("idea id"),
|
|
210
|
+
title: strSchema(),
|
|
211
|
+
note_md: strSchema(),
|
|
212
|
+
team: strSchema("dev|mkt")
|
|
213
|
+
}, ["project_key", "id"]),
|
|
214
|
+
call: async (args) => {
|
|
215
|
+
const { project_key, id, ...body } = args;
|
|
216
|
+
return (await apiCall("PATCH", `/api/projects/${project_key}/ideas/${id}`, body)).body;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: "polaris.idea.promote",
|
|
221
|
+
description: "Promote an idea into a milestone \u2014 the one door between the idea list and the timeline. Demands what a milestone demands: end_date, and a team (unless the idea already carries one). The milestone is created and the idea stamped in ONE transaction; promoting twice returns the first milestone and writes nothing. Needs a token.",
|
|
222
|
+
inputSchema: objSchema({
|
|
223
|
+
project_key: strSchema(),
|
|
224
|
+
id: intSchema("idea id"),
|
|
225
|
+
end_date: strSchema("YYYY-MM-DD \u2014 the deadline the milestone commits to"),
|
|
226
|
+
team: strSchema("dev|mkt \u2014 required unless the idea already has one"),
|
|
227
|
+
start_date: strSchema("YYYY-MM-DD, optional"),
|
|
228
|
+
name: strSchema("optional: overrides the idea's title"),
|
|
229
|
+
description_md: strSchema("optional: overrides the idea's note"),
|
|
230
|
+
framework_key: strSchema("optional: e.g. feature, marketing")
|
|
231
|
+
}, ["project_key", "id", "end_date"]),
|
|
232
|
+
call: async (args) => {
|
|
233
|
+
const { project_key, id, ...body } = args;
|
|
234
|
+
return (await apiCall("POST", `/api/projects/${project_key}/ideas/${id}/promote`, body)).body;
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
name: "polaris.idea.drop",
|
|
239
|
+
description: "Drop an idea, with the reason it was dropped. Reversible (polaris.idea.reopen) \u2014 dropping is not a one-way door, because almost every good idea looks bad at first. Idempotent: dropping twice keeps the first reason. Needs a token.",
|
|
240
|
+
inputSchema: objSchema({
|
|
241
|
+
project_key: strSchema(),
|
|
242
|
+
id: intSchema("idea id"),
|
|
243
|
+
reason: strSchema("why it was dropped")
|
|
244
|
+
}, ["project_key", "id"]),
|
|
245
|
+
call: async (args) => {
|
|
246
|
+
const { project_key, id, ...body } = args;
|
|
247
|
+
return (await apiCall("POST", `/api/projects/${project_key}/ideas/${id}/drop`, body)).body;
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
name: "polaris.idea.reopen",
|
|
252
|
+
description: "Put a dropped idea back on the open list, clearing its reason. Required before promoting a dropped idea \u2014 resurrecting is a decision, not a side effect. Needs a token.",
|
|
253
|
+
inputSchema: objSchema({ project_key: strSchema(), id: intSchema("idea id") }, [
|
|
254
|
+
"project_key",
|
|
255
|
+
"id"
|
|
256
|
+
]),
|
|
257
|
+
call: async (args) => (await apiCall("POST", `/api/projects/${args.project_key}/ideas/${args.id}/reopen`, {})).body
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: "polaris.project.pause_publishing",
|
|
261
|
+
description: "Pause publishing through Polaris for a product (human-only). While paused, no creative of this product goes out at its scheduled hour. It does NOT hold the clock: a piece whose hour passes meanwhile comes back to the person in `release`, like any other late piece \u2014 that is what pausing is for. Idempotent: a second call keeps the original pause, and the original reason. `reason` is optional and is what whoever finds it paused reads.",
|
|
262
|
+
inputSchema: objSchema({
|
|
263
|
+
key: strSchema("project key (e.g. saasA)"),
|
|
264
|
+
reason: strSchema("why publishing was stopped \u2014 read by whoever finds it paused")
|
|
265
|
+
}, ["key"]),
|
|
266
|
+
call: async (args) => (await apiCall("POST", `/api/projects/${args.key}/pause-publishing`, {
|
|
267
|
+
reason: args.reason
|
|
268
|
+
})).body
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
name: "polaris.project.resume_publishing",
|
|
272
|
+
description: "Resume publishing through Polaris (human-only). Immediate: the next pass publishes whatever is still inside its 15-minute window; anything past it has already gone back to the person. Idempotent.",
|
|
273
|
+
inputSchema: objSchema({ key: strSchema("project key (e.g. saasA)") }, ["key"]),
|
|
274
|
+
call: async (args) => (await apiCall("POST", `/api/projects/${args.key}/resume-publishing`)).body
|
|
275
|
+
},
|
|
175
276
|
{
|
|
176
277
|
name: "polaris.milestone.list",
|
|
177
278
|
description: "List milestones in a project.",
|
|
@@ -325,18 +426,19 @@ var TOOLS = [
|
|
|
325
426
|
},
|
|
326
427
|
{
|
|
327
428
|
name: "polaris.task.create",
|
|
328
|
-
description: "Create a task within a milestone.
|
|
429
|
+
description: "Create a task within a milestone. A marketing CREATIVE (a task in an mkt campaign) carries WHERE IT GOES: `presence_id`, one of the destinations from polaris.destination.list. The channel and the market are read from that destination, and sending them here is refused. It also takes format + scheduled_date (the publish day / calendar slot) + platform (if this creative is individually paid). A CAROUSEL (format=carrossel) also requires `slides` (2..10) \u2014 without it the call is refused, because a carousel with no declared size ships one image.",
|
|
329
430
|
inputSchema: objSchema({
|
|
330
431
|
milestone_id: intSchema(),
|
|
331
432
|
name: strSchema(),
|
|
332
433
|
description_md: strSchema(),
|
|
333
434
|
status: strSchema("draft \u2014 the only status a task can be created in; it reaches the rest by being moved, one legal step at a time (polaris.task.transition)"),
|
|
334
|
-
|
|
435
|
+
presence_id: intSchema("mkt: WHERE THE PIECE GOES \u2014 the id of one of the product's destinations " + "(polaris.destination.list). Required for a creative; the channel and the market come " + "from it. A place the product is not on is refused, with the reason."),
|
|
335
436
|
format: strSchema("mkt: post, carrossel, reel, story, artigo, \u2026"),
|
|
336
437
|
slides: intSchema("mkt: REQUIRED when format is a carousel \u2014 how many images the piece has (2..10). " + "It is a contract: the generator delivers exactly this many. Omit for every other format."),
|
|
337
438
|
medium: strSchema("mkt: what the piece IS \u2014 image | video | text. The engine follows it (Codex, Remotion, " + "the writer). A carousel is `image` with slides > 1: only an image has more than one."),
|
|
338
439
|
surface: strSchema("mkt: where it publishes \u2014 feed | stories | reels | shorts | article | newsletter. It is " + "what separates a reel from a story: same medium, same 9:16, different place (and a " + "story is gone in 24h)."),
|
|
339
440
|
aspect: strSchema("mkt: the piece's SHAPE \u2014 1:1 | 4:5 | 9:16 | 16:9 | 2:3. The format says what the piece " + "IS (post, carrossel, reel), this says how it is framed, and they are independent: a " + "carousel can be vertical, a reel can be square. Omit to take the channel's usual one."),
|
|
441
|
+
link_url: strSchema("mkt: WHERE THE PIECE SENDS THE READER \u2014 the full URL, tracking parameters already in " + "it. Required on a PAID piece: the network does not create an ad without a " + "destination, and the click leaves through the ad itself. On an organic piece it is " + "optional, because there the link travels in the body text."),
|
|
340
442
|
output_type: strSchema("pr|post|video|email|generic \u2014 the delivery medium. Omit it: the format decides (reel/v\xEDdeo/short \u2192 video). Only pass it to override."),
|
|
341
443
|
scheduled_date: strSchema("mkt: publish day (ISO date) \u2014 the calendar slot"),
|
|
342
444
|
platform: strSchema("mkt: ad platform if this creative is individually paid"),
|
|
@@ -406,7 +508,8 @@ var TOOLS = [
|
|
|
406
508
|
name: strSchema(),
|
|
407
509
|
description_md: strSchema("full markdown brief; replaces the current description"),
|
|
408
510
|
asset_url: strSchema("mkt: URL of the produced creative asset (image/video) for the reviewer"),
|
|
409
|
-
output_type: strSchema("pr|post|video|email|generic \u2014 fix the delivery medium of a task filed with the wrong one (it routes the worker to the video or the image pipeline).")
|
|
511
|
+
output_type: strSchema("pr|post|video|email|generic \u2014 fix the delivery medium of a task filed with the wrong one (it routes the worker to the video or the image pipeline)."),
|
|
512
|
+
link_url: strSchema("mkt: where the piece sends the reader \u2014 the full URL with its tracking parameters. A " + "PAID piece cannot go to review without one: the network does not create an ad with " + 'no destination. Send "" to clear it.')
|
|
410
513
|
}, ["id"]),
|
|
411
514
|
call: async (args) => {
|
|
412
515
|
const body = {};
|
|
@@ -418,6 +521,8 @@ var TOOLS = [
|
|
|
418
521
|
body.asset_url = args.asset_url;
|
|
419
522
|
if (typeof args.output_type === "string")
|
|
420
523
|
body.output_type = args.output_type;
|
|
524
|
+
if (typeof args.link_url === "string")
|
|
525
|
+
body.link_url = args.link_url;
|
|
421
526
|
return (await apiCall("PATCH", `/api/tasks/${args.id}`, body)).body;
|
|
422
527
|
}
|
|
423
528
|
},
|
|
@@ -442,7 +547,7 @@ var TOOLS = [
|
|
|
442
547
|
},
|
|
443
548
|
{
|
|
444
549
|
name: "polaris.task.schedule",
|
|
445
|
-
description:
|
|
550
|
+
description: 'Schedule a mkt creative for publication: release \u2192 agendado, and the publisher takes it to `done` when its time arrives. The creative must be bound to an active social account (resolved from its market + channel) and have a publish_at in the future. Its copy is frozen while scheduled \u2014 editing it requires unscheduling first. The hour is not a promise the clock keeps at any cost (docs/spec/publishing.md, "Rules \u2014 the brakes on publishing through Polaris"): more than 15 minutes past it the piece is NOT published, it comes back to `release` carrying the reason, because a post at the wrong hour is not the post that was planned. Publishing is also skipped entirely while the product is paused (polaris.project.pause_publishing), and a piece whose hour passes meanwhile comes back the same way.',
|
|
446
551
|
inputSchema: objSchema({ id: intSchema() }, ["id"]),
|
|
447
552
|
call: async (args) => (await apiCall("POST", `/api/tasks/${args.id}/schedule`)).body
|
|
448
553
|
},
|
|
@@ -781,7 +886,7 @@ var TOOLS = [
|
|
|
781
886
|
},
|
|
782
887
|
{
|
|
783
888
|
name: "polaris.social_account.list",
|
|
784
|
-
description: "The social accounts connected to publish through: a product's (`key`), or the organization's own when `key` is left out \u2014 the company's identity, which publishes as the company and not as a product. Each account says its channel, handle, market and timezone, whether it is `schedulable` (market and timezone set), and whether its credential needs a person (`token_expired`). No credential ever comes back. Connecting is a person's job, through the provider's consent screen; read this to know where a creative can go.",
|
|
889
|
+
description: "The social accounts connected to publish through: a product's (`key`), or the organization's own when `key` is left out \u2014 the company's identity, which publishes as the company and not as a product. Each account says its channel, handle, market and timezone, whether it is `schedulable` (market and timezone set), and whether its credential needs a person (`token_expired`). It also says `settings_problem`: what the NETWORK still requires of this account before anything can go out through it, in a sentence naming the field and where to set it, or null when nothing is missing. A YouTube channel needs a video category (YouTube refuses the upload without one) and an answer to whether its content is made for children (a legal declaration its API never asks for). No credential ever comes back. Connecting is a person's job, through the provider's consent screen; read this to know where a creative can go.",
|
|
785
890
|
inputSchema: objSchema({
|
|
786
891
|
key: strSchema("project key; leave it out for the organization's own accounts")
|
|
787
892
|
}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glie/mcp-polaris",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Model Context Protocol (stdio) server exposing Polaris, glie's ops platform, as native tools in Claude Code and any MCP client.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "glie <carlos@glie.ai>",
|