loopctl-mcp-server 2.22.0 → 2.23.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.
Files changed (2) hide show
  1. package/index.js +66 -22
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -178,8 +178,12 @@ async function getTenant() {
178
178
  return toContent(result);
179
179
  }
180
180
 
181
- async function listProjects() {
182
- const result = await apiCall("GET", "/api/v1/projects");
181
+ async function listProjects({ page, page_size } = {}) {
182
+ const params = new URLSearchParams();
183
+ if (page != null) params.set("page", String(page));
184
+ if (page_size != null) params.set("page_size", String(page_size));
185
+ const query = params.toString() ? `?${params}` : "";
186
+ const result = await apiCall("GET", `/api/v1/projects${query}`);
183
187
  return toContent(result);
184
188
  }
185
189
 
@@ -381,12 +385,13 @@ async function listStories({ project_id, agent_status, verified_status, epic_id,
381
385
  return toContentCompact(result);
382
386
  }
383
387
 
384
- async function listReadyStories({ project_id, limit }) {
388
+ async function listReadyStories({ project_id, page, page_size }) {
389
+ // /stories/ready paginates by page/page_size — the old `limit` param was
390
+ // silently ignored by the server, capping callers at the first page.
385
391
  const params = new URLSearchParams({ project_id });
386
- params.set(
387
- "limit",
388
- String(Math.min(limit ?? DEFAULT_STORY_PAGE_SIZE, SERVER_MAX_STORY_PAGE_SIZE)),
389
- );
392
+ if (page != null) params.set("page", String(page));
393
+ if (page_size != null)
394
+ params.set("page_size", String(Math.min(page_size, SERVER_MAX_STORY_PAGE_SIZE)));
390
395
 
391
396
  const result = await apiCall("GET", `/api/v1/stories/ready?${params}`);
392
397
  return toContentCompact(result);
@@ -559,14 +564,20 @@ async function getCostSummary({ project_id, breakdown }) {
559
564
  return toContent(result);
560
565
  }
561
566
 
562
- async function getStoryTokenUsage({ story_id }) {
563
- const result = await apiCall("GET", `/api/v1/stories/${story_id}/token-usage`);
567
+ async function getStoryTokenUsage({ story_id, page, page_size }) {
568
+ const params = new URLSearchParams();
569
+ if (page != null) params.set("page", String(page));
570
+ if (page_size != null) params.set("page_size", String(page_size));
571
+ const query = params.toString() ? `?${params}` : "";
572
+ const result = await apiCall("GET", `/api/v1/stories/${story_id}/token-usage${query}`);
564
573
  return toContent(result);
565
574
  }
566
575
 
567
- async function getCostAnomalies({ project_id }) {
576
+ async function getCostAnomalies({ project_id, page, page_size }) {
568
577
  const params = new URLSearchParams();
569
578
  if (project_id) params.set("project_id", project_id);
579
+ if (page != null) params.set("page", String(page));
580
+ if (page_size != null) params.set("page_size", String(page_size));
570
581
 
571
582
  const query = params.toString() ? `?${params}` : "";
572
583
  const result = await apiCall("GET", `/api/v1/cost-anomalies${query}`);
@@ -1069,8 +1080,18 @@ async function knowledgeIngestBatch({ items, project_id, publish }) {
1069
1080
  return toContent(result);
1070
1081
  }
1071
1082
 
1072
- async function knowledgeIngestionJobs() {
1073
- const result = await apiCall("GET", "/api/v1/knowledge/ingestion-jobs", null, process.env.LOOPCTL_ORCH_KEY);
1083
+ async function knowledgeIngestionJobs({ limit, offset, since_days } = {}) {
1084
+ const params = new URLSearchParams();
1085
+ if (limit != null) params.set("limit", String(limit));
1086
+ if (offset != null) params.set("offset", String(offset));
1087
+ if (since_days != null) params.set("since_days", String(since_days));
1088
+ const query = params.toString() ? `?${params}` : "";
1089
+ const result = await apiCall(
1090
+ "GET",
1091
+ `/api/v1/knowledge/ingestion-jobs${query}`,
1092
+ null,
1093
+ process.env.LOOPCTL_ORCH_KEY,
1094
+ );
1074
1095
  return toContent(result);
1075
1096
  }
1076
1097
 
@@ -1401,10 +1422,15 @@ const TOOLS = [
1401
1422
  },
1402
1423
  {
1403
1424
  name: "list_projects",
1404
- description: "List all projects in the current tenant.",
1425
+ description:
1426
+ "List projects in the current tenant. Paginated (page/page_size); advance " +
1427
+ "`page` to enumerate all projects. Response includes pagination meta.",
1405
1428
  inputSchema: {
1406
1429
  type: "object",
1407
- properties: {},
1430
+ properties: {
1431
+ page: { type: "integer", description: "Page number (default 1)." },
1432
+ page_size: { type: "integer", description: "Items per page (default 20)." },
1433
+ },
1408
1434
  required: [],
1409
1435
  },
1410
1436
  },
@@ -1608,7 +1634,8 @@ const TOOLS = [
1608
1634
  description:
1609
1635
  "List stories that are ready to be worked on (contracted, dependencies met). " +
1610
1636
  "Returns compact results — use get_story for full details. " +
1611
- "Defaults to 20 per page; pass `limit` up to 500 to page larger. Response includes total_count.",
1637
+ "Paginated (page/page_size); advance `page` to enumerate all ready stories. " +
1638
+ "Response includes total_count.",
1612
1639
  inputSchema: {
1613
1640
  type: "object",
1614
1641
  properties: {
@@ -1616,9 +1643,10 @@ const TOOLS = [
1616
1643
  type: "string",
1617
1644
  description: "The UUID of the project.",
1618
1645
  },
1619
- limit: {
1646
+ page: { type: "integer", description: "Page number (default 1)." },
1647
+ page_size: {
1620
1648
  type: "integer",
1621
- description: "Maximum number of stories to return (default 20, max 500).",
1649
+ description: "Stories per page (default 100, max 500).",
1622
1650
  },
1623
1651
  },
1624
1652
  required: ["project_id"],
@@ -1963,7 +1991,9 @@ const TOOLS = [
1963
1991
  },
1964
1992
  {
1965
1993
  name: "get_story_token_usage",
1966
- description: "Get token usage records for a single story.",
1994
+ description:
1995
+ "Get token usage records for a single story. Paginated (page/page_size); " +
1996
+ "advance `page` to enumerate all records.",
1967
1997
  inputSchema: {
1968
1998
  type: "object",
1969
1999
  properties: {
@@ -1971,6 +2001,8 @@ const TOOLS = [
1971
2001
  type: "string",
1972
2002
  description: "The UUID of the story.",
1973
2003
  },
2004
+ page: { type: "integer", description: "Page number (default 1)." },
2005
+ page_size: { type: "integer", description: "Records per page (default 20)." },
1974
2006
  },
1975
2007
  required: ["story_id"],
1976
2008
  },
@@ -1979,7 +2011,8 @@ const TOOLS = [
1979
2011
  name: "get_cost_anomalies",
1980
2012
  description:
1981
2013
  "Get cost anomaly alerts — stories or agents that exceed expected token budgets. " +
1982
- "Optionally filter by project.",
2014
+ "Optionally filter by project. Paginated (page/page_size); advance `page` to " +
2015
+ "enumerate all anomalies.",
1983
2016
  inputSchema: {
1984
2017
  type: "object",
1985
2018
  properties: {
@@ -1987,6 +2020,8 @@ const TOOLS = [
1987
2020
  type: "string",
1988
2021
  description: "Optional: filter anomalies to a specific project UUID.",
1989
2022
  },
2023
+ page: { type: "integer", description: "Page number (default 1)." },
2024
+ page_size: { type: "integer", description: "Anomalies per page (default 20)." },
1990
2025
  },
1991
2026
  required: [],
1992
2027
  },
@@ -3038,11 +3073,20 @@ const TOOLS = [
3038
3073
  {
3039
3074
  name: "knowledge_ingestion_jobs",
3040
3075
  description:
3041
- "List recent content ingestion jobs for the current tenant. " +
3042
- "Returns jobs from the last 7 days, max 50 results. Requires orchestrator role.",
3076
+ "List content ingestion jobs for the current tenant, newest first. " +
3077
+ "Paginated (limit/offset over the full history; advance `offset` by `meta.limit` " +
3078
+ "to enumerate to completeness). Optional `since_days` narrows to a recent window. " +
3079
+ "Requires orchestrator role.",
3043
3080
  inputSchema: {
3044
3081
  type: "object",
3045
- properties: {},
3082
+ properties: {
3083
+ limit: { type: "integer", description: "Jobs per page (default 20)." },
3084
+ offset: { type: "integer", description: "Rows to skip (default 0)." },
3085
+ since_days: {
3086
+ type: "integer",
3087
+ description: "Optional: only jobs from the last N days (default: all history).",
3088
+ },
3089
+ },
3046
3090
  required: [],
3047
3091
  },
3048
3092
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loopctl-mcp-server",
3
- "version": "2.22.0",
3
+ "version": "2.23.0",
4
4
  "description": "MCP server for loopctl — structural trust for AI development loops",
5
5
  "type": "module",
6
6
  "main": "index.js",