Developers

Self-Hosted Teamso MCP

Run the Teamso MCP server from the open-source npm package (@teamso/teamso-mcp) with npx on your machine or on your own server. Nothing sits between your client and the Teamso API.

Quick start

Requires Node.js 20 or later. Add this to your MCP client's configuration:

mcp.json
{
  "mcpServers": {
    "teamso": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@teamso/[email protected]"
      ],
      "env": {
        "TEAMSO_ACCESS_TOKEN": "tms_pat_..."
      }
    }
  }
}

The version is pinned so npx does not run an old cached build.

Setup

The package runs over stdio and works with any MCP client that supports stdio.

Cursor

Open ~/.cursor/mcp.json with Cmd+Shift+P → Open MCP settings and add:

~/.cursor/mcp.json
{
  "mcpServers": {
    "teamso": {
      "command": "npx",
      "args": [
        "-y",
        "@teamso/[email protected]"
      ],
      "env": {
        "TEAMSO_ACCESS_TOKEN": "tms_pat_..."
      }
    }
  }
}

Claude Code

Add it, passing the token as an environment variable:

bash
claude mcp add teamso --env TEAMSO_ACCESS_TOKEN=tms_pat_... -- npx -y @teamso/[email protected]

Claude Desktop

Add it to claude_desktop_config.json and restart Claude Desktop:

claude_desktop_config.json
{
  "mcpServers": {
    "teamso": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@teamso/[email protected]"
      ],
      "env": {
        "TEAMSO_ACCESS_TOKEN": "tms_pat_..."
      }
    }
  }
}

Windsurf

Add it under Windsurf → Settings → MCP:

mcp_config.json
{
  "mcpServers": {
    "teamso": {
      "command": "npx",
      "args": [
        "-y",
        "@teamso/[email protected]"
      ],
      "env": {
        "TEAMSO_ACCESS_TOKEN": "tms_pat_..."
      }
    }
  }
}

Other clients

Any stdio client can run this command; the token is read from the TEAMSO_ACCESS_TOKEN environment variable:

bash
TEAMSO_ACCESS_TOKEN=tms_pat_... npx -y @teamso/[email protected]

Authentication

The package uses a single credential: the personal access token you create on the MCP access page in Teamso. Put it in TEAMSO_ACCESS_TOKEN; the package sends it as the Authorization: Bearer header on every request.

.env
TEAMSO_ACCESS_TOKEN=tms_pat_...

With the local package, requests come from your own IP address; if your company restricts IPs, that address must be allowed. Permissions, operations blocked for tokens and revocation work as on the hosted server.

Hosted MCP server · Authentication

Available tools

The package offers the same 34 tools as the hosted server. The table shows the Teamso REST endpoint each tool calls (relative to TEAMSO_API_BASE_URL); the help tools read the public guide bundle instead of the API.

Since 1.2.0 the package works across every module your permissions allow, through the generic API tools (find_api_endpoints, call_api_read, call_api_write...). The flow, the safety rules and examples are on the hosted server page.

Hosted MCP server · All modules

Help

Searches the Teamso how-to guides. Reads the public guide bundle instead of calling the API.

ToolAPI endpointWhat it does
search_help_articles
GET {TEAMSO_HELP_BASE_URL}/how-to/bundle.{lang}.json
Searches the Teamso guides by keyword; filters by module and role.
get_help_article
GET {TEAMSO_HELP_BASE_URL}/how-to/bundle.{lang}.json
Returns a full guide with its steps.
list_help_modules
GET {TEAMSO_HELP_BASE_URL}/how-to/bundle.{lang}.json
Lists the modules that have guides, with each module's article titles and ids.

Account

Returns the token owner and their permissions.

ToolAPI endpointWhat it does
get_me
GET /user
Your name, email, company, roles, permission codes, manager, department and position.

Leave

Creating and cancelling a leave request is confirmed with an SMS code sent to your phone: the code is valid for 3 minutes and uses digital credit.

