Sprucely title background

MCP API

Tổng quan

Các MCP API của Sprucely.io mở nền tảng bảng điều khiển cho trợ lý AI và phần mềm bên thứ ba thông qua Model Context Protocol (MCP), một chuẩn mở để kết nối các mô hình AI với công cụ qua HTTP. Bất kỳ client tương thích MCP nào cũng có thể tạo bảng điều khiển được lưu trữ, liệt kê và xem chi tiết chúng, và bổ sung dữ liệu vào chúng theo cách lập trình. Các bảng điều khiển được tạo qua các API này thuộc về tài khoản của bạn và có thể được chia sẻ, nhúng hoặc chỉnh sửa thêm trong dịch vụ. Để nhúng các bảng điều khiển kết quả vào website của riêng bạn, xem ghi chú tích hợp dashboard đơn giản. Nếu bạn dùng Claude, cách nhanh nhất để bắt đầu là trình kết nối Sprucely.io.

Kết nối

Máy chủ MCP được phục vụ qua Streamable HTTP tại:

https://www.sprucely.io/mcp

Bất kỳ client MCP nào cũng có thể kết nối tới điểm cuối này. Ví dụ, một lệnh duy nhất đăng ký máy chủ trong Claude Code:

claude mcp add --transport http sprucely https://www.sprucely.io/mcp

Bạn cũng có thể gọi trực tiếp máy chủ bằng JSON-RPC 2.0 qua HTTP. Hầu hết các client MCP tự thực hiện quy trình bắt tay giao thức; yêu cầu bên dưới liệt kê các công cụ khả dụng bằng một khóa API:

curl -X POST https://www.sprucely.io/mcp \
  -H "Authorization: Bearer spr_mcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Xác thực

Các yêu cầu được ủy quyền bằng header Authorization Bearer tiêu chuẩn. Hai loại thông tin xác thực được hỗ trợ.

Khóa API - Tạo khóa API trong mục MCP của hồ sơ bạn. Khóa bắt đầu bằng spr_mcp_, chỉ hiển thị một lần khi tạo, và có thể thu hồi bất cứ lúc nào. Dùng chúng cho script, máy chủ và các client MCP không có giao diện.

OAuth 2.1 - Các client MCP tương tác có thể thay vào đó để người dùng đăng nhập bằng tài khoản Sprucely.io của họ qua OAuth 2.1. Máy chủ ủy quyền hỗ trợ luồng authorization code với PKCE (bắt buộc), refresh token và đăng ký client động, nên các client tương thích tự cấu hình từ resource metadata:

https://www.sprucely.io/.well-known/oauth-protected-resource

Các scope khả dụng: openid, offline_access, dashboards:read và dashboards:write. Các scope được áp dụng theo từng công cụ: create_dashboard, add_dataset_sharing yêu cầu dashboards:write và sẽ trả về lỗi nếu thiếu. Các công cụ còn lại chỉ cần dashboards:read.

Đối với các client cần cấu hình thủ công, các điểm cuối của máy chủ ủy quyền là:

  • https://www.sprucely.io/oauth/.well-known/openid-configuration - metadata của máy chủ ủy quyền
  • https://www.sprucely.io/oauth/auth - điểm cuối ủy quyền (yêu cầu PKCE)
  • https://www.sprucely.io/oauth/token - điểm cuối token
  • https://www.sprucely.io/oauth/reg - đăng ký client động
  • https://www.sprucely.io/oauth/jwks - khóa ký (JWKS)
  • https://www.sprucely.io/oauth/token/revocation - thu hồi token
  • https://www.sprucely.io/oauth/token/introspection - kiểm tra token

Công cụ

Máy chủ MCP cung cấp tám công cụ: create_dashboard, get_dashboard, list_dashboards, add_data, get_dataset_schema, set_sharing, get_embed_codestorage_status.

Các tham số dataset và dashboard bên dưới không phải một định dạng riêng cho MCP - đó chính xác là cùng một JSON dataset/dashboard được trình bày trên trang Data Format và được dùng ở mọi nơi khác trong dịch vụ (API nhập dữ liệu của runtime nhúng độc lập, các bố cục do AI tạo, và trình chỉnh sửa dashboard), nên bất cứ điều gì được viết theo tài liệu tham khảo đó cũng áp dụng ở đây.

