@glie/mcp-polaris 0.1.0 → 0.2.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 +53 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { createInterface } from "readline";
|
|
6
6
|
var BASE = process.env.POLARIS_URL ?? "http://127.0.0.1:7843";
|
|
7
7
|
var TOKEN = process.env.POLARIS_TOKEN ?? "";
|
|
8
|
+
var PROJECT = process.env.POLARIS_PROJECT ?? "";
|
|
8
9
|
var log = (msg, ctx) => process.stderr.write(`mcp-polaris: ${msg}${ctx ? ` ${JSON.stringify(ctx)}` : ""}
|
|
9
10
|
`);
|
|
10
11
|
async function apiCall(method, path, body) {
|
|
@@ -41,10 +42,38 @@ function objSchema(properties, required = []) {
|
|
|
41
42
|
additionalProperties: false
|
|
42
43
|
};
|
|
43
44
|
}
|
|
45
|
+
var INSTRUCTIONS = [
|
|
46
|
+
`Polaris is the studio's operating system. All product work lives as Projects \u2192 Milestones \u2192 Tasks, and agents ("employees") move it forward. Each polaris.* tool wraps one REST call.`,
|
|
47
|
+
PROJECT ? `You are scoped to project \`${PROJECT}\` \u2014 use it as project_key/product_key unless told otherwise.` : "This connector is not pinned to a project; use polaris.project.list to find yours.",
|
|
48
|
+
"",
|
|
49
|
+
"START HERE \u2014 get what is YOURS (resolved from your token, no id lookup needed):",
|
|
50
|
+
'\u2022 agent \u2192 polaris.task.list { assignee_agent_id: "self" }',
|
|
51
|
+
'\u2022 human \u2192 polaris.task.list { assignee_human_id: "self" } (and polaris.me for your identity)',
|
|
52
|
+
" Narrow with status (e.g. dev) once you know what's assigned to you.",
|
|
53
|
+
"\u2022 polaris.claude_md.get(project_key) \u2014 read the project's conventions BEFORE you touch its tasks.",
|
|
54
|
+
"",
|
|
55
|
+
"STATE MACHINES \u2014 transitions are enforced; only legal moves succeed:",
|
|
56
|
+
"\u2022 Task: draft \u2192 backlog \u2192 dev \u2192 test \u2192 approval \u2192 release \u2192 done (any \u2192 canceled)",
|
|
57
|
+
" dev = an agent implements it & opens a PR \xB7 test = QA \xB7 approval = a human reviews \xB7 release = merged to dev/shipped.",
|
|
58
|
+
"\u2022 Milestone: draft \u2192 discovery \u2192 loop \u2192 release \u2192 done (any \u2192 canceled)",
|
|
59
|
+
" discovery = answer the framework Q&A to split it into tasks \xB7 loop = build/test/approve \xB7 release = ship.",
|
|
60
|
+
"\u2022 Stack (Release Candidate): 2+ approval tasks of ONE milestone on an rc branch, tested & shipped together \u2014",
|
|
61
|
+
" liquid (assembling) \u2192 blocked (a member conflicts) | frozen (human-resolved) \u2192 released (any \u2192 canceled).",
|
|
62
|
+
"",
|
|
63
|
+
"WHICH TOOL WHEN:",
|
|
64
|
+
`\u2022 "What's mine / what next?" \u2192 polaris.task.list (assignee \u2026="self", status=\u2026)`,
|
|
65
|
+
'\u2022 "Read X in full" \u2192 polaris.task.get \xB7 milestone.get \xB7 project.get \xB7 stack.get',
|
|
66
|
+
'\u2022 "Move my task forward" \u2192 polaris.task.transition(id, status)',
|
|
67
|
+
`\u2022 "It's reviewed, ship it" \u2192 polaris.task.approve (human-only); ship several together via polaris.stack.* \u2192 stack.release`,
|
|
68
|
+
'\u2022 "Break a milestone into tasks" \u2192 polaris.milestone.qa_list / qa_answer (while in discovery)',
|
|
69
|
+
"",
|
|
70
|
+
"Identifiers: projects by `key` (string, e.g. saasA); milestones/tasks/agents/stacks by numeric `id`. Writes need a token; reads work anonymously."
|
|
71
|
+
].join(`
|
|
72
|
+
`);
|
|
44
73
|
var TOOLS = [
|
|
45
74
|
{
|
|
46
75
|
name: "polaris.me",
|
|
47
|
-
description:
|
|
76
|
+
description: `Resolve the human your PAT belongs to (identity + org). Humans call this first; agents don't need it \u2014 they pass "self" to other tools.`,
|
|
48
77
|
inputSchema: objSchema({}),
|
|
49
78
|
call: async () => {
|
|
50
79
|
const r = await apiCall("GET", "/api/humans/me");
|
|
@@ -121,17 +150,27 @@ var TOOLS = [
|
|
|
121
150
|
},
|
|
122
151
|
{
|
|
123
152
|
name: "polaris.task.list",
|
|
124
|
-
description:
|
|
153
|
+
description: `Find tasks \u2014 the agent's entry point. Pass assignee_agent_id="self" (or assignee_human_id="self" for a human) to get what is YOURS; add status=dev (etc.) to see only active work. Other filters: milestone_id, product_key, team.`,
|
|
125
154
|
inputSchema: objSchema({
|
|
126
|
-
status: strSchema("comma-separated: backlog,dev,test
|
|
155
|
+
status: strSchema("comma-separated subset of: draft,backlog,dev,test,approval,release,done,canceled"),
|
|
127
156
|
milestone_id: intSchema(),
|
|
128
|
-
product_key: strSchema(),
|
|
157
|
+
product_key: strSchema("project key, e.g. saasA"),
|
|
129
158
|
team: strSchema("dev|mkt"),
|
|
159
|
+
assignee_agent_id: strSchema('agent id, or "self" for the calling agent'),
|
|
160
|
+
assignee_human_id: strSchema('human id, or "self" for the calling human'),
|
|
130
161
|
limit: intSchema()
|
|
131
162
|
}),
|
|
132
163
|
call: async (args) => {
|
|
133
164
|
const qs = new URLSearchParams;
|
|
134
|
-
for (const k of [
|
|
165
|
+
for (const k of [
|
|
166
|
+
"status",
|
|
167
|
+
"milestone_id",
|
|
168
|
+
"product_key",
|
|
169
|
+
"team",
|
|
170
|
+
"assignee_agent_id",
|
|
171
|
+
"assignee_human_id",
|
|
172
|
+
"limit"
|
|
173
|
+
]) {
|
|
135
174
|
const v = args[k];
|
|
136
175
|
if (v !== undefined && v !== null)
|
|
137
176
|
qs.set(k, String(v));
|
|
@@ -154,13 +193,13 @@ var TOOLS = [
|
|
|
154
193
|
},
|
|
155
194
|
{
|
|
156
195
|
name: "polaris.task.transition",
|
|
157
|
-
description: "
|
|
196
|
+
description: "Move a task to its next status when you finish a stage (e.g. dev\u2192test once your PR is up). Enforced flow: draft\u2192backlog\u2192dev\u2192test\u2192approval\u2192release\u2192done (any\u2192canceled). Illegal jumps are rejected. The approval\u2192release gate is polaris.task.approve (human-only).",
|
|
158
197
|
inputSchema: objSchema({ id: intSchema(), status: strSchema() }, ["id", "status"]),
|
|
159
198
|
call: async (args) => (await apiCall("POST", `/api/tasks/${args.id}/state`, { status: args.status })).body
|
|
160
199
|
},
|
|
161
200
|
{
|
|
162
201
|
name: "polaris.task.approve",
|
|
163
|
-
description: "
|
|
202
|
+
description: "The human review gate: approve a task in `approval` \u2192 it advances toward release. Human-only. To ship several approval tasks of one milestone together, group them into a stack and use polaris.stack.release instead.",
|
|
164
203
|
inputSchema: objSchema({ id: intSchema() }, ["id"]),
|
|
165
204
|
call: async (args) => (await apiCall("POST", `/api/tasks/${args.id}/approve`)).body
|
|
166
205
|
},
|
|
@@ -178,8 +217,8 @@ var TOOLS = [
|
|
|
178
217
|
},
|
|
179
218
|
{
|
|
180
219
|
name: "polaris.stack.list",
|
|
181
|
-
description: "List
|
|
182
|
-
inputSchema: objSchema({ status: strSchema("liquid|frozen|released|canceled") }),
|
|
220
|
+
description: "List Release-Candidate stacks (groups of approval tasks shipped together). Filter by status: liquid|blocked|frozen|released|canceled.",
|
|
221
|
+
inputSchema: objSchema({ status: strSchema("liquid|blocked|frozen|released|canceled") }),
|
|
183
222
|
call: async (args) => {
|
|
184
223
|
const qs = typeof args.status === "string" ? `?status=${encodeURIComponent(args.status)}` : "";
|
|
185
224
|
return (await apiCall("GET", `/api/stacks${qs}`)).body;
|
|
@@ -187,22 +226,16 @@ var TOOLS = [
|
|
|
187
226
|
},
|
|
188
227
|
{
|
|
189
228
|
name: "polaris.stack.get",
|
|
190
|
-
description: "
|
|
229
|
+
description: "Inspect one stack by id \u2014 its member tasks, the rc branch + PR, and (when blocked) which member failed to integrate and why.",
|
|
191
230
|
inputSchema: objSchema({ id: intSchema() }, ["id"]),
|
|
192
231
|
call: async (args) => (await apiCall("GET", `/api/stacks/${args.id}`)).body
|
|
193
232
|
},
|
|
194
233
|
{
|
|
195
234
|
name: "polaris.stack.release",
|
|
196
|
-
description: "
|
|
235
|
+
description: "Ship a stack \u2014 merge its rc PR into dev, settle members to release, then close & delete the member branches (their commits land via the rc). Human-only; barred while blocked.",
|
|
197
236
|
inputSchema: objSchema({ id: intSchema() }, ["id"]),
|
|
198
237
|
call: async (args) => (await apiCall("POST", `/api/stacks/${args.id}/release`)).body
|
|
199
238
|
},
|
|
200
|
-
{
|
|
201
|
-
name: "polaris.stack.reject",
|
|
202
|
-
description: "Reject a stack \u2014 return its member tasks to their prior state (human-only).",
|
|
203
|
-
inputSchema: objSchema({ id: intSchema() }, ["id"]),
|
|
204
|
-
call: async (args) => (await apiCall("POST", `/api/stacks/${args.id}/reject`)).body
|
|
205
|
-
},
|
|
206
239
|
{
|
|
207
240
|
name: "polaris.agent.list",
|
|
208
241
|
description: "List agents.",
|
|
@@ -223,7 +256,7 @@ var TOOLS = [
|
|
|
223
256
|
},
|
|
224
257
|
{
|
|
225
258
|
name: "polaris.claude_md.get",
|
|
226
|
-
description: "Read
|
|
259
|
+
description: "Read a project's CLAUDE.md \u2014 its conventions, stack and rules (served from main via polaris-bot). Do this BEFORE working that project's tasks.",
|
|
227
260
|
inputSchema: objSchema({ project_key: strSchema() }, ["project_key"]),
|
|
228
261
|
call: async (args) => (await apiCall("GET", `/api/projects/${args.project_key}/claude-md`)).body
|
|
229
262
|
},
|
|
@@ -252,7 +285,8 @@ async function handle(req) {
|
|
|
252
285
|
return ok(id, {
|
|
253
286
|
protocolVersion: "2024-11-05",
|
|
254
287
|
capabilities: { tools: {} },
|
|
255
|
-
serverInfo: { name: "mcp-polaris", version: "0.1.0" }
|
|
288
|
+
serverInfo: { name: "mcp-polaris", version: "0.1.0" },
|
|
289
|
+
instructions: INSTRUCTIONS
|
|
256
290
|
});
|
|
257
291
|
case "initialized":
|
|
258
292
|
return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glie/mcp-polaris",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.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>",
|