Merge branch 'main' into pr/224
This commit is contained in:
commit
54d6b58901
37 changed files with 2766 additions and 297 deletions
2
.github/workflows/typescript.yml
vendored
2
.github/workflows/typescript.yml
vendored
|
|
@ -74,6 +74,6 @@ jobs:
|
|||
|
||||
- name: Publish package
|
||||
working-directory: src/${{ matrix.package }}
|
||||
run: npm publish # --provenance
|
||||
run: npm publish --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
|
|
|||
17
README.md
17
README.md
|
|
@ -10,18 +10,21 @@ Each MCP server is implemented with either the [Typescript MCP SDK](https://gith
|
|||
|
||||
These servers aim to demonstrate MCP features and the Typescript and Python SDK.
|
||||
|
||||
- **[AWS KB Retrieval](src/aws-kb-retrieval)** - Retrieval from AWS Knowledge Base using Bedrock Agent Runtime
|
||||
- **[Brave Search](src/brave-search)** - Web and local search using Brave's Search API
|
||||
- **[EverArt](src/everart)** - AI image generation using various models
|
||||
- **[Fetch](src/fetch)** - Web content fetching and conversion for efficient LLM usage
|
||||
- **[Filesystem](src/filesystem)** - Secure file operations with configurable access controls
|
||||
- **[Git](src/git)** - Tools to read, search, and manipulate Git repositories
|
||||
- **[GitHub](src/github)** - Repository management, file operations, and GitHub API integration
|
||||
- **[GitLab](src/gitlab)** - GitLab API, enabling project management
|
||||
- **[Git](src/git)** - Tools to read, search, and manipulate Git repositories
|
||||
- **[Google Drive](src/gdrive)** - File access and search capabilities for Google Drive
|
||||
- **[Google Maps](src/google-maps)** - Location services, directions, and place details
|
||||
- **[Memory](src/memory)** - Knowledge graph-based persistent memory system
|
||||
- **[PostgreSQL](src/postgres)** - Read-only database access with schema inspection
|
||||
- **[Puppeteer](src/puppeteer)** - Browser automation and web scraping
|
||||
- **[Sentry](src/sentry)** - Retrieving and analyzing issues from Sentry.io
|
||||
- **[Sequential Thinking](src/sequentialthinking)** - Dynamic and reflective problem-solving through thought sequences
|
||||
- **[Slack](src/slack)** - Channel management and messaging capabilities
|
||||
- **[Sqlite](src/sqlite)** - Database interaction and business intelligence capabilities
|
||||
|
||||
|
|
@ -31,6 +34,7 @@ These servers aim to demonstrate MCP features and the Typescript and Python SDK.
|
|||
|
||||
Official integrations are maintained by companies building production ready MCP servers for their platforms.
|
||||
|
||||
- <img height="12" width="12" src="https://browserbase.com/favicon.ico" alt="Browserbase Logo" /> **[Browserbase](https://github.com/browserbase/mcp-server-browserbase)** - Automate browser interactions in the cloud (e.g. web navigation, data extraction, form filling, and more)
|
||||
- <img height="12" width="12" src="https://cdn.simpleicons.org/cloudflare" /> **[Cloudflare](https://github.com/cloudflare/mcp-server-cloudflare)** - Deploy, configure & interrogate your resources on the Cloudflare developer platform (e.g. Workers/KV/R2/D1)
|
||||
- **[Raygun](https://github.com/MindscapeHQ/mcp-server-raygun)** - Interact with your crash reporting and real using monitoring data on your Raygun account
|
||||
- <img height="12" width="12" src="https://e2b.dev/favicon.ico" alt="E2B Logo" /> **[E2B](https://github.com/e2b-dev/mcp-server)** - Run code in secure sandboxes hosted by [E2B](https://e2b.dev)
|
||||
|
|
@ -48,8 +52,18 @@ A growing set of community-developed and maintained servers demonstrates various
|
|||
- **[MCP Installer](https://github.com/anaisbetts/mcp-installer)** - This server is a server that installs other MCP servers for you.
|
||||
- **[Spotify MCP](https://github.com/varunneal/spotify-mcp)** - This MCP allows an LLM to play and use Spotify.
|
||||
- **[Inoyu](https://github.com/sergehuber/inoyu-mcp-unomi-server)** - Interact with an Apache Unomi CDP customer data platform to retrieve and update customer profiles
|
||||
- **[MySQL](https://github.com/designcomputer/mysql_mcp_server)** - MySQL database integration with configurable access controls and schema inspection
|
||||
- **[BigQuery](https://github.com/LucasHild/mcp-server-bigquery)** (by LucasHild) - This server enables LLMs to inspect database schemas and execute queries on BigQuery.
|
||||
- **[BigQuery](https://github.com/ergut/mcp-bigquery-server)** (by ergut) - Server implementation for Google BigQuery integration that enables direct BigQuery database access and querying capabilities
|
||||
- **[Todoist](https://github.com/abhiz123/todoist-mcp-server)** - Interact with Todoist to manage your tasks.
|
||||
- **[Tavily search](https://github.com/RamXX/mcp-tavily")** - An MCP server for Tavily's search & news API, with explicit site inclusions/exclusions
|
||||
- **[Linear](https://github.com/jerhadf/linear-mcp-server)** - Allows LLM to interact with Linear's API for project management, including searching, creating, and updating issues.
|
||||
- **[Playwright MCP](https://github.com/executeautomation/mcp-playwright)** - This MCP Server will help you run browser automation and webscraping using Playwright
|
||||
- **[AWS](https://github.com/rishikavikondala/mcp-server-aws)** - Perform operations on your AWS resources using an LLM
|
||||
- **[LlamaCloud](https://github.com/run-llama/mcp-server-llamacloud)** (by marcusschiesser) - Integrate the data stored in a managed index on [LlamaCloud](https://cloud.llamaindex.ai/)
|
||||
- **[Any Chat Completions](https://github.com/pyroprompts/any-chat-completions-mcp)** - Interact with any OpenAI SDK Compatible Chat Completions API like OpenAI, Perplexity, Groq, xAI and many more.
|
||||
- **[Windows CLI](https://github.com/SimonB97/win-cli-mcp-server)** - MCP server for secure command-line interactions on Windows systems, enabling controlled access to PowerShell, CMD, and Git Bash shells.
|
||||
- **[OpenRPC](https://github.com/shanejonas/openrpc-mpc-server)** - Interact with and discover JSON-RPC APIs via [OpenRPC](https://open-rpc.org).
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
|
|
@ -59,6 +73,7 @@ Additional resources on MCP.
|
|||
- **[Awesome MCP Servers by wong2](https://github.com/wong2/awesome-mcp-servers)** - A curated list of MCP servers by **[wong2](https://github.com/wong2)**
|
||||
- **[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)**
|
||||
- **[mcp-get](https://mcp-get.com)** - Command line tool for installing and managing MCP servers by **[Michael Latman](https://github.com/michaellatman)**
|
||||
- **[mcp-cli](https://github.com/wong2/mcp-cli)** - A CLI inspector for the Model Context Protocol by **[wong2](https://github.com/wong2)**
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
|
|
|
|||
1345
package-lock.json
generated
1345
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/servers",
|
||||
"private": true,
|
||||
"version": "0.6.1",
|
||||
"version": "0.6.2",
|
||||
"description": "Model Context Protocol servers",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
|
|
@ -30,4 +30,4 @@
|
|||
"@modelcontextprotocol/server-everart": "*",
|
||||
"@modelcontextprotocol/server-sequential-thinking": "*"
|
||||
}
|
||||
}
|
||||
}
|
||||
53
src/aws-kb-retrieval-server/README.md
Normal file
53
src/aws-kb-retrieval-server/README.md
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# AWS Knowledge Base Retrieval MCP Server
|
||||
|
||||
An MCP server implementation for retrieving information from the AWS Knowledge Base using the Bedrock Agent Runtime.
|
||||
|
||||
## Features
|
||||
|
||||
- **RAG (Retrieval-Augmented Generation)**: Retrieve context from the AWS Knowledge Base based on a query and a Knowledge Base ID.
|
||||
- **Supports multiple results retrieval**: Option to retrieve a customizable number of results.
|
||||
|
||||
## Tools
|
||||
|
||||
- **retrieve_from_aws_kb**
|
||||
- Perform retrieval operations using the AWS Knowledge Base.
|
||||
- Inputs:
|
||||
- `query` (string): The search query for retrieval.
|
||||
- `knowledgeBaseId` (string): The ID of the AWS Knowledge Base.
|
||||
- `n` (number, optional): Number of results to retrieve (default: 3).
|
||||
|
||||
## Configuration
|
||||
|
||||
### Setting up AWS Credentials
|
||||
|
||||
1. Obtain AWS access key ID, secret access key, and region from the AWS Management Console.
|
||||
2. Ensure these credentials have appropriate permissions for Bedrock Agent Runtime operations.
|
||||
|
||||
### Usage with Claude Desktop
|
||||
|
||||
Add this to your `claude_desktop_config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"aws-kb-retrieval": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-aws-kb-retrieval"
|
||||
],
|
||||
"env": {
|
||||
"AWS_ACCESS_KEY_ID": "YOUR_ACCESS_KEY_HERE",
|
||||
"AWS_SECRET_ACCESS_KEY": "YOUR_SECRET_ACCESS_KEY_HERE",
|
||||
"AWS_REGION": "YOUR_AWS_REGION_HERE"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
This README assumes that your server package is named `@modelcontextprotocol/server-aws-kb-retrieval`. Adjust the package name and installation details if they differ in your setup. Also, ensure that your server script is correctly built and that all dependencies are properly managed in your `package.json`.
|
||||
166
src/aws-kb-retrieval-server/index.ts
Normal file
166
src/aws-kb-retrieval-server/index.ts
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
#!/usr/bin/env node
|
||||
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import {
|
||||
CallToolRequestSchema,
|
||||
ListToolsRequestSchema,
|
||||
Tool,
|
||||
} from "@modelcontextprotocol/sdk/types.js";
|
||||
import {
|
||||
BedrockAgentRuntimeClient,
|
||||
RetrieveCommand,
|
||||
RetrieveCommandInput,
|
||||
} from "@aws-sdk/client-bedrock-agent-runtime";
|
||||
|
||||
// AWS client initialization
|
||||
const bedrockClient = new BedrockAgentRuntimeClient({
|
||||
region: process.env.AWS_REGION,
|
||||
credentials: {
|
||||
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
||||
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
||||
},
|
||||
});
|
||||
|
||||
interface RAGSource {
|
||||
id: string;
|
||||
fileName: string;
|
||||
snippet: string;
|
||||
score: number;
|
||||
}
|
||||
|
||||
async function retrieveContext(
|
||||
query: string,
|
||||
knowledgeBaseId: string,
|
||||
n: number = 3
|
||||
): Promise<{
|
||||
context: string;
|
||||
isRagWorking: boolean;
|
||||
ragSources: RAGSource[];
|
||||
}> {
|
||||
try {
|
||||
if (!knowledgeBaseId) {
|
||||
console.error("knowledgeBaseId is not provided");
|
||||
return {
|
||||
context: "",
|
||||
isRagWorking: false,
|
||||
ragSources: [],
|
||||
};
|
||||
}
|
||||
|
||||
const input: RetrieveCommandInput = {
|
||||
knowledgeBaseId: knowledgeBaseId,
|
||||
retrievalQuery: { text: query },
|
||||
retrievalConfiguration: {
|
||||
vectorSearchConfiguration: { numberOfResults: n },
|
||||
},
|
||||
};
|
||||
|
||||
const command = new RetrieveCommand(input);
|
||||
const response = await bedrockClient.send(command);
|
||||
const rawResults = response?.retrievalResults || [];
|
||||
const ragSources: RAGSource[] = rawResults
|
||||
.filter((res) => res?.content?.text)
|
||||
.map((result, index) => {
|
||||
const uri = result?.location?.s3Location?.uri || "";
|
||||
const fileName = uri.split("/").pop() || `Source-${index}.txt`;
|
||||
return {
|
||||
id: (result.metadata?.["x-amz-bedrock-kb-chunk-id"] as string) || `chunk-${index}`,
|
||||
fileName: fileName.replace(/_/g, " ").replace(".txt", ""),
|
||||
snippet: result.content?.text || "",
|
||||
score: (result.score as number) || 0,
|
||||
};
|
||||
})
|
||||
.slice(0, 3);
|
||||
|
||||
const context = rawResults
|
||||
.filter((res): res is { content: { text: string } } => res?.content?.text !== undefined)
|
||||
.map(res => res.content.text)
|
||||
.join("\n\n");
|
||||
|
||||
return {
|
||||
context,
|
||||
isRagWorking: true,
|
||||
ragSources,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("RAG Error:", error);
|
||||
return { context: "", isRagWorking: false, ragSources: [] };
|
||||
}
|
||||
}
|
||||
|
||||
// Define the retrieval tool
|
||||
const RETRIEVAL_TOOL: Tool = {
|
||||
name: "retrieve_from_aws_kb",
|
||||
description: "Performs retrieval from the AWS Knowledge Base using the provided query and Knowledge Base ID.",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: { type: "string", description: "The query to perform retrieval on" },
|
||||
knowledgeBaseId: { type: "string", description: "The ID of the AWS Knowledge Base" },
|
||||
n: { type: "number", default: 3, description: "Number of results to retrieve" },
|
||||
},
|
||||
required: ["query", "knowledgeBaseId"],
|
||||
},
|
||||
};
|
||||
|
||||
// Server setup
|
||||
const server = new Server(
|
||||
{
|
||||
name: "aws-kb-retrieval-server",
|
||||
version: "0.2.0",
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
tools: {},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// Request handlers
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
||||
tools: [RETRIEVAL_TOOL],
|
||||
}));
|
||||
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params;
|
||||
|
||||
if (name === "retrieve_from_aws_kb") {
|
||||
const { query, knowledgeBaseId, n = 3 } = args as Record<string, any>;
|
||||
try {
|
||||
const result = await retrieveContext(query, knowledgeBaseId, n);
|
||||
if (result.isRagWorking) {
|
||||
return {
|
||||
content: [
|
||||
{ type: "text", text: `Context: ${result.context}` },
|
||||
{ type: "text", text: `RAG Sources: ${JSON.stringify(result.ragSources)}` },
|
||||
],
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
content: [{ type: "text", text: "Retrieval failed or returned no results." }],
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [{ type: "text", text: `Error occurred: ${error}` }],
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Server startup
|
||||
async function runServer() {
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
console.error("AWS KB Retrieval Server running on stdio");
|
||||
}
|
||||
|
||||
runServer().catch((error) => {
|
||||
console.error("Fatal error running server:", error);
|
||||
process.exit(1);
|
||||
});
|
||||
30
src/aws-kb-retrieval-server/package.json
Normal file
30
src/aws-kb-retrieval-server/package.json
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/server-aws-kb-retrieval",
|
||||
"version": "0.6.2",
|
||||
"description": "MCP server for AWS Knowledge Base retrieval using Bedrock Agent Runtime",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
"homepage": "https://modelcontextprotocol.io",
|
||||
"bugs": "https://github.com/modelcontextprotocol/servers/issues",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"mcp-server-aws-kb-retrieval": "dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc && shx chmod +x dist/*.js",
|
||||
"prepare": "npm run build",
|
||||
"watch": "tsc --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "0.5.0",
|
||||
"@aws-sdk/client-bedrock-agent-runtime": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.10.0",
|
||||
"shx": "^0.3.4",
|
||||
"typescript": "^5.6.2"
|
||||
}
|
||||
}
|
||||
17
src/aws-kb-retrieval-server/tsconfig.json
Normal file
17
src/aws-kb-retrieval-server/tsconfig.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": ".",
|
||||
"composite": true,
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": "./dist/.tsbuildinfo"
|
||||
},
|
||||
"include": [
|
||||
"./**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/server-brave-search",
|
||||
"version": "0.6.1",
|
||||
"version": "0.6.2",
|
||||
"description": "MCP server for Brave Search API integration",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
|
|
@ -26,4 +26,4 @@
|
|||
"shx": "^0.3.4",
|
||||
"typescript": "^5.6.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/server-everart",
|
||||
"version": "0.6.1",
|
||||
"version": "0.6.2",
|
||||
"description": "MCP server for EverArt API integration",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
|
|
@ -29,4 +29,4 @@
|
|||
"shx": "^0.3.4",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/server-everything",
|
||||
"version": "0.6.1",
|
||||
"version": "0.6.2",
|
||||
"description": "MCP server that exercises all the features of the MCP protocol",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
|
|
@ -29,4 +29,4 @@
|
|||
"shx": "^0.3.4",
|
||||
"typescript": "^5.6.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "mcp-server-fetch"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
description = "A Model Context Protocol server providing tools to fetch and convert web content for usage by LLMs"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
|
|
|||
2
src/fetch/uv.lock
generated
2
src/fetch/uv.lock
generated
|
|
@ -327,7 +327,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "mcp-server-fetch"
|
||||
version = "0.1.3"
|
||||
version = "0.6.2"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "markdownify" },
|
||||
|
|
|
|||
|
|
@ -36,6 +36,30 @@ Node.js server implementing Model Context Protocol (MCP) for filesystem operatio
|
|||
- `path` (string): File location
|
||||
- `content` (string): File content
|
||||
|
||||
- **edit_file**
|
||||
- Make selective edits using advanced pattern matching and formatting
|
||||
- Features:
|
||||
- Line-based and multi-line content matching
|
||||
- Whitespace normalization with indentation preservation
|
||||
- Fuzzy matching with confidence scoring
|
||||
- Multiple simultaneous edits with correct positioning
|
||||
- Indentation style detection and preservation
|
||||
- Git-style diff output with context
|
||||
- Preview changes with dry run mode
|
||||
- Failed match debugging with confidence scores
|
||||
- Inputs:
|
||||
- `path` (string): File to edit
|
||||
- `edits` (array): List of edit operations
|
||||
- `oldText` (string): Text to search for (can be substring)
|
||||
- `newText` (string): Text to replace with
|
||||
- `dryRun` (boolean): Preview changes without applying (default: false)
|
||||
- `options` (object): Optional formatting settings
|
||||
- `preserveIndentation` (boolean): Keep existing indentation (default: true)
|
||||
- `normalizeWhitespace` (boolean): Normalize spaces while preserving structure (default: true)
|
||||
- `partialMatch` (boolean): Enable fuzzy matching (default: true)
|
||||
- Returns detailed diff and match information for dry runs, otherwise applies changes
|
||||
- Best Practice: Always use dryRun first to preview changes before applying them
|
||||
|
||||
- **create_directory**
|
||||
- Create new directory or ensure it exists
|
||||
- Input: `path` (string)
|
||||
|
|
@ -98,4 +122,4 @@ Add this to your `claude_desktop_config.json`:
|
|||
|
||||
## 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.
|
||||
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.
|
||||
|
|
@ -12,6 +12,7 @@ import path from "path";
|
|||
import os from 'os';
|
||||
import { z } from "zod";
|
||||
import { zodToJsonSchema } from "zod-to-json-schema";
|
||||
import { diffLines, createTwoFilesPatch } from 'diff';
|
||||
|
||||
// Command line argument parsing
|
||||
const args = process.argv.slice(2);
|
||||
|
|
@ -106,6 +107,17 @@ const WriteFileArgsSchema = z.object({
|
|||
content: z.string(),
|
||||
});
|
||||
|
||||
const EditOperation = z.object({
|
||||
oldText: z.string().describe('Text to search for - must match exactly'),
|
||||
newText: z.string().describe('Text to replace with')
|
||||
});
|
||||
|
||||
const EditFileArgsSchema = z.object({
|
||||
path: z.string(),
|
||||
edits: z.array(EditOperation),
|
||||
dryRun: z.boolean().default(false).describe('Preview changes using git-style diff format')
|
||||
});
|
||||
|
||||
const CreateDirectoryArgsSchema = z.object({
|
||||
path: z.string(),
|
||||
});
|
||||
|
|
@ -202,6 +214,104 @@ async function searchFiles(
|
|||
return results;
|
||||
}
|
||||
|
||||
// file editing and diffing utilities
|
||||
function normalizeLineEndings(text: string): string {
|
||||
return text.replace(/\r\n/g, '\n');
|
||||
}
|
||||
|
||||
function createUnifiedDiff(originalContent: string, newContent: string, filepath: string = 'file'): string {
|
||||
// Ensure consistent line endings for diff
|
||||
const normalizedOriginal = normalizeLineEndings(originalContent);
|
||||
const normalizedNew = normalizeLineEndings(newContent);
|
||||
|
||||
return createTwoFilesPatch(
|
||||
filepath,
|
||||
filepath,
|
||||
normalizedOriginal,
|
||||
normalizedNew,
|
||||
'original',
|
||||
'modified'
|
||||
);
|
||||
}
|
||||
|
||||
async function applyFileEdits(
|
||||
filePath: string,
|
||||
edits: Array<{oldText: string, newText: string}>,
|
||||
dryRun = false
|
||||
): Promise<string> {
|
||||
// Read file content and normalize line endings
|
||||
const content = normalizeLineEndings(await fs.readFile(filePath, 'utf-8'));
|
||||
|
||||
// Apply edits sequentially
|
||||
let modifiedContent = content;
|
||||
for (const edit of edits) {
|
||||
const normalizedOld = normalizeLineEndings(edit.oldText);
|
||||
const normalizedNew = normalizeLineEndings(edit.newText);
|
||||
|
||||
// If exact match exists, use it
|
||||
if (modifiedContent.includes(normalizedOld)) {
|
||||
modifiedContent = modifiedContent.replace(normalizedOld, normalizedNew);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, try line-by-line matching with flexibility for whitespace
|
||||
const oldLines = normalizedOld.split('\n');
|
||||
const contentLines = modifiedContent.split('\n');
|
||||
let matchFound = false;
|
||||
|
||||
for (let i = 0; i <= contentLines.length - oldLines.length; i++) {
|
||||
const potentialMatch = contentLines.slice(i, i + oldLines.length);
|
||||
|
||||
// Compare lines with normalized whitespace
|
||||
const isMatch = oldLines.every((oldLine, j) => {
|
||||
const contentLine = potentialMatch[j];
|
||||
return oldLine.trim() === contentLine.trim();
|
||||
});
|
||||
|
||||
if (isMatch) {
|
||||
// Preserve original indentation of first line
|
||||
const originalIndent = contentLines[i].match(/^\s*/)?.[0] || '';
|
||||
const newLines = normalizedNew.split('\n').map((line, j) => {
|
||||
if (j === 0) return originalIndent + line.trimStart();
|
||||
// For subsequent lines, try to preserve relative indentation
|
||||
const oldIndent = oldLines[j]?.match(/^\s*/)?.[0] || '';
|
||||
const newIndent = line.match(/^\s*/)?.[0] || '';
|
||||
if (oldIndent && newIndent) {
|
||||
const relativeIndent = newIndent.length - oldIndent.length;
|
||||
return originalIndent + ' '.repeat(Math.max(0, relativeIndent)) + line.trimStart();
|
||||
}
|
||||
return line;
|
||||
});
|
||||
|
||||
contentLines.splice(i, oldLines.length, ...newLines);
|
||||
modifiedContent = contentLines.join('\n');
|
||||
matchFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matchFound) {
|
||||
throw new Error(`Could not find exact match for edit:\n${edit.oldText}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Create unified diff
|
||||
const diff = createUnifiedDiff(content, modifiedContent, filePath);
|
||||
|
||||
// Format diff with appropriate number of backticks
|
||||
let numBackticks = 3;
|
||||
while (diff.includes('`'.repeat(numBackticks))) {
|
||||
numBackticks++;
|
||||
}
|
||||
const formattedDiff = `${'`'.repeat(numBackticks)}diff\n${diff}${'`'.repeat(numBackticks)}\n\n`;
|
||||
|
||||
if (!dryRun) {
|
||||
await fs.writeFile(filePath, modifiedContent, 'utf-8');
|
||||
}
|
||||
|
||||
return formattedDiff;
|
||||
}
|
||||
|
||||
// Tool handlers
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
return {
|
||||
|
|
@ -233,6 +343,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|||
"Handles text content with proper encoding. Only works within allowed directories.",
|
||||
inputSchema: zodToJsonSchema(WriteFileArgsSchema) as ToolInput,
|
||||
},
|
||||
{
|
||||
name: "edit_file",
|
||||
description:
|
||||
"Make line-based edits to a text file. Each edit replaces exact line sequences " +
|
||||
"with new content. Returns a git-style diff showing the changes made. " +
|
||||
"Only works within allowed directories.",
|
||||
inputSchema: zodToJsonSchema(EditFileArgsSchema) as ToolInput,
|
||||
},
|
||||
{
|
||||
name: "create_directory",
|
||||
description:
|
||||
|
|
@ -346,6 +464,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|||
};
|
||||
}
|
||||
|
||||
case "edit_file": {
|
||||
const parsed = EditFileArgsSchema.safeParse(args);
|
||||
if (!parsed.success) {
|
||||
throw new Error(`Invalid arguments for edit_file: ${parsed.error}`);
|
||||
}
|
||||
const validPath = await validatePath(parsed.data.path);
|
||||
const result = await applyFileEdits(validPath, parsed.data.edits, parsed.data.dryRun);
|
||||
return {
|
||||
content: [{ type: "text", text: result }],
|
||||
};
|
||||
}
|
||||
|
||||
case "create_directory": {
|
||||
const parsed = CreateDirectoryArgsSchema.safeParse(args);
|
||||
if (!parsed.success) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/server-filesystem",
|
||||
"version": "0.6.1",
|
||||
"version": "0.6.2",
|
||||
"description": "MCP server for filesystem access",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
|
|
@ -19,13 +19,15 @@
|
|||
"watch": "tsc --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "1.0.1",
|
||||
"@modelcontextprotocol/sdk": "0.5.0",
|
||||
"diff": "^5.1.0",
|
||||
"glob": "^10.3.10",
|
||||
"zod-to-json-schema": "^3.23.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/diff": "^5.0.9",
|
||||
"@types/node": "^20.11.0",
|
||||
"shx": "^0.3.4",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/server-gdrive",
|
||||
"version": "0.6.1",
|
||||
"version": "0.6.2",
|
||||
"description": "MCP server for interacting with Google Drive",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
|
|
@ -28,4 +28,4 @@
|
|||
"shx": "^0.3.4",
|
||||
"typescript": "^5.6.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "mcp-server-git"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
description = "A Model Context Protocol server providing tools to read, search, and manipulate Git repositories programmatically via LLMs"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
|
|
|||
10
src/git/uv.lock
generated
10
src/git/uv.lock
generated
|
|
@ -146,7 +146,7 @@ wheels = [
|
|||
|
||||
[[package]]
|
||||
name = "mcp"
|
||||
version = "0.9.1"
|
||||
version = "1.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
|
|
@ -156,14 +156,14 @@ dependencies = [
|
|||
{ name = "sse-starlette" },
|
||||
{ name = "starlette" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e7/1c/932818470ffd49c33509110c835101a8dc4c9cdd06028b9f647fb3dde237/mcp-0.9.1.tar.gz", hash = "sha256:e8509a37c2ab546095788ed170e0fb4d7ce0cf5a3ee56b6449c78af27321a425", size = 78218 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/77/f2/067b1fc114e8d3ae4af02fc4f4ed8971a2c4900362d976fabe0f4e9a3418/mcp-1.1.0.tar.gz", hash = "sha256:e3c8d6df93a4de90230ea944dd667730744a3cd91a4cc0ee66a5acd53419e100", size = 83802 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/a0/2ee813d456b57a726d583868417d1ad900fbe12ee3c8cd866e3e804ca486/mcp-0.9.1-py3-none-any.whl", hash = "sha256:7f640fcfb0be486aa510594df309920ae1d375cdca1f8aff21db3a96d837f303", size = 31562 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/3e/aef19ac08a6f9a347c086c4e628c2f7329659828cbe92ffd524ec2aac833/mcp-1.1.0-py3-none-any.whl", hash = "sha256:44aa4d2e541f0924d6c344aa7f96b427a6ee1df2fab70b5f9ae2f8777b3f05f2", size = 36576 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mcp-server-git"
|
||||
version = "0.4.1"
|
||||
version = "0.6.2"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
|
|
@ -182,7 +182,7 @@ dev = [
|
|||
requires-dist = [
|
||||
{ name = "click", specifier = ">=8.1.7" },
|
||||
{ name = "gitpython", specifier = ">=3.1.43" },
|
||||
{ name = "mcp", specifier = ">=0.6.0" },
|
||||
{ name = "mcp", specifier = ">=1.0.0" },
|
||||
{ name = "pydantic", specifier = ">=2.0.0" },
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# GitHub MCP Server
|
||||
|
||||
MCP Server for the GitHub API, enabling file operations, repository management, and more.
|
||||
MCP Server for the GitHub API, enabling file operations, repository management, search functionality, and more.
|
||||
|
||||
### Features
|
||||
|
||||
|
|
@ -8,6 +8,7 @@ MCP Server for the GitHub API, enabling file operations, repository management,
|
|||
- **Comprehensive Error Handling**: Clear error messages for common issues
|
||||
- **Git History Preservation**: Operations maintain proper Git history without force pushing
|
||||
- **Batch Operations**: Support for both single-file and multi-file operations
|
||||
- **Advanced Search**: Support for searching code, issues/PRs, and users
|
||||
|
||||
|
||||
## Tools
|
||||
|
|
@ -102,7 +103,74 @@ MCP Server for the GitHub API, enabling file operations, repository management,
|
|||
- `from_branch` (optional string): Source branch (defaults to repo default)
|
||||
- Returns: Created branch reference
|
||||
|
||||
10. `list_commits`
|
||||
10. `list_issues`
|
||||
- List and filter repository issues
|
||||
- Inputs:
|
||||
- `owner` (string): Repository owner
|
||||
- `repo` (string): Repository name
|
||||
- `state` (optional string): Filter by state ('open', 'closed', 'all')
|
||||
- `labels` (optional string[]): Filter by labels
|
||||
- `sort` (optional string): Sort by ('created', 'updated', 'comments')
|
||||
- `direction` (optional string): Sort direction ('asc', 'desc')
|
||||
- `since` (optional string): Filter by date (ISO 8601 timestamp)
|
||||
- `page` (optional number): Page number
|
||||
- `per_page` (optional number): Results per page
|
||||
- Returns: Array of issue details
|
||||
|
||||
11. `update_issue`
|
||||
- Update an existing issue
|
||||
- Inputs:
|
||||
- `owner` (string): Repository owner
|
||||
- `repo` (string): Repository name
|
||||
- `issue_number` (number): Issue number to update
|
||||
- `title` (optional string): New title
|
||||
- `body` (optional string): New description
|
||||
- `state` (optional string): New state ('open' or 'closed')
|
||||
- `labels` (optional string[]): New labels
|
||||
- `assignees` (optional string[]): New assignees
|
||||
- `milestone` (optional number): New milestone number
|
||||
- Returns: Updated issue details
|
||||
|
||||
12. `add_issue_comment`
|
||||
- Add a comment to an issue
|
||||
- Inputs:
|
||||
- `owner` (string): Repository owner
|
||||
- `repo` (string): Repository name
|
||||
- `issue_number` (number): Issue number to comment on
|
||||
- `body` (string): Comment text
|
||||
- Returns: Created comment details
|
||||
|
||||
13. `search_code`
|
||||
- Search for code across GitHub repositories
|
||||
- Inputs:
|
||||
- `q` (string): Search query using GitHub code search syntax
|
||||
- `sort` (optional string): Sort field ('indexed' only)
|
||||
- `order` (optional string): Sort order ('asc' or 'desc')
|
||||
- `per_page` (optional number): Results per page (max 100)
|
||||
- `page` (optional number): Page number
|
||||
- Returns: Code search results with repository context
|
||||
|
||||
14. `search_issues`
|
||||
- Search for issues and pull requests
|
||||
- Inputs:
|
||||
- `q` (string): Search query using GitHub issues search syntax
|
||||
- `sort` (optional string): Sort field (comments, reactions, created, etc.)
|
||||
- `order` (optional string): Sort order ('asc' or 'desc')
|
||||
- `per_page` (optional number): Results per page (max 100)
|
||||
- `page` (optional number): Page number
|
||||
- Returns: Issue and pull request search results
|
||||
|
||||
15. `search_users`
|
||||
- Search for GitHub users
|
||||
- Inputs:
|
||||
- `q` (string): Search query using GitHub users search syntax
|
||||
- `sort` (optional string): Sort field (followers, repositories, joined)
|
||||
- `order` (optional string): Sort order ('asc' or 'desc')
|
||||
- `per_page` (optional number): Results per page (max 100)
|
||||
- `page` (optional number): Page number
|
||||
- Returns: User search results
|
||||
|
||||
16. `list_commits`
|
||||
- Gets commits of a branch in a repository
|
||||
- Inputs:
|
||||
- `owner` (string): Repository owner
|
||||
|
|
@ -112,6 +180,30 @@ MCP Server for the GitHub API, enabling file operations, repository management,
|
|||
- `sha` (optional string): branch name
|
||||
- Returns: List of commits
|
||||
|
||||
## Search Query Syntax
|
||||
|
||||
### Code Search
|
||||
- `language:javascript`: Search by programming language
|
||||
- `repo:owner/name`: Search in specific repository
|
||||
- `path:app/src`: Search in specific path
|
||||
- `extension:js`: Search by file extension
|
||||
- Example: `q: "import express" language:typescript path:src/`
|
||||
|
||||
### Issues Search
|
||||
- `is:issue` or `is:pr`: Filter by type
|
||||
- `is:open` or `is:closed`: Filter by state
|
||||
- `label:bug`: Search by label
|
||||
- `author:username`: Search by author
|
||||
- Example: `q: "memory leak" is:issue is:open label:bug`
|
||||
|
||||
### Users Search
|
||||
- `type:user` or `type:org`: Filter by account type
|
||||
- `followers:>1000`: Filter by followers
|
||||
- `location:London`: Search by location
|
||||
- Example: `q: "fullstack developer" location:London followers:>100`
|
||||
|
||||
For detailed search syntax, see [GitHub's searching documentation](https://docs.github.com/en/search-github/searching-on-github).
|
||||
|
||||
## Setup
|
||||
|
||||
### Personal Access Token
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue