├── .config
└── dotnet-tools.json
├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ ├── ci-build-test.yml
│ ├── ci-code-coverage.yml
│ ├── docs.yml
│ ├── markdown-link-check.yml
│ ├── release.md
│ └── release.yml
├── .gitignore
├── Directory.Build.props
├── Directory.Packages.props
├── LICENSE
├── Makefile
├── ModelContextProtocol.slnx
├── Open.snk
├── README.md
├── SECURITY.md
├── THIRD-PARTY-NOTICES.txt
├── docs
├── docfx.json
├── images
│ ├── favicon.ico
│ └── mcp.svg
├── index.md
└── toc.yml
├── global.json
├── logo.png
├── nuget.config
├── samples
├── AspNetCoreSseServer
│ ├── AspNetCoreSseServer.csproj
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Tools
│ │ ├── EchoTool.cs
│ │ └── SampleLlmTool.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
├── ChatWithTools
│ ├── ChatWithTools.csproj
│ └── Program.cs
├── EverythingServer
│ ├── EverythingServer.csproj
│ ├── LoggingUpdateMessageSender.cs
│ ├── Program.cs
│ ├── Prompts
│ │ ├── ComplexPromptType.cs
│ │ └── SimplePromptType.cs
│ ├── ResourceGenerator.cs
│ ├── Resources
│ │ └── SimpleResourceType.cs
│ ├── SubscriptionMessageSender.cs
│ └── Tools
│ │ ├── AddTool.cs
│ │ ├── AnnotatedMessageTool.cs
│ │ ├── EchoTool.cs
│ │ ├── LongRunningTool.cs
│ │ ├── PrintEnvTool.cs
│ │ ├── SampleLlmTool.cs
│ │ └── TinyImageTool.cs
├── QuickstartClient
│ ├── Program.cs
│ └── QuickstartClient.csproj
├── QuickstartWeatherServer
│ ├── Program.cs
│ ├── QuickstartWeatherServer.csproj
│ └── Tools
│ │ ├── HttpClientExt.cs
│ │ └── WeatherTools.cs
└── TestServerWithHosting
│ ├── Program.cs
│ ├── TestServerWithHosting.csproj
│ └── Tools
│ ├── EchoTool.cs
│ └── SampleLlmTool.cs
├── src
├── Common
│ ├── Polyfills
│ │ └── System
│ │ │ ├── Collections
│ │ │ └── Generic
│ │ │ │ └── CollectionExtensions.cs
│ │ │ ├── Diagnostics
│ │ │ └── CodeAnalysis
│ │ │ │ ├── DynamicallyAccessedMemberTypes.cs
│ │ │ │ ├── DynamicallyAccessedMembersAttribute.cs
│ │ │ │ ├── NullableAttributes.cs
│ │ │ │ ├── RequiresDynamicCodeAttribute.cs
│ │ │ │ ├── RequiresUnreferencedCode.cs
│ │ │ │ ├── SetsRequiredMembersAttribute.cs
│ │ │ │ └── UnconditionalSuppressMessageAttribute.cs
│ │ │ ├── IO
│ │ │ ├── StreamExtensions.cs
│ │ │ ├── TextReaderExtensions.cs
│ │ │ └── TextWriterExtensions.cs
│ │ │ ├── Net
│ │ │ └── Http
│ │ │ │ └── HttpClientExtensions.cs
│ │ │ ├── PasteArguments.cs
│ │ │ ├── Runtime
│ │ │ └── CompilerServices
│ │ │ │ ├── CallerArgumentExpressionAttribute.cs
│ │ │ │ ├── CompilerFeatureRequiredAttribute.cs
│ │ │ │ ├── DefaultInterpolatedStringHandler.cs
│ │ │ │ ├── IsExternalInit.cs
│ │ │ │ └── RequiredMemberAttribute.cs
│ │ │ └── Threading
│ │ │ ├── CancellationTokenSourceExtensions.cs
│ │ │ ├── Channels
│ │ │ └── ChannelExtensions.cs
│ │ │ ├── ForceYielding.cs
│ │ │ └── Tasks
│ │ │ └── TaskExtensions.cs
│ └── Throw.cs
├── Directory.Build.props
├── ModelContextProtocol.AspNetCore
│ ├── HttpMcpServerBuilderExtensions.cs
│ ├── HttpMcpSession.cs
│ ├── HttpServerTransportOptions.cs
│ ├── IdleTrackingBackgroundService.cs
│ ├── McpEndpointRouteBuilderExtensions.cs
│ ├── ModelContextProtocol.AspNetCore.csproj
│ ├── README.md
│ ├── SseHandler.cs
│ ├── Stateless
│ │ ├── StatelessSessionId.cs
│ │ ├── StatelessSessionIdJsonContext.cs
│ │ └── UserIdClaim.cs
│ └── StreamableHttpHandler.cs
├── ModelContextProtocol.Core
│ ├── AIContentExtensions.cs
│ ├── Client
│ │ ├── AutoDetectingClientSessionTransport.cs
│ │ ├── HttpTransportMode.cs
│ │ ├── IClientTransport.cs
│ │ ├── IMcpClient.cs
│ │ ├── McpClient.cs
│ │ ├── McpClientExtensions.cs
│ │ ├── McpClientFactory.cs
│ │ ├── McpClientOptions.cs
│ │ ├── McpClientPrompt.cs
│ │ ├── McpClientResource.cs
│ │ ├── McpClientResourceTemplate.cs
│ │ ├── McpClientTool.cs
│ │ ├── SseClientSessionTransport.cs
│ │ ├── SseClientTransport.cs
│ │ ├── SseClientTransportOptions.cs
│ │ ├── StdioClientSessionTransport.cs
│ │ ├── StdioClientTransport.cs
│ │ ├── StdioClientTransportOptions.cs
│ │ ├── StreamClientSessionTransport.cs
│ │ ├── StreamClientTransport.cs
│ │ └── StreamableHttpClientSessionTransport.cs
│ ├── CustomizableJsonStringEnumConverter.cs
│ ├── Diagnostics.cs
│ ├── IMcpEndpoint.cs
│ ├── McpEndpoint.cs
│ ├── McpEndpointExtensions.cs
│ ├── McpErrorCode.cs
│ ├── McpException.cs
│ ├── McpJsonUtilities.cs
│ ├── McpSession.cs
│ ├── ModelContextProtocol.Core.csproj
│ ├── NopProgress.cs
│ ├── NotificationHandlers.cs
│ ├── ProcessHelper.cs
│ ├── ProgressNotificationValue.cs
│ ├── Protocol
│ │ ├── Annotations.cs
│ │ ├── Argument.cs
│ │ ├── BlobResourceContents.cs
│ │ ├── CallToolRequestParams.cs
│ │ ├── CallToolResponse.cs
│ │ ├── CancelledNotification.cs
│ │ ├── ClientCapabilities.cs
│ │ ├── CompleteContext.cs
│ │ ├── CompleteRequestParams.cs
│ │ ├── CompleteResult.cs
│ │ ├── Completion.cs
│ │ ├── CompletionsCapability.cs
│ │ ├── Content.cs
│ │ ├── ContextInclusion.cs
│ │ ├── CreateMessageRequestParams.cs
│ │ ├── CreateMessageResult.cs
│ │ ├── ElicitRequestParams.cs
│ │ ├── ElicitResult.cs
│ │ ├── ElicitationCapability.cs
│ │ ├── EmptyResult.cs
│ │ ├── GetPromptRequestParams.cs
│ │ ├── GetPromptResult.cs
│ │ ├── ITransport.cs
│ │ ├── Implementation.cs
│ │ ├── InitializeRequestParams.cs
│ │ ├── InitializeResult.cs
│ │ ├── JsonRpcError.cs
│ │ ├── JsonRpcErrorDetail.cs
│ │ ├── JsonRpcMessage.cs
│ │ ├── JsonRpcMessageWithId.cs
│ │ ├── JsonRpcNotification.cs
│ │ ├── JsonRpcRequest.cs
│ │ ├── JsonRpcResponse.cs
│ │ ├── ListPromptsRequestParams.cs
│ │ ├── ListPromptsResult.cs
│ │ ├── ListResourceTemplatesRequestParams.cs
│ │ ├── ListResourceTemplatesResult.cs
│ │ ├── ListResourcesRequestParams.cs
│ │ ├── ListResourcesResult.cs
│ │ ├── ListRootsRequestParams.cs
│ │ ├── ListRootsResult.cs
│ │ ├── ListToolsRequestParams.cs
│ │ ├── ListToolsResult.cs
│ │ ├── LoggingCapability.cs
│ │ ├── LoggingLevel.cs
│ │ ├── LoggingMessageNotificationParams.cs
│ │ ├── ModelHint.cs
│ │ ├── ModelPreferences.cs
│ │ ├── NotificationMethods.cs
│ │ ├── PaginatedRequest.cs
│ │ ├── PaginatedResult.cs
│ │ ├── PingResult.cs
│ │ ├── ProgressNotification.cs
│ │ ├── ProgressToken.cs
│ │ ├── Prompt.cs
│ │ ├── PromptArgument.cs
│ │ ├── PromptMessage.cs
│ │ ├── PromptsCapability.cs
│ │ ├── ReadResourceRequestParams.cs
│ │ ├── ReadResourceResult.cs
│ │ ├── Reference.cs
│ │ ├── RequestId.cs
│ │ ├── RequestMethods.cs
│ │ ├── RequestParams.cs
│ │ ├── RequestParamsMetadata.cs
│ │ ├── Resource.cs
│ │ ├── ResourceContents.cs
│ │ ├── ResourceTemplate.cs
│ │ ├── ResourceUpdatedNotificationParams.cs
│ │ ├── ResourcesCapability.cs
│ │ ├── Role.cs
│ │ ├── Root.cs
│ │ ├── RootsCapability.cs
│ │ ├── SamplingCapability.cs
│ │ ├── SamplingMessage.cs
│ │ ├── ServerCapabilities.cs
│ │ ├── SetLevelRequestParams.cs
│ │ ├── SubscribeRequestParams.cs
│ │ ├── TextResourceContents.cs
│ │ ├── Tool.cs
│ │ ├── ToolAnnotations.cs
│ │ ├── ToolsCapability.cs
│ │ ├── TransportBase.cs
│ │ └── UnsubscribeRequestParams.cs
│ ├── README.md
│ ├── RequestHandlers.cs
│ ├── SemaphoreSlimExtensions.cs
│ ├── Server
│ │ ├── AIFunctionMcpServerPrompt.cs
│ │ ├── AIFunctionMcpServerResource.cs
│ │ ├── AIFunctionMcpServerTool.cs
│ │ ├── DelegatingMcpServerPrompt.cs
│ │ ├── DelegatingMcpServerResource.cs
│ │ ├── DelegatingMcpServerTool.cs
│ │ ├── DestinationBoundMcpServer.cs
│ │ ├── IMcpServer.cs
│ │ ├── IMcpServerPrimitive.cs
│ │ ├── McpServer.cs
│ │ ├── McpServerExtensions.cs
│ │ ├── McpServerFactory.cs
│ │ ├── McpServerOptions.cs
│ │ ├── McpServerPrimitiveCollection.cs
│ │ ├── McpServerPrompt.cs
│ │ ├── McpServerPromptAttribute.cs
│ │ ├── McpServerPromptCreateOptions.cs
│ │ ├── McpServerPromptTypeAttribute.cs
│ │ ├── McpServerResource.cs
│ │ ├── McpServerResourceAttribute.cs
│ │ ├── McpServerResourceCreateOptions.cs
│ │ ├── McpServerResourceTypeAttribute.cs
│ │ ├── McpServerTool.cs
│ │ ├── McpServerToolAttribute.cs
│ │ ├── McpServerToolCreateOptions.cs
│ │ ├── McpServerToolTypeAttribute.cs
│ │ ├── RequestContext.cs
│ │ ├── SseResponseStreamTransport.cs
│ │ ├── SseWriter.cs
│ │ ├── StdioServerTransport.cs
│ │ ├── StreamServerTransport.cs
│ │ ├── StreamableHttpPostTransport.cs
│ │ └── StreamableHttpServerTransport.cs
│ ├── TokenProgress.cs
│ └── UriTemplate.cs
└── ModelContextProtocol
│ ├── DefaultMcpServerBuilder.cs
│ ├── IMcpServerBuilder.cs
│ ├── McpServerBuilderExtensions.cs
│ ├── McpServerHandlers.cs
│ ├── McpServerOptionsSetup.cs
│ ├── McpServerServiceCollectionExtensions.cs
│ ├── ModelContextProtocol.csproj
│ └── SingleSessionMcpServerHostedService.cs
└── tests
├── Common
└── Utils
│ ├── DelegatingTestOutputHelper.cs
│ ├── LoggedTest.cs
│ ├── MockHttpHandler.cs
│ ├── MockLoggerProvider.cs
│ ├── TestServerTransport.cs
│ └── XunitLoggerProvider.cs
├── ModelContextProtocol.AspNetCore.Tests
├── GlobalUsings.cs
├── HttpServerIntegrationTests.cs
├── MapMcpSseTests.cs
├── MapMcpStatelessTests.cs
├── MapMcpStreamableHttpTests.cs
├── MapMcpTests.cs
├── ModelContextProtocol.AspNetCore.Tests.csproj
├── SseIntegrationTests.cs
├── SseServerIntegrationTestFixture.cs
├── SseServerIntegrationTests.cs
├── StatelessServerIntegrationTests.cs
├── StatelessServerTests.cs
├── StreamableHttpClientConformanceTests.cs
├── StreamableHttpServerConformanceTests.cs
├── StreamableHttpServerIntegrationTests.cs
└── Utils
│ ├── KestrelInMemoryConnection.cs
│ ├── KestrelInMemoryTest.cs
│ └── KestrelInMemoryTransport.cs
├── ModelContextProtocol.TestServer
├── ModelContextProtocol.TestServer.csproj
└── Program.cs
├── ModelContextProtocol.TestSseServer
├── ModelContextProtocol.TestSseServer.csproj
├── Program.cs
└── Properties
│ └── launchSettings.json
└── ModelContextProtocol.Tests
├── Client
├── McpClientExtensionsTests.cs
├── McpClientFactoryTests.cs
└── McpClientResourceTemplateTests.cs
├── ClientIntegrationTestFixture.cs
├── ClientIntegrationTests.cs
├── ClientServerTestBase.cs
├── Configuration
├── McpServerBuilderExtensionsHandlerTests.cs
├── McpServerBuilderExtensionsPromptsTests.cs
├── McpServerBuilderExtensionsResourcesTests.cs
├── McpServerBuilderExtensionsToolsTests.cs
├── McpServerBuilderExtensionsTransportsTests.cs
└── McpServerScopedTests.cs
├── DiagnosticTests.cs
├── DockerEverythingServerTests.cs
├── EverythingSseServerFixture.cs
├── GlobalUsings.cs
├── McpJsonUtilitiesTests.cs
├── ModelContextProtocol.Tests.csproj
├── Protocol
├── CancellationTests.cs
├── NotificationHandlerTests.cs
├── ProtocolTypeTests.cs
└── RequestIdTests.cs
├── Server
├── McpServerDelegatesTests.cs
├── McpServerFactoryTests.cs
├── McpServerLoggingLevelTests.cs
├── McpServerPromptTests.cs
├── McpServerResourceTests.cs
├── McpServerTests.cs
└── McpServerToolTests.cs
├── StdioServerIntegrationTests.cs
├── TestAttributes.cs
└── Transport
├── SseClientTransportAutoDetectTests.cs
├── SseClientTransportTests.cs
├── SseResponseStreamTransportTests.cs
├── StdioClientTransportTests.cs
└── StdioServerTransportTests.cs
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "docfx": {
6 | "version": "2.78.3",
7 | "commands": [
8 | "docfx"
9 | ],
10 | "rollForward": false
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Remove the line below if you want to inherit .editorconfig settings from higher directories
2 | root = true
3 |
4 | # C# files
5 | [*.cs]
6 |
7 | # Compiler
8 | dotnet_diagnostic.CS1998.severity = suggestion # CS1998: Missing awaits
9 |
10 | # Code Analysis
11 | dotnet_diagnostic.CA1002.severity = none # CA1002: Do not expose generic lists
12 | dotnet_diagnostic.CA1031.severity = none # CA1031: Do not catch general exception types
13 | dotnet_diagnostic.CA1054.severity = none # CA1054: URI-like parameters should not be strings
14 | dotnet_diagnostic.CA1056.severity = none # CA1056: URI-like properties should not be strings
15 | dotnet_diagnostic.CA1062.severity = suggestion # CA1062: Validate arguments of public methods
16 | dotnet_diagnostic.CA1510.severity = suggestion # CA1510: Use ArgumentNullException throw helper
17 | dotnet_diagnostic.CA1849.severity = suggestion # CA1849: Call async methods when in an async method
18 | dotnet_diagnostic.CA2000.severity = suggestion # CA2000: Dispose objects before losing scope
19 | dotnet_diagnostic.CA2227.severity = suggestion # CA2227: Collection properties should be read only
20 | dotnet_diagnostic.CA2249.severity = suggestion # CA2249: Use 'string.Contains' instead of 'string.IndexOf'
21 | dotnet_diagnostic.CA1819.severity = suggestion # CA1819: Properties should not return arrays
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set default behavior to automatically normalize line endings.
2 | * text=auto
3 |
4 | *.doc diff=astextplain
5 | *.DOC diff=astextplain
6 | *.docx diff=astextplain
7 | *.DOCX diff=astextplain
8 | *.dot diff=astextplain
9 | *.DOT diff=astextplain
10 | *.pdf diff=astextplain
11 | *.PDF diff=astextplain
12 | *.rtf diff=astextplain
13 | *.RTF diff=astextplain
14 |
15 | *.jpg binary
16 | *.png binary
17 | *.gif binary
18 |
19 | *.lss text
20 |
21 | # Force bash scripts to always use lf line endings so that if a repo is accessed
22 | # in Unix via a file share from Windows, the scripts will work.
23 | *.in text eol=lf
24 | *.sh text eol=lf
25 |
26 | # Likewise, force cmd and batch scripts to always use crlf
27 | *.cmd text eol=crlf
28 | *.bat text eol=crlf
29 |
30 | *.cs text diff=csharp
31 | *.vb text
32 | *.resx text
33 | *.c text
34 | *.cpp text
35 | *.cxx text
36 | *.h text
37 | *.hxx text
38 | *.py text
39 | *.rb text
40 | *.java text
41 | *.html text
42 | *.htm text
43 | *.css text
44 | *.scss text
45 | *.sass text
46 | *.less text
47 | *.js text
48 | *.lisp text
49 | *.clj text
50 | *.sql text
51 | *.php text
52 | *.lua text
53 | *.m text
54 | *.asm text
55 | *.erl text
56 | *.fs text
57 | *.fsx text
58 | *.hs text
59 |
60 | *.csproj text
61 | *.vbproj text
62 | *.fsproj text
63 | *.dbproj text
64 | *.sln text eol=crlf
65 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: Publish Docs
2 |
3 | on:
4 | release:
5 | types: [published]
6 | workflow_dispatch:
7 |
8 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
9 | permissions:
10 | contents: read
11 | pages: write
12 | id-token: write # Required for actions/deploy-pages
13 |
14 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
15 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
16 | concurrency:
17 | group: "pages"
18 | cancel-in-progress: false
19 |
20 | jobs:
21 | publish-docs:
22 | # Only publish from the modelcontextprotocol/csharp-sdk repository
23 | if: ${{ github.repository == 'modelcontextprotocol/csharp-sdk' }}
24 | environment:
25 | name: github-pages
26 | url: ${{ steps.deployment.outputs.page_url }}
27 | runs-on: ubuntu-latest
28 | steps:
29 | - name: Checkout
30 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
31 |
32 | - name: .NET Setup
33 | uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
34 | with:
35 | dotnet-version: 9.x
36 |
37 | - name: Generate documentation
38 | run: make generate-docs
39 |
40 | - name: Upload Pages artifact
41 | uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
42 | with:
43 | path: 'artifacts/_site'
44 |
45 | - name: Deploy to GitHub Pages
46 | id: deployment
47 | uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
48 |
--------------------------------------------------------------------------------
/.github/workflows/markdown-link-check.yml:
--------------------------------------------------------------------------------
1 | name: Check Markdown links
2 |
3 | on:
4 | push:
5 | branches: [ "main" ]
6 | paths: "**.md"
7 | pull_request:
8 | branches: [ "main" ]
9 | paths: "**.md"
10 |
11 | permissions:
12 | contents: read
13 |
14 | jobs:
15 | markdown-link-check:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Checkout
19 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
20 |
21 | - name: Markup Link Checker (mlc)
22 | uses: becheran/mlc@c925f90a9a25e16e4c4bfa29058f6f9ffa9f0d8c # v0.21.0
23 | with:
24 | # Ignore external links that result in 403 errors during CI. Do not warn for redirects where we want to keep the vanity URL in the markdown or for GitHub links that redirect to the login.
25 | args: --ignore-links "https://www.anthropic.com/*,https://hackerone.com/anthropic-vdp/*" --do-not-warn-for-redirect-to "https://modelcontextprotocol.io/*,https://github.com/login?*" ./
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Cake tools
2 | /[Tt]ools/
3 |
4 | # Build output
5 | [Bb]uildArtifacts/
6 | # Build results
7 | [Dd]ebug/
8 | [Rr]elease/
9 | x64/
10 | x86/
11 | [Aa][Rr][Mm]/
12 | [Aa][Rr][Mm]64/
13 | bld/
14 | [Bb]in/
15 | [Oo]bj/
16 | [Ll]og/
17 | [Ll]ogs/
18 |
19 | # Visual Studio files
20 | .vs/
21 | *.user
22 | *.userosscache
23 | *.sln.docstates
24 | *.userprefs
25 |
26 | # ReSharper
27 | _ReSharper*/
28 | *.[Rr]e[Ss]harper
29 | *.DotSettings.user
30 |
31 | # NuGet
32 | *.nupkg
33 | *.snupkg
34 | **/packages/*
35 | !**/packages/build/
36 |
37 | # MSTest test Results
38 | [Tt]est[Rr]esult*/
39 | [Bb]uild[Ll]og.*
40 |
41 | # .NET Core
42 | project.lock.json
43 | project.fragment.lock.json
44 | artifacts/
45 |
46 | # VS Code files
47 | .vscode/*
48 | !.vscode/settings.json
49 | !.vscode/tasks.json
50 | !.vscode/launch.json
51 | !.vscode/extensions.json
52 | *.code-workspace
53 |
54 | # Local History for Visual Studio Code
55 | .history/
56 |
57 | # Windows image file caches
58 | Thumbs.db
59 | ehthumbs.db
60 |
61 | # Folder config file
62 | Desktop.ini
63 |
64 | # Recycle Bin used on file shares
65 | $RECYCLE.BIN/
66 |
67 | # DotCover is a Code Coverage Tool
68 | *.dotCover
69 |
70 | # NCrunch
71 | _NCrunch_*
72 | .*crunch*.local.xml
73 | nCrunchTemp_*
74 |
75 | *.orig
76 |
77 | # Auto-generated documentation
78 | docs/_site
79 | docs/api
80 |
81 | # Rider
82 | .idea/
83 | .idea_modules/
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 13
4 | true
5 | enable
6 | enable
7 | false
8 | false
9 |
10 |
11 |
12 | $([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)'))
13 | $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'artifacts'))
14 | $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'obj'))
15 | $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'bin'))
16 | $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'TestResults', '$(Configuration)'))
17 | $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'packages', '$(Configuration)'))
18 | $(MSBuildProjectName)
19 |
20 | $([System.IO.Path]::GetFullPath('$(ArtifactsObjDir)$(OutDirName)\'))
21 | $(BaseIntermediateOutputPath)$(Configuration)\
22 |
23 | $([System.IO.Path]::GetFullPath('$(ArtifactsBinDir)$(OutDirName)\'))
24 | $(BaseOutputPath)$(Configuration)\
25 |
26 | $(ArtifactsPackagesDir)
27 |
28 |
29 |
30 | trx%3bLogFileName=$(MSBuildProjectName).$(TargetFramework).$(OS).trx
31 | $(ArtifactsTestResultsDir)
32 |
33 |
34 |
35 | true
36 |
37 |
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Anthropic and Contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | SOURCE_DIRECTORY := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
2 | ARTIFACT_PATH := $(SOURCE_DIRECTORY)artifacts
3 | DOCS_PATH := $(SOURCE_DIRECTORY)docs
4 | CONFIGURATION ?= Release
5 |
6 | clean:
7 | dotnet clean
8 | rm -rf $(ARTIFACT_PATH)/*
9 | rm -rf $(DOCS_PATH)/api
10 |
11 | restore:
12 | dotnet tool restore
13 | dotnet restore
14 |
15 | build: restore
16 | dotnet build --no-restore --configuration $(CONFIGURATION)
17 |
18 | test: build
19 | dotnet test \
20 | --no-build \
21 | --configuration $(CONFIGURATION) \
22 | --filter '(Execution!=Manual)' \
23 | --blame \
24 | --diag "$(ARTIFACT_PATH)/diag.txt" \
25 | --logger "trx" \
26 | --collect "Code Coverage;Format=cobertura" \
27 | --results-directory $(ARTIFACT_PATH)/test-results \
28 | -- \
29 | RunConfiguration.CollectSourceInformation=true
30 |
31 | generate-docs: clean restore
32 | dotnet build --no-restore --configuration Release
33 | dotnet docfx $(DOCS_PATH)/docfx.json
34 |
35 | serve-docs: generate-docs
36 | dotnet docfx serve $(ARTIFACT_PATH)/_site --port 8080
37 |
38 | .DEFAULT_GOAL := build
--------------------------------------------------------------------------------
/ModelContextProtocol.slnx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Open.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/modelcontextprotocol/csharp-sdk/fa017c04c3b92764856ca56337a7eda39c74a3cd/Open.snk
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 | Thank you for helping us keep the SDKs and systems they interact with secure.
3 |
4 | ## Reporting Security Issues
5 |
6 | This SDK is maintained by [Anthropic](https://www.anthropic.com/) as part of the Model Context Protocol project.
7 |
8 | The security of our systems and user data is Anthropic’s top priority. We appreciate the work of security researchers acting in good faith in identifying and reporting potential vulnerabilities.
9 |
10 | Our security program is managed on HackerOne and we ask that any validated vulnerability in this functionality be reported through their [submission form](https://hackerone.com/anthropic-vdp/reports/new?type=team&report_type=vulnerability).
11 |
12 | ## Vulnerability Disclosure Program
13 |
14 | Our Vulnerability Program Guidelines are defined on our [HackerOne program page](https://hackerone.com/anthropic-vdp).
15 |
--------------------------------------------------------------------------------
/docs/docfx.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/dotnet/docfx/main/schemas/docfx.schema.json",
3 | "metadata": [
4 | {
5 | "src": [
6 | {
7 | "src": "../src",
8 | "files": [
9 | "**/*.csproj"
10 | ]
11 | }
12 | ],
13 | "output": "api"
14 | }
15 | ],
16 | "build": {
17 | "content": [
18 | {
19 | "files": [
20 | "**/*.{md,yml}"
21 | ],
22 | "exclude": [
23 | "_site/**"
24 | ]
25 | }
26 | ],
27 | "resource": [
28 | {
29 | "files": [
30 | "images/**"
31 | ]
32 | }
33 | ],
34 | "output": "../artifacts/_site",
35 | "template": [
36 | "default",
37 | "modern"
38 | ],
39 | "globalMetadata": {
40 | "_appName": "MCP C# SDK",
41 | "_appTitle": "MCP C# SDK",
42 | "_appLogoPath": "images/mcp.svg",
43 | "_appFaviconPath": "images/favicon.ico",
44 | "_enableSearch": true,
45 | "pdf": false
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/docs/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/modelcontextprotocol/csharp-sdk/fa017c04c3b92764856ca56337a7eda39c74a3cd/docs/images/favicon.ico
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | _layout: landing
3 | ---
4 |
5 | # Overview
6 |
7 | The official C# SDK for the [Model Context Protocol](https://modelcontextprotocol.io/), enabling .NET applications, services, and libraries to implement and interact with MCP clients and servers. Please visit our [API documentation](https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.html) for more details on available functionality.
8 |
9 | ## About MCP
10 |
11 | The Model Context Protocol (MCP) is an open protocol that standardizes how applications provide context to Large Language Models (LLMs). It enables secure integration between LLMs and various data sources and tools.
12 |
13 | For more information about MCP:
14 |
15 | - [Official Documentation](https://modelcontextprotocol.io/)
16 | - [Protocol Specification](https://spec.modelcontextprotocol.io/)
17 | - [GitHub Organization](https://github.com/modelcontextprotocol)
18 |
19 | For how-to guides, tutorials, and additional guidance, refer to the [official MCP documentation](https://modelcontextprotocol.io/).
20 |
21 | ## License
22 |
23 | This project is licensed under the [MIT License](https://github.com/modelcontextprotocol/csharp-sdk/blob/main/LICENSE).
24 |
--------------------------------------------------------------------------------
/docs/toc.yml:
--------------------------------------------------------------------------------
1 | items:
2 | - name: API Docs
3 | href: api/ModelContextProtocol.yml
4 | - name: Github
5 | href: https://github.com/ModelContextProtocol/csharp-sdk
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "9.0.204",
4 | "rollForward": "minor"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/modelcontextprotocol/csharp-sdk/fa017c04c3b92764856ca56337a7eda39c74a3cd/logo.png
--------------------------------------------------------------------------------
/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/samples/AspNetCoreSseServer/AspNetCoreSseServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/samples/AspNetCoreSseServer/Program.cs:
--------------------------------------------------------------------------------
1 | using OpenTelemetry;
2 | using OpenTelemetry.Metrics;
3 | using OpenTelemetry.Trace;
4 | using TestServerWithHosting.Tools;
5 |
6 | var builder = WebApplication.CreateBuilder(args);
7 | builder.Services.AddMcpServer()
8 | .WithHttpTransport()
9 | .WithTools()
10 | .WithTools();
11 |
12 | builder.Services.AddOpenTelemetry()
13 | .WithTracing(b => b.AddSource("*")
14 | .AddAspNetCoreInstrumentation()
15 | .AddHttpClientInstrumentation())
16 | .WithMetrics(b => b.AddMeter("*")
17 | .AddAspNetCoreInstrumentation()
18 | .AddHttpClientInstrumentation())
19 | .WithLogging()
20 | .UseOtlpExporter();
21 |
22 | var app = builder.Build();
23 |
24 | app.MapMcp();
25 |
26 | app.Run();
27 |
--------------------------------------------------------------------------------
/samples/AspNetCoreSseServer/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/launchsettings.json",
3 | "profiles": {
4 | "http": {
5 | "commandName": "Project",
6 | "dotnetRunMessages": true,
7 | "applicationUrl": "http://localhost:3001",
8 | "environmentVariables": {
9 | "ASPNETCORE_ENVIRONMENT": "Development",
10 | "OTEL_SERVICE_NAME": "sse-server",
11 | }
12 | },
13 | "https": {
14 | "commandName": "Project",
15 | "dotnetRunMessages": true,
16 | "applicationUrl": "https://localhost:7133;http://localhost:3001",
17 | "environmentVariables": {
18 | "ASPNETCORE_ENVIRONMENT": "Development",
19 | "OTEL_SERVICE_NAME": "sse-server",
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/samples/AspNetCoreSseServer/Tools/EchoTool.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 | using System.ComponentModel;
3 |
4 | namespace TestServerWithHosting.Tools;
5 |
6 | [McpServerToolType]
7 | public sealed class EchoTool
8 | {
9 | [McpServerTool, Description("Echoes the input back to the client.")]
10 | public static string Echo(string message)
11 | {
12 | return "hello " + message;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/samples/AspNetCoreSseServer/Tools/SampleLlmTool.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.AI;
2 | using ModelContextProtocol.Server;
3 | using System.ComponentModel;
4 |
5 | namespace TestServerWithHosting.Tools;
6 |
7 | ///
8 | /// This tool uses dependency injection and async method
9 | ///
10 | [McpServerToolType]
11 | public sealed class SampleLlmTool
12 | {
13 | [McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
14 | public static async Task SampleLLM(
15 | IMcpServer thisServer,
16 | [Description("The prompt to send to the LLM")] string prompt,
17 | [Description("Maximum number of tokens to generate")] int maxTokens,
18 | CancellationToken cancellationToken)
19 | {
20 | ChatMessage[] messages =
21 | [
22 | new(ChatRole.System, "You are a helpful test server."),
23 | new(ChatRole.User, prompt),
24 | ];
25 |
26 | ChatOptions options = new()
27 | {
28 | MaxOutputTokens = maxTokens,
29 | Temperature = 0.7f,
30 | };
31 |
32 | var samplingResponse = await thisServer.AsSamplingChatClient().GetResponseAsync(messages, options, cancellationToken);
33 |
34 | return $"LLM sampling result: {samplingResponse}";
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/samples/AspNetCoreSseServer/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/samples/AspNetCoreSseServer/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*"
9 | }
10 |
--------------------------------------------------------------------------------
/samples/ChatWithTools/ChatWithTools.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/samples/EverythingServer/EverythingServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | Exe
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/samples/EverythingServer/LoggingUpdateMessageSender.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Hosting;
2 | using ModelContextProtocol;
3 | using ModelContextProtocol.Protocol;
4 | using ModelContextProtocol.Server;
5 |
6 | namespace EverythingServer;
7 |
8 | public class LoggingUpdateMessageSender(IMcpServer server, Func getMinLevel) : BackgroundService
9 | {
10 | readonly Dictionary _loggingLevelMap = new()
11 | {
12 | { LoggingLevel.Debug, "Debug-level message" },
13 | { LoggingLevel.Info, "Info-level message" },
14 | { LoggingLevel.Notice, "Notice-level message" },
15 | { LoggingLevel.Warning, "Warning-level message" },
16 | { LoggingLevel.Error, "Error-level message" },
17 | { LoggingLevel.Critical, "Critical-level message" },
18 | { LoggingLevel.Alert, "Alert-level message" },
19 | { LoggingLevel.Emergency, "Emergency-level message" }
20 | };
21 |
22 | protected override async Task ExecuteAsync(CancellationToken stoppingToken)
23 | {
24 | while (!stoppingToken.IsCancellationRequested)
25 | {
26 | var newLevel = (LoggingLevel)Random.Shared.Next(_loggingLevelMap.Count);
27 |
28 | var message = new
29 | {
30 | Level = newLevel.ToString().ToLower(),
31 | Data = _loggingLevelMap[newLevel],
32 | };
33 |
34 | if (newLevel > getMinLevel())
35 | {
36 | await server.SendNotificationAsync("notifications/message", message, cancellationToken: stoppingToken);
37 | }
38 |
39 | await Task.Delay(15000, stoppingToken);
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/samples/EverythingServer/Prompts/ComplexPromptType.cs:
--------------------------------------------------------------------------------
1 | using EverythingServer.Tools;
2 | using Microsoft.Extensions.AI;
3 | using ModelContextProtocol.Server;
4 | using System.ComponentModel;
5 |
6 | namespace EverythingServer.Prompts;
7 |
8 | [McpServerPromptType]
9 | public class ComplexPromptType
10 | {
11 | [McpServerPrompt(Name = "complex_prompt"), Description("A prompt with arguments")]
12 | public static IEnumerable ComplexPrompt(
13 | [Description("Temperature setting")] int temperature,
14 | [Description("Output style")] string? style = null)
15 | {
16 | return [
17 | new ChatMessage(ChatRole.User,$"This is a complex prompt with arguments: temperature={temperature}, style={style}"),
18 | new ChatMessage(ChatRole.Assistant, "I understand. You've provided a complex prompt with temperature and style arguments. How would you like me to proceed?"),
19 | new ChatMessage(ChatRole.User, [new DataContent(TinyImageTool.MCP_TINY_IMAGE)])
20 | ];
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/samples/EverythingServer/Prompts/SimplePromptType.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 | using System.ComponentModel;
3 |
4 | namespace EverythingServer.Prompts;
5 |
6 | [McpServerPromptType]
7 | public class SimplePromptType
8 | {
9 | [McpServerPrompt(Name = "simple_prompt"), Description("A prompt without arguments")]
10 | public static string SimplePrompt() => "This is a simple prompt without arguments";
11 | }
12 |
--------------------------------------------------------------------------------
/samples/EverythingServer/ResourceGenerator.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 |
3 | namespace EverythingServer;
4 |
5 | static class ResourceGenerator
6 | {
7 | private static readonly List _resources = Enumerable.Range(1, 100).Select(i =>
8 | {
9 | var uri = $"test://template/resource/{i}";
10 | if (i % 2 != 0)
11 | {
12 | return new Resource
13 | {
14 | Uri = uri,
15 | Name = $"Resource {i}",
16 | MimeType = "text/plain",
17 | Description = $"Resource {i}: This is a plaintext resource"
18 | };
19 | }
20 | else
21 | {
22 | var buffer = System.Text.Encoding.UTF8.GetBytes($"Resource {i}: This is a base64 blob");
23 | return new Resource
24 | {
25 | Uri = uri,
26 | Name = $"Resource {i}",
27 | MimeType = "application/octet-stream",
28 | Description = Convert.ToBase64String(buffer)
29 | };
30 | }
31 | }).ToList();
32 |
33 | public static IReadOnlyList Resources => _resources;
34 | }
--------------------------------------------------------------------------------
/samples/EverythingServer/Resources/SimpleResourceType.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 | using ModelContextProtocol.Server;
3 | using System.ComponentModel;
4 |
5 | namespace EverythingServer.Resources;
6 |
7 | [McpServerResourceType]
8 | public class SimpleResourceType
9 | {
10 | [McpServerResource(UriTemplate = "test://direct/text/resource", Name = "Direct Text Resource", MimeType = "text/plain")]
11 | [Description("A direct text resource")]
12 | public static string DirectTextResource() => "This is a direct resource";
13 |
14 | [McpServerResource(UriTemplate = "test://template/resource/{id}", Name = "Template Resource")]
15 | [Description("A template resource with a numeric ID")]
16 | public static ResourceContents TemplateResource(RequestContext requestContext, int id)
17 | {
18 | int index = id - 1;
19 | if ((uint)index >= ResourceGenerator.Resources.Count)
20 | {
21 | throw new NotSupportedException($"Unknown resource: {requestContext.Params?.Uri}");
22 | }
23 |
24 | var resource = ResourceGenerator.Resources[index];
25 | return resource.MimeType == "text/plain" ?
26 | new TextResourceContents
27 | {
28 | Text = resource.Description!,
29 | MimeType = resource.MimeType,
30 | Uri = resource.Uri,
31 | } :
32 | new BlobResourceContents
33 | {
34 | Blob = resource.Description!,
35 | MimeType = resource.MimeType,
36 | Uri = resource.Uri,
37 | };
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/samples/EverythingServer/SubscriptionMessageSender.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Hosting;
2 | using ModelContextProtocol;
3 | using ModelContextProtocol.Server;
4 |
5 | internal class SubscriptionMessageSender(IMcpServer server, HashSet subscriptions) : BackgroundService
6 | {
7 | protected override async Task ExecuteAsync(CancellationToken stoppingToken)
8 | {
9 | while (!stoppingToken.IsCancellationRequested)
10 | {
11 | foreach (var uri in subscriptions)
12 | {
13 | await server.SendNotificationAsync("notifications/resource/updated",
14 | new
15 | {
16 | Uri = uri,
17 | }, cancellationToken: stoppingToken);
18 | }
19 |
20 | await Task.Delay(5000, stoppingToken);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/samples/EverythingServer/Tools/AddTool.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 | using System.ComponentModel;
3 |
4 | namespace EverythingServer.Tools;
5 |
6 | [McpServerToolType]
7 | public class AddTool
8 | {
9 | [McpServerTool(Name = "add"), Description("Adds two numbers.")]
10 | public static string Add(int a, int b) => $"The sum of {a} and {b} is {a + b}";
11 | }
12 |
--------------------------------------------------------------------------------
/samples/EverythingServer/Tools/AnnotatedMessageTool.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 | using ModelContextProtocol.Server;
3 | using System.ComponentModel;
4 |
5 | namespace EverythingServer.Tools;
6 |
7 | [McpServerToolType]
8 | public class AnnotatedMessageTool
9 | {
10 | public enum MessageType
11 | {
12 | Error,
13 | Success,
14 | Debug,
15 | }
16 |
17 | [McpServerTool(Name = "annotatedMessage"), Description("Generates an annotated message")]
18 | public static IEnumerable AnnotatedMessage(MessageType messageType, bool includeImage = true)
19 | {
20 | List contents = messageType switch
21 | {
22 | MessageType.Error => [new()
23 | {
24 | Type = "text",
25 | Text = "Error: Operation failed",
26 | Annotations = new() { Audience = [Role.User, Role.Assistant], Priority = 1.0f }
27 | }],
28 | MessageType.Success => [new()
29 | {
30 | Type = "text",
31 | Text = "Operation completed successfully",
32 | Annotations = new() { Audience = [Role.User], Priority = 0.7f }
33 | }],
34 | MessageType.Debug => [new()
35 | {
36 | Type = "text",
37 | Text = "Debug: Cache hit ratio 0.95, latency 150ms",
38 | Annotations = new() { Audience = [Role.Assistant], Priority = 0.3f }
39 | }],
40 | _ => throw new ArgumentOutOfRangeException(nameof(messageType), messageType, null)
41 | };
42 |
43 | if (includeImage)
44 | {
45 | contents.Add(new()
46 | {
47 | Type = "image",
48 | Data = TinyImageTool.MCP_TINY_IMAGE.Split(",").Last(),
49 | MimeType = "image/png",
50 | Annotations = new() { Audience = [Role.User], Priority = 0.5f }
51 | });
52 | }
53 |
54 | return contents;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/samples/EverythingServer/Tools/EchoTool.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 | using System.ComponentModel;
3 |
4 | namespace EverythingServer.Tools;
5 |
6 | [McpServerToolType]
7 | public class EchoTool
8 | {
9 | [McpServerTool(Name = "echo"), Description("Echoes the message back to the client.")]
10 | public static string Echo(string message) => $"Echo: {message}";
11 | }
12 |
--------------------------------------------------------------------------------
/samples/EverythingServer/Tools/LongRunningTool.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol;
2 | using ModelContextProtocol.Protocol;
3 | using ModelContextProtocol.Server;
4 | using System.ComponentModel;
5 |
6 | namespace EverythingServer.Tools;
7 |
8 | [McpServerToolType]
9 | public class LongRunningTool
10 | {
11 | [McpServerTool(Name = "longRunningOperation"), Description("Demonstrates a long running operation with progress updates")]
12 | public static async Task LongRunningOperation(
13 | IMcpServer server,
14 | RequestContext context,
15 | int duration = 10,
16 | int steps = 5)
17 | {
18 | var progressToken = context.Params?.Meta?.ProgressToken;
19 | var stepDuration = duration / steps;
20 |
21 | for (int i = 1; i <= steps + 1; i++)
22 | {
23 | await Task.Delay(stepDuration * 1000);
24 |
25 | if (progressToken is not null)
26 | {
27 | await server.SendNotificationAsync("notifications/progress", new
28 | {
29 | Progress = i,
30 | Total = steps,
31 | progressToken
32 | });
33 | }
34 | }
35 |
36 | return $"Long running operation completed. Duration: {duration} seconds. Steps: {steps}.";
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/samples/EverythingServer/Tools/PrintEnvTool.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 | using System.ComponentModel;
3 | using System.Text.Json;
4 |
5 | namespace EverythingServer.Tools;
6 |
7 | [McpServerToolType]
8 | public class PrintEnvTool
9 | {
10 | private static readonly JsonSerializerOptions options = new()
11 | {
12 | WriteIndented = true
13 | };
14 |
15 | [McpServerTool(Name = "printEnv"), Description("Prints all environment variables, helpful for debugging MCP server configuration")]
16 | public static string PrintEnv() =>
17 | JsonSerializer.Serialize(Environment.GetEnvironmentVariables(), options);
18 | }
19 |
--------------------------------------------------------------------------------
/samples/EverythingServer/Tools/SampleLlmTool.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 | using ModelContextProtocol.Server;
3 | using System.ComponentModel;
4 |
5 | namespace EverythingServer.Tools;
6 |
7 | [McpServerToolType]
8 | public class SampleLlmTool
9 | {
10 | [McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
11 | public static async Task SampleLLM(
12 | IMcpServer server,
13 | [Description("The prompt to send to the LLM")] string prompt,
14 | [Description("Maximum number of tokens to generate")] int maxTokens,
15 | CancellationToken cancellationToken)
16 | {
17 | var samplingParams = CreateRequestSamplingParams(prompt ?? string.Empty, "sampleLLM", maxTokens);
18 | var sampleResult = await server.SampleAsync(samplingParams, cancellationToken);
19 |
20 | return $"LLM sampling result: {sampleResult.Content.Text}";
21 | }
22 |
23 | private static CreateMessageRequestParams CreateRequestSamplingParams(string context, string uri, int maxTokens = 100)
24 | {
25 | return new CreateMessageRequestParams()
26 | {
27 | Messages = [new SamplingMessage()
28 | {
29 | Role = Role.User,
30 | Content = new Content()
31 | {
32 | Type = "text",
33 | Text = $"Resource {uri} context: {context}"
34 | }
35 | }],
36 | SystemPrompt = "You are a helpful test server.",
37 | MaxTokens = maxTokens,
38 | Temperature = 0.7f,
39 | IncludeContext = ContextInclusion.ThisServer
40 | };
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/samples/QuickstartClient/QuickstartClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 | a4e20a70-5009-4b81-b5b6-780b6d43e78e
9 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/samples/QuickstartWeatherServer/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Hosting;
3 | using Microsoft.Extensions.Logging;
4 | using QuickstartWeatherServer.Tools;
5 | using System.Net.Http.Headers;
6 |
7 | var builder = Host.CreateApplicationBuilder(args);
8 |
9 | builder.Services.AddMcpServer()
10 | .WithStdioServerTransport()
11 | .WithTools();
12 |
13 | builder.Logging.AddConsole(options =>
14 | {
15 | options.LogToStandardErrorThreshold = LogLevel.Trace;
16 | });
17 |
18 | builder.Services.AddSingleton(_ =>
19 | {
20 | var client = new HttpClient() { BaseAddress = new Uri("https://api.weather.gov") };
21 | client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("weather-tool", "1.0"));
22 | return client;
23 | });
24 |
25 | await builder.Build().RunAsync();
26 |
--------------------------------------------------------------------------------
/samples/QuickstartWeatherServer/QuickstartWeatherServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 | true
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/samples/QuickstartWeatherServer/Tools/HttpClientExt.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 |
3 | namespace ModelContextProtocol;
4 |
5 | internal static class HttpClientExt
6 | {
7 | public static async Task ReadJsonDocumentAsync(this HttpClient client, string requestUri)
8 | {
9 | using var response = await client.GetAsync(requestUri);
10 | response.EnsureSuccessStatusCode();
11 | return await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
12 | }
13 | }
--------------------------------------------------------------------------------
/samples/TestServerWithHosting/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Hosting;
3 | using Serilog;
4 | using TestServerWithHosting.Tools;
5 |
6 | Log.Logger = new LoggerConfiguration()
7 | .MinimumLevel.Verbose() // Capture all log levels
8 | .WriteTo.File(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "TestServer_.log"),
9 | rollingInterval: RollingInterval.Day,
10 | outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}")
11 | .WriteTo.Debug()
12 | .WriteTo.Console(standardErrorFromLevel: Serilog.Events.LogEventLevel.Verbose)
13 | .CreateLogger();
14 |
15 | try
16 | {
17 | Log.Information("Starting server...");
18 |
19 | var builder = Host.CreateApplicationBuilder(args);
20 | builder.Services.AddSerilog();
21 | builder.Services.AddMcpServer()
22 | .WithStdioServerTransport()
23 | .WithTools()
24 | .WithTools();
25 |
26 | var app = builder.Build();
27 |
28 | await app.RunAsync();
29 | return 0;
30 | }
31 | catch (Exception ex)
32 | {
33 | Log.Fatal(ex, "Host terminated unexpectedly");
34 | return 1;
35 | }
36 | finally
37 | {
38 | Log.CloseAndFlush();
39 | }
--------------------------------------------------------------------------------
/samples/TestServerWithHosting/TestServerWithHosting.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0;net8.0;net472
6 | enable
7 | enable
8 | true
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/samples/TestServerWithHosting/Tools/EchoTool.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 | using System.ComponentModel;
3 |
4 | namespace TestServerWithHosting.Tools;
5 |
6 | [McpServerToolType]
7 | public sealed class EchoTool
8 | {
9 | [McpServerTool, Description("Echoes the input back to the client.")]
10 | public static string Echo(string message)
11 | {
12 | return "hello " + message;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/samples/TestServerWithHosting/Tools/SampleLlmTool.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 | using ModelContextProtocol.Server;
3 | using System.ComponentModel;
4 |
5 | namespace TestServerWithHosting.Tools;
6 |
7 | ///
8 | /// This tool uses depenency injection and async method
9 | ///
10 | [McpServerToolType]
11 | public sealed class SampleLlmTool
12 | {
13 | [McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
14 | public static async Task SampleLLM(
15 | IMcpServer thisServer,
16 | [Description("The prompt to send to the LLM")] string prompt,
17 | [Description("Maximum number of tokens to generate")] int maxTokens,
18 | CancellationToken cancellationToken)
19 | {
20 | var samplingParams = CreateRequestSamplingParams(prompt ?? string.Empty, "sampleLLM", maxTokens);
21 | var sampleResult = await thisServer.SampleAsync(samplingParams, cancellationToken);
22 |
23 | return $"LLM sampling result: {sampleResult.Content.Text}";
24 | }
25 |
26 | private static CreateMessageRequestParams CreateRequestSamplingParams(string context, string uri, int maxTokens = 100)
27 | {
28 | return new CreateMessageRequestParams()
29 | {
30 | Messages = [new SamplingMessage()
31 | {
32 | Role = Role.User,
33 | Content = new Content()
34 | {
35 | Type = "text",
36 | Text = $"Resource {uri} context: {context}"
37 | }
38 | }],
39 | SystemPrompt = "You are a helpful test server.",
40 | MaxTokens = maxTokens,
41 | Temperature = 0.7f,
42 | IncludeContext = ContextInclusion.ThisServer
43 | };
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Collections/Generic/CollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol;
2 |
3 | namespace System.Collections.Generic;
4 |
5 | internal static class CollectionExtensions
6 | {
7 | public static TValue? GetValueOrDefault(this IReadOnlyDictionary dictionary, TKey key)
8 | {
9 | return dictionary.GetValueOrDefault(key, default!);
10 | }
11 |
12 | public static TValue GetValueOrDefault(this IReadOnlyDictionary dictionary, TKey key, TValue defaultValue)
13 | {
14 | Throw.IfNull(dictionary);
15 |
16 | return dictionary.TryGetValue(key, out TValue? value) ? value : defaultValue;
17 | }
18 |
19 | public static Dictionary ToDictionary(this IEnumerable> source) =>
20 | source.ToDictionary(kv => kv.Key, kv => kv.Value);
21 | }
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 |
4 | namespace System.Diagnostics.CodeAnalysis;
5 |
6 | ///
7 | /// Indicates that the specified method requires the ability to generate new code at runtime,
8 | /// for example through .
9 | ///
10 | ///
11 | /// This allows tools to understand which methods are unsafe to call when compiling ahead of time.
12 | ///
13 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)]
14 | internal sealed class RequiresDynamicCodeAttribute : Attribute
15 | {
16 | ///
17 | /// Initializes a new instance of the class
18 | /// with the specified message.
19 | ///
20 | ///
21 | /// A message that contains information about the usage of dynamic code.
22 | ///
23 | public RequiresDynamicCodeAttribute(string message)
24 | {
25 | Message = message;
26 | }
27 |
28 | ///
29 | /// Gets a message that contains information about the usage of dynamic code.
30 | ///
31 | public string Message { get; }
32 |
33 | ///
34 | /// Gets or sets an optional URL that contains more information about the method,
35 | /// why it requires dynamic code, and what options a consumer has to deal with it.
36 | ///
37 | public string? Url { get; set; }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCode.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 |
4 | namespace System.Diagnostics.CodeAnalysis;
5 |
6 | ///
7 | /// Indicates that the specified method requires dynamic access to code that is not referenced
8 | /// statically, for example through .
9 | ///
10 | ///
11 | /// This allows tools to understand which methods are unsafe to call when removing unreferenced
12 | /// code from an application.
13 | ///
14 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)]
15 | internal sealed class RequiresUnreferencedCodeAttribute : Attribute
16 | {
17 | ///
18 | /// Initializes a new instance of the class
19 | /// with the specified message.
20 | ///
21 | ///
22 | /// A message that contains information about the usage of unreferenced code.
23 | ///
24 | public RequiresUnreferencedCodeAttribute(string message)
25 | {
26 | Message = message;
27 | }
28 |
29 | ///
30 | /// Gets a message that contains information about the usage of unreferenced code.
31 | ///
32 | public string Message { get; }
33 |
34 | ///
35 | /// Gets or sets an optional URL that contains more information about the method,
36 | /// why it requires unreferenced code, and what options a consumer has to deal with it.
37 | ///
38 | public string? Url { get; set; }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs:
--------------------------------------------------------------------------------
1 | namespace System.Diagnostics.CodeAnalysis
2 | {
3 | [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
4 | internal sealed class SetsRequiredMembersAttribute : Attribute;
5 | }
6 |
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/IO/StreamExtensions.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol;
2 | using System.Buffers;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace System.IO;
6 |
7 | internal static class StreamExtensions
8 | {
9 | public static ValueTask WriteAsync(this Stream stream, ReadOnlyMemory buffer, CancellationToken cancellationToken)
10 | {
11 | Throw.IfNull(stream);
12 |
13 | if (MemoryMarshal.TryGetArray(buffer, out ArraySegment segment))
14 | {
15 | return new ValueTask(stream.WriteAsync(segment.Array, segment.Offset, segment.Count, cancellationToken));
16 | }
17 | else
18 | {
19 | return WriteAsyncCore(stream, buffer, cancellationToken);
20 |
21 | static async ValueTask WriteAsyncCore(Stream stream, ReadOnlyMemory buffer, CancellationToken cancellationToken)
22 | {
23 | byte[] array = ArrayPool.Shared.Rent(buffer.Length);
24 | try
25 | {
26 | buffer.Span.CopyTo(array);
27 | await stream.WriteAsync(array, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
28 | }
29 | finally
30 | {
31 | ArrayPool.Shared.Return(array);
32 | }
33 | }
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/IO/TextReaderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace System.IO;
2 |
3 | internal static class TextReaderExtensions
4 | {
5 | public static Task ReadLineAsync(this TextReader reader, CancellationToken cancellationToken)
6 | {
7 | cancellationToken.ThrowIfCancellationRequested();
8 | return reader.ReadLineAsync();
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/IO/TextWriterExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace System.IO;
2 |
3 | internal static class TextWriterExtensions
4 | {
5 | public static async Task FlushAsync(this TextWriter writer, CancellationToken cancellationToken)
6 | {
7 | cancellationToken.ThrowIfCancellationRequested();
8 | await writer.FlushAsync();
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Net/Http/HttpClientExtensions.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol;
2 |
3 | namespace System.Net.Http;
4 |
5 | internal static class HttpClientExtensions
6 | {
7 | public static async Task ReadAsStreamAsync(this HttpContent content, CancellationToken cancellationToken)
8 | {
9 | Throw.IfNull(content);
10 |
11 | cancellationToken.ThrowIfCancellationRequested();
12 | return await content.ReadAsStreamAsync();
13 | }
14 |
15 | public static async Task ReadAsStringAsync(this HttpContent content, CancellationToken cancellationToken)
16 | {
17 | Throw.IfNull(content);
18 |
19 | cancellationToken.ThrowIfCancellationRequested();
20 | return await content.ReadAsStringAsync();
21 | }
22 | }
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 |
4 | namespace System.Runtime.CompilerServices;
5 |
6 | [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
7 | internal sealed class CallerArgumentExpressionAttribute : Attribute
8 | {
9 | public CallerArgumentExpressionAttribute(string parameterName)
10 | {
11 | ParameterName = parameterName;
12 | }
13 |
14 | public string ParameterName { get; }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Runtime/CompilerServices/CompilerFeatureRequiredAttribute.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 |
4 | namespace System.Runtime.CompilerServices
5 | {
6 | ///
7 | /// Indicates that compiler support for a particular feature is required for the location where this attribute is applied.
8 | ///
9 | [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
10 | internal sealed class CompilerFeatureRequiredAttribute : Attribute
11 | {
12 | public CompilerFeatureRequiredAttribute(string featureName)
13 | {
14 | FeatureName = featureName;
15 | }
16 |
17 | ///
18 | /// The name of the compiler feature.
19 | ///
20 | public string FeatureName { get; }
21 |
22 | ///
23 | /// If true, the compiler can choose to allow access to the location where this attribute is applied if it does not understand .
24 | ///
25 | public bool IsOptional { get; init; }
26 |
27 | ///
28 | /// The used for the required members C# feature.
29 | ///
30 | public const string RequiredMembers = nameof(RequiredMembers);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Runtime/CompilerServices/IsExternalInit.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 |
4 | using System.ComponentModel;
5 |
6 | namespace System.Runtime.CompilerServices
7 | {
8 | ///
9 | /// Reserved to be used by the compiler for tracking metadata.
10 | /// This class should not be used by developers in source code.
11 | ///
12 | [EditorBrowsable(EditorBrowsableState.Never)]
13 | internal static class IsExternalInit;
14 | }
15 |
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Runtime/CompilerServices/RequiredMemberAttribute.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 |
4 | using System.ComponentModel;
5 |
6 | namespace System.Runtime.CompilerServices
7 | {
8 | /// Specifies that a type has required members or that a member is required.
9 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
10 | [EditorBrowsable(EditorBrowsableState.Never)]
11 | internal sealed class RequiredMemberAttribute : Attribute;
12 | }
13 |
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Threading/CancellationTokenSourceExtensions.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol;
2 |
3 | namespace System.Threading.Tasks;
4 |
5 | internal static class CancellationTokenSourceExtensions
6 | {
7 | public static Task CancelAsync(this CancellationTokenSource cancellationTokenSource)
8 | {
9 | Throw.IfNull(cancellationTokenSource);
10 |
11 | cancellationTokenSource.Cancel();
12 | return Task.CompletedTask;
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Threading/Channels/ChannelExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | namespace System.Threading.Channels;
4 |
5 | internal static class ChannelExtensions
6 | {
7 | public static async IAsyncEnumerable ReadAllAsync(this ChannelReader reader, [EnumeratorCancellation] CancellationToken cancellationToken)
8 | {
9 | while (await reader.WaitToReadAsync(cancellationToken).ConfigureAwait(false))
10 | {
11 | while (reader.TryRead(out var item))
12 | {
13 | yield return item;
14 | }
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Threading/ForceYielding.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | namespace System.Threading;
4 |
5 | ///
6 | /// await default(ForceYielding) to provide the same behavior as
7 | /// await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding).
8 | ///
9 | internal readonly struct ForceYielding : INotifyCompletion, ICriticalNotifyCompletion
10 | {
11 | public ForceYielding GetAwaiter() => this;
12 |
13 | public bool IsCompleted => false;
14 | public void OnCompleted(Action continuation) => ThreadPool.QueueUserWorkItem(a => ((Action)a!)(), continuation);
15 | public void UnsafeOnCompleted(Action continuation) => ThreadPool.UnsafeQueueUserWorkItem(a => ((Action)a!)(), continuation);
16 | public void GetResult() { }
17 | }
--------------------------------------------------------------------------------
/src/Common/Polyfills/System/Threading/Tasks/TaskExtensions.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol;
2 |
3 | namespace System.Threading.Tasks;
4 |
5 | internal static class TaskExtensions
6 | {
7 | public static Task WaitAsync(this Task task, CancellationToken cancellationToken)
8 | {
9 | return WaitAsync(task, Timeout.InfiniteTimeSpan, cancellationToken);
10 | }
11 |
12 | public static Task WaitAsync(this Task task, CancellationToken cancellationToken)
13 | {
14 | return WaitAsync(task, Timeout.InfiniteTimeSpan, cancellationToken);
15 | }
16 |
17 | public static async Task WaitAsync(this Task task, TimeSpan timeout, CancellationToken cancellationToken = default)
18 | {
19 | await WaitAsync((Task)task, timeout, cancellationToken).ConfigureAwait(false);
20 | return task.Result;
21 | }
22 |
23 | public static async Task WaitAsync(this Task task, TimeSpan timeout, CancellationToken cancellationToken = default)
24 | {
25 | Throw.IfNull(task);
26 |
27 | if (timeout < TimeSpan.Zero && timeout != Timeout.InfiniteTimeSpan)
28 | {
29 | throw new ArgumentOutOfRangeException(nameof(timeout));
30 | }
31 |
32 | if (!task.IsCompleted)
33 | {
34 | cancellationToken.ThrowIfCancellationRequested();
35 |
36 | using CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
37 | cts.CancelAfter(timeout);
38 |
39 | var cancellationTask = new TaskCompletionSource();
40 | using var _ = cts.Token.Register(tcs => ((TaskCompletionSource)tcs!).TrySetResult(true), cancellationTask);
41 | await Task.WhenAny(task, cancellationTask.Task).ConfigureAwait(false);
42 |
43 | if (!task.IsCompleted)
44 | {
45 | cancellationToken.ThrowIfCancellationRequested();
46 | throw new TimeoutException();
47 | }
48 | }
49 |
50 | await task.ConfigureAwait(false);
51 | }
52 | }
--------------------------------------------------------------------------------
/src/Common/Throw.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 | using System.Runtime.CompilerServices;
3 |
4 | namespace ModelContextProtocol;
5 |
6 | /// Provides helper methods for throwing exceptions.
7 | internal static class Throw
8 | {
9 | // NOTE: Most of these should be replaced with extension statics for the relevant extension
10 | // type as downlevel polyfills once the C# 14 extension everything feature is available.
11 |
12 | public static void IfNull([NotNull] object? arg, [CallerArgumentExpression(nameof(arg))] string? parameterName = null)
13 | {
14 | if (arg is null)
15 | {
16 | ThrowArgumentNullException(parameterName);
17 | }
18 | }
19 |
20 | public static void IfNullOrWhiteSpace([NotNull] string? arg, [CallerArgumentExpression(nameof(arg))] string? parameterName = null)
21 | {
22 | if (arg is null || arg.AsSpan().IsWhiteSpace())
23 | {
24 | ThrowArgumentNullOrWhiteSpaceException(parameterName);
25 | }
26 | }
27 |
28 | [DoesNotReturn]
29 | private static void ThrowArgumentNullOrWhiteSpaceException(string? parameterName)
30 | {
31 | if (parameterName is null)
32 | {
33 | ThrowArgumentNullException(parameterName);
34 | }
35 |
36 | throw new ArgumentException("Value cannot be empty or composed entirely of whitespace.", parameterName);
37 | }
38 |
39 | [DoesNotReturn]
40 | private static void ThrowArgumentNullException(string? parameterName) => throw new ArgumentNullException(parameterName);
41 | }
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | https://github.com/modelcontextprotocol/csharp-sdk
6 | https://github.com/modelcontextprotocol/csharp-sdk
7 | git
8 | 0.2.0
9 | preview.4
10 | ModelContextProtocolOfficial
11 | © Anthropic and Contributors.
12 | ModelContextProtocol;mcp;ai;llm
13 | MIT
14 | logo.png
15 | true
16 | snupkg
17 | true
18 | $(RepoRoot)\Open.snk
19 | true
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.AspNetCore/HttpMcpServerBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection.Extensions;
2 | using ModelContextProtocol.AspNetCore;
3 | using ModelContextProtocol.Server;
4 |
5 | namespace Microsoft.Extensions.DependencyInjection;
6 |
7 | ///
8 | /// Provides methods for configuring HTTP MCP servers via dependency injection.
9 | ///
10 | public static class HttpMcpServerBuilderExtensions
11 | {
12 | ///
13 | /// Adds the services necessary for
14 | /// to handle MCP requests and sessions using the MCP Streamable HTTP transport. For more information on configuring the underlying HTTP server
15 | /// to control things like port binding custom TLS certificates, see the Minimal APIs quick reference.
16 | ///
17 | /// The builder instance.
18 | /// Configures options for the Streamable HTTP transport. This allows configuring per-session
19 | /// and running logic before and after a session.
20 | /// The builder provided in .
21 | /// is .
22 | public static IMcpServerBuilder WithHttpTransport(this IMcpServerBuilder builder, Action? configureOptions = null)
23 | {
24 | ArgumentNullException.ThrowIfNull(builder);
25 |
26 | builder.Services.TryAddSingleton();
27 | builder.Services.TryAddSingleton();
28 | builder.Services.AddHostedService();
29 | builder.Services.AddDataProtection();
30 |
31 | if (configureOptions is not null)
32 | {
33 | builder.Services.Configure(configureOptions);
34 | }
35 |
36 | return builder;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.AspNetCore/ModelContextProtocol.AspNetCore.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0;net8.0
5 | enable
6 | enable
7 | true
8 | true
9 | ModelContextProtocol.AspNetCore
10 | ASP.NET Core extensions for the C# Model Context Protocol (MCP) SDK.
11 | README.md
12 | true
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.AspNetCore/README.md:
--------------------------------------------------------------------------------
1 | # ASP.NET Core extensions for the MCP C# SDK
2 |
3 | [](https://www.nuget.org/packages/ModelContextProtocol/absoluteLatest)
4 |
5 | The official C# SDK for the [Model Context Protocol](https://modelcontextprotocol.io/), enabling .NET applications, services, and libraries to implement and interact with MCP clients and servers. Please visit our [API documentation](https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.html) for more details on available functionality.
6 |
7 | > [!NOTE]
8 | > This project is in preview; breaking changes can be introduced without prior notice.
9 |
10 | ## About MCP
11 |
12 | The Model Context Protocol (MCP) is an open protocol that standardizes how applications provide context to Large Language Models (LLMs). It enables secure integration between LLMs and various data sources and tools.
13 |
14 | For more information about MCP:
15 |
16 | - [Official Documentation](https://modelcontextprotocol.io/)
17 | - [Protocol Specification](https://spec.modelcontextprotocol.io/)
18 | - [GitHub Organization](https://github.com/modelcontextprotocol)
19 |
20 | ## Installation
21 |
22 | To get started, install the package from NuGet
23 |
24 | ```
25 | dotnet new web
26 | dotnet add package ModelContextProtocol.AspNetCore --prerelease
27 | ```
28 |
29 | ## Getting Started
30 |
31 | ```csharp
32 | // Program.cs
33 | using ModelContextProtocol.Server;
34 | using System.ComponentModel;
35 |
36 | var builder = WebApplication.CreateBuilder(args);
37 | builder.Services.AddMcpServer()
38 | .WithHttpTransport()
39 | .WithToolsFromAssembly();
40 | var app = builder.Build();
41 |
42 | app.MapMcp();
43 |
44 | app.Run("http://localhost:3001");
45 |
46 | [McpServerToolType]
47 | public static class EchoTool
48 | {
49 | [McpServerTool, Description("Echoes the message back to the client.")]
50 | public static string Echo(string message) => $"hello {message}";
51 | }
52 | ```
53 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.AspNetCore/Stateless/StatelessSessionId.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.AspNetCore.Stateless;
5 |
6 | internal sealed class StatelessSessionId
7 | {
8 | [JsonPropertyName("clientInfo")]
9 | public Implementation? ClientInfo { get; init; }
10 |
11 | [JsonPropertyName("userIdClaim")]
12 | public UserIdClaim? UserIdClaim { get; init; }
13 | }
14 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.AspNetCore/Stateless/StatelessSessionIdJsonContext.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.AspNetCore.Stateless;
4 |
5 | [JsonSerializable(typeof(StatelessSessionId))]
6 | internal sealed partial class StatelessSessionIdJsonContext : JsonSerializerContext;
7 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.AspNetCore/Stateless/UserIdClaim.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.AspNetCore.Stateless;
2 |
3 | internal sealed record UserIdClaim(string Type, string Value, string Issuer);
4 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Client/HttpTransportMode.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Client;
2 |
3 | ///
4 | /// Specifies the transport mode for HTTP client connections.
5 | ///
6 | public enum HttpTransportMode
7 | {
8 | ///
9 | /// Automatically detect the appropriate transport by trying Streamable HTTP first, then falling back to SSE if that fails.
10 | /// This is the recommended mode for maximum compatibility.
11 | ///
12 | AutoDetect,
13 |
14 | ///
15 | /// Use only the Streamable HTTP transport.
16 | ///
17 | StreamableHttp,
18 |
19 | ///
20 | /// Use only the HTTP with SSE transport.
21 | ///
22 | Sse
23 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Client/IMcpClient.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 |
3 | namespace ModelContextProtocol.Client;
4 |
5 | ///
6 | /// Represents an instance of a Model Context Protocol (MCP) client that connects to and communicates with an MCP server.
7 | ///
8 | public interface IMcpClient : IMcpEndpoint
9 | {
10 | ///
11 | /// Gets the capabilities supported by the connected server.
12 | ///
13 | /// The client is not connected.
14 | ServerCapabilities ServerCapabilities { get; }
15 |
16 | ///
17 | /// Gets the implementation information of the connected server.
18 | ///
19 | ///
20 | ///
21 | /// This property provides identification details about the connected server, including its name and version.
22 | /// It is populated during the initialization handshake and is available after a successful connection.
23 | ///
24 | ///
25 | /// This information can be useful for logging, debugging, compatibility checks, and displaying server
26 | /// information to users.
27 | ///
28 | ///
29 | /// The client is not connected.
30 | Implementation ServerInfo { get; }
31 |
32 | ///
33 | /// Gets any instructions describing how to use the connected server and its features.
34 | ///
35 | ///
36 | ///
37 | /// This property contains instructions provided by the server during initialization that explain
38 | /// how to effectively use its capabilities. These instructions can include details about available
39 | /// tools, expected input formats, limitations, or any other helpful information.
40 | ///
41 | ///
42 | /// This can be used by clients to improve an LLM's understanding of available tools, prompts, and resources.
43 | /// It can be thought of like a "hint" to the model and may be added to a system prompt.
44 | ///
45 | ///
46 | string? ServerInstructions { get; }
47 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Client/StreamClientTransport.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using ModelContextProtocol.Client;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Provides an implemented around a pair of input/output streams.
8 | ///
9 | ///
10 | /// This transport is useful for scenarios where you already have established streams for communication,
11 | /// such as custom network protocols, pipe connections, or for testing purposes. It works with any
12 | /// readable and writable streams.
13 | ///
14 | public sealed class StreamClientTransport : IClientTransport
15 | {
16 | private readonly Stream _serverInput;
17 | private readonly Stream _serverOutput;
18 | private readonly ILoggerFactory? _loggerFactory;
19 |
20 | ///
21 | /// Initializes a new instance of the class.
22 | ///
23 | ///
24 | /// The stream representing the connected server's input.
25 | /// Writes to this stream will be sent to the server.
26 | ///
27 | ///
28 | /// The stream representing the connected server's output.
29 | /// Reads from this stream will receive messages from the server.
30 | ///
31 | /// A logger factory for creating loggers.
32 | public StreamClientTransport(
33 | Stream serverInput, Stream serverOutput, ILoggerFactory? loggerFactory = null)
34 | {
35 | Throw.IfNull(serverInput);
36 | Throw.IfNull(serverOutput);
37 |
38 | _serverInput = serverInput;
39 | _serverOutput = serverOutput;
40 | _loggerFactory = loggerFactory;
41 | }
42 |
43 | ///
44 | public string Name => "in-memory-stream";
45 |
46 | ///
47 | public Task ConnectAsync(CancellationToken cancellationToken = default)
48 | {
49 | return Task.FromResult(new StreamClientSessionTransport(
50 | new StreamWriter(_serverInput),
51 | new StreamReader(_serverOutput),
52 | "Client (stream)",
53 | _loggerFactory));
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/McpErrorCode.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol;
2 |
3 | ///
4 | /// Represents standard JSON-RPC error codes as defined in the MCP specification.
5 | ///
6 | public enum McpErrorCode
7 | {
8 | ///
9 | /// Indicates that the JSON received could not be parsed.
10 | ///
11 | ///
12 | /// This error occurs when the input contains malformed JSON or incorrect syntax.
13 | ///
14 | ParseError = -32700,
15 |
16 | ///
17 | /// Indicates that the JSON payload does not conform to the expected Request object structure.
18 | ///
19 | ///
20 | /// The request is considered invalid if it lacks required fields or fails to follow the JSON-RPC protocol.
21 | ///
22 | InvalidRequest = -32600,
23 |
24 | ///
25 | /// Indicates that the requested method does not exist or is not available on the server.
26 | ///
27 | ///
28 | /// This error is returned when the method name specified in the request cannot be found.
29 | ///
30 | MethodNotFound = -32601,
31 |
32 | ///
33 | /// Indicates that one or more parameters provided in the request are invalid.
34 | ///
35 | ///
36 | /// This error is returned when the parameters do not match the expected method signature or constraints.
37 | /// This includes cases where required parameters are missing or not understood, such as when a name for
38 | /// a tool or prompt is not recognized.
39 | ///
40 | InvalidParams = -32602,
41 |
42 | ///
43 | /// Indicates that an internal error occurred while processing the request.
44 | ///
45 | ///
46 | /// This error is used when the endpoint encounters an unexpected condition that prevents it from fulfilling the request.
47 | ///
48 | InternalError = -32603,
49 | }
50 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0;net8.0;netstandard2.0
5 | true
6 | true
7 | ModelContextProtocol.Core
8 | Core .NET SDK for the Model Context Protocol (MCP)
9 | README.md
10 | preview
11 |
12 |
13 |
14 | true
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/NopProgress.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol;
2 |
3 | /// Provides an that's a nop.
4 | internal sealed class NullProgress : IProgress
5 | {
6 | ///
7 | /// Gets the singleton instance of the class that performs no operations when progress is reported.
8 | ///
9 | ///
10 | /// Use this property when you need to provide an implementation
11 | /// but don't need to track or report actual progress.
12 | ///
13 | public static NullProgress Instance { get; } = new();
14 |
15 | ///
16 | public void Report(ProgressNotificationValue value)
17 | {
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/ProgressNotificationValue.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol;
2 |
3 | /// Provides a progress value that can be sent using .
4 | public class ProgressNotificationValue
5 | {
6 | ///
7 | /// Gets or sets the progress thus far.
8 | ///
9 | ///
10 | ///
11 | /// This value typically represents either a percentage (0-100) or the number of items processed so far (when used with the property).
12 | ///
13 | ///
14 | /// When reporting progress, this value should increase monotonically as the operation proceeds.
15 | /// Values are typically between 0 and 100 when representing percentages, or can be any positive number
16 | /// when representing completed items in combination with the property.
17 | ///
18 | ///
19 | public required float Progress { get; init; }
20 |
21 | /// Gets or sets the total number of items to process (or total progress required), if known.
22 | public float? Total { get; init; }
23 |
24 | /// Gets or sets an optional message describing the current progress.
25 | public string? Message { get; init; }
26 | }
27 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/Annotations.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents annotations that can be attached to content, resources, and resource templates.
7 | ///
8 | ///
9 | /// Annotations enable filtering and prioritization of content for different audiences.
10 | /// See the schema for details.
11 | ///
12 | public class Annotations
13 | {
14 | ///
15 | /// Gets or sets the intended audience for this content as an array of values.
16 | ///
17 | [JsonPropertyName("audience")]
18 | public Role[]? Audience { get; init; }
19 |
20 | ///
21 | /// Gets or sets a value indicating how important this data is for operating the server.
22 | ///
23 | ///
24 | /// The value is a floating-point number between 0 and 1, where 0 represents the lowest priority
25 | /// 1 represents highest priority.
26 | ///
27 | [JsonPropertyName("priority")]
28 | public float? Priority { get; init; }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/Argument.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents an argument used in completion requests to provide context for auto-completion functionality.
7 | ///
8 | ///
9 | /// This class is used when requesting completion suggestions for a particular field or parameter.
10 | /// See the schema for details.
11 | ///
12 | public class Argument
13 | {
14 | ///
15 | /// Gets or sets the name of the argument being completed.
16 | ///
17 | [JsonPropertyName("name")]
18 | public string Name { get; set; } = string.Empty;
19 |
20 | ///
21 | /// Gets or sets the current partial text value for which completion suggestions are requested.
22 | ///
23 | ///
24 | /// This represents the text that has been entered so far and for which completion
25 | /// options should be generated.
26 | ///
27 | [JsonPropertyName("value")]
28 | public string Value { get; set; } = string.Empty;
29 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/BlobResourceContents.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents the binary contents of a resource in the Model Context Protocol.
7 | ///
8 | ///
9 | ///
10 | /// is used when binary data needs to be exchanged through
11 | /// the Model Context Protocol. The binary data is represented as a base64-encoded string
12 | /// in the property.
13 | ///
14 | ///
15 | /// This class inherits from , which also has a sibling implementation
16 | /// for text-based resources. When working with resources, the
17 | /// appropriate type is chosen based on the nature of the content.
18 | ///
19 | ///
20 | /// See the schema for more details.
21 | ///
22 | ///
23 | public class BlobResourceContents : ResourceContents
24 | {
25 | ///
26 | /// Gets or sets the base64-encoded string representing the binary data of the item.
27 | ///
28 | [JsonPropertyName("blob")]
29 | public string Blob { get; set; } = string.Empty;
30 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/CallToolRequestParams.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents the parameters used with a request from a client to invoke a tool provided by the server.
8 | ///
9 | ///
10 | /// The server will respond with a containing the result of the tool invocation.
11 | /// See the schema for details.
12 | ///
13 | public class CallToolRequestParams : RequestParams
14 | {
15 | /// Gets or sets the name of the tool to invoke.
16 | [JsonPropertyName("name")]
17 | public required string Name { get; init; }
18 |
19 | ///
20 | /// Gets or sets optional arguments to pass to the tool when invoking it on the server.
21 | ///
22 | ///
23 | /// This dictionary contains the parameter values to be passed to the tool. Each key-value pair represents
24 | /// a parameter name and its corresponding argument value.
25 | ///
26 | [JsonPropertyName("arguments")]
27 | public IReadOnlyDictionary? Arguments { get; init; }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/CallToolResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Nodes;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents the result of a request from a client to invoke a tool provided by the server.
8 | ///
9 | ///
10 | ///
11 | /// Any errors that originate from the tool should be reported inside the result
12 | /// object, with set to true, rather than as a .
13 | ///
14 | ///
15 | /// However, any errors in finding the tool, an error indicating that the
16 | /// server does not support tool calls, or any other exceptional conditions,
17 | /// should be reported as an MCP error response.
18 | ///
19 | ///
20 | /// See the schema for details.
21 | ///
22 | ///
23 | public class CallToolResponse
24 | {
25 | ///
26 | /// Gets or sets the response content from the tool call.
27 | ///
28 | [JsonPropertyName("content")]
29 | public List Content { get; set; } = [];
30 |
31 | ///
32 | /// Gets or sets an optional JSON object representing the structured result of the tool call.
33 | ///
34 | [JsonPropertyName("structuredContent")]
35 | public JsonNode? StructuredContent { get; set; }
36 |
37 | ///
38 | /// Gets or sets an indication of whether the tool call was unsuccessful.
39 | ///
40 | ///
41 | /// When set to , it signifies that the tool execution failed.
42 | /// Tool errors are reported with this property set to and details in the
43 | /// property, rather than as protocol-level errors. This allows LLMs to see that an error occurred
44 | /// and potentially self-correct in subsequent requests.
45 | ///
46 | [JsonPropertyName("isError")]
47 | public bool IsError { get; set; }
48 | }
49 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/CancelledNotification.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a notification indicating that a request has been cancelled by the client,
7 | /// and that any associated processing should cease immediately.
8 | ///
9 | ///
10 | /// This class is typically used in conjunction with the
11 | /// method identifier. When a client sends this notification, the server should attempt to
12 | /// cancel any ongoing operations associated with the specified request ID.
13 | ///
14 | public sealed class CancelledNotification
15 | {
16 | ///
17 | /// Gets or sets the ID of the request to cancel.
18 | ///
19 | ///
20 | /// This must match the ID of an in-flight request that the sender wishes to cancel.
21 | ///
22 | [JsonPropertyName("requestId")]
23 | public RequestId RequestId { get; set; }
24 |
25 | ///
26 | /// Gets or sets an optional string describing the reason for the cancellation request.
27 | ///
28 | [JsonPropertyName("reason")]
29 | public string? Reason { get; set; }
30 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/CompleteContext.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents additional context information for completion requests.
7 | ///
8 | ///
9 | /// This context provides information that helps the server generate more relevant
10 | /// completion suggestions, such as previously resolved variables in a template.
11 | ///
12 | public class CompleteContext
13 | {
14 | ///
15 | /// Gets or sets previously-resolved variables in a URI template or prompt.
16 | ///
17 | [JsonPropertyName("arguments")]
18 | public IDictionary? Arguments { get; init; }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/CompleteRequestParams.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents the parameters used with a request from
7 | /// a client to ask a server for auto-completion suggestions.
8 | ///
9 | ///
10 | ///
11 | /// is used in the Model Context Protocol completion workflow
12 | /// to provide intelligent suggestions for partial inputs related to resources, prompts, or other referenceable entities.
13 | /// The completion mechanism in MCP allows clients to request suggestions based on partial inputs.
14 | /// The server will respond with a containing matching values.
15 | ///
16 | ///
17 | /// See the schema for details.
18 | ///
19 | ///
20 | public class CompleteRequestParams : RequestParams
21 | {
22 | ///
23 | /// Gets or sets the reference's information.
24 | ///
25 | [JsonPropertyName("ref")]
26 | public required Reference Ref { get; init; }
27 |
28 | ///
29 | /// Gets or sets the argument information for the completion request, specifying what is being completed
30 | /// and the current partial input.
31 | ///
32 | [JsonPropertyName("argument")]
33 | public required Argument Argument { get; init; }
34 |
35 | ///
36 | /// Gets or sets additional, optional context for completions.
37 | ///
38 | [JsonPropertyName("context")]
39 | public CompleteContext? Context { get; init; }
40 | }
41 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/CompleteResult.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents the server's response to a request,
7 | /// containing suggested values for a given argument.
8 | ///
9 | ///
10 | ///
11 | /// is returned by the server in response to a
12 | /// request from the client. It provides suggested completions or valid values for a specific argument in a tool or resource reference.
13 | ///
14 | ///
15 | /// The result contains a object with suggested values, pagination information,
16 | /// and the total number of available completions. This is similar to auto-completion functionality in code editors.
17 | ///
18 | ///
19 | /// Clients typically use this to implement auto-suggestion features when users are inputting parameters
20 | /// for tool calls or resource references.
21 | ///
22 | ///
23 | /// See the schema for details.
24 | ///
25 | ///
26 | public class CompleteResult
27 | {
28 | ///
29 | /// Gets or sets the completion object containing the suggested values and pagination information.
30 | ///
31 | ///
32 | /// If no completions are available for the given input, the
33 | /// collection will be empty.
34 | ///
35 | [JsonPropertyName("completion")]
36 | public Completion Completion { get; set; } = new Completion();
37 | }
38 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/Completion.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a completion object in the server's response to a request.
7 | ///
8 | ///
9 | /// See the schema for details.
10 | ///
11 | public class Completion
12 | {
13 | ///
14 | /// Gets or sets an array of completion values (auto-suggestions) for the requested input.
15 | ///
16 | ///
17 | /// This collection contains the actual text strings to be presented to users as completion suggestions.
18 | /// The array will be empty if no suggestions are available for the current input.
19 | /// Per the specification, this should not exceed 100 items.
20 | ///
21 | [JsonPropertyName("values")]
22 | public string[] Values { get; set; } = [];
23 |
24 | ///
25 | /// Gets or sets the total number of completion options available.
26 | ///
27 | ///
28 | /// This can exceed the number of values actually sent in the response.
29 | ///
30 | [JsonPropertyName("total")]
31 | public int? Total { get; set; }
32 |
33 | ///
34 | /// Gets or sets an indicator as to whether there are additional completion options beyond
35 | /// those provided in the current response, even if the exact total is unknown.
36 | ///
37 | [JsonPropertyName("hasMore")]
38 | public bool? HasMore { get; set; }
39 | }
40 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/CompletionsCapability.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents the completions capability for providing auto-completion suggestions
8 | /// for prompt arguments and resource references.
9 | ///
10 | ///
11 | ///
12 | /// When enabled, this capability allows a Model Context Protocol server to provide
13 | /// auto-completion suggestions. This capability is advertised to clients during the initialize handshake.
14 | ///
15 | ///
16 | /// The primary function of this capability is to improve the user experience by offering
17 | /// contextual suggestions for argument values or resource identifiers based on partial input.
18 | ///
19 | ///
20 | /// See the schema for details.
21 | ///
22 | ///
23 | public class CompletionsCapability
24 | {
25 | // Currently empty in the spec, but may be extended in the future.
26 |
27 | ///
28 | /// Gets or sets the handler for completion requests.
29 | ///
30 | ///
31 | /// This handler provides auto-completion suggestions for prompt arguments or resource references in the Model Context Protocol.
32 | /// The handler receives a reference type (e.g., "ref/prompt" or "ref/resource") and the current argument value,
33 | /// and should return appropriate completion suggestions.
34 | ///
35 | [JsonIgnore]
36 | public Func, CancellationToken, ValueTask>? CompleteHandler { get; set; }
37 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ContextInclusion.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Specifies the context inclusion options for a request in the Model Context Protocol (MCP).
7 | ///
8 | ///
9 | /// See the schema for details.
10 | ///
11 | [JsonConverter(typeof(CustomizableJsonStringEnumConverter))]
12 | public enum ContextInclusion
13 | {
14 | ///
15 | /// Indicates that no context should be included.
16 | ///
17 | [JsonStringEnumMemberName("none")]
18 | None,
19 |
20 | ///
21 | /// Indicates that context from the server that sent the request should be included.
22 | ///
23 | [JsonStringEnumMemberName("thisServer")]
24 | ThisServer,
25 |
26 | ///
27 | /// Indicates that context from all servers that the client is connected to should be included.
28 | ///
29 | [JsonStringEnumMemberName("allServers")]
30 | AllServers
31 | }
32 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/CreateMessageResult.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a client's response to a from the server.
7 | ///
8 | ///
9 | /// See the schema for details.
10 | ///
11 | public class CreateMessageResult
12 | {
13 | ///
14 | /// Gets or sets the content of the message.
15 | ///
16 | [JsonPropertyName("content")]
17 | public required Content Content { get; init; }
18 |
19 | ///
20 | /// Gets or sets the name of the model that generated the message.
21 | ///
22 | ///
23 | ///
24 | /// This should contain the specific model identifier such as "claude-3-5-sonnet-20241022" or "o3-mini".
25 | ///
26 | ///
27 | /// This property allows the server to know which model was used to generate the response,
28 | /// enabling appropriate handling based on the model's capabilities and characteristics.
29 | ///
30 | ///
31 | [JsonPropertyName("model")]
32 | public required string Model { get; init; }
33 |
34 | ///
35 | /// Gets or sets the reason why message generation (sampling) stopped, if known.
36 | ///
37 | ///
38 | /// Common values include:
39 | ///
40 | /// - endTurnThe model naturally completed its response.
41 | /// - maxTokensThe response was truncated due to reaching token limits.
42 | /// - stopSequenceA specific stop sequence was encountered during generation.
43 | ///
44 | ///
45 | [JsonPropertyName("stopReason")]
46 | public string? StopReason { get; init; }
47 |
48 | ///
49 | /// Gets or sets the role of the user who generated the message.
50 | ///
51 | [JsonPropertyName("role")]
52 | public required Role Role { get; init; }
53 | }
54 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ElicitResult.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents the client's response to an elicitation request.
8 | ///
9 | public class ElicitResult
10 | {
11 | ///
12 | /// Gets or sets the user action in response to the elicitation.
13 | ///
14 | ///
15 | ///
16 | /// -
17 | /// "accept"
18 | /// User submitted the form/confirmed the action
19 | ///
20 | /// -
21 | /// "decline"
22 | /// User explicitly declined the action
23 | ///
24 | /// -
25 | /// "cancel"
26 | /// User dismissed without making an explicit choice
27 | ///
28 | ///
29 | ///
30 | [JsonPropertyName("action")]
31 | public string Action { get; set; } = "cancel";
32 |
33 | ///
34 | /// Gets or sets the submitted form data.
35 | ///
36 | ///
37 | /// This is typically omitted if the action is "cancel" or "decline".
38 | ///
39 | [JsonPropertyName("content")]
40 | public JsonElement? Content { get; set; }
41 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ElicitationCapability.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents the capability for a client to provide server-requested additional information during interactions.
7 | ///
8 | ///
9 | ///
10 | /// This capability enables the MCP client to respond to elicitation requests from an MCP server.
11 | ///
12 | ///
13 | /// When this capability is enabled, an MCP server can request the client to provide additional information
14 | /// during interactions. The client must set a to process these requests.
15 | ///
16 | ///
17 | public class ElicitationCapability
18 | {
19 | // Currently empty in the spec, but may be extended in the future.
20 |
21 | ///
22 | /// Gets or sets the handler for processing requests.
23 | ///
24 | ///
25 | ///
26 | /// This handler function is called when an MCP server requests the client to provide additional
27 | /// information during interactions. The client must set this property for the elicitation capability to work.
28 | ///
29 | ///
30 | /// The handler receives message parameters and a cancellation token.
31 | /// It should return a containing the response to the elicitation request.
32 | ///
33 | ///
34 | [JsonIgnore]
35 | public Func>? ElicitationHandler { get; set; }
36 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/EmptyResult.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents an empty result object for operations that need to indicate successful completion
7 | /// but don't need to return any specific data.
8 | ///
9 | public class EmptyResult
10 | {
11 | [JsonIgnore]
12 | internal static EmptyResult Instance { get; } = new();
13 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/GetPromptRequestParams.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents the parameters used with a request from a client to get a prompt provided by a server.
8 | ///
9 | ///
10 | /// The server will respond with a containing the resulting prompt.
11 | /// See the schema for details.
12 | ///
13 | public class GetPromptRequestParams : RequestParams
14 | {
15 | ///
16 | /// Gets or sets the name of the prompt.
17 | ///
18 | [JsonPropertyName("name")]
19 | public required string Name { get; init; }
20 |
21 | ///
22 | /// Gets or sets arguments to use for templating the prompt when retrieving it from the server.
23 | ///
24 | ///
25 | /// Typically, these arguments are used to replace placeholders in prompt templates. The keys in this dictionary
26 | /// should match the names defined in the prompt's list. However, the server may
27 | /// choose to use these arguments in any way it deems appropriate to generate the prompt.
28 | ///
29 | [JsonPropertyName("arguments")]
30 | public IReadOnlyDictionary? Arguments { get; init; }
31 | }
32 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/GetPromptResult.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.AI;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents a server's response to a request from the client.
8 | ///
9 | ///
10 | ///
11 | /// For integration with AI client libraries, can be converted to
12 | /// a collection of objects using the extension method.
13 | ///
14 | ///
15 | /// See the schema for details.
16 | ///
17 | ///
18 | public class GetPromptResult
19 | {
20 | ///
21 | /// Gets or sets an optional description for the prompt.
22 | ///
23 | ///
24 | ///
25 | /// This description provides contextual information about the prompt's purpose and use cases.
26 | /// It helps developers understand what the prompt is designed for and how it should be used.
27 | ///
28 | ///
29 | /// When returned from a server in response to a request,
30 | /// this description can be used by client applications to provide context about the prompt or to
31 | /// display in user interfaces.
32 | ///
33 | ///
34 | [JsonPropertyName("description")]
35 | public string? Description { get; set; }
36 |
37 | ///
38 | /// Gets or sets the prompt that the server offers.
39 | ///
40 | [JsonPropertyName("messages")]
41 | public List Messages { get; set; } = [];
42 | }
43 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/Implementation.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Provides the name and version of an MCP implementation.
7 | ///
8 | ///
9 | ///
10 | /// The class is used to identify MCP clients and servers during the initialization handshake.
11 | /// It provides version and name information that can be used for compatibility checks, logging, and debugging.
12 | ///
13 | ///
14 | /// Both clients and servers provide this information during connection establishment.
15 | ///
16 | ///
17 | /// See the schema for details.
18 | ///
19 | ///
20 | public class Implementation
21 | {
22 | ///
23 | /// Gets or sets the name of the implementation.
24 | ///
25 | ///
26 | /// This is typically the name of the client or server library/application.
27 | ///
28 | [JsonPropertyName("name")]
29 | public required string Name { get; set; }
30 |
31 | ///
32 | /// Gets or sets the version of the implementation.
33 | ///
34 | ///
35 | /// The version is used during client-server handshake to identify implementation versions,
36 | /// which can be important for troubleshooting compatibility issues or when reporting bugs.
37 | ///
38 | [JsonPropertyName("version")]
39 | public required string Version { get; set; }
40 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/JsonRpcError.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents an error response message in the JSON-RPC protocol.
7 | ///
8 | ///
9 | ///
10 | /// Error responses are sent when a request cannot be fulfilled or encounters an error during processing.
11 | /// Like successful responses, error messages include the same ID as the original request, allowing the
12 | /// sender to match errors with their corresponding requests.
13 | ///
14 | ///
15 | /// Each error response contains a structured error detail object with a numeric code, descriptive message,
16 | /// and optional additional data to provide more context about the error.
17 | ///
18 | ///
19 | public class JsonRpcError : JsonRpcMessageWithId
20 | {
21 | ///
22 | /// Gets detailed error information for the failed request, containing an error code,
23 | /// message, and optional additional data
24 | ///
25 | [JsonPropertyName("error")]
26 | public required JsonRpcErrorDetail Error { get; init; }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/JsonRpcErrorDetail.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents detailed error information for JSON-RPC error responses.
7 | ///
8 | ///
9 | /// This class is used as part of the message to provide structured
10 | /// error information when a request cannot be fulfilled. The JSON-RPC 2.0 specification defines
11 | /// a standard format for error responses that includes a numeric code, a human-readable message,
12 | /// and optional additional data.
13 | ///
14 | public class JsonRpcErrorDetail
15 | {
16 | ///
17 | /// Gets an integer error code according to the JSON-RPC specification.
18 | ///
19 | [JsonPropertyName("code")]
20 | public required int Code { get; init; }
21 |
22 | ///
23 | /// Gets a short description of the error.
24 | ///
25 | ///
26 | /// This is expected to be a brief, human-readable explanation of what went wrong.
27 | /// For standard error codes, it's recommended to use the descriptions defined
28 | /// in the JSON-RPC 2.0 specification.
29 | ///
30 | [JsonPropertyName("message")]
31 | public required string Message { get; init; }
32 |
33 | ///
34 | /// Gets optional additional error data.
35 | ///
36 | ///
37 | /// This property can contain any additional information that might help the client
38 | /// understand or resolve the error. Common examples include validation errors,
39 | /// stack traces (in development environments), or contextual information about
40 | /// the error condition.
41 | ///
42 | [JsonPropertyName("data")]
43 | public object? Data { get; init; }
44 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/JsonRpcMessageWithId.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a JSON-RPC message used in the Model Context Protocol (MCP) and that includes an ID.
7 | ///
8 | ///
9 | /// In the JSON-RPC protocol, messages with an ID require a response from the receiver.
10 | /// This includes request messages (which expect a matching response) and response messages
11 | /// (which include the ID of the original request they're responding to).
12 | /// The ID is used to correlate requests with their responses, allowing asynchronous
13 | /// communication where multiple requests can be sent without waiting for responses.
14 | ///
15 | public abstract class JsonRpcMessageWithId : JsonRpcMessage
16 | {
17 | ///
18 | /// Gets the message identifier.
19 | ///
20 | ///
21 | /// Each ID is expected to be unique within the context of a given session.
22 | ///
23 | [JsonPropertyName("id")]
24 | public RequestId Id { get; init; }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/JsonRpcNotification.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Nodes;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents a notification message in the JSON-RPC protocol.
8 | ///
9 | ///
10 | /// Notifications are messages that do not require a response and are not matched with a response message.
11 | /// They are useful for one-way communication, such as log notifications and progress updates.
12 | /// Unlike requests, notifications do not include an ID field, since there will be no response to match with it.
13 | ///
14 | public class JsonRpcNotification : JsonRpcMessage
15 | {
16 | ///
17 | /// Gets or sets the name of the notification method.
18 | ///
19 | [JsonPropertyName("method")]
20 | public required string Method { get; init; }
21 |
22 | ///
23 | /// Gets or sets optional parameters for the notification.
24 | ///
25 | [JsonPropertyName("params")]
26 | public JsonNode? Params { get; init; }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/JsonRpcRequest.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Nodes;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// A request message in the JSON-RPC protocol.
8 | ///
9 | ///
10 | /// Requests are messages that require a response from the receiver. Each request includes a unique ID
11 | /// that will be included in the corresponding response message (either a success response or an error).
12 | ///
13 | /// The receiver of a request message is expected to execute the specified method with the provided parameters
14 | /// and return either a with the result, or a
15 | /// if the method execution fails.
16 | ///
17 | public class JsonRpcRequest : JsonRpcMessageWithId
18 | {
19 | ///
20 | /// Name of the method to invoke.
21 | ///
22 | [JsonPropertyName("method")]
23 | public required string Method { get; init; }
24 |
25 | ///
26 | /// Optional parameters for the method.
27 | ///
28 | [JsonPropertyName("params")]
29 | public JsonNode? Params { get; init; }
30 |
31 | internal JsonRpcRequest WithId(RequestId id)
32 | {
33 | return new JsonRpcRequest
34 | {
35 | JsonRpc = JsonRpc,
36 | Id = id,
37 | Method = Method,
38 | Params = Params,
39 | RelatedTransport = RelatedTransport,
40 | };
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/JsonRpcResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Nodes;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// A successful response message in the JSON-RPC protocol.
8 | ///
9 | ///
10 | ///
11 | /// Response messages are sent in reply to a request message and contain the result of the method execution.
12 | /// Each response includes the same ID as the original request, allowing the sender to match responses
13 | /// with their corresponding requests.
14 | ///
15 | ///
16 | /// This class represents a successful response with a result. For error responses, see .
17 | ///
18 | ///
19 | public class JsonRpcResponse : JsonRpcMessageWithId
20 | {
21 | ///
22 | /// Gets the result of the method invocation.
23 | ///
24 | ///
25 | /// This property contains the result data returned by the server in response to the JSON-RPC method request.
26 | ///
27 | [JsonPropertyName("result")]
28 | public required JsonNode? Result { get; init; }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ListPromptsRequestParams.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Protocol;
2 |
3 | ///
4 | /// Represents the parameters used with a request from a client to request
5 | /// a list of prompts available from the server.
6 | ///
7 | ///
8 | /// The server responds with a containing the available prompts.
9 | /// See the schema for details.
10 | ///
11 | public class ListPromptsRequestParams : PaginatedRequestParams;
12 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ListPromptsResult.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a server's response to a request from the client, containing available prompts.
7 | ///
8 | ///
9 | ///
10 | /// This result is returned when a client sends a request to discover available prompts on the server.
11 | ///
12 | ///
13 | /// It inherits from , allowing for paginated responses when there are many prompts.
14 | /// The server can provide the property to indicate there are more
15 | /// prompts available beyond what was returned in the current response.
16 | ///
17 | ///
18 | /// See the schema for details.
19 | ///
20 | ///
21 | public class ListPromptsResult : PaginatedResult
22 | {
23 | ///
24 | /// A list of prompts or prompt templates that the server offers.
25 | ///
26 | [JsonPropertyName("prompts")]
27 | public List Prompts { get; set; } = [];
28 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ListResourceTemplatesRequestParams.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Protocol;
2 |
3 | ///
4 | /// Represents the parameters used with a request from a client to request
5 | /// a list of resource templates available from the server.
6 | ///
7 | ///
8 | /// The server responds with a containing the available resource templates.
9 | /// See the schema for details.
10 | ///
11 | public class ListResourceTemplatesRequestParams : PaginatedRequestParams;
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ListResourceTemplatesResult.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a server's response to a request from the client,
7 | /// containing available resource templates.
8 | ///
9 | ///
10 | ///
11 | /// This result is returned when a client sends a request to discover
12 | /// available resource templates on the server.
13 | ///
14 | ///
15 | /// It inherits from , allowing for paginated responses when there are many resource templates.
16 | /// The server can provide the property to indicate there are more
17 | /// resource templates available beyond what was returned in the current response.
18 | ///
19 | ///
20 | /// See the schema for details.
21 | ///
22 | ///
23 | public class ListResourceTemplatesResult : PaginatedResult
24 | {
25 | ///
26 | /// Gets or sets a list of resource templates that the server offers.
27 | ///
28 | ///
29 | /// This collection contains all the resource templates returned in the current page of results.
30 | /// Each provides metadata about resources available on the server,
31 | /// including URI templates, names, descriptions, and MIME types.
32 | ///
33 | [JsonPropertyName("resourceTemplates")]
34 | public List ResourceTemplates { get; set; } = [];
35 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ListResourcesRequestParams.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Protocol;
2 |
3 | ///
4 | /// Represents the parameters used with a request from a client to request
5 | /// a list of resources available from the server.
6 | ///
7 | ///
8 | /// The server responds with a containing the available resources.
9 | /// See the schema for details.
10 | ///
11 | public class ListResourcesRequestParams : PaginatedRequestParams;
12 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ListResourcesResult.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a server's response to a request from the client, containing available resources.
7 | ///
8 | ///
9 | ///
10 | /// This result is returned when a client sends a request to discover available resources on the server.
11 | ///
12 | ///
13 | /// It inherits from , allowing for paginated responses when there are many resources.
14 | /// The server can provide the property to indicate there are more
15 | /// resources available beyond what was returned in the current response.
16 | ///
17 | ///
18 | /// See the schema for details.
19 | ///
20 | ///
21 | public class ListResourcesResult : PaginatedResult
22 | {
23 | ///
24 | /// A list of resources that the server offers.
25 | ///
26 | [JsonPropertyName("resources")]
27 | public List Resources { get; set; } = [];
28 | }
29 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ListRootsRequestParams.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Protocol;
2 |
3 | ///
4 | /// Represents the parameters used with a request from a server to request
5 | /// a list of roots available from the client.
6 | ///
7 | ///
8 | /// The client responds with a containing the client's roots.
9 | /// See the schema for details.
10 | ///
11 | public class ListRootsRequestParams : RequestParams;
12 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ListRootsResult.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents a client's response to a request from the server,
8 | /// containing available roots.
9 | ///
10 | ///
11 | ///
12 | /// This result is returned when a server sends a request to discover
13 | /// available roots on the client.
14 | ///
15 | ///
16 | /// See the schema for details.
17 | ///
18 | ///
19 | public class ListRootsResult
20 | {
21 | ///
22 | /// Gets or sets additional metadata for the result.
23 | ///
24 | ///
25 | /// This property is reserved by the protocol for future use.
26 | ///
27 | [JsonPropertyName("meta")]
28 | public JsonElement? Meta { get; init; }
29 |
30 | ///
31 | /// Gets or sets the list of root URIs provided by the client.
32 | ///
33 | ///
34 | /// This collection contains all available root URIs and their associated metadata.
35 | /// Each root serves as an entry point for resource navigation in the Model Context Protocol.
36 | ///
37 | [JsonPropertyName("roots")]
38 | public required IReadOnlyList Roots { get; init; }
39 | }
40 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ListToolsRequestParams.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Protocol;
2 |
3 | ///
4 | /// Represents the parameters used with a request from a client to request
5 | /// a list of tools available from the server.
6 | ///
7 | ///
8 | /// The server responds with a containing the available tools.
9 | /// See the schema for details.
10 | ///
11 | public class ListToolsRequestParams : PaginatedRequestParams;
12 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ListToolsResult.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a server's response to a request from the client, containing available tools.
7 | ///
8 | ///
9 | ///
10 | /// This result is returned when a client sends a request to discover available tools on the server.
11 | ///
12 | ///
13 | /// It inherits from , allowing for paginated responses when there are many tools.
14 | /// The server can provide the property to indicate there are more
15 | /// tools available beyond what was returned in the current response.
16 | ///
17 | ///
18 | /// See the schema for details.
19 | ///
20 | ///
21 | public class ListToolsResult : PaginatedResult
22 | {
23 | ///
24 | /// The server's response to a tools/list request from the client.
25 | ///
26 | [JsonPropertyName("tools")]
27 | public List Tools { get; set; } = [];
28 | }
29 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/LoggingCapability.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents the logging capability configuration for a Model Context Protocol server.
8 | ///
9 | ///
10 | /// This capability allows clients to set the logging level and receive log messages from the server.
11 | /// See the schema for details.
12 | ///
13 | public class LoggingCapability
14 | {
15 | // Currently empty in the spec, but may be extended in the future
16 |
17 | ///
18 | /// Gets or sets the handler for set logging level requests from clients.
19 | ///
20 | [JsonIgnore]
21 | public Func, CancellationToken, ValueTask>? SetLoggingLevelHandler { get; set; }
22 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/LoggingLevel.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Indicates the severity of a log message.
7 | ///
8 | ///
9 | /// These map to syslog message severities, as specified in RFC-5424.
10 | ///
11 | [JsonConverter(typeof(CustomizableJsonStringEnumConverter))]
12 | public enum LoggingLevel
13 | {
14 | /// Detailed debug information, typically only valuable to developers.
15 | [JsonStringEnumMemberName("debug")]
16 | Debug,
17 |
18 | /// Normal operational messages that require no action.
19 | [JsonStringEnumMemberName("info")]
20 | Info,
21 |
22 | /// Normal but significant events that might deserve attention.
23 | [JsonStringEnumMemberName("notice")]
24 | Notice,
25 |
26 | /// Warning conditions that don't represent an error but indicate potential issues.
27 | [JsonStringEnumMemberName("warning")]
28 | Warning,
29 |
30 | /// Error conditions that should be addressed but don't require immediate action.
31 | [JsonStringEnumMemberName("error")]
32 | Error,
33 |
34 | /// Critical conditions that require immediate attention.
35 | [JsonStringEnumMemberName("critical")]
36 | Critical,
37 |
38 | /// Action must be taken immediately to address the condition.
39 | [JsonStringEnumMemberName("alert")]
40 | Alert,
41 |
42 | /// System is unusable and requires immediate attention.
43 | [JsonStringEnumMemberName("emergency")]
44 | Emergency
45 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/LoggingMessageNotificationParams.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents the parameters used with a
8 | /// notification sent whenever a log message is generated.
9 | ///
10 | ///
11 | ///
12 | /// Logging notifications allow servers to communicate diagnostic information to clients with varying severity levels.
13 | /// Clients can filter these messages based on the and properties.
14 | ///
15 | ///
16 | /// If no request has been sent from the client, the server may decide which
17 | /// messages to send automatically.
18 | ///
19 | ///
20 | /// See the schema for details.
21 | ///
22 | ///
23 | public class LoggingMessageNotificationParams
24 | {
25 | ///
26 | /// Gets or sets the severity of this log message.
27 | ///
28 | [JsonPropertyName("level")]
29 | public LoggingLevel Level { get; init; }
30 |
31 | ///
32 | /// Gets or sets an optional name of the logger issuing this message.
33 | ///
34 | ///
35 | ///
36 | /// typically represents a category or component in the server's logging system.
37 | /// The logger name is useful for filtering and routing log messages in client applications.
38 | ///
39 | ///
40 | /// When implementing custom servers, choose clear, hierarchical logger names to help
41 | /// clients understand the source of log messages.
42 | ///
43 | ///
44 | [JsonPropertyName("logger")]
45 | public string? Logger { get; init; }
46 |
47 | ///
48 | /// Gets or sets the data to be logged, such as a string message.
49 | ///
50 | [JsonPropertyName("data")]
51 | public JsonElement? Data { get; init; }
52 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ModelHint.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Provides hints to use for model selection.
7 | ///
8 | ///
9 | ///
10 | /// When multiple hints are specified in , they are evaluated in order,
11 | /// with the first match taking precedence. Clients should prioritize these hints over numeric priorities.
12 | ///
13 | ///
14 | /// See the schema for details.
15 | ///
16 | ///
17 | public class ModelHint
18 | {
19 | ///
20 | /// Gets or sets a hint for a model name.
21 | ///
22 | ///
23 | /// The specified string can be a partial or full model name. Clients may also
24 | /// map hints to equivalent models from different providers. Clients make the final model
25 | /// selection based on these preferences and their available models.
26 | ///
27 | [JsonPropertyName("name")]
28 | public string? Name { get; init; }
29 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/PaginatedRequest.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Provides a base class for paginated requests.
7 | ///
8 | ///
9 | /// See the schema for details
10 | ///
11 | public class PaginatedRequestParams : RequestParams
12 | {
13 | ///
14 | /// Gets or sets an opaque token representing the current pagination position.
15 | ///
16 | ///
17 | /// If provided, the server should return results starting after this cursor.
18 | /// This value should be obtained from the
19 | /// property of a previous request's response.
20 | ///
21 | [JsonPropertyName("cursor")]
22 | public string? Cursor { get; init; }
23 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/PaginatedResult.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Protocol;
2 |
3 | ///
4 | /// Provides a base class for result payloads that support cursor-based pagination.
5 | ///
6 | ///
7 | ///
8 | /// Pagination allows API responses to be broken into smaller, manageable chunks when
9 | /// there are potentially many results to return or when dynamically-computed results
10 | /// may incur measurable latency.
11 | ///
12 | ///
13 | /// Classes that inherit from implement cursor-based pagination,
14 | /// where the property serves as an opaque token pointing to the next
15 | /// set of results.
16 | ///
17 | ///
18 | public class PaginatedResult
19 | {
20 | ///
21 | /// Gets or sets an opaque token representing the pagination position after the last returned result.
22 | ///
23 | ///
24 | /// When a paginated result has more data available, the
25 | /// property will contain a non- token that can be used in subsequent requests
26 | /// to fetch the next page. When there are no more results to return, the property
27 | /// will be .
28 | ///
29 | public string? NextCursor { get; set; }
30 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/PingResult.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Protocol;
2 |
3 | ///
4 | /// Represents the result of a request in the Model Context Protocol.
5 | ///
6 | ///
7 | ///
8 | /// The is returned in response to a request,
9 | /// which is used to verify that the connection between client and server is still alive and responsive.
10 | /// Since this is a simple connectivity check, the result is an empty object containing no data.
11 | ///
12 | ///
13 | /// Ping requests can be initiated by either the client or the server to check if the other party
14 | /// is still responsive.
15 | ///
16 | ///
17 | public class PingResult;
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/Prompt.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a prompt that the server offers.
7 | ///
8 | ///
9 | /// See the schema for details.
10 | ///
11 | public class Prompt
12 | {
13 | ///
14 | /// Gets or sets a list of arguments that this prompt accepts for templating and customization.
15 | ///
16 | ///
17 | ///
18 | /// This list defines the arguments that can be provided when requesting the prompt.
19 | /// Each argument specifies metadata like name, description, and whether it's required.
20 | ///
21 | ///
22 | /// When a client makes a request, it can provide values for these arguments
23 | /// which will be substituted into the prompt template or otherwise used to render the prompt.
24 | ///
25 | ///
26 | [JsonPropertyName("arguments")]
27 | public List? Arguments { get; set; }
28 |
29 | ///
30 | /// Gets or sets an optional description of what this prompt provides.
31 | ///
32 | ///
33 | ///
34 | /// This description helps developers understand the purpose and use cases for the prompt.
35 | /// It should explain what the prompt is designed to accomplish and any important context.
36 | ///
37 | ///
38 | /// The description is typically used in documentation, UI displays, and for providing context
39 | /// to client applications that may need to choose between multiple available prompts.
40 | ///
41 | ///
42 | [JsonPropertyName("description")]
43 | public string? Description { get; set; }
44 |
45 | ///
46 | /// Gets or sets the name of the prompt.
47 | ///
48 | [JsonPropertyName("name")]
49 | public string Name { get; set; } = string.Empty;
50 | }
51 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/PromptArgument.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents an argument that a prompt can accept for templating and customization.
7 | ///
8 | ///
9 | ///
10 | /// The class defines metadata for arguments that can be provided
11 | /// to a prompt. These arguments are used to customize or parameterize prompts when they are
12 | /// retrieved using requests.
13 | ///
14 | ///
15 | /// See the schema for details.
16 | ///
17 | ///
18 | public class PromptArgument
19 | {
20 | ///
21 | /// Gets or sets the name of the argument used for referencing in prompt templates.
22 | ///
23 | [JsonPropertyName("name")]
24 | public string Name { get; set; } = string.Empty;
25 |
26 | ///
27 | /// Gets or sets a human-readable description of the argument's purpose and expected values.
28 | ///
29 | ///
30 | /// This description helps developers understand what information should be provided
31 | /// for this argument and how it will affect the generated prompt.
32 | ///
33 | [JsonPropertyName("description")]
34 | public string? Description { get; set; } = string.Empty;
35 |
36 | ///
37 | /// Gets or sets an indication as to whether this argument must be provided when requesting the prompt.
38 | ///
39 | ///
40 | /// When set to , the client must include this argument when making a request.
41 | /// If a required argument is missing, the server should respond with an error.
42 | ///
43 | [JsonPropertyName("required")]
44 | public bool? Required { get; set; }
45 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ReadResourceRequestParams.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents the parameters used with a request from a client to get a resource provided by a server.
7 | ///
8 | ///
9 | /// The server will respond with a containing the resulting resource data.
10 | /// See the schema for details.
11 | ///
12 | public class ReadResourceRequestParams : RequestParams
13 | {
14 | ///
15 | /// The URI of the resource to read. The URI can use any protocol; it is up to the server how to interpret it.
16 | ///
17 | [JsonPropertyName("uri")]
18 | public required string Uri { get; init; }
19 | }
20 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ReadResourceResult.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a server's response to a request from the client.
7 | ///
8 | ///
9 | /// See the schema for details.
10 | ///
11 | public class ReadResourceResult
12 | {
13 | ///
14 | /// Gets or sets a list of objects that this resource contains.
15 | ///
16 | ///
17 | /// This property contains the actual content of the requested resource, which can be
18 | /// either text-based () or binary ().
19 | /// The type of content included depends on the resource being accessed.
20 | ///
21 | [JsonPropertyName("contents")]
22 | public List Contents { get; set; } = [];
23 | }
24 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/RequestParams.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Provides a base class for all request parameters.
7 | ///
8 | ///
9 | /// See the schema for details.
10 | ///
11 | public abstract class RequestParams
12 | {
13 | ///
14 | /// Gets or sets metadata related to the request that provides additional protocol-level information.
15 | ///
16 | ///
17 | /// This can include progress tracking tokens and other protocol-specific properties
18 | /// that are not part of the primary request parameters.
19 | ///
20 | [JsonPropertyName("_meta")]
21 | public RequestParamsMetadata? Meta { get; init; }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/RequestParamsMetadata.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Provides metadata related to the request that provides additional protocol-level information.
7 | ///
8 | ///
9 | /// This class contains properties that are used by the Model Context Protocol
10 | /// for features like progress tracking and other protocol-specific capabilities.
11 | ///
12 | public class RequestParamsMetadata
13 | {
14 | ///
15 | /// Gets or sets an opaque token that will be attached to any subsequent progress notifications.
16 | ///
17 | ///
18 | /// The receiver is not obligated to provide these notifications.
19 | ///
20 | [JsonPropertyName("progressToken")]
21 | public ProgressToken? ProgressToken { get; set; } = default!;
22 | }
23 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/ResourceUpdatedNotificationParams.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents the parameters used with a
7 | /// notification sent whenever a subscribed resource changes.
8 | ///
9 | ///
10 | ///
11 | /// When a client subscribes to resource updates using , the server will
12 | /// send notifications with this payload whenever the subscribed resource is modified. These notifications
13 | /// allow clients to maintain synchronized state without needing to poll the server for changes.
14 | ///
15 | ///
16 | /// See the schema for details.
17 | ///
18 | ///
19 | public class ResourceUpdatedNotificationParams
20 | {
21 | ///
22 | /// Gets or sets the URI of the resource that was updated.
23 | ///
24 | ///
25 | /// The URI can use any protocol; it is up to the server how to interpret it.
26 | ///
27 | [JsonPropertyName("uri")]
28 | public string? Uri { get; init; }
29 | }
30 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/Role.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents the type of role in the Model Context Protocol conversation.
7 | ///
8 | [JsonConverter(typeof(CustomizableJsonStringEnumConverter))]
9 | public enum Role
10 | {
11 | ///
12 | /// Corresponds to a human user in the conversation.
13 | ///
14 | [JsonStringEnumMemberName("user")]
15 | User,
16 |
17 | ///
18 | /// Corresponds to the AI assistant in the conversation.
19 | ///
20 | [JsonStringEnumMemberName("assistant")]
21 | Assistant
22 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/Root.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace ModelContextProtocol.Protocol;
5 |
6 | ///
7 | /// Represents a root URI and its metadata in the Model Context Protocol.
8 | ///
9 | ///
10 | /// Root URIs serve as entry points for resource navigation, typically representing
11 | /// top-level directories or container resources that can be accessed and traversed.
12 | /// Roots provide a hierarchical structure for organizing and accessing resources within the protocol.
13 | /// Each root has a URI that uniquely identifies it and optional metadata like a human-readable name.
14 | ///
15 | public class Root
16 | {
17 | ///
18 | /// Gets or sets the URI of the root.
19 | ///
20 | [JsonPropertyName("uri")]
21 | public required string Uri { get; init; }
22 |
23 | ///
24 | /// Gets or sets a human-readable name for the root.
25 | ///
26 | [JsonPropertyName("name")]
27 | public string? Name { get; init; }
28 |
29 | ///
30 | /// Gets or sets additional metadata for the root.
31 | ///
32 | ///
33 | /// This is reserved by the protocol for future use.
34 | ///
35 | [JsonPropertyName("meta")]
36 | public JsonElement? Meta { get; init; }
37 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/RootsCapability.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a client capability that enables root resource discovery in the Model Context Protocol.
7 | ///
8 | ///
9 | ///
10 | /// When present in , it indicates that the client supports listing
11 | /// root URIs that serve as entry points for resource navigation.
12 | ///
13 | ///
14 | /// The roots capability establishes a mechanism for servers to discover and access the hierarchical
15 | /// structure of resources provided by a client. Root URIs represent top-level entry points from which
16 | /// servers can navigate to access specific resources.
17 | ///
18 | ///
19 | /// See the schema for details.
20 | ///
21 | ///
22 | public class RootsCapability
23 | {
24 | ///
25 | /// Gets or sets whether the client supports notifications for changes to the roots list.
26 | ///
27 | ///
28 | /// When set to , the client can notify servers when roots are added,
29 | /// removed, or modified, allowing servers to refresh their roots cache accordingly.
30 | /// This enables servers to stay synchronized with client-side changes to available roots.
31 | ///
32 | [JsonPropertyName("listChanged")]
33 | public bool? ListChanged { get; set; }
34 |
35 | ///
36 | /// Gets or sets the handler for requests.
37 | ///
38 | ///
39 | /// This handler is invoked when a client sends a request to retrieve available roots.
40 | /// The handler receives request parameters and should return a containing the collection of available roots.
41 | ///
42 | [JsonIgnore]
43 | public Func>? RootsHandler { get; set; }
44 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/SamplingCapability.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.AI;
2 | using ModelContextProtocol.Client;
3 | using System.Text.Json.Serialization;
4 |
5 | namespace ModelContextProtocol.Protocol;
6 |
7 | ///
8 | /// Represents the capability for a client to generate text or other content using an AI model.
9 | ///
10 | ///
11 | ///
12 | /// This capability enables the MCP client to respond to sampling requests from an MCP server.
13 | ///
14 | ///
15 | /// When this capability is enabled, an MCP server can request the client to generate content
16 | /// using an AI model. The client must set a to process these requests.
17 | ///
18 | ///
19 | public class SamplingCapability
20 | {
21 | // Currently empty in the spec, but may be extended in the future
22 |
23 | ///
24 | /// Gets or sets the handler for processing requests.
25 | ///
26 | ///
27 | ///
28 | /// This handler function is called when an MCP server requests the client to generate content
29 | /// using an AI model. The client must set this property for the sampling capability to work.
30 | ///
31 | ///
32 | /// The handler receives message parameters, a progress reporter for updates, and a
33 | /// cancellation token. It should return a containing the
34 | /// generated content.
35 | ///
36 | ///
37 | /// You can create a handler using the extension
38 | /// method with any implementation of .
39 | ///
40 | ///
41 | [JsonIgnore]
42 | public Func, CancellationToken, ValueTask>? SamplingHandler { get; set; }
43 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/SamplingMessage.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents a message issued to or received from an LLM API within the Model Context Protocol.
7 | ///
8 | ///
9 | ///
10 | /// A encapsulates content sent to or received from AI models in the Model Context Protocol.
11 | /// Each message has a specific role ( or ) and contains content which can be text or images.
12 | ///
13 | ///
14 | /// objects are typically used in collections within
15 | /// to represent prompts or queries for LLM sampling. They form the core data structure for text generation requests
16 | /// within the Model Context Protocol.
17 | ///
18 | ///
19 | /// While similar to , the is focused on direct LLM sampling
20 | /// operations rather than the enhanced resource embedding capabilities provided by .
21 | ///
22 | ///
23 | /// See the schema for details.
24 | ///
25 | ///
26 | public class SamplingMessage
27 | {
28 | ///
29 | /// Gets or sets the content of the message.
30 | ///
31 | [JsonPropertyName("content")]
32 | public required Content Content { get; init; }
33 |
34 | ///
35 | /// Gets or sets the role of the message sender, indicating whether it's from a "user" or an "assistant".
36 | ///
37 | [JsonPropertyName("role")]
38 | public required Role Role { get; init; }
39 | }
40 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/SetLevelRequestParams.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents the parameters used with a request from a client
7 | /// to enable or adjust logging.
8 | ///
9 | ///
10 | /// This request allows clients to configure the level of logging information they want to receive from the server.
11 | /// The server will send notifications for log events at the specified level and all higher (more severe) levels.
12 | ///
13 | public class SetLevelRequestParams : RequestParams
14 | {
15 | ///
16 | /// Gets or sets the level of logging that the client wants to receive from the server.
17 | ///
18 | [JsonPropertyName("level")]
19 | public required LoggingLevel Level { get; init; }
20 | }
21 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/SubscribeRequestParams.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents the parameters used with a request from a client
7 | /// to request real-time notifications from the server whenever a particular resource changes.
8 | ///
9 | ///
10 | ///
11 | /// The subscription mechanism allows clients to be notified about changes to specific resources
12 | /// identified by their URI. When a subscribed resource changes, the server sends a notification
13 | /// to the client with the updated resource information.
14 | ///
15 | ///
16 | /// Subscriptions remain active until explicitly canceled using
17 | /// or until the connection is terminated.
18 | ///
19 | ///
20 | /// The server may refuse or limit subscriptions based on its capabilities or resource constraints.
21 | ///
22 | ///
23 | public class SubscribeRequestParams : RequestParams
24 | {
25 | ///
26 | /// Gets or sets the URI of the resource to subscribe to.
27 | ///
28 | ///
29 | /// The URI can use any protocol; it is up to the server how to interpret it.
30 | ///
31 | [JsonPropertyName("uri")]
32 | public string? Uri { get; init; }
33 | }
34 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/TextResourceContents.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Represents text-based contents of a resource in the Model Context Protocol.
7 | ///
8 | ///
9 | ///
10 | /// is used when textual data needs to be exchanged through
11 | /// the Model Context Protocol. The text is stored directly in the property.
12 | ///
13 | ///
14 | /// This class inherits from , which also has a sibling implementation
15 | /// for binary resources. When working with resources, the
16 | /// appropriate type is chosen based on the nature of the content.
17 | ///
18 | ///
19 | /// See the schema for more details.
20 | ///
21 | ///
22 | public class TextResourceContents : ResourceContents
23 | {
24 | ///
25 | /// Gets or sets the text of the item.
26 | ///
27 | [JsonPropertyName("text")]
28 | public string Text { get; set; } = string.Empty;
29 | }
30 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Protocol/UnsubscribeRequestParams.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace ModelContextProtocol.Protocol;
4 |
5 | ///
6 | /// Sent from the client to cancel resource update notifications from the server for a specific resource.
7 | ///
8 | ///
9 | ///
10 | /// After a client has subscribed to resource updates using ,
11 | /// this message can be sent to stop receiving notifications for a specific resource.
12 | /// This is useful for conserving resources and network bandwidth when
13 | /// the client no longer needs to track changes to a particular resource.
14 | ///
15 | ///
16 | /// The unsubscribe operation is idempotent, meaning it can be called multiple times
17 | /// for the same resource without causing errors, even if there is no active subscription.
18 | ///
19 | ///
20 | public class UnsubscribeRequestParams : RequestParams
21 | {
22 | ///
23 | /// The URI of the resource to unsubscribe from. The URI can use any protocol; it is up to the server how to interpret it.
24 | ///
25 | [JsonPropertyName("uri")]
26 | public string? Uri { get; init; }
27 | }
28 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/SemaphoreSlimExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol;
2 |
3 | internal static class SynchronizationExtensions
4 | {
5 | ///
6 | /// Asynchronously acquires a lock on the semaphore and returns a disposable object that releases the lock when disposed.
7 | ///
8 | /// The semaphore to acquire a lock on.
9 | /// A cancellation token to observe while waiting for the semaphore.
10 | /// A disposable that releases the semaphore when disposed.
11 | ///
12 | /// This extension method provides a convenient pattern for using a semaphore in asynchronous code,
13 | /// similar to how the `lock` statement is used in synchronous code.
14 | ///
15 | /// The was canceled.
16 | public static async ValueTask LockAsync(this SemaphoreSlim semaphore, CancellationToken cancellationToken = default)
17 | {
18 | await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
19 | return new(semaphore);
20 | }
21 |
22 | ///
23 | /// A disposable struct that releases a semaphore when disposed.
24 | ///
25 | ///
26 | /// This struct is used with the extension method to provide
27 | /// a using-pattern for semaphore locking, similar to lock statements.
28 | ///
29 | public readonly struct Releaser(SemaphoreSlim semaphore) : IDisposable
30 | {
31 | ///
32 | /// Releases the semaphore.
33 | ///
34 | ///
35 | /// This method is called automatically when the goes out of scope
36 | /// in a using statement or expression.
37 | ///
38 | public void Dispose() => semaphore.Release();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Server/DelegatingMcpServerPrompt.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 |
3 | namespace ModelContextProtocol.Server;
4 |
5 | /// Provides an that delegates all operations to an inner .
6 | ///
7 | /// This is recommended as a base type when building prompts that can be chained around an underlying .
8 | /// The default implementation simply passes each call to the inner prompt instance.
9 | ///
10 | public abstract class DelegatingMcpServerPrompt : McpServerPrompt
11 | {
12 | private readonly McpServerPrompt _innerPrompt;
13 |
14 | /// Initializes a new instance of the class around the specified .
15 | /// The inner prompt wrapped by this delegating prompt.
16 | protected DelegatingMcpServerPrompt(McpServerPrompt innerPrompt)
17 | {
18 | Throw.IfNull(innerPrompt);
19 | _innerPrompt = innerPrompt;
20 | }
21 |
22 | ///
23 | public override Prompt ProtocolPrompt => _innerPrompt.ProtocolPrompt;
24 |
25 | ///
26 | public override ValueTask GetAsync(
27 | RequestContext request,
28 | CancellationToken cancellationToken = default) =>
29 | _innerPrompt.GetAsync(request, cancellationToken);
30 |
31 | ///
32 | public override string ToString() => _innerPrompt.ToString();
33 | }
34 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Server/DelegatingMcpServerResource.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 |
3 | namespace ModelContextProtocol.Server;
4 |
5 | /// Provides an that delegates all operations to an inner .
6 | ///
7 | /// This is recommended as a base type when building resources that can be chained around an underlying .
8 | /// The default implementation simply passes each call to the inner resource instance.
9 | ///
10 | public abstract class DelegatingMcpServerResource : McpServerResource
11 | {
12 | private readonly McpServerResource _innerResource;
13 |
14 | /// Initializes a new instance of the class around the specified .
15 | /// The inner resource wrapped by this delegating resource.
16 | protected DelegatingMcpServerResource(McpServerResource innerResource)
17 | {
18 | Throw.IfNull(innerResource);
19 | _innerResource = innerResource;
20 | }
21 |
22 | ///
23 | public override Resource? ProtocolResource => _innerResource.ProtocolResource;
24 |
25 | ///
26 | public override ResourceTemplate ProtocolResourceTemplate => _innerResource.ProtocolResourceTemplate;
27 |
28 | ///
29 | public override ValueTask ReadAsync(RequestContext request, CancellationToken cancellationToken = default) =>
30 | _innerResource.ReadAsync(request, cancellationToken);
31 |
32 | ///
33 | public override string ToString() => _innerResource.ToString();
34 | }
35 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Server/DelegatingMcpServerTool.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 |
3 | namespace ModelContextProtocol.Server;
4 |
5 | /// Provides an that delegates all operations to an inner .
6 | ///
7 | /// This is recommended as a base type when building tools that can be chained around an underlying .
8 | /// The default implementation simply passes each call to the inner tool instance.
9 | ///
10 | public abstract class DelegatingMcpServerTool : McpServerTool
11 | {
12 | private readonly McpServerTool _innerTool;
13 |
14 | /// Initializes a new instance of the class around the specified .
15 | /// The inner tool wrapped by this delegating tool.
16 | protected DelegatingMcpServerTool(McpServerTool innerTool)
17 | {
18 | Throw.IfNull(innerTool);
19 | _innerTool = innerTool;
20 | }
21 |
22 | ///
23 | public override Tool ProtocolTool => _innerTool.ProtocolTool;
24 |
25 | ///
26 | public override ValueTask InvokeAsync(
27 | RequestContext request,
28 | CancellationToken cancellationToken = default) =>
29 | _innerTool.InvokeAsync(request, cancellationToken);
30 |
31 | ///
32 | public override string ToString() => _innerTool.ToString();
33 | }
34 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Server/DestinationBoundMcpServer.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 | using System.Diagnostics;
3 |
4 | namespace ModelContextProtocol.Server;
5 |
6 | internal sealed class DestinationBoundMcpServer(McpServer server, ITransport? transport) : IMcpServer
7 | {
8 | public string EndpointName => server.EndpointName;
9 | public ClientCapabilities? ClientCapabilities => server.ClientCapabilities;
10 | public Implementation? ClientInfo => server.ClientInfo;
11 | public McpServerOptions ServerOptions => server.ServerOptions;
12 | public IServiceProvider? Services => server.Services;
13 | public LoggingLevel? LoggingLevel => server.LoggingLevel;
14 |
15 | public ValueTask DisposeAsync() => server.DisposeAsync();
16 |
17 | public IAsyncDisposable RegisterNotificationHandler(string method, Func handler) => server.RegisterNotificationHandler(method, handler);
18 |
19 | // This will throw because the server must already be running for this class to be constructed, but it should give us a good Exception message.
20 | public Task RunAsync(CancellationToken cancellationToken) => server.RunAsync(cancellationToken);
21 |
22 | public Task SendMessageAsync(JsonRpcMessage message, CancellationToken cancellationToken = default)
23 | {
24 | Debug.Assert(message.RelatedTransport is null);
25 | message.RelatedTransport = transport;
26 | return server.SendMessageAsync(message, cancellationToken);
27 | }
28 |
29 | public Task SendRequestAsync(JsonRpcRequest request, CancellationToken cancellationToken = default)
30 | {
31 | Debug.Assert(request.RelatedTransport is null);
32 | request.RelatedTransport = transport;
33 | return server.SendRequestAsync(request, cancellationToken);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Server/IMcpServerPrimitive.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Server;
2 |
3 | ///
4 | /// Represents an MCP server primitive, like a tool or a prompt.
5 | ///
6 | public interface IMcpServerPrimitive
7 | {
8 | /// Gets the unique identifier of the primitive.
9 | string Id { get; }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Server/McpServerFactory.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using ModelContextProtocol.Protocol;
3 |
4 | namespace ModelContextProtocol.Server;
5 |
6 | ///
7 | /// Provides a factory for creating instances.
8 | ///
9 | ///
10 | /// This is the recommended way to create instances.
11 | /// The factory handles proper initialization of server instances with the required dependencies.
12 | ///
13 | public static class McpServerFactory
14 | {
15 | ///
16 | /// Creates a new instance of an .
17 | ///
18 | /// Transport to use for the server representing an already-established MCP session.
19 | /// Configuration options for this server, including capabilities.
20 | /// Logger factory to use for logging. If null, logging will be disabled.
21 | /// Optional service provider to create new instances of tools and other dependencies.
22 | /// An instance that should be disposed when no longer needed.
23 | /// is .
24 | /// is .
25 | public static IMcpServer Create(
26 | ITransport transport,
27 | McpServerOptions serverOptions,
28 | ILoggerFactory? loggerFactory = null,
29 | IServiceProvider? serviceProvider = null)
30 | {
31 | Throw.IfNull(transport);
32 | Throw.IfNull(serverOptions);
33 |
34 | return new McpServer(transport, serverOptions, loggerFactory, serviceProvider);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Server/McpServerPromptTypeAttribute.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 |
3 | namespace ModelContextProtocol.Server;
4 |
5 | ///
6 | /// Used to attribute a type containing methods that should be exposed as s.
7 | ///
8 | ///
9 | ///
10 | /// This attribute is used to mark a class containing methods that should be automatically
11 | /// discovered and registered as s. When combined with discovery methods like
12 | /// WithPromptsFromAssembly, it enables automatic registration of prompts without explicitly listing each prompt class.
13 | /// The attribute is not necessary when a reference to the type is provided directly to a method like WithPrompts.
14 | ///
15 | ///
16 | /// Within a class marked with this attribute, individual methods that should be exposed as
17 | /// prompts must be marked with the .
18 | ///
19 | ///
20 | [AttributeUsage(AttributeTargets.Class)]
21 | public sealed class McpServerPromptTypeAttribute : Attribute;
22 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Server/McpServerResourceTypeAttribute.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 |
3 | namespace ModelContextProtocol.Server;
4 |
5 | ///
6 | /// Used to attribute a type containing members that should be exposed as s.
7 | ///
8 | ///
9 | ///
10 | /// This attribute is used to mark a class containing members that should be automatically
11 | /// discovered and registered as s. When combined with discovery methods like
12 | /// WithResourcesFromAssembly, it enables automatic registration of resources without explicitly listing each
13 | /// resource class. The attribute is not necessary when a reference to the type is provided directly to a method
14 | /// like McpServerBuilderExtensions.WithResources.
15 | ///
16 | ///
17 | /// Within a class marked with this attribute, individual members that should be exposed as
18 | /// resources must be marked with the .
19 | ///
20 | ///
21 | [AttributeUsage(AttributeTargets.Class)]
22 | public sealed class McpServerResourceTypeAttribute : Attribute;
23 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Server/McpServerToolTypeAttribute.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 |
3 | namespace ModelContextProtocol.Server;
4 |
5 | ///
6 | /// Used to attribute a type containing methods that should be exposed as s.
7 | ///
8 | ///
9 | ///
10 | /// This attribute is used to mark a class containing methods that should be automatically
11 | /// discovered and registered as s. When combined with discovery methods like
12 | /// WithToolsFromAssembly, it enables automatic registration of tools without explicitly listing each tool
13 | /// class. The attribute is not necessary when a reference to the type is provided directly to a method like WithTools.
14 | ///
15 | ///
16 | /// Within a class marked with this attribute, individual methods that should be exposed as
17 | /// tools must be marked with the .
18 | ///
19 | ///
20 | [AttributeUsage(AttributeTargets.Class)]
21 | public sealed class McpServerToolTypeAttribute : Attribute;
22 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/Server/RequestContext.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 |
3 | namespace ModelContextProtocol.Server;
4 |
5 | ///
6 | /// Provides a context container that provides access to the client request parameters and resources for the request.
7 | ///
8 | /// Type of the request parameters specific to each MCP operation.
9 | ///
10 | /// The encapsulates all contextual information for handling an MCP request.
11 | /// This type is typically received as a parameter in handler delegates registered with IMcpServerBuilder,
12 | /// and may be injected as parameters into s.
13 | ///
14 | public sealed class RequestContext
15 | {
16 | /// The server with which this instance is associated.
17 | private IMcpServer _server;
18 |
19 | ///
20 | /// Initializes a new instance of the class with the specified server.
21 | ///
22 | /// The server with which this instance is associated.
23 | public RequestContext(IMcpServer server)
24 | {
25 | Throw.IfNull(server);
26 |
27 | _server = server;
28 | Services = server.Services;
29 | }
30 |
31 | /// Gets or sets the server with which this instance is associated.
32 | public IMcpServer Server
33 | {
34 | get => _server;
35 | set
36 | {
37 | Throw.IfNull(value);
38 | _server = value;
39 | }
40 | }
41 |
42 | /// Gets or sets the services associated with this request.
43 | ///
44 | /// This may not be the same instance stored in
45 | /// if was true, in which case this
46 | /// might be a scoped derived from the server's
47 | /// .
48 | ///
49 | public IServiceProvider? Services { get; set; }
50 |
51 | /// Gets or sets the parameters associated with this request.
52 | public TParams? Params { get; set; }
53 | }
--------------------------------------------------------------------------------
/src/ModelContextProtocol.Core/TokenProgress.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 |
3 | namespace ModelContextProtocol;
4 |
5 | ///
6 | /// Provides an tied to a specific progress token and that will issue
7 | /// progress notifications on the supplied endpoint.
8 | ///
9 | internal sealed class TokenProgress(IMcpEndpoint endpoint, ProgressToken progressToken) : IProgress
10 | {
11 | ///
12 | public void Report(ProgressNotificationValue value)
13 | {
14 | _ = endpoint.NotifyProgressAsync(progressToken, value, CancellationToken.None);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol/DefaultMcpServerBuilder.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol;
2 |
3 | namespace Microsoft.Extensions.DependencyInjection;
4 |
5 | ///
6 | /// Default implementation of that enables fluent configuration
7 | /// of the Model Context Protocol (MCP) server. This builder is returned by the
8 | /// extension method and
9 | /// provides access to the service collection for registering additional MCP components.
10 | ///
11 | internal sealed class DefaultMcpServerBuilder : IMcpServerBuilder
12 | {
13 | ///
14 | public IServiceCollection Services { get; }
15 |
16 | ///
17 | /// Initializes a new instance of the class.
18 | ///
19 | /// The service collection to which MCP server services will be added. This collection
20 | /// is exposed through the property to allow additional configuration.
21 | /// Thrown when is null.
22 | public DefaultMcpServerBuilder(IServiceCollection services)
23 | {
24 | Throw.IfNull(services);
25 |
26 | Services = services;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol/IMcpServerBuilder.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 |
3 | namespace Microsoft.Extensions.DependencyInjection;
4 |
5 | ///
6 | /// Provides a builder for configuring instances.
7 | ///
8 | ///
9 | ///
10 | /// The interface provides a fluent API for configuring Model Context Protocol (MCP) servers
11 | /// when using dependency injection. It exposes methods for registering tools, prompts, custom request handlers,
12 | /// and server transports, allowing for comprehensive server configuration through a chain of method calls.
13 | ///
14 | ///
15 | /// The builder is obtained from the extension
16 | /// method and provides access to the underlying service collection via the property.
17 | ///
18 | ///
19 | public interface IMcpServerBuilder
20 | {
21 | ///
22 | /// Gets the associated service collection.
23 | ///
24 | IServiceCollection Services { get; }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol/McpServerServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection.Extensions;
2 | using Microsoft.Extensions.Options;
3 | using ModelContextProtocol;
4 | using ModelContextProtocol.Server;
5 |
6 | namespace Microsoft.Extensions.DependencyInjection;
7 |
8 | ///
9 | /// Provides extension methods for configuring MCP servers with dependency injection.
10 | ///
11 | public static class McpServerServiceCollectionExtensions
12 | {
13 | ///
14 | /// Adds the Model Context Protocol (MCP) server to the service collection with default options.
15 | ///
16 | /// The to add the server to.
17 | /// Optional callback to configure the .
18 | /// An that can be used to further configure the MCP server.
19 |
20 | public static IMcpServerBuilder AddMcpServer(this IServiceCollection services, Action? configureOptions = null)
21 | {
22 | services.AddOptions();
23 | services.TryAddEnumerable(ServiceDescriptor.Transient, McpServerOptionsSetup>());
24 | if (configureOptions is not null)
25 | {
26 | services.Configure(configureOptions);
27 | }
28 |
29 | return new DefaultMcpServerBuilder(services);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol/ModelContextProtocol.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0;net8.0;netstandard2.0
5 | true
6 | true
7 | ModelContextProtocol
8 | .NET SDK for the Model Context Protocol (MCP) with hosting and dependency injection extensions.
9 | README.md
10 | preview
11 |
12 |
13 |
14 | true
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/ModelContextProtocol/SingleSessionMcpServerHostedService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Hosting;
2 | using ModelContextProtocol.Server;
3 |
4 | namespace ModelContextProtocol;
5 |
6 | ///
7 | /// Hosted service for a single-session (e.g. stdio) MCP server.
8 | ///
9 | /// The server representing the session being hosted.
10 | ///
11 | /// The host's application lifetime. If available, it will have termination requested when the session's run completes.
12 | ///
13 | internal sealed class SingleSessionMcpServerHostedService(IMcpServer session, IHostApplicationLifetime? lifetime = null) : BackgroundService
14 | {
15 | ///
16 | protected override async Task ExecuteAsync(CancellationToken stoppingToken)
17 | {
18 | try
19 | {
20 | await session.RunAsync(stoppingToken).ConfigureAwait(false);
21 | }
22 | finally
23 | {
24 | lifetime?.StopApplication();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/Common/Utils/DelegatingTestOutputHelper.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Tests.Utils;
2 |
3 | public class DelegatingTestOutputHelper() : ITestOutputHelper
4 | {
5 | public ITestOutputHelper? CurrentTestOutputHelper { get; set; }
6 |
7 | public string Output => CurrentTestOutputHelper?.Output ?? string.Empty;
8 |
9 | public void Write(string message) => CurrentTestOutputHelper?.Write(message);
10 | public void Write(string format, params object[] args) => CurrentTestOutputHelper?.Write(format, args);
11 | public void WriteLine(string message) => CurrentTestOutputHelper?.WriteLine(message);
12 | public void WriteLine(string format, params object[] args) => CurrentTestOutputHelper?.WriteLine(format, args);
13 | }
14 |
--------------------------------------------------------------------------------
/tests/Common/Utils/LoggedTest.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 |
3 | namespace ModelContextProtocol.Tests.Utils;
4 |
5 | public class LoggedTest : IDisposable
6 | {
7 | private readonly DelegatingTestOutputHelper _delegatingTestOutputHelper;
8 |
9 | public LoggedTest(ITestOutputHelper testOutputHelper)
10 | {
11 | _delegatingTestOutputHelper = new()
12 | {
13 | CurrentTestOutputHelper = testOutputHelper,
14 | };
15 | XunitLoggerProvider = new XunitLoggerProvider(_delegatingTestOutputHelper);
16 | LoggerFactory = Microsoft.Extensions.Logging.LoggerFactory.Create(builder =>
17 | {
18 | builder.AddProvider(XunitLoggerProvider);
19 | });
20 | }
21 |
22 | public ITestOutputHelper TestOutputHelper => _delegatingTestOutputHelper;
23 | public ILoggerFactory LoggerFactory { get; set; }
24 | public ILoggerProvider XunitLoggerProvider { get; }
25 |
26 | public virtual void Dispose()
27 | {
28 | _delegatingTestOutputHelper.CurrentTestOutputHelper = null;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/Common/Utils/MockHttpHandler.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.Tests.Utils;
2 |
3 | public class MockHttpHandler : HttpMessageHandler
4 | {
5 | public Func>? RequestHandler { get; set; }
6 |
7 | protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
8 | {
9 | if (RequestHandler == null)
10 | throw new InvalidOperationException($"No {nameof(RequestHandler)} was set! Please set handler first and make request afterwards.");
11 |
12 | cancellationToken.ThrowIfCancellationRequested();
13 |
14 | var result = await RequestHandler.Invoke(request);
15 |
16 | cancellationToken.ThrowIfCancellationRequested();
17 |
18 | return result;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/tests/Common/Utils/MockLoggerProvider.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using System.Collections.Concurrent;
3 |
4 | namespace ModelContextProtocol.Tests.Utils;
5 |
6 | public class MockLoggerProvider() : ILoggerProvider
7 | {
8 | public ConcurrentQueue<(string Category, LogLevel LogLevel, string Message, Exception? Exception)> LogMessages { get; } = [];
9 |
10 | public ILogger CreateLogger(string categoryName)
11 | {
12 | return new MockLogger(this, categoryName);
13 | }
14 |
15 | public void Dispose()
16 | {
17 | }
18 |
19 | private class MockLogger(MockLoggerProvider mockProvider, string category) : ILogger
20 | {
21 | public void Log(
22 | LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter)
23 | {
24 | mockProvider.LogMessages.Enqueue((category, logLevel, formatter(state, exception), exception));
25 | }
26 |
27 | public bool IsEnabled(LogLevel logLevel) => true;
28 |
29 | // The MockLoggerProvider is a convenient NoopDisposable
30 | public IDisposable BeginScope(TState state) where TState : notnull => mockProvider;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tests/Common/Utils/XunitLoggerProvider.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using System.Globalization;
3 | using System.Text;
4 |
5 | namespace ModelContextProtocol.Tests.Utils;
6 |
7 | public class XunitLoggerProvider(ITestOutputHelper output) : ILoggerProvider
8 | {
9 | public ILogger CreateLogger(string categoryName)
10 | {
11 | return new XunitLogger(output, categoryName);
12 | }
13 |
14 | public void Dispose()
15 | {
16 | }
17 |
18 | private class XunitLogger(ITestOutputHelper output, string category) : ILogger
19 | {
20 | public void Log(
21 | LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter)
22 | {
23 | var sb = new StringBuilder();
24 |
25 | var timestamp = DateTimeOffset.UtcNow.ToString("s", CultureInfo.InvariantCulture);
26 | var prefix = $"| [{timestamp}] {category} {logLevel}: ";
27 | var lines = formatter(state, exception);
28 | sb.Append(prefix);
29 | sb.Append(lines);
30 |
31 | if (exception is not null)
32 | {
33 | sb.AppendLine();
34 | sb.Append(exception.ToString());
35 | }
36 |
37 | output.WriteLine(sb.ToString());
38 | }
39 |
40 | public bool IsEnabled(LogLevel logLevel) => true;
41 |
42 | public IDisposable BeginScope(TState state) where TState : notnull
43 | => new NoopDisposable();
44 |
45 | private sealed class NoopDisposable : IDisposable
46 | {
47 | public void Dispose()
48 | {
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.AspNetCore.Tests/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using Xunit;
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.AspNetCore.Tests/MapMcpStatelessTests.cs:
--------------------------------------------------------------------------------
1 | namespace ModelContextProtocol.AspNetCore.Tests;
2 |
3 | public class MapMcpStatelessTests(ITestOutputHelper outputHelper) : MapMcpStreamableHttpTests(outputHelper)
4 | {
5 | protected override bool UseStreamableHttp => true;
6 | protected override bool Stateless => true;
7 | }
8 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.AspNetCore.Tests/StatelessServerIntegrationTests.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Client;
2 |
3 | namespace ModelContextProtocol.AspNetCore.Tests;
4 |
5 | public class StatelessServerIntegrationTests(SseServerIntegrationTestFixture fixture, ITestOutputHelper testOutputHelper)
6 | : StreamableHttpServerIntegrationTests(fixture, testOutputHelper)
7 | {
8 | protected override SseClientTransportOptions ClientTransportOptions => new()
9 | {
10 | Endpoint = new Uri("http://localhost/stateless"),
11 | Name = "In-memory Streamable HTTP Client",
12 | TransportMode = HttpTransportMode.StreamableHttp,
13 | };
14 | }
15 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.AspNetCore.Tests/Utils/KestrelInMemoryTest.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Connections;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using Microsoft.Extensions.DependencyInjection.Extensions;
5 | using ModelContextProtocol.Tests.Utils;
6 |
7 | namespace ModelContextProtocol.AspNetCore.Tests.Utils;
8 |
9 | public class KestrelInMemoryTest : LoggedTest
10 | {
11 | private readonly KestrelInMemoryTransport _inMemoryTransport = new();
12 |
13 | public KestrelInMemoryTest(ITestOutputHelper testOutputHelper)
14 | : base(testOutputHelper)
15 | {
16 | // Use SlimBuilder instead of EmptyBuilder to avoid having to call UseRouting() and UseEndpoints(_ => { })
17 | // or a helper that does the same every test. But clear out the existing socket transport to avoid potential port conflicts.
18 | Builder = WebApplication.CreateSlimBuilder();
19 | Builder.Services.RemoveAll();
20 | Builder.Services.AddSingleton(_inMemoryTransport);
21 | Builder.Services.AddSingleton(XunitLoggerProvider);
22 |
23 | HttpClient = new HttpClient(new SocketsHttpHandler()
24 | {
25 | ConnectCallback = (context, token) =>
26 | {
27 | var connection = _inMemoryTransport.CreateConnection();
28 | return new(connection.ClientStream);
29 | },
30 | })
31 | {
32 | BaseAddress = new Uri("http://localhost:5000/"),
33 | Timeout = TimeSpan.FromSeconds(10),
34 | };
35 | }
36 |
37 | public WebApplicationBuilder Builder { get; }
38 |
39 | public HttpClient HttpClient { get; }
40 |
41 | public override void Dispose()
42 | {
43 | HttpClient.Dispose();
44 | base.Dispose();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.AspNetCore.Tests/Utils/KestrelInMemoryTransport.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Connections;
2 | using System.Net;
3 | using System.Threading.Channels;
4 |
5 | namespace ModelContextProtocol.AspNetCore.Tests.Utils;
6 |
7 | public sealed class KestrelInMemoryTransport : IConnectionListenerFactory, IConnectionListener
8 | {
9 | private readonly Channel _acceptQueue = Channel.CreateUnbounded();
10 | private EndPoint? _endPoint;
11 |
12 | public EndPoint EndPoint => _endPoint ?? throw new InvalidOperationException("EndPoint is not set. Call BindAsync first.");
13 |
14 | public KestrelInMemoryConnection CreateConnection()
15 | {
16 | var connection = new KestrelInMemoryConnection();
17 | _acceptQueue.Writer.TryWrite(connection);
18 | return connection;
19 | }
20 |
21 | public async ValueTask AcceptAsync(CancellationToken cancellationToken = default)
22 | {
23 | if (await _acceptQueue.Reader.WaitToReadAsync(cancellationToken))
24 | {
25 | while (_acceptQueue.Reader.TryRead(out var item))
26 | {
27 | return item;
28 | }
29 | }
30 |
31 | return null;
32 | }
33 |
34 | public ValueTask BindAsync(EndPoint endpoint, CancellationToken cancellationToken = default)
35 | {
36 | _endPoint = endpoint;
37 | return new ValueTask(this);
38 | }
39 |
40 | public ValueTask DisposeAsync()
41 | {
42 | return UnbindAsync(default);
43 | }
44 |
45 | public ValueTask UnbindAsync(CancellationToken cancellationToken = default)
46 | {
47 | _acceptQueue.Writer.TryComplete();
48 | return default;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.TestServer/ModelContextProtocol.TestServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0;net8.0;net472
6 | enable
7 | enable
8 | TestServer
9 | ModelContextProtocol.TestServer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.TestSseServer/ModelContextProtocol.TestSseServer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0;net8.0
6 | enable
7 | enable
8 | TestSseServer
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.TestSseServer/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "ModelContextProtocol.TestSseServer": {
4 | "commandName": "Project",
5 | "launchBrowser": false,
6 | "environmentVariables": {
7 | "ASPNETCORE_ENVIRONMENT": "Development"
8 | },
9 | "applicationUrl": "http://localhost:3001"
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/ClientIntegrationTestFixture.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using ModelContextProtocol.Client;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace ModelContextProtocol.Tests;
6 |
7 | public class ClientIntegrationTestFixture
8 | {
9 | private ILoggerFactory? _loggerFactory;
10 |
11 | public StdioClientTransportOptions EverythingServerTransportOptions { get; }
12 | public StdioClientTransportOptions TestServerTransportOptions { get; }
13 |
14 | public static IEnumerable ClientIds => ["everything", "test_server"];
15 |
16 | public ClientIntegrationTestFixture()
17 | {
18 | EverythingServerTransportOptions = new()
19 | {
20 | Command = "npx",
21 | // Change to Arguments = ["mcp-server-everything"] if you want to run the server locally after creating a symlink
22 | Arguments = ["-y", "--verbose", "@modelcontextprotocol/server-everything"],
23 | Name = "Everything",
24 | };
25 |
26 | TestServerTransportOptions = new()
27 | {
28 | Command = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "TestServer.exe" : "dotnet",
29 | Name = "TestServer",
30 | };
31 |
32 | if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
33 | {
34 | // Change to Arguments to "mcp-server-everything" if you want to run the server locally after creating a symlink
35 | TestServerTransportOptions.Arguments = ["TestServer.dll"];
36 | }
37 | }
38 |
39 | public void Initialize(ILoggerFactory loggerFactory)
40 | {
41 | _loggerFactory = loggerFactory;
42 | }
43 |
44 | public Task CreateClientAsync(string clientId, McpClientOptions? clientOptions = null) =>
45 | McpClientFactory.CreateAsync(new StdioClientTransport(clientId switch
46 | {
47 | "everything" => EverythingServerTransportOptions,
48 | "test_server" => TestServerTransportOptions,
49 | _ => throw new ArgumentException($"Unknown client ID: {clientId}")
50 | }), clientOptions, loggerFactory: _loggerFactory);
51 | }
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/Configuration/McpServerBuilderExtensionsTransportsTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.Extensions.Hosting;
3 | using ModelContextProtocol.Protocol;
4 | using ModelContextProtocol.Server;
5 | using Moq;
6 | using System.IO.Pipelines;
7 |
8 | namespace ModelContextProtocol.Tests.Configuration;
9 |
10 | public class McpServerBuilderExtensionsTransportsTests
11 | {
12 | [Fact]
13 | public void WithStdioServerTransport_Sets_Transport()
14 | {
15 | var services = new ServiceCollection();
16 | services.AddMcpServer().WithStdioServerTransport();
17 |
18 | var transportServiceType = services.FirstOrDefault(s => s.ServiceType == typeof(ITransport));
19 | Assert.NotNull(transportServiceType);
20 |
21 | var serviceProvider = services.BuildServiceProvider();
22 | Assert.IsType(serviceProvider.GetRequiredService());
23 | }
24 |
25 | [Fact]
26 | public async Task HostExecutionShutsDownWhenSingleSessionServerExits()
27 | {
28 | Pipe clientToServerPipe = new(), serverToClientPipe = new();
29 |
30 | var builder = Host.CreateEmptyApplicationBuilder(null);
31 | builder.Services
32 | .AddMcpServer()
33 | .WithStreamServerTransport(clientToServerPipe.Reader.AsStream(), serverToClientPipe.Writer.AsStream());
34 |
35 | IHost host = builder.Build();
36 |
37 | Task t = host.RunAsync(TestContext.Current.CancellationToken);
38 | await Task.Delay(1, TestContext.Current.CancellationToken);
39 | Assert.False(t.IsCompleted);
40 |
41 | clientToServerPipe.Writer.Complete();
42 | await t;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using Xunit;
2 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/McpJsonUtilitiesTests.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 |
3 | namespace ModelContextProtocol.Tests;
4 |
5 | public static class McpJsonUtilitiesTests
6 | {
7 | [Fact]
8 | public static void DefaultOptions_IsSingleton()
9 | {
10 | var options = McpJsonUtilities.DefaultOptions;
11 |
12 | Assert.NotNull(options);
13 | Assert.True(options.IsReadOnly);
14 | Assert.Same(options, McpJsonUtilities.DefaultOptions);
15 | }
16 |
17 | [Fact]
18 | public static void DefaultOptions_UseReflectionWhenEnabled()
19 | {
20 | var options = McpJsonUtilities.DefaultOptions;
21 | Type anonType = new { Id = 42 }.GetType();
22 |
23 | Assert.Equal(JsonSerializer.IsReflectionEnabledByDefault, options.TryGetTypeInfo(anonType, out _));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/Protocol/RequestIdTests.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 | using System.Text.Json;
3 |
4 | namespace ModelContextProtocol.Tests.Protocol;
5 |
6 | public class RequestIdTests
7 | {
8 | [Fact]
9 | public void StringCtor_Roundtrips()
10 | {
11 | RequestId id = new("test-id");
12 | Assert.Equal("test-id", id.ToString());
13 | Assert.Equal("\"test-id\"", JsonSerializer.Serialize(id, McpJsonUtilities.DefaultOptions));
14 | Assert.Same("test-id", id.Id);
15 |
16 | Assert.True(id.Equals(new("test-id")));
17 | Assert.False(id.Equals(new("tEst-id")));
18 | Assert.Equal("test-id".GetHashCode(), id.GetHashCode());
19 |
20 | Assert.Equal(id, JsonSerializer.Deserialize(JsonSerializer.Serialize(id, McpJsonUtilities.DefaultOptions), McpJsonUtilities.DefaultOptions));
21 | }
22 |
23 | [Fact]
24 | public void Int64Ctor_Roundtrips()
25 | {
26 | RequestId id = new(42);
27 | Assert.Equal("42", id.ToString());
28 | Assert.Equal("42", JsonSerializer.Serialize(id, McpJsonUtilities.DefaultOptions));
29 | Assert.Equal(42, Assert.IsType(id.Id));
30 |
31 | Assert.True(id.Equals(new(42)));
32 | Assert.False(id.Equals(new(43)));
33 | Assert.False(id.Equals(new("42")));
34 | Assert.Equal(42L.GetHashCode(), id.GetHashCode());
35 |
36 | Assert.Equal(id, JsonSerializer.Deserialize(JsonSerializer.Serialize(id, McpJsonUtilities.DefaultOptions), McpJsonUtilities.DefaultOptions));
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/Server/McpServerDelegatesTests.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Protocol;
2 | using ModelContextProtocol.Server;
3 |
4 | namespace ModelContextProtocol.Tests.Server;
5 |
6 | public class McpServerHandlerTests
7 | {
8 | [Fact]
9 | public void AllPropertiesAreSettable()
10 | {
11 | var handlers = new McpServerHandlers();
12 |
13 | Assert.Null(handlers.ListToolsHandler);
14 | Assert.Null(handlers.CallToolHandler);
15 | Assert.Null(handlers.ListPromptsHandler);
16 | Assert.Null(handlers.GetPromptHandler);
17 | Assert.Null(handlers.ListResourceTemplatesHandler);
18 | Assert.Null(handlers.ListResourcesHandler);
19 | Assert.Null(handlers.ReadResourceHandler);
20 | Assert.Null(handlers.CompleteHandler);
21 | Assert.Null(handlers.SubscribeToResourcesHandler);
22 | Assert.Null(handlers.UnsubscribeFromResourcesHandler);
23 |
24 | handlers.ListToolsHandler = async (p, c) => new ListToolsResult();
25 | handlers.CallToolHandler = async (p, c) => new CallToolResponse();
26 | handlers.ListPromptsHandler = async (p, c) => new ListPromptsResult();
27 | handlers.GetPromptHandler = async (p, c) => new GetPromptResult();
28 | handlers.ListResourceTemplatesHandler = async (p, c) => new ListResourceTemplatesResult();
29 | handlers.ListResourcesHandler = async (p, c) => new ListResourcesResult();
30 | handlers.ReadResourceHandler = async (p, c) => new ReadResourceResult();
31 | handlers.CompleteHandler = async (p, c) => new CompleteResult();
32 | handlers.SubscribeToResourcesHandler = async (s, c) => new EmptyResult();
33 | handlers.UnsubscribeFromResourcesHandler = async (s, c) => new EmptyResult();
34 |
35 | Assert.NotNull(handlers.ListToolsHandler);
36 | Assert.NotNull(handlers.CallToolHandler);
37 | Assert.NotNull(handlers.ListPromptsHandler);
38 | Assert.NotNull(handlers.GetPromptHandler);
39 | Assert.NotNull(handlers.ListResourceTemplatesHandler);
40 | Assert.NotNull(handlers.ListResourcesHandler);
41 | Assert.NotNull(handlers.ReadResourceHandler);
42 | Assert.NotNull(handlers.CompleteHandler);
43 | Assert.NotNull(handlers.SubscribeToResourcesHandler);
44 | Assert.NotNull(handlers.UnsubscribeFromResourcesHandler);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/Server/McpServerFactoryTests.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 | using ModelContextProtocol.Tests.Utils;
3 |
4 | namespace ModelContextProtocol.Tests.Server;
5 |
6 | public class McpServerFactoryTests : LoggedTest
7 | {
8 | private readonly McpServerOptions _options;
9 |
10 | public McpServerFactoryTests(ITestOutputHelper testOutputHelper)
11 | : base(testOutputHelper)
12 | {
13 | _options = new McpServerOptions
14 | {
15 | ProtocolVersion = "1.0",
16 | InitializationTimeout = TimeSpan.FromSeconds(30)
17 | };
18 | }
19 |
20 | [Fact]
21 | public async Task Create_Should_Initialize_With_Valid_Parameters()
22 | {
23 | // Arrange & Act
24 | await using var transport = new TestServerTransport();
25 | await using IMcpServer server = McpServerFactory.Create(transport, _options, LoggerFactory);
26 |
27 | // Assert
28 | Assert.NotNull(server);
29 | }
30 |
31 | [Fact]
32 | public void Create_Throws_For_Null_ServerTransport()
33 | {
34 | // Arrange, Act & Assert
35 | Assert.Throws("transport", () => McpServerFactory.Create(null!, _options, LoggerFactory));
36 | }
37 |
38 | [Fact]
39 | public async Task Create_Throws_For_Null_Options()
40 | {
41 | // Arrange, Act & Assert
42 | await using var transport = new TestServerTransport();
43 | Assert.Throws("serverOptions", () => McpServerFactory.Create(transport, null!, LoggerFactory));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/Server/McpServerLoggingLevelTests.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using ModelContextProtocol.Protocol;
3 | using ModelContextProtocol.Server;
4 |
5 | namespace ModelContextProtocol.Tests.Server;
6 |
7 | public class McpServerLoggingLevelTests
8 | {
9 | [Fact]
10 | public void CanCreateServerWithLoggingLevelHandler()
11 | {
12 | var services = new ServiceCollection();
13 |
14 | services.AddMcpServer()
15 | .WithStdioServerTransport()
16 | .WithSetLoggingLevelHandler(async (ctx, ct) => new EmptyResult());
17 |
18 | var provider = services.BuildServiceProvider();
19 |
20 | provider.GetRequiredService();
21 | }
22 |
23 | [Fact]
24 | public void AddingLoggingLevelHandlerSetsLoggingCapability()
25 | {
26 | var services = new ServiceCollection();
27 |
28 | services.AddMcpServer()
29 | .WithStdioServerTransport()
30 | .WithSetLoggingLevelHandler(async (ctx, ct) => new EmptyResult());
31 |
32 | var provider = services.BuildServiceProvider();
33 |
34 | var server = provider.GetRequiredService();
35 |
36 | Assert.NotNull(server.ServerOptions.Capabilities?.Logging);
37 | Assert.NotNull(server.ServerOptions.Capabilities.Logging.SetLoggingLevelHandler);
38 | }
39 |
40 | [Fact]
41 | public void ServerWithoutCallingLoggingLevelHandlerDoesNotSetLoggingCapability()
42 | {
43 | var services = new ServiceCollection();
44 | services.AddMcpServer()
45 | .WithStdioServerTransport();
46 | var provider = services.BuildServiceProvider();
47 | var server = provider.GetRequiredService();
48 | Assert.Null(server.ServerOptions.Capabilities?.Logging);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/TestAttributes.cs:
--------------------------------------------------------------------------------
1 | // Uncomment to disable parallel test execution for the whole assembly
2 | //[assembly: CollectionBehavior(DisableTestParallelization = true)]
3 |
4 | ///
5 | /// Enables test classes to individually be attributed as [Collection(nameof(DisableParallelization))]
6 | /// to have those tests run non-concurrently with any other tests.
7 | ///
8 | [CollectionDefinition(nameof(DisableParallelization), DisableParallelization = true)]
9 | public sealed class DisableParallelization;
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/Transport/SseResponseStreamTransportTests.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Server;
2 | using ModelContextProtocol.Tests.Utils;
3 | using System.IO.Pipelines;
4 |
5 | namespace ModelContextProtocol.Tests.Transport;
6 |
7 | public class SseResponseStreamTransportTests(ITestOutputHelper testOutputHelper) : LoggedTest(testOutputHelper)
8 | {
9 | [Fact]
10 | public async Task Can_Customize_MessageEndpoint()
11 | {
12 | var responsePipe = new Pipe();
13 |
14 | await using var transport = new SseResponseStreamTransport(responsePipe.Writer.AsStream(), "/my-message-endpoint");
15 | var transportRunTask = transport.RunAsync(TestContext.Current.CancellationToken);
16 |
17 | using var responseStreamReader = new StreamReader(responsePipe.Reader.AsStream());
18 | var firstLine = await responseStreamReader.ReadLineAsync(TestContext.Current.CancellationToken);
19 | Assert.Equal("event: endpoint", firstLine);
20 |
21 | var secondLine = await responseStreamReader.ReadLineAsync(TestContext.Current.CancellationToken);
22 | Assert.Equal("data: /my-message-endpoint", secondLine);
23 |
24 | responsePipe.Reader.Complete();
25 | responsePipe.Writer.Complete();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/ModelContextProtocol.Tests/Transport/StdioClientTransportTests.cs:
--------------------------------------------------------------------------------
1 | using ModelContextProtocol.Client;
2 | using ModelContextProtocol.Tests.Utils;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace ModelContextProtocol.Tests.Transport;
6 |
7 | public class StdioClientTransportTests(ITestOutputHelper testOutputHelper) : LoggedTest(testOutputHelper)
8 | {
9 | [Fact]
10 | public async Task CreateAsync_ValidProcessInvalidServer_Throws()
11 | {
12 | string id = Guid.NewGuid().ToString("N");
13 |
14 | StdioClientTransport transport = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
15 | new(new() { Command = "cmd", Arguments = ["/C", $"echo \"{id}\" >&2"] }, LoggerFactory) :
16 | new(new() { Command = "ls", Arguments = [id] }, LoggerFactory);
17 |
18 | IOException e = await Assert.ThrowsAsync(() => McpClientFactory.CreateAsync(transport, loggerFactory: LoggerFactory, cancellationToken: TestContext.Current.CancellationToken));
19 | Assert.Contains(id, e.ToString());
20 | }
21 | }
22 |
--------------------------------------------------------------------------------