@letpeoplework/lighthouse-mcp-core 0.1.0 → 0.3.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.
- package/dist/index.d.mts +138 -1
- package/dist/index.d.ts +138 -1
- package/dist/index.js +251 -0
- package/dist/index.mjs +251 -0
- package/package.json +5 -3
package/dist/index.d.mts
CHANGED
|
@@ -13,7 +13,7 @@ type McpToolResult = {
|
|
|
13
13
|
readonly content: readonly McpToolContent[];
|
|
14
14
|
};
|
|
15
15
|
type McpToolDefinition = {
|
|
16
|
-
readonly name: "lighthouse.health.check" | "lighthouse.version.get" | "lighthouse.worktracking.list" | "lighthouse.worktracking.get" | "lighthouse.team.list" | "lighthouse.team.get" | "lighthouse.team.refresh" | "lighthouse.portfolio.list" | "lighthouse.portfolio.get" | "lighthouse.portfolio.refresh";
|
|
16
|
+
readonly name: "lighthouse.health.check" | "lighthouse.version.get" | "lighthouse.worktracking.list" | "lighthouse.worktracking.get" | "lighthouse.team.list" | "lighthouse.team.get" | "lighthouse.team.refresh" | "lighthouse.portfolio.list" | "lighthouse.portfolio.get" | "lighthouse.portfolio.refresh" | "lighthouse.team.metrics.throughput" | "lighthouse.team.metrics.cycleTimePercentiles" | "lighthouse.portfolio.metrics.throughput" | "lighthouse.feature.get" | "lighthouse.feature.workitems" | "lighthouse.delivery.list" | "lighthouse.forecast.manual" | "lighthouse.forecast.backtest";
|
|
17
17
|
readonly description: string;
|
|
18
18
|
readonly inputSchema: {
|
|
19
19
|
readonly type: "object";
|
|
@@ -116,6 +116,143 @@ type McpRuntimeClient = {
|
|
|
116
116
|
readonly reason: string;
|
|
117
117
|
};
|
|
118
118
|
}>;
|
|
119
|
+
readonly getTeamThroughput: (id: number, range?: {
|
|
120
|
+
readonly startDate: string;
|
|
121
|
+
readonly endDate: string;
|
|
122
|
+
}) => Promise<{
|
|
123
|
+
readonly ok: true;
|
|
124
|
+
readonly value: unknown;
|
|
125
|
+
} | {
|
|
126
|
+
readonly ok: false;
|
|
127
|
+
readonly error: {
|
|
128
|
+
readonly category: string;
|
|
129
|
+
readonly reason: string;
|
|
130
|
+
};
|
|
131
|
+
}>;
|
|
132
|
+
readonly getTeamCycleTimePercentiles: (id: number, range?: {
|
|
133
|
+
readonly startDate: string;
|
|
134
|
+
readonly endDate: string;
|
|
135
|
+
}) => Promise<{
|
|
136
|
+
readonly ok: true;
|
|
137
|
+
readonly value: readonly unknown[];
|
|
138
|
+
} | {
|
|
139
|
+
readonly ok: false;
|
|
140
|
+
readonly error: {
|
|
141
|
+
readonly category: string;
|
|
142
|
+
readonly reason: string;
|
|
143
|
+
};
|
|
144
|
+
}>;
|
|
145
|
+
readonly getPortfolioThroughput: (id: number, range?: {
|
|
146
|
+
readonly startDate: string;
|
|
147
|
+
readonly endDate: string;
|
|
148
|
+
}) => Promise<{
|
|
149
|
+
readonly ok: true;
|
|
150
|
+
readonly value: unknown;
|
|
151
|
+
} | {
|
|
152
|
+
readonly ok: false;
|
|
153
|
+
readonly error: {
|
|
154
|
+
readonly category: string;
|
|
155
|
+
readonly reason: string;
|
|
156
|
+
};
|
|
157
|
+
}>;
|
|
158
|
+
readonly getFeaturesByIds: (ids: readonly number[]) => Promise<{
|
|
159
|
+
readonly ok: true;
|
|
160
|
+
readonly value: readonly unknown[];
|
|
161
|
+
} | {
|
|
162
|
+
readonly ok: false;
|
|
163
|
+
readonly error: {
|
|
164
|
+
readonly category: string;
|
|
165
|
+
readonly reason: string;
|
|
166
|
+
};
|
|
167
|
+
}>;
|
|
168
|
+
readonly getFeaturesByReferences: (refs: readonly string[]) => Promise<{
|
|
169
|
+
readonly ok: true;
|
|
170
|
+
readonly value: readonly unknown[];
|
|
171
|
+
} | {
|
|
172
|
+
readonly ok: false;
|
|
173
|
+
readonly error: {
|
|
174
|
+
readonly category: string;
|
|
175
|
+
readonly reason: string;
|
|
176
|
+
};
|
|
177
|
+
}>;
|
|
178
|
+
readonly getFeatureWorkItems: (featureId: number) => Promise<{
|
|
179
|
+
readonly ok: true;
|
|
180
|
+
readonly value: readonly unknown[];
|
|
181
|
+
} | {
|
|
182
|
+
readonly ok: false;
|
|
183
|
+
readonly error: {
|
|
184
|
+
readonly category: string;
|
|
185
|
+
readonly reason: string;
|
|
186
|
+
};
|
|
187
|
+
}>;
|
|
188
|
+
readonly listDeliveries: (portfolioId: number) => Promise<{
|
|
189
|
+
readonly ok: true;
|
|
190
|
+
readonly value: readonly unknown[];
|
|
191
|
+
} | {
|
|
192
|
+
readonly ok: false;
|
|
193
|
+
readonly error: {
|
|
194
|
+
readonly category: string;
|
|
195
|
+
readonly reason: string;
|
|
196
|
+
};
|
|
197
|
+
}>;
|
|
198
|
+
readonly createDelivery: (portfolioId: number, payload: Readonly<Record<string, unknown>>) => Promise<{
|
|
199
|
+
readonly ok: true;
|
|
200
|
+
readonly value: unknown;
|
|
201
|
+
} | {
|
|
202
|
+
readonly ok: false;
|
|
203
|
+
readonly error: {
|
|
204
|
+
readonly category: string;
|
|
205
|
+
readonly reason: string;
|
|
206
|
+
};
|
|
207
|
+
}>;
|
|
208
|
+
readonly updateDelivery: (deliveryId: number, payload: Readonly<Record<string, unknown>>) => Promise<{
|
|
209
|
+
readonly ok: true;
|
|
210
|
+
readonly value: unknown;
|
|
211
|
+
} | {
|
|
212
|
+
readonly ok: false;
|
|
213
|
+
readonly error: {
|
|
214
|
+
readonly category: string;
|
|
215
|
+
readonly reason: string;
|
|
216
|
+
};
|
|
217
|
+
}>;
|
|
218
|
+
readonly deleteDelivery: (deliveryId: number) => Promise<{
|
|
219
|
+
readonly ok: true;
|
|
220
|
+
readonly value: undefined;
|
|
221
|
+
} | {
|
|
222
|
+
readonly ok: false;
|
|
223
|
+
readonly error: {
|
|
224
|
+
readonly category: string;
|
|
225
|
+
readonly reason: string;
|
|
226
|
+
};
|
|
227
|
+
}>;
|
|
228
|
+
readonly runManualForecast: (teamId: number, payload: {
|
|
229
|
+
readonly remainingItems?: number;
|
|
230
|
+
readonly targetDate?: string;
|
|
231
|
+
}) => Promise<{
|
|
232
|
+
readonly ok: true;
|
|
233
|
+
readonly value: unknown;
|
|
234
|
+
} | {
|
|
235
|
+
readonly ok: false;
|
|
236
|
+
readonly error: {
|
|
237
|
+
readonly category: string;
|
|
238
|
+
readonly reason: string;
|
|
239
|
+
};
|
|
240
|
+
}>;
|
|
241
|
+
readonly runBacktest: (teamId: number, payload: {
|
|
242
|
+
readonly startDate: string;
|
|
243
|
+
readonly endDate: string;
|
|
244
|
+
readonly historicalStartDate: string;
|
|
245
|
+
readonly historicalEndDate: string;
|
|
246
|
+
}) => Promise<{
|
|
247
|
+
readonly ok: true;
|
|
248
|
+
readonly value: unknown;
|
|
249
|
+
} | {
|
|
250
|
+
readonly ok: false;
|
|
251
|
+
readonly error: {
|
|
252
|
+
readonly category: string;
|
|
253
|
+
readonly reason: string;
|
|
254
|
+
};
|
|
255
|
+
}>;
|
|
119
256
|
};
|
|
120
257
|
type McpCoreRuntimeDependencies = {
|
|
121
258
|
readonly createClient: () => McpRuntimeClient;
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ type McpToolResult = {
|
|
|
13
13
|
readonly content: readonly McpToolContent[];
|
|
14
14
|
};
|
|
15
15
|
type McpToolDefinition = {
|
|
16
|
-
readonly name: "lighthouse.health.check" | "lighthouse.version.get" | "lighthouse.worktracking.list" | "lighthouse.worktracking.get" | "lighthouse.team.list" | "lighthouse.team.get" | "lighthouse.team.refresh" | "lighthouse.portfolio.list" | "lighthouse.portfolio.get" | "lighthouse.portfolio.refresh";
|
|
16
|
+
readonly name: "lighthouse.health.check" | "lighthouse.version.get" | "lighthouse.worktracking.list" | "lighthouse.worktracking.get" | "lighthouse.team.list" | "lighthouse.team.get" | "lighthouse.team.refresh" | "lighthouse.portfolio.list" | "lighthouse.portfolio.get" | "lighthouse.portfolio.refresh" | "lighthouse.team.metrics.throughput" | "lighthouse.team.metrics.cycleTimePercentiles" | "lighthouse.portfolio.metrics.throughput" | "lighthouse.feature.get" | "lighthouse.feature.workitems" | "lighthouse.delivery.list" | "lighthouse.forecast.manual" | "lighthouse.forecast.backtest";
|
|
17
17
|
readonly description: string;
|
|
18
18
|
readonly inputSchema: {
|
|
19
19
|
readonly type: "object";
|
|
@@ -116,6 +116,143 @@ type McpRuntimeClient = {
|
|
|
116
116
|
readonly reason: string;
|
|
117
117
|
};
|
|
118
118
|
}>;
|
|
119
|
+
readonly getTeamThroughput: (id: number, range?: {
|
|
120
|
+
readonly startDate: string;
|
|
121
|
+
readonly endDate: string;
|
|
122
|
+
}) => Promise<{
|
|
123
|
+
readonly ok: true;
|
|
124
|
+
readonly value: unknown;
|
|
125
|
+
} | {
|
|
126
|
+
readonly ok: false;
|
|
127
|
+
readonly error: {
|
|
128
|
+
readonly category: string;
|
|
129
|
+
readonly reason: string;
|
|
130
|
+
};
|
|
131
|
+
}>;
|
|
132
|
+
readonly getTeamCycleTimePercentiles: (id: number, range?: {
|
|
133
|
+
readonly startDate: string;
|
|
134
|
+
readonly endDate: string;
|
|
135
|
+
}) => Promise<{
|
|
136
|
+
readonly ok: true;
|
|
137
|
+
readonly value: readonly unknown[];
|
|
138
|
+
} | {
|
|
139
|
+
readonly ok: false;
|
|
140
|
+
readonly error: {
|
|
141
|
+
readonly category: string;
|
|
142
|
+
readonly reason: string;
|
|
143
|
+
};
|
|
144
|
+
}>;
|
|
145
|
+
readonly getPortfolioThroughput: (id: number, range?: {
|
|
146
|
+
readonly startDate: string;
|
|
147
|
+
readonly endDate: string;
|
|
148
|
+
}) => Promise<{
|
|
149
|
+
readonly ok: true;
|
|
150
|
+
readonly value: unknown;
|
|
151
|
+
} | {
|
|
152
|
+
readonly ok: false;
|
|
153
|
+
readonly error: {
|
|
154
|
+
readonly category: string;
|
|
155
|
+
readonly reason: string;
|
|
156
|
+
};
|
|
157
|
+
}>;
|
|
158
|
+
readonly getFeaturesByIds: (ids: readonly number[]) => Promise<{
|
|
159
|
+
readonly ok: true;
|
|
160
|
+
readonly value: readonly unknown[];
|
|
161
|
+
} | {
|
|
162
|
+
readonly ok: false;
|
|
163
|
+
readonly error: {
|
|
164
|
+
readonly category: string;
|
|
165
|
+
readonly reason: string;
|
|
166
|
+
};
|
|
167
|
+
}>;
|
|
168
|
+
readonly getFeaturesByReferences: (refs: readonly string[]) => Promise<{
|
|
169
|
+
readonly ok: true;
|
|
170
|
+
readonly value: readonly unknown[];
|
|
171
|
+
} | {
|
|
172
|
+
readonly ok: false;
|
|
173
|
+
readonly error: {
|
|
174
|
+
readonly category: string;
|
|
175
|
+
readonly reason: string;
|
|
176
|
+
};
|
|
177
|
+
}>;
|
|
178
|
+
readonly getFeatureWorkItems: (featureId: number) => Promise<{
|
|
179
|
+
readonly ok: true;
|
|
180
|
+
readonly value: readonly unknown[];
|
|
181
|
+
} | {
|
|
182
|
+
readonly ok: false;
|
|
183
|
+
readonly error: {
|
|
184
|
+
readonly category: string;
|
|
185
|
+
readonly reason: string;
|
|
186
|
+
};
|
|
187
|
+
}>;
|
|
188
|
+
readonly listDeliveries: (portfolioId: number) => Promise<{
|
|
189
|
+
readonly ok: true;
|
|
190
|
+
readonly value: readonly unknown[];
|
|
191
|
+
} | {
|
|
192
|
+
readonly ok: false;
|
|
193
|
+
readonly error: {
|
|
194
|
+
readonly category: string;
|
|
195
|
+
readonly reason: string;
|
|
196
|
+
};
|
|
197
|
+
}>;
|
|
198
|
+
readonly createDelivery: (portfolioId: number, payload: Readonly<Record<string, unknown>>) => Promise<{
|
|
199
|
+
readonly ok: true;
|
|
200
|
+
readonly value: unknown;
|
|
201
|
+
} | {
|
|
202
|
+
readonly ok: false;
|
|
203
|
+
readonly error: {
|
|
204
|
+
readonly category: string;
|
|
205
|
+
readonly reason: string;
|
|
206
|
+
};
|
|
207
|
+
}>;
|
|
208
|
+
readonly updateDelivery: (deliveryId: number, payload: Readonly<Record<string, unknown>>) => Promise<{
|
|
209
|
+
readonly ok: true;
|
|
210
|
+
readonly value: unknown;
|
|
211
|
+
} | {
|
|
212
|
+
readonly ok: false;
|
|
213
|
+
readonly error: {
|
|
214
|
+
readonly category: string;
|
|
215
|
+
readonly reason: string;
|
|
216
|
+
};
|
|
217
|
+
}>;
|
|
218
|
+
readonly deleteDelivery: (deliveryId: number) => Promise<{
|
|
219
|
+
readonly ok: true;
|
|
220
|
+
readonly value: undefined;
|
|
221
|
+
} | {
|
|
222
|
+
readonly ok: false;
|
|
223
|
+
readonly error: {
|
|
224
|
+
readonly category: string;
|
|
225
|
+
readonly reason: string;
|
|
226
|
+
};
|
|
227
|
+
}>;
|
|
228
|
+
readonly runManualForecast: (teamId: number, payload: {
|
|
229
|
+
readonly remainingItems?: number;
|
|
230
|
+
readonly targetDate?: string;
|
|
231
|
+
}) => Promise<{
|
|
232
|
+
readonly ok: true;
|
|
233
|
+
readonly value: unknown;
|
|
234
|
+
} | {
|
|
235
|
+
readonly ok: false;
|
|
236
|
+
readonly error: {
|
|
237
|
+
readonly category: string;
|
|
238
|
+
readonly reason: string;
|
|
239
|
+
};
|
|
240
|
+
}>;
|
|
241
|
+
readonly runBacktest: (teamId: number, payload: {
|
|
242
|
+
readonly startDate: string;
|
|
243
|
+
readonly endDate: string;
|
|
244
|
+
readonly historicalStartDate: string;
|
|
245
|
+
readonly historicalEndDate: string;
|
|
246
|
+
}) => Promise<{
|
|
247
|
+
readonly ok: true;
|
|
248
|
+
readonly value: unknown;
|
|
249
|
+
} | {
|
|
250
|
+
readonly ok: false;
|
|
251
|
+
readonly error: {
|
|
252
|
+
readonly category: string;
|
|
253
|
+
readonly reason: string;
|
|
254
|
+
};
|
|
255
|
+
}>;
|
|
119
256
|
};
|
|
120
257
|
type McpCoreRuntimeDependencies = {
|
|
121
258
|
readonly createClient: () => McpRuntimeClient;
|
package/dist/index.js
CHANGED
|
@@ -119,6 +119,78 @@ var toolDefinitions = [
|
|
|
119
119
|
properties: {},
|
|
120
120
|
additionalProperties: false
|
|
121
121
|
}
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: "lighthouse.team.metrics.throughput",
|
|
125
|
+
description: "Get throughput run-chart data for a team. Requires id. Optional startDate and endDate (ISO date strings, defaults to last 90 days).",
|
|
126
|
+
inputSchema: {
|
|
127
|
+
type: "object",
|
|
128
|
+
properties: {},
|
|
129
|
+
additionalProperties: false
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "lighthouse.team.metrics.cycleTimePercentiles",
|
|
134
|
+
description: "Get cycle-time percentiles for a team. Requires id. Optional startDate and endDate (ISO date strings, defaults to last 90 days).",
|
|
135
|
+
inputSchema: {
|
|
136
|
+
type: "object",
|
|
137
|
+
properties: {},
|
|
138
|
+
additionalProperties: false
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "lighthouse.portfolio.metrics.throughput",
|
|
143
|
+
description: "Get throughput run-chart data for a portfolio. Requires id. Optional startDate and endDate (ISO date strings, defaults to last 90 days).",
|
|
144
|
+
inputSchema: {
|
|
145
|
+
type: "object",
|
|
146
|
+
properties: {},
|
|
147
|
+
additionalProperties: false
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: "lighthouse.feature.get",
|
|
152
|
+
description: "Get features by ids (provide ids array) or by reference ids (provide refs array).",
|
|
153
|
+
inputSchema: {
|
|
154
|
+
type: "object",
|
|
155
|
+
properties: {},
|
|
156
|
+
additionalProperties: false
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: "lighthouse.feature.workitems",
|
|
161
|
+
description: "Get work items for a feature. Requires id.",
|
|
162
|
+
inputSchema: {
|
|
163
|
+
type: "object",
|
|
164
|
+
properties: {},
|
|
165
|
+
additionalProperties: false
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "lighthouse.delivery.list",
|
|
170
|
+
description: "List deliveries for a portfolio. Requires id (portfolio id).",
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: "object",
|
|
173
|
+
properties: {},
|
|
174
|
+
additionalProperties: false
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: "lighthouse.forecast.manual",
|
|
179
|
+
description: "Run a manual forecast for a team. Requires id (team id). Optional remainingItems and targetDate.",
|
|
180
|
+
inputSchema: {
|
|
181
|
+
type: "object",
|
|
182
|
+
properties: {},
|
|
183
|
+
additionalProperties: false
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: "lighthouse.forecast.backtest",
|
|
188
|
+
description: "Run a backtest forecast for a team. Requires id, startDate, endDate, historicalStartDate, historicalEndDate.",
|
|
189
|
+
inputSchema: {
|
|
190
|
+
type: "object",
|
|
191
|
+
properties: {},
|
|
192
|
+
additionalProperties: false
|
|
193
|
+
}
|
|
122
194
|
}
|
|
123
195
|
];
|
|
124
196
|
var getSuccessToolResult = (text) => ({
|
|
@@ -149,6 +221,20 @@ var getNumericId = (argumentsPayload) => {
|
|
|
149
221
|
}
|
|
150
222
|
return null;
|
|
151
223
|
};
|
|
224
|
+
var isObjectRecord = (value) => {
|
|
225
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
226
|
+
};
|
|
227
|
+
var getDateRange = (argumentsPayload) => {
|
|
228
|
+
if (!isObjectRecord(argumentsPayload)) {
|
|
229
|
+
return void 0;
|
|
230
|
+
}
|
|
231
|
+
const startDate = argumentsPayload.startDate;
|
|
232
|
+
const endDate = argumentsPayload.endDate;
|
|
233
|
+
if (typeof startDate === "string" && typeof endDate === "string") {
|
|
234
|
+
return { startDate, endDate };
|
|
235
|
+
}
|
|
236
|
+
return void 0;
|
|
237
|
+
};
|
|
152
238
|
var createMcpCoreRuntime = (dependencies) => ({
|
|
153
239
|
listTools: () => toolDefinitions,
|
|
154
240
|
callTool: async (name, argumentsPayload) => {
|
|
@@ -271,6 +357,171 @@ var createMcpCoreRuntime = (dependencies) => ({
|
|
|
271
357
|
`portfolio refresh: ${result.error.category} (${result.error.reason})`
|
|
272
358
|
);
|
|
273
359
|
}
|
|
360
|
+
if (name === "lighthouse.team.metrics.throughput") {
|
|
361
|
+
const id = getNumericId(argumentsPayload);
|
|
362
|
+
if (id === null) {
|
|
363
|
+
return getErrorToolResult("team metrics: invalid id");
|
|
364
|
+
}
|
|
365
|
+
const range = getDateRange(argumentsPayload);
|
|
366
|
+
const result = await client.getTeamThroughput(id, range);
|
|
367
|
+
if (result.ok) {
|
|
368
|
+
return getSuccessToolResult(
|
|
369
|
+
`team throughput: ${JSON.stringify(result.value)}`
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
return getErrorToolResult(
|
|
373
|
+
`team metrics: ${result.error.category} (${result.error.reason})`
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
if (name === "lighthouse.team.metrics.cycleTimePercentiles") {
|
|
377
|
+
const id = getNumericId(argumentsPayload);
|
|
378
|
+
if (id === null) {
|
|
379
|
+
return getErrorToolResult("team metrics: invalid id");
|
|
380
|
+
}
|
|
381
|
+
const range = getDateRange(argumentsPayload);
|
|
382
|
+
const result = await client.getTeamCycleTimePercentiles(id, range);
|
|
383
|
+
if (result.ok) {
|
|
384
|
+
return getSuccessToolResult(
|
|
385
|
+
`team cycleTimePercentiles: ${JSON.stringify(result.value)}`
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
return getErrorToolResult(
|
|
389
|
+
`team metrics: ${result.error.category} (${result.error.reason})`
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
if (name === "lighthouse.portfolio.metrics.throughput") {
|
|
393
|
+
const id = getNumericId(argumentsPayload);
|
|
394
|
+
if (id === null) {
|
|
395
|
+
return getErrorToolResult("portfolio metrics: invalid id");
|
|
396
|
+
}
|
|
397
|
+
const range = getDateRange(argumentsPayload);
|
|
398
|
+
const result = await client.getPortfolioThroughput(id, range);
|
|
399
|
+
if (result.ok) {
|
|
400
|
+
return getSuccessToolResult(
|
|
401
|
+
`portfolio throughput: ${JSON.stringify(result.value)}`
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
return getErrorToolResult(
|
|
405
|
+
`portfolio metrics: ${result.error.category} (${result.error.reason})`
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
if (name === "lighthouse.feature.get") {
|
|
409
|
+
const payload = isObjectRecord(argumentsPayload) ? argumentsPayload : {};
|
|
410
|
+
const idsValue = payload.ids;
|
|
411
|
+
const refsValue = payload.refs;
|
|
412
|
+
if (Array.isArray(idsValue) && idsValue.length > 0) {
|
|
413
|
+
const ids = idsValue.filter((v) => typeof v === "number");
|
|
414
|
+
const result = await client.getFeaturesByIds(ids);
|
|
415
|
+
if (result.ok) {
|
|
416
|
+
return getSuccessToolResult(
|
|
417
|
+
`features: ${JSON.stringify(result.value)}`
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
return getErrorToolResult(
|
|
421
|
+
`features: ${result.error.category} (${result.error.reason})`
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
if (Array.isArray(refsValue) && refsValue.length > 0) {
|
|
425
|
+
const refs = refsValue.filter(
|
|
426
|
+
(v) => typeof v === "string"
|
|
427
|
+
);
|
|
428
|
+
const result = await client.getFeaturesByReferences(refs);
|
|
429
|
+
if (result.ok) {
|
|
430
|
+
return getSuccessToolResult(
|
|
431
|
+
`features: ${JSON.stringify(result.value)}`
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
return getErrorToolResult(
|
|
435
|
+
`features: ${result.error.category} (${result.error.reason})`
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
return getErrorToolResult(
|
|
439
|
+
"features: provide ids (array of numbers) or refs (array of strings)"
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
if (name === "lighthouse.feature.workitems") {
|
|
443
|
+
const id = getNumericId(argumentsPayload);
|
|
444
|
+
if (id === null) {
|
|
445
|
+
return getErrorToolResult("feature workitems: invalid id");
|
|
446
|
+
}
|
|
447
|
+
const result = await client.getFeatureWorkItems(id);
|
|
448
|
+
if (result.ok) {
|
|
449
|
+
return getSuccessToolResult(
|
|
450
|
+
`feature workitems: ${JSON.stringify(result.value)}`
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
return getErrorToolResult(
|
|
454
|
+
`feature workitems: ${result.error.category} (${result.error.reason})`
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
if (name === "lighthouse.delivery.list") {
|
|
458
|
+
const id = getNumericId(argumentsPayload);
|
|
459
|
+
if (id === null) {
|
|
460
|
+
return getErrorToolResult(
|
|
461
|
+
"delivery: invalid id (portfolio id required)"
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
const result = await client.listDeliveries(id);
|
|
465
|
+
if (result.ok) {
|
|
466
|
+
return getSuccessToolResult(
|
|
467
|
+
`deliveries: ${JSON.stringify(result.value)}`
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
return getErrorToolResult(
|
|
471
|
+
`delivery: ${result.error.category} (${result.error.reason})`
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
if (name === "lighthouse.forecast.manual") {
|
|
475
|
+
const id = getNumericId(argumentsPayload);
|
|
476
|
+
if (id === null) {
|
|
477
|
+
return getErrorToolResult("forecast: invalid id (team id required)");
|
|
478
|
+
}
|
|
479
|
+
const payload = isObjectRecord(argumentsPayload) ? argumentsPayload : {};
|
|
480
|
+
const remainingItems = typeof payload.remainingItems === "number" ? payload.remainingItems : void 0;
|
|
481
|
+
const targetDate = typeof payload.targetDate === "string" ? payload.targetDate : void 0;
|
|
482
|
+
const result = await client.runManualForecast(id, {
|
|
483
|
+
remainingItems,
|
|
484
|
+
targetDate
|
|
485
|
+
});
|
|
486
|
+
if (result.ok) {
|
|
487
|
+
return getSuccessToolResult(
|
|
488
|
+
`forecast: ${JSON.stringify(result.value)}`
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
return getErrorToolResult(
|
|
492
|
+
`forecast: ${result.error.category} (${result.error.reason})`
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
if (name === "lighthouse.forecast.backtest") {
|
|
496
|
+
const id = getNumericId(argumentsPayload);
|
|
497
|
+
if (id === null) {
|
|
498
|
+
return getErrorToolResult("backtest: invalid id (team id required)");
|
|
499
|
+
}
|
|
500
|
+
const payload = isObjectRecord(argumentsPayload) ? argumentsPayload : {};
|
|
501
|
+
const startDate = typeof payload.startDate === "string" ? payload.startDate : void 0;
|
|
502
|
+
const endDate = typeof payload.endDate === "string" ? payload.endDate : void 0;
|
|
503
|
+
const historicalStartDate = typeof payload.historicalStartDate === "string" ? payload.historicalStartDate : void 0;
|
|
504
|
+
const historicalEndDate = typeof payload.historicalEndDate === "string" ? payload.historicalEndDate : void 0;
|
|
505
|
+
if (!startDate || !endDate || !historicalStartDate || !historicalEndDate) {
|
|
506
|
+
return getErrorToolResult(
|
|
507
|
+
"backtest: startDate, endDate, historicalStartDate, and historicalEndDate are required"
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
const result = await client.runBacktest(id, {
|
|
511
|
+
startDate,
|
|
512
|
+
endDate,
|
|
513
|
+
historicalStartDate,
|
|
514
|
+
historicalEndDate
|
|
515
|
+
});
|
|
516
|
+
if (result.ok) {
|
|
517
|
+
return getSuccessToolResult(
|
|
518
|
+
`backtest: ${JSON.stringify(result.value)}`
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
return getErrorToolResult(
|
|
522
|
+
`backtest: ${result.error.category} (${result.error.reason})`
|
|
523
|
+
);
|
|
524
|
+
}
|
|
274
525
|
return getErrorToolResult(`Unknown tool: ${name}`);
|
|
275
526
|
}
|
|
276
527
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -94,6 +94,78 @@ var toolDefinitions = [
|
|
|
94
94
|
properties: {},
|
|
95
95
|
additionalProperties: false
|
|
96
96
|
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "lighthouse.team.metrics.throughput",
|
|
100
|
+
description: "Get throughput run-chart data for a team. Requires id. Optional startDate and endDate (ISO date strings, defaults to last 90 days).",
|
|
101
|
+
inputSchema: {
|
|
102
|
+
type: "object",
|
|
103
|
+
properties: {},
|
|
104
|
+
additionalProperties: false
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "lighthouse.team.metrics.cycleTimePercentiles",
|
|
109
|
+
description: "Get cycle-time percentiles for a team. Requires id. Optional startDate and endDate (ISO date strings, defaults to last 90 days).",
|
|
110
|
+
inputSchema: {
|
|
111
|
+
type: "object",
|
|
112
|
+
properties: {},
|
|
113
|
+
additionalProperties: false
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "lighthouse.portfolio.metrics.throughput",
|
|
118
|
+
description: "Get throughput run-chart data for a portfolio. Requires id. Optional startDate and endDate (ISO date strings, defaults to last 90 days).",
|
|
119
|
+
inputSchema: {
|
|
120
|
+
type: "object",
|
|
121
|
+
properties: {},
|
|
122
|
+
additionalProperties: false
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: "lighthouse.feature.get",
|
|
127
|
+
description: "Get features by ids (provide ids array) or by reference ids (provide refs array).",
|
|
128
|
+
inputSchema: {
|
|
129
|
+
type: "object",
|
|
130
|
+
properties: {},
|
|
131
|
+
additionalProperties: false
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: "lighthouse.feature.workitems",
|
|
136
|
+
description: "Get work items for a feature. Requires id.",
|
|
137
|
+
inputSchema: {
|
|
138
|
+
type: "object",
|
|
139
|
+
properties: {},
|
|
140
|
+
additionalProperties: false
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: "lighthouse.delivery.list",
|
|
145
|
+
description: "List deliveries for a portfolio. Requires id (portfolio id).",
|
|
146
|
+
inputSchema: {
|
|
147
|
+
type: "object",
|
|
148
|
+
properties: {},
|
|
149
|
+
additionalProperties: false
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: "lighthouse.forecast.manual",
|
|
154
|
+
description: "Run a manual forecast for a team. Requires id (team id). Optional remainingItems and targetDate.",
|
|
155
|
+
inputSchema: {
|
|
156
|
+
type: "object",
|
|
157
|
+
properties: {},
|
|
158
|
+
additionalProperties: false
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: "lighthouse.forecast.backtest",
|
|
163
|
+
description: "Run a backtest forecast for a team. Requires id, startDate, endDate, historicalStartDate, historicalEndDate.",
|
|
164
|
+
inputSchema: {
|
|
165
|
+
type: "object",
|
|
166
|
+
properties: {},
|
|
167
|
+
additionalProperties: false
|
|
168
|
+
}
|
|
97
169
|
}
|
|
98
170
|
];
|
|
99
171
|
var getSuccessToolResult = (text) => ({
|
|
@@ -124,6 +196,20 @@ var getNumericId = (argumentsPayload) => {
|
|
|
124
196
|
}
|
|
125
197
|
return null;
|
|
126
198
|
};
|
|
199
|
+
var isObjectRecord = (value) => {
|
|
200
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
201
|
+
};
|
|
202
|
+
var getDateRange = (argumentsPayload) => {
|
|
203
|
+
if (!isObjectRecord(argumentsPayload)) {
|
|
204
|
+
return void 0;
|
|
205
|
+
}
|
|
206
|
+
const startDate = argumentsPayload.startDate;
|
|
207
|
+
const endDate = argumentsPayload.endDate;
|
|
208
|
+
if (typeof startDate === "string" && typeof endDate === "string") {
|
|
209
|
+
return { startDate, endDate };
|
|
210
|
+
}
|
|
211
|
+
return void 0;
|
|
212
|
+
};
|
|
127
213
|
var createMcpCoreRuntime = (dependencies) => ({
|
|
128
214
|
listTools: () => toolDefinitions,
|
|
129
215
|
callTool: async (name, argumentsPayload) => {
|
|
@@ -246,6 +332,171 @@ var createMcpCoreRuntime = (dependencies) => ({
|
|
|
246
332
|
`portfolio refresh: ${result.error.category} (${result.error.reason})`
|
|
247
333
|
);
|
|
248
334
|
}
|
|
335
|
+
if (name === "lighthouse.team.metrics.throughput") {
|
|
336
|
+
const id = getNumericId(argumentsPayload);
|
|
337
|
+
if (id === null) {
|
|
338
|
+
return getErrorToolResult("team metrics: invalid id");
|
|
339
|
+
}
|
|
340
|
+
const range = getDateRange(argumentsPayload);
|
|
341
|
+
const result = await client.getTeamThroughput(id, range);
|
|
342
|
+
if (result.ok) {
|
|
343
|
+
return getSuccessToolResult(
|
|
344
|
+
`team throughput: ${JSON.stringify(result.value)}`
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
return getErrorToolResult(
|
|
348
|
+
`team metrics: ${result.error.category} (${result.error.reason})`
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
if (name === "lighthouse.team.metrics.cycleTimePercentiles") {
|
|
352
|
+
const id = getNumericId(argumentsPayload);
|
|
353
|
+
if (id === null) {
|
|
354
|
+
return getErrorToolResult("team metrics: invalid id");
|
|
355
|
+
}
|
|
356
|
+
const range = getDateRange(argumentsPayload);
|
|
357
|
+
const result = await client.getTeamCycleTimePercentiles(id, range);
|
|
358
|
+
if (result.ok) {
|
|
359
|
+
return getSuccessToolResult(
|
|
360
|
+
`team cycleTimePercentiles: ${JSON.stringify(result.value)}`
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
return getErrorToolResult(
|
|
364
|
+
`team metrics: ${result.error.category} (${result.error.reason})`
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
if (name === "lighthouse.portfolio.metrics.throughput") {
|
|
368
|
+
const id = getNumericId(argumentsPayload);
|
|
369
|
+
if (id === null) {
|
|
370
|
+
return getErrorToolResult("portfolio metrics: invalid id");
|
|
371
|
+
}
|
|
372
|
+
const range = getDateRange(argumentsPayload);
|
|
373
|
+
const result = await client.getPortfolioThroughput(id, range);
|
|
374
|
+
if (result.ok) {
|
|
375
|
+
return getSuccessToolResult(
|
|
376
|
+
`portfolio throughput: ${JSON.stringify(result.value)}`
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
return getErrorToolResult(
|
|
380
|
+
`portfolio metrics: ${result.error.category} (${result.error.reason})`
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
if (name === "lighthouse.feature.get") {
|
|
384
|
+
const payload = isObjectRecord(argumentsPayload) ? argumentsPayload : {};
|
|
385
|
+
const idsValue = payload.ids;
|
|
386
|
+
const refsValue = payload.refs;
|
|
387
|
+
if (Array.isArray(idsValue) && idsValue.length > 0) {
|
|
388
|
+
const ids = idsValue.filter((v) => typeof v === "number");
|
|
389
|
+
const result = await client.getFeaturesByIds(ids);
|
|
390
|
+
if (result.ok) {
|
|
391
|
+
return getSuccessToolResult(
|
|
392
|
+
`features: ${JSON.stringify(result.value)}`
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
return getErrorToolResult(
|
|
396
|
+
`features: ${result.error.category} (${result.error.reason})`
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
if (Array.isArray(refsValue) && refsValue.length > 0) {
|
|
400
|
+
const refs = refsValue.filter(
|
|
401
|
+
(v) => typeof v === "string"
|
|
402
|
+
);
|
|
403
|
+
const result = await client.getFeaturesByReferences(refs);
|
|
404
|
+
if (result.ok) {
|
|
405
|
+
return getSuccessToolResult(
|
|
406
|
+
`features: ${JSON.stringify(result.value)}`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
return getErrorToolResult(
|
|
410
|
+
`features: ${result.error.category} (${result.error.reason})`
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
return getErrorToolResult(
|
|
414
|
+
"features: provide ids (array of numbers) or refs (array of strings)"
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
if (name === "lighthouse.feature.workitems") {
|
|
418
|
+
const id = getNumericId(argumentsPayload);
|
|
419
|
+
if (id === null) {
|
|
420
|
+
return getErrorToolResult("feature workitems: invalid id");
|
|
421
|
+
}
|
|
422
|
+
const result = await client.getFeatureWorkItems(id);
|
|
423
|
+
if (result.ok) {
|
|
424
|
+
return getSuccessToolResult(
|
|
425
|
+
`feature workitems: ${JSON.stringify(result.value)}`
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
return getErrorToolResult(
|
|
429
|
+
`feature workitems: ${result.error.category} (${result.error.reason})`
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
if (name === "lighthouse.delivery.list") {
|
|
433
|
+
const id = getNumericId(argumentsPayload);
|
|
434
|
+
if (id === null) {
|
|
435
|
+
return getErrorToolResult(
|
|
436
|
+
"delivery: invalid id (portfolio id required)"
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
const result = await client.listDeliveries(id);
|
|
440
|
+
if (result.ok) {
|
|
441
|
+
return getSuccessToolResult(
|
|
442
|
+
`deliveries: ${JSON.stringify(result.value)}`
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
return getErrorToolResult(
|
|
446
|
+
`delivery: ${result.error.category} (${result.error.reason})`
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
if (name === "lighthouse.forecast.manual") {
|
|
450
|
+
const id = getNumericId(argumentsPayload);
|
|
451
|
+
if (id === null) {
|
|
452
|
+
return getErrorToolResult("forecast: invalid id (team id required)");
|
|
453
|
+
}
|
|
454
|
+
const payload = isObjectRecord(argumentsPayload) ? argumentsPayload : {};
|
|
455
|
+
const remainingItems = typeof payload.remainingItems === "number" ? payload.remainingItems : void 0;
|
|
456
|
+
const targetDate = typeof payload.targetDate === "string" ? payload.targetDate : void 0;
|
|
457
|
+
const result = await client.runManualForecast(id, {
|
|
458
|
+
remainingItems,
|
|
459
|
+
targetDate
|
|
460
|
+
});
|
|
461
|
+
if (result.ok) {
|
|
462
|
+
return getSuccessToolResult(
|
|
463
|
+
`forecast: ${JSON.stringify(result.value)}`
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
return getErrorToolResult(
|
|
467
|
+
`forecast: ${result.error.category} (${result.error.reason})`
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
if (name === "lighthouse.forecast.backtest") {
|
|
471
|
+
const id = getNumericId(argumentsPayload);
|
|
472
|
+
if (id === null) {
|
|
473
|
+
return getErrorToolResult("backtest: invalid id (team id required)");
|
|
474
|
+
}
|
|
475
|
+
const payload = isObjectRecord(argumentsPayload) ? argumentsPayload : {};
|
|
476
|
+
const startDate = typeof payload.startDate === "string" ? payload.startDate : void 0;
|
|
477
|
+
const endDate = typeof payload.endDate === "string" ? payload.endDate : void 0;
|
|
478
|
+
const historicalStartDate = typeof payload.historicalStartDate === "string" ? payload.historicalStartDate : void 0;
|
|
479
|
+
const historicalEndDate = typeof payload.historicalEndDate === "string" ? payload.historicalEndDate : void 0;
|
|
480
|
+
if (!startDate || !endDate || !historicalStartDate || !historicalEndDate) {
|
|
481
|
+
return getErrorToolResult(
|
|
482
|
+
"backtest: startDate, endDate, historicalStartDate, and historicalEndDate are required"
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
const result = await client.runBacktest(id, {
|
|
486
|
+
startDate,
|
|
487
|
+
endDate,
|
|
488
|
+
historicalStartDate,
|
|
489
|
+
historicalEndDate
|
|
490
|
+
});
|
|
491
|
+
if (result.ok) {
|
|
492
|
+
return getSuccessToolResult(
|
|
493
|
+
`backtest: ${JSON.stringify(result.value)}`
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
return getErrorToolResult(
|
|
497
|
+
`backtest: ${result.error.category} (${result.error.reason})`
|
|
498
|
+
);
|
|
499
|
+
}
|
|
249
500
|
return getErrorToolResult(`Unknown tool: ${name}`);
|
|
250
501
|
}
|
|
251
502
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@letpeoplework/lighthouse-mcp-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Shared MCP semantics for Lighthouse",
|
|
5
5
|
"repository": "https://github.com/LetPeopleWork/lighthouse-clients",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -17,10 +17,12 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"publishConfig": {
|
|
20
|
-
"access": "public"
|
|
20
|
+
"access": "public",
|
|
21
|
+
"provenance": true,
|
|
22
|
+
"registry": "https://registry.npmjs.org/"
|
|
21
23
|
},
|
|
22
24
|
"dependencies": {
|
|
23
|
-
"@letpeoplework/lighthouse-client": "0.
|
|
25
|
+
"@letpeoplework/lighthouse-client": "0.3.0"
|
|
24
26
|
},
|
|
25
27
|
"scripts": {
|
|
26
28
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|