Skip to main content
Glama
bdiaby1

Lexware Office MCP Server

by bdiaby1

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
LEXWARE_OFFICE_API_KEYYesYour Lexware Office API key. Create one at https://app.lexoffice.de/addons/public-api.
LEXWARE_OFFICE_READ_ONLYNoIf set to 'true', blocks all write operations. This is a hard block that wins over ALLOW_WRITES=true. Defaults to 'true' (read-only by default).true
LEXWARE_OFFICE_ALLOW_WRITESNoSet to 'true' to explicitly allow write operations (POST, PUT, PATCH, DELETE). Defaults to 'false'.false

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": true
}

Tools

Functions exposed to the LLM to take actions

NameDescription
searchA

Search the curated Lexware Office API catalog by running a JavaScript async arrow function.

Use this before execute to discover endpoints, request shapes, response notes, workflows, and domain-specific caveats.

Available global:

declare const spec: LexwareApiCatalog;

Useful starting points:

  • spec.info.domainIndex: compact map from business domains to endpoint lists

  • spec.info.writesEnabled: whether this server currently allows POST/PUT/PATCH/DELETE — check before planning writes

  • spec.paths: path -> method -> operation catalog with params, requestBody, responses, examples, capabilities, docsUrl

  • spec.workflows: curated recipes for reporting, sales documents, files/uploads, webhooks, and API quirks

  • spec.info.voucherStatusSemantics and financeReportingSemantics: finance/status guidance for revenue/Umsatz/profit questions

Sandbox: no network, filesystem, process, fetch, imports, or API key. Return JSON-serializable data; console logs are captured.

Examples:

async () => Object.entries(spec.info.domainIndex) .filter(([name, domain]) => [name, ...domain.tags].some(value => value.toLowerCase().includes('contact'))) .map(([name, domain]) => ({ name, ...domain }))

async () => { const op = spec.paths['/v1/voucherlist']?.get; return { summary: op?.summary, parameters: op?.parameters, notes: op?.notes, examples: op?.examples }; }

executeA

Execute a constrained Lexware Office API workflow by running a JavaScript async arrow function.

Use search first when you need endpoint/domain guidance; do not guess Lexware paths from memory. The sandbox exposes no API key, filesystem, process, imports, fetch, or arbitrary network access.

Available globals:

declare const spec: LexwareApiCatalog; declare const lexware: { request<T = unknown>(input: LexwareRequest): Promise<LexwareResponse>; json(input: LexwareRequest): Promise; paginate<T = unknown>(input: LexwareRequest, options?: { maxPages?: number }): Promise<T[]>; requireNumber(row: unknown, fieldPath: string): number; requireMoney(row: unknown, fieldPath: string): number; sumMoney(rows: unknown[], fieldPath: string): number; formatMoney(cents: number, currency?: string): string; };

type LexwareRequest = { method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; path: string; // relative /v1/... only; no absolute URLs or // hosts query?: Record<string, string | number | boolean | Array<string | number | boolean> | null | undefined>; body?: unknown; // JSON by default; string when rawBody=true (UTF-8 encoded, NOT binary-safe) bodyBase64?: string; // raw binary body as base64; the host decodes it outside the sandbox multipart?: MultipartPart[]; // multipart/form-data uploads (e.g. POST /v1/files); host builds FormData contentType?: string; rawBody?: boolean; accept?: string; }; // At most one of body, bodyBase64, or multipart per request.

type MultipartPart = { name: string; value?: string; // plain text form field contentBase64?: string; // binary part content as base64; host decodes it contentPath?: string; // absolute file path on the MCP server machine; host reads the file directly — preferred for local files (no base64, no size blowup) filename?: string; // defaults to the contentPath basename contentType?: string; }; // Exactly one of value, contentBase64, or contentPath per part.

type LexwareResponse<T = unknown> = { ok: boolean; status: number; statusText: string; data?: T; text?: string; truncated?: boolean; contentType: string; headers: Record<string, string>; errorCategory?: string; retryAfterSeconds?: number; operation?: { operationId: string; method: string; pathTemplate: string; summary: string }; request: { method: string; path: string; query: Record<string, string[]> }; sent?: { bytes: number; sha256?: string; parts?: Array<{ name: string; filename?: string; bytes: number; sha256: string }> }; // echo of uploaded binary payloads for integrity checks };

lexware.request returns all HTTP responses, including non-OK, as LexwareResponse. Check response.ok/status for recovery logic, or use lexware.json(...) / lexware.paginate(...) when you want non-OK or non-JSON responses to throw.

This server is read-only by default. POST, PUT, PATCH, and DELETE are blocked unless the server is started with LEXWARE_OFFICE_ALLOW_WRITES=true. Setting LEXWARE_OFFICE_READ_ONLY=true is a hard block that overrides ALLOW_WRITES. Check spec.info.writesEnabled to branch before attempting a write.

Example:

async () => { const response = await lexware.request({ path: '/v1/contacts', query: { page: 0, size: 5 } }); return { status: response.status, request: response.request, data: response.data }; }

File upload example (bookkeeping Beleg). Never inline file bytes in code — pass the file's absolute path via contentPath and the host reads it from disk:

async () => { const response = await lexware.request({ method: 'POST', path: '/v1/files', multipart: [ { name: 'file', contentType: 'application/pdf', contentPath: '/absolute/path/to/receipt.pdf' }, { name: 'type', value: 'voucher' }, ], }); return { status: response.status, id: response.data?.id, sent: response.sent }; }

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A4.9/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: search is for discovering API endpoints and workflows, while execute is for making actual API requests. The descriptions explicitly state to use search before execute, eliminating ambiguity.

Naming Consistency5/5

Both tool names are single lowercase verbs ('search' and 'execute'), following a consistent imperative style. There is no mixing of conventions or confusing patterns.

Tool Count3/5

With only 2 tools, the server is at the low end of what might be considered adequate. However, the design intentionally uses a minimal pair of discovery and execution, which is reasonable for the broad API access it provides.

Completeness5/5

The search tool exposes the full API catalog, including workflows and domain guides, while execute can perform any documented API operation. Together they cover the complete lifecycle of discovering and interacting with the Lexware Office API, leaving no functional gaps.

Maintenance

ActivitySlowing
ResponsivenessNo issues