Skip to content

Latest commit

 

History

History
2381 lines (1883 loc) · 78.8 KB

File metadata and controls

2381 lines (1883 loc) · 78.8 KB

MCP Maendeleo Mazoea Bora

MCP Development Best Practices

(Bonyeza picha hapo juu kutazama video ya somo hili)

Muhtasari

Somo hili linazingatia mbinu za hali ya juu za maendeleo, upimaji, na ueneaji wa seva na vipengele vya MCP katika mazingira ya uzalishaji. Kadiri mifumo ya MCP inavyoongezeka kwa ugumu na umuhimu, kufuata mifumo iliyowekwa kunahakikisha kuaminika, urahisi wa matengenezo, na mwingiliano. Somo hili linakusanya hekima ya vitendo iliyopatikana kutoka kwa utekelezaji halisi wa MCP ili kukuongoza katika kuunda seva imara, yenye ufanisi kwa rasilimali, viamsha, na zana bora.

Malengo ya Kujifunza

Mwisho wa somo hili, utaweza:

  • Kutumia mbinu bora za tasnia katika usanifu wa seva na vipengele vya MCP
  • Kuunda mikakati kamili ya upimaji kwa seva za MCP
  • Kubuni mifumo bora, inayorudiwa ya mtiririko wa kazi kwa programu tata za MCP
  • Kutekeleza usimamizi sahihi wa makosa, kurekodi kumbukumbu, na ufuatiliaji katika seva za MCP
  • Kuboresha utekelezaji wa MCP kwa ufanisi, usalama, na urahisi wa matengenezo

Kanuni za Msingi za MCP

Kabla ya kuingia katika mbinu maalum za utekelezaji, ni muhimu kuelewa kanuni msingi zinazowaongoza maendeleo ya MCP yenye ufanisi:

  1. Mawasiliano Yaliyopangwa Sanifu: MCP hutumia JSON-RPC 2.0 kama msingi wake, ikitoa muundo thabiti kwa maombi, majibu, na usimamizi wa makosa katika utekelezaji wote.

  2. Ubunifu Unaomzingatia Mtumiaji: Kila wakati weka mbele idhini, udhibiti, na uwazi wa mtumiaji katika utekelezaji wako wa MCP.

  3. Usalama Kwanza: Tekeleza hatua imara za usalama ikiwa ni pamoja na utambulisho, idhini, uthibitishaji, na kipimo cha kiwango cha maombi.

  4. Mimambo ya Kihusianisho: Buni seva zako za MCP kwa njia ya moduli, ambapo kila zana na rasilimali inakuwa na kusudi wazi na lengo.

  5. Mawasiliano ya Kidumu: Tumia uwezo wa MCP kudumisha hali kati ya maombi mengi kwa mazungumzo yaliyo na muktadha zaidi.

Mazoea Bora Rasmi ya MCP

Mazoea bora yafuatayo yanatokana na nyaraka rasmi za Itifaki ya Muktadha wa Mfano:

Mazoea Bora ya Usalama

  1. Idhini na Udhibiti wa Mtumiaji: Ikiwa daima inahitaji idhini wazi ya mtumiaji kabla ya kupata data au kufanya shughuli. Toa udhibiti wazi juu ya data inayoshirikiwa na vitendo vinavyoruhusiwa.

  2. Faragha ya Data: Weka wazi data ya mtumiaji tu kwa idhini ya wazi na uilinde kwa udhibiti wa upatikanaji unaofaa. Linda dhidi ya usambazaji wa data usioidhinishwa.

  3. Usalama wa Zana: Takikisha idhini wazi ya mtumiaji kabla ya kuitisha zana yoyote. Hakikisha watumiaji wanaelewa kazi za kila zana na zingatia mipaka imara ya usalama.

  4. Udhibiti wa Ruhusa za Zana: Sanidi ni zana gani modeli inaruhusiwa kutumia wakati wa kikao, kuhakikisha zana zilizoidhinishwa tu ndizo zinapatikana.

  5. Utambulisho: Hitaji utambulisho unaofaa kabla ya kutoa ruhusa ya kutumia zana, rasilimali, au shughuli nyeti kwa kutumia funguo za API, tokeni za OAuth, au njia nyingine salama za uthibitishaji.

  6. Uhakiki wa Vigezo: Fanya uhakikisho wa vigezo vya kila uitikaji wa zana ili kuzuia pembejeo zisizotakikana au hatari kufikia utekelezaji wa zana.

  7. Kipimo cha Kiwango cha Maombi: Tekeleza kipimo cha kiwango cha maombi ili kuzuia matumizi mabaya na kuhakikisha matumizi ya haki ya rasilimali za seva.

Mazoea Bora ya Utekelezaji

  1. Mjadala wa Uwezo: Wakati wa usanidi wa muunganisho, badilishana taarifa kuhusu vipengele vinavyotegemewa, matoleo ya itifaki, zana, na rasilimali zilizopo.

  2. Ubunifu wa Zana: Unda zana zenye lengo wazi zinazozingatia kazi moja vizuri, badala ya zana kubwa zinazoshughulikia masuala mengi.

  3. Usimamizi wa Makosa: Tekeleza ujumbe wa makosa na nambari zilizopangwa ili kusaidia kutambua matatizo, kushughulikia kushindwa kwa upole, na kutoa maoni yanayoweza kuchukuliwa hatua.

  4. Kurekodi Kumbukumbu: Sanidi kumbukumbu zilizoandaliwa kwa ukaguzi, utatuzi wa matatizo, na ufuatiliaji wa mwingiliano wa itifaki.

  5. Ufuatiliaji wa Maendeleo: Kwa shughuli zenye mzunguko mrefu, toa taarifa za maendeleo ili kuwezesha matumizi ya kiolesura vinavyojibu haraka.

  6. Kuahirisha Maombi: Ruhusu wateja kuahirisha maombi yaliyomo safarini ambayo hayahitajiki tena au yanachukua muda mrefu sana.

Marejeleo Zaidi

Kwa habari za kisasa zaidi kuhusu mazoea bora ya MCP, rejelea:

Mifano ya Utekelezaji wa Vitendo

Mazoea Bora ya Ubunifu wa Zana

1. Kanuni ya Majukumu Mmoja

Kila zana ya MCP inapaswa kuwa na kusudi wazi na lengo. Badala ya kuunda zana kubwa zinazojaribu kushughulikia masuala mengi, tengeneza zana maalum zinazobobea katika kazi maalum.

// A focused tool that does one thing well
public class WeatherForecastTool : ITool
{
    private readonly IWeatherService _weatherService;
    
    public WeatherForecastTool(IWeatherService weatherService)
    {
        _weatherService = weatherService;
    }
    
    public string Name => "weatherForecast";
    public string Description => "Gets weather forecast for a specific location";
    
    public ToolDefinition GetDefinition()
    {
        return new ToolDefinition
        {
            Name = Name,
            Description = Description,
            Parameters = new Dictionary<string, ParameterDefinition>
            {
                ["location"] = new ParameterDefinition
                {
                    Type = ParameterType.String,
                    Description = "City or location name"
                },
                ["days"] = new ParameterDefinition
                {
                    Type = ParameterType.Integer,
                    Description = "Number of forecast days",
                    Default = 3
                }
            },
            Required = new[] { "location" }
        };
    }
    
    public async Task<ToolResponse> ExecuteAsync(IDictionary<string, object> parameters)
    {
        var location = parameters["location"].ToString();
        var days = parameters.ContainsKey("days") 
            ? Convert.ToInt32(parameters["days"]) 
            : 3;
            
        var forecast = await _weatherService.GetForecastAsync(location, days);
        
        return new ToolResponse
        {
            Content = new List<ContentItem>
            {
                new TextContent(JsonSerializer.Serialize(forecast))
            }
        };
    }
}

2. Usimamizi Wakaidi wa Makosa

Tekeleza usimamizi imara wa makosa ukitumia ujumbe wa makosa wenye taarifa na mbinu zinazofaa za kupona.

# Mfano wa Python wenye uchunguzi wa makosa kwa kina
class DataQueryTool:
    def get_name(self):
        return "dataQuery"
        
    def get_description(self):
        return "Queries data from specified database tables"
    
    async def execute(self, parameters):
        try:
            # Uthibitishaji wa vigezo
            if "query" not in parameters:
                raise ToolParameterError("Missing required parameter: query")
                
            query = parameters["query"]
            
            # Uthibitishaji wa usalama
            if self._contains_unsafe_sql(query):
                raise ToolSecurityError("Query contains potentially unsafe SQL")
            
            try:
                # Operesheni ya database na muda wa kusubiri
                async with timeout(10):  # Muda wa kusubiri wa sekunde 10
                    result = await self._database.execute_query(query)
                    
                return ToolResponse(
                    content=[TextContent(json.dumps(result))]
                )
            except asyncio.TimeoutError:
                raise ToolExecutionError("Database query timed out after 10 seconds")
            except DatabaseConnectionError as e:
                # Makosa ya muunganisho yanaweza kuwa ya muda mfupi
                self._log_error("Database connection error", e)
                raise ToolExecutionError(f"Database connection error: {str(e)}")
            except DatabaseQueryError as e:
                # Makosa ya maswali yana uwezekano wa kuwa makosa ya mteja
                self._log_error("Database query error", e)
                raise ToolExecutionError(f"Invalid query: {str(e)}")
                
        except ToolError:
            # Ruhusu makosa maalum ya zana kupitishwa
            raise
        except Exception as e:
            # Kamili kwa makosa yasiyotarajiwa
            self._log_error("Unexpected error in DataQueryTool", e)
            raise ToolExecutionError(f"An unexpected error occurred: {str(e)}")
    
    def _contains_unsafe_sql(self, query):
        # Utekelezaji wa ugundaji wa sindano ya SQL
        pass
        
    def _log_error(self, message, error):
        # Utekelezaji wa kurekodi makosa
        pass

3. Uhakiki wa Vigezo

Daima hakiki vigezo vyote kwa kina ili kuzuia pembejeo zisizotakikana au hatari.