create_dashboard - Tạo một dashboard được lưu trữ từ một dataset nội tuyến và một cây widget, rồi trả về liên kết xem và liên kết nhúng. Tham số:

  • name - tiêu đề dashboard (bắt buộc)
  • dataset - dataset cần trực quan hóa: name, headers (tên cột), types (một kiểu database cho mỗi header - VARCHAR, BOOLEAN, INTEGER, BIGINT, FLOAT, DOUBLE, DATE hoặc TIMESTAMP) và entries (các dòng, mỗi dòng là một mảng giá trị theo thứ tự header), tối đa 100 cột và 50.000 dòng dữ liệu thô, cấp bản ghi mỗi lệnh gọi (bắt buộc). Entries không được tổng hợp trước: gửi một dòng cho mỗi bản ghi gốc, và để dataFunction của từng biểu đồ tính số lượng, tổng, trung bình, v.v. tại thời điểm hiển thị.
  • dashboard - từ 1 đến 40 widget cấp cao nhất, từ trên xuống dưới (bắt buộc). Mỗi widget là một dash_chart (một loại biểu đồ - area, bar, cell, dot, hexbin hoặc line - ánh xạ cột cho x, y, dr, một dataFunction tùy chọn và một tiêu đề tùy chọn), một dash_table, một khối dash_text, một dash_spacer, hoặc một container dash_stacker_hor/dash_stacker_ver. Các stacker lồng nhau đệ quy - children của một stacker có thể chứa thêm các stacker khác - để sắp xếp widget thành hàng và cột với độ sâu bất kỳ. Loại cột nào (phân loại, liên tục hoặc ngày/giờ) mà các chiều x/y/d/r của mỗi loại biểu đồ chấp nhận, và cách phân khoảng thời gian một cột ngày tháng bằng seasonX/seasonY biến nó thành phân loại, được trình bày trên từng trường qua tools/list và trên trang Data Format.
  • theme - màu sắc tùy chọn áp dụng cho toàn bộ dashboard (nền, chữ, các màu nhấn chính/phụ/nhạt); mỗi widget vẫn có thể ghi đè màu hoặc nền riêng của nó
  • shared - dashboard có xem được với bất kỳ ai có liên kết hay không (tùy chọn, mặc định false). Dashboard mới ở chế độ riêng tư cho đến khi bạn đặt giá trị này thành true hoặc gọi set_sharing sau đó.

Kết quả trả về mang theo dashboardIddatasetId của dashboard mới (cần cho add_data, get_dataset_schema, set_sharingget_embed_code sau đó), cùng với url, viewUrl và đoạn mã nhúng iframe. Ví dụ - tạo một dashboard với một biểu đồ cột và một màu nhấn áp dụng cho toàn bộ dashboard:

curl -X POST https://www.sprucely.io/mcp \
  -H "Authorization: Bearer spr_mcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "create_dashboard",
      "arguments": {
        "name": "Regional Sales",
        "dataset": {
          "name": "Sales",
          "headers": ["region", "revenue"],
          "types": ["VARCHAR", "DOUBLE"],
          "entries": [
            ["North", 1250.5],
            ["South", 980.25],
            ["East", 1420.0]
          ]
        },
        "dashboard": {
          "type": "dash",
          "children": [
            { "type": "dash_chart", "chartType": "bar", "x": "region", "d": "revenue", "dataFunction": "sum", "title": "Revenue by region" }
          ]
        },
        "theme": { "themePrimary": "#6E2BDC" }
      }
    }
  }'

# Result (result.structuredContent in the JSON-RPC response):
{
  "dashboardId": "dash_a1b2c3d4",
  "datasetId": "data_e5f6g7h8",
  "name": "Regional Sales",
  "shared": false,
  "rows": 3,
  "columns": 2,
  "url": "https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4",
  "viewUrl": "https://www.sprucely.io/service/dashboards/view/123/dash_a1b2c3d4",
  "iframe": "<iframe src=\"https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4\" style=\"width:100%;height:640px;border:0\" title=\"Sprucely dashboard\" loading=\"lazy\"></iframe>"
}

get_dashboard - Trả về tên, trạng thái chia sẻ, ID dataset và các liên kết của một dashboard. Tham số: dashboardId (bắt buộc). Ví dụ:

curl -X POST https://www.sprucely.io/mcp \
  -H "Authorization: Bearer spr_mcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "get_dashboard",
      "arguments": {
        "dashboardId": "dash_a1b2c3d4"
      }
    }
  }'

# Result (result.structuredContent in the JSON-RPC response):
{
  "dashboardId": "dash_a1b2c3d4",
  "name": "Regional Sales",
  "shared": false,
  "archived": false,
  "datasetIds": ["data_e5f6g7h8"],
  "source": "mcp",
  "updatedAt": "2026-07-29T10:15:00.000Z",
  "url": "https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4",
  "viewUrl": "https://www.sprucely.io/service/dashboards/view/123/dash_a1b2c3d4",
  "iframe": "<iframe src=\"https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4\" style=\"width:100%;height:640px;border:0\" title=\"Sprucely dashboard\" loading=\"lazy\"></iframe>"
}

