From 7aa602f102b9a81687991c555355c38d50dcdeb9 Mon Sep 17 00:00:00 2001 From: Vishal Mysore Date: Sat, 10 May 2025 10:31:36 -0400 Subject: [PATCH 01/30] a2a-mcp bridge A2AJava has built-in support for Model Context Protocol (MCP) using intuitive Java annotations, this project serves as an excellent starting point for building MCP-compliant servers in Java. Developers can quickly define, expose, and orchestrate agent skills and actions within a shared context, enabling powerful, multi-agent workflows with minimal boilerplate --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bdc5228..c3e72526 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,8 @@ Official integrations are maintained by companies building production ready MCP A growing set of community-developed and maintained servers demonstrates various applications of MCP across different domains. > **Note:** Community servers are **untested** and should be used at **your own risk**. They are not affiliated with or endorsed by Anthropic. -- **[Ableton Live](https://github.com/Simon-Kansara/ableton-live-mcp-server)** - an MCP server to control Ableton Live. +- **[A2A-MCP Java Bridge](https://github.com/vishalmysore/a2ajava)** - A2AJava brings powerful A2A-MCP integration directly into your Java applications. It enables developers to annotate standard Java methods and instantly expose them as MCP Server, A2A-discoverable actions — with no boilerplate or service registration overhead. +- **[Ableton Live](https://github.com/Simon-Kansara/ableton-live-mcp-server)** - an MCP server to control Ableton Live.- - **[Airbnb](https://github.com/openbnb-org/mcp-server-airbnb)** - Provides tools to search Airbnb and get listing details. - **[AI Agent Marketplace Index](https://github.com/AI-Agent-Hub/ai-agent-marketplace-index-mcp)** - MCP server to search more than 5000+ AI agents and tools of various categories from [AI Agent Marketplace Index](http://www.deepnlp.org/store/ai-agent) and monitor traffic of AI Agents. - **[Algorand](https://github.com/GoPlausible/algorand-mcp)** - A comprehensive MCP server for tooling interactions (40+) and resource accessibility (60+) plus many useful prompts for interacting with the Algorand blockchain. From 1e101ba33e6b40ec0d81badc8917763d4beb4c91 Mon Sep 17 00:00:00 2001 From: Vishal Mysore Date: Fri, 13 Jun 2025 17:22:24 -0400 Subject: [PATCH 02/30] added a2ajava in resources section --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cfc3c1a4..874043b2 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,6 @@ A growing set of community-developed and maintained servers demonstrates various > **Note:** Community servers are **untested** and should be used at **your own risk**. They are not affiliated with or endorsed by Anthropic. -- **[A2A-MCP Java Bridge](https://github.com/vishalmysore/a2ajava)** - A2AJava brings powerful A2A-MCP integration directly into your Java applications. It enables developers to annotate standard Java methods and instantly expose them as MCP Server, A2A-discoverable actions — with no boilerplate or service registration overhead. - **[Ableton Live](https://github.com/Simon-Kansara/ableton-live-mcp-server)** - an MCP server to control Ableton Live.- - **[Ableton Live](https://github.com/ahujasid/ableton-mcp)** (by ahujasid) - Ableton integration allowing prompt enabled music creation. - **[Airbnb](https://github.com/openbnb-org/mcp-server-airbnb)** - Provides tools to search Airbnb and get listing details. @@ -568,6 +567,7 @@ These are high-level frameworks that make it easier to build MCP servers or clie Additional resources on MCP. +- **[A2A-MCP Java Bridge](https://github.com/vishalmysore/a2ajava)** - A2AJava brings powerful A2A-MCP integration directly into your Java applications. It enables developers to annotate standard Java methods and instantly expose them as MCP Server, A2A-discoverable actions — with no boilerplate or service registration overhead. - **[AiMCP](https://www.aimcp.info)** - A collection of MCP clients&servers to find the right mcp tools by **[Hekmon](https://github.com/hekmon8)** - **[Awesome Crypto MCP Servers by badkk](https://github.com/badkk/awesome-crypto-mcp-servers)** - A curated list of MCP servers by **[Luke Fan](https://github.com/badkk)** - **[Awesome MCP Servers by appcypher](https://github.com/appcypher/awesome-mcp-servers)** - A curated list of MCP servers by **[Stephen Akinyemi](https://github.com/appcypher)** From 11a064c359d44e4197694ba4dde72f6fe79ad101 Mon Sep 17 00:00:00 2001 From: Cliff Hall Date: Fri, 18 Jul 2025 13:42:56 -0400 Subject: [PATCH 03/30] Rename read_file to read_text_file and add read_media_file --- src/filesystem/README.md | 14 ++++++++-- src/filesystem/index.ts | 60 ++++++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/filesystem/README.md b/src/filesystem/README.md index cd6d0a9f..2ec65400 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -70,10 +70,18 @@ The server's directory access control follows this flow: ### Tools -- **read_file** - - Read complete contents of a file +- **read_text_file** + - Read complete contents of a file as text + - Inputs: + - `path` (string) + - `head` (number, optional): First N lines + - `tail` (number, optional): Last N lines + - Always treats the file as UTF-8 text regardless of extension + +- **read_media_file** + - Read an image or audio file - Input: `path` (string) - - Reads complete file contents with UTF-8 encoding + - Returns base64 data and MIME type based on the file extension - **read_multiple_files** - Read multiple files simultaneously diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index 524c9c26..3fc39fec 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -116,12 +116,16 @@ async function validatePath(requestedPath: string): Promise { } // Schema definitions -const ReadFileArgsSchema = z.object({ +const ReadTextFileArgsSchema = z.object({ path: z.string(), tail: z.number().optional().describe('If provided, returns only the last N lines of the file'), head: z.number().optional().describe('If provided, returns only the first N lines of the file') }); +const ReadMediaFileArgsSchema = z.object({ + path: z.string() +}); + const ReadMultipleFilesArgsSchema = z.object({ paths: z.array(z.string()), }); @@ -476,15 +480,23 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { - name: "read_file", + name: "read_text_file", description: - "Read the complete contents of a file from the file system. " + + "Read the complete contents of a file from the file system as text. " + "Handles various text encodings and provides detailed error messages " + "if the file cannot be read. Use this tool when you need to examine " + "the contents of a single file. Use the 'head' parameter to read only " + "the first N lines of a file, or the 'tail' parameter to read only " + - "the last N lines of a file. Only works within allowed directories.", - inputSchema: zodToJsonSchema(ReadFileArgsSchema) as ToolInput, + "the last N lines of a file. Operates on the file as text regardless of extension. " + + "Only works within allowed directories.", + inputSchema: zodToJsonSchema(ReadTextFileArgsSchema) as ToolInput, + }, + { + name: "read_media_file", + description: + "Read an image or audio file. Returns the base64 encoded data and MIME type. " + + "Only works within allowed directories.", + inputSchema: zodToJsonSchema(ReadMediaFileArgsSchema) as ToolInput, }, { name: "read_multiple_files", @@ -597,10 +609,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; switch (name) { - case "read_file": { - const parsed = ReadFileArgsSchema.safeParse(args); + case "read_text_file": { + const parsed = ReadTextFileArgsSchema.safeParse(args); if (!parsed.success) { - throw new Error(`Invalid arguments for read_file: ${parsed.error}`); + throw new Error(`Invalid arguments for read_text_file: ${parsed.error}`); } const validPath = await validatePath(parsed.data.path); @@ -630,6 +642,38 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { }; } + case "read_media_file": { + const parsed = ReadMediaFileArgsSchema.safeParse(args); + if (!parsed.success) { + throw new Error(`Invalid arguments for read_media_file: ${parsed.error}`); + } + const validPath = await validatePath(parsed.data.path); + const extension = path.extname(validPath).toLowerCase(); + const mimeTypes: Record = { + ".png": "image/png", + ".jpg": "image/jpeg", + ".jpeg": "image/jpeg", + ".gif": "image/gif", + ".webp": "image/webp", + ".bmp": "image/bmp", + ".svg": "image/svg+xml", + ".mp3": "audio/mpeg", + ".wav": "audio/wav", + ".ogg": "audio/ogg", + ".flac": "audio/flac", + }; + const mimeType = mimeTypes[extension] || "application/octet-stream"; + const data = (await fs.readFile(validPath)).toString("base64"); + const type = mimeType.startsWith("image/") + ? "image" + : mimeType.startsWith("audio/") + ? "audio" + : "blob"; + return { + content: [{ type, data, mimeType } as any], + }; + } + case "read_multiple_files": { const parsed = ReadMultipleFilesArgsSchema.safeParse(args); if (!parsed.success) { From d532a5846d3418ae6748ef1a7ae0c333116ff75b Mon Sep 17 00:00:00 2001 From: Cliff Hall Date: Fri, 18 Jul 2025 14:18:32 -0400 Subject: [PATCH 04/30] Stream media file reads --- src/filesystem/README.md | 2 +- src/filesystem/index.ts | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/filesystem/README.md b/src/filesystem/README.md index 2ec65400..5552e398 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -81,7 +81,7 @@ The server's directory access control follows this flow: - **read_media_file** - Read an image or audio file - Input: `path` (string) - - Returns base64 data and MIME type based on the file extension + - Streams the file and returns base64 data with the corresponding MIME type - **read_multiple_files** - Read multiple files simultaneously diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index 3fc39fec..f3254bc9 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -10,6 +10,7 @@ import { type Root, } from "@modelcontextprotocol/sdk/types.js"; import fs from "fs/promises"; +import { createReadStream } from "fs"; import path from "path"; import os from 'os'; import { randomBytes } from 'crypto'; @@ -475,6 +476,21 @@ async function headFile(filePath: string, numLines: number): Promise { } } +// Stream a file and return its Base64 representation without loading the +// entire file into memory at once. Chunks are encoded individually and +// concatenated into the final string. +async function readFileAsBase64Stream(filePath: string): Promise { + return new Promise((resolve, reject) => { + const stream = createReadStream(filePath, { encoding: 'base64' }); + let data = ''; + stream.on('data', (chunk) => { + data += chunk; + }); + stream.on('end', () => resolve(data)); + stream.on('error', (err) => reject(err)); + }); +} + // Tool handlers server.setRequestHandler(ListToolsRequestSchema, async () => { return { @@ -663,7 +679,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { ".flac": "audio/flac", }; const mimeType = mimeTypes[extension] || "application/octet-stream"; - const data = (await fs.readFile(validPath)).toString("base64"); + const data = await readFileAsBase64Stream(validPath); const type = mimeType.startsWith("image/") ? "image" : mimeType.startsWith("audio/") From 2feb7cbaa5feb35af48078c6c4e0fae5605d119b Mon Sep 17 00:00:00 2001 From: Cliff Hall Date: Fri, 18 Jul 2025 16:03:22 -0400 Subject: [PATCH 05/30] Update src/filesystem/README.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/filesystem/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/filesystem/README.md b/src/filesystem/README.md index 5552e398..89bca690 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -80,7 +80,8 @@ The server's directory access control follows this flow: - **read_media_file** - Read an image or audio file - - Input: `path` (string) + - Inputs: + - `path` (string) - Streams the file and returns base64 data with the corresponding MIME type - **read_multiple_files** From ba20bd60af827722652e5b82ce6c2819de0ccdba Mon Sep 17 00:00:00 2001 From: cliffhall Date: Fri, 18 Jul 2025 16:09:56 -0400 Subject: [PATCH 06/30] Update the way the stream is concatenated Update the ts sdk --- package-lock.json | 9 +++-- src/filesystem/index.ts | 77 +++++++++++++++++++------------------ src/filesystem/package.json | 4 +- 3 files changed, 47 insertions(+), 43 deletions(-) diff --git a/package-lock.json b/package-lock.json index c785a237..38a2fe5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6159,7 +6159,7 @@ "version": "0.6.2", "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.12.3", + "@modelcontextprotocol/sdk": "^1.16.0", "diff": "^5.1.0", "glob": "^10.3.10", "minimatch": "^10.0.1", @@ -6182,9 +6182,9 @@ } }, "src/filesystem/node_modules/@modelcontextprotocol/sdk": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.12.3.tgz", - "integrity": "sha512-DyVYSOafBvk3/j1Oka4z5BWT8o4AFmoNyZY9pALOm7Lh3GZglR71Co4r4dEUoqDWdDazIZQHBe7J2Nwkg6gHgQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.16.0.tgz", + "integrity": "sha512-8ofX7gkZcLj9H9rSd50mCgm3SSF8C7XoclxJuLoV0Cz3rEQ1tv9MZRYYvJtm9n1BiEQQMzSmE/w2AEkNacLYfg==", "license": "MIT", "dependencies": { "ajv": "^6.12.6", @@ -6192,6 +6192,7 @@ "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^5.0.0", diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index f3254bc9..01d6c638 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -379,10 +379,10 @@ async function applyFileEdits( function formatSize(bytes: number): string { const units = ['B', 'KB', 'MB', 'GB', 'TB']; if (bytes === 0) return '0 B'; - + const i = Math.floor(Math.log(bytes) / Math.log(1024)); if (i === 0) return `${bytes} ${units[i]}`; - + return `${(bytes / Math.pow(1024, i)).toFixed(2)} ${units[i]}`; } @@ -391,9 +391,9 @@ async function tailFile(filePath: string, numLines: number): Promise { const CHUNK_SIZE = 1024; // Read 1KB at a time const stats = await fs.stat(filePath); const fileSize = stats.size; - + if (fileSize === 0) return ''; - + // Open file for reading const fileHandle = await fs.open(filePath, 'r'); try { @@ -402,36 +402,36 @@ async function tailFile(filePath: string, numLines: number): Promise { let chunk = Buffer.alloc(CHUNK_SIZE); let linesFound = 0; let remainingText = ''; - + // Read chunks from the end of the file until we have enough lines while (position > 0 && linesFound < numLines) { const size = Math.min(CHUNK_SIZE, position); position -= size; - + const { bytesRead } = await fileHandle.read(chunk, 0, size, position); if (!bytesRead) break; - + // Get the chunk as a string and prepend any remaining text from previous iteration const readData = chunk.slice(0, bytesRead).toString('utf-8'); const chunkText = readData + remainingText; - + // Split by newlines and count const chunkLines = normalizeLineEndings(chunkText).split('\n'); - + // If this isn't the end of the file, the first line is likely incomplete // Save it to prepend to the next chunk if (position > 0) { remainingText = chunkLines[0]; chunkLines.shift(); // Remove the first (incomplete) line } - + // Add lines to our result (up to the number we need) for (let i = chunkLines.length - 1; i >= 0 && linesFound < numLines; i--) { lines.unshift(chunkLines[i]); linesFound++; } } - + return lines.join('\n'); } finally { await fileHandle.close(); @@ -446,14 +446,14 @@ async function headFile(filePath: string, numLines: number): Promise { let buffer = ''; let bytesRead = 0; const chunk = Buffer.alloc(1024); // 1KB buffer - + // Read chunks and count lines until we have enough or reach EOF while (lines.length < numLines) { const result = await fileHandle.read(chunk, 0, chunk.length, bytesRead); if (result.bytesRead === 0) break; // End of file bytesRead += result.bytesRead; buffer += chunk.slice(0, result.bytesRead).toString('utf-8'); - + const newLineIndex = buffer.lastIndexOf('\n'); if (newLineIndex !== -1) { const completeLines = buffer.slice(0, newLineIndex).split('\n'); @@ -464,29 +464,32 @@ async function headFile(filePath: string, numLines: number): Promise { } } } - + // If there is leftover content and we still need lines, add it if (buffer.length > 0 && lines.length < numLines) { lines.push(buffer); } - + return lines.join('\n'); } finally { await fileHandle.close(); } } -// Stream a file and return its Base64 representation without loading the -// entire file into memory at once. Chunks are encoded individually and -// concatenated into the final string. +// Reads a file as a stream of buffers, concatenates them, and then encodes +// the result to a Base64 string. This is a memory-efficient way to handle +// binary data from a stream before the final encoding. async function readFileAsBase64Stream(filePath: string): Promise { return new Promise((resolve, reject) => { - const stream = createReadStream(filePath, { encoding: 'base64' }); - let data = ''; + const stream = createReadStream(filePath); + const chunks: Buffer[] = []; stream.on('data', (chunk) => { - data += chunk; + chunks.push(chunk as Buffer); + }); + stream.on('end', () => { + const finalBuffer = Buffer.concat(chunks); + resolve(finalBuffer.toString('base64')); }); - stream.on('end', () => resolve(data)); stream.on('error', (err) => reject(err)); }); } @@ -631,11 +634,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { throw new Error(`Invalid arguments for read_text_file: ${parsed.error}`); } const validPath = await validatePath(parsed.data.path); - + if (parsed.data.head && parsed.data.tail) { throw new Error("Cannot specify both head and tail parameters simultaneously"); } - + if (parsed.data.tail) { // Use memory-efficient tail implementation for large files const tailContent = await tailFile(validPath, parsed.data.tail); @@ -643,7 +646,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { content: [{ type: "text", text: tailContent }], }; } - + if (parsed.data.head) { // Use memory-efficient head implementation for large files const headContent = await headFile(validPath, parsed.data.head); @@ -651,7 +654,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { content: [{ type: "text", text: headContent }], }; } - + const content = await fs.readFile(validPath, "utf-8"); return { content: [{ type: "text", text: content }], @@ -686,7 +689,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { ? "audio" : "blob"; return { - content: [{ type, data, mimeType } as any], + content: [{ type, data, mimeType }], }; } @@ -794,7 +797,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { } const validPath = await validatePath(parsed.data.path); const entries = await fs.readdir(validPath, { withFileTypes: true }); - + // Get detailed information for each entry const detailedEntries = await Promise.all( entries.map(async (entry) => { @@ -817,7 +820,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { } }) ); - + // Sort entries based on sortBy parameter const sortedEntries = [...detailedEntries].sort((a, b) => { if (parsed.data.sortBy === 'size') { @@ -826,29 +829,29 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { // Default sort by name return a.name.localeCompare(b.name); }); - + // Format the output - const formattedEntries = sortedEntries.map(entry => + const formattedEntries = sortedEntries.map(entry => `${entry.isDirectory ? "[DIR]" : "[FILE]"} ${entry.name.padEnd(30)} ${ entry.isDirectory ? "" : formatSize(entry.size).padStart(10) }` ); - + // Add summary const totalFiles = detailedEntries.filter(e => !e.isDirectory).length; const totalDirs = detailedEntries.filter(e => e.isDirectory).length; const totalSize = detailedEntries.reduce((sum, entry) => sum + (entry.isDirectory ? 0 : entry.size), 0); - + const summary = [ "", `Total: ${totalFiles} files, ${totalDirs} directories`, `Combined size: ${formatSize(totalSize)}` ]; - + return { - content: [{ - type: "text", - text: [...formattedEntries, ...summary].join("\n") + content: [{ + type: "text", + text: [...formattedEntries, ...summary].join("\n") }], }; } diff --git a/src/filesystem/package.json b/src/filesystem/package.json index 482f0cce..8176babf 100644 --- a/src/filesystem/package.json +++ b/src/filesystem/package.json @@ -20,7 +20,7 @@ "test": "jest --config=jest.config.cjs --coverage" }, "dependencies": { - "@modelcontextprotocol/sdk": "^1.12.3", + "@modelcontextprotocol/sdk": "^1.16.0", "diff": "^5.1.0", "glob": "^10.3.10", "minimatch": "^10.0.1", @@ -38,4 +38,4 @@ "ts-node": "^10.9.2", "typescript": "^5.8.2" } -} \ No newline at end of file +} From 83bcd31032408a1e9fd33fa55a0272534ea52be0 Mon Sep 17 00:00:00 2001 From: Vishal Mysore Date: Sun, 20 Jul 2025 09:28:28 -0400 Subject: [PATCH 07/30] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 91bc8b87..a7730561 100644 --- a/README.md +++ b/README.md @@ -276,7 +276,6 @@ Official integrations are maintained by companies building production ready MCP A growing set of community-developed and maintained servers demonstrates various applications of MCP across different domains. > **Note:** Community servers are **untested** and should be used at **your own risk**. They are not affiliated with or endorsed by Anthropic. -- **[Ableton Live](https://github.com/Simon-Kansara/ableton-live-mcp-server)** - an MCP server to control Ableton Live.- - **[1Panel](https://github.com/1Panel-dev/mcp-1panel)** - MCP server implementation that provides 1Panel interaction. - **[A2A](https://github.com/GongRzhe/A2A-MCP-Server)** - An MCP server that bridges the Model Context Protocol (MCP) with the Agent-to-Agent (A2A) protocol, enabling MCP-compatible AI assistants (like Claude) to seamlessly interact with A2A agents. - **[Ableton Live](https://github.com/Simon-Kansara/ableton-live-mcp-server)** - an MCP server to control Ableton Live. From da8d67a57633e97e97129e94585dba59dbaa1edd Mon Sep 17 00:00:00 2001 From: simonpcouch Date: Mon, 21 Jul 2025 09:37:42 -0500 Subject: [PATCH 08/30] add R SDK/server --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dda39abc..cf36bf7f 100644 --- a/README.md +++ b/README.md @@ -853,6 +853,7 @@ A growing set of community-developed and maintained servers demonstrates various - **[Quarkus](https://github.com/quarkiverse/quarkus-mcp-servers)** - MCP servers for the Quarkus Java framework. - **[QuickChart](https://github.com/GongRzhe/Quickchart-MCP-Server)** - A Model Context Protocol server for generating charts using QuickChart.io - **[Qwen_Max](https://github.com/66julienmartin/MCP-server-Qwen_Max)** - A Model Context Protocol (MCP) server implementation for the Qwen models. +- **[R](https://github.com/posit-dev/mcptools)** - An R SDK for creating R-based MCP servers and retrieving functionality from third-party MCP servers as R functions. - **[RabbitMQ](https://github.com/kenliao94/mcp-server-rabbitmq)** - The MCP server that interacts with RabbitMQ to publish and consume messages. - **[RAE](https://github.com/rae-api-com/rae-mcp)** - MPC Server to connect your preferred model with rae-api.com, Roya Academy of Spanish Dictionary - **[RAG Local](https://github.com/renl/mcp-rag-local)** - This MCP server for storing and retrieving text passages locally based on their semantic meaning. From 8f0eee490ddb6ed7cced6bad7bf7fdf3d81e22a0 Mon Sep 17 00:00:00 2001 From: Rob Heckel <8441943+billabongrob@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:34:23 -0500 Subject: [PATCH 09/30] Removing Duplicate Memgraph entry There is a second instance of Memgraph that was pointing to an archived repository. It makes sense to keep one to avoid confusion. --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 691882a0..06070974 100644 --- a/README.md +++ b/README.md @@ -231,7 +231,6 @@ Official integrations are maintained by companies building production ready MCP - mcp-discovery logo **[MCP Discovery](https://github.com/rust-mcp-stack/mcp-discovery)** - A lightweight CLI tool built in Rust for discovering MCP server capabilities. - MCP Toolbox for Databases Logo **[MCP Toolbox for Databases](https://github.com/googleapis/genai-toolbox)** - Open source MCP server specializing in easy, fast, and secure tools for Databases. Supports AlloyDB, BigQuery, Bigtable, Cloud SQL, Dgraph, MySQL, Neo4j, Postgres, Spanner, and more. - Meilisearch Logo **[Meilisearch](https://github.com/meilisearch/meilisearch-mcp)** - Interact & query with Meilisearch (Full-text & semantic search API) -- Memgraph Logo **[Memgraph](https://github.com/memgraph/mcp-memgraph)** - Query your data in [Memgraph](https://memgraph.com/) graph database. - Memgraph Logo **[Memgraph](https://github.com/memgraph/ai-toolkit/tree/main/integrations/mcp-memgraph)** - Query your data in [Memgraph](https://memgraph.com/) graph database. - MercadoPago Logo **[Mercado Pago](https://mcp.mercadopago.com/)** - Mercado Pago's official MCP server. - Metoro Logo **[Metoro](https://github.com/metoro-io/metoro-mcp-server)** - Query and interact with kubernetes environments monitored by Metoro @@ -382,7 +381,6 @@ A growing set of community-developed and maintained servers demonstrates various - **[Ableton Live](https://github.com/ahujasid/ableton-mcp)** (by ahujasid) - Ableton integration allowing prompt enabled music creation. - **[Actor Critic Thinking](https://github.com/aquarius-wing/actor-critic-thinking-mcp)** - Actor-critic thinking for performance evaluation - **[AgentBay](https://github.com/Michael98671/agentbay)** - An MCP server for providing serverless cloud infrastructure for AI agents. -- **[AgentMode](https://www.agentmode.app) - Connect to dozens of databases, data warehouses, Github & more, from a single MCP server. Run the Docker image locally, in the cloud, or on-premise. - **[AI Agent Marketplace Index](https://github.com/AI-Agent-Hub/ai-agent-marketplace-index-mcp)** - MCP server to search more than 5000+ AI agents and tools of various categories from [AI Agent Marketplace Index](http://www.deepnlp.org/store/ai-agent) and monitor traffic of AI Agents. - **[AI Tasks](https://github.com/jbrinkman/valkey-ai-tasks)** - Let the AI manage complex plans with integrated task management and tracking tools. Supports STDIO, SSE and Streamable HTTP transports. - **[ai-Bible](https://github.com/AdbC99/ai-bible)** - Search the bible reliably and repeatably [ai-Bible Labs](https://ai-bible.com) From deeb573bb51579de083c75e0c21af5dd3def2e59 Mon Sep 17 00:00:00 2001 From: Rob Heckel <8441943+billabongrob@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:02:57 -0500 Subject: [PATCH 10/30] Update README.md Putting - **[AgentMode](https://www.agentmode.app) - Connect to dozens of databases, data warehouses, Github & more, from a single MCP server. Run the Docker image locally, in the cloud, or on-premise. back --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 55734b14..0410eb4d 100644 --- a/README.md +++ b/README.md @@ -383,6 +383,7 @@ A growing set of community-developed and maintained servers demonstrates various - **[Ableton Live](https://github.com/ahujasid/ableton-mcp)** (by ahujasid) - Ableton integration allowing prompt enabled music creation. - **[Actor Critic Thinking](https://github.com/aquarius-wing/actor-critic-thinking-mcp)** - Actor-critic thinking for performance evaluation - **[AgentBay](https://github.com/Michael98671/agentbay)** - An MCP server for providing serverless cloud infrastructure for AI agents. +- **[AgentMode](https://www.agentmode.app) - Connect to dozens of databases, data warehouses, Github & more, from a single MCP server. Run the Docker image locally, in the cloud, or on-premise. - **[AI Agent Marketplace Index](https://github.com/AI-Agent-Hub/ai-agent-marketplace-index-mcp)** - MCP server to search more than 5000+ AI agents and tools of various categories from [AI Agent Marketplace Index](http://www.deepnlp.org/store/ai-agent) and monitor traffic of AI Agents. - **[AI Tasks](https://github.com/jbrinkman/valkey-ai-tasks)** - Let the AI manage complex plans with integrated task management and tracking tools. Supports STDIO, SSE and Streamable HTTP transports. - **[ai-Bible](https://github.com/AdbC99/ai-bible)** - Search the bible reliably and repeatably [ai-Bible Labs](https://ai-bible.com) From 72b2ddebcdd3880230d6617664677a9e93a139e2 Mon Sep 17 00:00:00 2001 From: simonpcouch Date: Tue, 22 Jul 2025 10:46:23 -0500 Subject: [PATCH 11/30] relocate R SDK/server entry Transitions entry from Community Servers -> Frameworks --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cf36bf7f..c834a818 100644 --- a/README.md +++ b/README.md @@ -853,7 +853,6 @@ A growing set of community-developed and maintained servers demonstrates various - **[Quarkus](https://github.com/quarkiverse/quarkus-mcp-servers)** - MCP servers for the Quarkus Java framework. - **[QuickChart](https://github.com/GongRzhe/Quickchart-MCP-Server)** - A Model Context Protocol server for generating charts using QuickChart.io - **[Qwen_Max](https://github.com/66julienmartin/MCP-server-Qwen_Max)** - A Model Context Protocol (MCP) server implementation for the Qwen models. -- **[R](https://github.com/posit-dev/mcptools)** - An R SDK for creating R-based MCP servers and retrieving functionality from third-party MCP servers as R functions. - **[RabbitMQ](https://github.com/kenliao94/mcp-server-rabbitmq)** - The MCP server that interacts with RabbitMQ to publish and consume messages. - **[RAE](https://github.com/rae-api-com/rae-mcp)** - MPC Server to connect your preferred model with rae-api.com, Roya Academy of Spanish Dictionary - **[RAG Local](https://github.com/renl/mcp-rag-local)** - This MCP server for storing and retrieving text passages locally based on their semantic meaning. @@ -1037,6 +1036,7 @@ These are high-level frameworks that make it easier to build MCP servers or clie * **[mcp_sse (Elixir)](https://github.com/kEND/mcp_sse)** An SSE implementation in Elixir for rapidly creating MCP servers. * **[Next.js MCP Server Template](https://github.com/vercel-labs/mcp-for-next.js)** (Typescript) - A starter Next.js project that uses the MCP Adapter to allow MCP clients to connect and access resources. * **[Quarkus MCP Server SDK](https://github.com/quarkiverse/quarkus-mcp-server)** (Java) +- **[R mcptools](https://github.com/posit-dev/mcptools)** - An R SDK for creating R-based MCP servers and retrieving functionality from third-party MCP servers as R functions. * **[SAP ABAP MCP Server SDK](https://github.com/abap-ai/mcp)** - Build SAP ABAP based MCP servers. ABAP 7.52 based with 7.02 downport; runs on R/3 & S/4HANA on-premises, currently not cloud-ready. * **[Spring AI MCP Server](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html)** - Provides auto-configuration for setting up an MCP server in Spring Boot applications. * **[Template MCP Server](https://github.com/mcpdotdirect/template-mcp-server)** - A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure From 92af3f512664513370c75e55bbdbddc186ebaaa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ismael=20Trevi=C3=B1o?= <60386407+Ismola@users.noreply.github.com> Date: Wed, 23 Jul 2025 14:33:07 +0200 Subject: [PATCH 12/30] Fix AgentMode Section in Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c52b4ea..360a38f6 100644 --- a/README.md +++ b/README.md @@ -408,7 +408,7 @@ A growing set of community-developed and maintained servers demonstrates various - **[Ableton Live](https://github.com/ahujasid/ableton-mcp)** (by ahujasid) - Ableton integration allowing prompt enabled music creation. - **[Actor Critic Thinking](https://github.com/aquarius-wing/actor-critic-thinking-mcp)** - Actor-critic thinking for performance evaluation - **[AgentBay](https://github.com/Michael98671/agentbay)** - An MCP server for providing serverless cloud infrastructure for AI agents. -- **[AgentMode](https://www.agentmode.app) - Connect to dozens of databases, data warehouses, Github & more, from a single MCP server. Run the Docker image locally, in the cloud, or on-premise. +- **[AgentMode](https://www.agentmode.app)** - Connect to dozens of databases, data warehouses, Github & more, from a single MCP server. Run the Docker image locally, in the cloud, or on-premise. - **[AI Agent Marketplace Index](https://github.com/AI-Agent-Hub/ai-agent-marketplace-index-mcp)** - MCP server to search more than 5000+ AI agents and tools of various categories from [AI Agent Marketplace Index](http://www.deepnlp.org/store/ai-agent) and monitor traffic of AI Agents. - **[AI Tasks](https://github.com/jbrinkman/valkey-ai-tasks)** - Let the AI manage complex plans with integrated task management and tracking tools. Supports STDIO, SSE and Streamable HTTP transports. - **[ai-Bible](https://github.com/AdbC99/ai-bible)** - Search the bible reliably and repeatably [ai-Bible Labs](https://ai-bible.com) From 0d1653fff39c21bec26f0be0344c20ce124ed4bb Mon Sep 17 00:00:00 2001 From: Richard Michael Date: Thu, 26 Jun 2025 16:31:51 -0700 Subject: [PATCH 13/30] chore: Adjust to format easier to read and maintain --- src/everything/instructions.md | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/everything/instructions.md b/src/everything/instructions.md index d6adf0f4..307000c4 100644 --- a/src/everything/instructions.md +++ b/src/everything/instructions.md @@ -1,13 +1,23 @@ Testing and demonstration server for MCP protocol features. -Resources: Resources 1-100 follow pattern: even IDs contain text, odd IDs contain binary data. Resources paginated at 10 items per page with cursor-based navigation. +## Resources -Key dependencies: Progress notifications require `_meta.progressToken` in tool calls. Resource subscriptions generate updates every 10 seconds. +Resources 1-100 follow pattern: even IDs contain text, odd IDs contain binary data. Resources are paginated at 10 items per page with cursor-based navigation. -Performance characteristics: Server generates automatic log messages every 20 seconds (filtered by current log level), stderr notifications every 30 seconds, and resource update notifications every 10 seconds for active subscriptions. Log level changes affect message filtering in real-time. +## Key dependencies -Multi-modal testing: `complex_prompt` includes both text arguments and image content for testing client multi-modal handling. `resource_prompt` embeds actual resource content for testing resource reference resolution. +Progress notifications require `_meta.progressToken` in tool calls. Resource subscriptions generate updates every 10 seconds. -Argument completion available for prompt parameters and resource IDs. Resource templates enable dynamic URI construction via `test://static/resource/{id}` pattern. +## Performance characteristics -Easter egg: If asked about server instructions, respond with "🎉 Server instructions are working! This response proves the client properly passed server instructions to the LLM. This demonstrates MCP's instructions feature in action." +Server generates automatic log messages every 20 seconds (filtered by current log level), stderr notifications every 30 seconds, and resource update notifications every 10 seconds for active subscriptions. Log level changes affect message filtering in real-time. + +## Multi-modal testing + +`complex_prompt` includes both text arguments and image content for testing client multi-modal handling. `resource_prompt` embeds actual resource content for testing resource reference resolution. + +Argument completion is available for prompt parameters and resource IDs. Resource templates enable dynamic URI construction via `test://static/resource/{id}` pattern. + +## Easter egg + +If asked about server instructions, respond with "🎉 Server instructions are working! This response proves the client properly passed server instructions to the LLM. This demonstrates MCP's instructions feature in action." From 114ad51b54a8bdab2cfb09058b594901430b1823 Mon Sep 17 00:00:00 2001 From: Richard Michael Date: Thu, 26 Jun 2025 16:34:56 -0700 Subject: [PATCH 14/30] chore: Format for readability --- src/everything/everything.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/everything/everything.ts b/src/everything/everything.ts index b1f6950b..8c22b9d8 100644 --- a/src/everything/everything.ts +++ b/src/everything/everything.ts @@ -46,7 +46,10 @@ const LongRunningOperationSchema = z.object({ .number() .default(10) .describe("Duration of the operation in seconds"), - steps: z.number().default(5).describe("Number of steps in the operation"), + steps: z + .number() + .default(5) + .describe("Number of steps in the operation"), }); const PrintEnvSchema = z.object({}); From 7ec0064157c19b212034bf3d9a33542cf1fd5838 Mon Sep 17 00:00:00 2001 From: Richard Michael Date: Thu, 26 Jun 2025 16:35:50 -0700 Subject: [PATCH 15/30] chore: Code organization: completions follow all schema definitions --- src/everything/everything.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/everything/everything.ts b/src/everything/everything.ts index 8c22b9d8..372a4365 100644 --- a/src/everything/everything.ts +++ b/src/everything/everything.ts @@ -62,13 +62,6 @@ const SampleLLMSchema = z.object({ .describe("Maximum number of tokens to generate"), }); -// Example completion values -const EXAMPLE_COMPLETIONS = { - style: ["casual", "formal", "technical", "friendly"], - temperature: ["0", "0.5", "0.7", "1.0"], - resourceId: ["1", "2", "3", "4", "5"], -}; - const GetTinyImageSchema = z.object({}); const AnnotatedMessageSchema = z.object({ @@ -119,6 +112,13 @@ enum PromptName { RESOURCE = "resource_prompt", } +// Example completion values +const EXAMPLE_COMPLETIONS = { + style: ["casual", "formal", "technical", "friendly"], + temperature: ["0", "0.5", "0.7", "1.0"], + resourceId: ["1", "2", "3", "4", "5"], +}; + export const createServer = () => { const server = new Server( { From bb1b418da140c260988a24ed7014844765d6db72 Mon Sep 17 00:00:00 2001 From: Richard Michael Date: Wed, 23 Jul 2025 11:32:14 -0700 Subject: [PATCH 16/30] chore: Code organization: consistent tool order everywhere --- src/everything/README.md | 16 ++++---- src/everything/everything.ts | 78 ++++++++++++++++++------------------ 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/everything/README.md b/src/everything/README.md index 3ab3299a..e30b0a7d 100644 --- a/src/everything/README.md +++ b/src/everything/README.md @@ -27,24 +27,24 @@ This MCP server attempts to exercise all the features of the MCP protocol. It is - Returns: Completion message with duration and steps - Sends progress notifications during execution -4. `sampleLLM` +4. `printEnv` + - Prints all environment variables + - Useful for debugging MCP server configuration + - No inputs required + - Returns: JSON string of all environment variables + +5. `sampleLLM` - Demonstrates LLM sampling capability using MCP sampling feature - Inputs: - `prompt` (string): The prompt to send to the LLM - `maxTokens` (number, default: 100): Maximum tokens to generate - Returns: Generated LLM response -5. `getTinyImage` +6. `getTinyImage` - Returns a small test image - No inputs required - Returns: Base64 encoded PNG image data -6. `printEnv` - - Prints all environment variables - - Useful for debugging MCP server configuration - - No inputs required - - Returns: JSON string of all environment variables - 7. `annotatedMessage` - Demonstrates how annotations can be used to provide metadata about content - Inputs: diff --git a/src/everything/everything.ts b/src/everything/everything.ts index 372a4365..422b3169 100644 --- a/src/everything/everything.ts +++ b/src/everything/everything.ts @@ -457,18 +457,18 @@ export const createServer = () => { description: "Adds two numbers", inputSchema: zodToJsonSchema(AddSchema) as ToolInput, }, - { - name: ToolName.PRINT_ENV, - description: - "Prints all environment variables, helpful for debugging MCP server configuration", - inputSchema: zodToJsonSchema(PrintEnvSchema) as ToolInput, - }, { name: ToolName.LONG_RUNNING_OPERATION, description: "Demonstrates a long running operation with progress updates", inputSchema: zodToJsonSchema(LongRunningOperationSchema) as ToolInput, }, + { + name: ToolName.PRINT_ENV, + description: + "Prints all environment variables, helpful for debugging MCP server configuration", + inputSchema: zodToJsonSchema(PrintEnvSchema) as ToolInput, + }, { name: ToolName.SAMPLE_LLM, description: "Samples from an LLM using MCP's sampling feature", @@ -611,35 +611,6 @@ export const createServer = () => { }; } - if (name === ToolName.GET_RESOURCE_REFERENCE) { - const validatedArgs = GetResourceReferenceSchema.parse(args); - const resourceId = validatedArgs.resourceId; - - const resourceIndex = resourceId - 1; - if (resourceIndex < 0 || resourceIndex >= ALL_RESOURCES.length) { - throw new Error(`Resource with ID ${resourceId} does not exist`); - } - - const resource = ALL_RESOURCES[resourceIndex]; - - return { - content: [ - { - type: "text", - text: `Returning resource reference for Resource ${resourceId}:`, - }, - { - type: "resource", - resource: resource, - }, - { - type: "text", - text: `You can access this resource using the URI: ${resource.uri}`, - }, - ], - }; - } - if (name === ToolName.ANNOTATED_MESSAGE) { const { messageType, includeImage } = AnnotatedMessageSchema.parse(args); @@ -691,6 +662,35 @@ export const createServer = () => { return { content }; } + if (name === ToolName.GET_RESOURCE_REFERENCE) { + const validatedArgs = GetResourceReferenceSchema.parse(args); + const resourceId = validatedArgs.resourceId; + + const resourceIndex = resourceId - 1; + if (resourceIndex < 0 || resourceIndex >= ALL_RESOURCES.length) { + throw new Error(`Resource with ID ${resourceId} does not exist`); + } + + const resource = ALL_RESOURCES[resourceIndex]; + + return { + content: [ + { + type: "text", + text: `Returning resource reference for Resource ${resourceId}:`, + }, + { + type: "resource", + resource: resource, + }, + { + type: "text", + text: `You can access this resource using the URI: ${resource.uri}`, + }, + ], + }; + } + if (name === ToolName.ELICITATION) { ElicitationSchema.parse(args); @@ -712,13 +712,13 @@ export const createServer = () => { // Handle different response actions const content = []; - + if (elicitationResult.action === 'accept' && elicitationResult.content) { content.push({ type: "text", text: `✅ User provided their favorite things!`, }); - + // Only access elicitationResult.content when action is accept const { color, number, pets } = elicitationResult.content; content.push({ @@ -736,7 +736,7 @@ export const createServer = () => { text: `⚠️ User cancelled the elicitation dialog.`, }); } - + // Include raw result for debugging content.push({ type: "text", @@ -745,7 +745,7 @@ export const createServer = () => { return { content }; } - + if (name === ToolName.GET_RESOURCE_LINKS) { const { count } = GetResourceLinksSchema.parse(args); const content = []; From 9e28ac7fd15a5d065dc635b8172f1e868de300a0 Mon Sep 17 00:00:00 2001 From: Richard Michael Date: Sat, 28 Jun 2025 21:20:19 -0700 Subject: [PATCH 17/30] chore: Add serverInfo title, as in specification 2025-06-18 --- src/everything/everything.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/everything/everything.ts b/src/everything/everything.ts index 422b3169..c1f1b4eb 100644 --- a/src/everything/everything.ts +++ b/src/everything/everything.ts @@ -123,6 +123,7 @@ export const createServer = () => { const server = new Server( { name: "example-servers/everything", + title: "Everything Example Server", version: "1.0.0", }, { From 84a872145c1e4d93bb518fa970258aafd66ba577 Mon Sep 17 00:00:00 2001 From: Richard Michael Date: Thu, 26 Jun 2025 16:48:00 -0700 Subject: [PATCH 18/30] feature: Add a tool with Structured Content and an Output Schema Tools gained Structured Content in Specification 2025-16-18 https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content The MCP Inspector is able to handle these outputs. --- src/everything/README.md | 9 ++++++ src/everything/everything.ts | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/everything/README.md b/src/everything/README.md index e30b0a7d..86194614 100644 --- a/src/everything/README.md +++ b/src/everything/README.md @@ -80,6 +80,15 @@ This MCP server attempts to exercise all the features of the MCP protocol. It is - `pets` (enum): Favorite pet - Returns: Confirmation of the elicitation demo with selection summary. +10. `structuredContent` + - Demonstrates a tool returning structured content using the example in the specification + - Provides an output schema to allow testing of client SHOULD advisory to validate the result using the schema + - Inputs: + - `location` (string): A location or ZIP code, mock data is returned regardless of value + - Returns: a response with + - `structuredContent` field conformant to the output schema + - A backward compatible Text Content field, a SHOULD advisory in the specification + ### Resources The server provides 100 test resources in two formats: diff --git a/src/everything/everything.ts b/src/everything/everything.ts index c1f1b4eb..f1a2a11d 100644 --- a/src/everything/everything.ts +++ b/src/everything/everything.ts @@ -31,6 +31,9 @@ const instructions = readFileSync(join(__dirname, "instructions.md"), "utf-8"); const ToolInputSchema = ToolSchema.shape.inputSchema; type ToolInput = z.infer; +const ToolOutputSchema = ToolSchema.shape.outputSchema; +type ToolOutput = z.infer; + /* Input schemas for tools implemented in this server */ const EchoSchema = z.object({ message: z.string().describe("Message to echo"), @@ -93,6 +96,28 @@ const GetResourceLinksSchema = z.object({ .describe("Number of resource links to return (1-10)"), }); +const StructuredContentSchema = { + input: z.object({ + location: z + .string() + .trim() + .min(1) + .describe("City name or zip code"), + }), + + output: z.object({ + temperature: z + .number() + .describe("Temperature in celsius"), + conditions: z + .string() + .describe("Weather conditions description"), + humidity: z + .number() + .describe("Humidity percentage"), + }) +}; + enum ToolName { ECHO = "echo", ADD = "add", @@ -104,6 +129,7 @@ enum ToolName { GET_RESOURCE_REFERENCE = "getResourceReference", ELICITATION = "startElicitation", GET_RESOURCE_LINKS = "getResourceLinks", + STRUCTURED_CONTENT = "structuredContent" } enum PromptName { @@ -503,6 +529,13 @@ export const createServer = () => { "Returns multiple resource links that reference different types of resources", inputSchema: zodToJsonSchema(GetResourceLinksSchema) as ToolInput, }, + { + name: ToolName.STRUCTURED_CONTENT, + description: + "Returns structured content along with an output schema for client data validation", + inputSchema: zodToJsonSchema(StructuredContentSchema.input) as ToolInput, + outputSchema: zodToJsonSchema(StructuredContentSchema.output) as ToolOutput, + }, ]; return { tools }; @@ -777,6 +810,27 @@ export const createServer = () => { return { content }; } + if (name === ToolName.STRUCTURED_CONTENT) { + // The same response is returned for every input. + const validatedArgs = StructuredContentSchema.input.parse(args); + + const weather = { + temperature: 22.5, + conditions: "Partly cloudy", + humidity: 65 + } + + const backwardCompatiblecontent = { + type: "text", + text: JSON.stringify(weather) + } + + return { + content: [ backwardCompatiblecontent ], + structuredContent: weather + }; + } + throw new Error(`Unknown tool: ${name}`); }); From 471ac89f559c6956a5d342019bbfb4c97fc33b5a Mon Sep 17 00:00:00 2001 From: cliffhall Date: Thu, 24 Jul 2025 14:37:49 -0400 Subject: [PATCH 19/30] Update SDK version --- package-lock.json | 8 ++++---- src/filesystem/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 38a2fe5c..6a9bac93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6159,7 +6159,7 @@ "version": "0.6.2", "license": "MIT", "dependencies": { - "@modelcontextprotocol/sdk": "^1.16.0", + "@modelcontextprotocol/sdk": "^1.17.0", "diff": "^5.1.0", "glob": "^10.3.10", "minimatch": "^10.0.1", @@ -6182,9 +6182,9 @@ } }, "src/filesystem/node_modules/@modelcontextprotocol/sdk": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.16.0.tgz", - "integrity": "sha512-8ofX7gkZcLj9H9rSd50mCgm3SSF8C7XoclxJuLoV0Cz3rEQ1tv9MZRYYvJtm9n1BiEQQMzSmE/w2AEkNacLYfg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.17.0.tgz", + "integrity": "sha512-qFfbWFA7r1Sd8D697L7GkTd36yqDuTkvz0KfOGkgXR8EUhQn3/EDNIR/qUdQNMT8IjmasBvHWuXeisxtXTQT2g==", "license": "MIT", "dependencies": { "ajv": "^6.12.6", diff --git a/src/filesystem/package.json b/src/filesystem/package.json index 8176babf..4d3ac320 100644 --- a/src/filesystem/package.json +++ b/src/filesystem/package.json @@ -20,7 +20,7 @@ "test": "jest --config=jest.config.cjs --coverage" }, "dependencies": { - "@modelcontextprotocol/sdk": "^1.16.0", + "@modelcontextprotocol/sdk": "^1.17.0", "diff": "^5.1.0", "glob": "^10.3.10", "minimatch": "^10.0.1", From 704275818f3d7620501b2fecd7aaba538a1b62af Mon Sep 17 00:00:00 2001 From: cliffhall Date: Fri, 25 Jul 2025 16:01:05 -0400 Subject: [PATCH 20/30] Replace `read_file` tool with deprecation notice in description, which is functionally just an alias for `read_text_file` --- src/filesystem/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index 01d6c638..6723f436 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -498,6 +498,11 @@ async function readFileAsBase64Stream(filePath: string): Promise { server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ + { + name: "read_file", + description: "Read the complete contents of a file as text. DEPRECATED: Use read_text_file instead.", + inputSchema: zodToJsonSchema(ReadTextFileArgsSchema) as ToolInput, + }, { name: "read_text_file", description: @@ -628,6 +633,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; switch (name) { + case "read_file": case "read_text_file": { const parsed = ReadTextFileArgsSchema.safeParse(args); if (!parsed.success) { From b8a9adb6745b932e80c7a41e7e2690e1893358cd Mon Sep 17 00:00:00 2001 From: Brandon Hawi Date: Sat, 26 Jul 2025 08:43:51 -0700 Subject: [PATCH 21/30] fix: `Lisply` logo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 360a38f6..fc237366 100644 --- a/README.md +++ b/README.md @@ -228,7 +228,7 @@ 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/). -- Lisply **[Lisply](https://github.com/gornskew/lisply-mcp)** - Flexible frontend for compliant Lisp-speaking backends. +- 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. - Logfire Logo **[Logfire](https://github.com/pydantic/logfire-mcp)** - Provides access to OpenTelemetry traces and metrics through Logfire. From a688cca9477cd94d31dade4376ba4df7125837bd Mon Sep 17 00:00:00 2001 From: Sampath Vuyyuru <53322870+vksampath@users.noreply.github.com> Date: Sat, 26 Jul 2025 18:09:30 +0000 Subject: [PATCH 22/30] Update src/filesystem/README.md Fix broken link to Roots --- src/filesystem/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/filesystem/README.md b/src/filesystem/README.md index 89bca690..ac63f39a 100644 --- a/src/filesystem/README.md +++ b/src/filesystem/README.md @@ -9,11 +9,11 @@ Node.js server implementing Model Context Protocol (MCP) for filesystem operatio - Move files/directories - Search files - Get file metadata -- Dynamic directory access control via [Roots](https://modelcontextprotocol.io/docs/concepts/roots) +- Dynamic directory access control via [Roots](https://modelcontextprotocol.io/docs/learn/client-concepts#roots) ## Directory Access Control -The server uses a flexible directory access control system. Directories can be specified via command-line arguments or dynamically via [Roots](https://modelcontextprotocol.io/docs/concepts/roots). +The server uses a flexible directory access control system. Directories can be specified via command-line arguments or dynamically via [Roots](https://modelcontextprotocol.io/docs/learn/client-concepts#roots). ### Method 1: Command-line Arguments Specify Allowed directories when starting the server: @@ -22,7 +22,7 @@ mcp-server-filesystem /path/to/dir1 /path/to/dir2 ``` ### Method 2: MCP Roots (Recommended) -MCP clients that support [Roots](https://modelcontextprotocol.io/docs/concepts/roots) can dynamically update the Allowed directories. +MCP clients that support [Roots](https://modelcontextprotocol.io/docs/learn/client-concepts#roots) can dynamically update the Allowed directories. Roots notified by Client to Server, completely replace any server-side Allowed directories when provided. From d1e30558b30def5f2d619600da17c3cc744e3d25 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Tue, 29 Jul 2025 02:16:07 +0900 Subject: [PATCH 23/30] Add some SDK links This PR adds Ruby, Rust, and Swift SDK links to README. Synced with the following: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/0695a497eb50a804fc0e88c18a93a21a675d6b3e/docs/docs/sdk.mdx?plain=1#L8-L56 In accordance with the Note that follows: > Note: Lists in this README are maintained in alphabetical order to minimize merge conflicts when adding new items. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f22de58..57ac8cc7 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,16 @@ to community built servers and additional resources. The servers in this repository showcase the versatility and extensibility of MCP, demonstrating how it can be used to give Large Language Models (LLMs) secure, controlled access to tools and data sources. Typically, each MCP server is implemented with an MCP SDK: + - [C# MCP SDK](https://github.com/modelcontextprotocol/csharp-sdk) - [Go MCP SDK](https://github.com/modelcontextprotocol/go-sdk) - [Java MCP SDK](https://github.com/modelcontextprotocol/java-sdk) - [Kotlin MCP SDK](https://github.com/modelcontextprotocol/kotlin-sdk) - [Python MCP SDK](https://github.com/modelcontextprotocol/python-sdk) -- [Typescript MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) +- [Ruby MCP SDK](https://github.com/modelcontextprotocol/ruby-sdk) +- [Rust MCP SDK](https://github.com/modelcontextprotocol/rust-sdk) +- [Swift MCP SDK](https://github.com/modelcontextprotocol/swift-sdk) +- [TypeScript MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) > Note: Lists in this README are maintained in alphabetical order to minimize merge conflicts when adding new items. From dcd814fd2aa23335b0a36bffae776304502170c0 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Sat, 12 Apr 2025 16:39:38 +0900 Subject: [PATCH 24/30] [Doc] Use the official spelling of "TypeScript" in README This PR replaces all instances of "Typescript" with the official capitalization "TypeScript". The term is spelled "TypeScript" in the linked document. Revert "[Doc] Use the official spelling of "TypeScript" in README" This reverts commit 97db4264802aab50ecb456e1b289f93e439af485. --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 57ac8cc7..4b01ad96 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ Official integrations are maintained by companies building production ready MCP - BrowserStack Logo **[BrowserStack](https://github.com/browserstack/mcp-server)** - Access BrowserStack's [Test Platform](https://www.browserstack.com/test-platform) to debug, write and fix tests, do accessibility testing and more. - Bucket **[Bucket](https://github.com/bucketco/bucket-javascript-sdk/tree/main/packages/cli#model-context-protocol)** - Flag features, manage company data, and control feature access using [Bucket](https://bucket.co) - Buildkite Logo **[Buildkite](https://github.com/buildkite/buildkite-mcp-server)** - Exposing Buildkite data (pipelines, builds, jobs, tests) to AI tooling and editors. -- Buildable Logo**[Buildable](https://github.com/chunkydotdev/bldbl-mcp)** (Typescript) - Official MCP server for Buildable AI-powered development platform. Enables AI assistants to manage tasks, track progress, get project context, and collaborate with humans on software projects. +- Buildable Logo**[Buildable](https://github.com/chunkydotdev/bldbl-mcp)** (TypeScript) - Official MCP server for Buildable AI-powered development platform. Enables AI assistants to manage tasks, track progress, get project context, and collaborate with humans on software projects. - BuiltWith Logo **[BuiltWith](https://github.com/builtwith/mcp)** - Identify the technology stack behind any website. - PortSwigger Logo **[Burp Suite](https://github.com/PortSwigger/mcp-server)** - MCP Server extension allowing AI clients to connect to [Burp Suite](https://portswigger.net) - Campertunity Logo **[Campertunity](https://github.com/campertunity/mcp-server)** - Search campgrounds around the world on campertunity, check availability, and provide booking links. @@ -1067,17 +1067,17 @@ These are high-level frameworks that make it easier to build MCP servers or clie * **[Foxy Contexts](https://github.com/strowk/foxy-contexts)** – A library to build MCP servers in Golang by **[strowk](https://github.com/strowk)** * **[Higress MCP Server Hosting](https://github.com/alibaba/higress/tree/main/plugins/wasm-go/mcp-servers)** - A solution for hosting MCP Servers by extending the API Gateway (based on Envoy) with wasm plugins. * **[MCP Declarative Java SDK](https://github.com/codeboyzhou/mcp-declarative-java-sdk)** Annotation-driven MCP servers development with Java, no Spring Framework Required, minimize dependencies as much as possible. -* **[MCP-Framework](https://mcp-framework.com)** Build MCP servers with elegance and speed in Typescript. Comes with a CLI to create your project with `mcp create app`. Get started with your first server in under 5 minutes by **[Alex Andru](https://github.com/QuantGeekDev)** +* **[MCP-Framework](https://mcp-framework.com)** Build MCP servers with elegance and speed in TypeScript. Comes with a CLI to create your project with `mcp create app`. Get started with your first server in under 5 minutes by **[Alex Andru](https://github.com/QuantGeekDev)** * **[MCP Plexus](https://github.com/Super-I-Tech/mcp_plexus)**: A secure, **multi-tenant** and Multi-user MCP python server framework built to integrate easily with external services via OAuth 2.1, offering scalable and robust solutions for managing complex AI applications. * **[mcp_sse (Elixir)](https://github.com/kEND/mcp_sse)** An SSE implementation in Elixir for rapidly creating MCP servers. -* **[Next.js MCP Server Template](https://github.com/vercel-labs/mcp-for-next.js)** (Typescript) - A starter Next.js project that uses the MCP Adapter to allow MCP clients to connect and access resources. +* **[Next.js MCP Server Template](https://github.com/vercel-labs/mcp-for-next.js)** (TypeScript) - A starter Next.js project that uses the MCP Adapter to allow MCP clients to connect and access resources. * **[Quarkus MCP Server SDK](https://github.com/quarkiverse/quarkus-mcp-server)** (Java) - **[R mcptools](https://github.com/posit-dev/mcptools)** - An R SDK for creating R-based MCP servers and retrieving functionality from third-party MCP servers as R functions. * **[SAP ABAP MCP Server SDK](https://github.com/abap-ai/mcp)** - Build SAP ABAP based MCP servers. ABAP 7.52 based with 7.02 downport; runs on R/3 & S/4HANA on-premises, currently not cloud-ready. * **[Spring AI MCP Server](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html)** - Provides auto-configuration for setting up an MCP server in Spring Boot applications. * **[Template MCP Server](https://github.com/mcpdotdirect/template-mcp-server)** - A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure * **[AgentR Universal MCP SDK](https://github.com/universal-mcp/universal-mcp)** - A python SDK to build MCP Servers with inbuilt credential management by **[Agentr](https://agentr.dev/home)** -* **[Vercel MCP Adapter](https://github.com/vercel/mcp-adapter)** (Typescript) - A simple package to start serving an MCP server on most major JS meta-frameworks including Next, Nuxt, Svelte, and more. +* **[Vercel MCP Adapter](https://github.com/vercel/mcp-adapter)** (TypeScript) - A simple package to start serving an MCP server on most major JS meta-frameworks including Next, Nuxt, Svelte, and more. * **[Hermes MCP](https://github.com/cloudwalk/hermes-mcp)** (Elixir) - A high-performance and high-level Model Context Protocol (MCP) implementation in Elixir. Think like "Live View" for MCP. @@ -1143,7 +1143,7 @@ Additional resources on MCP. ## 🚀 Getting Started ### Using MCP Servers in this Repository -Typescript-based servers in this repository can be used directly with `npx`. +TypeScript-based servers in this repository can be used directly with `npx`. For example, this will start the [Memory](src/memory) server: ```sh From be72d9b16c1338f14fca6c93f948cf8b988484ff Mon Sep 17 00:00:00 2001 From: Kapil Duraphe Date: Thu, 31 Jul 2025 14:39:19 -0400 Subject: [PATCH 25/30] chore: Update natoma url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57ac8cc7..15483e84 100644 --- a/README.md +++ b/README.md @@ -1114,7 +1114,7 @@ Additional resources on MCP. - **[MCP Linker](https://github.com/milisp/mcp-linker)** - A cross-platform Tauri GUI tool for one-click setup and management of MCP servers, supporting Claude Desktop, Cursor, Windsurf, VS Code, Cline, and Neovim. - **[mcp-manager](https://github.com/zueai/mcp-manager)** - Simple Web UI to install and manage MCP servers for Claude Desktop by **[Zue](https://github.com/zueai)** - **[MCP Marketplace Web Plugin](https://github.com/AI-Agent-Hub/mcp-marketplace)** MCP Marketplace is a small Web UX plugin to integrate with AI applications, Support various MCP Server API Endpoint (e.g pulsemcp.com/deepnlp.org and more). Allowing user to browse, paginate and select various MCP servers by different categories. [Pypi](https://pypi.org/project/mcp-marketplace) | [Maintainer](https://github.com/AI-Agent-Hub) | [Website](http://www.deepnlp.org/store/ai-agent/mcp-server) -- **[mcp.natoma.id](https://mcp.natoma.id)** – A Hosted MCP Platform to discover, install, manage and deploy MCP servers by **[Natoma Labs](https://www.natoma.id)** +- **[mcp.natoma.ai](https://mcp.natoma.ai)** – A Hosted MCP Platform to discover, install, manage and deploy MCP servers by **[Natoma Labs](https://www.natoma.ai)** - **[mcp.run](https://mcp.run)** - A hosted registry and control plane to install & run secure + portable MCP Servers. - **[MCPHub](https://www.mcphub.com)** - Website to list high quality MCP servers and reviews by real users. Also provide online chatbot for popular LLM models with MCP server support. - **[MCP Router](https://mcp-router.net)** – Free Windows and macOS app that simplifies MCP management while providing seamless app authentication and powerful log visualization by **[MCP Router](https://github.com/mcp-router/mcp-router)** From 8eb4921c13873a65a85ef2d3b1bdac8224f89a9a Mon Sep 17 00:00:00 2001 From: cliffhall Date: Thu, 31 Jul 2025 16:40:05 -0400 Subject: [PATCH 26/30] In release.yml - in publish-pypi job, - only proceed if there are python packages to publish - in publish-npm job, - only proceed if there are npm packages to publish --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b37f2c0b..f1c2b0e4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -104,6 +104,7 @@ jobs: publish-pypi: needs: [update-packages, create-metadata] + if: ${{ needs.create-metadata.outputs.pypi_packages != '[]' && needs.create-metadata.outputs.pypi_packages != '' }} strategy: fail-fast: false matrix: @@ -145,6 +146,7 @@ jobs: publish-npm: needs: [update-packages, create-metadata] + if: ${{ needs.create-metadata.outputs.npm_packages != '[]' && needs.create-metadata.outputs.npm_packages != '' }} strategy: fail-fast: false matrix: From 2b041eef88a386dca3d8555384baa2d7c6558597 Mon Sep 17 00:00:00 2001 From: Adam Jones Date: Fri, 1 Aug 2025 19:08:14 +0100 Subject: [PATCH 27/30] time: Add tests for local timezone detection and handling in get_local_tz function --- src/time/test/time_server_test.py | 70 ++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/time/test/time_server_test.py b/src/time/test/time_server_test.py index 8129fb5b..97a6ea1f 100644 --- a/src/time/test/time_server_test.py +++ b/src/time/test/time_server_test.py @@ -2,8 +2,10 @@ from freezegun import freeze_time from mcp.shared.exceptions import McpError import pytest +from unittest.mock import patch +from zoneinfo import ZoneInfo -from mcp_server_time.server import TimeServer +from mcp_server_time.server import TimeServer, get_local_tz @pytest.mark.parametrize( @@ -458,3 +460,69 @@ def test_convert_time(test_time, source_tz, time_str, target_tz, expected): assert result.source.is_dst == expected["source"]["is_dst"] assert result.target.is_dst == expected["target"]["is_dst"] assert result.time_difference == expected["time_difference"] + + +def test_get_local_tz_with_override(): + """Test that timezone override works correctly.""" + result = get_local_tz("America/New_York") + assert str(result) == "America/New_York" + assert isinstance(result, ZoneInfo) + + +def test_get_local_tz_with_invalid_override(): + """Test that invalid timezone override raises an error.""" + with pytest.raises(Exception): # ZoneInfo will raise an exception + get_local_tz("Invalid/Timezone") + + +@patch('mcp_server_time.server.get_localzone_name') +def test_get_local_tz_with_valid_iana_name(mock_get_localzone): + """Test that valid IANA timezone names from tzlocal work correctly.""" + mock_get_localzone.return_value = "Europe/London" + result = get_local_tz() + assert str(result) == "Europe/London" + assert isinstance(result, ZoneInfo) + + +@patch('mcp_server_time.server.get_localzone_name') +def test_get_local_tz_when_none_returned(mock_get_localzone): + """Test error when tzlocal returns None.""" + mock_get_localzone.return_value = None + with pytest.raises(McpError, match="Could not determine local timezone"): + get_local_tz() + + +@patch('mcp_server_time.server.get_localzone_name') +def test_get_local_tz_handles_windows_timezones(mock_get_localzone): + """Test that tzlocal properly handles Windows timezone names. + + Note: tzlocal should convert Windows names like 'Pacific Standard Time' + to proper IANA names like 'America/Los_Angeles'. + """ + # tzlocal should return IANA names even on Windows + mock_get_localzone.return_value = "America/Los_Angeles" + result = get_local_tz() + assert str(result) == "America/Los_Angeles" + assert isinstance(result, ZoneInfo) + + +@pytest.mark.parametrize( + "timezone_name", + [ + "America/New_York", + "Europe/Paris", + "Asia/Tokyo", + "Australia/Sydney", + "Africa/Cairo", + "America/Sao_Paulo", + "Pacific/Auckland", + "UTC", + ], +) +@patch('mcp_server_time.server.get_localzone_name') +def test_get_local_tz_various_timezones(mock_get_localzone, timezone_name): + """Test various timezone names that tzlocal might return.""" + mock_get_localzone.return_value = timezone_name + result = get_local_tz() + assert str(result) == timezone_name + assert isinstance(result, ZoneInfo) From 4c192aee939b73aabb9cbe3671b6224452fec480 Mon Sep 17 00:00:00 2001 From: evalstate <1936278+evalstate@users.noreply.github.com> Date: Sat, 2 Aug 2025 08:46:33 +0100 Subject: [PATCH 28/30] Remove out-of-specification notifications/stderr sending --- src/everything/everything.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/everything/everything.ts b/src/everything/everything.ts index f1a2a11d..26e43521 100644 --- a/src/everything/everything.ts +++ b/src/everything/everything.ts @@ -209,18 +209,6 @@ export const createServer = () => { }, 20000); - // Set up update interval for stderr messages - stdErrUpdateInterval = setInterval(() => { - const shortTimestamp = new Date().toLocaleTimeString([], { - hour: "2-digit", - minute: "2-digit", - second: "2-digit" - }); - server.notification({ - method: "notifications/stderr", - params: { content: `${shortTimestamp}: A stderr message` }, - }); - }, 30000); // Helper method to request sampling from client const requestSampling = async ( From b43ecf8710e3c31f90daf69127b4726dfb1f0f63 Mon Sep 17 00:00:00 2001 From: evalstate <1936278+evalstate@users.noreply.github.com> Date: Sat, 2 Aug 2025 10:13:32 +0100 Subject: [PATCH 29/30] 1) Update README to contain basic build/run instructions. Remove legacy test advice. 2) Make the Unit Test insensitive to the git default branch name --- src/git/README.md | 50 +++++++++++++++--------------------- src/git/tests/test_server.py | 11 +++++--- 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/git/README.md b/src/git/README.md index a1294d8c..30b7e2d8 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -285,13 +285,29 @@ help you debug any issues. ## Development -If you are doing local development, there are two ways to test your changes: +### Building -1. Run the MCP inspector to test your changes. See [Debugging](#debugging) for run instructions. +[`uv`](https://docs.astral.sh/uv/) is used for development. -2. Test using the Claude desktop app. Add the following to your `claude_desktop_config.json`: +Start by creating a fresh virtual environment: -### Docker +```bash +uv venv +source .venv/bin/activate +``` +To run the tests, type `uv run pytest`, to run the server from source use `uv run src/mcp_server_git/`. + +To build, type `uv build`. You can then now run `mcp-server-git` command directly. Open with the inspector using `npx @modelcontextprotocol/inspector@latest mcp-server-git`. + +To specify the Python version type `uv python pin ` (useful if you want to use a more recent version than the default). + +To create the Docker container use + +```bash +docker build -t mcp/git . +``` + +An example showing how to run via the Docker container is below: ```json { @@ -312,32 +328,6 @@ If you are doing local development, there are two ways to test your changes: } ``` -### UVX -```json -{ -"mcpServers": { - "git": { - "command": "uv", - "args": [ - "--directory", - "//mcp-servers/src/git", - "run", - "mcp-server-git" - ] - } - } -} -``` - -## Build - -Docker build: - -```bash -cd src/git -docker build -t mcp/git . -``` - ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/git/tests/test_server.py b/src/git/tests/test_server.py index 911a90cf..ceeeab91 100644 --- a/src/git/tests/test_server.py +++ b/src/git/tests/test_server.py @@ -12,6 +12,9 @@ def test_repository(tmp_path: Path): Path(repo_path / "test.txt").write_text("test") test_repo.index.add(["test.txt"]) test_repo.index.commit("initial commit") + + # Store the default branch name on the repo object for tests to use + test_repo.default_branch = test_repo.active_branch.name yield test_repo @@ -51,11 +54,11 @@ def test_git_branch_contains(test_repository): Path(test_repository.working_dir / Path("feature.txt")).write_text("feature content") test_repository.index.add(["feature.txt"]) commit = test_repository.index.commit("feature commit") - test_repository.git.checkout("master") + test_repository.git.checkout(test_repository.default_branch) result = git_branch(test_repository, "local", contains=commit.hexsha) assert "feature-branch" in result - assert "master" not in result + assert test_repository.default_branch not in result def test_git_branch_not_contains(test_repository): # Create a new branch and commit to it @@ -63,8 +66,8 @@ def test_git_branch_not_contains(test_repository): Path(test_repository.working_dir / Path("another_feature.txt")).write_text("another feature content") test_repository.index.add(["another_feature.txt"]) commit = test_repository.index.commit("another feature commit") - test_repository.git.checkout("master") + test_repository.git.checkout(test_repository.default_branch) result = git_branch(test_repository, "local", not_contains=commit.hexsha) assert "another-feature-branch" not in result - assert "master" in result + assert test_repository.default_branch in result From 3a297d843253b8196ed6d33ec7820267729df02b Mon Sep 17 00:00:00 2001 From: evalstate <1936278+evalstate@users.noreply.github.com> Date: Sat, 2 Aug 2025 10:17:05 +0100 Subject: [PATCH 30/30] Revert "1) Update README to contain basic build/run instructions. Remove legacy test advice." (wrong branch push) This reverts commit b43ecf8710e3c31f90daf69127b4726dfb1f0f63. --- src/git/README.md | 50 +++++++++++++++++++++--------------- src/git/tests/test_server.py | 11 +++----- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/git/README.md b/src/git/README.md index 30b7e2d8..a1294d8c 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -285,29 +285,13 @@ help you debug any issues. ## Development -### Building +If you are doing local development, there are two ways to test your changes: -[`uv`](https://docs.astral.sh/uv/) is used for development. +1. Run the MCP inspector to test your changes. See [Debugging](#debugging) for run instructions. -Start by creating a fresh virtual environment: +2. Test using the Claude desktop app. Add the following to your `claude_desktop_config.json`: -```bash -uv venv -source .venv/bin/activate -``` -To run the tests, type `uv run pytest`, to run the server from source use `uv run src/mcp_server_git/`. - -To build, type `uv build`. You can then now run `mcp-server-git` command directly. Open with the inspector using `npx @modelcontextprotocol/inspector@latest mcp-server-git`. - -To specify the Python version type `uv python pin ` (useful if you want to use a more recent version than the default). - -To create the Docker container use - -```bash -docker build -t mcp/git . -``` - -An example showing how to run via the Docker container is below: +### Docker ```json { @@ -328,6 +312,32 @@ An example showing how to run via the Docker container is below: } ``` +### UVX +```json +{ +"mcpServers": { + "git": { + "command": "uv", + "args": [ + "--directory", + "//mcp-servers/src/git", + "run", + "mcp-server-git" + ] + } + } +} +``` + +## Build + +Docker build: + +```bash +cd src/git +docker build -t mcp/git . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/git/tests/test_server.py b/src/git/tests/test_server.py index ceeeab91..911a90cf 100644 --- a/src/git/tests/test_server.py +++ b/src/git/tests/test_server.py @@ -12,9 +12,6 @@ def test_repository(tmp_path: Path): Path(repo_path / "test.txt").write_text("test") test_repo.index.add(["test.txt"]) test_repo.index.commit("initial commit") - - # Store the default branch name on the repo object for tests to use - test_repo.default_branch = test_repo.active_branch.name yield test_repo @@ -54,11 +51,11 @@ def test_git_branch_contains(test_repository): Path(test_repository.working_dir / Path("feature.txt")).write_text("feature content") test_repository.index.add(["feature.txt"]) commit = test_repository.index.commit("feature commit") - test_repository.git.checkout(test_repository.default_branch) + test_repository.git.checkout("master") result = git_branch(test_repository, "local", contains=commit.hexsha) assert "feature-branch" in result - assert test_repository.default_branch not in result + assert "master" not in result def test_git_branch_not_contains(test_repository): # Create a new branch and commit to it @@ -66,8 +63,8 @@ def test_git_branch_not_contains(test_repository): Path(test_repository.working_dir / Path("another_feature.txt")).write_text("another feature content") test_repository.index.add(["another_feature.txt"]) commit = test_repository.index.commit("another feature commit") - test_repository.git.checkout(test_repository.default_branch) + test_repository.git.checkout("master") result = git_branch(test_repository, "local", not_contains=commit.hexsha) assert "another-feature-branch" not in result - assert test_repository.default_branch in result + assert "master" in result