Etsy MCP Server

Etsy MCP Server

An MCP server for interacting with the Etsy API, enabling listing management, shop information, shipping profiles, and image uploads.

Category
访问服务器

README

Etsy MCP Server

An MCP (Model Context Protocol) server for interacting with the Etsy API. This service handles authentication, API calls to Etsy for managing listings, shop details, shipping profiles, and image uploads.

Overview

This service provides a set of tools accessible via the Model Context Protocol (MCP) to interact with the Etsy V3 API. It manages the OAuth 2.0 authentication flow (including PKCE token refresh), stores tokens securely, and exposes functionalities like creating listings, fetching shop data, managing shipping profiles, and uploading images. The goal is to simplify interactions with the Etsy API for MCP-compatible clients.

This MCP server is primarily designed for development and tool integration. Please ensure you comply with Etsy's API Terms of Use.

Features

  • 🔑 OAuth2 Authentication: Handles the complete Etsy OAuth2 flow with PKCE.
  • 🛍️ Listing Management: Create, and retrieve Etsy listings.
  • ℹ️ Shop Information: Fetch details for your Etsy shop.
  • 📦 Shipping Profiles: List and create shipping profiles for your shop.
  • 🖼️ Image Uploads: Upload images and associate them with your listings.
  • 🔧 Default Shop Management: Set and get a default shop for easier multi-shop use.
  • 🔒 Secure Token Storage: Persists OAuth tokens securely.

Installation

Prerequisites

  • Node.js (version 18.0.0 or higher recommended - see package.json engines)
  • npm (usually comes with Node.js) or yarn

