项目文件夹

文件
2026-07-13 13:31:35 +08:00

39 KiB

Общество и приноси

Как да допринесете за MCP: Инструменти, документация, код и други

(Кликнете върху изображението по-горе, за да гледате видеото на този урок)

Преглед

Този урок е насочен към това как да се ангажирате с общността на MCP, да допринасяте за екосистемата на MCP и да следвате добрите практики за съвместна разработка. Разбирането как да участвате в проекти с отворен код на MCP е от съществено значение за тези, които искат да оформят бъдещето на тази технология.

Образователни цели

До края на този урок ще можете да:

  • Разберете структурата на общността и екосистемата на MCP
  • Участвате ефективно във форуми и дискусии на общността на MCP
  • Допринасяте в откритите хранилища на MCP
  • Създавате и споделяте персонализирани инструменти и сървъри за MCP
  • Следвате добрите практики за разработка и сътрудничество в MCP
  • Откривате ресурси на общността и рамки за разработка на MCP

Екосистемата на общността на MCP

Екосистемата на MCP се състои от различни компоненти и участници, които работят заедно за развитието на протокола.

Ключови компоненти на общността

  1. Основни поддръжници на протокола: Официалната GitHub организация на Model Context Protocol поддържа основните спецификации на MCP и референтните реализации
  2. Разработчици на инструменти: Индивиди и екипи, които създават инструменти и сървъри за MCP
  3. Доставчици на интеграции: Фирми, които интегрират MCP в своите продукти и услуги
  4. Крайни потребители: Разработчици и организации, които използват MCP в своите приложения
  5. Приносители: Членове на общността, които допринасят с код, документация или други ресурси

Ресурси на общността

Официални канали

Ресурси, създадени от общността

Принос към MCP

Видове приноси

Екосистемата на MCP приветства различни видове приноси:

  1. Приноси с код:

    • Подобрения на основния протокол
    • Поправки на грешки
    • Имплементации на инструменти и сървъри
    • Библиотеки за клиенти/сървъри на различни езици
  2. Документация:

    • Подобряване на съществуващата документация
    • Създаване на уроци и ръководства
    • Превод на документация
    • Създаване на примери и примерни приложения
  3. Поддръжка на общността:

    • Отговаряне на въпроси във форуми и дискусии
    • Тестване и докладване на проблеми
    • Организиране на събития за общността
    • Менторство на нови приносители

Процес на принос: Основен протокол

За да допринесете към основния MCP протокол или официалните реализации, следвайте тези принципи от официалните указания за принос:

  1. Простота и минимализъм: Спецификацията на MCP поддържа висок стандарт за добавяне на нови концепции. По-лесно е да се добавят неща към спецификацията, отколкото да се премахват.

  2. Конкретен подход: Промените в спецификацията трябва да се основават на конкретни проблеми при имплементацията, а не на спекулативни идеи.

  3. Етапи на предложение:

    • Дефиниране: Изследвайте проблемното пространство, валидирайте, че други потребители на MCP имат подобен проблем
    • Прототип: Създайте примерни решения и демонстрирайте практическото им приложение
    • Писане: Въз основа на прототипа, напишете предложение за спецификация

Настройка на средата за разработка

# Форкирай хранилището
git clone https://github.com/YOUR-USERNAME/modelcontextprotocol.git
cd modelcontextprotocol

# Инсталирай зависимости
npm install

# За промени в схемата, валидация и генериране на schema.json:
npm run check:schema:ts
npm run generate:schema

# За промени в документацията
npm run check:docs
npm run format

# Прегледай документацията локално (по избор):
npm run serve:docs

Пример: Принос с поправка на грешка

// Оригинален код с бъг в typescript-sdk
export function validateResource(resource: unknown): resource is MCPResource {
  if (!resource || typeof resource !== 'object') {
    return false;
  }
  
  // Бъг: Липсва проверка на свойството
  // Текуща имплементация:
  const hasName = 'name' in resource;
  const hasSchema = 'schema' in resource;
  
  return hasName && hasSchema;
}

