Skip to content

Commit 50a6d3e

Browse files
committed
fix (integrations): resolved issues in notion, gdocs, github, whatsapp
feat (integrations): added gtasks mcp
1 parent 74dae2d commit 50a6d3e

File tree

23 files changed

+477
-169
lines changed

23 files changed

+477
-169
lines changed

src/client/app/chat/page.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ import {
3434
IconNews,
3535
IconBrandDiscord,
3636
IconBrandWhatsapp,
37-
IconCalendarEvent
37+
IconCalendarEvent,
38+
IconListCheck
3839
} from "@tabler/icons-react"
3940
import {
4041
IconBrandSlack,
@@ -77,6 +78,7 @@ const toolIcons = {
7778
discord: IconBrandDiscord,
7879
whatsapp: IconBrandWhatsapp,
7980
gcalendar_alt: IconCalendarEvent,
81+
gtasks: IconListCheck,
8082
default: IconTool
8183
}
8284

src/client/app/integrations/page.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1648,4 +1648,4 @@ const IntegrationsPage = () => {
16481648
)
16491649
}
16501650

1651-
export default IntegrationsPage
1651+
export default IntegrationsPage

src/client/components/ChatBubble.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
IconChartPie,
2020
IconBrandTrello,
2121
IconNews,
22-
IconListCheck,
22+
IconListCheck as IconListCheckTabler,
2323
IconBrandDiscord,
2424
IconBrandWhatsapp,
2525
IconCalendarEvent,
@@ -60,6 +60,7 @@ const toolIcons = {
6060
todoist: IconListCheck,
6161
discord: IconBrandDiscord,
6262
whatsapp: IconBrandWhatsapp,
63+
gtasks: IconListCheckTabler,
6364
gcalendar_alt: IconCalendarEvent,
6465
default: IconTool
6566
}

src/client/utils/integration-capabilities.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/server/.env.selfhost.template

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ GMAIL_AUTH_CONFIG_ID=<your_composio_gmail_auth_config_id>
8888
GDRIVE_AUTH_CONFIG_ID=<your_composio_gdrive_auth_config_id>
8989
GCALENDAR_AUTH_CONFIG_ID=<your_composio_gcalendar_auth_config_id>
9090
GDOCS_AUTH_CONFIG_ID=<your_composio_gdocs_auth_config_id>
91+
GTASKS_AUTH_CONFIG_ID=<your_composio_gtasks_auth_config_id>
9192
GSHEETS_AUTH_CONFIG_ID=<your_composio_gsheets_auth_config_id>
9293

9394
# --- Encryption ---
@@ -121,6 +122,7 @@ NEWS_MCP_SERVER_URL=http://localhost:9012/sse/
121122
GSLIDES_MCP_SERVER_URL=http://localhost:9014/sse/
122123
GSHEETS_MCP_SERVER_URL=http://localhost:9015/sse/
123124
GMAPS_MCP_SERVER_URL=http://localhost:9016/sse/
125+
GTASKS_MCP_SERVER_URL=http://localhost:9028/sse/
124126
TASKS_MCP_SERVER_URL=http://localhost:9018/sse/
125127
GPEOPLE_MCP_SERVER_URL=http://localhost:9019/sse/
126128
HISTORY_MCP_SERVER_URL=http://localhost:9020/sse/

src/server/.env.template

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ GMAIL_AUTH_CONFIG_ID=<your_composio_gmail_auth_config_id>
9898
GDRIVE_AUTH_CONFIG_ID=<your_composio_gdrive_auth_config_id>
9999
GCALENDAR_AUTH_CONFIG_ID=<your_composio_gcalendar_auth_config_id>
100100
GDOCS_AUTH_CONFIG_ID=<your_composio_gdocs_auth_config_id>
101+
GTASKS_AUTH_CONFIG_ID=<your_composio_gtasks_auth_config_id>
101102
GSHEETS_AUTH_CONFIG_ID=<your_composio_gsheets_auth_config_id>
102103

103104
# --- Encryption ---
@@ -132,6 +133,7 @@ NEWS_MCP_SERVER_URL=http://localhost:9012/sse/
132133
GSLIDES_MCP_SERVER_URL=http://localhost:9014/sse/
133134
GSHEETS_MCP_SERVER_URL=http://localhost:9015/sse/
134135
GMAPS_MCP_SERVER_URL=http://localhost:9016/sse/
136+
GTASKS_MCP_SERVER_URL=http://localhost:9028/sse/
135137
TASKS_MCP_SERVER_URL=http://localhost:9018/sse/
136138
GPEOPLE_MCP_SERVER_URL=http://localhost:9019/sse/
137139
HISTORY_MCP_SERVER_URL=http://localhost:9020/sse/

src/server/main/chat/prompts.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"gdrive": "Use this tool to search and read files in Google Drive.",
2121
"github": "Use this tool to perform actions related to GitHub repositories.",
2222
"gmail": "Use this tool to send and manage emails in Gmail.",
23+
"gtasks": "Use this tool to manage your to-do lists and tasks in Google Tasks.",
2324
"gmaps": "Use this tool for navigation, location search, and directions.",
2425
"gpeople": "Use this tool for storing and organizing personal and professional contacts.",
2526
"gsheets": "Use this tool to create and edit spreadsheets in Google Sheets.",
@@ -87,6 +88,7 @@
8788
"gdrive": "Searching and reading files in Google Drive.",
8889
"github": "Interacting with GitHub.",
8990
"gmail": "Managing emails in Gmail.",
91+
"gtasks": "Managing your to-do lists and tasks in Google Tasks.",
9092
"gmaps": "Navigation and location search.",
9193
"gpeople": "Managing contacts.",
9294
"gsheets": "Creating/editing Google Sheets.",

src/server/main/config.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@
9090
TODOIST_CLIENT_ID = os.getenv("TODOIST_CLIENT_ID")
9191
TODOIST_CLIENT_SECRET = os.getenv("TODOIST_CLIENT_SECRET")
9292

