) => {
+ const fileCount = metadata.files.length;
+
+ return (
+
+ Compared
+
+ {metadata.base}
+
+ to
+
+ {metadata.head}
+
+ in
+
+ {metadata.repo}
+
+
+
+ {fileCount} changed {fileCount === 1 ? 'file' : 'files'}
+
+
+
+ );
+};
diff --git a/packages/web/src/features/chat/tools.ts b/packages/web/src/features/chat/tools.ts
index 37ad7e0a8..149748bff 100644
--- a/packages/web/src/features/chat/tools.ts
+++ b/packages/web/src/features/chat/tools.ts
@@ -3,6 +3,7 @@ import {
readFileDefinition,
listCommitsDefinition,
listReposDefinition,
+ getDiffDefinition,
grepDefinition,
globDefinition,
findSymbolReferencesDefinition,
@@ -17,6 +18,7 @@ export const createTools = (context: ToolContext) => ({
[readFileDefinition.name]: toVercelAITool(readFileDefinition, context),
[listCommitsDefinition.name]: toVercelAITool(listCommitsDefinition, context),
[listReposDefinition.name]: toVercelAITool(listReposDefinition, context),
+ [getDiffDefinition.name]: toVercelAITool(getDiffDefinition, context),
[grepDefinition.name]: toVercelAITool(grepDefinition, context),
[globDefinition.name]: toVercelAITool(globDefinition, context),
[findSymbolReferencesDefinition.name]: toVercelAITool(findSymbolReferencesDefinition, context),
@@ -27,6 +29,7 @@ export const createTools = (context: ToolContext) => ({
export type ReadFileToolUIPart = ToolUIPart<{ read_file: SBChatMessageToolTypes['read_file'] }>;
export type ListCommitsToolUIPart = ToolUIPart<{ list_commits: SBChatMessageToolTypes['list_commits'] }>;
export type ListReposToolUIPart = ToolUIPart<{ list_repos: SBChatMessageToolTypes['list_repos'] }>;
+export type GetDiffToolUIPart = ToolUIPart<{ get_diff: SBChatMessageToolTypes['get_diff'] }>;
export type GrepToolUIPart = ToolUIPart<{ grep: SBChatMessageToolTypes['grep'] }>;
export type GlobToolUIPart = ToolUIPart<{ glob: SBChatMessageToolTypes['glob'] }>;
export type FindSymbolReferencesToolUIPart = ToolUIPart<{ find_symbol_references: SBChatMessageToolTypes['find_symbol_references'] }>;
diff --git a/packages/web/src/features/mcp/server.ts b/packages/web/src/features/mcp/server.ts
index ec4103f36..953953f14 100644
--- a/packages/web/src/features/mcp/server.ts
+++ b/packages/web/src/features/mcp/server.ts
@@ -13,6 +13,7 @@ import { getConfiguredLanguageModelsInfo } from "../chat/utils.server";
import {
findSymbolDefinitionsDefinition,
findSymbolReferencesDefinition,
+ getDiffDefinition,
listCommitsDefinition,
listReposDefinition,
listTreeDefinition,
@@ -40,6 +41,7 @@ export async function createMcpServer(): Promise {
registerMcpTool(server, grepDefinition, toolContext);
registerMcpTool(server, globDefinition, toolContext);
+ registerMcpTool(server, getDiffDefinition, toolContext);
registerMcpTool(server, listCommitsDefinition, toolContext);
registerMcpTool(server, listReposDefinition, toolContext);
registerMcpTool(server, readFileDefinition, toolContext);
diff --git a/packages/web/src/features/tools/getDiff.ts b/packages/web/src/features/tools/getDiff.ts
new file mode 100644
index 000000000..803a9429d
--- /dev/null
+++ b/packages/web/src/features/tools/getDiff.ts
@@ -0,0 +1,40 @@
+import { getDiff, GetDiffResult } from '@/features/git';
+import { getDiffRequestSchema } from '@/features/git/schemas';
+import { isServiceError } from '@/lib/utils';
+import description from './getDiff.txt';
+import { logger } from './logger';
+import { ToolDefinition } from './types';
+
+export type GetDiffMetadata = GetDiffResult & {
+ repo: string;
+ base: string;
+ head: string;
+};
+
+export const getDiffDefinition: ToolDefinition<'get_diff', typeof getDiffRequestSchema.shape, GetDiffMetadata> = {
+ name: 'get_diff',
+ title: 'Get diff',
+ isReadOnly: true,
+ isIdempotent: true,
+ description,
+ inputSchema: getDiffRequestSchema,
+ execute: async ({ repo, base, head }, _context) => {
+ logger.debug('get_diff', { repo, base, head });
+
+ const response = await getDiff({ repo, base, head });
+
+ if (isServiceError(response)) {
+ throw new Error(response.message);
+ }
+
+ return {
+ output: JSON.stringify(response),
+ metadata: {
+ ...response,
+ repo,
+ base,
+ head,
+ },
+ };
+ },
+};
diff --git a/packages/web/src/features/tools/getDiff.txt b/packages/web/src/features/tools/getDiff.txt
new file mode 100644
index 000000000..84cea0153
--- /dev/null
+++ b/packages/web/src/features/tools/getDiff.txt
@@ -0,0 +1,4 @@
+Returns a structured git diff between two refs in a repository.
+
+Use this tool when you need patch details (added, removed, and context lines) between a base and head revision.
+The output includes changed files and hunks with line ranges and diff body content.
diff --git a/packages/web/src/features/tools/index.ts b/packages/web/src/features/tools/index.ts
index 1a8f04013..04ac7014d 100644
--- a/packages/web/src/features/tools/index.ts
+++ b/packages/web/src/features/tools/index.ts
@@ -3,6 +3,7 @@ export * from './listCommits';
export * from './listRepos';
export * from './grep';
export * from './glob';
+export * from './getDiff';
export * from './findSymbolReferences';
export * from './findSymbolDefinitions';
export * from './listTree';