repo_create_pull_request_thread
Add a comment thread to a specific pull request in Azure DevOps, enabling detailed discussions on files or code sections using repository ID, pull request ID, and content.
Instructions
Creates a new comment thread on a pull request.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | The content of the comment to be added. | |
| filePath | No | The path of the file where the comment thread will be created. (optional) | |
| project | No | Project ID or project name (optional) | |
| pullRequestId | Yes | The ID of the pull request where the comment thread exists. | |
| repositoryId | Yes | The ID of the repository where the pull request is located. | |
| rightFileEndLine | No | Position of last character of the thread's span in right file. The line number of a thread's position. Starts at 1. Must only be set if rightFileStartLine is also specified. (optional) | |
| rightFileEndOffset | No | Position of last character of the thread's span in right file. The character offset of a thread's position inside of a line. Must only be set if rightFileEndLine is also specified. (optional) | |
| rightFileStartLine | No | Position of first character of the thread's span in right file. The line number of a thread's position. Starts at 1. (optional) | |
| rightFileStartOffset | No | Position of first character of the thread's span in right file. The line number of a thread's position. The character offset of a thread's position inside of a line. Starts at 1. Must only be set if rightFileStartLine is also specified. (optional) | |
| status | No | The status of the comment thread. Defaults to 'Active'. | Active |
Implementation Reference
- src/tools/repos.ts:663-715 (handler)The handler function for the 'repo_create_pull_request_thread' tool. It constructs a CommentThreadContext based on provided parameters and uses the Azure DevOps Git API to create a new comment thread on the specified pull request.async ({ repositoryId, pullRequestId, content, project, filePath, status, rightFileStartLine, rightFileStartOffset, rightFileEndLine, rightFileEndOffset }) => { const connection = await connectionProvider(); const gitApi = await connection.getGitApi(); const threadContext: CommentThreadContext = { filePath: filePath }; if (rightFileStartLine !== undefined) { if (rightFileStartLine < 1) { throw new Error("rightFileStartLine must be greater than or equal to 1."); } threadContext.rightFileStart = { line: rightFileStartLine }; if (rightFileStartOffset !== undefined) { if (rightFileStartOffset < 1) { throw new Error("rightFileStartOffset must be greater than or equal to 1."); } threadContext.rightFileStart.offset = rightFileStartOffset; } } if (rightFileEndLine !== undefined) { if (rightFileStartLine === undefined) { throw new Error("rightFileEndLine must only be specified if rightFileStartLine is also specified."); } if (rightFileEndLine < 1) { throw new Error("rightFileEndLine must be greater than or equal to 1."); } threadContext.rightFileEnd = { line: rightFileEndLine }; if (rightFileEndOffset !== undefined) { if (rightFileEndOffset < 1) { throw new Error("rightFileEndOffset must be greater than or equal to 1."); } threadContext.rightFileEnd.offset = rightFileEndOffset; } } const thread = await gitApi.createThread( { comments: [{ content: content }], threadContext: threadContext, status: CommentThreadStatus[status as keyof typeof CommentThreadStatus] }, repositoryId, pullRequestId, project ); return { content: [{ type: "text", text: JSON.stringify(thread, null, 2) }], }; }
- src/tools/repos.ts:633-662 (schema)Zod schema defining the input parameters for the 'repo_create_pull_request_thread' tool, including repositoryId, pullRequestId, content, and optional positioning parameters.repositoryId: z.string().describe("The ID of the repository where the pull request is located."), pullRequestId: z.number().describe("The ID of the pull request where the comment thread exists."), content: z.string().describe("The content of the comment to be added."), project: z.string().optional().describe("Project ID or project name (optional)"), filePath: z.string().optional().describe("The path of the file where the comment thread will be created. (optional)"), status: z .enum(getEnumKeys(CommentThreadStatus) as [string, ...string[]]) .optional() .default(CommentThreadStatus[CommentThreadStatus.Active]) .describe("The status of the comment thread. Defaults to 'Active'."), rightFileStartLine: z.number().optional().describe("Position of first character of the thread's span in right file. The line number of a thread's position. Starts at 1. (optional)"), rightFileStartOffset: z .number() .optional() .describe( "Position of first character of the thread's span in right file. The line number of a thread's position. The character offset of a thread's position inside of a line. Starts at 1. Must only be set if rightFileStartLine is also specified. (optional)" ), rightFileEndLine: z .number() .optional() .describe( "Position of last character of the thread's span in right file. The line number of a thread's position. Starts at 1. Must only be set if rightFileStartLine is also specified. (optional)" ), rightFileEndOffset: z .number() .optional() .describe( "Position of last character of the thread's span in right file. The character offset of a thread's position inside of a line. Must only be set if rightFileEndLine is also specified. (optional)" ), },
- src/tools/repos.ts:629-716 (registration)The server.tool call that registers the 'repo_create_pull_request_thread' tool with its schema and handler.server.tool( REPO_TOOLS.create_pull_request_thread, "Creates a new comment thread on a pull request.", { repositoryId: z.string().describe("The ID of the repository where the pull request is located."), pullRequestId: z.number().describe("The ID of the pull request where the comment thread exists."), content: z.string().describe("The content of the comment to be added."), project: z.string().optional().describe("Project ID or project name (optional)"), filePath: z.string().optional().describe("The path of the file where the comment thread will be created. (optional)"), status: z .enum(getEnumKeys(CommentThreadStatus) as [string, ...string[]]) .optional() .default(CommentThreadStatus[CommentThreadStatus.Active]) .describe("The status of the comment thread. Defaults to 'Active'."), rightFileStartLine: z.number().optional().describe("Position of first character of the thread's span in right file. The line number of a thread's position. Starts at 1. (optional)"), rightFileStartOffset: z .number() .optional() .describe( "Position of first character of the thread's span in right file. The line number of a thread's position. The character offset of a thread's position inside of a line. Starts at 1. Must only be set if rightFileStartLine is also specified. (optional)" ), rightFileEndLine: z .number() .optional() .describe( "Position of last character of the thread's span in right file. The line number of a thread's position. Starts at 1. Must only be set if rightFileStartLine is also specified. (optional)" ), rightFileEndOffset: z .number() .optional() .describe( "Position of last character of the thread's span in right file. The character offset of a thread's position inside of a line. Must only be set if rightFileEndLine is also specified. (optional)" ), }, async ({ repositoryId, pullRequestId, content, project, filePath, status, rightFileStartLine, rightFileStartOffset, rightFileEndLine, rightFileEndOffset }) => { const connection = await connectionProvider(); const gitApi = await connection.getGitApi(); const threadContext: CommentThreadContext = { filePath: filePath }; if (rightFileStartLine !== undefined) { if (rightFileStartLine < 1) { throw new Error("rightFileStartLine must be greater than or equal to 1."); } threadContext.rightFileStart = { line: rightFileStartLine }; if (rightFileStartOffset !== undefined) { if (rightFileStartOffset < 1) { throw new Error("rightFileStartOffset must be greater than or equal to 1."); } threadContext.rightFileStart.offset = rightFileStartOffset; } } if (rightFileEndLine !== undefined) { if (rightFileStartLine === undefined) { throw new Error("rightFileEndLine must only be specified if rightFileStartLine is also specified."); } if (rightFileEndLine < 1) { throw new Error("rightFileEndLine must be greater than or equal to 1."); } threadContext.rightFileEnd = { line: rightFileEndLine }; if (rightFileEndOffset !== undefined) { if (rightFileEndOffset < 1) { throw new Error("rightFileEndOffset must be greater than or equal to 1."); } threadContext.rightFileEnd.offset = rightFileEndOffset; } } const thread = await gitApi.createThread( { comments: [{ content: content }], threadContext: threadContext, status: CommentThreadStatus[status as keyof typeof CommentThreadStatus] }, repositoryId, pullRequestId, project ); return { content: [{ type: "text", text: JSON.stringify(thread, null, 2) }], }; } );
- src/tools/repos.ts:25-44 (helper)Constant object mapping internal tool names to their string identifiers, used for registration.const REPO_TOOLS = { list_repos_by_project: "repo_list_repos_by_project", list_pull_requests_by_repo: "repo_list_pull_requests_by_repo", list_pull_requests_by_project: "repo_list_pull_requests_by_project", list_branches_by_repo: "repo_list_branches_by_repo", list_my_branches_by_repo: "repo_list_my_branches_by_repo", list_pull_request_threads: "repo_list_pull_request_threads", list_pull_request_thread_comments: "repo_list_pull_request_thread_comments", get_repo_by_name_or_id: "repo_get_repo_by_name_or_id", get_branch_by_name: "repo_get_branch_by_name", get_pull_request_by_id: "repo_get_pull_request_by_id", create_pull_request: "repo_create_pull_request", update_pull_request: "repo_update_pull_request", update_pull_request_reviewers: "repo_update_pull_request_reviewers", reply_to_comment: "repo_reply_to_comment", create_pull_request_thread: "repo_create_pull_request_thread", resolve_comment: "repo_resolve_comment", search_commits: "repo_search_commits", list_pull_requests_by_commits: "repo_list_pull_requests_by_commits", };