
GitHub MCP Server 代码规范11 条工程标准快速读懂并扩展官方仓库【免费下载链接】github-mcp-serverGitHubs official MCP Server项目地址: https://gitcode.com/GitHub_Trending/gi/github-mcp-server读完这篇指南你会拿到 GitHub MCP Server 这套官方代码库的完整开发标准参数怎么校验、错误怎么分类、分页怎么声明、大日志怎么缓冲、scope 怎么约束以及新增工具时该照抄哪条既有模式。这个项目用 Go 把 GitHub 的 REST 与 GraphQL API 包装成 MCP 工具让 AI 宿主VS Code、Claude、Cursor 等用自然语言直接驱动仓库、Issue、PR 与 Actions。下面按「工程底座 → 输入 → 输出 → 性能 → 安全 → 横切 → 质量 → 交付」的顺序拆解。项目全景先看模块边界再读代码仓库按「入口 / 工具面 / 公共能力」三层切分cmd/是二进制入口pkg/github/按功能域拆文件actions、issues、pullrequests、code_scanning 等承载全部工具pkg/其余目录提供参数、错误、scope、缓冲、观测等公共件internal/放 OAuth 流程、profiler、mock 等不可外部复用的实现。两种部署形态共用同一套工具面stdio 本地进程或 streamable-http 远程服务。读任何新工具前先确认它落在哪个功能域文件再看它引用了pkg/里哪些公共件——这就是本仓库的模块边界约定。工程底座新代码该放哪、按什么命名技术栈固定Go 1.25.12核心依赖是 MCP Go SDK、go-github/v89REST、shurcooL/githubv4GraphQL、jsonschema-go工具入参 schema、cobra/viperCLI 与配置断言统一用testify。目录约定回答「新代码放哪」目录职责你新增代码的位置cmd/二进制入口与子命令只有新子命令才动这里pkg/github/全部 MCP 工具实现按功能域一个文件新工具放对应功能域文件pkg/参数、错误、scope、缓冲、观测等公共件跨工具复用的逻辑internal/OAuth 流程、profiler、GraphQL mock不可被外部 import 的实现docs/安装、配置、特性说明新功能同步补文档命名约定很硬文件即功能域labels.go放 labels 工具测试与源码同目录同前缀labels_test.go工具函数导出名与工具注册名可对应GetLabel↔get_label。工具注册统一走 pkg/inventory/ 的ServerTool类型工具集toolset元数据集中在 tools.go别在工具文件里另起炉灶。输入规范参数校验怎么写分页怎么声明痛点是 MCP 宿主传来的参数是不可信的map[string]any——可能是字符串数字、可能是nil。本仓库用 params.go 的泛型 helper 统一收口func RequiredParamT comparable (T, error) { if _, ok : args[p]; !ok { return varZero[T](), fmt.Errorf(missing required parameter: %s, p) } val, ok : args[p].(T) if !ok || val zero[T]() { return zero, fmt.Errorf(parameter %s is not of type %T, p, zero) } return val, nil }三条规则必需参数必须「存在 类型对 非零值」可选参数缺省返回零值、类型错才报错数字参数一律走toInt/toInt64它会接受字符串数字但拒绝 NaN、Inf、小数和超范围值数组参数要同时兼容nil、[]string、[]any三种形态并逐项校验。取值范围与枚举不靠 runtime 检查而是写在 JSON Schema 里mcp.Min(1)、Max(100)、Enum(...)在工具定义阶段就约束住 LLM 生成的参数。分页则用三个声明器注入声明器注入的参数适用工具WithPaginationpage / perPageREST APIWithCursorPaginationperPage / after纯 GraphQL 游标WithUnifiedPaginationpage / perPage / after对外统一分页、内部转游标perPage全部统一为 min 1 / max 100新工具不要自定义分页字段名。输出规范错误分类表、统一响应与资源清理输出侧第一个决策是「业务失败」还是「系统失败」参数错、未找到、限流用utils.NewToolResultError作为工具结果返回error 为 nil让 LLM 能读到原因并自纠panic、客户端构造失败等系统错误才走 Go error 通道。API 错误按上游分三类封装全部在 pkg/errors/错误类型构造器特殊处理REST API 错误NewGitHubAPIErrorResponse识别RateLimitError/AbuseRateLimitError换算成「Retry after Xs」提示GraphQL 错误NewGitHubGraphQLErrorResponse消息 原始 err 包装Raw HTTP 错误NewGitHubRawAPIErrorResponse携带原始*http.Response名称解析失败NewStructuredResolutionErrorResponse返回 JSON 结构体kind candidates hint供 agent 自纠这些构造器同时把错误写入 contextContextWithGitHubErrors供 pkg/http/ 中间件统一做观测与 scope 诊断。响应体清理有固定写法result, resp, err : client.Repositories.ListBranches(ctx, owner, repo, opts) if err ! nil { return ghErrors.NewGitHubAPIErrorResponse(ctx, list branches failed, resp, err), nil } defer func() { _ resp.Body.Close() }()注意err ! nil时 resp 可能为 nil所以构造器内部做了 nil 容忍——新工具照抄这个顺序即可。性能护栏大日志环形缓冲、分页策略与埋点最典型的性能场景是get_job_logsActions 日志可能几百 MB绝不能整体读进内存。pkg/buffer/ 用环形缓冲流式处理// 64KB 块读取只保留最后 N 行单行超 10MB 截断并加标记 lines : make([]string, maxJobLogLines) writeIndex : 0 for { n, err : httpResp.Body.Read(readBuf) // 按 \n 切分storeLine 覆盖 writeIndex 位置 writeIndex (writeIndex 1) % maxJobLogLines if err io.EOF { break } }三个护栏值得记住环形窗口默认 500 行、上限 10 万行单行 10MB 硬顶、截断行只留前 1000 字符加... [TRUNCATED]读缓冲固定 64KB。分页策略对比策略游标形态适用特点REST page/perPage页码go-github 列表接口简单稳定跳页可预估GraphQL 游标 after不透明游标githubv4高效适合增量拉取统一分页page after 并存对外 API 一致性handler 内部转游标性能分析走 internal/profiler/由GITHUB_MCP_PROFILING_ENABLED开关控制未启用时Start返回 noop 闭包零开销finish : profiler.Start(ctx, log_buffer_processing) // ... 业务逻辑 ... profile : finish(lineCount, byteCount) // 记录 duration / 内存 delta / 行数 / 字节数安全红线令牌流转、最小权限与校验边界令牌有两条路GITHUB_PERSONAL_ACCESS_TOKEN环境变量优先级最高和 OAuth 浏览器登录token 只存内存回调端口由GITHUB_OAUTH_CALLBACK_PORT发布到 loopback。安全要点PAT 建议放进.env并加入.gitignore含 token 的配置文件chmod 600GHE 主机强制 HTTPS非回环地址拒绝明文传输防止凭据裸奔。最小权限不靠文档约定而是代码约束。pkg/scopes/ 把全部 OAuth scope 定义为常量每个工具在注册时声明自己需要的 scopefunc GetLabel(t translations.TranslationHelperFunc) inventory.ServerTool { return NewTool( ToolsetMetadataIssues, mcp.Tool{ Name: get_label, /* ... */ }, []scopes.Scope{scopes.Repo}, // 声明式最小权限 func(ctx context.Context, deps ToolDependencies, ...) { /* handler */ }, ) }运行期由scope_challenge中间件校验实际令牌 scope 是否覆盖声明不足时在请求阶段就挑战而不是等 API 返回 403。输入校验边界则如前文所述schema 的 Min/Max/Enum 挡住 LLM 幻觉参数toInt挡住脏数字两层都不信任外部输入。横切关注点日志分级、监控注入与国际化日志统一走标准库log/slog没有第三方可观测框架。分级约定级别场景例子ErrorAPI 失败、不可恢复错误错误构造器 中间件兜底Warn配置降级、scope 不足scope_challenge 未通过Info工具调用、性能 profileprofile.String()输出Debug字节级 I/O 调试IOLogger的 stdin/stdout 记录pkg/log/ 的IOLogger包装 stdio 流把每段收发字节记入日志专治 MCP stdio 传输问题。监控通过 pkg/observability/ 的Exporters接口注入Logger() *slog.LoggerMetrics(ctx) metrics.Metrics依赖注入、允许替换任意 slog.Handler不需要监控时用slog.DiscardHandlermetrics.NewNoopMetrics()接口拒绝 nil 实现。国际化/文案覆盖走 pkg/translations/ 的t(key, default)函数key 全大写常量形式解析顺序是「进程内缓存 → 环境变量GITHUB_MCP_KEY→ viper JSON 配置 → 默认值」。所有工具描述、标题都必须过t()禁止把文案裸写在工具定义里——这也让运维不改代码就能覆盖任意提示语。质量保障测试布局、mock 与快照测试布局只有一个规则与源码同目录、同前缀labels.go↔labels_test.go工具级断言用testify。三个专门机制值得新贡献者直接复用internal/githubv4mock/——GitHub GraphQL 的 mock 客户端含本地 round-tripper让*_test.go不碰真实 APIpkg/github/toolsnaps/——工具定义快照约 120 个.snap锁定每个工具的名称、描述、schema、注解schema 漂移会被 tools_static_validation_test.go 这类静态校验测试抓住e2e/——面向真实服务的端到端测试独立于单测运行。测试类型位置重点单元测试各*_test.go参数校验分支、错误分类、scope 声明静态校验tools_*_validation_test.go 快照工具定义与.snap一致、注解齐全Mock 集成githubv4mockGraphQL 查询回环、字段过滤E2Ee2e/真实认证链路、远端服务行为贡献前跑 script/ 下的lint与test新工具没有对应测试文件或快照更新基本过不了 CI 心态关。交付与运行多阶段 Dockerfile 与环境变量Dockerfile 是三段式每段都锁定镜像 digest可复现构建node:26-alpine把 ui/ 的 Vite 产物构建进pkg/github/ui_dist/golang:1.25-alpine以CGO_ENABLED0交叉编译-ldflags注入 version/commit/dateOAuth 凭据走--mounttypesecret而非明文 layer最终distroless/base-debian12运行无 shell、攻击面最小默认CMD [stdio]对外EXPOSE 8082streamable-http 模式。环境变量作用备注GITHUB_PERSONAL_ACCESS_TOKEN认证优先于 OAuthGITHUB_HOSTGHE/ghe.com 主机非回环必须 HTTPSGITHUB_TOOLSETS/GITHUB_TOOLS工具面裁剪env 优先于 CLI flagGITHUB_INSIDERS内测特性开关true/falseGITHUB_OAUTH_CALLBACK_PORTOAuth 回调端口Docker 下需发布到 loopbackGITHUB_MCP_PROFILING_ENABLED性能 profile 开关默认关交付前检查清单10 项可勾选提交新工具或改动前把下面这份清单过一遍——它汇总了前文全部规范工具注册在正确的功能域文件复用NewToolinventory.ServerTool模式未另造结构必需参数走RequiredParam/RequiredInt可选参数走Optional*数字参数全部过toInt参数 schema 声明了 Min/Max/Enum 边界分页用了With*Pagination三选一工具级错误用NewToolResultError返回API 错误走ghErrors.New*ErrorResponse错误已入 context每个 HTTP 响应体都有defer resp.Body.Close()声明了最小 scope 列表[]scopes.Scope{...}写操作确认过ReadOnlyHint文案全部过t(key, default)无硬编码描述大输出路径日志、列表评估过缓冲与分页上限未整块读入内存补了*_test.go工具定义变更同步更新了__toolsnaps__/*.snap跑通script/lint与script/testdocs/ 下相关说明同步更新照着既有模式写你的代码就会和官方仓库保持同一套标准——这正是这个仓库最值得借鉴的工程纪律。【免费下载链接】github-mcp-serverGitHubs official MCP Server项目地址: https://gitcode.com/GitHub_Trending/gi/github-mcp-server创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考