@@ -36,10 +36,13 @@ The SDK consists of three main packages:
3636- Support both builder patterns and options configuration
3737
3838### JSON Serialization
39- - Use ` System.Text.Json ` for all JSON operations
40- - Use ` McpJsonUtilities.DefaultOptions ` for consistent serialization
41- - Support source generation for Native AOT compatibility
42- - Set ` JsonIgnoreCondition.WhenWritingNull ` for optional properties
39+ - Use ` System.Text.Json ` exclusively for all JSON operations
40+ - Use ` McpJsonUtilities.DefaultOptions ` for consistent serialization settings across the SDK
41+ - Support source generation for Native AOT compatibility via ` McpJsonUtilities ` source generators
42+ - Set ` JsonIgnoreCondition.WhenWritingNull ` for optional properties to minimize payload size
43+ - Use ` JsonSerializerDefaults.Web ` for camelCase property naming
44+ - Protocol types are decorated with ` [JsonSerializable] ` attributes for AOT support
45+ - Custom converters: ` CustomizableJsonStringEnumConverter ` for flexible enum serialization
4346
4447### Async Patterns
4548- All I/O operations should be async
@@ -53,18 +56,38 @@ The SDK consists of three main packages:
5356- Support all standard MCP capabilities (e.g. tools, prompts, resources, sampling)
5457- Implement proper error handling with ` McpException ` and ` McpErrorCode `
5558
59+ ### Error Handling
60+ - Throw ` McpException ` for MCP protocol-level errors with appropriate ` McpErrorCode `
61+ - Use standard error codes: ` InvalidRequest ` , ` MethodNotFound ` , ` InvalidParams ` , ` InternalError `
62+ - Let domain exceptions bubble up and convert to ` InternalError ` at transport boundary
63+ - Include detailed error messages in exception ` Message ` property for debugging
64+ - Errors are automatically converted to JSON-RPC error responses by the server infrastructure
65+
5666## Testing
5767
5868### Test Organization
59- - Unit tests in ` tests/ModelContextProtocol.Tests `
60- - Integration tests in ` tests/ModelContextProtocol.AspNetCore.Tests `
61- - Test helpers in ` tests/Common `
62- - Filter manual tests with ` [Trait("Execution", "Manual")] `
63-
64- ### Test Infrastructure
65- - Use xUnit for all tests
69+ - Unit tests in ` tests/ModelContextProtocol.Tests ` for core functionality
70+ - Integration tests in ` tests/ModelContextProtocol.AspNetCore.Tests ` for HTTP/SSE transports
71+ - Shared test utilities in ` tests/Common/Utils/ `
72+ - Test servers in ` tests/ModelContextProtocol.Test*Server/ ` for integration scenarios
73+ - Filter manual tests with ` [Trait("Execution", "Manual")] ` - these require external dependencies
74+
75+ ### Test Infrastructure and Helpers
76+ - ** LoggedTest** : Base class for tests that need logging output captured to xUnit test output
77+ - Provides ` ILoggerFactory ` and ` ITestOutputHelper ` for test logging
78+ - Use when debugging or when tests need to verify log output
79+ - ** TestServerTransport** : In-memory transport for testing client-server interactions without network I/O
80+ - ** MockLoggerProvider** : For capturing and asserting on log messages
81+ - ** XunitLoggerProvider** : Routes ` ILogger ` output to xUnit's ` ITestOutputHelper `
82+ - ** KestrelInMemoryTransport** (AspNetCore.Tests): In-memory Kestrel connection for HTTP transport testing without network stack
83+
84+ ### Test Best Practices
85+ - Inherit from ` LoggedTest ` for tests needing logging infrastructure
86+ - Use ` TestServerTransport ` for in-memory client-server testing
87+ - Mock external dependencies (filesystem, HTTP clients) rather than calling real services
88+ - Use ` CancellationTokenSource ` with timeouts to prevent hanging tests
89+ - Dispose resources properly (servers, clients, transports) using ` IDisposable ` or ` await using `
6690- Run tests with: ` dotnet test --filter '(Execution!=Manual)' `
67- - Tests should be isolated and not depend on external services (except manual tests)
6891
6992## Build and Development
7093
@@ -75,8 +98,8 @@ The SDK consists of three main packages:
7598- ** Clean** : ` dotnet clean ` or ` make clean `
7699
77100### SDK Requirements
78- - The project uses .NET SDK preview versions
79- - Target frameworks: .NET 8 .0, .NET 9.0, .NET Standard 2.0
101+ - The project currently uses .NET SDK 10.0 RC (this is temporary while waiting for .NET 10 to go GA)
102+ - Target frameworks: .NET 10 .0, .NET 9.0, .NET 8 .0, .NET Standard 2.0
80103- Support Native AOT compilation
81104
82105### Project Structure
@@ -86,10 +109,40 @@ The SDK consists of three main packages:
86109- Documentation: ` docs/ `
87110- Build artifacts: ` artifacts/ ` (not committed)
88111
89- ## Common Patterns
90-
91- ### MCP Server Tools
92- Tools are exposed using attributes:
112+ ## Architecture and Design Patterns
113+
114+ ### Server Implementation Architecture
115+ - ** McpServer** is the core server implementation in ` ModelContextProtocol.Core/Server/ `
116+ - ** IMcpServerBuilder** pattern provides fluent API for configuring servers via DI
117+ - Server primitives (tools, prompts, resources) are discovered via reflection using attributes
118+ - Support both attribute-based registration (` WithTools<T>() ` ) and instance-based (` WithTools(target) ` )
119+ - Use ` McpServerFactory ` to create server instances with configured options
120+
121+ ### Tool/Prompt/Resource Discovery
122+ - Tools, prompts, and resources use attribute-based discovery: ` [McpServerTool] ` , ` [McpServerPrompt] ` , ` [McpServerResource] `
123+ - Type-level attributes (` [McpServerToolType] ` , etc.) mark classes containing server primitives
124+ - Discovery supports both static and instance methods (public and non-public)
125+ - For Native AOT compatibility, use generic ` WithTools<T>() ` methods instead of reflection-based variants
126+ - ` AIFunctionMcpServerTool ` , ` AIFunctionMcpServerPrompt ` , and ` AIFunctionMcpServerResource ` wrap ` AIFunction ` for integration with Microsoft.Extensions.AI
127+
128+ ### Request Processing Pipeline
129+ - Requests flow through ` McpServer.Methods.cs ` which handles JSON-RPC message routing
130+ - Use ` McpRequestFilter ` for cross-cutting concerns (logging, auth, validation)
131+ - ` RequestContext ` provides access to current request state and services
132+ - ` RequestServiceProvider ` enables scoped dependency injection per request
133+ - Filters can short-circuit request processing or transform requests/responses
134+
135+ ### Transport Layer Abstraction
136+ - Transport implementations handle message serialization and connection management
137+ - Core transports: ` StdioServerTransport ` , ` StreamServerTransport ` , ` SseResponseStreamTransport ` , ` StreamableHttpServerTransport `
138+ - Transports must implement bidirectional JSON-RPC message exchange
139+ - SSE (Server-Sent Events) transport for unidirectional server→client streaming
140+ - Streamable HTTP for request/response with streamed progress updates
141+
142+ ## Implementation Patterns
143+
144+ ### Tool Implementation
145+ Tools are methods marked with ` [McpServerTool] ` :
93146``` csharp
94147[McpServerToolType ]
95148public class MyTools
@@ -99,13 +152,18 @@ public class MyTools
99152 [Description (" Parameter description" )] string param ,
100153 CancellationToken cancellationToken )
101154 {
102- // Implementation
155+ // Implementation - use Description attributes for parameter documentation
156+ // Return string, TextContent, ImageContent, EmbeddedResource, or arrays of these
103157 }
104158}
105159```
160+ - Tools support dependency injection in constructors for instance methods
161+ - Parameters are automatically deserialized from JSON using ` System.Text.Json `
162+ - Use ` [Description] ` attributes on parameters to generate tool schemas
163+ - Return types: ` string ` , ` TextContent ` , ` ImageContent ` , ` EmbeddedResource ` , or collections of content types
106164
107- ### MCP Server Prompts
108- Prompts are exposed similarly :
165+ ### Prompt Implementation
166+ Prompts return ` ChatMessage ` or arrays thereof :
109167``` csharp
110168[McpServerPromptType ]
111169public static class MyPrompts
@@ -115,17 +173,45 @@ public static class MyPrompts
115173 new (ChatRole .User , $" Prompt template: {content }" );
116174}
117175```
176+ - Prompts can accept arguments to customize generated messages
177+ - Return single ` ChatMessage ` or ` ChatMessage[] ` for multi-turn prompts
178+ - Use ` ChatRole.User ` , ` ChatRole.Assistant ` , or ` ChatRole.System ` appropriately
118179
119- ### Client Usage
180+ ### Resource Implementation
181+ Resources provide access to data with URI templates:
120182``` csharp
121- var client = await McpClient .CreateAsync (
122- new StdioClientTransport (new () { Command = " ..." , Arguments = [.. .] }),
123- clientOptions : new () { /* ... */ },
124- loggerFactory : loggerFactory );
183+ [McpServerResourceType ]
184+ public class MyResources
185+ {
186+ [McpServerResource (" file:///{path}" ), Description (" Reads file content" )]
187+ public static async Task <string > ReadFile (string path , CancellationToken cancellationToken )
188+ {
189+ // Resource URI matching uses UriTemplate syntax
190+ // Extract parameters from URI and return content
191+ }
192+ }
193+ ```
194+ - Use URI templates to define resource paths with parameters
195+ - Resources support subscription for dynamic content updates
196+ - Return content types similar to tools
125197
126- var tools = await client .ListToolsAsync ();
127- var result = await client .CallToolAsync (" tool-name" , arguments , cancellationToken );
198+ ### Filters and Middleware
199+ Implement ` McpRequestFilter ` for request/response interception:
200+ ``` csharp
201+ public class LoggingFilter : McpRequestFilter
202+ {
203+ public override async ValueTask InvokeAsync (RequestContext context , Func <ValueTask > next )
204+ {
205+ // Pre-processing
206+ await next (); // Call next filter or handler
207+ // Post-processing
208+ }
209+ }
128210```
211+ - Filters execute in registration order
212+ - Can short-circuit by not calling ` next() `
213+ - Access request context, services, and can modify responses
214+ - Use for cross-cutting concerns: logging, auth, validation, caching
129215
130216## OpenTelemetry Integration
131217
0 commit comments