| name | mcp-rest-tool-authoring |
| description | Create or update agent-facing tools in this repository's source-generated tool model. Use when a request asks to add, modify, scaffold, refactor, or secure a tool exposed through REST, MCP, or CLI, including provider-specific request/response DTOs, handler classes under `TemplateService.Tools/`, auth attributes, service-layer wiring, capability metadata, or related tests. |
MCP REST CLI Tool Authoring
Overview
Author tools once as typed handlers in TemplateService.Tools/ and let the repository generator emit REST controllers, MCP wrappers, CLI catalog/invoker services, and DI registration. Keep manual changes focused on DTOs, handlers, service logic, auth attributes, tests, and docs.
When provider contracts differ materially, prefer one handler and request DTO per contract shape. Keep specialization at the transport boundary and normalize in the shared service layer unless the business workflow itself also differs materially.
Workflow
- Read
references/repo-patterns.md before editing code. Read docs/specs/AGENT_ENDPOINT_METHODOLOGY.md too when provider contract shape or agent-facing tool choice matters.
- Inspect existing DTOs, handlers, and services with
rg before creating new types.
- Decide whether the request only needs:
- shared DTOs and a shared handler because the contract shape stays materially aligned
- provider-specific DTOs and handlers because fields, enum values, required fields, semantics, output shape, or async lifecycle differ materially
- new or updated DTOs under
TemplateService.Contracts/Models/Requests/ and TemplateService.Contracts/Models/Responses/
- a new or updated handler under
TemplateService.Tools/
- changes to an existing service under
TemplateService.Application/Services/
- capability metadata or example payload updates
- auth metadata via
Authorize or AllowAnonymous
- Implement the request in this order when possible:
- request DTO or DTO family
- response DTO or response family
- service contract and implementation
- tool handler or handler set
- capability metadata and examples
- tests
- docs or notes when the new pattern is durable
- Annotate each handler with:
[Tool(name, route, httpMethod)]
DescriptionAttribute
Authorize or AllowAnonymous when needed
- Make handler descriptions decision-oriented:
- what the tool is best at
- relative cost, quality, or latency if known
- major limitations
- important output characteristics
- when to prefer it over sibling tools
- Do not handwrite controller classes or MCP wrapper methods for normal tool work. The source generator owns those transports.
- Do not handwrite CLI catalogs or CLI invokers for normal tool work. The source generator owns that surface too.
- Keep transport boundaries clean:
- REST stays generated under
Controllers
- MCP stays generated under
Mcp
- CLI metadata and invocation stay generated under
Generated
- business behavior stays in
TemplateService.Application/Services/
- Reuse
ToolAuthorizationPolicies.AuthenticatedTool for API key protected tools unless the task explicitly needs a different policy.
- Validate with:
dotnet build TemplateService.slnx -c Release
dotnet test TemplateService.slnx -c Release
pwsh -File scripts/validate-template.ps1
DTO Rules
- Prefer DTO shapes that remain generator-safe across shared assemblies: either a public constructor matching public properties or a parameterless constructor with writable public properties.
- Use
Mithril.MasTools.EmptyToolRequest for parameterless tools.
- Split DTOs by materially different provider contract shape instead of collecting provider-only optional fields in one generic request.
- Add
DescriptionAttribute to every request property so MCP and Swagger/OpenAPI share the same parameter description source.
- Add validation coverage to every request property via
ValidationAttribute, enum typing, or AllowAnyValueAttribute.
- For positional record requests, keep validation metadata on the constructor parameter (
[param: Required], [param: Range], etc.) and transport/docs metadata on the property target when needed ([property: Description]).
- Enum request properties serialize and bind as enum names, not numeric ordinals; clients may vary casing on input but should still send the textual enum name.
- Enum request properties automatically surface their allowed textual values and any enum-member
DescriptionAttribute text on both MCP and REST docs.
- When writing enum property descriptions or examples, describe the textual values that appear on the wire rather than the enum's underlying integers.
- Prefer enums for stable closed sets that help schema enforcement. Prefer validated strings plus capability metadata for volatile provider-driven values.
- Missing request-property descriptions trigger generator warning
TOOL003.
- Missing request-property validation coverage triggers generator error
TOOL004.
- Custom validation can be added through
IToolRequestValidator<TRequest>; those validators are auto-registered by the generator when implemented in the shared tool assembly.
- Keep DTOs transport-safe and free of service dependencies.
Handler Rules
- Place handlers in
TemplateService.Tools/.
- Implement
IToolHandler<TRequest, TResponse>.
- Prefer explicit names that reveal provider and operation intent when a tool is provider-specific.
- Delegate real behavior to focused services instead of growing handlers into orchestration objects.
- Normalize provider-specific requests below the handler boundary instead of branching in generated transports.
- Keep one tool per file and one primary responsibility per handler.
Auth Rules
- Use
[AllowAnonymous] explicitly for public sample or health-like tools.
- Use
[Authorize(Policy = ToolAuthorizationPolicies.AuthenticatedTool)] for API key protected tools.
- If auth changes the public surface or conventions, update
.env.example, README.md, and decision or note artifacts when appropriate.
Validation Handoff
- Confirm generated transports compile by building the solution, not by editing generated files.
- Check invalid inputs too: REST and MCP should return agent-friendly validation errors with machine-readable
issues.
- When the task is provider-specific or async, add or update tests for contract shape, capability metadata, example payload presence, and pending/completed response metadata as appropriate.
- If the task changes public sample behavior, update integration tests under
TemplateService.Api.Tests/Http/ and add CLI smoke or process coverage when the CLI surface is affected.
- If the task introduces a durable tool-authoring convention, update the relevant note or decision entry.