taskin 4.2.0 → 4.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/README.md +45 -23
- package/dist/index.js +967 -570
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -278,8 +278,8 @@ ${body}` : subject;
|
|
|
278
278
|
}
|
|
279
279
|
const lines = output.split("\n").filter((l) => l.trim());
|
|
280
280
|
for (const line of lines) {
|
|
281
|
-
const [added, removed,
|
|
282
|
-
if (added === void 0 || removed === void 0 ||
|
|
281
|
+
const [added, removed, path16] = line.split(" ");
|
|
282
|
+
if (added === void 0 || removed === void 0 || path16 === void 0) continue;
|
|
283
283
|
if (added === "-" || removed === "-") {
|
|
284
284
|
continue;
|
|
285
285
|
}
|
|
@@ -288,7 +288,7 @@ ${body}` : subject;
|
|
|
288
288
|
totalLinesAdded += linesAdded;
|
|
289
289
|
totalLinesRemoved += linesRemoved;
|
|
290
290
|
files.push({
|
|
291
|
-
path:
|
|
291
|
+
path: path16,
|
|
292
292
|
linesAdded,
|
|
293
293
|
linesRemoved,
|
|
294
294
|
changeType: "modified"
|
|
@@ -314,15 +314,15 @@ ${body}` : subject;
|
|
|
314
314
|
if (!output) {
|
|
315
315
|
return null;
|
|
316
316
|
}
|
|
317
|
-
const [added, removed,
|
|
318
|
-
if (added === void 0 || removed === void 0 ||
|
|
317
|
+
const [added, removed, path16] = output.split(" ");
|
|
318
|
+
if (added === void 0 || removed === void 0 || path16 === void 0) {
|
|
319
319
|
return null;
|
|
320
320
|
}
|
|
321
321
|
if (added === "-" || removed === "-") {
|
|
322
322
|
return null;
|
|
323
323
|
}
|
|
324
324
|
return {
|
|
325
|
-
path:
|
|
325
|
+
path: path16,
|
|
326
326
|
linesAdded: parseInt(added, 10),
|
|
327
327
|
linesRemoved: parseInt(removed, 10),
|
|
328
328
|
changeType: "modified"
|
|
@@ -493,8 +493,8 @@ var init_git_service = __esm({
|
|
|
493
493
|
}).trim();
|
|
494
494
|
if (files) {
|
|
495
495
|
taskFilePath = files.split("\n")[0] ?? null;
|
|
496
|
-
const { readFileSync:
|
|
497
|
-
taskFileContent =
|
|
496
|
+
const { readFileSync: readFileSync7 } = await import("fs");
|
|
497
|
+
taskFileContent = readFileSync7(`${this.cwd}/${taskFilePath}`, "utf-8");
|
|
498
498
|
}
|
|
499
499
|
} catch {
|
|
500
500
|
}
|
|
@@ -514,8 +514,8 @@ var init_git_service = __esm({
|
|
|
514
514
|
});
|
|
515
515
|
let committed = false;
|
|
516
516
|
if (taskFileContent && taskFilePath) {
|
|
517
|
-
const { writeFileSync:
|
|
518
|
-
|
|
517
|
+
const { writeFileSync: writeFileSync4 } = await import("fs");
|
|
518
|
+
writeFileSync4(`${this.cwd}/${taskFilePath}`, taskFileContent, "utf-8");
|
|
519
519
|
const message = buildTaskStatusCommitMessage({ taskId, status, ciSkipTag: this.ciSkipTag });
|
|
520
520
|
committed = await this.addAndCommit(taskPattern, message);
|
|
521
521
|
} else {
|
|
@@ -2737,6 +2737,610 @@ var init_src3 = __esm({
|
|
|
2737
2737
|
}
|
|
2738
2738
|
});
|
|
2739
2739
|
|
|
2740
|
+
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/filter-tasks/filter-tasks.js
|
|
2741
|
+
function casaResponsavel2(task, procurado) {
|
|
2742
|
+
const alvo = procurado.toLowerCase();
|
|
2743
|
+
return contem2(task.assignee?.id, alvo) || contem2(task.assignee?.name, alvo);
|
|
2744
|
+
}
|
|
2745
|
+
function filterTasks2(tasks, criteria) {
|
|
2746
|
+
return tasks.filter((task) => {
|
|
2747
|
+
if (criteria.status !== void 0) {
|
|
2748
|
+
if (task.status !== criteria.status)
|
|
2749
|
+
return false;
|
|
2750
|
+
} else if (criteria.open && !EM_ABERTO2.includes(task.status)) {
|
|
2751
|
+
return false;
|
|
2752
|
+
} else if (criteria.closed && !ENCERRADOS2.includes(task.status)) {
|
|
2753
|
+
return false;
|
|
2754
|
+
}
|
|
2755
|
+
if (criteria.type !== void 0 && task.type !== criteria.type)
|
|
2756
|
+
return false;
|
|
2757
|
+
if (criteria.assignee !== void 0 && !casaResponsavel2(task, criteria.assignee))
|
|
2758
|
+
return false;
|
|
2759
|
+
if (criteria.text !== void 0) {
|
|
2760
|
+
const procurado = criteria.text.toLowerCase();
|
|
2761
|
+
const casa = task.id.toLowerCase().includes(procurado) || contem2(task.title, procurado) || contem2(task.status, procurado) || casaResponsavel2(task, procurado);
|
|
2762
|
+
if (!casa)
|
|
2763
|
+
return false;
|
|
2764
|
+
}
|
|
2765
|
+
return true;
|
|
2766
|
+
});
|
|
2767
|
+
}
|
|
2768
|
+
function summarizeTask2(task) {
|
|
2769
|
+
return {
|
|
2770
|
+
id: task.id,
|
|
2771
|
+
title: task.title,
|
|
2772
|
+
status: task.status,
|
|
2773
|
+
type: task.type,
|
|
2774
|
+
...task.assignee && { assignee: { id: task.assignee.id, name: task.assignee.name } },
|
|
2775
|
+
...task.order !== void 0 && { priority: task.order },
|
|
2776
|
+
...task.groupId && { groupId: task.groupId },
|
|
2777
|
+
...task.groupName && { groupName: task.groupName },
|
|
2778
|
+
...task.difficulty !== void 0 && { difficulty: task.difficulty }
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2781
|
+
var EM_ABERTO2, ENCERRADOS2, contem2;
|
|
2782
|
+
var init_filter_tasks = __esm({
|
|
2783
|
+
"node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/filter-tasks/filter-tasks.js"() {
|
|
2784
|
+
"use strict";
|
|
2785
|
+
init_esm_shims();
|
|
2786
|
+
EM_ABERTO2 = ["pending", "in-progress", "paused", "in-review", "blocked"];
|
|
2787
|
+
ENCERRADOS2 = ["done", "canceled"];
|
|
2788
|
+
contem2 = (valor, procurado) => valor?.toLowerCase().includes(procurado) ?? false;
|
|
2789
|
+
}
|
|
2790
|
+
});
|
|
2791
|
+
|
|
2792
|
+
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/filter-tasks/index.js
|
|
2793
|
+
var init_filter_tasks2 = __esm({
|
|
2794
|
+
"node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/filter-tasks/index.js"() {
|
|
2795
|
+
"use strict";
|
|
2796
|
+
init_esm_shims();
|
|
2797
|
+
init_filter_tasks();
|
|
2798
|
+
}
|
|
2799
|
+
});
|
|
2800
|
+
|
|
2801
|
+
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/metrics.types.js
|
|
2802
|
+
var init_metrics_types = __esm({
|
|
2803
|
+
"node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/metrics.types.js"() {
|
|
2804
|
+
"use strict";
|
|
2805
|
+
init_esm_shims();
|
|
2806
|
+
}
|
|
2807
|
+
});
|
|
2808
|
+
|
|
2809
|
+
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/task-manager.js
|
|
2810
|
+
var init_task_manager = __esm({
|
|
2811
|
+
"node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/task-manager.js"() {
|
|
2812
|
+
"use strict";
|
|
2813
|
+
init_esm_shims();
|
|
2814
|
+
}
|
|
2815
|
+
});
|
|
2816
|
+
|
|
2817
|
+
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/task-manager.types.js
|
|
2818
|
+
var init_task_manager_types = __esm({
|
|
2819
|
+
"node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/task-manager.types.js"() {
|
|
2820
|
+
"use strict";
|
|
2821
|
+
init_esm_shims();
|
|
2822
|
+
}
|
|
2823
|
+
});
|
|
2824
|
+
|
|
2825
|
+
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/user-registry.types.js
|
|
2826
|
+
var init_user_registry_types = __esm({
|
|
2827
|
+
"node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/user-registry.types.js"() {
|
|
2828
|
+
"use strict";
|
|
2829
|
+
init_esm_shims();
|
|
2830
|
+
}
|
|
2831
|
+
});
|
|
2832
|
+
|
|
2833
|
+
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/index.js
|
|
2834
|
+
var init_dist = __esm({
|
|
2835
|
+
"node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/index.js"() {
|
|
2836
|
+
"use strict";
|
|
2837
|
+
init_esm_shims();
|
|
2838
|
+
init_filter_tasks2();
|
|
2839
|
+
init_metrics_types();
|
|
2840
|
+
init_task_manager();
|
|
2841
|
+
init_task_manager_types();
|
|
2842
|
+
init_user_registry_types();
|
|
2843
|
+
}
|
|
2844
|
+
});
|
|
2845
|
+
|
|
2846
|
+
// node_modules/@opentask/taskin-task-server-mcp/dist/task-server-mcp.js
|
|
2847
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2848
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2849
|
+
import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
2850
|
+
import { TaskIdSchema as TaskIdSchema4 } from "@opentask/taskin-types";
|
|
2851
|
+
function readTaskId(raw) {
|
|
2852
|
+
if (typeof raw !== "string")
|
|
2853
|
+
return void 0;
|
|
2854
|
+
const parsed = TaskIdSchema4.safeParse(raw);
|
|
2855
|
+
return parsed.success ? parsed.data : void 0;
|
|
2856
|
+
}
|
|
2857
|
+
function invalidTaskId(raw) {
|
|
2858
|
+
return {
|
|
2859
|
+
content: [
|
|
2860
|
+
{
|
|
2861
|
+
type: "text",
|
|
2862
|
+
text: `Invalid task id: ${JSON.stringify(raw)}. Expected the numeric id of a task, e.g. "020".`
|
|
2863
|
+
}
|
|
2864
|
+
],
|
|
2865
|
+
isError: true
|
|
2866
|
+
};
|
|
2867
|
+
}
|
|
2868
|
+
async function createTaskMCPServer(taskManager, options) {
|
|
2869
|
+
const server = new TaskMCPServer({
|
|
2870
|
+
taskManager,
|
|
2871
|
+
...options
|
|
2872
|
+
});
|
|
2873
|
+
await server.connect({ transport: "stdio" });
|
|
2874
|
+
return server;
|
|
2875
|
+
}
|
|
2876
|
+
var TaskMCPServer;
|
|
2877
|
+
var init_task_server_mcp = __esm({
|
|
2878
|
+
"node_modules/@opentask/taskin-task-server-mcp/dist/task-server-mcp.js"() {
|
|
2879
|
+
"use strict";
|
|
2880
|
+
init_esm_shims();
|
|
2881
|
+
init_dist();
|
|
2882
|
+
TaskMCPServer = class _TaskMCPServer {
|
|
2883
|
+
server;
|
|
2884
|
+
taskManager;
|
|
2885
|
+
config;
|
|
2886
|
+
constructor(config) {
|
|
2887
|
+
this.taskManager = config.taskManager;
|
|
2888
|
+
this.config = {
|
|
2889
|
+
name: "taskin-mcp-server",
|
|
2890
|
+
version: "1.0.0",
|
|
2891
|
+
debug: false,
|
|
2892
|
+
...config,
|
|
2893
|
+
taskManager: config.taskManager
|
|
2894
|
+
};
|
|
2895
|
+
this.server = new Server({
|
|
2896
|
+
name: this.config.name,
|
|
2897
|
+
version: this.config.version
|
|
2898
|
+
}, {
|
|
2899
|
+
capabilities: {
|
|
2900
|
+
tools: {},
|
|
2901
|
+
prompts: {},
|
|
2902
|
+
resources: {}
|
|
2903
|
+
}
|
|
2904
|
+
});
|
|
2905
|
+
this.setupHandlers();
|
|
2906
|
+
}
|
|
2907
|
+
/**
|
|
2908
|
+
* Setup MCP request handlers
|
|
2909
|
+
*/
|
|
2910
|
+
setupHandlers() {
|
|
2911
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
2912
|
+
const { tools } = this.listTools();
|
|
2913
|
+
return { tools };
|
|
2914
|
+
});
|
|
2915
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
2916
|
+
const result = await this.callTool({
|
|
2917
|
+
name: request.params.name,
|
|
2918
|
+
arguments: request.params.arguments
|
|
2919
|
+
});
|
|
2920
|
+
return {
|
|
2921
|
+
content: result.content,
|
|
2922
|
+
isError: result.isError
|
|
2923
|
+
};
|
|
2924
|
+
});
|
|
2925
|
+
this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
2926
|
+
const { prompts } = this.listPrompts();
|
|
2927
|
+
return { prompts };
|
|
2928
|
+
});
|
|
2929
|
+
this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
2930
|
+
const result = await this.getPrompt({
|
|
2931
|
+
name: request.params.name,
|
|
2932
|
+
arguments: request.params.arguments
|
|
2933
|
+
});
|
|
2934
|
+
return {
|
|
2935
|
+
messages: result.messages.map((msg) => ({
|
|
2936
|
+
role: msg.role,
|
|
2937
|
+
content: {
|
|
2938
|
+
type: "text",
|
|
2939
|
+
text: msg.content
|
|
2940
|
+
}
|
|
2941
|
+
}))
|
|
2942
|
+
};
|
|
2943
|
+
});
|
|
2944
|
+
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
2945
|
+
const result = await this.listResources();
|
|
2946
|
+
return { resources: result.resources };
|
|
2947
|
+
});
|
|
2948
|
+
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
2949
|
+
const result = await this.readResource({
|
|
2950
|
+
uri: request.params.uri
|
|
2951
|
+
});
|
|
2952
|
+
return result;
|
|
2953
|
+
});
|
|
2954
|
+
}
|
|
2955
|
+
/**
|
|
2956
|
+
* Connect to MCP transport
|
|
2957
|
+
*
|
|
2958
|
+
* `MCPTransportType` tem um valor so, entao nao ha o que despachar. O ramo
|
|
2959
|
+
* que existia aqui aceitava `'sse'` pelo tipo e recusava em tempo de
|
|
2960
|
+
* execucao, ja com o provider inicializado.
|
|
2961
|
+
*/
|
|
2962
|
+
async connect(_options) {
|
|
2963
|
+
await this.server.connect(new StdioServerTransport());
|
|
2964
|
+
this.log("MCP Server connected via stdio");
|
|
2965
|
+
}
|
|
2966
|
+
/**
|
|
2967
|
+
* Get server information
|
|
2968
|
+
*/
|
|
2969
|
+
getServerInfo() {
|
|
2970
|
+
return {
|
|
2971
|
+
name: this.config.name,
|
|
2972
|
+
version: this.config.version,
|
|
2973
|
+
protocolVersion: "2024-11-05",
|
|
2974
|
+
capabilities: {
|
|
2975
|
+
tools: {},
|
|
2976
|
+
prompts: {},
|
|
2977
|
+
resources: {}
|
|
2978
|
+
}
|
|
2979
|
+
};
|
|
2980
|
+
}
|
|
2981
|
+
/**
|
|
2982
|
+
* List available tools
|
|
2983
|
+
*/
|
|
2984
|
+
listTools() {
|
|
2985
|
+
const tools = [
|
|
2986
|
+
{
|
|
2987
|
+
name: "list_tasks",
|
|
2988
|
+
description: "List the tasks in the project. Returns a JSON array with what identifies each task \u2014 id, title, status, type, assignee \u2014 without the markdown body. Fetch a task body by id after choosing one.",
|
|
2989
|
+
inputSchema: {
|
|
2990
|
+
type: "object",
|
|
2991
|
+
properties: {
|
|
2992
|
+
status: { type: "string", description: "Exact status (pending, in-progress, done, ...)" },
|
|
2993
|
+
type: { type: "string", description: "Exact type (feat, fix, chore, ...)" },
|
|
2994
|
+
assignee: { type: "string", description: "Assignee id or name, whole or in part" },
|
|
2995
|
+
open: { type: "boolean", description: "Only tasks still open" },
|
|
2996
|
+
closed: { type: "boolean", description: "Only tasks already closed" },
|
|
2997
|
+
text: { type: "string", description: "Free text over id, title, status and assignee" }
|
|
2998
|
+
},
|
|
2999
|
+
required: []
|
|
3000
|
+
}
|
|
3001
|
+
},
|
|
3002
|
+
{
|
|
3003
|
+
name: "start_task",
|
|
3004
|
+
description: "Start working on a task by changing its status to in-progress",
|
|
3005
|
+
inputSchema: {
|
|
3006
|
+
type: "object",
|
|
3007
|
+
properties: {
|
|
3008
|
+
taskId: {
|
|
3009
|
+
type: "string",
|
|
3010
|
+
description: "The unique identifier of the task (UUID)"
|
|
3011
|
+
}
|
|
3012
|
+
},
|
|
3013
|
+
required: ["taskId"]
|
|
3014
|
+
}
|
|
3015
|
+
},
|
|
3016
|
+
{
|
|
3017
|
+
name: "finish_task",
|
|
3018
|
+
description: "Mark a task as completed by changing its status to done",
|
|
3019
|
+
inputSchema: {
|
|
3020
|
+
type: "object",
|
|
3021
|
+
properties: {
|
|
3022
|
+
taskId: {
|
|
3023
|
+
type: "string",
|
|
3024
|
+
description: "The unique identifier of the task (UUID)"
|
|
3025
|
+
}
|
|
3026
|
+
},
|
|
3027
|
+
required: ["taskId"]
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
];
|
|
3031
|
+
return { tools };
|
|
3032
|
+
}
|
|
3033
|
+
/**
|
|
3034
|
+
* Call a tool
|
|
3035
|
+
*/
|
|
3036
|
+
async callTool(params) {
|
|
3037
|
+
try {
|
|
3038
|
+
this.log(`Calling tool: ${params.name}`, params.arguments);
|
|
3039
|
+
switch (params.name) {
|
|
3040
|
+
case "list_tasks":
|
|
3041
|
+
return await this.handleListTasks(params.arguments ?? {});
|
|
3042
|
+
case "start_task": {
|
|
3043
|
+
const taskId = readTaskId(params.arguments?.taskId);
|
|
3044
|
+
return taskId ? await this.handleStartTask(taskId) : invalidTaskId(params.arguments?.taskId);
|
|
3045
|
+
}
|
|
3046
|
+
case "finish_task": {
|
|
3047
|
+
const taskId = readTaskId(params.arguments?.taskId);
|
|
3048
|
+
return taskId ? await this.handleFinishTask(taskId) : invalidTaskId(params.arguments?.taskId);
|
|
3049
|
+
}
|
|
3050
|
+
default:
|
|
3051
|
+
return {
|
|
3052
|
+
content: [
|
|
3053
|
+
{
|
|
3054
|
+
type: "text",
|
|
3055
|
+
text: `Unknown tool: ${params.name}`
|
|
3056
|
+
}
|
|
3057
|
+
],
|
|
3058
|
+
isError: true
|
|
3059
|
+
};
|
|
3060
|
+
}
|
|
3061
|
+
} catch (error2) {
|
|
3062
|
+
this.log("Tool call error:", error2);
|
|
3063
|
+
return {
|
|
3064
|
+
content: [
|
|
3065
|
+
{
|
|
3066
|
+
type: "text",
|
|
3067
|
+
text: error2 instanceof Error ? error2.message : String(error2)
|
|
3068
|
+
}
|
|
3069
|
+
],
|
|
3070
|
+
isError: true
|
|
3071
|
+
};
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
/**
|
|
3075
|
+
* Handle start_task tool
|
|
3076
|
+
*/
|
|
3077
|
+
async handleStartTask(taskId) {
|
|
3078
|
+
const task = await this.taskManager.startTask(taskId);
|
|
3079
|
+
return {
|
|
3080
|
+
content: [
|
|
3081
|
+
{
|
|
3082
|
+
type: "text",
|
|
3083
|
+
text: JSON.stringify({
|
|
3084
|
+
success: true,
|
|
3085
|
+
message: `Task ${taskId} started successfully`,
|
|
3086
|
+
task: {
|
|
3087
|
+
id: task.id,
|
|
3088
|
+
title: task.title,
|
|
3089
|
+
status: task.status,
|
|
3090
|
+
type: task.type
|
|
3091
|
+
}
|
|
3092
|
+
}, null, 2)
|
|
3093
|
+
}
|
|
3094
|
+
]
|
|
3095
|
+
};
|
|
3096
|
+
}
|
|
3097
|
+
/**
|
|
3098
|
+
* Handle finish_task tool
|
|
3099
|
+
*/
|
|
3100
|
+
async handleFinishTask(taskId) {
|
|
3101
|
+
const task = await this.taskManager.finishTask(taskId);
|
|
3102
|
+
return {
|
|
3103
|
+
content: [
|
|
3104
|
+
{
|
|
3105
|
+
type: "text",
|
|
3106
|
+
text: JSON.stringify({
|
|
3107
|
+
success: true,
|
|
3108
|
+
message: `Task ${taskId} finished successfully`,
|
|
3109
|
+
task: {
|
|
3110
|
+
id: task.id,
|
|
3111
|
+
title: task.title,
|
|
3112
|
+
status: task.status,
|
|
3113
|
+
type: task.type
|
|
3114
|
+
}
|
|
3115
|
+
}, null, 2)
|
|
3116
|
+
}
|
|
3117
|
+
]
|
|
3118
|
+
};
|
|
3119
|
+
}
|
|
3120
|
+
/**
|
|
3121
|
+
* List available prompts
|
|
3122
|
+
*/
|
|
3123
|
+
listPrompts() {
|
|
3124
|
+
const prompts = [
|
|
3125
|
+
{
|
|
3126
|
+
name: "start-task-workflow",
|
|
3127
|
+
description: "Guide the user through starting work on a task with git branch creation",
|
|
3128
|
+
arguments: [
|
|
3129
|
+
{
|
|
3130
|
+
name: "taskId",
|
|
3131
|
+
description: "The task ID to start",
|
|
3132
|
+
required: true
|
|
3133
|
+
}
|
|
3134
|
+
]
|
|
3135
|
+
},
|
|
3136
|
+
{
|
|
3137
|
+
name: "finish-task-workflow",
|
|
3138
|
+
description: "Guide the user through completing a task with commit and PR creation",
|
|
3139
|
+
arguments: [
|
|
3140
|
+
{
|
|
3141
|
+
name: "taskId",
|
|
3142
|
+
description: "The task ID to finish",
|
|
3143
|
+
required: true
|
|
3144
|
+
}
|
|
3145
|
+
]
|
|
3146
|
+
},
|
|
3147
|
+
{
|
|
3148
|
+
name: "task-summary",
|
|
3149
|
+
description: "Generate a summary of a task for documentation or reports",
|
|
3150
|
+
arguments: [
|
|
3151
|
+
{
|
|
3152
|
+
name: "taskId",
|
|
3153
|
+
description: "The task ID to summarize",
|
|
3154
|
+
required: true
|
|
3155
|
+
}
|
|
3156
|
+
]
|
|
3157
|
+
}
|
|
3158
|
+
];
|
|
3159
|
+
return { prompts };
|
|
3160
|
+
}
|
|
3161
|
+
/**
|
|
3162
|
+
* Get a prompt
|
|
3163
|
+
*/
|
|
3164
|
+
async getPrompt(params) {
|
|
3165
|
+
this.log(`Getting prompt: ${params.name}`, params.arguments);
|
|
3166
|
+
switch (params.name) {
|
|
3167
|
+
case "start-task-workflow":
|
|
3168
|
+
return {
|
|
3169
|
+
description: "Workflow for starting a task",
|
|
3170
|
+
messages: [
|
|
3171
|
+
{
|
|
3172
|
+
role: "user",
|
|
3173
|
+
content: {
|
|
3174
|
+
type: "text",
|
|
3175
|
+
text: `I want to start working on task ${params.arguments?.taskId}. Can you help me set everything up?`
|
|
3176
|
+
}
|
|
3177
|
+
},
|
|
3178
|
+
{
|
|
3179
|
+
role: "assistant",
|
|
3180
|
+
content: {
|
|
3181
|
+
type: "text",
|
|
3182
|
+
text: `I'll help you start working on task ${params.arguments?.taskId}. Here's what I'll do:
|
|
3183
|
+
|
|
3184
|
+
1. Mark the task as "in-progress"
|
|
3185
|
+
2. Create a git branch based on the task type and ID
|
|
3186
|
+
3. Ensure your working directory is clean
|
|
3187
|
+
4. Switch to the new branch
|
|
3188
|
+
|
|
3189
|
+
Let me start by marking the task as in-progress using the start_task tool.`
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3192
|
+
]
|
|
3193
|
+
};
|
|
3194
|
+
case "finish-task-workflow":
|
|
3195
|
+
return {
|
|
3196
|
+
description: "Workflow for finishing a task",
|
|
3197
|
+
messages: [
|
|
3198
|
+
{
|
|
3199
|
+
role: "user",
|
|
3200
|
+
content: {
|
|
3201
|
+
type: "text",
|
|
3202
|
+
text: `I've completed task ${params.arguments?.taskId}. What should I do next?`
|
|
3203
|
+
}
|
|
3204
|
+
},
|
|
3205
|
+
{
|
|
3206
|
+
role: "assistant",
|
|
3207
|
+
content: {
|
|
3208
|
+
type: "text",
|
|
3209
|
+
text: `Great! Let me help you finish task ${params.arguments?.taskId}. Here's the workflow:
|
|
3210
|
+
|
|
3211
|
+
1. Mark the task as "done"
|
|
3212
|
+
2. Ensure all changes are committed
|
|
3213
|
+
3. Push your branch to remote
|
|
3214
|
+
4. Create a pull request
|
|
3215
|
+
|
|
3216
|
+
Let me start by marking the task as done using the finish_task tool.`
|
|
3217
|
+
}
|
|
3218
|
+
}
|
|
3219
|
+
]
|
|
3220
|
+
};
|
|
3221
|
+
case "task-summary":
|
|
3222
|
+
return {
|
|
3223
|
+
description: "Generate task summary",
|
|
3224
|
+
messages: [
|
|
3225
|
+
{
|
|
3226
|
+
role: "user",
|
|
3227
|
+
content: {
|
|
3228
|
+
type: "text",
|
|
3229
|
+
text: `Can you provide a summary of task ${params.arguments?.taskId}?`
|
|
3230
|
+
}
|
|
3231
|
+
},
|
|
3232
|
+
{
|
|
3233
|
+
role: "assistant",
|
|
3234
|
+
content: {
|
|
3235
|
+
type: "text",
|
|
3236
|
+
text: `I'll generate a comprehensive summary of task ${params.arguments?.taskId} including its current status, description, and any relevant metadata.`
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
]
|
|
3240
|
+
};
|
|
3241
|
+
default:
|
|
3242
|
+
throw new Error(`Unknown prompt: ${params.name}`);
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
/**
|
|
3246
|
+
* Le e seleciona as tarefas, pela mesma seam que o CLI usa.
|
|
3247
|
+
*
|
|
3248
|
+
* `filterTasks` e `summarizeTask` vivem no pacote agnostico justamente para
|
|
3249
|
+
* que a resposta aqui e a de `taskin list --json` nao possam divergir — ja
|
|
3250
|
+
* houve duas filtragens discordando no repositorio.
|
|
3251
|
+
*/
|
|
3252
|
+
async selecionarTarefas(criteria) {
|
|
3253
|
+
const tasks = await this.taskManager.getAllTasks();
|
|
3254
|
+
return filterTasks2(tasks, criteria).map(summarizeTask2);
|
|
3255
|
+
}
|
|
3256
|
+
/** Converte os argumentos crus da chamada MCP no criterio tipado. */
|
|
3257
|
+
static criterioDe(args) {
|
|
3258
|
+
return {
|
|
3259
|
+
...typeof args.status === "string" && { status: args.status },
|
|
3260
|
+
...typeof args.type === "string" && { type: args.type },
|
|
3261
|
+
...typeof args.assignee === "string" && { assignee: args.assignee },
|
|
3262
|
+
...args.open === true && { open: true },
|
|
3263
|
+
...args.closed === true && { closed: true },
|
|
3264
|
+
...typeof args.text === "string" && { text: args.text }
|
|
3265
|
+
};
|
|
3266
|
+
}
|
|
3267
|
+
async handleListTasks(args) {
|
|
3268
|
+
const tarefas = await this.selecionarTarefas(_TaskMCPServer.criterioDe(args));
|
|
3269
|
+
return {
|
|
3270
|
+
content: [{ type: "text", text: JSON.stringify(tarefas, null, 2) }],
|
|
3271
|
+
isError: false
|
|
3272
|
+
};
|
|
3273
|
+
}
|
|
3274
|
+
/**
|
|
3275
|
+
* List available resources
|
|
3276
|
+
*/
|
|
3277
|
+
async listResources() {
|
|
3278
|
+
return {
|
|
3279
|
+
resources: [
|
|
3280
|
+
{
|
|
3281
|
+
uri: "taskin://tasks",
|
|
3282
|
+
name: "All Tasks",
|
|
3283
|
+
description: "Access to all tasks in the system",
|
|
3284
|
+
mimeType: "application/json"
|
|
3285
|
+
}
|
|
3286
|
+
]
|
|
3287
|
+
};
|
|
3288
|
+
}
|
|
3289
|
+
/**
|
|
3290
|
+
* Read a resource
|
|
3291
|
+
*/
|
|
3292
|
+
async readResource(params) {
|
|
3293
|
+
this.log(`Reading resource: ${params.uri}`);
|
|
3294
|
+
const uri = params.uri;
|
|
3295
|
+
if (uri === "taskin://tasks") {
|
|
3296
|
+
const tarefas = await this.selecionarTarefas({});
|
|
3297
|
+
return {
|
|
3298
|
+
contents: [
|
|
3299
|
+
{
|
|
3300
|
+
uri,
|
|
3301
|
+
mimeType: "application/json",
|
|
3302
|
+
text: JSON.stringify(tarefas, null, 2)
|
|
3303
|
+
}
|
|
3304
|
+
]
|
|
3305
|
+
};
|
|
3306
|
+
}
|
|
3307
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
3308
|
+
}
|
|
3309
|
+
/**
|
|
3310
|
+
* Debug logging
|
|
3311
|
+
*/
|
|
3312
|
+
log(...args) {
|
|
3313
|
+
if (this.config.debug) {
|
|
3314
|
+
console.error("[TaskMCPServer]", ...args);
|
|
3315
|
+
}
|
|
3316
|
+
}
|
|
3317
|
+
};
|
|
3318
|
+
}
|
|
3319
|
+
});
|
|
3320
|
+
|
|
3321
|
+
// node_modules/@opentask/taskin-task-server-mcp/dist/task-server-mcp.types.js
|
|
3322
|
+
var init_task_server_mcp_types = __esm({
|
|
3323
|
+
"node_modules/@opentask/taskin-task-server-mcp/dist/task-server-mcp.types.js"() {
|
|
3324
|
+
"use strict";
|
|
3325
|
+
init_esm_shims();
|
|
3326
|
+
}
|
|
3327
|
+
});
|
|
3328
|
+
|
|
3329
|
+
// node_modules/@opentask/taskin-task-server-mcp/dist/index.js
|
|
3330
|
+
var dist_exports = {};
|
|
3331
|
+
__export(dist_exports, {
|
|
3332
|
+
TaskMCPServer: () => TaskMCPServer,
|
|
3333
|
+
createTaskMCPServer: () => createTaskMCPServer
|
|
3334
|
+
});
|
|
3335
|
+
var init_dist2 = __esm({
|
|
3336
|
+
"node_modules/@opentask/taskin-task-server-mcp/dist/index.js"() {
|
|
3337
|
+
"use strict";
|
|
3338
|
+
init_esm_shims();
|
|
3339
|
+
init_task_server_mcp();
|
|
3340
|
+
init_task_server_mcp_types();
|
|
3341
|
+
}
|
|
3342
|
+
});
|
|
3343
|
+
|
|
2740
3344
|
// src/index.ts
|
|
2741
3345
|
init_esm_shims();
|
|
2742
3346
|
import { Command } from "commander";
|
|
@@ -3463,7 +4067,7 @@ init_esm_shims();
|
|
|
3463
4067
|
init_esm_shims();
|
|
3464
4068
|
var EM_ABERTO = ["pending", "in-progress", "paused", "in-review", "blocked"];
|
|
3465
4069
|
var ENCERRADOS = ["done", "canceled"];
|
|
3466
|
-
var contem = (valor, procurado) => valor
|
|
4070
|
+
var contem = (valor, procurado) => valor?.toLowerCase().includes(procurado) ?? false;
|
|
3467
4071
|
function casaResponsavel(task, procurado) {
|
|
3468
4072
|
const alvo = procurado.toLowerCase();
|
|
3469
4073
|
return contem(task.assignee?.id, alvo) || contem(task.assignee?.name, alvo);
|
|
@@ -4550,6 +5154,15 @@ init_src3();
|
|
|
4550
5154
|
init_src();
|
|
4551
5155
|
import { execSync as execSync5 } from "child_process";
|
|
4552
5156
|
|
|
5157
|
+
// src/lib/ci-skip-tag/index.ts
|
|
5158
|
+
init_esm_shims();
|
|
5159
|
+
|
|
5160
|
+
// src/lib/ci-skip-tag/resolve-ci-skip-tag.ts
|
|
5161
|
+
init_esm_shims();
|
|
5162
|
+
function resolveCiSkipTag(configurada, skipCi) {
|
|
5163
|
+
return skipCi === false ? "" : configurada;
|
|
5164
|
+
}
|
|
5165
|
+
|
|
4553
5166
|
// src/lib/notification/notify-helper.ts
|
|
4554
5167
|
init_esm_shims();
|
|
4555
5168
|
import { execSync as execSync4 } from "child_process";
|
|
@@ -4946,6 +5559,10 @@ var finishCommand = defineCommand({
|
|
|
4946
5559
|
{
|
|
4947
5560
|
flags: "--dry-run",
|
|
4948
5561
|
description: "Show what would be executed without running"
|
|
5562
|
+
},
|
|
5563
|
+
{
|
|
5564
|
+
flags: "--no-skip-ci",
|
|
5565
|
+
description: "Write the status commit without the CI-skip tag"
|
|
4949
5566
|
}
|
|
4950
5567
|
],
|
|
4951
5568
|
handler: async (taskId, options) => {
|
|
@@ -4971,11 +5588,12 @@ async function finishTask(taskId, options, gitService) {
|
|
|
4971
5588
|
info(`Current status: ${task.status}`);
|
|
4972
5589
|
const configManager = new ConfigManager(monorepoRoot);
|
|
4973
5590
|
const behavior = configManager.getAutomationBehavior();
|
|
5591
|
+
const ciSkipTag = resolveCiSkipTag(behavior.ciSkipTag, options.skipCi);
|
|
4974
5592
|
const autoSyncActive = behavior.autoSync && !!behavior.defaultBranch;
|
|
4975
5593
|
const statusCommitMessage = buildTaskStatusCommitMessage({
|
|
4976
5594
|
taskId: normalizedId,
|
|
4977
5595
|
status: "done",
|
|
4978
|
-
ciSkipTag
|
|
5596
|
+
ciSkipTag
|
|
4979
5597
|
});
|
|
4980
5598
|
if (options.dryRun) {
|
|
4981
5599
|
console.log();
|
|
@@ -5008,7 +5626,7 @@ async function finishTask(taskId, options, gitService) {
|
|
|
5008
5626
|
if (behavior.autoSync && !behavior.defaultBranch) {
|
|
5009
5627
|
warning("autoSync is enabled but no defaultBranch is configured. Nothing will be synced.");
|
|
5010
5628
|
}
|
|
5011
|
-
const git = gitService ?? new GitService(process.cwd(), { ciSkipTag
|
|
5629
|
+
const git = gitService ?? new GitService(process.cwd(), { ciSkipTag });
|
|
5012
5630
|
if (!options.skipUpdate) {
|
|
5013
5631
|
info("Marking task as done...");
|
|
5014
5632
|
const updatedTask = await taskManager.finishTask(task.id);
|
|
@@ -5026,7 +5644,7 @@ async function finishTask(taskId, options, gitService) {
|
|
|
5026
5644
|
taskId: normalizedId,
|
|
5027
5645
|
defaultBranch: behavior.defaultBranch,
|
|
5028
5646
|
originBranch: behavior.originBranch,
|
|
5029
|
-
ciSkipTag
|
|
5647
|
+
ciSkipTag
|
|
5030
5648
|
});
|
|
5031
5649
|
if (squashed) {
|
|
5032
5650
|
success(`Squash commit pushed to ${behavior.originBranch}`);
|
|
@@ -5267,7 +5885,7 @@ async function initializeTaskin(options) {
|
|
|
5267
5885
|
await ensureProviderInstalled(selectedProvider);
|
|
5268
5886
|
}
|
|
5269
5887
|
const providerConfig = await setupProviderConfig(selectedProvider, cwd);
|
|
5270
|
-
const ciSkipTag = await
|
|
5888
|
+
const ciSkipTag = await resolveCiSkipTag2(options.ciSkipTag);
|
|
5271
5889
|
const config = {
|
|
5272
5890
|
version: "1.0.3",
|
|
5273
5891
|
automation: {
|
|
@@ -5301,7 +5919,7 @@ async function initializeTaskin(options) {
|
|
|
5301
5919
|
info("For more information, run: taskin --help");
|
|
5302
5920
|
console.log();
|
|
5303
5921
|
}
|
|
5304
|
-
async function
|
|
5922
|
+
async function resolveCiSkipTag2(fromFlag) {
|
|
5305
5923
|
if (fromFlag !== void 0) {
|
|
5306
5924
|
return normalizeCiSkipTag(fromFlag);
|
|
5307
5925
|
}
|
|
@@ -5674,554 +6292,324 @@ function getTypeColor(type) {
|
|
|
5674
6292
|
}
|
|
5675
6293
|
}
|
|
5676
6294
|
|
|
5677
|
-
// src/commands/mcp-
|
|
5678
|
-
init_esm_shims();
|
|
5679
|
-
|
|
5680
|
-
// node_modules/@opentask/taskin-task-server-mcp/dist/index.js
|
|
5681
|
-
init_esm_shims();
|
|
5682
|
-
|
|
5683
|
-
// node_modules/@opentask/taskin-task-server-mcp/dist/task-server-mcp.js
|
|
5684
|
-
init_esm_shims();
|
|
5685
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
5686
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5687
|
-
import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
5688
|
-
|
|
5689
|
-
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/index.js
|
|
6295
|
+
// src/commands/mcp-install.ts
|
|
5690
6296
|
init_esm_shims();
|
|
6297
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
6298
|
+
import path14 from "path";
|
|
5691
6299
|
|
|
5692
|
-
//
|
|
6300
|
+
// src/lib/mcp-install/index.ts
|
|
5693
6301
|
init_esm_shims();
|
|
5694
6302
|
|
|
5695
|
-
//
|
|
6303
|
+
// src/lib/mcp-install/merge-mcp-config.ts
|
|
5696
6304
|
init_esm_shims();
|
|
5697
|
-
var
|
|
5698
|
-
var
|
|
5699
|
-
var
|
|
5700
|
-
function
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
}
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
6305
|
+
var NOME_DO_SERVIDOR = "taskin";
|
|
6306
|
+
var ehObjeto = (valor) => typeof valor === "object" && valor !== null && !Array.isArray(valor);
|
|
6307
|
+
var mesmaEntrada = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
6308
|
+
function mergeMcpConfig(existente, entrada, options = {}) {
|
|
6309
|
+
if (existente === void 0) {
|
|
6310
|
+
return { outcome: "created", config: { mcpServers: { [NOME_DO_SERVIDOR]: entrada } } };
|
|
6311
|
+
}
|
|
6312
|
+
let lido;
|
|
6313
|
+
try {
|
|
6314
|
+
lido = JSON.parse(existente);
|
|
6315
|
+
} catch {
|
|
6316
|
+
return { outcome: "unreadable", reason: "o arquivo n\xE3o \xE9 JSON v\xE1lido" };
|
|
6317
|
+
}
|
|
6318
|
+
if (!ehObjeto(lido)) {
|
|
6319
|
+
return { outcome: "unreadable", reason: "o conte\xFAdo n\xE3o \xE9 um objeto" };
|
|
6320
|
+
}
|
|
6321
|
+
const servidores = lido.mcpServers;
|
|
6322
|
+
if (servidores !== void 0 && !ehObjeto(servidores)) {
|
|
6323
|
+
return { outcome: "unreadable", reason: "`mcpServers` n\xE3o \xE9 um objeto" };
|
|
6324
|
+
}
|
|
6325
|
+
const atuais = ehObjeto(servidores) ? servidores : {};
|
|
6326
|
+
const atual = atuais[NOME_DO_SERVIDOR];
|
|
6327
|
+
if (atual !== void 0) {
|
|
6328
|
+
if (mesmaEntrada(atual, entrada)) {
|
|
6329
|
+
return { outcome: "unchanged" };
|
|
5713
6330
|
}
|
|
5714
|
-
if (
|
|
5715
|
-
return
|
|
5716
|
-
if (criteria.assignee !== void 0 && !casaResponsavel2(task, criteria.assignee))
|
|
5717
|
-
return false;
|
|
5718
|
-
if (criteria.text !== void 0) {
|
|
5719
|
-
const procurado = criteria.text.toLowerCase();
|
|
5720
|
-
const casa = task.id.toLowerCase().includes(procurado) || contem2(task.title, procurado) || contem2(task.status, procurado) || casaResponsavel2(task, procurado);
|
|
5721
|
-
if (!casa)
|
|
5722
|
-
return false;
|
|
6331
|
+
if (!options.overwrite) {
|
|
6332
|
+
return { outcome: "conflict", current: atual };
|
|
5723
6333
|
}
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
return {
|
|
5729
|
-
id: task.id,
|
|
5730
|
-
title: task.title,
|
|
5731
|
-
status: task.status,
|
|
5732
|
-
type: task.type,
|
|
5733
|
-
...task.assignee && { assignee: { id: task.assignee.id, name: task.assignee.name } },
|
|
5734
|
-
...task.order !== void 0 && { priority: task.order },
|
|
5735
|
-
...task.groupId && { groupId: task.groupId },
|
|
5736
|
-
...task.groupName && { groupName: task.groupName },
|
|
5737
|
-
...task.difficulty !== void 0 && { difficulty: task.difficulty }
|
|
6334
|
+
}
|
|
6335
|
+
const config = {
|
|
6336
|
+
...lido,
|
|
6337
|
+
mcpServers: { ...atuais, [NOME_DO_SERVIDOR]: entrada }
|
|
5738
6338
|
};
|
|
6339
|
+
return atual === void 0 ? { outcome: "added", config } : { outcome: "replaced", config };
|
|
5739
6340
|
}
|
|
5740
6341
|
|
|
5741
|
-
//
|
|
5742
|
-
init_esm_shims();
|
|
5743
|
-
|
|
5744
|
-
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/task-manager.js
|
|
5745
|
-
init_esm_shims();
|
|
5746
|
-
|
|
5747
|
-
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/task-manager.types.js
|
|
5748
|
-
init_esm_shims();
|
|
5749
|
-
|
|
5750
|
-
// node_modules/@opentask/taskin-task-server-mcp/node_modules/@opentask/taskin-task-manager/dist/user-registry.types.js
|
|
6342
|
+
// src/lib/mcp-install/package-manager.ts
|
|
5751
6343
|
init_esm_shims();
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
],
|
|
5769
|
-
isError: true
|
|
5770
|
-
};
|
|
5771
|
-
}
|
|
5772
|
-
var TaskMCPServer = class _TaskMCPServer {
|
|
5773
|
-
server;
|
|
5774
|
-
taskManager;
|
|
5775
|
-
config;
|
|
5776
|
-
constructor(config) {
|
|
5777
|
-
this.taskManager = config.taskManager;
|
|
5778
|
-
this.config = {
|
|
5779
|
-
name: "taskin-mcp-server",
|
|
5780
|
-
version: "1.0.0",
|
|
5781
|
-
debug: false,
|
|
5782
|
-
...config,
|
|
5783
|
-
taskManager: config.taskManager
|
|
5784
|
-
};
|
|
5785
|
-
this.server = new Server({
|
|
5786
|
-
name: this.config.name,
|
|
5787
|
-
version: this.config.version
|
|
5788
|
-
}, {
|
|
5789
|
-
capabilities: {
|
|
5790
|
-
tools: {},
|
|
5791
|
-
prompts: {},
|
|
5792
|
-
resources: {}
|
|
5793
|
-
}
|
|
5794
|
-
});
|
|
5795
|
-
this.setupHandlers();
|
|
5796
|
-
}
|
|
5797
|
-
/**
|
|
5798
|
-
* Setup MCP request handlers
|
|
5799
|
-
*/
|
|
5800
|
-
setupHandlers() {
|
|
5801
|
-
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
5802
|
-
const { tools } = this.listTools();
|
|
5803
|
-
return { tools };
|
|
5804
|
-
});
|
|
5805
|
-
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
5806
|
-
const result = await this.callTool({
|
|
5807
|
-
name: request.params.name,
|
|
5808
|
-
arguments: request.params.arguments
|
|
5809
|
-
});
|
|
5810
|
-
return {
|
|
5811
|
-
content: result.content,
|
|
5812
|
-
isError: result.isError
|
|
5813
|
-
};
|
|
5814
|
-
});
|
|
5815
|
-
this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
5816
|
-
const { prompts } = this.listPrompts();
|
|
5817
|
-
return { prompts };
|
|
5818
|
-
});
|
|
5819
|
-
this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
5820
|
-
const result = await this.getPrompt({
|
|
5821
|
-
name: request.params.name,
|
|
5822
|
-
arguments: request.params.arguments
|
|
5823
|
-
});
|
|
5824
|
-
return {
|
|
5825
|
-
messages: result.messages.map((msg) => ({
|
|
5826
|
-
role: msg.role,
|
|
5827
|
-
content: {
|
|
5828
|
-
type: "text",
|
|
5829
|
-
text: msg.content
|
|
5830
|
-
}
|
|
5831
|
-
}))
|
|
5832
|
-
};
|
|
5833
|
-
});
|
|
5834
|
-
this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
5835
|
-
const result = await this.listResources();
|
|
5836
|
-
return { resources: result.resources };
|
|
5837
|
-
});
|
|
5838
|
-
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
5839
|
-
const result = await this.readResource({
|
|
5840
|
-
uri: request.params.uri
|
|
5841
|
-
});
|
|
5842
|
-
return result;
|
|
5843
|
-
});
|
|
6344
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3 } from "fs";
|
|
6345
|
+
import path11 from "path";
|
|
6346
|
+
var POR_LOCKFILE = [
|
|
6347
|
+
["pnpm-lock.yaml", "pnpm"],
|
|
6348
|
+
["yarn.lock", "yarn"],
|
|
6349
|
+
["bun.lockb", "bun"],
|
|
6350
|
+
["package-lock.json", "npm"]
|
|
6351
|
+
];
|
|
6352
|
+
function declarado(raiz) {
|
|
6353
|
+
try {
|
|
6354
|
+
const { packageManager } = JSON.parse(readFileSync3(path11.join(raiz, "package.json"), "utf-8"));
|
|
6355
|
+
if (typeof packageManager !== "string") return void 0;
|
|
6356
|
+
const nome = packageManager.split("@")[0];
|
|
6357
|
+
return POR_LOCKFILE.some(([, gerenciador]) => gerenciador === nome) ? nome : void 0;
|
|
6358
|
+
} catch {
|
|
6359
|
+
return void 0;
|
|
5844
6360
|
}
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
await this.server.connect(transport);
|
|
5852
|
-
this.log("MCP Server connected via stdio");
|
|
5853
|
-
} else {
|
|
5854
|
-
throw new Error(`Transport ${options.transport} not yet implemented`);
|
|
5855
|
-
}
|
|
6361
|
+
}
|
|
6362
|
+
function detectPackageManager2(raiz) {
|
|
6363
|
+
const explicito = declarado(raiz);
|
|
6364
|
+
if (explicito) return explicito;
|
|
6365
|
+
for (const [lockfile, gerenciador] of POR_LOCKFILE) {
|
|
6366
|
+
if (existsSync6(path11.join(raiz, lockfile))) return gerenciador;
|
|
5856
6367
|
}
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
}
|
|
5870
|
-
};
|
|
6368
|
+
return "npm";
|
|
6369
|
+
}
|
|
6370
|
+
function mcpCommandFor(manager) {
|
|
6371
|
+
switch (manager) {
|
|
6372
|
+
case "pnpm":
|
|
6373
|
+
return { command: "pnpm", args: ["exec", "taskin", "mcp-server"] };
|
|
6374
|
+
case "yarn":
|
|
6375
|
+
return { command: "yarn", args: ["taskin", "mcp-server"] };
|
|
6376
|
+
case "bun":
|
|
6377
|
+
return { command: "bunx", args: ["taskin", "mcp-server"] };
|
|
6378
|
+
case "npm":
|
|
6379
|
+
return { command: "npx", args: ["taskin", "mcp-server"] };
|
|
5871
6380
|
}
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
{
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
type: "string",
|
|
5915
|
-
description: "The unique identifier of the task (UUID)"
|
|
5916
|
-
}
|
|
5917
|
-
},
|
|
5918
|
-
required: ["taskId"]
|
|
6381
|
+
}
|
|
6382
|
+
|
|
6383
|
+
// src/lib/mcp-install/probe-server.ts
|
|
6384
|
+
init_esm_shims();
|
|
6385
|
+
import { spawn } from "child_process";
|
|
6386
|
+
var LIMITE_MS = 3e4;
|
|
6387
|
+
var requisicao = (id, method, params) => `${JSON.stringify({ jsonrpc: "2.0", id, method, ...params !== void 0 && { params } })}
|
|
6388
|
+
`;
|
|
6389
|
+
function probeMcpServer(entrada, cwd, esperadas = []) {
|
|
6390
|
+
return new Promise((resolve) => {
|
|
6391
|
+
const filho = spawn(entrada.command, [...entrada.args], {
|
|
6392
|
+
cwd,
|
|
6393
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
6394
|
+
env: { ...process.env }
|
|
6395
|
+
});
|
|
6396
|
+
let saida = "";
|
|
6397
|
+
let erro = "";
|
|
6398
|
+
let respondido = false;
|
|
6399
|
+
const encerrar = (resultado) => {
|
|
6400
|
+
if (respondido) return;
|
|
6401
|
+
respondido = true;
|
|
6402
|
+
clearTimeout(cronometro);
|
|
6403
|
+
filho.kill();
|
|
6404
|
+
resolve(resultado);
|
|
6405
|
+
};
|
|
6406
|
+
const cronometro = setTimeout(
|
|
6407
|
+
() => encerrar({ ok: false, reason: `o servidor n\xE3o respondeu em ${LIMITE_MS / 1e3}s`, stderr: erro.trim() }),
|
|
6408
|
+
LIMITE_MS
|
|
6409
|
+
);
|
|
6410
|
+
filho.on("error", (e) => encerrar({ ok: false, reason: e.message, stderr: erro.trim() }));
|
|
6411
|
+
filho.stderr.on("data", (pedaco) => {
|
|
6412
|
+
erro += pedaco.toString();
|
|
6413
|
+
});
|
|
6414
|
+
filho.stdout.on("data", (pedaco) => {
|
|
6415
|
+
saida += pedaco.toString();
|
|
6416
|
+
for (const linha2 of saida.split("\n")) {
|
|
6417
|
+
if (!linha2.trim()) continue;
|
|
6418
|
+
let mensagem;
|
|
6419
|
+
try {
|
|
6420
|
+
mensagem = JSON.parse(linha2);
|
|
6421
|
+
} catch {
|
|
6422
|
+
continue;
|
|
5919
6423
|
}
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
/**
|
|
5925
|
-
* Call a tool
|
|
5926
|
-
*/
|
|
5927
|
-
async callTool(params) {
|
|
5928
|
-
try {
|
|
5929
|
-
this.log(`Calling tool: ${params.name}`, params.arguments);
|
|
5930
|
-
switch (params.name) {
|
|
5931
|
-
case "list_tasks":
|
|
5932
|
-
return await this.handleListTasks(params.arguments ?? {});
|
|
5933
|
-
case "start_task": {
|
|
5934
|
-
const taskId = readTaskId(params.arguments?.taskId);
|
|
5935
|
-
return taskId ? await this.handleStartTask(taskId) : invalidTaskId(params.arguments?.taskId);
|
|
6424
|
+
if (mensagem.id !== 2) continue;
|
|
6425
|
+
if (mensagem.error) {
|
|
6426
|
+
encerrar({ ok: false, reason: `recusou tools/list: ${mensagem.error.message}`, stderr: erro.trim() });
|
|
6427
|
+
return;
|
|
5936
6428
|
}
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
6429
|
+
const ferramentas = (mensagem.result?.tools ?? []).map((t) => t.name);
|
|
6430
|
+
if (ferramentas.length === 0) {
|
|
6431
|
+
encerrar({ ok: false, reason: "subiu, mas n\xE3o anuncia ferramenta nenhuma", stderr: erro.trim() });
|
|
6432
|
+
return;
|
|
5940
6433
|
}
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
}
|
|
5948
|
-
],
|
|
5949
|
-
isError: true
|
|
5950
|
-
};
|
|
5951
|
-
}
|
|
5952
|
-
} catch (error2) {
|
|
5953
|
-
this.log("Tool call error:", error2);
|
|
5954
|
-
return {
|
|
5955
|
-
content: [
|
|
5956
|
-
{
|
|
5957
|
-
type: "text",
|
|
5958
|
-
text: error2 instanceof Error ? error2.message : String(error2)
|
|
6434
|
+
const faltando = esperadas.filter((nome) => !ferramentas.includes(nome));
|
|
6435
|
+
encerrar(
|
|
6436
|
+
faltando.length === 0 ? { ok: true, tools: ferramentas } : {
|
|
6437
|
+
ok: false,
|
|
6438
|
+
reason: `respondeu, mas sem ${faltando.join(", ")} \u2014 o comando provavelmente alcan\xE7a outra instala\xE7\xE3o do taskin (anunciou: ${ferramentas.join(", ")})`,
|
|
6439
|
+
stderr: erro.trim()
|
|
5959
6440
|
}
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
}
|
|
5963
|
-
}
|
|
6441
|
+
);
|
|
6442
|
+
return;
|
|
6443
|
+
}
|
|
6444
|
+
});
|
|
6445
|
+
filho.on(
|
|
6446
|
+
"close",
|
|
6447
|
+
(code) => encerrar({ ok: false, reason: `encerrou com c\xF3digo ${code} sem responder`, stderr: erro.trim() })
|
|
6448
|
+
);
|
|
6449
|
+
filho.stdin.write(
|
|
6450
|
+
requisicao(1, "initialize", {
|
|
6451
|
+
protocolVersion: "2024-11-05",
|
|
6452
|
+
capabilities: {},
|
|
6453
|
+
clientInfo: { name: "taskin-install", version: "1" }
|
|
6454
|
+
})
|
|
6455
|
+
);
|
|
6456
|
+
filho.stdin.write(requisicao(2, "tools/list"));
|
|
6457
|
+
});
|
|
6458
|
+
}
|
|
6459
|
+
|
|
6460
|
+
// src/lib/mcp-install/resolve-invocation.ts
|
|
6461
|
+
init_esm_shims();
|
|
6462
|
+
import { existsSync as existsSync7, readFileSync as readFileSync4 } from "fs";
|
|
6463
|
+
import path12 from "path";
|
|
6464
|
+
function viaScript(manager) {
|
|
6465
|
+
if (manager === "npm") {
|
|
6466
|
+
return { command: "npm", args: ["run", "taskin", "--", "mcp-server"] };
|
|
5964
6467
|
}
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
const
|
|
5970
|
-
return
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
type: "text",
|
|
5974
|
-
text: JSON.stringify({
|
|
5975
|
-
success: true,
|
|
5976
|
-
message: `Task ${taskId} started successfully`,
|
|
5977
|
-
task: {
|
|
5978
|
-
id: task.id,
|
|
5979
|
-
title: task.title,
|
|
5980
|
-
status: task.status,
|
|
5981
|
-
type: task.type
|
|
5982
|
-
}
|
|
5983
|
-
}, null, 2)
|
|
5984
|
-
}
|
|
5985
|
-
]
|
|
5986
|
-
};
|
|
6468
|
+
return { command: manager, args: ["taskin", "mcp-server"] };
|
|
6469
|
+
}
|
|
6470
|
+
function temScriptTaskin(raiz) {
|
|
6471
|
+
try {
|
|
6472
|
+
const { scripts } = JSON.parse(readFileSync4(path12.join(raiz, "package.json"), "utf-8"));
|
|
6473
|
+
return typeof scripts?.taskin === "string";
|
|
6474
|
+
} catch {
|
|
6475
|
+
return false;
|
|
5987
6476
|
}
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
const task = await this.taskManager.finishTask(taskId);
|
|
5993
|
-
return {
|
|
5994
|
-
content: [
|
|
5995
|
-
{
|
|
5996
|
-
type: "text",
|
|
5997
|
-
text: JSON.stringify({
|
|
5998
|
-
success: true,
|
|
5999
|
-
message: `Task ${taskId} finished successfully`,
|
|
6000
|
-
task: {
|
|
6001
|
-
id: task.id,
|
|
6002
|
-
title: task.title,
|
|
6003
|
-
status: task.status,
|
|
6004
|
-
type: task.type
|
|
6005
|
-
}
|
|
6006
|
-
}, null, 2)
|
|
6007
|
-
}
|
|
6008
|
-
]
|
|
6009
|
-
};
|
|
6477
|
+
}
|
|
6478
|
+
function resolveInvocation(raiz, manager) {
|
|
6479
|
+
if (existsSync7(path12.join(raiz, "node_modules", ".bin", "taskin"))) {
|
|
6480
|
+
return mcpCommandFor(manager);
|
|
6010
6481
|
}
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
*/
|
|
6014
|
-
listPrompts() {
|
|
6015
|
-
const prompts = [
|
|
6016
|
-
{
|
|
6017
|
-
name: "start-task-workflow",
|
|
6018
|
-
description: "Guide the user through starting work on a task with git branch creation",
|
|
6019
|
-
arguments: [
|
|
6020
|
-
{
|
|
6021
|
-
name: "taskId",
|
|
6022
|
-
description: "The task ID to start",
|
|
6023
|
-
required: true
|
|
6024
|
-
}
|
|
6025
|
-
]
|
|
6026
|
-
},
|
|
6027
|
-
{
|
|
6028
|
-
name: "finish-task-workflow",
|
|
6029
|
-
description: "Guide the user through completing a task with commit and PR creation",
|
|
6030
|
-
arguments: [
|
|
6031
|
-
{
|
|
6032
|
-
name: "taskId",
|
|
6033
|
-
description: "The task ID to finish",
|
|
6034
|
-
required: true
|
|
6035
|
-
}
|
|
6036
|
-
]
|
|
6037
|
-
},
|
|
6038
|
-
{
|
|
6039
|
-
name: "task-summary",
|
|
6040
|
-
description: "Generate a summary of a task for documentation or reports",
|
|
6041
|
-
arguments: [
|
|
6042
|
-
{
|
|
6043
|
-
name: "taskId",
|
|
6044
|
-
description: "The task ID to summarize",
|
|
6045
|
-
required: true
|
|
6046
|
-
}
|
|
6047
|
-
]
|
|
6048
|
-
}
|
|
6049
|
-
];
|
|
6050
|
-
return { prompts };
|
|
6482
|
+
if (temScriptTaskin(raiz)) {
|
|
6483
|
+
return viaScript(manager);
|
|
6051
6484
|
}
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
*/
|
|
6055
|
-
async getPrompt(params) {
|
|
6056
|
-
this.log(`Getting prompt: ${params.name}`, params.arguments);
|
|
6057
|
-
switch (params.name) {
|
|
6058
|
-
case "start-task-workflow":
|
|
6059
|
-
return {
|
|
6060
|
-
description: "Workflow for starting a task",
|
|
6061
|
-
messages: [
|
|
6062
|
-
{
|
|
6063
|
-
role: "user",
|
|
6064
|
-
content: {
|
|
6065
|
-
type: "text",
|
|
6066
|
-
text: `I want to start working on task ${params.arguments?.taskId}. Can you help me set everything up?`
|
|
6067
|
-
}
|
|
6068
|
-
},
|
|
6069
|
-
{
|
|
6070
|
-
role: "assistant",
|
|
6071
|
-
content: {
|
|
6072
|
-
type: "text",
|
|
6073
|
-
text: `I'll help you start working on task ${params.arguments?.taskId}. Here's what I'll do:
|
|
6074
|
-
|
|
6075
|
-
1. Mark the task as "in-progress"
|
|
6076
|
-
2. Create a git branch based on the task type and ID
|
|
6077
|
-
3. Ensure your working directory is clean
|
|
6078
|
-
4. Switch to the new branch
|
|
6079
|
-
|
|
6080
|
-
Let me start by marking the task as in-progress using the start_task tool.`
|
|
6081
|
-
}
|
|
6082
|
-
}
|
|
6083
|
-
]
|
|
6084
|
-
};
|
|
6085
|
-
case "finish-task-workflow":
|
|
6086
|
-
return {
|
|
6087
|
-
description: "Workflow for finishing a task",
|
|
6088
|
-
messages: [
|
|
6089
|
-
{
|
|
6090
|
-
role: "user",
|
|
6091
|
-
content: {
|
|
6092
|
-
type: "text",
|
|
6093
|
-
text: `I've completed task ${params.arguments?.taskId}. What should I do next?`
|
|
6094
|
-
}
|
|
6095
|
-
},
|
|
6096
|
-
{
|
|
6097
|
-
role: "assistant",
|
|
6098
|
-
content: {
|
|
6099
|
-
type: "text",
|
|
6100
|
-
text: `Great! Let me help you finish task ${params.arguments?.taskId}. Here's the workflow:
|
|
6485
|
+
return mcpCommandFor(manager);
|
|
6486
|
+
}
|
|
6101
6487
|
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
3. Push your branch to remote
|
|
6105
|
-
4. Create a pull request
|
|
6488
|
+
// src/lib/project-root/index.ts
|
|
6489
|
+
init_esm_shims();
|
|
6106
6490
|
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
role: "user",
|
|
6118
|
-
content: {
|
|
6119
|
-
type: "text",
|
|
6120
|
-
text: `Can you provide a summary of task ${params.arguments?.taskId}?`
|
|
6121
|
-
}
|
|
6122
|
-
},
|
|
6123
|
-
{
|
|
6124
|
-
role: "assistant",
|
|
6125
|
-
content: {
|
|
6126
|
-
type: "text",
|
|
6127
|
-
text: `I'll generate a comprehensive summary of task ${params.arguments?.taskId} including its current status, description, and any relevant metadata.`
|
|
6128
|
-
}
|
|
6129
|
-
}
|
|
6130
|
-
]
|
|
6131
|
-
};
|
|
6132
|
-
default:
|
|
6133
|
-
throw new Error(`Unknown prompt: ${params.name}`);
|
|
6134
|
-
}
|
|
6491
|
+
// src/lib/project-root/project-root.ts
|
|
6492
|
+
init_esm_shims();
|
|
6493
|
+
import { statSync } from "fs";
|
|
6494
|
+
import path13 from "path";
|
|
6495
|
+
var MARCADOR = ".taskin.json";
|
|
6496
|
+
function temMarcador(diretorio) {
|
|
6497
|
+
try {
|
|
6498
|
+
return statSync(path13.join(diretorio, MARCADOR)).isFile();
|
|
6499
|
+
} catch {
|
|
6500
|
+
return false;
|
|
6135
6501
|
}
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
const tasks = await this.taskManager.getAllTasks();
|
|
6145
|
-
return filterTasks2(tasks, criteria).map(summarizeTask2);
|
|
6502
|
+
}
|
|
6503
|
+
function findProjectRoot(startDir = process.cwd()) {
|
|
6504
|
+
let atual = path13.resolve(startDir);
|
|
6505
|
+
while (true) {
|
|
6506
|
+
if (temMarcador(atual)) return atual;
|
|
6507
|
+
const acima = path13.dirname(atual);
|
|
6508
|
+
if (acima === atual) return void 0;
|
|
6509
|
+
atual = acima;
|
|
6146
6510
|
}
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
};
|
|
6511
|
+
}
|
|
6512
|
+
|
|
6513
|
+
// src/commands/mcp-install.ts
|
|
6514
|
+
var ARQUIVO = ".mcp.json";
|
|
6515
|
+
function lerSeExistir(caminho) {
|
|
6516
|
+
try {
|
|
6517
|
+
return readFileSync5(caminho, "utf-8");
|
|
6518
|
+
} catch {
|
|
6519
|
+
return void 0;
|
|
6157
6520
|
}
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6521
|
+
}
|
|
6522
|
+
var mcpInstallCommand = defineCommand({
|
|
6523
|
+
name: "mcp-install",
|
|
6524
|
+
description: "\u{1F50C} Register the Taskin MCP server in this project's .mcp.json",
|
|
6525
|
+
options: [
|
|
6526
|
+
{
|
|
6527
|
+
flags: "-f, --force",
|
|
6528
|
+
description: "Replace an existing taskin entry that differs"
|
|
6529
|
+
},
|
|
6530
|
+
{
|
|
6531
|
+
flags: "--no-probe",
|
|
6532
|
+
description: "Skip starting the server to verify the entry works"
|
|
6533
|
+
}
|
|
6534
|
+
],
|
|
6535
|
+
handler: async (options) => {
|
|
6536
|
+
await instalar(options);
|
|
6164
6537
|
}
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
{
|
|
6172
|
-
uri: "taskin://tasks",
|
|
6173
|
-
name: "All Tasks",
|
|
6174
|
-
description: "Access to all tasks in the system",
|
|
6175
|
-
mimeType: "application/json"
|
|
6176
|
-
}
|
|
6177
|
-
]
|
|
6178
|
-
};
|
|
6538
|
+
});
|
|
6539
|
+
async function instalar(options) {
|
|
6540
|
+
const raiz = findProjectRoot();
|
|
6541
|
+
if (!raiz) {
|
|
6542
|
+
error('No .taskin.json found here or in any parent directory. Run "taskin init" first.');
|
|
6543
|
+
process.exit(1);
|
|
6179
6544
|
}
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6545
|
+
const caminho = path14.join(raiz, ARQUIVO);
|
|
6546
|
+
const manager = detectPackageManager2(raiz);
|
|
6547
|
+
const entrada = resolveInvocation(raiz, manager);
|
|
6548
|
+
info(`Project root: ${raiz}`);
|
|
6549
|
+
info(`Package manager: ${manager} \u2014 the entry will run \`${[entrada.command, ...entrada.args].join(" ")}\``);
|
|
6550
|
+
const resultado = mergeMcpConfig(lerSeExistir(caminho), entrada, { overwrite: options.force === true });
|
|
6551
|
+
switch (resultado.outcome) {
|
|
6552
|
+
case "unreadable":
|
|
6553
|
+
error(`${ARQUIVO} exists but ${resultado.reason}. Nothing was written \u2014 fix or remove it first.`);
|
|
6554
|
+
process.exit(1);
|
|
6555
|
+
return;
|
|
6556
|
+
case "conflict":
|
|
6557
|
+
warning(`${ARQUIVO} already has a "${NOME_DO_SERVIDOR}" entry that differs:`);
|
|
6558
|
+
console.log(` current: ${JSON.stringify(resultado.current)}`);
|
|
6559
|
+
console.log(` new: ${JSON.stringify(entrada)}`);
|
|
6560
|
+
info("Run again with --force to replace it.");
|
|
6561
|
+
process.exit(1);
|
|
6562
|
+
return;
|
|
6563
|
+
case "unchanged":
|
|
6564
|
+
success(`${ARQUIVO} already registers the Taskin MCP server. Nothing to do.`);
|
|
6565
|
+
break;
|
|
6566
|
+
default:
|
|
6567
|
+
writeFileSync3(caminho, `${JSON.stringify(resultado.config, null, 2)}
|
|
6568
|
+
`, "utf-8");
|
|
6569
|
+
success(
|
|
6570
|
+
resultado.outcome === "created" ? `Created ${ARQUIVO}` : `${resultado.outcome === "added" ? "Added" : "Replaced"} the "${NOME_DO_SERVIDOR}" entry in ${ARQUIVO}`
|
|
6571
|
+
);
|
|
6199
6572
|
}
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6573
|
+
if (options.probe === false) {
|
|
6574
|
+
info("Skipped the check. Run without --no-probe to verify the server actually starts.");
|
|
6575
|
+
return;
|
|
6576
|
+
}
|
|
6577
|
+
info("Starting the server to check the entry actually works...");
|
|
6578
|
+
const { TaskMCPServer: TaskMCPServer2 } = await Promise.resolve().then(() => (init_dist2(), dist_exports));
|
|
6579
|
+
const esperadas = new TaskMCPServer2({ taskManager: {} }).listTools().tools.map((t) => t.name);
|
|
6580
|
+
const sonda = await probeMcpServer(entrada, raiz, esperadas);
|
|
6581
|
+
if (!sonda.ok) {
|
|
6582
|
+
error(`The entry was written, but the server did not answer: ${sonda.reason}`);
|
|
6583
|
+
if (sonda.stderr) {
|
|
6584
|
+
console.log(sonda.stderr);
|
|
6206
6585
|
}
|
|
6586
|
+
process.exit(1);
|
|
6587
|
+
return;
|
|
6207
6588
|
}
|
|
6208
|
-
};
|
|
6209
|
-
|
|
6210
|
-
// node_modules/@opentask/taskin-task-server-mcp/dist/task-server-mcp.types.js
|
|
6211
|
-
init_esm_shims();
|
|
6589
|
+
success(`The server answered with ${sonda.tools.length} tool(s): ${sonda.tools.join(", ")}`);
|
|
6590
|
+
}
|
|
6212
6591
|
|
|
6213
6592
|
// src/commands/mcp-server.ts
|
|
6593
|
+
init_esm_shims();
|
|
6594
|
+
init_dist2();
|
|
6214
6595
|
import chalk6 from "chalk";
|
|
6596
|
+
var linha = (texto = "") => process.stderr.write(`${texto}
|
|
6597
|
+
`);
|
|
6598
|
+
var aviso = (mensagem) => linha(colors.info(`\u2139 ${mensagem}`));
|
|
6599
|
+
var feito = (mensagem) => linha(colors.success(`\u2713 ${mensagem}`));
|
|
6600
|
+
var falha = (mensagem) => linha(colors.error(`\u2717 ${mensagem}`));
|
|
6601
|
+
function cabecalho(titulo, icone) {
|
|
6602
|
+
linha();
|
|
6603
|
+
linha(colors.highlight("=".repeat(60)));
|
|
6604
|
+
linha(colors.highlight(`${icone} ${titulo}`));
|
|
6605
|
+
linha(colors.highlight("=".repeat(60)));
|
|
6606
|
+
linha();
|
|
6607
|
+
}
|
|
6215
6608
|
var mcpServerCommand = defineCommand({
|
|
6216
6609
|
name: "mcp-server",
|
|
6217
6610
|
description: "\u{1F916} Start Model Context Protocol server for LLM integration",
|
|
6218
6611
|
alias: "mcp",
|
|
6219
6612
|
options: [
|
|
6220
|
-
{
|
|
6221
|
-
flags: "-t, --transport <type>",
|
|
6222
|
-
description: "Transport type (stdio or sse)",
|
|
6223
|
-
defaultValue: "stdio"
|
|
6224
|
-
},
|
|
6225
6613
|
{
|
|
6226
6614
|
flags: "-d, --debug",
|
|
6227
6615
|
description: "Enable debug logging"
|
|
@@ -6233,45 +6621,40 @@ var mcpServerCommand = defineCommand({
|
|
|
6233
6621
|
});
|
|
6234
6622
|
async function startMCPServer(options) {
|
|
6235
6623
|
requireTaskinProject();
|
|
6236
|
-
const transport = options.transport || "stdio";
|
|
6237
6624
|
const debug = options.debug || false;
|
|
6238
|
-
|
|
6625
|
+
cabecalho("Starting MCP Server", "\u{1F916}");
|
|
6239
6626
|
try {
|
|
6240
|
-
|
|
6627
|
+
aviso("Initializing task manager...");
|
|
6241
6628
|
const { provider } = await resolveTaskProvider();
|
|
6242
6629
|
const manager = new TaskManager(provider);
|
|
6243
|
-
info(`Creating MCP server with ${transport} transport...`);
|
|
6244
6630
|
const mcpServer = new TaskMCPServer({
|
|
6245
6631
|
taskManager: manager,
|
|
6246
6632
|
name: "taskin-mcp-server",
|
|
6247
6633
|
version: "1.0.0",
|
|
6248
6634
|
debug
|
|
6249
6635
|
});
|
|
6250
|
-
|
|
6251
|
-
await mcpServer.connect({ transport });
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
const cleanup = async () => {
|
|
6273
|
-
info("\nShutting down MCP server...");
|
|
6274
|
-
success("Server stopped");
|
|
6636
|
+
aviso("Starting MCP server over stdio...");
|
|
6637
|
+
await mcpServer.connect({ transport: "stdio" });
|
|
6638
|
+
feito("MCP server started successfully");
|
|
6639
|
+
linha();
|
|
6640
|
+
aviso(` ${chalk6.bold("Debug")}: ${chalk6.cyan(debug ? "enabled" : "disabled")}`);
|
|
6641
|
+
linha();
|
|
6642
|
+
aviso(chalk6.bold("Available Tools:"));
|
|
6643
|
+
for (const ferramenta of mcpServer.listTools().tools) {
|
|
6644
|
+
aviso(` \u2022 ${chalk6.green(ferramenta.name)} - ${ferramenta.description}`);
|
|
6645
|
+
}
|
|
6646
|
+
linha();
|
|
6647
|
+
aviso(chalk6.bold("Available Prompts:"));
|
|
6648
|
+
for (const prompt of mcpServer.listPrompts().prompts) {
|
|
6649
|
+
aviso(` \u2022 ${chalk6.green(prompt.name)} - ${prompt.description}`);
|
|
6650
|
+
}
|
|
6651
|
+
linha();
|
|
6652
|
+
aviso(`Press ${chalk6.bold("Ctrl+C")} to stop the server`);
|
|
6653
|
+
linha();
|
|
6654
|
+
const cleanup = () => {
|
|
6655
|
+
linha();
|
|
6656
|
+
aviso("Shutting down MCP server...");
|
|
6657
|
+
feito("Server stopped");
|
|
6275
6658
|
process.exit(0);
|
|
6276
6659
|
};
|
|
6277
6660
|
process.on("SIGINT", cleanup);
|
|
@@ -6279,9 +6662,9 @@ async function startMCPServer(options) {
|
|
|
6279
6662
|
await new Promise(() => {
|
|
6280
6663
|
});
|
|
6281
6664
|
} catch (err) {
|
|
6282
|
-
|
|
6665
|
+
falha("Failed to start MCP server");
|
|
6283
6666
|
if (err instanceof Error) {
|
|
6284
|
-
|
|
6667
|
+
falha(err.message);
|
|
6285
6668
|
if (debug) {
|
|
6286
6669
|
console.error(err.stack);
|
|
6287
6670
|
}
|
|
@@ -6316,6 +6699,10 @@ var createCommand = defineCommand({
|
|
|
6316
6699
|
{
|
|
6317
6700
|
flags: "-u, --user <user>",
|
|
6318
6701
|
description: "Assignee user"
|
|
6702
|
+
},
|
|
6703
|
+
{
|
|
6704
|
+
flags: "--no-skip-ci",
|
|
6705
|
+
description: "Write the status commit without the CI-skip tag"
|
|
6319
6706
|
}
|
|
6320
6707
|
],
|
|
6321
6708
|
handler: async (options) => {
|
|
@@ -6391,11 +6778,12 @@ async function createTask(options, gitService) {
|
|
|
6391
6778
|
await userRegistry.ensureCurrentUser();
|
|
6392
6779
|
const configManager = new ConfigManager(monorepoRoot);
|
|
6393
6780
|
const behavior = configManager.getAutomationBehavior();
|
|
6781
|
+
const ciSkipTag = resolveCiSkipTag(behavior.ciSkipTag, options.skipCi);
|
|
6394
6782
|
const autoSyncActive = behavior.autoSync && !!behavior.defaultBranch;
|
|
6395
6783
|
if (behavior.autoSync && !behavior.defaultBranch) {
|
|
6396
6784
|
warning("autoSync is enabled but no defaultBranch is configured. Nothing will be synced.");
|
|
6397
6785
|
}
|
|
6398
|
-
const git = gitService ?? new GitService(process.cwd(), { ciSkipTag
|
|
6786
|
+
const git = gitService ?? new GitService(process.cwd(), { ciSkipTag });
|
|
6399
6787
|
if (autoSyncActive) {
|
|
6400
6788
|
try {
|
|
6401
6789
|
await syncBeforeCreate(git, {
|
|
@@ -6428,7 +6816,7 @@ async function createTask(options, gitService) {
|
|
|
6428
6816
|
taskId,
|
|
6429
6817
|
title: options.title,
|
|
6430
6818
|
defaultBranch: behavior.defaultBranch,
|
|
6431
|
-
ciSkipTag
|
|
6819
|
+
ciSkipTag
|
|
6432
6820
|
});
|
|
6433
6821
|
} catch (pushError) {
|
|
6434
6822
|
error(
|
|
@@ -6750,6 +7138,10 @@ var reviewCommand = defineCommand({
|
|
|
6750
7138
|
{
|
|
6751
7139
|
flags: "--no-sound",
|
|
6752
7140
|
description: "Disable review sound"
|
|
7141
|
+
},
|
|
7142
|
+
{
|
|
7143
|
+
flags: "--no-skip-ci",
|
|
7144
|
+
description: "Write the status commit without the CI-skip tag"
|
|
6753
7145
|
}
|
|
6754
7146
|
],
|
|
6755
7147
|
handler: async (taskId, options) => {
|
|
@@ -6781,6 +7173,7 @@ async function reviewTask(taskId, options) {
|
|
|
6781
7173
|
const hookSettings = configManager.getHookSettings();
|
|
6782
7174
|
const reviewHooks = configManager.getCommandHooks("review");
|
|
6783
7175
|
const behavior = configManager.getAutomationBehavior();
|
|
7176
|
+
const ciSkipTag = resolveCiSkipTag(behavior.ciSkipTag, options.skipCi);
|
|
6784
7177
|
const hookRunner = new HookRunner();
|
|
6785
7178
|
const hookContext = {
|
|
6786
7179
|
taskId: normalizedId,
|
|
@@ -6874,10 +7267,7 @@ async function reviewTask(taskId, options) {
|
|
|
6874
7267
|
success(`Task ${updatedTask.id} status changed to: ${updatedTask.status}`);
|
|
6875
7268
|
if (behavior.autoCommitStatusChange) {
|
|
6876
7269
|
try {
|
|
6877
|
-
const message = appendCiSkipTag(
|
|
6878
|
-
`docs(TASKS): task-${normalizedId} - mark as ready for review`,
|
|
6879
|
-
behavior.ciSkipTag
|
|
6880
|
-
);
|
|
7270
|
+
const message = appendCiSkipTag(`docs(TASKS): task-${normalizedId} - mark as ready for review`, ciSkipTag);
|
|
6881
7271
|
execSync9(`git add TASKS/task-${normalizedId}-*.md && git commit -m "${message}"`, {
|
|
6882
7272
|
cwd: monorepoRoot,
|
|
6883
7273
|
stdio: "ignore"
|
|
@@ -6950,13 +7340,17 @@ var startCommand = defineCommand({
|
|
|
6950
7340
|
{
|
|
6951
7341
|
flags: "--dry-run",
|
|
6952
7342
|
description: "Show what would be executed without running"
|
|
7343
|
+
},
|
|
7344
|
+
{
|
|
7345
|
+
flags: "--no-skip-ci",
|
|
7346
|
+
description: "Write the status commit without the CI-skip tag"
|
|
6953
7347
|
}
|
|
6954
7348
|
],
|
|
6955
7349
|
handler: async (taskId, options) => {
|
|
6956
7350
|
await startTask(taskId, options);
|
|
6957
7351
|
}
|
|
6958
7352
|
});
|
|
6959
|
-
async function startTask(taskId,
|
|
7353
|
+
async function startTask(taskId, options, gitService) {
|
|
6960
7354
|
requireTaskinProject();
|
|
6961
7355
|
printHeader(`Starting Task ${taskId}`, "\u{1F680}");
|
|
6962
7356
|
const normalizedId = normalizeTaskId(taskId);
|
|
@@ -6976,12 +7370,13 @@ async function startTask(taskId, _options, gitService) {
|
|
|
6976
7370
|
info(`Current status: ${task.status}`);
|
|
6977
7371
|
const configManager = new ConfigManager(monorepoRoot);
|
|
6978
7372
|
const behavior = configManager.getAutomationBehavior();
|
|
7373
|
+
const ciSkipTag = resolveCiSkipTag(behavior.ciSkipTag, options.skipCi);
|
|
6979
7374
|
const statusCommitMessage = buildTaskStatusCommitMessage({
|
|
6980
7375
|
taskId: normalizedId,
|
|
6981
7376
|
status: "in-progress",
|
|
6982
|
-
ciSkipTag
|
|
7377
|
+
ciSkipTag
|
|
6983
7378
|
});
|
|
6984
|
-
if (
|
|
7379
|
+
if (options.dryRun) {
|
|
6985
7380
|
console.log();
|
|
6986
7381
|
info("\u{1F50D} Dry run mode - showing what would be executed:");
|
|
6987
7382
|
console.log();
|
|
@@ -7011,7 +7406,7 @@ async function startTask(taskId, _options, gitService) {
|
|
|
7011
7406
|
const updatedTask = await taskManager.startTask(task.id);
|
|
7012
7407
|
success(`Task ${updatedTask.id} started successfully!`);
|
|
7013
7408
|
success(`Status changed to: ${updatedTask.status}`);
|
|
7014
|
-
const git = gitService ?? new GitService(process.cwd(), { ciSkipTag
|
|
7409
|
+
const git = gitService ?? new GitService(process.cwd(), { ciSkipTag });
|
|
7015
7410
|
if (behavior.autoCommitStatusChange) {
|
|
7016
7411
|
const committed = await git.commitTaskStatusChangeOnBranch(normalizedId, "in-progress", behavior.defaultBranch);
|
|
7017
7412
|
if (committed) {
|
|
@@ -7037,7 +7432,7 @@ async function startTask(taskId, _options, gitService) {
|
|
|
7037
7432
|
}
|
|
7038
7433
|
console.log();
|
|
7039
7434
|
await sendTaskNotification(configManager, "task:start", normalizedId, task.title);
|
|
7040
|
-
if (
|
|
7435
|
+
if (options.sound !== false) {
|
|
7041
7436
|
playSound("start");
|
|
7042
7437
|
}
|
|
7043
7438
|
}
|
|
@@ -7047,7 +7442,7 @@ init_esm_shims();
|
|
|
7047
7442
|
init_src3();
|
|
7048
7443
|
init_src();
|
|
7049
7444
|
import chalk7 from "chalk";
|
|
7050
|
-
import
|
|
7445
|
+
import path15 from "path";
|
|
7051
7446
|
var statsCommand = defineCommand({
|
|
7052
7447
|
name: "stats",
|
|
7053
7448
|
description: "\u{1F4CA} Show user/team metrics and statistics",
|
|
@@ -7079,7 +7474,7 @@ var statsCommand = defineCommand({
|
|
|
7079
7474
|
});
|
|
7080
7475
|
async function showStats(options) {
|
|
7081
7476
|
requireTaskinProject();
|
|
7082
|
-
const tasksDir =
|
|
7477
|
+
const tasksDir = path15.join(process.cwd(), "TASKS");
|
|
7083
7478
|
const { userRegistry } = await resolveTaskProvider();
|
|
7084
7479
|
const gitAnalyzer = new GitAnalyzer(process.cwd());
|
|
7085
7480
|
const metricsAdapter = new FileSystemMetricsAdapter(tasksDir, userRegistry, gitAnalyzer);
|
|
@@ -7251,6 +7646,7 @@ var EXEMPLOS = {
|
|
|
7251
7646
|
export: ["taskin export", "taskin export --format json"],
|
|
7252
7647
|
lint: ["taskin lint", "taskin lint --fix", "taskin lint --fix --metadata-style=list"],
|
|
7253
7648
|
dashboard: ["taskin dashboard", "taskin dashboard --port 3000", "taskin dashboard --filter-open"],
|
|
7649
|
+
"mcp-install": ["taskin mcp-install", "taskin mcp-install --force", "taskin mcp-install --no-probe"],
|
|
7254
7650
|
"mcp-server": ["taskin mcp-server", "taskin mcp"],
|
|
7255
7651
|
notify: ["taskin notify --event task:done --task 001"]
|
|
7256
7652
|
};
|
|
@@ -7334,7 +7730,7 @@ function showCustomHelp(program2) {
|
|
|
7334
7730
|
|
|
7335
7731
|
// src/version.ts
|
|
7336
7732
|
init_esm_shims();
|
|
7337
|
-
import { readFileSync as
|
|
7733
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
7338
7734
|
import { dirname, join as join4 } from "path";
|
|
7339
7735
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7340
7736
|
var __filename3 = fileURLToPath3(import.meta.url);
|
|
@@ -7342,7 +7738,7 @@ var __dirname3 = dirname(__filename3);
|
|
|
7342
7738
|
function getVersion() {
|
|
7343
7739
|
try {
|
|
7344
7740
|
const packageJsonPath = join4(__dirname3, "../package.json");
|
|
7345
|
-
const packageJson = JSON.parse(
|
|
7741
|
+
const packageJson = JSON.parse(readFileSync6(packageJsonPath, "utf-8"));
|
|
7346
7742
|
return packageJson.version;
|
|
7347
7743
|
} catch {
|
|
7348
7744
|
return "0.0.0";
|
|
@@ -7715,6 +8111,7 @@ configCommand(program);
|
|
|
7715
8111
|
registerExportCommand(program);
|
|
7716
8112
|
lintCommand(program);
|
|
7717
8113
|
dashboardCommand(program);
|
|
8114
|
+
mcpInstallCommand(program);
|
|
7718
8115
|
mcpServerCommand(program);
|
|
7719
8116
|
notifyCommand(program);
|
|
7720
8117
|
program.on("option:help", () => {
|