Manual Installation

  1. Clone the repository (replace with your repository URL if you host it on GitHub/GitLab etc.):

    git clone <your-repository-url>
    cd etsy-mcp
    

    (If you're working locally, you can skip the clone and just cd into the project directory.)

  2. Install dependencies:

    npm install
    

    Or if you use yarn:

    yarn install
    
  3. Configure Environment Variables: Copy the .env.example file to a new file named .env:

    cp .env.example .env
    

    Then, open .env and fill in your Etsy App credentials:

    ETSY_API_KEY=YOUR_ETSY_APP_API_KEY
    ETSY_CLIENT_SECRET=YOUR_ETSY_APP_CLIENT_SECRET
    # Optional: define a specific host and port for the OAuth callback redirect URI
    # ETSY_MCP_HOST=localhost
    # ETSY_MCP_OAUTH_PORT=3003
    # ETSY_MCP_REDIRECT_URI=http://localhost:3003/oauth/callback
    # Optional: define a custom path for token storage and logs
    # ETSY_MCP_TOKEN_PATH=/path/to/your/token_storage_directory
    # ETSY_MCP_LOG_PATH=/path/to/your/logs_directory
    # Optional: Your default shipping profile ID for physical items
    # SHIPPING_PROFILE_ID=YOUR_DEFAULT_SHIPPING_PROFILE_ID
    

    Note: The REDIRECT_URI in your .env file (or the default http://localhost:3003/oauth/callback) must match one of the redirect URIs configured for your Etsy App.

Usage

Run the Service

  • For production/built version:
    npm run build
    npm start
    
  • For development with auto-reload:
    npm run dev
    

This will launch the server, which listens for MCP commands, typically via standard input/output.

Use in Cursor IDE (or other MCP Clients)

To use this Etsy MCP server with an MCP client like Cursor IDE, you'll typically provide a JSON configuration.

In Cursor settings, navigate to the MCP tab, click "+ Add new global MCP server", and input:

{
    "mcpServers": {
        "Etsy MCP": {
            "command": "npm",
            "args": ["run", "dev"],
            "env": {
                "ETSY_API_KEY": "YOUR_ETSY_API_KEY_HERE",
                "ETSY_CLIENT_SECRET": "YOUR_ETSY_CLIENT_SECRET_HERE"
                // Add other ENV VARS from your .env if needed, e.g., REDIRECT_URI
                // "REDIRECT_URI": "http://localhost:3003/oauth/callback"
                // "SHIPPING_PROFILE_ID": "YOUR_DEFAULT_SHIPPING_PROFILE_ID_HERE"
            },
            "cwd": "/Users/name/Desktop/repos/ai gemini apps/etsy_api/etsy-mcp" // IMPORTANT: Update this to the correct absolute path of your project
        }
    }
}

Key points for the client configuration:

  • command & args: The example uses npm run dev for development. For a production setup, you might use npm start (which implies npm run build first if not already built).
  • env:
    • Replace YOUR_ETSY_API_KEY_HERE and YOUR_ETSY_CLIENT_SECRET_HERE with your actual credentials if you don't want to rely on the .env file being picked up by the npm run dev script's environment. It's generally better to let the server pick up credentials from its .env file. The example above is for overriding or ensuring they are set for the client's execution context.
  • cwd: Crucially, update this to the absolute path where your etsy-mcp project is located on your machine.
  • The tools array can also be defined here, but the server itself reports its capabilities, so it's often not strictly needed in the client-side static configuration if the client can dynamically fetch them.

API Reference

The service provides the following MCP tools. Parameters are based on Zod schemas defined in the server.

authenticate()

Initiates the OAuth2 authentication flow with Etsy.

  • Description: Starts the authentication process. The server will return a URL that you need to open in a browser to grant access to your Etsy account.
  • Parameters: None.
  • Returns:
{
  "content": [
    {
      "type": "text",
      "text": "Please visit this URL to authorize the application: https://www.etsy.com/oauth/connect?response_type=code&client_id=YOUR_API_KEY...\nComplete the process in your browser. You can then use other tools."
    }
  ]
}

set_default_shop()

Fetches your Etsy shops and sets the first one found as the default for this session.

  • Description: After successful authentication, use this tool to select a default shop. If you have multiple shops, it will automatically use the first one returned by Etsy. This default shop will be used by other tools unless a shop_id is explicitly provided to them.
  • Parameters: None.
  • Returns:
{
  "content": [
    {
      "type": "text",
      "text": "Default shop set to: YourShopName (ID: 12345678). Other tools will now use this shop unless a specific shop_id is provided."
    }
  ]
}

Or if no shops are found:

{
  "content": [
    {
      "type": "text",
      "text": "No shops found for your Etsy account."
    }
  ]
}

get_default_shop()

Gets the currently configured default Etsy shop ID and name.

  • Description: Use this to check which shop is currently set as the default.
  • Parameters: None.
  • Returns:
{
  "content": [
    {
      "type": "text",
      "text": "Current default shop: YourShopName (ID: 12345678)"
    }
  ]
}

Or if no default shop is set:

{
  "content": [
    {
      "type": "text",
      "text": "No default shop is currently set. Please run the `set_default_shop` tool after authenticating."
    }
  ]
}

get_listings(shop_id?: number)

Get all active listings for a shop.

  • Parameters:
    • shop_id (number, optional): The ID of the shop. If not provided, uses the default shop.
  • Returns:
{
  "content": [
    {
      "type": "text",
      "text": "{\n  \"count\": 1,\n  \"results\": [\n    {\n      \"listing_id\": 123456789,\n      \"user_id\": 98765432,\n      \"shop_id\": 12345678,\n      \"title\": \"Handmade Ceramic Mug\",\n      \"description\": \"A beautiful handmade ceramic mug...\",\n      \"state\": \"active\",\n      \"price\": { \"amount\": 2500, \"divisor\": 100, \"currency_code\": \"USD\" },\n      \"quantity\": 5,\n      /* ... other listing fields ... */\n    }\n  ]\n}"
    }
  ]
}

get_shop_details(shop_id?: number)

Get details for a specific shop.

  • Parameters:
    • shop_id (number, optional): The ID of the shop. If not provided, uses the default shop.
  • Returns:
{
  "content": [
    {
      "type": "text",
      "text": "{\n  \"shop_id\": 12345678,\n  \"shop_name\": \"YourShopName\",\n  \"user_id\": 98765432,\n  \"title\": \"Unique Handmade Goods\",\n  \"status\": \"active\",\n  /* ... other shop fields ... */\n}"
    }
  ]
}

create_listing(shop_id?: number, listing_data: object)

Creates a new Etsy listing.

  • Description: For physical items, ensure you have a shipping_profile_id. To add images, create the listing first, then use the upload_listing_image tool with the returned listing_id.
  • Parameters:
    • shop_id (number, optional): The ID of the shop. If not provided, uses the default shop.
    • listing_data (object):
      • title (string): Listing title.
      • description (string): Listing description.
      • price (number): Listing price (e.g., 25.99).
      • quantity (number): Available quantity.
      • who_made (string): e.g., 'i_did', 'collective', 'someone_else'.
      • when_made (string): e.g., 'made_to_order', '2020_2024', '1950_1959'.
      • taxonomy_id (number): The numeric ID of the listing's category.
      • shipping_profile_id (number, optional): The numeric ID of the shipping profile. Required if type is 'physical'.
      • type (enum: "physical", "digital", "download"): Listing type.
  • Returns:
{
  "content": [
    {
      "type": "text",
      "text": "{\n  \"listing_id\": 123456790,\n  \"user_id\": 98765432,\n  \"shop_id\": 12345678,\n  \"title\": \"New Awesome Product\",\n  /* ... other fields of the newly created listing ... */\n}"
    }
  ]
}

list_shop_shipping_profiles(shop_id?: number)

Lists all shipping profiles for a given shop.

  • Parameters:
    • shop_id (number, optional): The ID of the shop. If not provided, uses the default shop.
  • Returns:
{
  "content": [
    {
      "type": "text",
      "text": "{\n  \"count\": 1,\n  \"results\": [\n    {\n      \"shipping_profile_id\": 7654321,\n      \"title\": \"Standard US Shipping\",\n      \"origin_country_iso\": \"US\",\n      /* ... other shipping profile fields ... */\n    }\n  ]\n}"
    }
  ]
}

create_shop_shipping_profile(shop_id?: number, title: string, origin_country_iso: string, primary_cost: number, secondary_cost: number, min_processing_time: number, max_processing_time: number, destination_country_iso?: string, destination_region?: string)

Creates a new shipping profile for a shop.

  • Parameters:
    • shop_id (number, optional): The ID of the shop. If not provided, uses the default shop.
    • title (string): A title for the shipping profile (e.g., 'US Standard').
    • origin_country_iso (string, length 2): ISO code of the origin country (e.g., 'US').
    • primary_cost (number, min 0): Cost of shipping to this destination alone.
    • secondary_cost (number, min 0): Cost of shipping with another item.
    • min_processing_time (integer, min 1): Minimum days to process the order.
    • max_processing_time (integer, min 1): Maximum days to process the order.
    • destination_country_iso (string, length 2, optional): ISO code for a specific destination country.
    • destination_region (enum: "eu", "non_eu", "none", optional): A specific destination region. (Note: Either destination_country_iso OR destination_region must be provided, but not both.)
  • Returns:
{
  "content": [
    {
      "type": "text",
      "text": "{\n  \"shipping_profile_id\": 7654322,\n  \"title\": \"New Express Profile\",\n  /* ... other fields of the newly created shipping profile ... */\n}"
    }
  ]
}

upload_listing_image(shop_id?: number, listing_id: number, file_name: string, image_name?: string)

Uploads an image from a predefined local server directory and associates it with an Etsy listing.

  • Description: After creating a listing, use this tool to upload images. Images must be placed in the public/uploads/listing_images directory on the server (relative to the project root).
  • Parameters:
    • shop_id (number, optional): Shop ID. Uses default if not provided.
    • listing_id (integer): The ID of the listing to add the image to.
    • file_name (string): The name of the image file (e.g., 'my_image.jpg') located in the server's public/uploads/listing_images directory.
    • image_name (string, optional): The desired filename for the image on Etsy. Defaults to file_name if not provided.
  • Returns:
{
  "content": [
    {
      "type": "text",
      "text": "{\n  \"listing_image_id\": 987654321,\n  \"listing_id\": 123456790,\n  \"hex_code\": \"f1e2d3\",\n  \"url_75x75\": \"https://.../75x75.jpg\",\n  /* ... other image details ... */\n}"
    }
  ]
}

How It Works

  1. Client Request: An MCP client sends a tool call request to this server (e.g., via stdio when run locally).
  2. Authentication Check: For tools requiring authentication, the server checks for a valid OAuth token using TokenStorage.
  3. OAuth Flow (if needed): a. If no valid token exists, the authenticate tool is typically invoked by the client (or instructed by the server). b. The EtsyMCPServer calls the OAuthServer to generate an Etsy authorization URL (using PKCE). c. The user opens this URL in a browser and authorizes the application. d. Etsy redirects to the OAuthServer's callback endpoint with an authorization code. e. The OAuthServer exchanges the code for an access token and refresh token using the PKCE code verifier. f. Tokens (including user_id and potentially default shop_id and shop_name) are saved by TokenStorage.
  4. API Call: The EtsyMCPServer uses the EtsyApiClient (which holds the access token) to make the requested API call to the Etsy V3 API.
  5. Token Refresh: If an access token is expired, getValidAccessToken() in EtsyMCPServer attempts to use the refresh token to get a new access token.
  6. Response: The response from the Etsy API is processed and returned to the MCP client in the standard MCP format.

Troubleshooting

  • Authentication Errors / Invalid Grant:
    • Ensure your ETSY_API_KEY, ETSY_CLIENT_SECRET in .env are correct.
    • Verify that the REDIRECT_URI used by the server (default http://localhost:3003/oauth/callback or as set in .env) exactly matches one of the "Callback URLs" configured in your Etsy App settings.
    • Stale tokens: Try clearing tokens.json from your token storage path (see TokenStorage.ts or your ETSY_MCP_TOKEN_PATH env var) and re-authenticating.
  • EADDRINUSE for OAuth Server: This means the port (default 3003) for the OAuth callback server is already in use. Stop the other process or configure a different ETSY_MCP_OAUTH_PORT in your .env file and update your Etsy App's redirect URI accordingly.
  • File Not Found for Image Upload: Ensure the file_name provided to upload_listing_image exists within the public/uploads/listing_images/ directory relative to your project root.
  • Log Files: Check the log files generated in the logs directory (or ETSY_MCP_LOG_PATH) for detailed error messages. Each run creates a timestamped log file.

License

MIT License (Please create a LICENSE file with the MIT License text if you choose this license, or specify another.)

Sponsors

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选