list_dashboards - Liệt kê các dashboard trong tài khoản của bạn, sắp xếp theo lần cập nhật gần nhất, mỗi dashboard kèm theo datasetIds riêng để một dataset có thể được chuyển thẳng cho get_dataset_schema hoặc add_data mà không cần gọi get_dashboard riêng. Tham số: limitoffset để phân trang, query để lọc theo tên không phân biệt chữ hoa/thường (đều tùy chọn). Ví dụ:

curl -X POST https://www.sprucely.io/mcp \
  -H "Authorization: Bearer spr_mcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 4,
    "method": "tools/call",
    "params": {
      "name": "list_dashboards",
      "arguments": {
        "limit": 10,
        "query": "sales"
      }
    }
  }'

# Result (result.structuredContent in the JSON-RPC response):
{
  "total": 1,
  "limit": 10,
  "offset": 0,
  "hasMore": false,
  "dashboards": [
    {
      "dashboardId": "dash_a1b2c3d4",
      "name": "Regional Sales",
      "shared": false,
      "datasetIds": ["data_e5f6g7h8"],
      "source": "mcp",
      "updatedAt": "2026-07-29T10:15:00.000Z",
      "url": "https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4",
      "viewUrl": "https://www.sprucely.io/service/dashboards/view/123/dash_a1b2c3d4",
      "iframe": "<iframe src=\"https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4\" style=\"width:100%;height:640px;border:0\" title=\"Sprucely dashboard\" loading=\"lazy\"></iframe>"
    }
  ]
}

add_data - Bổ sung entries vào dataset của một dashboard hiện có; mọi dashboard dùng dataset đó tự động làm mới. Tham số:

  • dashboardId - dashboard cần bổ sung dữ liệu vào (bắt buộc)
  • entries - các dòng khớp theo vị trí với header của dataset, tối đa 50.000 dòng mỗi lệnh gọi (bắt buộc) - áp dụng cùng quy tắc dữ liệu thô, cấp bản ghi như create_dashboard. Gọi get_dataset_schema trước nếu bạn chưa biết chính xác tên/thứ tự cột của dashboard. Dùng nó để nạp các dataset lớn theo từng lô, hoặc để giữ dashboard luôn cập nhật.
  • run_id - một khóa idempotency tùy chọn cho riêng lô này (tùy chọn). Nếu một lệnh gọi add_data trước đó với cùng dashboardIdrun_id đã thành công, gọi lại sẽ trả về kết quả trước đó thay vì bổ sung các dòng đó thêm một lần nữa, nên một lô có thể được thử lại an toàn sau khi hết thời gian chờ hoặc mất kết nối - dùng một run_id mới cho mỗi lô riêng biệt (ví dụ một UUID hoặc một hash của nội dung lô đó).

Ví dụ:

curl -X POST https://www.sprucely.io/mcp \
  -H "Authorization: Bearer spr_mcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 5,
    "method": "tools/call",
    "params": {
      "name": "add_data",
      "arguments": {
        "dashboardId": "dash_a1b2c3d4",
        "entries": [
          ["West", 875.0]
        ],
        "run_id": "batch-2026-07-29T10:20:00Z"
      }
    }
  }'

# Result (result.structuredContent in the JSON-RPC response):
{
  "dashboardId": "dash_a1b2c3d4",
  "datasetId": "data_e5f6g7h8",
  "addedRows": 1,
  "url": "https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4",
  "viewUrl": "https://www.sprucely.io/service/dashboards/view/123/dash_a1b2c3d4",
  "iframe": "<iframe src=\"https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4\" style=\"width:100%;height:640px;border:0\" title=\"Sprucely dashboard\" loading=\"lazy\"></iframe>"
}
# Calling again later with the same dashboardId + run_id (e.g. after a dropped
# connection) is safe: the rows are not appended twice, and the response also
# carries "duplicate": true instead of appending again.

get_dataset_schema - Trả về tên và kiểu các cột của một dataset. Dùng công cụ này trước khi gọi add_data (hoặc dựng một biểu đồ mới trên cùng dataset) bất cứ khi nào tên/thứ tự/kiểu cột chính xác chưa được biết trước, ví dụ trong một phiên làm việc mới hoặc khi một tác nhân khác đã tạo dashboard đó. Tham số: datasetId (bắt buộc). Ví dụ:

