Task link MCP tools + anti-loop agent prompts
Tools: create_task_link, list_task_links, delete_task_link (23 total) TrackerClient.request() made public for generic API calls Agent prompts: anti-loop rules for agent-to-agent communication
This commit is contained in:
parent
007beaad92
commit
7d7fe6df42
@ -6,6 +6,7 @@ import { createMessageTools } from './messages.js';
|
||||
import { createProjectTools } from './projects.js';
|
||||
import { createMemberTools } from './members.js';
|
||||
import { createFileTools } from './files.js';
|
||||
import { taskLinkTools } from './tasks.js';
|
||||
|
||||
/**
|
||||
* Create all Team Board tracker tools for the agent.
|
||||
@ -19,6 +20,7 @@ export function createTrackerTools(ctx: ToolContext): ToolDefinition[] {
|
||||
...createProjectTools(ctx),
|
||||
...createMemberTools(ctx),
|
||||
...createFileTools(ctx),
|
||||
...taskLinkTools(ctx),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -127,3 +127,58 @@ export function createTaskTools(ctx: ToolContext): ToolDefinition<any>[] {
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// --- Task Links ---
|
||||
|
||||
const CreateTaskLinkParams = Type.Object({
|
||||
task_id: Type.String({ description: 'Source task ID (UUID)' }),
|
||||
target_id: Type.String({ description: 'Target task ID (UUID)' }),
|
||||
link_type: Type.String({ description: 'Link type: blocks | depends_on | relates_to' }),
|
||||
});
|
||||
|
||||
const ListTaskLinksParams = Type.Object({
|
||||
task_id: Type.String({ description: 'Task ID (UUID)' }),
|
||||
});
|
||||
|
||||
const DeleteTaskLinkParams = Type.Object({
|
||||
task_id: Type.String({ description: 'Task ID (UUID)' }),
|
||||
link_id: Type.String({ description: 'Link ID (UUID)' }),
|
||||
});
|
||||
|
||||
export function taskLinkTools(ctx: ToolContext): ToolDefinition<any>[] {
|
||||
return [
|
||||
{
|
||||
name: 'create_task_link',
|
||||
label: 'Create Task Link',
|
||||
description: 'Create a dependency/link between tasks. Types: blocks (source blocks target), depends_on (source depends on target), relates_to (informational).',
|
||||
parameters: CreateTaskLinkParams,
|
||||
async execute(_id: string, params: any) {
|
||||
const { task_id, target_id, link_type } = params as { task_id: string; target_id: string; link_type: string };
|
||||
const resp = await ctx.trackerClient.request('POST', `/api/v1/tasks/${task_id}/links`, { target_id, link_type });
|
||||
return ok(JSON.stringify(resp));
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'list_task_links',
|
||||
label: 'List Task Links',
|
||||
description: 'List all dependencies/links for a task. Shows both outgoing (this task blocks/depends_on) and incoming (blocked_by/required_by) links.',
|
||||
parameters: ListTaskLinksParams,
|
||||
async execute(_id: string, params: any) {
|
||||
const { task_id } = params as { task_id: string };
|
||||
const resp = await ctx.trackerClient.request('GET', `/api/v1/tasks/${task_id}/links`);
|
||||
return ok(JSON.stringify(resp));
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete_task_link',
|
||||
label: 'Delete Task Link',
|
||||
description: 'Remove a dependency/link between tasks.',
|
||||
parameters: DeleteTaskLinkParams,
|
||||
async execute(_id: string, params: any) {
|
||||
const { task_id, link_id } = params as { task_id: string; link_id: string };
|
||||
const resp = await ctx.trackerClient.request('DELETE', `/api/v1/tasks/${task_id}/links/${link_id}`);
|
||||
return ok(JSON.stringify(resp));
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ export class TrackerClient {
|
||||
private token: string,
|
||||
) {}
|
||||
|
||||
private async request<T>(method: string, path: string, body?: unknown): Promise<T> {
|
||||
async request<T>(method: string, path: string, body?: unknown): Promise<T> {
|
||||
const url = `${this.baseUrl}${path}`;
|
||||
this.log.info(' REST %s %s', method, path);
|
||||
if (body) this.log.info(' body: %s', JSON.stringify(body).slice(0, 300));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user