#
tokens: 18084/50000 6/6 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

```
├── .gitignore
├── package-lock.json
├── package.json
├── README.md
├── src
│   ├── server.ts
│   └── types.ts
├── tsconfig.json
└── tsconfig.tsbuildinfo
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
node_modules/
dist/
.env
.DS_Store
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# Sakura Cloud MCP Server

A Model Context Protocol (MCP) server implementation for interacting with Sakura Cloud's API.

## What is MCP?

The Model Context Protocol (MCP) is a standardized communication protocol that enables AI applications to securely interact with external systems and data sources. It follows a client-server architecture where LLM applications initiate connections to servers that expose resources and tools.

## Overview

This project implements an MCP server that allows AI assistants to interact with Sakura Cloud infrastructure through a standardized interface. It enables AI assistants to:

- Access Sakura Cloud resources like servers, disks, networks, and more
- Use tools to list resources and retrieve detailed information about specific resources
- Query public pricing information without authentication requirements
- Manage AppRun containerized applications

## Prerequisites

- Node.js (v16 or higher)
- Sakura Cloud API credentials (token and secret)
- Claude Desktop app for using with Claude (MCP is currently only supported in the desktop app)

## Installation

```bash
# Clone the repository
git clone https://github.com/hidenorigoto/sacloud-mcp.git
cd sacloud-mcp

# Install dependencies
npm install

# Build the project
npm run build
```

## Configuration

Set the following environment variables:

- `SACLOUD_API_TOKEN`: Your Sakura Cloud API token
- `SACLOUD_API_SECRET`: Your Sakura Cloud API secret

## Usage

### Available Resources

| Resource URI | Description |
|--------------|-------------|
| `sakura:///servers` | Lists all servers in your Sakura Cloud account |
| `sakura:///switches` | Lists all switches in your Sakura Cloud account |
| `sakura:///appliances` | Lists all appliances in your Sakura Cloud account |
| `sakura:///disks` | Lists all disks in your Sakura Cloud account |
| `sakura:///archives` | Lists all archives in your Sakura Cloud account |
| `sakura:///cdrom` | Lists all ISO images (CD-ROMs) in your Sakura Cloud account |
| `sakura:///bridge` | Lists all bridges in your Sakura Cloud account |
| `sakura:///internet` | Lists all routers in your Sakura Cloud account |
| `sakura:///interface` | Lists all network interfaces in your Sakura Cloud account |
| `sakura:///icon` | Lists all icons in your Sakura Cloud account |
| `sakura:///note` | Lists all startup scripts and notes in your Sakura Cloud account |
| `sakura:///sshkey` | Lists all SSH keys in your Sakura Cloud account |
| `sakura:///region` | Lists all regions in your Sakura Cloud account |
| `sakura:///zone` | Lists all zones in your Sakura Cloud account |
| `sakura:///product` | Lists all available products in your Sakura Cloud account |
| `sakura:///commonserviceitem` | Lists all common service items (DNS, Simple Monitor, etc.) in your Sakura Cloud account |
| `sakura:///license` | Lists all licenses in your Sakura Cloud account |
| `sakura:///auth-status` | Shows current authentication status and permissions |
| `sakura:///bill` | Shows monthly billing information |
| `sakura:///bill-detail` | Shows detailed breakdown of billing information |
| `sakura:///coupon` | Lists all available coupons |
| `sakura:///privatehost` | Lists all private hosts in your Sakura Cloud account |
| `sakura:///public-price` | Shows public pricing information for Sakura Cloud services (no authentication required) |
| `sakura:///apprun` | Lists all AppRun applications in your Sakura Cloud account |

### Available Tools

| Tool Name | Description | Required Parameters |
|-----------|-------------|---------------------|
| `get_server_list` | Retrieves list of all servers | None |
| `get_server_info` | Retrieves detailed information about a specific server | `serverId` |
| `get_switch_list` | Retrieves list of all switches | None |
| `get_switch_info` | Retrieves detailed information about a specific switch | `switchId` |
| `get_appliance_list` | Retrieves list of all appliances | None |
| `get_appliance_info` | Retrieves detailed information about a specific appliance | `applianceId` |
| `get_disk_list` | Retrieves list of all disks | None |
| `get_disk_info` | Retrieves detailed information about a specific disk | `diskId` |
| `get_archive_list` | Retrieves list of all archives | None |
| `get_archive_info` | Retrieves detailed information about a specific archive | `archiveId` |
| `get_cdrom_list` | Retrieves list of all ISO images | None |
| `get_cdrom_info` | Retrieves detailed information about a specific ISO image | `cdromId` |
| `get_bridge_list` | Retrieves list of all bridges | None |
| `get_bridge_info` | Retrieves detailed information about a specific bridge | `bridgeId` |
| `get_router_list` | Retrieves list of all routers | None |
| `get_router_info` | Retrieves detailed information about a specific router | `routerId` |
| `get_interface_list` | Retrieves list of all network interfaces | None |
| `get_interface_info` | Retrieves detailed information about a specific network interface | `interfaceId` |
| `get_icon_list` | Retrieves list of all icons | None |
| `get_icon_info` | Retrieves detailed information about a specific icon | `iconId` |
| `get_note_list` | Retrieves list of all notes and startup scripts | None |
| `get_note_info` | Retrieves detailed information about a specific note or startup script | `noteId` |
| `get_sshkey_list` | Retrieves list of all SSH keys | None |
| `get_sshkey_info` | Retrieves detailed information about a specific SSH key | `sshkeyId` |
| `get_region_list` | Retrieves list of all regions | None |
| `get_region_info` | Retrieves detailed information about a specific region | `regionId` |
| `get_zone_list` | Retrieves list of all zones | None |
| `get_zone_info` | Retrieves detailed information about a specific zone | `zoneId` |
| `get_product_info` | Retrieves detailed information about specific product offerings | `productType` |
| `get_commonserviceitem_list` | Retrieves list of all common service items | None |
| `get_commonserviceitem_info` | Retrieves detailed information about a specific common service item | `itemId` |
| `get_license_list` | Retrieves list of all licenses | None |
| `get_license_info` | Retrieves detailed information about a specific license | `licenseId` |
| `get_bill_info` | Retrieves billing information for a specific month | `year`, `month` |
| `get_bill_detail` | Retrieves detailed billing information for a specific month | `year`, `month` |
| `get_coupon_info` | Retrieves information about a specific coupon | `couponId` |
| `get_privatehost_info` | Retrieves detailed information about a specific private host | `privateHostId` |
| `get_public_price` | Retrieves public pricing information for Sakura Cloud services | None |
| `get_apprun_list` | Retrieves list of all AppRun applications | None |
| `get_apprun_info` | Retrieves detailed information about a specific AppRun application | `appId` |
| `create_apprun` | Creates a new AppRun application | `name`, `dockerImage`, `planId` |
| `delete_apprun` | Deletes an AppRun application | `appId` |
| `start_apprun` | Starts an AppRun application | `appId` |
| `stop_apprun` | Stops an AppRun application | `appId` |
| `update_apprun` | Updates an existing AppRun application | `appId` |
| `get_apprun_logs` | Gets logs from an AppRun application | `appId` |

## AppRun Integration

Sakura Cloud AppRun is a containerized application platform that allows you to run Docker containers without managing infrastructure. This MCP server provides full AppRun management capabilities:

- View all your AppRun applications
- Create new applications with custom Docker images
- Update existing applications (change image, configuration, etc.)
- Start and stop applications
- View application logs
- Delete applications when no longer needed

When creating or updating an AppRun application, you can specify:
- Application name and description
- Docker image to use
- Plan ID (determines resources allocated)
- Environment variables as key-value pairs

## Zone Support

All API calls support specifying a zone parameter to target specific Sakura Cloud data centers. The default zone is `tk1v` (Tokyo), but you can specify others such as:
- `is1a` (Ishikari)
- `tk1a` (Tokyo)
- And more...

Example URI with zone parameter: `sakura:///servers?zone=is1a`

## Integrating with Claude

Claude Desktop app provides MCP support. Follow these steps to integrate this server with Claude:

1. Make sure the server is running locally or on an accessible host.

2. Create a `claude_desktop_config.json` file in the appropriate location for your OS:
   - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
   - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - Linux: `~/.config/Claude/claude_desktop_config.json`

3. Add the following configuration to the file:

```json
{
  "sacloud-server": {
    "command": "node",
    "args": ["path/to/mcp/dist/server.js"],
    "env": {
      "SACLOUD_API_TOKEN": "your_token_here",
      "SACLOUD_API_SECRET": "your_secret_here"
    }
  }
}
```

4. Restart the Claude Desktop app to apply the configuration.

5. In a conversation with Claude, you can now access Sakura Cloud resources and tools.

## Security Considerations

- This server handles sensitive API credentials
- Never commit API tokens or secrets to version control
- Use environment variables for all sensitive information
- Implement proper access controls in production

## License

ISC
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "rootDir": "./src",
    "outDir": "./dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "sacloud-mcp",
  "version": "1.0.0",
  "main": "dist/server.js",
  "scripts": {
    "start": "node dist/server.js",
    "dev": "ts-node src/server.ts",
    "build": "tsc",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@types/node": "^22.13.14",
    "ts-node": "^10.9.2",
    "typescript": "^5.8.2"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.8.0"
  }
}

```

--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------

```typescript
declare module '@modelcontextprotocol/sdk' {
  export interface ServerConfig {
    name: string;
    version: string;
  }

  export interface TransportConfig {
    transport: {
      type: 'http';
      port: number;
    };
  }

  export class Server {
    constructor(serverConfig: ServerConfig, transportConfig: TransportConfig);
    setRequestHandler<P, R>(schema: { params: P, result: R }, handler: (request: { params: P }) => Promise<R>): void;
    listen(): Promise<void>;
    close(): Promise<void>;
  }

  export const ListResourcesRequestSchema: {
    params: null;
    result: {
      resources: Array<{
        uri: string;
        name: string;
        description?: string;
        mimeType?: string;
      }>;
    };
  };

  export const ReadResourceRequestSchema: {
    params: {
      uri: string;
    };
    result: {
      contents: Array<{
        uri: string;
        mimeType: string;
        text: string;
      }>;
    };
  };

  export const ListToolsRequestSchema: {
    params: null;
    result: {
      tools: Array<{
        name: string;
        description: string;
        inputSchema: {
          type: string;
          properties: Record<string, any>;
          required?: string[];
        };
      }>;
    };
  };

  export const CallToolRequestSchema: {
    params: {
      name: string;
      arguments: Record<string, any>;
    };
    result: {
      content: Array<{
        type: string;
        text: string;
      }>;
    };
  };
}
```

--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
  ListToolsRequestSchema,
  CallToolRequestSchema
} from '@modelcontextprotocol/sdk/types.js';
import https from 'https';

const SACLOUD_API_TOKEN = process.env.SACLOUD_API_TOKEN || '';
const SACLOUD_API_SECRET = process.env.SACLOUD_API_SECRET || '';

// Default zone to use if not specified
const DEFAULT_ZONE = 'tk1v';

// Helper function to make API calls to Sakura Cloud
async function fetchFromSakuraCloud(path: string, isPublicAPI: boolean = false, zone: string = DEFAULT_ZONE, method: string = 'GET', bodyData?: any): Promise<any> {
  return new Promise((resolve, reject) => {
    const basePath = isPublicAPI ? '/cloud/api/cloud/1.1' : `/cloud/zone/${zone}/api/cloud/1.1`;
    
    const options = {
      hostname: 'secure.sakura.ad.jp',
      port: 443,
      path: `${basePath}${path}`,
      method: method,
      headers: {
        'Accept': 'application/json',
        'Authorization': '',
        'Content-Type': 'application/json'
      }
    };
    
    // Add authorization for non-public APIs
    if (!isPublicAPI) {
      options.headers['Authorization'] = `Basic ${Buffer.from(`${SACLOUD_API_TOKEN}:${SACLOUD_API_SECRET}`).toString('base64')}`;
    }

    const req = https.request(options, (res) => {
      let data = '';
      
      res.on('data', (chunk) => {
        data += chunk;
      });
      
      res.on('end', () => {
        try {
          if (data) {
            const parsedData = JSON.parse(data);
            resolve(parsedData);
          } else {
            resolve({});
          }
        } catch (err) {
          reject(new Error(`Failed to parse response: ${err}`));
        }
      });
    });
    
    req.on('error', (error) => {
      reject(error);
    });
    
    if (bodyData && (method === 'POST' || method === 'PUT')) {
      req.write(JSON.stringify(bodyData));
    }
    
    req.end();
  });
}

// Helper function to fetch data from AppRun API
async function fetchFromAppRunAPI(path: string, method: string = 'GET', bodyData?: any): Promise<any> {
  return new Promise((resolve, reject) => {
    validateCredentials();
    
    const options = {
      hostname: 'secure.sakura.ad.jp',
      port: 443,
      path: `/cloud/api/apprun/1.0/apprun/api${path}`,
      method: method,
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': `Basic ${Buffer.from(`${SACLOUD_API_TOKEN}:${SACLOUD_API_SECRET}`).toString('base64')}`
      }
    };

    const req = https.request(options, (res) => {
      let data = '';
      
      res.on('data', (chunk) => {
        data += chunk;
      });
      
      res.on('end', () => {
        try {
          if (data) {
            const parsedData = JSON.parse(data);
            resolve(parsedData);
          } else {
            resolve({});
          }
        } catch (err) {
          reject(new Error(`Failed to parse response: ${err}`));
        }
      });
    });
    
    req.on('error', (error) => {
      reject(error);
    });
    
    if (bodyData && (method === 'POST' || method === 'PUT')) {
      req.write(JSON.stringify(bodyData));
    }
    
    req.end();
  });
}

// Check if API credentials are provided
function validateCredentials(): void {
  if (!SACLOUD_API_TOKEN || !SACLOUD_API_SECRET) {
    throw new Error('Missing API credentials. Set SACLOUD_API_TOKEN and SACLOUD_API_SECRET environment variables.');
  }
}

// Initialize MCP server
const server = new Server(
  {
    name: 'sacloud-mcp-server',
    version: '1.0.0',
    port: 3001
  },
  {
    capabilities: {
      resources: {},
      tools: {},
    },
  }
);

// Register resources
server.setRequestHandler(ListResourcesRequestSchema, async () => {
  return {
    resources: [
      {
        uri: 'sakura:///servers',
        name: 'Sakura Cloud Servers',
        description: 'List of all servers in Sakura Cloud'
      },
      {
        uri: 'sakura:///switches',
        name: 'Sakura Cloud Switches',
        description: 'List of all switches in Sakura Cloud'
      },
      {
        uri: 'sakura:///appliances',
        name: 'Sakura Cloud Appliances',
        description: 'List of all appliances in Sakura Cloud'
      },
      {
        uri: 'sakura:///disks',
        name: 'Sakura Cloud Disks',
        description: 'List of all disks in Sakura Cloud'
      },
      {
        uri: 'sakura:///archives',
        name: 'Sakura Cloud Archives',
        description: 'List of all archives in Sakura Cloud'
      },
      {
        uri: 'sakura:///cdrom',
        name: 'Sakura Cloud ISO Images',
        description: 'List of all ISO images (CD-ROMs) in Sakura Cloud'
      },
      {
        uri: 'sakura:///bridge',
        name: 'Sakura Cloud Bridges',
        description: 'List of all bridges in Sakura Cloud'
      },
      {
        uri: 'sakura:///internet',
        name: 'Sakura Cloud Routers',
        description: 'List of all routers in Sakura Cloud'
      },
      {
        uri: 'sakura:///interface',
        name: 'Sakura Cloud Interfaces',
        description: 'List of all network interfaces in Sakura Cloud'
      },
      {
        uri: 'sakura:///icon',
        name: 'Sakura Cloud Icons',
        description: 'List of all icons in Sakura Cloud'
      },
      {
        uri: 'sakura:///note',
        name: 'Sakura Cloud Notes',
        description: 'List of all startup scripts and notes in Sakura Cloud'
      },
      {
        uri: 'sakura:///sshkey',
        name: 'Sakura Cloud SSH Keys',
        description: 'List of all SSH keys in Sakura Cloud'
      },
      {
        uri: 'sakura:///region',
        name: 'Sakura Cloud Regions',
        description: 'List of all regions in Sakura Cloud'
      },
      {
        uri: 'sakura:///zone',
        name: 'Sakura Cloud Zones',
        description: 'List of all zones in Sakura Cloud'
      },
      {
        uri: 'sakura:///product',
        name: 'Sakura Cloud Products',
        description: 'List of all available products in Sakura Cloud'
      },
      {
        uri: 'sakura:///commonserviceitem',
        name: 'Sakura Cloud Common Service Items',
        description: 'List of all common service items (DNS, Simple Monitor, etc.) in Sakura Cloud'
      },
      {
        uri: 'sakura:///license',
        name: 'Sakura Cloud Licenses',
        description: 'List of all licenses in Sakura Cloud'
      },
      {
        uri: 'sakura:///auth-status',
        name: 'Sakura Cloud Authentication Status',
        description: 'Current authentication status and permissions'
      },
      {
        uri: 'sakura:///bill',
        name: 'Sakura Cloud Billing Information',
        description: 'Monthly billing information'
      },
      {
        uri: 'sakura:///bill-detail',
        name: 'Sakura Cloud Billing Details',
        description: 'Detailed breakdown of billing information'
      },
      {
        uri: 'sakura:///coupon',
        name: 'Sakura Cloud Coupons',
        description: 'List of all available coupons'
      },
      {
        uri: 'sakura:///privatehost',
        name: 'Sakura Cloud Private Hosts',
        description: 'List of all private hosts in Sakura Cloud'
      },
      {
        uri: 'sakura:///public-price',
        name: 'Sakura Cloud Public Price List',
        description: 'Public pricing information for Sakura Cloud services'
      },
      {
        uri: 'sakura:///apprun',
        name: 'Sakura Cloud AppRun',
        description: 'List of all AppRun applications in Sakura Cloud'
      }
    ]
  };
});

server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
  const uri = request.params.uri;
  
  // Parse the URI to extract zone information if present
  // Format: sakura:///resource?zone=zoneName
  let zone = DEFAULT_ZONE;
  const uriParts = uri.split('?');
  const resourcePath = uriParts[0];
  
  if (uriParts.length > 1) {
    const queryParams = new URLSearchParams(uriParts[1]);
    if (queryParams.has('zone')) {
      zone = queryParams.get('zone') || DEFAULT_ZONE;
    }
  }
  
  if (resourcePath === 'sakura:///servers') {
    try {
      validateCredentials();
      const serversData = await fetchFromSakuraCloud('/server', false, zone);
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(serversData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching servers:', error);
      throw error;
    }
  } else if (resourcePath === 'sakura:///switches') {
    try {
      validateCredentials();
      const switchesData = await fetchFromSakuraCloud('/switch', false, zone);
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(switchesData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching switches:', error);
      throw error;
    }
  } else if (resourcePath === 'sakura:///appliances') {
    try {
      validateCredentials();
      const appliancesData = await fetchFromSakuraCloud('/appliance', false, zone);
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(appliancesData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching appliances:', error);
      throw error;
    }
  } else if (resourcePath === 'sakura:///disks') {
    try {
      validateCredentials();
      const disksData = await fetchFromSakuraCloud('/disk', false, zone);
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(disksData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching disks:', error);
      throw error;
    }
  } else if (resourcePath === 'sakura:///archives') {
    try {
      validateCredentials();
      const archivesData = await fetchFromSakuraCloud('/archive', false, zone);
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(archivesData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching archives:', error);
      throw error;
    }
  } else if (resourcePath === 'sakura:///cdrom') {
    try {
      validateCredentials();
      const cdromData = await fetchFromSakuraCloud('/cdrom', false, zone);
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(cdromData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching ISO images:', error);
      throw error;
    }
  } else if (uri === 'sakura:///bridge') {
    try {
      validateCredentials();
      const bridgeData = await fetchFromSakuraCloud('/bridge');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(bridgeData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching bridges:', error);
      throw error;
    }
  } else if (uri === 'sakura:///internet') {
    try {
      validateCredentials();
      const routerData = await fetchFromSakuraCloud('/internet');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(routerData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching routers:', error);
      throw error;
    }
  } else if (uri === 'sakura:///interface') {
    try {
      validateCredentials();
      const interfaceData = await fetchFromSakuraCloud('/interface');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(interfaceData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching interfaces:', error);
      throw error;
    }
  } else if (uri === 'sakura:///icon') {
    try {
      validateCredentials();
      const iconData = await fetchFromSakuraCloud('/icon');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(iconData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching icons:', error);
      throw error;
    }
  } else if (uri === 'sakura:///note') {
    try {
      validateCredentials();
      const noteData = await fetchFromSakuraCloud('/note');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(noteData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching notes:', error);
      throw error;
    }
  } else if (uri === 'sakura:///sshkey') {
    try {
      validateCredentials();
      const sshkeyData = await fetchFromSakuraCloud('/sshkey');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(sshkeyData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching SSH keys:', error);
      throw error;
    }
  } else if (uri === 'sakura:///region') {
    try {
      validateCredentials();
      const regionData = await fetchFromSakuraCloud('/region');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(regionData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching regions:', error);
      throw error;
    }
  } else if (uri === 'sakura:///zone') {
    try {
      validateCredentials();
      const zoneData = await fetchFromSakuraCloud('/zone');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(zoneData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching zones:', error);
      throw error;
    }
  } else if (uri === 'sakura:///product') {
    try {
      validateCredentials();
      // Fetch multiple product types and combine them
      const serverPlans = await fetchFromSakuraCloud('/product/server');
      const diskPlans = await fetchFromSakuraCloud('/product/disk');
      const internetPlans = await fetchFromSakuraCloud('/product/internet');
      const licensePlans = await fetchFromSakuraCloud('/product/license');
      
      const combinedProducts = {
        server: serverPlans,
        disk: diskPlans,
        internet: internetPlans,
        license: licensePlans
      };
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(combinedProducts, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching products:', error);
      throw error;
    }
  } else if (uri === 'sakura:///commonserviceitem') {
    try {
      validateCredentials();
      const commonServiceItemData = await fetchFromSakuraCloud('/commonserviceitem');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(commonServiceItemData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching common service items:', error);
      throw error;
    }
  } else if (uri === 'sakura:///license') {
    try {
      validateCredentials();
      const licenseData = await fetchFromSakuraCloud('/license');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(licenseData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching licenses:', error);
      throw error;
    }
  } else if (uri === 'sakura:///auth-status') {
    try {
      validateCredentials();
      const authStatusData = await fetchFromSakuraCloud('/auth-status');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(authStatusData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching authentication status:', error);
      throw error;
    }
  } else if (uri === 'sakura:///bill') {
    try {
      validateCredentials();
      const billData = await fetchFromSakuraCloud('/bill');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(billData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching billing information:', error);
      throw error;
    }
  } else if (uri === 'sakura:///bill-detail') {
    try {
      validateCredentials();
      const billDetailData = await fetchFromSakuraCloud('/bill/detail');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(billDetailData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching billing details:', error);
      throw error;
    }
  } else if (uri === 'sakura:///coupon') {
    try {
      validateCredentials();
      const couponData = await fetchFromSakuraCloud('/coupon');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(couponData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching coupons:', error);
      throw error;
    }
  } else if (uri === 'sakura:///privatehost') {
    try {
      validateCredentials();
      const privateHostData = await fetchFromSakuraCloud('/privatehost');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(privateHostData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching private hosts:', error);
      throw error;
    }
  } else if (uri === 'sakura:///public-price') {
    try {
      // No authentication needed for public price API
      const priceData = await fetchFromSakuraCloud('/public/price', false);
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(priceData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching public price data:', error);
      throw error;
    }
  } else if (resourcePath === 'sakura:///apprun') {
    try {
      validateCredentials();
      const appRunData = await fetchFromAppRunAPI('/applications');
      
      return {
        contents: [
          {
            uri,
            mimeType: 'application/json',
            text: JSON.stringify(appRunData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error fetching AppRun data:', error);
      throw error;
    }
  }
  
  throw new Error(`Resource not found: ${resourcePath}`);
});

// Register tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'get_server_info',
        description: 'Get detailed information about a specific server',
        inputSchema: {
          type: 'object',
          properties: {
            serverId: {
              type: 'string',
              description: 'The ID of the server to retrieve'
            },
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
          required: ['serverId']
        }
      },
      {
        name: 'get_server_list',
        description: 'Get list of servers',
        inputSchema: {
          type: 'object',
          properties: {
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
        }
      },
      {
        name: 'get_switch_list',
        description: 'Get list of switches',
        inputSchema: {
          type: 'object',
          properties: {
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
        }
      },
      {
        name: 'get_switch_info',
        description: 'Get detailed information about a specific switch',
        inputSchema: {
          type: 'object',
          properties: {
            switchId: {
              type: 'string',
              description: 'The ID of the switch to retrieve'
            },
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
          required: ['switchId']
        }
      },
      {
        name: 'get_appliance_list',
        description: 'Get list of appliances',
        inputSchema: {
          type: 'object',
          properties: {
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
        }
      },
      {
        name: 'get_appliance_info',
        description: 'Get detailed information about a specific appliance',
        inputSchema: {
          type: 'object',
          properties: {
            applianceId: {
              type: 'string',
              description: 'The ID of the appliance to retrieve'
            }
          },
          required: ['applianceId']
        }
      },
      {
        name: 'get_disk_list',
        description: 'Get list of disks',
        inputSchema: {
          type: 'object',
          properties: {
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
        }
      },
      {
        name: 'get_disk_info',
        description: 'Get detailed information about a specific disk',
        inputSchema: {
          type: 'object',
          properties: {
            diskId: {
              type: 'string',
              description: 'The ID of the disk to retrieve'
            },
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
          required: ['diskId']
        }
      },
      {
        name: 'get_archive_list',
        description: 'Get list of archives',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_archive_info',
        description: 'Get detailed information about a specific archive',
        inputSchema: {
          type: 'object',
          properties: {
            archiveId: {
              type: 'string',
              description: 'The ID of the archive to retrieve'
            }
          },
          required: ['archiveId']
        }
      },
      {
        name: 'get_cdrom_list',
        description: 'Get list of ISO images',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_cdrom_info',
        description: 'Get detailed information about a specific ISO image',
        inputSchema: {
          type: 'object',
          properties: {
            cdromId: {
              type: 'string',
              description: 'The ID of the ISO image to retrieve'
            }
          },
          required: ['cdromId']
        }
      },
      {
        name: 'get_bridge_list',
        description: 'Get list of bridges',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_bridge_info',
        description: 'Get detailed information about a specific bridge',
        inputSchema: {
          type: 'object',
          properties: {
            bridgeId: {
              type: 'string',
              description: 'The ID of the bridge to retrieve'
            }
          },
          required: ['bridgeId']
        }
      },
      {
        name: 'get_router_list',
        description: 'Get list of routers',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_router_info',
        description: 'Get detailed information about a specific router',
        inputSchema: {
          type: 'object',
          properties: {
            routerId: {
              type: 'string',
              description: 'The ID of the router to retrieve'
            }
          },
          required: ['routerId']
        }
      },
      {
        name: 'get_interface_list',
        description: 'Get list of network interfaces',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_interface_info',
        description: 'Get detailed information about a specific network interface',
        inputSchema: {
          type: 'object',
          properties: {
            interfaceId: {
              type: 'string',
              description: 'The ID of the interface to retrieve'
            }
          },
          required: ['interfaceId']
        }
      },
      {
        name: 'get_icon_list',
        description: 'Get list of icons',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_icon_info',
        description: 'Get detailed information about a specific icon',
        inputSchema: {
          type: 'object',
          properties: {
            iconId: {
              type: 'string',
              description: 'The ID of the icon to retrieve'
            }
          },
          required: ['iconId']
        }
      },
      {
        name: 'get_note_list',
        description: 'Get list of notes and startup scripts',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_note_info',
        description: 'Get detailed information about a specific note or startup script',
        inputSchema: {
          type: 'object',
          properties: {
            noteId: {
              type: 'string',
              description: 'The ID of the note to retrieve'
            }
          },
          required: ['noteId']
        }
      },
      {
        name: 'get_sshkey_list',
        description: 'Get list of SSH keys',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_sshkey_info',
        description: 'Get detailed information about a specific SSH key',
        inputSchema: {
          type: 'object',
          properties: {
            sshkeyId: {
              type: 'string',
              description: 'The ID of the SSH key to retrieve'
            }
          },
          required: ['sshkeyId']
        }
      },
      {
        name: 'get_region_list',
        description: 'Get list of regions',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_region_info',
        description: 'Get detailed information about a specific region',
        inputSchema: {
          type: 'object',
          properties: {
            regionId: {
              type: 'string',
              description: 'The ID of the region to retrieve'
            }
          },
          required: ['regionId']
        }
      },
      {
        name: 'get_zone_list',
        description: 'Get list of zones',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_zone_info',
        description: 'Get detailed information about a specific zone',
        inputSchema: {
          type: 'object',
          properties: {
            zoneId: {
              type: 'string',
              description: 'The ID of the zone to retrieve'
            }
          },
          required: ['zoneId']
        }
      },
      {
        name: 'get_product_info',
        description: 'Get detailed information about specific product offerings',
        inputSchema: {
          type: 'object',
          properties: {
            productType: {
              type: 'string',
              description: 'The type of product to retrieve (server, disk, internet, license)',
              enum: ['server', 'disk', 'internet', 'license']
            }
          },
          required: ['productType']
        }
      },
      {
        name: 'get_commonserviceitem_list',
        description: 'Get list of common service items (DNS, Simple Monitor, etc.)',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_commonserviceitem_info',
        description: 'Get detailed information about a specific common service item',
        inputSchema: {
          type: 'object',
          properties: {
            itemId: {
              type: 'string',
              description: 'The ID of the common service item to retrieve'
            }
          },
          required: ['itemId']
        }
      },
      {
        name: 'get_license_list',
        description: 'Get list of licenses',
        inputSchema: {
          type: 'object',
          properties: {
          },
        }
      },
      {
        name: 'get_license_info',
        description: 'Get detailed information about a specific license',
        inputSchema: {
          type: 'object',
          properties: {
            licenseId: {
              type: 'string',
              description: 'The ID of the license to retrieve'
            }
          },
          required: ['licenseId']
        }
      },
      {
        name: 'get_bill_info',
        description: 'Get billing information for a specific month',
        inputSchema: {
          type: 'object',
          properties: {
            year: {
              type: 'string',
              description: 'The year (YYYY) of the billing period'
            },
            month: {
              type: 'string',
              description: 'The month (MM) of the billing period'
            }
          },
          required: ['year', 'month']
        }
      },
      {
        name: 'get_bill_detail',
        description: 'Get detailed billing information for a specific month',
        inputSchema: {
          type: 'object',
          properties: {
            year: {
              type: 'string',
              description: 'The year (YYYY) of the billing period'
            },
            month: {
              type: 'string',
              description: 'The month (MM) of the billing period'
            }
          },
          required: ['year', 'month']
        }
      },
      {
        name: 'get_coupon_info',
        description: 'Get information about a specific coupon',
        inputSchema: {
          type: 'object',
          properties: {
            couponId: {
              type: 'string',
              description: 'The ID of the coupon to retrieve'
            }
          },
          required: ['couponId']
        }
      },
      {
        name: 'get_privatehost_info',
        description: 'Get detailed information about a specific private host',
        inputSchema: {
          type: 'object',
          properties: {
            privateHostId: {
              type: 'string',
              description: 'The ID of the private host to retrieve'
            }
          },
          required: ['privateHostId']
        }
      },
      {
        name: 'get_public_price',
        description: 'Get public pricing information for Sakura Cloud services',
        inputSchema: {
          type: 'object',
          properties: {}
        }
      },
      {
        name: 'get_apprun_list',
        description: 'Get list of all AppRun applications',
        inputSchema: {
          type: 'object',
          properties: {
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          }
        }
      },
      {
        name: 'get_apprun_info',
        description: 'Get detailed information about a specific AppRun application',
        inputSchema: {
          type: 'object',
          properties: {
            appId: {
              type: 'string',
              description: 'The ID of the AppRun application to retrieve'
            },
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
          required: ['appId']
        }
      },
      {
        name: 'create_apprun',
        description: 'Create a new AppRun application',
        inputSchema: {
          type: 'object',
          properties: {
            name: {
              type: 'string',
              description: 'Name of the AppRun application'
            },
            description: {
              type: 'string',
              description: 'Description of the AppRun application'
            },
            dockerImage: {
              type: 'string',
              description: 'Docker image to use for the AppRun application'
            },
            planId: {
              type: 'string',
              description: 'Plan ID for the AppRun application'
            },
            environment: {
              type: 'array',
              description: 'Environment variables for the AppRun application',
              items: {
                type: 'object',
                properties: {
                  key: { type: 'string' },
                  value: { type: 'string' }
                }
              }
            },
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
          required: ['name', 'dockerImage', 'planId']
        }
      },
      {
        name: 'delete_apprun',
        description: 'Delete an AppRun application',
        inputSchema: {
          type: 'object',
          properties: {
            appId: {
              type: 'string',
              description: 'The ID of the AppRun application to delete'
            },
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
          required: ['appId']
        }
      },
      {
        name: 'start_apprun',
        description: 'Start an AppRun application',
        inputSchema: {
          type: 'object',
          properties: {
            appId: {
              type: 'string',
              description: 'The ID of the AppRun application to start'
            },
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
          required: ['appId']
        }
      },
      {
        name: 'stop_apprun',
        description: 'Stop an AppRun application',
        inputSchema: {
          type: 'object',
          properties: {
            appId: {
              type: 'string',
              description: 'The ID of the AppRun application to stop'
            },
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
          required: ['appId']
        }
      },
      {
        name: 'update_apprun',
        description: 'Update an existing AppRun application',
        inputSchema: {
          type: 'object',
          properties: {
            appId: {
              type: 'string',
              description: 'The ID of the AppRun application to update'
            },
            name: {
              type: 'string',
              description: 'New name of the AppRun application'
            },
            description: {
              type: 'string',
              description: 'New description of the AppRun application'
            },
            dockerImage: {
              type: 'string',
              description: 'New Docker image to use for the AppRun application'
            },
            planId: {
              type: 'string',
              description: 'New plan ID for the AppRun application'
            },
            environment: {
              type: 'array',
              description: 'New environment variables for the AppRun application',
              items: {
                type: 'object',
                properties: {
                  key: { type: 'string' },
                  value: { type: 'string' }
                }
              }
            },
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
          required: ['appId']
        }
      },
      {
        name: 'get_apprun_logs',
        description: 'Get logs from an AppRun application',
        inputSchema: {
          type: 'object',
          properties: {
            appId: {
              type: 'string',
              description: 'The ID of the AppRun application to get logs from'
            },
            offset: {
              type: 'number',
              description: 'Offset to start fetching logs from (default: 0)'
            },
            limit: {
              type: 'number',
              description: 'Maximum number of log entries to fetch (default: 100)'
            },
            zone: {
              type: 'string',
              description: 'The zone to use (e.g., "tk1v", "is1a", "tk1a"). Defaults to "tk1v" if not specified.'
            }
          },
          required: ['appId']
        }
      }
    ]
  };
});

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === 'get_server_info') {
    try {
      validateCredentials();
      
      const serverId = request.params.arguments?.serverId as string;
      if (!serverId) {
        throw new Error('Server ID is required');
      }
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const serverInfo = await fetchFromSakuraCloud(`/server/${serverId}`, false, zone);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(serverInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_server_list') {
    try {
      validateCredentials();
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const serverList = await fetchFromSakuraCloud(`/server`, false, zone);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(serverList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_switch_list') {
    try {
      validateCredentials();
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const switchList = await fetchFromSakuraCloud(`/switch`, false, zone);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(switchList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_switch_info') {
    try {
      validateCredentials();
      
      const switchId = request.params.arguments?.switchId as string;
      if (!switchId) {
        throw new Error('Switch ID is required');
      }
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const switchInfo = await fetchFromSakuraCloud(`/switch/${switchId}`, false, zone);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(switchInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_appliance_list') {
    try {
      validateCredentials();
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const applianceList = await fetchFromSakuraCloud(`/appliance`, false, zone);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(applianceList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_appliance_info') {
    try {
      validateCredentials();
      
      const applianceId = request.params.arguments?.applianceId as string;
      if (!applianceId) {
        throw new Error('Appliance ID is required');
      }
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const applianceInfo = await fetchFromSakuraCloud(`/appliance/${applianceId}`, false, zone);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(applianceInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_disk_list') {
    try {
      validateCredentials();
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const diskList = await fetchFromSakuraCloud(`/disk`, false, zone);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(diskList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_disk_info') {
    try {
      validateCredentials();
      
      const diskId = request.params.arguments?.diskId as string;
      if (!diskId) {
        throw new Error('Disk ID is required');
      }
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const diskInfo = await fetchFromSakuraCloud(`/disk/${diskId}`, false, zone);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(diskInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_archive_list') {
    try {
      validateCredentials();
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const archiveList = await fetchFromSakuraCloud(`/archive`, false, zone);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(archiveList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_archive_info') {
    try {
      validateCredentials();
      
      const archiveId = request.params.arguments?.archiveId as string;
      if (!archiveId) {
        throw new Error('Archive ID is required');
      }
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const archiveInfo = await fetchFromSakuraCloud(`/archive/${archiveId}`, false, zone);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(archiveInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_cdrom_list') {
    try {
      validateCredentials();
      
      const cdromList = await fetchFromSakuraCloud(`/cdrom`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(cdromList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_cdrom_info') {
    try {
      validateCredentials();
      
      const cdromId = request.params.arguments?.cdromId as string;
      if (!cdromId) {
        throw new Error('ISO Image ID is required');
      }
      
      const cdromInfo = await fetchFromSakuraCloud(`/cdrom/${cdromId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(cdromInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_bridge_list') {
    try {
      validateCredentials();
      
      const bridgeList = await fetchFromSakuraCloud(`/bridge`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(bridgeList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_bridge_info') {
    try {
      validateCredentials();
      
      const bridgeId = request.params.arguments?.bridgeId as string;
      if (!bridgeId) {
        throw new Error('Bridge ID is required');
      }
      
      const bridgeInfo = await fetchFromSakuraCloud(`/bridge/${bridgeId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(bridgeInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_router_list') {
    try {
      validateCredentials();
      
      const routerList = await fetchFromSakuraCloud(`/internet`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(routerList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_router_info') {
    try {
      validateCredentials();
      
      const routerId = request.params.arguments?.routerId as string;
      if (!routerId) {
        throw new Error('Router ID is required');
      }
      
      const routerInfo = await fetchFromSakuraCloud(`/internet/${routerId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(routerInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_interface_list') {
    try {
      validateCredentials();
      
      const interfaceList = await fetchFromSakuraCloud(`/interface`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(interfaceList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_interface_info') {
    try {
      validateCredentials();
      
      const interfaceId = request.params.arguments?.interfaceId as string;
      if (!interfaceId) {
        throw new Error('Interface ID is required');
      }
      
      const interfaceInfo = await fetchFromSakuraCloud(`/interface/${interfaceId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(interfaceInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_icon_list') {
    try {
      validateCredentials();
      
      const iconList = await fetchFromSakuraCloud(`/icon`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(iconList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_icon_info') {
    try {
      validateCredentials();
      
      const iconId = request.params.arguments?.iconId as string;
      if (!iconId) {
        throw new Error('Icon ID is required');
      }
      
      const iconInfo = await fetchFromSakuraCloud(`/icon/${iconId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(iconInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_note_list') {
    try {
      validateCredentials();
      
      const noteList = await fetchFromSakuraCloud(`/note`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(noteList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_note_info') {
    try {
      validateCredentials();
      
      const noteId = request.params.arguments?.noteId as string;
      if (!noteId) {
        throw new Error('Note ID is required');
      }
      
      const noteInfo = await fetchFromSakuraCloud(`/note/${noteId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(noteInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_sshkey_list') {
    try {
      validateCredentials();
      
      const sshkeyList = await fetchFromSakuraCloud(`/sshkey`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(sshkeyList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_sshkey_info') {
    try {
      validateCredentials();
      
      const sshkeyId = request.params.arguments?.sshkeyId as string;
      if (!sshkeyId) {
        throw new Error('SSH Key ID is required');
      }
      
      const sshkeyInfo = await fetchFromSakuraCloud(`/sshkey/${sshkeyId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(sshkeyInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_region_list') {
    try {
      validateCredentials();
      
      const regionList = await fetchFromSakuraCloud(`/region`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(regionList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_region_info') {
    try {
      validateCredentials();
      
      const regionId = request.params.arguments?.regionId as string;
      if (!regionId) {
        throw new Error('Region ID is required');
      }
      
      const regionInfo = await fetchFromSakuraCloud(`/region/${regionId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(regionInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_zone_list') {
    try {
      validateCredentials();
      
      const zoneList = await fetchFromSakuraCloud(`/zone`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(zoneList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_zone_info') {
    try {
      validateCredentials();
      
      const zoneId = request.params.arguments?.zoneId as string;
      if (!zoneId) {
        throw new Error('Zone ID is required');
      }
      
      const zoneInfo = await fetchFromSakuraCloud(`/zone/${zoneId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(zoneInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_product_info') {
    try {
      validateCredentials();
      
      const productType = request.params.arguments?.productType as string;
      if (!productType) {
        throw new Error('Product type is required');
      }
      
      // Validate product type
      if (!['server', 'disk', 'internet', 'license'].includes(productType)) {
        throw new Error('Invalid product type. Must be one of: server, disk, internet, license');
      }
      
      const productInfo = await fetchFromSakuraCloud(`/product/${productType}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(productInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_commonserviceitem_list') {
    try {
      validateCredentials();
      
      const commonServiceItemList = await fetchFromSakuraCloud(`/commonserviceitem`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(commonServiceItemList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_commonserviceitem_info') {
    try {
      validateCredentials();
      
      const itemId = request.params.arguments?.itemId as string;
      if (!itemId) {
        throw new Error('Common Service Item ID is required');
      }
      
      const itemInfo = await fetchFromSakuraCloud(`/commonserviceitem/${itemId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(itemInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_license_list') {
    try {
      validateCredentials();
      
      const licenseList = await fetchFromSakuraCloud(`/license`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(licenseList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_license_info') {
    try {
      validateCredentials();
      
      const licenseId = request.params.arguments?.licenseId as string;
      if (!licenseId) {
        throw new Error('License ID is required');
      }
      
      const licenseInfo = await fetchFromSakuraCloud(`/license/${licenseId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(licenseInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_bill_info') {
    try {
      validateCredentials();
      
      const year = request.params.arguments?.year as string;
      const month = request.params.arguments?.month as string;
      
      if (!year || !month) {
        throw new Error('Year and month are required for billing information');
      }
      
      const billInfo = await fetchFromSakuraCloud(`/bill/${year}${month}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(billInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_bill_detail') {
    try {
      validateCredentials();
      
      const year = request.params.arguments?.year as string;
      const month = request.params.arguments?.month as string;
      
      if (!year || !month) {
        throw new Error('Year and month are required for billing details');
      }
      
      const billDetailInfo = await fetchFromSakuraCloud(`/bill/${year}${month}/detail`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(billDetailInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_coupon_info') {
    try {
      validateCredentials();
      
      const couponId = request.params.arguments?.couponId as string;
      if (!couponId) {
        throw new Error('Coupon ID is required');
      }
      
      const couponInfo = await fetchFromSakuraCloud(`/coupon/${couponId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(couponInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_privatehost_info') {
    try {
      validateCredentials();
      
      const privateHostId = request.params.arguments?.privateHostId as string;
      if (!privateHostId) {
        throw new Error('Private Host ID is required');
      }
      
      const privateHostInfo = await fetchFromSakuraCloud(`/privatehost/${privateHostId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(privateHostInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_public_price') {
    try {
      // No authentication needed for public price API
      const priceData = await fetchFromSakuraCloud('/public/price', true);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(priceData, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_apprun_list') {
    try {
      validateCredentials();
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const appRunList = await fetchFromAppRunAPI('/applications');
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(appRunList, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_apprun_info') {
    try {
      validateCredentials();
      
      const appId = request.params.arguments?.appId as string;
      if (!appId) {
        throw new Error('AppRun application ID is required');
      }
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const appRunInfo = await fetchFromAppRunAPI(`/applications/${appId}`);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(appRunInfo, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'create_apprun') {
    try {
      validateCredentials();
      
      const name = request.params.arguments?.name as string;
      const description = request.params.arguments?.description as string || '';
      const dockerImage = request.params.arguments?.dockerImage as string;
      const planId = request.params.arguments?.planId as string;
      const environment = request.params.arguments?.environment as Array<{key: string, value: string}> || [];
      
      if (!name || !dockerImage || !planId) {
        throw new Error('Name, Docker image, and plan ID are required');
      }
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      
      const createBody = {
        name: name,
        description: description,
        planId: planId,
        image: dockerImage,
        environment: environment.map(env => ({ key: env.key, value: env.value })),
      };
      
      const createResult = await fetchFromAppRunAPI('/applications', 'POST', createBody);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(createResult, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'delete_apprun') {
    try {
      validateCredentials();
      
      const appId = request.params.arguments?.appId as string;
      if (!appId) {
        throw new Error('AppRun application ID is required');
      }
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const deleteResult = await fetchFromAppRunAPI(`/applications/${appId}`, 'DELETE');
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(deleteResult, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'start_apprun') {
    try {
      validateCredentials();
      
      const appId = request.params.arguments?.appId as string;
      if (!appId) {
        throw new Error('AppRun application ID is required');
      }
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const startResult = await fetchFromAppRunAPI(`/applications/${appId}/start`, 'POST');
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(startResult, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'stop_apprun') {
    try {
      validateCredentials();
      
      const appId = request.params.arguments?.appId as string;
      if (!appId) {
        throw new Error('AppRun application ID is required');
      }
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const stopResult = await fetchFromAppRunAPI(`/applications/${appId}/stop`, 'POST');
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(stopResult, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'update_apprun') {
    try {
      validateCredentials();
      
      const appId = request.params.arguments?.appId as string;
      if (!appId) {
        throw new Error('AppRun application ID is required');
      }
      
      // Get current application data first
      const currentApp = await fetchFromAppRunAPI(`/applications/${appId}`);
      
      // Extract current values
      const currentName = currentApp.name || '';
      const currentDescription = currentApp.description || '';
      const currentPlanId = currentApp.planId || '';
      const currentDockerImage = currentApp.image || '';
      const currentEnvironment = currentApp.environment || [];
      
      // Get update values from request or use current values
      const name = request.params.arguments?.name as string || currentName;
      const description = request.params.arguments?.description as string || currentDescription;
      const planId = request.params.arguments?.planId as string || currentPlanId;
      const dockerImage = request.params.arguments?.dockerImage as string || currentDockerImage;
      const environment = request.params.arguments?.environment as Array<{key: string, value: string}> || 
        currentEnvironment.map((env: {Key: string, Value: string}) => ({ key: env.Key, value: env.Value }));
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      
      const updateBody = {
        name: name,
        description: description,
        planId: planId,
        image: dockerImage,
        environment: environment.map(env => ({ key: env.key, value: env.value })),
      };
      
      const updateResult = await fetchFromAppRunAPI(`/applications/${appId}`, 'PUT', updateBody);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(updateResult, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  } else if (request.params.name === 'get_apprun_logs') {
    try {
      validateCredentials();
      
      const appId = request.params.arguments?.appId as string;
      if (!appId) {
        throw new Error('AppRun application ID is required');
      }
      
      const offset = request.params.arguments?.offset as number || 0;
      const limit = request.params.arguments?.limit as number || 100;
      
      const zone = request.params.arguments?.zone as string || DEFAULT_ZONE;
      const logsQuery = `/applications/${appId}/logs?offset=${offset}&limit=${limit}`;
      const logs = await fetchFromAppRunAPI(logsQuery);
      
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(logs, null, 2)
          }
        ]
      };
    } catch (error) {
      console.error('Error calling tool:', error);
      throw error;
    }
  }
  
  throw new Error(`Tool not found: ${request.params.name}`);
});

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Sacloud MCP Server running on stdio");
}

main().catch((error) => {
  console.error("Fatal error in main():", error);
  process.exit(1);
});
```