Developers

Guide

MCP server

The Model Context Protocol (MCP) is an open standard that lets AI assistants call tools in external systems. Kelomo ships an MCP server, so an assistant can answer questions like "who is working today", "how much leave do I have left" or "is the payroll material ready" directly from your organisation's data.

How it works

The server speaks stateless Streamable HTTP at https://mcp.kelomo.fi/mcp and takes the same bearer credentials as the REST API: an OAuth access token, or an API key. It is deliberately a thin client of the public API: every tool call travels through the same HTTP surface as any integration, so capability scopes, feature gates, rate limits and the audit trail apply structurally, and an assistant reaches exactly what its credential allows. A request without one is refused with 401 and a WWW-Authenticate header naming the resource metadata, so a host can start the sign-in itself.

  • Read-first tool set. A curated catalogue of 62 tools covers presence and schedules (who_is_working, get_schedule, team_absence, my_shifts), timesheets and balances (my_week, my_open_days, get_timesheet, leave_balance, balance_history), your own drafts and requests (my_requests, my_tasks), the approvals inbox, payroll readiness, sales and invoicing figures (sales_pipeline, list_leads, sales_agenda, list_quotes, list_invoices, customer_360), single records by id (get_customer, get_deal, get_lead, get_quote, get_invoice), projects (project_status, list_tasks), field service (service_orders, my_service_day, service_asset_log, maintenance_due, inventory_stock), the intake queue, tenant catalogues (list_catalogs), the integration event log, credential introspection (my_access) and report generation. A tenant sees only the tools of the modules it runs.
  • Writes a person finishes. log_time records the caller's own hours with project allocation, create_trip and create_expense file a travel claim, request_absence asks for leave, claim_open_shift asks for a shift, create_task, create_lead, log_activity, create_intake and create_service_order create work someone triages or schedules, set_task_status moves the caller's own card, create_entry_link mints a shareable link that pre-fills a time entry, and set_phase_lock closes a project phase for new bookings or reopens it. complete_activity ticks a follow-up off the sales agenda and add_contact adds a person to a customer. delete_draft removes the caller's own draft trip or expense line, withdraw_absence takes back the caller's own undecided absence request, and restore_day_proposal shows a cleared day's pre-fill again. Every write lands in a state a person still has to act on, carries an idempotency key (an ambiguous network failure cannot double-file a claim) and answers with a link to the exact Kelomo page where the person finishes the job.
  • Preview where it matters. A write that moves something forward or discards information is two-phase: the first call previews, and nothing is saved until you call again with confirm=true — request_absence and log_time replacing a day's rows. An additive draft (a trip, an expense line, hours added to a day) is written directly when the user has stated every fact, because delete_draft and the day's previous rows undo it.
  • Two tools that decide. approve and reject settle an approvals-inbox item, so both require reading the queue first and cannot be undone from the assistant — and reject refuses to run without a stated reason, because a rejection nobody explained is bad management.
  • Workflow prompts and resources. The server also publishes five workflow prompts (weekly review, approvals triage, payroll close, travel claim from a description, sales morning briefing) that hosts surface as slash commands, and resources such as kelomo://me/week; a large generated report is returned as a resource link rather than pasted into the conversation.
  • Deliberately absent: punching the clock (an assistant cannot witness "I am at work now", and the person tapping is already there) and issuing or dispatching invoices (money documents with unbroken numbering).
  • Scope with the credential. The capabilities on the token or key decide what the tools reach, so narrow is the right default: a read-only key for a setup you configure, and for a user-authorised connection whatever scopes the assistant genuinely needs.

Connect from Claude Code

Terminal
claude mcp add --transport http kelomo https://mcp.kelomo.fi/mcp \
  --header "Authorization: Bearer kelomo_YOUR_KEY"

Then ask in a session: "Using kelomo, who is working today?" Claude Code discovers the tools automatically.

Connect from Cursor

Add the server to .cursor/mcp.json (project) or ~/.cursor/mcp.json (global):

.cursor/mcp.json
{
  "mcpServers": {
    "kelomo": {
      "url": "https://mcp.kelomo.fi/mcp",
      "headers": {
        "Authorization": "Bearer kelomo_YOUR_KEY"
      }
    }
  }
}

Connect from the Claude API

Applications built on the Claude API can pass the server in the mcp_servers parameter and enable it with an mcp_toolset entry in tools, sending the header anthropic-beta: mcp-client-2025-11-20. Claude then calls Kelomo tools itself during the conversation:

Messages API request body
{
  "model": "claude-fable-5-1",
  "max_tokens": 16000,
  "mcp_servers": [
    {
      "type": "url",
      "url": "https://mcp.kelomo.fi/mcp",
      "name": "kelomo",
      "authorization_token": "kelomo_YOUR_KEY"
    }
  ],
  "tools": [{ "type": "mcp_toolset", "mcp_server_name": "kelomo" }],
  "messages": [
    { "role": "user", "content": "Who is working today, and are there coverage gaps this week?" }
  ]
}

Which clients this covers

Two ways in, separated by who does the configuring.

  • You hold the credential. Claude Code, Cursor, the Claude API and any agent whose configuration you edit send an API key in a header, as above.
  • The user authorises it. Hosts that accept an MCP server as a URL, such as Claude.ai, Codex and editor extensions, need only https://mcp.kelomo.fi/mcp: the person adds it, chooses Authenticate, signs in to Kelomo and approves. The host reads the 401, follows it to the resource metadata, registers itself and runs the consent flow, so the URL is the only thing anyone types. The OAuth guide walks the same chain by hand.

Key hygiene for assistants: mint a dedicated key per assistant integration, mark it read-only unless a write tool is genuinely needed, scope it minimally, and set an expiry. Everything an assistant does with the key is attributable in the audit trail.