# Directory Structure
```
├── .gitignore
├── .npmignore
├── jest.config.js
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── src
│ ├── diffGetter.ts
│ └── index.ts
├── test
│ └── diffGetter.test.ts
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
node_modules/
build/
*.log
.env*
```
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
```
node_modules
src
test
tsconfig.json
jest.config.js
.gitignore
package-lock.json
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
# mcp-server-diff-typescript MCP Server
A Model Context Protocol server that provides unified diff generation capabilities.
This TypeScript-based MCP server implements a diff generation system. It provides a tool to generate unified diffs between two text strings, which is useful for comparing and analyzing text differences.
<a href="https://glama.ai/mcp/servers/3sbmp65pce"><img width="380" height="200" src="https://glama.ai/mcp/servers/3sbmp65pce/badge" alt="Server Diff TypeScript MCP server" /></a>
## Features
### Tools
- `get-unified-diff` - Generate unified diff between two text strings
- Takes `oldString` and `newString` as required parameters
- Returns the difference in unified diff format
- Uses the `diff` package for accurate difference detection
- Includes 3 lines of context around changes
## Installation
### As a Global Package
```bash
npm install -g mcp-server-diff-typescript
```
### As a Project Dependency
```bash
npm install mcp-server-diff-typescript
```
## Usage
### Using with Claude Desktop
To use with Claude Desktop, add the server config:
On MacOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
On Windows: `%APPDATA%/Claude/claude_desktop_config.json`
```json
"mcpServers": {
"mcp-server-diff-typescript": {
"command": "npx",
"args": [
"-y",
"mcp-server-diff-typescript"
]
}
}
```
or Add the following configuration:
```bash
git clone https://github.com/tatn/mcp-server-diff-typescript.git
cd mcp-server-diff-typescript
npm install
npm run build
```
```json
"mcpServers": {
"mcp-server-diff-typescript": {
"command": "node",
"args": [
"/path/to/mcp-server-diff-typescript/build/index.js"
]
}
}
```
### Debugging
To debug the MCP server:
```bash
npx @modelcontextprotocol/inspector npx -y mcp-server-diff-typescript
```
```bash
npx @modelcontextprotocol/inspector node /path/to/mcp-server-diff-typescript/build/index.js
```
```
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
```javascript
/** @type {import('ts-jest').JestConfigWithTsJest} */
export default {
preset: 'ts-jest',
testEnvironment: 'node',
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
transform: {
'^.+\\.tsx?$': ['ts-jest', {
useESM: true,
}],
},
};
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules","build"]
}
```
--------------------------------------------------------------------------------
/src/diffGetter.ts:
--------------------------------------------------------------------------------
```typescript
import { diffLines, createPatch } from 'diff';
export function generateUnifiedDiff(oldString: string, newString: string, oldHeader: string = '', newHeader: string = '', fileName: string = ''): string {
const diff = diffLines(oldString, newString);
if (diff.length === 1 && !diff[0].added && !diff[0].removed) {
return ''; // No change detected
}
return createPatch(fileName, oldString, newString, oldHeader, newHeader, { context: 3 });
}
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "mcp-server-diff-typescript",
"version": "1.0.5",
"description": "A Model Context Protocol server that provides unified diff generation capabilities",
"main": "./build/index.js",
"type": "module",
"bin": {
"mcp-server-diff-typescript": "build/index.js"
},
"files": [
"build"
],
"scripts": {
"build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
"prepare": "npm run build",
"watch": "tsc --watch",
"test": "jest",
"inspector": "npx @modelcontextprotocol/inspector build/index.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/tatn/mcp-server-diff-typescript.git"
},
"keywords": [
"mcp",
"server",
"diff",
"unified"
],
"homepage": "https://github.com/tatn/mcp-server-diff-typescript",
"license": "MIT",
"author": "tatn",
"dependencies": {
"@modelcontextprotocol/sdk": "0.6.0",
"diff": "^7.0.0"
},
"devDependencies": {
"@types/diff": "^7.0.0",
"@types/jest": "^29.5.14",
"@types/node": "^20.11.24",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"typescript": "^5.3.3"
},
"types": "build/index.d.ts"
}
```
--------------------------------------------------------------------------------
/test/diffGetter.test.ts:
--------------------------------------------------------------------------------
```typescript
import { generateUnifiedDiff } from '../src/diffGetter';
describe('generateUnifiedDiff', () => {
it('should return an empty string when there are no changes', () => {
const oldString = 'Hello World';
const newString = 'Hello World';
const result = generateUnifiedDiff(oldString, newString);
expect(result).toBe('');
});
it('should generate a unified diff for changed content', () => {
const oldString = 'Hello World';
const newString = 'Hello GitHub Copilot';
const result = generateUnifiedDiff(oldString, newString);
expect(result).toContain('Hello World');
expect(result).toContain('Hello GitHub Copilot');
});
it('should include headers in the diff', () => {
const oldString = 'Hello World';
const newString = 'Hello GitHub Copilot';
const oldHeader = 'v1';
const newHeader = 'v2';
const result = generateUnifiedDiff(oldString, newString, oldHeader, newHeader);
expect(result).toContain('--- v1');
expect(result).toContain('+++ v2');
});
it('should include file name in the diff', () => {
const oldString = 'Hello World';
const newString = 'Hello GitHub Copilot';
const fileName = 'testFile.txt';
const result = generateUnifiedDiff(oldString, newString, '', '', fileName);
expect(result).toContain('--- testFile.txt');
expect(result).toContain('+++ testFile.txt');
});
});
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
#!/usr/bin/env node
/**
* MCP server that returns the difference between strings in Unified Diff format.
*/
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { generateUnifiedDiff } from "./diffGetter.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{
name: "mcp-server-diff-typescript",
version: "0.1.0",
},
{
capabilities: {
resources: {},
tools: {},
prompts: {},
},
}
);
/**
*/
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get-unified-diff",
description: "Get the difference between two text articles in Unified diff format.",
inputSchema: {
type: "object",
properties: {
oldString: {
type: "string",
description: "old string to compare"
},
newString: {
type: "string",
description: "new string to compare"
}
},
required: ["oldString", "newString"]
}
}
]
};
});
/**
* Handler for the create_note and get-unified-diff tools.
*/
server.setRequestHandler(CallToolRequestSchema, async (request) => {
switch (request.params.name) {
case "get-unified-diff": {
const oldString = String(request.params.arguments?.oldString);
const newString = String(request.params.arguments?.newString);
if (!oldString || !newString) {
throw new Error("oldString and newString are required");
}
const diffResult = generateUnifiedDiff(oldString, newString, "", "", "");
return {
content: [{
type: "text",
text: diffResult
}]
};
}
default:
throw new Error("Unknown tool");
}
});
/**
* Start the server using stdio transport.
* This allows the server to communicate via standard input/output streams.
*/
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch((error) => {
console.error("Server error:", error);
process.exit(1);
});
```