Jira Managed MCP Server
The Jira managed MCP server lets agents search, read, and manage Jira issues. It authenticates with either a shared API token (Basic authentication) or, for per-user identity, user-delegated OAuth. With OAuth it’s the enterprise counterpart to the Slack setup guide, and Atlassian’s flow has its own scope model and quirks worth calling out.
After reading this page, you will be able to:
-
Configure the Jira managed MCP server with Basic authentication or Atlassian’s OAuth flow
-
Pick the right scopes for the tools your agents use
-
Walk a user through the consent flow and verify the connection
What this MCP server does
The Jira managed type exposes the following read tools:
-
query: Search for issues using a JQL query. Returns the matching issues as JSON. -
get_issue: Retrieve a single issue by its key, for examplePROJ-123. -
list_projects: Return visible Jira projects, optionally filtered by a search query. -
get_transitions: Return the available workflow transitions for an issue.
It also exposes the following write tools:
-
create_issue: Create a new issue. -
update_issue: Update fields on an existing issue. -
transition_issue: Move an issue to a new workflow state. -
add_comment: Add a comment to an issue. -
add_worklog: Log time spent on an issue. -
create_issue_link: Create a directional link between two issues.
It can also expose Jira issues and projects as SQL-queryable tables, through two more tools. If SQL tools are available in your organization, SQL exposure is on by default for servers created in the UI. See Expose Jira data as SQL tables.
Prerequisites
-
A Jira (Atlassian Cloud) site and its base URL, for example
https://mycompany.atlassian.net. -
Credentials for one of the following authentication modes:
-
Basic Auth: An Atlassian account email and an API token fromid.atlassian.com, with the token stored in the Redpanda Agentic Data Plane secret store. -
User OAuth: Your own Atlassian OAuth 2.0 (3LO) app, created in the Atlassian developer console, plus an OAuth provider in Redpanda Agentic Data Plane that uses the Atlassian / Jira preset and carries the app’s client credentials. See Configure User-Delegated OAuth.
-
Atlassian’s scope model (user-delegated OAuth)
When you use user-delegated OAuth, Atlassian uses a granular, prefixed scope namespace. Request these scopes as a set:
| Scope | Allows |
|---|---|
|
Read Jira project and issue data and search for issues. Needed for the read tools. |
|
Create and edit issues, post comments, and create worklogs. Needed for the write tools. |
|
Issue a refresh token so Redpanda can refresh expired access tokens without asking the user to consent again. |
Every scope in the server’s Required scopes must also be in the OAuth provider’s scope list, and in the scopes you added to the Atlassian app in the developer console. The Atlassian / Jira preset requests read:jira-work, write:jira-work, read:confluence-content.all, and offline_access. A required scope the provider doesn’t request makes tool calls fail with scope_upgrade_required until each user reconnects and grants it. If the Atlassian app isn’t allowed to grant that scope, every tool call keeps failing.
|
Configure
-
Open MCP servers in the sidebar.
-
Click Add MCP server.
-
Click the Jira card in the marketplace picker.
-
Replace the suggested
Name, and optionally add aDescription. -
In the Jira configuration form:
-
Base URL: Your Jira instance URL, for examplehttps://mycompany.atlassian.net. -
Max Results Per Page(optional): Page size for thequerytool when a call doesn’t set one. Leave it at0to use the default,50. -
Auth: SelectBasic AuthorUser OAuth.-
For
Basic Auth: Provide the account email and the API-token secret reference. -
For
User OAuth: Pick the Atlassian OAuth provider you configured, and setRequired scopestoread:jira-workandoffline_access. Addwrite:jira-workif your agents use the write tools.
-
-
EnabledunderQueryable: On whenever the form shows it. Turn it off unless your agents need the two SQL tools. See Expose Jira data as SQL tables.
-
-
Click Create server.
To narrow which tables and columns the SQL tools expose, use the SQL exposure tab on the server’s page after you create it. See Narrow what the SQL tools expose.
The create form turns Enable code mode on by default for this server type. rpk ai mcp-server create has no code-mode flag. To add code mode from the CLI, create a Code MCP server named <server-name>-code with --code.mcp-servers <server-name>. See Code Mode.
Expose Jira data as SQL tables
The Jira server can present its data as read-only SQL tables instead of only as tools, so an agent can filter Jira records the way it would query a database. SQL exposure is the Enabled toggle under Queryable in the server’s configuration. If SQL tools are available in your organization, the create form shows Queryable with Enabled on, so a server you create there is queryable unless you turn it off. Otherwise the form doesn’t show Queryable, and the server starts with SQL exposure off. Creating a server with rpk ai leaves SQL exposure off unless the managed configuration sets it. An existing server keeps the setting it was saved with. To change it, open the server’s edit form, which shows Queryable if SQL tools are available in your organization or if the server was saved with SQL exposure on. SQL exposure adds two tools:
-
list_tables: Return the table catalog. For each table, the catalog lists its columns and their types, which columns can be filtered and with which operators, whether each filter is exact, the page-size limit, and a schema fingerprint that every query response repeats so a caller can tell when the catalog changed. -
execute_query: Run one query against a table and return a page of rows plus a cursor for the next page.
The execute_query tool reads Jira through the server’s configured authentication, so with user-delegated OAuth a query returns only the records the calling user can see, exactly as the other tools do. The list_tables tool returns the catalog, which is the same for every caller and carries no Jira data. With user-delegated OAuth, a caller who hasn’t connected an Atlassian account yet can still read the catalog and plan a query, while every other tool on the server, including execute_query, keeps asking for that connection. A list_tables call routed through the server’s code mode endpoint needs the connection too. Neither tool writes to Jira.
The tables are:
| Table | Contents |
|---|---|
|
Jira issues, from Jira’s issue search. Columns: |
|
Jira projects, from Jira’s project search. Columns: |
Not every column can be filtered. A filter is offered only where Jira’s search never drops a matching row, but most filters can return extra rows:
-
On
issues, filter onkey,project,issue_type,status, orpriorityfor a value or a list of up to 100 values, onassigneeorreporterby account ID (and onassignee, whether the issue is unassigned), and oncreatedorupdatedwith a time range. Matching onkey,project,issue_type,status, andpriorityis case-insensitive, so astatusfilter fordonealso returns issues inDone. A time range is widened by 15 hours on each side before it reaches Jira, so it can return issues created or updated outside the range. Only theassigneeandreporterfilters are exact. Thesummary,description, andlabelscolumns can be returned but not filtered. -
On
projects, filter onidorkeyfor a value or a list of up to 50 values, or ontypefor a single value. Matching onkeyandtypeis case-insensitive, and only theidfilter is exact. Thenamecolumn can be returned but not filtered. A query on this table takes one filter per column, and it can’t filter onidandkeytogether, so pick whichever identifier you have.
Because execute_query returns the rows Jira sends back without re-checking them against your filters, an agent that needs exact results must re-apply its filters to the rows it receives. The list_tables catalog marks which filters are exact.
A list longer than the cap fails rather than being silently cut short.
Two more limits are worth designing around:
-
Every query against
issuesneeds a filter. At least one predicate onkey,project,issue_type,status,priority,assignee,reporter,created, orupdatedis required, and an unfiltered query is refused before Jira is called. A query againstprojectshas no such requirement. -
A paged scan is best-effort. A page holds at most 100 rows for
issuesand 50 forprojects, and Jira keeps changing under a multi-page scan, so a long scan can miss a row or return one twice. A cursor is bound to the query that produced it. Reusing one with different filters or against another table is refused instead of quietly starting a new scan.
If a data policy masks a column you can also filter on, the mask hides that column’s values but not which rows carry them, because a caller who can run execute_query can still filter on it. The filterable columns on issues are key, project, issue_type, status, priority, assignee, reporter, created, and updated. On projects they are id, key, and type. A mask on a column that can’t be filtered, such as summary, description, labels, or name, isn’t exposed this way. See the data policy limitations.
With SQL exposure on, the two tools are available to every caller of the server, including agents. Turn off Enabled on a server whose agents should only reach the curated Jira tools.
|
Narrow what the SQL tools expose
A curator can trim the catalog that list_tables reports, table by table, from the SQL exposure tab on the server’s own page. The tab’s Enable SQL for this server button is the same setting as Enabled in the server’s configuration, and the tab lists the tables only while SQL is on. The card holding that button says which state the server is in and how many tables turning SQL off would withdraw after you save. Turning it off leaves your saved table settings in place and doesn’t affect the server’s other tools. With SQL on, the tab lists the tables the server can expose, and for the table you select, which of its columns the catalog reports and which of those it offers as filters. For each table you can:
-
Hide the table completely, with the Exposed switch on the table’s card. The
Tableslist marks ithidden, and marks a table you changed in other ways with the number of changes. -
Hide columns but keep the table.
-
Keep a column visible in the catalog and stop offering it as a filter. The catalog no longer declares a filter on that column, so
execute_queryrefuses a predicate on it and a caller has to apply the condition to the rows it reads back. -
Add filter requirements on top of the ones the table already carries. Each requirement must name at least one column that survives your other changes, and a query has to filter on at least one column of every requirement.
-
Serve a column as a different SQL type than the table declares. The column’s
Typelist offers text, bigint, double precision, boolean, timestamptz, date, and json. It labels the table’s own typederived, and labels a type the column can’t convert tonot allowed. A value that doesn’t convert is served as SQLNULL, so a retyped column is nullable, and it’s no longer offered as a filter, which meansexecute_queryrefuses a predicate on it and a caller has to filter the rows it reads back. A timestamp served asdatekeeps its UTC calendar date. -
Serve the table under another name, which changes the name every query has to use.
Click Save to apply your changes, or Discard to drop them.
Set a new table name in the SQL name field on the selected table. Use lowercase letters, digits, and underscores, starting with a letter or an underscore, up to 63 characters. A name that’s a SQL keyword, that’s the other table’s own name, or that you already gave to the other table is refused when you save. Reset puts the original name back, and a renamed table carries a served as badge. An excluded table can’t carry a rename.
| Renaming a table breaks every SQL tool built on the old name until that tool is updated. Saving a rename asks you to confirm, and the confirmation lists the renames along with the SQL tools it found that query a renamed table. Only tools you have access to are checked, and the confirmation tells you when the check couldn’t run at all. |
When the confirmation found dependent tools, it offers to fix them for you. Click Rename and update tools to point each one at the new name, or click Rename anyway to rename now and fix them yourself later. Either way the rename is saved. After an update, the dialog reports each tool as updated, as already using the new name, or as not updated with the reason, so a tool that failed is named rather than left to surface as a broken query.
None of these settings widens what the SQL tools can do. You can’t make a column filterable that Jira can’t filter on, and you can’t add a table. Renaming a table or retyping a column changes how its data is served, not what Jira’s search can do with it. Hiding a column also removes it from the table’s filter requirements, which is fine until a requirement loses every column it named. A query against issues needs one predicate from a single requirement holding all nine of its filterable columns, so you can hide eight of them and the table still works. Hiding all nine is refused, with a message telling you to exclude the table instead.
The tab’s Read-only boundary card shows how the server’s read operations were split. Under Became SQL tables, it lists each operation with the table it produced, marked hidden when you hid that table. Under Stayed direct tools, it lists each remaining operation with the reason it produced no table. Read it to confirm that an operation you expected to query as a table actually became one.
The tab’s Test query card runs a read-only query against the tables this server exposes, so you can check that the types, the filters, and the filter requirements behave the way you set them. It offers example queries to start from, runs as you with data policies applied, and uses your settings as saved. Unsaved edits don’t reach a test run, so save first. Until you do, the card says so and stays disabled. It’s also disabled while the server itself is disabled, while SQL exposure is off in the saved configuration, and when the server has no catalog to test.
If the server’s page has no SQL exposure tab, narrowing isn’t enabled for your organization. The Enabled setting on the server’s configuration still turns the two SQL tools on and off.
Test the consent flow
-
Open the Inspector tab.
-
Run the
querytool with a small JQL filter. -
The first call fails with a connection-required result that carries an Atlassian authorization URL.
-
Open the authorization URL. Atlassian asks you to pick a site (Cloud instance) and approve the scopes.
-
Atlassian redirects back. Your connection appears under Connections.
-
Run the search again. Results come back.
Use with agents
Point an agent at the Server URL on the server’s Connection tab. Each user who calls the agent triggers their own consent flow on their first call.
With user-delegated OAuth, set the server’s required_scopes to every scope your agents' tools need before users connect. An Atlassian app can request only scopes you’ve already added to it in the developer console, and if you widen required_scopes later, users who already connected have to consent again.
Troubleshooting
| Symptom | What to check |
|---|---|
|
|
"Resource not found" for a project the user has access to |
Atlassian’s OAuth grants are site-scoped. The user authorized for one Cloud instance. The project lives on another. They need to re-consent with the second site. |
|
The server’s required scopes were extended after users consented, so users reconnect to grant them. If it persists after reconnecting, a required scope is missing from the provider’s scopes or from the Atlassian app. |
|
Refresh tokens expire if unused for ~90 days. The user re-consents. |
Limitations
-
Atlassian app management: The OAuth app and its callback URLs are managed in
developer.atlassian.com, not in Agentic Data Plane. -
Jira Server / Data Center (self-hosted): This MCP type targets Atlassian Cloud. Self-hosted Jira may need a self-managed MCP server instead. See Register a self-managed MCP server.
-
Confluence access: Confluence uses a separate scope namespace. This MCP server doesn’t expose Confluence.
-
SQL exposure is read-only: The
execute_querytool reads issues and projects. Use the write tools to change anything in Jira. See Expose Jira data as SQL tables.