๊ณต์‹ C# MCP SDK 1.0 ์ถœ์‹œ

์ž์„ธํ•œ ๋‚ด์šฉ ๋ณด๊ธฐ: Release v1.0 of the official MCP C# SDK - .NET Blog

MCP(Model Context Protocol) C# SDK๊ฐ€ v1.0 ๋งˆ์ผ์Šคํ†ค์— ๋„๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ๋ฆด๋ฆฌ์Šค๋Š” MCP ์ŠคํŽ™ 2025-11-25 ๋ฒ„์ „์„ ์™„์ „ํ•˜๊ฒŒ ์ง€์›ํ•˜๋ฉฐ, ์ธ์ฆ ํ๋ฆ„ ๊ฐœ์„ ๋ถ€ํ„ฐ ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ ์ฒ˜๋ฆฌ, ์‹คํ—˜์  ๊ธฐ๋Šฅ์ธ Tasks๊นŒ์ง€ ํญ๋„“์€ ๋ณ€ํ™”๋ฅผ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ต์‹ฌ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.


1. ์ธ์ฆ ์„œ๋ฒ„ ๋””์Šค์ปค๋ฒ„๋ฆฌ ๊ฐœ์„ 

์„œ๋ฒ„๊ฐ€ Protected Resource Metadata(PRM) ๋ฌธ์„œ๋ฅผ ๋…ธ์ถœํ•˜๋Š” ๊ฒฝ๋กœ๊ฐ€ ์„ธ ๊ฐ€์ง€๋กœ ํ™•์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  1. WWW-Authenticate ํ—ค๋”์˜ resource_metadata ํŒŒ๋ผ๋ฏธํ„ฐ (๊ธฐ์กด ๋ฐฉ์‹)

  2. MCP ์—”๋“œํฌ์ธํŠธ ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ well-known URL (์˜ˆ: /.well-known/oauth-protected-resource/public/mcp)

  3. ๋ฃจํŠธ well-known URL (์˜ˆ: /.well-known/oauth-protected-resource)

ํด๋ผ์ด์–ธํŠธ๋Š” ์ด ์„ธ ์œ„์น˜๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ํƒ์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์ธก์—์„œ๋Š” AddMcp ํ™•์žฅ ๋ฉ”์„œ๋“œ๋กœ PRM์„ ๊ตฌ์„ฑํ•˜๋ฉด, SDK๊ฐ€ well-known ๊ฒฝ๋กœ ํ˜ธ์ŠคํŒ…๊ณผ WWW-Authenticate ํ—ค๋” ์„ค์ •์„ ์ž๋™ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

2. ๋„๊ตฌยท๋ฆฌ์†Œ์Šคยทํ”„๋กฌํ”„ํŠธ์— ์•„์ด์ฝ˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ถ”๊ฐ€

tools/list, resources/list, prompts/list ์‘๋‹ต์— ์•„์ด์ฝ˜ ์ •๋ณด๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ McpServerToolAttribute์˜ IconSource ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์“ฐ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

[McpServerTool(Title = "๋‚ ์”จ ์กฐํšŒ", IconSource = "https://example.com/weather-icon.svg")]
public static string GetWeather(...)

MIME ํƒ€์ž…, ํฌ๊ธฐ ํžŒํŠธ, ๋ผ์ดํŠธ/๋‹คํฌ ํ…Œ๋งˆ ๊ตฌ๋ถ„์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ McpServerToolCreateOptions.Icons๋ฅผ ํ†ตํ•ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, Implementation ํด๋ž˜์Šค์—๋„ Icons์™€ WebsiteUrl ์†์„ฑ์ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

3. ์ ์ง„์  ์Šค์ฝ”ํ”„ ๋™์˜ (Incremental Scope Consent)

์ตœ์†Œ ๊ถŒํ•œ ์›์น™์„ MCP ์ธ์ฆ์— ์ ์šฉํ•œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ธ์ฆ ์—†์ด ์š”์ฒญํ•˜๋ฉด ์„œ๋ฒ„๋Š” 401๊ณผ ํ•จ๊ป˜ ํ•„์š”ํ•œ ์Šค์ฝ”ํ”„๋ฅผ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค.

  • ํ† ํฐ์— ํŠน์ • ์ž‘์—…์˜ ์Šค์ฝ”ํ”„๊ฐ€ ๋ถ€์กฑํ•˜๋ฉด 403 Forbidden + insufficient_scope ์—๋Ÿฌ๋กœ ์ถ”๊ฐ€ ์Šค์ฝ”ํ”„๋ฅผ ์•ˆ๋‚ดํ•ฉ๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ SDK๋Š” ์ด ํ๋ฆ„์„ ์ž๋™ ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ ๋ณ„๋„ ์ฝ”๋“œ๊ฐ€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์ธก์—์„œ๋Š” ASP.NET Core ๋ฏธ๋“ค์›จ์–ด์—์„œ ์ธ๊ฐ€ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š”๋ฐ, MCP HTTP ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋„๊ตฌ ํ˜ธ์ถœ ์ „์— ์‘๋‹ต ํ—ค๋”๋ฅผ flushํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋„๊ตฌ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€๊ฐ€ ์•„๋‹Œ ๋ฏธ๋“ค์›จ์–ด์—์„œ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