ToolAPI endpointWhat it does
list_leave_types
GET /leave-policy/getListAllLeavePolicyForUserGET /leave-policy/getDetailLeavePolicyForUser/{id}
Leave types you can request and the remaining balance of each.
get_my_leave_balance
GET /leave-policy/getListAllLeavePolicyForUserGET /leave-policy/getDetailLeavePolicyForUser/{id}
A summary of your leave balance: remaining days per type.
calculate_leave_days
GET /working-days/getWorkingDaysByMeGET /public-holiday/getPublicHolidayByMeGET /leave/dayCalculator/{workingDaysId}/{publicHolidayId}/{leaveTypeId}/{start}/{end}POST /leave/controlToAddLeave
Calculates how many working days a date range takes and the return-to-work date, using your working calendar and public holidays.
request_leave_otp
GET /sms/generateToken?checkCredit=true
Sends a confirmation code to your phone (valid for 3 minutes, uses SMS credit).
create_leave_request
GET /leave/dayCalculator/…POST /leave/controlToAddLeaveGET /sms/checkToken/{code}POST /leave
Verifies the SMS code, recalculates the days and submits the request to the approval chain.
list_my_leaves
GET /leave/listAllLeavesAdvancedPagination
Your own leave requests, filterable by date and status.
cancel_leave_request
GET /leave/listAllLeavesAdvancedPaginationGET /sms/checkToken/{code}DELETE /leave/{id}
Deletes a leave request after SMS confirmation; requires the leave delete permission.

Approvals

Leave requests where it is your turn to decide.

ToolAPI endpointWhat it does
list_pending_approvals
GET /leave/listAllLeavesAdvancedPagination?searchKey=state&searchValue=0
Leave requests waiting for your approval.
approve_or_reject_leave
GET /leave/listAllLeavesAdvancedPagination?searchKey=state&searchValue=0PUT /leave/state/{id}/{approve}/{answer}
Approves or rejects a request after checking that it is your turn to decide. A rejection needs a reason.

Employees

Only employees you are allowed to see.

ToolAPI endpointWhat it does
search_employees
GET /user/list-paginationGET /authorized-employee/list
Finds active colleagues by name or email (accent-insensitive). Without access to the company directory it searches the employees you are responsible for.
get_employee_profile
GET /user/getUserSummaryByUserId/{userId}
A colleague's work profile: branch, department, position, manager, work location and contact details (the phone number is masked unless you may read it).

Performance

Goals are linked to a period by its name (the title from list_performance_periods); list the periods before the goal tools.

ToolAPI endpointWhat it does
list_performance_periods
GET /performance-settings
Performance periods, goal entry windows and the evaluation scale.
list_my_goals
GET /user-goal/my
Your goals in the period and the actions available on each.
list_team_goals
GET /user-goal/assigned
Goals of the employees you manage or assigned goals to (drafts excluded), with the approvals you can give on each.
create_user_goal
GET /performance-settingsPOST /user-goal
Adds a draft goal for yourself or a direct report (performance admins: for anyone).
send_goals_to_approval
POST /user-goal/send-to-approval
Sends your draft (PENDING) goals to your manager for approval.
approve_goal
GET /user-goal/approve/{goalId}
Approves a goal that is waiting for approval.
revise_and_approve_goal
GET /user-goal/{goalId}PUT /user-goal/revise-and-approve/{goalId}
Revises a goal (name, description, weight, target) and approves it.
update_goal_actual_value
GET /performance-settingsPUT /user-goal/{goalId}/actual-value
Enters your actual value on a goal under evaluation.
update_manager_actual_value
GET /performance-settingsPUT /user-goal/{goalId}/manager-actual-value
Enters the achieved value of an employee's goal as their direct manager or an admin.
approve_goal_evaluation
GET /performance-settingsPOST /user-goal/approve-evaluation-process
Approves an employee's evaluation for the period at your approval step; at the last step Teamso computes the final score.

Communication

Announcements visible to you.

