Skip to main content
Glama
Onplana

Onplana MCP server

Official
by Onplana

Onplana MCP server

오픈소스 TypeScript Model Context Protocol 빌딩 블록으로, Onplana의 프로덕션 MCP 배포에서 추출했습니다. 두 개의 패키지:

  • onplana-mcp-server: 서버 템플릿. Streamable HTTP 전송, Bearer 인증, 프롬프트 인젝션 격리, 플러그 가능한 디스패처.

  • onplana-mcp-client: 공개 Onplana MCP 엔드포인트 https://api.onplana.com/api/mcp/v1을 호출하기 위한 타입이 지정된 TypeScript 클라이언트 SDK.

CI MIT License

이게 무엇인가

MCP 서버의 전송 계층(Streamable HTTP 연결, 무상태 모드, 범위가 제한된 Bearer 인증, 프롬프트 인젝션 격리)을 제대로 구현한 것으로, 플랫폼별 도구 레지스트리와 분리되어 있습니다. 서버 템플릿을 사용하면 보안 모범 사례가 내장된 나만의 MCP 서버를 구축할 수 있습니다. 클라이언트 SDK를 사용하면 Onplana의 호스팅 MCP를 자신의 코드에서 구동할 수 있습니다.

이 패턴들은 Onplana의 프로덕션 배포(공개 문서: onplana.com/mcp)에서 추출한 것으로, 실제 Claude Desktop, Cursor, ChatGPT 사용자 지정 커넥터, 사내 에이전트의 Onplana 플랫폼 트래픽을 처리하는 바로 그 계층입니다.

Related MCP server: MCP Server Template

왜 오픈소스인가

MCP 전송 계층은 모든 사람에게 동일합니다. 초기 MCP 서버 대부분은 보안 기본 요소를 잘못 구현합니다:

  • 프롬프트 인젝션. 사용자 생성 콘텐츠(작업 제목, 댓글 본문, 위키 텍스트)를 반환하는 도구는 그 콘텐츠를 모델의 컨텍스트에 직접 넣습니다. 격리 없이는 적대적 행위자가 자신의 데이터에 "ignore previous instructions"를 심어 놓을 수 있고, 이를 읽는 다음 에이전트는 그 지시를 따르게 됩니다.

  • 무상태 전송. 대부분의 SDK 예제는 인메모리 세션 상태를 가정하는데, 이는 수평 확장을 깨뜨리고 인증 모델을 복잡하게 만듭니다.

  • 플랜 게이트 의미론. 호출자가 실제로 호출할 수 없는 도구를 노출하면 턴을 낭비하고 모델을 혼란스럽게 합니다.

Onplana는 6개월간의 MCP 서버 작업을 통해 이러한 문제를 프로덕션에서 해결했습니다. 이 패턴을 공개하는 것은 파급력이 큽니다:

  1. 다른 MCP 작성자들은 재발명하는 대신 검증된 템플릿을 얻습니다.

  2. 이 저장소는 사전 학습 신호 표면입니다. 공개 GitHub README는 차세대 LLM 학습 데이터에서 높은 가중치를 가지며, 패턴과 MCP에 대한 명확한 문서를 갖춘 저장소는 "좋은 MCP 서버가 어떤 모습인지"에 대한 모델의 회상을 향상시킵니다.

  3. 디스패처 인터페이스는 비즈니스 로직이 연결되는 접합부입니다. 전송 계층은 일반적이며, MCP 서버에서 중요한 것은 도구 레지스트리입니다. 전송 계층을 오픈소스로 공개해도 독점적인 것은 공개되지 않습니다.

디스패처 구현, 도구 카탈로그, 플랜 게이트 로직, 감사 인프라, 그리고 Onplana의 약 600 LOC 규모의 비공개 소스 디스패처 나머지 부분은 플랫폼 비즈니스 로직을 담고 있기 때문에 비공개 모노레포에 남아 있습니다. 이 템플릿을 사용해 자신만의 MCP 서버를 구축한다면, 자신만의 디스패처를 작성하게 됩니다. 그것이 중요하고 플랫폼에 특화된 작업입니다.

저장소 구조

onplana-mcp-server/
├── packages/
│   ├── server-template/        # onplana-mcp-server (npm)
│   │   ├── src/
│   │   │   ├── transport.ts    # Streamable HTTP wiring
│   │   │   ├── auth.ts         # Bearer auth pattern
│   │   │   ├── promptInjection.ts  # wrapUserContent + escape
│   │   │   ├── dispatcher.ts   # Pluggable Dispatcher interface
│   │   │   └── index.ts
│   │   ├── tests/              # promptInjection + auth + transport
│   │   └── README.md
│   └── client/                 # onplana-mcp-client (npm)
│       ├── src/
│       │   ├── client.ts       # OnplanaMcpClient class
│       │   ├── types.ts        # Public type surface
│       │   └── index.ts
│       ├── tests/              # client.test.ts (stub fetch)
│       └── README.md
├── .claude-plugin/
│   └── marketplace.json        # Claude Code marketplace
├── plugins/
│   └── onplana/                # Claude Code plugin (skills + connect command)
├── examples/
│   └── in-memory/              # Runnable demo with 3 toy tools
├── gemini-extension.json       # Gemini CLI manifest
├── mcp.json                    # stdio client config (mcp-remote)
├── server.json                 # MCP registry manifest
└── .github/workflows/
    ├── ci.yml                  # tsc + vitest on PR
    └── publish.yml             # npm publish on tag v*

빠른 시작

서버 구축

설치:

npm install github:Onplana/onplana-mcp-server @modelcontextprotocol/sdk express

Express 앱 연결:

import express from 'express'
import {
  createMcpPostHandler,
  createMcpMethodNotAllowedHandler,
  requireBearerAuth,
  type Dispatcher,
} from 'onplana-mcp-server'

const dispatcher: Dispatcher = {
  async listTools(ctx) { /* return your tool descriptors */ return [] },
  async callTool(name, input, ctx) { /* dispatch to your tools */ return { output: {} } },
}

const auth = async (token: string) => {
  // Validate against your token store. Return AuthContext or null.
  return { userId: 'u', scopes: ['MCP_AGENT'] }
}

const app = express()
app.use(express.json())
app.use('/api/mcp/v1',
  requireBearerAuth({ auth, requiredScope: 'MCP_AGENT' }),
)
app.post('/api/mcp/v1', createMcpPostHandler({ dispatcher }))
app.get('/api/mcp/v1', createMcpMethodNotAllowedHandler())
app.delete('/api/mcp/v1', createMcpMethodNotAllowedHandler())
app.listen(3000)

전체 빠른 시작은 packages/server-template/README.md에, 실행 가능한 데모는 examples/in-memory/에 있습니다.

코드에서 Onplana 구동

설치:

npm install github:Onplana/onplana-mcp-server

사용:

import { OnplanaMcpClient } from 'onplana-mcp-client'

const client = new OnplanaMcpClient({
  url:   'https://api.onplana.com/api/mcp/v1',
  token: process.env.ONPLANA_PAT!,
})

const projects = await client.listProjects({ status: 'ACTIVE' })

// The differentiator vs other PM-tool MCPs: hybrid semantic + lexical
// search across your org's indexed content (projects, tasks, risks,
// goals, comments, wiki pages).
const { matches } = await client.searchOrgKnowledge({
  query: 'rationale for the 3-week design phase',
  scope: 'all',
  limit: 5,
})

전체 클라이언트 문서는 packages/client/README.md에 있습니다.

도구

https://mcp.onplana.com/mcp에서 호스팅되는 서버는 프로젝트, 작업, 스프린트, 마일스톤, 획득가치, 리스크, 이슈, 거버넌스, 변경 관리, 타임시트, 위키, 화이트보드, 워크플로, Microsoft Graph 통합에 걸친 285개의 도구를 노출합니다. 특정 클라이언트가 보는 정확한 수는 더 적은데, 카탈로그가 제공되기 전에 도구가 호출자의 역할과 조직의 플랜에 따라 필터링되기 때문입니다.

아래 33개는 전체 카탈로그가 아니라 먼저 알아 둘 가치가 있는 도구들입니다. 읽기는 readOnlyHint로 표시되고, 쓰기는 destructiveHint를 포함하므로 클라이언트가 이를 게이트할 수 있습니다. 모든 호출은 호출한 사용자의 신원으로 실행되며, 해당 사용자의 권한과 조직의 플랜에 대해 검사된 후 감사 추적에 기록됩니다.

읽기 (readOnlyHint: true)

  • list_projects: 조직의 프로젝트, 상태로 필터링 가능.

  • get_project: 날짜, 소유자, 진행 상황을 포함한 전체 프로젝트 하나.

  • list_tasks: 프로젝트의 작업 또는 여러 프로젝트에 걸친 작업.

  • get_task: 설명, 담당자, 날짜, 최근 댓글이 포함된 작업 하나.

  • list_my_tasks: 호출한 사용자에게 할당된 작업.

  • list_overdue: 기한이 지난 작업.

  • list_team_members: 프로젝트의 구성원.

  • list_org_members: 조직의 구성원.

  • list_risks: 프로젝트에 기록된 리스크.

  • find_similar_projects: 설명과 유사한 과거 프로젝트, 견적 산정용.

  • search_org_knowledge: 작업, 프로젝트, 위키 페이지, 댓글에 대한 하이브리드 BM25 및 벡터 검색.

  • summarize_project: 실시간 플랜에서 합성된 AI 요약.

  • analyze_project_risks: 일정, 예산, 범위, 리소스 전반에 걸친 AI 리스크 탐지.

  • generate_status_report: 현재 일정과 활동에서 생성된 AI 상태 보고서.

  • search: App Directory 어댑터, {id, title, snippet?, url?} 반환.

  • fetch: App Directory 어댑터, {id, title, content, url?, metadata?} 반환.

