Skip to main content
Glama

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'
      );

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