// Поправена имплементация в принос
export function validateResource(resource: unknown): resource is MCPResource {
  if (!resource || typeof resource !== 'object') {
    return false;
  }
  
  // Подобрена валидация
  const hasName = 'name' in resource && typeof (resource as MCPResource).name === 'string';
  const hasSchema = 'schema' in resource && typeof (resource as MCPResource).schema === 'object';
  const hasDescription = !('description' in resource) || typeof (resource as MCPResource).description === 'string';
  
  return hasName && hasSchema && hasDescription;
}

Пример: Принос с нов инструмент към стандартната библиотека

# Примерен принос: Инструмент за обработка на CSV данни за библиотеката MCP стандарт

from mcp_tools import Tool, ToolRequest, ToolResponse, ToolExecutionException
import pandas as pd
import io
import json
from typing import Dict, Any, List, Optional

class CsvProcessingTool(Tool):
    """
    Tool for processing and analyzing CSV data.
    
    This tool allows models to extract information from CSV files,
    run basic analysis, and convert data between formats.
    """
    
    def get_name(self):
        return "csvProcessor"
        
    def get_description(self):
        return "Processes and analyzes CSV data"
    
    def get_schema(self):
        return {
            "type": "object",
            "properties": {
                "csvData": {
                    "type": "string", 
                    "description": "CSV data as a string"
                },
                "csvUrl": {
                    "type": "string",
                    "description": "URL to a CSV file (alternative to csvData)"
                },
                "operation": {
                    "type": "string",
                    "enum": ["summary", "filter", "transform", "convert"],
                    "description": "Operation to perform on the CSV data"
                },
                "filterColumn": {
                    "type": "string",
                    "description": "Column to filter by (for filter operation)"
                },
                "filterValue": {
                    "type": "string",
                    "description": "Value to filter for (for filter operation)"
                },
                "outputFormat": {
                    "type": "string",
                    "enum": ["json", "csv", "markdown"],
                    "default": "json",
                    "description": "Output format for the processed data"
                }
            },
            "oneOf": [
                {"required": ["csvData", "operation"]},
                {"required": ["csvUrl", "operation"]}
            ]
        }
    
    async def execute_async(self, request: ToolRequest) -> ToolResponse:
        try:
            # Извличане на параметри
            operation = request.parameters.get("operation")
            output_format = request.parameters.get("outputFormat", "json")
            
            # Получаване на CSV данни от директни данни или URL
            df = await self._get_dataframe(request)
            
            # Обработка въз основа на поискана операция
            result = {}
            
            if operation == "summary":
                result = self._generate_summary(df)
            elif operation == "filter":
                column = request.parameters.get("filterColumn")
                value = request.parameters.get("filterValue")
                if not column:
                    raise ToolExecutionException("filterColumn is required for filter operation")
                result = self._filter_data(df, column, value)
            elif operation == "transform":
                result = self._transform_data(df, request.parameters)
            elif operation == "convert":
                result = self._convert_format(df, output_format)
            else:
                raise ToolExecutionException(f"Unknown operation: {operation}")
            
            return ToolResponse(result=result)
        
        except Exception as e:
            raise ToolExecutionException(f"CSV processing failed: {str(e)}")
    
    async def _get_dataframe(self, request: ToolRequest) -> pd.DataFrame:
        """Gets a pandas DataFrame from either CSV data or URL"""
        if "csvData" in request.parameters:
            csv_data = request.parameters.get("csvData")
            return pd.read_csv(io.StringIO(csv_data))
        elif "csvUrl" in request.parameters:
            csv_url = request.parameters.get("csvUrl")
            return pd.read_csv(csv_url)
        else:
            raise ToolExecutionException("Either csvData or csvUrl must be provided")
    
    def _generate_summary(self, df: pd.DataFrame) -> Dict[str, Any]:
        """Generates a summary of the CSV data"""
        return {
            "columns": df.columns.tolist(),
            "rowCount": len(df),
            "columnCount": len(df.columns),
            "numericColumns": df.select_dtypes(include=['number']).columns.tolist(),
            "categoricalColumns": df.select_dtypes(include=['object']).columns.tolist(),
            "sampleRows": json.loads(df.head(5).to_json(orient="records")),
            "statistics": json.loads(df.describe().to_json())
        }
    
    def _filter_data(self, df: pd.DataFrame, column: str, value: str) -> Dict[str, Any]:
        """Filters the DataFrame by a column value"""
        if column not in df.columns:
            raise ToolExecutionException(f"Column '{column}' not found")
            
        filtered_df = df[df[column].astype(str).str.contains(value)]
        
        return {
            "originalRowCount": len(df),
            "filteredRowCount": len(filtered_df),
            "data": json.loads(filtered_df.to_json(orient="records"))
        }
    
    def _transform_data(self, df: pd.DataFrame, params: Dict[str, Any]) -> Dict[str, Any]:
        """Transforms the data based on parameters"""
        # Имплементацията би включвала различни трансформации
        return {
            "status": "success",
            "message": "Transformation applied"
        }
    
    def _convert_format(self, df: pd.DataFrame, format: str) -> Dict[str, Any]:
        """Converts the DataFrame to different formats"""
        if format == "json":
            return {
                "data": json.loads(df.to_json(orient="records")),
                "format": "json"
            }
        elif format == "csv":
            return {
                "data": df.to_csv(index=False),
                "format": "csv"
            }
        elif format == "markdown":
            return {
                "data": df.to_markdown(),
                "format": "markdown"
            }
        else:
            raise ToolExecutionException(f"Unsupported output format: {format}")

