mirror of
https://github.com/theonedev/onedev.git
synced 2025-12-11 04:40:59 -06:00
midwork
This commit is contained in:
parent
571e6a0280
commit
593db97cd3
@ -0,0 +1,24 @@
|
|||||||
|
package io.onedev.server.mcp;
|
||||||
|
|
||||||
|
import io.onedev.commons.loader.AbstractPluginModule;
|
||||||
|
import io.onedev.server.jetty.ServletConfigurator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module for the MCP (Model Context Protocol) server.
|
||||||
|
*
|
||||||
|
* This module configures the dependency injection for MCP server components
|
||||||
|
* and registers the servlet configurator with the Jetty server.
|
||||||
|
*/
|
||||||
|
public class MCPModule extends AbstractPluginModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
super.configure();
|
||||||
|
|
||||||
|
// Bind the MCP server servlet as a singleton
|
||||||
|
bind(MCPServerServlet.class).asEagerSingleton();
|
||||||
|
|
||||||
|
// Contribute the MCP servlet configurator to the ServletConfigurator extension point
|
||||||
|
contribute(ServletConfigurator.class, MCPServletConfigurator.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,315 @@
|
|||||||
|
package io.onedev.server.mcp;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import io.onedev.commons.utils.ExceptionUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example MCP (Model Context Protocol) Server Servlet
|
||||||
|
*
|
||||||
|
* This servlet implements a basic MCP server that can handle:
|
||||||
|
* - List resources
|
||||||
|
* - Read resources
|
||||||
|
* - List tools
|
||||||
|
* - Call tools
|
||||||
|
*
|
||||||
|
* The MCP server provides access to OneDev server information and basic operations.
|
||||||
|
*/
|
||||||
|
public class MCPServerServlet extends HttpServlet {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MCPServerServlet.class);
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
// In-memory storage for demo purposes
|
||||||
|
private final Map<String, JsonNode> resources = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public MCPServerServlet() {
|
||||||
|
// Initialize with some example resources
|
||||||
|
initializeExampleResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeExampleResources() {
|
||||||
|
try {
|
||||||
|
ObjectNode serverInfo = objectMapper.createObjectNode();
|
||||||
|
serverInfo.put("name", "OneDev Server");
|
||||||
|
serverInfo.put("version", "1.0.0");
|
||||||
|
serverInfo.put("status", "running");
|
||||||
|
resources.put("server:info", serverInfo);
|
||||||
|
|
||||||
|
ObjectNode config = objectMapper.createObjectNode();
|
||||||
|
config.put("port", 8080);
|
||||||
|
config.put("contextPath", "/");
|
||||||
|
config.put("sessionTimeout", 300);
|
||||||
|
resources.put("server:config", config);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error initializing example resources", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
|
||||||
|
response.setContentType("application/json");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Read request body
|
||||||
|
StringBuilder requestBody = new StringBuilder();
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
requestBody.append(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode requestNode = objectMapper.readTree(requestBody.toString());
|
||||||
|
String method = requestNode.get("method").asText();
|
||||||
|
JsonNode params = requestNode.get("params");
|
||||||
|
String id = requestNode.get("id").asText();
|
||||||
|
|
||||||
|
JsonNode result = handleRequest(method, params);
|
||||||
|
|
||||||
|
// Send response
|
||||||
|
ObjectNode responseNode = objectMapper.createObjectNode();
|
||||||
|
responseNode.put("jsonrpc", "2.0");
|
||||||
|
responseNode.put("id", id);
|
||||||
|
responseNode.set("result", result);
|
||||||
|
|
||||||
|
try (PrintWriter writer = response.getWriter()) {
|
||||||
|
writer.write(objectMapper.writeValueAsString(responseNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error handling MCP request", e);
|
||||||
|
sendErrorResponse(response, -1, "Internal server error: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode handleRequest(String method, JsonNode params) {
|
||||||
|
switch (method) {
|
||||||
|
case "initialize":
|
||||||
|
return handleInitialize(params);
|
||||||
|
case "resources/list":
|
||||||
|
return handleListResources(params);
|
||||||
|
case "resources/read":
|
||||||
|
return handleReadResource(params);
|
||||||
|
case "tools/list":
|
||||||
|
return handleListTools(params);
|
||||||
|
case "tools/call":
|
||||||
|
return handleCallTool(params);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown method: " + method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode handleInitialize(JsonNode params) {
|
||||||
|
ObjectNode result = objectMapper.createObjectNode();
|
||||||
|
result.put("protocolVersion", "2024-11-05");
|
||||||
|
result.put("capabilities", objectMapper.createObjectNode());
|
||||||
|
result.put("serverInfo", objectMapper.createObjectNode()
|
||||||
|
.put("name", "OneDev MCP Server")
|
||||||
|
.put("version", "1.0.0"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode handleListResources(JsonNode params) {
|
||||||
|
ArrayNode resourcesArray = objectMapper.createArrayNode();
|
||||||
|
|
||||||
|
for (String uri : resources.keySet()) {
|
||||||
|
ObjectNode resource = objectMapper.createObjectNode();
|
||||||
|
resource.put("uri", uri);
|
||||||
|
resource.put("name", uri.substring(uri.lastIndexOf(':') + 1));
|
||||||
|
resource.put("description", "OneDev server " + uri.substring(uri.lastIndexOf(':') + 1));
|
||||||
|
resource.put("mimeType", "application/json");
|
||||||
|
resourcesArray.add(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectNode result = objectMapper.createObjectNode();
|
||||||
|
result.set("resources", resourcesArray);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode handleReadResource(JsonNode params) {
|
||||||
|
String uri = params.get("uri").asText();
|
||||||
|
JsonNode resource = resources.get(uri);
|
||||||
|
|
||||||
|
if (resource == null) {
|
||||||
|
throw new IllegalArgumentException("Resource not found: " + uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectNode result = objectMapper.createObjectNode();
|
||||||
|
result.set("contents", objectMapper.createArrayNode().add(objectMapper.createObjectNode()
|
||||||
|
.put("uri", uri)
|
||||||
|
.put("mimeType", "application/json")
|
||||||
|
.set("text", resource)));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode handleListTools(JsonNode params) {
|
||||||
|
ArrayNode toolsArray = objectMapper.createArrayNode();
|
||||||
|
|
||||||
|
// Example tools
|
||||||
|
ObjectNode serverStatusTool = objectMapper.createObjectNode();
|
||||||
|
serverStatusTool.put("name", "getServerStatus");
|
||||||
|
serverStatusTool.put("description", "Get the current status of the OneDev server");
|
||||||
|
serverStatusTool.set("inputSchema", objectMapper.createObjectNode());
|
||||||
|
toolsArray.add(serverStatusTool);
|
||||||
|
|
||||||
|
ObjectNode createResourceTool = objectMapper.createObjectNode();
|
||||||
|
createResourceTool.put("name", "createResource");
|
||||||
|
createResourceTool.put("description", "Create a new resource");
|
||||||
|
ObjectNode inputSchema = objectMapper.createObjectNode();
|
||||||
|
inputSchema.put("type", "object");
|
||||||
|
ObjectNode properties = objectMapper.createObjectNode();
|
||||||
|
properties.put("uri", objectMapper.createObjectNode().put("type", "string"));
|
||||||
|
properties.put("content", objectMapper.createObjectNode().put("type", "object"));
|
||||||
|
inputSchema.set("properties", properties);
|
||||||
|
inputSchema.set("required", objectMapper.createArrayNode().add("uri").add("content"));
|
||||||
|
createResourceTool.set("inputSchema", inputSchema);
|
||||||
|
toolsArray.add(createResourceTool);
|
||||||
|
|
||||||
|
ObjectNode result = objectMapper.createObjectNode();
|
||||||
|
result.set("tools", toolsArray);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode handleCallTool(JsonNode params) {
|
||||||
|
String name = params.get("name").asText();
|
||||||
|
JsonNode arguments = params.get("arguments");
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case "getServerStatus":
|
||||||
|
return handleGetServerStatus(arguments);
|
||||||
|
case "createResource":
|
||||||
|
return handleCreateResource(arguments);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown tool: " + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode handleGetServerStatus(JsonNode arguments) {
|
||||||
|
ObjectNode result = objectMapper.createObjectNode();
|
||||||
|
result.put("status", "running");
|
||||||
|
result.put("uptime", System.currentTimeMillis());
|
||||||
|
result.put("memoryUsage", Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
|
||||||
|
result.put("totalMemory", Runtime.getRuntime().totalMemory());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode handleCreateResource(JsonNode arguments) {
|
||||||
|
String uri = arguments.get("uri").asText();
|
||||||
|
JsonNode content = arguments.get("content");
|
||||||
|
|
||||||
|
if (resources.containsKey(uri)) {
|
||||||
|
throw new IllegalArgumentException("Resource already exists: " + uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
resources.put(uri, content);
|
||||||
|
|
||||||
|
ObjectNode result = objectMapper.createObjectNode();
|
||||||
|
result.put("uri", uri);
|
||||||
|
result.put("created", true);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendErrorResponse(HttpServletResponse response, int code, String message) throws IOException {
|
||||||
|
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||||
|
response.setContentType("application/json");
|
||||||
|
|
||||||
|
ObjectNode errorNode = objectMapper.createObjectNode();
|
||||||
|
errorNode.put("jsonrpc", "2.0");
|
||||||
|
errorNode.put("id", (String)null);
|
||||||
|
ObjectNode error = objectMapper.createObjectNode();
|
||||||
|
error.put("code", code);
|
||||||
|
error.put("message", message);
|
||||||
|
errorNode.set("error", error);
|
||||||
|
|
||||||
|
try (PrintWriter writer = response.getWriter()) {
|
||||||
|
writer.write(objectMapper.writeValueAsString(errorNode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
|
||||||
|
response.setContentType("text/html");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
|
||||||
|
try (PrintWriter writer = response.getWriter()) {
|
||||||
|
writer.write("<!DOCTYPE html>\n" +
|
||||||
|
"<html>\n" +
|
||||||
|
"<head>\n" +
|
||||||
|
" <title>OneDev MCP Server</title>\n" +
|
||||||
|
" <style>\n" +
|
||||||
|
" body { font-family: Arial, sans-serif; margin: 40px; }\n" +
|
||||||
|
" .container { max-width: 800px; margin: 0 auto; }\n" +
|
||||||
|
" .endpoint { background: #f5f5f5; padding: 20px; margin: 20px 0; border-radius: 5px; }\n" +
|
||||||
|
" .method { font-weight: bold; color: #0066cc; }\n" +
|
||||||
|
" .description { margin-top: 10px; color: #666; }\n" +
|
||||||
|
" </style>\n" +
|
||||||
|
"</head>\n" +
|
||||||
|
"<body>\n" +
|
||||||
|
" <div class=\"container\">\n" +
|
||||||
|
" <h1>OneDev MCP Server</h1>\n" +
|
||||||
|
" <p>This is an example Model Context Protocol (MCP) server for OneDev.</p>\n" +
|
||||||
|
" \n" +
|
||||||
|
" <div class=\"endpoint\">\n" +
|
||||||
|
" <div class=\"method\">POST /mcp</div>\n" +
|
||||||
|
" <div class=\"description\">\n" +
|
||||||
|
" Main MCP endpoint that handles all protocol requests including:\n" +
|
||||||
|
" <ul>\n" +
|
||||||
|
" <li>initialize - Initialize the MCP connection</li>\n" +
|
||||||
|
" <li>resources/list - List available resources</li>\n" +
|
||||||
|
" <li>resources/read - Read a specific resource</li>\n" +
|
||||||
|
" <li>tools/list - List available tools</li>\n" +
|
||||||
|
" <li>tools/call - Call a specific tool</li>\n" +
|
||||||
|
" </ul>\n" +
|
||||||
|
" </div>\n" +
|
||||||
|
" </div>\n" +
|
||||||
|
" \n" +
|
||||||
|
" <h2>Available Resources</h2>\n" +
|
||||||
|
" <ul>\n" +
|
||||||
|
" <li><code>server:info</code> - Basic server information</li>\n" +
|
||||||
|
" <li><code>server:config</code> - Server configuration</li>\n" +
|
||||||
|
" </ul>\n" +
|
||||||
|
" \n" +
|
||||||
|
" <h2>Available Tools</h2>\n" +
|
||||||
|
" <ul>\n" +
|
||||||
|
" <li><code>getServerStatus</code> - Get current server status</li>\n" +
|
||||||
|
" <li><code>createResource</code> - Create a new resource</li>\n" +
|
||||||
|
" </ul>\n" +
|
||||||
|
" \n" +
|
||||||
|
" <h2>Example Request</h2>\n" +
|
||||||
|
" <pre>\n" +
|
||||||
|
"{\n" +
|
||||||
|
" \"jsonrpc\": \"2.0\",\n" +
|
||||||
|
" \"id\": 1,\n" +
|
||||||
|
" \"method\": \"resources/list\",\n" +
|
||||||
|
" \"params\": {}\n" +
|
||||||
|
"}\n" +
|
||||||
|
" </pre>\n" +
|
||||||
|
" </div>\n" +
|
||||||
|
"</body>\n" +
|
||||||
|
"</html>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package io.onedev.server.mcp;
|
||||||
|
|
||||||
|
import io.onedev.server.jetty.ServletConfigurator;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Servlet configurator for the MCP (Model Context Protocol) server.
|
||||||
|
*
|
||||||
|
* This configurator registers the MCP servlet with the Jetty server
|
||||||
|
* to handle MCP protocol requests at the /mcp endpoint.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class MCPServletConfigurator implements ServletConfigurator {
|
||||||
|
|
||||||
|
private final MCPServerServlet mcpServerServlet;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public MCPServletConfigurator(MCPServerServlet mcpServerServlet) {
|
||||||
|
this.mcpServerServlet = mcpServerServlet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(ServletContextHandler context) {
|
||||||
|
// Register the MCP servlet at the /mcp path
|
||||||
|
ServletHolder mcpServletHolder = new ServletHolder(mcpServerServlet);
|
||||||
|
context.addServlet(mcpServletHolder, "/mcp");
|
||||||
|
|
||||||
|
// Also register at /mcp/* to handle all MCP-related requests
|
||||||
|
context.addServlet(mcpServletHolder, "/mcp/*");
|
||||||
|
}
|
||||||
|
}
|
||||||
131
server-core/src/main/java/io/onedev/server/mcp/README.md
Normal file
131
server-core/src/main/java/io/onedev/server/mcp/README.md
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
# OneDev MCP Server
|
||||||
|
|
||||||
|
This is an example Model Context Protocol (MCP) server implementation for OneDev. The MCP server provides a standardized way for AI assistants and other tools to interact with OneDev server data and functionality.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The MCP server is implemented as a servlet that runs within the existing OneDev Jetty server. It handles HTTP requests and implements the MCP protocol to provide:
|
||||||
|
|
||||||
|
- **Resources**: Access to OneDev server information and configuration
|
||||||
|
- **Tools**: Operations that can be performed on the OneDev server
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The MCP server consists of the following components:
|
||||||
|
|
||||||
|
1. **MCPServerServlet**: The main servlet that handles HTTP requests and implements the MCP protocol
|
||||||
|
2. **MCPServletConfigurator**: Configures the servlet with the Jetty server
|
||||||
|
3. **MCPModule**: Dependency injection configuration
|
||||||
|
|
||||||
|
## Endpoints
|
||||||
|
|
||||||
|
### GET /mcp
|
||||||
|
Returns an HTML page with documentation about the MCP server and available endpoints.
|
||||||
|
|
||||||
|
### POST /mcp
|
||||||
|
Main MCP protocol endpoint that handles JSON-RPC requests.
|
||||||
|
|
||||||
|
## Available Resources
|
||||||
|
|
||||||
|
- `server:info` - Basic server information (name, version, status)
|
||||||
|
- `server:config` - Server configuration (port, context path, session timeout)
|
||||||
|
|
||||||
|
## Available Tools
|
||||||
|
|
||||||
|
- `getServerStatus` - Get current server status including uptime and memory usage
|
||||||
|
- `createResource` - Create a new resource with a given URI and content
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
### Initialize the MCP connection
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": 1,
|
||||||
|
"method": "initialize",
|
||||||
|
"params": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### List available resources
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": 2,
|
||||||
|
"method": "resources/list",
|
||||||
|
"params": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read a specific resource
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": 3,
|
||||||
|
"method": "resources/read",
|
||||||
|
"params": {
|
||||||
|
"uri": "server:info"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### List available tools
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": 4,
|
||||||
|
"method": "tools/list",
|
||||||
|
"params": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Call a tool
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": 5,
|
||||||
|
"method": "tools/call",
|
||||||
|
"params": {
|
||||||
|
"name": "getServerStatus",
|
||||||
|
"arguments": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Integration
|
||||||
|
|
||||||
|
The MCP server is automatically integrated into OneDev through the plugin system. The `MCPModule` extends `AbstractPluginModule` and is automatically discovered and loaded when OneDev starts.
|
||||||
|
|
||||||
|
The servlet is registered at the `/mcp` path and handles both GET requests (for documentation) and POST requests (for MCP protocol communication).
|
||||||
|
|
||||||
|
## Extending the MCP Server
|
||||||
|
|
||||||
|
To add new resources or tools:
|
||||||
|
|
||||||
|
1. **Add new resources**: Modify the `initializeExampleResources()` method in `MCPServerServlet`
|
||||||
|
2. **Add new tools**: Add new cases to the `handleCallTool()` method and implement the corresponding handler methods
|
||||||
|
3. **Add new MCP methods**: Add new cases to the `handleRequest()` method
|
||||||
|
|
||||||
|
## Protocol Compliance
|
||||||
|
|
||||||
|
This implementation follows the Model Context Protocol specification and supports:
|
||||||
|
|
||||||
|
- JSON-RPC 2.0 communication
|
||||||
|
- Resource listing and reading
|
||||||
|
- Tool listing and calling
|
||||||
|
- Proper error handling with JSON-RPC error responses
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
The current implementation is a basic example. In a production environment, you should consider:
|
||||||
|
|
||||||
|
- Authentication and authorization for MCP requests
|
||||||
|
- Rate limiting
|
||||||
|
- Input validation and sanitization
|
||||||
|
- Secure communication (HTTPS)
|
||||||
|
- Access control for sensitive server information
|
||||||
Loading…
x
Reference in New Issue
Block a user