mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-19 08:43:28 +02:00
Merge branch 'main' into bugfix/github-issue-label-null-description
This commit is contained in:
@@ -96,6 +96,20 @@ Resource features:
|
||||
- `style` (string): Output style preference
|
||||
- Returns: Multi-turn conversation with images
|
||||
|
||||
### Logging
|
||||
|
||||
The server sends random-leveled log messages every 15 seconds, e.g.:
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "notifications/message",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"data": "Info-level message"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage with Claude Desktop
|
||||
|
||||
Add to your `claude_desktop_config.json`:
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
ListResourcesRequestSchema,
|
||||
ListResourceTemplatesRequestSchema,
|
||||
ListToolsRequestSchema,
|
||||
LoggingLevel,
|
||||
ReadResourceRequestSchema,
|
||||
Resource,
|
||||
SetLevelRequestSchema,
|
||||
@@ -99,10 +100,10 @@ export const createServer = () => {
|
||||
);
|
||||
|
||||
let subscriptions: Set<string> = new Set();
|
||||
let updateInterval: NodeJS.Timeout | undefined;
|
||||
|
||||
let subsUpdateInterval: NodeJS.Timeout | undefined;
|
||||
// Set up update interval for subscribed resources
|
||||
updateInterval = setInterval(() => {
|
||||
|
||||
subsUpdateInterval = setInterval(() => {
|
||||
for (const uri of subscriptions) {
|
||||
server.notification({
|
||||
method: "notifications/resources/updated",
|
||||
@@ -111,6 +112,34 @@ export const createServer = () => {
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
let logLevel: LoggingLevel = "debug";
|
||||
let logsUpdateInterval: NodeJS.Timeout | undefined;
|
||||
const messages = [
|
||||
{level: "debug", data: "Debug-level message"},
|
||||
{level: "info", data: "Info-level message"},
|
||||
{level: "notice", data: "Notice-level message"},
|
||||
{level: "warning", data: "Warning-level message"},
|
||||
{level: "error", data: "Error-level message"},
|
||||
{level: "critical", data: "Critical-level message"},
|
||||
{level: "alert", data: "Alert level-message"},
|
||||
{level: "emergency", data: "Emergency-level message"}
|
||||
]
|
||||
|
||||
const isMessageIgnored = (level:LoggingLevel):boolean => {
|
||||
const currentLevel = messages.findIndex((msg) => logLevel === msg.level);
|
||||
const messageLevel = messages.findIndex((msg) => level === msg.level);
|
||||
return messageLevel < currentLevel;
|
||||
}
|
||||
|
||||
// Set up update interval for random log messages
|
||||
logsUpdateInterval = setInterval(() => {
|
||||
let message = {
|
||||
method: "notifications/message",
|
||||
params: messages[Math.floor(Math.random() * messages.length)],
|
||||
}
|
||||
if (!isMessageIgnored(message.params.level as LoggingLevel)) server.notification(message);
|
||||
}, 15000);
|
||||
|
||||
// Helper method to request sampling from client
|
||||
const requestSampling = async (
|
||||
context: string,
|
||||
@@ -451,7 +480,7 @@ export const createServer = () => {
|
||||
|
||||
if (name === ToolName.ANNOTATED_MESSAGE) {
|
||||
const { messageType, includeImage } = AnnotatedMessageSchema.parse(args);
|
||||
|
||||
|
||||
const content = [];
|
||||
|
||||
// Main message with different priorities/audiences based on type
|
||||
@@ -511,7 +540,7 @@ export const createServer = () => {
|
||||
if (!resourceId) return { completion: { values: [] } };
|
||||
|
||||
// Filter resource IDs that start with the input value
|
||||
const values = EXAMPLE_COMPLETIONS.resourceId.filter(id =>
|
||||
const values = EXAMPLE_COMPLETIONS.resourceId.filter(id =>
|
||||
id.startsWith(argument.value)
|
||||
);
|
||||
return { completion: { values, hasMore: false, total: values.length } };
|
||||
@@ -522,7 +551,7 @@ export const createServer = () => {
|
||||
const completions = EXAMPLE_COMPLETIONS[argument.name as keyof typeof EXAMPLE_COMPLETIONS];
|
||||
if (!completions) return { completion: { values: [] } };
|
||||
|
||||
const values = completions.filter(value =>
|
||||
const values = completions.filter(value =>
|
||||
value.startsWith(argument.value)
|
||||
);
|
||||
return { completion: { values, hasMore: false, total: values.length } };
|
||||
@@ -533,6 +562,7 @@ export const createServer = () => {
|
||||
|
||||
server.setRequestHandler(SetLevelRequestSchema, async (request) => {
|
||||
const { level } = request.params;
|
||||
logLevel = level;
|
||||
|
||||
// Demonstrate different log levels
|
||||
await server.notification({
|
||||
@@ -540,7 +570,7 @@ export const createServer = () => {
|
||||
params: {
|
||||
level: "debug",
|
||||
logger: "test-server",
|
||||
data: `Logging level set to: ${level}`,
|
||||
data: `Logging level set to: ${logLevel}`,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -548,9 +578,8 @@ export const createServer = () => {
|
||||
});
|
||||
|
||||
const cleanup = async () => {
|
||||
if (updateInterval) {
|
||||
clearInterval(updateInterval);
|
||||
}
|
||||
if (subsUpdateInterval) clearInterval(subsUpdateInterval);
|
||||
if (logsUpdateInterval) clearInterval(logsUpdateInterval);
|
||||
};
|
||||
|
||||
return { server, cleanup };
|
||||
|
||||
@@ -41,22 +41,16 @@ Node.js server implementing Model Context Protocol (MCP) for filesystem operatio
|
||||
- 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
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ const allowedDirectories = args.map(dir =>
|
||||
// Validate that all directories exist and are accessible
|
||||
await Promise.all(args.map(async (dir) => {
|
||||
try {
|
||||
const stats = await fs.stat(dir);
|
||||
const stats = await fs.stat(expandHome(dir));
|
||||
if (!stats.isDirectory()) {
|
||||
console.error(`Error: ${dir} is not a directory`);
|
||||
process.exit(1);
|
||||
|
||||
4
src/git/uv.lock
generated
4
src/git/uv.lock
generated
@@ -165,9 +165,9 @@ dependencies = [
|
||||
{ name = "sse-starlette" },
|
||||
{ name = "starlette" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/97/de/a9ec0a1b6439f90ea59f89004bb2e7ec6890dfaeef809751d9e6577dca7e/mcp-1.0.0.tar.gz", hash = "sha256:dba51ce0b5c6a80e25576f606760c49a91ee90210fed805b530ca165d3bbc9b7", size = 82891 }
|
||||
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/56/89/900c0c8445ec001d3725e475fc553b0feb2e8a51be018f3bb7de51e683db/mcp-1.0.0-py3-none-any.whl", hash = "sha256:bbe70ffa3341cd4da78b5eb504958355c68381fb29971471cea1e642a2af5b8a", size = 36361 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/3e/aef19ac08a6f9a347c086c4e628c2f7329659828cbe92ffd524ec2aac833/mcp-1.1.0-py3-none-any.whl", hash = "sha256:44aa4d2e541f0924d6c344aa7f96b427a6ee1df2fab70b5f9ae2f8777b3f05f2", size = 36576 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -149,6 +149,51 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
name: "get_issue",
|
||||
description: "Get details of a specific issue in a GitHub repository.",
|
||||
inputSchema: zodToJsonSchema(issues.GetIssueSchema)
|
||||
},
|
||||
{
|
||||
name: "get_pull_request",
|
||||
description: "Get details of a specific pull request",
|
||||
inputSchema: zodToJsonSchema(pulls.GetPullRequestSchema)
|
||||
},
|
||||
{
|
||||
name: "list_pull_requests",
|
||||
description: "List and filter repository pull requests",
|
||||
inputSchema: zodToJsonSchema(pulls.ListPullRequestsSchema)
|
||||
},
|
||||
{
|
||||
name: "create_pull_request_review",
|
||||
description: "Create a review on a pull request",
|
||||
inputSchema: zodToJsonSchema(pulls.CreatePullRequestReviewSchema)
|
||||
},
|
||||
{
|
||||
name: "merge_pull_request",
|
||||
description: "Merge a pull request",
|
||||
inputSchema: zodToJsonSchema(pulls.MergePullRequestSchema)
|
||||
},
|
||||
{
|
||||
name: "get_pull_request_files",
|
||||
description: "Get the list of files changed in a pull request",
|
||||
inputSchema: zodToJsonSchema(pulls.GetPullRequestFilesSchema)
|
||||
},
|
||||
{
|
||||
name: "get_pull_request_status",
|
||||
description: "Get the combined status of all status checks for a pull request",
|
||||
inputSchema: zodToJsonSchema(pulls.GetPullRequestStatusSchema)
|
||||
},
|
||||
{
|
||||
name: "update_pull_request_branch",
|
||||
description: "Update a pull request branch with the latest changes from the base branch",
|
||||
inputSchema: zodToJsonSchema(pulls.UpdatePullRequestBranchSchema)
|
||||
},
|
||||
{
|
||||
name: "get_pull_request_comments",
|
||||
description: "Get the review comments on a pull request",
|
||||
inputSchema: zodToJsonSchema(pulls.GetPullRequestCommentsSchema)
|
||||
},
|
||||
{
|
||||
name: "get_pull_request_reviews",
|
||||
description: "Get the reviews on a pull request",
|
||||
inputSchema: zodToJsonSchema(pulls.GetPullRequestReviewsSchema)
|
||||
}
|
||||
],
|
||||
};
|
||||
@@ -335,6 +380,82 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
};
|
||||
}
|
||||
|
||||
case "get_pull_request": {
|
||||
const args = pulls.GetPullRequestSchema.parse(request.params.arguments);
|
||||
const pullRequest = await pulls.getPullRequest(args.owner, args.repo, args.pull_number);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(pullRequest, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "list_pull_requests": {
|
||||
const args = pulls.ListPullRequestsSchema.parse(request.params.arguments);
|
||||
const { owner, repo, ...options } = args;
|
||||
const pullRequests = await pulls.listPullRequests(owner, repo, options);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(pullRequests, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "create_pull_request_review": {
|
||||
const args = pulls.CreatePullRequestReviewSchema.parse(request.params.arguments);
|
||||
const { owner, repo, pull_number, ...options } = args;
|
||||
const review = await pulls.createPullRequestReview(owner, repo, pull_number, options);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(review, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "merge_pull_request": {
|
||||
const args = pulls.MergePullRequestSchema.parse(request.params.arguments);
|
||||
const { owner, repo, pull_number, ...options } = args;
|
||||
const result = await pulls.mergePullRequest(owner, repo, pull_number, options);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "get_pull_request_files": {
|
||||
const args = pulls.GetPullRequestFilesSchema.parse(request.params.arguments);
|
||||
const files = await pulls.getPullRequestFiles(args.owner, args.repo, args.pull_number);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(files, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "get_pull_request_status": {
|
||||
const args = pulls.GetPullRequestStatusSchema.parse(request.params.arguments);
|
||||
const status = await pulls.getPullRequestStatus(args.owner, args.repo, args.pull_number);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(status, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "update_pull_request_branch": {
|
||||
const args = pulls.UpdatePullRequestBranchSchema.parse(request.params.arguments);
|
||||
const { owner, repo, pull_number, expected_head_sha } = args;
|
||||
await pulls.updatePullRequestBranch(owner, repo, pull_number, expected_head_sha);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify({ success: true }, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "get_pull_request_comments": {
|
||||
const args = pulls.GetPullRequestCommentsSchema.parse(request.params.arguments);
|
||||
const comments = await pulls.getPullRequestComments(args.owner, args.repo, args.pull_number);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(comments, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "get_pull_request_reviews": {
|
||||
const args = pulls.GetPullRequestReviewsSchema.parse(request.params.arguments);
|
||||
const reviews = await pulls.getPullRequestReviews(args.owner, args.repo, args.pull_number);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(reviews, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown tool: ${request.params.name}`);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
{
|
||||
"name": "redis",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"name": "@modelcontextprotocol/server-redis",
|
||||
"version": "0.1.0",
|
||||
"description": "MCP server for using Redis",
|
||||
"license": "MIT",
|
||||
"author": "Anthropic, PBC (https://anthropic.com)",
|
||||
"homepage": "https://modelcontextprotocol.io",
|
||||
"bugs": "https://github.com/modelcontextprotocol/servers/issues",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"redis": "./build/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\""
|
||||
},
|
||||
"files": [
|
||||
"build"
|
||||
],
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.2",
|
||||
"typescript": "^5.7.2"
|
||||
"scripts": {
|
||||
"build": "tsc && shx chmod +x build/*.js",
|
||||
"prepare": "npm run build",
|
||||
"watch": "tsc --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^0.4.0",
|
||||
"@modelcontextprotocol/sdk": "^1.7.0",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/redis": "^4.0.10",
|
||||
"redis": "^4.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"shx": "^0.3.4",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user