@aioproductoscom/mcp 0.8.0 → 0.10.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 +4 -0
- package/dist/client.js +21 -0
- package/dist/index.js +13 -7
- package/dist/pm-skill.js +40 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,6 +61,10 @@ at a self-hosted platform.
|
|
|
61
61
|
| `list_bookings` | scheduled calls/meetings (upcoming by default) |
|
|
62
62
|
| `cancel_booking` | cancel a booking (frees the slot, cancels the meeting) |
|
|
63
63
|
| `reschedule_booking` | move a booking to a new open slot |
|
|
64
|
+
| `list_channels` | the team Comms channels you belong to |
|
|
65
|
+
| `read_channel` | recent messages in a channel (catch up before replying) |
|
|
66
|
+
| `post_to_channel` | post into a team channel — visible live to teammates, as you |
|
|
67
|
+
| `reply_in_channel` | reply in a thread under a message |
|
|
64
68
|
|
|
65
69
|
> For an assignable **coding teammate** (Backend / Frontend / Mobile / QA that
|
|
66
70
|
> opens PRs in your repo), install the separate
|
package/dist/client.js
CHANGED
|
@@ -114,4 +114,25 @@ export class PlatformClient {
|
|
|
114
114
|
schedulingAction(body) {
|
|
115
115
|
return this.req("/api/me/scheduling", { method: "POST", body: JSON.stringify(body) });
|
|
116
116
|
}
|
|
117
|
+
listChannels() {
|
|
118
|
+
return this.req("/api/me/comms");
|
|
119
|
+
}
|
|
120
|
+
readChannel(channelId, limit) {
|
|
121
|
+
const p = new URLSearchParams({ channel_id: channelId });
|
|
122
|
+
if (limit)
|
|
123
|
+
p.set("limit", String(limit));
|
|
124
|
+
return this.req(`/api/me/comms?${p.toString()}`);
|
|
125
|
+
}
|
|
126
|
+
postToChannel(channelId, body) {
|
|
127
|
+
return this.req("/api/me/comms", {
|
|
128
|
+
method: "POST",
|
|
129
|
+
body: JSON.stringify({ action: "post", channel_id: channelId, body }),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
replyInChannel(channelId, parentId, body) {
|
|
133
|
+
return this.req("/api/me/comms", {
|
|
134
|
+
method: "POST",
|
|
135
|
+
body: JSON.stringify({ action: "reply", channel_id: channelId, parent_id: parentId, body }),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
117
138
|
}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { PlatformClient } from "./client.js";
|
|
6
|
+
import { PM_PLAYBOOK, PM_SKILL_VERSION } from "./pm-skill.js";
|
|
6
7
|
const token = process.env.PRODUCTOS_TOKEN;
|
|
7
8
|
const baseUrl = (process.env.PRODUCTOS_URL ?? "https://platform.aioproductos.com").replace(/\/$/, "");
|
|
8
9
|
if (!token) {
|
|
@@ -17,15 +18,16 @@ function text(data) {
|
|
|
17
18
|
],
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
|
-
const server = new McpServer({ name: "productos", version: "0.
|
|
21
|
-
instructions: "You manage
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"writes you actually made.",
|
|
21
|
+
const server = new McpServer({ name: "productos", version: "0.10.0" }, {
|
|
22
|
+
instructions: "You manage product work on ProductOS for the connected member — board, insights, features, and " +
|
|
23
|
+
"analytics all hang off one spine. Call get_pm_playbook first for how to operate: ground in " +
|
|
24
|
+
"get_product_brain, keep work tied to the spine (insight→feature→task→outcome), and prioritize on " +
|
|
25
|
+
"evidence (affected accounts + MRR + reach), never an invented score. Resolve names to ids with " +
|
|
26
|
+
"pm_meta before create_task / update_task; never guess an id. Confirm what you changed in plain " +
|
|
27
|
+
"language, and claim only writes you actually made.",
|
|
27
28
|
});
|
|
28
29
|
server.tool("whoami", "Show the connected ProductOS identity (org, member).", {}, async () => text(await client.whoami()));
|
|
30
|
+
server.tool("get_pm_playbook", "How to operate as a product manager on ProductOS — ground in the brain, keep work tied to the spine (insight→feature→task→outcome), and prioritize on evidence (affected accounts + MRR + reach), never an invented score. Read this before planning or prioritizing.", {}, async () => text(`${PM_PLAYBOOK}\n\n— pm playbook v${PM_SKILL_VERSION}`));
|
|
29
31
|
server.tool("pm_meta", "List the org's PM lists, statuses, members, and features — use to resolve names to ids before create/update.", {}, async () => text(await client.meta()));
|
|
30
32
|
server.tool("list_tasks", "List tasks in the org. Optional filters: status_id, list_id.", { status_id: z.string().optional(), list_id: z.string().optional() }, async (a) => text(await client.listTasks(a)));
|
|
31
33
|
server.tool("get_task", "Get one task with its comments and assignees.", { id: z.string() }, async (a) => text(await client.getTask(a.id)));
|
|
@@ -70,6 +72,10 @@ server.tool("resolve_conversation", "Mark a support conversation resolved (statu
|
|
|
70
72
|
server.tool("list_bookings", "List scheduled bookings (calls/meetings) — upcoming confirmed ones by default; pass include='all' for past + cancelled. Each has id, event type, guest, host, start/end, and status.", { include: z.enum(["all"]).optional() }, async (a) => text(await client.listBookings({ include: a.include })));
|
|
71
73
|
server.tool("cancel_booking", "Cancel a booking by id — frees the slot and cancels the linked meeting. Cannot cancel a meeting that has already started.", { booking_id: z.string() }, async (a) => text(await client.schedulingAction({ action: "cancel", booking_id: a.booking_id })));
|
|
72
74
|
server.tool("reschedule_booking", "Move a booking to a new start time (ISO 8601, e.g. 2026-06-20T15:00:00Z). The new time must be a currently-open slot for that event type. Cannot reschedule a meeting that has already started.", { booking_id: z.string(), start: z.string() }, async (a) => text(await client.schedulingAction({ action: "reschedule", booking_id: a.booking_id, start: a.start })));
|
|
75
|
+
server.tool("list_channels", "List the team Comms channels you (this token's member) belong to — id, name, kind, topic. These are the channels you can read and post into. An admin adds you to a channel in ProductOS → Comms.", {}, async () => text(await client.listChannels()));
|
|
76
|
+
server.tool("read_channel", "Read recent messages in a Comms channel you belong to (oldest→newest), so you can catch up before replying. Pass the channel_id from list_channels.", { channel_id: z.string(), limit: z.number().optional() }, async (a) => text(await client.readChannel(a.channel_id, a.limit)));
|
|
77
|
+
server.tool("post_to_channel", "Post a message into a team Comms channel you belong to. 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. Only works for channels you're a member of (see list_channels).", { channel_id: z.string(), body: z.string() }, async (a) => text(await client.postToChannel(a.channel_id, a.body)));
|
|
78
|
+
server.tool("reply_in_channel", "Reply in a thread under a specific message in a Comms channel you belong to. Pass the parent message's id (from read_channel) as parent_id.", { channel_id: z.string(), parent_id: z.string(), body: z.string() }, async (a) => text(await client.replyInChannel(a.channel_id, a.parent_id, a.body)));
|
|
73
79
|
async function main() {
|
|
74
80
|
await server.connect(new StdioServerTransport());
|
|
75
81
|
}
|
package/dist/pm-skill.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// The PM operating playbook — OUR product logic, handed to the customer's PM-side
|
|
2
|
+
// agent via get_pm_playbook() so it works like a great PM grounded in ProductOS,
|
|
3
|
+
// not a generic ticket bot. The server's `instructions` points at it; the agent
|
|
4
|
+
// pulls the full doctrine on demand (keeps it out of every session's context).
|
|
5
|
+
//
|
|
6
|
+
// Bump PM_SKILL_VERSION on any behavioural change so a run traces to a playbook.
|
|
7
|
+
export const PM_SKILL_VERSION = "0.1.0";
|
|
8
|
+
export const PM_PLAYBOOK = `# ProductOS · Product Manager
|
|
9
|
+
|
|
10
|
+
You operate the product on ProductOS for the connected member. The board, insights, features, and
|
|
11
|
+
analytics all hang off one spine — your job is to keep work tied to the real why and to decide from evidence.
|
|
12
|
+
|
|
13
|
+
## Ground yourself first
|
|
14
|
+
Call \`get_product_brain\` before you reason about priorities: a live, read-only snapshot of THIS product —
|
|
15
|
+
revenue and top accounts, web + product analytics, features, recent verbatim customer signals, and the open
|
|
16
|
+
work. Decide from it, not from memory. Use \`pm_meta\` to resolve names → ids before any write; never guess an id.
|
|
17
|
+
|
|
18
|
+
## The spine logic — keep everything connected
|
|
19
|
+
Customer signal (insight) → the bet (feature) → the work (task) → the result (outcome). Don't create orphans:
|
|
20
|
+
- A task that exists because a customer asked → link its \`insight_id\`. Because it serves a bet → link its \`feature_id\`.
|
|
21
|
+
- When you capture feedback, tie it to the account and the feature it's about, in the customer's own words —
|
|
22
|
+
a specific verbatim beats your paraphrase.
|
|
23
|
+
- Work with no why is the thing to question, not to dutifully schedule.
|
|
24
|
+
|
|
25
|
+
## Prioritize on evidence — never on a score you invented
|
|
26
|
+
This org has its OWN prioritization framework (RICE, ICE, MoSCoW, WSJF, value/effort, Kano — whatever they set).
|
|
27
|
+
Do NOT assume one, and do NOT compute the score yourself. Attach the EVIDENCE and let their framework do the math:
|
|
28
|
+
- Which accounts are affected, and the MRR behind them (the revenue weight).
|
|
29
|
+
- The reach/usage from analytics (\`analyze_funnel\`, \`get_retention\`, \`analyze_paths\`, the brain).
|
|
30
|
+
- The customer signals that back it.
|
|
31
|
+
Hand work off as an opportunity with that evidence attached — a human (or their configured model) does the ranking.
|
|
32
|
+
You ground the call; you never fake the number.
|
|
33
|
+
|
|
34
|
+
## Decide from data, not vibes
|
|
35
|
+
Before you assert a priority or a problem, pull the number — funnel drop, retention curve, the path users take,
|
|
36
|
+
the MRR behind a segment — and quote it. "Signups drop 38% on the company-size field" beats "the form feels long".
|
|
37
|
+
|
|
38
|
+
## Output discipline
|
|
39
|
+
Concise and honest. Confirm only the writes you actually made, in plain language. Resolve ids via \`pm_meta\`.
|
|
40
|
+
Keep titles and descriptions concrete and scoped — a task a teammate can pick up cold.`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aioproductoscom/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "ProductOS MCP — manage tickets, read your product brain + analytics, and run the support inbox from Claude Code, Cursor, Codex, and any MCP host.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|