본문으로 건너뛰기

MCP 확장 방법

이 페이지에서는 두 가지 확장 가이드를 제공합니다. 하나는 Elftia에 새로운 MCP 전송 방식을 추가하는 방법이고, 다른 하나는 Elftia와 연동되는 커스텀 MCP 서버를 작성하는 방법입니다.

가이드 1: 새로운 전송 방식 추가

Stdio/SSE/HTTP 이외의 전송 방식(예: WebSocket, gRPC 등)을 지원해야 하는 경우, 다음 파일들을 수정해야 합니다.

수정 체크리스트

단계파일변경 내용
1packages/desktop/app/shared/contracts/mcp-types.tsMcpServerTransport 타입 확장
2packages/desktop/app/main/services/capabilities/tools/mcp-users/McpService.tscreateTransport()에 새 분기 추가
3packages/desktop/app/main/services/routers/McpRouter.tsmcpAddSchema의 type 열거형 확장
4packages/renderer/src/features/settings/components/tabs/tools-tab/types.ts프론트엔드 타입 업데이트
5packages/renderer/src/features/settings/components/tabs/tools-tab/McpServerForm.tsx폼 옵션 추가
6i18n 파일새 전송 방식의 표시 이름 추가

단계 1: 타입 확장

mcp-types.ts에 새 전송 방식 값을 추가합니다.

export type McpServerTransport = 'stdio' | 'http' | 'sse' | 'websocket';

McpServerConfig에 새 필드가 필요한지도 확인합니다.

export type McpServerConfig = {
command?: string;
args?: string[];
env?: Record<string, string>;
url?: string;
headers?: Record<string, string>;
transport?: string;
// 필요한 경우 새 필드 추가
wsProtocol?: string;
};

단계 2: 전송 계층 구현

McpService.tscreateTransport() 메서드에 새 case 분기를 추가합니다.

private async createTransport(server: McpServerRecord) {
switch (server.type) {
case 'stdio':
// ...
case 'sse':
// ...
case 'http':
// ...
case 'websocket':
if (!server.config.url) {
throw new Error('WebSocket server requires url');
}
// WebSocket 전송 구현체 사용
return new WebSocketClientTransport(
new URL(server.config.url),
{ headers: server.config.headers || {} }
);
default:
throw new Error(`Unsupported transport type: ${server.type}`);
}
}

요구 사항: 전송 구현체는 MCP SDK의 Transport 인터페이스를 준수하고 Client.connect()와 함께 동작해야 합니다.

단계 3: IPC 유효성 검사 업데이트

McpRouter.ts의 Zod 스키마를 확장합니다.

const mcpAddSchema = z.object({
// ...
type: z.enum(['stdio', 'http', 'sse', 'websocket']),
// ...
});

단계 4-5: 프론트엔드 업데이트

McpServerForm.tsx의 전송 방식 선택기에 옵션을 추가합니다.

options={[
{ value: 'stdio', label: t('...stdio') },
{ value: 'sse', label: t('...sse') },
{ value: 'http', label: t('...http') },
{ value: 'websocket', label: t('...websocket') },
]}

새 전송 방식의 요구 사항에 따라 대응하는 설정 폼 필드(URL, 프로토콜 선택 등)를 추가합니다.

단계 6: 국제화

locales/{en,zh,ja}/settings/tools.json에 새 전송 방식의 표시 이름을 추가합니다.

가이드 2: 커스텀 MCP 서버 작성

Elftia와 연동되는 MCP 서버를 작성하려면 MCP 프로토콜 사양을 준수해야 합니다.

최소 Stdio 서버 (Node.js)

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const server = new Server(
{ name: 'my-custom-server', version: '1.0.0' },
{
capabilities: {
tools: {}
}
}
);

// 툴 목록 등록
server.setRequestHandler('tools/list', async () => ({
tools: [
{
name: 'hello',
description: '인사말을 반환합니다',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string', description: '인사할 이름' }
},
required: ['name']
}
}
]
}));

// 툴 호출 처리
server.setRequestHandler('tools/call', async (request) => {
if (request.params.name === 'hello') {
const name = request.params.arguments?.name ?? 'World';
return {
content: [
{ type: 'text', text: `Hello, ${name}!` }
]
};
}
return {
content: [{ type: 'text', text: 'Unknown tool' }],
isError: true
};
});

// 시작
const transport = new StdioServerTransport();
await server.connect(transport);

Elftia에서 사용하기

위 서버를 my-server.js로 저장한 후, Elftia에서 Stdio 서버를 추가합니다.

