Tools & Connectors
Project Management
Jira and Linear toolsets.
#Project management
Issue trackers and team-planning tools. Every connector follows the
standard @toolset / @toolify shape and the agent-ready toolset
pattern (compact summaries by default, opt-in raw IDs, tolerant write
inputs).
#JiraToolSet
JiraToolSet wraps the Atlassian Jira Cloud REST API v3 (with a small
slice of the Jira Agile API for boards and sprints). It authenticates
with HTTP Basic auth using your Atlassian email and an API token issued
at https://id.atlassian.com/manage-profile/security/api-tokens.
from maivn import Agentfrom maivn_tools import JiraToolSet, register_connector connector = JiraToolSet( base_url="https://acme.atlassian.net", email="ops@acme.com", api_token=secrets["JIRA_API_TOKEN"],)agent = Agent(model="auto")register_connector(agent, connector)#Tools
Identity. myself.
Issues. search_issues (JQL), get_issue, list_transitions,create_issue, update_issue, transition_issue, assign_issue,delete_issue (destructive).
Comments and worklog. list_comments, add_comment,update_comment, delete_comment (destructive), list_worklogs,add_worklog.
Links and attachments. link_issues, delete_issue_link
(destructive), list_attachments, delete_attachment (destructive).
Projects, users, metadata. list_projects, get_project,list_issue_types, get_user, search_users, list_statuses,list_priorities, list_resolutions, list_fields.
Agile (boards, sprints, versions). list_boards, list_sprints,get_sprint, list_versions.
extra_fields on create_issue is merged into the request payload so
the caller can set custom fields (e.g. customfield_10010).
#Agent-ready behavior
search_issuesreturns compact summaries by default. Each summary
carries a stableissue_ref(issue_1,issue_2, ...) plus the
issuekey(e.g.ENG-123— the canonical user-facing handle),summary,status,assignee,priority,issue_type, andupdated. The issue key is safe to surface in final answers.list_projectsreturns the same compact shape with a stableproject_ref(project_1, ...) plus the projectkey,name,type, andlead.- Default
max_resultsis 25 onsearch_issues(max 100) and 25 onlist_projects. - Jira numeric
idvalues are hidden by default on both tools. Passinclude_ids=Trueto addissue_idorproject_idto each summary
— the issue key is normally enough, raw IDs are internal handles. - Pass
include_metadata=Falseonsearch_issuesorlist_projects
to receive the raw Jira response, includingstartAt,total, andisLastfor pagination. get_issue,update_issue,add_comment,transition_issue,assign_issue,delete_issue,list_comments,list_transitions,list_worklogs,add_worklog, andlist_attachmentsaccept either
a key string ("ENG-123"), a summary dict fromsearch_issues, or
a list of such dicts. The connector resolves the key fromkey,issue_key, orissueKey.
#Destructive tools
delete_issue, delete_comment, delete_issue_link, anddelete_attachment carry destructive=True. Issue and link deletes
are permanent — confirm with the user, or filter them out withexclude_tags=["destructive"].
#Example: summary-mode search
agent.add_toolset(JiraToolSet(base_url="https://acme.atlassian.net", email="ops@acme.com", api_token=secrets["JIRA_API_TOKEN"])) response = connector.search_issues( "project = ENG AND status = 'In Progress' ORDER BY updated DESC", max_results=10,)# response == {# "issues": [# {"issue_ref": "issue_1", "key": "ENG-512",# "summary": "Fix login flakiness", "status": "In Progress",# "assignee": "Casey K.", "priority": "High",# "issue_type": "Bug", "updated": "..."},# ...# ],# "startAt": 0, "maxResults": 10, "total": 3,# }The key is enough to drive follow-up actions — no include_ids round
trip required:
hits = connector.search_issues("assignee = currentUser()")["issues"]connector.transition_issue(hits[0], transition_id="31")#Live tests
Set MAIVN_TOOLS_JIRA_LIVE_BASE_URL, MAIVN_TOOLS_JIRA_LIVE_EMAIL, andMAIVN_TOOLS_JIRA_LIVE_TOKEN to exercise the connector against a
sandbox Jira Cloud site. See testing.md.
#LinearToolSet
LinearToolSet wraps the
Linear GraphQL API.
from maivn_tools import LinearToolSet connector = LinearToolSet(api_key=secrets["LINEAR_API_KEY"])Pass use_bearer=True if the credential is an OAuth bearer rather
than a personal API key.
#Tools
viewer, list_teams, list_users, list_projects, list_cycles,list_issues (filter follows Linear's IssueFilter shape),get_issue (UUID or shortcut like ENG-123), create_issue,update_issue, archive_issue (destructive), list_comments,create_comment, graphql (escape hatch for arbitrary
queries / mutations).
#Agent-ready behavior
list_issuesreturns compact summaries by default. Each summary
carries a stableissue_ref(issue_1,issue_2, ...) plus the
Linearidentifier(e.g.ENG-123— the canonical user-facing
handle),title,status,priority,assignee,teamkey,updated_at, andurl. The identifier is safe to show in final
answers.- Default
firstis 25 onlist_issues,list_teams,list_users,list_projects, andlist_cycles(max 250). - The GraphQL
id(UUID) is hidden by default onlist_issues. Passinclude_ids=Trueto addissue_idto each summary — only needed
for tools that explicitly require the UUID; most operations accept
the identifier directly. - Pass
include_metadata=Falseonlist_issuesto receive the raw
Linear{"issues": {"nodes": [...], "pageInfo": ...}}response.
The other list tools always return the raw GraphQL payload. get_issue,update_issue,archive_issue,list_comments, andcreate_commentaccept either a Linear identifier string
("ENG-123"), a UUID string, a summary dict fromlist_issues, or
a list of such dicts. The connector resolves the handle fromidentifier,issue_id, orid.
#Destructive tools
archive_issue carries destructive=True. Archive is a soft-delete
(recoverable through the Linear UI), but should still be confirmed
with the user, or filtered out with exclude_tags=["destructive"].graphql is gated with READ permission; if you need raw mutations,
gate it behind a write permission in your own override.
#Example: summary-mode list
agent.add_toolset(LinearToolSet(api_key=secrets["LINEAR_API_KEY"])) response = connector.list_issues( filter={"team": {"key": {"eq": "ENG"}}, "state": {"name": {"eq": "Todo"}}}, first=10,)# response == {# "issues": [# {"issue_ref": "issue_1", "identifier": "ENG-512",# "title": "Fix login flakiness", "status": "Todo",# "priority": 2, "assignee": "Casey K.", "team": "ENG",# "updated_at": "...", "url": "https://linear.app/..."},# ...# ],# "pageInfo": {"hasNextPage": False, "endCursor": "..."},# }The identifier is enough to drive follow-up actions:
hits = connector.list_issues( filter={"assignee": {"isMe": {"eq": True}}})["issues"]connector.create_comment(issue_id=hits[0], body="Picking this up.")