replace broken native Jira/Linear tools with MCP equivalents

This commit is contained in:
CREDO23 2026-04-22 18:57:49 +02:00
parent f2d9e67ac2
commit 9452d1090a
2 changed files with 143 additions and 81 deletions

View file

@ -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
* 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
* Queries about services that have direct tools (Linear, ClickUp, Jira, Slack, Airtable) see <tool_routing> below
</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>
IMPORTANT After understanding each user message, ALWAYS check: does this message
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
* 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
* Queries about services that have direct tools (Linear, ClickUp, Jira, Slack, Airtable) see <tool_routing> below
</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>
IMPORTANT After understanding each user message, ALWAYS check: does this message
reveal durable facts about the team (decisions, conventions, architecture, processes,

View file

@ -78,16 +78,11 @@ from .google_drive import (
create_create_google_drive_file_tool,
create_delete_google_drive_file_tool,
)
from .jira import (
create_create_jira_issue_tool,
create_delete_jira_issue_tool,
create_update_jira_issue_tool,
)
from .linear import (
create_create_linear_issue_tool,
create_delete_linear_issue_tool,
create_update_linear_issue_tool,
)
# NOTE: Native Jira CRUD tools (create/update/delete_jira_issue) have been
# replaced by MCP equivalents (createJiraIssue, editJiraIssue). The native
# tools used the REST API which is incompatible with MCP-scoped OAuth tokens.
from .connected_accounts import create_get_connected_accounts_tool
# NOTE: Native Linear delete tool disabled — see comment in BUILTIN_TOOLS.
from .luma import (
create_create_luma_event_tool,
create_list_luma_events_tool,
@ -242,6 +237,21 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
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
# =========================================================================
ToolDefinition(
@ -269,42 +279,11 @@ BUILTIN_TOOLS: list[ToolDefinition] = [
],
),
# =========================================================================
# LINEAR TOOLS - create, update, delete issues
# Auto-disabled when no Linear connector is configured (see chat_deepagent.py)
# LINEAR TOOLS — create/update handled by MCP save_issue. Delete/archive
# 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
# 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",
),
# =========================================================================
# JIRA TOOLS - create, update, delete issues
# Auto-disabled when no Jira connector is configured (see chat_deepagent.py)
# JIRA TOOLS — Now fully handled by MCP (createJiraIssue, editJiraIssue,
# 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
# 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
logging.exception(f"Failed to load MCP tools: {e!s}")
# Log all tools being returned to agent
logging.info(
f"Total tools for agent: {len(tools)} - {[t.name for t in tools]}",
)