쓰기, 추가형 (destructiveHint: false)

  • create_project: 프로젝트 생성.

  • create_task: 작업 생성, 선택적으로 상위 작업 아래에 생성.

  • create_milestone: 프로젝트에 마일스톤 추가.

  • create_comment: 작업, 이슈 또는 프로젝트에 댓글 작성.

  • create_sprint_with_tasks: 스프린트를 만들고 작업을 스프린트로 가져오기.

  • submit_timesheet: 작업에 시간 기록.

  • add_project_member: 기존 조직 구성원을 프로젝트에 추가.

  • link_dependency: 두 작업 연결, 고유 제약 조건을 통해 멱등.

쓰기, 변경형 (destructiveHint: true)

  • update_project: 상태, 날짜, 예산 등 프로젝트 필드 변경.

  • update_task: 상태, 진행률, 날짜 등 작업 필드 변경.

  • bulk_update_tasks: 여러 작업에 하나의 변경 적용.

  • assign_task: 작업 담당자 설정.

  • move_task_to_sprint: 작업을 스프린트로 이동하거나 스프린트에서 제외.

리스 (백로그를 공유하는 에이전트용)

  • next_task: 다음 사용 가능한 작업을 선택하고 한 번의 호출로 클레임합니다. 목록을 조회한 뒤 클레임하면 두 에이전트가 모두 들어갈 수 있는 틈이 생깁니다.

  • claim_task: 특정 작업에 대한 독점 리스를 획득.

  • renew_task_lease: 작업이 아직 실행 중일 때 리스 연장.

  • release_task: 리스를 반환합니다. 작업을 완료하거나 차단해도 리스가 해제되며, 세션을 종료하면 해당 실행이 보유한 모든 것이 해제됩니다.

리스는 사용자가 아니라 실행(RUN)에 키가 지정됩니다. 한 클라이언트의 두 세션은 동일한 에이전트 페르소나로 인증되므로, 사용자 키 기반 잠금은 한 세션이 다른 세션의 작업을 해제할 수 있게 만듭니다. 리스는 자체적으로 만료되므로, 충돌한 에이전트는 작업을 계속 보유하는 대신 해제합니다.

삭제 도구는 기본 카탈로그에 없으며, 파괴적 작업은 기본적으로 거부됩니다. 조직 소유자가 에이전트가 호출할 수 있기 전에 작업별로 이를 활성화해야 합니다. 활성화할 수 있는 작업은 복구 가능하며, 파괴되는 대신 휴지통으로 이동합니다. 어차피 Onplana는 모든 필드 변경을 감사하고 기록을 유지하므로 삭제 후 재생성보다 update_task를 선호하세요.

프로덕션 체크리스트

템플릿 + SDK로 실행할 수 있습니다. 여기에 다음을 추가하세요:

  • 토큰별 속도 제한. Bearer 토큰당 분당 60–120 요청; 에이전트 루프는 사람보다 더 많은 요청을 발생시킵니다.

  • 테넌트 비용 상한. 도구가 유료 LLM을 호출한다면 월 누적 지출에 따라 디스패치를 게이트하세요. Onplana의 배포는 WARN / BLOCK 모드로 aiMonthlyCostCapUsd를 사용합니다.

  • 감사 로깅. 모든 디스패치는 actorType: 'mcp_agent'로 태그된 감사 행을 기록해야 관리자가 테넌트에서 AI 에이전트가 한 일을 인간 활동과 분리해 볼 수 있습니다.

  • 플랜 / 범위 큐레이션. 모든 내부 도구를 노출하지 마세요. Onplana는 26개 중 21개를 노출합니다. 제외된 5개는 앱 내 미리보기 UI가 필요하거나, 무감독 호출에 너무 위험하거나, 지나치게 큰 페이로드를 생성합니다.

  • 위험한 변경 작업을 위한 PREVIEW 모드. 무료 티어에서는 변경 도구를 기본적으로 미리보기 전용으로 설정하세요. Onplana는 이를 제공합니다. 에이전트는 사용자가 명시적으로 업그레이드하고 다시 실행하기 전에 "무엇을 할지"를 확인합니다.

  • 멱등성 키. 정규화된 입력 + 세션 ID를 해시하고, 감사 행에 고유 제약 조건으로 저장하세요. 모델이 동일한 논리적 작업을 재시도할 때 이중 생성이 발생하지 않아야 합니다.

