Connect
Build your own client
Use the official MCP SDKs or the MCP connectors of the Anthropic and OpenAI APIs.
The official SDKs
Link to this section: The official SDKsWith this server, the TypeScript SDK's Client. and the Python SDK's call_tool return successes and errors without raising -32602. Filmo checked it with @modelcontextprotocol 1.26.0 and 1.32.1, @modelcontextprotocol 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 }
}import asyncio, json, os
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def main():
headers = {"Authorization": f"Bearer {os.environ['FILMO_API_KEY']}"}
async with streamablehttp_client("https://app.filmo.io/api/v1/mcp", headers=headers) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool("filmo_orders_list", arguments={"limit": 20})
if result.isError:
# A tool error: the problem is JSON in the first text block.
problem = json.loads(result.content[0].text)
print(problem["code"], problem["detail"])
else:
print(result.structuredContent) # {"data": ..., "meta": ...}
asyncio.run(main())The 2.x packages of both SDKs (@modelcontextprotocol, mcp 2.x with result. and httpx2) have a different API; the server's contract is the same.
The MCP connectors of the LLM APIs
Link to this section: The MCP connectors of the LLM APIsBoth 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
}
}
}
]
}{
"type": "mcp",
"server_label": "filmo",
"server_url": "https://app.filmo.io/api/v1/mcp",
"authorization": "<FILMO_API_KEY>",
"allowed_tools": [
"filmo_items_list",
"filmo_items_get",
"filmo_availability_check",
"filmo_serialized_items_list",
"filmo_serialized_items_get",
"filmo_spaces_list",
"filmo_spaces_get",
"filmo_vehicles_list",
"filmo_vehicles_get",
"filmo_staff_list",
"filmo_staff_get",
"filmo_staff_availability_check",
"filmo_vehicles_availability_check",
"filmo_kits_list",
"filmo_kits_get",
"filmo_planner_services_list",
"filmo_schedule_get",
"filmo_unavailabilities_list",
"filmo_planner_resources_list",
"filmo_account_get"
],
"require_approval": {
"never": {
"tool_names": [
"filmo_items_list",
"filmo_items_get",
"filmo_availability_check",
"filmo_serialized_items_list",
"filmo_serialized_items_get",
"filmo_spaces_list",
"filmo_spaces_get",
"filmo_vehicles_list",
"filmo_vehicles_get",
"filmo_staff_list",
"filmo_staff_get",
"filmo_staff_availability_check",
"filmo_vehicles_availability_check",
"filmo_kits_list",
"filmo_kits_get",
"filmo_planner_services_list",
"filmo_schedule_get",
"filmo_unavailabilities_list",
"filmo_planner_resources_list",
"filmo_account_get"
]
}
}
}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"
]Do not paste the key into code or a file of the repository: read it from a secret store or the environment.
Related pages
Link to this section: Related pagesIntroduction
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.
Was this page helpful?