// Mfano wa JavaScript/TypeScript pamoja na uhakiki wa kina wa vigezo
class FileOperationTool {
  getName() {
    return "fileOperation";
  }
  
  getDescription() {
    return "Performs file operations like read, write, and delete";
  }
  
  getDefinition() {
    return {
      name: this.getName(),
      description: this.getDescription(),
      parameters: {
        operation: {
          type: "string",
          description: "Operation to perform",
          enum: ["read", "write", "delete"]
        },
        path: {
          type: "string",
          description: "File path (must be within allowed directories)"
        },
        content: {
          type: "string",
          description: "Content to write (only for write operation)",
          optional: true
        }
      },
      required: ["operation", "path"]
    };
  }
  
  async execute(parameters) {
    // 1. Thibitisha uwepo wa kigezo
    if (!parameters.operation) {
      throw new ToolError("Missing required parameter: operation");
    }
    
    if (!parameters.path) {
      throw new ToolError("Missing required parameter: path");
    }
    
    // 2. Thibitisha aina za vigezo
    if (typeof parameters.operation !== "string") {
      throw new ToolError("Parameter 'operation' must be a string");
    }
    
    if (typeof parameters.path !== "string") {
      throw new ToolError("Parameter 'path' must be a string");
    }
    
    // 3. Thibitisha thamani za vigezo
    const validOperations = ["read", "write", "delete"];
    if (!validOperations.includes(parameters.operation)) {
      throw new ToolError(`Invalid operation. Must be one of: ${validOperations.join(", ")}`);
    }
    
    // 4. Thibitisha uwepo wa maudhui kwa operesheni ya kuandika
    if (parameters.operation === "write" && !parameters.content) {
      throw new ToolError("Content parameter is required for write operation");
    }
    
    // 5. Uhakiki wa usalama wa njia
    if (!this.isPathWithinAllowedDirectories(parameters.path)) {
      throw new ToolError("Access denied: path is outside of allowed directories");
    }
    
    // Utekelezaji unaotegemea vigezo vilivyothibitishwa
    // ...
  }
  
  isPathWithinAllowedDirectories(path) {
    // Utekelezaji wa ukaguzi wa usalama wa njia
    // ...
  }
}

Mifano ya Utekelezaji wa Usalama

1. Utambulisho na Idhini

// Mfano wa Java na uthibitishaji na idhini
public class SecureDataAccessTool implements Tool {
    private final AuthenticationService authService;
    private final AuthorizationService authzService;
    private final DataService dataService;
    
    // Injection ya utegemezi
    public SecureDataAccessTool(
            AuthenticationService authService,
            AuthorizationService authzService,
            DataService dataService) {
        this.authService = authService;
        this.authzService = authzService;
        this.dataService = dataService;
    }
    
    @Override
    public String getName() {
        return "secureDataAccess";
    }
    
    @Override
    public ToolResponse execute(ToolRequest request) {
        // 1. Toa muktadha wa uthibitishaji
        String authToken = request.getContext().getAuthToken();
        
        // 2. Thibitisha mtumiaji
        UserIdentity user;
        try {
            user = authService.validateToken(authToken);
        } catch (AuthenticationException e) {
            return ToolResponse.error("Authentication failed: " + e.getMessage());
        }
        
        // 3. Angalia idhini kwa ajili ya operesheni maalum
        String dataId = request.getParameters().get("dataId").getAsString();
        String operation = request.getParameters().get("operation").getAsString();
        
        boolean isAuthorized = authzService.isAuthorized(user, "data:" + dataId, operation);
        if (!isAuthorized) {
            return ToolResponse.error("Access denied: Insufficient permissions for this operation");
        }
        
        // 4. Endelea na operesheni iliyoruhusiwa
        try {
            switch (operation) {
                case "read":
                    Object data = dataService.getData(dataId, user.getId());
                    return ToolResponse.success(data);
                case "update":
                    JsonNode newData = request.getParameters().get("newData");
                    dataService.updateData(dataId, newData, user.getId());
                    return ToolResponse.success("Data updated successfully");
                default:
                    return ToolResponse.error("Unsupported operation: " + operation);
            }
        } catch (Exception e) {
            return ToolResponse.error("Operation failed: " + e.getMessage());
        }
    }
}

2. Kipimo cha Kiwango cha Maombi

// C# rate limiting implementation
public class RateLimitingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IMemoryCache _cache;
    private readonly ILogger<RateLimitingMiddleware> _logger;
    
    // Configuration options
    private readonly int _maxRequestsPerMinute;
    
    public RateLimitingMiddleware(
        RequestDelegate next,
        IMemoryCache cache,
        ILogger<RateLimitingMiddleware> logger,
        IConfiguration config)
    {
        _next = next;
        _cache = cache;
        _logger = logger;
        _maxRequestsPerMinute = config.GetValue<int>("RateLimit:MaxRequestsPerMinute", 60);
    }
    
    public async Task InvokeAsync(HttpContext context)
    {
        // 1. Get client identifier (API key or user ID)
        string clientId = GetClientIdentifier(context);
        
        // 2. Get rate limiting key for this minute
        string cacheKey = $"rate_limit:{clientId}:{DateTime.UtcNow:yyyyMMddHHmm}";
        
        // 3. Check current request count
        if (!_cache.TryGetValue(cacheKey, out int requestCount))
        {
            requestCount = 0;
        }
        
        // 4. Enforce rate limit
        if (requestCount >= _maxRequestsPerMinute)
        {
            _logger.LogWarning("Rate limit exceeded for client {ClientId}", clientId);
            
            context.Response.StatusCode = StatusCodes.Status429TooManyRequests;
            context.Response.Headers.Add("Retry-After", "60");
            
            await context.Response.WriteAsJsonAsync(new
            {
                error = "Rate limit exceeded",
                message = "Too many requests. Please try again later.",
                retryAfterSeconds = 60
            });
            
            return;
        }
        
        // 5. Increment request count
        _cache.Set(cacheKey, requestCount + 1, TimeSpan.FromMinutes(2));
        
        // 6. Add rate limit headers
        context.Response.Headers.Add("X-RateLimit-Limit", _maxRequestsPerMinute.ToString());
        context.Response.Headers.Add("X-RateLimit-Remaining", (_maxRequestsPerMinute - requestCount - 1).ToString());
        
        // 7. Continue with the request
        await _next(context);
    }
    
    private string GetClientIdentifier(HttpContext context)
    {
        // Implementation to extract API key or user ID
        // ...
    }
}

Mazoea Bora ya Upimaji

1. Upimaji wa Zana za MCP kwa Kiwango Kidogo

Daima jaribu zana zako peke yake ukitumia maigizo ya utegemezi wa nje:

// Mfano wa TypeScript wa jaribio la kitengo cha zana
describe('WeatherForecastTool', () => {
  let tool: WeatherForecastTool;
  let mockWeatherService: jest.Mocked<IWeatherService>;
  
  beforeEach(() => {
    // Unda huduma ya hali ya hewa ya uigaji
    mockWeatherService = {
      getForecasts: jest.fn()
    } as any;
    
    // Unda zana na utegemezi wa uigaji
    tool = new WeatherForecastTool(mockWeatherService);
  });
  
  it('should return weather forecast for a location', async () => {
    // Panga
    const mockForecast = {
      location: 'Seattle',
      forecasts: [
        { date: '2025-07-16', temperature: 72, conditions: 'Sunny' },
        { date: '2025-07-17', temperature: 68, conditions: 'Partly Cloudy' },
        { date: '2025-07-18', temperature: 65, conditions: 'Rain' }
      ]
    };
    
    mockWeatherService.getForecasts.mockResolvedValue(mockForecast);
    
    // Fanya
    const response = await tool.execute({
      location: 'Seattle',
      days: 3
    });
    
    // Thibitisha
    expect(mockWeatherService.getForecasts).toHaveBeenCalledWith('Seattle', 3);
    expect(response.content[0].text).toContain('Seattle');
    expect(response.content[0].text).toContain('Sunny');
  });
  
  it('should handle errors from the weather service', async () => {
    // Panga
    mockWeatherService.getForecasts.mockRejectedValue(new Error('Service unavailable'));
    
    // Fanya & Thibitisha
    await expect(tool.execute({
      location: 'Seattle',
      days: 3
    })).rejects.toThrow('Weather service error: Service unavailable');
  });
});

2. Upimaji wa Uunganishaji

Jaribu mtiririko kamili kutoka maombi ya mteja hadi majibu ya seva:

# Mfano wa jaribio la muunganisho wa Python
@pytest.mark.asyncio
async def test_mcp_server_integration():
    # Anzisha seva ya jaribio
    server = McpServer()
    server.register_tool(WeatherForecastTool(MockWeatherService()))
    await server.start(port=5000)
    
    try:
        # Unda mteja
        client = McpClient("http://localhost:5000")
        
        # Jaribu ugunduzi wa zana
        tools = await client.discover_tools()
        assert "weatherForecast" in [t.name for t in tools]
        
        # Jaribu utekelezaji wa zana
        response = await client.execute_tool("weatherForecast", {
            "location": "Seattle",
            "days": 3
        })
        
        # Thibitisha majibu
        assert response.status_code == 200
        assert "Seattle" in response.content[0].text
        assert len(json.loads(response.content[0].text)["forecasts"]) == 3
        
    finally:
        # Safisha mazingira
        await server.stop()

Uboreshaji wa Utendaji

1. Mikakati ya Kuhifadhi Nakala

Tekeleza uhifadhi mzuri ili kupunguza ucheleweshaji na matumizi ya rasilimali:

// C# example with caching
public class CachedWeatherTool : ITool
{
    private readonly IWeatherService _weatherService;
    private readonly IDistributedCache _cache;
    private readonly ILogger<CachedWeatherTool> _logger;
    
    public CachedWeatherTool(
        IWeatherService weatherService,
        IDistributedCache cache,
        ILogger<CachedWeatherTool> logger)
    {
        _weatherService = weatherService;
        _cache = cache;
        _logger = logger;
    }
    
    public string Name => "weatherForecast";
    