Насоки за принос

За да направите успешен принос в MCP проекти:

  1. Започнете с малко: Започнете с документация, поправки на грешки или малки подобрения
  2. Следвайте стила: Спазвайте стила на кодиране и конвенциите на проекта
  3. Пишете тестове: Включете модулни тестове за вашите кодови приноси
  4. Документирайте работата си: Добавете ясна документация за нови функции или промени
  5. Подайте целенасочени PR: Поддържайте заявките за внасяне, фокусирани върху един проблем или функция
  6. Ангажирайте се с обратна връзка: Бъдете отзивчиви към обратната връзка за вашите приноси

Примерен работен процес за принос

# Клонирайте хранилището
git clone https://github.com/modelcontextprotocol/typescript-sdk.git
cd typescript-sdk

# Създайте нов клон за вашия принос
git checkout -b feature/my-contribution

# Направете промените си
# ...

# Стартирайте тестове, за да се уверите, че промените ви не нарушават съществуващата функционалност
npm test

# Задействайте промените си с описателно съобщение
git commit -am "Fix validation in resource handler"

# Качете вашия клон във вашето форк хранилище
git push origin feature/my-contribution

# Създайте заявка за сливане от вашия клон към главното хранилище
# След това ангажирайте се с обратна връзка и преглеждайте вашата заявка за сливане според нуждите

Създаване и споделяне на MCP сървъри

Един от най-ценните начини да допринесете за екосистемата на MCP е чрез създаване и споделяне на персонализирани MCP сървъри. Общността вече е разработила стотици сървъри за различни услуги и случаи на употреба.

Рамки за разработка на MCP сървъри

Няколко рамки са налични за опростяване на разработката на MCP сървъри:

  1. Официални SDK (съгласувани с MCP Спецификация 2025-11-25):

  2. Рамки на общността:

Разработка на споделими инструменти

Пример за .NET: Създаване на пакет с инструменти за споделяне

// Create a new .NET library project
// dotnet new classlib -n McpFinanceTools

using Microsoft.Mcp.Tools;
using System.Threading.Tasks;
using System.Net.Http;
using System.Text.Json;

namespace McpFinanceTools
{
    // Stock quote tool
    public class StockQuoteTool : IMcpTool
    {
        private readonly HttpClient _httpClient;
        
        public StockQuoteTool(HttpClient httpClient = null)
        {
            _httpClient = httpClient ?? new HttpClient();
        }
        
        public string Name => "stockQuote";
        public string Description => "Gets current stock quotes for specified symbols";
        
        public object GetSchema()
        {
            return new {
                type = "object",
                properties = new {
                    symbol = new { 
                        type = "string",
                        description = "Stock symbol (e.g., MSFT, AAPL)" 
                    },
                    includeHistory = new { 
                        type = "boolean",
                        description = "Whether to include historical data",
                        default = false
                    }
                },
                required = new[] { "symbol" }
            };
        }
        