4. URL ๋ชจ๋“œ Elicitation

MCP ํ˜ธ์ŠคํŠธ/ํด๋ผ์ด์–ธํŠธ๋ฅผ ์šฐํšŒํ•˜์—ฌ ์„œ๋ฒ„์™€ ์ตœ์ข… ์‚ฌ์šฉ์ž ๊ฐ„์— ๋Œ€์—ญ ์™ธ(out-of-band) ์ƒํ˜ธ์ž‘์šฉ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. API ํ‚ค, ์„œ๋“œํŒŒํ‹ฐ ์ธ์ฆ, ๊ฒฐ์ œ ์ •๋ณด ๊ฐ™์€ ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ๋Š” Capabilities.Elicitation.Url์„ ์„ค์ •ํ•˜๊ณ  ElicitationHandler๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • ์„œ๋ฒ„๋Š” Elicitation URL ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ •์˜ํ•˜๊ณ , Razor Page ๋“ฑ์œผ๋กœ ํผ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Streamable HTTP Transport์˜ ๋ฉ€ํ‹ฐํ…Œ๋„ŒํŠธ ํŠน์„ฑ์ƒ, ๊ฐ Elicitation ์š”์ฒญ์„ ์˜ฌ๋ฐ”๋ฅธ MCP ์„ธ์…˜์— ์—ฐ๊ฒฐํ•˜๋Š” ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

5. ์ƒ˜ํ”Œ๋ง์—์„œ์˜ ๋„๊ตฌ ํ˜ธ์ถœ ์ง€์›

์ด๋ฒˆ ์ŠคํŽ™์—์„œ ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ์ถ”๊ฐ€ ์‚ฌํ•ญ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ์ƒ˜ํ”Œ๋ง ์š”์ฒญ์— ๋„๊ตฌ๋ฅผ ํฌํ•จ์‹œํ‚ค๋ฉด, LLM์ด ํ•ด๋‹น ๋„๊ตฌ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‘๋‹ต์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ํ๋ฆ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

  1. ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ์— CreateMessage ์š”์ฒญ (ํ”„๋กฌํ”„ํŠธ + ๋„๊ตฌ ์ •์˜ ํฌํ•จ)

  2. ํด๋ผ์ด์–ธํŠธ(LLM)๊ฐ€ ๋„๊ตฌ ํ˜ธ์ถœ์„ ์š”์ฒญํ•˜๋Š” ์‘๋‹ต ๋ฐ˜ํ™˜ (stopReason: tool_calls)

  3. ์„œ๋ฒ„๊ฐ€ ๋„๊ตฌ๋ฅผ ๋กœ์ปฌ ์‹คํ–‰ํ•œ ๋’ค, ๋„๊ตฌ ํ˜ธ์ถœ/์‘๋‹ต์„ ํฌํ•จํ•œ ์ƒˆ CreateMessage ์š”์ฒญ ๋ฐœ์†ก

  4. ์ตœ์ข… ์‘๋‹ต์ด ์˜ฌ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต

Microsoft.Extensions.AI์˜ IChatClient์™€ CreateSamplingHandler()๋ฅผ ํ™œ์šฉํ•˜๋ฉด MCP-LLM ๊ฐ„ ํฌ๋งท ๋ณ€ํ™˜์„ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์ธก์—์„œ๋Š” McpServer.AsSamplingChatClient()๋กœ IChatClient๋ฅผ ์–ป๊ณ , UseFunctionInvocation()์œผ๋กœ ๋„๊ตฌ ํ˜ธ์ถœ์„ ์ถ”๊ฐ€ํ•˜๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค.

6. Client ID Metadata Documents (CIMD)

Dynamic Client Registration(DCR)์˜ ๋Œ€์•ˆ์œผ๋กœ, ์ด์ œ MCP์—์„œ ํด๋ผ์ด์–ธํŠธ ๋“ฑ๋ก์˜ ๊ถŒ์žฅ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๊ฐ€ client_id๋กœ URL์„ ์ง€์ •ํ•˜๋ฉด, ์ธ๊ฐ€ ์„œ๋ฒ„๊ฐ€ ํ•ด๋‹น URL์—์„œ JSON ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค.

SDK๋Š” CIMD๋ฅผ ๋จผ์ € ์‹œ๋„ํ•˜๊ณ , ์ธ๊ฐ€ ์„œ๋ฒ„๊ฐ€ ๋ฏธ์ง€์› ์‹œ DCR๋กœ ํด๋ฐฑํ•ฉ๋‹ˆ๋‹ค.

7. HTTP ๊ธฐ๋ฐ˜ ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ โ€” ํด๋ง ๋ฐฉ์‹

