@aioproductoscom/mcp 0.15.2 → 0.15.4
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/client.js +12 -0
- package/dist/index.js +39 -4
- package/package.json +6 -7
package/dist/client.js
CHANGED
|
@@ -48,6 +48,18 @@ export class PlatformClient {
|
|
|
48
48
|
createTask(body) {
|
|
49
49
|
return this.req("/api/pm/tasks", { method: "POST", body: JSON.stringify(body) });
|
|
50
50
|
}
|
|
51
|
+
createFeature(body) {
|
|
52
|
+
return this.req("/api/me/features", { method: "POST", body: JSON.stringify(body) });
|
|
53
|
+
}
|
|
54
|
+
createObjective(body) {
|
|
55
|
+
return this.req("/api/me/objectives", { method: "POST", body: JSON.stringify(body) });
|
|
56
|
+
}
|
|
57
|
+
createSprint(body) {
|
|
58
|
+
return this.req("/api/me/sprints", { method: "POST", body: JSON.stringify(body) });
|
|
59
|
+
}
|
|
60
|
+
createPage(body) {
|
|
61
|
+
return this.req("/api/me/pages", { method: "POST", body: JSON.stringify(body) });
|
|
62
|
+
}
|
|
51
63
|
updateTask(id, body) {
|
|
52
64
|
return this.req(`/api/pm/tasks/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(body) });
|
|
53
65
|
}
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,7 @@ function text(data) {
|
|
|
23
23
|
function promptMsg(body) {
|
|
24
24
|
return { messages: [{ role: "user", content: { type: "text", text: body } }] };
|
|
25
25
|
}
|
|
26
|
-
const server = new McpServer({ name: "AIOProductOS", version: "0.15.
|
|
26
|
+
const server = new McpServer({ name: "AIOProductOS", version: "0.15.4" }, {
|
|
27
27
|
instructions: "You manage product work on AIOProductOS for the connected member — board, insights, features, and " +
|
|
28
28
|
"analytics all hang off one spine. Call get_pm_playbook first for how to operate: ground in " +
|
|
29
29
|
"get_product_brain, keep work tied to the spine (insight→feature→task→outcome), and prioritize on " +
|
|
@@ -49,6 +49,41 @@ server.tool("create_task", "Create a task and return the created task. A write
|
|
|
49
49
|
insight_id: z.string().optional().describe("Link to an insight (optional)."),
|
|
50
50
|
assignee_member_ids: z.array(z.string()).optional().describe("Member ids to assign, from pm_meta (optional)."),
|
|
51
51
|
}, async (a) => text(await client.createTask(a)));
|
|
52
|
+
server.tool("create_feature", "Create a feature on the product spine and return it (id, key, name, status). The key is generated from the name; status starts 'active'. product_id defaults to the org's primary product when omitted — pass one from whoami for a multi-product org. Only name is required; create the feature before linking tasks to it with create_task.", {
|
|
53
|
+
name: z.string().describe("Feature name (the only required field), e.g. 'SAML SSO'."),
|
|
54
|
+
description: z.string().optional().describe("What the feature is / why it matters (optional)."),
|
|
55
|
+
product_id: z.string().optional().describe("Product to create it under, from whoami (optional; the org's primary product when omitted)."),
|
|
56
|
+
}, async (a) => text(await client.createFeature(a)));
|
|
57
|
+
server.tool("create_objective", "Create an objective (OKR), optionally with key results, and return it. period is free text (e.g. 'Q3 2026'); product_id and parent_id (a parent objective) are optional and verified in-org. Each key result takes name + optional unit / start_value / target_value. Only name is required.", {
|
|
58
|
+
name: z.string().describe("Objective name (the only required field), e.g. 'Reach $50k MRR'."),
|
|
59
|
+
description: z.string().optional().describe("Context for the objective (optional)."),
|
|
60
|
+
period: z.string().optional().describe("Free-text period, e.g. 'Q3 2026' (optional)."),
|
|
61
|
+
product_id: z.string().optional().describe("Product to scope it to, from whoami (optional)."),
|
|
62
|
+
parent_id: z.string().optional().describe("Parent objective id to nest under (optional)."),
|
|
63
|
+
key_results: z
|
|
64
|
+
.array(z.object({
|
|
65
|
+
name: z.string().describe("Key result name, e.g. 'MRR'."),
|
|
66
|
+
unit: z.string().optional().describe("Unit, e.g. 'USD' or '%' (optional)."),
|
|
67
|
+
start_value: z.number().optional().describe("Starting value (optional; default 0)."),
|
|
68
|
+
target_value: z.number().optional().describe("Target value (optional)."),
|
|
69
|
+
}))
|
|
70
|
+
.optional()
|
|
71
|
+
.describe("Key results to attach (optional; up to 10)."),
|
|
72
|
+
}, async (a) => text(await client.createObjective(a)));
|
|
73
|
+
server.tool("create_sprint", "Create a sprint and return it (id, name, goal, state, dates). state is 'future' (default) or 'active'; start_date / end_date are optional ISO 8601. Only name is required. Schedule tasks into it by passing the returned sprint id as sprint_id on create_task / update_task.", {
|
|
74
|
+
name: z.string().describe("Sprint name (the only required field), e.g. 'Sprint 12'."),
|
|
75
|
+
goal: z.string().optional().describe("The sprint goal (optional)."),
|
|
76
|
+
state: z.enum(["future", "active"]).optional().describe("Lifecycle state (optional; default 'future')."),
|
|
77
|
+
start_date: z.string().optional().describe("Start, ISO 8601 e.g. '2026-07-15T00:00:00Z' (optional)."),
|
|
78
|
+
end_date: z.string().optional().describe("End, ISO 8601 (optional)."),
|
|
79
|
+
}, async (a) => text(await client.createSprint(a)));
|
|
80
|
+
server.tool("create_page", "Create a Page (in-product doc / PRD on the spine) and return it (id, title). `body` is plain text — blank-line-separated blocks become paragraphs; omit it for a blank page. title defaults to 'Untitled'. product_id / parent_id (a parent page) are optional and verified in-org.", {
|
|
81
|
+
title: z.string().optional().describe("Page title (optional; 'Untitled' when omitted)."),
|
|
82
|
+
body: z.string().optional().describe("Page content as plain text; blank lines separate paragraphs (optional)."),
|
|
83
|
+
icon: z.string().optional().describe("An emoji icon for the page (optional)."),
|
|
84
|
+
product_id: z.string().optional().describe("Product to scope it to, from whoami (optional)."),
|
|
85
|
+
parent_id: z.string().optional().describe("Parent page id to nest under (optional)."),
|
|
86
|
+
}, async (a) => text(await client.createPage(a)));
|
|
52
87
|
server.tool("update_task", "Update one or more of a task's fields and return the updated task; fields you omit are left unchanged (idempotent — re-sending the same values is a no-op), and passing null clears a nullable field. Resolve ids first — the task via list_tasks/get_task, and status/feature/insight/member ids via pm_meta — never guess them. Only id is required.", {
|
|
53
88
|
id: z.string().describe("Task id, from list_tasks or get_task."),
|
|
54
89
|
title: z.string().optional().describe("New title (optional)."),
|
|
@@ -64,7 +99,7 @@ server.tool("comment_on_task", "Add a comment to a task, authored as the connect
|
|
|
64
99
|
body: z.string().describe("Comment body."),
|
|
65
100
|
}, async (a) => text(await client.comment(a.id, a.body)));
|
|
66
101
|
server.tool("get_product_brain", "Read a grounded, read-only snapshot of the org's product so YOU can reason about it on your own model: revenue + top paying accounts, web + product analytics, features, recent verbatim customer signals, and open work. Optional product_id; omit for the primary product. Returns the brain text plus the list of products you can ask about.", { product_id: z.string().optional().describe("Product id, from whoami (optional; primary by default).") }, async (a) => text(await client.brain(a.product_id)));
|
|
67
|
-
server.tool("get_customer_360", "Everything about ONE customer, resolved by id, email, domain, or company name: profile, subscription + MRR, how many users sit under the account, and their verbatim feedback. Read-only; returns the
|
|
102
|
+
server.tool("get_customer_360", "Everything about ONE customer, resolved by id, email, domain, or company name: profile, subscription + MRR, how many users sit under the account, and their verbatim feedback (newest first). Read-only; returns the single best-matching account, or an empty result when nothing matches. The money + people + voice join on one record — use it before answering anything about a specific account.", { query: z.string().describe("The account to resolve — an account id (exact), a user's email (exact), a company domain like 'acme.com', or a company name (partial match). Pass one value; the strongest match wins.") }, async (a) => text(await client.customer360(a.query)));
|
|
68
103
|
server.tool("analyze_nps", "NPS for the product — standard score AND revenue-weighted NPS (each respondent weighted by their account MRR), plus the detractor accounts ranked by what they're worth, with verbatims. The revenue weighting is the spine join no standalone survey tool can compute: it surfaces when your biggest customers are the unhappy ones even if the headline score looks fine. Optional product_id (primary by default) and window_days (default 90).", {
|
|
69
104
|
product_id: z.string().optional().describe("Product id, from whoami (optional; primary by default)."),
|
|
70
105
|
window_days: z.number().optional().describe("Window in days (default 90)."),
|
|
@@ -113,9 +148,9 @@ server.tool("reschedule_booking", "Move a booking to a new start time and return
|
|
|
113
148
|
start: z.string().describe("New start time, ISO 8601 (e.g. 2026-06-20T15:00:00Z); must be an open slot."),
|
|
114
149
|
}, async (a) => text(await client.schedulingAction({ action: "reschedule", booking_id: a.booking_id, start: a.start })));
|
|
115
150
|
server.tool("list_channels", "List the team Comms channels you (this token's member) belong to — id, name, kind, topic. Read-only; returns your channels, empty when you belong to none (an admin adds you in AIOProductOS → Comms). These are the channels you can read_channel and post_to_channel into.", {}, async () => text(await client.listChannels()));
|
|
116
|
-
server.tool("read_channel", "Read recent messages in a Comms channel you belong to
|
|
151
|
+
server.tool("read_channel", "Read recent messages in a Comms channel you belong to, oldest→newest, so you can catch up before replying. Read-only; returns each message with its author, body, and timestamp — empty when the channel is silent. Resolve the channel_id first with list_channels — never guess it. Pass limit to cap how many of the most-recent messages come back; the server applies a default when it's omitted.", {
|
|
117
152
|
channel_id: z.string().describe("Channel id, from list_channels."),
|
|
118
|
-
limit: z.number().optional().describe("
|
|
153
|
+
limit: z.number().int().positive().optional().describe("Maximum number of most-recent messages to return (optional; the server applies a sensible default when omitted)."),
|
|
119
154
|
}, async (a) => text(await client.readChannel(a.channel_id, a.limit)));
|
|
120
155
|
server.tool("post_to_channel", "Post a message into a team Comms channel you belong to and return the posted message. It goes out as you (this token's member) and appears live for your teammates — use it to tell the team what you did, share a link, or ask a question. Resolve the channel_id first with list_channels; only works for channels you're a member of.", {
|
|
121
156
|
channel_id: z.string().describe("Channel id, from list_channels."),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aioproductoscom/mcp",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.4",
|
|
4
4
|
"mcpName": "com.aioproductos/mcp",
|
|
5
5
|
"description": "AIOProductOS MCP — manage the board, read your product brain + analytics, and run the support inbox from Claude Code, Cursor, Codex, and any MCP host.",
|
|
6
6
|
"type": "module",
|
|
@@ -37,11 +37,6 @@
|
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
|
-
"scripts": {
|
|
41
|
-
"build": "tsc",
|
|
42
|
-
"prepublishOnly": "npm run build",
|
|
43
|
-
"start": "node dist/index.js"
|
|
44
|
-
},
|
|
45
40
|
"dependencies": {
|
|
46
41
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
47
42
|
"zod": "^3.23.8"
|
|
@@ -49,5 +44,9 @@
|
|
|
49
44
|
"devDependencies": {
|
|
50
45
|
"@types/node": "^22.7.0",
|
|
51
46
|
"typescript": "^5.6.0"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc",
|
|
50
|
+
"start": "node dist/index.js"
|
|
52
51
|
}
|
|
53
|
-
}
|
|
52
|
+
}
|