    public async Task<ToolResponse> ExecuteAsync(IDictionary<string, object> parameters)
    {
        var location = parameters["location"].ToString();
        var days = Convert.ToInt32(parameters.GetValueOrDefault("days", 3));
        
        // Create cache key
        string cacheKey = $"weather:{location}:{days}";
        
        // Try to get from cache
        string cachedForecast = await _cache.GetStringAsync(cacheKey);
        if (!string.IsNullOrEmpty(cachedForecast))
        {
            _logger.LogInformation("Cache hit for weather forecast: {Location}", location);
            return new ToolResponse
            {
                Content = new List<ContentItem>
                {
                    new TextContent(cachedForecast)
                }
            };
        }
        
        // Cache miss - get from service
        _logger.LogInformation("Cache miss for weather forecast: {Location}", location);
        var forecast = await _weatherService.GetForecastAsync(location, days);
        string forecastJson = JsonSerializer.Serialize(forecast);
        
        // Store in cache (weather forecasts valid for 1 hour)
        await _cache.SetStringAsync(
            cacheKey,
            forecastJson,
            new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
            });
        
        return new ToolResponse
        {
            Content = new List<ContentItem>
            {
                new TextContent(forecastJson)
            }
        };
    }
}

2. Uingizaji wa Utegemezi na Uwezekano wa Kupimika

Buni zana kupokea utegemezi wake kupitia uingizaji wa konstrukta, zikifanya ziweze kupimika na kubadilishwa:

// Mfano wa Java na sindano ya utegemezi
public class CurrencyConversionTool implements Tool {
    private final ExchangeRateService exchangeService;
    private final CacheService cacheService;
    private final Logger logger;
    
    // Vitegemezi vilivyowekwa kupitia kimojawapo
    public CurrencyConversionTool(
            ExchangeRateService exchangeService,
            CacheService cacheService,
            Logger logger) {
        this.exchangeService = exchangeService;
        this.cacheService = cacheService;
        this.logger = logger;
    }
    
    // Utekelezaji wa chombo
    // ...
}

3. Zana Zinazoweza Kuunganishwa

Buni zana ambazo zinaweza kuunganishwa pamoja kuunda mitiririko ya kazi tata zaidi:

# Mfano wa Python unaoonyesha zana zinazoweza kuunganishwa
class DataFetchTool(Tool):
    def get_name(self):
        return "dataFetch"
    
    # Utekelezaji...

class DataAnalysisTool(Tool):
    def get_name(self):
        return "dataAnalysis"
    
    # Zana hii inaweza kutumia matokeo kutoka kwa zana ya dataFetch
    async def execute_async(self, request):
        # Utekelezaji...
        pass

class DataVisualizationTool(Tool):
    def get_name(self):
        return "dataVisualize"
    
    # Zana hii inaweza kutumia matokeo kutoka kwa zana ya dataAnalysis
    async def execute_async(self, request):
        # Utekelezaji...
        pass

# Zana hizi zinaweza kutumika kwa kujitegemea au kama sehemu ya mchakato wa kazi

Mazoea Bora ya Ubunifu wa Mpangilio wa Data (Schema)

Mpangilio ni mkataba kati ya modeli na zana yako. Mipangilio iliyobuniwa vizuri hutoa urahisi zaidi wa matumizi ya zana.

1. Maelezo Wazi ya Vigezo

Daima jumuisha taarifa za maelezo kwa kila kigezo:

public object GetSchema()
{
    return new {
        type = "object",
        properties = new {
            query = new { 
                type = "string", 
                description = "Search query text. Use precise keywords for better results." 
            },
            filters = new {
                type = "object",
                description = "Optional filters to narrow down search results",
                properties = new {
                    dateRange = new { 
                        type = "string", 
                        description = "Date range in format YYYY-MM-DD:YYYY-MM-DD" 
                    },
                    category = new { 
                        type = "string", 
                        description = "Category name to filter by" 
                    }
                }
            },
            limit = new { 
                type = "integer", 
                description = "Maximum number of results to return (1-50)",
                default = 10
            }
        },
        required = new[] { "query" }
    };
}

2. Vizuizi vya Uhakiki

Jumuisha vizuizi vya uhakiki ili kuzuia pembejeo zisizofaa:

Map<String, Object> getSchema() {
    Map<String, Object> schema = new HashMap<>();
    schema.put("type", "object");
    
    Map<String, Object> properties = new HashMap<>();
    
    // Mali ya barua pepe yenye uthibitisho wa muundo
    Map<String, Object> email = new HashMap<>();
    email.put("type", "string");
    email.put("format", "email");
    email.put("description", "User email address");
    
    // Mali ya umri yenye vizingiti vya nambari
    Map<String, Object> age = new HashMap<>();
    age.put("type", "integer");
    age.put("minimum", 13);
    age.put("maximum", 120);
    age.put("description", "User age in years");
    
    // Mali ya orodha iliyoorodheshwa
    Map<String, Object> subscription = new HashMap<>();
    subscription.put("type", "string");
    subscription.put("enum", Arrays.asList("free", "basic", "premium"));
    subscription.put("default", "free");
    subscription.put("description", "Subscription tier");
    
    properties.put("email", email);
    properties.put("age", age);
    properties.put("subscription", subscription);
    
    schema.put("properties", properties);
    schema.put("required", Arrays.asList("email"));
    
    return schema;
}

3. Muundo Thabiti wa Majibu

Dumisha muundo thabiti wa majibu yako ili kurahisisha modeli kutafsiri matokeo:

async def execute_async(self, request):
    try:
        # Shughulikia ombi
        results = await self._search_database(request.parameters["query"])
        
        # Daima rudisha muundo thabiti
        return ToolResponse(
            result={
                "matches": [self._format_item(item) for item in results],
                "totalCount": len(results),
                "queryTime": calculation_time_ms,
                "status": "success"
            }
        )
    except Exception as e:
        return ToolResponse(
            result={
                "matches": [],
                "totalCount": 0,
                "queryTime": 0,
                "status": "error",
                "error": str(e)
            }
        )
    
def _format_item(self, item):
    """Ensures each item has a consistent structure"""
    return {
        "id": item.id,
        "title": item.title,
        "summary": item.summary[:100] + "..." if len(item.summary) > 100 else item.summary,
        "url": item.url,
        "relevance": item.score
    }

Usimamizi wa Makosa

Usimamizi imara wa makosa ni muhimu kwa zana za MCP kudumisha kuaminika.

1. Usimamizi wa Makosa kwa Upole

Shughulikia makosa ngazi zinazofaa na toa ujumbe wenye taarifa:

public async Task<ToolResponse> ExecuteAsync(ToolRequest request)
{
    try
    {
        string fileId = request.Parameters.GetProperty("fileId").GetString();
        
        try
        {
            var fileData = await _fileService.GetFileAsync(fileId);
            return new ToolResponse { 
                Result = JsonSerializer.SerializeToElement(fileData) 
            };
        }
        catch (FileNotFoundException)
        {
            throw new ToolExecutionException($"File not found: {fileId}");
        }
        catch (UnauthorizedAccessException)
        {
            throw new ToolExecutionException("You don't have permission to access this file");
        }
        catch (Exception ex) when (ex is IOException || ex is TimeoutException)
        {
            _logger.LogError(ex, "Error accessing file {FileId}", fileId);
            throw new ToolExecutionException("Error accessing file: The service is temporarily unavailable");
        }
    }
    catch (JsonException)
    {
        throw new ToolExecutionException("Invalid file ID format");
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Unexpected error in FileAccessTool");
        throw new ToolExecutionException("An unexpected error occurred");
    }
}

2. Majibu ya Makosa Yaliyoundwa kwa Muundo

Rudisha taarifa za makosa zilizo na muundo pale inapowezekana:

@Override
public ToolResponse execute(ToolRequest request) {
    try {
        // Utekelezaji
    } catch (Exception ex) {
        Map<String, Object> errorResult = new HashMap<>();
        
        errorResult.put("success", false);
        
        if (ex instanceof ValidationException) {
            ValidationException validationEx = (ValidationException) ex;
            
            errorResult.put("errorType", "validation");
            errorResult.put("errorMessage", validationEx.getMessage());
            errorResult.put("validationErrors", validationEx.getErrors());
            
            return new ToolResponse.Builder()
                .setResult(errorResult)
                .build();
        }
        
        // Rudi kosa lingine kama ToolExecutionException
        throw new ToolExecutionException("Tool execution failed: " + ex.getMessage(), ex);
    }
}

3. Mchakato wa Jaribu Tena

Tekeleza mchakato unaofaa wa jaribu tena kwa kushindwa za muda mfupi:

async def execute_async(self, request):
    max_retries = 3
    retry_count = 0
    base_delay = 1  # sekunde
    
    while retry_count < max_retries:
        try:
            # Piga API ya nje
            return await self._call_api(request.parameters)
        except TransientError as e:
            retry_count += 1
            if retry_count >= max_retries:
                raise ToolExecutionException(f"Operation failed after {max_retries} attempts: {str(e)}")
                
            # Kurudi nyuma kwa mwelekeo wa eksponential
            delay = base_delay * (2 ** (retry_count - 1))
            logging.warning(f"Transient error, retrying in {delay}s: {str(e)}")
            await asyncio.sleep(delay)
        except Exception as e:
            # Hitilafu isiyo ya muda, usijaribu tena
            raise ToolExecutionException(f"Operation failed: {str(e)}")

Uboreshaji wa Utendaji

1. Kuhifadhi Nakala

Tekeleza uhifadhi kwa ajili ya operesheni ghali:

public class CachedDataTool : IMcpTool
{
    private readonly IDatabase _database;
    private readonly IMemoryCache _cache;
    
    public CachedDataTool(IDatabase database, IMemoryCache cache)
    {
        _database = database;
        _cache = cache;
    }
    
