loopctl-mcp-server 1.0.0 → 1.0.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.
Files changed (2) hide show
  1. package/index.js +35 -6
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -115,6 +115,32 @@ function toContent(result) {
115
115
  };
116
116
  }
117
117
 
118
+ /**
119
+ * Compact variant for list endpoints — strips bulky fields (acceptance_criteria,
120
+ * description) from each story to stay within token limits. Callers can use
121
+ * get_story for full details on individual stories.
122
+ */
123
+ function toContentCompact(result) {
124
+ if (result && result.error === true) return toContent(result);
125
+
126
+ if (result && Array.isArray(result.data)) {
127
+ const compact = {
128
+ ...result,
129
+ data: result.data.map(({ acceptance_criteria, description, ...rest }) => rest),
130
+ };
131
+ return {
132
+ content: [
133
+ {
134
+ type: "text",
135
+ text: JSON.stringify(compact, null, 2),
136
+ },
137
+ ],
138
+ };
139
+ }
140
+
141
+ return toContent(result);
142
+ }
143
+
118
144
  // ---------------------------------------------------------------------------
119
145
  // Tool implementations
120
146
  // ---------------------------------------------------------------------------
@@ -162,19 +188,19 @@ async function listStories({ project_id, agent_status, verified_status, epic_id,
162
188
  if (agent_status) params.set("agent_status", agent_status);
163
189
  if (verified_status) params.set("verified_status", verified_status);
164
190
  if (epic_id) params.set("epic_id", epic_id);
165
- if (limit != null) params.set("limit", String(limit));
191
+ params.set("limit", String(limit ?? 20));
166
192
  if (offset != null) params.set("offset", String(offset));
167
193
 
168
194
  const result = await apiCall("GET", `/api/v1/stories?${params}`);
169
- return toContent(result);
195
+ return toContentCompact(result);
170
196
  }
171
197
 
172
198
  async function listReadyStories({ project_id, limit }) {
173
199
  const params = new URLSearchParams({ project_id });
174
- if (limit != null) params.set("limit", String(limit));
200
+ params.set("limit", String(limit ?? 20));
175
201
 
176
202
  const result = await apiCall("GET", `/api/v1/stories/ready?${params}`);
177
- return toContent(result);
203
+ return toContentCompact(result);
178
204
  }
179
205
 
180
206
  async function getStory({ story_id }) {
@@ -391,7 +417,9 @@ const TOOLS = [
391
417
  {
392
418
  name: "list_stories",
393
419
  description:
394
- "List stories for a project, optionally filtered by agent_status, verified_status, or epic_id.",
420
+ "List stories for a project, optionally filtered by agent_status, verified_status, or epic_id. " +
421
+ "Returns compact results (no acceptance_criteria/description) — use get_story for full details. " +
422
+ "Defaults to 20 stories per page; use limit/offset to paginate.",
395
423
  inputSchema: {
396
424
  type: "object",
397
425
  properties: {
@@ -427,7 +455,8 @@ const TOOLS = [
427
455
  {
428
456
  name: "list_ready_stories",
429
457
  description:
430
- "List stories that are ready to be worked on (contracted, dependencies met). These are the stories an agent should pick up next.",
458
+ "List stories that are ready to be worked on (contracted, dependencies met). " +
459
+ "Returns compact results — use get_story for full details. Defaults to 20 per page.",
431
460
  inputSchema: {
432
461
  type: "object",
433
462
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loopctl-mcp-server",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "MCP server for loopctl — structural trust for AI development loops",
5
5
  "type": "module",
6
6
  "main": "index.js",