settings
Retrieve and manage OfficeRnD organization settings including locations, resource types, business hours, and custom properties through list or get actions.
Instructions
Query organization settings and configuration in OfficeRnD.
action=list: List configuration entities. action=get: Get a single location by ID (locations only).
Entity-specific filters when listing:
locations: name
resource_types: (pagination only)
business_hours: location
custom_properties: (pagination only)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action to perform | |
| entity | Yes | Entity type to query | |
| id | No | Location ID (required for action=get, locations only) | |
| name | No | Filter by exact name (locations) | |
| location | No | Filter by location ID (business_hours) | |
| cursorNext | No | Cursor token for next page of results | |
| limit | No | Results per page (max 50, default 50) |
Implementation Reference
- src/tools/settings.ts:104-164 (handler)The main handler function for the "settings" tool, which processes 'list' and 'get' actions for various entities.
async ({ action, entity, id, name, location, cursorNext, limit }) => { try { const cfg = ENTITIES[entity]; if (action === "get") { if (!cfg.getPath) { return { content: [{ type: "text" as const, text: `Entity "${entity}" does not support get by ID.` }], isError: true, }; } if (!id) { return { content: [{ type: "text" as const, text: "id is required for action=get." }], isError: true, }; } const item = await apiGet<Record<string, unknown>>(`${cfg.getPath}/${id}`); return { content: [{ type: "text" as const, text: cfg.formatter(item) }] }; } // list const params: Record<string, string> = {}; if (cursorNext) params["$cursorNext"] = cursorNext; if (limit) params["$limit"] = limit; switch (entity) { case "locations": if (name) params["name"] = name; break; case "business_hours": if (location) params["location"] = location; break; } const data = await apiGet<PaginatedResponse<Record<string, unknown>>>(cfg.listPath, params); if (data.results.length === 0) { return { content: [{ type: "text" as const, text: `No ${cfg.label} found.` }] }; } const text = data.results.map(cfg.formatter).join("\n---\n"); let result = `Found ${data.results.length} ${cfg.label} (range ${data.rangeStart}-${data.rangeEnd}):\n\n${text}`; if (data.cursorNext) { result += `\n\n[More results available — use cursorNext: "${data.cursorNext}"]`; } return { content: [{ type: "text" as const, text: result }] }; } catch (error) { return { content: [ { type: "text" as const, text: `Error querying ${entity}: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } ); - src/tools/settings.ts:77-102 (schema)Input schema definition for the "settings" tool using Zod.
inputSchema: { action: z.enum(["list", "get"]).describe("Action to perform"), entity: z .enum(["locations", "resource_types", "business_hours", "custom_properties"]) .describe("Entity type to query"), id: z .string() .optional() .describe("Location ID (required for action=get, locations only)"), name: z .string() .optional() .describe("Filter by exact name (locations)"), location: z .string() .optional() .describe("Filter by location ID (business_hours)"), cursorNext: z .string() .optional() .describe("Cursor token for next page of results"), limit: z .string() .optional() .describe("Results per page (max 50, default 50)"), }, - src/tools/settings.ts:62-165 (registration)Registration function for the "settings" tool on the McpServer.
export function registerSettingsTool(server: McpServer): void { server.registerTool( "settings", { title: "Settings", description: `Query organization settings and configuration in OfficeRnD. action=list: List configuration entities. action=get: Get a single location by ID (locations only). Entity-specific filters when listing: - locations: name - resource_types: (pagination only) - business_hours: location - custom_properties: (pagination only)`, inputSchema: { action: z.enum(["list", "get"]).describe("Action to perform"), entity: z .enum(["locations", "resource_types", "business_hours", "custom_properties"]) .describe("Entity type to query"), id: z .string() .optional() .describe("Location ID (required for action=get, locations only)"), name: z .string() .optional() .describe("Filter by exact name (locations)"), location: z .string() .optional() .describe("Filter by location ID (business_hours)"), cursorNext: z .string() .optional() .describe("Cursor token for next page of results"), limit: z .string() .optional() .describe("Results per page (max 50, default 50)"), }, }, async ({ action, entity, id, name, location, cursorNext, limit }) => { try { const cfg = ENTITIES[entity]; if (action === "get") { if (!cfg.getPath) { return { content: [{ type: "text" as const, text: `Entity "${entity}" does not support get by ID.` }], isError: true, }; } if (!id) { return { content: [{ type: "text" as const, text: "id is required for action=get." }], isError: true, }; } const item = await apiGet<Record<string, unknown>>(`${cfg.getPath}/${id}`); return { content: [{ type: "text" as const, text: cfg.formatter(item) }] }; } // list const params: Record<string, string> = {}; if (cursorNext) params["$cursorNext"] = cursorNext; if (limit) params["$limit"] = limit; switch (entity) { case "locations": if (name) params["name"] = name; break; case "business_hours": if (location) params["location"] = location; break; } const data = await apiGet<PaginatedResponse<Record<string, unknown>>>(cfg.listPath, params); if (data.results.length === 0) { return { content: [{ type: "text" as const, text: `No ${cfg.label} found.` }] }; } const text = data.results.map(cfg.formatter).join("\n---\n"); let result = `Found ${data.results.length} ${cfg.label} (range ${data.rangeStart}-${data.rangeEnd}):\n\n${text}`; if (data.cursorNext) { result += `\n\n[More results available — use cursorNext: "${data.cursorNext}"]`; } return { content: [{ type: "text" as const, text: result }] }; } catch (error) { return { content: [ { type: "text" as const, text: `Error querying ${entity}: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } ); }