@limeadelabs/launchpad-mcp 1.2.0 → 1.2.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/dist/index.js +43 -38
- package/package.json +8 -2
package/dist/index.js
CHANGED
|
@@ -184,7 +184,7 @@ function registerProjectTools(server2, client2) {
|
|
|
184
184
|
"lp_get_project",
|
|
185
185
|
"Get project details including agent_instructions",
|
|
186
186
|
{
|
|
187
|
-
project_id: z.number().describe("Project ID")
|
|
187
|
+
project_id: z.coerce.number().describe("Project ID")
|
|
188
188
|
},
|
|
189
189
|
async (params) => {
|
|
190
190
|
try {
|
|
@@ -204,11 +204,11 @@ function registerTaskTools(server2, client2) {
|
|
|
204
204
|
"lp_list_tasks",
|
|
205
205
|
"List tasks from LaunchPad with optional filters (project, status, priority, label, assignee)",
|
|
206
206
|
{
|
|
207
|
-
project_id: z2.number().optional().describe("Filter by project ID"),
|
|
207
|
+
project_id: z2.coerce.number().optional().describe("Filter by project ID"),
|
|
208
208
|
status: z2.string().optional().describe("Filter by status: todo, ready, in_progress, review, done"),
|
|
209
209
|
priority: z2.string().optional().describe("Filter by priority: low, medium, high"),
|
|
210
210
|
label: z2.string().optional().describe("Filter by label name"),
|
|
211
|
-
assignee_id: z2.number().optional().describe("Filter by assignee user ID")
|
|
211
|
+
assignee_id: z2.coerce.number().optional().describe("Filter by assignee user ID")
|
|
212
212
|
},
|
|
213
213
|
async (params) => {
|
|
214
214
|
try {
|
|
@@ -223,7 +223,7 @@ function registerTaskTools(server2, client2) {
|
|
|
223
223
|
"lp_get_task",
|
|
224
224
|
"Get full task context \u2014 description, comments, links, specs",
|
|
225
225
|
{
|
|
226
|
-
task_id: z2.number().describe("Task ID")
|
|
226
|
+
task_id: z2.coerce.number().describe("Task ID")
|
|
227
227
|
},
|
|
228
228
|
async (params) => {
|
|
229
229
|
try {
|
|
@@ -238,7 +238,7 @@ function registerTaskTools(server2, client2) {
|
|
|
238
238
|
"lp_create_task",
|
|
239
239
|
"Create a new task in LaunchPad",
|
|
240
240
|
{
|
|
241
|
-
project_id: z2.number().describe("Project ID to create the task in"),
|
|
241
|
+
project_id: z2.coerce.number().describe("Project ID to create the task in"),
|
|
242
242
|
title: z2.string().describe("Task title"),
|
|
243
243
|
description: z2.string().optional().describe("Task description"),
|
|
244
244
|
status: z2.string().optional().describe("Initial status: todo, ready, in_progress, review, done"),
|
|
@@ -257,10 +257,10 @@ function registerTaskTools(server2, client2) {
|
|
|
257
257
|
"lp_update_task",
|
|
258
258
|
"Update task status and/or fields. LaunchPad enforces workflow transitions \u2014 use lp_get_workflow to check valid transitions before changing status.",
|
|
259
259
|
{
|
|
260
|
-
task_id: z2.number().describe("Task ID"),
|
|
260
|
+
task_id: z2.coerce.number().describe("Task ID"),
|
|
261
261
|
status: z2.string().optional().describe("New status (must be a valid workflow transition)"),
|
|
262
262
|
priority: z2.string().optional().describe("New priority: low, medium, high"),
|
|
263
|
-
assignee_id: z2.number().optional().describe("Assignee user ID"),
|
|
263
|
+
assignee_id: z2.coerce.number().optional().describe("Assignee user ID"),
|
|
264
264
|
title: z2.string().optional().describe("New title"),
|
|
265
265
|
description: z2.string().optional().describe("New description")
|
|
266
266
|
},
|
|
@@ -283,7 +283,7 @@ function registerClaimTools(server2, client2) {
|
|
|
283
283
|
"lp_claim_task",
|
|
284
284
|
"Claim a task before working on it. Prevents other agents from picking it up.",
|
|
285
285
|
{
|
|
286
|
-
task_id: z3.number().describe("Task ID to claim")
|
|
286
|
+
task_id: z3.coerce.number().describe("Task ID to claim")
|
|
287
287
|
},
|
|
288
288
|
async (params) => {
|
|
289
289
|
try {
|
|
@@ -298,7 +298,7 @@ function registerClaimTools(server2, client2) {
|
|
|
298
298
|
"lp_release_task",
|
|
299
299
|
"Release a claimed task so others can pick it up",
|
|
300
300
|
{
|
|
301
|
-
task_id: z3.number().describe("Task ID to release")
|
|
301
|
+
task_id: z3.coerce.number().describe("Task ID to release")
|
|
302
302
|
},
|
|
303
303
|
async (params) => {
|
|
304
304
|
try {
|
|
@@ -313,7 +313,7 @@ function registerClaimTools(server2, client2) {
|
|
|
313
313
|
"lp_heartbeat",
|
|
314
314
|
"Send a heartbeat for a claimed task to keep the claim alive. Claims expire after 30 minutes without a heartbeat.",
|
|
315
315
|
{
|
|
316
|
-
task_id: z3.number().describe("Task ID to heartbeat")
|
|
316
|
+
task_id: z3.coerce.number().describe("Task ID to heartbeat")
|
|
317
317
|
},
|
|
318
318
|
async (params) => {
|
|
319
319
|
try {
|
|
@@ -333,7 +333,7 @@ function registerCommentTools(server2, client2) {
|
|
|
333
333
|
"lp_add_comment",
|
|
334
334
|
"Post a comment on a task (progress updates, notes, questions)",
|
|
335
335
|
{
|
|
336
|
-
task_id: z4.number().describe("Task ID to comment on"),
|
|
336
|
+
task_id: z4.coerce.number().describe("Task ID to comment on"),
|
|
337
337
|
body: z4.string().describe("Comment body text")
|
|
338
338
|
},
|
|
339
339
|
async (params) => {
|
|
@@ -354,8 +354,8 @@ function registerTimeTools(server2, client2) {
|
|
|
354
354
|
"lp_log_time",
|
|
355
355
|
"Track time spent on a task",
|
|
356
356
|
{
|
|
357
|
-
task_id: z5.number().describe("Task ID"),
|
|
358
|
-
duration_minutes: z5.number().positive().describe("Duration in minutes"),
|
|
357
|
+
task_id: z5.coerce.number().describe("Task ID"),
|
|
358
|
+
duration_minutes: z5.coerce.number().positive().describe("Duration in minutes"),
|
|
359
359
|
description: z5.string().optional().describe("Description of work done")
|
|
360
360
|
},
|
|
361
361
|
async (params) => {
|
|
@@ -376,7 +376,7 @@ function registerPromptTools(server2, client2) {
|
|
|
376
376
|
"lp_generate_prompt",
|
|
377
377
|
"Generate a build-ready prompt/spec for a task with full context, conventions, and acceptance criteria",
|
|
378
378
|
{
|
|
379
|
-
task_id: z6.number().describe("Task ID")
|
|
379
|
+
task_id: z6.coerce.number().describe("Task ID")
|
|
380
380
|
},
|
|
381
381
|
async (params) => {
|
|
382
382
|
try {
|
|
@@ -394,14 +394,16 @@ import { z as z7 } from "zod";
|
|
|
394
394
|
function registerPageTools(server2, client2) {
|
|
395
395
|
server2.tool(
|
|
396
396
|
"lp_list_pages",
|
|
397
|
-
"List spec/doc pages for a project",
|
|
397
|
+
"List spec/doc pages for a project (titles and IDs only \u2014 use lp_get_page to fetch full content)",
|
|
398
398
|
{
|
|
399
|
-
project_id: z7.number().describe("Project ID")
|
|
399
|
+
project_id: z7.coerce.number().describe("Project ID")
|
|
400
400
|
},
|
|
401
401
|
async (params) => {
|
|
402
402
|
try {
|
|
403
403
|
const result = await client2.listPages(params.project_id);
|
|
404
|
-
|
|
404
|
+
const pages = result.pages ?? result;
|
|
405
|
+
const summary = Array.isArray(pages) ? pages.map(({ id, title, author, created_at, updated_at }) => ({ id, title, author, created_at, updated_at })) : pages;
|
|
406
|
+
return { content: [{ type: "text", text: JSON.stringify(summary, null, 2) }] };
|
|
405
407
|
} catch (error) {
|
|
406
408
|
return handleError(error, client2.timeoutMs);
|
|
407
409
|
}
|
|
@@ -409,14 +411,17 @@ function registerPageTools(server2, client2) {
|
|
|
409
411
|
);
|
|
410
412
|
server2.tool(
|
|
411
413
|
"lp_get_page",
|
|
412
|
-
"Get a page's full content",
|
|
414
|
+
"Get a page's full content by project_id and page_id (also accepts id as alias for page_id)",
|
|
413
415
|
{
|
|
414
|
-
project_id: z7.number().describe("Project ID"),
|
|
415
|
-
page_id: z7.number().describe("Page ID")
|
|
416
|
+
project_id: z7.coerce.number().describe("Project ID"),
|
|
417
|
+
page_id: z7.coerce.number().optional().describe("Page ID"),
|
|
418
|
+
id: z7.coerce.number().optional().describe("Page ID (alias for page_id)")
|
|
416
419
|
},
|
|
417
420
|
async (params) => {
|
|
418
421
|
try {
|
|
419
|
-
const
|
|
422
|
+
const pageId = params.page_id ?? params.id;
|
|
423
|
+
if (!pageId) throw new Error("page_id or id is required");
|
|
424
|
+
const result = await client2.getPage(params.project_id, pageId);
|
|
420
425
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
421
426
|
} catch (error) {
|
|
422
427
|
return handleError(error, client2.timeoutMs);
|
|
@@ -427,7 +432,7 @@ function registerPageTools(server2, client2) {
|
|
|
427
432
|
"lp_get_workflow",
|
|
428
433
|
"Get valid workflow states and transitions for a project",
|
|
429
434
|
{
|
|
430
|
-
project_id: z7.number().describe("Project ID")
|
|
435
|
+
project_id: z7.coerce.number().describe("Project ID")
|
|
431
436
|
},
|
|
432
437
|
async (params) => {
|
|
433
438
|
try {
|
|
@@ -447,11 +452,11 @@ function registerContextTools(server2, client2) {
|
|
|
447
452
|
"lp_context_list",
|
|
448
453
|
"List available context entries with optional filters",
|
|
449
454
|
{
|
|
450
|
-
project_id: z8.number().optional().describe("Filter by project ID"),
|
|
455
|
+
project_id: z8.coerce.number().optional().describe("Filter by project ID"),
|
|
451
456
|
entry_type: z8.string().optional().describe("Filter by entry type"),
|
|
452
457
|
search: z8.string().optional().describe("Text search on entry name"),
|
|
453
|
-
limit: z8.number().min(1).max(100).optional().describe("Max entries to return (default 50)"),
|
|
454
|
-
offset: z8.number().min(0).optional().describe("Offset for pagination")
|
|
458
|
+
limit: z8.coerce.number().min(1).max(100).optional().describe("Max entries to return (default 50)"),
|
|
459
|
+
offset: z8.coerce.number().min(0).optional().describe("Offset for pagination")
|
|
455
460
|
},
|
|
456
461
|
async (params) => {
|
|
457
462
|
try {
|
|
@@ -467,7 +472,7 @@ function registerContextTools(server2, client2) {
|
|
|
467
472
|
"Fetch a specific context entry by slug or ID",
|
|
468
473
|
{
|
|
469
474
|
slug: z8.string().optional().describe("Entry slug"),
|
|
470
|
-
id: z8.number().optional().describe("Entry ID")
|
|
475
|
+
id: z8.coerce.number().optional().describe("Entry ID")
|
|
471
476
|
},
|
|
472
477
|
async (params) => {
|
|
473
478
|
const identifier = params.slug || (params.id !== void 0 ? String(params.id) : void 0);
|
|
@@ -489,7 +494,7 @@ function registerContextTools(server2, client2) {
|
|
|
489
494
|
"lp_context_package",
|
|
490
495
|
"Get the assembled context package for a task \u2014 task details, context entries, specs, pages, comments",
|
|
491
496
|
{
|
|
492
|
-
task_id: z8.number().describe("Task ID")
|
|
497
|
+
task_id: z8.coerce.number().describe("Task ID")
|
|
493
498
|
},
|
|
494
499
|
async (params) => {
|
|
495
500
|
try {
|
|
@@ -505,7 +510,7 @@ function registerContextTools(server2, client2) {
|
|
|
505
510
|
"Update a context entry's content (requires write access)",
|
|
506
511
|
{
|
|
507
512
|
slug: z8.string().optional().describe("Entry slug"),
|
|
508
|
-
id: z8.number().optional().describe("Entry ID"),
|
|
513
|
+
id: z8.coerce.number().optional().describe("Entry ID"),
|
|
509
514
|
content: z8.string().describe("New markdown content"),
|
|
510
515
|
change_summary: z8.string().describe("What changed and why")
|
|
511
516
|
},
|
|
@@ -563,7 +568,7 @@ function registerSessionTools(server2, client2) {
|
|
|
563
568
|
"lp_session_start",
|
|
564
569
|
"Start a new agent session for a task. Creates session via API and saves session_id to disk for later lookup.",
|
|
565
570
|
{
|
|
566
|
-
task_id: z9.number().describe("LaunchPad task ID"),
|
|
571
|
+
task_id: z9.coerce.number().describe("LaunchPad task ID"),
|
|
567
572
|
agent_type: z9.string().optional().describe("Agent type (default: claude_code)")
|
|
568
573
|
},
|
|
569
574
|
async ({ task_id, agent_type }) => {
|
|
@@ -582,8 +587,8 @@ function registerSessionTools(server2, client2) {
|
|
|
582
587
|
"lp_session_heartbeat",
|
|
583
588
|
"Send a heartbeat for an active session. Provide session_id directly or task_id to look up session from disk. Graceful no-op if neither provided.",
|
|
584
589
|
{
|
|
585
|
-
session_id: z9.number().optional().describe("Session ID"),
|
|
586
|
-
task_id: z9.number().optional().describe("Task ID to look up session from disk")
|
|
590
|
+
session_id: z9.coerce.number().optional().describe("Session ID"),
|
|
591
|
+
task_id: z9.coerce.number().optional().describe("Task ID to look up session from disk")
|
|
587
592
|
},
|
|
588
593
|
async ({ session_id, task_id }) => {
|
|
589
594
|
try {
|
|
@@ -606,7 +611,7 @@ function registerSessionTools(server2, client2) {
|
|
|
606
611
|
"lp_session_progress",
|
|
607
612
|
'Report progress on an active session. Sends an activity update with action "progress".',
|
|
608
613
|
{
|
|
609
|
-
session_id: z9.number().describe("Session ID"),
|
|
614
|
+
session_id: z9.coerce.number().describe("Session ID"),
|
|
610
615
|
detail: z9.string().describe("Description of progress made")
|
|
611
616
|
},
|
|
612
617
|
async ({ session_id, detail }) => {
|
|
@@ -626,7 +631,7 @@ function registerSessionTools(server2, client2) {
|
|
|
626
631
|
"lp_session_event",
|
|
627
632
|
"Log a discrete event for a session (commit, ci_pass, ci_fail, pr_opened, blocker, cost_update).",
|
|
628
633
|
{
|
|
629
|
-
session_id: z9.number().describe("Session ID"),
|
|
634
|
+
session_id: z9.coerce.number().describe("Session ID"),
|
|
630
635
|
event_type: z9.enum(["commit", "ci_pass", "ci_fail", "pr_opened", "blocker", "cost_update"]).describe("Type of event"),
|
|
631
636
|
payload: z9.record(z9.unknown()).describe("Event payload data")
|
|
632
637
|
},
|
|
@@ -645,7 +650,7 @@ function registerSessionTools(server2, client2) {
|
|
|
645
650
|
"lp_session_blocked",
|
|
646
651
|
'Mark a session as blocked. Updates status to "blocked" and logs a blocker event.',
|
|
647
652
|
{
|
|
648
|
-
session_id: z9.number().describe("Session ID"),
|
|
653
|
+
session_id: z9.coerce.number().describe("Session ID"),
|
|
649
654
|
reason: z9.string().describe("Reason the session is blocked")
|
|
650
655
|
},
|
|
651
656
|
async ({ session_id, reason }) => {
|
|
@@ -669,9 +674,9 @@ function registerSessionTools(server2, client2) {
|
|
|
669
674
|
"lp_session_complete",
|
|
670
675
|
"Mark a session as completed with a result summary. Clears session from disk.",
|
|
671
676
|
{
|
|
672
|
-
session_id: z9.number().describe("Session ID"),
|
|
677
|
+
session_id: z9.coerce.number().describe("Session ID"),
|
|
673
678
|
result_summary: z9.string().describe("Summary of what was accomplished"),
|
|
674
|
-
task_id: z9.number().optional().describe("Task ID to clear from disk (if not provided, derived from session)")
|
|
679
|
+
task_id: z9.coerce.number().optional().describe("Task ID to clear from disk (if not provided, derived from session)")
|
|
675
680
|
},
|
|
676
681
|
async ({ session_id, result_summary, task_id }) => {
|
|
677
682
|
try {
|
|
@@ -693,9 +698,9 @@ function registerSessionTools(server2, client2) {
|
|
|
693
698
|
"lp_session_fail",
|
|
694
699
|
"Mark a session as failed with an error detail. Clears session from disk.",
|
|
695
700
|
{
|
|
696
|
-
session_id: z9.number().describe("Session ID"),
|
|
701
|
+
session_id: z9.coerce.number().describe("Session ID"),
|
|
697
702
|
error_detail: z9.string().describe("Description of the failure"),
|
|
698
|
-
task_id: z9.number().optional().describe("Task ID to clear from disk (if not provided, derived from session)")
|
|
703
|
+
task_id: z9.coerce.number().optional().describe("Task ID to clear from disk (if not provided, derived from session)")
|
|
699
704
|
},
|
|
700
705
|
async ({ session_id, error_detail, task_id }) => {
|
|
701
706
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@limeadelabs/launchpad-mcp",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "LaunchPad MCP server for Claude Code — AI-native project management integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -29,7 +29,13 @@
|
|
|
29
29
|
"engines": {
|
|
30
30
|
"node": ">=18.0.0"
|
|
31
31
|
},
|
|
32
|
-
"keywords": [
|
|
32
|
+
"keywords": [
|
|
33
|
+
"mcp",
|
|
34
|
+
"launchpad",
|
|
35
|
+
"claude",
|
|
36
|
+
"project-management",
|
|
37
|
+
"ai-agents"
|
|
38
|
+
],
|
|
33
39
|
"license": "MIT",
|
|
34
40
|
"publishConfig": {
|
|
35
41
|
"access": "public"
|