Skip to main content
Glama

ChatGPT Todo MCP 데모 (Apps SDK + React)

ChatGPT를 위한 최소한의 할 일(todo) 앱: MCP 서버가 도구와 대화형 HTML UI를 노출하며, React + Vite로 빌드되어 단일 파일 번들로 포함됩니다. ChatGPT의 커넥터 마법사가 검색을 완료할 수 있도록 작은 개발용 OAuth 계층을 포함합니다.

공식 참조: Apps SDK 빠른 시작.

빠른 시작

npm install
npm start          # builds widget (prestart) then runs server on port 8787 by default
  • MCP 엔드포인트: http://localhost:8787/mcp

  • ChatGPT용: HTTPS(예: ngrok)로 노출하고 https://<your-host>/mcp를 가리키는 커넥터를 생성합니다.

  • 터널 뒤에서 검색 URL이 잘못된 스키마/호스트를 표시하는 경우 다음을 설정하세요:

    export PUBLIC_BASE_URL=https://your-ngrok-host.example

Related MCP server: mcp-todo-demo

프로젝트 레이아웃

경로

역할

server.js

HTTP 라우터: OAuth 검색 + CORS + /mcp에서의 MCP StreamableHTTPServerTransport

oauth-dev.js

개발 전용 OAuth 2.1 검색 + DCR/PKCE (프로덕션에서는 실제 IdP로 교체)

widget/

인챗 UI를 위한 Vite + React 소스

dist/todo-widget.html

빌드된 단일 파일 HTML (gitignored); 시작 시 server.js에 의해 로드됨


아키텍처 및 개념

한 문장 모델

ChatGPT는 MCP 클라이언트로 작동합니다. 이는 /mcp에서 Node 서버HTTPS를 통한 MCP로 통신합니다. 서버는 도구(모델이 호출할 수 있는 것)와 리소스(위젯용 HTML)를 등록합니다. 위젯은 iframe에서 실행되며 postMessage를 통한 JSON-RPC 브리지를 통해 ChatGPT와 통신합니다. 동일한 오리진의 OAuth 메타데이터를 통해 ChatGPT가 커넥터를 연결할 수 있게 하며, 이는 MCP 도구 실행과는 별개이지만 온보딩을 위해 필요합니다.

모델 컨텍스트 프로토콜 (MCP)

MCP는 호스트(ChatGPT)가 서버에서 도구를 검색 및 호출하고 리소스를 읽기 위한 표준 방식입니다. 이 저장소는 @modelcontextprotocol/sdk를 사용합니다. McpServer 인스턴스는 기능을 등록하고 MCP 메시지를 HTTP(StreamableHTTPServerTransport)로 매핑하는 **전송(transport)**에 연결됩니다.

기본 MCP vs Apps SDK 헬퍼

  • @modelcontextprotocol/sdk: 핵심 McpServer, 스키마, 전송.

  • @modelcontextprotocol/ext-apps: registerAppToolregisterAppResourceUI 메타데이터(도구에 대해 표시할 HTML 리소스)를 정규화하고 Apps HTML MIME 유형(RESOURCE_MIME_TYPE)을 설정합니다.

