Skip to main content
Glama

Create Issue

create_issue

Create a new bug report or feature request in MantisBT with required details like summary, description, project ID, and category to track software issues.

Instructions

Create a new MantisBT issue. Returns the created issue including its assigned ID.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
summaryYesIssue summary/title
descriptionYesDetailed issue description. Required — do not create issues without a description. Plain text or Markdown.
project_idYesProject ID the issue belongs to
categoryYesCategory name (use get_project_categories to list available categories)
priorityNoPriority: canonical English name (none, low, normal, high, urgent, immediate) or localized label. Default: "normal". Use get_issue_enums to see all available values.normal
severityNoSeverity: canonical English name (feature, trivial, text, tweak, minor, major, crash, block) or localized label. Default: "minor". Use get_issue_enums to see all available values.minor
handler_idNoUser ID of the person to assign the issue to
handlerNoUsername (login name) of the person to assign the issue to. Alternative to handler_id — the server resolves the name to a user ID from the project members. Use get_project_users to see available users.
versionNoAffected product version name (use get_project_versions to list available versions)
target_versionNoTarget version name — version in which the issue is planned to be fixed (use get_project_versions to list available versions)
fixed_in_versionNoVersion name in which the issue was fixed (use get_project_versions to list available versions)
steps_to_reproduceNoSteps to reproduce the issue. Plain text or Markdown.
additional_informationNoAdditional information about the issue. Plain text or Markdown.
reproducibilityNoReproducibility: canonical English name or localized label (always, sometimes, random, have not tried, unable to reproduce, N/A). Use get_issue_enums to see all available values.
view_stateNoVisibility of the issue: "public" (default) or "private"

Implementation Reference

  • The implementation of the create_issue tool, including schema definition and handler logic.
    server.registerTool(
      'create_issue',
      {
        title: 'Create Issue',
        description: 'Create a new MantisBT issue. Returns the created issue including its assigned ID.',
        inputSchema: z.object({
          summary: z.string().min(1).describe('Issue summary/title'),
          description: z.string().min(1).describe('Detailed issue description. Required — do not create issues without a description. Plain text or Markdown.'),
          project_id: z.coerce.number().int().positive().describe('Project ID the issue belongs to'),
          category: z.string().min(1).describe('Category name (use get_project_categories to list available categories)'),
          priority: z.string().default('normal').describe('Priority: canonical English name (none, low, normal, high, urgent, immediate) or localized label. Default: "normal". Use get_issue_enums to see all available values.'),
          severity: z.string().default('minor').describe('Severity: canonical English name (feature, trivial, text, tweak, minor, major, crash, block) or localized label. Default: "minor". Use get_issue_enums to see all available values.'),
          handler_id: z.coerce.number().int().positive().optional().describe('User ID of the person to assign the issue to'),
          handler: z.string().optional().describe('Username (login name) of the person to assign the issue to. Alternative to handler_id — the server resolves the name to a user ID from the project members. Use get_project_users to see available users.'),
          version: z.string().optional().describe('Affected product version name (use get_project_versions to list available versions)'),
          target_version: z.string().optional().describe('Target version name — version in which the issue is planned to be fixed (use get_project_versions to list available versions)'),
          fixed_in_version: z.string().optional().describe('Version name in which the issue was fixed (use get_project_versions to list available versions)'),
          steps_to_reproduce: z.string().optional().describe('Steps to reproduce the issue. Plain text or Markdown.'),
          additional_information: z.string().optional().describe('Additional information about the issue. Plain text or Markdown.'),
          reproducibility: z.string().optional().describe('Reproducibility: canonical English name or localized label (always, sometimes, random, have not tried, unable to reproduce, N/A). Use get_issue_enums to see all available values.'),
          view_state: z.enum(['public', 'private']).optional().describe('Visibility of the issue: "public" (default) or "private"'),
        }),
        annotations: {
          readOnlyHint: false,
          destructiveHint: false,
          idempotentHint: false,
        },
      },
      async ({ summary, description, project_id, category, priority, severity, handler_id, handler, version, target_version, fixed_in_version, steps_to_reproduce, additional_information, reproducibility, view_state }) => {
        // Resolve handler username to handler_id when only a name is given
        let resolvedHandlerId = handler_id;
        if (resolvedHandlerId === undefined && handler !== undefined) {
          const metadata = await cache.loadIfValid();
          let users: MantisUser[] = metadata?.byProject[project_id]?.users ?? [];
          if (users.length === 0) {
            try {
              const usersResult = await client.get<{ users: MantisUser[] }>(`projects/${project_id}/users`);
              users = usersResult.users ?? [];
            } catch {
              users = [];
            }
          }
          const user = users.find(u => u.name === handler || u.real_name === handler);
          if (!user) {
            const names = users.map(u => u.name).join(', ');
            return {
              content: [{ type: 'text', text: errorText(`User "${handler}" not found in project ${project_id}. Available users: ${names || 'none (run sync_metadata or check project_id)'}`) }],
              isError: true,
            };
          }
          resolvedHandlerId = user.id;
        }
    
        try {
          const body: Record<string, unknown> = {
            summary,
            description,
            project: { id: project_id },
            category: { name: category },
          };
          const priorityResolved = await resolveEnum('priority', priority, client);
          if (typeof priorityResolved === 'string') return { content: [{ type: 'text', text: errorText(priorityResolved) }], isError: true };
          body.priority = priorityResolved;
          const severityResolved = await resolveEnum('severity', severity, client);
          if (typeof severityResolved === 'string') return { content: [{ type: 'text', text: errorText(severityResolved) }], isError: true };
          body.severity = severityResolved;
          if (resolvedHandlerId) body.handler = { id: resolvedHandlerId };
          if (version !== undefined) body.version = { name: version };
          if (target_version !== undefined) body.target_version = { name: target_version };
          if (fixed_in_version !== undefined) body.fixed_in_version = { name: fixed_in_version };
          if (steps_to_reproduce !== undefined) body.steps_to_reproduce = steps_to_reproduce;
          if (additional_information !== undefined) body.additional_information = additional_information;
          if (reproducibility !== undefined) {
            const reproducibilityResolved = await resolveEnum('reproducibility', reproducibility, client);
            if (typeof reproducibilityResolved === 'string') return { content: [{ type: 'text', text: errorText(reproducibilityResolved) }], isError: true };
            body.reproducibility = reproducibilityResolved;
          }
          if (view_state !== undefined) body.view_state = { name: view_state };
    
          const raw = await client.post<Record<string, unknown>>('issues', body);
          const partial = ('issue' in raw && typeof raw['issue'] === 'object' && raw['issue'] !== null)
            ? raw['issue'] as MantisIssue
            : raw as unknown as MantisIssue;
          let issue: MantisIssue = partial;
          if (!('summary' in (partial as unknown as Record<string, unknown>))) {
            // Older MantisBT returned only { id: N } — fetch the full issue.
            // Suppress GET errors: the issue was already created.
            try {
              const fetched = await client.get<{ issues: MantisIssue[] }>(`issues/${partial.id}`);
              issue = fetched.issues?.[0] ?? partial;
            } catch {
              // unable to fetch details — return minimal object
            }
          }
          return {
            content: [{ type: 'text', text: JSON.stringify(issue, null, 2) }],
          };
        } catch (error) {
          const msg = error instanceof Error ? error.message : String(error);
          return { content: [{ type: 'text', text: errorText(msg) }], isError: true };
        }
      }
    );
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations correctly identify this as a non-read-only, non-idempotent, non-destructive operation. The description adds valuable behavioral context by specifying the return value ('created issue including its assigned ID'), which is important given the lack of an output schema. However, it omits error handling behavior, validation constraints, and side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description consists of two efficient, front-loaded sentences where every word earns its place—stating purpose first, then return value. It is appropriately concise, though given the high complexity (15 parameters), a brief mention of required fields or non-idempotent behavior could have been included without violating conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex 15-parameter creation tool, the description covers the basic contract (action and return value) and relies appropriately on the rich schema and annotations. However, it lacks workflow context, explicit mention of required fields, and guidance on the tool's non-idempotent nature (creating duplicates if called twice), leaving notable gaps despite the comprehensive schema coverage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the baseline score is 3. The description does not mention any parameters, but given the comprehensive schema documentation for all 15 parameters (including references to related tools like 'get_issue_enums'), no additional parameter semantics are required in the description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Create') and resource ('MantisBT issue'). However, it does not explicitly distinguish this tool from sibling 'update_issue' or clarify when to create versus update, falling short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no explicit guidance on when to use this tool versus alternatives (e.g., 'update_issue'), nor does it mention prerequisites such as verifying project_id or category existence. While the schema references helper tools like 'get_project_categories', this usage guidance is not present in the description text itself.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dpesch/mantisbt-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server