        public async Task<ToolResponse> ExecuteAsync(ToolRequest request)
        {
            // Extract parameters
            string symbol = request.Parameters.GetProperty("symbol").GetString();
            bool includeHistory = false;
            
            if (request.Parameters.TryGetProperty("includeHistory", out var historyProp))
            {
                includeHistory = historyProp.GetBoolean();
            }
            
            // Call external API (example)
            var quoteResult = await GetStockQuoteAsync(symbol);
            
            // Add historical data if requested
            if (includeHistory)
            {
                var historyData = await GetStockHistoryAsync(symbol);
                quoteResult.Add("history", historyData);
            }
            
            // Return formatted result
            return new ToolResponse {
                Result = JsonSerializer.SerializeToElement(quoteResult)
            };
        }
        
        private async Task<Dictionary<string, object>> GetStockQuoteAsync(string symbol)
        {
            // Implementation would call a real stock API
            // This is a simplified example
            return new Dictionary<string, object>
            {
                ["symbol"] = symbol,
                ["price"] = 123.45,
                ["change"] = 2.5,
                ["percentChange"] = 1.2,
                ["lastUpdated"] = DateTime.UtcNow
            };
        }
        
        private async Task<object> GetStockHistoryAsync(string symbol)
        {
            // Implementation would get historical data
            // Simplified example
            return new[]
            {
                new { date = DateTime.Now.AddDays(-7).Date, price = 120.25 },
                new { date = DateTime.Now.AddDays(-6).Date, price = 122.50 },
                new { date = DateTime.Now.AddDays(-5).Date, price = 121.75 }
                // More historical data...
            };
        }
    }
}

// Create package and publish to NuGet
// dotnet pack -c Release
// dotnet nuget push bin/Release/McpFinanceTools.1.0.0.nupkg -s https://api.nuget.org/v3/index.json -k YOUR_API_KEY

Пример за Java: Създаване на Maven пакет за инструменти

// pom.xml конфигурация за споделян MCP инструментален пакет
<!-- 
<project>
    <groupId>com.example</groupId>
    <artifactId>mcp-weather-tools</artifactId>
    <version>1.0.0</version>
    
    <dependencies>
        <dependency>
            <groupId>com.mcp</groupId>
            <artifactId>mcp-server</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
    
    <distributionManagement>
        <repository>
            <id>github</id>
            <name>GitHub Packages</name>
            <url>https://maven.pkg.github.com/username/mcp-weather-tools</url>
        </repository>
    </distributionManagement>
</project>
-->

package com.example.mcp.weather;

import com.mcp.tools.Tool;
import com.mcp.tools.ToolRequest;
import com.mcp.tools.ToolResponse;
import com.mcp.tools.ToolExecutionException;

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;

public class WeatherForecastTool implements Tool {
    private final HttpClient httpClient;
    private final String apiKey;
    
    public WeatherForecastTool(String apiKey) {
        this.httpClient = HttpClient.newHttpClient();
        this.apiKey = apiKey;
    }
    
    @Override
    public String getName() {
        return "weatherForecast";
    }
    
    @Override
    public String getDescription() {
        return "Gets weather forecast for a specified location";
    }
    
    @Override
    public Object getSchema() {
        Map<String, Object> schema = new HashMap<>();
        // Дефиниция на схема...
        return schema;
    }
    
    @Override
    public ToolResponse execute(ToolRequest request) {
        try {
            String location = request.getParameters().get("location").asText();
            int days = request.getParameters().has("days") ? 
                request.getParameters().get("days").asInt() : 3;
            
            // Извикване на API за времето
            Map<String, Object> forecast = getForecast(location, days);
            
            // Построяване на отговор
            return new ToolResponse.Builder()
                .setResult(forecast)
                .build();
        } catch (Exception ex) {
            throw new ToolExecutionException("Weather forecast failed: " + ex.getMessage(), ex);
        }
    }
    
    private Map<String, Object> getForecast(String location, int days) {
        // Имплементацията би извиквала API за времето
        // Опостижен пример
        Map<String, Object> result = new HashMap<>();
        // Добавяне на данни за прогноза...
        return result;
    }
}

// Създаване и публикуване с Maven
// mvn clean package
// mvn deploy

Пример за Python: Публикуване на пакет в PyPI

# Структура на директория за PyPI пакет:
# mcp_nlp_tools/
# ├── ЛИЦЕНЗ
# ├── README.md
# ├── setup.py
# ├── mcp_nlp_tools/
# │   ├── __init__.py
# │   ├── sentiment_tool.py
# │   └── translation_tool.py

