Agent Skills › stella/stella › conventions-mcp

conventions-mcp

GitHub

定义面向AI Agent的MCP工具契约规范,指导如何设计易被模型驱动的Schema与API。强调通过自动化评估验证可用性,遵循单一意图、精简可选参数及容错处理等原则,确保Agent能高效完成工作流。

.ai/local-skills/conventions-mcp/SKILL.md stella/stella

Trigger Scenarios

新增或修改MCP工具定义 调整CLI生成能力或输入输出Schema 优化Agent交互接口描述

Install

npx skills add stella/stella --skill conventions-mcp -g -y
More Options

Non-standard path

npx skills add https://github.com/stella/stella/tree/main/.ai/local-skills/conventions-mcp -g -y

Use without installing

npx skills use stella/stella@conventions-mcp

指定 Agent (Claude Code)

npx skills add stella/stella --skill conventions-mcp -a claude-code -g -y

安装 repo 全部 skill

npx skills add stella/stella --all -g -y

预览 repo 内 skill

npx skills add stella/stella --list

SKILL.md

Frontmatter
{
    "name": "conventions-mcp",
    "description": "Apply when adding or changing an MCP tool, a capability the CLI generates, a tool input or output schema, a tool description, an error envelope, or an agent-facing reference resource. Enforces contracts that language models can actually drive, measured by evals rather than by schema soundness."
}

Agent-Facing Contract Conventions

An MCP tool or CLI capability is a user interface whose user is a language model. A schema can be type-sound, validated, and documented and still be undrivable: models copy examples, fill every property they see, retry with the same call, and cannot inspect bytes. Design for that behaviour and measure it.

Target Property

A capable model, given only what tools/list and the reference resources expose, completes the workflow on the first or second attempt, and every rejection it receives names the next call to make. The authoring eval, not code review, decides whether a contract change helped.