필드
이름my-custom-server
전송 방식Stdio
명령어node
인수/path/to/my-server.js

툴 정의 사양

Elftia는 MCP 툴에 대해 다음 요건을 요구합니다.

요건설명
이름반드시 제공해야 하며, 툴 ID 생성에 사용됩니다(mcp__server__name)
설명강력히 권장하며, LLM이 언제 호출할지 판단하는 기준이 됩니다
inputSchema유효한 JSON Schema이어야 하며, type: 'object' 필요
반환 형식content 배열, 각 항목에 type과 해당 데이터 포함

반환 콘텐츠 타입

// 텍스트 반환
{ type: 'text', text: '결과 텍스트' }

// 이미지 반환
{ type: 'image', mimeType: 'image/png', data: '<base64-encoded>' }

// 오디오 반환
{ type: 'audio', mimeType: 'audio/wav', data: '<base64-encoded>' }

참고: Elftia의 McpToolAdapter는 이미지와 오디오를 플레이스홀더 텍스트([Image: mime])로 변환하며, 실제 바이너리 데이터는 ToolCallDisplay 컴포넌트에서 렌더링을 처리합니다.

타임아웃 주의 사항

Elftia는 MCP 툴 호출에 120초 타임아웃을 설정합니다. 툴이 장시간 작업을 수행할 가능성이 있는 경우 다음을 권장합니다.

  • 비동기 처리를 구현하여 먼저 작업 ID를 반환하고 폴링 인터페이스를 제공
  • 툴 설명에 예상 대기 시간 명시
  • 스트리밍 반환 방식 검토(전송 계층이 지원하는 경우)

npm 패키지 배포

MCP 서버를 npm 패키지로 배포하여 npx로 원클릭 실행을 지원하려면:

  1. package.jsonbin 필드를 설정합니다.

    {
    "name": "@yourorg/mcp-server-example",
    "bin": {
    "mcp-server-example": "./dist/index.js"
    }
    }
  2. 진입 파일에 shebang이 있는지 확인합니다.

    #!/usr/bin/env node
  3. 사용자는 Elftia에서 다음과 같이 설정합니다.

    필드
    명령어npx
    인수-y , @yourorg/mcp-server-example

공식 프리셋에 추가하기

MCP 서버를 Elftia의 공식 프리셋 목록에 포함시키려면 packages/desktop/app/shared/mcp-presets.ts에 설정을 추가합니다.

export const OFFICIAL_MCP_PRESETS: OfficialMcpPreset[] = [
// 기존 프리셋...
{
id: 'your-server-id',
name: 'Your Server Name',
provider: 'your-org',
category: 'general', // search | vision | web-reading | code-repo | general
description: '서버 기능 설명',
tools: ['tool1', 'tool2'],
command: 'npx',
args: ['-y', '@yourorg/mcp-server@latest'],
requiresApiKey: true,
apiKeyEnvVar: 'YOUR_API_KEY',
linkedProviderIds: ['provider-id'],
documentationUrl: 'https://docs.example.com',
icon: 'icon-name',
},
];

프리셋 필드 설명:

필드필수 여부설명
id필수고유 식별자
name필수표시 이름
provider필수프로바이더 식별자
category필수카테고리: search / vision / web-reading / code-repo / general
description필수기능 설명
tools필수제공하는 툴 이름 목록
transportType선택stdio(기본값) / http
commandStdio 필요실행 명령어
argsStdio 필요명령어 인수
urlHTTP 필요원격 URL
requiresApiKey필수API Key 필요 여부
apiKeyEnvVar선택API Key 환경 변수 이름
linkedProviderIds선택연관된 LLM 프로바이더 ID (Key 자동 가져오기)
extraEnv선택추가 고정 환경 변수
documentationUrl선택문서 링크

DependencyCheckService 확장

MCP 서버가 비표준 CLI 툴에 의존하는 경우, DependencyCheckServiceinstallCommand() 메서드를 확장할 수 있습니다.

파일 경로: packages/desktop/app/main/services/capabilities/tools/mcp-users/DependencyCheckService.ts

async installCommand(command: string): Promise<DependencyInstallResult> {
// ...
if (command === 'your-tool') {
return await this.installYourTool(command);
}
// ...
}

현재 지원되는 자동 설치 목록:

명령어설치 방법
npx / npm / nodeWindows: winget; macOS: Homebrew; 기타: 다운로드 페이지
uv / uvx공식 설치 스크립트 (Windows: PowerShell; Unix: curl + sh)

관련 파일