# Пример setup.py
"""
from setuptools import setup, find_packages

setup(
    name="mcp_nlp_tools",
    version="0.1.0",
    packages=find_packages(),
    install_requires=[
        "mcp_server>=1.0.0",
        "transformers>=4.0.0",
        "torch>=1.8.0"
    ],
    author="Your Name",
    author_email="your.email@example.com",
    description="MCP tools for natural language processing tasks",
    long_description=open("README.md").read(),
    long_description_content_type="text/markdown",
    url="https://github.com/username/mcp_nlp_tools",
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires=">=3.8",
)
"""

# Пример за имплементация на NLP инструмент (sentiment_tool.py)
from mcp_tools import Tool, ToolRequest, ToolResponse, ToolExecutionException
from transformers import pipeline
import torch

class SentimentAnalysisTool(Tool):
    """MCP tool for sentiment analysis of text"""
    
    def __init__(self, model_name="distilbert-base-uncased-finetuned-sst-2-english"):
        # Зареди модела за анализ на настроението
        self.sentiment_analyzer = pipeline("sentiment-analysis", model=model_name)
    
    def get_name(self):
        return "sentimentAnalysis"
        
    def get_description(self):
        return "Analyzes the sentiment of text, classifying it as positive or negative"
    
    def get_schema(self):
        return {
            "type": "object",
            "properties": {
                "text": {
                    "type": "string", 
                    "description": "The text to analyze for sentiment"
                },
                "includeScore": {
                    "type": "boolean",
                    "description": "Whether to include confidence scores",
                    "default": True
                }
            },
            "required": ["text"]
        }
    
    async def execute_async(self, request: ToolRequest) -> ToolResponse:
        try:
            # Извлечи параметрите
            text = request.parameters.get("text")
            include_score = request.parameters.get("includeScore", True)
            
            # Анализирай настроението
            sentiment_result = self.sentiment_analyzer(text)[0]
            
            # Форматирай резултата
            result = {
                "sentiment": sentiment_result["label"],
                "text": text
            }
            
            if include_score:
                result["score"] = sentiment_result["score"]
            
            # Върни резултата
            return ToolResponse(result=result)
            
        except Exception as e:
            raise ToolExecutionException(f"Sentiment analysis failed: {str(e)}")

# За публикуване:
# python setup.py sdist bdist_wheel
# python -m twine upload dist/*

Споделяне на добри практики

Когато споделяте MCP инструменти с общността:

  1. Пълна документация:

    • Документирайте целта, употребата и примери
    • Обяснете параметрите и стойностите на връщане
    • Документирайте всички външни зависимости
  2. Обработка на грешки:

    • Прилагайте надеждна обработка на грешки
    • Предоставяйте полезни съобщения за грешки
    • Обработвайте гранични случаи внимателно
  3. Съображения за производителност:

    • Оптимизирайте за скорост и използване на ресурси
    • Внедрете кеширане, когато е подходящо
    • Помислете за мащабируемост
  4. Сигурност:

    • Използвайте защитени API ключове и автентикация
    • Валидирайте и почиствате входящи данни
    • Прилагайте ограничаване на честотата на външни API повиквания
  5. Тестване:

    • Включвайте всеобхватно покритие на тестове
    • Тествайте с различни видове вход и гранични случаи
    • Документирайте процедурите за тестване

Сътрудничество в общността и добри практики

Ефективното сътрудничество е ключът към процъфтяваща екосистема на MCP.

Канали за комуникация

  • GitHub Issues и дискусии
  • Microsoft Tech Community
  • Discord и Slack канали
  • Stack Overflow (таг: model-context-protocol или mcp)

Преглед на код

При преглед на приноси към MCP:

  1. Яснота: Кодът ясен ли е и добре документиран?
  2. Коректност: Работи ли както се очаква?
  3. Последователност: Следва ли конвенциите на проекта?
  4. Пълнота: Включени ли са тестове и документация?
  5. Сигурност: Има ли някакви проблеми със сигурността?

Съвместимост на версиите

При разработка за MCP:

  1. Версиониране на протокола: Спазвайте версията на MCP протокола, която вашият инструмент поддържа
  2. Съвместимост с клиенти: Обмислете обратно съвместимост
  3. Съвместимост със сървъри: Следвайте указанията за имплементация на сървъри
  4. Разбиващи промени: Ясно документирайте всякакви разбиващи промени