    public async Task<ToolResponse> ExecuteAsync(ToolRequest request)
    {
        var query = request.Parameters.GetProperty("query").GetString();
        
        // Create cache key based on parameters
        var cacheKey = $"data_query_{ComputeHash(query)}";
        
        // Try to get from cache first
        if (_cache.TryGetValue(cacheKey, out var cachedResult))
        {
            return new ToolResponse { Result = cachedResult };
        }
        
        // Cache miss - perform actual query
        var result = await _database.QueryAsync(query);
        
        // Store in cache with expiration
        var cacheOptions = new MemoryCacheEntryOptions()
            .SetAbsoluteExpiration(TimeSpan.FromMinutes(15));
            
        _cache.Set(cacheKey, JsonSerializer.SerializeToElement(result), cacheOptions);
        
        return new ToolResponse { Result = JsonSerializer.SerializeToElement(result) };
    }
    
    private string ComputeHash(string input)
    {
        // Implementation to generate stable hash for cache key
    }
}

2. Usindikaji Usio na Mfuatano

Tumia mifumo ya programu isiyo na mfuatano kwa operesheni za I/O:

public class AsyncDocumentProcessingTool implements Tool {
    private final DocumentService documentService;
    private final ExecutorService executorService;
    
    @Override
    public ToolResponse execute(ToolRequest request) {
        String documentId = request.getParameters().get("documentId").asText();
        
        // Kwa shughuli zinazochukua muda mrefu, rudisha kitambulisho cha usindikaji mara moja
        String processId = UUID.randomUUID().toString();
        
        // Anzisha usindikaji usioambatishwa
        CompletableFuture.runAsync(() -> {
            try {
                // Fanya shughuli inayochukua muda mrefu
                documentService.processDocument(documentId);
                
                // Sasisha hali (kawaida itahifadhiwa katika hifadhidata)
                processStatusRepository.updateStatus(processId, "completed");
            } catch (Exception ex) {
                processStatusRepository.updateStatus(processId, "failed", ex.getMessage());
            }
        }, executorService);
        
        // Rejesha jibu la papo hapo lenye kitambulisho cha mchakato
        Map<String, Object> result = new HashMap<>();
        result.put("processId", processId);
        result.put("status", "processing");
        result.put("estimatedCompletionTime", ZonedDateTime.now().plusMinutes(5));
        
        return new ToolResponse.Builder().setResult(result).build();
    }
    
    // Zana ya ukaguzi wa hali mwenzake
    public class ProcessStatusTool implements Tool {
        @Override
        public ToolResponse execute(ToolRequest request) {
            String processId = request.getParameters().get("processId").asText();
            ProcessStatus status = processStatusRepository.getStatus(processId);
            
            return new ToolResponse.Builder().setResult(status).build();
        }
    }
}

3. Kuzuia Kupitia Rasilimali

Tekeleza kuzuia kwa kutumia rasilimali ili kuzuia mzigo kupita kiasi:

class ThrottledApiTool(Tool):
    def __init__(self):
        self.rate_limiter = TokenBucketRateLimiter(
            tokens_per_second=5,  # Ruhusu maombi 5 kwa sekunde
            bucket_size=10        # Ruhusu mlipuko hadi maombi 10
        )
    
    async def execute_async(self, request):
        # Angalia ikiwa tunaweza kuendelea au tunahitaji kusubiri
        delay = self.rate_limiter.get_delay_time()
        
        if delay > 0:
            if delay > 2.0:  # Ikiwa kusubiri ni kwa muda mrefu sana
                raise ToolExecutionException(
                    f"Rate limit exceeded. Please try again in {delay:.1f} seconds."
                )
            else:
                # Subiri kwa muda unaofaa wa kuchelewa
                await asyncio.sleep(delay)
        
        # Tumia tokeni moja na endelea na ombi
        self.rate_limiter.consume()
        
        # Piga API
        result = await self._call_api(request.parameters)
        return ToolResponse(result=result)

class TokenBucketRateLimiter:
    def __init__(self, tokens_per_second, bucket_size):
        self.tokens_per_second = tokens_per_second
        self.bucket_size = bucket_size
        self.tokens = bucket_size
        self.last_refill = time.time()
        self.lock = asyncio.Lock()
    
    async def get_delay_time(self):
        async with self.lock:
            self._refill()
            if self.tokens >= 1:
                return 0
            
            # Hesabu muda mpaka tokeni inayofuata itapatikana
            return (1 - self.tokens) / self.tokens_per_second
    
    async def consume(self):
        async with self.lock:
            self._refill()
            self.tokens -= 1
    
    def _refill(self):
        now = time.time()
        elapsed = now - self.last_refill
        
        # Ongeza tokeni mpya kulingana na muda uliopita
        new_tokens = elapsed * self.tokens_per_second
        self.tokens = min(self.bucket_size, self.tokens + new_tokens)
        self.last_refill = now

Mazoea Bora ya Usalama

1. Uhakiki wa Ingizo

Daima hakiki vigezo vya ingizo kwa kina:

public async Task<ToolResponse> ExecuteAsync(ToolRequest request)
{
    // Validate parameters exist
    if (!request.Parameters.TryGetProperty("query", out var queryProp))
    {
        throw new ToolExecutionException("Missing required parameter: query");
    }
    
    // Validate correct type
    if (queryProp.ValueKind != JsonValueKind.String)
    {
        throw new ToolExecutionException("Query parameter must be a string");
    }
    
    var query = queryProp.GetString();
    
    // Validate string content
    if (string.IsNullOrWhiteSpace(query))
    {
        throw new ToolExecutionException("Query parameter cannot be empty");
    }
    
    if (query.Length > 500)
    {
        throw new ToolExecutionException("Query parameter exceeds maximum length of 500 characters");
    }
    
    // Check for SQL injection attacks if applicable
    if (ContainsSqlInjection(query))
    {
        throw new ToolExecutionException("Invalid query: contains potentially unsafe SQL");
    }
    
    // Proceed with execution
    // ...
}

2. Ukaguzi wa Idhini

Tekeleza ukaguzi sahihi wa idhini:

@Override
public ToolResponse execute(ToolRequest request) {
    // Pata muktadha wa mtumiaji kutoka kwa ombi
    UserContext user = request.getContext().getUserContext();
    
    // Angalia kama mtumiaji ana ruhusa zinazohitajika
    if (!authorizationService.hasPermission(user, "documents:read")) {
        throw new ToolExecutionException("User does not have permission to access documents");
    }
    
    // Kwa rasilimali maalum, angalia ufikiaji wa rasilimali hiyo
    String documentId = request.getParameters().get("documentId").asText();
    if (!documentService.canUserAccess(user.getId(), documentId)) {
        throw new ToolExecutionException("Access denied to the requested document");
    }
    
    // Endelea na utekelezaji wa chombo
    // ...
}

3. Usimamizi wa Data Nyeti

Shughulikia data nyeti kwa tahadhari:

class SecureDataTool(Tool):
    def get_schema(self):
        return {
            "type": "object",
            "properties": {
                "userId": {"type": "string"},
                "includeSensitiveData": {"type": "boolean", "default": False}
            },
            "required": ["userId"]
        }
    
    async def execute_async(self, request):
        user_id = request.parameters["userId"]
        include_sensitive = request.parameters.get("includeSensitiveData", False)
        
        # Pata data ya mtumiaji
        user_data = await self.user_service.get_user_data(user_id)
        
        # Chuja sehemu nyeti isipokuwa ziombwe wazi NA ruhusiwa
        if not include_sensitive or not self._is_authorized_for_sensitive_data(request):
            user_data = self._redact_sensitive_fields(user_data)
        
        return ToolResponse(result=user_data)
    
    def _is_authorized_for_sensitive_data(self, request):
        # Angalia kiwango cha idhini katika muktadha wa ombi
        auth_level = request.context.get("authorizationLevel")
        return auth_level == "admin"
    
    def _redact_sensitive_fields(self, user_data):
        # Tengeneza nakala ili kuepuka kubadilisha asili
        redacted = user_data.copy()
        
        # Ficha sehemu maalum nyeti
        sensitive_fields = ["ssn", "creditCardNumber", "password"]
        for field in sensitive_fields:
            if field in redacted:
                redacted[field] = "REDACTED"
        
        # Ficha data nyeti zilizoko ndani
        if "financialInfo" in redacted:
            redacted["financialInfo"] = {"available": True, "accessRestricted": True}
        
        return redacted

Mazoea Bora ya Upimaji kwa Zana za MCP

Upimaji kamili huhakikisha zana za MCP zinafanya kazi kwa usahihi, kushughulikia matukio ya pembezoni, na kuunganishwa vyema na mfumo mzima.

Upimaji wa Kiwango Kidogo

1. Jaribu Kila Zana Peke Yake

Unda majaribio maalum kwa kazi ya kila zana:

[Fact]
public async Task WeatherTool_ValidLocation_ReturnsCorrectForecast()
{
    // Arrange
    var mockWeatherService = new Mock<IWeatherService>();
    mockWeatherService
        .Setup(s => s.GetForecastAsync("Seattle", 3))
        .ReturnsAsync(new WeatherForecast(/* test data */));
    
    var tool = new WeatherForecastTool(mockWeatherService.Object);
    
    var request = new ToolRequest(
        toolName: "weatherForecast",
        parameters: JsonSerializer.SerializeToElement(new { 
            location = "Seattle", 
            days = 3 
        })
    );
    
    // Act
    var response = await tool.ExecuteAsync(request);
    
    // Assert
    Assert.NotNull(response);
    var result = JsonSerializer.Deserialize<WeatherForecast>(response.Result);
    Assert.Equal("Seattle", result.Location);
    Assert.Equal(3, result.DailyForecasts.Count);
}

[Fact]
public async Task WeatherTool_InvalidLocation_ThrowsToolExecutionException()
{
    // Arrange
    var mockWeatherService = new Mock<IWeatherService>();
    mockWeatherService
        .Setup(s => s.GetForecastAsync("InvalidLocation", It.IsAny<int>()))
        .ThrowsAsync(new LocationNotFoundException("Location not found"));
    
    var tool = new WeatherForecastTool(mockWeatherService.Object);
    
    var request = new ToolRequest(
        toolName: "weatherForecast",
        parameters: JsonSerializer.SerializeToElement(new { 
            location = "InvalidLocation", 
            days = 3 
        })
    );
    
    // Act & Assert
    var exception = await Assert.ThrowsAsync<ToolExecutionException>(
        () => tool.ExecuteAsync(request)
    );
    
    Assert.Contains("Location not found", exception.Message);
}

