wiki_update_page
Update existing Azure DevOps Wiki pages or create new ones by modifying content in Markdown format.
Instructions
Update content of an existing wiki page or create a new page if it does not exist
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| organization | No | Azure DevOps organization name | |
| project | No | Project name | |
| wikiId | Yes | Wiki identifier | |
| path | Yes | Page path or page ID | |
| content | Yes | New page content (Markdown) |
Implementation Reference
- src/server.ts:289-310 (handler)Server-side handler for wiki_update_page tool: parses arguments using schema, initializes client if needed, calls client.updatePage, and formats response.private async handleUpdatePage(args: any) { const request = WikiUpdatePageRequestSchema.parse(args); const organization = request.organization || this.config.defaultOrganization; const project = request.project || this.config.defaultProject; if (!organization) { throw new Error('Organization is required either as parameter or in server configuration'); } if (!project) { throw new Error('Project is required either as parameter or in server configuration'); } const client = await this.getClient(organization, project); const result = await client.updatePage(request); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }
- src/azure-client.ts:284-395 (helper)Core implementation in AzureDevOpsWikiClient: handles page existence check, version management, and HTTP PUT to Azure DevOps Wiki API for update/create.async updatePage(request: WikiUpdatePageRequest): Promise<WikiPageUpdateResult> { if (!this.wikiApi || !this.connection) { throw new Error('Azure DevOps client not initialized'); } try { const organization = request.organization || this.config.organization; const project = request.project || this.config.project; if (!organization || !project) { throw new Error('Organization and project must be provided'); } // Set encoded pagePath const encodedPath = encodeURIComponent(request.path); // Get wiki object const wiki = await this.wikiApi.getWiki(request.wikiId, project); // Fix: Access the first element of versions array safely and get its version property const wikiVersion = Array.isArray(wiki.versions) && wiki.versions.length > 0 ? wiki.versions[0].version : 'wikiMaster'; // First, check if page exists to get version for updates let pageVersion: string | undefined; let pageExists = false; try { let wikiPageResponse = await this.wikiApi.http.get(`${wiki.url}/pages?path=${encodedPath}`); if (wikiPageResponse.message && wikiPageResponse.message.statusCode === 200) { pageExists = true; pageVersion = wikiPageResponse.message.headers.etag; } } catch (checkError) { // Page doesn't exist, we'll create it pageExists = false; } // Create headers object with proper typing const headers: { [key: string]: string } = { 'Content-Type': 'application/json' }; // Only add If-Match header if page exists and we have a version // For new pages, don't include If-Match header if (pageExists && pageVersion) { headers['If-Match'] = pageVersion; } const requestBody = { content: request.content }; // TODO: Add versionDescriptor.versionType and versionDescriptor.version as optional environment variables const apiUrl = `${wiki.url}/pages?path=${encodedPath}&api-version=7.1&versionDescriptor.versionType=branch&versionDescriptor.version=${wikiVersion}`; const response = await this.wikiApi.http.put(apiUrl, JSON.stringify(requestBody), headers); if (!response.message || (response.message.statusCode !== 200 && response.message.statusCode !== 201)) { // Enhanced error information for debugging const errorDetails: { statusCode: number | undefined; statusMessage: string | undefined; headers: { [key: string]: string | string[] | undefined } | undefined; url: string; requestHeaders: { [key: string]: string }; requestBody: { content: string }; pageExists: boolean; pageVersion: string | undefined; responseBody?: string; } = { statusCode: response.message?.statusCode, statusMessage: response.message?.statusMessage, headers: response.message?.headers, url: apiUrl, requestHeaders: headers, requestBody: requestBody, pageExists, pageVersion }; throw new Error(`Failed to ${pageExists ? 'update' : 'create'} page: HTTP ${response.message?.statusCode || 'Unknown'}. Details: ${JSON.stringify(errorDetails, null, 2)}`); } const responseBody = await response.readBody(); if (!responseBody) { throw new Error('Empty response body'); } const data = JSON.parse(responseBody); // Handle the response structure let pageData = data.value || data; if (!pageData || pageData === null || (data.value !== undefined && data.value === null)) { throw new Error(`Failed to ${pageExists ? 'update' : 'create'} page: ${request.path}`); } return { id: pageData.id?.toString() || '', path: pageData.path || request.path, title: pageData.path ? pageData.path.split('/').pop() || '' : '', version: pageData.version || response.message.headers.etag || '', isParentPage: pageData.isParentPage || false, order: pageData.order || 0, gitItemPath: pageData.gitItemPath || '' }; } catch (error) { throw new Error(`Failed to update page: ${error instanceof Error ? error.message : String(error)}`); } }
- src/types.ts:24-30 (schema)Zod schema defining input parameters for wiki_update_page tool.export const WikiUpdatePageRequestSchema = z.object({ organization: z.string().min(1).optional(), project: z.string().min(1).optional(), wikiId: z.string().min(1), path: z.string().min(1), content: z.string(), });
- src/server.ts:108-137 (registration)Tool registration in ListToolsRequestHandler: defines name, description, and inputSchema for wiki_update_page.{ name: 'wiki_update_page', description: 'Update content of an existing wiki page or create a new page if it does not exist', inputSchema: { type: 'object', properties: { organization: { type: 'string', description: 'Azure DevOps organization name' }, project: { type: 'string', description: 'Project name' }, wikiId: { type: 'string', description: 'Wiki identifier' }, path: { type: 'string', description: 'Page path or page ID' }, content: { type: 'string', description: 'New page content (Markdown)' } }, required: ['wikiId', 'path', 'content'] } },
- src/server.ts:164-177 (registration)Tool dispatch in CallToolRequestHandler: switch case routes wiki_update_page to its handler.switch (name) { case 'search_wiki': return await this.handleSearchWiki(args); case 'wiki_get_page_tree': return await this.handleGetPageTree(args); case 'wiki_get_page': return await this.handleGetPage(args); case 'wiki_update_page': return await this.handleUpdatePage(args); case 'list_wiki': return await this.handleListWiki(args); default: throw new Error(`Unknown tool: ${name}`); }