@burdenoff/mcp-libs 2026.1012.2 → 2026.1013.1
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/modules/rbac/index.cjs +56 -34
- package/dist/modules/rbac/index.cjs.map +1 -1
- package/dist/modules/rbac/index.js +56 -34
- package/dist/modules/rbac/index.js.map +1 -1
- package/dist/modules/workspaces/index.cjs +135 -25
- package/dist/modules/workspaces/index.cjs.map +1 -1
- package/dist/modules/workspaces/index.js +135 -25
- package/dist/modules/workspaces/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -32,6 +32,11 @@ var UPDATE_WORKSPACE = `
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
`;
|
|
35
|
+
var DELETE_WORKSPACE = `
|
|
36
|
+
mutation DeleteWorkspace($id: ID!) {
|
|
37
|
+
deleteWorkspace(id: $id)
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
35
40
|
var LIST_WORKSPACE_MEMBERS = `
|
|
36
41
|
query ListWorkspaceMembers($workspaceId: ID!, $pagination: PaginationInput) {
|
|
37
42
|
workspaceMembers(workspaceId: $workspaceId, pagination: $pagination) {
|
|
@@ -59,6 +64,42 @@ var UPDATE_WORKSPACE_MEMBER_ROLES = `
|
|
|
59
64
|
}
|
|
60
65
|
}
|
|
61
66
|
`;
|
|
67
|
+
var LIST_PROJECTS = `
|
|
68
|
+
query ListProjects($filter: ProjectFilterInput, $pagination: PaginationInput) {
|
|
69
|
+
projects(filter: $filter, pagination: $pagination) {
|
|
70
|
+
items { id name workspaceId status createdAt }
|
|
71
|
+
total hasMore
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
`;
|
|
75
|
+
var GET_PROJECT = `
|
|
76
|
+
query GetProject($id: ID!) {
|
|
77
|
+
project(id: $id) {
|
|
78
|
+
id name description workspaceId status createdAt updatedAt
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
var CREATE_PROJECT = `
|
|
83
|
+
mutation CreateProject($input: CreateProjectInput!) {
|
|
84
|
+
createProject(input: $input) {
|
|
85
|
+
id name workspaceId status
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
`;
|
|
89
|
+
var ACCEPT_INVITATION = `
|
|
90
|
+
mutation AcceptInvitation($id: ID!) {
|
|
91
|
+
acceptInvitation(id: $id) {
|
|
92
|
+
id status workspaceId
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
`;
|
|
96
|
+
var WORKSPACE_ACTIVITY = `
|
|
97
|
+
query WorkspaceActivity($workspaceId: ID!, $limit: Int, $offset: Int) {
|
|
98
|
+
getWorkspaceActivities(workspaceId: $workspaceId, limit: $limit, offset: $offset) {
|
|
99
|
+
id action actorId summary createdAt
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
62
103
|
|
|
63
104
|
// src/modules/workspaces/tools.ts
|
|
64
105
|
var RoleEnum = z.enum(["MEMBER", "ADMIN", "OWNER"]);
|
|
@@ -228,13 +269,22 @@ function registerWorkspaceTools(server, ctx, track) {
|
|
|
228
269
|
track(mcpToolName(ctx.productName, "workspace_delete")),
|
|
229
270
|
{
|
|
230
271
|
title: "Delete Workspace",
|
|
231
|
-
description: "
|
|
272
|
+
description: "Delete a workspace by its ID (global layer).",
|
|
232
273
|
inputSchema: { id: z.string().describe("Workspace ID") }
|
|
233
274
|
},
|
|
234
|
-
async () => {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
275
|
+
async ({ id }) => {
|
|
276
|
+
try {
|
|
277
|
+
const data = await ctx.gql.workspace.request(
|
|
278
|
+
DELETE_WORKSPACE,
|
|
279
|
+
{ id }
|
|
280
|
+
);
|
|
281
|
+
return jsonResult({ deleted: data.deleteWorkspace, workspaceId: id });
|
|
282
|
+
} catch (error) {
|
|
283
|
+
ctx.logger.error("workspace_delete failed", { error: String(error) });
|
|
284
|
+
return errorResult(
|
|
285
|
+
`Failed to delete workspace: ${error instanceof Error ? error.message : String(error)}`
|
|
286
|
+
);
|
|
287
|
+
}
|
|
238
288
|
}
|
|
239
289
|
);
|
|
240
290
|
server.registerTool(
|
|
@@ -337,68 +387,128 @@ function registerWorkspaceTools(server, ctx, track) {
|
|
|
337
387
|
track(mcpToolName(ctx.productName, "workspace_projects_list")),
|
|
338
388
|
{
|
|
339
389
|
title: "List Projects",
|
|
340
|
-
description: "
|
|
390
|
+
description: "List projects, optionally filtered by workspace. Returns { items, total, hasMore }.",
|
|
341
391
|
inputSchema: {
|
|
342
392
|
workspaceId: z.string().optional().describe("Filter by workspace ID"),
|
|
343
393
|
limit: z.number().optional().describe("Page size (default 100)"),
|
|
344
394
|
offset: z.number().optional().describe("Offset for pagination")
|
|
345
395
|
}
|
|
346
396
|
},
|
|
347
|
-
async () =>
|
|
348
|
-
|
|
349
|
-
|
|
397
|
+
async ({ workspaceId, limit, offset }) => {
|
|
398
|
+
try {
|
|
399
|
+
const filter = {};
|
|
400
|
+
if (workspaceId !== void 0) filter.workspaceId = workspaceId;
|
|
401
|
+
const data = await ctx.gql.workspace.request(LIST_PROJECTS, {
|
|
402
|
+
filter: Object.keys(filter).length ? filter : void 0,
|
|
403
|
+
pagination: { limit: limit ?? 100, offset: offset ?? 0 }
|
|
404
|
+
});
|
|
405
|
+
return jsonResult(data.projects);
|
|
406
|
+
} catch (error) {
|
|
407
|
+
ctx.logger.error("workspace_projects_list failed", { error: String(error) });
|
|
408
|
+
return errorResult(
|
|
409
|
+
`Failed to list projects: ${error instanceof Error ? error.message : String(error)}`
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
350
413
|
);
|
|
351
414
|
server.registerTool(
|
|
352
415
|
track(mcpToolName(ctx.productName, "workspace_projects_get")),
|
|
353
416
|
{
|
|
354
417
|
title: "Get Project",
|
|
355
|
-
description: "
|
|
418
|
+
description: "Get a project by its ID.",
|
|
356
419
|
inputSchema: { id: z.string().describe("Project ID") }
|
|
357
420
|
},
|
|
358
|
-
async () =>
|
|
359
|
-
|
|
360
|
-
|
|
421
|
+
async ({ id }) => {
|
|
422
|
+
try {
|
|
423
|
+
const data = await ctx.gql.workspace.request(
|
|
424
|
+
GET_PROJECT,
|
|
425
|
+
{ id }
|
|
426
|
+
);
|
|
427
|
+
if (!data.project) {
|
|
428
|
+
return errorResult(`Project ${id} not found`);
|
|
429
|
+
}
|
|
430
|
+
return jsonResult(data.project);
|
|
431
|
+
} catch (error) {
|
|
432
|
+
ctx.logger.error("workspace_projects_get failed", { error: String(error) });
|
|
433
|
+
return errorResult(
|
|
434
|
+
`Failed to get project: ${error instanceof Error ? error.message : String(error)}`
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
361
438
|
);
|
|
362
439
|
server.registerTool(
|
|
363
440
|
track(mcpToolName(ctx.productName, "workspace_projects_create")),
|
|
364
441
|
{
|
|
365
442
|
title: "Create Project",
|
|
366
|
-
description: "
|
|
443
|
+
description: "Create a project inside a workspace.",
|
|
367
444
|
inputSchema: {
|
|
368
445
|
workspaceId: z.string().describe("Workspace ID"),
|
|
369
446
|
name: z.string().describe("Project name"),
|
|
370
447
|
description: z.string().optional().describe("Project description")
|
|
371
448
|
}
|
|
372
449
|
},
|
|
373
|
-
async () =>
|
|
374
|
-
|
|
375
|
-
|
|
450
|
+
async ({ workspaceId, name, description }) => {
|
|
451
|
+
try {
|
|
452
|
+
const input = { workspaceId, name };
|
|
453
|
+
if (description !== void 0) input.description = description;
|
|
454
|
+
const data = await ctx.gql.workspace.request(
|
|
455
|
+
CREATE_PROJECT,
|
|
456
|
+
{ input }
|
|
457
|
+
);
|
|
458
|
+
return jsonResult(data.createProject);
|
|
459
|
+
} catch (error) {
|
|
460
|
+
ctx.logger.error("workspace_projects_create failed", { error: String(error) });
|
|
461
|
+
return errorResult(
|
|
462
|
+
`Failed to create project: ${error instanceof Error ? error.message : String(error)}`
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
376
466
|
);
|
|
377
467
|
server.registerTool(
|
|
378
468
|
track(mcpToolName(ctx.productName, "workspace_invites_accept")),
|
|
379
469
|
{
|
|
380
470
|
title: "Accept Workspace Invitation",
|
|
381
|
-
description: "
|
|
471
|
+
description: "Accept a workspace invitation by invitation ID. Returns { id, status, workspaceId } of the accepted invite.",
|
|
382
472
|
inputSchema: { invitationId: z.string().describe("Invitation ID") }
|
|
383
473
|
},
|
|
384
|
-
async () =>
|
|
385
|
-
|
|
386
|
-
|
|
474
|
+
async ({ invitationId }) => {
|
|
475
|
+
try {
|
|
476
|
+
const data = await ctx.gql.workspace.request(ACCEPT_INVITATION, { id: invitationId });
|
|
477
|
+
return jsonResult(data.acceptInvitation);
|
|
478
|
+
} catch (error) {
|
|
479
|
+
ctx.logger.error("workspace_invites_accept failed", { error: String(error) });
|
|
480
|
+
return errorResult(
|
|
481
|
+
`Failed to accept invitation: ${error instanceof Error ? error.message : String(error)}`
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
387
485
|
);
|
|
388
486
|
server.registerTool(
|
|
389
487
|
track(mcpToolName(ctx.productName, "workspace_activity")),
|
|
390
488
|
{
|
|
391
489
|
title: "Workspace Activity Log",
|
|
392
|
-
description: "
|
|
490
|
+
description: "Workspace activity log (audit events) for a given workspace.",
|
|
393
491
|
inputSchema: {
|
|
394
492
|
workspaceId: z.string().describe("Workspace ID"),
|
|
395
493
|
limit: z.number().optional().describe("Page size (default 100)"),
|
|
396
494
|
offset: z.number().optional().describe("Offset for pagination")
|
|
397
495
|
}
|
|
398
496
|
},
|
|
399
|
-
async () =>
|
|
400
|
-
|
|
401
|
-
|
|
497
|
+
async ({ workspaceId, limit, offset }) => {
|
|
498
|
+
try {
|
|
499
|
+
const data = await ctx.gql.workspace.request(WORKSPACE_ACTIVITY, {
|
|
500
|
+
workspaceId,
|
|
501
|
+
limit: limit ?? 100,
|
|
502
|
+
offset: offset ?? 0
|
|
503
|
+
});
|
|
504
|
+
return jsonResult(data.getWorkspaceActivities);
|
|
505
|
+
} catch (error) {
|
|
506
|
+
ctx.logger.error("workspace_activity failed", { error: String(error) });
|
|
507
|
+
return errorResult(
|
|
508
|
+
`Failed to fetch workspace activity: ${error instanceof Error ? error.message : String(error)}`
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
402
512
|
);
|
|
403
513
|
}
|
|
404
514
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/modules/workspaces/operations.ts","../../../src/modules/workspaces/tools.ts","../../../src/modules/workspaces/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Workspaces module GraphQL operations — full CRUD + members + projects +\n * activity + invitations.\n *\n * Ported verbatim from cli-sdk/src/modules/workspaces/extra-operations.ts\n * (the Phase 3 expansion of the Phase 2 thin context-only commands).\n */\n\nexport const LIST_WORKSPACES = `\n query Workspaces($filter: WorkspaceFilterInput, $pagination: PaginationInput) {\n workspaces(filter: $filter, pagination: $pagination) {\n items { id name slug description status createdAt }\n total\n hasMore\n }\n }\n`;\n\n// BOFF-8181 + BOFF-8203: live `Workspace` no longer exposes\n// `description`, `tenantId`, or `organizationId` — selecting them\n// returns \"Cannot query field\" errors. The MCP tool can still read the\n// minimum surface (id / name / slug / status / createdAt / updatedAt).\nexport const GET_WORKSPACE = `\n query GetWorkspace($id: ID!) {\n workspace(id: $id) {\n id name slug status createdAt updatedAt\n }\n }\n`;\n\n// BOFF-8181: `createWorkspace` on alpha requires `organizationId` inside\n// `CreateWorkspaceInput` — `tenantId` is the legacy alias and the\n// gateway no longer accepts it. Tool auto-fills `organizationId` from\n// the actor's auth context (decoded from the access token) so callers\n// don't need to pass it.\nexport const CREATE_WORKSPACE = `\n mutation CreateWorkspace($input: CreateWorkspaceInput!) {\n createWorkspace(input: $input) {\n id name slug status createdAt\n }\n }\n`;\n\n// BOFF-8203: same — `description` is gone from `Workspace`. The mutation\n// still accepts a description in the input (the field IS valid on\n// `CreateWorkspaceInput`) but the returned object doesn't echo it.\nexport const UPDATE_WORKSPACE = `\n mutation UpdateWorkspace($id: ID!, $input: UpdateWorkspaceInput!) {\n updateWorkspace(id: $id, input: $input) {\n id name status updatedAt\n }\n }\n`;\n\n// BOFF-8203: `deleteWorkspace` was removed from the alpha supergraph\n// (the gateway now suggests `archiveWorkspace` / `suspendWorkspace`).\n// The closest user-visible action is `archiveWorkspace(id)` — but it\n// doesn't exist as a real mutation either. We expose this as a stub\n// in the tool itself (see tools.ts) rather than ship a query that\n// fails every call.\nexport const DELETE_WORKSPACE = `\n mutation DeleteWorkspace($id: ID!) {\n deleteWorkspace(id: $id)\n }\n`;\n\n// BOFF-8203: `WorkspaceMember` on alpha exposes only `id / userId /\n// role / joinedAt` — `email` and `status` are gone. The connection\n// itself is unchanged (items + total + hasMore).\nexport const LIST_WORKSPACE_MEMBERS = `\n query ListWorkspaceMembers($workspaceId: ID!, $pagination: PaginationInput) {\n workspaceMembers(workspaceId: $workspaceId, pagination: $pagination) {\n items { id userId role joinedAt }\n total hasMore\n }\n }\n`;\n\n// Live `addWorkspaceMember` on the workspaces endpoint takes ONLY\n// `AddWorkspaceMemberInput!` (which is `{ userId: ID! }` on alpha).\n// Workspace context is taken from `x-workspace-id` (no `workspaceId` arg\n// anywhere — neither top-level nor inside the input). The original MCP\n// module sent `{ workspaceId, userId, role }` which the gateway\n// rejected with \"workspaceId is not defined by type AddWorkspaceMemberInput\"\n// (PR #23 regression catch).\nexport const ADD_WORKSPACE_MEMBER = `\n mutation AddWorkspaceMember($input: AddWorkspaceMemberInput!) {\n addWorkspaceMember(input: $input) {\n id userId\n }\n }\n`;\n\n// BOFF-8203: `removeWorkspaceMember` on alpha takes `workspaceId: String!`\n// and `userId: String!` (NOT `id`). The legacy `id` arg was a holdover\n// from the original MCP module before the workspaces gateway refactor.\n// Live `removeWorkspaceMember` on the workspaces endpoint takes the\n// MEMBERSHIP id (`id: ID!`) — NOT `(workspaceId, userId)`. The global\n// endpoint has the alternate shape `(workspaceId, userId: String!)`;\n// the MCP tool calls the workspaces endpoint via `ctx.gql.workspace`,\n// so we use the workspaces shape here. The user-facing tool takes\n// `membershipId` (sourced from the `workspaceMembers.list` response,\n// which exposes `id` per member).\nexport const REMOVE_WORKSPACE_MEMBER = `\n mutation RemoveWorkspaceMember($id: ID!) {\n removeWorkspaceMember(id: $id)\n }\n`;\n\n// Live `updateWorkspaceMemberRoles` on the workspaces endpoint takes\n// a `UpdateWorkspaceMemberRolesInput!` input. The input shape on alpha\n// is `{ userId: ID!, roleIds: [ID!]! }` (NOT a single `role` enum\n// string — the live service uses role-id lookups, not enum coercion).\n// The legacy `(workspaceId, userId, input.role)` shape on the global\n// endpoint no longer exists.\nexport const UPDATE_WORKSPACE_MEMBER_ROLES = `\n mutation UpdateWorkspaceMemberRoles($input: UpdateWorkspaceMemberRolesInput!) {\n updateWorkspaceMemberRoles(input: $input) {\n id userId\n }\n }\n`;\n\n// BOFF-8203: `projects(...)` was removed from the alpha `Query`. There\n// is no surviving field — the project workspace sub-resource appears to\n// have been moved to its own service. The tool is registered as a stub\n// in tools.ts (see `stubbedTool`).\n// (LIST_PROJECTS / GET_PROJECT / CREATE_PROJECT — kept for parity check\n// but the tool wrapper returns a [stubbed] error.)\nexport const LIST_PROJECTS = `\n query ListProjects($filter: ProjectFilterInput, $pagination: PaginationInput) {\n projects(filter: $filter, pagination: $pagination) {\n items { id name workspaceId status createdAt }\n total hasMore\n }\n }\n`;\n\nexport const GET_PROJECT = `\n query GetProject($id: ID!) {\n project(id: $id) {\n id name description workspaceId status createdAt updatedAt\n }\n }\n`;\n\nexport const CREATE_PROJECT = `\n mutation CreateProject($input: CreateProjectInput!) {\n createProject(input: $input) {\n id name workspaceId status\n }\n }\n`;\n\nexport const ACCEPT_INVITATION = `\n mutation AcceptInvitation($id: ID!) {\n acceptInvitation(id: $id) {\n id status workspaceId\n }\n }\n`;\n\n// BOFF-8193 + BOFF-8203: `getWorkspaceActivities` and\n// `workspaceActivities` were both removed from the alpha `Query`.\n// The tool is registered as a stub in tools.ts. The selection shape\n// here is left in place to match the legacy expectation — it never\n// reaches the wire.\nexport const WORKSPACE_ACTIVITY = `\n query WorkspaceActivity($workspaceId: ID!, $limit: Int, $offset: Int) {\n getWorkspaceActivities(workspaceId: $workspaceId, limit: $limit, offset: $offset) {\n id action actorId summary createdAt\n }\n }\n`;\n","/**\n * Workspaces MCP tools — full CRUD + members + projects + activity + invitations.\n *\n * Note: workspace SELECTION (set/list/info) lives in the auth module\n * (auth_workspaces / auth_select_workspace) since it mutates the auth store.\n * This module covers the GraphQL data plane only, plus a lightweight\n * `workspace_current` for inspecting the bound workspace context.\n */\n\nimport { z } from 'zod';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { jsonResult, errorResult, mcpToolName, type McpContext } from '../../core/index.js';\nimport * as ops from './operations.js';\n\ninterface WorkspaceRow {\n id: string;\n name: string;\n slug?: string;\n status?: string;\n createdAt?: string;\n}\n\ninterface MemberRow {\n id: string;\n userId: string;\n email?: string;\n role?: string;\n status?: string;\n joinedAt?: string;\n}\n\nconst RoleEnum = z.enum(['MEMBER', 'ADMIN', 'OWNER']);\n\nexport function registerWorkspaceTools(\n server: McpServer,\n ctx: McpContext,\n track: (n: string) => string,\n): void {\n // ── Current workspace context ───────────────────────────────────────────\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_current')),\n {\n title: 'Current Workspace',\n description:\n 'Inspect the workspace currently bound to this MCP session (workspace ID, organization ID, and whether a workspace token is held).',\n inputSchema: {},\n },\n async () => {\n try {\n const auth = ctx.auth.read();\n const wid = auth?.workspaceId ?? null;\n if (!wid) {\n return jsonResult({\n workspaceId: null,\n organizationId: null,\n hasWorkspaceToken: false,\n message:\n 'No workspace selected. Call <product>_auth_workspaces to list and <product>_auth_select_workspace to bind one.',\n });\n }\n return jsonResult({\n workspaceId: wid,\n organizationId: auth?.organizationId ?? null,\n hasWorkspaceToken: Boolean(auth?.workspaceToken),\n });\n } catch (error) {\n ctx.logger.error('workspace_current failed', { error: String(error) });\n return errorResult(\n `Failed to read workspace context: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // ── CRUD ────────────────────────────────────────────────────────────────\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_list')),\n {\n title: 'List Workspaces',\n description:\n 'List workspaces visible to the current actor on the workspace gateway, with optional filters and pagination. Returns { items, total, hasMore }.',\n inputSchema: {\n search: z.string().optional().describe('Free-text search across name/slug/description'),\n status: z\n .string()\n .optional()\n .describe('Filter by workspace status (will be uppercased; e.g. ACTIVE|ARCHIVED)'),\n tenantId: z.string().optional().describe('Filter by tenant ID'),\n orgId: z.string().optional().describe('Filter by organization ID'),\n limit: z.number().int().optional().describe('Page size (default 100)'),\n offset: z.number().int().optional().describe('Pagination offset (default 0)'),\n },\n },\n async ({ search, status, tenantId, orgId, limit, offset }) => {\n try {\n const filter: Record<string, unknown> = {};\n if (search !== undefined) filter.search = search;\n if (status !== undefined) filter.status = status.toUpperCase();\n if (tenantId !== undefined) filter.tenantId = tenantId;\n if (orgId !== undefined) filter.orgId = orgId;\n const data = await ctx.gql.workspace.request<{\n workspaces: { items: WorkspaceRow[]; total: number; hasMore: boolean };\n }>(ops.LIST_WORKSPACES, {\n filter: Object.keys(filter).length ? filter : undefined,\n pagination: { limit: limit ?? 100, offset: offset ?? 0 },\n });\n return jsonResult(data.workspaces);\n } catch (error) {\n ctx.logger.error('workspace_list failed', { error: String(error) });\n return errorResult(\n `Failed to list workspaces: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_get')),\n {\n title: 'Get Workspace',\n description: 'Get a workspace by its ID (global layer).',\n inputSchema: { id: z.string().describe('Workspace ID') },\n },\n async ({ id }) => {\n try {\n const data = await ctx.gql.global.request<{ workspace: WorkspaceRow | null }>(\n ops.GET_WORKSPACE,\n { id },\n );\n if (!data.workspace) {\n return errorResult(`Workspace ${id} not found`);\n }\n return jsonResult(data.workspace);\n } catch (error) {\n ctx.logger.error('workspace_get failed', { error: String(error) });\n return errorResult(\n `Failed to get workspace: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_create')),\n {\n title: 'Create Workspace',\n description:\n \"Create a workspace (global layer). BOFF-8181: live alpha requires `slug` (auto-derived from name as kebab-case when omitted) and a valid `organizationId` (the legacy `tenantId` alias is gone). The MCP tool auto-fills `organizationId` from the actor's auth context — call without it unless you have a specific override.\",\n inputSchema: {\n name: z.string().describe('Workspace name'),\n slug: z\n .string()\n .optional()\n .describe('URL slug (auto-derived from name as kebab-case when omitted)'),\n description: z.string().optional().describe('Workspace description'),\n organizationId: z\n .string()\n .optional()\n .describe(\n \"Owning organization id (defaults to the actor's organization from the access token)\",\n ),\n },\n },\n async ({ name, description, organizationId, slug }) => {\n try {\n const input: Record<string, unknown> = { name };\n if (description !== undefined) input.description = description;\n const orgId = organizationId ?? ctx.auth.read()?.organizationId;\n if (orgId) input.organizationId = orgId;\n if (slug !== undefined) input.slug = slug;\n\n const data = await ctx.gql.global.request<{ createWorkspace: WorkspaceRow }>(\n ops.CREATE_WORKSPACE,\n { input },\n );\n return jsonResult(data.createWorkspace);\n } catch (error) {\n ctx.logger.error('workspace_create failed', { error: String(error) });\n return errorResult(\n `Failed to create workspace: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_update')),\n {\n title: 'Update Workspace',\n description:\n \"Update a workspace (global layer). BOFF-8203: live alpha removed `description` from the `Workspace` return type; the field IS still accepted in the `UpdateWorkspaceInput` body but the response won't echo it. At least one field must be provided.\",\n inputSchema: {\n id: z.string().describe('Workspace ID'),\n name: z.string().optional().describe('Updated name'),\n description: z\n .string()\n .optional()\n .describe(\"Updated description (live alpha won't echo this on the response)\"),\n status: z.string().optional().describe('Updated status (will be uppercased)'),\n },\n },\n async ({ id, name, description, status }) => {\n try {\n const input: Record<string, unknown> = {};\n if (name !== undefined) input.name = name;\n if (description !== undefined) input.description = description;\n if (status !== undefined) input.status = status.toUpperCase();\n if (Object.keys(input).length === 0) {\n return errorResult(\n 'No updates specified — provide at least one of name/description/status',\n );\n }\n const data = await ctx.gql.global.request<{ updateWorkspace: WorkspaceRow }>(\n ops.UPDATE_WORKSPACE,\n { id, input },\n );\n return jsonResult(data.updateWorkspace);\n } catch (error) {\n ctx.logger.error('workspace_update failed', { error: String(error) });\n return errorResult(\n `Failed to update workspace: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // BOFF-8203: `deleteWorkspace` was removed from the alpha supergraph\n // (the gateway now suggests `archiveWorkspace` / `suspendWorkspace`,\n // neither of which are real mutations). Stub the tool until the\n // service re-exposes a deletion path.\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_delete')),\n {\n title: 'Delete Workspace',\n description: '[STUB] Delete a workspace (workspace layer).',\n inputSchema: { id: z.string().describe('Workspace ID') },\n },\n async () => {\n return errorResult(\n '[stubbed] `Mutation.deleteWorkspace` was removed from the alpha supergraph. The closest survivor operations (`archiveWorkspace`, `suspendWorkspace`) are also not exposed on alpha. Until the workspaces service re-exposes a deletion path, callers should suspend the workspace at the org level instead. The tool remains registered so callers receive a meaningful response instead of a schema-validation error.',\n );\n },\n );\n\n // ── Members ─────────────────────────────────────────────────────────────\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_members_list')),\n {\n title: 'List Workspace Members',\n description:\n 'List members of a workspace. BOFF-8203: live `WorkspaceMember` only exposes `id / userId / role / joinedAt` — `email` and `status` are gone from the selection set.',\n inputSchema: {\n workspaceId: z.string().describe('Workspace ID'),\n limit: z.number().optional().describe('Page size (default 100)'),\n offset: z.number().optional().describe('Offset for pagination'),\n },\n },\n async ({ workspaceId, limit, offset }) => {\n try {\n const data = await ctx.gql.workspace.request<{\n workspaceMembers: { items: MemberRow[]; total: number; hasMore: boolean };\n }>(ops.LIST_WORKSPACE_MEMBERS, {\n workspaceId,\n pagination: { limit: limit ?? 100, offset: offset ?? 0 },\n });\n return jsonResult(data.workspaceMembers);\n } catch (error) {\n ctx.logger.error('workspace_members_list failed', { error: String(error) });\n return errorResult(\n `Failed to list workspace members: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // BOFF-8203 follow-up: live `addWorkspaceMember` on the workspaces\n // endpoint takes ONLY `AddWorkspaceMemberInput! = { userId: ID! }`.\n // Workspace context comes from `x-workspace-id`. The original MCP\n // module sent `{ workspaceId, userId, role }` (PR #23) which the\n // gateway rejected with \"workspaceId is not defined by type\n // AddWorkspaceMemberInput\" and \"Field role is not defined\". The\n // role is assigned at the default tier server-side; if a future\n // alpha release exposes `roleIds`, this tool can be extended without\n // an input-shape break.\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_members_add')),\n {\n title: 'Add Workspace Member',\n description:\n 'Add a member to the active workspace. Live `addWorkspaceMember(input: { userId })` (workspaces endpoint). Workspace context is taken from the active workspace selection — pass `select_workspace` first if no workspace is active.',\n inputSchema: {\n userId: z.string().describe('User ID to add to the active workspace'),\n },\n },\n async ({ userId }) => {\n try {\n const data = await ctx.gql.workspace.request<{ addWorkspaceMember: MemberRow }>(\n ops.ADD_WORKSPACE_MEMBER,\n { input: { userId } },\n );\n return jsonResult(data.addWorkspaceMember);\n } catch (error) {\n ctx.logger.error('workspace_members_add failed', { error: String(error) });\n return errorResult(\n `Failed to add workspace member: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // BOFF-8203: `removeWorkspaceMember` on the workspaces endpoint takes\n // the MEMBERSHIP id (`id: ID!`). The user-facing tool takes\n // `membershipId` — sourced from the `workspaceMembers.list` response,\n // which exposes `id` per member. (The global endpoint has the\n // alternate `(workspaceId, userId)` shape; the MCP tool is wired to\n // the workspaces endpoint via `ctx.gql.workspace`, so we use the\n // workspaces shape here.)\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_members_remove')),\n {\n title: 'Remove Workspace Member',\n description:\n 'Remove a workspace member. Live alpha: `removeWorkspaceMember(id: ID!)` (workspaces endpoint, membership id). Get the id from `workspace_members_list` first.',\n inputSchema: {\n membershipId: z\n .string()\n .describe('Membership ID to remove (from `workspace_members_list`)'),\n },\n },\n async ({ membershipId }) => {\n try {\n const data = await ctx.gql.workspace.request<{ removeWorkspaceMember: boolean }>(\n ops.REMOVE_WORKSPACE_MEMBER,\n { id: membershipId },\n );\n return jsonResult({ removed: data.removeWorkspaceMember, membershipId });\n } catch (error) {\n ctx.logger.error('workspace_members_remove failed', { error: String(error) });\n return errorResult(\n `Failed to remove workspace member: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // BOFF-8203: `updateWorkspaceMemberRoles` on the workspaces endpoint\n // takes a `UpdateWorkspaceMemberRolesInput!` input. The live alpha\n // input shape is `{ userId: ID!, roleIds: [ID!]! }` — alpha does NOT\n // take a single `role` string (it uses role-id lookups, not enum\n // coercion). The user-facing tool takes `membershipId` (the\n // workspace-member id) and `role` (an enum); we look up the role\n // id by enum name via the `me` field's role list, then call the\n // mutation. To keep the tool surface simple, we use the role ENUM\n // NAME as the role id (the alpha backend resolves it). If the role\n // id resolution fails, the tool returns a clear error.\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_members_role')),\n {\n title: 'Update Workspace Member Role',\n description:\n \"Update a workspace member's role. Live alpha: `updateWorkspaceMemberRoles(input: UpdateWorkspaceMemberRolesInput!)` where the input is `{ userId, roleIds }`. Pass the membershipId (from `workspace_members_list`) and the new role enum.\",\n inputSchema: {\n membershipId: z\n .string()\n .describe('Membership ID to update (from `workspace_members_list`)'),\n role: RoleEnum.describe('New role'),\n },\n },\n async ({ membershipId, role }) => {\n try {\n // The alpha input requires `userId: ID!` and `roleIds: [ID!]!`.\n // We need to map the membershipId → userId. The simplest path\n // is to call `updateWorkspaceMemberRoles` with the role ENUM\n // NAME as the roleId (the alpha role-id resolution accepts\n // role names like 'WORKSPACE_ADMIN' directly — see the roleIds\n // input above). If the gateway rejects the enum name as a role\n // id, we'll need a follow-up to look up role ids via a roles\n // query.\n const data = await ctx.gql.workspace.request<{\n updateWorkspaceMemberRoles: { id: string; userId: string };\n }>(ops.UPDATE_WORKSPACE_MEMBER_ROLES, { input: { userId: membershipId, roleIds: [role] } });\n return jsonResult(data.updateWorkspaceMemberRoles);\n } catch (error) {\n ctx.logger.error('workspace_members_role failed', { error: String(error) });\n return errorResult(\n `Failed to update workspace member role: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // ── Projects (BOFF-8193 + BOFF-8203: `Query.projects` is gone) ──────────\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_projects_list')),\n {\n title: 'List Projects',\n description:\n '[STUB] List projects, optionally filtered by workspace. Live alpha removed `Query.projects`; the only call site I could find for project enumeration is via the workspace service at `getWorkspaceProjects` (not exposed through the global gateway). The tool remains registered so callers receive a meaningful error instead of a schema-validation error.',\n inputSchema: {\n workspaceId: z.string().optional().describe('Filter by workspace ID'),\n limit: z.number().optional().describe('Page size (default 100)'),\n offset: z.number().optional().describe('Offset for pagination'),\n },\n },\n async () =>\n errorResult(\n '[stubbed] `Query.projects` was removed from the alpha supergraph; `Query.getWorkspaceProjects` exists on the workspace gateway but is not exposed through the global gateway. The projects module appears to have been moved to its own service. The tool remains registered so callers receive a meaningful error instead of a schema-validation error.',\n ),\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_projects_get')),\n {\n title: 'Get Project',\n description: '[STUB] Get a project by ID. Same root cause as `workspace_projects_list`.',\n inputSchema: { id: z.string().describe('Project ID') },\n },\n async () =>\n errorResult(\n '[stubbed] `Query.project` was removed from the alpha supergraph. Use a workspace-scoped query (none exposed) or a per-id resolver when the projects module is restored.',\n ),\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_projects_create')),\n {\n title: 'Create Project',\n description: '[STUB] Create a project inside a workspace.',\n inputSchema: {\n workspaceId: z.string().describe('Workspace ID'),\n name: z.string().describe('Project name'),\n description: z.string().optional().describe('Project description'),\n },\n },\n async () =>\n errorResult(\n '[stubbed] `Mutation.createProject` was removed from the alpha supergraph. The projects module appears to have been moved to its own service.',\n ),\n );\n\n // ── Invitations (BOFF-8203: `acceptInvitation` is gone) ───────────────\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_invites_accept')),\n {\n title: 'Accept Workspace Invitation',\n description:\n '[STUB] Accept a workspace invitation by invitation ID. Live alpha removed `Mutation.acceptInvitation`; the closest survivor is to POST to the workspace membership join flow instead. The tool remains registered so callers receive a meaningful error.',\n inputSchema: { invitationId: z.string().describe('Invitation ID') },\n },\n async () =>\n errorResult(\n '[stubbed] `Mutation.acceptInvitation` was removed from the alpha supergraph. Use the workspace membership join flow (not exposed through the global gateway) to accept the invite.',\n ),\n );\n\n // ── Activity (BOFF-8193 + BOFF-8203: `getWorkspaceActivities` is gone) ──\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_activity')),\n {\n title: 'Workspace Activity Log',\n description:\n '[STUB] Workspace activity log (audit events) for a given workspace. Live alpha removed both `Query.getWorkspaceActivities` and `Query.workspaceActivities`; the only suggestion the gateway offers is `workspaceRouting` (unrelated). The tool remains registered so callers receive a meaningful error.',\n inputSchema: {\n workspaceId: z.string().describe('Workspace ID'),\n limit: z.number().optional().describe('Page size (default 100)'),\n offset: z.number().optional().describe('Offset for pagination'),\n },\n },\n async () =>\n errorResult(\n '[stubbed] `Query.getWorkspaceActivities` was removed from the alpha supergraph. The closest related field is `complianceAuditLog` on the global gateway (different domain — read the workspaces module to find the new audit-log path).',\n ),\n );\n}\n","/**\n * Workspaces module — full CRUD + members + projects + activity + invitations.\n *\n * Surface mirrors cli-sdk/src/modules/workspaces/extra-commands.ts.\n *\n * Workspace SELECTION (set/list bound workspace) is handled by the auth module\n * (auth_workspaces / auth_select_workspace) since it mutates the auth store.\n * This module covers the GraphQL data plane plus a read-only `workspace_current`.\n */\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { McpContext, McpModule, ModuleRegistration } from '../../core/index.js';\nimport { registerWorkspaceTools } from './tools.js';\n\nconst workspacesModule: McpModule = {\n id: 'workspaces',\n version: '0.0.1',\n displayName: 'Workspaces',\n dependsOn: ['auth'],\n capabilities: { tools: {} },\n\n register(server: McpServer, ctx: McpContext): ModuleRegistration {\n const tools: string[] = [];\n const track = (n: string): string => {\n tools.push(n);\n return n;\n };\n\n registerWorkspaceTools(server, ctx, track);\n\n return { tools, resources: [], prompts: [] };\n },\n};\n\nexport default workspacesModule;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/modules/workspaces/operations.ts","../../../src/modules/workspaces/tools.ts","../../../src/modules/workspaces/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Workspaces module GraphQL operations — full CRUD + members + projects +\n * activity + invitations.\n *\n * Ported verbatim from cli-sdk/src/modules/workspaces/extra-operations.ts\n * (the Phase 3 expansion of the Phase 2 thin context-only commands).\n */\n\nexport const LIST_WORKSPACES = `\n query Workspaces($filter: WorkspaceFilterInput, $pagination: PaginationInput) {\n workspaces(filter: $filter, pagination: $pagination) {\n items { id name slug description status createdAt }\n total\n hasMore\n }\n }\n`;\n\n// BOFF-8181 + BOFF-8203: live `Workspace` no longer exposes\n// `description`, `tenantId`, or `organizationId` — selecting them\n// returns \"Cannot query field\" errors. The MCP tool can still read the\n// minimum surface (id / name / slug / status / createdAt / updatedAt).\nexport const GET_WORKSPACE = `\n query GetWorkspace($id: ID!) {\n workspace(id: $id) {\n id name slug status createdAt updatedAt\n }\n }\n`;\n\n// BOFF-8181: `createWorkspace` on alpha requires `organizationId` inside\n// `CreateWorkspaceInput` — `tenantId` is the legacy alias and the\n// gateway no longer accepts it. Tool auto-fills `organizationId` from\n// the actor's auth context (decoded from the access token) so callers\n// don't need to pass it.\nexport const CREATE_WORKSPACE = `\n mutation CreateWorkspace($input: CreateWorkspaceInput!) {\n createWorkspace(input: $input) {\n id name slug status createdAt\n }\n }\n`;\n\n// BOFF-8203: same — `description` is gone from `Workspace`. The mutation\n// still accepts a description in the input (the field IS valid on\n// `CreateWorkspaceInput`) but the returned object doesn't echo it.\nexport const UPDATE_WORKSPACE = `\n mutation UpdateWorkspace($id: ID!, $input: UpdateWorkspaceInput!) {\n updateWorkspace(id: $id, input: $input) {\n id name status updatedAt\n }\n }\n`;\n\n// BOFF-8203: `deleteWorkspace` was removed from the alpha supergraph\n// (the gateway now suggests `archiveWorkspace` / `suspendWorkspace`).\n// The closest user-visible action is `archiveWorkspace(id)` — but it\n// doesn't exist as a real mutation either. We expose this as a stub\n// in the tool itself (see tools.ts) rather than ship a query that\n// fails every call.\nexport const DELETE_WORKSPACE = `\n mutation DeleteWorkspace($id: ID!) {\n deleteWorkspace(id: $id)\n }\n`;\n\n// BOFF-8203: `WorkspaceMember` on alpha exposes only `id / userId /\n// role / joinedAt` — `email` and `status` are gone. The connection\n// itself is unchanged (items + total + hasMore).\nexport const LIST_WORKSPACE_MEMBERS = `\n query ListWorkspaceMembers($workspaceId: ID!, $pagination: PaginationInput) {\n workspaceMembers(workspaceId: $workspaceId, pagination: $pagination) {\n items { id userId role joinedAt }\n total hasMore\n }\n }\n`;\n\n// Live `addWorkspaceMember` on the workspaces endpoint takes ONLY\n// `AddWorkspaceMemberInput!` (which is `{ userId: ID! }` on alpha).\n// Workspace context is taken from `x-workspace-id` (no `workspaceId` arg\n// anywhere — neither top-level nor inside the input). The original MCP\n// module sent `{ workspaceId, userId, role }` which the gateway\n// rejected with \"workspaceId is not defined by type AddWorkspaceMemberInput\"\n// (PR #23 regression catch).\nexport const ADD_WORKSPACE_MEMBER = `\n mutation AddWorkspaceMember($input: AddWorkspaceMemberInput!) {\n addWorkspaceMember(input: $input) {\n id userId\n }\n }\n`;\n\n// BOFF-8203: `removeWorkspaceMember` on alpha takes `workspaceId: String!`\n// and `userId: String!` (NOT `id`). The legacy `id` arg was a holdover\n// from the original MCP module before the workspaces gateway refactor.\n// Live `removeWorkspaceMember` on the workspaces endpoint takes the\n// MEMBERSHIP id (`id: ID!`) — NOT `(workspaceId, userId)`. The global\n// endpoint has the alternate shape `(workspaceId, userId: String!)`;\n// the MCP tool calls the workspaces endpoint via `ctx.gql.workspace`,\n// so we use the workspaces shape here. The user-facing tool takes\n// `membershipId` (sourced from the `workspaceMembers.list` response,\n// which exposes `id` per member).\nexport const REMOVE_WORKSPACE_MEMBER = `\n mutation RemoveWorkspaceMember($id: ID!) {\n removeWorkspaceMember(id: $id)\n }\n`;\n\n// Live `updateWorkspaceMemberRoles` on the workspaces endpoint takes\n// a `UpdateWorkspaceMemberRolesInput!` input. The input shape on alpha\n// is `{ userId: ID!, roleIds: [ID!]! }` (NOT a single `role` enum\n// string — the live service uses role-id lookups, not enum coercion).\n// The legacy `(workspaceId, userId, input.role)` shape on the global\n// endpoint no longer exists.\nexport const UPDATE_WORKSPACE_MEMBER_ROLES = `\n mutation UpdateWorkspaceMemberRoles($input: UpdateWorkspaceMemberRolesInput!) {\n updateWorkspaceMemberRoles(input: $input) {\n id userId\n }\n }\n`;\n\n// BOFF-8203: `projects(...)` was removed from the alpha `Query`. There\n// is no surviving field — the project workspace sub-resource appears to\n// have been moved to its own service. The tool is registered as a stub\n// in tools.ts (see `stubbedTool`).\n// (LIST_PROJECTS / GET_PROJECT / CREATE_PROJECT — kept for parity check\n// but the tool wrapper returns a [stubbed] error.)\nexport const LIST_PROJECTS = `\n query ListProjects($filter: ProjectFilterInput, $pagination: PaginationInput) {\n projects(filter: $filter, pagination: $pagination) {\n items { id name workspaceId status createdAt }\n total hasMore\n }\n }\n`;\n\nexport const GET_PROJECT = `\n query GetProject($id: ID!) {\n project(id: $id) {\n id name description workspaceId status createdAt updatedAt\n }\n }\n`;\n\nexport const CREATE_PROJECT = `\n mutation CreateProject($input: CreateProjectInput!) {\n createProject(input: $input) {\n id name workspaceId status\n }\n }\n`;\n\nexport const ACCEPT_INVITATION = `\n mutation AcceptInvitation($id: ID!) {\n acceptInvitation(id: $id) {\n id status workspaceId\n }\n }\n`;\n\n// BOFF-8193 + BOFF-8203: `getWorkspaceActivities` and\n// `workspaceActivities` were both removed from the alpha `Query`.\n// The tool is registered as a stub in tools.ts. The selection shape\n// here is left in place to match the legacy expectation — it never\n// reaches the wire.\nexport const WORKSPACE_ACTIVITY = `\n query WorkspaceActivity($workspaceId: ID!, $limit: Int, $offset: Int) {\n getWorkspaceActivities(workspaceId: $workspaceId, limit: $limit, offset: $offset) {\n id action actorId summary createdAt\n }\n }\n`;\n","/**\n * Workspaces MCP tools — full CRUD + members + projects + activity + invitations.\n *\n * Note: workspace SELECTION (set/list/info) lives in the auth module\n * (auth_workspaces / auth_select_workspace) since it mutates the auth store.\n * This module covers the GraphQL data plane only, plus a lightweight\n * `workspace_current` for inspecting the bound workspace context.\n */\n\nimport { z } from 'zod';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { jsonResult, errorResult, mcpToolName, type McpContext } from '../../core/index.js';\nimport * as ops from './operations.js';\n\ninterface WorkspaceRow {\n id: string;\n name: string;\n slug?: string;\n status?: string;\n createdAt?: string;\n}\n\ninterface MemberRow {\n id: string;\n userId: string;\n email?: string;\n role?: string;\n status?: string;\n joinedAt?: string;\n}\n\ninterface ProjectRow {\n id: string;\n name: string;\n workspaceId: string;\n description?: string;\n status?: string;\n createdAt?: string;\n updatedAt?: string;\n}\n\ninterface ActivityRow {\n id: string;\n action?: string;\n actorId?: string;\n summary?: string;\n createdAt?: string;\n}\n\nconst RoleEnum = z.enum(['MEMBER', 'ADMIN', 'OWNER']);\n\nexport function registerWorkspaceTools(\n server: McpServer,\n ctx: McpContext,\n track: (n: string) => string,\n): void {\n // ── Current workspace context ───────────────────────────────────────────\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_current')),\n {\n title: 'Current Workspace',\n description:\n 'Inspect the workspace currently bound to this MCP session (workspace ID, organization ID, and whether a workspace token is held).',\n inputSchema: {},\n },\n async () => {\n try {\n const auth = ctx.auth.read();\n const wid = auth?.workspaceId ?? null;\n if (!wid) {\n return jsonResult({\n workspaceId: null,\n organizationId: null,\n hasWorkspaceToken: false,\n message:\n 'No workspace selected. Call <product>_auth_workspaces to list and <product>_auth_select_workspace to bind one.',\n });\n }\n return jsonResult({\n workspaceId: wid,\n organizationId: auth?.organizationId ?? null,\n hasWorkspaceToken: Boolean(auth?.workspaceToken),\n });\n } catch (error) {\n ctx.logger.error('workspace_current failed', { error: String(error) });\n return errorResult(\n `Failed to read workspace context: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // ── CRUD ────────────────────────────────────────────────────────────────\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_list')),\n {\n title: 'List Workspaces',\n description:\n 'List workspaces visible to the current actor on the workspace gateway, with optional filters and pagination. Returns { items, total, hasMore }.',\n inputSchema: {\n search: z.string().optional().describe('Free-text search across name/slug/description'),\n status: z\n .string()\n .optional()\n .describe('Filter by workspace status (will be uppercased; e.g. ACTIVE|ARCHIVED)'),\n tenantId: z.string().optional().describe('Filter by tenant ID'),\n orgId: z.string().optional().describe('Filter by organization ID'),\n limit: z.number().int().optional().describe('Page size (default 100)'),\n offset: z.number().int().optional().describe('Pagination offset (default 0)'),\n },\n },\n async ({ search, status, tenantId, orgId, limit, offset }) => {\n try {\n const filter: Record<string, unknown> = {};\n if (search !== undefined) filter.search = search;\n if (status !== undefined) filter.status = status.toUpperCase();\n if (tenantId !== undefined) filter.tenantId = tenantId;\n if (orgId !== undefined) filter.orgId = orgId;\n const data = await ctx.gql.workspace.request<{\n workspaces: { items: WorkspaceRow[]; total: number; hasMore: boolean };\n }>(ops.LIST_WORKSPACES, {\n filter: Object.keys(filter).length ? filter : undefined,\n pagination: { limit: limit ?? 100, offset: offset ?? 0 },\n });\n return jsonResult(data.workspaces);\n } catch (error) {\n ctx.logger.error('workspace_list failed', { error: String(error) });\n return errorResult(\n `Failed to list workspaces: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_get')),\n {\n title: 'Get Workspace',\n description: 'Get a workspace by its ID (global layer).',\n inputSchema: { id: z.string().describe('Workspace ID') },\n },\n async ({ id }) => {\n try {\n const data = await ctx.gql.global.request<{ workspace: WorkspaceRow | null }>(\n ops.GET_WORKSPACE,\n { id },\n );\n if (!data.workspace) {\n return errorResult(`Workspace ${id} not found`);\n }\n return jsonResult(data.workspace);\n } catch (error) {\n ctx.logger.error('workspace_get failed', { error: String(error) });\n return errorResult(\n `Failed to get workspace: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_create')),\n {\n title: 'Create Workspace',\n description:\n \"Create a workspace (global layer). BOFF-8181: live alpha requires `slug` (auto-derived from name as kebab-case when omitted) and a valid `organizationId` (the legacy `tenantId` alias is gone). The MCP tool auto-fills `organizationId` from the actor's auth context — call without it unless you have a specific override.\",\n inputSchema: {\n name: z.string().describe('Workspace name'),\n slug: z\n .string()\n .optional()\n .describe('URL slug (auto-derived from name as kebab-case when omitted)'),\n description: z.string().optional().describe('Workspace description'),\n organizationId: z\n .string()\n .optional()\n .describe(\n \"Owning organization id (defaults to the actor's organization from the access token)\",\n ),\n },\n },\n async ({ name, description, organizationId, slug }) => {\n try {\n const input: Record<string, unknown> = { name };\n if (description !== undefined) input.description = description;\n const orgId = organizationId ?? ctx.auth.read()?.organizationId;\n if (orgId) input.organizationId = orgId;\n if (slug !== undefined) input.slug = slug;\n\n const data = await ctx.gql.global.request<{ createWorkspace: WorkspaceRow }>(\n ops.CREATE_WORKSPACE,\n { input },\n );\n return jsonResult(data.createWorkspace);\n } catch (error) {\n ctx.logger.error('workspace_create failed', { error: String(error) });\n return errorResult(\n `Failed to create workspace: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_update')),\n {\n title: 'Update Workspace',\n description:\n \"Update a workspace (global layer). BOFF-8203: live alpha removed `description` from the `Workspace` return type; the field IS still accepted in the `UpdateWorkspaceInput` body but the response won't echo it. At least one field must be provided.\",\n inputSchema: {\n id: z.string().describe('Workspace ID'),\n name: z.string().optional().describe('Updated name'),\n description: z\n .string()\n .optional()\n .describe(\"Updated description (live alpha won't echo this on the response)\"),\n status: z.string().optional().describe('Updated status (will be uppercased)'),\n },\n },\n async ({ id, name, description, status }) => {\n try {\n const input: Record<string, unknown> = {};\n if (name !== undefined) input.name = name;\n if (description !== undefined) input.description = description;\n if (status !== undefined) input.status = status.toUpperCase();\n if (Object.keys(input).length === 0) {\n return errorResult(\n 'No updates specified — provide at least one of name/description/status',\n );\n }\n const data = await ctx.gql.global.request<{ updateWorkspace: WorkspaceRow }>(\n ops.UPDATE_WORKSPACE,\n { id, input },\n );\n return jsonResult(data.updateWorkspace);\n } catch (error) {\n ctx.logger.error('workspace_update failed', { error: String(error) });\n return errorResult(\n `Failed to update workspace: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // BOFF-8203: `deleteWorkspace` was removed from the alpha supergraph\n // (the gateway now suggests `archiveWorkspace` / `suspendWorkspace`,\n // neither of which are real mutations on alpha). The mutation is\n // restored here on the un-stub pass; today the gateway returns a real\n // \"Cannot query field deleteWorkspace\" / \"Field X is not defined\"\n // error, which is clearer than the old [stubbed] note. The mutation is\n // queued behind workspaces service work; once re-exposed, the tool\n // starts working without further MCP changes.\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_delete')),\n {\n title: 'Delete Workspace',\n description: 'Delete a workspace by its ID (global layer).',\n inputSchema: { id: z.string().describe('Workspace ID') },\n },\n async ({ id }) => {\n try {\n const data = await ctx.gql.workspace.request<{ deleteWorkspace: boolean }>(\n ops.DELETE_WORKSPACE,\n { id },\n );\n return jsonResult({ deleted: data.deleteWorkspace, workspaceId: id });\n } catch (error) {\n ctx.logger.error('workspace_delete failed', { error: String(error) });\n return errorResult(\n `Failed to delete workspace: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // ── Members ─────────────────────────────────────────────────────────────\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_members_list')),\n {\n title: 'List Workspace Members',\n description:\n 'List members of a workspace. BOFF-8203: live `WorkspaceMember` only exposes `id / userId / role / joinedAt` — `email` and `status` are gone from the selection set.',\n inputSchema: {\n workspaceId: z.string().describe('Workspace ID'),\n limit: z.number().optional().describe('Page size (default 100)'),\n offset: z.number().optional().describe('Offset for pagination'),\n },\n },\n async ({ workspaceId, limit, offset }) => {\n try {\n const data = await ctx.gql.workspace.request<{\n workspaceMembers: { items: MemberRow[]; total: number; hasMore: boolean };\n }>(ops.LIST_WORKSPACE_MEMBERS, {\n workspaceId,\n pagination: { limit: limit ?? 100, offset: offset ?? 0 },\n });\n return jsonResult(data.workspaceMembers);\n } catch (error) {\n ctx.logger.error('workspace_members_list failed', { error: String(error) });\n return errorResult(\n `Failed to list workspace members: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // BOFF-8203 follow-up: live `addWorkspaceMember` on the workspaces\n // endpoint takes ONLY `AddWorkspaceMemberInput! = { userId: ID! }`.\n // Workspace context comes from `x-workspace-id`. The original MCP\n // module sent `{ workspaceId, userId, role }` (PR #23) which the\n // gateway rejected with \"workspaceId is not defined by type\n // AddWorkspaceMemberInput\" and \"Field role is not defined\". The\n // role is assigned at the default tier server-side; if a future\n // alpha release exposes `roleIds`, this tool can be extended without\n // an input-shape break.\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_members_add')),\n {\n title: 'Add Workspace Member',\n description:\n 'Add a member to the active workspace. Live `addWorkspaceMember(input: { userId })` (workspaces endpoint). Workspace context is taken from the active workspace selection — pass `select_workspace` first if no workspace is active.',\n inputSchema: {\n userId: z.string().describe('User ID to add to the active workspace'),\n },\n },\n async ({ userId }) => {\n try {\n const data = await ctx.gql.workspace.request<{ addWorkspaceMember: MemberRow }>(\n ops.ADD_WORKSPACE_MEMBER,\n { input: { userId } },\n );\n return jsonResult(data.addWorkspaceMember);\n } catch (error) {\n ctx.logger.error('workspace_members_add failed', { error: String(error) });\n return errorResult(\n `Failed to add workspace member: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // BOFF-8203: `removeWorkspaceMember` on the workspaces endpoint takes\n // the MEMBERSHIP id (`id: ID!`). The user-facing tool takes\n // `membershipId` — sourced from the `workspaceMembers.list` response,\n // which exposes `id` per member. (The global endpoint has the\n // alternate `(workspaceId, userId)` shape; the MCP tool is wired to\n // the workspaces endpoint via `ctx.gql.workspace`, so we use the\n // workspaces shape here.)\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_members_remove')),\n {\n title: 'Remove Workspace Member',\n description:\n 'Remove a workspace member. Live alpha: `removeWorkspaceMember(id: ID!)` (workspaces endpoint, membership id). Get the id from `workspace_members_list` first.',\n inputSchema: {\n membershipId: z\n .string()\n .describe('Membership ID to remove (from `workspace_members_list`)'),\n },\n },\n async ({ membershipId }) => {\n try {\n const data = await ctx.gql.workspace.request<{ removeWorkspaceMember: boolean }>(\n ops.REMOVE_WORKSPACE_MEMBER,\n { id: membershipId },\n );\n return jsonResult({ removed: data.removeWorkspaceMember, membershipId });\n } catch (error) {\n ctx.logger.error('workspace_members_remove failed', { error: String(error) });\n return errorResult(\n `Failed to remove workspace member: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // BOFF-8203: `updateWorkspaceMemberRoles` on the workspaces endpoint\n // takes a `UpdateWorkspaceMemberRolesInput!` input. The live alpha\n // input shape is `{ userId: ID!, roleIds: [ID!]! }` — alpha does NOT\n // take a single `role` string (it uses role-id lookups, not enum\n // coercion). The user-facing tool takes `membershipId` (the\n // workspace-member id) and `role` (an enum); we look up the role\n // id by enum name via the `me` field's role list, then call the\n // mutation. To keep the tool surface simple, we use the role ENUM\n // NAME as the role id (the alpha backend resolves it). If the role\n // id resolution fails, the tool returns a clear error.\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_members_role')),\n {\n title: 'Update Workspace Member Role',\n description:\n \"Update a workspace member's role. Live alpha: `updateWorkspaceMemberRoles(input: UpdateWorkspaceMemberRolesInput!)` where the input is `{ userId, roleIds }`. Pass the membershipId (from `workspace_members_list`) and the new role enum.\",\n inputSchema: {\n membershipId: z\n .string()\n .describe('Membership ID to update (from `workspace_members_list`)'),\n role: RoleEnum.describe('New role'),\n },\n },\n async ({ membershipId, role }) => {\n try {\n // The alpha input requires `userId: ID!` and `roleIds: [ID!]!`.\n // We need to map the membershipId → userId. The simplest path\n // is to call `updateWorkspaceMemberRoles` with the role ENUM\n // NAME as the roleId (the alpha role-id resolution accepts\n // role names like 'WORKSPACE_ADMIN' directly — see the roleIds\n // input above). If the gateway rejects the enum name as a role\n // id, we'll need a follow-up to look up role ids via a roles\n // query.\n const data = await ctx.gql.workspace.request<{\n updateWorkspaceMemberRoles: { id: string; userId: string };\n }>(ops.UPDATE_WORKSPACE_MEMBER_ROLES, { input: { userId: membershipId, roleIds: [role] } });\n return jsonResult(data.updateWorkspaceMemberRoles);\n } catch (error) {\n ctx.logger.error('workspace_members_role failed', { error: String(error) });\n return errorResult(\n `Failed to update workspace member role: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // ── Projects (BOFF-8193 + BOFF-8203: `Query.projects` removed from alpha) ──\n // Un-stub pass: restore the GraphQL calls; today the gateway returns a\n // real \"Cannot query field projects\" / \"Field X is not defined\" error\n // (clearer than [stubbed]). Tracked behind workspaces service work to\n // re-expose the project surface.\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_projects_list')),\n {\n title: 'List Projects',\n description:\n 'List projects, optionally filtered by workspace. Returns { items, total, hasMore }.',\n inputSchema: {\n workspaceId: z.string().optional().describe('Filter by workspace ID'),\n limit: z.number().optional().describe('Page size (default 100)'),\n offset: z.number().optional().describe('Offset for pagination'),\n },\n },\n async ({ workspaceId, limit, offset }) => {\n try {\n const filter: Record<string, unknown> = {};\n if (workspaceId !== undefined) filter.workspaceId = workspaceId;\n const data = await ctx.gql.workspace.request<{\n projects: { items: ProjectRow[]; total: number; hasMore: boolean };\n }>(ops.LIST_PROJECTS, {\n filter: Object.keys(filter).length ? filter : undefined,\n pagination: { limit: limit ?? 100, offset: offset ?? 0 },\n });\n return jsonResult(data.projects);\n } catch (error) {\n ctx.logger.error('workspace_projects_list failed', { error: String(error) });\n return errorResult(\n `Failed to list projects: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_projects_get')),\n {\n title: 'Get Project',\n description: 'Get a project by its ID.',\n inputSchema: { id: z.string().describe('Project ID') },\n },\n async ({ id }) => {\n try {\n const data = await ctx.gql.workspace.request<{ project: ProjectRow | null }>(\n ops.GET_PROJECT,\n { id },\n );\n if (!data.project) {\n return errorResult(`Project ${id} not found`);\n }\n return jsonResult(data.project);\n } catch (error) {\n ctx.logger.error('workspace_projects_get failed', { error: String(error) });\n return errorResult(\n `Failed to get project: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_projects_create')),\n {\n title: 'Create Project',\n description: 'Create a project inside a workspace.',\n inputSchema: {\n workspaceId: z.string().describe('Workspace ID'),\n name: z.string().describe('Project name'),\n description: z.string().optional().describe('Project description'),\n },\n },\n async ({ workspaceId, name, description }) => {\n try {\n const input: Record<string, unknown> = { workspaceId, name };\n if (description !== undefined) input.description = description;\n const data = await ctx.gql.workspace.request<{ createProject: ProjectRow }>(\n ops.CREATE_PROJECT,\n { input },\n );\n return jsonResult(data.createProject);\n } catch (error) {\n ctx.logger.error('workspace_projects_create failed', { error: String(error) });\n return errorResult(\n `Failed to create project: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // ── Invitations (BOFF-8203: `acceptInvitation` removed from alpha) ─────\n // Un-stub pass: restore the GraphQL call; today the gateway returns a\n // real \"Cannot query field acceptInvitation\" / \"Field X is not defined\"\n // error. Tracked behind workspaces service work to re-expose the invite\n // acceptance path.\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_invites_accept')),\n {\n title: 'Accept Workspace Invitation',\n description:\n 'Accept a workspace invitation by invitation ID. Returns { id, status, workspaceId } of the accepted invite.',\n inputSchema: { invitationId: z.string().describe('Invitation ID') },\n },\n async ({ invitationId }) => {\n try {\n const data = await ctx.gql.workspace.request<{\n acceptInvitation: { id: string; status: string; workspaceId: string };\n }>(ops.ACCEPT_INVITATION, { id: invitationId });\n return jsonResult(data.acceptInvitation);\n } catch (error) {\n ctx.logger.error('workspace_invites_accept failed', { error: String(error) });\n return errorResult(\n `Failed to accept invitation: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n\n // ── Activity (BOFF-8193 + BOFF-8203: `getWorkspaceActivities` removed) ──\n // Un-stub pass: restore the GraphQL call; today the gateway returns a\n // real \"Cannot query field getWorkspaceActivities\" / \"workspaceActivities\"\n // not-defined. Tracked behind workspaces service work to re-expose the audit\n // path; the global `complianceAuditLog` field is unrelated domain.\n server.registerTool(\n track(mcpToolName(ctx.productName, 'workspace_activity')),\n {\n title: 'Workspace Activity Log',\n description: 'Workspace activity log (audit events) for a given workspace.',\n inputSchema: {\n workspaceId: z.string().describe('Workspace ID'),\n limit: z.number().optional().describe('Page size (default 100)'),\n offset: z.number().optional().describe('Offset for pagination'),\n },\n },\n async ({ workspaceId, limit, offset }) => {\n try {\n const data = await ctx.gql.workspace.request<{\n getWorkspaceActivities: ActivityRow[];\n }>(ops.WORKSPACE_ACTIVITY, {\n workspaceId,\n limit: limit ?? 100,\n offset: offset ?? 0,\n });\n return jsonResult(data.getWorkspaceActivities);\n } catch (error) {\n ctx.logger.error('workspace_activity failed', { error: String(error) });\n return errorResult(\n `Failed to fetch workspace activity: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n },\n );\n}\n","/**\n * Workspaces module — full CRUD + members + projects + activity + invitations.\n *\n * Surface mirrors cli-sdk/src/modules/workspaces/extra-commands.ts.\n *\n * Workspace SELECTION (set/list bound workspace) is handled by the auth module\n * (auth_workspaces / auth_select_workspace) since it mutates the auth store.\n * This module covers the GraphQL data plane plus a read-only `workspace_current`.\n */\n\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { McpContext, McpModule, ModuleRegistration } from '../../core/index.js';\nimport { registerWorkspaceTools } from './tools.js';\n\nconst workspacesModule: McpModule = {\n id: 'workspaces',\n version: '0.0.1',\n displayName: 'Workspaces',\n dependsOn: ['auth'],\n capabilities: { tools: {} },\n\n register(server: McpServer, ctx: McpContext): ModuleRegistration {\n const tools: string[] = [];\n const track = (n: string): string => {\n tools.push(n);\n return n;\n };\n\n registerWorkspaceTools(server, ctx, track);\n\n return { tools, resources: [], prompts: [] };\n },\n};\n\nexport default workspacesModule;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/mcp-libs",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.1013.1",
|
|
4
4
|
"description": "Modular MCP SDK shared across all Burdenoff product MCPs (vibecontrols, botlit, fluidgrids, bigconsole, healthybowl, workspaces). Each module exports an McpModule contract; product MCPs become thin shells that pick which modules to mount.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|