curl -X POST https://www.sprucely.io/mcp \
  -H "Authorization: Bearer spr_mcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 6,
    "method": "tools/call",
    "params": {
      "name": "get_dataset_schema",
      "arguments": {
        "datasetId": "data_e5f6g7h8"
      }
    }
  }'

# Result (result.structuredContent in the JSON-RPC response):
{
  "datasetId": "data_e5f6g7h8",
  "headers": ["region", "revenue"],
  "types": ["VARCHAR", "DOUBLE"]
}

set_sharing - Bật hoặc tắt liên kết công khai của một dashboard. Tắt liên kết sẽ thu hồi quyền truy cập cho mọi phiên bản trước đó của dashboard, nên một liên kết đã từng được chia sẻ trước đây sẽ ngừng hoạt động. Tham số: dashboardIdshared (đều bắt buộc). Ví dụ:

curl -X POST https://www.sprucely.io/mcp \
  -H "Authorization: Bearer spr_mcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 7,
    "method": "tools/call",
    "params": {
      "name": "set_sharing",
      "arguments": {
        "dashboardId": "dash_a1b2c3d4",
        "shared": true
      }
    }
  }'

# Result (result.structuredContent in the JSON-RPC response):
{
  "dashboardId": "dash_a1b2c3d4",
  "shared": true,
  "url": "https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4",
  "viewUrl": "https://www.sprucely.io/service/dashboards/view/123/dash_a1b2c3d4",
  "iframe": "<iframe src=\"https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4\" style=\"width:100%;height:640px;border:0\" title=\"Sprucely dashboard\" loading=\"lazy\"></iframe>"
}

get_embed_code - Trả về liên kết xem có thể chia sẻ và đoạn mã nhúng iframe cho một dashboard - cùng liên kết/mã nhúng mà create_dashboardset_sharing đã trả về, dùng khi cần lấy lại chúng một cách riêng lẻ. Liên kết chỉ hoạt động với người khác khi dashboard đang ở chế độ chia sẻ. Tham số: dashboardId (bắt buộc). Ví dụ:

curl -X POST https://www.sprucely.io/mcp \
  -H "Authorization: Bearer spr_mcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 8,
    "method": "tools/call",
    "params": {
      "name": "get_embed_code",
      "arguments": {
        "dashboardId": "dash_a1b2c3d4"
      }
    }
  }'

# Result (result.structuredContent in the JSON-RPC response):
{
  "dashboardId": "dash_a1b2c3d4",
  "shared": true,
  "url": "https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4",
  "viewUrl": "https://www.sprucely.io/service/dashboards/view/123/dash_a1b2c3d4",
  "iframe": "<iframe src=\"https://www.sprucely.io/service/dashboards/embed/123/dash_a1b2c3d4\" style=\"width:100%;height:640px;border:0\" title=\"Sprucely dashboard\" loading=\"lazy\"></iframe>"
}

storage_status - Báo cáo dung lượng lưu trữ tài khoản đã dùng và còn lại, hữu ích trước một lệnh gọi create_dashboard hoặc add_data đủ lớn để có nguy cơ vượt hạn mức lưu trữ của gói dịch vụ. Không có tham số. Ví dụ:

curl -X POST https://www.sprucely.io/mcp \
  -H "Authorization: Bearer spr_mcp_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 9,
    "method": "tools/call",
    "params": {
      "name": "storage_status",
      "arguments": {}
    }
  }'

# Result (result.structuredContent in the JSON-RPC response):
{
  "used": 5242880,
  "limit": 104857600,
  "percent": 5,
  "plan": "Regular",
  "over": 0,
  "blocked": false
}

Giới hạn và lỗi

  • Điểm cuối MCP chấp nhận 25 yêu cầu mỗi phút cho mỗi client và nội dung yêu cầu tối đa 25 MB - hãy nạp các dataset lớn hơn theo từng lô add_data.
  • Dataset chấp nhận tối đa 100 cột và 50.000 dòng mỗi lệnh gọi, và một dashboard chấp nhận tối đa 40 widget ở mỗi cấp lồng nhau. Các dashboard đã lưu trữ được tính vào hạn mức lưu trữ của gói dịch vụ bạn dùng - gọi storage_status để kiểm tra dung lượng còn lại trước một lệnh gọi create_dashboard hoặc add_data lớn.
  • Các mã trạng thái HTTP tiêu chuẩn được sử dụng: 401 khi thiếu hoặc sai thông tin xác thực (kèm một thách thức WWW-Authenticate trỏ đến resource metadata), 403 khi thông tin xác thực đã bị thu hồi hoặc không đủ quyền, 413 khi yêu cầu quá lớn và 429 khi bị giới hạn tần suất.