2. Upimaji wa Uhakiki wa Mpangilio

Jaribu kwamba mipangilio ni halali na inatekeleza vizuizi ipasavyo:

@Test
public void testSchemaValidation() {
    // Tengeneza mfano wa chombo
    SearchTool searchTool = new SearchTool();
    
    // Pata skimu
    Object schema = searchTool.getSchema();
    
    // Badilisha skimu kuwa JSON kwa ajili ya uthibitishaji
    String schemaJson = objectMapper.writeValueAsString(schema);
    
    // Thibitisha skimu ni JSONSchema halali
    JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
    JsonSchema jsonSchema = factory.getJsonSchema(schemaJson);
    
    // Jaribu vigezo halali
    JsonNode validParams = objectMapper.createObjectNode()
        .put("query", "test query")
        .put("limit", 5);
        
    ProcessingReport validReport = jsonSchema.validate(validParams);
    assertTrue(validReport.isSuccess());
    
    // Jaribu kigezo kilichokosekana kinachohitajika
    JsonNode missingRequired = objectMapper.createObjectNode()
        .put("limit", 5);
        
    ProcessingReport missingReport = jsonSchema.validate(missingRequired);
    assertFalse(missingReport.isSuccess());
    
    // Jaribu aina ya kigezo isiyo halali
    JsonNode invalidType = objectMapper.createObjectNode()
        .put("query", "test")
        .put("limit", "not-a-number");
        
    ProcessingReport invalidReport = jsonSchema.validate(invalidType);
    assertFalse(invalidReport.isSuccess());
}

3. Majaribio ya Usimamizi wa Makosa

Tengeneza majaribio maalum ya hali za makosa:

@pytest.mark.asyncio
async def test_api_tool_handles_timeout():
    # Panga
    tool = ApiTool(timeout=0.1)  # Muda mfupi sana wa kusubiri
    
    # Fanya mfano wa ombi litakaloisha muda
    with aioresponses() as mocked:
        mocked.get(
            "https://api.example.com/data",
            callback=lambda *args, **kwargs: asyncio.sleep(0.5)  # Ndefu zaidi ya muda wa kusubiri
        )
        
        request = ToolRequest(
            tool_name="apiTool",
            parameters={"url": "https://api.example.com/data"}
        )
        
        # Tenda & Thibitisha
        with pytest.raises(ToolExecutionException) as exc_info:
            await tool.execute_async(request)
        
        # Hakiki ujumbe wa makosa
        assert "timed out" in str(exc_info.value).lower()

@pytest.mark.asyncio
async def test_api_tool_handles_rate_limiting():
    # Panga
    tool = ApiTool()
    
    # Fanya mfano wa jibu lililozuiliwa kwa kiwango cha kiwango
    with aioresponses() as mocked:
        mocked.get(
            "https://api.example.com/data",
            status=429,
            headers={"Retry-After": "2"},
            body=json.dumps({"error": "Rate limit exceeded"})
        )
        
        request = ToolRequest(
            tool_name="apiTool",
            parameters={"url": "https://api.example.com/data"}
        )
        
        # Tenda & Thibitisha
        with pytest.raises(ToolExecutionException) as exc_info:
            await tool.execute_async(request)
        
        # Hakiki makosa yanayoonyesha taarifa za kiwango cha kiwango
        error_msg = str(exc_info.value).lower()
        assert "rate limit" in error_msg
        assert "try again" in error_msg

Upimaji wa Uunganishaji

1. Upimaji wa Mnyororo wa Zana

Jaribu zana zikifanya kazi pamoja katika mchanganyiko unaotarajiwa:

[Fact]
public async Task DataProcessingWorkflow_CompletesSuccessfully()
{
    // Arrange
    var dataFetchTool = new DataFetchTool(mockDataService.Object);
    var analysisTools = new DataAnalysisTool(mockAnalysisService.Object);
    var visualizationTool = new DataVisualizationTool(mockVisualizationService.Object);
    
    var toolRegistry = new ToolRegistry();
    toolRegistry.RegisterTool(dataFetchTool);
    toolRegistry.RegisterTool(analysisTools);
    toolRegistry.RegisterTool(visualizationTool);
    
    var workflowExecutor = new WorkflowExecutor(toolRegistry);
    
    // Act
    var result = await workflowExecutor.ExecuteWorkflowAsync(new[] {
        new ToolCall("dataFetch", new { source = "sales2023" }),
        new ToolCall("dataAnalysis", ctx => new { 
            data = ctx.GetResult("dataFetch"),
            analysis = "trend" 
        }),
        new ToolCall("dataVisualize", ctx => new {
            analysisResult = ctx.GetResult("dataAnalysis"),
            type = "line-chart"
        })
    });
    
    // Assert
    Assert.NotNull(result);
    Assert.True(result.Success);
    Assert.NotNull(result.GetResult("dataVisualize"));
    Assert.Contains("chartUrl", result.GetResult("dataVisualize").ToString());
}

2. Upimaji wa Seva za MCP

Jaribu seva ya MCP kwa usajili na utekelezaji kamili wa zana:

@SpringBootTest
@AutoConfigureMockMvc
public class McpServerIntegrationTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Test
    public void testToolDiscovery() throws Exception {
        // Jaribu kiunganishi cha ugunduzi
        mockMvc.perform(get("/mcp/tools"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.tools").isArray())
            .andExpect(jsonPath("$.tools[*].name").value(hasItems(
                "weatherForecast", "calculator", "documentSearch"
            )));
    }
    
    @Test
    public void testToolExecution() throws Exception {
        // Tengeneza ombi la chombo
        Map<String, Object> request = new HashMap<>();
        request.put("toolName", "calculator");
        
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("operation", "add");
        parameters.put("a", 5);
        parameters.put("b", 7);
        request.put("parameters", parameters);
        
        // Tuma ombi na hakiki jibu
        mockMvc.perform(post("/mcp/execute")
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(request)))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.result.value").value(12));
    }
    
    @Test
    public void testToolValidation() throws Exception {
        // Tengeneza ombi batili la chombo
        Map<String, Object> request = new HashMap<>();
        request.put("toolName", "calculator");
        
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("operation", "divide");
        parameters.put("a", 10);
        // Kipengele kinachokosekana "b"
        request.put("parameters", parameters);
        
        // Tuma ombi na hakiki jibu la kosa
        mockMvc.perform(post("/mcp/execute")
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(request)))
            .andExpect(status().isBadRequest())
            .andExpect(jsonPath("$.error").exists());
    }
}

3. Upimaji wa Mwisho-mwisho

Jaribu mitiririko kamili kutoka kiamsha cha modeli hadi utekelezaji wa zana:

@pytest.mark.asyncio
async def test_model_interaction_with_tool():
    # Panga - Tengeneza mteja wa MCP na mfano wa kuigiza
    mcp_client = McpClient(server_url="http://localhost:5000")
    
    # Jibu la mfano wa kuigiza
    mock_model = MockLanguageModel([
        MockResponse(
            "What's the weather in Seattle?",
            tool_calls=[{
                "tool_name": "weatherForecast",
                "parameters": {"location": "Seattle", "days": 3}
            }]
        ),
        MockResponse(
            "Here's the weather forecast for Seattle:\n- Today: 65°F, Partly Cloudy\n- Tomorrow: 68°F, Sunny\n- Day after: 62°F, Rain",
            tool_calls=[]
        )
    ])
    
    # Jibu la chombo cha hali ya hewa cha kuigiza
    with aioresponses() as mocked:
        mocked.post(
            "http://localhost:5000/mcp/execute",
            payload={
                "result": {
                    "location": "Seattle",
                    "forecast": [
                        {"date": "2023-06-01", "temperature": 65, "conditions": "Partly Cloudy"},
                        {"date": "2023-06-02", "temperature": 68, "conditions": "Sunny"},
                        {"date": "2023-06-03", "temperature": 62, "conditions": "Rain"}
                    ]
                }
            }
        )
        
        # Fanya
        response = await mcp_client.send_prompt(
            "What's the weather in Seattle?",
            model=mock_model,
            allowed_tools=["weatherForecast"]
        )
        
        # Thibitisha
        assert "Seattle" in response.generated_text
        assert "65" in response.generated_text
        assert "Sunny" in response.generated_text
        assert "Rain" in response.generated_text
        assert len(response.tool_calls) == 1
        assert response.tool_calls[0].tool_name == "weatherForecast"

Upimaji wa Utendaji

1. Upimaji wa Mzigo

Jaribu ni maombi mangapi sawa seva yako ya MCP inaweza kushughulikia:

[Fact]
public async Task McpServer_HandlesHighConcurrency()
{
    // Arrange
    var server = new McpServer(
        name: "TestServer",
        version: "1.0",
        maxConcurrentRequests: 100
    );
    
    server.RegisterTool(new FastExecutingTool());
    await server.StartAsync();
    
    var client = new McpClient("http://localhost:5000");
    
    // Act
    var tasks = new List<Task<McpResponse>>();
    for (int i = 0; i < 1000; i++)
    {
        tasks.Add(client.ExecuteToolAsync("fastTool", new { iteration = i }));
    }
    
    var results = await Task.WhenAll(tasks);
    
    // Assert
    Assert.Equal(1000, results.Length);
    Assert.All(results, r => Assert.NotNull(r));
}

2. Upimaji wa Msongo wa Mawazo

Jaribu mfumo chini ya mzigo wa hali ya juu sana:

@Test
public void testServerUnderStress() {
    int maxUsers = 1000;
    int rampUpTimeSeconds = 60;
    int testDurationSeconds = 300;
    
    // Tengeneza JMeter kwa jaribio la msongo
    StandardJMeterEngine jmeter = new StandardJMeterEngine();
    
    // Sanidi mpango wa jaribio la JMeter
    HashTree testPlanTree = new HashTree();
    
    // Unda mpango wa jaribio, kikundi cha nyuzi, sampuli, n.k.
    TestPlan testPlan = new TestPlan("MCP Server Stress Test");
    testPlanTree.add(testPlan);
    
    ThreadGroup threadGroup = new ThreadGroup();
    threadGroup.setNumThreads(maxUsers);
    threadGroup.setRampUp(rampUpTimeSeconds);
    threadGroup.setScheduler(true);
    threadGroup.setDuration(testDurationSeconds);
    
    testPlanTree.add(threadGroup);
    
    // Ongeza sampuli ya HTTP kwa ajili ya utekelezaji wa zana
    HTTPSampler toolExecutionSampler = new HTTPSampler();
    toolExecutionSampler.setDomain("localhost");
    toolExecutionSampler.setPort(5000);
    toolExecutionSampler.setPath("/mcp/execute");
    toolExecutionSampler.setMethod("POST");
    toolExecutionSampler.addArgument("toolName", "calculator");
    toolExecutionSampler.addArgument("parameters", "{\"operation\":\"add\",\"a\":5,\"b\":7}");
    
    threadGroup.add(toolExecutionSampler);
    
    // Ongeza wasikilizaji
    SummaryReport summaryReport = new SummaryReport();
    threadGroup.add(summaryReport);
    
    // Endesha jaribio
    jmeter.configure(testPlanTree);
    jmeter.run();
    
    // Hakiki matokeo
    assertEquals(0, summaryReport.getErrorCount());
    assertTrue(summaryReport.getAverage() < 200); // Wakati wa majibu wastani < 200ms
    assertTrue(summaryReport.getPercentile(90.0) < 500); // Asilimia ya 90 < 500ms
}

3. Ufuatiliaji na Uchanganuzi wa Utendaji

Weka ufuatiliaji kwa ajili ya uchambuzi wa utendaji wa muda mrefu:

# Sanidi ufuatiliaji kwa seva ya MCP
def configure_monitoring(server):
    # Weka vipimo vya Prometheus
    prometheus_metrics = {
        "request_count": Counter("mcp_requests_total", "Total MCP requests"),
        "request_latency": Histogram(
            "mcp_request_duration_seconds", 
            "Request duration in seconds",
            buckets=[0.01, 0.05, 0.1, 0.5, 1.0, 2.5, 5.0, 10.0]
        ),
        "tool_execution_count": Counter(
            "mcp_tool_executions_total", 
            "Tool execution count",
            labelnames=["tool_name"]
        ),
        "tool_execution_latency": Histogram(
            "mcp_tool_duration_seconds", 
            "Tool execution duration in seconds",
            labelnames=["tool_name"],
            buckets=[0.01, 0.05, 0.1, 0.5, 1.0, 2.5, 5.0, 10.0]
        ),
        "tool_errors": Counter(
            "mcp_tool_errors_total",
            "Tool execution errors",
            labelnames=["tool_name", "error_type"]
        )
    }
    
    # Ongeza tabaka kati kwa upimaji na kurekodi vipimo
    server.add_middleware(PrometheusMiddleware(prometheus_metrics))
    
    # Fungua sehemu ya vipimo
    @server.router.get("/metrics")
    async def metrics():
        return generate_latest()
    
    return server

Mifumo ya Ubunifu wa Mtiririko wa Kazi wa MCP

Mitiririko ya kazi ya MCP imetengenezwa vizuri huongeza ufanisi, kuaminika, na urahisi wa matengenezo. Hapa kuna mifumo muhimu ya kufuata:

1. Mfumo wa Mnyororo wa Zana

Unganisha zana nyingi mfululizo ambapo pato la kila zana linakuwa pembejeo kwa inayofuata:

# Utekelezaji wa Mnyororo wa Zana za Python
class ChainWorkflow:
    def __init__(self, tools_chain):
        self.tools_chain = tools_chain  # Orodha ya majina ya zana za kutekeleza kwa mfululizo
    
    async def execute(self, mcp_client, initial_input):
        current_result = initial_input
        all_results = {"input": initial_input}
        
        for tool_name in self.tools_chain:
            # Tekeleza kila zana katika mnyororo, ukipitisha matokeo ya awali
            response = await mcp_client.execute_tool(tool_name, current_result)
            
            # Hifadhi matokeo na utumie kama pembejeo kwa zana inayofuata
            all_results[tool_name] = response.result
            current_result = response.result
        
        return {
            "final_result": current_result,
            "all_results": all_results
        }

# Mfano wa matumizi
data_processing_chain = ChainWorkflow([
    "dataFetch",
    "dataCleaner",
    "dataAnalyzer",
    "dataVisualizer"
])

result = await data_processing_chain.execute(
    mcp_client,
    {"source": "sales_database", "table": "transactions"}
)

2. Mfumo wa Mtoaji Amri

Tumia zana kuu inayosambaza kwenda kwa zana maalum kulingana na pembejeo:

public class ContentDispatcherTool : IMcpTool
{
    private readonly IMcpClient _mcpClient;
    
    public ContentDispatcherTool(IMcpClient mcpClient)
    {
        _mcpClient = mcpClient;
    }
    
    public string Name => "contentProcessor";
    public string Description => "Processes content of various types";
    
    public object GetSchema()
    {
        return new {
            type = "object",
            properties = new {
                content = new { type = "string" },
                contentType = new { 
                    type = "string",
                    enum = new[] { "text", "html", "markdown", "csv", "code" }
                },
                operation = new { 
                    type = "string",
                    enum = new[] { "summarize", "analyze", "extract", "convert" }
                }
            },
            required = new[] { "content", "contentType", "operation" }
        };
    }
    
    public async Task<ToolResponse> ExecuteAsync(ToolRequest request)
    {
        var content = request.Parameters.GetProperty("content").GetString();
        var contentType = request.Parameters.GetProperty("contentType").GetString();
        var operation = request.Parameters.GetProperty("operation").GetString();
        
        // Determine which specialized tool to use
        string targetTool = DetermineTargetTool(contentType, operation);
        
        // Forward to the specialized tool
        var specializedResponse = await _mcpClient.ExecuteToolAsync(
            targetTool,
            new { content, options = GetOptionsForTool(targetTool, operation) }
        );
        
        return new ToolResponse { Result = specializedResponse.Result };
    }
    
    private string DetermineTargetTool(string contentType, string operation)
    {
        return (contentType, operation) switch
        {
            ("text", "summarize") => "textSummarizer",
            ("text", "analyze") => "textAnalyzer",
            ("html", _) => "htmlProcessor",
            ("markdown", _) => "markdownProcessor",
            ("csv", _) => "csvProcessor",
            ("code", _) => "codeAnalyzer",
            _ => throw new ToolExecutionException($"No tool available for {contentType}/{operation}")
        };
    }
    
    private object GetOptionsForTool(string toolName, string operation)
    {
        // Return appropriate options for each specialized tool
        return toolName switch
        {
            "textSummarizer" => new { length = "medium" },
            "htmlProcessor" => new { cleanUp = true, operation },
            // Options for other tools...
            _ => new { }
        };
    }
}

3. Mfumo wa Usindikaji Sambamba

Tekeleza zana nyingi kwa wakati mmoja kwa ufanisi:

public class ParallelDataProcessingWorkflow {
    private final McpClient mcpClient;
    
    public ParallelDataProcessingWorkflow(McpClient mcpClient) {
        this.mcpClient = mcpClient;
    }
    
    public WorkflowResult execute(String datasetId) {
        // Hatua 1: Pata metadata ya dataseti (kwa mstari)
        ToolResponse metadataResponse = mcpClient.executeTool("datasetMetadata", 
            Map.of("datasetId", datasetId));
        
        // Hatua 2: Anzisha uchambuzi mwingi kwa wakati mmoja
        CompletableFuture<ToolResponse> statisticalAnalysis = CompletableFuture.supplyAsync(() ->
            mcpClient.executeTool("statisticalAnalysis", Map.of(
                "datasetId", datasetId,
                "type", "comprehensive"
            ))
        );
        
        CompletableFuture<ToolResponse> correlationAnalysis = CompletableFuture.supplyAsync(() ->
            mcpClient.executeTool("correlationAnalysis", Map.of(
                "datasetId", datasetId,
                "method", "pearson"
            ))
        );
        
        CompletableFuture<ToolResponse> outlierDetection = CompletableFuture.supplyAsync(() ->
            mcpClient.executeTool("outlierDetection", Map.of(
                "datasetId", datasetId,
                "sensitivity", "medium"
            ))
        );
        
        // Subiri kazi zote zinazofanywa kwa pamoja kukamilika
        CompletableFuture<Void> allAnalyses = CompletableFuture.allOf(
            statisticalAnalysis, correlationAnalysis, outlierDetection
        );
        
        allAnalyses.join();  // Subiri kumalizika
        
        // Hatua 3: Changanya matokeo
        Map<String, Object> combinedResults = new HashMap<>();
        combinedResults.put("metadata", metadataResponse.getResult());
        combinedResults.put("statistics", statisticalAnalysis.join().getResult());
        combinedResults.put("correlations", correlationAnalysis.join().getResult());
        combinedResults.put("outliers", outlierDetection.join().getResult());
        
        // Hatua 4: Tengeneza ripoti ya muhtasari
        ToolResponse summaryResponse = mcpClient.executeTool("reportGenerator", 
            Map.of("analysisResults", combinedResults));
        
        // Rudisha matokeo ya mchakato kamili
        WorkflowResult result = new WorkflowResult();
        result.setDatasetId(datasetId);
        result.setAnalysisResults(combinedResults);
        result.setSummaryReport(summaryResponse.getResult());
        
        return result;
    }
}

4. Mfumo wa Kupona Makosa

Tekeleza mbinu za kupunguzia kwa upole kushindwa kwa zana:

class ResilientWorkflow:
    def __init__(self, mcp_client):
        self.client = mcp_client
    
    async def execute_with_fallback(self, primary_tool, fallback_tool, parameters):
        try:
            # Jaribu chombo cha msingi kwanza
            response = await self.client.execute_tool(primary_tool, parameters)
            return {
                "result": response.result,
                "source": "primary",
                "tool": primary_tool
            }
        except ToolExecutionException as e:
            # Rekodi kushindwa
            logging.warning(f"Primary tool '{primary_tool}' failed: {str(e)}")
            
            # Rudia tena kwa chombo cha sekondari
            try:
                # Inaweza kuhitaji kubadilisha vigezo kwa chombo cha akiba
                fallback_params = self._adapt_parameters(parameters, primary_tool, fallback_tool)
                
                response = await self.client.execute_tool(fallback_tool, fallback_params)
                return {
                    "result": response.result,
                    "source": "fallback",
                    "tool": fallback_tool,
                    "primaryError": str(e)
                }
            except ToolExecutionException as fallback_error:
                # Vyombo vyote vilianguka
                logging.error(f"Both primary and fallback tools failed. Fallback error: {str(fallback_error)}")
                raise WorkflowExecutionException(
                    f"Workflow failed: primary error: {str(e)}; fallback error: {str(fallback_error)}"
                )
    
    def _adapt_parameters(self, params, from_tool, to_tool):
        """Adapt parameters between different tools if needed"""
        # Utekelezaji huu utategemea vyombo maalum
        # Kwa mfano huu, tutarudisha tu vigezo vya awali
        return params

# Matumizi ya mfano
async def get_weather(workflow, location):
    return await workflow.execute_with_fallback(
        "premiumWeatherService",  # API ya hali ya hewa ya msingi (ililipwa)
        "basicWeatherService",    # API ya hali ya hewa ya akiba (bure)
        {"location": location}
    )

5. Mfumo wa Muundo wa Mtiririko wa Kazi

Jenga mitiririko tata kwa kuunganisha mitiririko rahisi:

public class CompositeWorkflow : IWorkflow
{
    private readonly List<IWorkflow> _workflows;
    
    public CompositeWorkflow(IEnumerable<IWorkflow> workflows)
    {
        _workflows = new List<IWorkflow>(workflows);
    }
    
    public async Task<WorkflowResult> ExecuteAsync(WorkflowContext context)
    {
        var results = new Dictionary<string, object>();
        
        foreach (var workflow in _workflows)
        {
            var workflowResult = await workflow.ExecuteAsync(context);
            
            // Store each workflow's result
            results[workflow.Name] = workflowResult;
            
            // Update context with the result for the next workflow
            context = context.WithResult(workflow.Name, workflowResult);
        }
        
        return new WorkflowResult(results);
    }
    
    public string Name => "CompositeWorkflow";
    public string Description => "Executes multiple workflows in sequence";
}

// Example usage
var documentWorkflow = new CompositeWorkflow(new IWorkflow[] {
    new DocumentFetchWorkflow(),
    new DocumentProcessingWorkflow(),
    new InsightGenerationWorkflow(),
    new ReportGenerationWorkflow()
});

var result = await documentWorkflow.ExecuteAsync(new WorkflowContext {
    Parameters = new { documentId = "12345" }
});

Upimaji wa Seva za MCP: Mazoea Bora na Vidokezo Vya Juu

Muhtasari

Upimaji ni kipengele muhimu katika kuendeleza seva za MCP zenye kuaminika na ubora wa hali ya juu. Mwongozo huu unatoa mazoea bora na vidokezo vya upimaji seva zako za MCP katika mzunguko wote wa maendeleo, kutoka majaribio ya msingi hadi majaribio ya uunganishaji na uthibitishaji wa mwisho-mwisho.

Kwa Nini Upimaji ni Muhimu kwa Seva za MCP

Seva za MCP hutumikia kama programu za kati muhimu kati ya modeli za AI na programu za wateja. Upimaji kamili huhakikisha:

  • Kuaminika katika mazingira ya uzalishaji
  • Kushughulikia kwa usahihi maombi na majibu
  • Utekelezaji sahihi wa vipimo vya MCP
  • Ustahimilivu dhidi ya kushindwa na matukio ya pembezoni
  • Utendaji thabiti chini ya mizunguko mbalimbali ya mzigo

Upimaji wa Kiwango Kidogo kwa Seva za MCP

Upimaji wa Kiwango Kidogo (Msingi)

Majaribio ya kiwango kidogo yanathibitisha vipengele binafsi vya seva yako ya MCP kwa kujitenga.

Kitu cha Kupima

  1. Watendaji wa Rasilimali: Jaribu mantiki ya kila mtendaji wa rasilimali kwa kujitegemea
  2. Utekelezaji wa Zana: Hakiki tabia ya zana kwa pembejeo mbalimbali
  3. Mitindo ya Kiamsha: Hakikisha mitindo ya viamsha inatolewa vizuri
  4. Uhakiki wa Mpangilio: Jaribu mantiki ya uhakiki wa vigezo
  5. Usimamizi wa Makosa: Hakiki majibu ya makosa kwa pembejeo batili

Mazoea Bora kwa Upimaji wa Kiwango Kidogo

// Example unit test for a calculator tool in C#
[Fact]
public async Task CalculatorTool_Add_ReturnsCorrectSum()
{
    // Arrange
    var calculator = new CalculatorTool();
    var parameters = new Dictionary<string, object>
    {
        ["operation"] = "add",
        ["a"] = 5,
        ["b"] = 7
    };
    
    // Act
    var response = await calculator.ExecuteAsync(parameters);
    var result = JsonSerializer.Deserialize<CalculationResult>(response.Content[0].ToString());
    
    // Assert
    Assert.Equal(12, result.Value);
}
# Mfano wa jaribio la kitengo kwa chombo cha kalkuleta katika Python
def test_calculator_tool_add():
    # Panga
    calculator = CalculatorTool()
    parameters = {
        "operation": "add",
        "a": 5,
        "b": 7
    }
    
    # Fanya
    response = calculator.execute(parameters)
    result = json.loads(response.content[0].text)
    
    # Thibitisha
    assert result["value"] == 12

Upimaji wa Uunganishaji (Kiungo cha Kati)

Majaribio ya uunganishaji yanathibitisha mwingiliano kati ya vipengele vya seva yako ya MCP.

Kitu cha Kupima

  1. Kuanza Seva: Jaribu huduma ya seva na usanidi tofauti
  2. Usajili wa Njia: Hakiki kwamba vituo vyote vinaandikishwa ipasavyo
  3. Usindikaji wa Maombi: Jaribu mzunguko kamili wa maombi-majibu
  4. Uenezaji wa Makosa: Hakikisha makosa yanashughulikiwa ipasavyo kati ya vipengele
  5. Utambulisho na Idhini: Jaribu mifumo ya usalama

Mazoea Bora kwa Upimaji wa Uunganishaji

// Example integration test for MCP server in C#
[Fact]
public async Task Server_ProcessToolRequest_ReturnsValidResponse()
{
    // Arrange
    var server = new McpServer();
    server.RegisterTool(new CalculatorTool());
    await server.StartAsync();
    
    var request = new McpRequest
    {
        Tool = "calculator",
        Parameters = new Dictionary<string, object>
        {
            ["operation"] = "multiply",
            ["a"] = 6,
            ["b"] = 7
        }
    };
    
    // Act
    var response = await server.ProcessRequestAsync(request);
    
    // Assert
    Assert.NotNull(response);
    Assert.Equal(McpStatusCodes.Success, response.StatusCode);
    // Additional assertions for response content
    
    // Cleanup
    await server.StopAsync();
}

Upimaji wa Mwisho-mwisho (Ngazi ya Juu)

Majaribio ya mwisho-mwisho yanathibitisha tabia kamili ya mfumo kutoka kwa mteja hadi seva.

Kitu cha Kupima

  1. Mawasiliano ya Mteja-Seva: Jaribu mizunguko kamili ya maombi-majibu
  2. SDK za Mteja Halisi: Jaribu kwa utekelezaji halisi wa wateja
  3. Utendaji Chini ya Mzigo: Hakiki tabia kwa maombi mengi sambamba
  4. Kupona Makosa: Jaribu kupona kwa mfumo kutoka kwa kushindwa
  5. Shughuli Zenye Mzunguko Mrefu: Hakiki usimamizi wa mtiririko na shughuli ndefu

Mazoea Bora kwa Upimaji wa Mwisho-mwisho

// Mfano wa jaribio la E2E na mteja katika TypeScript
describe('MCP Server E2E Tests', () => {
  let client: McpClient;
  
  beforeAll(async () => {
    // Anzisha seva katika mazingira ya mtihani
    await startTestServer();
    client = new McpClient('http://localhost:5000');
  });
  
  afterAll(async () => {
    await stopTestServer();
  });
  
  test('Client can invoke calculator tool and get correct result', async () => {
    // Tenda
    const response = await client.invokeToolAsync('calculator', {
      operation: 'divide',
      a: 20,
      b: 4
    });
    
    // Thibitisha
    expect(response.statusCode).toBe(200);
    expect(response.content[0].text).toContain('5');
  });
});

Mikakati ya Kuiga Kupima MCP

Kuiga ni muhimu ili kutenganisha vipengele wakati wa upimaji.

Vipengele vya Kuiga

  1. Mifano ya AI ya Nje: Kuiga majibu ya modeli kwa upimaji wa utabiri
  2. Huduma za Nje: Kuiga utegemezi wa API (hifadhidata, huduma za tatu)
  3. Huduma za Utambulisho: Kuiga watoaji wa utambulisho
  4. Watoa Rasilimali: Kuiga watendaji wa rasilimali ghali

Mfano: Kuiga Jibu la Modeli ya AI

// C# example with Moq
var mockModel = new Mock<ILanguageModel>();
mockModel
    .Setup(m => m.GenerateResponseAsync(
        It.IsAny<string>(),
        It.IsAny<McpRequestContext>()))
    .ReturnsAsync(new ModelResponse { 
        Text = "Mocked model response",
        FinishReason = FinishReason.Completed
    });

var server = new McpServer(modelClient: mockModel.Object);
# Mfano wa Python na unittest.mock
@patch('mcp_server.models.OpenAIModel')
def test_with_mock_model(mock_model):
    # Sanidi mock
    mock_model.return_value.generate_response.return_value = {
        "text": "Mocked model response",
        "finish_reason": "completed"
    }
    
    # Tumia mock katika jaribio
    server = McpServer(model_client=mock_model)
    # Endelea na jaribio

