Agent Skills
› supercheck-io/supercheck
› supercheck-mcp-server
supercheck-mcp-server
GitHubSupercheck MCP 服务端技能,涵盖只读工具开发、OAuth 认证、限流、RBAC 权限控制及输出脱敏等安全与功能实现。
Trigger Scenarios
新增或修改 MCP 只读工具
调整 OAuth 授权流程
配置速率限制或身体大小限制
实施来源检查或输出脱敏逻辑
Install
npx skills add supercheck-io/supercheck --skill supercheck-mcp-server -g -y
SKILL.md
Frontmatter
{
"name": "supercheck-mcp-server",
"description": "Work on the Supercheck MCP server and its OAuth authorization flow, such as adding or changing an MCP tool, MCP client connections and project scoping, rate and body limits, origin checks, redaction of tool output, or the MCP docs."
}
Supercheck MCP server
The app exposes a read-only Model Context Protocol endpoint for AI clients. It is off unless MCP_SERVER_ENABLED=true (app/src/lib/mcp/config.ts).
flowchart LR
CLIENT[MCP client] --> ROUTE["/api/mcp route"]
ROUTE --> ORIGIN[Origin check]
ORIGIN --> TOKEN[OAuth access token verified]
TOKEN --> BODY[Bounded body read]
BODY --> LIMIT[Admission keyed on token claims]
LIMIT --> CTX[Call context: org, project, role]
CTX --> TOOL[Read-only tool]
TOOL --> RBAC[assertCanView resource]
RBAC --> QUERY[Org- and project-scoped query]
QUERY --> REDACT[safeText / safeTarget]
Start here
| File | Why |
|---|---|
app/src/app/api/mcp/route.ts |
Transport, hasTrustedRequestOrigin, admission, body read |
app/src/lib/mcp/tools.ts |
Tool registry (registerMcpTools) and the tool helper every tool goes through |
app/src/lib/mcp/context.ts |
resolveMcpCallContext from token claims, assertCanView |
app/src/lib/mcp/call-limits.ts |
Per-client and per-user message rates, batch and concurrency caps, readMcpBody |
app/src/lib/mcp/redact.ts, http-policy.ts, auth-plugins.ts |
Output redaction, OAuth endpoint deny list, OAuth plugin setup |
User docs: docs/content/docs/mcp/ (tools.mdx, security.mdx, connect.mdx).
Tool rules
- Tools are read-only: register with the shared annotations (
readOnlyHint: true,destructiveHint: false). A write tool needs its own scope, RBAC action, quota preflight, and audit design first; do not add one as a small change. - Register every tool through the
tool(...)helper intools.tswith an RBAC resource; it runsassertCanView, maps errors toforbidden/not_found/internal_error, and writes anmcp_tool_callaudit event with ids and timing only (never arguments or results). - Scope every query with the call's
organizationIdandprojectId(thescope()helper). A connection is bound to one project. Tables without an organization column (runs,project_variables) are scoped through the owning project (existsonprojects), and child rows (job tests, requirement links, component monitors) through a project-scoped parent. - Validate arguments with Zod: ids are UUIDs, lists use the shared
pageshape (limitcapped atMAX_LIMIT, cursor is the last id). - Never return scripts, secrets, variable values (
list_variablesreturns variable metadata without values: id, key, type, isSecret, description, updatedAt), headers, auth or request bodies (get_monitoruses an allow-list of scalar settings), notification channels or trigger keys, status page subscribers, investigation prompts, agent state, evidence or cost, or raw response bodies. Pass user-controlled text throughsafeText(bounded, redacted) and monitor targets throughsafeTarget(no credentials or query strings). - Tools returning stored data end their description with the
UNTRUSTEDsuffix (the staticprepare_local_authoringhint is the exception): returned text comes from test output or incidents and is prompt-injection input for the client. - Do not expose billable AI SRE actions (triage, investigate, Copilot chat, evidence briefs): they spend credits and stream output. Stored results are readable (
list_investigations,get_investigation); starting work needs a separate scope, consent wording and cost guard. - Return
ok(...)/fail(code, message): structured content plus a JSON text copy; errors are stable codes, not stack traces.
Transport and auth rules
- Request order in
route.ts:POSTchecks the origin (hasTrustedRequestOrigin), thenrequireMcpAuthverifies the token; insidehandle, a Content-Length precheck, admission (admitMcpCall, keyed on the verifiedsub/azpclaims: rate and concurrency, with the one-message charge taken up front), then the bounded body read (readMcpBody,MAX_BODY_BYTESand aMCP_BODY_READ_TIMEOUT_MSdeadline answered with 408; a batch is charged for its extra messages after parsing), then per-call context resolution. Admission cannot move ahead of token verification. Every new code path must stay behind the same checks, and the permit must be released on every exit. - Tokens come from the Better Auth OAuth provider; OAuth HTTP endpoints outside the supported flow are denied (
isOAuthEndpointDenied) and pruned from discovery metadata. resolveMcpCallContextre-checks the user on every call: banned or inactive owners are rejected (isCredentialOwnerActive), not only at connect time.
Verify
- Each tool: happy path, cross-org and cross-project denial, wrong role, malformed id, pagination edge, redaction of secrets and URLs in output.
- Route: forged origin, oversized body, rate and concurrency limits, disabled flag returns no endpoint.
- DB-backed specs (
*.db.spec.ts) run only withnpm run test:db. - Update
docs/content/docs/mcp/tools.mdxwhen the tool surface changes.
Version History
- 8a9bade Current 2026-11-03 04:16


