expose-a-use-case
Skill1 starsChanged 7 days agoMITView on GitHub
How to put an Application use case on the MCP server as a tool, resource or prompt - partial static methods with McpServer attributes, XML comments that become the descriptions, result models, completions and tests. Use when adding or changing a tool, resource or prompt on this MCP server.
In this repository40 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- add-a-use-caseSkill
- api-conventionsSkill
- branches-and-pull-requestsSkill
- cancellationSkill
- ci-for-your-solutionSkill
- ci-pipelineSkill
- clean-architecture-layersSkill
- configuration-and-environmentsSkill
- coverageSkill
- csharp-house-styleSkill
- data-access-ef-coreSkill
- database-migrationsSkill
- docker-and-composeSkill
- docs-and-voiceSkill
- errors-and-exceptionsSkill
- family-syncSkill
- health-checksSkill
- integration-testsSkill
- json-serializationSkill
- mapping-with-mapperlySkill
- mcp-inspectorSkill
- mediatorSkill
- optional-token-authSkill
- packages-and-dependenciesSkill
- pagingSkill
- presentation-integration-testsSkill
- releasesSkill
- sample-dataSkill
- security-findingsSkill
- serilogSkill
- telemetrySkill
- template-authoringSkill
- test-designSkill
- time-providerSkill
- unit-testsSkill
- validationSkill
- writing-a-skillSkill
- xml-docs-and-openapiSkill
The file
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 0 are distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 26
Add the use case first (add-a-use-case).
- Very specific: line 29
Write the method with sender and cancellationToken first, then required inputs, then optional ones with defaults.
- Very specific: line 30
Document it: <summary> saying what it does, what it returns and which tool to call first.
- Very specific: line 33
Update the server instructions in WebApplicationBuilderExtensions if the model needs to know the new thing exists (api-conventions).
- Very specific: line 34
Test it twice: a unit test calling the static method with a faked ISender (tests/Presentation.Tests.Unit/Tools/), and an integration test …
- Very specific: line 59
Write [Description] attributes on tool, resource or prompt methods or their parameters.
- Very specific: line 60
Document sender or the cancellation token.
- Very specific: line 63
Add a tool for every query.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Expose a use case (MCP)
The rule
The server offers three kinds of thing, each in its own folder of src/Presentation, one public static partial class per feature:
| Kind | Folder | Attribute | Returns |
| Tool, something the model calls | Tools/ | [McpServerToolType] on the class, [McpServerTool(...)] on the method | A result model from Models/, as structured content |
| Resource, something the client reads by URI | Resources/ | [McpServerResourceType], [McpServerResource(UriTemplate = ...)] | A JSON string from McpSerializer.Serialize |
| Prompt, a ready-made request the user picks | Prompts/ | [McpServerPromptType], [McpServerPrompt(...)] | A GetPromptResult |
Each method is public static async partial (or public static partial with no awaits). The MCP SDK's source generator turns the method's XML <summary> and <param> comments into the [Description] attributes the model reads, so the comments are the documentation. Methods take ISender sender and CancellationToken cancellationToken, build the Application request, send it and map the result. They contain no rules: validation and not-found come from Application, and the error filters turn them into MCP errors (api-conventions).
The SDK finds every class in the assembly (WithToolsFromAssembly, WithResourcesFromAssembly, WithPromptsFromAssembly), so a new class needs no registration.
Steps
- Add the use case first (
add-a-use-case). - Pick the kind: a tool when the model should decide to call it, a resource when the client reads a known thing by id or a fixed list such as
movies://top-rated, a prompt when a person starts a task. - Choose the name, title and annotations for a tool (
api-conventions). - Write the method with
senderandcancellationTokenfirst, then required inputs, then optional ones with defaults. - Document it:
<summary>saying what it does, what it returns and which tool to call first; a<param>for every input exceptsenderand the token, with allowed values and where to find ids. Put the XML comment above the attributes. - Return a result model from
src/Presentation/Models/(records with[property: Description], because the output schema reads attributes), mapped inResultMapper. Add new models toAppJsonSerializerContext(json-serialization). - Build a prompt's messages with
PromptContent, and embed the movie or author it's about when you can find one. A prompt argument that names a movie or author gets suggestions fromCompletions/CompletionHandler.cs; add its name there. So does a prompt'smovieId, and the id in a resource template, which suggest ids by their first characters or the title or name they belong to. - Update the server instructions in
WebApplicationBuilderExtensionsif the model needs to know the new thing exists (api-conventions). - Test it twice: a unit test calling the static method with a faked
ISender(tests/Presentation.Tests.Unit/Tools/), and an integration test through the MCP client (presentation-integration-tests). Add a tool to the list inToolListTests.
Example
// src/Presentation/Tools/MovieTools.cs
/// <summary>Get one movie with its review count, average stars and every review, including each author's name.</summary>
/// <param name="movieId">The movie's id (a GUID). Use movies_search to find it.</param>
[McpServerTool(Name = "movies_get", Title = "Get movie", ReadOnly = true, Idempotent = true, OpenWorld = false, UseStructuredContent = true)]
public static async partial Task<MovieResult> GetMovie(
ISender sender,
Guid movieId,
CancellationToken cancellationToken)
{
var movie = await sender.Send(new Queries.GetMovieById.GetMovieByIdQuery
{
Id = movieId
}, cancellationToken);
return movie.ToResult(includeReviews: true);
}Don't
- Write
[Description]attributes on tool, resource or prompt methods or their parameters. Write XML comments and keep the methodpartial. - Document
senderor the cancellation token. They aren't arguments the model sees. - Return Application entities from a tool. Return a result model.
- Catch exceptions in a tool. The filters do it.
- Add a tool for every query. Six tools cover the jobs a model has; extend one before adding another (
api-conventions).
Check
dotnet build # MCP002 warns when a documented method isn't partial
dotnet test tests/Presentation.Tests.Unit
dotnet test tests/Presentation.Tests.IntegrationDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