위젯은 논리적 URI(예: ui://widget/todo.html)의 리소스로 등록됩니다. 해당 URI는 공개 웹 URL일 필요는 없으며, 호스트는 MCP resources/read를 통해 이를 확인합니다. 각 도구의 _meta.ui.resourceUri는 동일한 URI를 가리키므로 ChatGPT는 어떤 UI 표면이 어떤 도구에 속하는지 알 수 있습니다.

HTTP 프런트 도어 (server.js)

하나의 Node http.Server가 여러 표면을 처리합니다:

  1. OAuth / 검색 (oauth-dev.js) — ChatGPT가 예상하는 잘 알려진 URL 및 토큰 엔드포인트.

  2. CORS /mcp에 대한 OPTIONS.

  3. 상태 확인 GET /.

  4. MCP 스트리밍 가능한 HTTP 전송을 통한 /mcp에서의 POST / GET / DELETE.

  5. 404 알 수 없는 경로에 대해.

따라서 하나의 프로세스여러 논리적 HTTP API(OAuth HTTP + MCP HTTP)를 갖게 됩니다.

스트리밍 가능한 HTTP 및 서버 수명

전송은 들어오는 각 MCP 요청마다 생성되며, sessionIdGenerator: undefined(이 데모에서는 상태 비저장 모드)로 설정됩니다. 요청마다 새로운 McpServer가 생성되고 응답이 닫히면 삭제됩니다.

중요: 메모리 내 할 일 상태(server.jstodos)는 McpServer 인스턴스 내부가 아닌 모듈 범위에 존재합니다. 따라서 각 요청이 새로운 MCP 서버 객체를 얻더라도 상태는 Node 프로세스의 수명 동안 유지됩니다.

도구 및 UI 계약

도구(add_todo, complete_todo)는 호스트가 인수를 검증할 수 있도록 입력 스키마(Zod)를 선언합니다.

도구 결과에는 다음이 포함됩니다:

  • content: 모델/대화를 위한 일반적인 MCP 콘텐츠(예: 텍스트).

  • structuredContent: 위젯이 소비하는 JSON — 여기서는 { tasks: [...] }.

모든 변경 사항에 대해 동일한 structuredContent 형태를 사용하면 사용자가 위젯에서 호출했든 모델이 채팅에서 호출했든 관계없이 React UI를 동기화 상태로 유지할 수 있습니다.

OAuth (oauth-dev.js)

ChatGPT의 커넥터 흐름은 OAuth 보호 리소스 메타데이터권한 부여 서버 메타데이터를 가져옵니다(Apps SDK 인증 참조). 해당 경로가 없으면 설정 시 “Error fetching OAuth configuration” 오류가 발생할 수 있습니다.

이 저장소는 ChatGPT 리디렉션 URL로 범위가 지정된 개발 전용 권한 부여 서버(검색, 동적 클라이언트 등록, 권한 부여 리디렉션, PKCE 토큰 교환)를 제공합니다. 프로덕션에서 그대로 사용하지 마십시오. Auth0, Stytch, Cognito 등으로 교체하고 MCP 요청 시 토큰을 확인하십시오.

PUBLIC_BASE_URL은 프록시/ngrok이 Host / X-Forwarded-Proto를 필요한 방식으로 설정하지 않을 때 메타데이터에서 공개 https:// 오리진을 강제합니다.

위젯 브리지 (widget/src/bridge.ts)

빌드된 HTML은 ChatGPT의 iframe 내부에서 실행됩니다. 일반 SPA처럼 /mcp URL을 호출하지 않고 MCP Apps UI 브리지를 사용합니다:

  1. ui/initializeui/notifications/initialized — 호스트와의 핸드셰이크.

  2. tools/call — 호스트에게 인수와 함께 명명된 MCP 도구를 실행하도록 요청(모델이 사용하는 도구와 동일).

  3. ui/notifications/tool-result모델이 도구를 실행할 때, 호스트는 tools/call로부터 직접적인 반환 경로 없이도 UI가 업데이트되도록 결과를 푸시할 수 있습니다.

따라서 두 가지 업데이트 경로가 있습니다: UI가 시작한 호출에 대한 RPC 응답과 모델이 시작한 호출에 대한 알림.

단일 파일 HTML을 사용하는 이유 (Vite + vite-plugin-singlefile)

ChatGPT는 위젯을 “귀하의 사이트 + 별도의 JS 청크”가 아닌 MCP 리소스 읽기를 통해 임베디드 HTML로 수신합니다. 상대적인 청크 URL은 해당 임베딩 모델에서 작동하지 않습니다. 빌드 결과물은 JS/CSS가 인라인된 하나의 dist/todo-widget.html이며, server.js는 시작 시 이를 todoHtml로 읽어들입니다.

React는 개발자 편의성 계층이며, 배포 가능한 아티팩트는 정적 HTML입니다.

엔드투엔드 흐름

ChatGPT의 사용자: 메시지 → 모델이 도구 선택 → ChatGPT가 귀하의 /mcp로 POST → 도구 실행 → structuredContent.tasks 반환 → 호스트가 위젯을 표시/업데이트.

위젯의 사용자: React → postMessage를 통한 tools/call → 호스트가 MCP로 전달 → 동일한 핸들러 → RPC 결과가 상태 업데이트.

커넥터 설정: ChatGPT가 귀하의 오리진에서 /.well-known/...을 호출 → 필요한 경우 OAuth 연결 → 이후 /mcp에 대한 MCP 호출에 Authorization: Bearer ...가 포함될 수 있음(모든 도구에서 이를 강제하는 것은 프로덕션 단계).

자연스러운 다음 단계

영역

방향

상태

데이터베이스에 할 일을 저장하고, 액세스 토큰에서 인증된 사용자 ID별로 범위를 지정합니다.

인증

oauth-dev.js를 실제 IdP로 교체하고, 각 MCP 요청에서 발급자, 대상, 범위를 검증합니다.

MCP 세션

다른 스트리밍 또는 수명 주기 의미론이 필요한 경우 상태 저장 세션을 사용합니다.

도구

더 풍부한 설명/스키마, 선택적 outputSchema, 모델 라우팅을 위한 더 명확한 이름.

위젯

동일한 브리지 사용; UX, 오류 및 로딩 상태 개선.

스크립트

스크립트

설명

npm run build

widget/에서 dist/todo-widget.html 빌드

npm start

npm run buildnode server.js 실행

npm run build:widget

Vite 빌드만 수행

기본 포트: 8787 (PORT 환경 변수로 재정의 가능).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityInactive
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A minimal MCP server demonstrating how to build ChatGPT-compatible applications using Next.js with widget rendering capabilities. Provides a starter template for integrating Next.js applications with the ChatGPT Apps SDK through the Model Context Protocol.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    A minimal MCP server that provides an interactive to-do list with checkboxes in chat, demonstrating MCP Apps UI resource integration and tool-based state updates.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    A minimal Next.js application demonstrating how to build an OpenAI Apps SDK compatible MCP server with widget rendering in ChatGPT.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    A Model Context Protocol server with a built-in OAuth 2.1 authorization server and a Next.js todo app, enabling authenticated task management (create, read, update, delete tasks) via natural language through an MCP client.
    7
    ISC

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/iamzeeali/mcpserver2'

If you have feedback or need assistance with the MCP directory API, please join our Discord server