Measure Before Believing

  1. An eval is the acceptance test. Every agent-facing workflow has an eval that drives the real tools with the real schemas and scores each step separately (authored, created, configured, filled, or the workflow's equivalents). Run it before and after a contract change and put both tables in the PR. A change that is "obviously better" without numbers is a hypothesis.
  2. Keep the rejected call, in the eval only. The eval records the raw input of every call the schema rejected before the handler ran; a pass rate without the rejected payloads cannot say whether the model or the contract failed. Eval fixtures are synthetic, so the trace may hold them whole. Production telemetry for a rejected call records the tool name, the issue codes, and the issue paths, never the payload: tool arguments carry matter content and personal data.
  3. Parse through the schema the handler uses. The eval, the tests, and the handler must validate the same object; a normalisation that lives only in one handler's pre-step is invisible to the eval and drifts.

Shape Tools For How Models Behave

  1. One tool, one intent. Split create, configure, and update into separate tools rather than one tool whose meaning depends on which optional arguments are present. Cross-field "provide A or B, not both" checks are a sign the tool has more than one job.
  2. Few optionals, one discriminator. Replace a set of mutually exclusive optional keys with one discriminated union (source: { type: "ai" | "lookup" | ... }). A model that fills every property cannot produce a contradictory union member; it can produce six contradictory optionals.
  3. Best effort over all-or-nothing for collections. When a call carries a list of entries, validate each entry independently, apply the valid ones, and return the rest as per-entry issues[]. One bad property must not sink a call that carried seven good entries.
  4. Echo the next call. Return, from the call that discovers state, the exact payload the next call accepts (a configure skeleton, canonical path spelling, allowed values). Copying beats inferring. Read-back must round-trip: the shape a describe tool returns is the shape the configure tool accepts, byte for byte, and a test pins that fixed point.
  5. Idempotent and re-entrant. Models retry with the same call and resend everything they know. Accept the resend: upsert on a stable id, idempotency keys that cover every argument, durable receipts replayed without re-executing.
  6. Keep artefacts out of the model. Bytes are the hardest step in any loop. Prefer references (a host file reference, an id of something already stored) over inline base64; when inline is the only path, bound it by the request frame, derive the limit from the shared constant, and state it in the description. Never let an error hint invite the model to shrink or rewrite a document.

Every Error Is A Next Step

  1. Structured envelope, closed codes. Failures return { code, message, hint, issues[] } with codes from a closed set. hint names the corrective action, the tool to call, and where to go (a deep link when the fix is in the UI). "Disabled" without "enable it here" is a dead end.
  2. Never leak the substrate. A malformed id is a validation issue at the boundary, never a database cast error reported as internal_error. Every id input is declared with the shared id schema; a registry-wide test enforces it.
  3. Warn about what the model probably meant. Discovery and save return warnings[] with closed codes for the known traps (unprefixed loop item, unknown directive, split marker, and so on). A census test keeps the code list and the reference in step.
  4. Read each value kind leniently, in one place. A model spells a value the way its training data did: null for an unset optional, 4 000 for a number, 1. 10. 2026 for a date, ano for a boolean, cs_CZ for a locale. Every kind the wire accepts gets ONE owner that auto-normalizes the spellings carrying a single meaning and returns ONE ask-for-a-fix shape (received, expected, hint) when a spelling carries two: 01/02/2026 and a bare 1,234 are asked about with both readings named, never guessed, because guessing wrong is a wrong date or a factor of a thousand on an instrument. Null and the placeholder encodings are that rule for "absent" and live in the tool factory; the value kinds live in packages/agent-input/: number (a page size clamps with a note), boolean, date (a range bound reads 2020 as its first or last day and 0001-01-01/9999-12-31 as no bound), uuid (the all-zero and example ids are placeholders), filter (" ", "all", "-" mean "not filtering"), vocabulary (a data-owned value such as a court, read through case, diacritics, abbreviations and English names), string list (a lone string is a one-item list; only constrained tokens split on commas), ELI, country, locale, enum. A repaired value returns a note ("Read X as Y") that reaches the caller beside the result. A placeholder in an optional property is absence on a read and an ask on a write, where an optional id can switch update into create. An optional filter read against a data-owned vocabulary (court) never empties a search: a value that names no stored value, or several, is dropped with a warning naming the stored ones. A filter with no such vocabulary yet reads only its placeholders, and an empty page under it carries no_hits_filtered naming the values that would have matched; do not advertise resolution a filter does not do. An opaque token the server issues extends "absent" one step: a client filling every declared property invents a first-call cursor (" ", "0", "start"), so cursorInput reads a value outside the class its encoders emit as no cursor, while a value inside that class still reaches the decoder and fails through invalidCursorResult, which names the restart; restarting a damaged or invented cursor at page one silently would repeat a page the caller already read. Kinds a property's name implies (limit, date_from, date_to) are bound by the factory, so a new tool inherits them. Cover each kind with a property test over its whole spelling class rather than the examples someone happened to write down, and add a guard (an ownership row, a census test) so a new call site cannot parse the kind itself. Never per-tool tolerance code, and never a second reader: two lenient readers of one kind are worse than one strict one, because they disagree.

References Are Read Verbatim

  1. Every sentence must be true of the code. Reference resources and tool descriptions are copied into model context as the complete contract. A promised behaviour the code does not have (a preserved extension, a size limit that is not the enforced one) is a bug, not a docs nit. Render numbers from the constants; type tool names against the registry; keep drift tests.
  2. One workflow resource per workflow. Publish the ordered steps (create, read back, configure, preview, persist) as a resource pointed to from the MCP instructions, and keep the quiz or eval that checks a model understood it.
  3. Decide grammar leniency by evidence. When two independent models write the same form the grammar rejects, that is a product signal: either accept the form or make the reference unambiguous, then re-measure. Do not do both at once.

Name Capabilities By Resource

A capability id is its handler path under apps/api/src/handlers/: <domain>[.<resource>…].<action>. The action is ONE word, either a canonical verb (list, get, create, update, delete) or an entry in the closed DOMAIN_ACTION_VERBS list (apps/api/scripts/lib/capability-catalog.ts; docs/capability-coverage.md renders the current list). A compound action is a nested resource directory: clauses/categories/create.ts, not clauses/categories-create.ts; entities/versions/list.ts, not entities/read-versions.ts. A new domain verb is a reviewed addition to that list; the exporter fails on an unlisted verb and on a listed verb no capability uses, and the capability-domain-action-verbs ratchet holds hyphenated entries at 0.

Guards Make It Stick

  • Registry-wide tests over every tool definition: id schemas, null-optional tolerance, description and reference drift, and a zero-diff capability export.
  • Total companion maps keyed by tool name (as const satisfies Record<ToolName, ...>) for policy, consent, projection, and CLI disposition, so a new tool cannot land without each decision.
  • Compile-time gates in the tool factory (a schema that is not wrapped, an id that is not the shared schema) rather than review discipline.
  • The CLI is generated from the same catalog: a capability whose transport the generator cannot invoke is not advertised anywhere, and generated artifacts are regenerated in order (capability export, then CLI codegen) until the diff is zero.

Existing References

  • Tool factory and boundary normalisation: apps/api/src/mcp/valibot-tool-definition.ts, apps/api/src/mcp/tool-utils.ts
  • One reader per value kind, and its census: packages/agent-input/src/, apps/api/src/lib/agent-input-owner.test.ts
  • Registry-wide guards: apps/api/src/mcp/uuid-id-inputs.test.ts, apps/api/src/mcp/null-optional-inputs.test.ts
  • Warnings census and references: apps/api/src/lib/docx/template-warnings.ts, apps/api/src/mcp/template-workflow-reference.ts
  • Authoring eval: apps/api/evals/template-authoring.ts

These are examples of the mechanisms, not proof that a new tool meets the bar: run the eval.

Version History

  • 0f3714b Current 2026-10-19 03:36

    新增agent-input读取器的宽松拼写解析功能,支持ID、过滤器、列表等类型的共享读取,提升对不可读游标的容忍度。

  • d37ba69 2026-09-27 20:52

    重构能力 ID 命名空间,将复合动作嵌套至资源层级(如 create-versions 改为 versions.create),并统一动词列表规范。

  • e41bf51 2026-09-22 09:02

    修复MCP工具中伪造分页游标的识别问题,统一游标校验逻辑,防止无效游标导致页面重复或无法重启。

  • 7b52e43 2026-09-09 03:27

Same Skill Collection

.agents/skills/click-around/SKILL.md
.agents/skills/conventions-ai/SKILL.md
.agents/skills/conventions-db/SKILL.md
.agents/skills/conventions-i18n/SKILL.md
.agents/skills/conventions-ingestion/SKILL.md
.agents/skills/conventions-mcp/SKILL.md
.agents/skills/conventions-perf/SKILL.md
.agents/skills/conventions-scale/SKILL.md
.agents/skills/conventions-security/SKILL.md
.agents/skills/conventions-use-effect/SKILL.md
.agents/skills/conventions-ux/SKILL.md
.agents/skills/dev/SKILL.md
.agents/skills/finish-pr/SKILL.md
.agents/skills/new-handler/SKILL.md
.agents/skills/open-pr/SKILL.md
.agents/skills/plan/SKILL.md
.agents/skills/product-deep-think/SKILL.md
.agents/skills/product-think/SKILL.md
.agents/skills/rabbit-round/SKILL.md
.agents/skills/regression-hunt/SKILL.md
.agents/skills/security-audit/SKILL.md
.agents/skills/update-deps/SKILL.md
.ai/local-skills/click-around/SKILL.md
.ai/local-skills/conventions-ai/SKILL.md
.ai/local-skills/conventions-db/SKILL.md
.ai/local-skills/conventions-i18n/SKILL.md
.ai/local-skills/conventions-ingestion/SKILL.md
.ai/local-skills/conventions-perf/SKILL.md
.ai/local-skills/conventions-scale/SKILL.md
.ai/local-skills/conventions-security/SKILL.md
.ai/local-skills/conventions-use-effect/SKILL.md
.ai/local-skills/conventions-ux/SKILL.md
.ai/local-skills/dev/SKILL.md
.ai/local-skills/new-handler/SKILL.md
.ai/local-skills/open-pr/SKILL.md
.ai/local-skills/plan/SKILL.md
.ai/local-skills/product-deep-think/SKILL.md
.ai/local-skills/rabbit-round/SKILL.md
.ai/local-skills/security-audit/SKILL.md
.ai/local-skills/update-deps/SKILL.md
.claude/skills/conventions-ai/SKILL.md
.claude/skills/conventions-db/SKILL.md
.claude/skills/conventions-i18n/SKILL.md
.claude/skills/conventions-ingestion/SKILL.md
.claude/skills/conventions-mcp/SKILL.md
.claude/skills/conventions-perf/SKILL.md
.claude/skills/conventions-scale/SKILL.md
.claude/skills/conventions-security/SKILL.md
.claude/skills/conventions-use-effect/SKILL.md

Metadata

Files
0
Version
0f3714b
Hash
9a13a793
Indexed
2026-09-09 03:27

홈 - 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-10-19 10:12
浙ICP备14020137号-1