Skip to main content

Documentation Index

Fetch the complete documentation index at: https://ancplua.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

The Qyl.Agents.Generator package is an incremental source generator that transforms [McpServer] classes into fully functional MCP servers at build time.

How It Works

  1. Extraction — scans for [McpServer] classes and [Tool] methods
  2. Modeling — builds value-equatable models (incremental generator cache-friendly)
  3. Generation — emits a single .g.cs file per server with all dispatch, schema, OTel, and metadata code

Server Declaration

using Qyl.Agents;

/// <summary>A document search server</summary>
[McpServer]
public partial class DocTools
{
    /// <summary>Search documents by query</summary>
    [Tool]
    public string Search(
        [Description("Query text")] string query,
        int limit = 10) => query;
}
The class must be partial — the generator adds the IMcpServer implementation.

McpServer Attribute

PropertyTypeDefaultDescription
Namestring?Class name, kebab-casedServer name in MCP protocol
Descriptionstring?XML doc summaryServer description
Versionstring?Assembly informational versionSemantic version

Tool Attribute

PropertyTypeDefaultDescription
Namestring?Method name, kebab-casedTool name in MCP protocol
Descriptionstring?XML doc summaryTool description
ReadOnlyToolHintUnsetHint: tool does not modify state
IdempotentToolHintUnsetHint: repeated calls have same effect
DestructiveToolHintUnsetHint: tool may delete or destroy data
OpenWorldToolHintUnsetHint: tool interacts with external systems
TaskSupportToolTaskSupportUnsetDeclares long-running task execution support
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:
ValueWire behavior
UnsetOmitted from tools/list
ForbiddenTask execution is forbidden for this tool
OptionalServer may return a task or an immediate result
RequiredServer always returns a task
[Tool(ReadOnly = ToolHint.True, Idempotent = ToolHint.True)]
public string Search([Description("Query")] string query) => query;

[Tool(TaskSupport = ToolTaskSupport.Optional)]
public Task<string> LongRunningAnalysis([Description("Input")] string data) => /* ... */;

Generated Output

For each [McpServer] class, the generator produces a single .g.cs file containing:

Tool Dispatch

A DispatchToolCallAsync method that routes by tool name using a switch expression:
public async Task<string> DispatchToolCallAsync(
    string toolName,
    JsonElement arguments,
    CancellationToken cancellationToken = default)
{
    return toolName switch
    {
        "search" => await ExecuteTool_SearchAsync(arguments, cancellationToken),
        _ => throw new ArgumentException($"Unknown tool: {toolName}")
    };
}

Parameter Deserialization

Primitives use direct JsonElement accessors (AOT-safe). Complex types fall back to JsonSerializer.
TypeAccessorAOT-safe
stringGetString()Yes
intGetInt32()Yes
boolGetBoolean()Yes
DateTimeOffsetGetDateTimeOffset()Yes
GuidGetGuid()Yes
Urinew Uri(GetString())Yes
EnumsEnum.Parse<T>(GetString())Yes
string[], custom typesJsonSerializer.Deserialize<T>()No

JSON Schema

Each tool gets a static s_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 with gen_ai.* semantic conventions
  • A gen_ai.client.operation.duration histogram for latency tracking
  • Error status and error.type tag on exceptions

SKILL.md

A SkillMd static property with the full SKILL.md content including YAML frontmatter, tool descriptions, and parameter documentation.

LLMS.txt

A LlmsTxt static property with a summary of the server’s capabilities, including tools, resources, and prompts sections.

Resources

Expose read-only data via [Resource]:
[McpServer]
public partial class ConfigServer
{
    [Resource("config://app-settings")]
    public Task<string> GetAppSettings(CancellationToken ct) =>
        File.ReadAllTextAsync("appsettings.json", ct);
}

Resource Attribute

PropertyTypeDefaultDescription
Uristring(required)Resource URI for MCP protocol
Namestring?nullDisplay name for the resource
Descriptionstring?XML doc summaryResource description
MimeTypestring?nullContent MIME type
The generator emits DispatchResourceReadAsync for URI-based dispatch and GetResourceInfos for resources/list. Supported return types for resource methods:
Return typeContent encoding
stringPlain text
Task<string>Plain text
ValueTask<string>Plain text
byte[]Base64-encoded
Task<byte[]>Base64-encoded
ValueTask<byte[]>Base64-encoded

Prompts

Expose reusable prompt templates via [Prompt("name")]:
[McpServer]
public partial class MyServer
{
    /// <summary>Summarize a document</summary>
    [Prompt("summarize")]
    public string Summarize([Description("Text to summarize")] string text) =>
        $"Please summarize the following:\n\n{text}";

    /// <summary>Code review with structured messages</summary>
    [Prompt("review")]
    public PromptResult Review([Description("Code to review")] string code) =>
        new([new(PromptRole.User, $"Review this code:\n\n{code}")]);
}
  • string return → wrapped as a single user-role message
  • PromptResult return → 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>.

Supported Parameter Types

CategoryTypes
Primitivesstring, bool, int, long, double, float, decimal, byte, sbyte, short, ushort, uint, ulong
SpecialDateTimeOffset, DateTime, Guid, Uri
EnumsAny enum type (schema includes allowed values)
NullableT? for all above
ComplexArrays, custom objects (requires JsonSerializer)
ControlCancellationToken (passed through, not in schema)

Supported Return Types

TypeSerialization
voidReturns "null"
stringDirect passthrough
bool"true" / "false"
Numeric typesToString(InvariantCulture)
Task / ValueTaskReturns "null"
Task<T> / ValueTask<T>Same rules as sync T
Complex typesJsonSerializer.Serialize<T>()