Примерен проект на общността: Регистър на MCP инструменти

Важен принос за общността може да бъде разработването на публичен регистър за MCP инструменти.

# Примерна схема за API на регистър на инструменти за общността

from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel, Field, HttpUrl
from typing import List, Optional
import datetime
import uuid

# Модели за регистъра на инструментите
class ToolSchema(BaseModel):
    """JSON Schema for a tool"""
    type: str
    properties: dict
    required: List[str] = []

class ToolRegistration(BaseModel):
    """Information for registering a tool"""
    name: str = Field(..., description="Unique name for the tool")
    description: str = Field(..., description="Description of what the tool does")
    version: str = Field(..., description="Semantic version of the tool")
    schema: ToolSchema = Field(..., description="JSON Schema for tool parameters")
    author: str = Field(..., description="Author of the tool")
    repository: Optional[HttpUrl] = Field(None, description="Repository URL")
    documentation: Optional[HttpUrl] = Field(None, description="Documentation URL")
    package: Optional[HttpUrl] = Field(None, description="Package URL")
    tags: List[str] = Field(default_factory=list, description="Tags for categorization")
    examples: List[dict] = Field(default_factory=list, description="Example usage")

class Tool(ToolRegistration):
    """Tool with registry metadata"""
    id: uuid.UUID = Field(default_factory=uuid.uuid4)
    created_at: datetime.datetime = Field(default_factory=datetime.datetime.now)
    updated_at: datetime.datetime = Field(default_factory=datetime.datetime.now)
    downloads: int = Field(default=0)
    rating: float = Field(default=0.0)
    ratings_count: int = Field(default=0)

# FastAPI приложение за регистъра
app = FastAPI(title="MCP Tool Registry")

# Паметна база данни за този пример
tools_db = {}

@app.post("/tools", response_model=Tool)
async def register_tool(tool: ToolRegistration):
    """Register a new tool in the registry"""
    if tool.name in tools_db:
        raise HTTPException(status_code=400, detail=f"Tool '{tool.name}' already exists")
    
    new_tool = Tool(**tool.dict())
    tools_db[tool.name] = new_tool
    return new_tool

@app.get("/tools", response_model=List[Tool])
async def list_tools(tag: Optional[str] = None):
    """List all registered tools, optionally filtered by tag"""
    if tag:
        return [tool for tool in tools_db.values() if tag in tool.tags]
    return list(tools_db.values())

@app.get("/tools/{tool_name}", response_model=Tool)
async def get_tool(tool_name: str):
    """Get information about a specific tool"""
    if tool_name not in tools_db:
        raise HTTPException(status_code=404, detail=f"Tool '{tool_name}' not found")
    return tools_db[tool_name]

@app.delete("/tools/{tool_name}")
async def delete_tool(tool_name: str):
    """Delete a tool from the registry"""
    if tool_name not in tools_db:
        raise HTTPException(status_code=404, detail=f"Tool '{tool_name}' not found")
    del tools_db[tool_name]
    return {"message": f"Tool '{tool_name}' deleted"}

Основни изводи

  • Общността на MCP е разнообразна и приветства различни видове приноси
  • Приносът към MCP може да варира от подобрения на основния протокол до персонализирани инструменти
  • Следването на насоките за принос повишава шансовете вашият PR да бъде приет
  • Създаването и споделянето на MCP инструменти е ценен начин за разширяване на екосистемата
  • Сътрудничеството в общността е от съществено значение за растежа и подобрението на MCP

Упражнение

  1. Идентифицирайте област в екосистемата на MCP, където може да направите принос според уменията и интересите си
  2. Форкнете MCP хранилището и настройте локална среда за разработка
  3. Създайте малко подобрение, поправка на грешка или инструмент, който би бил полезен за общността
  4. Документирайте приноса си с подходящи тестове и документация
  5. Подайте pull request към съответното хранилище

Допълнителни ресурси


Какво следва

Следва: Уроци от ранното приемане


Отказ от отговорност: Този документ е преведен чрез AI преводаческа услуга Co-op Translator. Въпреки че се стремим към точност, моля имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е неразбирателства или неправилни тълкувания, възникнали от използването на този превод.