ToolAPI endpointWhat it does
list_announcements
GET /dashboard/getAnnouncements
Company and shuttle announcements visible to you, newest first.

Payroll

Only your own payslips.

ToolAPI endpointWhat it does
list_my_payslips
GET /payroll/getPayrollsByMe-pagination
Your e-payslips and their status, filterable by month or year.
get_payslip_pdf
GET /payroll/download-file/{payrollId}
Returns a payslip PDF as an embedded resource.

All modules

The rest of Teamso (expenses, requests, overtime, time tracking, payroll, recruiting, inventory, settings...) through the generic API tools. Only the endpoints your own permissions allow are listed and callable; the read tool cannot change data and the write tool shows a preview first.

ToolAPI endpointWhat it does
find_api_endpoints
GET /mcp-catalog/endpoints?q=&module=&method=&page=&size=
Searches the Teamso API endpoints your permissions allow by keyword (Turkish or English), module, HTTP method or effect (read, write, delete). Each result has the endpoint id, a summary, its effect and whether it needs an SMS code or returns a file.
list_api_modules
GET /mcp-catalog/modules
Lists the modules you can use and how many endpoints each one offers you.
describe_api_endpoint
GET /mcp-catalog/endpoint?id={METHOD /path}
Shows an endpoint's parameters, body schema, response type, whether it needs an SMS code, and a ready-made example call.
call_api_read
GET /mcp-catalog/endpoint?id={METHOD /path}GET /{path} + X-Teamso-Mcp-Intent: readPOST /{path} + X-Teamso-Mcp-Intent: read
Runs read endpoints only and returns the data. The request is marked read-only, so Teamso refuses anything that would change data. Large lists are shortened; files (PDF, Excel, CSV, images) come back embedded, up to 8 MB.
call_api_write
GET /mcp-catalog/endpoint?id={METHOD /path}GET /sms/checkToken/{code}POST /{path}PUT /{path}PATCH /{path}DELETE /{path}
Creates, changes or deletes records. Without confirm it sends nothing and returns a preview of the request with a schema check; it runs with confirm=true only after you agree. Takes otp_code for actions that need an SMS code and uploads files as base64 (10 MB in total).
request_sms_code
GET /sms/generateToken?checkCredit=true
After you confirm an action that needs an SMS code, sends a 6-digit verification code to your phone (valid for 3 minutes, uses SMS credit).

The distributor account's content tools are not in the package; they are served by the hosted server only.

Ready-made prompts

Next to the tools, the server publishes MCP prompts (prompts/list, prompts/get); your client shows them as slash commands or in a prompt picker. A prompt only steers the assistant through the tools: every write still needs your confirmation, and a leave request still needs the SMS code.

PromptArgumentsWhat it does
request_leave
start (optional)First day of leave: yyyy-MM-dd or words like “tomorrow” (Turkey time).
end (optional)Last day of leave (yyyy-MM-dd); empty means the same day as start.
leave_type (optional)Leave type name, e.g. “Annual leave”; empty means annual leave.
note (optional)Note for the approver.
Creates a leave request for the signed-in user: picks the leave type, shows the working days and the remaining balance, asks you to confirm, then sends the request with the SMS code. Missing dates are asked for.
Tool chain: list_leave_typescalculate_leave_daysrequest_leave_otpcreate_leave_request
review_pending_approvalsTakes no arguments.
Lists the leave requests waiting for your approval as a table and asks you, request by request, whether to approve or reject; it never decides for you. A rejection needs a reason.
Tool chain: list_pending_approvalsapprove_or_reject_leave

Prompts were added in version 1.1.0 of the package, and createMcpServer registers them together with the tools. In your own server use the registerPrompts and PROMPT_NAMES exports (@teamso/teamso-mcp/prompts).

Environment variables

The package reads these environment variables:

