# How to integrate Todoist MCP with OpenAI Agents SDK

```json
{
  "title": "How to integrate Todoist MCP with OpenAI Agents SDK",
  "toolkit": "Todoist",
  "toolkit_slug": "todoist",
  "framework": "OpenAI Agents SDK",
  "framework_slug": "open-ai-agents-sdk",
  "url": "https://composio.dev/toolkits/todoist/framework/open-ai-agents-sdk",
  "markdown_url": "https://composio.dev/toolkits/todoist/framework/open-ai-agents-sdk.md",
  "updated_at": "2026-05-12T10:28:47.155Z"
}
```

## Introduction

This guide walks you through connecting Todoist to the OpenAI Agents SDK using the Composio tool router. By the end, you'll have a working Todoist agent that can add a high-priority task for today, create a new project called 'team offsite', close all completed tasks from this week through natural language commands.
This guide will help you understand how to give your OpenAI Agents SDK agent real control over a Todoist account through Composio's Todoist MCP server.
Before we dive in, let's take a quick look at the key ideas and tools involved.

## Also integrate Todoist with

- [ChatGPT](https://composio.dev/toolkits/todoist/framework/chatgpt)
- [Claude Agent SDK](https://composio.dev/toolkits/todoist/framework/claude-agents-sdk)
- [Claude Code](https://composio.dev/toolkits/todoist/framework/claude-code)
- [Claude Cowork](https://composio.dev/toolkits/todoist/framework/claude-cowork)
- [Codex](https://composio.dev/toolkits/todoist/framework/codex)
- [Cursor](https://composio.dev/toolkits/todoist/framework/cursor)
- [VS Code](https://composio.dev/toolkits/todoist/framework/vscode)
- [OpenCode](https://composio.dev/toolkits/todoist/framework/opencode)
- [OpenClaw](https://composio.dev/toolkits/todoist/framework/openclaw)
- [Hermes](https://composio.dev/toolkits/todoist/framework/hermes-agent)
- [CLI](https://composio.dev/toolkits/todoist/framework/cli)
- [Google ADK](https://composio.dev/toolkits/todoist/framework/google-adk)
- [LangChain](https://composio.dev/toolkits/todoist/framework/langchain)
- [Vercel AI SDK](https://composio.dev/toolkits/todoist/framework/ai-sdk)
- [Mastra AI](https://composio.dev/toolkits/todoist/framework/mastra-ai)
- [LlamaIndex](https://composio.dev/toolkits/todoist/framework/llama-index)
- [CrewAI](https://composio.dev/toolkits/todoist/framework/crew-ai)

## TL;DR

Here's what you'll learn:
- Get and set up your OpenAI and Composio API keys
- Install the necessary dependencies
- Initialize Composio and create a Tool Router session for Todoist
- Configure an AI agent that can use Todoist as a tool
- Run a live chat session where you can ask the agent to perform Todoist operations

## What is OpenAI Agents SDK?

The OpenAI Agents SDK is a lightweight framework for building AI agents that can use tools and maintain conversation state. It provides a simple interface for creating agents with hosted MCP tool support.
Key features include:
- Hosted MCP Tools: Connect to external services through hosted MCP endpoints
- SQLite Sessions: Persist conversation history across interactions
- Simple API: Clean interface with Agent, Runner, and tool configuration
- Streaming Support: Real-time response streaming for interactive applications

## What is the Todoist MCP server, and what's possible with it?

The Todoist MCP server is an implementation of the Model Context Protocol that connects your AI agent and assistants like Claude, Cursor, etc directly to your Todoist account. It provides structured and secure access to your tasks, projects, and labels, so your agent can create tasks, manage projects, add comments, organize sections, and update your to-do lists on your behalf.
- Task creation and scheduling: Instantly ask your agent to add new tasks with specific details, deadlines, priorities, or even as subtasks within projects or sections.
- Project and workspace management: Let your agent create, organize, or delete projects and workspaces to keep your productivity system tidy and up-to-date.
- Section and label organization: Direct your agent to create, delete, or update sections and labels, helping you structure your tasks and filter lists for better focus.
- Task completion and commenting: Have your agent mark tasks as complete or add helpful comments and notes to specific tasks or projects for seamless collaboration.
- Streamlined cleanup and maintenance: Empower your agent to remove unused projects, labels, or sections, ensuring your Todoist stays clutter-free and organized.

## Supported Tools

| Tool slug | Name | Description |
|---|---|---|
| `TODOIST_ADD_WORKSPACE` | Add Workspace | Tool to create a new workspace in Todoist. Use when you need a separate workspace to organize projects. Generates UUID and temp_id automatically. |
| `TODOIST_ARCHIVE_PROJECT2` | Archive Project (API v1) | Tool to archive a project using Todoist API v1. For personal projects, archives it for the initiating user. For workspace projects, archives it for all workspace users. |
| `TODOIST_BULK_CREATE_TASKS` | Bulk Create Tasks | Create many tasks in one request using Todoist's Sync batching. Use when scaffolding projects or creating multiple tasks at once to reduce round trips. |
| `TODOIST_CLOSE_TASK_V1` | Close Task (API v1) | Tool to close (complete) a task in Todoist using API v1. Use when you need to mark a task as complete using the v1 endpoint. |
| `TODOIST_CREATE_COMMENT_V1` | Create Comment (API v1) | Tool to create a new comment on a project or task using Todoist API v1. Use when you need to add a note to a specific task or project. IMPORTANT: You must provide EXACTLY ONE of task_id or project_id - these parameters are mutually exclusive. - To comment on a task, provide task_id (and omit project_id) - To comment on a project, provide project_id (and omit task_id) - Providing both task_id AND project_id will cause an error. |
| `TODOIST_CREATE_LABEL_V1` | Create Label (API v1) | Tool to create a new personal label using API v1. Use when you need to add a new label to organize tasks. |
| `TODOIST_CREATE_PROJECT2` | Create Project (API v1) | Tool to create a new project in Todoist using the unified API v1. Use when you need to create a new project with specific parameters like name, color, or parent project. |
| `TODOIST_CREATE_SECTION_V1` | Create Section (API v1) | Tool to create a new section within a project using API v1. Use when you need to organize tasks under a new heading in a project. |
| `TODOIST_CREATE_TASK` | Create task | Create a new task in Todoist using the unified API v1. This action allows users to create tasks with various parameters including content, due dates, priority, and more. The task can be created in a specific project, section, or as a subtask of another task. Bulk creation may trigger HTTP 429; honor Retry-After response headers. |
| `TODOIST_DELETE_COMMENT` | Delete Comment | Tool to delete a specific comment from Todoist by its ID. Use when you need to permanently remove a comment. |
| `TODOIST_DELETE_LABEL_V1` | Delete Label (V1) | Tool to delete a personal label using API v1. Use when you need to permanently remove a label by its ID. All instances of the label will be removed from tasks. |
| `TODOIST_DELETE_PROJECT2` | Delete Project (API v1) | Tool to delete a project and all of its sections and tasks using Todoist API v1. Use when you need to permanently remove a project by its ID. |
| `TODOIST_DELETE_SECTION2` | Delete Section (v1) | Tool to delete a section and all tasks within it. Use when you need to permanently remove a section by its ID. |
| `TODOIST_DELETE_TASK` | Delete Task | Tool to delete a specific task from Todoist. Permanently removes the task and all its subtasks with no recycle bin or undo option. Confirm with the user before executing, especially for bulk deletions. |
| `TODOIST_DELETE_UPLOAD` | Delete Upload | Tool to delete an uploaded file from Todoist. Use when you need to remove a file that was previously uploaded. |
| `TODOIST_EXPORT_TEMPLATE_AS_FILE` | Export Template As File | Tool to export a Todoist project as a CSV template file. Use when you need to download a project template as a file for backup or sharing. |
| `TODOIST_EXPORT_TEMPLATE_AS_URL` | Export Template As URL | Tool to export a Todoist project as a shareable template URL. Use when you need to share a project structure or create copies from a template. |
| `TODOIST_FILTER_TASKS` | Filter Tasks | Tool to get all tasks matching the filter. Use when you need to retrieve tasks based on specific filter criteria. This is a paginated endpoint using cursor-based pagination. |
| `TODOIST_GET_ALL_COMMENTS` | Get All Comments | This tool retrieves all comments associated with a specific task or project in Todoist. You must provide exactly one of task_id or project_id (they are mutually exclusive - do not provide both). Returns a JSON array of comment objects with details such as id, posted_at, content, and attachment information. |
| `TODOIST_GET_ALL_PROJECTS` | Get all projects | Get all projects from a user's Todoist account. Retrieves all active (non-archived) projects; use TODOIST_LIST_ARCHIVED_WORKSPACE_PROJECTS for archived ones. Response returns the list in the projects field, with fields including project_id, name, color, parent project, sharing status, and is_inbox_project flag. Always reference projects by project_id — names are non-unique and may be localized. Detect the Inbox via is_inbox_project, not by name. Results are a point-in-time snapshot; re-call after structural changes before relying on cached project_ids. In large accounts, paginate until no next-page token remains to avoid missing projects. Check existing projects before creating new ones to prevent duplicates. |
| `TODOIST_GET_ALL_TASKS` | Get All Tasks | Fetches all INCOMPLETE tasks from Todoist and returns their details. Supports cursor-based pagination. IMPORTANT LIMITATIONS: - This endpoint only returns active (incomplete) tasks - Cannot retrieve completed tasks - use a different endpoint for that - Filter queries using 'completed', '!completed', or 'completed after' will fail - Project/label references must use ACTUAL EXISTING names from the user's account - Arbitrary text in filters causes 400 errors - use 'search: keyword' for text search Common use cases: - Get all tasks: no filter - Get today's tasks: filter="today" - Get overdue tasks: filter="overdue" - Get tasks from specific project: filter="#ProjectName" (project must exist) - Get high priority tasks: filter="p1" - Search task content: filter="search: keyword" - Paginate results: use limit and cursor parameters |
| `TODOIST_GET_BACKUPS` | Get Backups | Tool to list all available backup archives for the user. Returns archive metadata only — not live task or project data; do not use as a proxy for active data availability. May return an empty list if no backups exist or backups are not enabled. For completed task history, use /sync/v9/completed/get_all instead. |
| `TODOIST_GET_COMMENT_V1` | Get Comment (V1) | Tool to retrieve a single comment by ID using the v1 API. Use when you need to fetch details of a specific comment. |
| `TODOIST_GET_COMPLETED_TASKS_BY_COMPLETION_DATE` | Get Completed Tasks By Completion Date | Tool to retrieve completed tasks within a specified completion date window. Use when you need to fetch historical completed tasks for reporting, audits, or weekly summaries. The API restricts the completion-date range to approximately 3 months between since and until parameters. |
| `TODOIST_GET_ID_MAPPINGS` | Get ID Mappings | Tool to translate IDs between Todoist API v1 and v2. Use when you need to convert IDs between API versions for sections, tasks, comments, reminders, location_reminders, or projects. |
| `TODOIST_GET_PERSONAL_LABEL` | Get Personal Label | Tool to retrieve a personal label by its ID. Use when you need to fetch details about a specific personal label. |
| `TODOIST_GET_PRODUCTIVITY_STATS` | Get Productivity Stats | Tool to retrieve comprehensive productivity statistics for the authenticated user. Use when you need detailed completion data, karma scores, streaks, or goal tracking information for productivity reports and analysis. |
| `TODOIST_GET_PROJECT` | Get Project (API v1) | Tool to retrieve a specific project by its ID using Todoist API v1. Use when you have a project ID and need its metadata before display or update. Verify project_id matches the intended project before destructive operations — similar project names can cause mistakes; use TODOIST_GET_ALL_PROJECTS to resolve ambiguous names to IDs first. |
| `TODOIST_GET_PROJECT_FULL` | Get Full Project Data | Tool to retrieve full project data including all sections, tasks, and collaborators. Use when you need comprehensive project information beyond basic metadata. |
| `TODOIST_GET_PROJECT_PERMISSIONS` | Get Project Permissions | Tool to retrieve all available roles and their associated actions in Todoist projects. Use when you need to understand what permissions different roles have in projects. |
| `TODOIST_GET_SECTION_V1` | Get Section (v1 API) | Tool to retrieve a specific section by its ID using Todoist v1 API. Use when you need section metadata from the v1 endpoint. |
| `TODOIST_GET_SPECIAL_BACKUPS` | Get Special Backups | Tool to list special backup archives for the authenticated user's projects. Returns an empty list if no backups exist — callers must not assume archives are present. Read-only: confirms archive visibility only, not live task or project data access. |
| `TODOIST_GET_TASK2` | Get Task (API v1) | Tool to retrieve a single active (non-completed) task by ID using API v1. Use when you need to fetch task details from the v1 endpoint. |
| `TODOIST_GET_USER` | Get User | Tool to retrieve information about the currently authenticated user. Use when you need user details like email, name, preferences, karma, or subscription status. |
| `TODOIST_GET_WORKSPACE_PLAN_DETAILS` | Get Workspace Plan Details | Tool to retrieve details about a workspace's current plan and usage. Use when you need information about subscription status, member count, project limits, pricing, or trial status for a specific workspace. |
| `TODOIST_IMPORT_TEMPLATE_INTO_PROJECT_BY_ID` | Import Template Into Project By ID | Tool to import a template from Todoist's template gallery into an existing project. Use when you need to add structured tasks and sections from a pre-made template to an existing project. |
| `TODOIST_IMPORT_TEMPLATE_INTO_PROJECT_FROM_FILE` | Import Template Into Project From File | Tool to import a CSV template into an existing Todoist project from a file. Use when you need to bulk-create tasks, sections, and notes from a template file. |
| `TODOIST_INVITE_PROJECT_COLLABORATOR` | Invite Project Collaborator | Tool to invite a collaborator to a Todoist project by email. Use when the user asks to share, invite someone to, or add a collaborator to a project. For workspace or team projects, you can optionally specify a role. If the role is omitted, the workspace default role is used. For invite-only workspace projects, the caller may need admin or owner permissions; otherwise the API may return a forbidden error. |
| `TODOIST_LIST_ACTIVITIES` | List Activities | Tool to get activity logs from Todoist. Returns a paginated list of activity events for the user. Events can be filtered by object type (project, item, note), event type, and other criteria. Uses cursor-based pagination for efficient navigation through results. |
| `TODOIST_LIST_ALL_INVITATIONS_WORKSPACES` | List All Workspace Invitations | Tool to return a list containing details of all pending invitations to a workspace. Use when you need to view all pending workspace invitations. This list is not paginated, and all workspace members can access it. |
| `TODOIST_LIST_ARCHIVED_PROJECTS` | List Archived Projects | Tool to get all archived projects from Todoist. Use when you need to retrieve archived projects with pagination support. |
| `TODOIST_LIST_ARCHIVED_SECTIONS` | List Archived Sections | Tool to retrieve all archived sections for a specific project in Todoist. Use when you need to access sections that have been archived in a project. |
| `TODOIST_LIST_ARCHIVED_WORKSPACE_PROJECTS` | List Archived Workspace Projects | Tool to list all archived projects in a workspace. Archived projects are excluded from TODOIST_GET_ALL_PROJECTS; combine both tools when a complete project list is needed. Use when you need to retrieve archived workspace projects with optional filters or pagination. |
| `TODOIST_LIST_COMPLETED_TASKS` | List Completed Tasks | Tool to retrieve all completed tasks with optional project filtering. Use when you need to fetch completed tasks without date range restrictions. Note: This action uses an undocumented Todoist API endpoint (/api/v1/tasks/completed). The endpoint is not officially documented but is confirmed to work based on runtime testing. The response schemas are based on actual API responses. |
| `TODOIST_LIST_COMPLETED_TASKS_BY_DUE_DATE` | List Completed Tasks By Due Date | Tool to retrieve completed tasks within a specified due date range (up to 6 weeks). Use when you need to fetch completed tasks filtered by their original due dates rather than completion dates. |
| `TODOIST_LIST_FILTERS` | List Filters | Tool to list all filters for the authenticated user. Use when you need to retrieve the current set of custom filters. |
| `TODOIST_LIST_JOINABLE_WORKSPACES` | List Joinable Workspaces | Tool to get workspaces the user can join. Use when you need to discover available workspaces that the authenticated user can join. |
| `TODOIST_LIST_LABELS` | List Labels | Tool to get all user labels with pagination support. Use when you need to retrieve labels from the user's Todoist account. |
| `TODOIST_LIST_PENDING_WORKSPACE_INVITATIONS` | List Pending Workspace Invitations | Tool to list pending invitation emails in a workspace. Use when you need to check which email invites are still pending acceptance in a workspace. |
| `TODOIST_LIST_PROJECT_COLLABORATORS` | List Project Collaborators | Tool to get all collaborators for a given project with cursor-based pagination. Use when you need to retrieve the list of people who have access to a specific project. |
| `TODOIST_LIST_SECTIONS` | List Sections | Tool to get all active sections for the user, with optional filtering by project. Supports cursor-based pagination to handle large result sets. |
| `TODOIST_LIST_SHARED_LABELS` | List Shared Labels | Tool to retrieve shared label names from active tasks with pagination support. Use when you need to list labels across the workspace with optional filtering of personal labels. |
| `TODOIST_LIST_WORKSPACE_ACTIVE_PROJECTS` | List Workspace Active Projects | Tool to list all active workspace projects. Returns active projects that are visible to the user, including those not yet joined. For guest users, only joined workspace projects are returned. |
| `TODOIST_LIST_WORKSPACE_ARCHIVED_PROJECTS` | List Workspace Archived Projects | Tool to get archived projects in a workspace. Use when you need to retrieve a list of archived projects for a specific workspace with optional pagination. |
| `TODOIST_LIST_WORKSPACE_INVITATIONS` | List Workspace Invitations | Tool to list user emails with pending invitations to a workspace. Use when you need to check which email invites are still pending. The list is not paginated and accessible by all workspace members. |
| `TODOIST_LIST_WORKSPACE_USERS` | List Workspace Users | Tool to list users in workspace(s). Use when you need to retrieve workspace members. Returns users from a specific workspace if workspace_id is provided, otherwise returns users from all workspaces the authenticated user is part of. Not accessible by guests. |
| `TODOIST_MOVE_TASK` | Move Task | Tool to move a task to another project, section, or parent task while preserving task identity and metadata. Use when you need to relocate a task without recreating it. |
| `TODOIST_MOVE_TASK_REST_API` | Move Task (REST API) | Tool to move a task to another project, section, or parent task using the REST API. Use when you need to relocate a task while preserving its identity and metadata. |
| `TODOIST_QUICK_ADD_TASK` | Quick Add Task | Tool to add tasks using natural language parsing similar to the official Todoist clients. Use when you want to create a task quickly with natural language that includes dates, projects, labels, priority, and other task attributes in a single text string. |
| `TODOIST_REMOVE_SHARED_LABEL_V1` | Remove Shared Label (API v1) | Tool to remove a shared label from all active tasks using API v1. Use when you need to remove a shared label created by a collaborator from your account. |
| `TODOIST_RENAME_SHARED_LABELS_V1` | Rename Shared Labels (API v1) | Tool to rename a shared label across all active tasks using API v1. Use when you need to change the name of a shared label. |
| `TODOIST_REOPEN_TASK2` | Reopen Task (API v1) | Tool to reopen a completed task in Todoist using API v1. Use when you need to restore a previously completed task. Any ancestor tasks or sections will also be marked as uncomplete and restored from history. |
| `TODOIST_REORDER_TASKS` | Reorder Tasks | Reorder tasks deterministically by updating child_order in bulk via the Sync API item_reorder command. Use when you need to set specific ordering for tasks. |
| `TODOIST_SEARCH_LABELS` | Search Labels | Tool to search user labels by name with case-insensitive matching. Use when you need to find specific labels by name pattern. |
| `TODOIST_SEARCH_PROJECTS` | Search Projects | Search active user projects by name with support for wildcards and pagination. Use when you need to find projects matching a specific name pattern. |
| `TODOIST_SEARCH_SECTIONS` | Search Sections | Tool to search active sections by name, optionally filtered by project. Use when you need to find sections matching a specific name pattern across all projects or within a specific project. Supports pagination for large result sets. |
| `TODOIST_SYNC` | Todoist Sync | Tool to sync data with Todoist server, supporting both read and write operations. This is the central endpoint used by Todoist apps for all data synchronization. Use this action to: - Read multiple resource types in a single request (projects, tasks, labels, etc.) - Perform batch write operations (create/update/delete up to 100 resources at once) - Implement efficient incremental sync using sync tokens - Execute complex multi-step operations in a single atomic request For read-only operations, pass sync_token and resource_types. For write operations, include commands array with the operations to execute. Commands support batching up to 100 operations per request. |
| `TODOIST_UNARCHIVE_PROJECT2` | Unarchive Project (API v1) | Tool to unarchive a previously archived Todoist project using API v1. Use when you need to reactivate an archived project, making it visible again for the initiating user (personal projects) or all workspace users (workspace projects). |
| `TODOIST_UPDATE_COMMENT2` | Update Comment (v1) | Tool to update a comment by ID and return its content via v1 API. Use when you need to modify an existing comment's text using the v1 API endpoint. |
| `TODOIST_UPDATE_LABEL_V1_SECOND` | Update Label (API v1) | Tool to update an existing label using API v1. Use when you need to modify a label's name, color, order, or favorite status. |
| `TODOIST_UPDATE_NOTIFICATION_SETTING` | Update Notification Setting | Tool to update notification settings for the current user. Use when you need to enable or disable notifications for specific event types and channels. |
| `TODOIST_UPDATE_PROJECT2` | Update Project (API v1) | Tool to update a project's properties using Todoist API v1. Use when you need to modify project settings like name, description, favorite status, color, or view style. |
| `TODOIST_UPDATE_SECTION2` | Update Section (v1) | Tool to update an existing section by its ID using Todoist v1 API. Use when you need to rename a section. |
| `TODOIST_UPDATE_TASK` | Update Task | Tool to update an existing task's properties. Cannot change a task's project; to move a task, use TODOIST_CREATE_TASK then TODOIST_DELETE_TASK. Use when you need to modify a task's details after confirming its ID and new values. |
| `TODOIST_UPDATE_WORKSPACE_LOGO` | Update Workspace Logo | Tool to upload an image as the workspace logo or delete the existing logo. Use when you need to set or remove a workspace's branding image. |
| `TODOIST_UPLOAD_FILE` | Upload File | Tool to upload a file to Todoist. Use when you need to attach files to tasks or projects. The uploaded file can be later attached to comments or tasks using the returned file_url. |

## Supported Triggers

| Trigger slug | Name | Description |
|---|---|---|
| `TODOIST_NEW_TASK_CREATED` | New Task Created | Trigger when a new task is added to Todoist. |

## Creating MCP Server - Stand-alone vs Composio SDK

The Todoist MCP server is an implementation of the Model Context Protocol that connects your AI agent to Todoist. It provides structured and secure access so your agent can perform Todoist operations on your behalf through a secure, permission-based interface.
With Composio's managed implementation, you don't have to create your own developer app. For production, if you're building an end product, we recommend using your own credentials. The managed server helps you prototype fast and go from 0-1 faster.

## Step-by-step Guide

### 1. Prerequisites

Before starting, make sure you have:
- Composio API Key and OpenAI API Key
- Primary know-how of OpenAI Agents SDK
- A live Todoist project
- Some knowledge of Python or Typescript

### 1. Getting API Keys for OpenAI and Composio

OpenAI API Key
- Go to the [OpenAI dashboard](https://platform.openai.com/settings/organization/api-keys) and create an API key. You'll need credits to use the models, or you can connect to another model provider.
- Keep the API key safe.
Composio API Key
- Log in to the [Composio dashboard](https://dashboard.composio.dev?utm_source=toolkits&utm_medium=framework_docs).
- Go to Settings and copy your API key.

### 2. Install dependencies

Install the Composio SDK and the OpenAI Agents SDK.
```python
pip install composio_openai_agents openai-agents python-dotenv
```

```typescript
npm install @composio/openai-agents @openai/agents dotenv
```

### 3. Set up environment variables

Create a .env file and add your OpenAI and Composio API keys.
```bash
OPENAI_API_KEY=sk-...your-api-key
COMPOSIO_API_KEY=your-api-key
USER_ID=composio_user@gmail.com
```

### 4. Import dependencies

What's happening:
- You're importing all necessary libraries.
- The Composio and OpenAIAgentsProvider classes are imported to connect your OpenAI agent to Composio tools like Todoist.
```python
import asyncio
import os
from dotenv import load_dotenv

from composio import Composio
from composio_openai_agents import OpenAIAgentsProvider
from agents import Agent, Runner, HostedMCPTool, SQLiteSession
```

```typescript
import 'dotenv/config';
import { Composio } from '@composio/core';
import { OpenAIAgentsProvider } from '@composio/openai-agents';
import { Agent, hostedMcpTool, run, OpenAIConversationsSession } from '@openai/agents';
import * as readline from 'readline';
```

### 5. Set up the Composio instance

No description provided.
```python
load_dotenv()

api_key = os.getenv("COMPOSIO_API_KEY")
user_id = os.getenv("USER_ID")

if not api_key:
    raise RuntimeError("COMPOSIO_API_KEY is not set. Create a .env file with COMPOSIO_API_KEY=your_key")

# Initialize Composio
composio = Composio(api_key=api_key, provider=OpenAIAgentsProvider())
```

```typescript
dotenv.config();

const composioApiKey = process.env.COMPOSIO_API_KEY;
const userId = process.env.USER_ID;

if (!composioApiKey) {
  throw new Error('COMPOSIO_API_KEY is not set. Create a .env file with COMPOSIO_API_KEY=your_key');
}
if (!userId) {
  throw new Error('USER_ID is not set');
}

// Initialize Composio
const composio = new Composio({
  apiKey: composioApiKey,
  provider: new OpenAIAgentsProvider(),
});
```

### 6. Create a Tool Router session

What is happening:
- You give the Tool Router the user id and the toolkits you want available. Here, it is only todoist.
- The router checks the user's Todoist connection and prepares the MCP endpoint.
- The returned session.mcp.url is the MCP URL that your agent will use to access Todoist.
- This approach keeps things lightweight and lets the agent request Todoist tools only when needed during the conversation.
```python
# Create a Todoist Tool Router session
session = composio.create(
    user_id=user_id,
    toolkits=["todoist"]
)

mcp_url = session.mcp.url
```

```typescript
// Create Tool Router session for Todoist
const session = await composio.create(userId as string, {
  toolkits: ['todoist'],
});
const mcpUrl = session.mcp.url;
```

### 7. Configure the agent

No description provided.
```python
# Configure agent with MCP tool
agent = Agent(
    name="Assistant",
    model="gpt-5",
    instructions=(
        "You are a helpful assistant that can access Todoist. "
        "Help users perform Todoist operations through natural language."
    ),
    tools=[
        HostedMCPTool(
            tool_config={
                "type": "mcp",
                "server_label": "tool_router",
                "server_url": mcp_url,
                "headers": {"x-api-key": api_key},
                "require_approval": "never",
            }
        )
    ],
)
```

```typescript
// Configure agent with MCP tool
const agent = new Agent({
  name: 'Assistant',
  model: 'gpt-5',
  instructions:
    'You are a helpful assistant that can access Todoist. Help users perform Todoist operations through natural language.',
  tools: [
    hostedMcpTool({
      serverLabel: 'tool_router',
      serverUrl: mcpUrl,
      headers: { 'x-api-key': composioApiKey },
      requireApproval: 'never',
    }),
  ],
});
```

### 8. Start chat loop and handle conversation

No description provided.
```python
print("\nComposio Tool Router session created.")

chat_session = SQLiteSession("conversation_openai_toolrouter")

print("\nChat started. Type your requests below.")
print("Commands: 'exit', 'quit', or 'q' to end\n")

async def main():
    try:
        result = await Runner.run(
            agent,
            "What can you help me with?",
            session=chat_session
        )
        print(f"Assistant: {result.final_output}\n")
    except Exception as e:
        print(f"Error: {e}\n")

    while True:
        user_input = input("You: ").strip()
        if user_input.lower() in {"exit", "quit", "q"}:
            print("Goodbye!")
            break

        result = await Runner.run(
            agent,
            user_input,
            session=chat_session
        )
        print(f"Assistant: {result.final_output}\n")

asyncio.run(main())
```

```typescript
// Keep conversation state across turns
const conversationSession = new OpenAIConversationsSession();

// Simple CLI
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  prompt: 'You: ',
});

console.log('\nComposio Tool Router session created.');
console.log('\nChat started. Type your requests below.');
console.log("Commands: 'exit', 'quit', or 'q' to end\n");

try {
  const first = await run(agent, 'What can you help me with?', { session: conversationSession });
  console.log(`Assistant: ${first.finalOutput}\n`);
} catch (e) {
  console.error('Error:', e instanceof Error ? e.message : e, '\n');
}

rl.prompt();

rl.on('line', async (userInput) => {
  const text = userInput.trim();

  if (['exit', 'quit', 'q'].includes(text.toLowerCase())) {
    console.log('Goodbye!');
    rl.close();
    process.exit(0);
  }

  if (!text) {
    rl.prompt();
    return;
  }

  try {
    const result = await run(agent, text, { session: conversationSession });
    console.log(`\nAssistant: ${result.finalOutput}\n`);
  } catch (e) {
    console.error('Error:', e instanceof Error ? e.message : e, '\n');
  }

  rl.prompt();
});

rl.on('close', () => {
  console.log('\n👋 Session ended.');
  process.exit(0);
});
```

## Complete Code

```python
import asyncio
import os
from dotenv import load_dotenv

from composio import Composio
from composio_openai_agents import OpenAIAgentsProvider
from agents import Agent, Runner, HostedMCPTool, SQLiteSession

load_dotenv()

api_key = os.getenv("COMPOSIO_API_KEY")
user_id = os.getenv("USER_ID")

if not api_key:
    raise RuntimeError("COMPOSIO_API_KEY is not set. Create a .env file with COMPOSIO_API_KEY=your_key")

# Initialize Composio
composio = Composio(api_key=api_key, provider=OpenAIAgentsProvider())

# Create Tool Router session
session = composio.create(
    user_id=user_id,
    toolkits=["todoist"]
)
mcp_url = session.mcp.url

# Configure agent with MCP tool
agent = Agent(
    name="Assistant",
    model="gpt-5",
    instructions=(
        "You are a helpful assistant that can access Todoist. "
        "Help users perform Todoist operations through natural language."
    ),
    tools=[
        HostedMCPTool(
            tool_config={
                "type": "mcp",
                "server_label": "tool_router",
                "server_url": mcp_url,
                "headers": {"x-api-key": api_key},
                "require_approval": "never",
            }
        )
    ],
)

print("\nComposio Tool Router session created.")

chat_session = SQLiteSession("conversation_openai_toolrouter")

print("\nChat started. Type your requests below.")
print("Commands: 'exit', 'quit', or 'q' to end\n")

async def main():
    try:
        result = await Runner.run(
            agent,
            "What can you help me with?",
            session=chat_session
        )
        print(f"Assistant: {result.final_output}\n")
    except Exception as e:
        print(f"Error: {e}\n")

    while True:
        user_input = input("You: ").strip()
        if user_input.lower() in {"exit", "quit", "q"}:
            print("Goodbye!")
            break

        result = await Runner.run(
            agent,
            user_input,
            session=chat_session
        )
        print(f"Assistant: {result.final_output}\n")

asyncio.run(main())
```

```typescript
import 'dotenv/config';
import { Composio } from '@composio/core';
import { OpenAIAgentsProvider } from '@composio/openai-agents';
import { Agent, hostedMcpTool, run, OpenAIConversationsSession } from '@openai/agents';
import * as readline from 'readline';

const composioApiKey = process.env.COMPOSIO_API_KEY;
const userId = process.env.USER_ID;

if (!composioApiKey) {
  throw new Error('COMPOSIO_API_KEY is not set. Create a .env file with COMPOSIO_API_KEY=your_key');
}
if (!userId) {
  throw new Error('USER_ID is not set');
}

// Initialize Composio
const composio = new Composio({
  apiKey: composioApiKey,
  provider: new OpenAIAgentsProvider(),
});

async function main() {
  // Create Tool Router session
  const session = await composio.create(userId as string, {
    toolkits: ['todoist'],
  });
  const mcpUrl = session.mcp.url;

  // Configure agent with MCP tool
  const agent = new Agent({
    name: 'Assistant',
    model: 'gpt-5',
    instructions:
      'You are a helpful assistant that can access Todoist. Help users perform Todoist operations through natural language.',
    tools: [
      hostedMcpTool({
        serverLabel: 'tool_router',
        serverUrl: mcpUrl,
        headers: { 'x-api-key': composioApiKey },
        requireApproval: 'never',
      }),
    ],
  });

  // Keep conversation state across turns
  const conversationSession = new OpenAIConversationsSession();

  // Simple CLI
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    prompt: 'You: ',
  });

  console.log('\nComposio Tool Router session created.');
  console.log('\nChat started. Type your requests below.');
  console.log("Commands: 'exit', 'quit', or 'q' to end\n");

  try {
    const first = await run(agent, 'What can you help me with?', { session: conversationSession });
    console.log(`Assistant: ${first.finalOutput}\n`);
  } catch (e) {
    console.error('Error:', e instanceof Error ? e.message : e, '\n');
  }

  rl.prompt();

  rl.on('line', async (userInput) => {
    const text = userInput.trim();

    if (['exit', 'quit', 'q'].includes(text.toLowerCase())) {
      console.log('Goodbye!');
      rl.close();
      process.exit(0);
    }

    if (!text) {
      rl.prompt();
      return;
    }

    try {
      const result = await run(agent, text, { session: conversationSession });
      console.log(`\nAssistant: ${result.finalOutput}\n`);
    } catch (e) {
      console.error('Error:', e instanceof Error ? e.message : e, '\n');
    }

    rl.prompt();
  });

  rl.on('close', () => {
    console.log('\nSession ended.');
    process.exit(0);
  });
}

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

## Conclusion

This was a starter code for integrating Todoist MCP with OpenAI Agents SDK to build a functional AI agent that can interact with Todoist.
Key features:
- Hosted MCP tool integration through Composio's Tool Router
- SQLite session persistence for conversation history
- Simple async chat loop for interactive testing
You can extend this by adding more toolkits, implementing custom business logic, or building a web interface around the agent.

## How to build Todoist MCP Agent with another framework

- [ChatGPT](https://composio.dev/toolkits/todoist/framework/chatgpt)
- [Claude Agent SDK](https://composio.dev/toolkits/todoist/framework/claude-agents-sdk)
- [Claude Code](https://composio.dev/toolkits/todoist/framework/claude-code)
- [Claude Cowork](https://composio.dev/toolkits/todoist/framework/claude-cowork)
- [Codex](https://composio.dev/toolkits/todoist/framework/codex)
- [Cursor](https://composio.dev/toolkits/todoist/framework/cursor)
- [VS Code](https://composio.dev/toolkits/todoist/framework/vscode)
- [OpenCode](https://composio.dev/toolkits/todoist/framework/opencode)
- [OpenClaw](https://composio.dev/toolkits/todoist/framework/openclaw)
- [Hermes](https://composio.dev/toolkits/todoist/framework/hermes-agent)
- [CLI](https://composio.dev/toolkits/todoist/framework/cli)
- [Google ADK](https://composio.dev/toolkits/todoist/framework/google-adk)
- [LangChain](https://composio.dev/toolkits/todoist/framework/langchain)
- [Vercel AI SDK](https://composio.dev/toolkits/todoist/framework/ai-sdk)
- [Mastra AI](https://composio.dev/toolkits/todoist/framework/mastra-ai)
- [LlamaIndex](https://composio.dev/toolkits/todoist/framework/llama-index)
- [CrewAI](https://composio.dev/toolkits/todoist/framework/crew-ai)

## Related Toolkits

- [Google Sheets](https://composio.dev/toolkits/googlesheets) - Google Sheets is a cloud-based spreadsheet tool for real-time collaboration and data analysis. It lets teams work together from anywhere, updating information instantly.
- [Notion](https://composio.dev/toolkits/notion) - Notion is a collaborative workspace for notes, docs, wikis, and tasks. It streamlines team knowledge, project tracking, and workflow customization in one place.
- [Airtable](https://composio.dev/toolkits/airtable) - Airtable combines the flexibility of spreadsheets with the power of a database for easy project and data management. Teams use Airtable to organize, track, and collaborate with custom views and automations.
- [Asana](https://composio.dev/toolkits/asana) - Asana is a collaborative work management platform for teams to organize and track projects. It streamlines teamwork, boosts productivity, and keeps everyone aligned on goals.
- [Google Tasks](https://composio.dev/toolkits/googletasks) - Google Tasks is a to-do list and task management tool integrated into Gmail and Google Calendar. It helps you organize, track, and complete tasks across your Google ecosystem.
- [Linear](https://composio.dev/toolkits/linear) - Linear is a modern issue tracking and project planning tool for fast-moving teams. It helps streamline workflows, organize projects, and boost productivity.
- [Jira](https://composio.dev/toolkits/jira) - Jira is Atlassian’s platform for bug tracking, issue tracking, and agile project management. It helps teams organize work, prioritize tasks, and deliver projects efficiently.
- [Clickup](https://composio.dev/toolkits/clickup) - ClickUp is an all-in-one productivity platform for managing tasks, docs, goals, and team collaboration. It streamlines project workflows so teams can work smarter and stay organized in one place.
- [Monday](https://composio.dev/toolkits/monday) - Monday.com is a customizable work management platform for project planning and collaboration. It helps teams organize tasks, automate workflows, and track progress in real time.
- [Addressfinder](https://composio.dev/toolkits/addressfinder) - Addressfinder is a data quality platform for verifying addresses, emails, and phone numbers. It helps you ensure accurate customer and contact data every time.
- [Agiled](https://composio.dev/toolkits/agiled) - Agiled is an all-in-one business management platform for CRM, projects, and finance. It helps you streamline workflows, consolidate client data, and manage business processes in one place.
- [Ascora](https://composio.dev/toolkits/ascora) - Ascora is a cloud-based field service management platform for service businesses. It streamlines scheduling, invoicing, and customer operations in one place.
- [Basecamp](https://composio.dev/toolkits/basecamp) - Basecamp is a project management and team collaboration tool by 37signals. It helps teams organize tasks, share files, and communicate efficiently in one place.
- [Beeminder](https://composio.dev/toolkits/beeminder) - Beeminder is an online goal-tracking platform that uses monetary pledges to keep you motivated. Stay accountable and hit your targets with real financial incentives.
- [Boxhero](https://composio.dev/toolkits/boxhero) - Boxhero is a cloud-based inventory management platform for SMBs, offering real-time updates, barcode scanning, and team collaboration. It helps businesses streamline stock tracking and analytics for smarter inventory decisions.
- [Breathe HR](https://composio.dev/toolkits/breathehr) - Breathe HR is cloud-based HR software for SMEs to manage employee data, absences, and performance. It simplifies HR admin, making it easy to keep employee records accurate and up to date.
- [Breeze](https://composio.dev/toolkits/breeze) - Breeze is a project management platform designed to help teams plan, track, and collaborate on projects. It streamlines workflows and keeps everyone on the same page.
- [Bugherd](https://composio.dev/toolkits/bugherd) - Bugherd is a visual feedback and bug tracking tool for websites. It helps teams and clients report website issues directly on live sites for faster fixes.
- [Canny](https://composio.dev/toolkits/canny) - Canny is a platform for managing customer feedback and feature requests. It helps teams prioritize product decisions based on real user insights.
- [Chmeetings](https://composio.dev/toolkits/chmeetings) - Chmeetings is a church management platform for events, members, donations, and volunteers. It streamlines church operations and improves community engagement.

## Frequently Asked Questions

### What are the differences in Tool Router MCP and Todoist MCP?

With a standalone Todoist MCP server, the agents and LLMs can only access a fixed set of Todoist tools tied to that server. However, with the Composio Tool Router, agents can dynamically load tools from Todoist and many other apps based on the task at hand, all through a single MCP endpoint.

### Can I use Tool Router MCP with OpenAI Agents SDK?

Yes, you can. OpenAI Agents SDK fully supports MCP integration. You get structured tool calling, message history handling, and model orchestration while Tool Router takes care of discovering and serving the right Todoist tools.

### Can I manage the permissions and scopes for Todoist while using Tool Router?

Yes, absolutely. You can configure which Todoist scopes and actions are allowed when connecting your account to Composio. You can also bring your own OAuth credentials or API configuration so you keep full control over what the agent can do.

### How safe is my data with Composio Tool Router?

All sensitive data such as tokens, keys, and configuration is fully encrypted at rest and in transit. Composio is SOC 2 Type 2 compliant and follows strict security practices so your Todoist data and credentials are handled as safely as possible.

---
[See all toolkits](https://composio.dev/toolkits) · [Composio docs](https://docs.composio.dev/llms.txt)