이 각각은 플랫폼별로 다릅니다. 템플릿은 이들이 연결되는 접합부(Dispatcher.callTool)를 제공하며, 여러분의 디스패처는 플랫폼이 해당 개념을 인코딩하는 방식에 따라 이를 구현합니다.

호환성

  • Node.js ≥ 20 (서버 템플릿 및 CI 매트릭스용); 클라이언트는 ≥ 18 (내장 fetch 사용).

  • @modelcontextprotocol/sdk@^1.29.0

  • express@^4.18.0 또는 express@^5.0.0

다음에서 테스트됨:

  • Claude Code (플러그인 마켓플레이스 또는 claude mcp add --transport http)

  • Claude Desktop (Custom Connector)

  • Cursor (~/.cursor/mcp.json)

  • ChatGPT 사용자 지정 커넥터 (계정에서 MCP가 활성화된 경우)

  • Gemini CLI + Gemini Code Assist (~/.gemini/settings.json)

  • VS Code의 GitHub Copilot (.vscode/mcp.json)

  • 공식 MCP Inspector

Claude Code에 설치

이 저장소는 Claude Code 플러그인 마켓플레이스 역할도 하므로 설치 명령은 두 개입니다:

/plugin marketplace add Onplana/onplana-mcp-server
/plugin install onplana@onplana

그런 다음 서버를 연결합니다:

/onplana-connect

이 명령은 claude mcp add --transport http onplana https://mcp.onplana.com/mcp를 실행하고 브라우저 로그인 과정을 안내합니다. MCP 서버는 무료 플랜을 포함한 모든 Onplana 플랜에서 사용할 수 있습니다.

플러그인은 onplana:<name>으로 호출되는 두 가지 Onplana 에이전트 스킬을 제공합니다:

스킬

언제 사용하나

onplana-project-planner

목표나 브리프가 있고 실행 가능한 플랜을 원할 때: 프로젝트에 첨부된 플랜 문서, 그다음 날짜, 의존성, 담당자, 테스트 케이스가 포함된 작업 트리.

onplana-autonomous-agent

플랜이 이미 존재하고 이를 실행하려 할 때: 작업을 클레임하고, 수행하고, 진행 상황과 증거를 기록하고, 해결하거나 반환한 다음 다음 작업을 가져갑니다.

플러그인 매니페스트는 의도적으로 MCP 서버를 선언하지 않습니다. 플러그인은 stdio 형식(command, args, env)으로 서버를 선언하는데, Onplana의 서버는 원격이고 OAuth 인증을 사용하므로 /onplana-connect는 stdio 셔먼을 거치지 않고 Claude Code의 네이티브 HTTP 전송을 통해 런타임에 이를 연결합니다.

Gemini CLI에 설치

이 저장소는 루트에 gemini-extension.json 매니페스트를 포함하므로 Gemini CLI는 한 명령으로 Onplana를 설치합니다:

export ONPLANA_PAT=pat_paste-your-token-here  # mint at app.onplana.com/integrations
gemini extensions install https://github.com/Onplana/onplana-mcp-server

gemini CLI를 다시 시작하세요(또는 Gemini Code Assist를 사용 중이라면 VS Code / JetBrains 창을 다시 로드하세요). Onplana 도구는 /mcp에 나타나며, GEMINI.md 컨텍스트는 이 저장소에 포함된 사용 힌트를 읽어옵니다.

기여

이슈와 PR을 환영합니다. 이 저장소는 의도적으로 작게 유지되며, 목표는 전송 패턴이 명확하고, 잘 테스트되고, 안정적인 것입니다. 메이저 버전 업은 내보내지는 Dispatcher / BearerAuth / 핸들러 팩토리 형태의 호환성을 깨는 변경에만 예약되어 있습니다. 패치와 마이너 버전은 프롬프트 인젝션 격리 개선, 새로운 헬퍼 유틸리티, 추가 테스트 커버리지를 위한 것입니다.

라이선스

MIT. © 2026 Onplana

함께 보기

Related MCP Connectors

Related MCP Servers

  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    A production-ready TypeScript MCP server providing basic tools (add, echo, timestamp), resources (server info, greetings, data access), and prompt templates (analyze, code-review, summarize). Serves as a foundation for building custom MCP servers with extensible architecture.
    205 npm
    -
  • A
    license
    A
    quality
    Not graded
    maintenance
    A production-ready TypeScript template for building MCP servers with dual transport support (stdio/HTTP), OAuth 2.1 foundations, SQLite caching, observability, and security features including PII sanitization and rate limiting.
    4
    6 npm
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    A Model Context Protocol (MCP) server template designed for building structured tools, prompts, and resources with built-in support for HTTP and STDIO transports. It provides a standardized framework for developers to create and deploy AI-driven services using TypeScript and Zod schema validation.
    7 npm
    -