feat: Add tool annotations for improved LLM tool understanding (#1543)

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: triepod-ai <noreply@github.com>
Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com>
Co-authored-by: triepod-ai <199543909+triepod-ai@users.noreply.github.com>
This commit is contained in:
Bryan Thompson
2026-01-02 05:45:28 -06:00
committed by GitHub
parent 1d8d72315f
commit 9a6fa1bd2a
47 changed files with 192 additions and 0 deletions

View File

@@ -33,6 +33,10 @@ export function registerAddDependencyTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Add Dependency',
destructiveHint: true
},
execute: withToolContext(
'add-dependency',
async (args, { log, session }) => {

View File

@@ -62,6 +62,10 @@ export function registerAddSubtaskTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Add Subtask',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
const resolvedTag = resolveTag({

View File

@@ -50,6 +50,10 @@ export function registerAddTagTool(server) {
.string()
.describe('The directory of the project. Must be an absolute path.')
}),
annotations: {
title: 'Add Tag',
destructiveHint: false
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Starting add-tag with args: ${JSON.stringify(args)}`);

View File

@@ -65,6 +65,10 @@ export function registerAddTaskTool(server) {
.optional()
.describe('Whether to use research capabilities for task creation')
}),
annotations: {
title: 'Add Task',
destructiveHint: false
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Starting add-task with args: ${JSON.stringify(args)}`);

View File

@@ -75,6 +75,10 @@ export function registerAnalyzeProjectComplexityTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Analyze Project Complexity',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
const toolName = 'analyze_project_complexity'; // Define tool name for logging

View File

@@ -39,6 +39,10 @@ export function registerClearSubtasksTool(server) {
message: "Either 'id' or 'all' parameter must be provided",
path: ['id', 'all']
}),
annotations: {
title: 'Clear Subtasks',
destructiveHint: true
},
execute: withToolContext('clear-subtasks', async (args, context) => {
try {
context.log.info(

View File

@@ -33,6 +33,10 @@ export function registerComplexityReportTool(server) {
.string()
.describe('The directory of the project. Must be an absolute path.')
}),
annotations: {
title: 'Complexity Report',
readOnlyHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(

View File

@@ -36,6 +36,10 @@ export function registerCopyTagTool(server) {
.string()
.describe('The directory of the project. Must be an absolute path.')
}),
annotations: {
title: 'Copy Tag',
destructiveHint: false
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Starting copy-tag with args: ${JSON.stringify(args)}`);

View File

@@ -34,6 +34,10 @@ export function registerDeleteTagTool(server) {
.string()
.describe('The directory of the project. Must be an absolute path.')
}),
annotations: {
title: 'Delete Tag',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Starting delete-tag with args: ${JSON.stringify(args)}`);

View File

@@ -64,6 +64,10 @@ export function registerExpandAllTool(server) {
),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Expand All Tasks',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(

View File

@@ -52,6 +52,10 @@ export function registerExpandTaskTool(server) {
.describe('Force expansion even if subtasks exist'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Expand Task',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Starting expand-task with args: ${JSON.stringify(args)}`);

View File

@@ -24,6 +24,10 @@ export function registerFixDependenciesTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Fix Dependencies',
destructiveHint: true
},
execute: withToolContext('fix-dependencies', async (args, context) => {
try {
context.log.info(

View File

@@ -15,6 +15,10 @@ export function registerGetOperationStatusTool(server, asyncManager) {
parameters: z.object({
operationId: z.string().describe('The ID of the operation to check.')
}),
annotations: {
title: 'Get Operation Status',
readOnlyHint: true
},
execute: async (args, { log }) => {
try {
const { operationId } = args;

View File

@@ -56,6 +56,10 @@ export function registerInitializeProjectTool(server) {
`List of rule profiles to include at initialization. If omitted, defaults to Cursor profile only. Available options: ${RULE_PROFILES.join(', ')}`
)
}),
annotations: {
title: 'Initialize Project',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, context) => {
const { log } = context;
const session = context.session;

View File

@@ -33,6 +33,10 @@ export function registerListTagsTool(server) {
.string()
.describe('The directory of the project. Must be an absolute path.')
}),
annotations: {
title: 'List Tags',
readOnlyHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Starting list-tags with args: ${JSON.stringify(args)}`);

View File

@@ -79,6 +79,10 @@ export function registerModelsTool(server) {
'Custom base URL for providers that support it (e.g., https://api.example.com/v1).'
)
}),
annotations: {
title: 'Models',
destructiveHint: true
},
execute: withToolContext('models', async (args, context) => {
try {
context.log.info(

View File

@@ -54,6 +54,10 @@ export function registerMoveTaskTool(server) {
.optional()
.describe('Break cross-tag dependencies during move')
}),
annotations: {
title: 'Move Task',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
// Check if this is a cross-tag move

View File

@@ -38,6 +38,10 @@ export function registerNextTaskTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Next Task',
readOnlyHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Finding next task with args: ${JSON.stringify(args)}`);

View File

@@ -65,6 +65,10 @@ export function registerParsePRDTool(server) {
.optional()
.describe('Append generated tasks to existing file.')
}),
annotations: {
title: 'Parse PRD',
destructiveHint: true
},
execute: withNormalizedProjectRoot(
async (args, { log, session, reportProgress }) => {
try {

View File

@@ -31,6 +31,10 @@ export function registerRemoveDependencyTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Remove Dependency',
destructiveHint: true
},
execute: withToolContext('remove-dependency', async (args, context) => {
try {
const resolvedTag = resolveTag({

View File

@@ -48,6 +48,10 @@ export function registerRemoveSubtaskTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Remove Subtask',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
const resolvedTag = resolveTag({

View File

@@ -42,6 +42,10 @@ export function registerRemoveTaskTool(server) {
'Specify which tag context to operate on. Defaults to the current active tag.'
)
}),
annotations: {
title: 'Remove Task',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Removing task(s) with ID(s): ${args.id}`);

View File

@@ -31,6 +31,10 @@ export function registerRenameTagTool(server) {
.string()
.describe('The directory of the project. Must be an absolute path.')
}),
annotations: {
title: 'Rename Tag',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Starting rename-tag with args: ${JSON.stringify(args)}`);

View File

@@ -66,6 +66,11 @@ export function registerResearchTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Research',
destructiveHint: true,
openWorldHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
const resolvedTag = resolveTag({

View File

@@ -22,6 +22,10 @@ export function registerResponseLanguageTool(server) {
'The new response language to set. like "中文" "English" or "español".'
)
}),
annotations: {
title: 'Response Language',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(

View File

@@ -43,6 +43,10 @@ export function registerRulesTool(server) {
'DANGEROUS: Force removal even if it would leave no rule profiles. Only use if you are absolutely certain.'
)
}),
annotations: {
title: 'Rules',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(

View File

@@ -50,6 +50,10 @@ export function registerScopeDownTool(server) {
.optional()
.describe('Whether to use research capabilities for scoping')
}),
annotations: {
title: 'Scope Down Task',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Starting scope-down with args: ${JSON.stringify(args)}`);

View File

@@ -50,6 +50,10 @@ export function registerScopeUpTool(server) {
.optional()
.describe('Whether to use research capabilities for scoping')
}),
annotations: {
title: 'Scope Up Task',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Starting scope-up with args: ${JSON.stringify(args)}`);

View File

@@ -51,6 +51,10 @@ export function registerSetTaskStatusTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Optional tag context to operate on')
}),
annotations: {
title: 'Set Task Status',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(

View File

@@ -38,6 +38,10 @@ export function registerUpdateSubtaskTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Update Subtask',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
const toolName = 'update_subtask';

View File

@@ -47,6 +47,10 @@ export function registerUpdateTaskTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Update Task',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
const toolName = 'update_task';
try {

View File

@@ -47,6 +47,10 @@ export function registerUpdateTool(server) {
),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Update Tasks',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
const toolName = 'update';
const { from, prompt, research, file, projectRoot, tag } = args;

View File

@@ -30,6 +30,10 @@ export function registerUseTagTool(server) {
.string()
.describe('The directory of the project. Must be an absolute path.')
}),
annotations: {
title: 'Use Tag',
destructiveHint: true
},
execute: withNormalizedProjectRoot(async (args, { log, session }) => {
try {
log.info(`Starting use-tag with args: ${JSON.stringify(args)}`);

View File

@@ -25,6 +25,10 @@ export function registerValidateDependenciesTool(server) {
.describe('The directory of the project. Must be an absolute path.'),
tag: z.string().optional().describe('Tag context to operate on')
}),
annotations: {
title: 'Validate Dependencies',
readOnlyHint: true
},
execute: withToolContext(
'validate-dependencies',
async (args, { log, session }) => {