Skip to main content
Glama

asana_create_task_story

Add comments or formatted stories to Asana tasks using plain text or limited HTML formatting to provide updates, context, or feedback directly within task workflows.

Instructions

Create a comment or story on a task. Either text or html_text is required.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
html_textNoHTML-like formatted text for the comment. Required if text is not provided. Does not support ALL HTML tags. Only a subset. The only allowed TAG in the HTML are: <body> <h1> <h2> <ol> <ul> <li> <strong> <em> <u> <s> <code> <pre> <blockquote> <a data-asana-type="" data-asana-gid=""> <hr> <img> <table> <tr> <td>. No other tags are allowed. Use the \n to create a newline. Do not use \n after <body>.
opt_fieldsNoComma-separated list of optional fields to include
task_idYesThe task ID to add the story to
textNoThe plain text content of the story/comment. Required if html_text is not provided.

Implementation Reference

  • The main handler logic for the 'asana_create_task_story' tool. It validates HTML text if provided, handles errors with detailed feedback, and delegates to AsanaClientWrapper.createTaskStory.
    case "asana_create_task_story": { const { task_id, text, html_text, ...opts } = args; try { // Validate if html_text is provided if (html_text) { const xmlValidationErrors = validateAsanaXml(html_text); if (xmlValidationErrors.length > 0) { return { content: [{ type: "text", text: JSON.stringify({ error: "HTML validation failed", validation_errors: xmlValidationErrors, message: "The HTML text contains invalid XML formatting. Please check the validation errors above." }) }], }; } } const response = await asanaClient.createTaskStory(task_id, text, opts, html_text); return { content: [{ type: "text", text: JSON.stringify(response) }], }; } catch (error) { // When error occurs and html_text was provided, help troubleshoot if (html_text && error instanceof Error && error.message.includes('400')) { return { content: [{ type: "text", text: JSON.stringify({ error: error instanceof Error ? error.message : String(error), html_text_validation: "The HTML format is valid. The error must be related to something else in the API request." }) }], }; } throw error; // re-throw to be caught by the outer try/catch } }
  • Defines the Tool object with name, description, and detailed inputSchema for the 'asana_create_task_story' tool.
    export const createTaskStoryTool: Tool = { name: "asana_create_task_story", description: "Create a comment or story on a task. Either text or html_text is required.", inputSchema: { type: "object", properties: { task_id: { type: "string", description: "The task ID to add the story to" }, text: { type: "string", description: "The plain text content of the story/comment. Required if html_text is not provided." }, html_text: { type: "string", description: "HTML-like formatted text for the comment. Required if text is not provided. Does not support ALL HTML tags. Only a subset. The only allowed TAG in the HTML are: <body> <h1> <h2> <ol> <ul> <li> <strong> <em> <u> <s> <code> <pre> <blockquote> <a data-asana-type=\"\" data-asana-gid=\"\"> <hr> <img> <table> <tr> <td>. No other tags are allowed. Use the \\n to create a newline. Do not use \\n after <body>." }, opt_fields: { type: "string", description: "Comma-separated list of optional fields to include" } }, required: ["task_id"] } };
  • Registers the createTaskStoryTool in the all_tools array, which is exported (possibly filtered) as list_of_tools for MCP tool discovery.
    const all_tools: Tool[] = [ listWorkspacesTool, searchProjectsTool, searchTasksTool, getTaskTool, createTaskTool, getStoriesForTaskTool, updateTaskTool, getProjectTool, getProjectTaskCountsTool, getProjectSectionsTool, createTaskStoryTool, addTaskDependenciesTool, addTaskDependentsTool, createSubtaskTool, getMultipleTasksByGidTool, getProjectStatusTool, getProjectStatusesForProjectTool, createProjectStatusTool, deleteProjectStatusTool, setParentForTaskTool, getTasksForTagTool, getTagsForWorkspaceTool, ]; // List of tools that only read Asana state const READ_ONLY_TOOLS = [ 'asana_list_workspaces', 'asana_search_projects', 'asana_search_tasks', 'asana_get_task', 'asana_get_task_stories', 'asana_get_project', 'asana_get_project_task_counts', 'asana_get_project_status', 'asana_get_project_statuses', 'asana_get_project_sections', 'asana_get_multiple_tasks_by_gid', 'asana_get_tasks_for_tag', 'asana_get_tags_for_workspace' ]; // Filter tools based on READ_ONLY_MODE const isReadOnlyMode = process.env.READ_ONLY_MODE === 'true'; // Export filtered list of tools export const list_of_tools = isReadOnlyMode ? all_tools.filter(tool => READ_ONLY_TOOLS.includes(tool.name)) : all_tools;
  • Supporting method in AsanaClientWrapper that prepares the request body (ensuring text or html_text) and calls the underlying Asana SDK StoriesApi to create the story.
    async createTaskStory(taskId: string, text: string | null = null, opts: any = {}, html_text: string | null = null) { const options = opts.opt_fields ? opts : {}; const data: any = {}; if (text) { data.text = text; } else if (html_text) { data.html_text = html_text; } else { throw new Error("Either text or html_text must be provided"); } const body = { data }; const response = await this.stories.createStoryForTask(body, taskId, options); return response.data; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/roychri/mcp-server-asana'

If you have feedback or need assistance with the MCP directory API, please join our Discord server