ClineでSSE errorによりMCPサーバーと接続できない問題の解決方法

# ClineでMCPサーバーが接続できない問題の解決方法

## 概要

ClineでMCPサーバーを使用しようとした際に「SSE error: TypeError: fetch failed: connect ECONNREFUSED 127.0.0.1:*」エラーが発生する問題と、その解決方法について解説します。

## 問題の背景
ClineはModel Context Protocol (MCP)を使用して外部ツールと連携します。
WSL下にMCPサーバを作成し、起動が出来た段階で以下のような現象が発生しました。
- コンソールからのcurlリクエストは成功するが、ClineのGUIからMCPサーバーに接続できない
- エラーメッセージ: `SSE error: TypeError: fetch failed: connect ECONNREFUSED 127.0.0.1:3000`

## 原因

ClineのMCP統合は標準的なMCPプロトコル（JSON-RPC over stdio）を期待しているが、独自実装のHTTP APIサーバーとして作成されていたため、プロトコルの不一致が発生していました。

## 解決手順

### 1. プロジェクトの初期化

```bash
mkdir hello-mcp-server
cd hello-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk typescript @types/node
```

### 2. 標準的なMCPサーバーの実装

**src/index.ts**
```typescript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ErrorCode,
  ListToolsRequestSchema,
  McpError,
} from '@modelcontextprotocol/sdk/types.js';

class HelloMCPServer {
  private server: Server;

  constructor() {
    this.server = new Server(
      {
        name: 'hello-mcp-server',
        version: '1.0.0',
      },
      {
        capabilities: {
          tools: {},
        },
      }
    );

    this.setupToolHandlers();
    
    // Error handling
    this.server.onerror = (error) => console.error('[MCP Error]', error);
    process.on('SIGINT', async () => {
      await this.server.close();
      process.exit(0);
    });
  }

  private setupToolHandlers() {
    // ツールリストの定義
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        {
          name: 'say_hello',
          description: 'Hello Worldメッセージを返します',
          inputSchema: {
            type: 'object',
            properties: {
              name: {
                type: 'string',
                description: '挨拶する相手の名前',
              },
            },
            required: ['name'],
          },
        },
        {
          name: 'get_time',
          description: '現在の時刻を返します',
          inputSchema: {
            type: 'object',
            properties: {},
          },
        },
      ],
    }));

    // ツール実行の処理
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      try {
        switch (request.params.name) {
          case 'say_hello':
            if (!request.params.arguments) {
              throw new McpError(ErrorCode.InvalidParams, 'Missing arguments');
            }
            const args = request.params.arguments as { name: string };
            return {
              content: [
                {
                  type: 'text',
                  text: `Hello, ${args.name}! Welcome to MCP Server!`,
                },
              ],
            };

          case 'get_time':
            return {
              content: [
                {
                  type: 'text',
                  text: `Current time: ${new Date().toISOString()}`,
                },
              ],
            };

          default:
            throw new McpError(
              ErrorCode.MethodNotFound,
              `Unknown tool: ${request.params.name}`
            );
        }
      } catch (error: any) {
        console.error(`Tool execution error: ${error.message}`);
        return {
          content: [
            {
              type: 'text',
              text: `Error: ${error.message}`,
            },
          ],
          isError: true,
        };
      }
    });
  }

  async run() {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
    console.error('Hello MCP Server running on stdio');
  }
}

const server = new HelloMCPServer();
server.run().catch(console.error);
```

### 3. ビルド設定

**package.json**
```json
{
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  }
}
```

**tsconfig.json**
```json
{
  "compilerOptions": {
    "target": "es2020",
    "module": "es2020",
    "moduleResolution": "node",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  }
}
```

### 4. Cline設定ファイルの更新

ClineのMCP設定ファイルは、VSCodeの拡張機能データディレクトリに保存されます。
ここではWSLのVScode Serverで展開しているため以下の場所に設置しています。

**設定ファイルパス**: 
```
~/.vscode-server/data/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json
```

> **注意**: `saoudrizwan.claude-dev`は、ClineのVSCode拡張機能のパッケージ名です（作者名.拡張機能名）。VSCodeの拡張機能は、この形式でデータを保存します。

**変更前（HTTP/SSE）**:
```json
{
  "mcpServers": {
    "hello-mcp-server": {
      "autoApprove": [],
      "disabled": false,
      "timeout": 60,
      "url": "http://localhost:3000",
      "transportType": "sse"
    }
  }
}
```

**変更後（stdio）**:
```json
{
  "mcpServers": {
    "hello-mcp-server": {
      "autoApprove": [],
      "disabled": false,
      "timeout": 60,
      "command": "node",
      "args": ["/path/to/hello-mcp-server/dist/index.js"]
    }
  }
}
```

## 重要なポイント

### プロトコルの違い
- **HTTP/SSE**: 独自実装のREST APIサーバー
- **stdio**: 標準的なMCPプロトコル（JSON-RPC over stdio）

ClineのMCP統合では、標準的なMCPプロトコルを使用する必要があります。HTTP APIとして実装されたサーバーは、MCP SDKを使用してstdioベースの実装に変更する必要があります。

## 動作確認

### 1. ビルド
```bash
npm run build
```

### 2. ClineのGUIからのテスト
```xml
<!-- use_mcp_tool を使用してテスト -->
<use_mcp_tool>
<server_name>hello-mcp-server</server_name>
<tool_name>say_hello</tool_name>
<arguments>
{
  "name": "World"
}
</arguments>
</use_mcp_tool>
```

**期待される結果:**
```
Hello, World! Welcome to MCP Server!
```

## まとめ

ClineでMCPサーバーを使用する際は、標準的なMCPプロトコル（JSON-RPC over stdio）に準拠した実装が必要です。HTTP APIサーバーとして実装されている場合は、MCP SDKを使用して標準的な実装に変更し、設定ファイルもstdioトランスポートを使用するように更新する必要があります。

## 参考情報

- [Model Context Protocol (MCP) 公式ドキュメント](https://modelcontextprotocol.io/)
- [MCP SDK for TypeScript](https://github.com/modelcontextprotocol/typescript-sdk)

---

この記事が同様の問題に遭遇した方の参考になれば幸いです。