VariableRequiredDescription
TEAMSO_ACCESS_TOKENYesTeamso personal access token (tms_pat_...).
TEAMSO_API_BASE_URLNoTeamso API address; change it for a test environment or a private installation.Default: https://api.teamso.com/v1
TEAMSO_HELP_BASE_URLNoSite that serves the guide bundle (/how-to/bundle.en.json).Default: https://teamso.com
TEAMSO_TOOLSETSNoTool groups to serve, comma-separated: core, help, leave, approvals, employees, performance, communication, payroll, api. An unknown name stops the server and lists the valid names.Default: all
.env
TEAMSO_TOOLSETS=core,leave,api

GitHub and npm

The source code is published on GitHub under the MIT licence and the package on npm.

Using as a library

The package exports its core parts so you can build your own MCP server:

server.ts
import { TeamsoClient } from "@teamso/teamso-mcp/client";
import { createMcpServer } from "@teamso/teamso-mcp/server";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const client = new TeamsoClient(process.env.TEAMSO_ACCESS_TOKEN!, "https://api.teamso.com/v1");
const server = createMcpServer(client, { name: "my-teamso-assistant" });

await server.connect(new StdioServerTransport());

Exports

ExportDescription
createMcpServer(client, options?)@teamso/teamso-mcp/serverCreates an McpServer with every tool registered; name, version and instructions are optional.
TeamsoClient@teamso/teamso-mcp/clientTeamso API client: token, base URL and optional settings.
TeamsoApiError@teamso/teamso-mcp/clientA request Teamso refused: status, messageCode, apiMessage and the response body.
registerTools(server, client)@teamso/teamso-mcp/toolsRegisters the tools on an existing McpServer.
TOOL_NAMES@teamso/teamso-mcp/toolsThe list of tool names the package offers.
TOOLSETS, resolveToolsets(toolsets)@teamso/teamso-mcp/toolsThe tool groups, and resolveToolsets to validate a selection; createMcpServer and registerTools take a toolsets option.
registerPrompts(server)@teamso/teamso-mcp/promptsRegisters the ready-made prompts on an existing McpServer.
PROMPT_NAMES@teamso/teamso-mcp/promptsThe list of prompt names the package offers.
withJsonSchema2020_12(transport)@teamso/teamso-mcp/serverRewrites tools/list schemas to JSON Schema 2020-12 on any transport.
signProxyRequest(input)@teamso/teamso-mcp/clientThe trusted-proxy signature, for verifiers and tests.
VERSION@teamso/teamso-mcp/serverPackage version.

You can also import the parts on their own:

tools.ts
import { TeamsoClient } from "@teamso/teamso-mcp/client";
import { registerTools, TOOL_NAMES } from "@teamso/teamso-mcp/tools";

registerTools(existingMcpServer, new TeamsoClient(token));
console.log(TOOL_NAMES); // ["search_help_articles", "get_help_article", ...]

A server that forwards other people's requests can sign the caller's IP so Teamso applies the company IP restriction and the audit log to the real caller. The secret must match the API's security.mcp-proxy.shared-secret (at least 32 characters):

proxy.ts
const client = new TeamsoClient(userToken, "https://api.teamso.com/v1", {
  trustedProxy: { clientIp: request.ip, sharedSecret: process.env.TEAMSO_MCP_PROXY_SECRET! },
});

Self-hosting on your server

Build from source and run it on your own server (Node.js 20+):

bash
git clone https://github.com/Teamsocom/Teamso-MCP.git
cd Teamso-MCP
npm ci
npm run build
export TEAMSO_ACCESS_TOKEN=tms_pat_...
node dist/index.js

Point your client at the build instead of npx:

mcp.json
{
  "mcpServers": {
    "teamso": {
      "command": "node",
      "args": [
        "/absolute/path/to/Teamso-MCP/dist/index.js"
      ],
      "env": {
        "TEAMSO_ACCESS_TOKEN": "tms_pat_..."
      }
    }
  }
}

The package builds itself on install (prepare), so a tagged release can also be installed straight from GitHub:

bash
npm install github:Teamsocom/Teamso-MCP#v1.2.1

For a long-running process use a process manager such as systemd or pm2; pass the token as an environment variable or a secret file and never commit it.