@aioproductoscom/mcp-pm 0.1.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 ADDED
@@ -0,0 +1,61 @@
1
+ # ProductOS PM Helper · MCP server
2
+
3
+ Manage **ProductOS** tickets from your AI host — Claude Code, Cursor, Codex, or any
4
+ MCP client. List, create, update, and comment on tasks, grounded in the ProductOS
5
+ spine (features, insights). Thin and secret-free: the only credential is your
6
+ personal access token, which you paste into *your* host's config.
7
+
8
+ ## 1. Get a token
9
+
10
+ In ProductOS → **Settings → Tokens & Agents** → **Generate token**. Copy it (shown
11
+ once) — it looks like `pat_live_…`.
12
+
13
+ ## 2. Connect
14
+
15
+ ### Claude Code
16
+ ```bash
17
+ claude mcp add productos-pm -e PRODUCTOS_TOKEN=pat_live_… -- npx -y @aioproductoscom/mcp-pm
18
+ ```
19
+ or in `.mcp.json`:
20
+ ```json
21
+ {
22
+ "mcpServers": {
23
+ "productos-pm": {
24
+ "command": "npx",
25
+ "args": ["-y", "@aioproductoscom/mcp-pm"],
26
+ "env": { "PRODUCTOS_TOKEN": "pat_live_…" }
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ ### Cursor / Codex
33
+ Same shape in their `mcp.json`: `command: "npx"`, `args: ["-y", "@aioproductoscom/mcp-pm"]`,
34
+ `env.PRODUCTOS_TOKEN`.
35
+
36
+ `PRODUCTOS_URL` defaults to `https://platform.aioproductos.com`; set it to point at a
37
+ self-hosted platform.
38
+
39
+ ## Tools
40
+
41
+ | Tool | What it does |
42
+ |---|---|
43
+ | `whoami` | the connected org + member |
44
+ | `pm_meta` | lists / statuses / members / features (resolve names → ids) |
45
+ | `list_tasks` | list tasks (filter by `status_id`, `list_id`) |
46
+ | `get_task` | one task + comments + assignees |
47
+ | `create_task` | new task; `feature_id` / `insight_id` link it to the spine |
48
+ | `update_task` | change status, priority, fields, assignees |
49
+ | `comment_on_task` | add a comment |
50
+
51
+ ## Local build (until published to npm)
52
+
53
+ ```bash
54
+ pnpm install
55
+ pnpm --filter @aioproductoscom/mcp-pm build
56
+ ```
57
+ Then point the host at the built binary instead of `npx`:
58
+ ```json
59
+ { "command": "node", "args": ["<repo>/packages/mcps/productos-pm/dist/index.js"],
60
+ "env": { "PRODUCTOS_TOKEN": "pat_live_…" } }
61
+ ```
package/dist/client.js ADDED
@@ -0,0 +1,60 @@
1
+ // Thin typed HTTP client over the platform's token-authed PM endpoints.
2
+ // Uses global fetch (Node 18+). The PAT is the only credential; nothing is stored.
3
+ export class PlatformClient {
4
+ baseUrl;
5
+ token;
6
+ constructor(baseUrl, token) {
7
+ this.baseUrl = baseUrl;
8
+ this.token = token;
9
+ }
10
+ async req(path, init) {
11
+ const res = await fetch(`${this.baseUrl}${path}`, {
12
+ ...init,
13
+ headers: {
14
+ "Content-Type": "application/json",
15
+ Authorization: `Bearer ${this.token}`,
16
+ ...(init?.headers ?? {}),
17
+ },
18
+ });
19
+ const body = await res.text();
20
+ const json = body ? JSON.parse(body) : {};
21
+ if (!res.ok) {
22
+ const o = (json ?? {});
23
+ const msg = o.error ? `${o.error}${o.detail ? `: ${o.detail}` : ""}` : `HTTP ${res.status}`;
24
+ const e = new Error(msg);
25
+ e.status = res.status;
26
+ throw e;
27
+ }
28
+ return json;
29
+ }
30
+ whoami() {
31
+ return this.req("/api/me");
32
+ }
33
+ meta() {
34
+ return this.req("/api/pm/meta");
35
+ }
36
+ listTasks(q) {
37
+ const params = new URLSearchParams();
38
+ if (q.status_id)
39
+ params.set("status_id", q.status_id);
40
+ if (q.list_id)
41
+ params.set("list_id", q.list_id);
42
+ const qs = params.toString();
43
+ return this.req(`/api/pm/tasks${qs ? `?${qs}` : ""}`);
44
+ }
45
+ getTask(id) {
46
+ return this.req(`/api/pm/tasks/${encodeURIComponent(id)}`);
47
+ }
48
+ createTask(body) {
49
+ return this.req("/api/pm/tasks", { method: "POST", body: JSON.stringify(body) });
50
+ }
51
+ updateTask(id, body) {
52
+ return this.req(`/api/pm/tasks/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify(body) });
53
+ }
54
+ comment(id, body) {
55
+ return this.req(`/api/pm/tasks/${encodeURIComponent(id)}/comments`, {
56
+ method: "POST",
57
+ body: JSON.stringify({ body }),
58
+ });
59
+ }
60
+ }
package/dist/index.js ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ import { PlatformClient } from "./client.js";
6
+ const token = process.env.PRODUCTOS_TOKEN;
7
+ const baseUrl = (process.env.PRODUCTOS_URL ?? "https://platform.aioproductos.com").replace(/\/$/, "");
8
+ if (!token) {
9
+ console.error("[productos-pm] PRODUCTOS_TOKEN is required — generate one in ProductOS → Settings → Tokens & Agents.");
10
+ process.exit(1);
11
+ }
12
+ const client = new PlatformClient(baseUrl, token);
13
+ function text(data) {
14
+ return {
15
+ content: [
16
+ { type: "text", text: typeof data === "string" ? data : JSON.stringify(data, null, 2) },
17
+ ],
18
+ };
19
+ }
20
+ const server = new McpServer({ name: "productos-pm", version: "0.1.0" });
21
+ server.tool("whoami", "Show the connected ProductOS identity (org, member).", {}, async () => text(await client.whoami()));
22
+ 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()));
23
+ 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)));
24
+ server.tool("get_task", "Get one task with its comments and assignees.", { id: z.string() }, async (a) => text(await client.getTask(a.id)));
25
+ server.tool("create_task", "Create a task. Omitting list_id uses the org's first list. feature_id / insight_id link it to the ProductOS spine.", {
26
+ title: z.string(),
27
+ description: z.string().optional(),
28
+ priority: z.enum(["urgent", "high", "normal", "low"]).optional(),
29
+ list_id: z.string().optional(),
30
+ status_id: z.string().optional(),
31
+ feature_id: z.string().optional(),
32
+ insight_id: z.string().optional(),
33
+ assignee_member_ids: z.array(z.string()).optional(),
34
+ }, async (a) => text(await client.createTask(a)));
35
+ server.tool("update_task", "Update a task's fields (status, priority, title, description, feature, insight, assignees).", {
36
+ id: z.string(),
37
+ title: z.string().optional(),
38
+ description: z.string().nullable().optional(),
39
+ priority: z.enum(["urgent", "high", "normal", "low"]).nullable().optional(),
40
+ status_id: z.string().nullable().optional(),
41
+ feature_id: z.string().nullable().optional(),
42
+ insight_id: z.string().nullable().optional(),
43
+ assignee_member_ids: z.array(z.string()).optional(),
44
+ }, async ({ id, ...body }) => text(await client.updateTask(id, body)));
45
+ server.tool("comment_on_task", "Add a comment to a task.", { id: z.string(), body: z.string() }, async (a) => text(await client.comment(a.id, a.body)));
46
+ async function main() {
47
+ await server.connect(new StdioServerTransport());
48
+ }
49
+ main().catch((err) => {
50
+ console.error("[productos-pm] fatal:", err);
51
+ process.exit(1);
52
+ });
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@aioproductoscom/mcp-pm",
3
+ "version": "0.1.0",
4
+ "description": "ProductOS PM Helper — an MCP server to manage ProductOS tickets from Claude Code, Cursor, Codex, and any MCP host.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "AIITDEVELOPMENT DOO Novi Sad",
8
+ "homepage": "https://platform.aioproductos.com",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/businesstalksnetwork/productos.git",
12
+ "directory": "packages/mcps/productos-pm"
13
+ },
14
+ "bugs": { "url": "https://github.com/businesstalksnetwork/productos/issues" },
15
+ "keywords": [
16
+ "mcp",
17
+ "model-context-protocol",
18
+ "productos",
19
+ "claude",
20
+ "cursor",
21
+ "codex",
22
+ "project-management",
23
+ "product-management"
24
+ ],
25
+ "bin": { "productos-pm": "dist/index.js" },
26
+ "files": ["dist", "README.md"],
27
+ "engines": { "node": ">=18" },
28
+ "publishConfig": { "access": "public" },
29
+ "scripts": {
30
+ "build": "tsc",
31
+ "prepublishOnly": "npm run build",
32
+ "start": "node dist/index.js"
33
+ },
34
+ "dependencies": {
35
+ "@modelcontextprotocol/sdk": "^1.0.0",
36
+ "zod": "^3.23.8"
37
+ },
38
+ "devDependencies": {
39
+ "@types/node": "^22.7.0",
40
+ "typescript": "^5.6.0"
41
+ }
42
+ }