get_accessible_resources
Retrieve accessible Jira resources for a user by email to determine available projects and permissions for issue management.
Instructions
Fetches a list of resources the user has access to.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| userEmail | Yes | The email of the user accessing the resources. |
Implementation Reference
- src/tools/getAccessibleResources.ts:6-36 (handler)The main handler function that registers and implements the 'get_accessible_resources' tool. It validates the userEmail input using Zod schema, fetches cached data via getUpdatedCachedData helper, and returns the resources list or an error message if authorization is needed.
export function getAccessibleResourcesTool(server: McpServer) { server.tool('get_accessible_resources', 'Fetches a list of resources the user has access to.', { userEmail: z.string().email().describe("The email of the user accessing the resources.") }, async ({ userEmail }) => { const cacheData = await getUpdatedCachedData(userEmail); if(!cacheData) { return { isError: true, content: [ { type: "text", text: `Please try again after user confirmed that he authorized the app to access the Jira data.`, }, ], }; } return { content: [ { type: "text", text: JSON.stringify(cacheData.resources), }, ], } }); } - Input schema definition using Zod - validates that userEmail is a valid email address and provides a description for the parameter.
{ userEmail: z.string().email().describe("The email of the user accessing the resources.") }, - src/tools/index.ts:4-9 (registration)Registration point where getAccessibleResourcesTool is imported and invoked within the registerTools function to register the tool with the MCP server.
import {getAccessibleResourcesTool} from "./getAccessibleResources.js"; export function registerTools(server: McpServer) { createIssueTool(server); getProjectsTool(server); getAccessibleResourcesTool(server); - src/utils/cacheData.ts:10-51 (helper)Helper function getUpdatedCachedData that retrieves cached user data from Redis, handles OAuth token refresh if expired, and returns the CacheData containing resources, or null if authorization is needed.
export async function getUpdatedCachedData(userEmail: string): Promise<CacheData | null> { const cacheStr = await redisClient.get(userEmail); if(!cacheStr) { const authUrl = getAuthorizationUri(); await open(authUrl); return null; } const decompressed = await decompress(cacheStr); const data = JSON.parse(decompressed) as CacheData; const decodedToken = jwt.decode(data.accessToken) as JwtPayload; let accessToken = oauthClient.createToken({ access_token: data.accessToken, expires_at: decodedToken.expires_at || new Date((decodedToken.exp as number) * Constants.MILLISECOND_DIFFERENCE).toISOString(), token_type: 'Bearer', scope: decodedToken.scope || 'read:jira-user read:jira-work write:jira-work read:me' }); if(accessToken.expired()) { try { accessToken = await accessToken.refresh(); data.accessToken = accessToken.token.access_token as string; const expiration = new Date((decodedToken.exp as number) * Constants.MILLISECOND_DIFFERENCE + Constants.DAY_IN_MS).getTime() - Date.now(); const compressedData = await compress(JSON.stringify(data)); await redisClient.setex(userEmail, expiration, compressedData); return data; } catch (error) { logger.error('Error refreshing access token:', error); const authUrl = getAuthorizationUri(); await open(authUrl); return null; } } return data; } - src/models/cacheData.ts:2-13 (schema)Type definition for CacheData which includes accessToken, userInfo (accountId, email, displayName), and resources (id, url) - this defines the structure of the data returned by the tool.
export type CacheData = { accessToken: string; userInfo: { accountId: string; email: string; displayName: string; }, resources: { id: string; url: string; } }