# TypeScript 프로젝트 가이드 — File Time Search MCP
이 문서는 [PRD-FileTimeSearch-MCP.md](PRD-FileTimeSearch-MCP.md), [PRD-API.md](PRD-API.md)를 기반으로 **TypeScript + @modelcontextprotocol/sdk**로 MCP 서버를 구현/운영하기 위한 실행 가이드입니다.
> 목표: `fs.search_by_time` 도구를 구현해 “최근 수정일/생성일 기반 파일 검색”을 MCP Tool로 제공
---
## 1. 전제/권장 버전
- Node.js: **18+ 권장(가능하면 20+)**
- 패키지 매니저: npm / pnpm / yarn 중 택1
- OS: Windows 포함(본 워크스페이스 기준)
SDK 설치 시 주의:
- `@modelcontextprotocol/sdk`는 **`zod`가 필수 peer dependency**입니다.
---
## 2. 프로젝트 초기화(최소 구성)
아래는 “가장 작은” TypeScript 서버 프로젝트를 만드는 기준 예시입니다.
### 2.1 디렉터리/패키지 생성
```bash
# (repo 루트에서) TypeScript 구현 디렉터리를 따로 둘 수도 있고,
# repo 루트에 바로 구성해도 됩니다.
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript tsx @types/node
```
### 2.2 tsconfig
```bash
npx tsc --init --rootDir src --outDir dist --module NodeNext --moduleResolution NodeNext --target ES2022
```
권장 설정(요지):
- `module`/`moduleResolution`: `NodeNext`
- `target`: `ES2022` 이상
- `rootDir`: `src`, `outDir`: `dist`
### 2.3 package.json 스크립트(예시)
```json
{
"type": "module",
"scripts": {
"dev:stdio": "tsx src/stdio.ts",
"dev:http": "tsx src/http.ts",
"build": "tsc -p .",
"start:stdio": "node dist/stdio.js",
"start:http": "node dist/http.js"
}
}
```
> stdio 서버는 **stdout 출력 금지**입니다. 개발 중에도 `console.log` 대신 `console.error`를 사용하세요.
---
## 3. 추천 폴더 구조
```text
src/
index.ts # (선택) 공통 서버 생성 함수 export
stdio.ts # stdio transport 엔트리
http.ts # Streamable HTTP transport 엔트리
tools/
searchByTime.ts # fs.search_by_time 구현
core/
config.ts # allowRoots, 제한값 등
cursor.ts # cursor 인코딩/디코딩
errors.ts # tool error 유틸
```
---
## 4. MCP 서버 기본 골격(공통)
TypeScript SDK의 고수준 서버 API는 `McpServer`를 사용합니다.
- 서버: `@modelcontextprotocol/sdk/server/mcp.js`
- stdio transport: `@modelcontextprotocol/sdk/server/stdio.js`
- Streamable HTTP transport: `@modelcontextprotocol/sdk/server/streamableHttp.js`
- Express 앱(로컬 보호 포함): `@modelcontextprotocol/sdk/server/express.js`
도구 등록은 `server.registerTool(...)` 패턴을 사용합니다.
예시(개념):
```ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import * as z from 'zod/v4';
export function createServer() {
const server = new McpServer(
{ name: 'file-time-search', version: '1.0.0' },
{ capabilities: { logging: {} } }
);
server.registerTool(
'hello',
{
description: 'Example tool',
inputSchema: { name: z.string() },
outputSchema: { greeting: z.string() }
},
async ({ name }) => {
const out = { greeting: `Hello, ${name}` };
return {
content: [{ type: 'text', text: JSON.stringify(out) }],
structuredContent: out
};
}
);
return server;
}
```
---
## 5. `fs.search_by_time` 구현 가이드(핵심)
정확한 입력/출력 계약은 [PRD-API.md](PRD-API.md)를 기준으로 하되, TypeScript에서는 `zod` 스키마를 통해 입력을 구성합니다.
### 5.1 입력 파라미터 설계(권장)
PRD 요구사항을 TS/Zod로 옮기면 대략 아래 형태가 됩니다(요약):
- `root`: 검색 루트(허용된 경로 하위만)
- `timeField`: `"modified" | "created"`
- `from`, `to`: ISO 8601 date-time 문자열(타임존 포함)만(v0)
- `glob`: 예 `"**/*.md"`
- `recursive`: boolean
- `sort`: `"time_desc" | "time_asc"` (+ tie-breaker path)
- `limit`: number
- `cursor`: string (페이지네이션)
> 참고: v0는 [PRD-v0-Policy.md](PRD-v0-Policy.md)에 따라 `from/to`를 **ISO 8601 date-time 문자열만** 허용합니다. epoch ms 지원은 v1 옵션으로 분리하는 것을 권장합니다.
> Windows “created time”은 Node의 `stat.birthtime/birthtimeMs`를 사용합니다. 파일시스템에 따라 의미/정확도가 다를 수 있어 [PRD-ImplementationNotes.md](PRD-ImplementationNotes.md)의 경고를 따르세요.
### 5.2 결과/페이지네이션(권장)
- 결과는 `structuredContent`로 반환
- 호환을 위해 `content: [{type:'text', text: JSON.stringify(structuredContent)}]`도 함께 반환
- 커서는 “마지막 아이템의 (time, path)”를 기준으로 **안정적인 다음 페이지 시작점**을 만들어야 합니다.
- 예: `{ t: 1734220000000, p: "sub/dir/file.txt" }` JSON → base64url
### 5.3 에러 처리 원칙
- 요청 구조 자체가 틀림(unknown tool 등): JSON-RPC protocol error
- 입력 값이 잘못됨/접근 불가/비즈니스 오류: tool result에 `isError: true`
MCP 스펙의 도구 에러 원칙은 [PRD-API.md](PRD-API.md) 및 MCP Tools 문서를 따릅니다.
---
## 6. 파일 시간 읽기(Windows 포함)
Node.js에서 일반적으로:
- mtime: `stat.mtimeMs`
- created/birth: `stat.birthtimeMs`
주의사항(현실적인 함정):
- 일부 환경에서 `birthtime`이 기대와 다를 수 있음(특히 복사/복원/압축 해제 시)
- 네트워크 드라이브/가상 파일시스템/권한 제한 폴더는 에러가 빈번
따라서 구현 시:
- 시간 읽기 실패를 “전체 실패”로 만들지 말고, 파일 단위로 스킵 또는 `isError` 정책을 명확히
- 대규모 스캔은 반드시 `limit`, `timeout`, `maxDepth`, `maxFiles` 같은 안전장치 권장
---
## 7. 보안/운영 체크리스트(최소)
- **허용 루트(allowRoots)**: 서버가 접근 가능한 루트를 명시적으로 제한
- **경로 정규화**: `..`/드라이브 레터/심볼릭 링크를 통한 탈출 방지
- **심볼릭 링크 정책**: 기본은 follow 금지 권장
- **레이트 리밋/타임아웃**: 무한 스캔 방지
- stdio 서버는 **stdout 오염 금지**(로그는 stderr)
---
## 8. 흔한 문제
### 8.1 `TS2589: Type instantiation is excessively deep...`
SDK 업그레이드 후 `zod` 버전이 중복 설치되면 발생할 수 있습니다.
- `npm ls zod` / `pnpm why zod` / `yarn why zod`로 중복 여부 확인
- 필요 시 `overrides`/`resolutions`로 단일 버전으로 맞추기
관련 내용은 TypeScript SDK FAQ에서도 다룹니다.
---
## 9. 다음 문서
- 실행/테스트/Inspector 사용법: [TS-Runbook.md](TS-Runbook.md)