From d381cf1ffda963ccd04b9a5a1913595163d8bcf8 Mon Sep 17 00:00:00 2001 From: Enrico Ballardini Date: Sat, 23 Aug 2025 08:19:01 +0200 Subject: [PATCH 01/13] feat(directory_tree): add excludePatterns support & documentation (#623) - Update documentation with directory_tree declaration - Add excludePatterns parameter to DirectoryTreeArgsSchema - Implement pattern exclusion in buildTree function using minimatch - Pass excludePatterns through recursive calls - Support both simple and glob patterns for exclusion - Maintain consistent behavior with search_files implementation * Add tests and fix implementation --------- Co-authored-by: Ola Hungerford Co-authored-by: Adam Jones Co-authored-by: Adam Jones --- src/filesystem/README.md | 13 ++ .../__tests__/directory-tree.test.ts | 147 ++++++++++++++++++ src/filesystem/index.ts | 23 ++- 3 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 src/filesystem/__tests__/directory-tree.test.ts diff --git a/src/filesystem/README.md b/src/filesystem/README.md index 0f456f3..ccef2d6 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -153,6 +153,19 @@ The server's directory access control follows this flow: - Case-insensitive matching - Returns full paths to matches +- **directory_tree** + - Get recursive JSON tree structure of directory contents + - Inputs: + - `path` (string): Starting directory + - `excludePatterns` (string[]): Exclude any patterns. Glob formats are supported. + - Returns: + - JSON array where each entry contains: + - `name` (string): File/directory name + - `type` ('file'|'directory'): Entry type + - `children` (array): Present only for directories + - Empty array for empty directories + - Omitted for files + - **get_file_info** - Get detailed file/directory metadata - Input: `path` (string) diff --git a/src/filesystem/__tests__/directory-tree.test.ts b/src/filesystem/__tests__/directory-tree.test.ts new file mode 100644 index 0000000..6828650 --- /dev/null +++ b/src/filesystem/__tests__/directory-tree.test.ts @@ -0,0 +1,147 @@ +import { describe, it, expect, beforeEach, afterEach } from '@jest/globals'; +import * as fs from 'fs/promises'; +import * as path from 'path'; +import * as os from 'os'; + +// We need to test the buildTree function, but it's defined inside the request handler +// So we'll extract the core logic into a testable function +import { minimatch } from 'minimatch'; + +interface TreeEntry { + name: string; + type: 'file' | 'directory'; + children?: TreeEntry[]; +} + +async function buildTreeForTesting(currentPath: string, rootPath: string, excludePatterns: string[] = []): Promise { + const entries = await fs.readdir(currentPath, {withFileTypes: true}); + const result: TreeEntry[] = []; + + for (const entry of entries) { + const relativePath = path.relative(rootPath, path.join(currentPath, entry.name)); + const shouldExclude = excludePatterns.some(pattern => { + if (pattern.includes('*')) { + return minimatch(relativePath, pattern, {dot: true}); + } + // For files: match exact name or as part of path + // For directories: match as directory path + return minimatch(relativePath, pattern, {dot: true}) || + minimatch(relativePath, `**/${pattern}`, {dot: true}) || + minimatch(relativePath, `**/${pattern}/**`, {dot: true}); + }); + if (shouldExclude) + continue; + + const entryData: TreeEntry = { + name: entry.name, + type: entry.isDirectory() ? 'directory' : 'file' + }; + + if (entry.isDirectory()) { + const subPath = path.join(currentPath, entry.name); + entryData.children = await buildTreeForTesting(subPath, rootPath, excludePatterns); + } + + result.push(entryData); + } + + return result; +} + +describe('buildTree exclude patterns', () => { + let testDir: string; + + beforeEach(async () => { + testDir = await fs.mkdtemp(path.join(os.tmpdir(), 'filesystem-test-')); + + // Create test directory structure + await fs.mkdir(path.join(testDir, 'src')); + await fs.mkdir(path.join(testDir, 'node_modules')); + await fs.mkdir(path.join(testDir, '.git')); + await fs.mkdir(path.join(testDir, 'nested', 'node_modules'), { recursive: true }); + + // Create test files + await fs.writeFile(path.join(testDir, '.env'), 'SECRET=value'); + await fs.writeFile(path.join(testDir, '.env.local'), 'LOCAL_SECRET=value'); + await fs.writeFile(path.join(testDir, 'src', 'index.js'), 'console.log("hello");'); + await fs.writeFile(path.join(testDir, 'package.json'), '{}'); + await fs.writeFile(path.join(testDir, 'node_modules', 'module.js'), 'module.exports = {};'); + await fs.writeFile(path.join(testDir, 'nested', 'node_modules', 'deep.js'), 'module.exports = {};'); + }); + + afterEach(async () => { + await fs.rm(testDir, { recursive: true, force: true }); + }); + + it('should exclude files matching simple patterns', async () => { + // Test the current implementation - this will fail until the bug is fixed + const tree = await buildTreeForTesting(testDir, testDir, ['.env']); + const fileNames = tree.map(entry => entry.name); + + expect(fileNames).not.toContain('.env'); + expect(fileNames).toContain('.env.local'); // Should not exclude this + expect(fileNames).toContain('src'); + expect(fileNames).toContain('package.json'); + }); + + it('should exclude directories matching simple patterns', async () => { + const tree = await buildTreeForTesting(testDir, testDir, ['node_modules']); + const dirNames = tree.map(entry => entry.name); + + expect(dirNames).not.toContain('node_modules'); + expect(dirNames).toContain('src'); + expect(dirNames).toContain('.git'); + }); + + it('should exclude nested directories with same pattern', async () => { + const tree = await buildTreeForTesting(testDir, testDir, ['node_modules']); + + // Find the nested directory + const nestedDir = tree.find(entry => entry.name === 'nested'); + expect(nestedDir).toBeDefined(); + expect(nestedDir!.children).toBeDefined(); + + // The nested/node_modules should also be excluded + const nestedChildren = nestedDir!.children!.map(child => child.name); + expect(nestedChildren).not.toContain('node_modules'); + }); + + it('should handle glob patterns correctly', async () => { + const tree = await buildTreeForTesting(testDir, testDir, ['*.env']); + const fileNames = tree.map(entry => entry.name); + + expect(fileNames).not.toContain('.env'); + expect(fileNames).toContain('.env.local'); // *.env should not match .env.local + expect(fileNames).toContain('src'); + }); + + it('should handle dot files correctly', async () => { + const tree = await buildTreeForTesting(testDir, testDir, ['.git']); + const dirNames = tree.map(entry => entry.name); + + expect(dirNames).not.toContain('.git'); + expect(dirNames).toContain('.env'); // Should not exclude this + }); + + it('should work with multiple exclude patterns', async () => { + const tree = await buildTreeForTesting(testDir, testDir, ['node_modules', '.env', '.git']); + const entryNames = tree.map(entry => entry.name); + + expect(entryNames).not.toContain('node_modules'); + expect(entryNames).not.toContain('.env'); + expect(entryNames).not.toContain('.git'); + expect(entryNames).toContain('src'); + expect(entryNames).toContain('package.json'); + }); + + it('should handle empty exclude patterns', async () => { + const tree = await buildTreeForTesting(testDir, testDir, []); + const entryNames = tree.map(entry => entry.name); + + // All entries should be included + expect(entryNames).toContain('node_modules'); + expect(entryNames).toContain('.env'); + expect(entryNames).toContain('.git'); + expect(entryNames).toContain('src'); + }); +}); \ No newline at end of file diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index 310cfa6..ee4307c 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -14,6 +14,7 @@ import { createReadStream } from "fs"; import path from "path"; import { z } from "zod"; import { zodToJsonSchema } from "zod-to-json-schema"; +import { minimatch } from "minimatch"; import { normalizePath, expandHome } from './path-utils.js'; import { getValidRootDirectories } from './roots-utils.js'; import { @@ -121,6 +122,7 @@ const ListDirectoryWithSizesArgsSchema = z.object({ const DirectoryTreeArgsSchema = z.object({ path: z.string(), + excludePatterns: z.array(z.string()).optional().default([]) }); const MoveFileArgsSchema = z.object({ @@ -528,13 +530,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { type: 'file' | 'directory'; children?: TreeEntry[]; } + const rootPath = parsed.data.path; - async function buildTree(currentPath: string): Promise { + async function buildTree(currentPath: string, excludePatterns: string[] = []): Promise { const validPath = await validatePath(currentPath); const entries = await fs.readdir(validPath, {withFileTypes: true}); const result: TreeEntry[] = []; for (const entry of entries) { + const relativePath = path.relative(rootPath, path.join(currentPath, entry.name)); + const shouldExclude = excludePatterns.some(pattern => { + if (pattern.includes('*')) { + return minimatch(relativePath, pattern, {dot: true}); + } + // For files: match exact name or as part of path + // For directories: match as directory path + return minimatch(relativePath, pattern, {dot: true}) || + minimatch(relativePath, `**/${pattern}`, {dot: true}) || + minimatch(relativePath, `**/${pattern}/**`, {dot: true}); + }); + if (shouldExclude) + continue; + const entryData: TreeEntry = { name: entry.name, type: entry.isDirectory() ? 'directory' : 'file' @@ -542,7 +559,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { if (entry.isDirectory()) { const subPath = path.join(currentPath, entry.name); - entryData.children = await buildTree(subPath); + entryData.children = await buildTree(subPath, excludePatterns); } result.push(entryData); @@ -551,7 +568,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { return result; } - const treeData = await buildTree(parsed.data.path); + const treeData = await buildTree(rootPath, parsed.data.excludePatterns); return { content: [{ type: "text", From fd886fac9c40c579eaffde7a00f13fa769731bfc Mon Sep 17 00:00:00 2001 From: Finn Andersen Date: Sat, 23 Aug 2025 09:37:53 +0300 Subject: [PATCH 02/13] Support glob `pattern` in search_files tool (#745) Co-authored-by: Adam Jones Co-authored-by: Claude Co-authored-by: Adam Jones --- src/filesystem/README.md | 6 +++--- src/filesystem/__tests__/lib.test.ts | 6 +++--- src/filesystem/index.ts | 6 +++--- src/filesystem/lib.ts | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/filesystem/README.md b/src/filesystem/README.md index ccef2d6..499fca5 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -145,12 +145,12 @@ The server's directory access control follows this flow: - Fails if destination exists - **search_files** - - Recursively search for files/directories + - Recursively search for files/directories that match or do not match patterns - Inputs: - `path` (string): Starting directory - `pattern` (string): Search pattern - - `excludePatterns` (string[]): Exclude any patterns. Glob formats are supported. - - Case-insensitive matching + - `excludePatterns` (string[]): Exclude any patterns. + - Glob-style pattern matching - Returns full paths to matches - **directory_tree** diff --git a/src/filesystem/__tests__/lib.test.ts b/src/filesystem/__tests__/lib.test.ts index 76d3679..cc13ef0 100644 --- a/src/filesystem/__tests__/lib.test.ts +++ b/src/filesystem/__tests__/lib.test.ts @@ -316,7 +316,7 @@ describe('Lib Functions', () => { const result = await searchFilesWithValidation( testDir, - 'test', + '*test*', allowedDirs, { excludePatterns: ['*.log', 'node_modules'] } ); @@ -346,7 +346,7 @@ describe('Lib Functions', () => { const result = await searchFilesWithValidation( testDir, - 'test', + '*test*', allowedDirs, {} ); @@ -370,7 +370,7 @@ describe('Lib Functions', () => { const result = await searchFilesWithValidation( testDir, - 'test', + '*test*', allowedDirs, { excludePatterns: ['*.backup'] } ); diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index ee4307c..d732c4d 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -277,9 +277,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { name: "search_files", description: "Recursively search for files and directories matching a pattern. " + - "Searches through all subdirectories from the starting path. The search " + - "is case-insensitive and matches partial names. Returns full paths to all " + - "matching items. Great for finding files when you don't know their exact location. " + + "The patterns should be glob-style patterns that match paths relative to the working directory. " + + "Use pattern like '*.ext' to match files in current directory, and '**/*.ext' to match files in all subdirectories. " + + "Returns full paths to all matching items. Great for finding files when you don't know their exact location. " + "Only searches within allowed directories.", inputSchema: zodToJsonSchema(SearchFilesArgsSchema) as ToolInput, }, diff --git a/src/filesystem/lib.ts b/src/filesystem/lib.ts index 40cb316..240ca0d 100644 --- a/src/filesystem/lib.ts +++ b/src/filesystem/lib.ts @@ -367,14 +367,14 @@ export async function searchFilesWithValidation( await validatePath(fullPath); const relativePath = path.relative(rootPath, fullPath); - const shouldExclude = excludePatterns.some(excludePattern => { - const globPattern = excludePattern.includes('*') ? excludePattern : `**/${excludePattern}/**`; - return minimatch(relativePath, globPattern, { dot: true }); - }); + const shouldExclude = excludePatterns.some(excludePattern => + minimatch(relativePath, excludePattern, { dot: true }) + ); if (shouldExclude) continue; - if (entry.name.toLowerCase().includes(pattern.toLowerCase())) { + // Use glob matching for the search pattern + if (minimatch(relativePath, pattern, { dot: true })) { results.push(fullPath); } From c6cccec4e9651bf43c5635a87de8f0a600f30c8f Mon Sep 17 00:00:00 2001 From: Adam Jones Date: Sat, 23 Aug 2025 07:04:42 +0000 Subject: [PATCH 03/13] refactor(CONTRIBUTING.md): streamline contribution guidelines and improve clarity --- CONTRIBUTING.md | 106 ++++++++---------------------------------------- 1 file changed, 17 insertions(+), 89 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 28cba5a..1dfbc4b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,105 +1,33 @@ # Contributing to MCP Servers -Thank you for your interest in contributing to the Model Context Protocol (MCP) servers! This document provides guidelines and instructions for contributing. +Thanks for your interest in contributing! Here's how you can help make this repo better. -## Types of Contributions +We accept changes through [the standard GitHub flow model](https://docs.github.com/en/get-started/using-github/github-flow). -### 1. New Servers +## Server Listings -The repository contains reference implementations, as well as a list of community servers. -We generally don't accept new servers into the repository. We do accept pull requests to the [README.md](./README.md) -adding a reference to your servers. +We welcome PRs that add links to your servers in the [README.md](./README.md)! -Please keep lists in alphabetical order to minimize merge conflicts when adding new items. +## Server Implementations -- Check the [modelcontextprotocol.io](https://modelcontextprotocol.io) documentation -- Ensure your server doesn't duplicate existing functionality -- Consider whether your server would be generally useful to others -- Follow [security best practices](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations) from the MCP documentation -- Create a PR adding a link to your server to the [README.md](./README.md). +We welcome: +- **Bug fixes** — Help us squash those pesky bugs. +- **Ergonomic improvements** — Making servers easier to use for humans and agents. -### 2. Improvements to Existing Servers -Enhancements to existing servers are welcome! This includes: +We're more selective about: +- **New features** — Especially if they're not crucial to the server's core purpose or are highly opinionated. The existing servers are reference servers meant to inspire the community. If you need specific features, we encourage you to build enhanced versions! We think a diverse ecosystem of servers is beneficial for everyone, and would love to link to your improved server in our README. -- Bug fixes -- Performance improvements -- New features -- Security enhancements +We don't accept: +- **New server implementations** — We encourage you to publish them yourself, and link to them from the README. -### 3. Documentation -Documentation improvements are always welcome: +## Documentation -- Fixing typos or unclear instructions -- Adding examples -- Improving setup instructions -- Adding troubleshooting guides +Improvements to existing documentation is welcome - although generally we'd prefer ergonomic improvements than documenting pain points if possible! -## Getting Started - -1. Fork the repository -2. Clone your fork: - ```bash - git clone https://github.com/your-username/servers.git - ``` -3. Add the upstream remote: - ```bash - git remote add upstream https://github.com/modelcontextprotocol/servers.git - ``` -4. Create a branch: - ```bash - git checkout -b my-feature - ``` - -## Development Guidelines - -### Code Style -- Follow the existing code style in the repository -- Include appropriate type definitions -- Add comments for complex logic - -### Documentation -- Include a detailed README.md in your server directory -- Document all configuration options -- Provide setup instructions -- Include usage examples - -### Security -- Follow security best practices -- Implement proper input validation -- Handle errors appropriately -- Document security considerations - -## Submitting Changes - -1. Commit your changes: - ```bash - git add . - git commit -m "Description of changes" - ``` -2. Push to your fork: - ```bash - git push origin my-feature - ``` -3. Create a Pull Request through GitHub - -### Pull Request Guidelines - -- Thoroughly test your changes -- Fill out the pull request template completely -- Link any related issues -- Provide clear description of changes -- Include any necessary documentation updates -- Add screenshots for UI changes -- List any breaking changes +We're more selective about adding wholly new documentation, especially in ways that aren't vendor neutral (e.g. how to run a particular server with a particular client). ## Community -- Participate in [GitHub Discussions](https://github.com/orgs/modelcontextprotocol/discussions) -- Follow the [Code of Conduct](CODE_OF_CONDUCT.md) +[Learn how the MCP community communicates](https://modelcontextprotocol.io/community/communication). -## Questions? - -- Check the [documentation](https://modelcontextprotocol.io) -- Ask in GitHub Discussions - -Thank you for contributing to MCP Servers! +Thank you for helping make MCP servers better for everyone! \ No newline at end of file From 2a4b7b0649734b75faf85f11c80277ddc31d2348 Mon Sep 17 00:00:00 2001 From: Juliette Sivan <91728573+juliette0704@users.noreply.github.com> Date: Sat, 23 Aug 2025 09:29:17 +0200 Subject: [PATCH 04/13] feat(readme): add Linkup MCP server to the list of offical integrations (#2575) Co-authored-by: Adam Jones --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e230c71..f466376 100644 --- a/README.md +++ b/README.md @@ -259,6 +259,8 @@ Official integrations are maintained by companies building production ready MCP - Linear Logo **[Linear](https://linear.app/docs/mcp)** - Search, create, and update Linear issues, projects, and comments. - Lingo.dev Logo **[Lingo.dev](https://github.com/lingodotdev/lingo.dev/blob/main/mcp.md)** - Make your AI agent speak every language on the planet, using [Lingo.dev](https://lingo.dev) Localization Engine. - LiGo Logo **[LinkedIn MCP Runner](https://github.com/ertiqah/linkedin-mcp-runner)** - Write, edit, and schedule LinkedIn posts right from ChatGPT and Claude with [LiGo](https://ligo.ertiqah.com/). +- Linkup Logo **[Linkup](https://github.com/LinkupPlatform/js-mcp-server)** - (JS version) MCP server that provides web search capabilities through Linkup's advanced search API. This server enables AI assistants and development tools to perform intelligent web searches with natural language queries. +- Linkup Logo **[Linkup](https://github.com/LinkupPlatform/python-mcp-server)** - (Python version) MCP server that provides web search capabilities through Linkup's advanced search API. This server enables AI assistants and development tools to perform intelligent web searches with natural language queries. - Lisply **[Lisply](https://github.com/gornskew/lisply-mcp)** - Flexible frontend for compliant Lisp-speaking backends. - Litmus.io Logo **[Litmus.io](https://github.com/litmusautomation/litmus-mcp-server)** - Official MCP server for configuring [Litmus](https://litmus.io) Edge for Industrial Data Collection, Edge Analytics & Industrial AI. - Liveblocks Logo **[Liveblocks](https://github.com/liveblocks/liveblocks-mcp-server)** - Ready‑made features for AI & human collaboration—use this to develop your [Liveblocks](https://liveblocks.io) app quicker. From b647cb3019f8c0fe33818cd88ec623b21f8b42bf Mon Sep 17 00:00:00 2001 From: "Sebastien Rosset (serosset)" Date: Fri, 22 Aug 2025 10:59:29 -0700 Subject: [PATCH 05/13] Add documentation for the read_multiple_files action. --- src/filesystem/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index d732c4d..7888196 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -88,7 +88,10 @@ const ReadMediaFileArgsSchema = z.object({ }); const ReadMultipleFilesArgsSchema = z.object({ - paths: z.array(z.string()), + paths: z + .array(z.string()) + .min(1, "At least one file path must be provided") + .describe("Array of file paths to read. Each path must be a string pointing to a valid file within allowed directories."), }); const WriteFileArgsSchema = z.object({ From ec914212651ff90fe5896f886ae58d590c827aad Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 03:27:40 +0000 Subject: [PATCH 06/13] Improve parameter descriptions in sequential-thinking for better LLM type safety Update thoughtNumber and totalThoughts parameter descriptions to use positive-only examples that guide LLMs toward correct numeric type usage. This addresses the issue where LLMs sometimes generate string values (e.g. "1") instead of numeric values (e.g. 1) for integer parameters. Co-authored-by: Ola Hungerford --- src/sequentialthinking/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sequentialthinking/index.ts b/src/sequentialthinking/index.ts index bd486fd..3498697 100644 --- a/src/sequentialthinking/index.ts +++ b/src/sequentialthinking/index.ts @@ -206,12 +206,12 @@ You should: }, thoughtNumber: { type: "integer", - description: "Current thought number", + description: "Current thought number (numeric value, e.g., 1, 2, 3)", minimum: 1 }, totalThoughts: { type: "integer", - description: "Estimated total thoughts needed", + description: "Estimated total thoughts needed (numeric value, e.g., 5, 10)", minimum: 1 }, isRevision: { From 09adff0b296dae7c93c6e02ac2690a7c2a6ba17e Mon Sep 17 00:00:00 2001 From: Mohamed Amine Berguiga Date: Mon, 25 Aug 2025 19:26:32 +0200 Subject: [PATCH 07/13] feat(git): add date-based commit log retrieval functions (#2057) Co-authored-by: adam jones --- src/git/README.md | 4 +- src/git/src/mcp_server_git/server.py | 69 ++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/src/git/README.md b/src/git/README.md index 6ea2e8c..c56ef50 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -57,10 +57,12 @@ Please note that mcp-server-git is currently in early development. The functiona - Returns: Confirmation of reset operation 8. `git_log` - - Shows the commit logs + - Shows the commit logs with optional date filtering - Inputs: - `repo_path` (string): Path to Git repository - `max_count` (number, optional): Maximum number of commits to show (default: 10) + - `start_timestamp` (string, optional): Start timestamp for filtering commits. Accepts ISO 8601 format (e.g., '2024-01-15T14:30:25'), relative dates (e.g., '2 weeks ago', 'yesterday'), or absolute dates (e.g., '2024-01-15', 'Jan 15 2024') + - `end_timestamp` (string, optional): End timestamp for filtering commits. Accepts ISO 8601 format (e.g., '2024-01-15T14:30:25'), relative dates (e.g., '2 weeks ago', 'yesterday'), or absolute dates (e.g., '2024-01-15', 'Jan 15 2024') - Returns: Array of commit entries with hash, author, date, and message 9. `git_create_branch` diff --git a/src/git/src/mcp_server_git/server.py b/src/git/src/mcp_server_git/server.py index f1c4e83..a16b601 100644 --- a/src/git/src/mcp_server_git/server.py +++ b/src/git/src/mcp_server_git/server.py @@ -48,6 +48,14 @@ class GitReset(BaseModel): class GitLog(BaseModel): repo_path: str max_count: int = 10 + start_timestamp: Optional[str] = Field( + None, + description="Start timestamp for filtering commits. Accepts: ISO 8601 format (e.g., '2024-01-15T14:30:25'), relative dates (e.g., '2 weeks ago', 'yesterday'), or absolute dates (e.g., '2024-01-15', 'Jan 15 2024')" + ) + end_timestamp: Optional[str] = Field( + None, + description="End timestamp for filtering commits. Accepts: ISO 8601 format (e.g., '2024-01-15T14:30:25'), relative dates (e.g., '2 weeks ago', 'yesterday'), or absolute dates (e.g., '2024-01-15', 'Jan 15 2024')" + ) class GitCreateBranch(BaseModel): repo_path: str @@ -83,6 +91,7 @@ class GitBranch(BaseModel): description="The commit sha that branch should NOT contain. Do not pass anything to this param if no commit sha is specified", ) + class GitTools(str, Enum): STATUS = "git_status" DIFF_UNSTAGED = "git_diff_unstaged" @@ -125,17 +134,41 @@ def git_reset(repo: git.Repo) -> str: repo.index.reset() return "All staged changes reset" -def git_log(repo: git.Repo, max_count: int = 10) -> list[str]: - commits = list(repo.iter_commits(max_count=max_count)) - log = [] - for commit in commits: - log.append( - f"Commit: {commit.hexsha!r}\n" - f"Author: {commit.author!r}\n" - f"Date: {commit.authored_datetime}\n" - f"Message: {commit.message!r}\n" - ) - return log +def git_log(repo: git.Repo, max_count: int = 10, start_timestamp: Optional[str] = None, end_timestamp: Optional[str] = None) -> list[str]: + if start_timestamp or end_timestamp: + # Use git log command with date filtering + args = [] + if start_timestamp: + args.extend(['--since', start_timestamp]) + if end_timestamp: + args.extend(['--until', end_timestamp]) + args.extend(['--format=%H%n%an%n%ad%n%s%n']) + + log_output = repo.git.log(*args).split('\n') + + log = [] + # Process commits in groups of 4 (hash, author, date, message) + for i in range(0, len(log_output), 4): + if i + 3 < len(log_output) and len(log) < max_count: + log.append( + f"Commit: {log_output[i]}\n" + f"Author: {log_output[i+1]}\n" + f"Date: {log_output[i+2]}\n" + f"Message: {log_output[i+3]}\n" + ) + return log + else: + # Use existing logic for simple log without date filtering + commits = list(repo.iter_commits(max_count=max_count)) + log = [] + for commit in commits: + log.append( + f"Commit: {commit.hexsha!r}\n" + f"Author: {commit.author!r}\n" + f"Date: {commit.authored_datetime}\n" + f"Message: {commit.message!r}\n" + ) + return log def git_create_branch(repo: git.Repo, branch_name: str, base_branch: str | None = None) -> str: if base_branch: @@ -203,6 +236,7 @@ def git_branch(repo: git.Repo, branch_type: str, contains: str | None = None, no return branch_info + async def serve(repository: Path | None) -> None: logger = logging.getLogger(__name__) @@ -283,6 +317,7 @@ async def serve(repository: Path | None) -> None: name=GitTools.BRANCH, description="List Git branches", inputSchema=GitBranch.model_json_schema(), + ) ] @@ -380,13 +415,19 @@ async def serve(repository: Path | None) -> None: text=result )] + # Update the LOG case: case GitTools.LOG: - log = git_log(repo, arguments.get("max_count", 10)) + log = git_log( + repo, + arguments.get("max_count", 10), + arguments.get("start_timestamp"), + arguments.get("end_timestamp") + ) return [TextContent( type="text", text="Commit history:\n" + "\n".join(log) )] - + case GitTools.CREATE_BRANCH: result = git_create_branch( repo, @@ -423,7 +464,7 @@ async def serve(repository: Path | None) -> None: type="text", text=result )] - + case _: raise ValueError(f"Unknown tool: {name}") From 1445af12f45ae64fdf43509fbbf90ae80b653961 Mon Sep 17 00:00:00 2001 From: Stefano Amorelli Date: Mon, 25 Aug 2025 20:27:33 +0300 Subject: [PATCH 08/13] feat: add companies house mcp (#2613) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f466376..d47ebff 100644 --- a/README.md +++ b/README.md @@ -575,6 +575,7 @@ A growing set of community-developed and maintained servers demonstrates various - **[coin_api_mcp](https://github.com/longmans/coin_api_mcp)** - Provides access to [coinmarketcap](https://coinmarketcap.com/) cryptocurrency data. - **[CoinMarketCap](https://github.com/shinzo-labs/coinmarketcap-mcp)** - Implements the complete [CoinMarketCap](https://coinmarketcap.com/) API for accessing cryptocurrency market data, exchange information, and other blockchain-related metrics. - **[commands](https://github.com/g0t4/mcp-server-commands)** - Run commands and scripts. Just like in a terminal. +- **[Companies House MCP](https://github.com/stefanoamorelli/companies-house-mcp)** (by Stefano Amorelli) - MCP server to connect with the UK Companies House API. - **[computer-control-mcp](https://github.com/AB498/computer-control-mcp)** - MCP server that provides computer control capabilities, like mouse, keyboard, OCR, etc. using PyAutoGUI, RapidOCR, ONNXRuntime Without External Dependencies. - **[Computer-Use - Remote MacOS Use](https://github.com/baryhuang/mcp-remote-macos-use)** - Open-source out-of-the-box alternative to OpenAI Operator, providing a full desktop experience and optimized for using remote macOS machines as autonomous AI agents. - **[Congress.gov API](https://github.com/AshwinSundar/congress_gov_mcp)** - An MCP server to interact with real-time data from the Congress.gov API, which is the official API for the United States Congress. From 43a625917f5f99fe8040275ed8ba5f501a4b1464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernesto=20Garc=C3=ADa?= Date: Mon, 25 Aug 2025 13:28:40 -0400 Subject: [PATCH 09/13] Add official Todoist MCP server to README (#2612) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d47ebff..f0771e3 100644 --- a/README.md +++ b/README.md @@ -414,6 +414,7 @@ Official integrations are maintained by companies building production ready MCP - TiDB Logo **[TiDB](https://github.com/pingcap/pytidb)** - MCP Server to interact with TiDB database platform. - Tinybird Logo **[Tinybird](https://github.com/tinybirdco/mcp-tinybird)** - Interact with Tinybird serverless ClickHouse platform - Tldv Logo **[Tldv](https://gitlab.com/tldv/tldv-mcp-server)** - Connect your AI agents to Google-Meet, Zoom & Microsoft Teams through [tl;dv](https://tldv.io) +- Todoist Logo **[Todoist](https://github.com/doist/todoist-ai)** - Search, add, and update [Todoist](https://todoist.com) tasks, projects, sections, comments, and more. - Token Metrics Logo **[Token Metrics](https://github.com/token-metrics/mcp)** - [Token Metrics](https://www.tokenmetrics.com/) integration for fetching real-time crypto market data, trading signals, price predictions, and advanced analytics. - TomTom Logo **[TomTom-MCP](https://github.com/tomtom-international/tomtom-mcp)** - The [TomTom](https://www.tomtom.com/) MCP Server simplifies geospatial development by providing seamless access to TomTom's location services, including search, routing, traffic and static maps data. - Trade Agent Logo **[Trade Agent](https://github.com/Trade-Agent/trade-agent-mcp)** - Execute stock and crypto trades on your brokerage via [Trade Agent](https://thetradeagent.ai) From 666cba47d52d35fe6409719328d0c9a1ce5cf6b4 Mon Sep 17 00:00:00 2001 From: Denis Bondarenko <59018563+Scoteezy@users.noreply.github.com> Date: Mon, 25 Aug 2025 20:31:00 +0300 Subject: [PATCH 10/13] Add triplyfy-mcp to community servers list (#2616) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f0771e3..d0c2c91 100644 --- a/README.md +++ b/README.md @@ -1157,6 +1157,7 @@ A growing set of community-developed and maintained servers demonstrates various - **[Trello MCP Server](https://github.com/lioarce01/trello-mcp-server)** - An MCP server that interact with user Trello boards, modifying them with prompting. - **[Trino](https://github.com/tuannvm/mcp-trino)** - A high-performance Model Context Protocol (MCP) server for Trino implemented in Go. - **[Tripadvisor](https://github.com/pab1it0/tripadvisor-mcp)** - An MCP server that enables LLMs to interact with Tripadvisor API, supporting location data, reviews, and photos through standardized MCP interfaces +- **[Triplyfy MCP](https://github.com/helpful-AIs/triplyfy-mcp)** - An MCP server that lets LLMs plan and manage itineraries with interactive maps in Triplyfy; manage itineraries, places and notes, and search/save flights. - **[TrueNAS Core MCP](https://github.com/vespo92/TrueNasCoreMCP)** - An MCP server for interacting with TrueNAS Core. - **[TuriX Computer Automation MCP](https://github.com/TurixAI/TuriX-CUA/tree/mac_mcp)** - MCP server for helping automation control your computer complete your pre-setting task. - **[Tyk API Management](https://github.com/TykTechnologies/tyk-dashboard-mcp)** - Chat with all of your organization's managed APIs and perform other API lifecycle operations, managing tokens, users, analytics, and more. From c8fe7d995b99fda79131d2d474422f12c1b3aa02 Mon Sep 17 00:00:00 2001 From: Tosin Akinosho Date: Mon, 25 Aug 2025 13:31:29 -0400 Subject: [PATCH 11/13] feat(readme): add documcp to community servers list (#2614) Co-authored-by: Claude Co-authored-by: adam jones --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d0c2c91..63039d1 100644 --- a/README.md +++ b/README.md @@ -636,6 +636,7 @@ A growing set of community-developed and maintained servers demonstrates various - **[Docker](https://github.com/ckreiling/mcp-server-docker)** - Integrate with Docker to manage containers, images, volumes, and networks. - **[Docker](https://github.com/0xshariq/docker-mcp-server)** - Docker MCP Server provides advanced, unified Docker management via CLI and MCP workflows, supporting containers, images, volumes, networks, and orchestration. - **[Docs](https://github.com/da1z/docsmcp)** - Enable documentation access for the AI agent, supporting llms.txt and other remote or local files. +- **[documcp](https://github.com/tosin2013/documcp)** - An MCP server for intelligent document processing and management, supporting multiple formats and document operations. - **[Docy](https://github.com/oborchers/mcp-server-docy)** - Docy gives your AI direct access to the technical documentation it needs, right when it needs it. No more outdated information, broken links, or rate limits - just accurate, real-time documentation access for more precise coding assistance. - **[Dodo Payments](https://github.com/dodopayments/dodopayments-node/tree/main/packages/mcp-server)** - Enables AI agents to securely perform payment operations via a lightweight, serverless-compatible interface to the [Dodo Payments](https://dodopayments.com) API. - **[Domain Tools](https://github.com/deshabhishek007/domain-tools-mcp-server)** - A Model Context Protocol (MCP) server for comprehensive domain analysis: WHOIS, DNS records, and DNS health checks. From 414f98c35ed7e513480fe2fd0a999bb784b2bcd0 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:42:12 +0000 Subject: [PATCH 12/13] Apply review feedback: improve language accessibility and add MCP protocol features guidance - Replace 'Ergonomic improvements' with 'Usability improvements' for better accessibility - Add guidance encouraging enhancements that demonstrate underutilized MCP protocol features Co-authored-by: adam jones --- CONTRIBUTING.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1dfbc4b..4f47551 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,10 +12,11 @@ We welcome PRs that add links to your servers in the [README.md](./README.md)! We welcome: - **Bug fixes** — Help us squash those pesky bugs. -- **Ergonomic improvements** — Making servers easier to use for humans and agents. +- **Usability improvements** — Making servers easier to use for humans and agents. We're more selective about: - **New features** — Especially if they're not crucial to the server's core purpose or are highly opinionated. The existing servers are reference servers meant to inspire the community. If you need specific features, we encourage you to build enhanced versions! We think a diverse ecosystem of servers is beneficial for everyone, and would love to link to your improved server in our README. +- **Enhancements that demonstrate MCP protocol features** — We encourage contributions that help reference servers better illustrate underutilized aspects of the MCP protocol beyond just Tools, such as Resources, Prompts, or Roots. For example, adding Roots support to filesystem-server helps showcase this important but lesser-known feature. We don't accept: - **New server implementations** — We encourage you to publish them yourself, and link to them from the README. From 9b6892dc9abc045471b2df8773c69fdb8abb2828 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:45:48 +0000 Subject: [PATCH 13/13] Reorganize CONTRIBUTING.md: move MCP protocol features to 'we welcome' section and rename to 'other new features' Co-authored-by: adam jones --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f47551..7a10a22 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,10 +13,10 @@ We welcome PRs that add links to your servers in the [README.md](./README.md)! We welcome: - **Bug fixes** — Help us squash those pesky bugs. - **Usability improvements** — Making servers easier to use for humans and agents. +- **Enhancements that demonstrate MCP protocol features** — We encourage contributions that help reference servers better illustrate underutilized aspects of the MCP protocol beyond just Tools, such as Resources, Prompts, or Roots. For example, adding Roots support to filesystem-server helps showcase this important but lesser-known feature. We're more selective about: -- **New features** — Especially if they're not crucial to the server's core purpose or are highly opinionated. The existing servers are reference servers meant to inspire the community. If you need specific features, we encourage you to build enhanced versions! We think a diverse ecosystem of servers is beneficial for everyone, and would love to link to your improved server in our README. -- **Enhancements that demonstrate MCP protocol features** — We encourage contributions that help reference servers better illustrate underutilized aspects of the MCP protocol beyond just Tools, such as Resources, Prompts, or Roots. For example, adding Roots support to filesystem-server helps showcase this important but lesser-known feature. +- **Other new features** — Especially if they're not crucial to the server's core purpose or are highly opinionated. The existing servers are reference servers meant to inspire the community. If you need specific features, we encourage you to build enhanced versions! We think a diverse ecosystem of servers is beneficial for everyone, and would love to link to your improved server in our README. We don't accept: - **New server implementations** — We encourage you to publish them yourself, and link to them from the README.