Upimaji wa Utendaji

Upimaji wa utendaji ni muhimu kwa seva za MCP za uzalishaji.

Kitu cha Kupima

  1. Ucheleweshaji: Muda wa majibu kwa maombi
  2. Uwezo wa Kushughulikia Maombi: Idadi ya maombi yanayoshughulikiwa kwa sekunde
  3. Matumizi ya Rasilimali: Matumizi ya CPU, kumbukumbu, mtandao
  4. Usimamizi wa Mizunguko Sambamba: Tabia chini ya maombi ya sambamba
  5. Sifa za Kupanua: Utendaji unavyobadilika kwa kuongezeka kwa mzigo

Zana za Upimaji wa Utendaji

  • k6: Zana ya upimaji mzigo ya chanzo huria
  • JMeter: Upimaji wa utendaji kamili
  • Locust: Upimaji mzigo unaotumia Python
  • Azure Load Testing: Upimaji wa utendaji wa wingu

Mfano: Jaribio la Mzigo wa Msingi kwa k6

// skripti ya k6 kwa upimaji mzigo wa seva ya MCP
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 10,  // watumiaji wa mtandao 10
  duration: '30s',
};

export default function () {
  const payload = JSON.stringify({
    tool: 'calculator',
    parameters: {
      operation: 'add',
      a: Math.floor(Math.random() * 100),
      b: Math.floor(Math.random() * 100)
    }
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer test-token'
    },
  };

  const res = http.post('http://localhost:5000/api/tools/invoke', payload, params);
  
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
  });
  
  sleep(1);
}

Uendeshaji wa Jaribio kwa Seva za MCP

Kuendesha majaribio yako kwa njia ya kiotomatiki huhakikisha ubora thabiti na mizunguko ya majibu ya haraka.

Uunganisho wa CI/CD

  1. Endesha Vipimo vya Unit kwenye Maombi ya Kuvuta: Hakikisha mabadiliko ya msimbo hayatavunja utendakazi uliopo
  2. Vipimo vya Muunganisho katika Mazingira ya Kujaribu: Endesha vipimo vya muunganisho katika mazingira ya kabla ya uzalishaji
  3. Misingi ya Utendaji: Dumisha viwango vya utendaji ili kugundua nyuma
  4. Skani za Usalama: Tengeneza mtihani wa usalama kama sehemu ya mchakato

Mfano wa Mchakato wa CI (GitHub Actions)

name: MCP Server Tests

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v2
    
    - name: Set up Runtime
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: '8.0.x'
    
    - name: Restore dependencies
      run: dotnet restore
    
    - name: Build
      run: dotnet build --no-restore
    
    - name: Unit Tests
      run: dotnet test --no-build --filter Category=Unit
    
    - name: Integration Tests
      run: dotnet test --no-build --filter Category=Integration
      
    - name: Performance Tests
      run: dotnet run --project tests/PerformanceTests/PerformanceTests.csproj

Kupima Uzingatiaji wa Maelezo ya MCP

Thibitisha server yako inatekeleza maelezo ya MCP kwa usahihi.

Sehemu Muhimu za Uzingatiaji

  1. Vituo vya API: Jaribu vituo vinavyohitajika (/resources, /tools, n.k.)
  2. Muundo wa Maombi/Jawabu: Thibitisha ufuataji wa skema
  3. Nambari za Makosa: Hakikisha nambari sahihi za hali kwa matukio mbalimbali
  4. Aina za Yaliyomo: Jaribu kushughulikia aina tofauti za yaliyomo
  5. Mtiririko wa Uthibitishaji: Thibitisha michakato ya uthibitishaji inayolingana na maelezo

Mkusanyiko wa Vipimo vya Uzingatiaji

[Fact]
public async Task Server_ResourceEndpoint_ReturnsCorrectSchema()
{
    // Arrange
    var client = new HttpClient();
    client.DefaultRequestHeaders.Add("Authorization", "Bearer test-token");
    
    // Act
    var response = await client.GetAsync("http://localhost:5000/api/resources");
    var content = await response.Content.ReadAsStringAsync();
    var resources = JsonSerializer.Deserialize<ResourceList>(content);
    
    // Assert
    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    Assert.NotNull(resources);
    Assert.All(resources.Resources, resource => 
    {
        Assert.NotNull(resource.Id);
        Assert.NotNull(resource.Type);
        // Additional schema validation
    });
}

Vidokezo 10 Vikuu vya Vipimo Bora vya Server ya MCP

  1. Jaribu Maelezo ya Zana Kando: Thibitisha maelezo ya skema peke yake mbali na mantiki ya zana
  2. Tumia Vipimo Vilivyopangwa: Jaribu zana kwa aina mbalimbali za ingizo, ikijumuisha hali za kipekee
  3. Angalia Majibu ya Makosa: Hakikisha usimamizi sahihi wa makosa kwa hali zote za makosa zinazowezekana
  4. Jaribu Mantiki ya Idhini: Hakikisha udhibiti sahihi wa upatikanaji kwa majukumu tofauti ya watumiaji
  5. Fuatilia Ueneaji wa Vipimo: Lenga kufikia ueneaji mkubwa wa msimbo wa njia muhimu
  6. Jaribu Majibu ya Mtiririko: Hakikisha kushughulikia kwa usahihi yaliyomo yanayorushwa mtiririko
  7. Sanifu Matatizo ya Mtandao: Jaribu tabia chini ya hali mbaya za mtandao
  8. Jaribu Vizingiti vya Rasilimali: Thibitisha tabia wakati mipaka au viwango vya kasi vinafikiwa
  9. Jalibisha Vipimo vya Kuangusha Mabadiliko: Tengeneza mkusanyiko unaoendeshwa kila unapobadilisha msimbo
  10. Andika Hali za Vipimo: Dumisha nyaraka wazi za matukio ya vipimo

Mambo ya Kuepuka katika Vipimo

  • Kutegemea Kupita Kiasi Vipimo vya Njia Rahisi: Hakikisha kupima hali za makosa kwa kina
  • Kusahau Upimaji wa Utendaji: Tambua vizuizi kabla havijaathiri uzalishaji
  • Kupima Pekee Kwa Kutengwa: Changanya vipimo vya unit, muunganisho, na mwisho-mwisho
  • Ueneaji Usio Kamili wa API: Hakikisha vituo vyote na vipengele vinapimwa
  • Mazingaombwe ya Mazingira ya Vipimo Yasiyo Linganifu: Tumia kontena ili kuhakikisha mazingira ya vipimo yanalingana

Hitimisho

Mikakati kamili ya kupima ni muhimu kwa kuendeleza server za MCP zenye kuaminika na ubora wa juu. Kwa kutekeleza mbinu bora na vidokezo vilivyoainishwa katika mwongozo huu, unaweza kuhakikisha utekelezaji wako wa MCP unakutana na viwango vikubwa vya ubora, kuaminika, na utendaji.

Mikakati Muhimu

  1. Ubunifu wa Zana: Fuata kanuni ya jukumu moja, tumia sindano ya utegemezi, na ngaiza ubunifu wa muungano
  2. Ubunifu wa Skema: Tengeneza skema zilizo wazi na zilizotangazwa vyema na vizuizi vya uthibitishaji sahihi
  3. Usimamizi wa Makosa: Tekeleza usimamizi mzuri wa makosa, majibu ya makosa yaliyopangwa, na mantiki ya jaribio tena
  4. Utendaji: Tumia uhifadhi wa muda, usindikaji usio sambamba, na kuzuia matumizi ya rasilimali
  5. Usalama: Tekeleza uthibitishaji mzuri wa ingizo, ukaguzi wa idhini, na usimamizi wa data nyeti
  6. Vipimo: Tengeneza vipimo kamilifu vya unit, muunganisho, na mwisho-mwisho
  7. Mifumo ya Mtiririko wa Kazi: Tumia mifumo iliyojulikana kama mnyororo, wasambazaji, na usindikaji sambamba

Zoego

Sanifu zana ya MCP na mtiririko wa kazi kwa mfumo wa usindikaji wa nyaraka unaofanya:

  1. Kupokea nyaraka katika fomati mbalimbali (PDF, DOCX, TXT)
  2. Kuchuja maandishi na taarifa muhimu kutoka kwenye nyaraka
  3. Kugawanya nyaraka kwa aina na yaliyomo
  4. Kutengeneza muhtasari wa kila nyaraka

Tekeleza skema za zana, usimamizi wa makosa, na mtiririko wa kazi unaofaa zaidi kwa hali hii. Fikiria jinsi utakavyopima utekelezaji huu.

Vyanzo

  1. Jiunge na jamii ya MCP kwenye Azure AI Foundry Discord Community ili uwe na taarifa mpya za maendeleo
  2. Changia kwenye miradi ya chanzo wazi ya MCP projects
  3. Tumia kanuni za MCP katika miradi ya AI ya shirika lako
  4. Chunguza utekelezaji wa MCP maalum kwa sekta yako.
  5. Fikiria kuhudhuria kozi za juu juu ya mada maalum za MCP, kama vile muunganisho wa njia nyingi au muunganisho wa programu za biashara.
  6. Jaribu kujijengea zana na mitiririko yako ya MCP kwa kutumia kanuni ulizojifunza kupitia Hands on Lab

Kinachofuata

Kinachofuata: Case Studies


Kipinga Hukumu: Hati hii imetafsiriwa kwa kutumia huduma ya tafsiri ya AI Co-op Translator. Ingawa tunajitahidi kwa usahihi, tafadhali fahamu kwamba tafsiri za kiotomatiki zinaweza kuwa na makosa au upotovu wa maana. Hati asili katika lugha yake ya asili inapaswa kuzingatiwa kama chanzo cha mamlaka. Kwa habari muhimu, tafsiri ya mtaalamu wa binadamu inapendekezwa. Hatuwajibiki kwa kutoelewana au tafsiri isiyo sahihi inayotokana na matumizi ya tafsiri hii.