Qyl.Agents.Generator package is an incremental source generator that transforms [McpServer] classes into fully functional MCP servers at build time.
How It Works
- Extraction — scans for
[McpServer]classes and[Tool]methods - Modeling — builds value-equatable models (incremental generator cache-friendly)
- Generation — emits a single
.g.csfile per server with all dispatch, schema, OTel, and metadata code
Server Declaration
The class must be
partial — the generator adds the IMcpServer
implementation.McpServer Attribute
Tool Attribute
Safety hints are emitted in
tools/list only when non-Unset. ToolHint has three values: Unset (omitted), True, False.
ToolTaskSupport controls whether a tool can return an MCP task instead of an immediate result:
Generated Output
For each[McpServer] class, the generator produces a single .g.cs file containing:
Tool Dispatch
ADispatchToolCallAsync method that routes by tool name using a switch expression:
Parameter Deserialization
Primitives use directJsonElement accessors (AOT-safe). Complex types fall back to JsonSerializer.
JSON Schema
Each tool gets a statics_schema_{MethodName} byte array with the JSON Schema for its input parameters, including types, formats, required fields, descriptions, and enum values.
OpenTelemetry Instrumentation
Every tool call emits:- An
ActivitySource("Qyl.Agents")span withgen_ai.*semantic conventions - A
gen_ai.client.operation.durationhistogram for latency tracking - Error status and
error.typetag on exceptions
SKILL.md
ASkillMd static property with the full SKILL.md content including YAML frontmatter, tool descriptions, and parameter documentation.
LLMS.txt
ALlmsTxt static property with a summary of the server’s capabilities, including tools, resources, and prompts sections.
Resources
Expose read-only data via[Resource]:
Resource Attribute
The generator emits
DispatchResourceReadAsync for URI-based dispatch and GetResourceInfos for resources/list.
Supported return types for resource methods:
Prompts
Expose reusable prompt templates via[Prompt("name")]:
stringreturn → wrapped as a single user-role messagePromptResultreturn → structured messages passed through directly
PromptMessage takes (string role, string content) via constructor. Use the PromptRole constants (User, Assistant, System) for type-safe role values.
The generator emits DispatchPromptAsync and GetPromptInfos for prompts/list and prompts/get. Prompt methods must return string, Task<string>, PromptResult, or Task<PromptResult>.
