@convisoappsec/mcp 0.6.0 → 0.6.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@convisoappsec/mcp",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "MCP Server for Conviso Platform integration",
5
5
  "type": "module",
6
6
  "main": "src/conviso_mcp/server.js",
@@ -60,6 +60,9 @@ export function buildCreateProjectInput(a = {}) {
60
60
  scope: a.scope,
61
61
  startDate: a.start_date,
62
62
  endDate: a.end_date,
63
+ // Platform quirk: requirement/checklist IDs are called "playbooks" on this input.
64
+ playbooksIds: a.requirement_ids,
65
+ assetsIds: a.asset_ids,
63
66
  ...(a.extra || {}),
64
67
  }),
65
68
  };
@@ -557,6 +560,29 @@ class GraphQLClient {
557
560
  return this.execute(PROJECTS_QUERY, variables);
558
561
  }
559
562
 
563
+ async get_project_types(search = null) {
564
+ const query = `
565
+ query GetProjectTypes($page: Int, $limit: Int, $params: ProjectTypeSearch) {
566
+ projectTypes(page: $page, limit: $limit, params: $params) {
567
+ collection { id code label description defaultDuration }
568
+ metadata { totalCount totalPages currentPage limitValue }
569
+ }
570
+ }`;
571
+ const params = search ? { labelCont: search } : undefined;
572
+ return this.execute(query, { page: 1, limit: 100, params });
573
+ }
574
+
575
+ async get_project_statuses() {
576
+ const query = `
577
+ query GetProjectStatuses($page: Int, $limit: Int) {
578
+ projectStatuses(page: $page, limit: $limit) {
579
+ collection { id label isInitial }
580
+ metadata { totalCount }
581
+ }
582
+ }`;
583
+ return this.execute(query, { page: 1, limit: 100 });
584
+ }
585
+
560
586
  async get_project_by_id(project_id) {
561
587
  const query = `
562
588
  query GetProject($id: ID!) {
@@ -767,7 +793,8 @@ class GraphQLClient {
767
793
  return this.execute(query, { companyId: company_id, id: ticket_id });
768
794
  }
769
795
 
770
- async get_requirements(scope_id, { page = 1, limit = 25, filters } = {}) {
796
+ async get_requirements(scope_id, { page = 1, limit = 25, search, filters } = {}) {
797
+ if (search) filters = { ...(filters || {}), label: search };
771
798
  const query = `
772
799
  query GetRequirements($scopeId: Int!, $pagination: BasePaginationInput!, $filters: RequirementsFilterInput) {
773
800
  requirements(scopeId: $scopeId, pagination: $pagination, filters: $filters) {
@@ -231,6 +231,18 @@ function buildServer() {
231
231
  schema: z.object({ project_id: z.number() }),
232
232
  }, ({ project_id }) => gql.get_project_by_id(project_id));
233
233
 
234
+ tool('get_project_types', {
235
+ title: 'List Project Types',
236
+ desc: 'List the available project types (id, code, label, description). Use this to find the type_id required by create_project. Optional: search (label substring).',
237
+ schema: z.object({ search: z.string().optional() }),
238
+ }, ({ search }) => gql.get_project_types(search));
239
+
240
+ tool('get_project_statuses', {
241
+ title: 'List Project Statuses',
242
+ desc: 'List the available project statuses (id, label, isInitial). Use to find valid status values for project status updates.',
243
+ schema: z.object({}),
244
+ }, () => gql.get_project_statuses());
245
+
234
246
  tool('get_asset', {
235
247
  title: 'Asset Details',
236
248
  desc: 'Get an asset by ID.',
@@ -349,14 +361,19 @@ function buildServer() {
349
361
 
350
362
  tool('get_requirements', {
351
363
  title: 'List Requirements',
352
- desc: 'List security requirements/checklists for a scope (company) id, paginated. Optional: filters (raw RequirementsFilterInput).',
364
+ desc: 'List security requirements/checklists (also called playbooks) for a scope (company) id, paginated. Optional: search (label substring — use to find a requirement by name), only_from_company (exclude global requirements), filters (raw RequirementsFilterInput). To attach requirements to a NEW project, pass their ids as requirement_ids in create_project.',
353
365
  schema: z.object({
354
366
  scope_id: z.number(),
355
367
  page: z.number().optional(),
356
368
  limit: z.number().optional(),
369
+ search: z.string().optional(),
370
+ only_from_company: z.boolean().optional(),
357
371
  filters: z.record(z.string(), z.any()).optional(),
358
372
  }),
359
- }, ({ scope_id, page, limit, filters }) => gql.get_requirements(scope_id, { page, limit, filters }));
373
+ }, ({ scope_id, page, limit, search, only_from_company, filters }) => {
374
+ if (only_from_company !== undefined) filters = { ...(filters || {}), onlyFromCompany: only_from_company };
375
+ return gql.get_requirements(scope_id, { page, limit, search, filters });
376
+ });
360
377
 
361
378
  tool('get_requirement', {
362
379
  title: 'Requirement Details',
@@ -547,7 +564,7 @@ function buildServer() {
547
564
 
548
565
  tool('create_project', {
549
566
  title: 'Create Project',
550
- desc: 'Create a project. Required: company_id, type_id (project type id), label, goal, scope, start_date (YYYY-MM-DD). Optional: end_date; extra = advanced CreateProjectInput fields (assetsIds, tags, allocatedPortalUserEmails...).',
567
+ desc: 'Create a project. Required: company_id, type_id (call get_project_types to find it), label, goal, scope, start_date (YYYY-MM-DD). Optional: end_date; requirement_ids = requirement/checklist ids to associate (find them with get_requirements — the platform calls these playbooks); asset_ids = asset ids to link; extra = advanced CreateProjectInput fields (tags, allocatedPortalUserEmails...).',
551
568
  schema: z.object({
552
569
  company_id: z.number(),
553
570
  type_id: z.number(),
@@ -556,6 +573,8 @@ function buildServer() {
556
573
  scope: z.string(),
557
574
  start_date: z.string(),
558
575
  end_date: z.string().optional(),
576
+ requirement_ids: z.array(z.number()).optional(),
577
+ asset_ids: z.array(z.number()).optional(),
559
578
  extra: z.record(z.string(), z.any()).optional(),
560
579
  }),
561
580
  write: true,