Skip to main content
Glama

SharePoint Online MCP Server

by Zerg00s
addMockData.ts10.8 kB
// src/tools/addMockData.ts import request from 'request-promise'; import { ISharePointField, ILookupData, IMockDataResult, IToolResult } from '../interfaces'; import { getSharePointHeaders, getRequestDigest } from '../auth_factory'; import { SharePointConfig } from '../config'; import { generateMockValueForField } from '../utils/mockDataGenerator'; export interface AddMockDataParams { url: string; listTitle: string; itemCount: number; } /** * Add mock data items to a specific SharePoint list * @param params Parameters including site URL, list title, and item count * @param config SharePoint configuration * @returns Tool result with creation summary */ export async function addMockData( params: AddMockDataParams, config: SharePointConfig ): Promise<IToolResult> { const { url, listTitle, itemCount } = params; console.error(`addMockData tool called with URL: ${url}, List Title: ${listTitle}, Item Count: ${itemCount}`); try { // Authenticate with SharePoint const headers = await getSharePointHeaders(url, config); console.error("Headers prepared with authentication"); // Get request digest for POST operations headers['X-RequestDigest'] = await getRequestDigest(url, headers); headers['Content-Type'] = 'application/json;odata=verbose'; console.error("Headers prepared with request digest"); // Encode the list title to handle special characters const encodedListTitle = encodeURIComponent(listTitle); // First, get the list schema to understand its fields console.error(`Getting list schema for "${listTitle}"...`); const listResponse = await request({ url: `${url}/_api/web/lists/getByTitle('${encodedListTitle}')`, headers: { ...headers, 'Content-Type': undefined }, json: true, method: 'GET', timeout: 30000 }); // Get field details to understand which fields are writeable console.error(`Getting fields for list "${listTitle}"...`); const fieldsResponse = await request({ url: `${url}/_api/web/lists/getByTitle('${encodedListTitle}')/fields?$filter=ReadOnlyField eq false and Hidden eq false`, headers: { ...headers, 'Content-Type': undefined }, json: true, method: 'GET', timeout: 45000 }); // Process fields to get writeable ones const writeableFields = fieldsResponse.d.results.filter((field: ISharePointField) => { // Skip system fields and fields we shouldn't modify return !field.ReadOnlyField && !field.Hidden && field.InternalName !== 'ID' && field.InternalName !== 'Modified' && field.InternalName !== 'Created' && field.InternalName !== 'Author' && field.InternalName !== 'Editor' && field.InternalName !== 'GUID' && !field.InternalName.startsWith('_'); }); console.error(`Found ${writeableFields.length} writeable fields`); // Get lookup data for lookup fields const lookupFields = writeableFields.filter((field: ISharePointField) => field.TypeAsString?.toLowerCase().includes('lookup')); // Collect lookup data for each lookup field const lookupData: ILookupData = {}; for (const lookupField of lookupFields) { try { if (lookupField.LookupList) { console.error(`Getting lookup data for field ${lookupField.InternalName} from list ${lookupField.LookupList}...`); // Get the list schema first to find its web URL const lookupListSchema = await request({ url: `${url}/_api/web/lists(guid'${lookupField.LookupList}')`, headers: { ...headers, 'Content-Type': undefined }, json: true, method: 'GET', timeout: 30000 }); // Get items from the lookup list const lookupItems = await request({ url: `${url}/_api/web/lists(guid'${lookupField.LookupList}')/items?$select=ID,${lookupField.LookupField}&$top=100`, headers: { ...headers, 'Content-Type': undefined }, json: true, method: 'GET', timeout: 45000 }); if (lookupItems.d && lookupItems.d.results && lookupItems.d.results.length > 0) { lookupData[lookupField.InternalName] = lookupItems.d.results.map((item: any) => ({ ID: item.ID, Value: item[lookupField.LookupField] })); console.error(`Found ${lookupData[lookupField.InternalName].length} lookup values for ${lookupField.InternalName}`); } else { console.error(`No lookup data found for field ${lookupField.InternalName}`); lookupData[lookupField.InternalName] = []; } } } catch (error) { console.error(`Error fetching lookup data for ${lookupField.InternalName}:`, error); lookupData[lookupField.InternalName] = []; } } // Add mock items const successfulItems: number[] = []; const failedItems: Array<{index: number, error: string}> = []; for (let i = 0; i < itemCount; i++) { try { // Create mock item data based on field types const mockItemData: Record<string, any> = {}; for (const field of writeableFields) { const fieldName = field.InternalName; const fieldType = field.TypeAsString?.toLowerCase() || ''; let mockValue = generateMockValueForField(field, i); // Handle lookup fields with real lookup data if (mockValue && typeof mockValue === 'object' && mockValue.__lookupField) { const fieldLookupData = lookupData[fieldName] || []; if (fieldLookupData.length > 0) { // Use modulo to cycle through available lookup values const lookupIndex = i % fieldLookupData.length; const lookupItem = fieldLookupData[lookupIndex]; if (mockValue.multiple) { // Multi-value lookup requires array of lookup values mockItemData[fieldName] = { __metadata: { type: 'Collection(Edm.Int32)' }, results: [lookupItem.ID] }; } else { // Single-value lookup mockItemData[`${fieldName}Id`] = lookupItem.ID; } console.error(`Set lookup value for ${fieldName}: ${lookupItem.ID} (${lookupItem.Value})`); } else { console.error(`No lookup data available for ${fieldName}, skipping field`); } } else if (mockValue !== null && mockValue !== undefined) { mockItemData[fieldName] = mockValue; } } // Always include a Title if it exists in the writeable fields if (writeableFields.some((f: ISharePointField) => f.InternalName === 'Title') && !mockItemData['Title']) { mockItemData['Title'] = `Mock Item ${i + 1}`; } console.error(`Creating mock item ${i + 1}/${itemCount}...`); console.error(`Data: ${JSON.stringify(mockItemData)}`); // Create the item in SharePoint const createResponse = await request({ url: `${url}/_api/web/lists/getByTitle('${encodedListTitle}')/items`, headers: headers, json: true, method: 'POST', body: { __metadata: { type: listResponse.d.ListItemEntityTypeFullName }, ...mockItemData }, timeout: 15000 }); successfulItems.push(i + 1); console.error(`Successfully created item ${i + 1}`); } catch (error: any) { console.error(`Error creating item ${i + 1}:`, error.message); failedItems.push({ index: i + 1, error: error.message }); } } // Prepare result object const result: IMockDataResult = { listTitle: listTitle, writeableFields: writeableFields.map((f: ISharePointField) => ({ name: f.InternalName, title: f.Title, type: f.TypeAsString || f.TypeDisplayName || 'Unknown' })), lookupFields: Object.keys(lookupData).map(key => ({ name: key, valuesFound: lookupData[key].length })), requested: itemCount, successful: successfulItems.length, failed: failedItems.length, successfulItems, failedItems }; return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] } as IToolResult; } catch (error: unknown) { // Type-safe error handling let errorMessage: string; if (error instanceof Error) { errorMessage = error.message; } else if (typeof error === 'string') { errorMessage = error; } else { errorMessage = "Unknown error occurred"; } console.error("Error in addMockData tool:", errorMessage); return { content: [{ type: "text", text: `Error adding mock data: ${errorMessage}` }], isError: true } as IToolResult; } } export default addMockData;

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/Zerg00s/server-sharepoint'

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