Skip to main content
Glama

Update Project Section

update_project_section

Modify or update a specific section in a project’s main.md file without altering other parts. Use for targeted edits, error fixes, or adding new configurations, ensuring document structure and integrity are preserved.

Instructions

Update a specific section within the project main.md file efficiently.

When to use this tool:

  • Modifying a single section without affecting others

  • Adding new configuration or guidelines to existing section

  • Fixing errors in specific sections

  • Updating outdated information in targeted areas

  • Making incremental improvements

Key features:

  • Preserves all other sections intact (non-destructive)

  • More efficient than full file replacement

  • Maintains document structure

  • Atomic section-level updates

You should:

  1. Identify the exact section header including "## " prefix

  2. Read the current section content first if needed

  3. Preserve section formatting conventions

  4. Use this instead of update_project_main for small changes

  5. Verify section exists before attempting update

  6. Keep section content focused and relevant

  7. Consider impact on related sections

DO NOT use when:

  • Section doesn't exist (use add_project_section)

  • Need to update multiple sections (batch operations)

  • Restructuring entire document

Section header must match exactly (e.g., "## Installation") Returns: {success: bool, message?: str, error?: str}

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
new_contentYesThe new content for this section (without the header)
project_idYesThe project identifier
section_headerYesThe exact section header to update (e.g., "## Installation")

Implementation Reference

  • Asynchronous implementation of the tool handler. Locates the specified section header (## ) in the project's main.md file, replaces the section content with new_content, updates the file, auto-commits the change, and returns a formatted response.
    /**
     * Async version of updateProjectSection
     */
    async updateProjectSectionAsync(params: {
      project_id: z.infer<typeof secureProjectIdSchema>;
      section_header: z.infer<typeof secureSectionHeaderSchema>;
      new_content: z.infer<typeof secureContentSchema>;
    }): Promise<string> {
      const context = this.createContext('update_project_section', params);
    
      try {
        const { project_id, section_header, new_content } = params;
        const projectInfo = await getProjectDirectoryAsync(this.storagePath, project_id);
    
        // Check if project exists
        if (!projectInfo) {
          throw new MCPError(MCPErrorCode.PROJECT_NOT_FOUND, `Project ${project_id} not found`, {
            project_id,
            traceId: context.traceId,
          });
        }
    
        const [originalId, projectPath] = projectInfo;
        const mainFile = join(projectPath, 'main.md');
    
        try {
          await access(mainFile);
        } catch {
          throw new MCPError(MCPErrorCode.PROJECT_NOT_FOUND, `Project ${originalId} does not exist`, {
            project_id,
            section_header,
            traceId: context.traceId,
          });
        }
    
        const content = await readFile(mainFile, 'utf8');
        const lines = content.split('\n');
    
        // Find the section
        let sectionStart = -1;
        let sectionEnd = lines.length;
    
        for (let i = 0; i < lines.length; i++) {
          if (lines[i].trim() === section_header.trim()) {
            sectionStart = i;
            // Find the end of this section (next ## header or end of file)
            for (let j = i + 1; j < lines.length; j++) {
              if (lines[j].startsWith('## ')) {
                sectionEnd = j;
                break;
              }
            }
            break;
          }
        }
    
        if (sectionStart === -1) {
          throw new MCPError(
            MCPErrorCode.SECTION_NOT_FOUND,
            `Section "${section_header}" not found in project main`,
            { project_id, section_header, traceId: context.traceId }
          );
        }
    
        // Replace the section content
        const newLines = [
          ...lines.slice(0, sectionStart + 1),
          '',
          new_content,
          '',
          ...lines.slice(sectionEnd),
        ];
    
        const updatedContent = newLines.join('\n');
        await writeFile(mainFile, updatedContent);
    
        await autoCommitAsync(
          this.storagePath,
          `Update section "${section_header}" in ${originalId}`
        );
    
        await this.logSuccessAsync('update_project_section', { project_id, section_header }, context);
        return this.formatSuccessResponse({
          message: `Section "${section_header}" updated in project ${originalId}`,
        });
      } catch (error) {
        const mcpError =
          error instanceof MCPError
            ? error
            : new MCPError(
                MCPErrorCode.INTERNAL_ERROR,
                `Failed to update project section: ${error instanceof Error ? error.message : String(error)}`,
                {
                  project_id: params.project_id,
                  section_header: params.section_header,
                  traceId: context.traceId,
                }
              );
        await this.logErrorAsync(
          'update_project_section',
          {
            project_id: params.project_id,
            section_header: params.section_header,
          },
          mcpError,
          context
        );
        return this.formatErrorResponse(mcpError, context);
      }
    }
  • Registers the 'update_project_section' tool with the MCP server, specifying title, description, input schema, and the handler invocation.
    server.registerTool(
      'update_project_section',
      {
        title: 'Update Project Section',
        description: TOOL_DESCRIPTIONS.update_project_section,
        inputSchema: {
          project_id: secureProjectIdSchema.describe('The project identifier'),
          section_header: secureSectionHeaderSchema.describe(
            'The exact section header to update (e.g., "## Installation")'
          ),
          new_content: secureContentSchema.describe(
            'The new content for this section (without the header)'
          ),
        },
      },
      async ({ project_id, section_header, new_content }) => {
        const result = await projectHandler.updateProjectSectionAsync({
          project_id,
          section_header,
          new_content,
        });
        return {
          content: [
            {
              type: 'text',
              text: result,
            },
          ],
        };
      }
    );
  • Zod schema definitions for input parameters: secureProjectIdSchema, secureContentSchema, and secureSectionHeaderSchema used for validating project_id, new_content, and section_header.
    export const secureProjectIdSchema = z
      .string()
      .min(1, 'Project ID cannot be empty')
      .max(100, 'Project ID too long')
      .refine(
        (val) => !val.includes('..') && !val.startsWith('.') && !val.endsWith('.'),
        'Project ID cannot contain path traversal patterns'
      )
      .refine(
        (val) => !/[/\\:*?"<>|\0]/.test(val),
        'Project ID cannot contain filesystem reserved characters or null bytes'
      )
      .refine((val) => val.trim() === val, 'Project ID cannot have leading/trailing spaces');
    
    export const secureFilenameSchema = z
      .string()
      .min(1, 'Filename cannot be empty')
      .max(255, 'Filename too long')
      .refine(
        (val) => !val.includes('/') && !val.includes('\\') && !val.includes('\0'),
        'Filename contains invalid path characters'
      )
      .refine(
        (val) => !val.includes('..') && val.trim() === val,
        'Filename cannot contain path traversal or leading/trailing spaces'
      );
    
    export const secureContentSchema = z
      .string()
      .max(10 * 1024 * 1024, 'Content too large (max 10MB)')
      .refine((val) => !val.includes('\0'), 'Content cannot contain null bytes');
    
    export const secureSectionHeaderSchema = z
      .string()
      .min(1, 'Section header cannot be empty')
      .max(200, 'Section header too long')
      .regex(/^##\s+/, 'Section header must start with "## "')
      .refine(
        (val) => !val.includes('\0') && val.trim() === val,
        'Section header contains invalid characters'
      );
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behavioral traits: 'Preserves all other sections intact (non-destructive),' 'More efficient than full file replacement,' 'Maintains document structure,' 'Atomic section-level updates,' and the return format. It also includes practical steps like verifying section existence and preserving formatting. However, it doesn't mention potential side effects like versioning or backup behavior.

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 is well-structured with clear sections ('When to use this tool,' 'Key features,' 'You should,' 'DO NOT use when'), making it easy to scan. Each sentence adds value, such as distinguishing from sibling tools and providing actionable steps. However, it could be slightly more concise by integrating some bullet points into flowing text without losing clarity.

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

Completeness5/5

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

Given the tool's complexity (section-level updates in a file) and the absence of annotations and output schema, the description provides comprehensive context. It covers purpose, usage scenarios, behavioral traits, parameter nuances, and return values ('Returns: {success: bool, message?: str, error?: str}'). This is complete enough for an agent to understand and use the tool effectively without relying on other structured fields.

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

Parameters4/5

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

Schema description coverage is 100%, so the schema already documents all three parameters. The description adds meaningful context beyond the schema: it explains that 'section_header' must include the '## ' prefix and match exactly, and provides examples like '## Installation.' It also clarifies that 'new_content' should be without the header and advises reading current content first. This enhances understanding beyond the basic schema definitions.

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

Purpose5/5

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

The description clearly states the tool's purpose: 'Update a specific section within the project main.md file efficiently.' It specifies the verb ('update'), resource ('section within the project main.md file'), and distinguishes it from sibling tools like 'update_project_main' by focusing on section-level updates rather than full file replacement.

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

Usage Guidelines5/5

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

The description provides explicit guidance on when to use this tool ('Modifying a single section without affecting others,' 'Adding new configuration,' etc.) and when not to use it ('Section doesn't exist (use add_project_section),' 'Need to update multiple sections,' 'Restructuring entire document'). It also names alternatives like 'add_project_section' and 'update_project_main' for different scenarios.

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

Related 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/sven-borkert/knowledge-mcp'

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