mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-17 18:35:19 +02:00
replace broken native Jira/Linear tools with MCP equivalents
This commit is contained in:
parent
f2d9e67ac2
commit
9452d1090a
2 changed files with 143 additions and 81 deletions
|
|
@ -38,8 +38,66 @@ CRITICAL RULE — KNOWLEDGE BASE FIRST, NEVER DEFAULT TO GENERAL KNOWLEDGE:
|
||||||
* Formatting, summarization, or analysis of content already present in the conversation
|
* Formatting, summarization, or analysis of content already present in the conversation
|
||||||
* Following user instructions that are clearly task-oriented (e.g., "rewrite this in bullet points")
|
* Following user instructions that are clearly task-oriented (e.g., "rewrite this in bullet points")
|
||||||
* Tool-usage actions like generating reports, podcasts, images, or scraping webpages
|
* Tool-usage actions like generating reports, podcasts, images, or scraping webpages
|
||||||
|
* Queries about services that have direct tools (Linear, ClickUp, Jira, Slack, Airtable) — see <tool_routing> below
|
||||||
</knowledge_base_only_policy>
|
</knowledge_base_only_policy>
|
||||||
|
|
||||||
|
<tool_routing>
|
||||||
|
CRITICAL — You have direct tools for these services: Linear, ClickUp, Jira, Slack, Airtable.
|
||||||
|
Their data is NEVER in the knowledge base. You MUST call their tools immediately — never
|
||||||
|
say "I don't see it in the knowledge base" or ask the user if they want you to check.
|
||||||
|
Ignore any knowledge base results for these services.
|
||||||
|
|
||||||
|
When to use which tool:
|
||||||
|
- Linear (issues) → list_issues, get_issue, save_issue (create/update)
|
||||||
|
- ClickUp (tasks) → clickup_search, clickup_get_task
|
||||||
|
- Jira (issues) → getAccessibleAtlassianResources (cloudId discovery), getVisibleJiraProjects (project discovery), getJiraProjectIssueTypesMetadata (issue type discovery), searchJiraIssuesUsingJql, createJiraIssue, editJiraIssue
|
||||||
|
- Slack (messages, channels) → slack_search_channels, slack_read_channel, slack_read_thread
|
||||||
|
- Airtable (bases, tables, records) → list_bases, list_tables_for_base, list_records_for_table
|
||||||
|
- Knowledge base content (Notion, GitHub, files, notes) → automatically searched
|
||||||
|
- Real-time public web data → call web_search
|
||||||
|
- Reading a specific webpage → call scrape_webpage
|
||||||
|
</tool_routing>
|
||||||
|
|
||||||
|
<parameter_resolution>
|
||||||
|
Some service tools require identifiers or context you do not have (account IDs,
|
||||||
|
workspace names, channel IDs, project keys, etc.). NEVER ask the user for raw
|
||||||
|
IDs or technical identifiers — they cannot memorise them.
|
||||||
|
|
||||||
|
Instead, follow this discovery pattern:
|
||||||
|
1. Call a listing/discovery tool to find available options.
|
||||||
|
2. ONE result → use it silently, no question to the user.
|
||||||
|
3. MULTIPLE results → present the options by their display names and let the
|
||||||
|
user choose. Never show raw UUIDs — always use friendly names.
|
||||||
|
|
||||||
|
Discovery tools by level:
|
||||||
|
- Which account/workspace? → get_connected_accounts("<service>")
|
||||||
|
- Which Jira site (cloudId)? → getAccessibleAtlassianResources
|
||||||
|
- Which Jira project? → getVisibleJiraProjects (after resolving cloudId)
|
||||||
|
- Which Jira issue type? → getJiraProjectIssueTypesMetadata (after resolving project)
|
||||||
|
- Which channel? → slack_search_channels
|
||||||
|
- Which base? → list_bases
|
||||||
|
- Which table? → list_tables_for_base (after resolving baseId)
|
||||||
|
- Which task? → clickup_search
|
||||||
|
- Which issue? → list_issues (Linear) or searchJiraIssuesUsingJql (Jira)
|
||||||
|
|
||||||
|
For Jira specifically: ALWAYS call getAccessibleAtlassianResources first to
|
||||||
|
obtain the cloudId, then pass it to other Jira tools. When creating an issue,
|
||||||
|
chain: getAccessibleAtlassianResources → getVisibleJiraProjects → createJiraIssue.
|
||||||
|
If there is only one option at each step, use it silently. If multiple, present
|
||||||
|
friendly names.
|
||||||
|
|
||||||
|
Chain discovery when needed — e.g. for Airtable records: list_bases → pick
|
||||||
|
base → list_tables_for_base → pick table → list_records_for_table.
|
||||||
|
|
||||||
|
MULTI-ACCOUNT TOOL NAMING: When the user has multiple accounts connected for
|
||||||
|
the same service, tool names are prefixed to avoid collisions — e.g.
|
||||||
|
linear_25_list_issues and linear_30_list_issues instead of two list_issues.
|
||||||
|
Each prefixed tool's description starts with [Account: <display_name>] so you
|
||||||
|
know which account it targets. Use get_connected_accounts("<service>") to see
|
||||||
|
the full list of accounts with their connector IDs and display names.
|
||||||
|
When only one account is connected, tools have their normal unprefixed names.
|
||||||
|
</parameter_resolution>
|
||||||
|
|
||||||
<memory_protocol>
|
<memory_protocol>
|
||||||
IMPORTANT — After understanding each user message, ALWAYS check: does this message
|
IMPORTANT — After understanding each user message, ALWAYS check: does this message
|
||||||
reveal durable facts about the user (role, interests, preferences, projects,
|
reveal durable facts about the user (role, interests, preferences, projects,
|
||||||
|
|
@ -76,8 +134,66 @@ CRITICAL RULE — KNOWLEDGE BASE FIRST, NEVER DEFAULT TO GENERAL KNOWLEDGE:
|
||||||
* Formatting, summarization, or analysis of content already present in the conversation
|
* Formatting, summarization, or analysis of content already present in the conversation
|
||||||
* Following user instructions that are clearly task-oriented (e.g., "rewrite this in bullet points")
|
* Following user instructions that are clearly task-oriented (e.g., "rewrite this in bullet points")
|
||||||
* Tool-usage actions like generating reports, podcasts, images, or scraping webpages
|
* Tool-usage actions like generating reports, podcasts, images, or scraping webpages
|
||||||
|
* Queries about services that have direct tools (Linear, ClickUp, Jira, Slack, Airtable) — see <tool_routing> below
|
||||||
</knowledge_base_only_policy>
|
</knowledge_base_only_policy>
|
||||||
|
|
||||||
|
<tool_routing>
|
||||||
|
CRITICAL — You have direct tools for these services: Linear, ClickUp, Jira, Slack, Airtable.
|
||||||
|
Their data is NEVER in the knowledge base. You MUST call their tools immediately — never
|
||||||
|
say "I don't see it in the knowledge base" or ask if they want you to check.
|
||||||
|
Ignore any knowledge base results for these services.
|
||||||
|
|
||||||
|
When to use which tool:
|
||||||
|
- Linear (issues) → list_issues, get_issue, save_issue (create/update)
|
||||||
|
- ClickUp (tasks) → clickup_search, clickup_get_task
|
||||||
|
- Jira (issues) → getAccessibleAtlassianResources (cloudId discovery), getVisibleJiraProjects (project discovery), getJiraProjectIssueTypesMetadata (issue type discovery), searchJiraIssuesUsingJql, createJiraIssue, editJiraIssue
|
||||||
|
- Slack (messages, channels) → slack_search_channels, slack_read_channel, slack_read_thread
|
||||||
|
- Airtable (bases, tables, records) → list_bases, list_tables_for_base, list_records_for_table
|
||||||
|
- Knowledge base content (Notion, GitHub, files, notes) → automatically searched
|
||||||
|
- Real-time public web data → call web_search
|
||||||
|
- Reading a specific webpage → call scrape_webpage
|
||||||
|
</tool_routing>
|
||||||
|
|
||||||
|
<parameter_resolution>
|
||||||
|
Some service tools require identifiers or context you do not have (account IDs,
|
||||||
|
workspace names, channel IDs, project keys, etc.). NEVER ask the user for raw
|
||||||
|
IDs or technical identifiers — they cannot memorise them.
|
||||||
|
|
||||||
|
Instead, follow this discovery pattern:
|
||||||
|
1. Call a listing/discovery tool to find available options.
|
||||||
|
2. ONE result → use it silently, no question to the user.
|
||||||
|
3. MULTIPLE results → present the options by their display names and let the
|
||||||
|
user choose. Never show raw UUIDs — always use friendly names.
|
||||||
|
|
||||||
|
Discovery tools by level:
|
||||||
|
- Which account/workspace? → get_connected_accounts("<service>")
|
||||||
|
- Which Jira site (cloudId)? → getAccessibleAtlassianResources
|
||||||
|
- Which Jira project? → getVisibleJiraProjects (after resolving cloudId)
|
||||||
|
- Which Jira issue type? → getJiraProjectIssueTypesMetadata (after resolving project)
|
||||||
|
- Which channel? → slack_search_channels
|
||||||
|
- Which base? → list_bases
|
||||||
|
- Which table? → list_tables_for_base (after resolving baseId)
|
||||||
|
- Which task? → clickup_search
|
||||||
|
- Which issue? → list_issues (Linear) or searchJiraIssuesUsingJql (Jira)
|
||||||
|
|
||||||
|
For Jira specifically: ALWAYS call getAccessibleAtlassianResources first to
|
||||||
|
obtain the cloudId, then pass it to other Jira tools. When creating an issue,
|
||||||
|
chain: getAccessibleAtlassianResources → getVisibleJiraProjects → createJiraIssue.
|
||||||
|
If there is only one option at each step, use it silently. If multiple, present
|
||||||
|
friendly names.
|
||||||
|
|
||||||
|
Chain discovery when needed — e.g. for Airtable records: list_bases → pick
|
||||||
|
base → list_tables_for_base → pick table → list_records_for_table.
|
||||||
|
|
||||||
|
MULTI-ACCOUNT TOOL NAMING: When the user has multiple accounts connected for
|
||||||
|
the same service, tool names are prefixed to avoid collisions — e.g.
|
||||||
|
linear_25_list_issues and linear_30_list_issues instead of two list_issues.
|
||||||
|
Each prefixed tool's description starts with [Account: <display_name>] so you
|
||||||
|
know which account it targets. Use get_connected_accounts("<service>") to see
|
||||||
|
the full list of accounts with their connector IDs and display names.
|
||||||
|
When only one account is connected, tools have their normal unprefixed names.
|
||||||
|
</parameter_resolution>
|
||||||
|
|
||||||
<memory_protocol>
|
<memory_protocol>
|
||||||
IMPORTANT — After understanding each user message, ALWAYS check: does this message
|
IMPORTANT — After understanding each user message, ALWAYS check: does this message
|
||||||
reveal durable facts about the team (decisions, conventions, architecture, processes,
|
reveal durable facts about the team (decisions, conventions, architecture, processes,
|
||||||
|
|
|
||||||
|
|
@ -78,16 +78,11 @@ from .google_drive import (
|
||||||
create_create_google_drive_file_tool,
|
create_create_google_drive_file_tool,
|
||||||
create_delete_google_drive_file_tool,
|
create_delete_google_drive_file_tool,
|
||||||
)
|
)
|
||||||
from .jira import (
|
# NOTE: Native Jira CRUD tools (create/update/delete_jira_issue) have been
|
||||||
create_create_jira_issue_tool,
|
# replaced by MCP equivalents (createJiraIssue, editJiraIssue). The native
|
||||||
create_delete_jira_issue_tool,
|
# tools used the REST API which is incompatible with MCP-scoped OAuth tokens.
|
||||||
create_update_jira_issue_tool,
|
from .connected_accounts import create_get_connected_accounts_tool
|
||||||
)
|
# NOTE: Native Linear delete tool disabled — see comment in BUILTIN_TOOLS.
|
||||||
from .linear import (
|
|
||||||
create_create_linear_issue_tool,
|
|
||||||
create_delete_linear_issue_tool,
|
|
||||||
create_update_linear_issue_tool,
|
|
||||||
)
|
|
||||||
from .luma import (
|
from .luma import (
|
||||||
create_create_luma_event_tool,
|
create_create_luma_event_tool,
|
||||||
create_list_luma_events_tool,
|
create_list_luma_events_tool,
|
||||||
|
|
@ -242,6 +237,21 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
||||||
requires=["db_session"],
|
requires=["db_session"],
|
||||||
),
|
),
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
|
# SERVICE ACCOUNT DISCOVERY
|
||||||
|
# Generic tool for the LLM to discover connected accounts and resolve
|
||||||
|
# service-specific identifiers (e.g. Jira cloudId, Slack team, etc.)
|
||||||
|
# =========================================================================
|
||||||
|
ToolDefinition(
|
||||||
|
name="get_connected_accounts",
|
||||||
|
description="Discover connected accounts for a service and their metadata",
|
||||||
|
factory=lambda deps: create_get_connected_accounts_tool(
|
||||||
|
db_session=deps["db_session"],
|
||||||
|
search_space_id=deps["search_space_id"],
|
||||||
|
user_id=deps["user_id"],
|
||||||
|
),
|
||||||
|
requires=["db_session", "search_space_id", "user_id"],
|
||||||
|
),
|
||||||
|
# =========================================================================
|
||||||
# MEMORY TOOL - single update_memory, private or team by thread_visibility
|
# MEMORY TOOL - single update_memory, private or team by thread_visibility
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
ToolDefinition(
|
ToolDefinition(
|
||||||
|
|
@ -269,42 +279,11 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# LINEAR TOOLS - create, update, delete issues
|
# LINEAR TOOLS — create/update handled by MCP save_issue. Delete/archive
|
||||||
# Auto-disabled when no Linear connector is configured (see chat_deepagent.py)
|
# is NOT available: the official Linear MCP server does not expose a
|
||||||
|
# delete tool, and the native tool's GraphQL API call fails with
|
||||||
|
# MCP-scoped tokens (401). Re-enable when Linear adds MCP delete support.
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
ToolDefinition(
|
|
||||||
name="create_linear_issue",
|
|
||||||
description="Create a new issue in the user's Linear workspace",
|
|
||||||
factory=lambda deps: create_create_linear_issue_tool(
|
|
||||||
db_session=deps["db_session"],
|
|
||||||
search_space_id=deps["search_space_id"],
|
|
||||||
user_id=deps["user_id"],
|
|
||||||
),
|
|
||||||
requires=["db_session", "search_space_id", "user_id"],
|
|
||||||
required_connector="LINEAR_CONNECTOR",
|
|
||||||
),
|
|
||||||
ToolDefinition(
|
|
||||||
name="update_linear_issue",
|
|
||||||
description="Update an existing indexed Linear issue",
|
|
||||||
factory=lambda deps: create_update_linear_issue_tool(
|
|
||||||
db_session=deps["db_session"],
|
|
||||||
search_space_id=deps["search_space_id"],
|
|
||||||
user_id=deps["user_id"],
|
|
||||||
),
|
|
||||||
requires=["db_session", "search_space_id", "user_id"],
|
|
||||||
required_connector="LINEAR_CONNECTOR",
|
|
||||||
),
|
|
||||||
ToolDefinition(
|
|
||||||
name="delete_linear_issue",
|
|
||||||
description="Archive (delete) an existing indexed Linear issue",
|
|
||||||
factory=lambda deps: create_delete_linear_issue_tool(
|
|
||||||
db_session=deps["db_session"],
|
|
||||||
search_space_id=deps["search_space_id"],
|
|
||||||
user_id=deps["user_id"],
|
|
||||||
),
|
|
||||||
requires=["db_session", "search_space_id", "user_id"],
|
|
||||||
required_connector="LINEAR_CONNECTOR",
|
|
||||||
),
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# NOTION TOOLS - create, update, delete pages
|
# NOTION TOOLS - create, update, delete pages
|
||||||
# Auto-disabled when no Notion connector is configured (see chat_deepagent.py)
|
# Auto-disabled when no Notion connector is configured (see chat_deepagent.py)
|
||||||
|
|
@ -539,42 +518,10 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
|
||||||
required_connector="GOOGLE_GMAIL_CONNECTOR",
|
required_connector="GOOGLE_GMAIL_CONNECTOR",
|
||||||
),
|
),
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# JIRA TOOLS - create, update, delete issues
|
# JIRA TOOLS — Now fully handled by MCP (createJiraIssue, editJiraIssue,
|
||||||
# Auto-disabled when no Jira connector is configured (see chat_deepagent.py)
|
# searchJiraIssuesUsingJql, etc.). Native tools removed because the
|
||||||
|
# MCP-scoped OAuth token cannot call the Jira REST API.
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
ToolDefinition(
|
|
||||||
name="create_jira_issue",
|
|
||||||
description="Create a new issue in the user's Jira project",
|
|
||||||
factory=lambda deps: create_create_jira_issue_tool(
|
|
||||||
db_session=deps["db_session"],
|
|
||||||
search_space_id=deps["search_space_id"],
|
|
||||||
user_id=deps["user_id"],
|
|
||||||
),
|
|
||||||
requires=["db_session", "search_space_id", "user_id"],
|
|
||||||
required_connector="JIRA_CONNECTOR",
|
|
||||||
),
|
|
||||||
ToolDefinition(
|
|
||||||
name="update_jira_issue",
|
|
||||||
description="Update an existing indexed Jira issue",
|
|
||||||
factory=lambda deps: create_update_jira_issue_tool(
|
|
||||||
db_session=deps["db_session"],
|
|
||||||
search_space_id=deps["search_space_id"],
|
|
||||||
user_id=deps["user_id"],
|
|
||||||
),
|
|
||||||
requires=["db_session", "search_space_id", "user_id"],
|
|
||||||
required_connector="JIRA_CONNECTOR",
|
|
||||||
),
|
|
||||||
ToolDefinition(
|
|
||||||
name="delete_jira_issue",
|
|
||||||
description="Delete an existing indexed Jira issue",
|
|
||||||
factory=lambda deps: create_delete_jira_issue_tool(
|
|
||||||
db_session=deps["db_session"],
|
|
||||||
search_space_id=deps["search_space_id"],
|
|
||||||
user_id=deps["user_id"],
|
|
||||||
),
|
|
||||||
requires=["db_session", "search_space_id", "user_id"],
|
|
||||||
required_connector="JIRA_CONNECTOR",
|
|
||||||
),
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# CONFLUENCE TOOLS - create, update, delete pages
|
# CONFLUENCE TOOLS - create, update, delete pages
|
||||||
# Auto-disabled when no Confluence connector is configured (see chat_deepagent.py)
|
# Auto-disabled when no Confluence connector is configured (see chat_deepagent.py)
|
||||||
|
|
@ -902,7 +849,6 @@ async def build_tools_async(
|
||||||
# Log error but don't fail - just continue without MCP tools
|
# Log error but don't fail - just continue without MCP tools
|
||||||
logging.exception(f"Failed to load MCP tools: {e!s}")
|
logging.exception(f"Failed to load MCP tools: {e!s}")
|
||||||
|
|
||||||
# Log all tools being returned to agent
|
|
||||||
logging.info(
|
logging.info(
|
||||||
f"Total tools for agent: {len(tools)} - {[t.name for t in tools]}",
|
f"Total tools for agent: {len(tools)} - {[t.name for t in tools]}",
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue