Connect

Build your own client

Use the official MCP SDKs or the MCP connectors of the Anthropic and OpenAI APIs.

With this server, the TypeScript SDK's Client.callTool and the Python SDK's call_tool return successes and errors without raising -32602. Filmo checked it with @modelcontextprotocol/sdk 1.26.0 and 1.32.1, @modelcontextprotocol/client 2.3.1 and mcp 2.3.0 and 1.27.1. In the 2.x TypeScript client Client and StreamableHTTPClientTransport keep their names and arguments; only the package and the import change, so take the import from that package's documentation. The example below is the 1.x one. How to read an error is in Errors.

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const transport = new StreamableHTTPClientTransport(new URL("https://app.filmo.io/api/v1/mcp"), {
  requestInit: { headers: { Authorization: `Bearer ${process.env.FILMO_API_KEY}` } },
});
const client = new Client({ name: "my-agent", version: "1.0.0" });
await client.connect(transport);

const result = await client.callTool({ name: "filmo_orders_list", arguments: { limit: 20 } });
if (result.isError) {
  // A tool error: the problem is JSON in the first text block, and there is no structuredContent.
  const problem = JSON.parse((result.content as { text: string }[])[0].text);
  console.error(problem.code, problem.detail);
} else {
  console.log(result.structuredContent); // { data, meta }
}

The 2.x packages of both SDKs (@modelcontextprotocol/client, mcp 2.x with result.is_error and httpx2) have a different API; the server's contract is the same.

Both APIs accept a remote MCP server. The lists below come from the catalogue: the read tools of the recommended preset, and the tools that need human confirmation.

{
  "mcp_servers": [
    {
      "type": "url",
      "url": "https://app.filmo.io/api/v1/mcp",
      "name": "filmo",
      "authorization_token": "<FILMO_API_KEY>"
    }
  ],
  "tools": [
    {
      "type": "mcp_toolset",
      "mcp_server_name": "filmo",
      "default_config": {
        "enabled": false
      },
      "configs": {
        "filmo_items_list": {
          "enabled": true
        },
        "filmo_items_get": {
          "enabled": true
        },
        "filmo_availability_check": {
          "enabled": true
        },
        "filmo_serialized_items_list": {
          "enabled": true
        },
        "filmo_serialized_items_get": {
          "enabled": true
        },
        "filmo_spaces_list": {
          "enabled": true
        },
        "filmo_spaces_get": {
          "enabled": true
        },
        "filmo_vehicles_list": {
          "enabled": true
        },
        "filmo_vehicles_get": {
          "enabled": true
        },
        "filmo_staff_list": {
          "enabled": true
        },
        "filmo_staff_get": {
          "enabled": true
        },
        "filmo_staff_availability_check": {
          "enabled": true
        },
        "filmo_vehicles_availability_check": {
          "enabled": true
        },
        "filmo_kits_list": {
          "enabled": true
        },
        "filmo_kits_get": {
          "enabled": true
        },
        "filmo_planner_services_list": {
          "enabled": true
        },
        "filmo_schedule_get": {
          "enabled": true
        },
        "filmo_unavailabilities_list": {
          "enabled": true
        },
        "filmo_planner_resources_list": {
          "enabled": true
        },
        "filmo_account_get": {
          "enabled": true
        }
      }
    }
  ]
}

Anthropic needs the anthropic-beta: mcp-client-2025-11-20 header, and authorization_token is the Bearer token. OpenAI documents no header field of its own, only authorization. With OpenAI, require_approval with never for the read tools alone leaves everything else asking for approval.

Tools that need human confirmation (for your approval list)
[
  "filmo_contacts_delete",
  "filmo_contacts_update",
  "filmo_contacts_address_delete",
  "filmo_contacts_related_remove",
  "filmo_items_delete",
  "filmo_spaces_delete",
  "filmo_spaces_amenities_replace",
  "filmo_vehicles_delete",
  "filmo_staff_delete",
  "filmo_tags_delete",
  "filmo_tags_assignment_remove",
  "filmo_planner_assignment_remove",
  "filmo_unavailabilities_delete",
  "filmo_tasks_delete",
  "filmo_purchase_orders_receive",
  "filmo_repair_tickets_update",
  "filmo_treasury_payments_create",
  "filmo_orders_cancel",
  "filmo_items_accessories_update",
  "filmo_items_alternatives_update",
  "filmo_orders_line_items_return",
  "filmo_ai_ask",
  "filmo_workflows_run",
  "filmo_orders_unreserve",
  "filmo_projects_orders_unlink",
  "filmo_invoices_validate",
  "filmo_invoices_void",
  "filmo_credit_notes_validate",
  "filmo_credit_notes_void",
  "filmo_contracts_validate",
  "filmo_contracts_sign",
  "filmo_contracts_void",
  "filmo_contracts_cancel",
  "filmo_supplier_invoices_validate",
  "filmo_supplier_invoices_void"
]
Warning:

Do not paste the key into code or a file of the repository: read it from a secret store or the environment.

  • Introduction

    MCP quickstart

    Connect one assistant, check it with a read tool and choose the scopes it needs.

  • Access

    Authentication and permissions

    Authenticate with an API key in a header, or let the client sign in with OAuth 2.1. Either way the scopes decide which tools exist.

  • Guides

    Safe writes

    An assistant that can write can also write the wrong thing. Decide which tools need a person, retry without duplicating, and know what a write sets in motion.