HTTP ํƒ€์ž„์•„์›ƒ ํ™˜๊ฒฝ์—์„œ ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด ๊ฐœ์„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  • ์„œ๋ฒ„๊ฐ€ SSE ์ŠคํŠธ๋ฆผ์„ ์—ด ๋•Œ Event ID๊ฐ€ ํฌํ•จ๋œ ๋นˆ ์ด๋ฒคํŠธ๋ฅผ ๋จผ์ € ๋ณด๋ƒ…๋‹ˆ๋‹ค.

  • ์ดํ›„ ์„œ๋ฒ„๊ฐ€ ์–ธ์ œ๋“  ์ŠคํŠธ๋ฆผ์„ ๋‹ซ์„ ์ˆ˜ ์žˆ๊ณ , ํด๋ผ์ด์–ธํŠธ๋Š” Event ID๋กœ ์žฌ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

  • ISseEventStreamStore ๊ตฌํ˜„์ฒด๋ฅผ ์ œ๊ณตํ•˜๋ฉด ๋˜๋ฉฐ, SDK์— ํฌํ•จ๋œ DistributedCacheEventStreamStore๋Š” IDistributedCache ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

  • ํ•ธ๋“ค๋Ÿฌ์—์„œ context.EnablePollingAsync()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด SSE ์—ฐ๊ฒฐ์„ ๋Š๊ณ  ํด๋ง ๋ชจ๋“œ๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด ์„ธ์…˜ ์ข…๋ฃŒ ์‹œ ์ŠคํŠธ๋ฆผ ์‚ญ์ œ, ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ ๋งŒ๋ฃŒ ์ •์ฑ…, ์„ ํƒ์  ์ด๋ฒคํŠธ ์ €์žฅ ๋“ฑ์˜ ๋ณด์กด ์ „๋žต์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

8. Tasks (์‹คํ—˜์  ๊ธฐ๋Šฅ)

:warning: MCP ์ŠคํŽ™ 2025-11-25์˜ ์‹คํ—˜์  ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ํ–ฅํ›„ API ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด ์š”์ฒญ์— ๋‚ด๊ตฌ์„ฑ ์žˆ๋Š” ์ƒํƒœ ์ถ”์ ๊ณผ ์ง€์—ฐ ๊ฒฐ๊ณผ ์กฐํšŒ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์ƒˆ๋กœ์šด ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ์ž…๋‹ˆ๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์š”์ฒญ์— task ํ•„๋“œ๋ฅผ ํฌํ•จํ•˜๋ฉด, ์„œ๋ฒ„๋Š” Task IDยท์ƒํƒœยทTTL ๋“ฑ์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  • ์ดํ›„ tasks/get(์ƒํƒœ ํด๋ง), tasks/result(๊ฒฐ๊ณผ ์กฐํšŒ), tasks/list(๋ชฉ๋ก), tasks/cancel(์ทจ์†Œ)๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

  • Task ์ƒํƒœ๋Š” working โ†’ completed | failed | cancelled (+ input_required)์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

์„œ๋ฒ„์—์„œ๋Š” IMcpTaskStore๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ Task ์Šคํ† ์–ด๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. SDK์— ํฌํ•จ๋œ InMemoryMcpTaskStore๋Š” ๊ฐœ๋ฐœ ๋ฐ ๋‹จ์ผ ์„œ๋ฒ„ ๋ฐฐํฌ์— ์ ํ•ฉํ•˜๋ฉฐ, ํ”„๋กœ๋•์…˜ ๋ฉ€ํ‹ฐ ์„œ๋ฒ„ ํ™˜๊ฒฝ์—์„œ๋Š” DB๋‚˜ Redis ๋“ฑ ์˜์† ์ €์žฅ์†Œ ๊ธฐ๋ฐ˜ ๊ตฌํ˜„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๋น„๋™๊ธฐ ๋ฉ”์„œ๋“œ(Task<T>, ValueTask<T> ๋ฐ˜ํ™˜)๋Š” ์ž๋™์œผ๋กœ Task ์ง€์›์„ ์„ ์–ธํ•˜๋ฉฐ, McpServerToolAttribute์˜ TaskSupport ์†์„ฑ์œผ๋กœ Forbidden, Optional, Required๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


์ฐธ๊ณ  ๋งํฌ


์ด๋ฒˆ ๋ฆด๋ฆฌ์Šค๋Š” .NET ์ƒํƒœ๊ณ„์—์„œ MCP ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐ ์žˆ์–ด ๋ณธ๊ฒฉ์ ์ธ ํ”„๋กœ๋•์…˜ ๋ ˆ๋ฒจ์˜ ๊ธฐ๋ฐ˜์ด ๋งˆ๋ จ๋œ ๊ฒƒ์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ์ธ์ฆ ํ๋ฆ„, ์ƒ˜ํ”Œ๋ง ๋„๊ตฌ ํ˜ธ์ถœ, ์žฅ๊ธฐ ์‹คํ–‰ ์ฒ˜๋ฆฌ ํŒจํ„ด์€ ์‹ค์ œ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ๋ฐ”๋กœ ํ™œ์šฉ ๊ฐ€๋Šฅํ•œ ์ˆ˜์ค€์ž…๋‹ˆ๋‹ค.

์ด ์•„ํ‹ฐํด์€ ์ƒ์„ฑํ˜• AI๋ฅผ ํ†ตํ•ด ๋ฒˆ์—ญ/์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

2๊ฐœ์˜ ์ข‹์•„์š”