93+
# --- Composio Auth Config IDs ---
94+
GMAIL_AUTH_CONFIG_ID = os.getenv("GMAIL_AUTH_CONFIG_ID")
95+
GDRIVE_AUTH_CONFIG_ID = os.getenv("GDRIVE_AUTH_CONFIG_ID")
96+
GCALENDAR_AUTH_CONFIG_ID = os.getenv("GCALENDAR_AUTH_CONFIG_ID")
97+
GDOCS_AUTH_CONFIG_ID = os.getenv("GDOCS_AUTH_CONFIG_ID")
98+
GTASKS_AUTH_CONFIG_ID = os.getenv("GTASKS_AUTH_CONFIG_ID") # New: Google Tasks Auth Config ID
99+
GSHEETS_AUTH_CONFIG_ID = os.getenv("GSHEETS_AUTH_CONFIG_ID")
100+
93101
# --- WhatsApp ---
94102
WAHA_URL = os.getenv("WAHA_URL")
95103
WAHA_API_KEY = os.getenv("WAHA_API_KEY")
@@ -155,6 +163,18 @@
155163
"url": os.getenv("GDOCS_MCP_SERVER_URL", "http://localhost:9004/sse")
156164
}
157165
},
166+
"gtasks": {
167+
"display_name": "Google Tasks",
168+
"description": "Connect to manage your to-do lists and tasks. The agent can create, list, update, and delete tasks and task lists on your behalf.",
169+
"auth_type": "composio",
170+
"icon": "IconListCheck",
171+
"auth_config_env_var": "GTASKS_AUTH_CONFIG_ID",
172+
"category": "Productivity",
173+
"mcp_server_config": {
174+
"name": "gtasks_server",
175+
"url": os.getenv("GTASKS_MCP_SERVER_URL", "http://localhost:9028/sse")
176+
}
177+
},
158178
"gslides": {
159179
"display_name": "Google Slides",
160180
"description": "Create and manage presentations in Google Slides. The agent can build new slide decks with titles, content, images, and charts based on a structured outline you provide.",

src/server/mcp_hub/gdocs/main.py

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ async def create_document(ctx: Context, title: str, text: str = "") -> Dict:
6868
return await _execute_tool(ctx, "GOOGLEDOCS_CREATE_DOCUMENT", title=title, text=text)
6969

7070
@mcp.tool()
71-
async def get_document_by_id(ctx: Context, id: str) -> Dict:
71+
async def get_document_by_id(ctx: Context, document_id: str) -> Dict:
7272
"""Retrieves an existing google document by its id."""
73-
return await _execute_tool(ctx, "GOOGLEDOCS_GET_DOCUMENT_BY_ID", id=id)
73+
return await _execute_tool(ctx, "GOOGLEDOCS_GET_DOCUMENT_BY_ID", id=document_id)
7474

7575
@mcp.tool()
7676
async def search_documents(ctx: Context, query: Optional[str] = None, created_after: Optional[str] = None, include_trashed: Optional[bool] = None, max_results: int = 10, modified_after: Optional[str] = None, order_by: str = "modifiedTime desc", shared_with_me: Optional[bool] = None, starred_only: Optional[bool] = None) -> Dict:
@@ -93,19 +93,22 @@ async def create_footer(ctx: Context, document_id: str, type: str, section_break
9393
return await _execute_tool(ctx, "GOOGLEDOCS_CREATE_FOOTER", document_id=document_id, type=type, section_break_location=section_break_location)
9494

9595
@mcp.tool()
96-
async def create_footnote(ctx: Context, documentId: str, endOfSegmentLocation: Optional[Dict] = None, location: Optional[Dict] = None) -> Dict:
96+
async def create_footnote(ctx: Context, document_id: str, endOfSegmentLocation: Optional[Dict] = None, location: Optional[Dict] = None) -> Dict:
9797
"""Create a new footnote in a google document."""
98-
return await _execute_tool(ctx, "GOOGLEDOCS_CREATE_FOOTNOTE", documentId=documentId, endOfSegmentLocation=endOfSegmentLocation, location=location)
98+
return await _execute_tool(ctx, "GOOGLEDOCS_CREATE_FOOTNOTE", documentId=document_id, endOfSegmentLocation=endOfSegmentLocation, location=location)
9999

100100
@mcp.tool()
101-
async def create_header(ctx: Context, createHeader: Dict, documentId: str) -> Dict:
101+
async def create_header(ctx: Context, document_id: str, type: str, section_break_location: Optional[Dict] = None) -> Dict:
102102
"""Create a new header in a google document."""
103-
return await _execute_tool(ctx, "GOOGLEDOCS_CREATE_HEADER", createHeader=createHeader, documentId=documentId)
103+
createHeader_payload = {"type": type}
104+
if section_break_location:
105+
createHeader_payload["section_break_location"] = section_break_location
106+
return await _execute_tool(ctx, "GOOGLEDOCS_CREATE_HEADER", createHeader=createHeader_payload, documentId=document_id)
104107

105108
@mcp.tool()
106-
async def create_named_range(ctx: Context, documentId: str, name: str, rangeEndIndex: int, rangeStartIndex: int, rangeSegmentId: Optional[str] = None) -> Dict:
109+
async def create_named_range(ctx: Context, document_id: str, name: str, rangeEndIndex: int, rangeStartIndex: int, rangeSegmentId: Optional[str] = None) -> Dict:
107110
"""Create a new named range in a google document."""
108-
return await _execute_tool(ctx, "GOOGLEDOCS_CREATE_NAMED_RANGE", documentId=documentId, name=name, rangeEndIndex=rangeEndIndex, rangeStartIndex=rangeStartIndex, rangeSegmentId=rangeSegmentId)
111+
return await _execute_tool(ctx, "GOOGLEDOCS_CREATE_NAMED_RANGE", documentId=document_id, name=name, rangeEndIndex=rangeEndIndex, rangeStartIndex=rangeStartIndex, rangeSegmentId=rangeSegmentId)
109112

110113
@mcp.tool()
111114
async def create_paragraph_bullets(ctx: Context, createParagraphBullets: Dict, document_id: str) -> Dict:
@@ -148,29 +151,29 @@ async def delete_table_column(ctx: Context, document_id: str, requests: List[Dic
148151
return await _execute_tool(ctx, "GOOGLEDOCS_DELETE_TABLE_COLUMN", document_id=document_id, requests=requests)
149152

150153
@mcp.tool()
151-
async def delete_table_row(ctx: Context, documentId: str, tableCellLocation: Dict) -> Dict:
154+
async def delete_table_row(ctx: Context, document_id: str, tableCellLocation: Dict) -> Dict:
152155
"""Delete a row from a table in a google document."""
153-
return await _execute_tool(ctx, "GOOGLEDOCS_DELETE_TABLE_ROW", documentId=documentId, tableCellLocation=tableCellLocation)
156+
return await _execute_tool(ctx, "GOOGLEDOCS_DELETE_TABLE_ROW", documentId=document_id, tableCellLocation=tableCellLocation)
154157

155158
@mcp.tool()
156159
async def get_charts_from_spreadsheet(ctx: Context, spreadsheet_id: str) -> Dict:
157160
"""Retrieve a list of all charts from a specified google sheets spreadsheet."""
158161
return await _execute_tool(ctx, "GOOGLEDOCS_GET_CHARTS_FROM_SPREADSHEET", spreadsheet_id=spreadsheet_id)
159162

160163
@mcp.tool()
161-
async def insert_inline_image(ctx: Context, documentId: str, location: Dict, uri: str, objectSize: Optional[Dict] = None) -> Dict:
164+
async def insert_inline_image(ctx: Context, document_id: str, location: Dict, uri: str, objectSize: Optional[Dict] = None) -> Dict:
162165
"""Insert an image from a given uri at a specified location."""
163-
return await _execute_tool(ctx, "GOOGLEDOCS_INSERT_INLINE_IMAGE", documentId=documentId, location=location, uri=uri, objectSize=objectSize)
166+
return await _execute_tool(ctx, "GOOGLEDOCS_INSERT_INLINE_IMAGE", documentId=document_id, location=location, uri=uri, objectSize=objectSize)
164167

165168
@mcp.tool()
166-
async def insert_page_break(ctx: Context, documentId: str, insertPageBreak: Dict) -> Dict:
169+
async def insert_page_break(ctx: Context, document_id: str, insertPageBreak: Dict) -> Dict:
167170
"""Insert a page break into a google document."""
168-
return await _execute_tool(ctx, "GOOGLEDOCS_INSERT_PAGE_BREAK", documentId=documentId, insertPageBreak=insertPageBreak)
171+
return await _execute_tool(ctx, "GOOGLEDOCS_INSERT_PAGE_BREAK", documentId=document_id, insertPageBreak=insertPageBreak)
169172

170173
@mcp.tool()
171-
async def insert_table_action(ctx: Context, columns: int, documentId: str, rows: int, index: Optional[int] = None, insertAtEndOfSegment: Optional[bool] = None, segmentId: Optional[str] = None, tabId: Optional[str] = None) -> Dict:
174+
async def insert_table_action(ctx: Context, columns: int, document_id: str, rows: int, index: Optional[int] = None, insertAtEndOfSegment: Optional[bool] = None, segmentId: Optional[str] = None, tabId: Optional[str] = None) -> Dict:
172175
"""Insert a table into a google document."""
173-
return await _execute_tool(ctx, "GOOGLEDOCS_INSERT_TABLE_ACTION", columns=columns, documentId=documentId, rows=rows, index=index, insertAtEndOfSegment=insertAtEndOfSegment, segmentId=segmentId, tabId=tabId)
176+
return await _execute_tool(ctx, "GOOGLEDOCS_INSERT_TABLE_ACTION", columns=columns, documentId=document_id, rows=rows, index=index, insertAtEndOfSegment=insertAtEndOfSegment, segmentId=segmentId, tabId=tabId)
174177

175178
@mcp.tool()
176179
async def insert_table_column(ctx: Context, document_id: str, requests: List[Dict]) -> Dict:
@@ -208,9 +211,9 @@ async def update_document_style(ctx: Context, document_id: str, document_style:
208211
return await _execute_tool(ctx, "GOOGLEDOCS_UPDATE_DOCUMENT_STYLE", document_id=document_id, document_style=document_style, fields=fields, tab_id=tab_id)
209212

210213
@mcp.tool()
211-
async def update_table_row_style(ctx: Context, documentId: str, updateTableRowStyle: Dict) -> Dict:
214+
async def update_table_row_style(ctx: Context, document_id: str, updateTableRowStyle: Dict) -> Dict:
212215
"""Update the style of a table row in a google document."""
213-
return await _execute_tool(ctx, "GOOGLEDOCS_UPDATE_TABLE_ROW_STYLE", documentId=documentId, updateTableRowStyle=updateTableRowStyle)
216+
return await _execute_tool(ctx, "GOOGLEDOCS_UPDATE_TABLE_ROW_STYLE", documentId=document_id, updateTableRowStyle=updateTableRowStyle)
214217

215218
if __name__ == "__main__":
216219
host = os.getenv("MCP_SERVER_HOST", "127.0.0.1")

src/server/mcp_hub/gdocs/prompts.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
You are a Google Docs assistant. Your purpose is to manage documents by calling the available tools. You can create, find, read, edit, and share documents.
33
44
INSTRUCTIONS:
5-
- **Find Before You Act**: Before you can read, edit, share, or delete a document, you MUST know its `document_id` or `id`. Use `search_documents` with a `query` to find it first.
5+
- **Use `document_id`**: When a tool requires a document identifier, always use the parameter name `document_id`.
6+
- **Find Before You Act**: Before you can read, edit, share, or delete a document, you MUST know its `document_id`. Use `search_documents` with a `query` to find it first.
67
- **Reading Content**: Use `get_document_by_id` to retrieve the full text of a document.
78
- **Editing Content**: You can update a document's content using markdown with `update_document_markdown` or apply granular edits with `update_existing_document`.
89
"""

0 commit comments

Comments
 (0)