sync_metadata
Fetch and cache all MantisBT projects, users, versions, categories, and tags to provide a complete overview of your installation. Refresh stale data to maintain accurate metadata for issue management.
Instructions
Fetch all projects and their associated users, versions, categories, and tags from MantisBT and store them in the local metadata cache.
Tags are fetched via the dedicated GET /tags endpoint when available. On installations where that endpoint is missing (MantisBT < 2.26), tags are collected by scanning all issues across all projects.
This is useful for getting a complete overview of your MantisBT installation. The cache is valid for 24 hours by default (configurable via MANTIS_CACHE_TTL env var). Use this tool to refresh stale data.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/metadata.ts:181-201 (handler)The handler implementation for the `sync_metadata` tool, which calls `fetchAndCacheMetadata` to update the project metadata.
async () => { try { const data = await fetchAndCacheMetadata(client, cache); const projectCount = data.projects.length; const summary = data.projects.map((p) => { const meta = data.byProject[p.id]; return ` - ${p.name} (ID ${p.id}): ${meta?.users.length ?? 0} users, ${meta?.versions.length ?? 0} versions, ${meta?.categories.length ?? 0} categories`; }).join('\n'); return { content: [{ type: 'text', text: `Metadata synced successfully.\n\n${projectCount} project(s):\n${summary}\n\nGlobal tags: ${data.tags.length}`, }], }; } catch (error) { const msg = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text', text: errorText(msg) }], isError: true }; } } ); - src/tools/metadata.ts:163-180 (registration)Tool registration for `sync_metadata` in `registerMetadataTools`.
server.registerTool( 'sync_metadata', { title: 'Sync Metadata Cache', description: `Fetch all projects and their associated users, versions, categories, and tags from MantisBT and store them in the local metadata cache. Tags are fetched via the dedicated GET /tags endpoint when available. On installations where that endpoint is missing (MantisBT < 2.26), tags are collected by scanning all issues across all projects. This is useful for getting a complete overview of your MantisBT installation. The cache is valid for 24 hours by default (configurable via MANTIS_CACHE_TTL env var). Use this tool to refresh stale data.`, inputSchema: z.object({}), annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, }, }, - src/tools/metadata.ts:96-155 (helper)Helper function that performs the logic of fetching and caching metadata, used by `sync_metadata`.
async function fetchAndCacheMetadata(client: MantisClient, cache: MetadataCache): Promise<CachedMetadata> { // Fetch all projects const projectResult = await client.get<{ projects: MantisProject[] }>('projects'); const projects = projectResult.projects ?? []; const byProject: Record<number, CachedProjectMeta> = {}; // For each project, fetch users, versions, categories in parallel await Promise.all( projects.map(async (project) => { const [usersResult, versionsResult, projectDetailResult] = await Promise.allSettled([ client.get<{ users: MantisUser[] }>(`projects/${project.id}/users`), client.get<{ versions: MantisVersion[] }>(`projects/${project.id}/versions`, { obsolete: 1, inherit: 1 }), // Categories are embedded in the project detail response — same source as get_project_categories client.get<{ projects: Array<{ categories?: MantisCategory[] }> }>(`projects/${project.id}`), ]); const users: MantisUser[] = usersResult.status === 'fulfilled' ? (usersResult.value.users ?? []) : []; const versions: MantisVersion[] = versionsResult.status === 'fulfilled' ? (versionsResult.value.versions ?? []) : []; const ALL_PROJECTS_PREFIX = '[All Projects] '; const rawCategories: MantisCategory[] = projectDetailResult.status === 'fulfilled' ? (projectDetailResult.value.projects?.[0]?.categories ?? []) : []; const categories = rawCategories.map((cat) => ({ ...cat, name: cat.name.startsWith(ALL_PROJECTS_PREFIX) ? cat.name.slice(ALL_PROJECTS_PREFIX.length) : cat.name, })); byProject[project.id] = { users, versions, categories }; }) ); // Fetch all tags — try the dedicated endpoint first, fall back to collecting // from issues when the endpoint is not available (e.g. MantisBT < 2.26) let tags: MantisTag[] = []; try { const tagsResult = await client.get<{ tags: MantisTag[] }>('tags'); tags = tagsResult.tags ?? []; } catch { tags = await collectTagsFromIssues(client, projects); } const data: CachedMetadata = { timestamp: Date.now(), projects, byProject, tags, }; await cache.save(data); return data; }