@Module·@Injectable·@Tool·의존성 주입(DI)·가드/파이프/인터셉터에다, OAuth 2.1 인증과 채팅창 안에서 렌더되는 React "위젯"까지 기본 탑재다. 먼저 오해를 풀자 — 이건 MCP SDK를 대체하는 게 아니다. 공식 @modelcontextprotocol/sdk "위에" 앉아 그 저수준 배관을 데코레이터·모듈·DI로 감싸는 애플리케이션 프레임워크다.
두 번째로 각인할 것 — "엔터프라이즈/프로덕션 레디"라는 간판과 실제 저장소 상태 사이엔 틈이 있다. 프레임워크 코드는 진짜로 두껍고 성숙(인증·트랜스포트·697개 테스트)하지만, CI가 없고 Dockerfile이 안 딸려 오며 핵심 DX 도구(NitroStudio)는 비공개다. 이 문서는 소스를 직접 클론해 "이 저장소에서 무엇을 배울 수 있는가"와 "어디를 조심해야 하는가"를 함께 파고든다.
(저장소: nitrocloudofficial/nitrostack · TypeScript 모노레포 · Apache-2.0 · npm @nitrostack/core v1.0.13 / @nitrostack/cli v1.0.14 / @nitrostack/widgets v1.0.8 · 별 1,172 · 생성 2026-03-03 · 이번 회차는 TrendShift Daily·Weekly·Monthly가 모두 기분석 소진되어 OSSInsight 순위로 폴백)
nitrocloudofficial/nitrostack(줄여서 NitroStack)은 공식 MCP SDK로 도구 서버를 맨손으로 짤 때 반복되는 배관(트랜스포트 연결·세션 관리·인증·검증·핸들러 등록)을, NestJS 스타일 데코레이터와 DI 컨테이너로 감싸 없애 주는 TypeScript 프레임워크다. 저장소가 내건 한 줄은 이것 — "The enterprise-grade TypeScript framework for building production-ready MCP servers. Decorators. Dependency Injection. Widgets."(프로덕션급 MCP 서버를 만드는 엔터프라이즈 등급 TypeScript 프레임워크. 데코레이터. 의존성 주입. 위젯).
핵심은 "SDK는 라이브러리, NitroStack은 프레임워크"라는 포지셔닝이다. 개발자는 트랜스포트나 요청 라우팅을 신경 쓰지 않고, 함수 하나에 @Tool 데코레이터만 붙이면 그게 곧 에이전트가 호출할 수 있는 MCP 도구가 된다. 여기에 @Module·@Injectable(DI), @UseGuards(인증 게이트), @Widget(채팅창 안 React UI)까지 얹혀 있어, "비즈니스 로직만 쓰면 나머지는 프레임워크가"라는 NestJS의 개발 경험을 MCP 세계로 그대로 옮겨 왔다.
@modelcontextprotocol/sdk ^1.0.4)를 그대로 품고 그 위에 애플리케이션 계층을 덧댄다.@Controller·@Injectable·@Module, 싱글턴/트랜지언트/스코프드 생명주기, 가드·파이프·인터셉터·필터 파이프라인, OnModuleInit 같은 생명주기 훅까지. npm 패키지 키워드에 문자 그대로 nestjs-inspired가 박혀 있다. 그래서 NestJS를 써 봤다면 학습 곡선이 거의 없다.공식 MCP SDK로 서버를 짜는 건 전선을 벽에 직접 매설하고 차단기·접지·계량기를 손수 연결하는 것과 같다. 한 번은 되지만, 인증·세션·검증을 매번 다시 배선해야 하고 실수하면 감전(보안 구멍)이다.
NitroStack은 이미 배선·차단기·계량기가 다 들어간 배전반을 준다. 개발자는 "여기에 조명(@Tool), 저기에 콘센트(@Resource)"라고 스위치만 붙이면 된다. 인증(OAuth 2.1)·트랜스포트(stdio/HTTP)·검증(zod)은 배전반이 알아서 처리한다. 게다가 같은 배전반으로 로컬(stdio)·서버(HTTP) 어느 쪽이든 똑같이 켤 수 있다.
NitroStack이 4개월 남짓 만에 별 1,100+를 모으며 트렌딩에 오른 이유는 타이밍이다. 2025년 이후 MCP가 사실상 "AI 도구 연결의 표준"으로 자리 잡으면서 수많은 팀이 MCP 서버를 짜기 시작했는데, 정작 그걸 구조적으로 만들 "프레임워크"는 비어 있었다. FastMCP 같은 도구가 있었지만 대체로 "함수 등록 래퍼" 수준이었다. NitroStack은 여기서 한참 더 나아가 NestJS급 애플리케이션 프레임워크를 자처했다.
| 포인트 | 내용 |
|---|---|
| 정체 | MCP 서버 애플리케이션 프레임워크. 공식 SDK 위에 데코레이터·DI·모듈·가드/파이프/인터셉터/필터·인증·위젯을 얹음. 3개 npm 패키지(core·cli·widgets), TypeScript 38,398줄. |
| 차별점 ① | NestJS를 통째로 이식. @Module·@Injectable·@Controller, DI 생명주기(singleton/transient/scoped), 가드·파이프·인터셉터·필터·생명주기 훅. NestJS 경험자에게 학습비용 0. |
| 차별점 ② | 진짜 OAuth 2.1 인증이 기본. PKCE·동적 클라이언트 등록·토큰 검토(introspection)·보호 리소스 메타데이터를 RFC(7591/7636/8414/8707/9728/7662) 기준으로 실제 구현(약 3,500줄). |
| 차별점 ③ | 채팅창 안에서 렌더되는 위젯. 도구 결과에 Next.js(App Router) React 컴포넌트를 붙여 리치 카드로 표시. OpenAI Apps SDK(ChatGPT)와 MCP Apps 양쪽 호환. |
| 차별점 ④ | 세 가지 트랜스포트. stdio(로컬), Streamable HTTP(2025-06-18 스펙, 세션·재개 지원), 레거시 HTTP+SSE(Cursor 등). NODE_ENV로 자동 선택. |
| 주의할 간판 | "엔터프라이즈·프로덕션 레디"는 절반만 사실. 코드는 성숙하나 공개 저장소엔 CI 없음·Dockerfile 없음·핵심 도구(NitroStudio) 비공개·CLI 텔레메트리(PostHog) 내장. (§10에서 상술) |
공식 @modelcontextprotocol/sdk는 훌륭하지만 라이브러리다 — 트랜스포트, 요청 핸들러 같은 원시 재료를 준다. 서버를 진지하게 만들려면 인증·세션·검증·라우팅을 매번 손으로 배선해야 한다. NitroStack은 그 반복 배관을 애플리케이션 계층으로 흡수했다. 웹 개발에서 "Express(라이브러리) 위에 NestJS(프레임워크)"가 등장한 것과 정확히 같은 구도를, MCP 세계에서 재현했다. MCP 서버 수요가 폭발하는 시점에 나온 "프레임워크 공백을 메우는" 포지션이 트렌딩의 동력이다.
장난감 MCP 서버는 쉽다. 문제는 프로덕션에 필요한 "미들 마일" — 인증, 세션, 리치 UI다. NitroStack은 이 셋을 정면으로 판다. OAuth 2.1 + PKCE를 명명된 RFC 기준으로 구현한 건 오픈소스에서 드문 "읽을 만한 참조 구현"이고, 위젯은 도구 결과를 ChatGPT/MCP 클라이언트 안에서 인터랙티브 카드로 그린다(text/html+skybridge MIME, CSP 샌드박싱). "AI가 도구를 쓰는" 워크플로가 단순 텍스트를 넘어 UI로 확장되는 지금, 정확히 그 지점을 겨냥한다.
vs 공식 @modelcontextprotocol/sdk 직접 사용 — SDK는 NitroStack의 내부 의존성(토대)이다. SDK가 벽돌이라면 NitroStack은 집. 배관을 데코레이터로 감춘다.
vs FastMCP · 함수 등록형 래퍼 — 그것들은 대체로 "함수에 도구 딱지 붙이기" 수준. NitroStack은 DI·모듈·가드·인증·위젯까지 가는 애플리케이션 프레임워크다.
vs NestJS — NitroStack이 "베낀" 원본. 다만 HTTP 라우트가 아니라 MCP 도구/리소스/프롬프트를 1급 시민으로 다룬다. NestJS 지식이 거의 그대로 전이된다.
vs "Next.js for MCP" — 위젯 시스템 때문에 종종 이렇게도 불린다. 도구 출력에 Next.js React 컴포넌트를 붙여 인앱 UI를 렌더하는 부분이 그 프레이밍의 근거.
NitroStack은 typescript/packages/ 아래에 3개의 독립 배포 패키지를 둔 모노레포다. 그런데 흥미로운 결정이 하나 있다 — turbo·nx·lerna·pnpm-workspace 같은 모노레포 도구가 전혀 없고, 루트 package.json에 workspaces 필드조차 없다. 빌드 스크립트가 각 패키지로 cd해 순차로 tsc를 돌리는 "손빌드" 방식이다. 언어는 TypeScript 5.7.2, 전면 ESM("type":"module"), 타깃 ES2022, 그리고 데코레이터 시스템의 심장인 experimentalDecorators + emitDecoratorMetadata가 켜져 있다.
| 패키지 | 배포 이름 · 역할 |
|---|---|
| packages/core | npm @nitrostack/core v1.0.13 — 프레임워크 본체(약 24,487줄). 서버·데코레이터·DI·모듈·인증·가드/파이프. npm에 11개 버전(첫 배포 2026-01-31). |
| packages/cli | npm @nitrostack/cli v1.0.14 — CLI(약 11,568줄). 프로젝트 스캐폴딩·핫리로드 개발서버·esbuild 번들·스킬 설치. 바이너리 nitrostack-cli. |
| packages/widgets | npm @nitrostack/widgets v1.0.8 — React 위젯 SDK(약 2,343줄). 채팅창 안 UI를 위한 훅·런타임·SDK. |
| (루트 메타) | npm nitrostack v1.0.85 — 세 패키지를 묶는 메타 패키지. |
@nitrostack/core — 프레임워크의 심장순수 tsc로 빌드한다(번들러 없음). 진짜 일은 여기서 다 벌어진다. 런타임 의존성이 제법 많은데, 각각이 프레임워크의 한 축을 담당한다.
| 의존성 (버전) | 역할 |
|---|---|
| @modelcontextprotocol/sdk ^1.0.4 | 공식 MCP SDK — 트랜스포트·서버 원시 기능(NitroStack이 그 위에 앉음) |
| express ^4.21.2 | HTTP 트랜스포트 서버 |
| zod ^3.24.1 zod-to-json-schema ^3.24.6 | 스키마 검증(v3) + Zod→JSON Schema 변환(MCP 도구 스키마 생성). v3이지 v4 아님 |
| jose ^6.1.0 · jsonwebtoken ^9.0.2 | JWT/JWS/JWK — OAuth 인증의 토큰 처리 |
| bcryptjs ^2.4.3 | API 키·시크릿 해싱 |
| reflect-metadata ^0.2.1 | 데코레이터 메타데이터 — DI와 데코레이터 시스템의 뼈대 |
| winston ^3.17.0 | 구조적 로깅 |
| ws ^8.18.3 · cors ^2.8.5 · dotenv ^17.2.3 · uuid ^11.0.5 | WebSocket · CORS · 환경설정 · 세션 ID |
peerDependency로 @modelcontextprotocol/ext-apps >=0.1.0(MCP Apps / 위젯)를 요구한다.
@nitrostack/cli — 스캐폴딩과 개발 경험프로젝트를 만들고(init) 핫리로드로 돌리고(dev) esbuild로 사용자 프로젝트를 번들한다(build). 여기에 한 가지 주의점이 숨어 있다 — PostHog 텔레메트리가 내장돼 있어 사용 데이터를 외부로 보낸다.
| 의존성 (버전) | 역할 |
|---|---|
| commander ^12.1.0 | CLI 명령 파서 |
| esbuild ^0.24.0 | 사용자 프로젝트 번들러 |
| chokidar ^3.6.0 | 파일 감시(핫리로드) |
| inquirer ^9.3.7 · chalk ^5.3.0 · ora ^8.1.1 | 대화형 프롬프트 · 색상 · 스피너(TTY UI) |
| fs-extra ^11.3.2 · open ^10.1.0 | 파일 조작 · 브라우저 열기 |
| posthog-node ^5.21.2 | 텔레메트리(src/analytics/posthog.ts) — 프라이버시 민감 사용자는 주의 |
@nitrostack/widgets · 테스트 · 트랜스포트위젯 SDK는 React ^18 || ^19를 peer로 받고(개발은 React 19), @modelcontextprotocol/ext-apps를 함께 요구한다. 테스트는 코어·CLI 전반에서 Jest 29.7 + ts-jest를 ESM 모드(NODE_OPTIONS=--experimental-vm-modules)로 돌리며 — 69개 테스트 파일·약 697개 케이스·263개 describe로 실제 커버리지가 있다(스텁 아님). 트랜스포트는 server.ts 기준 세 가지다.
| 트랜스포트 | 클래스 · 용도 |
|---|---|
| stdio | StdioServerTransport — 로컬(Claude Desktop 등). NODE_ENV=development 기본값 |
| Streamable HTTP | StreamableHTTPServerTransport — 2025-06-18 스펙, 단일 엔드포인트 POST+GET/SSE, Mcp-Session-Id·Last-Event-ID로 세션·재개 지원 |
| 레거시 HTTP+SSE | SSEServerTransport — 구형 클라이언트(Cursor 등) 호환 |
모드는 NODE_ENV로 자동 선택된다(development→stdio, production→stdio+HTTP 이중). MCP_TRANSPORT_TYPE 환경변수로 강제 지정도 가능하다.
NitroStack의 생애는 McpApplicationFactory.create(AppModule) 한 줄에서 시작한다. 이 팩토리가 데코레이터로 심어 둔 메타데이터를 reflect-metadata로 읽어 애플리케이션을 조립한다. 아래는 생태계 4계층과 부트스트랩 흐름이다.
실제 요청이 들어오면 NestJS와 판박이인 파이프라인을 탄다. core/src/core/tool.ts에서 확인되는 도구 호출 생명주기는 이렇다.
구체적으로는 guard.canActivate(context)가 실행을 통과시킬지 결정하고(약 159행), executeWithInterceptors가 executeWithPipes를 감싸며, 그 안에서 pipe.transform(...)이 핸들러 앞에 실행된다. 여기에 @Cache({ttl})·@RateLimit(...)·@HealthCheck 같은 횡단 관심사 데코레이터가 더 끼어든다. 아래는 이 프레임워크를 떠받치는 네 가지 핵심 설계다.
@Tool·@Resource·@Prompt·@Widget·@Controller·@InitialTool이 클래스에 Reflect.defineMetadata로 메타데이터를 심고, 부트스트랩 때 extractTools/extractResources/extractPrompts가 그걸 되읽어 등록한다. @Controller('github')는 도구 이름에 접두사를 붙여(create_issue → github_create_issue) 자동으로 DI에 등록한다.
// NestJS를 아는 사람에겐 낯익은 그림 — @Tool이 곧 MCP 도구
@Controller('github') // 도구 이름에 github_ 접두사
export class GithubTools {
constructor(private gh: GithubService) {} // DI 주입
@Tool({ description: '이슈를 생성한다' })
async create_issue(input: CreateIssueInput, ctx: ExecutionContext) {
ctx.logger.info('creating issue');
return await this.gh.create(input); // → github_create_issue 로 노출
}
}
di/container.ts의 컨테이너가 @Injectable·@Inject로 의존성을 해결하고, 싱글턴/트랜지언트/스코프드 생명주기를 관리한다(lifecycle.ts). 애플리케이션은 @Module({ imports, providers })로 조립하며, ConfigModule.forRoot()·JWTModule·ApiKeyModule·OAuthModule 같은 기능 모듈을 가져다 쓴다. OnModuleInit·OnApplicationBootstrap 같은 생명주기 훅도 NestJS 그대로다.
auth/ 디렉토리(약 3,500줄 + 11개 테스트 파일)는 이 저장소에서 가장 값진 참조 구현이다. simple-jwt · token-store · token-validation · pkce · secure-secret · server-metadata · api-key · client · middleware로 나뉘어, OAuth 2.1의 리소스 서버 + 권한 서버를 명명된 RFC 기준으로 구현한다.
위젯 브리지(widget-mcp-meta.ts·ui-next/·widgets/)는 도구 결과에 OpenAI Apps SDK와 MCP Apps 두 규격의 UI 메타데이터를 병합한다 — CSP 허용목록, widgetDomain, prefersBorder 등을 얹고, Next.js 라우트가 실제 UI를 렌더한다(OpenAI 쪽은 text/html+skybridge MIME + openai/widget* 메타). MCP Tasks(task.ts, 556줄)는 TaskManager/TaskContext로 상태 머신을 굴려 오래 걸리는 비동기 도구를 지원한다(도구별 taskSupport: 'forbidden'|'optional'|'required').
server.ts(1,572) · oauth-module.ts(883) · ui-next/index.ts(767) · task.ts(556) · tool.ts(477) · app-decorator.ts(466). 진짜 무게중심이 "트랜스포트 + 서버 + 인증 + 위젯"에 있음이 파일 크기로 드러난다 — 마케팅이 아니라 실제 코드가 그 자리에 있다.core/src/core/와 core/src/auth/클론 직후의 구조다. 전체 371개 추적 파일, TypeScript 38,398줄. 공개 저장소는 단일 스쿼시 스냅샷 커밋(7d63f9e, "Versions Updated", 2026-07-14)이라 실제 개발 이력은 보이지 않는다 — 내부 모노레포의 "릴리스 미러"로 읽힌다.
모든 서브시스템에 __tests__/가 나란히 붙어 있다. 이 저장소를 읽을 때 지적 핵심은 두 곳 — core/src/core/(프레임워크 배관)와 core/src/auth/(OAuth 구현)다.
README.md로 전체 그림과 설치를 잡고 → ② core/app-decorator.ts에서 부트스트랩(@McpApp·McpApplicationFactory)이 어떻게 도는지 → ③ core/tool.ts에서 도구 생명주기(가드→인터셉터→파이프→핸들러)를 확인 → ④ di/container.ts로 DI 해결을 보고 → ⑤ 여유가 되면 auth/에서 OAuth 2.1을 정독한다. templates/typescript-starter(계산기 예제)를 나란히 열어 두면 "데코레이터가 실제로 어떻게 쓰이는지"가 손에 잡힌다.NitroStack이 학습 표본으로 훌륭한 이유는 프레임워크 설계·TypeScript 데코레이터·의존성 주입·MCP 프로토콜·OAuth 2.1·대규모 테스트·AI 네이티브 UI가 한 저장소에 모여 있기 때문이다. 관심사별로 짚어 보자.
DI 컨테이너, 모듈 그래프, 데코레이터 메타데이터 레지스트리, 가드/파이프/인터셉터/필터 파이프라인 — NestJS의 개념들이 어떻게 실제로 도는지를 읽기 좋은 크기(코어 24K줄)로 재현해 놨다. NestJS를 "쓸 줄만" 아는 사람이 "어떻게 만들어졌나"로 넘어가기에 이상적인 교재다. 프레임워크를 직접 짜 보고 싶은 사람에게 특히.
@Tool 하나가 어떻게 "런타임에 발견되는 MCP 도구"가 되는지 — 메타데이터 프로그래밍의 실제 사례다. tsconfig가 요구하는 정확한 플래그(experimentalDecorators·emitDecoratorMetadata)와 reflect-metadata 임포트가 왜 필요한지 몸으로 배운다. 데코레이터가 "마법"이 아니라 "메타데이터 저장 + 부트스트랩 때 되읽기"임을 깨닫는 순간이 온다.
도구/리소스/프롬프트가 와이어(전송선) 위에서 어떻게 표현되는지, 그리고 세 가지 트랜스포트(stdio, 세션·재개 가능한 Streamable HTTP, 레거시 SSE)가 어떻게 다른지. MCP 서버를 진지하게 만들려는 사람에게 "SDK만으론 안 보이던 전체 그림"을 준다.
auth/는 PKCE·동적 클라이언트 등록·토큰 검토·보호 리소스 메타데이터를 명명된 RFC 기준으로 구현한 드문 "읽을 수 있는" 코드다. MCP와 무관하게, OAuth 2.1이 실제로 어떻게 돌아가는지 배우려는 사람에게 값진 자료.
타입 안전한 도구 입출력을 위해 zod-to-json-schema로 Zod 스키마를 MCP가 요구하는 JSON Schema로 변환하는 패턴. 그리고 697개 Jest 케이스를 ESM 모드로 돌리는 것 자체가, 데코레이터가 잔뜩 낀 코드를 어떻게 테스트하는지에 대한 좋은 연구감이다.
도구 결과를 ChatGPT/MCP 클라이언트 안에서 렌더되는 React 위젯으로 만드는 법(OpenAI Apps SDK + MCP Apps 호환, CSP 샌드박싱). "AI가 텍스트를 넘어 UI를 반환하는" 다음 세대 인터페이스를 미리 만져 볼 수 있다.
npx @nitrostack/cli init my-server로 계산기 스타터를 만들고 npm run dev로 띄워 Claude Desktop에 stdio로 붙여 본다. ② @Tool 하나를 추가해 보고, core/tool.ts에 console.log를 심어 가드→파이프→핸들러 순서가 실제로 도는지 관찰한다. ③ typescript-oauth 템플릿을 열어 @UseGuards가 어디에 붙는지 추적한다. 이 셋만 해도 "데코레이터가 곧 배선"이라는 핵심이 몸에 붙는다.NitroStack은 특별한 하드웨어가 필요 없다 — stdio MCP 서버는 가볍다. 다만 Node 버전 요구가 문서마다 엇갈린다(§10 함정 참조). 안전하게 README를 따르자.
# 1) 새 MCP 서버 프로젝트 만들기 (계산기 스타터)
npx @nitrostack/cli init my-server
cd my-server
npm run dev # 핫리로드 개발 서버(stdio)
# 2) 프레임워크만 직접 설치해서 쓰기
npm install @nitrostack/core
npm install @nitrostack/widgets # 채팅창 위젯을 쓸 때(React + Next.js)
MCP 클라이언트(Claude Desktop 등) 설정은 이렇게 붙인다.
{
"mcpServers": {
"my-server": { "command": "node", "args": ["dist/index.js"] }
}
}
| 항목 | 요구 / 설명 |
|---|---|
| 런타임 | Node ≥ 20.18(README) · npm ≥ 9. package.json engines는 ≥18로 다르게 적혀 있음 — README를 따를 것 |
| 가속기 | 불필요 — 순수 프로토콜 서버. GPU 무관 |
| OS | 크로스플랫폼(macOS/Linux/Windows). CLI는 빌드 시 바이너리에 chmod +x |
| 트랜스포트 | MCP_TRANSPORT_TYPE로 stdio/http/dual 지정. 미지정 시 NODE_ENV로 자동 선택 |
| 위젯 사용 시 | Next.js 툴체인이 딸려 온다 — 단순 MCP 서버보다 무거워짐. React ^18 || ^19 |
| NitroStudio(선택) | 시각 테스트·인앱 AI 채팅용 비공개 데스크톱 앱 — 별도 다운로드(저장소에 없음) |
# 기여/개발 (저장소 루트 → typescript/)
git clone https://github.com/nitrocloudofficial/nitrostack && cd nitrostack/typescript
npm install
npm run build # 각 패키지로 cd 해서 tsc 순차 실행(모노레포 도구 없음)
NODE_OPTIONS=--experimental-vm-modules npm test # Jest(ESM), 약 697 케이스
npx @nitrostack/cli init my-server로 계산기 스타터를 만들고 npm run dev로 띄운 뒤, Claude Desktop에 stdio로 연결해 calculate 도구를 실제로 호출해 본다.
@Controller('math')
export class MathTools {
@Tool({ description: '두 수를 더한다' })
add(input: { a: number; b: number }) {
return { sum: input.a + input.b };
}
}
목표: "데코레이터 하나 = MCP 도구 하나"라는 핵심을 눈으로 확인.
@Injectable() 서비스를 하나 만들고 @Controller 도구 클래스의 constructor에 주입해, 비즈니스 로직(서비스)과 도구 표면(컨트롤러)의 분리를 체감한다. @Module({ providers: [...] })에 등록하는 흐름까지. 목표: NestJS식 DI가 MCP에서 어떻게 도는지 이해.
@UseGuards로 API 키를 검사하는 가드, @UsePipes로 입력을 정규화하는 파이프, ExceptionFilter로 오류를 예쁜 메시지로 바꾸는 필터를 각각 붙여 본다. core/tool.ts에 로그를 심어 실행 순서(가드→인터셉터→파이프→핸들러→필터)를 직접 관찰. 목표: 횡단 관심사 파이프라인의 실전 감각.
@Widget과 @nitrostack/widgets 훅(useWidgetSDK·use-theme·use-widget-state)으로 도구 결과를 인터랙티브 카드로 렌더한다. OpenAI Apps SDK/MCP Apps 호환 UI가 어떻게 도구 출력에 붙는지 확인. 목표: "AI가 UI를 반환하는" 워크플로 실측(Next.js 툴체인 경험).
typescript-oauth 템플릿에서 출발해 OAuthModule을 설정하고, PKCE 흐름으로 토큰을 발급받아 도구 호출을 보호한다. MCP_TRANSPORT_TYPE=dual로 stdio+HTTP를 동시에 띄우고, auth/pkce·token-validation 코드를 읽으며 RFC가 코드로 어떻게 옮겨졌는지 추적. 목표: "프로덕션 미들 마일(인증·트랜스포트)"의 실체를 손으로 검증.
| 주차 | 주제 · 학습 목표 |
|---|---|
| 1주차 MCP 프로토콜 | Model Context Protocol의 기본기. 도구·리소스·프롬프트가 무엇이고, 공식 @modelcontextprotocol/sdk로 "맨손" 서버를 하나 짜 본다. stdio vs HTTP 트랜스포트의 차이를 체감하면, NitroStack이 왜 "그 위에" 필요한지가 보인다. |
| 2주차 데코레이터 · DI | 메타데이터 프로그래밍. TypeScript 데코레이터와 reflect-metadata, 의존성 주입 컨테이너의 원리. NitroStack의 app-decorator.ts·di/container.ts를 읽으며 "데코레이터=메타데이터 저장+부트스트랩 되읽기"를 확인. NestJS 공식 문서를 곁들이면 이해가 빨라진다. |
| 3주차 OAuth 2.1 · 보안 | 인증을 제대로. OAuth 2.1과 PKCE·동적 클라이언트 등록·토큰 검토(RFC 7636/7591/7662). auth/를 교본 삼아 "토큰이 어떻게 발급·검증되는지"를 코드로 추적. 프롬프트 인젝션·CSP 같은 AI 특유의 위협 표면도 함께. |
| 4주차 위젯 · AI 네이티브 UI | AI가 UI를 반환하는 시대. OpenAI Apps SDK와 MCP Apps, text/html+skybridge, CSP 샌드박싱. widgets/와 ui-next/를 정독하며 Next.js React 컴포넌트가 채팅창 안에서 렌더되는 과정을 이해. MCP Tasks(비동기 도구)까지. |
@Tool·@Resource·@Prompt 데코레이터로 선언한다.Reflect.defineMetadata) 부트스트랩 때 되읽어 도구/모듈을 등록하는 뼈대. experimentalDecorators·emitDecoratorMetadata 필요.@Injectable·@Inject·컨테이너. singleton/transient/scoped 생명주기, OnModuleInit·OnApplicationBootstrap 훅.@Module({ imports, providers })로 구성, McpApplicationFactory.create(AppModule)가 전체를 부트스트랩한다.@Controller('github')가 도구 이름에 접두사를 붙임(create_issue→github_create_issue)하고 DI에 자동 등록.ctx.logger, 인증 컨텍스트 등).NODE_ENV/MCP_TRANSPORT_TYPE로 선택.auth/의 실제 구현. PKCE(7636)·동적 클라이언트 등록(7591)·토큰 검토(7662)·보호 리소스 메타데이터(9728) 등 명명된 RFC 기준.text/html+skybridge MIME + CSP 샌드박싱, 두 규격 호환.TaskManager/TaskContext 상태 머신, 도구별 taskSupport: forbidden|optional|required.저장소 & 배포
· GitHub: github.com/nitrocloudofficial/nitrostack (Apache-2.0, 별 1,172)
· npm 코어: @nitrostack/core (v1.0.13) · @nitrostack/cli (v1.0.14) · @nitrostack/widgets (v1.0.8)
프로젝트 사이트(문서 · 스튜디오)
· 홈: nitrostack.ai · 문서: docs.nitrostack.ai · 블로그: blog.nitrostack.ai
· NitroStudio(비공개 데스크톱 앱): nitrostack.ai/studio
· 커뮤니티: Discord · X @nitrostackai · YouTube @nitrostackai
저장소 내 핵심 코드/문서
· typescript/packages/core/src/core/(server·tool·app-decorator·transports) · .../auth/(OAuth 2.1) · .../ui-next/(위젯) · docs/(마크다운 66개) · templates/typescript-starter|oauth|pizzaz
상위 표준
· MCP: modelcontextprotocol.io · Streamable HTTP(2025-06-18 스펙) · OpenAI Apps SDK · @modelcontextprotocol/sdk(Anthropic PBC, MIT)
① 단일 스쿼시 스냅샷. 공개 저장소는 커밋 하나(7d63f9e "Versions Updated")뿐 — 내부 모노레포의 릴리스 미러라 개발 이력·코드 고고학이 불가능하다.
② CI/CD 없음. .github/workflows가 아예 없다(이슈/PR 템플릿·CODEOWNERS만 존재). 697개 테스트가 있어도 공개적으로 자동 실행되지 않는다.
③ Dockerfile 없음. Docker를 홍보하지만 실제 파일은 안 딸려 오고 docs/deployment/02-docker-guide.md만 있다(직접 작성해야 함).
④ NitroStudio는 비공개. 광고되는 DX(시각 테스트·인앱 AI 채팅·핫리로드 프리뷰)의 큰 조각이 이 저장소에 없는 프로프라이어터리 별도 다운로드다.
⑤ CLI 텔레메트리. @nitrostack/cli가 posthog-node로 사용 데이터를 외부에 보낸다 — 프라이버시 민감 환경에선 확인 필요.
⑥ 사소한 불일치. Node 버전(README ≥20.18 vs engines ≥18), NOTICE에 적힌 openai·@google/generative-ai·http-proxy-middleware는 어느 패키지 dependencies에도 없음(NitroStudio용이거나 잔재로 추정). Zod는 아직 v3. 캐럿(^) 버전이라 어린 MCP SDK의 마이너 변화에 흔들릴 수 있음.
정리: 코드는 진짜로 성숙(인증·트랜스포트·697 테스트)하다. 다만 공개 저장소의 운영 스토리(CI·컨테이너·비공개 도구)는 마케팅보다 얇으니, "프로덕션 레디"는 액면 그대로 믿지 말고 직접 검증할 것.