올려주신 내용이 좀 더 구체적으로 문서화된 것이 있나 해서 찾아보니 역시 reddit에 구체적인 내용이 있네요!
https://www.reddit.com/r/rust/comments/1kwjmjm/dotnet_10_introduces_implicit_projects_with_a/
그리고 이 기능을 implicit project (암시적 프로젝트)라고 부르는 것 같습니다.
본래 C#에서는 '#'으로 시작하는 것이 매크로 전처리기 밖에 없었던 것 같은데, 이 기능을 위해서 문법이 확장된 모양입니다. 파일의 시작을 다음과 같이 구성할 수 있습니다.
#!/usr/bin/dotnet run
#:sdk Microsoft.NET.Sdk.Web
제일 첫 줄은 Shebang으로 배시 셸 스크립트나 파워셸 스크립트 첫 줄에 sh, bash, zsh가 이 파일을 실행 파일로 다루려 할 때 해당 스크립트를 어느 인터프리터와 연결시킬지 결정하는 부분입니다. '#'을 전처리 기호로 쓴 것은 그래서 굉장히 영리한 선택이라는 생각이 듭니다 ㅎㅎ
이런 특성 덕분에 아래처럼 리눅스 명령어를 실행하면 .NET SDK 10 버전이 설치되어있기만 해도 바로 셸 파일처럼 닷넷 프로그램을 쓸 수 있습니다.
chmod +x ./app.cs
./app.cs
그리고 그 다음에 오는 라인들은 CSPROJ의 핵심 설정들 중 중요한 설정들을 편하게 지정할 수 있게 되어있었습니다. 덕분에 implicit project를 이용해서 ASP .NET Core Web API 서버도 손쉽게 만들 수 있습니다.
제가 요즈음 ASP .NET Core 기반 SSE MCP 서버를 만들어보고 있던 참이어서, LINQPad로 되어있던 예제를 그대로 옮겨올 수 있는지 테스트해봤는데 아주 훌륭하게 이식이 됩니다.
#!/usr/bin/dotnet run
#:sdk Microsoft.NET.Sdk.Web
#:package ModelContextProtocol@0.2.0-preview*
#:package ModelContextProtocol.AspNetCore@0.2.0-preview*
#:package OpenTelemetry.Exporter.OpenTelemetryProtocol@1.12.*
#:package OpenTelemetry.Extensions.Hosting@1.12.*
#:package OpenTelemetry.Instrumentation.AspNetCore@1.12.*
#:package OpenTelemetry.Instrumentation.Http@1.12.*
// Cloudflare로 tunnel을 만들기 위해서 cloudflared를 사용하면 편리합니다.
// winget install --id Cloudflare.cloudflared
// cloudflared tunnel --url http://localhost:5000
#if LINQPAD
var args = Environment.GetCommandLineArgs().Skip(1).ToArray();
#endif
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Server;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
using System.ComponentModel;
using System.Threading.Tasks;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMcpServer()
.WithHttpTransport()
.WithTools<EchoTool>()
.WithTools<EchoTool2>()
.WithTools<SampleLlmTool>();
builder.Services.AddOpenTelemetry()
.WithTracing(b => b.AddSource("*")
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation())
.WithMetrics(b => b.AddMeter("*")
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation())
.WithLogging()
.UseOtlpExporter();
var app = builder.Build();
app.MapMcp();
app.Run();
[McpServerToolType]
public sealed class EchoTool
{
[McpServerTool, Description("Echoes the input back to the client.")]
public static string Echo(string message)
{
return "hello " + message;
}
}
[McpServerToolType]
public sealed class EchoTool2
{
[McpServerTool, Description("Echoes the input back to the client with Korean.")]
public static string Echo2(string message)
{
return "안녕! " + message;
}
}
[McpServerToolType]
public sealed class SampleLlmTool
{
[McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
public static async Task<string> SampleLLM(
IMcpServer thisServer,
[Description("The prompt to send to the LLM")] string prompt,
[Description("Maximum number of tokens to generate")] int maxTokens,
CancellationToken cancellationToken)
{
ChatMessage[] messages =
[
new(ChatRole.System, "You are a helpful test server."),
new(ChatRole.User, prompt),
];
ChatOptions options = new()
{
MaxOutputTokens = maxTokens,
Temperature = 0.7f,
};
var samplingResponse = await thisServer.AsSamplingChatClient().GetResponseAsync(messages, options, cancellationToken);
return $"LLM sampling result: {samplingResponse}";
}
}
그리고 이렇게 만든 첫 파일을 dotnet project convert <app.cs 파일 경로>
명령어로 실행하면 Grow up 이라는 기능이 호출되어 일반적인 .NET SDK 프로젝트로 전환하는 것까지 완결성있게 처리되어 제가 앞에서 이야기했던 것처럼 빠른 프로토타이핑에서 시작하여 완성된 프로젝트로 전환하는 경험까지 구현되는 것이어서 마음에 쏙 듭니다.
아직 .NET 10이 프리뷰 버전이지만 그럼에도 지금부터 사용할 만한 강력한 동인이 저에게는 새롭게 생긴것 같습니다. ㅎㅎ